Update On Fri Sep 6 20:50:23 CEST 2024

This commit is contained in:
github-action[bot] 2024-09-06 20:50:24 +02:00
parent 5822b45acc
commit b3a8d77781
2384 changed files with 7853 additions and 3542 deletions

View file

@ -834,6 +834,9 @@ pref("browser.shopping.experience2023.sidebarClosedCount", 0);
// When conditions are met, shows a prompt on the shopping sidebar asking users if they want to disable auto-open behavior // When conditions are met, shows a prompt on the shopping sidebar asking users if they want to disable auto-open behavior
pref("browser.shopping.experience2023.showKeepSidebarClosedMessage", true); pref("browser.shopping.experience2023.showKeepSidebarClosedMessage", true);
// Integrates the Review Checker shopping feature into the global sidebar
pref("browser.shopping.experience2023.integratedSidebar", false);
// Spin the cursor while the page is loading // Spin the cursor while the page is loading
pref("browser.spin_cursor_while_busy", false); pref("browser.spin_cursor_while_busy", false);
@ -947,9 +950,6 @@ pref("browser.tabs.tabMinWidth", 76);
// of the text at small font sizes. // of the text at small font sizes.
pref("browser.tabs.secondaryTextUnsupportedLocales", "ar,bn,bo,ckb,fa,gu,he,hi,ja,km,kn,ko,lo,mr,my,ne,pa,si,ta,te,th,ur,zh"); pref("browser.tabs.secondaryTextUnsupportedLocales", "ar,bn,bo,ckb,fa,gu,he,hi,ja,km,kn,ko,lo,mr,my,ne,pa,si,ta,te,th,ur,zh");
//Control the visibility of Tab Manager Menu.
pref("browser.tabs.tabmanager.enabled", true);
// When tabs opened by links in other tabs via a combination of // When tabs opened by links in other tabs via a combination of
// browser.link.open_newwindow being set to 3 and target="_blank" etc are // browser.link.open_newwindow being set to 3 and target="_blank" etc are
// closed: // closed:
@ -1230,15 +1230,9 @@ pref("network.manage-offline-status", true);
// We want to make sure mail URLs are handled externally... // We want to make sure mail URLs are handled externally...
pref("network.protocol-handler.external.mailto", true); // for mail pref("network.protocol-handler.external.mailto", true); // for mail
#ifdef XP_WIN
pref("network.protocol-handler.external.ms-windows-store", true);
#endif
// ...without warning dialogs // ...without warning dialogs
pref("network.protocol-handler.warn-external.mailto", false); pref("network.protocol-handler.warn-external.mailto", false);
#ifdef XP_WIN
pref("network.protocol-handler.warn-external.ms-windows-store", false);
#endif
// By default, all protocol handlers are exposed. This means that // By default, all protocol handlers are exposed. This means that
// the browser will respond to openURL commands for all URL types. // the browser will respond to openURL commands for all URL types.
@ -1740,6 +1734,10 @@ pref("browser.partnerlink.campaign.topsites", "amzn_2020_a1");
// Activates preloading of the new tab url. // Activates preloading of the new tab url.
pref("browser.newtab.preload", true); pref("browser.newtab.preload", true);
// Mozilla Ad Routing Service (MARS) unified ads service
pref("browser.newtabpage.activity-stream.unifiedAds.enabled", false);
pref("browser.newtabpage.activity-stream.unifiedAds.endpoint", "https://ads.mozilla.org/");
// Weather widget for newtab // Weather widget for newtab
pref("browser.newtabpage.activity-stream.showWeather", true); pref("browser.newtabpage.activity-stream.showWeather", true);
pref("browser.newtabpage.activity-stream.weather.query", ""); pref("browser.newtabpage.activity-stream.weather.query", "");

View file

