Update On Wed Feb 14 19:41:21 CET 2024

This commit is contained in:
github-action[bot] 2024-02-14 19:41:21 +01:00
parent 868b916c9a
commit 0d528aea46
304 changed files with 12530 additions and 7509 deletions

25
Cargo.lock generated
View file

@ -899,7 +899,7 @@ dependencies = [
[[package]]
name = "coreaudio-sys-utils"
version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=4ba39ca14bbb5bb0274843701cd958717a0fe293#4ba39ca14bbb5bb0274843701cd958717a0fe293"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=d777208b31b9895cdbbc6d254ecb039a0d9c35c1#d777208b31b9895cdbbc6d254ecb039a0d9c35c1"
dependencies = [
"core-foundation-sys",
"coreaudio-sys",
@ -1110,7 +1110,7 @@ dependencies = [
[[package]]
name = "cubeb-coreaudio"
version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=4ba39ca14bbb5bb0274843701cd958717a0fe293#4ba39ca14bbb5bb0274843701cd958717a0fe293"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=d777208b31b9895cdbbc6d254ecb039a0d9c35c1#d777208b31b9895cdbbc6d254ecb039a0d9c35c1"
dependencies = [
"atomic",
"audio-mixer",
@ -2291,9 +2291,9 @@ dependencies = [
[[package]]
name = "glean"
version = "56.1.0"
version = "57.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12e51799c1e40ba51f24e0ff232d35ea321403920bea31dc11de1afaeb541ef"
checksum = "ae5847ad58b7f925c984de7f4dffcad67d7d0befa59a5a888cf93741b5ef1e6a"
dependencies = [
"chrono",
"crossbeam-channel",
@ -2311,9 +2311,9 @@ dependencies = [
[[package]]
name = "glean-core"
version = "56.1.0"
version = "57.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f7570206325e7a20c45b60bf63f1f5b69c2ce0ee79ca0dc774e7c39eaab19aa"
checksum = "6831cadd28b625bc296732d71dc7c978f208ba27911cad072785f87f23b1e634"
dependencies = [
"android_logger",
"bincode",
@ -3304,12 +3304,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.17"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if 1.0.0",
]
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "mach"
@ -4748,13 +4745,13 @@ dependencies = [
[[package]]
name = "rkv"
version = "0.18.4"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f0ea3af1393b22f8fe25615b6fa5d13072b7b622e66acffc8b12b2baa0342b1"
checksum = "2c6d906922d99c677624d2042a93f89b2b7df0f6411032237d5d99a602c2487c"
dependencies = [
"arrayref",
"bincode",
"bitflags 1.999.999",
"bitflags 2.4.1",
"byteorder",
"id-arena",
"lazy_static",

View file

@ -848,7 +848,11 @@ function getTextFromClipboard() {
}
trans.addDataFlavor("text/plain");
Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
Services.clipboard.getData(
trans,
Services.clipboard.kGlobalClipboard,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
var str = {};
trans.getTransferData("text/plain", str);

View file

@ -833,28 +833,28 @@ class SearchAdImpression {
for (let element of elements) {
let clickCallback = () => {
if (clickAction == "submitted") {
documentToSubmitMap.set(document, true);
}
callback({
type,
url,
action: clickAction,
});
if (clickAction == "submitted") {
documentToSubmitMap.set(document, true);
}
};
element.addEventListener("click", clickCallback);
let keydownCallback = event => {
if (event.key == "Enter") {
if (keydownEnterAction == "submitted") {
documentToSubmitMap.set(document, true);
}
callback({
type,
url,
action: keydownEnterAction,
});
}
if (keydownEnterAction == "submitted") {
documentToSubmitMap.set(document, true);
}
};
element.addEventListener("keydown", keydownCallback);
@ -906,6 +906,8 @@ class SearchAdImpression {
* The key name of the data attribute to lookup.
* @property {string | null} options.queryParamKey
* The key name of the query param value to lookup.
* @property {boolean | null} options.queryParamValueIsHref
* Whether the query param value is expected to contain an href.
*/
/**
@ -947,7 +949,8 @@ class DomainExtractor {
elements,
origin,
extractedDomains,
extractorInfo.options?.queryParamKey
extractorInfo.options?.queryParamKey,
extractorInfo.options?.queryParamValueIsHref
);
break;
}
@ -980,12 +983,15 @@ class DomainExtractor {
* The result set of domains extracted from the page.
* @param {string | null} queryParam
* An optional query param to search for in an element's href attribute.
* @param {boolean | null} queryParamValueIsHref
* Whether the query param value is expected to contain an href.
*/
#fromElementsConvertHrefsIntoDomains(
elements,
origin,
extractedDomains,
queryParam
queryParam,
queryParamValueIsHref
) {
for (let element of elements) {
let href = element.getAttribute("href");
@ -1002,9 +1008,20 @@ class DomainExtractor {
continue;
}
let domain = queryParam ? url.searchParams.get(queryParam) : url.hostname;
if (domain && !extractedDomains.has(domain)) {
extractedDomains.add(domain);
if (queryParam) {
let paramValue = url.searchParams.get(queryParam);
if (queryParamValueIsHref) {
try {
paramValue = new URL(paramValue).hostname;
} catch (e) {
continue;
}
}
if (paramValue && !extractedDomains.has(paramValue)) {
extractedDomains.add(paramValue);
}
} else if (url.hostname && !extractedDomains.has(url.hostname)) {
extractedDomains.add(url.hostname);
}
}
}

View file

@ -1483,15 +1483,8 @@ pref("browser.bookmarks.editDialog.maxRecentFolders", 7);
pref("browser.taskbar.previews.enable", false);
pref("browser.taskbar.previews.max", 20);
pref("browser.taskbar.previews.cachetime", 5);
pref("browser.taskbar.lists.legacyBackend", true);
// We'll only enable the new off-main-thread jumplist backend on Nightly for
// now while we test it.
#ifdef NIGHTLY_BUILD
pref("browser.taskbar.lists.legacyBackend", false);
#else
pref("browser.taskbar.lists.legacyBackend", true);
#endif
pref("browser.taskbar.lists.enabled", true);
pref("browser.taskbar.lists.frequent.enabled", true);

View file

@ -617,8 +617,8 @@
<toolbarbutton id="PanelUI-fxa-menu-sync-button" class="subviewbutton subviewbutton-iconic"
oncommand="gSync.openPrefsFromFxaMenu('sync_cta', this);">
<vbox flex="1">
<label id="fxa-menu-header-title" crop="end" data-l10n-id="sync-menu-title" />
<label id="cta-menu-header-description" crop="end" data-l10n-id="sync-menu-description" />
<label id="fxa-menu-header-title" crop="end" data-l10n-id="fxa-menu-sync-title" />
<label id="cta-menu-header-description" crop="end" data-l10n-id="fxa-menu-sync-description" />
</vbox>
<toolbarseparator id="PanelUI-remote-tabs-separator" />
</toolbarbutton>
@ -628,9 +628,9 @@
<vbox flex="1">
<hbox align="center">
<image class="PanelUI-fxa-menu-monitor-button ctaMenuLogo" role="presentation" />
<label id="fxa-menu-header-title" crop="end" data-l10n-id="pxi-menu-monitor-title" />
<label id="fxa-menu-header-title" crop="end" data-l10n-id="appmenuitem-monitor-title" />
</hbox>
<label id="cta-menu-header-description" crop="end" data-l10n-id="pxi-menu-monitor-description" />
<label id="cta-menu-header-description" crop="end" data-l10n-id="appmenuitem-monitor-description" />
</vbox>
</toolbarbutton>
<toolbarbutton id="PanelUI-fxa-menu-relay-button" class="subviewbutton subviewbutton-iconic"
@ -638,9 +638,9 @@
<vbox flex="1">
<hbox align="center">
<image class="PanelUI-fxa-menu-relay-button ctaMenuLogo" role="presentation" />
<label id="fxa-menu-header-title" crop="end" data-l10n-id="pxi-menu-relay-title" />
<label id="fxa-menu-header-title" crop="end" data-l10n-id="appmenuitem-relay-title" />
</hbox>
<label id="cta-menu-header-description" crop="end" data-l10n-id="pxi-menu-relay-description" />
<label id="cta-menu-header-description" crop="end" data-l10n-id="appmenuitem-relay-description" />
</vbox>
</toolbarbutton>
<toolbarbutton id="PanelUI-fxa-menu-vpn-button" class="subviewbutton subviewbutton-iconic"
@ -648,9 +648,9 @@
<vbox flex="1">
<hbox align="center">
<image class="PanelUI-fxa-menu-vpn-button ctaMenuLogo" role="presentation" />
<label id="fxa-menu-header-title" crop="end" data-l10n-id="pxi-menu-vpn-title" />
<label id="fxa-menu-header-title" crop="end" data-l10n-id="appmenuitem-vpn-title" />
</hbox>
<label id="cta-menu-header-description" crop="end" data-l10n-id="pxi-menu-vpn-description" />
<label id="cta-menu-header-description" crop="end" data-l10n-id="appmenuitem-vpn-description" />
</vbox>
</toolbarbutton>
</vbox>

View file

@ -385,8 +385,6 @@ var gSync = {
"browser/appmenu.ftl",
"browser/sync.ftl",
"toolkit/branding/accounts.ftl",
// untranslated FTL
"preview/appmenu.ftl",
],
true
));
@ -925,7 +923,7 @@ var gSync = {
syncSetupButtonEl.removeAttribute("hidden");
let headerTitleL10nId = this.PXI_TOOLBAR_ENABLED
? "appmenuitem-moz-accounts-sign-in"
? "appmenuitem-sign-in-account"
: "appmenuitem-fxa-sign-in";
let headerDescription;
if (state.status === UIState.STATUS_NOT_CONFIGURED) {

View file

@ -98,7 +98,6 @@
<link rel="localization" href="preview/select-translations.ftl"/>
<link rel="localization" href="browser/shopping.ftl"/>
<link rel="localization" href="preview/shopping.ftl"/>
<link rel="localization" href="preview/appmenu.ftl" />
<title data-l10n-id="browser-main-window-title"></title>

View file

@ -31,7 +31,11 @@ function getTransferableFromClipboard(asHTML) {
} else {
trans.addDataFlavor("text/plain");
}
Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
Services.clipboard.getData(
trans,
Ci.nsIClipboard.kGlobalClipboard,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
return trans;
}

View file

@ -190,16 +190,6 @@ add_task(async function navigate_around() {
},
};
if (Services.prefs.getBoolPref("browser.translations.enable")) {
// The translations pref logs the translation decision on each DOMContentLoaded,
// and only shows the log by the preferences set in the console.createInstance.
// See Bug 1835693. This means that it is invoked on each page load.
knownProblematicPrefs["browser.translations.logLevel"] = {
min: 50,
max: 150,
};
}
if (SpecialPowers.useRemoteSubframes) {
// We access this when considering starting a new content process.
// Because there is no complete list of content process types,

View file

@ -98,7 +98,16 @@ add_task(async function testSiteScopedPermissionBaseDomainAffectsSubdomain() {
Services.perms.removeFromPrincipal(principal, id);
// We intentionally turn off a11y_checks, because the following function
// is expected to click a toolbar button that may be already hidden
// with "display:none;". The permissions panel anchor is hidden because
// the last permission was removed, however we force opening the panel
// anyways in order to test that the list has been properly emptied:
AccessibilityUtils.setEnv({
mustHaveAccessibleRule: false,
});
await openPermissionPopup();
AccessibilityUtils.resetEnv();
listEntryCount = permissionsList.querySelectorAll(
".permission-popup-permission-item-3rdPartyStorage"

View file

@ -285,10 +285,6 @@ var allowlist = [
{ file: "chrome://browser/content/screenshots/copy.svg" },
{ file: "chrome://browser/content/screenshots/download.svg" },
{ file: "chrome://browser/content/screenshots/download-white.svg" },
// The file is temporarily left until a new conditioned profile is created,
// to be removed with bug 1878264
{ file: "chrome://browser/content/parent/ext-urlbar.js" },
];
if (AppConstants.platform != "win") {

View file

@ -607,7 +607,7 @@ add_task(async function test_experiment_ui_state_unconfigured() {
checkFxAAvatar("not_configured");
let expectedLabel = gSync.fluentStrings.formatValueSync(
"appmenuitem-moz-accounts-sign-in"
"appmenuitem-sign-in-account"
);
await openMainPanel();

View file

@ -1402,7 +1402,7 @@ html {
.dismiss-button {
position: absolute;
z-index: 1;
z-index: 2;
top: 0;
left: auto;
right: 0;

View file

@ -525,6 +525,7 @@ export class ProtonScreen extends React.PureComponent {
/>
) : null}
{includeNoodles ? this.renderNoodles() : null}
{content.dismiss_button ? this.renderDismissButton() : null}
<div
className={`main-content ${hideStepsIndicator ? "no-steps" : ""}`}
style={{
@ -605,7 +606,6 @@ export class ProtonScreen extends React.PureComponent {
? this.renderStepsIndicator()
: null}
</div>
{content.dismiss_button ? this.renderDismissButton() : null}
</div>
<Localized text={content.info_text}>
<span className="info-text" />

View file

@ -1180,7 +1180,7 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
content: content,
handleAction: this.props.handleAction,
position: "top"
}) : null, includeNoodles ? this.renderNoodles() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
}) : null, includeNoodles ? this.renderNoodles() : null, content.dismiss_button ? this.renderDismissButton() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: `main-content ${hideStepsIndicator ? "no-steps" : ""}`,
style: {
background: content.background && isCenterPosition ? content.background : null,
@ -1217,7 +1217,7 @@ class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCom
addonName: this.props.addonName,
handleAction: this.props.handleAction,
activeMultiSelect: this.props.activeMultiSelect
})), !hideStepsIndicator && !aboveButtonStepsIndicator ? this.renderStepsIndicator() : null), content.dismiss_button ? this.renderDismissButton() : null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
})), !hideStepsIndicator && !aboveButtonStepsIndicator ? this.renderStepsIndicator() : null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
text: content.info_text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", {
className: "info-text"

View file

@ -2090,7 +2090,7 @@ html {
}
.onboardingContainer .dismiss-button {
position: absolute;
z-index: 1;
z-index: 2;
top: 0;
left: auto;
right: 0;

View file

@ -1068,6 +1068,7 @@ const BASE_MESSAGES = () => [
id: "FOX_DOODLE_SET_DEFAULT",
screens: [
{
id: "FOX_DOODLE_SET_DEFAULT_SCREEN",
content: {
logo: {
height: "125px",

View file

@ -90,6 +90,7 @@ async function testCalloutHiddenIf(
message = getTestMessage()
) {
const win = await BrowserTestUtils.openNewBrowserWindow();
win.focus();
const doc = win.document;
const browser = win.gBrowser.selectedBrowser;
const { featureCallout, showing, closed } = await showFeatureCallout(
@ -352,3 +353,78 @@ add_task(async function feature_callout_split_dismiss_button() {
message
);
});
add_task(async function feature_callout_tab_order() {
let message = getTestMessage();
message.content.screens[0].content.secondary_button = {
label: { raw: "Dismiss" },
action: { dismiss: true },
};
message.content.screens[0].content.primary_button = {
label: { raw: "Advance" },
action: { navigate: true },
};
await testCalloutHiddenIf(
async (win, calloutContainer) => {
// Test that feature callout initially focuses the primary button.
let primaryButton = calloutContainer.querySelector(
`#${calloutId} .primary`
);
await BrowserTestUtils.waitForCondition(
() => win.document.activeElement === primaryButton,
"Primary button should be focused"
);
// Test that pressing Tab loops through the primary button, secondary
// button, and dismiss button.
let secondaryButton = calloutContainer.querySelector(
`#${calloutId} .secondary`
);
let onFocused2 = BrowserTestUtils.waitForEvent(secondaryButton, "focus");
EventUtils.synthesizeKey("KEY_Tab", {}, win);
await onFocused2;
is(
win.document.activeElement,
secondaryButton,
"Secondary button should be focused"
);
let dismissButton = calloutContainer.querySelector(
`#${calloutId} .dismiss-button`
);
let onFocused3 = BrowserTestUtils.waitForEvent(dismissButton, "focus");
EventUtils.synthesizeKey("KEY_Tab", {}, win);
await onFocused3;
is(
win.document.activeElement,
dismissButton,
"Dismiss button should be focused"
);
let onFocused4 = BrowserTestUtils.waitForEvent(primaryButton, "focus");
EventUtils.synthesizeKey("KEY_Tab", {}, win);
await onFocused4;
is(
win.document.activeElement,
primaryButton,
"Primary button should be focused"
);
// Test that pressing Shift+Tab loops back to the dismiss button.
let onFocused5 = BrowserTestUtils.waitForEvent(dismissButton, "focus");
EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true }, win);
await onFocused5;
is(
win.document.activeElement,
dismissButton,
"Dismiss button should be focused"
);
EventUtils.synthesizeKey("VK_SPACE", {}, win);
},
null,
message
);
});

View file

@ -28,7 +28,6 @@ browser.jar:
content/browser/parent/ext-tabs.js (parent/ext-tabs.js)
content/browser/parent/ext-topSites.js (parent/ext-topSites.js)
content/browser/parent/ext-url-overrides.js (parent/ext-url-overrides.js)
content/browser/parent/ext-urlbar.js (parent/ext-urlbar.js)
content/browser/parent/ext-windows.js (parent/ext-windows.js)
content/browser/child/ext-browser.js (child/ext-browser.js)
content/browser/child/ext-browser-content-only.js (child/ext-browser-content-only.js)

View file

@ -1,153 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
ChromeUtils.defineESModuleGetters(this, {
UrlbarProviderExtension:
"resource:///modules/UrlbarProviderExtension.sys.mjs",
});
var { ExtensionPreferencesManager } = ChromeUtils.importESModule(
"resource://gre/modules/ExtensionPreferencesManager.sys.mjs"
);
var { getSettingsAPI } = ExtensionPreferencesManager;
ExtensionPreferencesManager.addSetting("engagementTelemetry", {
prefNames: ["browser.urlbar.eventTelemetry.enabled"],
setCallback(value) {
return { [this.prefNames[0]]: value };
},
});
this.urlbar = class extends ExtensionAPI {
getAPI(context) {
return {
urlbar: {
closeView() {
let window = windowTracker.getTopNormalWindow(context);
window.gURLBar.view.close();
},
focus(select = false) {
let window = windowTracker.getTopNormalWindow(context);
if (select) {
window.gURLBar.select();
} else {
window.gURLBar.focus();
}
},
search(searchString, options = {}) {
let window = windowTracker.getTopNormalWindow(context);
window.gURLBar.search(searchString, options);
},
onBehaviorRequested: new EventManager({
context,
name: "urlbar.onBehaviorRequested",
register: (fire, providerName) => {
let provider = UrlbarProviderExtension.getOrCreate(providerName);
provider.setEventListener(
"behaviorRequested",
async queryContext => {
if (queryContext.isPrivate && !context.privateBrowsingAllowed) {
return "inactive";
}
return fire.async(queryContext).catch(error => {
throw context.normalizeError(error);
});
}
);
return () => provider.setEventListener("behaviorRequested", null);
},
}).api(),
onEngagement: new EventManager({
context,
name: "urlbar.onEngagement",
register: (fire, providerName) => {
let provider = UrlbarProviderExtension.getOrCreate(providerName);
provider.setEventListener(
"engagement",
async (isPrivate, state) => {
if (isPrivate && !context.privateBrowsingAllowed) {
return;
}
return fire.async(state).catch(error => {
throw context.normalizeError(error);
});
}
);
return () => provider.setEventListener("engagement", null);
},
}).api(),
onQueryCanceled: new EventManager({
context,
name: "urlbar.onQueryCanceled",
register: (fire, providerName) => {
let provider = UrlbarProviderExtension.getOrCreate(providerName);
provider.setEventListener("queryCanceled", async queryContext => {
if (queryContext.isPrivate && !context.privateBrowsingAllowed) {
return;
}
await fire.async(queryContext).catch(error => {
throw context.normalizeError(error);
});
});
return () => provider.setEventListener("queryCanceled", null);
},
}).api(),
onResultsRequested: new EventManager({
context,
name: "urlbar.onResultsRequested",
register: (fire, providerName) => {
let provider = UrlbarProviderExtension.getOrCreate(providerName);
provider.setEventListener(
"resultsRequested",
async queryContext => {
if (queryContext.isPrivate && !context.privateBrowsingAllowed) {
return [];
}
return fire.async(queryContext).catch(error => {
throw context.normalizeError(error);
});
}
);
return () => provider.setEventListener("resultsRequested", null);
},
}).api(),
onResultPicked: new EventManager({
context,
name: "urlbar.onResultPicked",
inputHandling: true,
register: (fire, providerName) => {
let provider = UrlbarProviderExtension.getOrCreate(providerName);
provider.setEventListener(
"resultPicked",
async (resultPayload, dynamicElementName) => {
return fire
.async(resultPayload, dynamicElementName)
.catch(error => {
throw context.normalizeError(error);
});
}
);
return () => provider.setEventListener("resultPicked", null);
},
}).api(),
engagementTelemetry: getSettingsAPI({
context,
name: "engagementTelemetry",
readOnly: true,
callback: () => false,
}),
},
};
}
};

View file

@ -688,7 +688,11 @@ function getRawClipboardData(flavor) {
);
xferable.init(null);
xferable.addDataFlavor(flavor);
Services.clipboard.getData(xferable, whichClipboard);
Services.clipboard.getData(
xferable,
whichClipboard,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
let data = {};
try {
// xferable.getTransferData(flavor, data);

View file

@ -90,16 +90,60 @@ const TESTS = [
],
expectedDomains: ["def.com"],
},
{
title:
"Extract domain from an href's query param value containing an href.",
extractorInfos: [
{
selectors: "#test7 a",
method: "href",
options: {
queryParamKey: "ad_domain",
queryParamValueIsHref: true,
},
},
],
expectedDomains: ["def.com"],
},
{
title:
"The param value contains an invalid href while queryParamValueIsHref enabled.",
extractorInfos: [
{
selectors: "#test8 a",
method: "href",
options: {
queryParamKey: "ad_domain",
queryParamValueIsHref: true,
},
},
],
expectedDomains: [],
},
{
title: "Param value is missing from the href.",
extractorInfos: [
{
selectors: "#test9 a",
method: "href",
options: {
queryParamKey: "ad_domain",
queryParamValueIsHref: true,
},
},
],
expectedDomains: [],
},
{
title: "Extraction preserves order of domains within the page.",
extractorInfos: [
{
selectors:
'#test7 [data-layout="organic"] a[data-testid="result-title-a"]',
'#test10 [data-layout="organic"] a[data-testid="result-title-a"]',
method: "href",
},
{
selectors: "#test7 [data-dtld]",
selectors: "#test10 [data-dtld]",
method: "data-attribute",
options: {
dataAttributeKey: "dtld",
@ -107,7 +151,7 @@ const TESTS = [
},
{
selectors:
'#test7 .js-carousel-item-title, #test7 [data-layout="ad"] [data-testid="result-title-a"]',
'#test10 .js-carousel-item-title, #test7 [data-layout="ad"] [data-testid="result-title-a"]',
method: "href",
options: {
queryParamKey: "ad_domain",
@ -121,7 +165,7 @@ const TESTS = [
extractorInfos: [
{
selectors:
'#test8 [data-layout="organic"] a[data-testid="result-title-a"]',
'#test11 [data-layout="organic"] a[data-testid="result-title-a"]',
method: "href",
},
],
@ -131,7 +175,7 @@ const TESTS = [
title: "Data attribute is present, but value is missing.",
extractorInfos: [
{
selectors: "#test9 [data-dtld]",
selectors: "#test12 [data-dtld]",
method: "data-attribute",
options: {
dataAttributeKey: "dtld",
@ -144,7 +188,7 @@ const TESTS = [
title: "Query param is present, but value is missing.",
extractorInfos: [
{
selectors: '#test10 [data-layout="ad"] [data-testid="result-title-a"]',
selectors: '#test13 [data-layout="ad"] [data-testid="result-title-a"]',
method: "href",
options: {
queryParamKey: "ad_domain",
@ -158,7 +202,7 @@ const TESTS = [
extractorInfos: [
{
selectors:
'#test11 [data-layout="organic"] a[data-testid="result-title-a"]',
'#test14 [data-layout="organic"] a[data-testid="result-title-a"]',
method: "href",
},
],

View file

@ -23,6 +23,152 @@ add_setup(async function () {
});
});
add_task(async function test_content_process_type_search_click_suggestion() {
resetTelemetry();
let tab = await SinglePageAppUtils.createTabAndLoadURL();
await SinglePageAppUtils.clickSearchboxAndType(tab);
await SinglePageAppUtils.clickSuggestion(tab);
await assertSearchSourcesTelemetry(
{},
{
"browser.search.content.unknown": {
"example1:tagged:ff": 2,
},
"browser.search.withads.unknown": {
"example1:tagged": 2,
},
}
);
assertSERPTelemetry([
{
impression: {
provider: "example1",
tagged: "true",
partner_code: "ff",
source: "unknown",
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
engagements: [
{
action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
target: SearchSERPTelemetryUtils.COMPONENTS.INCONTENT_SEARCHBOX,
},
{
action: SearchSERPTelemetryUtils.ACTIONS.SUBMITTED,
target: SearchSERPTelemetryUtils.COMPONENTS.INCONTENT_SEARCHBOX,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
{
impression: {
provider: "example1",
tagged: "true",
partner_code: "ff",
source: "follow_on_from_refine_on_incontent_search",
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await BrowserTestUtils.removeTab(tab);
});
add_task(
async function test_content_process_type_search_click_related_search() {
resetTelemetry();
let tab = await SinglePageAppUtils.createTabAndLoadURL();
await SinglePageAppUtils.clickSearchboxAndType(tab);
await SinglePageAppUtils.visitRelatedSearch(tab);
await assertSearchSourcesTelemetry(
{},
{
"browser.search.content.unknown": {
"example1:tagged:ff": 2,
},
"browser.search.withads.unknown": {
"example1:tagged": 2,
},
}
);
assertSERPTelemetry([
{
impression: {
provider: "example1",
tagged: "true",
partner_code: "ff",
source: "unknown",
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
engagements: [
{
action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
target: SearchSERPTelemetryUtils.COMPONENTS.INCONTENT_SEARCHBOX,
},
{
action: SearchSERPTelemetryUtils.ACTIONS.CLICKED,
target: SearchSERPTelemetryUtils.COMPONENTS.NON_ADS_LINK,
},
],
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
{
impression: {
provider: "example1",
tagged: "true",
partner_code: "ff",
source: "unknown",
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
},
adImpressions: [
{
component: SearchSERPTelemetryUtils.COMPONENTS.AD_LINK,
ads_loaded: "2",
ads_visible: "2",
ads_hidden: "0",
},
],
},
]);
await BrowserTestUtils.removeTab(tab);
}
);
add_task(async function test_content_process_engagement() {
resetTelemetry();

View file

@ -115,6 +115,15 @@ class SinglePageAppUtils {
await waitForIdle();
}
static async clickSearchboxAndType(tab, str = "hello world") {
await SinglePageAppUtils.clickSearchbox(tab);
info(`Type ${str} in searchbox.`);
for (let char of str) {
await BrowserTestUtils.sendChar(char, tab.linkedBrowser);
}
await waitForIdle();
}
static async clickSuggestion(tab) {
info("Clicking the first suggestion.");
let adsPromise = TestUtils.topicObserved(

View file

@ -44,6 +44,18 @@
</div>
<div id="test7">
<a href="https://example.com/test?ad_domain=https://def.com/path/to/nowhere">Extract domain from an href's query param value containing an absolute href.</a>
</div>
<div id="test8">
<a href="https://example.com/test?ad_domain=def.com/path/to/nowhere">Extract domain from an href's query param value containing a relative href.</a>
</div>
<div id="test9">
<a href="https://example.com/test?dummy_key=foo.com">Param value is missing from the href.</a>
</div>
<div id="test10">
<!-- Extraction preserves order of domains within the page. -->
<div data-layout="organic">
<a href="https://foobar.com" data-testid="result-title-a">Extract domain from href (absolute URL).</a>
@ -52,19 +64,19 @@
</div>
</div>
<div id="test8">
<div id="test11">
<a href="nomatches.com">Link that doesn't match a selector.</a>
</div>
<div id="test9">
<div id="test12">
<a href="#" data-dtld="">Data attribute is present, but value is missing.</a>
</div>
<div id="test10">
<div id="test13">
<a href="example.com/testing?ad_domain=" class="js-carousel-item-title">Query param is present, but value is missing.</a>
</div>
<div id="test11">
<div id="test14">
<a href="git://testing.com/testrepo">Non-standard URL scheme.</a>
</div>
</div>

View file

@ -222,7 +222,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.sys.mjs",
E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs",
HomePage: "resource:///modules/HomePage.sys.mjs",
PrivacyFilter: "resource://gre/modules/sessionstore/PrivacyFilter.sys.mjs",
RunState: "resource:///modules/sessionstore/RunState.sys.mjs",
SessionCookies: "resource:///modules/sessionstore/SessionCookies.sys.mjs",
SessionFile: "resource:///modules/sessionstore/SessionFile.sys.mjs",
@ -2320,8 +2319,6 @@ var SessionStoreInternal = {
// 3) When the flush is complete, revisit our decision to store the window
// in _closedWindows, and add/remove as necessary.
if (!winData.isPrivate) {
// Remove any open private tabs the window may contain.
lazy.PrivacyFilter.filterPrivateTabs(winData);
this.maybeSaveClosedWindow(winData, isLastWindow);
}
@ -2343,9 +2340,6 @@ var SessionStoreInternal = {
// Save non-private windows if they have at
// least one saveable tab or are the last window.
if (!winData.isPrivate) {
// It's possible that a tab switched its privacy state at some point
// before our flush, so we need to filter again.
lazy.PrivacyFilter.filterPrivateTabs(winData);
this.maybeSaveClosedWindow(winData, isLastWindow, true);
if (!isLastWindow && winData.closedId > -1) {

View file

@ -237,13 +237,13 @@ class ShoppingMessageBar extends MozLitElement {
<moz-button-group slot="actions">
<button
id="no-thanks-button"
class="small-button"
class="small-button shopping-button"
data-l10n-id="shopping-message-bar-keep-closed-dismiss-button"
@click=${this.handleNoThanksClick}
></button>
<button
id="yes-keep-closed-button"
class="primary small-button"
class="primary small-button shopping-button"
data-l10n-id="shopping-message-bar-keep-closed-accept-button"
@click=${this.handleKeepClosedClick}
></button>

View file

@ -20,7 +20,11 @@ function getTextFromClipboard() {
);
transferable.init(window.docShell.QueryInterface(Ci.nsILoadContext));
transferable.addDataFlavor("text/plain");
Services.clipboard.getData(transferable, Services.clipboard.kGlobalClipboard);
Services.clipboard.getData(
transferable,
Services.clipboard.kGlobalClipboard,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
const results = {};
transferable.getTransferData("text/plain", results);

View file

@ -15,6 +15,7 @@
-mdn-brand-name = MDN Web Docs
-mdn-brand-short-name = MDN
-yelp-brand-name = Yelp
## These strings are used in the urlbar panel.
@ -73,10 +74,16 @@ firefox-suggest-dismissal-acknowledgment-all = Thanks for your feedback. You won
# suggestion.
firefox-suggest-dismissal-acknowledgment-one-mdn = Thanks for your feedback. You wont see this { -mdn-brand-short-name } suggestion again.
# A message that replaces a result when the user dismisses all MDN suggestions of
# a particular type.
# A message that replaces a result when the user dismisses all MDN suggestions.
firefox-suggest-dismissal-acknowledgment-all-mdn = Thanks for your feedback. You wont see { -mdn-brand-short-name } suggestions anymore.
# A message that replaces a result when the user dismisses a single Yelp
# suggestion.
firefox-suggest-dismissal-acknowledgment-one-yelp = Thanks for your feedback. You wont see this { -yelp-brand-name } suggestion again.
# A message that replaces a result when the user dismisses all Yelp suggestions.
firefox-suggest-dismissal-acknowledgment-all-yelp = Thanks for your feedback. You wont see { -yelp-brand-name } suggestions anymore.
## These strings are used for weather suggestions in the urlbar.
# This string is displayed above the current temperature

View file

@ -7,6 +7,7 @@ import { BaseFeature } from "resource:///modules/urlbar/private/BaseFeature.sys.
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs",
MerinoClient: "resource:///modules/MerinoClient.sys.mjs",
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs",
@ -17,6 +18,7 @@ const RESULT_MENU_COMMAND = {
HELP: "help",
INACCURATE_LOCATION: "inaccurate_location",
NOT_INTERESTED: "not_interested",
NOT_RELEVANT: "not_relevant",
SHOW_LESS_FREQUENTLY: "show_less_frequentry",
};
@ -82,13 +84,14 @@ export class YelpSuggestions extends BaseFeature {
lazy.UrlbarUtils.RESULT_SOURCE.SEARCH,
...lazy.UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
url: url.toString(),
title,
title: [title, lazy.UrlbarUtils.HIGHLIGHT.TYPED],
shouldShowUrl: true,
bottomTextL10n: { id: "firefox-suggest-yelp-bottom-text" },
})
),
{
richSuggestionIconSize: 24,
isRichSuggestion: true,
richSuggestionIconSize: suggestion.is_top_pick ? 38 : 24,
showFeedbackMenu: true,
}
);
@ -115,10 +118,23 @@ export class YelpSuggestions extends BaseFeature {
commands.push(
{
name: RESULT_MENU_COMMAND.NOT_INTERESTED,
l10n: {
id: "firefox-suggest-command-dont-show-this",
},
children: [
{
name: RESULT_MENU_COMMAND.NOT_RELEVANT,
l10n: {
id: "firefox-suggest-command-not-relevant",
},
},
{
name: RESULT_MENU_COMMAND.NOT_INTERESTED,
l10n: {
id: "firefox-suggest-command-not-interested",
},
},
],
},
{ name: "separator" },
{
@ -144,15 +160,22 @@ export class YelpSuggestions extends BaseFeature {
// `inaccurate_location`.
view.acknowledgeFeedback(result);
break;
case RESULT_MENU_COMMAND.NOT_INTERESTED:
lazy.UrlbarPrefs.set("suggest.yelp", false);
// selType == "dismiss" when the user presses the dismiss key shortcut.
case "dismiss":
case RESULT_MENU_COMMAND.NOT_RELEVANT:
lazy.QuickSuggest.blockedSuggestions.add(result.payload.url);
result.acknowledgeDismissalL10n = {
id: "firefox-suggest-dismissal-acknowledgment-all",
id: "firefox-suggest-dismissal-acknowledgment-one-yelp",
};
view.controller.removeResult(result);
break;
case RESULT_MENU_COMMAND.NOT_INTERESTED:
lazy.UrlbarPrefs.set("suggest.yelp", false);
result.acknowledgeDismissalL10n = {
id: "firefox-suggest-dismissal-acknowledgment-all-yelp",
};
view.controller.removeResult(result);
break;
// selType == "dismiss" when the user presses the dismiss key shortcut.
case "dismiss":
case RESULT_MENU_COMMAND.SHOW_LESS_FREQUENTLY:
view.acknowledgeFeedback(result);
this.#incrementShowLessFrequentlyCount();

View file

@ -33,25 +33,49 @@ add_setup(async function () {
});
add_task(async function basic() {
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "RaMeN iN tOkYo",
});
for (let topPick of [true, false]) {
info("Setting yelpPriority: " + topPick);
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.quicksuggest.yelpPriority", topPick]],
});
Assert.equal(UrlbarTestUtils.getResultCount(window), 2);
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "RaMeN iN tOkYo",
});
const { result } = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
Assert.equal(
result.providerName,
UrlbarProviderQuickSuggest.name,
"The result should be from the expected provider"
);
Assert.equal(result.payload.provider, "Yelp");
Assert.equal(
result.payload.url,
"https://www.yelp.com/search?find_desc=RaMeN&find_loc=tOkYo&utm_medium=partner&utm_source=mozilla"
);
Assert.equal(result.payload.title, "RaMeN iN tOkYo");
Assert.equal(UrlbarTestUtils.getResultCount(window), 2);
const details = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
const { result } = details;
Assert.equal(
result.providerName,
UrlbarProviderQuickSuggest.name,
"The result should be from the expected provider"
);
Assert.equal(result.payload.provider, "Yelp");
Assert.equal(
result.payload.url,
"https://www.yelp.com/search?find_desc=RaMeN&find_loc=tOkYo&utm_medium=partner&utm_source=mozilla"
);
Assert.equal(result.payload.title, "RaMeN iN tOkYo");
const { row } = details.element;
const bottom = row.querySelector(".urlbarView-row-body-bottom");
Assert.ok(bottom, "Bottom text element should exist");
Assert.ok(
BrowserTestUtils.isVisible(bottom),
"Bottom text element should be visible"
);
Assert.equal(
bottom.textContent,
"Yelp · Sponsored",
"Bottom text is correct"
);
await UrlbarTestUtils.promisePopupClose(window);
await SpecialPowers.popPrefEnv();
}
});
// Tests the "Show less frequently" result menu command.
@ -208,8 +232,34 @@ async function doShowLessFrequently({
UrlbarPrefs.set("yelp.showLessFrequentlyCount", 0);
}
// Tests the "Don't show this again" result menu dismissal command.
// Tests the "Not relevant" result menu dismissal command.
add_task(async function resultMenu_not_relevant() {
await doDismiss({
menu: "not_relevant",
assert: resuilt => {
Assert.ok(
QuickSuggest.blockedSuggestions.has(resuilt.payload.url),
"The URL should be register as blocked"
);
},
});
await QuickSuggest.blockedSuggestions.clear();
});
// Tests the "Not interested" result menu dismissal command.
add_task(async function resultMenu_not_interested() {
await doDismiss({
menu: "not_interested",
assert: () => {
Assert.ok(!UrlbarPrefs.get("suggest.yelp"));
},
});
UrlbarPrefs.clear("suggest.yelp");
});
async function doDismiss({ menu, assert }) {
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "ramen",
@ -219,12 +269,17 @@ add_task(async function resultMenu_not_interested() {
let resultIndex = 1;
let details = await UrlbarTestUtils.getDetailsOfResultAt(window, resultIndex);
Assert.equal(details.result.payload.provider, "Yelp");
let result = details.result;
// Click the command.
await UrlbarTestUtils.openResultMenuAndClickItem(window, "not_interested", {
resultIndex,
openByMouse: true,
});
await UrlbarTestUtils.openResultMenuAndClickItem(
window,
["[data-l10n-id=firefox-suggest-command-dont-show-this]", menu],
{
resultIndex,
openByMouse: true,
}
);
// The row should be a tip now.
Assert.ok(gURLBar.view.isOpen, "The view should remain open after dismissal");
@ -278,11 +333,10 @@ add_task(async function resultMenu_not_interested() {
);
}
Assert.ok(!UrlbarPrefs.get("suggest.yelp"));
assert(result);
await UrlbarTestUtils.promisePopupClose(window);
UrlbarPrefs.clear("suggest.yelp");
});
}
// Tests the row/group label.
add_task(async function rowLabel() {

View file

@ -131,7 +131,11 @@ function getRawClipboardData(flavor) {
);
xferable.init(null);
xferable.addDataFlavor(flavor);
Services.clipboard.getData(xferable, whichClipboard);
Services.clipboard.getData(
xferable,
whichClipboard,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
let data = {};
try {
xferable.getTransferData(flavor, data);

View file

@ -303,3 +303,14 @@ appmenu-developer-tools-extensions =
.label = Extensions for developers
appmenuitem-report-broken-site =
.label = Report broken site
## Panel for privacy and security products
appmenuitem-sign-in-account = Sign in to your account
appmenuitem-monitor-title = { -monitor-brand-short-name }
appmenuitem-monitor-description = Get data breach alerts
appmenuitem-relay-title = { -relay-brand-short-name }
appmenuitem-relay-description = Mask your real email and phone
appmenuitem-vpn-title = { -mozilla-vpn-brand-name }
appmenuitem-vpn-description = Protect your online activity

View file

@ -39,3 +39,7 @@ fxa-menu-send-tab-to-device-description = Send a tab instantly to any device you
fxa-menu-sign-out =
.label = Sign out…
fxa-menu-sync-title = Sync
fxa-menu-sync-description = Access your web anywhere

View file

@ -14,7 +14,6 @@
preview/enUS-searchFeatures.ftl (../components/urlbar/content/enUS-searchFeatures.ftl)
preview/shopping.ftl (../components/shopping/content/shopping.ftl)
preview/onboarding.ftl (../components/aboutwelcome/content/onboarding.ftl)
preview/appmenu.ftl (../../services/fxaccounts/content/appmenu.ftl)
preview/select-translations.ftl (../locales-preview/select-translations.ftl)
preview/translations.ftl (../locales-preview/translations.ftl)
browser (%browser/**/*.ftl)

View file

@ -1425,7 +1425,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "56f6e9409d42d9531bf1a9b5b0cdc5059ee4cbfd"
"revision": "b479d2b231e7f33a8c7026a308e7da6aa89d4896"
},
"pt-PT": {
"pin": false,
@ -1443,7 +1443,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "27b0732cc71865d7186a5decb0d0ea9178501277"
"revision": "a7ad0a38713cb96fed8aa52e55bdebb86762f4bb"
},
"rm": {
"pin": false,

View file

@ -89,8 +89,8 @@
.urlbarView-row {
--urlbarView-second-line-indent: calc(var(--urlbarView-icon-margin-start) + var(--urlbarView-icon-margin-end) + var(--urlbarView-favicon-width));
/* Align the favicons and titles of rows with standard 16px icons with those
of rich suggestions. */
/* Align icons that are smaller than the default rich suggestion icon size
(28px) with default-size rich suggestion icons. */
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "browser.urlbar.richSuggestions.featureGate") {
&:not([rich-suggestion]),
@ -98,6 +98,10 @@
--urlbarView-icon-margin-start: calc((var(--urlbarView-rich-suggestion-default-icon-size) - 16px) / 2);
--urlbarView-icon-margin-end: calc(var(--urlbar-icon-padding) + var(--identity-box-margin-inline) + ((var(--urlbarView-rich-suggestion-default-icon-size) - 16px) / 2));
}
&[rich-suggestion][icon-size="24"] {
--urlbarView-icon-margin-start: calc((var(--urlbarView-rich-suggestion-default-icon-size) - 24px) / 2);
--urlbarView-icon-margin-end: calc(var(--urlbar-icon-padding) + var(--identity-box-margin-inline) + ((var(--urlbarView-rich-suggestion-default-icon-size) - 24px) / 2));
}
}
display: flex;
@ -766,6 +770,12 @@
flex-basis: 24px;
}
&[icon-size="38"] {
width: 38px;
height: 38px;
flex-basis: 38px;
}
&[icon-size="52"] {
width: 52px;
height: 52px;
@ -849,6 +859,16 @@
background-color: var(--urlbarView-result-button-selected-background-color);
}
.urlbarView-row[type$=_yelp][icon-size="38"] > .urlbarView-row-inner > .urlbarView-favicon {
padding: calc((52px - 38px) / 2);
border: 1px solid var(--urlbar-box-focus-bgcolor);
border-radius: 2px;
}
.urlbarView-row[type$=_yelp][icon-size="38"]:is([selected], :hover) > .urlbarView-row-inner > .urlbarView-favicon {
border-color: var(--urlbarView-result-button-selected-background-color);
}
/* Search one-offs */
#urlbar .search-one-offs:not([hidden]) {

View file

@ -60,7 +60,7 @@ allprojects {
topsrcdir = gradle.mozconfig.topsrcdir
topobjdir = gradle.mozconfig.topobjdir
gleanVersion = "56.1.0"
gleanVersion = "57.0.0"
if (gleanVersion != getRustVersionFor("glean")) {
throw new StopExecutionException("Mismatched Glean version, expected: ${gleanVersion}," +
" found ${getRustVersionFor("glean")}")

View file

@ -204,7 +204,7 @@ def check_symbol(symbol, language="C", flags=None, when=None, onerror=lambda: No
# when the warning flag is wanted.
# - `check`, when not set, skips checking whether the flag is supported and
# adds it to the list of flags unconditionally.
# - `link`, when set, also perform a linking step.
# - `mode`, can be "compile", "link" or "assemble"
@template
def check_and_add_flags(
flag,
@ -213,11 +213,13 @@ def check_and_add_flags(
compiler=None,
when=None,
check=True,
link=False,
mode="compile",
):
assert mode in ("compile", "link", "assemble")
if compiler is not None:
compilers = (compiler,)
elif link:
elif mode in ("link", "assemble"):
compilers = (c_compiler,)
else:
compilers = (c_compiler, cxx_compiler)
@ -234,20 +236,25 @@ def check_and_add_flags(
for c in compilers:
assert c in {c_compiler, cxx_compiler, host_c_compiler, host_cxx_compiler}
if link:
lang, list_of_flags = {
c_compiler: ("C", flags_collection.ldflags),
cxx_compiler: ("C++", flags_collection.ldflags),
host_c_compiler: ("host C", flags_collection.host_ldflags),
host_cxx_compiler: ("host C++", flags_collection.host_ldflags),
}[c]
else:
if mode == "compile":
lang, list_of_flags = {
c_compiler: ("C", flags_collection.cflags),
cxx_compiler: ("C++", flags_collection.cxxflags),
host_c_compiler: ("host C", flags_collection.host_cflags),
host_cxx_compiler: ("host C++", flags_collection.host_cxxflags),
}[c]
elif mode == "assemble":
lang, list_of_flags = {
c_compiler: ("C", flags_collection.asflags),
host_c_compiler: ("host C", flags_collection.host_asflags),
}[c]
elif mode == "link":
lang, list_of_flags = {
c_compiler: ("C", flags_collection.ldflags),
cxx_compiler: ("C++", flags_collection.ldflags),
host_c_compiler: ("host C", flags_collection.host_ldflags),
host_cxx_compiler: ("host C++", flags_collection.host_ldflags),
}[c]
result = when
@ -261,7 +268,7 @@ def check_and_add_flags(
return flags
if link:
if mode == "link":
def runner(*args, **kwargs):
if c in (c_compiler, cxx_compiler):
@ -377,6 +384,32 @@ def add_flag(warning, compiler=None, when=None):
check_and_add_flag(warning, compiler, when, check=False)
# Like the compilation checks above, but for asm flags.
@dependable
def asm_flags():
return namespace(asflags=[], host_asflags=[])
# Tests the given assembler flag is supported; if the flag
# is supported, add it to the list of compilation flags for the build.
# - `flag` is the flag to test
# - `when` (optional) is a @depends function or option name conditioning
# when the warning flag is wanted.
# - `check`, when not set, skips checking whether the flag is supported and
# adds it to the list of flags unconditionally. This is only meant for
# add_flag().
@template
def check_and_add_asm_flag(flag, when=None, check=True):
return check_and_add_flags(
flag,
asm_flags,
[flag],
when=when,
check=check,
mode="assemble",
)
# Like the compilation checks above, but for linker flags.
@dependable
def linker_flags():
@ -394,7 +427,12 @@ def linker_flags():
@template
def check_and_add_linker_flag(flag, compiler=None, when=None, check=True):
return check_and_add_flags(
flag, linker_flags, [flag], when=when, check=check, link=True
flag,
linker_flags,
[flag],
when=when,
check=check,
mode="link",
)

View file

@ -163,6 +163,7 @@ def check_build_id_sha1(developer_options):
check_and_add_linker_flag("-Wl,--build-id=uuid", when=check_build_id_uuid)
check_and_add_linker_flag("-Wl,--build-id=sha1", when=check_build_id_sha1)
check_and_add_asm_flag("-Wa,--noexecstack", when=is_gnu_cc)
check_and_add_linker_flag("-Wl,-z,noexecstack", when=is_gnu_cc)
check_and_add_linker_flag("-Wl,-z,text", when=is_gnu_cc)
check_and_add_linker_flag("-Wl,-z,relro", when=is_gnu_cc)
@ -184,5 +185,7 @@ def check_Bsymbolic(enable_asan, is_gnu_cc):
check_and_add_linker_flag("-Wl,-Bsymbolic", when=check_Bsymbolic)
# Please keep these last in this file.
add_old_configure_assignment("_COMPILATION_ASFLAGS", asm_flags.asflags)
add_old_configure_assignment("_COMPILATION_HOST_ASFLAGS", asm_flags.host_asflags)
add_old_configure_assignment("_COMPILATION_LDFLAGS", linker_flags.ldflags)
add_old_configure_assignment("_COMPILATION_HOST_LDFLAGS", linker_flags.host_ldflags)

View file

@ -65,6 +65,25 @@
fun:_Z21XRE_CreateStatsObjectv
...
}
{
We purposely leak forkserver children's new argv strings. (See bug 1878213.)
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:strdup
...
fun:_ZN4base17AppProcessBuilder14InitAppProcessEPiPPPc
...
}
{
We purposely leak copies of the initial argv/environ to implement setproctitle on Linux. (See bug 1878213.)
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:strdup
fun:_Z17setproctitle_initPPc
...
}
####################################
# Leaks in third party libraries #

View file

@ -211,17 +211,22 @@ function addThread(state, thread) {
if (!threadItem) {
threadItem = createThreadTreeItem(threadActorID);
state.threadItems = [...state.threadItems];
threadItem.thread = thread;
addSortedItem(state.threadItems, threadItem, sortThreadItems);
} else {
// We force updating the list to trigger mapStateToProps
// as the getSourcesTreeSources selector is awaiting for the `thread` attribute
// which we will set here.
state.threadItems = [...state.threadItems];
// Inject the reducer thread object on Thread Tree Items
// (this is handy shortcut to have access to from React components)
// (this is also used by sortThreadItems to sort the thread as a Tree in the Browser Toolbox)
threadItem.thread = thread;
// We have to re-sort all threads because of the new `thread` attribute on current thread item
state.threadItems.sort(sortThreadItems);
}
// Inject the reducer thread object on Thread Tree Items
// (this is handy shortcut to have access to from React components)
// (this is also used by sortThreadItems to sort the thread as a Tree in the Browser Toolbox)
threadItem.thread = thread;
}
function updateBlackbox(state, sources, shouldBlackBox) {

View file

@ -6,47 +6,37 @@
// THIS FILE IS AUTOGENERATED by wasm-bindgen.
//
// Generated from:
// https://github.com/mstange/profiler-get-symbols/commit/0373708893e45e8299e58ca692764be448e3457d
// https://github.com/mstange/profiler-get-symbols/commit/390b8c4be82c720dd3977ff205fb34bd7d0e00ba
// by following the instructions in that repository's Readme.md
//
let wasm_bindgen;
(function() {
const __exports = {};
let wasm;
let script_src;
if (typeof document !== 'undefined' && document.currentScript !== null) {
script_src = new URL(document.currentScript.src, location.href).toString();
}
let wasm = undefined;
const heap = new Array(32).fill(undefined);
const heap = new Array(128).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 36) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
let WASM_VECTOR_LEN = 0;
let cachedUint8Memory0 = new Uint8Array();
let cachedUint8Memory0 = null;
function getUint8Memory0() {
if (cachedUint8Memory0.byteLength === 0) {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}
const cachedTextEncoder = new TextEncoder();
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
? function (arg, view) {
@ -65,14 +55,14 @@ function passStringToWasm0(arg, malloc, realloc) {
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length);
const ptr = malloc(buf.length, 1) >>> 0;
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
let len = arg.length;
let ptr = malloc(len);
let ptr = malloc(len, 1) >>> 0;
const mem = getUint8Memory0();
@ -88,11 +78,12 @@ function passStringToWasm0(arg, malloc, realloc) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3);
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
ptr = realloc(ptr, len, offset, 1) >>> 0;
}
WASM_VECTOR_LEN = offset;
@ -103,15 +94,29 @@ function isLikeNone(x) {
return x === undefined || x === null;
}
let cachedInt32Memory0 = new Int32Array();
let cachedInt32Memory0 = null;
function getInt32Memory0() {
if (cachedInt32Memory0.byteLength === 0) {
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachedInt32Memory0;
}
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 132) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
@ -121,14 +126,21 @@ function addHeapObject(obj) {
return idx;
}
const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
cachedTextDecoder.decode();
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined')
? { register: () => {}, unregister: () => {} }
: new FinalizationRegistry(state => {
wasm.__wbindgen_export_2.get(state.dtor)(state.a, state.b)
});
function makeMutClosure(arg0, arg1, dtor, f) {
const state = { a: arg0, b: arg1, cnt: 1, dtor };
const real = (...args) => {
@ -143,18 +155,18 @@ function makeMutClosure(arg0, arg1, dtor, f) {
} finally {
if (--state.cnt === 0) {
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
CLOSURE_DTORS.unregister(state);
} else {
state.a = a;
}
}
};
real.original = state;
CLOSURE_DTORS.register(real, state, state);
return real;
}
function __wbg_adapter_16(arg0, arg1, arg2) {
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h19297bd79b0d78f6(arg0, arg1, addHeapObject(arg2));
function __wbg_adapter_20(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures__invoke1_mut__h5c75a368331e2dfc(arg0, arg1, addHeapObject(arg2));
}
function handleError(f, args) {
@ -164,8 +176,8 @@ function handleError(f, args) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
}
function __wbg_adapter_33(arg0, arg1, arg2, arg3) {
wasm.wasm_bindgen__convert__closures__invoke2_mut__h80dea6fd01e77b95(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
function __wbg_adapter_41(arg0, arg1, arg2, arg3) {
wasm.wasm_bindgen__convert__closures__invoke2_mut__hb4d9edc8ea00b6ab(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
}
/**
@ -258,7 +270,7 @@ __exports.queryAPI = function(url, request_json, helper) {
return takeObject(ret);
};
async function load(module, imports) {
async function __wbg_load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
@ -289,12 +301,116 @@ async function load(module, imports) {
}
}
function getImports() {
function __wbg_get_imports() {
const imports = {};
imports.wbg = {};
imports.wbg.__wbg_get_0ee8ea3c7c984c45 = function(arg0, arg1) {
const ret = getObject(arg0)[arg1 >>> 0];
return addHeapObject(ret);
};
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'string' ? obj : undefined;
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbg_self_05040bd9523805b9 = function() { return handleError(function () {
const ret = self.self;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_window_adc720039f2cb14f = function() { return handleError(function () {
const ret = window.window;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_globalThis_622105db80c1457d = function() { return handleError(function () {
const ret = globalThis.globalThis;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_global_f56b013ed9bcf359 = function() { return handleError(function () {
const ret = global.global;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_is_undefined = function(arg0) {
const ret = getObject(arg0) === undefined;
return ret;
};
imports.wbg.__wbg_newnoargs_cfecb3965268594c = function(arg0, arg1) {
const ret = new Function(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbg_call_3f093dd26d5569f8 = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).call(getObject(arg1));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_memory = function() {
const ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbg_buffer_b914fb8b50ebbc3e = function(arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_7f2d9491ea8c746e = function(arg0, arg1, arg2) {
const ret = new Uint32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_new_437b9c4fbab85dd9 = function(arg0) {
const ret = new Uint32Array(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_0de9ee56e9f6ee6e = function(arg0, arg1, arg2) {
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_new_b1f2d6842d615181 = function(arg0) {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_of_94ac9e20a3c46ec5 = function(arg0, arg1, arg2) {
const ret = Array.of(getObject(arg0), getObject(arg1), getObject(arg2));
return addHeapObject(ret);
};
imports.wbg.__wbg_call_67f2111acd2dfdb6 = function() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
const ret = getObject(arg0);
return addHeapObject(ret);
};
imports.wbg.__wbg_getCandidatePathsForDebugFile_19de1ea293153630 = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).getCandidatePathsForDebugFile(takeObject(arg1));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_name_405bb0aa047a1bf5 = function(arg0) {
const ret = getObject(arg0).name;
return addHeapObject(ret);
};
imports.wbg.__wbg_message_2a19bb5b62cf8e22 = function(arg0) {
const ret = getObject(arg0).message;
return addHeapObject(ret);
};
imports.wbg.__wbg_from_58c79ccfb68060f5 = function(arg0) {
const ret = Array.from(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_length_161c0d89c6535c1d = function(arg0) {
const ret = getObject(arg0).length;
return ret;
};
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
const ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
};
imports.wbg.__wbg_getCandidatePathsForBinary_8311cb7aeae90263 = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).getCandidatePathsForBinary(takeObject(arg1));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_cb_drop = function(arg0) {
const obj = takeObject(arg0).original;
if (obj.cnt-- == 1) {
@ -304,67 +420,39 @@ function getImports() {
const ret = false;
return ret;
};
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'string' ? obj : undefined;
var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_close_334601fc6c36b53e = function() { return handleError(function (arg0) {
getObject(arg0).close();
}, arguments) };
imports.wbg.__wbg_get_57245cc7d7c7619d = function(arg0, arg1) {
const ret = getObject(arg0)[arg1 >>> 0];
return addHeapObject(ret);
};
imports.wbg.__wbindgen_memory = function() {
const ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbg_buffer_3f3d764d4747d564 = function(arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_d9aa266703cb98be = function(arg0, arg1, arg2) {
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_readBytesInto_3ec3b16ea5839a95 = function() { return handleError(function (arg0, arg1, arg2) {
getObject(arg0).readBytesInto(takeObject(arg1), arg2);
}, arguments) };
imports.wbg.__wbg_name_48eda3ae6aa697ca = function(arg0) {
const ret = getObject(arg0).name;
return addHeapObject(ret);
};
imports.wbg.__wbg_message_fe2af63ccc8985bc = function(arg0) {
const ret = getObject(arg0).message;
return addHeapObject(ret);
};
imports.wbg.__wbg_new_0b9bfdd97583284e = function() {
imports.wbg.__wbg_new_632630b5cec17f21 = function() {
const ret = new Object();
return addHeapObject(ret);
};
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
const ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
};
imports.wbg.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) {
imports.wbg.__wbg_set_9182712abebf82ef = function(arg0, arg1, arg2) {
getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
};
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
const ret = getObject(arg0);
imports.wbg.__wbg_close_0c320371e818efa4 = function() { return handleError(function (arg0) {
getObject(arg0).close();
}, arguments) };
imports.wbg.__wbg_readBytesInto_8dda8e37c69f2cbd = function() { return handleError(function (arg0, arg1, arg2) {
getObject(arg0).readBytesInto(takeObject(arg1), arg2);
}, arguments) };
imports.wbg.__wbg_readFile_33b95391c6839d48 = function(arg0, arg1, arg2) {
const ret = getObject(arg0).readFile(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
};
imports.wbg.__wbg_new_9962f939219f1820 = function(arg0, arg1) {
imports.wbg.__wbg_then_20a5920e447d1cb1 = function(arg0, arg1, arg2) {
const ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
};
imports.wbg.__wbg_size_45521802c91634d3 = function() { return handleError(function (arg0) {
const ret = getObject(arg0).size;
return ret;
}, arguments) };
imports.wbg.__wbg_new_70828a4353259d4b = function(arg0, arg1) {
try {
var state0 = {a: arg0, b: arg1};
var cb0 = (arg0, arg1) => {
const a = state0.a;
state0.a = 0;
try {
return __wbg_adapter_33(a, state0.b, arg0, arg1);
return __wbg_adapter_41(a, state0.b, arg0, arg1);
} finally {
state0.a = a;
}
@ -375,91 +463,56 @@ function getImports() {
state0.a = state0.b = 0;
}
};
imports.wbg.__wbg_newwithbyteoffsetandlength_9cc9adccd861aa26 = function(arg0, arg1, arg2) {
const ret = new Uint32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_new_949418f5ed1e29f7 = function(arg0) {
const ret = new Uint32Array(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_new_8c3f0052272a457a = function(arg0) {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_of_22ee6ea02403744c = function(arg0, arg1, arg2) {
const ret = Array.of(getObject(arg0), getObject(arg1), getObject(arg2));
return addHeapObject(ret);
};
imports.wbg.__wbg_call_168da88779e35f61 = function() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_getCandidatePathsForDebugFile_19de1ea293153630 = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).getCandidatePathsForDebugFile(takeObject(arg1));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_from_7ce3cb27cb258569 = function(arg0) {
const ret = Array.from(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_length_6e3bbe7c8bd4dbd8 = function(arg0) {
const ret = getObject(arg0).length;
return ret;
};
imports.wbg.__wbg_getCandidatePathsForBinary_8311cb7aeae90263 = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).getCandidatePathsForBinary(takeObject(arg1));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_readFile_33b95391c6839d48 = function(arg0, arg1, arg2) {
const ret = getObject(arg0).readFile(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
};
imports.wbg.__wbg_then_cedad20fbbd9418a = function(arg0, arg1, arg2) {
const ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
};
imports.wbg.__wbg_size_c5375fc90958b38d = function() { return handleError(function (arg0) {
const ret = getObject(arg0).size;
return ret;
}, arguments) };
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
imports.wbg.__wbg_then_11f7a54d67b4bfad = function(arg0, arg1) {
imports.wbg.__wbg_then_f9e58f5a50f43eae = function(arg0, arg1) {
const ret = getObject(arg0).then(getObject(arg1));
return addHeapObject(ret);
};
imports.wbg.__wbg_resolve_99fe17964f31ffc0 = function(arg0) {
imports.wbg.__wbg_queueMicrotask_f61ee94ee663068b = function(arg0) {
queueMicrotask(getObject(arg0));
};
imports.wbg.__wbg_queueMicrotask_f82fc5d1e8f816ae = function(arg0) {
const ret = getObject(arg0).queueMicrotask;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_is_function = function(arg0) {
const ret = typeof(getObject(arg0)) === 'function';
return ret;
};
imports.wbg.__wbg_resolve_5da6faf2c96fd1d5 = function(arg0) {
const ret = Promise.resolve(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper1912 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 143, __wbg_adapter_16);
imports.wbg.__wbindgen_closure_wrapper2106 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 159, __wbg_adapter_20);
return addHeapObject(ret);
};
return imports;
}
function initMemory(imports, maybe_memory) {
function __wbg_init_memory(imports, maybe_memory) {
}
function finalizeInit(instance, module) {
function __wbg_finalize_init(instance, module) {
wasm = instance.exports;
init.__wbindgen_wasm_module = module;
cachedInt32Memory0 = new Int32Array();
cachedUint8Memory0 = new Uint8Array();
__wbg_init.__wbindgen_wasm_module = module;
cachedInt32Memory0 = null;
cachedUint8Memory0 = null;
return wasm;
}
function initSync(module) {
const imports = getImports();
if (wasm !== undefined) return wasm;
initMemory(imports);
const imports = __wbg_get_imports();
__wbg_init_memory(imports);
if (!(module instanceof WebAssembly.Module)) {
module = new WebAssembly.Module(module);
@ -467,32 +520,28 @@ function initSync(module) {
const instance = new WebAssembly.Instance(module, imports);
return finalizeInit(instance, module);
return __wbg_finalize_init(instance, module);
}
async function init(input) {
if (typeof input === 'undefined') {
let src;
if (typeof document === 'undefined') {
src = location.href;
} else {
src = document.currentScript.src;
}
input = src.replace(/\.js$/, '_bg.wasm');
async function __wbg_init(input) {
if (wasm !== undefined) return wasm;
if (typeof input === 'undefined' && typeof script_src !== 'undefined') {
input = script_src.replace(/\.js$/, '_bg.wasm');
}
const imports = getImports();
const imports = __wbg_get_imports();
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
input = fetch(input);
}
initMemory(imports);
__wbg_init_memory(imports);
const { instance, module } = await load(await input, imports);
const { instance, module } = await __wbg_load(await input, imports);
return finalizeInit(instance, module);
return __wbg_finalize_init(instance, module);
}
wasm_bindgen = Object.assign(init, { initSync }, __exports);
wasm_bindgen = Object.assign(__wbg_init, { initSync }, __exports);
})();

View file

@ -45,11 +45,11 @@ const global = globalThis;
// The sha384 sum can be computed with the following command (tested on macOS):
// shasum -b -a 384 profiler_get_symbols_wasm_bg.wasm | awk '{ print $1 }' | xxd -r -p | base64
// Generated from https://github.com/mstange/profiler-get-symbols/commit/0373708893e45e8299e58ca692764be448e3457d
// Generated from https://github.com/mstange/profiler-get-symbols/commit/390b8c4be82c720dd3977ff205fb34bd7d0e00ba
const WASM_MODULE_URL =
"https://storage.googleapis.com/firefox-profiler-get-symbols/0373708893e45e8299e58ca692764be448e3457d.wasm";
"https://storage.googleapis.com/firefox-profiler-get-symbols/390b8c4be82c720dd3977ff205fb34bd7d0e00ba.wasm";
const WASM_MODULE_INTEGRITY =
"sha384-rUGgHTg1eAKP2MB4JcX/HGROSBlRUmvpm6FFIihH0gGQ74zfJE2p7P8cxR86faQ7";
"sha384-P8j6U9jY+M4zSfJKXb1ECjsTPkzQ0hAvgb4zv3gHvlg+THRtVpOrDSywHJBhin00";
const EXPIRY_TIME_IN_MS = 5 * 60 * 1000; // 5 minutes

View file

@ -481,7 +481,6 @@
padding: 3px 4px;
min-width: 100px;
-moz-user-focus: normal;
color: var(--theme-body-color);
}
.table-widget-cell[hidden] {

View file

@ -1838,7 +1838,11 @@ async function getImageSizeFromClipboard() {
trans.init(null);
trans.addDataFlavor(flavor);
clip.getData(trans, clipid.kGlobalClipboard);
clip.getData(
trans,
clipid.kGlobalClipboard,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
const data = {};
trans.getTransferData(flavor, data);

View file

@ -32,6 +32,7 @@
#include "mozilla/ScopeExit.h"
#include "mozilla/ScrollingMetrics.h"
#include "mozilla/SharedStyleSheetCache.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/IdleDeadline.h"
@ -618,22 +619,150 @@ static mozJSModuleLoader* GetContextualESLoader(
return mozJSModuleLoader::Get();
}
static mozJSModuleLoader* GetModuleLoaderForCurrentGlobal(
JSContext* aCx, const GlobalObject& aGlobal,
Maybe<loader::NonSharedGlobalSyncModuleLoaderScope>&
aMaybeSyncLoaderScope) {
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
if (mozJSModuleLoader::IsSharedSystemGlobal(global)) {
return mozJSModuleLoader::Get();
}
if (mozJSModuleLoader::IsDevToolsLoaderGlobal(global)) {
return mozJSModuleLoader::GetOrCreateDevToolsLoader();
}
if (loader::NonSharedGlobalSyncModuleLoaderScope::IsActive()) {
mozJSModuleLoader* moduleloader =
loader::NonSharedGlobalSyncModuleLoaderScope::ActiveLoader();
if (!moduleloader->IsLoaderGlobal(global->GetGlobalJSObject())) {
JS_ReportErrorASCII(aCx,
"global: \"current\" option cannot be used for "
"different global while other importESModule "
"with global: \"current\" is on the stack");
return nullptr;
}
return moduleloader;
}
RefPtr targetModuleLoader = global->GetModuleLoader(aCx);
if (!targetModuleLoader) {
// Sandbox without associated window returns nullptr for GetModuleLoader.
JS_ReportErrorASCII(aCx, "No ModuleLoader found for the current context");
return nullptr;
}
if (targetModuleLoader->HasFetchingModules()) {
if (!NS_IsMainThread()) {
JS_ReportErrorASCII(aCx,
"ChromeUtils.importESModule cannot be used in worker "
"when there is ongoing dynamic import");
return nullptr;
}
if (!mozilla::SpinEventLoopUntil(
"importESModule for current global"_ns, [&]() -> bool {
return !targetModuleLoader->HasFetchingModules();
})) {
JS_ReportErrorASCII(aCx, "Failed to wait for ongoing module requests");
return nullptr;
}
}
aMaybeSyncLoaderScope.emplace(aCx, global);
return aMaybeSyncLoaderScope->ActiveLoader();
}
static mozJSModuleLoader* GetModuleLoaderForOptions(
JSContext* aCx, const GlobalObject& aGlobal,
const ImportESModuleOptionsDictionary& aOptions,
Maybe<loader::NonSharedGlobalSyncModuleLoaderScope>&
aMaybeSyncLoaderScope) {
if (!aOptions.mGlobal.WasPassed()) {
return GetContextualESLoader(aOptions.mLoadInDevToolsLoader, aGlobal.Get());
}
switch (aOptions.mGlobal.Value()) {
case ImportESModuleTargetGlobal::Shared:
return mozJSModuleLoader::Get();
case ImportESModuleTargetGlobal::Devtools:
return mozJSModuleLoader::GetOrCreateDevToolsLoader();
case ImportESModuleTargetGlobal::Contextual: {
if (!NS_IsMainThread()) {
return GetModuleLoaderForCurrentGlobal(aCx, aGlobal,
aMaybeSyncLoaderScope);
}
RefPtr devToolsModuleloader = mozJSModuleLoader::GetDevToolsLoader();
if (devToolsModuleloader &&
devToolsModuleloader->IsLoaderGlobal(aGlobal.Get())) {
return mozJSModuleLoader::GetOrCreateDevToolsLoader();
}
return mozJSModuleLoader::Get();
}
case ImportESModuleTargetGlobal::Current:
return GetModuleLoaderForCurrentGlobal(aCx, aGlobal,
aMaybeSyncLoaderScope);
default:
MOZ_CRASH("Unknown ImportESModuleTargetGlobal");
}
}
static bool ValidateImportOptions(
JSContext* aCx, const ImportESModuleOptionsDictionary& aOptions) {
if (!NS_IsMainThread() &&
(!aOptions.mGlobal.WasPassed() ||
(aOptions.mGlobal.Value() != ImportESModuleTargetGlobal::Current &&
aOptions.mGlobal.Value() != ImportESModuleTargetGlobal::Contextual))) {
JS_ReportErrorASCII(aCx,
"ChromeUtils.importESModule: Only { global: "
"\"current\" } and { global: \"contextual\" } options "
"are supported on worker");
return false;
}
if (aOptions.mGlobal.WasPassed() &&
aOptions.mLoadInDevToolsLoader.WasPassed()) {
JS_ReportErrorASCII(aCx,
"global option and loadInDevToolsLoader option "
"cannot be used at the same time");
return false;
}
return true;
}
/* static */
void ChromeUtils::ImportESModule(
const GlobalObject& aGlobal, const nsAString& aResourceURI,
const ImportESModuleOptionsDictionary& aOptions,
JS::MutableHandle<JSObject*> aRetval, ErrorResult& aRv) {
RefPtr moduleloader =
GetContextualESLoader(aOptions.mLoadInDevToolsLoader, aGlobal.Get());
MOZ_ASSERT(moduleloader);
JSContext* cx = aGlobal.Context();
if (!ValidateImportOptions(cx, aOptions)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
Maybe<loader::NonSharedGlobalSyncModuleLoaderScope> maybeSyncLoaderScope;
RefPtr<mozJSModuleLoader> moduleloader =
GetModuleLoaderForOptions(cx, aGlobal, aOptions, maybeSyncLoaderScope);
if (!moduleloader) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
NS_ConvertUTF16toUTF8 registryLocation(aResourceURI);
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE(
"ChromeUtils::ImportESModule", OTHER, registryLocation);
JSContext* cx = aGlobal.Context();
JS::Rooted<JSObject*> moduleNamespace(cx);
nsresult rv =
moduleloader->ImportESModule(cx, registryLocation, &moduleNamespace);
@ -649,6 +778,10 @@ void ChromeUtils::ImportESModule(
return;
}
aRetval.set(moduleNamespace);
if (maybeSyncLoaderScope) {
maybeSyncLoaderScope->Finish();
}
}
namespace lazy_getter {

View file

@ -99,7 +99,11 @@ async function testCopyPaste(isXHTML) {
].createInstance(SpecialPowers.Ci.nsITransferable);
transferable.init(getLoadContext());
transferable.addDataFlavor(mime);
clipboard.getData(transferable, 1);
clipboard.getData(
transferable,
1,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
var data = SpecialPowers.createBlankObject();
transferable.getTransferData(mime, data);
return data;

View file

@ -58,7 +58,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=816298
.createInstance(SpecialPowers.Ci.nsITransferable);
transferable.init(getLoadContext());
transferable.addDataFlavor(mime);
clipboard.getData(transferable, 1);
clipboard.getData(transferable, 1, SpecialPowers.wrap(window).browsingContext.currentWindowContext);
var data = SpecialPowers.createBlankObject();
transferable.getTransferData(mime, data) ;
return SpecialPowers.wrap(data);

View file

@ -30,7 +30,7 @@ function testCopyImage () {
.QueryInterface(Ci.nsILoadContext);
transferable.init(loadingContext);
transferable.addDataFlavor(mime);
clipboard.getData(transferable, 1);
clipboard.getData(transferable, 1, SpecialPowers.wrap(window).browsingContext.currentWindowContext);
var data = SpecialPowers.createBlankObject();
transferable.getTransferData(mime, data);
return data;

View file

@ -59,7 +59,7 @@ waitUntilApzStable().then(async function() {
].createInstance(SpecialPowers.Ci.nsITransferable);
transferable.init(getLoadContext());
transferable.addDataFlavor(mime);
clipboard.getData(transferable, 1);
clipboard.getData(transferable, 1, SpecialPowers.wrap(window).browsingContext.currentWindowContext);
var data = SpecialPowers.createBlankObject();
transferable.getTransferData(mime, data);
return data;

View file

@ -313,6 +313,25 @@ namespace ChromeUtils {
[NewObject]
Promise<sequence<CDMInformation>> getGMPContentDecryptionModuleInformation();
/**
* Synchronously loads and evaluates the JS module source located at
* 'aResourceURI'.
*
* @param aResourceURI A resource:// URI string to load the module from.
* @param aOption An option to specify where to load the module into.
* @returns the module's namespace object.
*
* The implementation maintains a hash of aResourceURI->global obj.
* Subsequent invocations of import with 'aResourceURI' pointing to
* the same file will not cause the module to be re-evaluated.
*
* In worker threads, aOption is required and only { global: "current" } and
* { global: "contextual" } are supported.
*/
[Throws]
object importESModule(DOMString aResourceURI,
optional ImportESModuleOptionsDictionary aOptions = {});
/**
* IF YOU ADD NEW METHODS HERE, MAKE SURE THEY ARE THREAD-SAFE.
*/
@ -508,20 +527,6 @@ partial namespace ChromeUtils {
[Throws]
object import(UTF8String aResourceURI, optional object aTargetObj);
/**
* Synchronously loads and evaluates the JS module source located at
* 'aResourceURI'.
*
* @param aResourceURI A resource:// URI string to load the module from.
* @returns the module's namespace object.
*
* The implementation maintains a hash of aResourceURI->global obj.
* Subsequent invocations of import with 'aResourceURI' pointing to
* the same file will not cause the module to be re-evaluated.
*/
[Throws]
object importESModule(DOMString aResourceURI, optional ImportESModuleOptionsDictionary options = {});
/**
* Defines a property on the given target which lazily imports a JavaScript
* module when accessed.
@ -983,6 +988,41 @@ dictionary CompileScriptOptionsDictionary {
boolean hasReturnValue = false;
};
/**
* Where the modules are loaded into with importESModule.
*/
enum ImportESModuleTargetGlobal {
/**
* Load into the shared system global.
* This is the default value.
*/
"shared",
/**
* Load into a distinct system global for DevTools, so that the DevTools can
* load a distinct set of modules and do not interfere with its debuggee.
*/
"devtools",
/**
* If the current global is DevTools' distinct system global, load into the
* DevTools' distinct system global.
* If the current thread is worker thread, load into the current global.
* Otherwise load into the shared system global.
*
* This is a temporary workaround until DevTools modules are ESMified.
*/
"contextual",
/**
* Load into current global.
*
* This can be used for any global. If this is used for shared global or
* devtools global, this has the same effect as "shared" or "devtools".
*/
"current",
};
dictionary ImportESModuleOptionsDictionary {
/**
* If true, a distinct module loader will be used, in the system principal,
@ -990,6 +1030,8 @@ dictionary ImportESModuleOptionsDictionary {
* of modules and do not interfere with its debuggee.
*/
boolean loadInDevToolsLoader;
ImportESModuleTargetGlobal global;
};
/**

View file

@ -885,7 +885,7 @@ Console::Console(JSContext* aCx, nsIGlobalObject* aGlobal,
mInnerID(aInnerWindowID),
mDumpToStdout(false),
mChromeInstance(false),
mMaxLogLevel(ConsoleLogLevel::All),
mCurrentLogLevel(WebIDLLogLevelToInteger(ConsoleLogLevel::All)),
mStatus(eUnknown),
mCreationTimeStamp(TimeStamp::Now()) {
// Let's enable the dumping to stdout by default for chrome.
@ -2832,43 +2832,8 @@ void Console::ExecuteDumpFunction(const nsAString& aMessage) {
fflush(stdout);
}
ConsoleLogLevel PrefToValue(const nsAString& aPref,
const ConsoleLogLevel aLevel) {
if (!NS_IsMainThread()) {
NS_WARNING("Console.maxLogLevelPref is not supported on workers!");
return ConsoleLogLevel::All;
}
if (aPref.IsEmpty()) {
return aLevel;
}
NS_ConvertUTF16toUTF8 pref(aPref);
nsAutoCString value;
nsresult rv = Preferences::GetCString(pref.get(), value);
if (NS_WARN_IF(NS_FAILED(rv))) {
return aLevel;
}
int index = FindEnumStringIndexImpl(value.get(), value.Length(),
ConsoleLogLevelValues::strings);
if (NS_WARN_IF(index < 0)) {
nsString message;
message.AssignLiteral("Invalid Console.maxLogLevelPref value: ");
message.Append(NS_ConvertUTF8toUTF16(value));
nsContentUtils::LogSimpleConsoleError(message, "chrome"_ns, false,
true /* from chrome context*/);
return aLevel;
}
MOZ_ASSERT(index < (int)ConsoleLogLevelValues::Count);
return static_cast<ConsoleLogLevel>(index);
}
bool Console::ShouldProceed(MethodName aName) const {
ConsoleLogLevel maxLogLevel = PrefToValue(mMaxLogLevelPref, mMaxLogLevel);
return WebIDLLogLevelToInteger(maxLogLevel) <=
InternalLogLevelToInteger(aName);
return mCurrentLogLevel <= InternalLogLevelToInteger(aName);
}
uint32_t Console::WebIDLLogLevelToInteger(ConsoleLogLevel aLevel) const {

View file

@ -425,8 +425,7 @@ class Console final : public nsIObserver, public nsSupportsWeakReference {
bool mDumpToStdout;
nsString mPrefix;
bool mChromeInstance;
ConsoleLogLevel mMaxLogLevel;
nsString mMaxLogLevelPref;
uint32_t mCurrentLogLevel;
enum { eUnknown, eInitialized, eShuttingDown } mStatus;

View file

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ConsoleInstance.h"
#include "Console.h"
#include "mozilla/dom/ConsoleBinding.h"
#include "mozilla/Preferences.h"
#include "ConsoleCommon.h"
@ -44,7 +45,8 @@ ConsoleUtils::Level WebIDLevelToConsoleUtilsLevel(ConsoleLevel aLevel) {
ConsoleInstance::ConsoleInstance(JSContext* aCx,
const ConsoleInstanceOptions& aOptions)
: mConsole(new Console(aCx, nullptr, 0, 0)) {
: mMaxLogLevel(ConsoleLogLevel::All),
mConsole(new Console(aCx, nullptr, 0, 0)) {
mConsole->mConsoleID = aOptions.mConsoleID;
mConsole->mPassedInnerID = aOptions.mInnerID;
@ -58,27 +60,81 @@ ConsoleInstance::ConsoleInstance(JSContext* aCx,
mConsole->mChromeInstance = true;
if (aOptions.mMaxLogLevel.WasPassed()) {
mConsole->mMaxLogLevel = aOptions.mMaxLogLevel.Value();
mMaxLogLevel = aOptions.mMaxLogLevel.Value();
}
if (!aOptions.mMaxLogLevelPref.IsEmpty()) {
mConsole->mMaxLogLevelPref = aOptions.mMaxLogLevelPref;
NS_ConvertUTF16toUTF8 pref(aOptions.mMaxLogLevelPref);
nsAutoCString value;
nsresult rv = Preferences::GetCString(pref.get(), value);
if (NS_WARN_IF(NS_FAILED(rv))) {
nsString message;
message.AssignLiteral(
"Console.maxLogLevelPref used with a non-existing pref: ");
message.Append(aOptions.mMaxLogLevelPref);
nsContentUtils::LogSimpleConsoleError(message, "chrome"_ns, false,
true /* from chrome context*/);
if (!NS_IsMainThread()) {
NS_WARNING("Console.maxLogLevelPref is not supported on workers!");
// Set the log level based on what we have.
SetLogLevel();
return;
}
CopyUTF16toUTF8(aOptions.mMaxLogLevelPref, mMaxLogLevelPref);
Preferences::RegisterCallback(MaxLogLevelPrefChangedCallback,
mMaxLogLevelPref, this);
}
SetLogLevel();
}
ConsoleInstance::~ConsoleInstance() = default;
ConsoleInstance::~ConsoleInstance() {
AssertIsOnMainThread();
if (!mMaxLogLevelPref.IsEmpty()) {
Preferences::UnregisterCallback(MaxLogLevelPrefChangedCallback,
mMaxLogLevelPref, this);
}
};
ConsoleLogLevel PrefToValue(const nsACString& aPref,
const ConsoleLogLevel aLevel) {
if (aPref.IsEmpty()) {
return aLevel;
}
nsAutoCString value;
nsresult rv = Preferences::GetCString(PromiseFlatCString(aPref).get(), value);
if (NS_WARN_IF(NS_FAILED(rv))) {
nsString message;
message.AssignLiteral(
"Console.maxLogLevelPref used with a non-existing pref: ");
message.Append(NS_ConvertUTF8toUTF16(aPref));
nsContentUtils::LogSimpleConsoleError(message, "chrome"_ns, false,
true /* from chrome context*/);
return aLevel;
}
int index = FindEnumStringIndexImpl(value.get(), value.Length(),
ConsoleLogLevelValues::strings);
if (NS_WARN_IF(index < 0)) {
nsString message;
message.AssignLiteral("Invalid Console.maxLogLevelPref value: ");
message.Append(NS_ConvertUTF8toUTF16(value));
nsContentUtils::LogSimpleConsoleError(message, "chrome"_ns, false,
true /* from chrome context*/);
return aLevel;
}
MOZ_ASSERT(index < (int)ConsoleLogLevelValues::Count);
return static_cast<ConsoleLogLevel>(index);
}
void ConsoleInstance::SetLogLevel() {
mConsole->mCurrentLogLevel = mConsole->WebIDLLogLevelToInteger(
PrefToValue(mMaxLogLevelPref, mMaxLogLevel));
}
// static
void ConsoleInstance::MaxLogLevelPrefChangedCallback(
const char* /* aPrefName */, void* aSelf) {
AssertIsOnMainThread();
if (RefPtr console = static_cast<ConsoleInstance*>(aSelf)) {
console->SetLogLevel();
}
}
JSObject* ConsoleInstance::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
@ -188,6 +244,11 @@ void ConsoleInstance::Clear(JSContext* aCx) {
console->MethodInternal(aCx, Console::MethodClear, u"clear"_ns, data);
}
bool ConsoleInstance::ShouldLog(ConsoleLogLevel aLevel) {
return mConsole->mCurrentLogLevel <=
mConsole->WebIDLLogLevelToInteger(aLevel);
}
void ConsoleInstance::ReportForServiceWorkerScope(const nsAString& aScope,
const nsAString& aMessage,
const nsAString& aFilename,

View file

@ -96,6 +96,8 @@ class ConsoleInstance final : public nsISupports, public nsWrapperCache {
MOZ_CAN_RUN_SCRIPT
void Clear(JSContext* aCx);
bool ShouldLog(ConsoleLogLevel aLevel);
// For testing only.
void ReportForServiceWorkerScope(const nsAString& aScope,
const nsAString& aMessage,
@ -106,6 +108,12 @@ class ConsoleInstance final : public nsISupports, public nsWrapperCache {
private:
~ConsoleInstance();
void SetLogLevel();
static void MaxLogLevelPrefChangedCallback(const char* /* aPrefName */,
void* /* aClosure */);
ConsoleLogLevel mMaxLogLevel;
nsCString mMaxLogLevelPref;
RefPtr<Console> mConsole;
};

View file

@ -83,6 +83,9 @@ async function test() {
await SpecialPowers.pushPrefEnv({set: [["pref.test.console", "log"]]})
ConsoleTest.go(dumpFunction);
// ConsoleTest.go() has already tested the console without this preference.
// This test checks that the addition of the preference is tracked and
// correctly applied.
await SpecialPowers.pushPrefEnv({
set: [["pref.test.console.notset", "Log"]],
});

View file

@ -0,0 +1,35 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(async function test_shouldLog_maxLogLevel() {
let ci = console.createInstance({ maxLogLevel: "Warn" });
Assert.ok(
ci.shouldLog("Error"),
"Should return true for logging a higher level"
);
Assert.ok(
ci.shouldLog("Warn"),
"Should return true for logging the same level"
);
Assert.ok(
!ci.shouldLog("Debug"),
"Should return false for logging a lower level;"
);
});
add_task(async function test_shouldLog_maxLogLevelPref() {
Services.prefs.setStringPref("test.log", "Warn");
let ci = console.createInstance({ maxLogLevelPref: "test.log" });
Assert.ok(
!ci.shouldLog("Debug"),
"Should return false for logging a lower level;"
);
Services.prefs.setStringPref("test.log", "Debug");
Assert.ok(
ci.shouldLog("Debug"),
"Should return true for logging a lower level after pref update"
);
});

View file

@ -4,6 +4,8 @@ support-files = ""
["test_basic.js"]
["test_console_shouldLog.js"]
["test_failing_console_listener.js"]
["test_formatting.js"]

View file

@ -21,6 +21,7 @@
#include "imgIContainer.h"
#include "imgITools.h"
#include "nsComponentManagerUtils.h"
#include "nsGlobalWindowInner.h"
#include "nsIClipboard.h"
#include "nsIFile.h"
#include "nsIInputStream.h"
@ -172,7 +173,15 @@ void DataTransferItem::FillInExternalData() {
return;
}
nsresult rv = clipboard->GetData(trans, mDataTransfer->ClipboardType());
nsCOMPtr<nsIGlobalObject> global = mDataTransfer->GetGlobal();
WindowContext* windowContext = nullptr;
if (global) {
const auto* innerWindow = global->GetAsInnerWindow();
windowContext = innerWindow ? innerWindow->GetWindowContext() : nullptr;
}
MOZ_ASSERT(windowContext);
nsresult rv = clipboard->GetData(trans, mDataTransfer->ClipboardType(),
windowContext);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}

View file

@ -197,6 +197,7 @@
#include "nsICaptivePortalService.h"
#include "nsICertOverrideService.h"
#include "nsIClipboard.h"
#include "nsIContentAnalysis.h"
#include "nsIContentProcess.h"
#include "nsIContentSecurityPolicy.h"
#include "nsICookie.h"
@ -3462,8 +3463,23 @@ static Result<nsCOMPtr<nsITransferable>, nsresult> CreateTransferable(
mozilla::ipc::IPCResult ContentParent::RecvGetClipboard(
nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard,
const MaybeDiscarded<WindowContext>& aRequestingWindowContext,
IPCTransferableData* aTransferableData) {
nsresult rv;
// We expect content processes to always pass a non-null window so Content
// Analysis can analyze it. (if Content Analysis is active)
// There may be some cases when a window is closing, etc., in
// which case returning no clipboard content should not be a problem.
if (aRequestingWindowContext.IsDiscarded()) {
NS_WARNING(
"discarded window passed to RecvGetClipboard(); returning no clipboard "
"content");
return IPC_OK();
}
if (aRequestingWindowContext.IsNull()) {
return IPC_FAIL(this, "passed null window to RecvGetClipboard()");
}
RefPtr<WindowGlobalParent> window = aRequestingWindowContext.get_canonical();
// Retrieve clipboard
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
if (NS_FAILED(rv)) {
@ -3478,7 +3494,7 @@ mozilla::ipc::IPCResult ContentParent::RecvGetClipboard(
// Get data from clipboard
nsCOMPtr<nsITransferable> trans = result.unwrap();
clipboard->GetData(trans, aWhichClipboard);
clipboard->GetData(trans, aWhichClipboard, window);
nsContentUtils::TransferableToIPCTransferableData(
trans, aTransferableData, true /* aInSyncMessage */, this);

View file

@ -955,6 +955,7 @@ class ContentParent final : public PContentParent,
mozilla::ipc::IPCResult RecvGetClipboard(
nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard,
const MaybeDiscarded<WindowContext>& aRequestingWindowContext,
IPCTransferableData* aTransferableData);
mozilla::ipc::IPCResult RecvEmptyClipboard(const int32_t& aWhichClipboard);

View file

@ -1220,7 +1220,10 @@ parent:
// Given a list of supported types, returns the clipboard data for the
// first type that matches.
sync GetClipboard(nsCString[] aTypes, int32_t aWhichClipboard)
// aRequestingWindowContext is the window that is requesting the clipboard,
// which is used for content analysis.
sync GetClipboard(nsCString[] aTypes, int32_t aWhichClipboard,
MaybeDiscardedWindowContext aRequestingWindowContext)
returns (IPCTransferableData transferableData);
// Returns a list of formats supported by the clipboard

View file

@ -48,7 +48,11 @@ add_task(async function () {
);
trans.init(null);
trans.addDataFlavor(flavor);
Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
Services.clipboard.getData(
trans,
Services.clipboard.kGlobalClipboard,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
let data = {};
trans.getTransferData(flavor, data);

View file

@ -414,10 +414,14 @@ class RemoteVideoDecoder final : public RemoteDataDecoder {
if (ok && (size > 0 || presentationTimeUs >= 0)) {
// On certain devices SMPTE 432 color primaries are rendered incorrectly,
// so we force BT709 to be used instead. The magic number 10 comes from
// so we force BT709 to be used instead.
// Color space 10 comes from the video in bug 1866020 and corresponds to
// libstagefright's kColorStandardDCI_P3.
// 65800 comes from the video in bug 1879720 and is vendor-specific.
static bool isSmpte432Buggy = areSmpte432ColorPrimariesBuggy();
bool forceBT709ColorSpace = isSmpte432Buggy && mColorSpace == Some(10);
bool forceBT709ColorSpace =
isSmpte432Buggy &&
(mColorSpace == Some(10) || mColorSpace == Some(65800));
RefPtr<layers::Image> img = new layers::SurfaceTextureImage(
mSurfaceHandle, inputInfo.mImageSize, false /* NOT continuous */,

View file

@ -52,7 +52,7 @@ VideoCaptureFactory::CreateDeviceInfo(
// Special case when PipeWire is not initialized yet and we need to insert
// a camera device placeholder based on camera device availability we get
// from the camera portal
if (!mCameraBackendInitialized) {
if (!mCameraBackendInitialized && mVideoCaptureOptions->allow_pipewire()) {
MOZ_ASSERT(mCameraAvailability != Unknown);
deviceInfo.reset(
new PlaceholderDeviceInfo(mCameraAvailability == Available));
@ -106,6 +106,28 @@ auto VideoCaptureFactory::InitCameraBackend()
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_BSD)) && !defined(WEBRTC_ANDROID)
MOZ_ASSERT(mVideoCaptureOptions);
mVideoCaptureOptions->Init(this);
mPromise = mPromise->Then(
GetCurrentSerialEventTarget(), __func__,
[this, self = RefPtr(this)](
const CameraBackendInitPromise::ResolveOrRejectValue& aValue) {
if (aValue.IsReject() &&
aValue.RejectValue() != NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR) {
// Fallback to V4L2 in case of PipeWire or camera portal failure.
// There is nothing we need to do in order to initialize V4L2 so
// consider the backend initialized and ready to be used.
mVideoCaptureOptions->set_allow_pipewire(false);
mCameraBackendInitialized = true;
return CameraBackendInitPromise::CreateAndResolve(
NS_OK,
"VideoCaptureFactory::InitCameraBackend Resolve with "
"fallback to V4L2");
}
return CameraBackendInitPromise::CreateAndResolveOrReject(
aValue,
"VideoCaptureFactory::InitCameraBackend Resolve or Reject");
});
#else
mCameraBackendInitialized = true;
mPromiseHolder.Resolve(NS_OK,
@ -156,7 +178,7 @@ auto VideoCaptureFactory::HasCameraDevice()
}
#endif
return HasCameraDevicePromise::CreateAndReject(
NS_ERROR_NOT_IMPLEMENTED, "VideoCaptureFactory::HasCameraDevice Resolve");
NS_ERROR_NOT_IMPLEMENTED, "VideoCaptureFactory::HasCameraDevice Reject");
}
auto VideoCaptureFactory::UpdateCameraAvailability()
@ -173,7 +195,11 @@ auto VideoCaptureFactory::UpdateCameraAvailability()
"VideoCaptureFactory::UpdateCameraAvailability Resolve");
}
mCameraAvailability = Unknown;
// We want to fallback to V4L2 at this point, therefore make sure a
// camera device is announced so we can proceed with a gUM request,
// where we can fallback to V4L2 backend.
mCameraAvailability = Available;
return HasCameraDevicePromise::CreateAndReject(
aValue.RejectValue(),
"VideoCaptureFactory::UpdateCameraAvailability Reject");

View file

@ -49,9 +49,7 @@ already_AddRefed<BindGroupLayout> ComputePipeline::GetBindGroupLayout(
const RawId bglId = ffi::wgpu_client_compute_pipeline_get_bind_group_layout(
client, mId, aIndex, ToFFI(&bb));
if (!bridge->SendDeviceAction(mParent->GetId(), std::move(bb))) {
MOZ_CRASH("IPC failure");
}
bridge->SendDeviceAction(mParent->GetId(), std::move(bb));
RefPtr<BindGroupLayout> object = new BindGroupLayout(mParent, bglId, false);
return object.forget();

View file

@ -102,10 +102,8 @@ void Queue::WriteBuffer(const Buffer& aBuffer, uint64_t aBufferOffset,
memcpy(mapping.Bytes().data(), aData.Elements() + aDataOffset, size);
ipc::ByteBuf bb;
ffi::wgpu_queue_write_buffer(aBuffer.mId, aBufferOffset, ToFFI(&bb));
if (!mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
std::move(handle))) {
MOZ_CRASH("IPC failure");
}
mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
std::move(handle));
});
}
@ -149,10 +147,8 @@ void Queue::WriteTexture(const dom::GPUImageCopyTexture& aDestination,
ipc::ByteBuf bb;
ffi::wgpu_queue_write_texture(copyView, dataLayout, extent, ToFFI(&bb));
if (!mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
std::move(handle))) {
MOZ_CRASH("IPC failure");
}
mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
std::move(handle));
});
}
@ -410,10 +406,8 @@ void Queue::CopyExternalImageToTexture(
CommandEncoder::ConvertTextureCopyViewToFFI(aDestination, &copyView);
ipc::ByteBuf bb;
ffi::wgpu_queue_write_texture(copyView, dataLayout, extent, ToFFI(&bb));
if (!mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
std::move(handle))) {
MOZ_CRASH("IPC failure");
}
mBridge->SendQueueWriteAction(mId, mParent->mId, std::move(bb),
std::move(handle));
}
} // namespace mozilla::webgpu

View file

@ -60,10 +60,9 @@ ffi::WGPURenderBundleEncoder* CreateRenderBundleEncoder(
ipc::ByteBuf failureAction;
auto* bundle = ffi::wgpu_device_create_render_bundle_encoder(
aDeviceId, &desc, ToFFI(&failureAction));
// report an error only if the operation failed
if (!bundle &&
!aBridge->SendDeviceAction(aDeviceId, std::move(failureAction))) {
MOZ_CRASH("IPC failure");
// Report an error only if the operation failed.
if (!bundle) {
aBridge->SendDeviceAction(aDeviceId, std::move(failureAction));
}
return bundle;
}

View file

@ -49,9 +49,7 @@ already_AddRefed<BindGroupLayout> RenderPipeline::GetBindGroupLayout(
const RawId bglId = ffi::wgpu_client_render_pipeline_get_bind_group_layout(
client, mId, aIndex, ToFFI(&bb));
if (!bridge->SendDeviceAction(mParent->GetId(), std::move(bb))) {
MOZ_CRASH("IPC failure");
}
bridge->SendDeviceAction(mParent->GetId(), std::move(bb));
RefPtr<BindGroupLayout> object = new BindGroupLayout(mParent, bglId, false);
return object.forget();

View file

@ -113,9 +113,7 @@ RawId WebGPUChild::RenderBundleEncoderFinish(
RawId id = ffi::wgpu_client_create_render_bundle(
mClient.get(), &aEncoder, aDeviceId, &desc, ToFFI(&bb));
if (!SendDeviceAction(aDeviceId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
SendDeviceAction(aDeviceId, std::move(bb));
return id;
}
@ -128,9 +126,7 @@ RawId WebGPUChild::RenderBundleEncoderFinishError(RawId aDeviceId,
RawId id = ffi::wgpu_client_create_render_bundle_error(
mClient.get(), aDeviceId, label.Get(), ToFFI(&bb));
if (!SendDeviceAction(aDeviceId, std::move(bb))) {
MOZ_CRASH("IPC failure");
}
SendDeviceAction(aDeviceId, std::move(bb));
return id;
}

View file

@ -198,6 +198,10 @@ interface ConsoleInstance {
undefined profile(any... data);
undefined profileEnd(any... data);
// Returns true if the given level would log a message. Used for avoiding
// long/significant processing when logging messages.
boolean shouldLog(ConsoleLogLevel level);
};
callback ConsoleInstanceDumpCallback = undefined (DOMString message);

View file

@ -2323,7 +2323,12 @@ nsresult HTMLEditor::PasteInternal(int32_t aClipboardType) {
return NS_ERROR_FAILURE;
}
// Get the Data from the clipboard
rv = clipboard->GetData(transferable, aClipboardType);
auto* windowContext = GetDocument()->GetWindowContext();
if (!windowContext) {
NS_WARNING("No window context");
return NS_ERROR_FAILURE;
}
rv = clipboard->GetData(transferable, aClipboardType, windowContext);
if (NS_FAILED(rv)) {
NS_WARNING("nsIClipboard::GetData() failed");
return rv;
@ -2357,7 +2362,8 @@ nsresult HTMLEditor::PasteInternal(int32_t aClipboardType) {
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsITransferable::AddDataFlavor(kHTMLContext) failed, but ignored");
rvIgnored = clipboard->GetData(contextTransferable, aClipboardType);
rvIgnored =
clipboard->GetData(contextTransferable, aClipboardType, windowContext);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"nsIClipboard::GetData() failed, but ignored");
nsCOMPtr<nsISupports> contextDataObj;
@ -2387,7 +2393,9 @@ nsresult HTMLEditor::PasteInternal(int32_t aClipboardType) {
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsITransferable::AddDataFlavor(kHTMLInfo) failed, but ignored");
clipboard->GetData(infoTransferable, aClipboardType);
rvIgnored =
clipboard->GetData(infoTransferable, aClipboardType, windowContext);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"nsIClipboard::GetData() failed, but ignored");
nsCOMPtr<nsISupports> infoDataObj;
@ -2553,6 +2561,11 @@ nsresult HTMLEditor::PasteNoFormattingAsAction(
NS_WARNING("Editor didn't have document, but ignored");
return NS_OK;
}
auto* windowContext = GetDocument()->GetWindowContext();
if (!windowContext) {
NS_WARNING("Editor didn't have document window context, but ignored");
return NS_OK;
}
Result<nsCOMPtr<nsITransferable>, nsresult> maybeTransferable =
EditorUtils::CreateTransferableForPlainText(*GetDocument());
@ -2573,7 +2586,7 @@ nsresult HTMLEditor::PasteNoFormattingAsAction(
}
// Get the Data from the clipboard
rv = clipboard->GetData(transferable, aClipboardType);
rv = clipboard->GetData(transferable, aClipboardType, windowContext);
if (NS_FAILED(rv)) {
NS_WARNING("nsIClipboard::GetData() failed");
return rv;
@ -2817,6 +2830,12 @@ nsresult HTMLEditor::PasteAsPlaintextQuotation(int32_t aSelectionType) {
}
RefPtr<Document> destdoc = GetDocument();
auto* windowContext = GetDocument()->GetWindowContext();
if (!windowContext) {
NS_WARNING("Editor didn't have document window context");
return NS_ERROR_FAILURE;
}
nsILoadContext* loadContext = destdoc ? destdoc->GetLoadContext() : nullptr;
DebugOnly<nsresult> rvIgnored = transferable->Init(loadContext);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
@ -2829,7 +2848,7 @@ nsresult HTMLEditor::PasteAsPlaintextQuotation(int32_t aSelectionType) {
"nsITransferable::AddDataFlavor(kTextMime) failed, but ignored");
// Get the Data from the clipboard
rvIgnored = clipboard->GetData(transferable, aSelectionType);
rvIgnored = clipboard->GetData(transferable, aSelectionType, windowContext);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"nsIClipboard::GetData() failed, but ignored");

View file

@ -599,8 +599,13 @@ nsresult TextEditor::HandlePasteAsQuotation(
return NS_OK;
}
auto* windowContext = GetDocument()->GetWindowContext();
if (!windowContext) {
NS_WARNING("Editor didn't have document window context");
return NS_ERROR_FAILURE;
}
// Get the Data from the clipboard
clipboard->GetData(trans, aClipboardType);
rv = clipboard->GetData(trans, aClipboardType, windowContext);
// Now we ask the transferable for the data
// it still owns the data, we just have a pointer to it.

View file

@ -193,7 +193,13 @@ nsresult TextEditor::HandlePaste(AutoEditActionDataSetter& aEditActionData,
return NS_OK; // XXX Why?
}
// Get the Data from the clipboard.
rv = clipboard->GetData(transferable, aClipboardType);
auto* windowContext = GetDocument()->GetWindowContext();
if (!windowContext) {
NS_WARNING("Editor didn't have document window context");
return NS_ERROR_FAILURE;
}
rv = clipboard->GetData(transferable, aClipboardType, windowContext);
if (NS_FAILED(rv)) {
NS_WARNING("nsIClipboard::GetData() failed, but ignored");
return NS_OK; // XXX Why?

View file

@ -52,7 +52,7 @@ function copyCF_HTML(cfhtml, success, failure) {
createInstance(Ci.nsITransferable);
trans.init(getLoadContext());
trans.addDataFlavor(CF_HTML);
cb.getData(trans, cb.kGlobalClipboard);
cb.getData(trans, cb.kGlobalClipboard, SpecialPowers.wrap(window).browsingContext.currentWindowContext);
var data = SpecialPowers.createBlankObject();
try {
trans.getTransferData(CF_HTML, data);

View file

@ -63,7 +63,7 @@ async function runTest() {
trans.addDataFlavor("text/plain");
}
var clip = SpecialPowers.Services.clipboard;
clip.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
clip.getData(trans, Ci.nsIClipboard.kGlobalClipboard, SpecialPowers.wrap(window).browsingContext.currentWindowContext);
return trans;
}

View file

@ -101,6 +101,8 @@ class SourceSurfaceRecording : public SourceSurface {
return nullptr;
}
already_AddRefed<SourceSurface> ExtractSubrect(const IntRect& aRect) override;
IntSize mSize;
SurfaceFormat mFormat;
RefPtr<DrawEventRecorderPrivate> mRecorder;
@ -493,6 +495,18 @@ already_AddRefed<SourceSurface> DrawTargetRecording::IntoLuminanceSource(
return retSurf.forget();
}
already_AddRefed<SourceSurface> SourceSurfaceRecording::ExtractSubrect(
const IntRect& aRect) {
if (aRect.IsEmpty() || !GetRect().Contains(aRect)) {
return nullptr;
}
RefPtr<SourceSurface> subSurf =
new SourceSurfaceRecording(aRect.Size(), mFormat, mRecorder);
mRecorder->RecordEvent(RecordedExtractSubrect(subSurf, this, aRect));
return subSurf.forget();
}
void DrawTargetRecording::Flush() {
mRecorder->RecordEvent(this, RecordedFlush());
}

View file

@ -418,6 +418,7 @@ class RecordedEvent {
UNSCALEDFONTCREATION,
UNSCALEDFONTDESTRUCTION,
INTOLUMINANCE,
EXTRACTSUBRECT,
EXTERNALSURFACECREATION,
FLUSH,
DETACHALLSNAPSHOTS,

View file

@ -1342,6 +1342,35 @@ class RecordedIntoLuminanceSource
MOZ_IMPLICIT RecordedIntoLuminanceSource(S& aStream);
};
class RecordedExtractSubrect
: public RecordedEventDerived<RecordedExtractSubrect> {
public:
RecordedExtractSubrect(ReferencePtr aRefPtr, ReferencePtr aSourceSurface,
const IntRect& aSubrect)
: RecordedEventDerived(EXTRACTSUBRECT),
mRefPtr(aRefPtr),
mSourceSurface(aSourceSurface),
mSubrect(aSubrect) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "ExtractSubrect"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
ReferencePtr mSourceSurface;
IntRect mSubrect;
template <class S>
MOZ_IMPLICIT RecordedExtractSubrect(S& aStream);
};
class RecordedFontData : public RecordedEventDerived<RecordedFontData> {
public:
static void FontDataProc(const uint8_t* aData, uint32_t aSize,
@ -3662,6 +3691,50 @@ inline void RecordedIntoLuminanceSource::OutputSimpleEventInfo(
aStringStream << "[" << mRefPtr << "] Into Luminance Source";
}
inline bool RecordedExtractSubrect::PlayEvent(Translator* aTranslator) const {
SourceSurface* sourceSurf = aTranslator->LookupSourceSurface(mSourceSurface);
if (!sourceSurf) {
return false;
}
RefPtr<SourceSurface> subSurf = sourceSurf->ExtractSubrect(mSubrect);
if (!subSurf) {
RefPtr<DrawTarget> dt =
aTranslator->GetReferenceDrawTarget()->CreateSimilarDrawTarget(
mSubrect.Size(), sourceSurf->GetFormat());
if (dt) {
dt->CopySurface(sourceSurf, mSubrect, IntPoint());
subSurf = dt->Snapshot();
}
}
if (!subSurf) {
return false;
}
aTranslator->AddSourceSurface(mRefPtr, subSurf);
return true;
}
template <class S>
void RecordedExtractSubrect::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mSourceSurface);
WriteElement(aStream, mSubrect);
}
template <class S>
RecordedExtractSubrect::RecordedExtractSubrect(S& aStream)
: RecordedEventDerived(EXTRACTSUBRECT) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mSourceSurface);
ReadElement(aStream, mSubrect);
}
inline void RecordedExtractSubrect::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] Exract Subrect";
}
inline bool RecordedFlush::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
@ -4335,6 +4408,7 @@ inline void RecordedDestination::OutputSimpleEventInfo(
f(UNSCALEDFONTCREATION, RecordedUnscaledFontCreation); \
f(UNSCALEDFONTDESTRUCTION, RecordedUnscaledFontDestruction); \
f(INTOLUMINANCE, RecordedIntoLuminanceSource); \
f(EXTRACTSUBRECT, RecordedExtractSubrect); \
f(EXTERNALSURFACECREATION, RecordedExternalSurfaceCreation); \
f(FLUSH, RecordedFlush); \
f(DETACHALLSNAPSHOTS, RecordedDetachAllSnapshots); \

View file

@ -1866,6 +1866,14 @@ bool NativeLayerCA::Representation::ApplyChanges(
IOSurfaceRef surface = aFrontSurface.get();
if (aSpecializeVideo) {
// If we just rebuilt our layer, ensure the first frame is visible by
// forcing the layer contents to display that frame. Our call to
// enqueueSampleBuffer will handle future async updates to the layer;
// buffers queued with enqueueSampleBuffer overwrite the layer contents.
if (layerNeedsInitialization) {
mContentCALayer.contents = (id)surface;
}
// Attempt to enqueue this as a video frame. If we fail, we'll rebuild
// our video layer in the next update.
bool isEnqueued = EnqueueSurface(surface);

View file

@ -129,6 +129,11 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
void AttachSurface() { mDetached = false; }
void DetachSurface() { mDetached = true; }
already_AddRefed<gfx::SourceSurface> ExtractSubrect(
const gfx::IntRect& aRect) final {
return mRecordedSurface->ExtractSubrect(aRect);
}
private:
void EnsureDataSurfaceOnMainThread() {
// The data can only be retrieved on the main thread.

View file

@ -46,6 +46,14 @@ const MAX_BUFFER_SIZE_U32: u32 = MAX_BUFFER_SIZE as u32;
// Mesa has issues with height/depth that don't fit in a 16 bits signed integers.
const MAX_TEXTURE_EXTENT: u32 = std::i16::MAX as u32;
// We have to restrict the number of bindings for any given resource type so that
// the sum of these limits multiplied by the number of shader stages fits
// maxBindingsPerBindGroup (1000). This restriction is arbitrary and is likely to
// change eventually. See github.com/gpuweb/gpuweb/pull/4484
// For now it's impractical for users to have very large numbers of bindings so this
// limit should not be too restrictive until we add support for a bindless API.
// Then we may have to ignore the spec or get it changed.
const MAX_BINDINGS_PER_RESOURCE_TYPE: u32 = 64;
fn restrict_limits(limits: wgt::Limits) -> wgt::Limits {
wgt::Limits {
@ -55,12 +63,19 @@ fn restrict_limits(limits: wgt::Limits) -> wgt::Limits {
max_texture_dimension_3d: limits.max_texture_dimension_3d.min(MAX_TEXTURE_EXTENT),
max_sampled_textures_per_shader_stage: limits
.max_sampled_textures_per_shader_stage
.min(256),
max_samplers_per_shader_stage: limits.max_samplers_per_shader_stage.min(256),
.min(MAX_BINDINGS_PER_RESOURCE_TYPE),
max_samplers_per_shader_stage: limits
.max_samplers_per_shader_stage
.min(MAX_BINDINGS_PER_RESOURCE_TYPE),
max_storage_textures_per_shader_stage: limits
.max_storage_textures_per_shader_stage
.min(256),
max_uniform_buffers_per_shader_stage: limits.max_uniform_buffers_per_shader_stage.min(256),
.min(MAX_BINDINGS_PER_RESOURCE_TYPE),
max_uniform_buffers_per_shader_stage: limits
.max_uniform_buffers_per_shader_stage
.min(MAX_BINDINGS_PER_RESOURCE_TYPE),
max_storage_buffers_per_shader_stage: limits
.max_storage_buffers_per_shader_stage
.min(MAX_BINDINGS_PER_RESOURCE_TYPE),
max_uniform_buffer_binding_size: limits
.max_uniform_buffer_binding_size
.min(MAX_BUFFER_SIZE_U32),

31
gfx/wr/Cargo.lock generated
View file

@ -180,9 +180,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.0"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
dependencies = [
"serde",
]
@ -996,9 +996,9 @@ dependencies = [
[[package]]
name = "glean"
version = "56.1.0"
version = "57.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12e51799c1e40ba51f24e0ff232d35ea321403920bea31dc11de1afaeb541ef"
checksum = "ae5847ad58b7f925c984de7f4dffcad67d7d0befa59a5a888cf93741b5ef1e6a"
dependencies = [
"chrono",
"crossbeam-channel",
@ -1016,9 +1016,9 @@ dependencies = [
[[package]]
name = "glean-core"
version = "56.1.0"
version = "57.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f7570206325e7a20c45b60bf63f1f5b69c2ce0ee79ca0dc774e7c39eaab19aa"
checksum = "6831cadd28b625bc296732d71dc7c978f208ba27911cad072785f87f23b1e634"
dependencies = [
"android_logger",
"bincode",
@ -1556,12 +1556,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.16"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
dependencies = [
"cfg-if 1.0.0",
]
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "malloc_buf"
@ -2262,13 +2259,13 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rkv"
version = "0.18.4"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f0ea3af1393b22f8fe25615b6fa5d13072b7b622e66acffc8b12b2baa0342b1"
checksum = "2c6d906922d99c677624d2042a93f89b2b7df0f6411032237d5d99a602c2487c"
dependencies = [
"arrayref",
"bincode",
"bitflags 1.3.2",
"bitflags 2.4.2",
"byteorder",
"id-arena",
"lazy_static",
@ -3072,7 +3069,7 @@ name = "webrender"
version = "0.62.0"
dependencies = [
"bincode",
"bitflags 2.4.0",
"bitflags 2.4.2",
"build-parallel",
"byteorder",
"derive_more",
@ -3127,7 +3124,7 @@ name = "webrender_api"
version = "0.62.0"
dependencies = [
"app_units",
"bitflags 2.4.0",
"bitflags 2.4.2",
"byteorder",
"crossbeam-channel",
"euclid",
@ -3144,7 +3141,7 @@ dependencies = [
name = "webrender_build"
version = "0.0.2"
dependencies = [
"bitflags 2.4.0",
"bitflags 2.4.2",
"lazy_static",
"serde",
]

View file

@ -52,7 +52,7 @@ svg_fmt = "0.4"
tracy-rs = "0.1.2"
derive_more = { version = "0.99", default-features = false, features = ["add_assign"] }
etagere = "0.2.6"
glean = "56.1.0"
glean = "57.0.0"
firefox-on-glean = { version = "0.1.0", optional = true }
swgl = { path = "../swgl", optional = true }
topological-sort = "0.1"

View file

@ -1480,7 +1480,10 @@ impl Device {
// On debug builds, assert that each GL call is error-free. We don't do
// this on release builds because the synchronous call can stall the
// pipeline.
let supports_khr_debug = supports_extension(&extensions, "GL_KHR_debug");
// We block this on Mali Valhall GPUs as the extension's functions always return
// GL_OUT_OF_MEMORY, causing us to panic in debug builds.
let supports_khr_debug =
supports_extension(&extensions, "GL_KHR_debug") && !is_mali_valhall(&renderer_name);
if panic_on_gl_error || cfg!(debug_assertions) {
gl = gl::ErrorReactingGl::wrap(gl, move |gl, name, code| {
if supports_khr_debug {

View file

@ -689,7 +689,7 @@ pub fn create_webrender_instance(
let debug_method = if !options.enable_gpu_markers {
// The GPU markers are disabled.
GpuDebugMethod::None
} else if device.supports_extension("GL_KHR_debug") {
} else if device.get_capabilities().supports_khr_debug {
GpuDebugMethod::KHR
} else if device.supports_extension("GL_EXT_debug_marker") {
GpuDebugMethod::MarkerEXT

View file

@ -25,7 +25,7 @@ tracy-rs = "0.1.2"
log = "0.4"
lazy_static = "1"
fxhash = "0.2.1"
glean = { version = "56.1.0", optional = true }
glean = { version = "57.0.0", optional = true }
firefox-on-glean = { version = "0.1.0", optional = true }
serde = { optional = true, version = "1.0", features = ["serde_derive"] }

View file

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ScriptLoadContext.h"
#include "mozilla/loader/ComponentModuleLoader.h"
#include "mozilla/loader/SyncModuleLoader.h"
#include "mozilla/dom/WorkerLoadContext.h"
#include "mozilla/dom/worklet/WorkletModuleLoader.h" // WorkletLoadContext
#include "js/loader/LoadContextBase.h"
@ -42,9 +42,9 @@ mozilla::dom::ScriptLoadContext* LoadContextBase::AsWindowContext() {
return static_cast<mozilla::dom::ScriptLoadContext*>(this);
}
mozilla::loader::ComponentLoadContext* LoadContextBase::AsComponentContext() {
MOZ_ASSERT(IsComponentContext());
return static_cast<mozilla::loader::ComponentLoadContext*>(this);
mozilla::loader::SyncLoadContext* LoadContextBase::AsSyncContext() {
MOZ_ASSERT(IsSyncContext());
return static_cast<mozilla::loader::SyncLoadContext*>(this);
}
mozilla::dom::WorkerLoadContext* LoadContextBase::AsWorkerContext() {

View file

@ -17,7 +17,7 @@ class WorkletLoadContext;
} // namespace mozilla::dom
namespace mozilla::loader {
class ComponentLoadContext;
class SyncLoadContext;
}
namespace JS::loader {
@ -32,7 +32,7 @@ class ScriptLoadRequest;
*
*/
enum class ContextKind { Window, Component, Worker, Worklet };
enum class ContextKind { Window, Sync, Worker, Worklet };
class LoadContextBase : public nsISupports {
private:
@ -56,8 +56,8 @@ class LoadContextBase : public nsISupports {
bool IsWindowContext() const { return mKind == ContextKind::Window; }
mozilla::dom::ScriptLoadContext* AsWindowContext();
bool IsComponentContext() const { return mKind == ContextKind::Component; }
mozilla::loader::ComponentLoadContext* AsComponentContext();
bool IsSyncContext() const { return mKind == ContextKind::Sync; }
mozilla::loader::SyncLoadContext* AsSyncContext();
bool IsWorkerContext() const { return mKind == ContextKind::Worker; }
mozilla::dom::WorkerLoadContext* AsWorkerContext();

View file

@ -20,11 +20,13 @@
#include "js/Modules.h" // JS::FinishDynamicModuleImport, JS::{G,S}etModuleResolveHook, JS::Get{ModulePrivate,ModuleScript,RequestedModule{s,Specifier,SourcePos}}, JS::SetModule{DynamicImport,Metadata}Hook
#include "js/PropertyAndElement.h" // JS_DefineProperty, JS_GetElement
#include "js/SourceText.h"
#include "mozilla/Assertions.h" // MOZ_ASSERT
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/ScriptLoadContext.h"
#include "mozilla/CycleCollectedJSContext.h" // nsAutoMicroTask
#include "mozilla/Preferences.h"
#include "mozilla/RefPtr.h" // mozilla::StaticRefPtr
#include "mozilla/StaticPrefs_dom.h"
#include "nsContentUtils.h"
#include "nsICacheInfoChannel.h" // nsICacheInfoChannel
@ -342,6 +344,34 @@ bool ModuleLoaderBase::HostImportModuleDynamically(
return true;
}
AutoOverrideModuleLoader::AutoOverrideModuleLoader(ModuleLoaderBase* aTarget,
ModuleLoaderBase* aLoader)
: mTarget(aTarget) {
mTarget->SetOverride(aLoader);
}
AutoOverrideModuleLoader::~AutoOverrideModuleLoader() {
mTarget->ResetOverride();
}
void ModuleLoaderBase::SetOverride(ModuleLoaderBase* aLoader) {
MOZ_ASSERT(!mOverriddenBy);
MOZ_ASSERT(!aLoader->mOverriddenBy);
MOZ_ASSERT(mGlobalObject == aLoader->mGlobalObject);
mOverriddenBy = aLoader;
}
bool ModuleLoaderBase::IsOverridden() { return !!mOverriddenBy; }
bool ModuleLoaderBase::IsOverriddenBy(ModuleLoaderBase* aLoader) {
return mOverriddenBy == aLoader;
}
void ModuleLoaderBase::ResetOverride() {
MOZ_ASSERT(mOverriddenBy);
mOverriddenBy = nullptr;
}
// static
ModuleLoaderBase* ModuleLoaderBase::GetCurrentModuleLoader(JSContext* aCx) {
auto reportError = mozilla::MakeScopeExit([aCx]() {
@ -366,6 +396,11 @@ ModuleLoaderBase* ModuleLoaderBase::GetCurrentModuleLoader(JSContext* aCx) {
MOZ_ASSERT(loader->mGlobalObject == global);
reportError.release();
if (loader->mOverriddenBy) {
MOZ_ASSERT(loader->mOverriddenBy->mGlobalObject == global);
return loader->mOverriddenBy;
}
return loader;
}
@ -1012,6 +1047,10 @@ void ModuleLoaderBase::Shutdown() {
mLoader = nullptr;
}
bool ModuleLoaderBase::HasFetchingModules() const {
return !mFetchingModules.IsEmpty();
}
bool ModuleLoaderBase::HasPendingDynamicImports() const {
return !mDynamicImportRequests.isEmpty();
}
@ -1183,7 +1222,10 @@ nsresult ModuleLoaderBase::EvaluateModuleInContext(
JSContext* aCx, ModuleLoadRequest* aRequest,
JS::ModuleErrorBehaviour errorBehaviour) {
MOZ_ASSERT(aRequest->mLoader == this);
MOZ_ASSERT(mGlobalObject->GetModuleLoader(aCx) == this);
MOZ_ASSERT_IF(!mGlobalObject->GetModuleLoader(aCx)->IsOverridden(),
mGlobalObject->GetModuleLoader(aCx) == this);
MOZ_ASSERT_IF(mGlobalObject->GetModuleLoader(aCx)->IsOverridden(),
mGlobalObject->GetModuleLoader(aCx)->IsOverriddenBy(this));
AUTO_PROFILER_LABEL("ModuleLoaderBase::EvaluateModule", JS);
@ -1347,6 +1389,42 @@ void ModuleLoaderBase::RegisterImportMap(UniquePtr<ImportMap> aImportMap) {
mImportMap = std::move(aImportMap);
}
void ModuleLoaderBase::CopyModulesTo(ModuleLoaderBase* aDest) {
MOZ_ASSERT(aDest->mFetchingModules.IsEmpty());
MOZ_ASSERT(aDest->mFetchedModules.IsEmpty());
MOZ_ASSERT(mFetchingModules.IsEmpty());
for (const auto& entry : mFetchedModules) {
RefPtr<ModuleScript> moduleScript = entry.GetData();
if (!moduleScript) {
continue;
}
aDest->mFetchedModules.InsertOrUpdate(entry.GetKey(), moduleScript);
}
}
void ModuleLoaderBase::MoveModulesTo(ModuleLoaderBase* aDest) {
MOZ_ASSERT(mFetchingModules.IsEmpty());
MOZ_ASSERT(aDest->mFetchingModules.IsEmpty());
for (const auto& entry : mFetchedModules) {
RefPtr<ModuleScript> moduleScript = entry.GetData();
if (!moduleScript) {
continue;
}
#ifdef DEBUG
if (auto existingEntry = aDest->mFetchedModules.Lookup(entry.GetKey())) {
MOZ_ASSERT(moduleScript == existingEntry.Data());
}
#endif
aDest->mFetchedModules.InsertOrUpdate(entry.GetKey(), moduleScript);
}
mFetchedModules.Clear();
}
#undef LOG
#undef LOG_ENABLED

View file

@ -21,6 +21,7 @@
#include "nsINode.h" // nsIURI
#include "nsThreadUtils.h" // GetMainThreadSerialEventTarget
#include "nsURIHashKey.h"
#include "mozilla/Attributes.h" // MOZ_RAII
#include "mozilla/CORSMode.h"
#include "mozilla/dom/JSExecutionContext.h"
#include "mozilla/MaybeOneOf.h"
@ -185,6 +186,11 @@ class ModuleLoaderBase : public nsISupports {
nsCOMPtr<nsIGlobalObject> mGlobalObject;
// If non-null, this module loader is overridden by the module loader pointed
// by mOverriddenBy.
// See ModuleLoaderBase::GetCurrentModuleLoader for more details.
RefPtr<ModuleLoaderBase> mOverriddenBy;
// https://html.spec.whatwg.org/multipage/webappapis.html#import-maps-allowed
//
// Each Window has an import maps allowed boolean, initially true.
@ -276,6 +282,8 @@ class ModuleLoaderBase : public nsISupports {
nsIGlobalObject* GetGlobalObject() const { return mGlobalObject; }
bool HasFetchingModules() const;
bool HasPendingDynamicImports() const;
void CancelDynamicImport(ModuleLoadRequest* aRequest, nsresult aResult);
#ifdef DEBUG
@ -329,6 +337,37 @@ class ModuleLoaderBase : public nsISupports {
// unlinked. Extreme care should be taken when calling this method.
bool RemoveFetchedModule(nsIURI* aURL);
// Override the module loader with given loader until ResetOverride is called.
// While overridden, ModuleLoaderBase::GetCurrentModuleLoader returns aLoader.
//
// This is used by mozJSModuleLoader to temporarily override the global's
// module loader with SyncModuleLoader while importing a module graph
// synchronously.
void SetOverride(ModuleLoaderBase* aLoader);
// Returns true if SetOverride was called.
bool IsOverridden();
// Returns true if SetOverride was called with aLoader.
bool IsOverriddenBy(ModuleLoaderBase* aLoader);
void ResetOverride();
// Copy fetched modules to `aDest`.
// `this` shouldn't have any fetching.
// `aDest` shouldn't have any fetching or fetched modules.
//
// This is used when starting sync module load, to replicate the module cache
// in the sync module loader pointed by `aDest`.
void CopyModulesTo(ModuleLoaderBase* aDest);
// Move all fetched modules to `aDest`.
// Both `this` and `aDest` shouldn't have any fetching.
//
// This is used when finishing sync module load, to reflect the loaded modules
// to the async module loader pointed by `aDest`.
void MoveModulesTo(ModuleLoaderBase* aDest);
// Internal methods.
private:
@ -446,6 +485,18 @@ class ModuleLoaderBase : public nsISupports {
static mozilla::LazyLogModule gModuleLoaderBaseLog;
};
// Override the target module loader with given module loader while this
// instance is on the stack.
class MOZ_RAII AutoOverrideModuleLoader {
public:
AutoOverrideModuleLoader(ModuleLoaderBase* aTarget,
ModuleLoaderBase* aLoader);
~AutoOverrideModuleLoader();
private:
RefPtr<ModuleLoaderBase> mTarget;
};
} // namespace loader
} // namespace JS

View file

@ -130,10 +130,9 @@ mozilla::dom::ScriptLoadContext* ScriptLoadRequest::GetScriptLoadContext() {
return mLoadContext->AsWindowContext();
}
mozilla::loader::ComponentLoadContext*
ScriptLoadRequest::GetComponentLoadContext() {
mozilla::loader::SyncLoadContext* ScriptLoadRequest::GetSyncLoadContext() {
MOZ_ASSERT(mLoadContext);
return mLoadContext->AsComponentContext();
return mLoadContext->AsSyncContext();
}
mozilla::dom::WorkerLoadContext* ScriptLoadRequest::GetWorkerLoadContext() {

View file

@ -38,7 +38,7 @@ enum class RequestPriority : uint8_t;
} // namespace mozilla::dom
namespace mozilla::loader {
class ComponentLoadContext;
class SyncLoadContext;
} // namespace mozilla::loader
namespace JS {
@ -194,7 +194,7 @@ class ScriptLoadRequest : public nsISupports,
mozilla::dom::ScriptLoadContext* GetScriptLoadContext();
mozilla::loader::ComponentLoadContext* GetComponentLoadContext();
mozilla::loader::SyncLoadContext* GetSyncLoadContext();
mozilla::dom::WorkerLoadContext* GetWorkerLoadContext();

View file

@ -473,7 +473,7 @@ MSG_DEF(JSMSG_WASM_BAD_I31REF_VALUE, 0, JSEXN_TYPEERR, "can only pass a 31-
MSG_DEF(JSMSG_WASM_BAD_STRUCTREF_VALUE, 0, JSEXN_TYPEERR, "can only pass a WebAssembly struct object to a structref")
MSG_DEF(JSMSG_WASM_BAD_ARRAYREF_VALUE, 0, JSEXN_TYPEERR, "can only pass a WebAssembly array object to an arrayref")
MSG_DEF(JSMSG_WASM_BAD_TYPEREF_VALUE, 0, JSEXN_TYPEERR, "bad type")
MSG_DEF(JSMSG_WASM_BAD_VAL_TYPE, 0, JSEXN_TYPEERR, "cannot pass v128 to or from JS")
MSG_DEF(JSMSG_WASM_BAD_VAL_TYPE, 0, JSEXN_TYPEERR, "cannot pass value to or from JS")
MSG_DEF(JSMSG_WASM_BAD_STRING_VAL_TYPE, 0, JSEXN_TYPEERR, "bad value type")
MSG_DEF(JSMSG_WASM_BAD_STRING_IDX_TYPE, 0, JSEXN_TYPEERR, "bad index type")
MSG_DEF(JSMSG_WASM_BAD_EXN_ARG, 0, JSEXN_TYPEERR, "first argument must be a WebAssembly.Tag")

View file

@ -0,0 +1,40 @@
// |jit-test| --ion-inlining=off; --fast-warmup
function calleeWithFormals(a, b, ...arr) {
assertEq(b, 2);
if (arr.length > 0) {
assertEq(arr[0], 3);
}
if (arr.length > 1) {
assertEq(arr[1], Math);
}
if (arr.length > 2) {
assertEq(arr[2], "foo");
}
return arr;
}
function calleeWithoutFormals(...arr) {
if (arr.length > 0) {
assertEq(arr[0], 3);
}
if (arr.length > 1) {
assertEq(arr[1], Math);
}
if (arr.length > 2) {
assertEq(arr[2], "foo");
}
return arr;
}
function f() {
for (var i = 0; i < 100; i++) {
assertEq(calleeWithFormals(1, 2).length, 0);
assertEq(calleeWithFormals(1, 2, 3).length, 1);
assertEq(calleeWithFormals(1, 2, 3, Math).length, 2);
assertEq(calleeWithFormals(1, 2, 3, Math, "foo").length, 3);
assertEq(calleeWithoutFormals().length, 0);
assertEq(calleeWithoutFormals(3).length, 1);
assertEq(calleeWithoutFormals(3, Math).length, 2);
assertEq(calleeWithoutFormals(3, Math, "foo").length, 3);
}
}
f();

View file

@ -0,0 +1,110 @@
// |jit-test| skip-if: !wasmGcEnabled()
const {
refCast,
refTest,
branch,
branchFail,
refCastNullable,
refTestNullable,
branchNullable,
branchFailNullable,
} = wasmEvalText(`(module
(tag $a)
(func $make (param $null i32) (result exnref)
(if (local.get $null)
(then
(return (ref.null exn))
)
)
try_table (catch_all_ref 0)
throw $a
end
unreachable
)
(func (export "refCast") (param $null i32)
(call $make (local.get $null))
ref.cast (ref exn)
drop
)
(func (export "refTest") (param $null i32) (result i32)
(call $make (local.get $null))
ref.test (ref exn)
)
(func (export "branch") (param $null i32) (result i32)
(block (result (ref exn))
(call $make (local.get $null))
br_on_cast 0 exnref (ref exn)
drop
(return (i32.const 0))
)
drop
(return (i32.const 1))
)
(func (export "branchFail") (param $null i32) (result i32)
(block (result exnref)
(call $make (local.get $null))
br_on_cast_fail 0 exnref (ref exn)
drop
(return (i32.const 1))
)
drop
(return (i32.const 0))
)
(func (export "refCastNullable") (param $null i32)
(call $make (local.get $null))
ref.cast exnref
drop
)
(func (export "refTestNullable") (param $null i32) (result i32)
(call $make (local.get $null))
ref.test exnref
)
(func (export "branchNullable") (param $null i32) (result i32)
(block (result exnref)
(call $make (local.get $null))
br_on_cast 0 exnref exnref
drop
(return (i32.const 0))
)
drop
(return (i32.const 1))
)
(func (export "branchFailNullable") (param $null i32) (result i32)
(block (result exnref)
(call $make (local.get $null))
br_on_cast_fail 0 exnref exnref
drop
(return (i32.const 1))
)
drop
(return (i32.const 0))
)
)`).exports;
// cast non-null exnref -> (ref exn)
refCast(0);
assertEq(refTest(0), 1);
assertEq(branch(0), 1);
assertEq(branchFail(0), 1);
// cast non-null exnref -> exnref
refCastNullable(0);
assertEq(refTestNullable(0), 1);
assertEq(branchNullable(0), 1);
assertEq(branchFailNullable(0), 1);
// cast null exnref -> (ref exn)
assertErrorMessage(() => refCast(1), WebAssembly.RuntimeError, /bad cast/);
assertEq(refTest(1), 0);
assertEq(branch(1), 0);
assertEq(branchFail(1), 0);
// cast null exnref -> exnref
refCastNullable(1);
assertEq(refTestNullable(1), 1);
assertEq(branchNullable(1), 1);
assertEq(branchFailNullable(1), 1);

View file

@ -1571,7 +1571,7 @@ assertSame(get(mem, 16, 16), xs.map((x,i) => x+i))
// Calling from JS to export that accepts v128.
assertErrorMessage(() => insworker.exports.worker(),
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
// Calling from wasm with v128 to import that comes from JS. The instantiation
// will succeed even if the param type of the import is v128 (see "create a host
@ -1586,7 +1586,7 @@ var badImporter = wasmEvalText(`
assertErrorMessage(() => badImporter.exports.run(),
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
// Imports and exports that pass and return v128 as stack (not register) args.
@ -1657,11 +1657,11 @@ assertSame(get(mem, 16, 16), iota(16));
assertErrorMessage(() => insexporter.exports.myglobal.value = 0,
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
assertErrorMessage(function () { let v = insexporter.exports.myglobal.value },
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
// Multi-value cases + v128 parameters to if, block, loop

View file

@ -42,10 +42,10 @@ function call_v128_result() { ins.exports.v128_result(); }
for ( let i = 0 ; i < 100; i++ ) {
assertErrorMessage(call_v128_param,
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
assertErrorMessage(call_v128_result,
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
}
// RULE: v128 cannot cross the JS/wasm boundary as a function parameter.
@ -72,10 +72,10 @@ function call_v128_result2() { ins2.exports.v128_result(); }
for ( let i = 0 ; i < 100; i++ ) {
assertErrorMessage(call_v128_param2,
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
assertErrorMessage(call_v128_result2,
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
}
// RULE: The rules about v128 passing into or out of a function apply even when
@ -89,7 +89,7 @@ var ins = wasmEvalText(`
{m:{fn: newfn}});
assertErrorMessage(() => ins.exports.newfn(3),
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
// RULE: WebAssembly.Global of type v128 is constructable from JS with a default
// value.
@ -100,13 +100,13 @@ assertErrorMessage(() => ins.exports.newfn(3),
assertErrorMessage(() => new WebAssembly.Global({value: "v128"}, 37),
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
assertErrorMessage(() => new WebAssembly.Global({value: "v128"}),
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
assertErrorMessage(() => new WebAssembly.Global({value: "v128", mutable: true}),
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
// RULE: WebAssembly.Global of type v128 have getters and setters that throw
// TypeError when called from JS.
@ -119,12 +119,12 @@ let {gi, gm} = wasmEvalText(`
assertErrorMessage(() => gi.value,
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
assertErrorMessage(() => gi.valueOf(),
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);
assertErrorMessage(() => gm.value = 0,
TypeError,
/cannot pass.*v128.*to or from JS/);
/cannot pass.*value.*to or from JS/);

View file

@ -14821,11 +14821,13 @@ void CodeGenerator::visitRest(LRest* lir) {
Register temp0 = ToRegister(lir->temp0());
Register temp1 = ToRegister(lir->temp1());
Register temp2 = ToRegister(lir->temp2());
Register temp3 = ToRegister(lir->temp3());
unsigned numFormals = lir->mir()->numFormals();
constexpr uint32_t arrayCapacity = 2;
if (Shape* shape = lir->mir()->shape()) {
uint32_t arrayLength = 0;
uint32_t arrayCapacity = 2;
gc::AllocKind allocKind = GuessArrayGCKind(arrayCapacity);
MOZ_ASSERT(CanChangeToBackgroundAllocKind(allocKind, &ArrayObject::class_));
allocKind = ForegroundToBackgroundAllocKind(allocKind);
@ -14884,12 +14886,60 @@ void CodeGenerator::visitRest(LRest* lir) {
lengthReg = numActuals;
}
// Try to initialize the array elements.
Label vmCall, done;
if (lir->mir()->shape()) {
// Call into C++ if we failed to allocate an array or there are more than
// |arrayCapacity| elements.
masm.branchTestPtr(Assembler::Zero, temp2, temp2, &vmCall);
masm.branch32(Assembler::Above, lengthReg, Imm32(arrayCapacity), &vmCall);
// The array must be nursery allocated so no post barrier is needed.
#ifdef DEBUG
Label ok;
masm.branchPtrInNurseryChunk(Assembler::Equal, temp2, temp3, &ok);
masm.assumeUnreachable("Unexpected tenured object for LRest");
masm.bind(&ok);
#endif
Label initialized;
masm.branch32(Assembler::Equal, lengthReg, Imm32(0), &initialized);
// Store length and initializedLength.
Register elements = temp3;
masm.loadPtr(Address(temp2, NativeObject::offsetOfElements()), elements);
Address lengthAddr(elements, ObjectElements::offsetOfLength());
Address initLengthAddr(elements,
ObjectElements::offsetOfInitializedLength());
masm.store32(lengthReg, lengthAddr);
masm.store32(lengthReg, initLengthAddr);
// Store either one or two elements. This may clobber lengthReg (temp0).
static_assert(arrayCapacity == 2, "code handles 1 or 2 elements");
Label storeFirst;
masm.branch32(Assembler::Equal, lengthReg, Imm32(1), &storeFirst);
masm.storeValue(Address(temp1, sizeof(Value)),
Address(elements, sizeof(Value)), temp0);
masm.bind(&storeFirst);
masm.storeValue(Address(temp1, 0), Address(elements, 0), temp0);
// Done.
masm.bind(&initialized);
masm.movePtr(temp2, ReturnReg);
masm.jump(&done);
}
masm.bind(&vmCall);
pushArg(temp2);
pushArg(temp1);
pushArg(lengthReg);
using Fn = JSObject* (*)(JSContext*, uint32_t, Value*, HandleObject);
using Fn =
ArrayObject* (*)(JSContext*, uint32_t, Value*, Handle<ArrayObject*>);
callVM<Fn, InitRestParameter>(lir);
masm.bind(&done);
}
// Create a stackmap from the given safepoint, with the structure:
@ -18753,19 +18803,27 @@ static void BranchWasmRefIsSubtype(MacroAssembler& masm, Register ref,
const wasm::RefType& destType, Label* label,
Register superSTV, Register scratch1,
Register scratch2) {
if (destType.isAnyHierarchy()) {
masm.branchWasmRefIsSubtypeAny(ref, sourceType, destType, label,
/*onSuccess=*/true, superSTV, scratch1,
scratch2);
} else if (destType.isFuncHierarchy()) {
masm.branchWasmRefIsSubtypeFunc(ref, sourceType, destType, label,
/*onSuccess=*/true, superSTV, scratch1,
scratch2);
} else if (destType.isExternHierarchy()) {
masm.branchWasmRefIsSubtypeExtern(ref, sourceType, destType, label,
/*onSuccess=*/true);
} else {
MOZ_CRASH("could not generate casting code for unknown type hierarchy");
switch (destType.hierarchy()) {
case wasm::RefTypeHierarchy::Any: {
masm.branchWasmRefIsSubtypeAny(ref, sourceType, destType, label,
/*onSuccess=*/true, superSTV, scratch1,
scratch2);
} break;
case wasm::RefTypeHierarchy::Func: {
masm.branchWasmRefIsSubtypeFunc(ref, sourceType, destType, label,
/*onSuccess=*/true, superSTV, scratch1,
scratch2);
} break;
case wasm::RefTypeHierarchy::Extern: {
masm.branchWasmRefIsSubtypeExtern(ref, sourceType, destType, label,
/*onSuccess=*/true);
} break;
case wasm::RefTypeHierarchy::Exn: {
masm.branchWasmRefIsSubtypeExn(ref, sourceType, destType, label,
/*onSuccess=*/true);
} break;
default:
MOZ_CRASH("could not generate casting code for unknown type hierarchy");
}
}

Some files were not shown because too many files have changed in this diff Show more