@ -87,6 +87,165 @@ const ERROR_L10N_IDS = new Map([
], ],
]); ]);
customElements.define(
"addon-webext-permissions-notification",
class MozAddonPermissionsNotification extends customElements.get(
"popupnotification"
) {
show() {
super.show();
if (!this.notification) {
return;
}
if (!this.notification.options?.customElementOptions) {
throw new Error(
"Mandatory customElementOptions property missing from notification options"
);
}
this.textEl = this.querySelector("#addon-webext-perm-text");
this.introEl = this.querySelector("#addon-webext-perm-intro");
this.permsSingleEl = this.querySelector(
"#addon-webext-perm-single-entry"
);
this.permsListEl = this.querySelector("#addon-webext-perm-list");
this.render();
}
get hasNoPermissions() {
const { strings, showIncognitoCheckbox } =
this.notification.options.customElementOptions;
return !(showIncognitoCheckbox || strings.msgs.length);
}
get hasMultiplePermissionsEntries() {
const { strings, showIncognitoCheckbox } =
this.notification.options.customElementOptions;
return (
strings.msgs.length > 1 ||
(strings.msgs.length === 1 && showIncognitoCheckbox)
);
}
render() {
const { strings, showIncognitoCheckbox } =
this.notification.options.customElementOptions;
const { textEl, introEl, permsSingleEl, permsListEl } = this;
const HTML_NS = "http://www.w3.org/1999/xhtml";
const doc = this.ownerDocument;
this.#clearChildElements();
if (strings.text) {
textEl.textContent = strings.text;
// By default, multiline strings don't get formatted properly. These
// are presently only used in site permission add-ons, so we treat it
// as a special case to avoid unintended effects on other things.
if (strings.text.includes("\n\n")) {
textEl.classList.add("addon-webext-perm-text-multiline");
}
textEl.hidden = false;
}
if (strings.listIntro) {
introEl.textContent = strings.listIntro;
introEl.hidden = false;
}
// Return earlier if there are no permissions to list.
if (this.hasNoPermissions) {
return;
}
// If there are multiple permissions entries to be shown,
// add to the list element one entry for each granted permission
// (and one for the private browsing checkbox, if it should
// be shown) and return earlier.
if (this.hasMultiplePermissionsEntries) {
for (let msg of strings.msgs) {
let item = doc.createElementNS(HTML_NS, "li");
item.classList.add("webext-perm-granted");
item.textContent = msg;
permsListEl.appendChild(item);
}
if (showIncognitoCheckbox) {
let item = doc.createElementNS(HTML_NS, "li");
item.classList.add(
"webext-perm-optional",
"webext-perm-privatebrowsing"
);
item.appendChild(this.#createPrivateBrowsingCheckbox());
permsListEl.appendChild(item);
}
permsListEl.hidden = false;
return;
}
// Render a single permission entry, which will be either:
// - an entry for the private browsing checkbox
// - or single granted permission entry.
if (showIncognitoCheckbox) {
permsSingleEl.appendChild(this.#createPrivateBrowsingCheckbox());
permsSingleEl.hidden = false;
permsSingleEl.classList.add(
"webext-perm-optional",
"webext-perm-privatebrowsing"
);
return;
}
permsSingleEl.textContent = strings.msgs[0];
permsSingleEl.hidden = false;
}
#clearChildElements() {
const { textEl, introEl, permsSingleEl, permsListEl } = this;
// Clear all changes to the child elements that may have been changed
// by a previous call of the render method.
textEl.textContent = "";
textEl.hidden = true;
textEl.classList.remove("addon-webext-perm-text-multiline");
introEl.textContent = "";
introEl.hidden = true;
permsSingleEl.textContent = "";
permsSingleEl.hidden = true;
permsSingleEl.classList.remove(
"webext-perm-optional",
"webext-perm-privatebrowsing"
);
permsListEl.textContent = "";
permsListEl.hidden = true;
}
#createPrivateBrowsingCheckbox() {
const { onPrivateBrowsingAllowedChanged, grantPrivateBrowsingAllowed } =
this.notification.options.customElementOptions;
const doc = this.ownerDocument;
let checkboxEl = doc.createXULElement("checkbox");
checkboxEl.checked = grantPrivateBrowsingAllowed;
checkboxEl.addEventListener("CheckboxStateChange", () => {
onPrivateBrowsingAllowedChanged?.(checkboxEl.checked);
});
doc.l10n.setAttributes(
checkboxEl,
"popup-notification-addon-privatebrowsing-checkbox"
);
return checkboxEl;
}
}
);
customElements.define( customElements.define(
"addon-progress-notification", "addon-progress-notification",
class MozAddonProgressNotification extends customElements.get( class MozAddonProgressNotification extends customElements.get(

View file

@ -5,7 +5,7 @@
<hbox flex="1" id="browser"> <hbox flex="1" id="browser">
<box context="sidebar-context-menu" id="sidebar-main" hidden="true"> <box context="sidebar-context-menu" id="sidebar-main" hidden="true">
<html:sidebar-main flex="1"> <html:sidebar-main flex="1">
<html:div id="vertical-tabs" slot="tabstrip" customizable="true"></html:div> <box id="vertical-tabs" slot="tabstrip" customizable="true" contextmenu="toolbar-context-menu"></box>
</html:sidebar-main> </html:sidebar-main>
</box> </box>
<vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome"> <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">

View file

@ -111,20 +111,14 @@
<popupnotificationcontent id="addon-install-confirmation-content" orient="vertical"/> <popupnotificationcontent id="addon-install-confirmation-content" orient="vertical"/>
</popupnotification> </popupnotification>
<popupnotification id="addon-webext-permissions-notification" hidden="true"> <popupnotification id="addon-webext-permissions-notification"
is="addon-webext-permissions-notification"
hidden="true">
<popupnotificationcontent class="addon-webext-perm-notification-content" orient="vertical"> <popupnotificationcontent class="addon-webext-perm-notification-content" orient="vertical">
<description id="addon-webext-perm-text" class="addon-webext-perm-text"/> <description id="addon-webext-perm-text" class="addon-webext-perm-text"/>
<label id="addon-webext-perm-intro" class="addon-webext-perm-text"/> <label id="addon-webext-perm-intro" class="addon-webext-perm-text"/>
<label id="addon-webext-perm-single-entry" class="addon-webext-perm-single-entry"/> <label id="addon-webext-perm-single-entry" class="addon-webext-perm-single-entry"/>
<html:ul id="addon-webext-perm-list" class="addon-webext-perm-list"/> <html:ul id="addon-webext-perm-list" class="addon-webext-perm-list"/>
<hbox>
<html:a
is="moz-support-link"
id="addon-webext-perm-info"
class="popup-notification-learnmore-link"
support-page="extension-permissions"
/>
</hbox>
</popupnotificationcontent> </popupnotificationcontent>
</popupnotification> </popupnotification>

View file

@ -244,11 +244,11 @@ skip-if = ["os == 'linux' && !debug"] # Bug 1556066
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
["browser_bug1261299.js"] ["browser_bug1261299.js"]
skip-if = ["os != 'mac'"] # Because of tests for supporting Service Menu of macOS, bug 1261299 run-if = ["os == 'mac'"] # Because of tests for supporting Service Menu of macOS, bug 1261299
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
["browser_bug1297539.js"] ["browser_bug1297539.js"]
skip-if = ["os != 'mac'"] # Because of tests for supporting pasting from Service Menu of macOS, bug 1297539 run-if = ["os == 'mac'"] # Because of tests for supporting pasting from Service Menu of macOS, bug 1297539
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
["browser_bug1299667.js"] ["browser_bug1299667.js"]
@ -273,10 +273,8 @@ skip-if = ["true"] # Clicks in content don't go through contentAreaClick.
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
["browser_datachoices_notification.js"] ["browser_datachoices_notification.js"]
skip-if = [ run-if = ["datareporting"]
"!datareporting", skip-if = ["verify && !debug && os == 'win'"]
"verify && !debug && os == 'win'",
]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
["browser_documentnavigation.js"] ["browser_documentnavigation.js"]
@ -397,10 +395,8 @@ support-files = [
["browser_remoteTroubleshoot.js"] ["browser_remoteTroubleshoot.js"]
https_first_disabled = true https_first_disabled = true
skip-if = [ run-if = ["updater"]
"!updater", skip-if = ["os == 'linux' && asan"] # Bug 1711507
"os == 'linux' && asan", # Bug 1711507
]
reason = "depends on UpdateUtils .Locale" reason = "depends on UpdateUtils .Locale"
support-files = ["test_remoteTroubleshoot.html"] support-files = ["test_remoteTroubleshoot.html"]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
@ -409,7 +405,7 @@ support-files = ["test_remoteTroubleshoot.html"]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
["browser_restore_isAppTab.js"] ["browser_restore_isAppTab.js"]
skip-if = ["!crashreporter"] # test requires crashreporter due to 1536221 run-if = ["crashreporter"] # test requires crashreporter due to 1536221
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD. # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
["browser_save_link-perwindowpb.js"] ["browser_save_link-perwindowpb.js"]

View file

@ -14,7 +14,10 @@ https_first_disabled = true
run-if = ["os == 'mac'"] # Mac only feature run-if = ["os == 'mac'"] # Mac only feature
["browser_history_recently_closed_tabs.js"] ["browser_history_recently_closed_tabs.js"]
skip-if = ["os == 'mac'"] # No menubar on macOS. run-if = [
"os == 'linux'",
"os == 'win'",
] # No menubar on macOS.
support-files = ["file_shareurl.html"] support-files = ["file_shareurl.html"]

View file

@ -40,8 +40,8 @@ support-files = ["!/browser/components/downloads/test/browser/head.js"]
["browser_preferences_usage.js"] ["browser_preferences_usage.js"]
https_first_disabled = true https_first_disabled = true
run-if = ["debug"]
skip-if = [ skip-if = [
"!debug",
"apple_catalina", # platform migration "apple_catalina", # platform migration
"socketprocess_networking", "socketprocess_networking",
] ]
@ -52,7 +52,7 @@ skip-if = [
support-files = ["file_empty.html"] support-files = ["file_empty.html"]
["browser_startup_content_subframe.js"] ["browser_startup_content_subframe.js"]
skip-if = ["!fission"] run-if = ["fission"]
support-files = [ support-files = [
"file_empty.html", "file_empty.html",
"StartupContentSubframe.sys.mjs", "StartupContentSubframe.sys.mjs",
@ -65,7 +65,10 @@ run-if = [
] ]
["browser_startup_hiddenwindow.js"] ["browser_startup_hiddenwindow.js"]
skip-if = ["os == 'mac'"] run-if = [
"os == 'linux'",
"os == 'win'",
]
["browser_tabclose.js"] ["browser_tabclose.js"]
skip-if = [ skip-if = [

View file

@ -5,4 +5,4 @@ prefs = [
] ]
["../browser_startup_images.js"] ["../browser_startup_images.js"]
skip-if = ["!debug"] run-if = ["debug"]

View file

@ -5,4 +5,4 @@ prefs = [
] ]
["../browser_startup_images.js"] ["../browser_startup_images.js"]
skip-if = ["!debug"] run-if = ["debug"]

View file

@ -1,5 +1,5 @@
[DEFAULT] [DEFAULT]
skip-if = ["!crashreporter"] run-if = ["crashreporter"]
support-files = [ support-files = [
"head.js", "head.js",
"file_contains_emptyiframe.html", "file_contains_emptyiframe.html",

View file

@ -39,10 +39,8 @@ skip-if = ["a11y_checks"] # Bug 1858037 to investigate intermittent a11y_checks
["browser_permissions_pointerevent.js"] ["browser_permissions_pointerevent.js"]
["browser_permissions_unsigned.js"] ["browser_permissions_unsigned.js"]
skip-if = [ run-if = ["!require_signing"]
"require_signing", skip-if = ["a11y_checks"] # Bugs 1858041 and 1854461 to investigate intermittent a11y_checks results (fails on Autoland, passes on Try)
"a11y_checks", # Bugs 1858041 and 1854461 to investigate intermittent a11y_checks results (fails on Autoland, passes on Try)
]
["browser_update_checkForUpdates.js"] ["browser_update_checkForUpdates.js"]

View file

@ -49,14 +49,12 @@ add_task(async function test_tab_switch_dismiss() {
content.wrappedJSObject.installMozAM(url); content.wrappedJSObject.installMozAM(url);
}); });
await promisePopupNotificationShown("addon-webext-permissions"); const panel = await promisePopupNotificationShown("addon-webext-permissions");
assertPermissionsListCount({ grantedPermissionsCount: 5 }); assertPermissionsListCount({ grantedPermissionsCount: 5 });
let permsLearnMore = document.getElementById("addon-webext-perm-info"); let permsLearnMore = panel.querySelector(
ok( ".popup-notification-learnmore-link"
BrowserTestUtils.isVisible(permsLearnMore),
"Learn more link is shown on Permission popup"
); );
is( is(
permsLearnMore.href, permsLearnMore.href,
@ -64,6 +62,10 @@ add_task(async function test_tab_switch_dismiss() {
"extension-permissions", "extension-permissions",
"Learn more link has desired URL" "Learn more link has desired URL"
); );
ok(
BrowserTestUtils.isVisible(permsLearnMore),
"Learn more link is shown on Permission popup"
);
// Switching tabs dismisses the notification and cancels the install. // Switching tabs dismisses the notification and cancels the install.
let switchTo = await BrowserTestUtils.openNewForegroundTab(gBrowser); let switchTo = await BrowserTestUtils.openNewForegroundTab(gBrowser);

View file

@ -230,9 +230,9 @@ function checkNotification(
expectIncognitoCheckboxHidden expectIncognitoCheckboxHidden
) { ) {
let icon = panel.getAttribute("icon"); let icon = panel.getAttribute("icon");
let learnMoreLink = panel.querySelector(".popup-notification-learnmore-link");
let ul = document.getElementById("addon-webext-perm-list"); let ul = document.getElementById("addon-webext-perm-list");
let singleDataEl = document.getElementById("addon-webext-perm-single-entry"); let singleDataEl = document.getElementById("addon-webext-perm-single-entry");
let learnMoreLink = document.getElementById("addon-webext-perm-info");
if (checkIcon instanceof RegExp) { if (checkIcon instanceof RegExp) {
ok( ok(

View file

@ -110,7 +110,8 @@ export var ToolbarContextMenu = {
parent.classList.contains("customization-target") || parent.classList.contains("customization-target") ||
parent.getAttribute("overflowfortoolbar") || // Needs to work in the overflow list as well. parent.getAttribute("overflowfortoolbar") || // Needs to work in the overflow list as well.
parent.localName == "toolbarpaletteitem" || parent.localName == "toolbarpaletteitem" ||
parent.localName == "toolbar" parent.localName == "toolbar" ||
parent.id == "vertical-tabs"
) { ) {
break; break;
} }
@ -126,36 +127,50 @@ export var ToolbarContextMenu = {
} }
} }
MozXULElement.insertFTLIfNeeded("browser/toolbarContextMenu.ftl"); let showTabStripItems = toolbarItem?.id == "tabbrowser-tabs";
let firstMenuItem = aInsertPoint || popup.firstElementChild; let isVerticalTabStripMenu =
let toolbarNodes = gNavToolbox.querySelectorAll("toolbar"); showTabStripItems && toolbarItem.parentElement.id == "vertical-tabs";
for (let toolbar of toolbarNodes) {
if (!toolbar.hasAttribute("toolbarname")) {
continue;
}
if (toolbar.id == "PersonalToolbar") { if (aInsertPoint) {
let menu = BookmarkingUI.buildBookmarksToolbarSubmenu(toolbar); aInsertPoint.hidden = isVerticalTabStripMenu;
popup.insertBefore(menu, firstMenuItem); }
} else { document.getElementById("toolbar-context-customize").hidden =
let menuItem = document.createXULElement("menuitem"); isVerticalTabStripMenu;
menuItem.setAttribute("id", "toggle_" + toolbar.id);
menuItem.setAttribute("toolbarId", toolbar.id); if (!isVerticalTabStripMenu) {
menuItem.setAttribute("type", "checkbox"); MozXULElement.insertFTLIfNeeded("browser/toolbarContextMenu.ftl");
menuItem.setAttribute("label", toolbar.getAttribute("toolbarname")); let firstMenuItem = aInsertPoint || popup.firstElementChild;
let hidingAttribute = let toolbarNodes = gNavToolbox.querySelectorAll("toolbar");
toolbar.getAttribute("type") == "menubar" ? "autohide" : "collapsed"; for (let toolbar of toolbarNodes) {
menuItem.setAttribute( if (!toolbar.hasAttribute("toolbarname")) {
"checked", continue;
toolbar.getAttribute(hidingAttribute) != "true"
);
menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
if (popup.id != "toolbar-context-menu") {
menuItem.setAttribute("key", toolbar.getAttribute("key"));
} }
popup.insertBefore(menuItem, firstMenuItem); if (toolbar.id == "PersonalToolbar") {
menuItem.addEventListener("command", onViewToolbarCommand); let menu = BookmarkingUI.buildBookmarksToolbarSubmenu(toolbar);
popup.insertBefore(menu, firstMenuItem);
} else {
let menuItem = document.createXULElement("menuitem");
menuItem.setAttribute("id", "toggle_" + toolbar.id);
menuItem.setAttribute("toolbarId", toolbar.id);
menuItem.setAttribute("type", "checkbox");
menuItem.setAttribute("label", toolbar.getAttribute("toolbarname"));
let hidingAttribute =
toolbar.getAttribute("type") == "menubar"
? "autohide"
: "collapsed";
menuItem.setAttribute(
"checked",
toolbar.getAttribute(hidingAttribute) != "true"
);
menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
if (popup.id != "toolbar-context-menu") {
menuItem.setAttribute("key", toolbar.getAttribute("key"));
}
popup.insertBefore(menuItem, firstMenuItem);
menuItem.addEventListener("command", onViewToolbarCommand);
}
} }
} }
@ -171,7 +186,6 @@ export var ToolbarContextMenu = {
return; return;
} }
let showTabStripItems = toolbarItem?.id == "tabbrowser-tabs";
for (let node of popup.querySelectorAll( for (let node of popup.querySelectorAll(
'menuitem[contexttype="toolbaritem"]' 'menuitem[contexttype="toolbaritem"]'
)) { )) {

View file

@ -316,6 +316,17 @@ export class ExtensionControlledPopup {
anchorButton = action || doc.getElementById("PanelUI-menu-button"); anchorButton = action || doc.getElementById("PanelUI-menu-button");
} }
let anchor = anchorButton.icon; let anchor = anchorButton.icon;
if (this.learnMoreLink) {
const learnMoreURL =
Services.urlFormatter.formatURLPref("app.support.baseURL") +
this.learnMoreLink;
popupnotification.setAttribute("learnmoreurl", learnMoreURL);
} else {
// In practice this isn't really needed because each of the
// controlled popups use its own popupnotification instance
// and they always have an learnMoreURL.
popupnotification.removeAttribute("learnmoreurl");
}
popupnotification.show(); popupnotification.show();
panel.openPopup(anchor); panel.openPopup(anchor);
} }
@ -349,11 +360,6 @@ export class ExtensionControlledPopup {
lazy.BrowserUIUtils.getLocalizedFragment(doc, message, addonDetails) lazy.BrowserUIUtils.getLocalizedFragment(doc, message, addonDetails)
); );
} }
let link = doc.createElement("a", { is: "moz-support-link" });
link.setAttribute("class", "learnMore");
link.setAttribute("support-page", this.learnMoreLink);
description.appendChild(link);
} }
async _ensureWindowReady(win) { async _ensureWindowReady(win) {

View file

@ -162,14 +162,23 @@ add_task(async function testExtensionControlledPopup() {
let description = doc.getElementById("extension-controlled-description"); let description = doc.getElementById("extension-controlled-description");
is( is(
description.textContent, description.textContent,
"An extension, Ext Controlled, changed the page you see when you open a new tab.Learn more", "An extension, Ext Controlled, changed the page you see when you open a new tab.",
"The extension name is in the description" "The extension name is in the description"
); );
let link = description.querySelector("a.learnMore");
const learnMoreEl = panel.querySelector(
"#extension-controlled-notification .popup-notification-learnmore-link"
);
ok(
BrowserTestUtils.isVisible(learnMoreEl),
"Expect the popupnotification learnmore link to be visible"
);
is( is(
link.href, learnMoreEl.getAttribute("href"),
"http://127.0.0.1:8888/support-dummy/extension-controlled", Services.urlFormatter.formatURLPref("app.support.baseURL") +
"The link has the href set from learnMoreLink" "extension-controlled",
"learnmore link should have the expected url set"
); );
// Force close the popup, as if a user clicked away from it. // Force close the popup, as if a user clicked away from it.

View file

@ -66,11 +66,12 @@ add_task(async function test_multiple_extensions_overriding_home_page() {
function background() { function background() {
browser.test.onMessage.addListener(async msg => { browser.test.onMessage.addListener(async msg => {
switch (msg) { switch (msg) {
case "checkHomepage": case "checkHomepage": {
let homepage = await browser.browserSettings.homepageOverride.get({}); let homepage = await browser.browserSettings.homepageOverride.get({});
browser.test.sendMessage("homepage", homepage); browser.test.sendMessage("homepage", homepage);
break; break;
case "trySet": }
case "trySet": {
let setResult = await browser.browserSettings.homepageOverride.set({ let setResult = await browser.browserSettings.homepageOverride.set({
value: "foo", value: "foo",
}); });
@ -80,7 +81,8 @@ add_task(async function test_multiple_extensions_overriding_home_page() {
); );
browser.test.sendMessage("homepageSet"); browser.test.sendMessage("homepageSet");
break; break;
case "tryClear": }
case "tryClear": {
let clearResult = let clearResult =
await browser.browserSettings.homepageOverride.clear({}); await browser.browserSettings.homepageOverride.clear({});
browser.test.assertFalse( browser.test.assertFalse(
@ -89,6 +91,7 @@ add_task(async function test_multiple_extensions_overriding_home_page() {
); );
browser.test.sendMessage("homepageCleared"); browser.test.sendMessage("homepageCleared");
break; break;
}
} }
}); });
} }
@ -489,13 +492,28 @@ add_task(async function test_doorhanger_new_window() {
is( is(
description.textContent, description.textContent,
"An extension, Ext2, changed what you see when you open your homepage and new windows.Learn more", "An extension, Ext2, changed what you see when you open your homepage and new windows.",
"The extension name is in the popup" "The extension name is in the popup"
); );
let popupnotification = doc.getElementById("extension-homepage-notification");
let learnMoreEl = popupnotification.querySelector(
".popup-notification-learnmore-link"
);
ok(
BrowserTestUtils.isVisible(learnMoreEl),
"Expect the popupnotification learnmore link to be visible"
);
is(
learnMoreEl.getAttribute("href"),
Services.urlFormatter.formatURLPref("app.support.baseURL") +
"extension-home",
"learnmore link should have the expected url set"
);
// Click Manage. // Click Manage.
let popupHidden = promisePopupHidden(panel); let popupHidden = promisePopupHidden(panel);
let popupnotification = doc.getElementById("extension-homepage-notification");
popupnotification.secondaryButton.click(); popupnotification.secondaryButton.click();
await popupHidden; await popupHidden;
@ -518,7 +536,7 @@ add_task(async function test_doorhanger_new_window() {
is( is(
description.textContent, description.textContent,
"An extension, Ext1, changed what you see when you open your homepage and new windows.Learn more", "An extension, Ext1, changed what you see when you open your homepage and new windows.",
"The extension name is in the popup" "The extension name is in the popup"
); );
@ -591,7 +609,7 @@ add_task(async function test_overriding_home_page_incognito_not_allowed() {
let popupnotification = description.closest("popupnotification"); let popupnotification = description.closest("popupnotification");
is( is(
description.textContent, description.textContent,
"An extension, extension, changed what you see when you open your homepage and new windows.Learn more", "An extension, extension, changed what you see when you open your homepage and new windows.",
"The extension name is in the popup" "The extension name is in the popup"
); );
is( is(

View file

@ -73,10 +73,34 @@ add_task(function test_doorhanger_keep() {
"The doorhanger is anchored to the all tabs button" "The doorhanger is anchored to the all tabs button"
); );
// Click the Keep Tabs Hidden button. let description = panel.querySelector(
let popupnotification = document.getElementById( "#extension-tab-hide-notification-description"
);
is(
description.textContent,
"An extension, Generated extension, is hiding some of your tabs. You can still access all of your tabs from .",
"The extension name is in the description"
);
const popupnotification = document.getElementById(
"extension-tab-hide-notification" "extension-tab-hide-notification"
); );
const learnMoreEl = popupnotification.querySelector(
".popup-notification-learnmore-link"
);
ok(
learnMoreEl,
"Expect the popupnotification learnmore link to be visible"
);
is(
learnMoreEl.getAttribute("href"),
Services.urlFormatter.formatURLPref("app.support.baseURL") +
"extension-hiding-tabs",
"learnmore link should have the expected url set"
);
// Click the Keep Tabs Hidden button.
let popupHidden = promisePopupHidden(panel); let popupHidden = promisePopupHidden(panel);
popupnotification.button.click(); popupnotification.button.click();
await popupHidden; await popupHidden;
@ -227,17 +251,6 @@ add_task(async function test_tabs_showhide() {
SessionStore.setBrowserState(JSON.stringify(sessData)); SessionStore.setBrowserState(JSON.stringify(sessData));
await restored; await restored;
if (!Services.prefs.getBoolPref("browser.tabs.tabmanager.enabled")) {
for (let win of BrowserWindowIterator()) {
let allTabsButton = win.document.getElementById("alltabs-button");
is(
getComputedStyle(allTabsButton).display,
"none",
"The all tabs button is hidden"
);
}
}
// Attempt to hide all the tabs, however the active tab in each window cannot // Attempt to hide all the tabs, however the active tab in each window cannot
// be hidden, so the result will be 3 hidden tabs. // be hidden, so the result will be 3 hidden tabs.
extension.sendMessage("hideall"); extension.sendMessage("hideall");

View file

@ -258,10 +258,25 @@ add_task(async function test_new_tab_keep_settings() {
is( is(
panel.querySelector("#extension-new-tab-notification-description") panel.querySelector("#extension-new-tab-notification-description")
.textContent, .textContent,
"An extension, New Tab Add-on, changed the page you see when you open a new tab.Learn more", "An extension, New Tab Add-on, changed the page you see when you open a new tab.",
"The description includes the add-on name" "The description includes the add-on name"
); );
const learnMoreEl = panel.querySelector(
"#extension-new-tab-notification .popup-notification-learnmore-link"
);
ok(
BrowserTestUtils.isVisible(learnMoreEl),
"Expect the popupnotification learnmore link to be visible"
);
is(
learnMoreEl.getAttribute("href"),
Services.urlFormatter.formatURLPref("app.support.baseURL") +
"extension-home",
"learnmore link should have the expected url set"
);
// Click the Keep Changes button. // Click the Keep Changes button.
let confirmationSaved = TestUtils.waitForCondition(() => { let confirmationSaved = TestUtils.waitForCondition(() => {
return ExtensionSettingsStore.getSetting( return ExtensionSettingsStore.getSetting(

View file

@ -210,6 +210,20 @@ export const PREFS_CONFIG = new Map([
value: true, value: true,
}, },
], ],
[
"unifiedAds.enabled",
{
title: "Use Mozilla Ad Routing Service (MARS) unified ads API",
value: false,
},
],
[
"unifiedAds.endpoint",
{
title: "Mozilla Ad Routing Service (MARS) unified ads API endpoint URL",
value: "https://ads.mozilla.org/",
},
],
[ [
"system.showWeather", "system.showWeather",
{ {

View file

@ -115,21 +115,13 @@ var TabStateCacheInternal = {
} }
let history = data.history; let history = data.history;
let toIdx = history.entries.length;
if ("toIdx" in change) {
toIdx = Math.min(toIdx, change.toIdx + 1);
}
for (let key of Object.keys(change)) { for (let key of Object.keys(change)) {
if (key == "entries") { if (key == "entries") {
if (change.fromIdx != kLastIndex) { if (change.fromIdx != kLastIndex) {
let start = change.fromIdx + 1; let start = change.fromIdx + 1;
history.entries.splice.apply( history.entries.splice(start, Infinity, ...change.entries);
history.entries,
[start, toIdx - start].concat(change.entries)
);
} }
} else if (key != "fromIdx" && key != "toIdx") { } else if (key != "fromIdx") {
history[key] = change[key]; history[key] = change[key];
} }
} }

View file

@ -38,6 +38,7 @@ export class SidebarHistory extends SidebarPage {
this._menuSortBySite = doc.getElementById("sidebar-history-sort-by-site"); this._menuSortBySite = doc.getElementById("sidebar-history-sort-by-site");
this._menu.addEventListener("command", this); this._menu.addEventListener("command", this);
this.addContextMenuListeners(); this.addContextMenuListeners();
this.addSidebarFocusedListeners();
this.controller.updateCache(); this.controller.updateCache();
} }
@ -45,6 +46,7 @@ export class SidebarHistory extends SidebarPage {
super.disconnectedCallback(); super.disconnectedCallback();
this._menu.removeEventListener("command", this); this._menu.removeEventListener("command", this);
this.removeContextMenuListeners(); this.removeContextMenuListeners();
this.removeSidebarFocusedListeners();
} }
handleContextMenuEvent(e) { handleContextMenuEvent(e) {
@ -74,6 +76,10 @@ export class SidebarHistory extends SidebarPage {
} }
} }
handleSidebarFocusedEvent() {
this.searchTextbox?.focus();
}
onPrimaryAction(e) { onPrimaryAction(e) {
navigateToLink(e); navigateToLink(e);
} }
@ -260,7 +266,6 @@ export class SidebarHistory extends SidebarPage {
data-l10n-attrs="placeholder" data-l10n-attrs="placeholder"
@fxview-search-textbox-query=${this.onSearchQuery} @fxview-search-textbox-query=${this.onSearchQuery}
.size=${15} .size=${15}
autofocus
></fxview-search-textbox> ></fxview-search-textbox>
<moz-button <moz-button
class="menu-button" class="menu-button"

View file

@ -93,7 +93,10 @@ export default class SidebarMain extends MozLitElement {
event.explicitOriginalTarget.flattenedTreeParentNode; event.explicitOriginalTarget.flattenedTreeParentNode;
if ( if (
this.contextMenuTarget.getAttribute("extensionId") || this.contextMenuTarget.getAttribute("extensionId") ||
this.contextMenuTarget.className.includes("tab") this.contextMenuTarget.className.includes("tab") ||
document
.getElementById("vertical-tabs")
.contains(this.contextMenuTarget.flattenedTreeParentNode)
) { ) {
this.updateExtensionContextMenuItems(); this.updateExtensionContextMenuItems();
return; return;

View file

@ -56,6 +56,14 @@ export class SidebarPage extends MozLitElement {
this._contextMenu.removeEventListener("command", this); this._contextMenu.removeEventListener("command", this);
} }
addSidebarFocusedListeners() {
this.topWindow.addEventListener("SidebarFocused", this);
}
removeSidebarFocusedListeners() {
this.topWindow.removeEventListener("SidebarFocused", this);
}
handleEvent(e) { handleEvent(e) {
switch (e.type) { switch (e.type) {
case "contextmenu": case "contextmenu":
@ -64,6 +72,9 @@ export class SidebarPage extends MozLitElement {
case "command": case "command":
this.handleCommandEvent?.(e); this.handleCommandEvent?.(e);
break; break;
case "SidebarFocused":
this.handleSidebarFocusedEvent?.(e);
break;
} }
} }

View file

@ -24,6 +24,7 @@ class SyncedTabsInSidebar extends SidebarPage {
static queries = { static queries = {
cards: { all: "moz-card" }, cards: { all: "moz-card" },
searchTextbox: "fxview-search-textbox",
}; };
constructor() { constructor() {
@ -36,12 +37,14 @@ class SyncedTabsInSidebar extends SidebarPage {
this.controller.addSyncObservers(); this.controller.addSyncObservers();
this.controller.updateStates(); this.controller.updateStates();
this.addContextMenuListeners(); this.addContextMenuListeners();
this.addSidebarFocusedListeners();
} }
disconnectedCallback() { disconnectedCallback() {
super.disconnectedCallback(); super.disconnectedCallback();
this.controller.removeSyncObservers(); this.controller.removeSyncObservers();
this.removeContextMenuListeners(); this.removeContextMenuListeners();
this.removeSidebarFocusedListeners();
} }
handleContextMenuEvent(e) { handleContextMenuEvent(e) {
@ -65,6 +68,10 @@ class SyncedTabsInSidebar extends SidebarPage {
} }
} }
handleSidebarFocusedEvent() {
this.searchTextbox?.focus();
}
/** /**
* The template shown when the list of synced devices is currently * The template shown when the list of synced devices is currently
* unavailable. * unavailable.
@ -208,7 +215,6 @@ class SyncedTabsInSidebar extends SidebarPage {
> >
</sidebar-panel-header> </sidebar-panel-header>
<fxview-search-textbox <fxview-search-textbox
autofocus
data-l10n-id="firefoxview-search-text-box-syncedtabs" data-l10n-id="firefoxview-search-text-box-syncedtabs"
data-l10n-attrs="placeholder" data-l10n-attrs="placeholder"
@fxview-search-textbox-query=${this.onSearchQuery} @fxview-search-textbox-query=${this.onSearchQuery}

View file

@ -31,11 +31,18 @@ add_task(async function test_adopt_from_window() {
}); });
// Check category of new window sidebar is that of opener window sidebar // Check category of new window sidebar is that of opener window sidebar
let newSidebarBox = document.getElementById("sidebar-box"); let newSidebarBox;
await BrowserTestUtils.waitForCondition( await BrowserTestUtils.waitForCondition(() => {
() => BrowserTestUtils.isVisible(newSidebarBox), newSidebarBox = newWin.document.getElementById("sidebar-box");
"New sidebar box is visible" return newSidebarBox && BrowserTestUtils.isVisible(newSidebarBox);
}, "New sidebar box is visible");
Assert.notEqual(
newSidebarBox,
sidebarBox,
"sidebar box from the new window should be a different object"
); );
await BrowserTestUtils.waitForCondition( await BrowserTestUtils.waitForCondition(
() => !!newSidebarBox.getAttribute("sidebarcommand"), () => !!newSidebarBox.getAttribute("sidebarcommand"),
"Category has been set" "Category has been set"
@ -60,3 +67,61 @@ add_task(async function test_adopt_from_window() {
await BrowserTestUtils.closeWindow(newWin); await BrowserTestUtils.closeWindow(newWin);
await BrowserTestUtils.closeWindow(win); await BrowserTestUtils.closeWindow(win);
}); });
add_task(async function test_focus_history_from_adopted() {
const win = await BrowserTestUtils.openNewBrowserWindow();
const { document } = win;
const sidebar = document.querySelector("sidebar-main");
ok(sidebar, "Sidebar is shown.");
await sidebar.updateComplete;
await toggleSidebarPanel(win, "viewHistorySidebar");
const { SidebarController } = win;
const { contentDocument } = SidebarController.browser;
const historySidebar = contentDocument.querySelector("sidebar-history");
await BrowserTestUtils.waitForCondition(
() => !historySidebar.controller.isHistoryPending
);
await historySidebar.updateComplete;
Assert.equal(
historySidebar.shadowRoot.activeElement,
historySidebar.searchTextbox,
"Search box should be focused"
);
// Open a new window from the window containing the open sidebar
const newWin = lazy.BrowserWindowTracker.openWindow({
openerWindow: win,
});
let NewSidebarController;
await BrowserTestUtils.waitForCondition(
() => (NewSidebarController = newWin.SidebarController),
"newWin SidebarController is present"
);
let newWinHistorySidebar;
let newContentDocument;
await BrowserTestUtils.waitForCondition(() => {
newContentDocument = NewSidebarController.browser.contentDocument;
newWinHistorySidebar = newContentDocument?.querySelector("sidebar-history");
return (
newWinHistorySidebar?.controller &&
!newWinHistorySidebar.controller.isHistoryPending
);
}, "Make sure sidebar-history is present and history isn't pending");
await newWinHistorySidebar.updateComplete;
ok(newWinHistorySidebar.searchTextbox, "Search box should be present");
Assert.notEqual(
newWinHistorySidebar.shadowRoot.activeElement,
newWinHistorySidebar.searchTextbox,
"Search box should not be focused"
);
await BrowserTestUtils.closeWindow(newWin);
await BrowserTestUtils.closeWindow(win);
});

View file

@ -88,6 +88,18 @@ add_task(async function test_history_cards_created() {
} }
}); });
add_task(async function test_history_searchbox_focus() {
const { component } = await showHistorySidebar();
const { searchTextbox } = component;
ok(component.shadowRoot.activeElement, "check activeElement is present");
Assert.equal(
component.shadowRoot.activeElement,
searchTextbox,
"Check search box is focused"
);
});
add_task(async function test_history_search() { add_task(async function test_history_search() {
const { component, contentWindow } = await showHistorySidebar(); const { component, contentWindow } = await showHistorySidebar();
const { searchTextbox } = component; const { searchTextbox } = component;

View file

@ -119,3 +119,17 @@ add_task(async function test_tabs() {
SidebarController.hide(); SidebarController.hide();
sandbox.restore(); sandbox.restore();
}); });
add_task(async function test_syncedtabs_searchbox_focus() {
await SidebarController.show("viewTabsSidebar");
const { contentDocument } = SidebarController.browser;
const component = contentDocument.querySelector("sidebar-syncedtabs");
const { searchTextbox } = component;
ok(component.shadowRoot.activeElement, "check activeElement is present");
Assert.equal(
component.shadowRoot.activeElement,
searchTextbox,
"Check search box is focused"
);
});

View file

@ -103,6 +103,40 @@ add_task(async function test_toggle_vertical_tabs() {
is(win.gBrowser.tabs.length, 4, "Tabstrip now has four tabs"); is(win.gBrowser.tabs.length, 4, "Tabstrip now has four tabs");
const toolbarContextMenu = document.getElementById("toolbar-context-menu");
EventUtils.synthesizeMouseAtPoint(
containerRect.left + containerRect.width / 2,
tabRect.bottom + 100,
{
type: "contextmenu",
button: 2,
},
win
);
await openAndWaitForContextMenu(
toolbarContextMenu,
win.gBrowser.selectedTab,
() => {
ok(
document.getElementById("toolbar-context-customize").hidden,
"Customize menu item should be hidden"
);
ok(
!document.getElementById("toggle_PersonalToolbar"),
"Bookmarks menu item should not be present"
);
ok(
!document.getElementById("toolbar-context-reloadSelectedTab").hidden,
"Reload tab item should be visible"
);
ok(
!document.getElementById("toolbar-context-undoCloseTab").hidden,
"Undo close tab item should be visible"
);
}
);
// flip the pref to move the tabstrip horizontally // flip the pref to move the tabstrip horizontally
await SpecialPowers.pushPrefEnv({ set: [["sidebar.verticalTabs", false]] }); await SpecialPowers.pushPrefEnv({ set: [["sidebar.verticalTabs", false]] });

View file

@ -59,14 +59,10 @@ var gTabsPanel = {
insertBefore: document.getElementById("allTabsMenu-tabsSeparator"), insertBefore: document.getElementById("allTabsMenu-tabsSeparator"),
filterFn: tab => tab.hidden && tab.soundPlaying, filterFn: tab => tab.hidden && tab.soundPlaying,
}); });
let showPinnedTabs = Services.prefs.getBoolPref(
"browser.tabs.tabmanager.enabled"
);
this.allTabsPanel = new TabsPanel({ this.allTabsPanel = new TabsPanel({
view: this.allTabsView, view: this.allTabsView,
containerNode: this.allTabsViewTabs, containerNode: this.allTabsViewTabs,
filterFn: tab => filterFn: tab => !tab.hidden,
!tab.hidden && (!tab.pinned || (showPinnedTabs && tab.pinned)),
dropIndicator: this.dropIndicator, dropIndicator: this.dropIndicator,
}); });

View file

@ -327,8 +327,6 @@ skip-if = ["true"] # Bug 1616418 Bug 1549985
["browser_tab_manager_keyboard_access.js"] ["browser_tab_manager_keyboard_access.js"]
skip-if = ["true"] # Bug 1900477 skip-if = ["true"] # Bug 1900477
["browser_tab_manager_visibility.js"]
["browser_tab_move_to_new_window_reload.js"] ["browser_tab_move_to_new_window_reload.js"]
["browser_tab_play.js"] ["browser_tab_play.js"]

View file

@ -4,12 +4,6 @@
"use strict"; "use strict";
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [["browser.tabs.tabmanager.enabled", true]],
});
});
async function openAllTabsPanel(win) { async function openAllTabsPanel(win) {
const button = win.document.getElementById("alltabs-button"); const button = win.document.getElementById("alltabs-button");
const allTabsView = win.document.getElementById("allTabsMenu-allTabsView"); const allTabsView = win.document.getElementById("allTabsMenu-allTabsView");

View file

@ -9,12 +9,6 @@ const URL3 = "data:text/plain,tab3";
const URL4 = "data:text/plain,tab4"; const URL4 = "data:text/plain,tab4";
const URL5 = "data:text/plain,tab5"; const URL5 = "data:text/plain,tab5";
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [["browser.tabs.tabmanager.enabled", true]],
});
});
/** /**
* Tests that middle-clicking on a tab in the Tab Manager will close it. * Tests that middle-clicking on a tab in the Tab Manager will close it.
*/ */

View file

@ -46,8 +46,6 @@ function getOrderOfTabs(tabs) {
} }
async function testWithNewWindow(func) { async function testWithNewWindow(func) {
Services.prefs.setBoolPref("browser.tabs.tabmanager.enabled", true);
const newWindow = await BrowserTestUtils.openNewBrowserWindow(); const newWindow = await BrowserTestUtils.openNewBrowserWindow();
await Promise.all([ await Promise.all([
@ -75,8 +73,6 @@ async function testWithNewWindow(func) {
await func(newWindow); await func(newWindow);
await BrowserTestUtils.closeWindow(newWindow); await BrowserTestUtils.closeWindow(newWindow);
Services.prefs.clearUserPref("browser.tabs.tabmanager.enabled");
} }
add_task(async function test_reorder() { add_task(async function test_reorder() {

View file

@ -25,9 +25,6 @@ async function waitForAllTabsMenu(window = window) {
* by other tests. * by other tests.
*/ */
add_task(async function test_open_tabmanager_keyboard() { add_task(async function test_open_tabmanager_keyboard() {
await SpecialPowers.pushPrefEnv({
set: [["browser.tabs.tabmanager.enabled", true]],
});
let newWindow = await BrowserTestUtils.openNewBrowserWindow(); let newWindow = await BrowserTestUtils.openNewBrowserWindow();
let elem = newWindow.document.getElementById("alltabs-button"); let elem = newWindow.document.getElementById("alltabs-button");

View file

@ -1,54 +0,0 @@
/**
* Test the Tab Manager visibility respects browser.tabs.tabmanager.enabled preference
* */
"use strict";
// The hostname for the test URIs.
const TEST_HOSTNAME = "https://example.com";
const DUMMY_PAGE_PATH =
"/browser/components/tabbrowser/test/browser/tabs/dummy_page.html";
add_task(async function tab_manager_visibility_preference_on() {
Services.prefs.setBoolPref("browser.tabs.tabmanager.enabled", true);
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
await BrowserTestUtils.withNewTab(
{
gBrowser: newWindow.gBrowser,
url: TEST_HOSTNAME + DUMMY_PAGE_PATH,
},
async function () {
await Assert.ok(
BrowserTestUtils.isVisible(
newWindow.document.getElementById("alltabs-button")
),
"tab manage menu is visible when browser.tabs.tabmanager.enabled preference is set to true"
);
}
);
Services.prefs.clearUserPref("browser.tabs.tabmanager.enabled");
BrowserTestUtils.closeWindow(newWindow);
});
add_task(async function tab_manager_visibility_preference_off() {
Services.prefs.setBoolPref("browser.tabs.tabmanager.enabled", false);
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
await BrowserTestUtils.withNewTab(
{
gBrowser: newWindow.gBrowser,
url: TEST_HOSTNAME + DUMMY_PAGE_PATH,
},
async function () {
await Assert.ok(
BrowserTestUtils.isHidden(
newWindow.document.getElementById("alltabs-button")
),
"tab manage menu is hidden when browser.tabs.tabmanager.enabled preference is set to true"
);
}
);
Services.prefs.clearUserPref("browser.tabs.tabmanager.enabled");
BrowserTestUtils.closeWindow(newWindow);
});

View file

@ -17,6 +17,7 @@ add_heuristic_tests(
{ fieldName: "cc-number" }, { fieldName: "cc-number" },
{ fieldName: "cc-exp-month" }, { fieldName: "cc-exp-month" },
{ fieldName: "cc-exp-year" }, { fieldName: "cc-exp-year" },
{ fieldName: "cc-csc" },
], ],
}, },
{ {
@ -47,6 +48,7 @@ add_heuristic_tests(
{ fieldName: "cc-number", reason: "autocomplete" }, { fieldName: "cc-number", reason: "autocomplete" },
{ fieldName: "cc-exp-month", reason: "regex-heuristic" }, { fieldName: "cc-exp-month", reason: "regex-heuristic" },
{ fieldName: "cc-exp-year", reason: "update-heuristic" }, { fieldName: "cc-exp-year", reason: "update-heuristic" },
{ fieldName: "cc-csc", reason: "regex-heuristic" },
], ],
}, },
], ],

View file

@ -14,6 +14,7 @@ add_heuristic_tests(
fields: [ fields: [
{ fieldName: "cc-number", reason: "fathom" }, { fieldName: "cc-number", reason: "fathom" },
{ fieldName: "cc-exp", reason: "update-heuristic" }, { fieldName: "cc-exp", reason: "update-heuristic" },
{ fieldName: "cc-csc", reason: "regex-heuristic" },
{ fieldName: "cc-name", reason: "regex-heuristic" }, { fieldName: "cc-name", reason: "regex-heuristic" },
], ],
}, },

View file

@ -70,7 +70,7 @@ add_heuristic_tests([
{ {
fields: [ fields: [
{ fieldName: "cc-number", reason: "autocomplete" }, { fieldName: "cc-number", reason: "autocomplete" },
//{ fieldName: "cc-csc", reason: "autocomplete" }, { fieldName: "cc-csc", reason: "autocomplete" },
], ],
}, },
{ {

View file

@ -77,7 +77,7 @@ add_heuristic_tests(
{ fieldName: "cc-number", reason: "fathom" }, // ac-off { fieldName: "cc-number", reason: "fathom" }, // ac-off
{ fieldName: "cc-exp-month" }, { fieldName: "cc-exp-month" },
{ fieldName: "cc-exp-year" }, { fieldName: "cc-exp-year" },
// { fieldName: "cc-csc"}, // ac-off { fieldName: "cc-csc"}, // ac-off
{ fieldName: "cc-name", reason: "fathom" }, // ac-off { fieldName: "cc-name", reason: "fathom" }, // ac-off
], ],
}, },

View file

@ -14,6 +14,7 @@ add_heuristic_tests(
fields: [ fields: [
{ fieldName: "cc-number" }, { fieldName: "cc-number" },
{ fieldName: "cc-name" }, { fieldName: "cc-name" },
{ fieldName: "cc-csc", reason: "regex-heuristic" },
{ fieldName: "cc-exp-month", reason: "regex-heuristic" }, { fieldName: "cc-exp-month", reason: "regex-heuristic" },
{ fieldName: "cc-exp-year", reason: "regex-heuristic" }, { fieldName: "cc-exp-year", reason: "regex-heuristic" },
], ],

View file

@ -14,6 +14,7 @@ add_heuristic_tests(
fields: [ fields: [
{ fieldName: "cc-number" }, { fieldName: "cc-number" },
{ fieldName: "cc-exp" }, { fieldName: "cc-exp" },
{ fieldName: "cc-csc" },
{ fieldName: "cc-given-name" }, { fieldName: "cc-given-name" },
{ fieldName: "cc-family-name" }, { fieldName: "cc-family-name" },
], ],

View file

@ -13,10 +13,10 @@ add_heuristic_tests(
}, },
fields: [ fields: [
{ fieldName: "cc-number" }, { fieldName: "cc-number" },
//{ fieldName: "cc-cvc" }, { fieldName: "cc-csc", reason: "regex-heuristic" },
{ fieldName: "cc-exp-month" }, { fieldName: "cc-exp-month" },
{ fieldName: "cc-exp-year" }, { fieldName: "cc-exp-year" },
{ fieldName: "cc-type", reason: "regex-heuristic" }, { fieldName: "cc-type", reason: "regex-heuristic" },
], ],
}, },
{ {

View file

@ -15,6 +15,7 @@ add_heuristic_tests(
{ fieldName: "cc-number", reason: "fathom" }, { fieldName: "cc-number", reason: "fathom" },
{ fieldName: "cc-exp-month" }, { fieldName: "cc-exp-month" },
{ fieldName: "cc-exp-year" }, { fieldName: "cc-exp-year" },
{ fieldName: "cc-csc" },
], ],
}, },
], ],

View file

@ -45,6 +45,7 @@ add_heuristic_tests(
fields: [ fields: [
{ fieldName: "cc-exp-month", reason: "regex-heuristic" }, // invisible { fieldName: "cc-exp-month", reason: "regex-heuristic" }, // invisible
{ fieldName: "cc-exp-year", reason: "regex-heuristic" }, // invisible { fieldName: "cc-exp-year", reason: "regex-heuristic" }, // invisible
{ fieldName: "cc-csc", reason: "regex-heuristic" },
], ],
}, },
], ],

View file

@ -19,6 +19,7 @@ add_heuristic_tests(
{ fieldName: "cc-number", part: 4 }, { fieldName: "cc-number", part: 4 },
{ fieldName: "cc-exp-month", reason: "regex-heuristic" }, { fieldName: "cc-exp-month", reason: "regex-heuristic" },
{ fieldName: "cc-exp-year", reason: "regex-heuristic" }, { fieldName: "cc-exp-year", reason: "regex-heuristic" },
{ fieldName: "cc-csc", reason: "regex-heuristic" },
], ],
}, },
], ],

View file

@ -27,12 +27,12 @@ add_heuristic_tests(
// field is currently recognized as a 'csc' field. We need to implement a heuristic // field is currently recognized as a 'csc' field. We need to implement a heuristic
// to accurately determine the field type when a field aligns with multiple field types // to accurately determine the field type when a field aligns with multiple field types
// instead of depending on the order of we perform the matching // instead of depending on the order of we perform the matching
//{ {
//invalid: true, invalid: true,
//fields: [ fields: [
//{ fieldName: "email", reason: "regex-heuristic"}, { fieldName: "cc-csc", reason: "regex-heuristic"},
//], ],
//}, },
], ],
}, },
], ],

View file

@ -36,6 +36,7 @@ add_heuristic_tests(
fields: [ fields: [
{ fieldName: "cc-name" }, { fieldName: "cc-name" },
{ fieldName: "cc-number" }, // ac-off { fieldName: "cc-number" }, // ac-off
{ fieldName: "cc-csc", reason: "regex-heuristic"},
], ],
}, },
{ {
@ -47,7 +48,7 @@ add_heuristic_tests(
{ fieldName: "cc-number" }, // ac-off { fieldName: "cc-number" }, // ac-off
{ fieldName: "cc-exp-month", reason: "regex-heuristic" }, { fieldName: "cc-exp-month", reason: "regex-heuristic" },
{ fieldName: "cc-exp-year", reason: "regex-heuristic" }, { fieldName: "cc-exp-year", reason: "regex-heuristic" },
// { fieldName: "cc-csc"}, { fieldName: "cc-csc", reason: "regex-heuristic"},
], ],
}, },
{ {

View file

@ -42,6 +42,7 @@ add_heuristic_tests(
{ fieldName: "cc-exp-month" }, { fieldName: "cc-exp-month" },
{ fieldName: "cc-exp-year" }, { fieldName: "cc-exp-year" },
{ fieldName: "cc-number" }, { fieldName: "cc-number" },
{ fieldName: "cc-csc" },
], ],
}, },
{ {

View file

@ -19,7 +19,7 @@ add_heuristic_tests(
}, },
{ {
fields: [ fields: [
// { fieldName: "cc-csc"}, { fieldName: "cc-csc", reason: "regex-heuristic"},
{ fieldName: "cc-type", reason: "regex-heuristic" }, { fieldName: "cc-type", reason: "regex-heuristic" },
{ fieldName: "cc-number", reason: "fathom" }, { fieldName: "cc-number", reason: "fathom" },
{ fieldName: "cc-exp", reason: "update-heuristic" }, { fieldName: "cc-exp", reason: "update-heuristic" },
@ -28,6 +28,7 @@ add_heuristic_tests(
{ {
invalid: true, invalid: true,
fields: [ fields: [
{ fieldName: "cc-csc", reason: "regex-heuristic" },
{ fieldName: "cc-number", reason: "regex-heuristic" }, // txtQvcGiftCardNumber { fieldName: "cc-number", reason: "regex-heuristic" }, // txtQvcGiftCardNumber
], ],
}, },
@ -58,15 +59,16 @@ add_heuristic_tests(
reason: "fathom", reason: "fathom",
}, },
fields: [ fields: [
{ fieldName: "cc-csc", reason: "regex-heuristic"},
{ fieldName: "cc-type", reason: "regex-heuristic" }, // ac-off { fieldName: "cc-type", reason: "regex-heuristic" }, // ac-off
{ fieldName: "cc-number" }, // ac-off { fieldName: "cc-number" }, // ac-off
{ fieldName: "cc-exp", reason: "update-heuristic" }, { fieldName: "cc-exp", reason: "update-heuristic" },
// { fieldName: "cc-csc"},
], ],
}, },
{ {
invalid: true, invalid: true,
fields: [ fields: [
{ fieldName: "cc-csc", reason: "regex-heuristic" },
{ fieldName: "cc-number", reason: "regex-heuristic" }, // txtQvcGiftCardNumbe, ac-off { fieldName: "cc-number", reason: "regex-heuristic" }, // txtQvcGiftCardNumbe, ac-off
], ],
}, },

View file

@ -212,6 +212,8 @@ this.addonsSearchDetection = class extends ExtensionAPI {
fire.sync({ addonId, firstUrl, lastUrl }); fire.sync({ addonId, firstUrl, lastUrl });
}; };
const remoteTab = context.xulBrowser.frameLoader.remoteTab;
const listener = ({ requestId, url, originUrl }) => { const listener = ({ requestId, url, originUrl }) => {
// We exclude requests not originating from the location bar, // We exclude requests not originating from the location bar,
// bookmarks and other "system-ish" requests. // bookmarks and other "system-ish" requests.
@ -227,20 +229,47 @@ this.addonsSearchDetection = class extends ExtensionAPI {
const wrapper = ChannelWrapper.getRegisteredChannel( const wrapper = ChannelWrapper.getRegisteredChannel(
requestId, requestId,
context.extension.policy, context.extension.policy,
context.xulBrowser.frameLoader.remoteTab remoteTab
); );
wrapper.addEventListener("stop", stopListener); wrapper.addEventListener("stop", stopListener);
} }
}; };
const ensureRegisterChannel = data => {
// onRedirected depends on ChannelWrapper.getRegisteredChannel,
// which in turn depends on registerTraceableChannel to have been
// called. When a blocking webRequest listener is present, the
// parent/ext-webRequest.js implementation already calls that.
//
// A downside to a blocking webRequest listener is that it delays
// the network request until a roundtrip to the listener in the
// extension process has happened. Since we don't need to handle
// the onBeforeRequest event, avoid the overhead by handling the
// event and registration here, in the parent process.
data.registerTraceableChannel(extension.policy, remoteTab);
};
const parsedFilter = {
types: ["main_frame"],
urls: ExtensionUtils.parseMatchPatterns(filter.urls),
};
WebRequest.onBeforeRequest.addListener(
ensureRegisterChannel,
parsedFilter,
// blocking is needed to unlock data.registerTraceableChannel.
["blocking"],
{
addonId: extension.id,
policy: extension.policy,
blockingAllowed: true,
}
);
WebRequest.onBeforeRedirect.addListener( WebRequest.onBeforeRedirect.addListener(
listener, listener,
// filter parsedFilter,
{
types: ["main_frame"],
urls: ExtensionUtils.parseMatchPatterns(filter.urls),
},
// info // info
[], [],
// listener details // listener details
@ -252,6 +281,7 @@ this.addonsSearchDetection = class extends ExtensionAPI {
); );
return () => { return () => {
WebRequest.onBeforeRequest.removeListener(ensureRegisterChannel);
WebRequest.onBeforeRedirect.removeListener(listener); WebRequest.onBeforeRedirect.removeListener(listener);
}; };
}, },

View file

@ -47,12 +47,6 @@ class AddonsSearchDetection {
this.onRedirectedListener this.onRedirectedListener
); );
} }
// If there is already a listener, remove it so that we can re-add one
// after. This is because we're using the same listener with different URL
// patterns (when the list of search engines changes).
if (browser.webRequest.onBeforeRequest.hasListener(this.noOpListener)) {
browser.webRequest.onBeforeRequest.removeListener(this.noOpListener);
}
// Retrieve the list of URL patterns to monitor with our listener. // Retrieve the list of URL patterns to monitor with our listener.
// //
@ -65,23 +59,12 @@ class AddonsSearchDetection {
return; return;
} }
browser.webRequest.onBeforeRequest.addListener(
this.noOpListener,
{ types: ["main_frame"], urls: patterns },
["blocking"]
);
browser.addonsSearchDetection.onRedirected.addListener( browser.addonsSearchDetection.onRedirected.addListener(
this.onRedirectedListener, this.onRedirectedListener,
{ urls: patterns } { urls: patterns }
); );
} }
// This listener is required to force the registration of traceable channels.
noOpListener() {
// Do nothing.
}
async onRedirectedListener({ addonId, firstUrl, lastUrl }) { async onRedirectedListener({ addonId, firstUrl, lastUrl }) {
// When we do not have an add-on ID (in the request property bag), we // When we do not have an add-on ID (in the request property bag), we
// likely detected a search server-side redirect. // likely detected a search server-side redirect.

View file

@ -16,7 +16,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"af": { "af": {
"pin": false, "pin": false,
@ -35,7 +35,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"an": { "an": {
"pin": false, "pin": false,
@ -54,7 +54,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ar": { "ar": {
"pin": false, "pin": false,
@ -73,7 +73,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ast": { "ast": {
"pin": false, "pin": false,
@ -92,7 +92,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"az": { "az": {
"pin": false, "pin": false,
@ -111,7 +111,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"be": { "be": {
"pin": false, "pin": false,
@ -130,7 +130,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"bg": { "bg": {
"pin": false, "pin": false,
@ -149,7 +149,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"bn": { "bn": {
"pin": false, "pin": false,
@ -168,7 +168,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"bo": { "bo": {
"pin": false, "pin": false,
@ -187,7 +187,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"br": { "br": {
"pin": false, "pin": false,
@ -206,7 +206,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"brx": { "brx": {
"pin": false, "pin": false,
@ -225,7 +225,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"bs": { "bs": {
"pin": false, "pin": false,
@ -244,7 +244,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ca": { "ca": {
"pin": false, "pin": false,
@ -263,7 +263,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ca-valencia": { "ca-valencia": {
"pin": false, "pin": false,
@ -282,7 +282,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"cak": { "cak": {
"pin": false, "pin": false,
@ -301,7 +301,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ckb": { "ckb": {
"pin": false, "pin": false,
@ -320,7 +320,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"cs": { "cs": {
"pin": false, "pin": false,
@ -339,7 +339,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"cy": { "cy": {
"pin": false, "pin": false,
@ -358,7 +358,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"da": { "da": {
"pin": false, "pin": false,
@ -377,7 +377,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"de": { "de": {
"pin": false, "pin": false,
@ -396,7 +396,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"dsb": { "dsb": {
"pin": false, "pin": false,
@ -415,7 +415,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"el": { "el": {
"pin": false, "pin": false,
@ -434,7 +434,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"en-CA": { "en-CA": {
"pin": false, "pin": false,
@ -453,7 +453,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"en-GB": { "en-GB": {
"pin": false, "pin": false,
@ -472,7 +472,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"eo": { "eo": {
"pin": false, "pin": false,
@ -491,7 +491,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"es-AR": { "es-AR": {
"pin": false, "pin": false,
@ -510,7 +510,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"es-CL": { "es-CL": {
"pin": false, "pin": false,
@ -529,7 +529,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"es-ES": { "es-ES": {
"pin": false, "pin": false,
@ -548,7 +548,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"es-MX": { "es-MX": {
"pin": false, "pin": false,
@ -567,7 +567,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"et": { "et": {
"pin": false, "pin": false,
@ -586,7 +586,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"eu": { "eu": {
"pin": false, "pin": false,
@ -605,7 +605,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"fa": { "fa": {
"pin": false, "pin": false,
@ -624,7 +624,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ff": { "ff": {
"pin": false, "pin": false,
@ -643,7 +643,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"fi": { "fi": {
"pin": false, "pin": false,
@ -662,7 +662,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"fr": { "fr": {
"pin": false, "pin": false,
@ -681,7 +681,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"fur": { "fur": {
"pin": false, "pin": false,
@ -700,7 +700,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"fy-NL": { "fy-NL": {
"pin": false, "pin": false,
@ -719,7 +719,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ga-IE": { "ga-IE": {
"pin": false, "pin": false,
@ -738,7 +738,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"gd": { "gd": {
"pin": false, "pin": false,
@ -757,7 +757,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"gl": { "gl": {
"pin": false, "pin": false,
@ -776,7 +776,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"gn": { "gn": {
"pin": false, "pin": false,
@ -795,7 +795,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"gu-IN": { "gu-IN": {
"pin": false, "pin": false,
@ -814,7 +814,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"he": { "he": {
"pin": false, "pin": false,
@ -833,7 +833,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"hi-IN": { "hi-IN": {
"pin": false, "pin": false,
@ -852,7 +852,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"hr": { "hr": {
"pin": false, "pin": false,
@ -871,7 +871,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"hsb": { "hsb": {
"pin": false, "pin": false,
@ -890,7 +890,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"hu": { "hu": {
"pin": false, "pin": false,
@ -909,7 +909,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"hy-AM": { "hy-AM": {
"pin": false, "pin": false,
@ -928,7 +928,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"hye": { "hye": {
"pin": false, "pin": false,
@ -947,7 +947,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ia": { "ia": {
"pin": false, "pin": false,
@ -966,7 +966,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"id": { "id": {
"pin": false, "pin": false,
@ -985,7 +985,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"is": { "is": {
"pin": false, "pin": false,
@ -1004,7 +1004,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"it": { "it": {
"pin": false, "pin": false,
@ -1023,7 +1023,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ja": { "ja": {
"pin": false, "pin": false,
@ -1040,7 +1040,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ja-JP-mac": { "ja-JP-mac": {
"pin": false, "pin": false,
@ -1048,7 +1048,7 @@
"macosx64", "macosx64",
"macosx64-devedition" "macosx64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ka": { "ka": {
"pin": false, "pin": false,
@ -1067,7 +1067,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"kab": { "kab": {
"pin": false, "pin": false,
@ -1086,7 +1086,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"kk": { "kk": {
"pin": false, "pin": false,
@ -1105,7 +1105,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"km": { "km": {
"pin": false, "pin": false,
@ -1124,7 +1124,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"kn": { "kn": {
"pin": false, "pin": false,
@ -1143,7 +1143,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ko": { "ko": {
"pin": false, "pin": false,
@ -1162,7 +1162,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"lij": { "lij": {
"pin": false, "pin": false,
@ -1181,7 +1181,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"lo": { "lo": {
"pin": false, "pin": false,
@ -1200,7 +1200,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"lt": { "lt": {
"pin": false, "pin": false,
@ -1219,7 +1219,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ltg": { "ltg": {
"pin": false, "pin": false,
@ -1238,7 +1238,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"lv": { "lv": {
"pin": false, "pin": false,
@ -1257,7 +1257,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"meh": { "meh": {
"pin": false, "pin": false,
@ -1276,7 +1276,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"mk": { "mk": {
"pin": false, "pin": false,
@ -1295,7 +1295,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"mr": { "mr": {
"pin": false, "pin": false,
@ -1314,7 +1314,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ms": { "ms": {
"pin": false, "pin": false,
@ -1333,7 +1333,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"my": { "my": {
"pin": false, "pin": false,
@ -1352,7 +1352,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"nb-NO": { "nb-NO": {
"pin": false, "pin": false,
@ -1371,7 +1371,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ne-NP": { "ne-NP": {
"pin": false, "pin": false,
@ -1390,7 +1390,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"nl": { "nl": {
"pin": false, "pin": false,
@ -1409,7 +1409,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"nn-NO": { "nn-NO": {
"pin": false, "pin": false,
@ -1428,7 +1428,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"oc": { "oc": {
"pin": false, "pin": false,
@ -1447,7 +1447,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"pa-IN": { "pa-IN": {
"pin": false, "pin": false,
@ -1466,7 +1466,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"pl": { "pl": {
"pin": false, "pin": false,
@ -1485,7 +1485,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"pt-BR": { "pt-BR": {
"pin": false, "pin": false,
@ -1504,7 +1504,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"pt-PT": { "pt-PT": {
"pin": false, "pin": false,
@ -1523,7 +1523,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"rm": { "rm": {
"pin": false, "pin": false,
@ -1542,7 +1542,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ro": { "ro": {
"pin": false, "pin": false,
@ -1561,7 +1561,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ru": { "ru": {
"pin": false, "pin": false,
@ -1580,7 +1580,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"sat": { "sat": {
"pin": false, "pin": false,
@ -1599,7 +1599,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"sc": { "sc": {
"pin": false, "pin": false,
@ -1618,7 +1618,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"scn": { "scn": {
"pin": false, "pin": false,
@ -1637,7 +1637,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"sco": { "sco": {
"pin": false, "pin": false,
@ -1656,7 +1656,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"si": { "si": {
"pin": false, "pin": false,
@ -1675,7 +1675,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"sk": { "sk": {
"pin": false, "pin": false,
@ -1694,7 +1694,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"skr": { "skr": {
"pin": false, "pin": false,
@ -1713,7 +1713,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"sl": { "sl": {
"pin": false, "pin": false,
@ -1732,7 +1732,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"son": { "son": {
"pin": false, "pin": false,
@ -1751,7 +1751,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"sq": { "sq": {
"pin": false, "pin": false,
@ -1770,7 +1770,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"sr": { "sr": {
"pin": false, "pin": false,
@ -1789,7 +1789,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"sv-SE": { "sv-SE": {
"pin": false, "pin": false,
@ -1808,7 +1808,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"szl": { "szl": {
"pin": false, "pin": false,
@ -1827,7 +1827,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ta": { "ta": {
"pin": false, "pin": false,
@ -1846,7 +1846,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"te": { "te": {
"pin": false, "pin": false,
@ -1865,7 +1865,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"tg": { "tg": {
"pin": false, "pin": false,
@ -1884,7 +1884,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"th": { "th": {
"pin": false, "pin": false,
@ -1903,7 +1903,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"tl": { "tl": {
"pin": false, "pin": false,
@ -1922,7 +1922,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"tr": { "tr": {
"pin": false, "pin": false,
@ -1941,7 +1941,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"trs": { "trs": {
"pin": false, "pin": false,
@ -1960,7 +1960,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"uk": { "uk": {
"pin": false, "pin": false,
@ -1979,7 +1979,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"ur": { "ur": {
"pin": false, "pin": false,
@ -1998,7 +1998,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"uz": { "uz": {
"pin": false, "pin": false,
@ -2017,7 +2017,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"vi": { "vi": {
"pin": false, "pin": false,
@ -2036,7 +2036,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"wo": { "wo": {
"pin": false, "pin": false,
@ -2055,7 +2055,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"xh": { "xh": {
"pin": false, "pin": false,
@ -2074,7 +2074,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"zh-CN": { "zh-CN": {
"pin": false, "pin": false,
@ -2093,7 +2093,7 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
}, },
"zh-TW": { "zh-TW": {
"pin": false, "pin": false,
@ -2112,6 +2112,6 @@
"win64-aarch64-devedition", "win64-aarch64-devedition",
"win64-devedition" "win64-devedition"
], ],
"revision": "aea3843a8a961607b1c86af8741670b3fce0bb0a" "revision": "9f4b4cc220a63529fa7cd67cc8f6479dfc33ab64"
} }
} }

View file

@ -43,8 +43,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
const DEFAULT_EXTENSION_ICON = const DEFAULT_EXTENSION_ICON =
"chrome://mozapps/skin/extensions/extensionGeneric.svg"; "chrome://mozapps/skin/extensions/extensionGeneric.svg";
const HTML_NS = "http://www.w3.org/1999/xhtml";
function getTabBrowser(browser) { function getTabBrowser(browser) {
while (browser.ownerGlobal.docShell.itemType !== Ci.nsIDocShell.typeChrome) { while (browser.ownerGlobal.docShell.itemType !== Ci.nsIDocShell.typeChrome) {
browser = browser.ownerGlobal.docShell.chromeEventHandler; browser = browser.ownerGlobal.docShell.chromeEventHandler;
@ -397,8 +395,6 @@ export var ExtensionsUI = {
); );
} }
let checkbox;
const incognitoPermissionName = "internal:privateBrowsingAllowed"; const incognitoPermissionName = "internal:privateBrowsingAllowed";
let grantPrivateBrowsingAllowed = false; let grantPrivateBrowsingAllowed = false;
if (showIncognitoCheckbox) { if (showIncognitoCheckbox) {
@ -416,79 +412,7 @@ export var ExtensionsUI = {
let promise = new Promise(resolve => { let promise = new Promise(resolve => {
function eventCallback(topic) { function eventCallback(topic) {
let doc = this.browser.ownerDocument; if (topic == "swapping") {
if (topic == "showing") {
let textEl = doc.getElementById("addon-webext-perm-text");
textEl.textContent = strings.text;
textEl.hidden = !strings.text;
// By default, multiline strings don't get formatted properly. These
// are presently only used in site permission add-ons, so we treat it
// as a special case to avoid unintended effects on other things.
let isMultiline = strings.text.includes("\n\n");
textEl.classList.toggle(
"addon-webext-perm-text-multiline",
isMultiline
);
let listIntroEl = doc.getElementById("addon-webext-perm-intro");
listIntroEl.textContent = strings.listIntro;
listIntroEl.hidden = !strings.msgs.length || !strings.listIntro;
// Show the link to the sumo page if there are permissions listed
// or the private browsing checkbox is visible.
let listInfoEl = doc.getElementById("addon-webext-perm-info");
listInfoEl.hidden = !strings.msgs.length && !showIncognitoCheckbox;
let list = doc.getElementById("addon-webext-perm-list");
while (list.firstChild) {
list.firstChild.remove();
}
let singleEntryEl = doc.getElementById(
"addon-webext-perm-single-entry"
);
singleEntryEl.textContent = "";
singleEntryEl.hidden = true;
list.hidden = true;
const createPrivateBrowsingCheckbox = () => {
let checkboxEl = doc.createXULElement("checkbox");
checkboxEl.checked = grantPrivateBrowsingAllowed;
doc.l10n.setAttributes(
checkboxEl,
"popup-notification-addon-privatebrowsing-checkbox"
);
return checkboxEl;
};
if (strings.msgs.length === 0 && showIncognitoCheckbox) {
checkbox = createPrivateBrowsingCheckbox();
singleEntryEl.appendChild(checkbox);
singleEntryEl.hidden = false;
singleEntryEl.classList.add("webext-perm-optional");
singleEntryEl.classList.add("webext-perm-privatebrowsing");
} else if (strings.msgs.length === 1 && !showIncognitoCheckbox) {
singleEntryEl.textContent = strings.msgs[0];
singleEntryEl.hidden = false;
} else if (strings.msgs.length) {
for (let msg of strings.msgs) {
let item = doc.createElementNS(HTML_NS, "li");
item.classList.add("webext-perm-granted");
item.textContent = msg;
list.appendChild(item);
}
if (showIncognitoCheckbox) {
let item = doc.createElementNS(HTML_NS, "li");
item.classList.add("webext-perm-optional");
item.classList.add("webext-perm-privatebrowsing");
checkbox = createPrivateBrowsingCheckbox();
item.appendChild(checkbox);
list.appendChild(item);
}
list.hidden = false;
}
} else if (topic == "swapping") {
return true; return true;
} }
if (topic == "removed") { if (topic == "removed") {
@ -499,16 +423,38 @@ export var ExtensionsUI = {
return false; return false;
} }
// Show the SUMO link already part of the popupnotification by
// setting learnMoreURL option if there are permissions to be
// granted to the addon being installed (or if the private
// browsing checkbox is shown).
const learnMoreURL =
strings.msgs.length || showIncognitoCheckbox
? Services.urlFormatter.formatURLPref("app.support.baseURL") +
"extension-permissions"
: undefined;
let options = { let options = {
hideClose: true, hideClose: true,
popupIconURL: icon || DEFAULT_EXTENSION_ICON, popupIconURL: icon || DEFAULT_EXTENSION_ICON,
popupIconClass: icon ? "" : "addon-warning-icon", popupIconClass: icon ? "" : "addon-warning-icon",
learnMoreURL,
persistent: true, persistent: true,
eventCallback, eventCallback,
removeOnDismissal: true, removeOnDismissal: true,
popupOptions: { popupOptions: {
position: "bottomright topright", position: "bottomright topright",
}, },
// Pass additional options used internally by the
// addon-webext-permissions-notification custom element
// (defined and registered by browser-addons.js).
customElementOptions: {
strings,
showIncognitoCheckbox,
grantPrivateBrowsingAllowed,
onPrivateBrowsingAllowedChanged(value) {
grantPrivateBrowsingAllowed = value;
},
},
}; };
// The prompt/notification machinery has a special affordance wherein // The prompt/notification machinery has a special affordance wherein
// certain subsets of the header string can be designated "names", and // certain subsets of the header string can be designated "names", and
@ -529,9 +475,6 @@ export var ExtensionsUI = {
label: strings.acceptText, label: strings.acceptText,
accessKey: strings.acceptKey, accessKey: strings.acceptKey,
callback: () => { callback: () => {
grantPrivateBrowsingAllowed = showIncognitoCheckbox
? checkbox.checked
: undefined;
resolve(true); resolve(true);
}, },
}; };

View file

@ -125,12 +125,15 @@
/* Content area */ /* Content area */
.sidebar-splitter { /* stylelint-disable-next-line media-query-no-invalid */
appearance: none; @media not (-moz-bool-pref: "sidebar.revamp") {
width: 6px; .sidebar-splitter {
background-color: -moz-dialog; appearance: none;
border: 1px ThreeDShadow; width: 6px;
border-style: none solid; background-color: -moz-dialog;
border: 1px ThreeDShadow;
border-style: none solid;
}
} }
/* Tabstrip */ /* Tabstrip */

View file

@ -16,7 +16,7 @@
html|*.addon-webext-perm-list { html|*.addon-webext-perm-list {
margin-block-end: 0; margin-block-end: 0;
padding-inline-start: 10px; padding-inline-start: 0;
> html|li { > html|li {
list-style: none; list-style: none;

View file

@ -195,6 +195,23 @@ body {
margin: 0; margin: 0;
} }
/* Chrome/content separation */
#navigator-toolbox {
/* This reserves space for the tabbox shadow */
border-bottom: var(--hairline-border-width) solid var(--toolbar-bgcolor);
}
#tabbrowser-tabbox {
position: relative;
box-shadow: 0 0 0 var(--hairline-border-width) var(--chrome-content-separator-color);
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") {
box-shadow: 0 0 0 var(--hairline-border-width) var(--chrome-content-separator-color), 0 2px 6px 0 light-dark(rgb(0, 0, 0, 0.2), rgb(0, 0, 0, 0.8));
}
}
/* Toolbox and Toolbars */ /* Toolbox and Toolbars */
#navigator-toolbox { #navigator-toolbox {
@ -318,23 +335,6 @@ body {
} }
} }
/* Chrome/content separation */
#navigator-toolbox {
/* This reserves space for the tabbox shadow */
border-bottom: var(--hairline-border-width) solid var(--toolbar-bgcolor);
}
#tabbrowser-tabbox {
position: relative;
box-shadow: 0 0 0 var(--hairline-border-width) var(--chrome-content-separator-color);
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") {
box-shadow: 0 0 0 var(--hairline-border-width) var(--chrome-content-separator-color), 0 2px 6px 0 light-dark(rgb(0, 0, 0, 0.2), rgb(0, 0, 0, 0.8));
}
}
/* Hide the TabsToolbar titlebar controls if the menubar is permanently shown. /* Hide the TabsToolbar titlebar controls if the menubar is permanently shown.
* (That is, if the menu bar doesn't autohide, and we're not in a fullscreen or * (That is, if the menu bar doesn't autohide, and we're not in a fullscreen or
* popup window.) */ * popup window.) */

View file

@ -78,7 +78,10 @@
} }
.sidebar-splitter { .sidebar-splitter {
@media not (-moz-platform: linux) { --splitter-width: 4px;
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") or (not (-moz-platform: linux)) {
/* We don't let the splitter overlap the sidebar on Linux since the sidebar's /* We don't let the splitter overlap the sidebar on Linux since the sidebar's
scrollbar is too narrow on Linux. */ scrollbar is too narrow on Linux. */
appearance: none; appearance: none;
@ -86,22 +89,23 @@
border-inline-end-width: 1px; border-inline-end-width: 1px;
border-color: var(--sidebar-border-color); border-color: var(--sidebar-border-color);
min-width: 1px; min-width: 1px;
width: 4px; width: var(--splitter-width);
background-image: none !important; background-image: none !important;
background-color: transparent; background-color: transparent;
margin-inline-start: -4px; margin-inline-start: calc(-1 * var(--splitter-width));
position: relative; position: relative;
#sidebar-box[positionend] + & { #sidebar-box[positionend] + & {
border-inline-width: 1px 0; border-inline-width: 1px 0;
margin-inline: 0 -4px; margin-inline: 0 calc(-1 * var(--splitter-width));
} }
} }
/* stylelint-disable-next-line media-query-no-invalid */ /* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") { @media (-moz-bool-pref: "sidebar.revamp") {
--splitter-width: 6px;
transition: background-color 0.5s ease-in-out; transition: background-color 0.5s ease-in-out;
border-color: transparent; border-style: none;
&:hover { &:hover {
background-color: var(--focus-outline-color); background-color: var(--focus-outline-color);

View file

@ -832,8 +832,6 @@ sidebar-main[expanded] > #vertical-tabs > #tabbrowser-tabs[orient="vertical"] .t
&[visible] { &[visible] {
display: flex; display: flex;
/* make the scrollbars hug the side of the container */
margin-inline-end: -2px;
} }
} }
@ -1000,19 +998,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button {
#alltabs-button { #alltabs-button {
list-style-image: url(chrome://global/skin/icons/arrow-down.svg); list-style-image: url(chrome://global/skin/icons/arrow-down.svg);
/* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "browser.tabs.tabmanager.enabled") {
#tabbrowser-tabs:not([overflow], [hashiddentabs]) ~ & {
display: none;
}
#tabbrowser-tabs:not([overflow])[using-closing-tabs-spacer] ~ & {
/* temporary space to keep a tab's close button under the cursor */
display: flex;
visibility: hidden;
}
}
#tabbrowser-tabs[hiddensoundplaying] ~ & > .toolbarbutton-badge-stack > .toolbarbutton-badge { #tabbrowser-tabs[hiddensoundplaying] ~ & > .toolbarbutton-badge-stack > .toolbarbutton-badge {
background: transparent url(chrome://browser/skin/tabbrowser/tab-audio-playing-small.svg); background: transparent url(chrome://browser/skin/tabbrowser/tab-audio-playing-small.svg);
box-shadow: none; box-shadow: none;

View file

@ -317,5 +317,4 @@ def googlevr_sdk(value, target):
set_define("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled) set_define("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled)
set_config("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled) set_config("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled)
set_config("MOZ_ANDROID_GOOGLE_VR_INCLUDE", googlevr_sdk.include)
set_config("MOZ_ANDROID_GOOGLE_VR_LIBS", googlevr_sdk.libs) set_config("MOZ_ANDROID_GOOGLE_VR_LIBS", googlevr_sdk.libs)

View file

@ -44,7 +44,6 @@ option(
set_config("ENABLE_MOZSEARCH_PLUGIN", True, when="--enable-mozsearch-plugin") set_config("ENABLE_MOZSEARCH_PLUGIN", True, when="--enable-mozsearch-plugin")
set_define("MOZ_MOZSEARCH_PLUGIN", True, when="--enable-mozsearch-plugin")
@depends( @depends(

View file

@ -76,42 +76,3 @@ set_define(
check_msg="for memfd_create in sys/mman.h", check_msg="for memfd_create in sys/mman.h",
), ),
) )
# TODO: Move these checks to file specific to --enable-project=js.
have_perf_event_h = check_header("linux/perf_event.h", when=building_linux)
option(
"--with-linux-headers",
help="location where the Linux kernel headers can be found",
nargs=1,
)
passed_linux_header_flags = depends_if("--with-linux-headers")(
lambda v: ["-I%s" % v[0]]
)
@depends(
try_compile(
includes=["asm/unistd.h"],
body="return sizeof(__NR_perf_event_open);",
flags=passed_linux_header_flags,
check_msg="for perf_event_open system call",
),
when=have_perf_event_h,
)
def have_perf_event_open(have_perf_event_open):
if have_perf_event_open:
return True
set_config("HAVE_LINUX_PERF_EVENT_H", have_perf_event_open)
@depends(passed_linux_header_flags, have_perf_event_open)
def linux_headers_includes(passed_linux_header_flags, have_perf_event_open):
if have_perf_event_open and passed_linux_header_flags:
return passed_linux_header_flags[0]
set_config("LINUX_HEADERS_INCLUDES", linux_headers_includes)

View file

@ -176,7 +176,6 @@ def virtualenv_python3():
set_config("PYTHON3", virtualenv_python3.path) set_config("PYTHON3", virtualenv_python3.path)
set_config("PYTHON3_VERSION", virtualenv_python3.str_version)
# Inject mozconfig options # Inject mozconfig options
@ -379,28 +378,6 @@ def exposed_vcs_checkout_type(vcs_checkout_type, hg, git, automation):
set_config("VCS_CHECKOUT_TYPE", exposed_vcs_checkout_type) set_config("VCS_CHECKOUT_TYPE", exposed_vcs_checkout_type)
# Obtain a Repository interface for the current VCS repository.
@depends(build_environment, exposed_vcs_checkout_type, hg, git)
@imports(_from="mozversioncontrol", _import="get_repository_object")
def vcs_repository(build_env, vcs_checkout_type, hg, git):
if vcs_checkout_type == "hg":
return get_repository_object(build_env.topsrcdir, hg=hg)
elif vcs_checkout_type == "git":
return get_repository_object(build_env.topsrcdir, git=git)
elif vcs_checkout_type:
raise FatalCheckError("unhandled VCS type: %s" % vcs_checkout_type)
@depends_if(vcs_repository)
@checking("for sparse checkout")
def vcs_sparse_checkout(repo):
return repo.sparse_checkout_present()
set_config("VCS_SPARSE_CHECKOUT", vcs_sparse_checkout)
# The application/project to build # The application/project to build
# ============================================================== # ==============================================================
option( option(
@ -1193,9 +1170,7 @@ set_config("EARLY_BETA_OR_EARLIER", milestone.is_early_beta_or_earlier)
set_define("EARLY_BETA_OR_EARLIER", milestone.is_early_beta_or_earlier) set_define("EARLY_BETA_OR_EARLIER", milestone.is_early_beta_or_earlier)
set_define("MOZILLA_VERSION", depends(milestone)(lambda m: '"%s"' % m.version)) set_define("MOZILLA_VERSION", depends(milestone)(lambda m: '"%s"' % m.version))
set_config("MOZILLA_VERSION", milestone.version) set_config("MOZILLA_VERSION", milestone.version)
set_define("MOZILLA_VERSION_U", milestone.version)
set_define("MOZILLA_UAVERSION", depends(milestone)(lambda m: '"%s"' % m.uaversion)) set_define("MOZILLA_UAVERSION", depends(milestone)(lambda m: '"%s"' % m.uaversion))
set_config("MOZILLA_SYMBOLVERSION", milestone.symbolversion)
set_config("MOZ_APP_VERSION", milestone.app_version) set_config("MOZ_APP_VERSION", milestone.app_version)
set_config("MOZ_APP_VERSION_DISPLAY", milestone.app_version_display) set_config("MOZ_APP_VERSION_DISPLAY", milestone.app_version_display)

View file

@ -131,7 +131,7 @@ with only_when(building_with_gnu_compatible_cc):
is_libatomic_optional = check_std_atomic_requirements() is_libatomic_optional = check_std_atomic_requirements()
is_libatomic_required = check_std_atomic_requirements( is_libatomic_required = check_std_atomic_requirements(
flag="-latomic", when=~is_libatomic_optional flag=["-latomic"], when=~is_libatomic_optional
) )
@depends(is_libatomic_optional, is_libatomic_required) @depends(is_libatomic_optional, is_libatomic_required)

View file

@ -51,7 +51,6 @@ def js_without_nspr(build_nspr, system_nspr, js_standalone):
return not build_nspr and not system_nspr return not build_nspr and not system_nspr
set_config("JS_WITHOUT_NSPR", True, when=js_without_nspr)
set_define("JS_WITHOUT_NSPR", True, when=js_without_nspr) set_define("JS_WITHOUT_NSPR", True, when=js_without_nspr)

View file

@ -406,9 +406,6 @@ def hazard_analysis(value):
return True return True
set_config("MOZ_HAZARD", hazard_analysis)
# Cross-compilation related things. # Cross-compilation related things.
# ============================================================== # ==============================================================
option( option(
@ -428,20 +425,6 @@ def toolchain_prefix(value, host, target, cross_compiling):
return ("%s-" % target.toolchain, "%s-" % target.alias) return ("%s-" % target.toolchain, "%s-" % target.alias)
@depends(toolchain_prefix, target)
def first_toolchain_prefix(toolchain_prefix, target):
# Pass TOOLCHAIN_PREFIX down to the build system if it was given from the
# command line/environment (in which case there's only one value in the tuple),
# or when cross-compiling for Android or OSX.
if toolchain_prefix and (
target.os in ("Android", "OSX") or len(toolchain_prefix) == 1
):
return toolchain_prefix[0]
set_config("TOOLCHAIN_PREFIX", first_toolchain_prefix)
# Compilers # Compilers
# ============================================================== # ==============================================================
include("compilers-util.configure") include("compilers-util.configure")
@ -1069,14 +1052,6 @@ def compiler_wrapper(wrapper, ccache):
return tuple(wrapper) return tuple(wrapper)
@depends_if(compiler_wrapper)
def using_compiler_wrapper(compiler_wrapper):
return True
set_config("MOZ_USING_COMPILER_WRAPPER", using_compiler_wrapper)
@dependable @dependable
def wasm(): def wasm():
return split_triplet("wasm32-wasi", allow_wasi=True) return split_triplet("wasm32-wasi", allow_wasi=True)
@ -2062,7 +2037,6 @@ def select_linker_tmpl(host_or_target):
select_linker = select_linker_tmpl(target) select_linker = select_linker_tmpl(target)
set_config("LINKER_KIND", select_linker.KIND)
@template @template
@ -2758,10 +2732,6 @@ def ub_signed_overflow_san_flags(
linker_flags.ldflags.extend(["-fsanitize=signed-integer-overflow", "-rdynamic"]) linker_flags.ldflags.extend(["-fsanitize=signed-integer-overflow", "-rdynamic"])
set_define("MOZ_SIGNED_OVERFLOW_SANITIZE", True, when=ub_signed_overflow_san)
set_config("MOZ_SIGNED_OVERFLOW_SANITIZE", True, when=ub_signed_overflow_san)
option( option(
"--enable-unsigned-overflow-sanitizer", "--enable-unsigned-overflow-sanitizer",
help="Enable UndefinedBehavior Sanitizer (Unsigned Integer Overflow Parts)", help="Enable UndefinedBehavior Sanitizer (Unsigned Integer Overflow Parts)",
@ -2801,9 +2771,6 @@ def ub_unsigned_overflow_san_flags(
) )
set_define("MOZ_UNSIGNED_OVERFLOW_SANITIZE", True, when=ub_unsigned_overflow_san)
set_config("MOZ_UNSIGNED_OVERFLOW_SANITIZE", True, when=ub_unsigned_overflow_san)
# #
any_ubsan = ubsan | ub_signed_overflow_san | ub_unsigned_overflow_san any_ubsan = ubsan | ub_signed_overflow_san | ub_unsigned_overflow_san

View file

@ -3,7 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import codecs import codecs
import errno
import io import io
import itertools import itertools
import logging import logging
@ -154,12 +153,7 @@ def main(argv):
js_config = config.copy() js_config = config.copy()
pwd = os.getcwd() pwd = os.getcwd()
try: try:
try: os.makedirs("js/src", exist_ok=True)
os.makedirs("js/src")
except OSError as e:
if e.errno != errno.EEXIST:
raise
os.chdir("js/src") os.chdir("js/src")
js_config["OLD_CONFIGURE_SUBSTS"] = old_js_configure_substs js_config["OLD_CONFIGURE_SUBSTS"] = old_js_configure_substs
js_config["OLD_CONFIGURE_DEFINES"] = old_js_configure_defines js_config["OLD_CONFIGURE_DEFINES"] = old_js_configure_defines

View file

@ -140,6 +140,9 @@ support-files = [
"test-network-exceptions.html", "test-network-exceptions.html",
"test-network-request.html", "test-network-request.html",
"test-network.html", "test-network.html",
"test-json-mime.html",
"test-json-mime.json",
"test-json-mime.json^headers^",
"test-non-javascript-mime.html", "test-non-javascript-mime.html",
"test-non-javascript-mime.js", "test-non-javascript-mime.js",
"test-non-javascript-mime.js^headers^", "test-non-javascript-mime.js^headers^",
@ -564,6 +567,8 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and
["browser_webconsole_non_javascript_mime_warning.js"] ["browser_webconsole_non_javascript_mime_warning.js"]
["browser_webconsole_json_mime_warning.js"]
["browser_webconsole_non_javascript_mime_worker_error.js"] ["browser_webconsole_non_javascript_mime_worker_error.js"]
["browser_webconsole_non_standard_doctype_errors.js"] ["browser_webconsole_non_standard_doctype_errors.js"]

View file

@ -0,0 +1,20 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that <script> loads with JSON MIME types produce a warning.
// See Bug 1916351.
"use strict";
const TEST_URI =
"https://example.com/browser/devtools/client/webconsole/" +
"test/browser/" +
"test-json-mime.html";
const MIME_WARNING_MSG =
"The script from “https://example.com/browser/devtools/client/webconsole/test/browser/test-json-mime.json” was loaded even though its MIME type (“application/json”) is not a valid JavaScript MIME type.";
add_task(async function () {
const hud = await openNewTabAndConsole(TEST_URI);
await waitFor(() => findWarningMessage(hud, MIME_WARNING_MSG), "", 100);
ok(true, "JSON MIME type warning displayed");
});

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Console test for script with JSON MIME type</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script src="test-json-mime.json"></script>
</head>
<body>
<p>Web Console test for script with JSON MIME type.</p>
</body>
</html>

View file

@ -0,0 +1 @@
{ "test": 123 }

View file

@ -0,0 +1 @@
Content-Type: application/json

View file

@ -9270,43 +9270,39 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
// XXXbz mTiming should know what channel it's for, so we don't // XXXbz mTiming should know what channel it's for, so we don't
// need this hackery. // need this hackery.
bool toBeReset = false; const bool isJavaScript = SchemeIsJavascript(aLoadState->URI());
bool isJavaScript = SchemeIsJavascript(aLoadState->URI()); const bool isDownload = !aLoadState->FileName().IsVoid();
const bool toBeReset = !isJavaScript && MaybeInitTiming();
if (!isJavaScript) { // FIXME(emilio): Should this be done by javascript: uris? What about external
toBeReset = MaybeInitTiming(); // protocols?
} if (mTiming && !isDownload) {
bool isNotDownload = aLoadState->FileName().IsVoid();
if (mTiming && isNotDownload) {
mTiming->NotifyBeforeUnload(); mTiming->NotifyBeforeUnload();
} }
// Check if the page doesn't want to be unloaded. The javascript: // Check if the page doesn't want to be unloaded. The javascript:
// protocol handler deals with this for javascript: URLs. // protocol handler deals with this for javascript: URLs.
if (!isJavaScript && isNotDownload && if (!isJavaScript && !isDownload &&
!aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) { !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
bool okToUnload;
// Check if request is exempted from HTTPSOnlyMode and if https-first is // Check if request is exempted from HTTPSOnlyMode and if https-first is
// enabled, if so it means: // enabled, if so it means:
// * https-first failed to upgrade request to https // * https-first failed to upgrade request to https
// * we already asked for permission to unload and the user accepted // * we already asked for permission to unload and the user accepted
// otherwise we wouldn't be here. // otherwise we wouldn't be here.
bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing(); const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing();
bool isHistoryOrReload = false; const uint32_t loadType = aLoadState->LoadType();
uint32_t loadType = aLoadState->LoadType();
// Check if request is a reload. // Check if request is a reload.
if (loadType == LOAD_RELOAD_NORMAL || const bool isHistoryOrReload =
loadType == LOAD_RELOAD_NORMAL ||
loadType == LOAD_RELOAD_BYPASS_CACHE || loadType == LOAD_RELOAD_BYPASS_CACHE ||
loadType == LOAD_RELOAD_BYPASS_PROXY || loadType == LOAD_RELOAD_BYPASS_PROXY ||
loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE || loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
loadType == LOAD_HISTORY) { loadType == LOAD_HISTORY;
isHistoryOrReload = true;
}
// If it isn't a reload, the request already failed to be upgraded and // If it isn't a reload, the request already failed to be upgraded and
// https-first is enabled then don't ask the user again for permission to // https-first is enabled then don't ask the user again for permission to
// unload and just unload. // unload and just unload.
bool okToUnload;
if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() && if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) { nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) {
rv = mDocumentViewer->PermitUnload( rv = mDocumentViewer->PermitUnload(
@ -9324,7 +9320,7 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
} }
} }
if (mTiming && isNotDownload) { if (mTiming && !isDownload) {
mTiming->NotifyUnloadAccepted(mCurrentURI); mTiming->NotifyUnloadAccepted(mCurrentURI);
} }
@ -9358,7 +9354,7 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
// new request parameter. // new request parameter.
// Also pass nullptr for the document, since it doesn't affect the return // Also pass nullptr for the document, since it doesn't affect the return
// value for our purposes here. // value for our purposes here.
bool savePresentation = const bool savePresentation =
CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr, CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr,
/* aReportBFCacheComboTelemetry */ true); /* aReportBFCacheComboTelemetry */ true);
@ -9379,12 +9375,12 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
} }
} }
// Don't stop current network activity for javascript: URL's since // Don't stop current network activity for javascript: URL's since they might
// they might not result in any data, and thus nothing should be // not result in any data, and thus nothing should be stopped in those cases.
// stopped in those cases. In the case where they do result in // In the case where they do result in data, the javascript: URL channel takes
// data, the javascript: URL channel takes care of stopping // care of stopping current network activity. Similarly, downloads don't
// current network activity. // unload this document...
if (!isJavaScript && isNotDownload) { if (!isJavaScript && !isDownload) {
// Stop any current network activity. // Stop any current network activity.
// Also stop content if this is a zombie doc. otherwise // Also stop content if this is a zombie doc. otherwise
// the onload will be delayed by other loads initiated in the // the onload will be delayed by other loads initiated in the
@ -9392,7 +9388,6 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
// didn't fully load before the next load was initiated. // didn't fully load before the next load was initiated.
// If not a zombie, don't stop content until data // If not a zombie, don't stop content until data
// starts arriving from the new URI... // starts arriving from the new URI...
if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) || if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)) { LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)) {
rv = Stop(nsIWebNavigation::STOP_ALL); rv = Stop(nsIWebNavigation::STOP_ALL);

View file

@ -45,6 +45,9 @@ class AbortFollower : public nsISupports {
}; };
/* /*
* TODO(krosylight): The only consumer of this is Fetch. It would be nice to
* merge this back to AbortSignal as it's quite a duplication right now.
*
* AbortSignalImpl is a minimal implementation without an associated global * AbortSignalImpl is a minimal implementation without an associated global
* and without event dispatching, those are added in AbortSignal. * and without event dispatching, those are added in AbortSignal.
* See Bug 1478101 * See Bug 1478101
@ -60,7 +63,7 @@ class AbortSignalImpl : public nsISupports, public SupportsWeakPtr {
// Helper for other DOM code // Helper for other DOM code
JS::Value RawReason() const; JS::Value RawReason() const;
virtual void SignalAbort(JS::Handle<JS::Value> aReason); void SignalAbort(JS::Handle<JS::Value> aReason);
protected: protected:
// Subclasses of this class must call these Traverse and Unlink functions // Subclasses of this class must call these Traverse and Unlink functions
@ -72,6 +75,10 @@ class AbortSignalImpl : public nsISupports, public SupportsWeakPtr {
virtual ~AbortSignalImpl() { UnlinkFollowers(); } virtual ~AbortSignalImpl() { UnlinkFollowers(); }
virtual void SignalAbortWithDependents();
virtual void RunAbortSteps();
void SetAborted(JS::Handle<JS::Value> aReason); void SetAborted(JS::Handle<JS::Value> aReason);
JS::Heap<JS::Value> mReason; JS::Heap<JS::Value> mReason;
@ -83,7 +90,10 @@ class AbortSignalImpl : public nsISupports, public SupportsWeakPtr {
void UnlinkFollowers(); void UnlinkFollowers();
// Raw pointers. |AbortFollower::Follow| adds to this array, and // TODO(krosylight): We should rename all names around the term "Follow". See
// bug 1873648.
//
// |AbortFollower::Follow| adds to this array, and
// |AbortFollower::Unfollow| (also called by the destructor) will remove // |AbortFollower::Unfollow| (also called by the destructor) will remove
// from this array. Finally, calling |SignalAbort()| will (after running all // from this array. Finally, calling |SignalAbort()| will (after running all
// abort algorithms) empty this and make all contained followers |Unfollow()|. // abort algorithms) empty this and make all contained followers |Unfollow()|.

View file

@ -41,17 +41,35 @@ void AbortSignalImpl::GetReason(JSContext* aCx,
JS::Value AbortSignalImpl::RawReason() const { return mReason.get(); } JS::Value AbortSignalImpl::RawReason() const { return mReason.get(); }
// https://dom.spec.whatwg.org/#abortsignal-signal-abort steps 1-4 // https://dom.spec.whatwg.org/#abortsignal-signal-abort
void AbortSignalImpl::SignalAbort(JS::Handle<JS::Value> aReason) { void AbortSignalImpl::SignalAbort(JS::Handle<JS::Value> aReason) {
// Step 1. // Step 1: If signal is aborted, then return.
if (mAborted) { if (mAborted) {
return; return;
} }
// Step 2. // Step 2: Set signals abort reason to reason if it is given; otherwise to a
// new "AbortError" DOMException.
//
// (But given AbortSignalImpl is supposed to run without JS context, the
// DOMException creation is deferred to the getter.)
SetAborted(aReason); SetAborted(aReason);
// Step 3. // Step 3 - 6
SignalAbortWithDependents();
}
void AbortSignalImpl::SignalAbortWithDependents() {
// AbortSignalImpl cannot have dependents, so just run abort steps for itself.
RunAbortSteps();
}
// https://dom.spec.whatwg.org/#run-the-abort-steps
// This skips event firing as AbortSignalImpl is not supposed to be exposed to
// JS. It's done instead in AbortSignal::RunAbortSteps.
void AbortSignalImpl::RunAbortSteps() {
// Step 1: For each algorithm of signals abort algorithms: run algorithm.
//
// When there are multiple followers, the follower removal algorithm // When there are multiple followers, the follower removal algorithm
// https://dom.spec.whatwg.org/#abortsignal-remove could be invoked in an // https://dom.spec.whatwg.org/#abortsignal-remove could be invoked in an
// earlier algorithm to remove a later algorithm, so |mFollowers| must be a // earlier algorithm to remove a later algorithm, so |mFollowers| must be a
@ -61,7 +79,7 @@ void AbortSignalImpl::SignalAbort(JS::Handle<JS::Value> aReason) {
follower->RunAbortAlgorithm(); follower->RunAbortAlgorithm();
} }
// Step 4. // Step 2: Empty signals abort algorithms.
UnlinkFollowers(); UnlinkFollowers();
} }
@ -277,14 +295,26 @@ already_AddRefed<AbortSignal> AbortSignal::Any(
RefPtr<AbortSignal> resultSignal = RefPtr<AbortSignal> resultSignal =
new AbortSignal(aGlobal, false, JS::UndefinedHandleValue); new AbortSignal(aGlobal, false, JS::UndefinedHandleValue);
// Step 2. For each signal of signals: if signal is aborted, then set if (!aSignals.IsEmpty()) {
// resultSignal's abort reason to signal's abort reason and return // (Prepare for step 2 which uses the reason of this. Cannot use
// resultSignal. // RawReason because that can cause constructing new DOMException for each
for (const auto& signal : aSignals) { // dependent signal instead of sharing the single one.)
if (signal->Aborted()) { AutoJSAPI jsapi;
JS::Rooted<JS::Value> reason(RootingCx(), signal->RawReason()); if (!jsapi.Init(aGlobal)) {
resultSignal->SetAborted(reason); return nullptr;
return resultSignal.forget(); }
JSContext* cx = jsapi.cx();
// Step 2. For each signal of signals: if signal is aborted, then set
// resultSignal's abort reason to signal's abort reason and return
// resultSignal.
for (const auto& signal : aSignals) {
if (signal->Aborted()) {
JS::Rooted<JS::Value> reason(cx);
signal->GetReason(cx, &reason);
resultSignal->SetAborted(reason);
return resultSignal.forget();
}
} }
} }
@ -339,17 +369,56 @@ void AbortSignal::ThrowIfAborted(JSContext* aCx, ErrorResult& aRv) {
} }
} }
// https://dom.spec.whatwg.org/#abortsignal-signal-abort // Step 3 - 6 of https://dom.spec.whatwg.org/#abortsignal-signal-abort
void AbortSignal::SignalAbort(JS::Handle<JS::Value> aReason) { void AbortSignal::SignalAbortWithDependents() {
// Step 1, in case "signal abort" algorithm is called directly // Step 3: Let dependentSignalsToAbort be a new list.
if (Aborted()) { nsTArray<RefPtr<AbortSignal>> dependentSignalsToAbort;
return;
// mDependentSignals can go away after this function.
nsTArray<RefPtr<AbortSignal>> dependentSignals = std::move(mDependentSignals);
if (!dependentSignals.IsEmpty()) {
// (Prepare for step 4.1.1 which uses the reason of this. Cannot use
// RawReason because that can cause constructing new DOMException for each
// dependent signal instead of sharing the single one.)
AutoJSAPI jsapi;
if (!jsapi.Init(GetParentObject())) {
return;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> reason(cx);
GetReason(cx, &reason);
// Step 4. For each dependentSignal of signals dependent signals:
for (const auto& dependentSignal : dependentSignals) {
MOZ_ASSERT(dependentSignal->mSourceSignals.Contains(this));
// Step 4.1: If dependentSignal is not aborted, then:
if (!dependentSignal->Aborted()) {
// Step 4.1.1: Set dependentSignals abort reason to signals abort
// reason.
dependentSignal->SetAborted(reason);
// Step 4.1.2: Append dependentSignal to dependentSignalsToAbort.
dependentSignalsToAbort.AppendElement(dependentSignal);
}
}
} }
// Steps 1-4. // Step 5: Run the abort steps for signal.
AbortSignalImpl::SignalAbort(aReason); RunAbortSteps();
// Step 5. Fire an event named abort at this signal // Step 6: For each dependentSignal of dependentSignalsToAbort, run the abort
// steps for dependentSignal.
for (const auto& dependentSignal : dependentSignalsToAbort) {
dependentSignal->RunAbortSteps();
}
}
// https://dom.spec.whatwg.org/#run-the-abort-steps
void AbortSignal::RunAbortSteps() {
// Step 1 - 2:
AbortSignalImpl::RunAbortSteps();
// Step 3. Fire an event named abort at this signal.
EventInit init; EventInit init;
init.mBubbles = false; init.mBubbles = false;
init.mCancelable = false; init.mCancelable = false;
@ -358,14 +427,6 @@ void AbortSignal::SignalAbort(JS::Handle<JS::Value> aReason) {
event->SetTrusted(true); event->SetTrusted(true);
DispatchEvent(*event); DispatchEvent(*event);
// Step 6. Abort dependentSignals of this signal
for (const auto& dependant : mDependentSignals) {
MOZ_ASSERT(dependant->mSourceSignals.Contains(this));
dependant->SignalAbort(aReason);
}
// clear dependent signals so that they might be garbage collected
mDependentSignals.Clear();
} }
bool AbortSignal::Dependent() const { return mDependent; } bool AbortSignal::Dependent() const { return mDependent; }

View file

@ -55,9 +55,6 @@ class AbortSignal : public DOMEventTargetHelper, public AbortSignalImpl {
void ThrowIfAborted(JSContext* aCx, ErrorResult& aRv); void ThrowIfAborted(JSContext* aCx, ErrorResult& aRv);
// AbortSignalImpl
void SignalAbort(JS::Handle<JS::Value> aReason) override;
virtual bool IsTaskSignal() const { return false; } virtual bool IsTaskSignal() const { return false; }
bool Dependent() const; bool Dependent() const;
@ -67,6 +64,10 @@ class AbortSignal : public DOMEventTargetHelper, public AbortSignalImpl {
void MakeDependentOn(AbortSignal* aSignal); void MakeDependentOn(AbortSignal* aSignal);
void SignalAbortWithDependents() override;
void RunAbortSteps() override;
nsTArray<WeakPtr<AbortSignal>> mSourceSignals; nsTArray<WeakPtr<AbortSignal>> mSourceSignals;
nsTArray<RefPtr<AbortSignal>> mDependentSignals; nsTArray<RefPtr<AbortSignal>> mDependentSignals;

View file

@ -1493,7 +1493,7 @@ inline Maybe<Enum> StringToEnum(const StringT& aString) {
} }
template <typename Enum> template <typename Enum>
inline const nsCString& GetEnumString(Enum stringId) { inline constexpr const nsLiteralCString& GetEnumString(Enum stringId) {
MOZ_RELEASE_ASSERT( MOZ_RELEASE_ASSERT(
static_cast<size_t>(stringId) < static_cast<size_t>(stringId) <
mozilla::ArrayLength(binding_detail::EnumStrings<Enum>::Values)); mozilla::ArrayLength(binding_detail::EnumStrings<Enum>::Values));

View file

@ -12458,22 +12458,22 @@ class CGEnum(CGThing):
declare=fill( declare=fill(
""" """
template <> struct EnumStrings<${name}> { template <> struct EnumStrings<${name}> {
static const nsLiteralCString Values[${count}]; static constexpr nsLiteralCString Values[${count}] {
}; $*{entries}
""", };
name=self.enum.identifier.name,
count=self.nEnumStrings(),
),
define=fill(
"""
const nsLiteralCString EnumStrings<${name}>::Values[${count}] = {
$*{entries}
}; };
""", """,
name=self.enum.identifier.name, name=self.enum.identifier.name,
count=self.nEnumStrings(), count=self.nEnumStrings(),
entries="".join('"%s"_ns,\n' % val for val in self.enum.values()), entries="".join('"%s"_ns,\n' % val for val in self.enum.values()),
), ),
define=fill(
"""
constexpr nsLiteralCString EnumStrings<${name}>::Values[${count}];
""",
name=self.enum.identifier.name,
count=self.nEnumStrings(),
),
), ),
) )
toJSValue = CGEnumToJSValue(enum) toJSValue = CGEnumToJSValue(enum)

View file

@ -2598,24 +2598,91 @@ bool SharedContextWebgl::PruneTextureMemory(size_t aMargin, bool aPruneUnused) {
return mNumTextureHandles < oldItems; return mNumTextureHandles < oldItems;
} }
void DrawTargetWebgl::FillRect(const Rect& aRect, const Pattern& aPattern, // Attempt to convert a linear gradient to a 1D ramp texture.
const DrawOptions& aOptions) { Maybe<SurfacePattern> DrawTargetWebgl::LinearGradientToSurface(
if (SupportsPattern(aPattern)) { const RectDouble& aBounds, const Pattern& aPattern) {
RectDouble xformRect = TransformDouble(aRect); MOZ_ASSERT(aPattern.GetType() == PatternType::LINEAR_GRADIENT);
if (aPattern.GetType() == PatternType::COLOR) { const auto& gradient = static_cast<const LinearGradientPattern&>(aPattern);
if (Maybe<Rect> clipped = RectClippedToViewport(xformRect)) { // The gradient points must be transformed by the gradient's matrix.
// If the pattern is transform-invariant and the rect clips to the Point gradBegin = gradient.mMatrix.TransformPoint(gradient.mBegin);
// viewport, just clip drawing to the viewport to avoid transform Point gradEnd = gradient.mMatrix.TransformPoint(gradient.mEnd);
// issues. // Get the gradient points in user-space.
DrawRect(*clipped, aPattern, aOptions, Nothing(), nullptr, false); Point begin = mTransform.TransformPoint(gradBegin);
return; Point end = mTransform.TransformPoint(gradEnd);
// Find the normalized direction of the gradient and its length.
Point dir = end - begin;
float len = dir.Length();
dir = dir / len;
// Restrict the rendered bounds to fall within the canvas.
Rect visBounds = NarrowToFloat(aBounds.SafeIntersect(RectDouble(GetRect())));
// Calculate the distances along the gradient direction of the bounds.
float dist0 = (visBounds.TopLeft() - begin).DotProduct(dir);
float distX = visBounds.width * dir.x;
float distY = visBounds.height * dir.y;
float minDist = floorf(
std::max(dist0 + std::min(distX, 0.0f) + std::min(distY, 0.0f), 0.0f));
float maxDist = ceilf(
std::min(dist0 + std::max(distX, 0.0f) + std::max(distY, 0.0f), len));
// Calculate the approximate size of the ramp texture, and see if it would be
// sufficiently smaller than just rendering the primitive.
float subLen = maxDist - minDist;
if (subLen > 0 && subLen < 0.5f * visBounds.Area()) {
// Create a 1D texture to contain the gradient ramp. Reserve two extra
// texels at the beginning and end of the ramp to account for clamping.
RefPtr<DrawTargetSkia> dt = new DrawTargetSkia;
if (dt->Init(IntSize(int32_t(subLen + 2), 1), SurfaceFormat::B8G8R8A8)) {
// Fill the section of the gradient ramp that is actually used.
dt->FillRect(Rect(dt->GetRect()),
LinearGradientPattern(Point(1 - minDist, 0.0f),
Point(len + 1 - minDist, 0.0f),
gradient.mStops));
if (RefPtr<SourceSurface> snapshot = dt->Snapshot()) {
// Calculate a matrix that will map the gradient ramp texture onto the
// actual direction of the gradient.
Point gradDir = (gradEnd - gradBegin) / len;
Point tangent = Point(-gradDir.y, gradDir.x) / gradDir.Length();
SurfacePattern surfacePattern(
snapshot, ExtendMode::CLAMP,
Matrix(gradDir.x, gradDir.y, tangent.x, tangent.y, gradBegin.x,
gradBegin.y)
.PreTranslate(minDist - 1, 0));
if (SupportsPattern(surfacePattern)) {
return Some(surfacePattern);
}
} }
} }
if (RectInsidePrecisionLimits(xformRect)) { }
DrawRect(aRect, aPattern, aOptions); return Nothing();
}
void DrawTargetWebgl::FillRect(const Rect& aRect, const Pattern& aPattern,
const DrawOptions& aOptions) {
RectDouble xformRect = TransformDouble(aRect);
if (aPattern.GetType() == PatternType::COLOR) {
if (Maybe<Rect> clipped = RectClippedToViewport(xformRect)) {
// If the pattern is transform-invariant and the rect clips to the
// viewport, just clip drawing to the viewport to avoid transform
// issues.
DrawRect(*clipped, aPattern, aOptions, Nothing(), nullptr, false);
return; return;
} }
} }
if (RectInsidePrecisionLimits(xformRect)) {
if (SupportsPattern(aPattern)) {
DrawRect(aRect, aPattern, aOptions);
return;
}
if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
if (Maybe<SurfacePattern> surface =
LinearGradientToSurface(xformRect, aPattern)) {
if (DrawRect(aRect, *surface, aOptions, Nothing(), nullptr, true, true,
true)) {
return;
}
}
}
}
if (!mWebglValid) { if (!mWebglValid) {
MarkSkiaChanged(aOptions); MarkSkiaChanged(aOptions);
mSkia->FillRect(aRect, aPattern, aOptions); mSkia->FillRect(aRect, aPattern, aOptions);
@ -2772,7 +2839,7 @@ void DrawTargetWebgl::Fill(const Path* aPath, const Pattern& aPattern,
const SkPath& skiaPath = static_cast<const PathSkia*>(aPath)->GetPath(); const SkPath& skiaPath = static_cast<const PathSkia*>(aPath)->GetPath();
SkRect skiaRect = SkRect::MakeEmpty(); SkRect skiaRect = SkRect::MakeEmpty();
// Draw the path as a simple rectangle with a supported pattern when possible. // Draw the path as a simple rectangle with a supported pattern when possible.
if (skiaPath.isRect(&skiaRect) && SupportsPattern(aPattern)) { if (skiaPath.isRect(&skiaRect)) {
RectDouble rect = SkRectToRectDouble(skiaRect); RectDouble rect = SkRectToRectDouble(skiaRect);
RectDouble xformRect = TransformDouble(rect); RectDouble xformRect = TransformDouble(rect);
if (aPattern.GetType() == PatternType::COLOR) { if (aPattern.GetType() == PatternType::COLOR) {
@ -2784,9 +2851,21 @@ void DrawTargetWebgl::Fill(const Path* aPath, const Pattern& aPattern,
return; return;
} }
} }
if (RectInsidePrecisionLimits(xformRect)) { if (RectInsidePrecisionLimits(xformRect)) {
DrawRect(NarrowToFloat(rect), aPattern, aOptions); if (SupportsPattern(aPattern)) {
return; DrawRect(NarrowToFloat(rect), aPattern, aOptions);
return;
}
if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
if (Maybe<SurfacePattern> surface =
LinearGradientToSurface(xformRect, aPattern)) {
if (DrawRect(NarrowToFloat(rect), *surface, aOptions, Nothing(),
nullptr, true, true, true)) {
return;
}
}
}
} }
} }

View file

@ -619,6 +619,8 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
bool aTransformed = true, bool aClipped = true, bool aTransformed = true, bool aClipped = true,
bool aAccelOnly = false, bool aForceUpdate = false, bool aAccelOnly = false, bool aForceUpdate = false,
const StrokeOptions* aStrokeOptions = nullptr); const StrokeOptions* aStrokeOptions = nullptr);
Maybe<SurfacePattern> LinearGradientToSurface(const RectDouble& aBounds,
const Pattern& aPattern);
ColorPattern GetClearPattern() const; ColorPattern GetClearPattern() const;

View file

@ -13,9 +13,6 @@
#include "nsStringFwd.h" #include "nsStringFwd.h"
namespace mozilla::dom { namespace mozilla::dom {
const char* kFetchPriorityAttributeValueHigh = "high";
const char* kFetchPriorityAttributeValueLow = "low";
const char* kFetchPriorityAttributeValueAuto = "auto";
FetchPriority ToFetchPriority(RequestPriority aRequestPriority) { FetchPriority ToFetchPriority(RequestPriority aRequestPriority) {
switch (aRequestPriority) { switch (aRequestPriority) {

View file

@ -37,9 +37,9 @@ void LogPriorityMapping(LazyLogModule& aLazyLogModule,
FetchPriority aFetchPriority, FetchPriority aFetchPriority,
int32_t aSupportsPriority); int32_t aSupportsPriority);
extern const char* kFetchPriorityAttributeValueHigh; constexpr const char kFetchPriorityAttributeValueHigh[] = "high";
extern const char* kFetchPriorityAttributeValueLow; constexpr const char kFetchPriorityAttributeValueLow[] = "low";
extern const char* kFetchPriorityAttributeValueAuto; constexpr const char kFetchPriorityAttributeValueAuto[] = "auto";
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View file

@ -229,10 +229,10 @@ nsresult HTMLDNSPrefetch::Prefetch(
const OriginAttributes& aPartitionedPrincipalOriginAttributes, const OriginAttributes& aPartitionedPrincipalOriginAttributes,
nsIDNSService::DNSFlags flags) { nsIDNSService::DNSFlags flags) {
if (IsNeckoChild()) { if (IsNeckoChild()) {
// We need to check IsEmpty() because net_IsValidHostName() // We need to check IsEmpty() because net_IsValidDNSHost()
// considers empty strings to be valid hostnames // considers empty strings to be valid hostnames
if (!hostname.IsEmpty() && if (!hostname.IsEmpty() &&
net_IsValidHostName(NS_ConvertUTF16toUTF8(hostname))) { net_IsValidDNSHost(NS_ConvertUTF16toUTF8(hostname))) {
// during shutdown gNeckoChild might be null // during shutdown gNeckoChild might be null
if (gNeckoChild) { if (gNeckoChild) {
gNeckoChild->SendHTMLDNSPrefetch( gNeckoChild->SendHTMLDNSPrefetch(
@ -312,10 +312,10 @@ nsresult HTMLDNSPrefetch::CancelPrefetch(
nsIDNSService::DNSFlags flags, nsresult aReason) { nsIDNSService::DNSFlags flags, nsresult aReason) {
// Forward this request to Necko Parent if we're a child process // Forward this request to Necko Parent if we're a child process
if (IsNeckoChild()) { if (IsNeckoChild()) {
// We need to check IsEmpty() because net_IsValidHostName() // We need to check IsEmpty() because net_IsValidDNSHost()
// considers empty strings to be valid hostnames // considers empty strings to be valid hostnames
if (!hostname.IsEmpty() && if (!hostname.IsEmpty() &&
net_IsValidHostName(NS_ConvertUTF16toUTF8(hostname))) { net_IsValidDNSHost(NS_ConvertUTF16toUTF8(hostname))) {
// during shutdown gNeckoChild might be null // during shutdown gNeckoChild might be null
if (gNeckoChild && gNeckoChild->CanSend()) { if (gNeckoChild && gNeckoChild->CanSend()) {
gNeckoChild->SendCancelHTMLDNSPrefetch( gNeckoChild->SendCancelHTMLDNSPrefetch(

View file

@ -104,7 +104,7 @@ static const uint8_t NS_INPUTMODE_NUMERIC = 6;
static const uint8_t NS_INPUTMODE_DECIMAL = 7; static const uint8_t NS_INPUTMODE_DECIMAL = 7;
static const uint8_t NS_INPUTMODE_SEARCH = 8; static const uint8_t NS_INPUTMODE_SEARCH = 8;
static const nsAttrValue::EnumTable kInputmodeTable[] = { static constexpr nsAttrValue::EnumTable kInputmodeTable[] = {
{"none", NS_INPUTMODE_NONE}, {"none", NS_INPUTMODE_NONE},
{"text", NS_INPUTMODE_TEXT}, {"text", NS_INPUTMODE_TEXT},
{"tel", NS_INPUTMODE_TEL}, {"tel", NS_INPUTMODE_TEL},
@ -123,7 +123,7 @@ static const uint8_t NS_ENTERKEYHINT_PREVIOUS = 5;
static const uint8_t NS_ENTERKEYHINT_SEARCH = 6; static const uint8_t NS_ENTERKEYHINT_SEARCH = 6;
static const uint8_t NS_ENTERKEYHINT_SEND = 7; static const uint8_t NS_ENTERKEYHINT_SEND = 7;
static const nsAttrValue::EnumTable kEnterKeyHintTable[] = { static constexpr nsAttrValue::EnumTable kEnterKeyHintTable[] = {
{"enter", NS_ENTERKEYHINT_ENTER}, {"enter", NS_ENTERKEYHINT_ENTER},
{"done", NS_ENTERKEYHINT_DONE}, {"done", NS_ENTERKEYHINT_DONE},
{"go", NS_ENTERKEYHINT_GO}, {"go", NS_ENTERKEYHINT_GO},
@ -138,7 +138,7 @@ static const uint8_t NS_AUTOCAPITALIZE_SENTENCES = 2;
static const uint8_t NS_AUTOCAPITALIZE_WORDS = 3; static const uint8_t NS_AUTOCAPITALIZE_WORDS = 3;
static const uint8_t NS_AUTOCAPITALIZE_CHARACTERS = 4; static const uint8_t NS_AUTOCAPITALIZE_CHARACTERS = 4;
static const nsAttrValue::EnumTable kAutocapitalizeTable[] = { static constexpr nsAttrValue::EnumTable kAutocapitalizeTable[] = {
{"none", NS_AUTOCAPITALIZE_NONE}, {"none", NS_AUTOCAPITALIZE_NONE},
{"sentences", NS_AUTOCAPITALIZE_SENTENCES}, {"sentences", NS_AUTOCAPITALIZE_SENTENCES},
{"words", NS_AUTOCAPITALIZE_WORDS}, {"words", NS_AUTOCAPITALIZE_WORDS},
@ -168,7 +168,7 @@ nsresult nsGenericHTMLElement::CopyInnerTo(Element* aDst) {
return NS_OK; return NS_OK;
} }
static const nsAttrValue::EnumTable kDirTable[] = { static constexpr nsAttrValue::EnumTable kDirTable[] = {
{"ltr", Directionality::Ltr}, {"ltr", Directionality::Ltr},
{"rtl", Directionality::Rtl}, {"rtl", Directionality::Rtl},
{"auto", Directionality::Auto}, {"auto", Directionality::Auto},
@ -179,11 +179,11 @@ namespace {
// See <https://html.spec.whatwg.org/#the-popover-attribute>. // See <https://html.spec.whatwg.org/#the-popover-attribute>.
enum class PopoverAttributeKeyword : uint8_t { Auto, EmptyString, Manual }; enum class PopoverAttributeKeyword : uint8_t { Auto, EmptyString, Manual };
static const char* kPopoverAttributeValueAuto = "auto"; static constexpr const char kPopoverAttributeValueAuto[] = "auto";
static const char* kPopoverAttributeValueEmptyString = ""; static constexpr const char kPopoverAttributeValueEmptyString[] = "";
static const char* kPopoverAttributeValueManual = "manual"; static constexpr const char kPopoverAttributeValueManual[] = "manual";
static const nsAttrValue::EnumTable kPopoverTable[] = { static constexpr nsAttrValue::EnumTable kPopoverTable[] = {
{kPopoverAttributeValueAuto, PopoverAttributeKeyword::Auto}, {kPopoverAttributeValueAuto, PopoverAttributeKeyword::Auto},
{kPopoverAttributeValueEmptyString, PopoverAttributeKeyword::EmptyString}, {kPopoverAttributeValueEmptyString, PopoverAttributeKeyword::EmptyString},
{kPopoverAttributeValueManual, PopoverAttributeKeyword::Manual}, {kPopoverAttributeValueManual, PopoverAttributeKeyword::Manual},
@ -210,7 +210,7 @@ FetchPriority nsGenericHTMLElement::ToFetchPriority(const nsAString& aValue) {
namespace { namespace {
// <https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fetch-priority-attributes>. // <https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fetch-priority-attributes>.
static const nsAttrValue::EnumTable kFetchPriorityEnumTable[] = { static constexpr nsAttrValue::EnumTable kFetchPriorityEnumTable[] = {
{kFetchPriorityAttributeValueHigh, FetchPriority::High}, {kFetchPriorityAttributeValueHigh, FetchPriority::High},
{kFetchPriorityAttributeValueLow, FetchPriority::Low}, {kFetchPriorityAttributeValueLow, FetchPriority::Low},
{kFetchPriorityAttributeValueAuto, FetchPriority::Auto}, {kFetchPriorityAttributeValueAuto, FetchPriority::Auto},
@ -1109,7 +1109,7 @@ nsMapRuleToAttributesFunc nsGenericHTMLElement::GetAttributeMappingFunction()
return &MapCommonAttributesInto; return &MapCommonAttributesInto;
} }
static const nsAttrValue::EnumTable kDivAlignTable[] = { static constexpr nsAttrValue::EnumTable kDivAlignTable[] = {
{"left", StyleTextAlign::MozLeft}, {"left", StyleTextAlign::MozLeft},
{"right", StyleTextAlign::MozRight}, {"right", StyleTextAlign::MozRight},
{"center", StyleTextAlign::MozCenter}, {"center", StyleTextAlign::MozCenter},
@ -1117,7 +1117,7 @@ static const nsAttrValue::EnumTable kDivAlignTable[] = {
{"justify", StyleTextAlign::Justify}, {"justify", StyleTextAlign::Justify},
{nullptr, 0}}; {nullptr, 0}};
static const nsAttrValue::EnumTable kFrameborderTable[] = { static constexpr nsAttrValue::EnumTable kFrameborderTable[] = {
{"yes", FrameBorderProperty::Yes}, {"yes", FrameBorderProperty::Yes},
{"no", FrameBorderProperty::No}, {"no", FrameBorderProperty::No},
{"1", FrameBorderProperty::One}, {"1", FrameBorderProperty::One},
@ -1125,7 +1125,7 @@ static const nsAttrValue::EnumTable kFrameborderTable[] = {
{nullptr, 0}}; {nullptr, 0}};
// TODO(emilio): Nobody uses the parsed attribute here. // TODO(emilio): Nobody uses the parsed attribute here.
static const nsAttrValue::EnumTable kScrollingTable[] = { static constexpr nsAttrValue::EnumTable kScrollingTable[] = {
{"yes", ScrollingAttribute::Yes}, {"yes", ScrollingAttribute::Yes},
{"no", ScrollingAttribute::No}, {"no", ScrollingAttribute::No},
{"on", ScrollingAttribute::On}, {"on", ScrollingAttribute::On},
@ -1135,7 +1135,7 @@ static const nsAttrValue::EnumTable kScrollingTable[] = {
{"auto", ScrollingAttribute::Auto}, {"auto", ScrollingAttribute::Auto},
{nullptr, 0}}; {nullptr, 0}};
static const nsAttrValue::EnumTable kTableVAlignTable[] = { static constexpr nsAttrValue::EnumTable kTableVAlignTable[] = {
{"top", StyleVerticalAlignKeyword::Top}, {"top", StyleVerticalAlignKeyword::Top},
{"middle", StyleVerticalAlignKeyword::Middle}, {"middle", StyleVerticalAlignKeyword::Middle},
{"bottom", StyleVerticalAlignKeyword::Bottom}, {"bottom", StyleVerticalAlignKeyword::Bottom},
@ -1144,7 +1144,7 @@ static const nsAttrValue::EnumTable kTableVAlignTable[] = {
bool nsGenericHTMLElement::ParseAlignValue(const nsAString& aString, bool nsGenericHTMLElement::ParseAlignValue(const nsAString& aString,
nsAttrValue& aResult) { nsAttrValue& aResult) {
static const nsAttrValue::EnumTable kAlignTable[] = { static constexpr nsAttrValue::EnumTable kAlignTable[] = {
{"left", StyleTextAlign::Left}, {"left", StyleTextAlign::Left},
{"right", StyleTextAlign::Right}, {"right", StyleTextAlign::Right},
@ -1194,7 +1194,7 @@ bool nsGenericHTMLElement::ParseAlignValue(const nsAString& aString,
//---------------------------------------- //----------------------------------------
static const nsAttrValue::EnumTable kTableHAlignTable[] = { static constexpr nsAttrValue::EnumTable kTableHAlignTable[] = {
{"left", StyleTextAlign::Left}, {"left", StyleTextAlign::Left},
{"right", StyleTextAlign::Right}, {"right", StyleTextAlign::Right},
{"center", StyleTextAlign::Center}, {"center", StyleTextAlign::Center},
@ -1209,7 +1209,7 @@ bool nsGenericHTMLElement::ParseTableHAlignValue(const nsAString& aString,
//---------------------------------------- //----------------------------------------
// This table is used for td, th, tr, col, thead, tbody and tfoot. // This table is used for td, th, tr, col, thead, tbody and tfoot.
static const nsAttrValue::EnumTable kTableCellHAlignTable[] = { static constexpr nsAttrValue::EnumTable kTableCellHAlignTable[] = {
{"left", StyleTextAlign::MozLeft}, {"left", StyleTextAlign::MozLeft},
{"right", StyleTextAlign::MozRight}, {"right", StyleTextAlign::MozRight},
{"center", StyleTextAlign::MozCenter}, {"center", StyleTextAlign::MozCenter},
@ -1251,9 +1251,7 @@ bool nsGenericHTMLElement::ParseImageAttribute(nsAtom* aAttribute,
bool nsGenericHTMLElement::ParseReferrerAttribute(const nsAString& aString, bool nsGenericHTMLElement::ParseReferrerAttribute(const nsAString& aString,
nsAttrValue& aResult) { nsAttrValue& aResult) {
using mozilla::dom::ReferrerInfo; using mozilla::dom::ReferrerInfo;
// This is a bit sketchy, we assume GetEnumString(…).get() points to a static static constexpr nsAttrValue::EnumTable kReferrerPolicyTable[] = {
// buffer, relying on the fact that GetEnumString(…) returns a literal string.
static const nsAttrValue::EnumTable kReferrerPolicyTable[] = {
{GetEnumString(ReferrerPolicy::No_referrer).get(), {GetEnumString(ReferrerPolicy::No_referrer).get(),
static_cast<int16_t>(ReferrerPolicy::No_referrer)}, static_cast<int16_t>(ReferrerPolicy::No_referrer)},
{GetEnumString(ReferrerPolicy::Origin).get(), {GetEnumString(ReferrerPolicy::Origin).get(),
@ -2770,7 +2768,7 @@ void nsGenericHTMLFormControlElement::SetFormAutofillState(
//---------------------------------------------------------------------- //----------------------------------------------------------------------
static const nsAttrValue::EnumTable kPopoverTargetActionTable[] = { static constexpr nsAttrValue::EnumTable kPopoverTargetActionTable[] = {
{"toggle", PopoverTargetAction::Toggle}, {"toggle", PopoverTargetAction::Toggle},
{"show", PopoverTargetAction::Show}, {"show", PopoverTargetAction::Show},
{"hide", PopoverTargetAction::Hide}, {"hide", PopoverTargetAction::Hide},

View file

@ -53,7 +53,7 @@ bool PrivateAttribution::GetSourceHostIfNonPrivate(nsACString& aSourceHost,
[[nodiscard]] static bool ValidateHost(const nsACString& aHost, [[nodiscard]] static bool ValidateHost(const nsACString& aHost,
ErrorResult& aRv) { ErrorResult& aRv) {
if (!net_IsValidHostName(aHost)) { if (!net_IsValidDNSHost(aHost)) {
aRv.ThrowSyntaxError(aHost + " is not a valid host name"_ns); aRv.ThrowSyntaxError(aHost + " is not a valid host name"_ns);
return false; return false;
} }

View file

@ -6,6 +6,7 @@
#include "SVGPolyElement.h" #include "SVGPolyElement.h"
#include "DOMSVGPointList.h" #include "DOMSVGPointList.h"
#include "mozilla/dom/SVGAnimatedLength.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "SVGContentUtils.h" #include "SVGContentUtils.h"
@ -48,13 +49,15 @@ void SVGPolyElement::GetMarkPoints(nsTArray<SVGMark>* aMarks) {
if (!points.Length()) return; if (!points.Length()) return;
float px = points[0].mX, py = points[0].mY, prevAngle = 0.0; float zoom = UserSpaceMetrics::GetZoom(this);
float px = points[0].mX * zoom, py = points[0].mY * zoom, prevAngle = 0.0;
aMarks->AppendElement(SVGMark(px, py, 0, SVGMark::eStart)); aMarks->AppendElement(SVGMark(px, py, 0, SVGMark::eStart));
for (uint32_t i = 1; i < points.Length(); ++i) { for (uint32_t i = 1; i < points.Length(); ++i) {
float x = points[i].mX; float x = points[i].mX * zoom;
float y = points[i].mY; float y = points[i].mY * zoom;
float angle = std::atan2(y - py, x - px); float angle = std::atan2(y - py, x - px);
// Vertex marker. // Vertex marker.
@ -93,18 +96,20 @@ bool SVGPolyElement::GetGeometryBounds(Rect* aBounds,
return false; return false;
} }
float zoom = UserSpaceMetrics::GetZoom(this);
if (aToBoundsSpace.IsRectilinear()) { if (aToBoundsSpace.IsRectilinear()) {
// We can avoid transforming each point and just transform the result. // We can avoid transforming each point and just transform the result.
// Important for large point lists. // Important for large point lists.
Rect bounds(points[0], Size()); Rect bounds(points[0] * zoom, Size());
for (uint32_t i = 1; i < points.Length(); ++i) { for (uint32_t i = 1; i < points.Length(); ++i) {
bounds.ExpandToEnclose(points[i]); bounds.ExpandToEnclose(points[i] * zoom);
} }
*aBounds = aToBoundsSpace.TransformBounds(bounds); *aBounds = aToBoundsSpace.TransformBounds(bounds);
} else { } else {
*aBounds = Rect(aToBoundsSpace.TransformPoint(points[0]), Size()); *aBounds = Rect(aToBoundsSpace.TransformPoint(points[0] * zoom), Size());
for (uint32_t i = 1; i < points.Length(); ++i) { for (uint32_t i = 1; i < points.Length(); ++i) {
aBounds->ExpandToEnclose(aToBoundsSpace.TransformPoint(points[i])); aBounds->ExpandToEnclose(aToBoundsSpace.TransformPoint(points[i] * zoom));
} }
} }
return true; return true;

View file

@ -6,6 +6,7 @@
#include "mozilla/dom/SVGPolygonElement.h" #include "mozilla/dom/SVGPolygonElement.h"
#include "mozilla/dom/SVGPolygonElementBinding.h" #include "mozilla/dom/SVGPolygonElementBinding.h"
#include "mozilla/dom/SVGAnimatedLength.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "SVGContentUtils.h" #include "SVGContentUtils.h"
@ -64,9 +65,11 @@ already_AddRefed<Path> SVGPolygonElement::BuildPath(PathBuilder* aBuilder) {
return nullptr; return nullptr;
} }
aBuilder->MoveTo(points[0]); float zoom = UserSpaceMetrics::GetZoom(this);
aBuilder->MoveTo(points[0] * zoom);
for (uint32_t i = 1; i < points.Length(); ++i) { for (uint32_t i = 1; i < points.Length(); ++i) {
aBuilder->LineTo(points[i]); aBuilder->LineTo(points[i] * zoom);
} }
aBuilder->Close(); aBuilder->Close();

View file

@ -6,6 +6,7 @@
#include "mozilla/dom/SVGPolylineElement.h" #include "mozilla/dom/SVGPolylineElement.h"
#include "mozilla/dom/SVGPolylineElementBinding.h" #include "mozilla/dom/SVGPolylineElementBinding.h"
#include "mozilla/dom/SVGAnimatedLength.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
using namespace mozilla::gfx; using namespace mozilla::gfx;
@ -41,9 +42,11 @@ already_AddRefed<Path> SVGPolylineElement::BuildPath(PathBuilder* aBuilder) {
return nullptr; return nullptr;
} }
aBuilder->MoveTo(points[0]); float zoom = UserSpaceMetrics::GetZoom(this);
aBuilder->MoveTo(points[0] * zoom);
for (uint32_t i = 1; i < points.Length(); ++i) { for (uint32_t i = 1; i < points.Length(); ++i) {
aBuilder->LineTo(points[i]); aBuilder->LineTo(points[i] * zoom);
} }
return aBuilder->Finish(); return aBuilder->Finish();

Binary file not shown.

View file

@ -1,10 +1,6 @@
# 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/.
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

7
gradlew vendored
View file

@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# SPDX-License-Identifier: Apache-2.0
#
############################################################################## ##############################################################################
# #
@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum

2
gradlew.bat vendored
View file

@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################

View file

@ -37,7 +37,7 @@ namespace gc {
class Arena; class Arena;
struct Cell; struct Cell;
class TenuredChunk; class ArenaChunk;
class StoreBuffer; class StoreBuffer;
class TenuredCell; class TenuredCell;
@ -84,7 +84,7 @@ const size_t ArenaBitmapWords = HowMany(ArenaBitmapBits, JS_BITS_PER_WORD);
enum class ChunkKind : uint8_t { enum class ChunkKind : uint8_t {
Invalid = 0, Invalid = 0,
TenuredHeap, TenuredArenas,
NurseryToSpace, NurseryToSpace,
NurseryFromSpace NurseryFromSpace
}; };
@ -97,13 +97,13 @@ class ChunkBase {
// Initialize a tenured heap chunk. // Initialize a tenured heap chunk.
explicit ChunkBase(JSRuntime* rt) { explicit ChunkBase(JSRuntime* rt) {
MOZ_ASSERT((uintptr_t(this) & ChunkMask) == 0); MOZ_ASSERT((uintptr_t(this) & ChunkMask) == 0);
initBaseForTenuredChunk(rt); initBaseForArenaChunk(rt);
} }
void initBaseForTenuredChunk(JSRuntime* rt) { void initBaseForArenaChunk(JSRuntime* rt) {
runtime = rt; runtime = rt;
storeBuffer = nullptr; storeBuffer = nullptr;
kind = ChunkKind::TenuredHeap; kind = ChunkKind::TenuredArenas;
nurseryChunkIndex = UINT8_MAX; nurseryChunkIndex = UINT8_MAX;
} }
@ -123,7 +123,7 @@ class ChunkBase {
ChunkKind getKind() const { ChunkKind getKind() const {
MOZ_ASSERT_IF(storeBuffer, kind == ChunkKind::NurseryToSpace || MOZ_ASSERT_IF(storeBuffer, kind == ChunkKind::NurseryToSpace ||
kind == ChunkKind::NurseryFromSpace); kind == ChunkKind::NurseryFromSpace);
MOZ_ASSERT_IF(!storeBuffer, kind == ChunkKind::TenuredHeap); MOZ_ASSERT_IF(!storeBuffer, kind == ChunkKind::TenuredArenas);
return kind; return kind;
} }
@ -139,12 +139,12 @@ class ChunkBase {
uint8_t nurseryChunkIndex; uint8_t nurseryChunkIndex;
}; };
// Information about tenured heap chunks. // Information about tenured heap chunks containing arenas.
struct TenuredChunkInfo { struct ArenaChunkInfo {
private: private:
friend class ChunkPool; friend class ChunkPool;
TenuredChunk* next = nullptr; ArenaChunk* next = nullptr;
TenuredChunk* prev = nullptr; ArenaChunk* prev = nullptr;
public: public:
/* Number of free arenas, either committed or decommitted. */ /* Number of free arenas, either committed or decommitted. */
@ -180,7 +180,7 @@ const size_t BitsPerPageWithHeaders =
(ArenaSize + ArenaBitmapBytes) * ArenasPerPage * CHAR_BIT + ArenasPerPage + (ArenaSize + ArenaBitmapBytes) * ArenasPerPage * CHAR_BIT + ArenasPerPage +
1; 1;
const size_t ChunkBitsAvailable = const size_t ChunkBitsAvailable =
(ChunkSize - sizeof(ChunkBase) - sizeof(TenuredChunkInfo)) * CHAR_BIT; (ChunkSize - sizeof(ChunkBase) - sizeof(ArenaChunkInfo)) * CHAR_BIT;
const size_t PagesPerChunk = ChunkBitsAvailable / BitsPerPageWithHeaders; const size_t PagesPerChunk = ChunkBitsAvailable / BitsPerPageWithHeaders;
const size_t ArenasPerChunk = PagesPerChunk * ArenasPerPage; const size_t ArenasPerChunk = PagesPerChunk * ArenasPerPage;
const size_t FreeCommittedBits = ArenasPerChunk; const size_t FreeCommittedBits = ArenasPerChunk;
@ -190,7 +190,7 @@ const size_t BitsPerArenaWithHeaders =
(DecommitBits / ArenasPerChunk) + 1; (DecommitBits / ArenasPerChunk) + 1;
const size_t CalculatedChunkSizeRequired = const size_t CalculatedChunkSizeRequired =
sizeof(ChunkBase) + sizeof(TenuredChunkInfo) + sizeof(ChunkBase) + sizeof(ArenaChunkInfo) +
RoundUp(ArenasPerChunk * ArenaBitmapBytes, sizeof(uintptr_t)) + RoundUp(ArenasPerChunk * ArenaBitmapBytes, sizeof(uintptr_t)) +
RoundUp(FreeCommittedBits, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT + RoundUp(FreeCommittedBits, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT +
RoundUp(DecommitBits, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT + RoundUp(DecommitBits, sizeof(uint32_t) * CHAR_BIT) / CHAR_BIT +
@ -205,10 +205,13 @@ static_assert(CalculatedChunkPadSize * CHAR_BIT < BitsPerArenaWithHeaders,
static_assert(ArenasPerChunk == 252, static_assert(ArenasPerChunk == 252,
"Do not accidentally change our heap's density."); "Do not accidentally change our heap's density.");
const size_t FirstArenaOffset = ChunkSize - ArenasPerChunk * ArenaSize;
// Mark bitmaps are atomic because they can be written by gray unmarking on the // Mark bitmaps are atomic because they can be written by gray unmarking on the
// main thread while read by sweeping on a background thread. The former does // main thread while read by sweeping on a background thread. The former does
// not affect the result of the latter. // not affect the result of the latter.
using MarkBitmapWord = mozilla::Atomic<uintptr_t, mozilla::Relaxed>; using MarkBitmapWord = mozilla::Atomic<uintptr_t, mozilla::Relaxed>;
static constexpr size_t MarkBitmapWordBits = sizeof(MarkBitmapWord) * CHAR_BIT;
/* /*
* Live objects are marked black or gray. Everything reachable from a JS root is * Live objects are marked black or gray. Everything reachable from a JS root is
@ -227,19 +230,63 @@ enum class ColorBit : uint32_t { BlackBit = 0, GrayOrBlackBit = 1 };
enum class MarkColor : uint8_t { Gray = 1, Black = 2 }; enum class MarkColor : uint8_t { Gray = 1, Black = 2 };
// Mark bitmap for a tenured heap chunk. // Mark bitmap for a tenured heap chunk.
template <size_t BytesPerMarkBit, size_t FirstThingOffset>
class alignas(TypicalCacheLineSize) MarkBitmap { class alignas(TypicalCacheLineSize) MarkBitmap {
static constexpr size_t WordCount = ArenaBitmapWords * ArenasPerChunk; static constexpr size_t ByteCount =
(ChunkSize - FirstThingOffset) / BytesPerMarkBit;
static constexpr size_t WordCount = HowMany(ByteCount, MarkBitmapWordBits);
MarkBitmapWord bitmap[WordCount]; MarkBitmapWord bitmap[WordCount];
public: public:
inline void getMarkWordAndMask(const TenuredCell* cell, ColorBit colorBit, static constexpr size_t FirstThingAdjustmentBits =
MarkBitmapWord** wordp, uintptr_t* maskp); FirstThingOffset / BytesPerMarkBit;
static constexpr size_t FirstThingAdjustmentWords =
FirstThingAdjustmentBits / MarkBitmapWordBits;
MOZ_ALWAYS_INLINE void getMarkWordAndMask(const TenuredCell* cell,
ColorBit colorBit,
MarkBitmapWord** wordp,
uintptr_t* maskp) {
// Note: the JIT pre-barrier trampolines inline this code. Update
// MacroAssembler::emitPreBarrierFastPath code too when making changes here!
MOZ_ASSERT(size_t(colorBit) < MarkBitsPerCell);
size_t offset = uintptr_t(cell) & ChunkMask;
MOZ_ASSERT(offset >= FirstThingOffset);
const size_t bit = offset / BytesPerMarkBit + size_t(colorBit);
size_t word = bit / MarkBitmapWordBits - FirstThingAdjustmentWords;
MOZ_ASSERT(word < WordCount);
*wordp = &bitmap[word];
*maskp = uintptr_t(1) << (bit % MarkBitmapWordBits);
}
// The following are not exported and are defined in gc/Heap.h: // The following are not exported and are defined in gc/Heap.h:
inline bool markBit(const TenuredCell* cell, ColorBit colorBit); MOZ_ALWAYS_INLINE bool markBit(const TenuredCell* cell, ColorBit colorBit) {
inline bool isMarkedAny(const TenuredCell* cell); MarkBitmapWord* word;
inline bool isMarkedBlack(const TenuredCell* cell); uintptr_t mask;
inline bool isMarkedGray(const TenuredCell* cell); getMarkWordAndMask(cell, colorBit, &word, &mask);
return *word & mask;
}
MOZ_ALWAYS_INLINE bool isMarkedAny(const TenuredCell* cell) {
return markBit(cell, ColorBit::BlackBit) ||
markBit(cell, ColorBit::GrayOrBlackBit);
}
MOZ_ALWAYS_INLINE bool isMarkedBlack(const TenuredCell* cell) {
// Return true if BlackBit is set.
return markBit(cell, ColorBit::BlackBit);
}
MOZ_ALWAYS_INLINE bool isMarkedGray(const TenuredCell* cell) {
// Return true if GrayOrBlackBit is set and BlackBit is not set.
return !markBit(cell, ColorBit::BlackBit) &&
markBit(cell, ColorBit::GrayOrBlackBit);
}
inline bool markIfUnmarked(const TenuredCell* cell, MarkColor color); inline bool markIfUnmarked(const TenuredCell* cell, MarkColor color);
inline bool markIfUnmarkedAtomic(const TenuredCell* cell, MarkColor color); inline bool markIfUnmarkedAtomic(const TenuredCell* cell, MarkColor color);
inline void markBlack(const TenuredCell* cell); inline void markBlack(const TenuredCell* cell);
@ -252,8 +299,7 @@ class alignas(TypicalCacheLineSize) MarkBitmap {
inline void copyFrom(const MarkBitmap& other); inline void copyFrom(const MarkBitmap& other);
}; };
static_assert(ArenaBitmapBytes * ArenasPerChunk == sizeof(MarkBitmap), using ChunkMarkBitmap = MarkBitmap<CellBytesPerMarkBit, FirstArenaOffset>;
"Ensure our MarkBitmap actually covers all arenas.");
// Bitmap with one bit per page used for decommitted page set. // Bitmap with one bit per page used for decommitted page set.
using ChunkPageBitmap = mozilla::BitSet<PagesPerChunk, uint32_t>; using ChunkPageBitmap = mozilla::BitSet<PagesPerChunk, uint32_t>;
@ -261,21 +307,25 @@ using ChunkPageBitmap = mozilla::BitSet<PagesPerChunk, uint32_t>;
// Bitmap with one bit per arena used for free committed arena set. // Bitmap with one bit per arena used for free committed arena set.
using ChunkArenaBitmap = mozilla::BitSet<ArenasPerChunk, uint32_t>; using ChunkArenaBitmap = mozilla::BitSet<ArenasPerChunk, uint32_t>;
// Base class containing data members for a tenured heap chunk. // Base class for a tenured heap chunk containing fixed size arenas.
class TenuredChunkBase : public ChunkBase { class ArenaChunkBase : public ChunkBase {
public: public:
TenuredChunkInfo info; ArenaChunkInfo info;
MarkBitmap markBits; ChunkMarkBitmap markBits;
ChunkArenaBitmap freeCommittedArenas; ChunkArenaBitmap freeCommittedArenas;
ChunkPageBitmap decommittedPages; ChunkPageBitmap decommittedPages;
protected: protected:
explicit TenuredChunkBase(JSRuntime* runtime) : ChunkBase(runtime) { explicit ArenaChunkBase(JSRuntime* runtime) : ChunkBase(runtime) {
static_assert(sizeof(markBits) == ArenaBitmapBytes * ArenasPerChunk,
"Ensure our MarkBitmap actually covers all arenas.");
info.numArenasFree = ArenasPerChunk; info.numArenasFree = ArenasPerChunk;
} }
void initAsDecommitted(); void initAsDecommitted();
}; };
static_assert(FirstArenaOffset ==
RoundUp(sizeof(gc::ArenaChunkBase), ArenaSize));
/* /*
* We sometimes use an index to refer to a cell in an arena. The index for a * We sometimes use an index to refer to a cell in an arena. The index for a
@ -285,17 +335,8 @@ class TenuredChunkBase : public ChunkBase {
const size_t ArenaCellIndexBytes = CellAlignBytes; const size_t ArenaCellIndexBytes = CellAlignBytes;
const size_t MaxArenaCellIndex = ArenaSize / CellAlignBytes; const size_t MaxArenaCellIndex = ArenaSize / CellAlignBytes;
const size_t MarkBitmapWordBits = sizeof(MarkBitmapWord) * CHAR_BIT;
constexpr size_t FirstArenaAdjustmentBits =
RoundUp(sizeof(gc::TenuredChunkBase), ArenaSize) / gc::CellBytesPerMarkBit;
static_assert((FirstArenaAdjustmentBits % MarkBitmapWordBits) == 0);
constexpr size_t FirstArenaAdjustmentWords =
FirstArenaAdjustmentBits / MarkBitmapWordBits;
const size_t ChunkStoreBufferOffset = offsetof(ChunkBase, storeBuffer); const size_t ChunkStoreBufferOffset = offsetof(ChunkBase, storeBuffer);
const size_t ChunkMarkBitmapOffset = offsetof(TenuredChunkBase, markBits); const size_t ChunkMarkBitmapOffset = offsetof(ArenaChunkBase, markBits);
// Hardcoded offsets into Arena class. // Hardcoded offsets into Arena class.
const size_t ArenaZoneOffset = 2 * sizeof(uint32_t); const size_t ArenaZoneOffset = 2 * sizeof(uint32_t);
@ -535,48 +576,6 @@ inline bool operator!=(JS::GCCellPtr ptr1, JS::GCCellPtr ptr2) {
namespace js { namespace js {
namespace gc { namespace gc {
/* static */
MOZ_ALWAYS_INLINE void MarkBitmap::getMarkWordAndMask(const TenuredCell* cell,
ColorBit colorBit,
MarkBitmapWord** wordp,
uintptr_t* maskp) {
// Note: the JIT pre-barrier trampolines inline this code. Update
// MacroAssembler::emitPreBarrierFastPath code too when making changes here!
MOZ_ASSERT(size_t(colorBit) < MarkBitsPerCell);
size_t offset = uintptr_t(cell) & ChunkMask;
const size_t bit = offset / CellBytesPerMarkBit + size_t(colorBit);
size_t word = bit / MarkBitmapWordBits - FirstArenaAdjustmentWords;
MOZ_ASSERT(word < WordCount);
*wordp = &bitmap[word];
*maskp = uintptr_t(1) << (bit % MarkBitmapWordBits);
}
MOZ_ALWAYS_INLINE bool MarkBitmap::markBit(const TenuredCell* cell,
ColorBit colorBit) {
MarkBitmapWord* word;
uintptr_t mask;
getMarkWordAndMask(cell, colorBit, &word, &mask);
return *word & mask;
}
MOZ_ALWAYS_INLINE bool MarkBitmap::isMarkedAny(const TenuredCell* cell) {
return markBit(cell, ColorBit::BlackBit) ||
markBit(cell, ColorBit::GrayOrBlackBit);
}
MOZ_ALWAYS_INLINE bool MarkBitmap::isMarkedBlack(const TenuredCell* cell) {
// Return true if BlackBit is set.
return markBit(cell, ColorBit::BlackBit);
}
MOZ_ALWAYS_INLINE bool MarkBitmap::isMarkedGray(const TenuredCell* cell) {
// Return true if GrayOrBlackBit is set and BlackBit is not set.
return !markBit(cell, ColorBit::BlackBit) &&
markBit(cell, ColorBit::GrayOrBlackBit);
}
namespace detail { namespace detail {
// `addr` must be an address within GC-controlled memory. Note that it cannot // `addr` must be an address within GC-controlled memory. Note that it cannot
@ -593,13 +592,12 @@ static MOZ_ALWAYS_INLINE ChunkBase* GetCellChunkBase(const Cell* cell) {
return GetGCAddressChunkBase(cell); return GetGCAddressChunkBase(cell);
} }
static MOZ_ALWAYS_INLINE TenuredChunkBase* GetCellChunkBase( static MOZ_ALWAYS_INLINE ArenaChunkBase* GetCellChunkBase(
const TenuredCell* cell) { const TenuredCell* cell) {
MOZ_ASSERT(cell); MOZ_ASSERT(cell);
auto* chunk = auto* chunk = reinterpret_cast<ArenaChunkBase*>(uintptr_t(cell) & ~ChunkMask);
reinterpret_cast<TenuredChunkBase*>(uintptr_t(cell) & ~ChunkMask);
MOZ_ASSERT(chunk->runtime); MOZ_ASSERT(chunk->runtime);
MOZ_ASSERT(chunk->kind == ChunkKind::TenuredHeap); MOZ_ASSERT(chunk->kind == ChunkKind::TenuredArenas);
return chunk; return chunk;
} }
@ -616,7 +614,7 @@ static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedBlack(
MOZ_ASSERT(cell); MOZ_ASSERT(cell);
MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); MOZ_ASSERT(!js::gc::IsInsideNursery(cell));
TenuredChunkBase* chunk = GetCellChunkBase(cell); ArenaChunkBase* chunk = GetCellChunkBase(cell);
return chunk->markBits.isMarkedBlack(cell); return chunk->markBits.isMarkedBlack(cell);
} }
@ -628,14 +626,14 @@ static MOZ_ALWAYS_INLINE bool NonBlackCellIsMarkedGray(
MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); MOZ_ASSERT(!js::gc::IsInsideNursery(cell));
MOZ_ASSERT(!TenuredCellIsMarkedBlack(cell)); MOZ_ASSERT(!TenuredCellIsMarkedBlack(cell));
TenuredChunkBase* chunk = GetCellChunkBase(cell); ArenaChunkBase* chunk = GetCellChunkBase(cell);
return chunk->markBits.markBit(cell, ColorBit::GrayOrBlackBit); return chunk->markBits.markBit(cell, ColorBit::GrayOrBlackBit);
} }
static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedGray(const TenuredCell* cell) { static MOZ_ALWAYS_INLINE bool TenuredCellIsMarkedGray(const TenuredCell* cell) {
MOZ_ASSERT(cell); MOZ_ASSERT(cell);
MOZ_ASSERT(!js::gc::IsInsideNursery(cell)); MOZ_ASSERT(!js::gc::IsInsideNursery(cell));
TenuredChunkBase* chunk = GetCellChunkBase(cell); ArenaChunkBase* chunk = GetCellChunkBase(cell);
return chunk->markBits.isMarkedGray(cell); return chunk->markBits.isMarkedGray(cell);
} }

View file

@ -1761,43 +1761,41 @@ bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
return true; return true;
} }
bool BytecodeEmitter::emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key, bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem,
ElemOpEmitter& eoe) { ElemOpEmitter& eoe) {
if (exprOrSuper->isKind(ParseNodeKind::SuperBase)) { ParseNode* exprOrSuper = &elem->expression();
if (!eoe.prepareForObj()) { ParseNode* key = &elem->key();
// [stack]
return false;
}
UnaryNode* base = &exprOrSuper->as<UnaryNode>();
if (!emitGetThisForSuperBase(base)) {
// [stack] THIS
return false;
}
if (!eoe.prepareForKey()) {
// [stack] THIS
return false;
}
if (!emitTree(key)) {
// [stack] THIS KEY
return false;
}
return true;
}
if (!eoe.prepareForObj()) { if (!eoe.prepareForObj()) {
// [stack] // [stack]
return false; return false;
} }
if (!emitTree(exprOrSuper)) {
// [stack] OBJ if (elem->isSuper()) {
return false; auto* base = &exprOrSuper->as<UnaryNode>();
if (!emitGetThisForSuperBase(base)) {
// [stack] THIS
return false;
}
} else {
if (!emitTree(exprOrSuper)) {
// [stack] OBJ
return false;
}
} }
if (!eoe.prepareForKey()) { if (!eoe.prepareForKey()) {
// [stack] # if Super
// [stack] THIS? THIS
// [stack] # otherwise
// [stack] OBJ? OBJ // [stack] OBJ? OBJ
return false; return false;
} }
if (!emitTree(key)) { if (!emitTree(key)) {
// [stack] # if Super
// [stack] THIS? THIS KEY
// [stack] # otherwise
// [stack] OBJ? OBJ KEY // [stack] OBJ? OBJ KEY
return false; return false;
} }
@ -1813,12 +1811,6 @@ bool BytecodeEmitter::emitElemOpBase(JSOp op) {
return true; return true;
} }
bool BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, bool isSuper,
ElemOpEmitter& eoe) {
MOZ_ASSERT(isSuper == elem->expression().isKind(ParseNodeKind::SuperBase));
return emitObjAndKey(&elem->expression(), &elem->key(), eoe);
}
static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) { static ElemOpEmitter::Kind ConvertIncDecKind(ParseNodeKind kind) {
switch (kind) { switch (kind) {
case ParseNodeKind::PostIncrementExpr: case ParseNodeKind::PostIncrementExpr:
@ -1857,7 +1849,7 @@ bool BytecodeEmitter::emitElemIncDec(UnaryNode* incDec, ValueUsage valueUsage) {
ElemOpEmitter eoe( ElemOpEmitter eoe(
this, ConvertIncDecKind(kind), this, ConvertIncDecKind(kind),
isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
if (!emitElemObjAndKey(elemExpr, isSuper, eoe)) { if (!emitElemObjAndKey(elemExpr, eoe)) {
// [stack] # if Super // [stack] # if Super
// [stack] THIS KEY // [stack] THIS KEY
// [stack] # otherwise // [stack] # otherwise
@ -2603,23 +2595,63 @@ bool BytecodeEmitter::emitFunctionScript(FunctionNode* funNode) {
return fse.intoStencil(); return fse.intoStencil();
} }
class js::frontend::DestructuringLHSRef {
struct None {
size_t numReferenceSlots() const { return 0; }
};
mozilla::Variant<None, NameOpEmitter, PropOpEmitter, ElemOpEmitter,
PrivateOpEmitter>
emitter_ = AsVariant(None{});
public:
template <typename T>
void from(T&& emitter) {
emitter_.emplace<T>(std::forward<T>(emitter));
}
template <typename T>
T& emitter() {
return emitter_.as<T>();
}
/**
* Return the number of values pushed onto the stack.
*/
size_t numReferenceSlots() const {
return emitter_.match([](auto& e) { return e.numReferenceSlots(); });
}
};
bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
size_t* emitted) { DestructuringFlavor flav,
DestructuringLHSRef& lref) {
#ifdef DEBUG #ifdef DEBUG
int depth = bytecodeSection().stackDepth(); int depth = bytecodeSection().stackDepth();
#endif #endif
switch (target->getKind()) { switch (target->getKind()) {
case ParseNodeKind::Name:
case ParseNodeKind::ArrayExpr: case ParseNodeKind::ArrayExpr:
case ParseNodeKind::ObjectExpr: case ParseNodeKind::ObjectExpr:
// No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object // No need to recurse into ParseNodeKind::Array and ParseNodeKind::Object
// subpatterns here, since emitSetOrInitializeDestructuring does the // subpatterns here, since emitSetOrInitializeDestructuring does the
// recursion when setting or initializing the value. Getting reference // recursion when setting or initializing the value.
// doesn't recurse.
*emitted = 0;
break; break;
case ParseNodeKind::Name: {
auto* name = &target->as<NameNode>();
NameOpEmitter noe(this, name->atom(),
flav == DestructuringFlavor::Assignment
? NameOpEmitter::Kind::SimpleAssignment
: NameOpEmitter::Kind::Initialize);
if (!noe.prepareForRhs()) {
return false;
}
lref.from(std::move(noe));
return true;
}
case ParseNodeKind::ArgumentsLength: case ParseNodeKind::ArgumentsLength:
case ParseNodeKind::DotExpr: { case ParseNodeKind::DotExpr: {
PropertyAccess* prop = &target->as<PropertyAccess>(); PropertyAccess* prop = &target->as<PropertyAccess>();
@ -2650,8 +2682,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
return false; return false;
} }
// SUPERBASE was pushed onto THIS in poe.prepareForRhs above. lref.from(std::move(poe));
*emitted = 1 + isSuper;
break; break;
} }
@ -2662,7 +2693,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment, ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
isSuper ? ElemOpEmitter::ObjKind::Super isSuper ? ElemOpEmitter::ObjKind::Super
: ElemOpEmitter::ObjKind::Other); : ElemOpEmitter::ObjKind::Other);
if (!emitElemObjAndKey(elem, isSuper, eoe)) { if (!emitElemObjAndKey(elem, eoe)) {
// [stack] # if Super // [stack] # if Super
// [stack] THIS KEY // [stack] THIS KEY
// [stack] # otherwise // [stack] # otherwise
@ -2677,8 +2708,7 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
return false; return false;
} }
// SUPERBASE was pushed onto KEY in eoe.prepareForRhs above. lref.from(std::move(eoe));
*emitted = 2 + isSuper;
break; break;
} }
@ -2694,7 +2724,8 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
// [stack] OBJ NAME // [stack] OBJ NAME
return false; return false;
} }
*emitted = xoe.numReferenceSlots();
lref.from(std::move(xoe));
break; break;
} }
@ -2709,13 +2740,14 @@ bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind"); MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind");
} }
MOZ_ASSERT(bytecodeSection().stackDepth() == depth + int(*emitted)); MOZ_ASSERT(bytecodeSection().stackDepth() ==
depth + int(lref.numReferenceSlots()));
return true; return true;
} }
bool BytecodeEmitter::emitSetOrInitializeDestructuring( bool BytecodeEmitter::emitSetOrInitializeDestructuring(
ParseNode* target, DestructuringFlavor flav) { ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref) {
// Now emit the lvalue opcode sequence. If the lvalue is a nested // Now emit the lvalue opcode sequence. If the lvalue is a nested
// destructuring initialiser-form, call ourselves to handle it, then pop // destructuring initialiser-form, call ourselves to handle it, then pop
// the matched value. Otherwise emit an lvalue bytecode sequence followed // the matched value. Otherwise emit an lvalue bytecode sequence followed
@ -2732,51 +2764,14 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring(
break; break;
case ParseNodeKind::Name: { case ParseNodeKind::Name: {
auto name = target->as<NameNode>().name(); // The environment is already pushed by emitDestructuringLHSRef.
NameLocation loc = lookupName(name); // [stack] ENV? VAL
NameOpEmitter::Kind kind; auto& noe = lref.emitter<NameOpEmitter>();
switch (flav) {
case DestructuringFlavor::Declaration:
kind = NameOpEmitter::Kind::Initialize;
break;
case DestructuringFlavor::Assignment:
kind = NameOpEmitter::Kind::SimpleAssignment;
break;
}
NameOpEmitter noe(this, name, loc, kind);
if (!noe.prepareForRhs()) {
// [stack] V ENV?
return false;
}
if (noe.emittedBindOp()) {
// This is like ordinary assignment, but with one difference.
//
// In `a = b`, we first determine a binding for `a` (using
// JSOp::BindName or JSOp::BindGName), then we evaluate `b`, then
// a JSOp::SetName instruction.
//
// In `[a] = [b]`, per spec, `b` is evaluated first, then we
// determine a binding for `a`. Then we need to do assignment--
// but the operands are on the stack in the wrong order for
// JSOp::SetProp, so we have to add a JSOp::Swap.
//
// In the cases where we are emitting a name op, emit a swap
// because of this.
if (!emit1(JSOp::Swap)) {
// [stack] ENV V
return false;
}
} else {
// In cases of emitting a frame slot or environment slot,
// nothing needs be done.
}
if (!noe.emitAssignment()) { if (!noe.emitAssignment()) {
// [stack] V // [stack] VAL
return false; return false;
} }
break; break;
} }
@ -2787,16 +2782,11 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring(
// [stack] THIS SUPERBASE VAL // [stack] THIS SUPERBASE VAL
// [stack] # otherwise // [stack] # otherwise
// [stack] OBJ VAL // [stack] OBJ VAL
PropertyAccess* prop = &target->as<PropertyAccess>(); auto& poe = lref.emitter<PropOpEmitter>();
bool isSuper = prop->isSuper(); auto* prop = &target->as<PropertyAccess>();
PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
isSuper ? PropOpEmitter::ObjKind::Super
: PropOpEmitter::ObjKind::Other);
if (!poe.skipObjAndRhs()) {
return false;
}
// [stack] # VAL
if (!poe.emitAssignment(prop->key().atom())) { if (!poe.emitAssignment(prop->key().atom())) {
// [stack] # VAL
return false; return false;
} }
break; break;
@ -2808,15 +2798,8 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring(
// [stack] THIS KEY SUPERBASE VAL // [stack] THIS KEY SUPERBASE VAL
// [stack] # otherwise // [stack] # otherwise
// [stack] OBJ KEY VAL // [stack] OBJ KEY VAL
PropertyByValue* elem = &target->as<PropertyByValue>(); auto& eoe = lref.emitter<ElemOpEmitter>();
bool isSuper = elem->isSuper();
MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName));
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::SimpleAssignment,
isSuper ? ElemOpEmitter::ObjKind::Super
: ElemOpEmitter::ObjKind::Other);
if (!eoe.skipObjAndKeyAndRhs()) {
return false;
}
if (!eoe.emitAssignment()) { if (!eoe.emitAssignment()) {
// [stack] VAL // [stack] VAL
return false; return false;
@ -2827,12 +2810,8 @@ bool BytecodeEmitter::emitSetOrInitializeDestructuring(
case ParseNodeKind::PrivateMemberExpr: { case ParseNodeKind::PrivateMemberExpr: {
// The reference is already pushed by emitDestructuringLHSRef. // The reference is already pushed by emitDestructuringLHSRef.
// [stack] OBJ NAME VAL // [stack] OBJ NAME VAL
PrivateMemberAccess* privateExpr = &target->as<PrivateMemberAccess>(); auto& xoe = lref.emitter<PrivateOpEmitter>();
PrivateOpEmitter xoe(this, PrivateOpEmitter::Kind::SimpleAssignment,
privateExpr->privateName().name());
if (!xoe.skipReference()) {
return false;
}
if (!xoe.emitAssignment()) { if (!xoe.emitAssignment()) {
// [stack] VAL // [stack] VAL
return false; return false;
@ -3383,6 +3362,7 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
idx += 1; idx += 1;
continue; continue;
} }
MOZ_ASSERT(member->isKind(ParseNodeKind::Name));
if (!emit1(JSOp::Dup)) { if (!emit1(JSOp::Dup)) {
// [stack] LENGTH OBJ OBJ // [stack] LENGTH OBJ OBJ
@ -3440,7 +3420,13 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
return false; return false;
} }
if (!emitSetOrInitializeDestructuring(member, flav)) { DestructuringLHSRef lref;
if (!emitDestructuringLHSRef(member, flav, lref)) {
// [stack] LENGTH OBJ
return false;
}
if (!emitSetOrInitializeDestructuring(member, flav, lref)) {
// [stack] LENGTH OBJ // [stack] LENGTH OBJ
return false; return false;
} }
@ -3527,14 +3513,12 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
pndefault = subpattern->as<AssignmentNode>().right(); pndefault = subpattern->as<AssignmentNode>().right();
} }
// Number of stack slots emitted for the LHS reference.
size_t emitted = 0;
// Spec requires LHS reference to be evaluated first. // Spec requires LHS reference to be evaluated first.
DestructuringLHSRef lref;
bool isElision = lhsPattern->isKind(ParseNodeKind::Elision); bool isElision = lhsPattern->isKind(ParseNodeKind::Elision);
if (!isElision) { if (!isElision) {
auto emitLHSRef = [lhsPattern, &emitted](BytecodeEmitter* bce) { auto emitLHSRef = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
return bce->emitDestructuringLHSRef(lhsPattern, &emitted); return bce->emitDestructuringLHSRef(lhsPattern, flav, lref);
// [stack] ... OBJ NEXT ITER DONE LREF* // [stack] ... OBJ NEXT ITER DONE LREF*
}; };
if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) { if (!wrapWithDestructuringTryNote(tryNoteDepth, emitLHSRef)) {
@ -3542,6 +3526,9 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
} }
} }
// Number of stack slots emitted for the LHS reference.
size_t emitted = lref.numReferenceSlots();
// Pick the DONE value to the top of the stack. // Pick the DONE value to the top of the stack.
if (emitted) { if (emitted) {
if (!emitPickN(emitted)) { if (!emitPickN(emitted)) {
@ -3624,8 +3611,8 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
return false; return false;
} }
auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) { auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
return bce->emitSetOrInitializeDestructuring(lhsPattern, flav); return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
// [stack] ... OBJ NEXT ITER TRUE // [stack] ... OBJ NEXT ITER TRUE
}; };
if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) { if (!wrapWithDestructuringTryNote(tryNoteDepth, emitAssignment)) {
@ -3749,8 +3736,8 @@ bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
} }
if (!isElision) { if (!isElision) {
auto emitAssignment = [lhsPattern, flav](BytecodeEmitter* bce) { auto emitAssignment = [lhsPattern, flav, &lref](BytecodeEmitter* bce) {
return bce->emitSetOrInitializeDestructuring(lhsPattern, flav); return bce->emitSetOrInitializeDestructuring(lhsPattern, flav, lref);
// [stack] ... OBJ NEXT ITER DONE // [stack] ... OBJ NEXT ITER DONE
}; };
@ -3841,6 +3828,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
for (ParseNode* member : pattern->contents()) { for (ParseNode* member : pattern->contents()) {
ParseNode* subpattern; ParseNode* subpattern;
bool hasKeyOnStack = false;
if (member->isKind(ParseNodeKind::MutateProto) || if (member->isKind(ParseNodeKind::MutateProto) ||
member->isKind(ParseNodeKind::Spread)) { member->isKind(ParseNodeKind::Spread)) {
subpattern = member->as<UnaryNode>().kid(); subpattern = member->as<UnaryNode>().kid();
@ -3851,6 +3839,16 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) || MOZ_ASSERT(member->isKind(ParseNodeKind::PropertyDefinition) ||
member->isKind(ParseNodeKind::Shorthand)); member->isKind(ParseNodeKind::Shorthand));
subpattern = member->as<BinaryNode>().right(); subpattern = member->as<BinaryNode>().right();
// Computed property names are evaluated before the subpattern.
ParseNode* key = member->as<BinaryNode>().left();
if (key->isKind(ParseNodeKind::ComputedName)) {
if (!emitComputedPropertyName(&key->as<UnaryNode>())) {
// [stack] ... SET? RHS KEY
return false;
}
hasKeyOnStack = true;
}
} }
ParseNode* lhs = subpattern; ParseNode* lhs = subpattern;
@ -3860,18 +3858,19 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
pndefault = subpattern->as<AssignmentNode>().right(); pndefault = subpattern->as<AssignmentNode>().right();
} }
// Number of stack slots emitted for the LHS reference.
size_t emitted = 0;
// Spec requires LHS reference to be evaluated first. // Spec requires LHS reference to be evaluated first.
if (!emitDestructuringLHSRef(lhs, &emitted)) { DestructuringLHSRef lref;
// [stack] ... SET? RHS LREF* if (!emitDestructuringLHSRef(lhs, flav, lref)) {
// [stack] ... SET? RHS KEY? LREF*
return false; return false;
} }
// Number of stack slots emitted for the LHS reference.
size_t emitted = lref.numReferenceSlots();
// Duplicate the value being destructured to use as a reference base. // Duplicate the value being destructured to use as a reference base.
if (!emitDupAt(emitted)) { if (!emitDupAt(emitted + hasKeyOnStack)) {
// [stack] ... SET? RHS LREF* RHS // [stack] ... SET? RHS KEY? LREF* RHS
return false; return false;
} }
@ -3908,7 +3907,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
} }
// Destructure TARGET per this member's lhs. // Destructure TARGET per this member's lhs.
if (!emitSetOrInitializeDestructuring(lhs, flav)) { if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
// [stack] ... RHS // [stack] ... RHS
return false; return false;
} }
@ -3947,8 +3946,9 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
// Otherwise this is a computed property name. BigInt keys are parsed // Otherwise this is a computed property name. BigInt keys are parsed
// as (synthetic) computed property names, too. // as (synthetic) computed property names, too.
MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName)); MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName));
MOZ_ASSERT(hasKeyOnStack);
if (!emitComputedPropertyName(&key->as<UnaryNode>())) { if (!emit2(JSOp::Pick, emitted + 1)) {
// [stack] ... SET? RHS LREF* RHS KEY // [stack] ... SET? RHS LREF* RHS KEY
return false; return false;
} }
@ -3994,7 +3994,7 @@ bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
} }
// Destructure PROP per this member's lhs. // Destructure PROP per this member's lhs.
if (!emitSetOrInitializeDestructuring(lhs, flav)) { if (!emitSetOrInitializeDestructuring(lhs, flav, lref)) {
// [stack] ... SET? RHS // [stack] ... SET? RHS
return false; return false;
} }
@ -4447,7 +4447,7 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs,
: ElemOpEmitter::Kind::SimpleAssignment, : ElemOpEmitter::Kind::SimpleAssignment,
isSuper ? ElemOpEmitter::ObjKind::Super isSuper ? ElemOpEmitter::ObjKind::Super
: ElemOpEmitter::ObjKind::Other); : ElemOpEmitter::ObjKind::Other);
if (!emitElemObjAndKey(elem, isSuper, *eoe)) { if (!emitElemObjAndKey(elem, *eoe)) {
// [stack] # if Super // [stack] # if Super
// [stack] THIS KEY // [stack] THIS KEY
// [stack] # otherwise // [stack] # otherwise
@ -4763,7 +4763,7 @@ bool BytecodeEmitter::emitShortCircuitAssignment(AssignmentNode* node) {
isSuper ? ElemOpEmitter::ObjKind::Super isSuper ? ElemOpEmitter::ObjKind::Super
: ElemOpEmitter::ObjKind::Other); : ElemOpEmitter::ObjKind::Other);
if (!emitElemObjAndKey(elem, isSuper, *eoe)) { if (!emitElemObjAndKey(elem, *eoe)) {
// [stack] # if Super // [stack] # if Super
// [stack] THIS KEY // [stack] THIS KEY
// [stack] # otherwise // [stack] # otherwise
@ -7273,20 +7273,20 @@ bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) {
propExpr->as<PropertyAccess>().isSuper() propExpr->as<PropertyAccess>().isSuper()
? PropOpEmitter::ObjKind::Super ? PropOpEmitter::ObjKind::Super
: PropOpEmitter::ObjKind::Other); : PropOpEmitter::ObjKind::Other);
if (!poe.prepareForObj()) {
return false;
}
if (propExpr->isSuper()) { if (propExpr->isSuper()) {
// The expression |delete super.foo;| has to evaluate |super.foo|, // The expression |delete super.foo;| has to evaluate |super.foo|, which
// which could throw if |this| hasn't yet been set by a |super(...)| // could throw if |this| hasn't yet been set by a |super(...)| call.
// call or the super-base is not an object, before throwing a auto* base = &propExpr->expression().as<UnaryNode>();
// ReferenceError for attempting to delete a super-reference.
UnaryNode* base = &propExpr->expression().as<UnaryNode>();
if (!emitGetThisForSuperBase(base)) { if (!emitGetThisForSuperBase(base)) {
// [stack] THIS // [stack] THIS
return false; return false;
} }
} else { } else {
if (!poe.prepareForObj()) {
return false;
}
if (!emitPropLHS(propExpr)) { if (!emitPropLHS(propExpr)) {
// [stack] OBJ // [stack] OBJ
return false; return false;
@ -7307,44 +7307,21 @@ bool BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) {
bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) { bool BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) {
MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteElemExpr)); MOZ_ASSERT(deleteNode->isKind(ParseNodeKind::DeleteElemExpr));
PropertyByValue* elemExpr = &deleteNode->kid()->as<PropertyByValue>(); auto* elemExpr = &deleteNode->kid()->as<PropertyByValue>();
bool isSuper = elemExpr->isSuper(); bool isSuper = elemExpr->isSuper();
DebugOnly<bool> isPrivate = MOZ_ASSERT(!elemExpr->key().isKind(ParseNodeKind::PrivateName));
elemExpr->key().isKind(ParseNodeKind::PrivateName);
MOZ_ASSERT(!isPrivate);
ElemOpEmitter eoe( ElemOpEmitter eoe(
this, ElemOpEmitter::Kind::Delete, this, ElemOpEmitter::Kind::Delete,
isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other);
if (isSuper) {
// The expression |delete super[foo];| has to evaluate |super[foo]|,
// which could throw if |this| hasn't yet been set by a |super(...)|
// call, or trigger side-effects when evaluating ToPropertyKey(foo),
// or also throw when the super-base is not an object, before throwing
// a ReferenceError for attempting to delete a super-reference.
if (!eoe.prepareForObj()) {
// [stack]
return false;
}
UnaryNode* base = &elemExpr->expression().as<UnaryNode>(); if (!emitElemObjAndKey(elemExpr, eoe)) {
if (!emitGetThisForSuperBase(base)) { // [stack] # if Super
// [stack] THIS // [stack] THIS KEY
return false; // [stack] # otherwise
} // [stack] OBJ KEY
if (!eoe.prepareForKey()) { return false;
// [stack] THIS
return false;
}
if (!emitTree(&elemExpr->key())) {
// [stack] THIS KEY
return false;
}
} else {
if (!emitElemObjAndKey(elemExpr, false, eoe)) {
// [stack] OBJ KEY
return false;
}
} }
if (!eoe.emitDelete()) { if (!eoe.emitDelete()) {
// [stack] # if Super // [stack] # if Super
// [stack] THIS // [stack] THIS
@ -8187,7 +8164,7 @@ bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, CallNode* maybeCall,
bool isSuper = elem->isSuper(); bool isSuper = elem->isSuper();
MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName)); MOZ_ASSERT(!elem->key().isKind(ParseNodeKind::PrivateName));
ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper); ElemOpEmitter& eoe = cone.prepareForElemCallee(isSuper);
if (!emitElemObjAndKey(elem, isSuper, eoe)) { if (!emitElemObjAndKey(elem, eoe)) {
// [stack] # if Super // [stack] # if Super
// [stack] THIS? THIS KEY // [stack] THIS? THIS KEY
// [stack] # otherwise // [stack] # otherwise
@ -12740,7 +12717,7 @@ bool BytecodeEmitter::emitTree(
ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get, ElemOpEmitter eoe(this, ElemOpEmitter::Kind::Get,
isSuper ? ElemOpEmitter::ObjKind::Super isSuper ? ElemOpEmitter::ObjKind::Super
: ElemOpEmitter::ObjKind::Other); : ElemOpEmitter::ObjKind::Other);
if (!emitElemObjAndKey(elem, isSuper, eoe)) { if (!emitElemObjAndKey(elem, eoe)) {
// [stack] # if Super // [stack] # if Super
// [stack] THIS KEY // [stack] THIS KEY
// [stack] # otherwise // [stack] # otherwise

View file

@ -55,6 +55,7 @@ namespace frontend {
class BytecodeOffset; class BytecodeOffset;
class CallOrNewEmitter; class CallOrNewEmitter;
class ClassEmitter; class ClassEmitter;
class DestructuringLHSRef;
class ElemOpEmitter; class ElemOpEmitter;
class EmitterScope; class EmitterScope;
class ErrorReporter; class ErrorReporter;
@ -751,9 +752,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
[[nodiscard]] bool emitComputedPropertyName(UnaryNode* computedPropName); [[nodiscard]] bool emitComputedPropertyName(UnaryNode* computedPropName);
[[nodiscard]] bool emitObjAndKey(ParseNode* exprOrSuper, ParseNode* key,
ElemOpEmitter& eoe);
// Emit bytecode to put operands for a JSOp::GetElem/CallElem/SetElem/DelElem // Emit bytecode to put operands for a JSOp::GetElem/CallElem/SetElem/DelElem
// opcode onto the stack in the right order. In the case of SetElem, the // opcode onto the stack in the right order. In the case of SetElem, the
// value to be assigned must already be pushed. // value to be assigned must already be pushed.
@ -761,7 +759,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
[[nodiscard]] bool emitElemOperands(PropertyByValue* elem, [[nodiscard]] bool emitElemOperands(PropertyByValue* elem,
EmitElemOption opts); EmitElemOption opts);
[[nodiscard]] bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper, [[nodiscard]] bool emitElemObjAndKey(PropertyByValue* elem,
ElemOpEmitter& eoe); ElemOpEmitter& eoe);
[[nodiscard]] bool emitElemOpBase(JSOp op); [[nodiscard]] bool emitElemOpBase(JSOp op);
@ -790,16 +788,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
// If the lhs expression is object property |OBJ.prop|, it emits |OBJ|. // If the lhs expression is object property |OBJ.prop|, it emits |OBJ|.
// If it's object element |OBJ[ELEM]|, it emits |OBJ| and |ELEM|. // If it's object element |OBJ[ELEM]|, it emits |OBJ| and |ELEM|.
// If there's nothing to evaluate for the reference, it emits nothing. // If there's nothing to evaluate for the reference, it emits nothing.
// |emitted| parameter receives the number of values pushed onto the stack.
[[nodiscard]] bool emitDestructuringLHSRef(ParseNode* target, [[nodiscard]] bool emitDestructuringLHSRef(ParseNode* target,
size_t* emitted); DestructuringFlavor flav,
DestructuringLHSRef& lref);
// emitSetOrInitializeDestructuring assumes the lhs expression's reference // emitSetOrInitializeDestructuring assumes the lhs expression's reference
// and the to-be-destructured value has been pushed on the stack. It emits // and the to-be-destructured value has been pushed on the stack. It emits
// code to destructure a single lhs expression (either a name or a compound // code to destructure a single lhs expression (either a name or a compound
// []/{} expression). // []/{} expression).
[[nodiscard]] bool emitSetOrInitializeDestructuring(ParseNode* target, [[nodiscard]] bool emitSetOrInitializeDestructuring(
DestructuringFlavor flav); ParseNode* target, DestructuringFlavor flav, DestructuringLHSRef& lref);
// emitDestructuringObjRestExclusionSet emits the property exclusion set // emitDestructuringObjRestExclusionSet emits the property exclusion set
// for the rest-property in an object pattern. // for the rest-property in an object pattern.

View file

@ -48,31 +48,38 @@ bool ElemOpEmitter::prepareForKey() {
bool ElemOpEmitter::emitGet() { bool ElemOpEmitter::emitGet() {
MOZ_ASSERT(state_ == State::Key); MOZ_ASSERT(state_ == State::Key);
// Inc/dec and compound assignment use the KEY twice, but if it's an object,
// it must be converted ToPropertyKey only once, per spec.
if (isIncDec() || isCompoundAssignment()) {
if (!bce_->emit1(JSOp::ToPropertyKey)) {
// [stack] # if Super
// [stack] THIS KEY
// [stack] # otherwise
// [stack] OBJ KEY
return false;
}
}
if (isSuper()) { if (isSuper()) {
if (!bce_->emitSuperBase()) { if (!bce_->emitSuperBase()) {
// [stack] THIS? THIS KEY SUPERBASE // [stack] THIS? THIS KEY SUPERBASE
return false; return false;
} }
} }
// Inc/dec and compound assignment use the KEY twice, but if it's an object,
// it must be converted by ToPropertyKey only once, per spec.
if (isIncDec() || isCompoundAssignment()) { if (isIncDec() || isCompoundAssignment()) {
if (isSuper()) { if (isSuper()) {
if (!bce_->emit1(JSOp::Swap)) {
// [stack] THIS SUPERBASE KEY
return false;
}
if (!bce_->emit1(JSOp::ToPropertyKey)) {
// [stack] THIS SUPERBASE KEY
return false;
}
if (!bce_->emit1(JSOp::Swap)) {
// [stack] THIS KEY SUPERBASE
return false;
}
if (!bce_->emitDupAt(2, 3)) { if (!bce_->emitDupAt(2, 3)) {
// [stack] THIS KEY SUPERBASE THIS KEY SUPERBASE // [stack] THIS KEY SUPERBASE THIS KEY SUPERBASE
return false; return false;
} }
} else { } else {
if (!bce_->emit1(JSOp::ToPropertyKey)) {
// [stack] OBJ KEY
return false;
}
if (!bce_->emit1(JSOp::Dup2)) { if (!bce_->emit1(JSOp::Dup2)) {
// [stack] OBJ KEY OBJ KEY // [stack] OBJ KEY OBJ KEY
return false; return false;
@ -131,25 +138,11 @@ bool ElemOpEmitter::prepareForRhs() {
return true; return true;
} }
bool ElemOpEmitter::skipObjAndKeyAndRhs() {
MOZ_ASSERT(state_ == State::Start);
MOZ_ASSERT(isSimpleAssignment() || isPropInit());
#ifdef DEBUG
state_ = State::Rhs;
#endif
return true;
}
bool ElemOpEmitter::emitDelete() { bool ElemOpEmitter::emitDelete() {
MOZ_ASSERT(state_ == State::Key); MOZ_ASSERT(state_ == State::Key);
MOZ_ASSERT(isDelete()); MOZ_ASSERT(isDelete());
if (isSuper()) { if (isSuper()) {
if (!bce_->emit1(JSOp::ToPropertyKey)) {
// [stack] THIS KEY
return false;
}
if (!bce_->emitSuperBase()) { if (!bce_->emitSuperBase()) {
// [stack] THIS KEY SUPERBASE // [stack] THIS KEY SUPERBASE
return false; return false;

View file

@ -9,6 +9,8 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include <stddef.h>
namespace js { namespace js {
namespace frontend { namespace frontend {
@ -142,38 +144,36 @@ class MOZ_STACK_CLASS ElemOpEmitter {
#ifdef DEBUG #ifdef DEBUG
// The state of this emitter. // The state of this emitter.
// //
// skipObjAndKeyAndRhs //
// +------------------------------------------------+ // +-------+ prepareForObj +-----+ prepareForKey +-----+
// | | // | Start |---------------->| Obj |-------------->| Key |-+
// +-------+ | prepareForObj +-----+ prepareForKey +-----+ | // +-------+ +-----+ +-----+ |
// | Start |-+-------------->| Obj |-------------->| Key |-+ | // |
// +-------+ +-----+ +-----+ | | // +-------------------------------------------------------+
// | | // |
// +-------------------------------------------------------+ | // | [Get]
// | | // | [Call]
// | [Get] | // | emitGet +-----+
// | [Call] | // +---------->| Get |
// | emitGet +-----+ | // | +-----+
// +---------->| Get | | // |
// | +-----+ | // | [Delete]
// | | // | emitDelete +--------+
// | [Delete] | // +------------->| Delete |
// | emitDelete +--------+ | // | +--------+
// +------------->| Delete | | // |
// | +--------+ | // | [PostIncrement]
// | | // | [PreIncrement]
// | [PostIncrement] | // | [PostDecrement]
// | [PreIncrement] | // | [PreDecrement]
// | [PostDecrement] | // | emitIncDec +--------+
// | [PreDecrement] | // +------------->| IncDec |
// | emitIncDec +--------+ | // | +--------+
// +------------->| IncDec | | // |
// | +--------+ | // | [SimpleAssignment]
// | +-------------------+ // | [PropInit]
// | [SimpleAssignment] | // | prepareForRhs +-----+
// | [PropInit] | // +--------------------->+----------------->| Rhs |-+
// | prepareForRhs v +-----+
// +--------------------->+-------------->+->| Rhs |-+
// | ^ +-----+ | // | ^ +-----+ |
// | | | // | | |
// | | +-------------+ // | | +-------------+
@ -200,7 +200,7 @@ class MOZ_STACK_CLASS ElemOpEmitter {
// After calling emitIncDec. // After calling emitIncDec.
IncDec, IncDec,
// After calling prepareForRhs or skipObjAndKeyAndRhs. // After calling prepareForRhs.
Rhs, Rhs,
// After calling emitAssignment. // After calling emitAssignment.
@ -252,13 +252,14 @@ class MOZ_STACK_CLASS ElemOpEmitter {
[[nodiscard]] bool emitGet(); [[nodiscard]] bool emitGet();
[[nodiscard]] bool prepareForRhs(); [[nodiscard]] bool prepareForRhs();
[[nodiscard]] bool skipObjAndKeyAndRhs();
[[nodiscard]] bool emitDelete(); [[nodiscard]] bool emitDelete();
[[nodiscard]] bool emitAssignment(); [[nodiscard]] bool emitAssignment();
[[nodiscard]] bool emitIncDec(ValueUsage valueUsage); [[nodiscard]] bool emitIncDec(ValueUsage valueUsage);
size_t numReferenceSlots() const { return 2 + isSuper(); }
}; };
} /* namespace frontend */ } /* namespace frontend */

View file

@ -9,6 +9,8 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include <stddef.h>
#include "frontend/NameAnalysisTypes.h" #include "frontend/NameAnalysisTypes.h"
#include "frontend/ParserAtom.h" // TaggedParserAtomIndex #include "frontend/ParserAtom.h" // TaggedParserAtomIndex
#include "vm/SharedStencil.h" // GCThingIndex #include "vm/SharedStencil.h" // GCThingIndex
@ -174,6 +176,8 @@ class MOZ_STACK_CLASS NameOpEmitter {
[[nodiscard]] bool prepareForRhs(); [[nodiscard]] bool prepareForRhs();
[[nodiscard]] bool emitAssignment(); [[nodiscard]] bool emitAssignment();
[[nodiscard]] bool emitIncDec(ValueUsage valueUsage); [[nodiscard]] bool emitIncDec(ValueUsage valueUsage);
size_t numReferenceSlots() const { return emittedBindOp(); }
}; };
} /* namespace frontend */ } /* namespace frontend */

View file

@ -100,19 +100,6 @@ bool PrivateOpEmitter::emitReference() {
return true; return true;
} }
bool PrivateOpEmitter::skipReference() {
MOZ_ASSERT(state_ == State::Start);
if (!init()) {
return false;
}
#ifdef DEBUG
state_ = State::Reference;
#endif
return true;
}
bool PrivateOpEmitter::emitGet() { bool PrivateOpEmitter::emitGet() {
MOZ_ASSERT(state_ == State::Reference); MOZ_ASSERT(state_ == State::Reference);

View file

@ -114,8 +114,7 @@ class MOZ_STACK_CLASS PrivateOpEmitter {
#ifdef DEBUG #ifdef DEBUG
// The state of this emitter. // The state of this emitter.
// //
// emitReference // +-------+ emitReference +-----------+
// +-------+ skipReference +-----------+
// | Start |---------------->| Reference | // | Start |---------------->| Reference |
// +-------+ +-----+-----+ // +-------+ +-----+-----+
// | // |
@ -144,7 +143,7 @@ class MOZ_STACK_CLASS PrivateOpEmitter {
// The initial state. // The initial state.
Start, Start,
// After calling emitReference or skipReference. // After calling emitReference.
Reference, Reference,
// After calling emitGet. // After calling emitGet.
@ -216,13 +215,12 @@ class MOZ_STACK_CLASS PrivateOpEmitter {
[[nodiscard]] bool emitBrandCheck(); [[nodiscard]] bool emitBrandCheck();
[[nodiscard]] bool emitReference(); [[nodiscard]] bool emitReference();
[[nodiscard]] bool skipReference();
[[nodiscard]] bool emitGet(); [[nodiscard]] bool emitGet();
[[nodiscard]] bool emitGetForCallOrNew(); [[nodiscard]] bool emitGetForCallOrNew();
[[nodiscard]] bool emitAssignment(); [[nodiscard]] bool emitAssignment();
[[nodiscard]] bool emitIncDec(ValueUsage valueUsage); [[nodiscard]] bool emitIncDec(ValueUsage valueUsage);
[[nodiscard]] size_t numReferenceSlots() { return 2; } size_t numReferenceSlots() const { return 2; }
}; };
} /* namespace frontend */ } /* namespace frontend */

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