Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Oana Pop Rus 2019-03-01 00:08:19 +02:00
Родитель 2321ecf84b 5c86c9efec
Коммит 775c1e3f87
172 изменённых файлов: 2323 добавлений и 932 удалений

Просмотреть файл

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<blocklist lastupdate="1550866974800" xmlns="http://www.mozilla.org/2006/addons-blocklist">
<blocklist lastupdate="1551250023025" xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
<prefs/>
@ -2512,6 +2512,26 @@
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="5b3fe8de-6d05-4d95-a6d2-cd5695f1b0c0" id="{157cd8f9-48f0-43a1-9bcf-c4316753e083}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="32227de6-a7bf-454c-bf44-4478ddd96abe" id="{4603d01d-ae80-4653-9288-d5ef98b99a17}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="ec121e9e-d56d-436b-bb2d-735fdcff3c03" id="/^((\{8387ccbe-b9ac-438d-b049-c86b30a6dacb\})|(\{2ef58672-740c-46bd-a50d-b9880986b574\})|(\{7ff51e81-f4b1-4682-9f45-43a771d80748\})|(\{ecb03616-f3c2-4580-99dd-6a233047abdd\})|(\{850be3a2-ca5f-47ad-838c-fe39b006e0da\})|(\{df9f6ab1-c82c-41d4-85ce-86dcfe839ce9\})|(\{a59679da-f097-4db4-b2bc-6ad7b645e127\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="7bb234b0-cfda-4a23-bf02-9c82fb3500a3" id="{9d7cfde2-39ae-11e9-bde0-02427e2eba50}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="37252271-9e38-46a9-b23a-2b6d7048c0db" id="/^((\{e0686c32-99b4-44d8-972f-88bf08b68f88\})|(\{b2225e4c-9d1d-472b-8aeb-5ff203bcff9a\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
</emItems>
<pluginItems>
<pluginItem blockID="p332">

Просмотреть файл

@ -93,8 +93,9 @@ var tabPreviewPanelHelper = {
if (host._prevFocus) {
Services.focus.setFocus(host._prevFocus, Ci.nsIFocusManager.FLAG_NOSCROLL);
host._prevFocus = null;
} else
} else {
gBrowser.selectedBrowser.focus();
}
if (host.tabToSelect) {
gBrowser.selectedTab = host.tabToSelect;

Просмотреть файл

@ -517,9 +517,9 @@ var FullScreen = {
// toggles chrome when moving mouse to the top, it doesn't go away again.
if (aEvent.type == "popupshown" && !FullScreen._isChromeCollapsed &&
aEvent.target.localName != "tooltip" && aEvent.target.localName != "window" &&
aEvent.target.getAttribute("nopreventnavboxhide") != "true")
aEvent.target.getAttribute("nopreventnavboxhide") != "true") {
FullScreen._isPopupOpen = true;
else if (aEvent.type == "popuphidden" && aEvent.target.localName != "tooltip" &&
} else if (aEvent.type == "popuphidden" && aEvent.target.localName != "tooltip" &&
aEvent.target.localName != "window") {
FullScreen._isPopupOpen = false;
// Try again to hide toolbar when we close the popup.

Просмотреть файл

@ -794,9 +794,9 @@ var BookmarksEventHandler = {
// Check whether the tooltipNode is a Places node.
// In such a case use it, otherwise check for targetURI attribute.
var tooltipNode = aDocument.tooltipNode;
if (tooltipNode._placesNode)
if (tooltipNode._placesNode) {
node = tooltipNode._placesNode;
else {
} else {
// This is a static non-Places node.
targetURI = tooltipNode.getAttribute("targetURI");
}

Просмотреть файл

@ -2791,8 +2791,9 @@ function UpdateUrlbarSearchSplitterState() {
splitter.className = "chromeclass-toolbar-additional";
}
urlbar.parentNode.insertBefore(splitter, ibefore);
} else if (splitter)
} else if (splitter) {
splitter.remove();
}
}
function UpdatePageProxyState() {
@ -3970,9 +3971,9 @@ const BrowserSearch = {
get icon() { return browser.mIconURL; },
});
if (hidden)
if (hidden) {
browser.hiddenEngines = engines;
else {
} else {
browser.engines = engines;
if (browser == gBrowser.selectedBrowser)
this.updateOpenSearchBadge();
@ -5406,9 +5407,9 @@ nsBrowserAccess.prototype = {
let win, needToFocusWin;
// try the current window. if we're in a popup, fall back on the most recent browser window
if (window.toolbar.visible)
if (window.toolbar.visible) {
win = window;
else {
} else {
win = BrowserWindowTracker.getTopWindow({private: aIsPrivate});
needToFocusWin = true;
}

Просмотреть файл

@ -479,9 +479,9 @@ async function makeGeneralTab(metaViewRows, docInfo) {
let length = metaViewRows.length;
var metaGroup = document.getElementById("metaTags");
if (!length)
if (!length) {
metaGroup.style.visibility = "hidden";
else {
} else {
document.l10n.setAttributes(document.getElementById("metaTagsCaption"),
"general-meta-tags", {"tags": length});
@ -916,19 +916,20 @@ function makeBlockImage(url) {
var checkbox = document.getElementById("blockImage");
var imagePref = Services.prefs.getIntPref("permissions.default.image");
if (!(/^https?:/.test(url)) || imagePref == 2)
if (!(/^https?:/.test(url)) || imagePref == 2) {
// We can't block the images from this host because either is is not
// for http(s) or we don't load images at all
checkbox.hidden = true;
else {
} else {
var uri = Services.io.newURI(url);
if (uri.host) {
checkbox.hidden = false;
document.l10n.setAttributes(checkbox, "media-block-image", {"website": uri.host});
var perm = permissionManager.testPermission(uri, "image");
checkbox.checked = perm == nsIPermissionManager.DENY_ACTION;
} else
} else {
checkbox.hidden = true;
}
}
}
@ -965,8 +966,9 @@ function setItemValue(id, value) {
if (value) {
item.parentNode.collapsed = false;
item.value = value;
} else
} else {
item.parentNode.collapsed = true;
}
}
function formatNumber(number) {

Просмотреть файл

@ -38,13 +38,15 @@ function onLoadPermission(uri, principal) {
var hostText = document.getElementById("hostText");
hostText.value = gPermURI.displayPrePath;
for (var i of gPermissions)
for (var i of gPermissions) {
initRow(i);
}
Services.obs.addObserver(permissionObserver, "perm-changed");
onUnloadRegistry.push(onUnloadPermission);
permTab.hidden = false;
} else
} else {
permTab.hidden = true;
}
}
function onUnloadPermission() {

Просмотреть файл

@ -238,8 +238,9 @@ function securityOnLoad(uri, windowInfo) {
if (info.cert) {
security._cert = info.cert;
viewCert.collapsed = false;
} else
} else {
viewCert.collapsed = true;
}
/* Set Privacy & History section text */
@ -316,9 +317,8 @@ function setText(id, value) {
return;
if (element.localName == "textbox" || element.localName == "label")
element.value = value;
else {
else
element.textContent = value;
}
}
function viewCertHelper(parent, cert) {

Просмотреть файл

@ -172,9 +172,10 @@ function checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled,
"checking item #" + index / 2 + " (" + expectedItem + ") has checked attr");
is(actualEnabled.disabled, expectedEnabled.disabled,
"checking item #" + index / 2 + " (" + expectedItem + ") has disabled attr");
} else if (expectedEnabled != null)
} else if (expectedEnabled != null) {
is(actualEnabled, expectedEnabled,
"checking item #" + index / 2 + " (" + expectedItem + ") enabled state");
}
}
/*

Просмотреть файл

@ -277,9 +277,9 @@ var gTests = [
let Perms = Services.perms;
let uri = gBrowser.selectedBrowser.documentURI;
let devicePerms = Perms.testExactPermission(uri, aDevice);
if (aExpected === undefined)
if (aExpected === undefined) {
is(devicePerms, Perms.UNKNOWN_ACTION, "no " + aDevice + " persistent permissions");
else {
} else {
is(devicePerms, aExpected ? Perms.ALLOW_ACTION : Perms.DENY_ACTION,
aDevice + " persistently " + (aExpected ? "allowed" : "denied"));
}

Просмотреть файл

@ -389,31 +389,33 @@ nsBrowserContentHandler.prototype = {
chromeParam == "chrome://browser/content/preferences/preferences.xul") {
openPreferences(cmdLine, {origin: "commandLineLegacy"});
cmdLine.preventDefault = true;
} else try {
let resolvedURI = resolveURIInternal(cmdLine, chromeParam);
let isLocal = uri => {
let localSchemes = new Set(["chrome", "file", "resource"]);
if (uri instanceof Ci.nsINestedURI) {
uri = uri.QueryInterface(Ci.nsINestedURI).innerMostURI;
} else {
try {
let resolvedURI = resolveURIInternal(cmdLine, chromeParam);
let isLocal = uri => {
let localSchemes = new Set(["chrome", "file", "resource"]);
if (uri instanceof Ci.nsINestedURI) {
uri = uri.QueryInterface(Ci.nsINestedURI).innerMostURI;
}
return localSchemes.has(uri.scheme);
};
if (isLocal(resolvedURI)) {
// If the URI is local, we are sure it won't wrongly inherit chrome privs
let features = "chrome,dialog=no,all" + this.getFeatures(cmdLine);
// Provide 1 null argument, as openWindow has a different behavior
// when the arg count is 0.
let argArray = Cc["@mozilla.org/array;1"]
.createInstance(Ci.nsIMutableArray);
argArray.appendElement(null);
Services.ww.openWindow(null, resolvedURI.spec, "_blank", features, argArray);
cmdLine.preventDefault = true;
} else {
dump("*** Preventing load of web URI as chrome\n");
dump(" If you're trying to load a webpage, do not pass --chrome.\n");
}
return localSchemes.has(uri.scheme);
};
if (isLocal(resolvedURI)) {
// If the URI is local, we are sure it won't wrongly inherit chrome privs
let features = "chrome,dialog=no,all" + this.getFeatures(cmdLine);
// Provide 1 null argument, as openWindow has a different behavior
// when the arg count is 0.
let argArray = Cc["@mozilla.org/array;1"]
.createInstance(Ci.nsIMutableArray);
argArray.appendElement(null);
Services.ww.openWindow(null, resolvedURI.spec, "_blank", features, argArray);
cmdLine.preventDefault = true;
} else {
dump("*** Preventing load of web URI as chrome\n");
dump(" If you're trying to load a webpage, do not pass --chrome.\n");
} catch (e) {
Cu.reportError(e);
}
} catch (e) {
Cu.reportError(e);
}
}
if (cmdLine.handleFlag("preferences", false)) {

Просмотреть файл

@ -18,7 +18,7 @@ add_task(async function() {
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
window.resizeTo(400, window.outerHeight);
await waitForCondition(() => navbar.hasAttribute("overflowing"));
await TestUtils.waitForCondition(() => navbar.hasAttribute("overflowing"));
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
let chevron = document.getElementById("nav-bar-overflow-button");
@ -61,7 +61,7 @@ add_task(async function() {
CustomizableUI.reset();
// In some cases, it can take a tick for the navbar to overflow again. Wait for it:
await waitForCondition(() => navbar.hasAttribute("overflowing"));
await TestUtils.waitForCondition(() => navbar.hasAttribute("overflowing"));
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
sidebarButtonPlacement = CustomizableUI.getPlacementOfWidget("sidebar-button");

Просмотреть файл

@ -57,7 +57,7 @@ skip-if = os == 'linux'
[browser_ext_browserAction_pageAction_icon.js]
[browser_ext_browserAction_pageAction_icon_permissions.js]
[browser_ext_browserAction_popup.js]
skip-if = (debug && os == 'linux' && bits == 32) || (os == 'win' && !debug) # Bug 1313372, win: Bug 1285500
skip-if = (debug && os == 'linux' && bits == 32) # Bug 1313372
[browser_ext_browserAction_popup_port.js]
[browser_ext_browserAction_popup_preload.js]
skip-if = (os == 'win' && !debug) || (verify && debug && (os == 'mac')) # bug 1352668

Просмотреть файл

@ -9,7 +9,7 @@ add_task(async function testBrowserActionClickCanceled() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
// Make sure the mouse isn't hovering over the browserAction widget.
EventUtils.synthesizeMouseAtCenter(gURLBar, {type: "mouseover"}, window);
EventUtils.synthesizeMouseAtCenter(gURLBar.textbox, {type: "mouseover"}, window);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
@ -87,7 +87,7 @@ add_task(async function testBrowserActionClickCanceled() {
add_task(async function testBrowserActionDisabled() {
// Make sure the mouse isn't hovering over the browserAction widget.
EventUtils.synthesizeMouseAtCenter(gURLBar, {type: "mouseover"}, window);
EventUtils.synthesizeMouseAtCenter(gURLBar.textbox, {type: "mouseover"}, window);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
@ -195,7 +195,7 @@ add_task(async function testBrowserActionTabPopulation() {
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
// Make sure the mouse isn't hovering over the browserAction widget.
EventUtils.synthesizeMouseAtCenter(win.gURLBar, {type: "mouseover"}, win);
EventUtils.synthesizeMouseAtCenter(win.gURLBar.textbox, {type: "mouseover"}, win);
await extension.startup();
@ -231,7 +231,7 @@ add_task(async function testClosePopupDuringPreload() {
});
// Make sure the mouse isn't hovering over the browserAction widget.
EventUtils.synthesizeMouseAtCenter(gURLBar, {type: "mouseover"}, window);
EventUtils.synthesizeMouseAtCenter(gURLBar.textbox, {type: "mouseover"}, window);
await extension.startup();

Просмотреть файл

@ -189,7 +189,7 @@ add_task(async function testBrowserActionTelemetryResults() {
await extension.startup();
// Make sure the mouse isn't hovering over the browserAction widget to start.
EventUtils.synthesizeMouseAtCenter(gURLBar, {type: "mouseover"}, window);
EventUtils.synthesizeMouseAtCenter(gURLBar.textbox, {type: "mouseover"}, window);
let widget = getBrowserActionWidget(extension).forWindow(window);

Просмотреть файл

@ -4,7 +4,7 @@
async function testExecuteBrowserActionWithOptions(options = {}) {
// Make sure the mouse isn't hovering over the browserAction widget.
EventUtils.synthesizeMouseAtCenter(gURLBar, {type: "mouseover"}, window);
EventUtils.synthesizeMouseAtCenter(gURLBar.textbox, {type: "mouseover"}, window);
let extensionOptions = {};

Просмотреть файл

@ -4,7 +4,7 @@
add_task(async function testIncognitoViews() {
// Make sure the mouse isn't hovering over the browserAction widget.
EventUtils.synthesizeMouseAtCenter(gURLBar, {type: "mouseover"}, window);
EventUtils.synthesizeMouseAtCenter(gURLBar.textbox, {type: "mouseover"}, window);
let extension = ExtensionTestUtils.loadExtension({
manifest: {

Просмотреть файл

@ -2,6 +2,8 @@
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const {UrlbarTestUtils} = ChromeUtils.import("resource://testing-common/UrlbarTestUtils.jsm");
add_task(async function() {
// This keyword needs to be unique to prevent history entries from unrelated
// tests from appearing in the suggestions list.
@ -81,25 +83,22 @@ add_task(async function() {
}
}
async function waitForAutocompleteResultAt(index) {
let searchString = gURLBar.controller.searchString;
await BrowserTestUtils.waitForCondition(
() => gURLBar.popup.richlistbox.itemChildren.length > index &&
gURLBar.popup.richlistbox.itemChildren[index].getAttribute("ac-text") == searchString,
`Waiting for the autocomplete result for "${searchString}" at [${index}] to appear`);
async function waitForResult(index, searchString) {
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, index);
// Ensure the addition is complete, for proper mouse events on the entries.
await new Promise(resolve => window.requestIdleCallback(resolve, {timeout: 1000}));
return gURLBar.popup.richlistbox.itemChildren[index];
return result;
}
async function promiseClickOnItem(item, details) {
async function promiseClickOnItem(index, details) {
// The Address Bar panel is animated and updated on a timer, thus it may not
// yet be listening to events when we try to click on it. This uses a
// polling strategy to repeat the click, if it doesn't go through.
let clicked = false;
item.addEventListener("mousedown", () => { clicked = true; }, {once: true});
let element = await UrlbarTestUtils.waitForAutocompleteResultAt(window, index);
element.addEventListener("mousedown", () => { clicked = true; }, {once: true});
while (!clicked) {
EventUtils.synthesizeMouseAtCenter(item, details);
EventUtils.synthesizeMouseAtCenter(element, details);
await new Promise(r => window.requestIdleCallback(r, {timeout: 1000}));
}
}
@ -111,7 +110,7 @@ add_task(async function() {
EventUtils.sendString(" ");
await expectEvent("on-input-started-fired");
// Always use a different input at every invokation, so that
// waitForAutocompleteResultAt can distinguish different cases.
// waitForResult can distinguish different cases.
let char = ((inputSessionSerial++) % 10).toString();
EventUtils.sendString(char);
@ -187,27 +186,25 @@ add_task(async function() {
}
let text = await startInputSession();
await waitForAutocompleteResultAt(0);
let result = await waitForResult(0);
let item = gURLBar.popup.richlistbox.itemChildren[0];
Assert.equal(result.displayed.title, expectedText,
`Expected heuristic result to have title: "${expectedText}".`);
is(item.getAttribute("title"), expectedText,
`Expected heuristic result to have title: "${expectedText}".`);
is(item.getAttribute("displayurl"), `${keyword} ${text}`,
`Expected heuristic result to have displayurl: "${keyword} ${text}".`);
Assert.equal(result.displayed.action, `${keyword} ${text}`,
`Expected heuristic result to have displayurl: "${keyword} ${text}".`);
let promiseEvent = expectEvent("on-input-entered-fired", {
text,
disposition: "currentTab",
});
await promiseClickOnItem(item, {});
await promiseClickOnItem(0, {});
await promiseEvent;
}
async function testDisposition(suggestionIndex, expectedDisposition, expectedText) {
await startInputSession();
await waitForAutocompleteResultAt(suggestionIndex);
await waitForResult(suggestionIndex);
// Select the suggestion.
EventUtils.synthesizeKey("KEY_ArrowDown", {repeat: suggestionIndex});
@ -217,13 +214,12 @@ add_task(async function() {
disposition: expectedDisposition,
});
let item = gURLBar.popup.richlistbox.itemChildren[suggestionIndex];
if (expectedDisposition == "currentTab") {
await promiseClickOnItem(item, {});
await promiseClickOnItem(suggestionIndex, {});
} else if (expectedDisposition == "newForegroundTab") {
await promiseClickOnItem(item, {accelKey: true});
await promiseClickOnItem(suggestionIndex, {accelKey: true});
} else if (expectedDisposition == "newBackgroundTab") {
await promiseClickOnItem(item, {shiftKey: true, accelKey: true});
await promiseClickOnItem(suggestionIndex, {shiftKey: true, accelKey: true});
}
await promiseEvent;
}
@ -232,33 +228,33 @@ add_task(async function() {
extension.sendMessage("set-synchronous", {synchronous: false});
await extension.awaitMessage("set-synchronous-set");
function expectSuggestion({content, description}, index) {
let item = gURLBar.popup.richlistbox.itemChildren[index + 1]; // Skip the heuristic result.
ok(!!item, "Expected item to exist");
is(item.getAttribute("title"), description,
`Expected suggestion to have title: "${description}".`);
is(item.getAttribute("displayurl"), `${keyword} ${content}`,
`Expected suggestion to have displayurl: "${keyword} ${content}".`);
}
let text = await startInputSession();
// Even if the results are generated asynchronously,
// the heuristic result should always be present.
await waitForAutocompleteResultAt(0);
if (!UrlbarPrefs.get("quantumbar")) {
// TODO Bug 1530338: We can't yet wait for a specific result for the
// quantumbar. Therefore we just skip this for now.
await waitForResult(0);
}
extension.sendMessage(info.test);
await extension.awaitMessage("test-ready");
await waitForAutocompleteResultAt(info.suggestions.length - 1);
info.suggestions.forEach(expectSuggestion);
await waitForResult(info.suggestions.length - 1);
// Skip the heuristic result.
let index = 1;
for (let {content, description} of info.suggestions) {
let item = await UrlbarTestUtils.getDetailsOfResultAt(window, index);
Assert.equal(item.displayed.title, description,
`Expected suggestion to have title: "${description}".`);
Assert.equal(item.displayed.action, `${keyword} ${content}`,
`Expected suggestion to have displayurl: "${keyword} ${content}".`);
index++;
}
let promiseEvent = expectEvent("on-input-entered-fired", {
text,
disposition: "currentTab",
});
await promiseClickOnItem(gURLBar.popup.richlistbox.itemChildren[0], {});
await promiseClickOnItem(0, {});
await promiseEvent;
}

Просмотреть файл

@ -2,13 +2,12 @@
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
async function testIncognito(incognitoOverride) {
add_task(async function test_sidebarAction_not_allowed() {
SpecialPowers.pushPrefEnv({set: [
["extensions.allowPrivateBrowsingByDefault", false],
]});
let extension = ExtensionTestUtils.loadExtension({
incognitoOverride,
manifest: {
sidebar_action: {
default_panel: "sidebar.html",
@ -18,40 +17,40 @@ async function testIncognito(incognitoOverride) {
browser.test.onMessage.addListener(async pbw => {
await browser.test.assertRejects(browser.sidebarAction.setTitle({
windowId: pbw.windowId, title: "test",
}), /Invalid window ID/, "should not be able to set title");
}), /Invalid window ID/, "should not be able to set title with windowId");
await browser.test.assertRejects(browser.sidebarAction.setTitle({
tabId: pbw.tabId, title: "test",
}), /Invalid tab ID/, "should not be able to set title");
await browser.test.assertRejects(browser.sidebarAction.getTitle({
windowId: pbw.windowId,
}), /Invalid window ID/, "should not be able to get title");
}), /Invalid window ID/, "should not be able to get title with windowId");
await browser.test.assertRejects(browser.sidebarAction.getTitle({
tabId: pbw.tabId,
}), /Invalid tab ID/, "should not be able to get title");
}), /Invalid tab ID/, "should not be able to get title with tabId");
await browser.test.assertRejects(browser.sidebarAction.setIcon({
windowId: pbw.windowId, path: "test",
}), /Invalid window ID/, "should not be able to set icon");
}), /Invalid window ID/, "should not be able to set icon with windowId");
await browser.test.assertRejects(browser.sidebarAction.setIcon({
tabId: pbw.tabId, path: "test",
}), /Invalid tab ID/, "should not be able to set icon");
}), /Invalid tab ID/, "should not be able to set icon with tabId");
await browser.test.assertRejects(browser.sidebarAction.setPanel({
windowId: pbw.windowId, panel: "test",
}), /Invalid window ID/, "should not be able to set panel");
}), /Invalid window ID/, "should not be able to set panel with windowId");
await browser.test.assertRejects(browser.sidebarAction.setPanel({
tabId: pbw.tabId, panel: "test",
}), /Invalid tab ID/, "should not be able to set panel");
}), /Invalid tab ID/, "should not be able to set panel with tabId");
await browser.test.assertRejects(browser.sidebarAction.getPanel({
windowId: pbw.windowId,
}), /Invalid window ID/, "should not be able to get panel");
}), /Invalid window ID/, "should not be able to get panel with windowId");
await browser.test.assertRejects(browser.sidebarAction.getPanel({
tabId: pbw.tabId,
}), /Invalid tab ID/, "should not be able to get panel");
}), /Invalid tab ID/, "should not be able to get panel with tabId");
await browser.test.assertRejects(browser.sidebarAction.isOpen({
windowId: pbw.windowId,
}), /Invalid window ID/, "should not be able to determine openness");
}), /Invalid window ID/, "should not be able to determine openness with windowId");
browser.test.notifyPass("pass");
});
@ -81,26 +80,14 @@ async function testIncognito(incognitoOverride) {
let sidebarID = `${makeWidgetId(extension.id)}-sidebar-action`;
ok(SidebarUI.sidebars.has(sidebarID), "sidebar exists in non-private window");
let winData = await getIncognitoWindow("about:blank");
let winData = await getIncognitoWindow();
let hasSidebar = winData.win.SidebarUI.sidebars.has(sidebarID);
if (incognitoOverride == "spanning") {
ok(hasSidebar, "sidebar exists in private window");
} else {
ok(!hasSidebar, "sidebar does not exist in private window");
// Test API access to private window data.
extension.sendMessage(winData.details);
await extension.awaitFinish("pass");
}
ok(!hasSidebar, "sidebar does not exist in private window");
// Test API access to private window data.
extension.sendMessage(winData.details);
await extension.awaitFinish("pass");
await BrowserTestUtils.closeWindow(winData.win);
await extension.unload();
}
add_task(async function test_sidebarAction_not_allowed() {
await testIncognito();
});
add_task(async function test_sidebarAction_allowed() {
await testIncognito("spanning");
});

Просмотреть файл

@ -672,7 +672,7 @@ async function startIncognitoMonitorExtension() {
return extension;
}
async function getIncognitoWindow(url) {
async function getIncognitoWindow(url = "about:privatebrowsing") {
// Since events will be limited based on incognito, we need a
// spanning extension to get the tab id so we can test access failure.

Просмотреть файл

@ -751,8 +751,9 @@ var PlacesUIUtils = {
// Use (no title) for non-standard URIs (data:, javascript:, ...)
title = "";
}
} else
} else {
title = aNode.title;
}
return title || this.getString("noTitle");
},

Просмотреть файл

@ -369,8 +369,9 @@ PlacesViewBase.prototype = {
}
this._domNodes.set(aPlacesNode, popup);
} else
} else {
throw "Unexpected node";
}
element.setAttribute("label", PlacesUIUtils.getBestTitle(aPlacesNode));
@ -1573,9 +1574,9 @@ PlacesToolbar.prototype = {
halfInd = Math.ceil(halfInd);
translateX = 0 - this._rootElt.getBoundingClientRect().right - halfInd;
if (this._rootElt.firstElementChild) {
if (dropPoint.beforeIndex == -1)
if (dropPoint.beforeIndex == -1) {
translateX += this._rootElt.lastElementChild.getBoundingClientRect().left;
else {
} else {
translateX += this._rootElt.children[dropPoint.beforeIndex]
.getBoundingClientRect().right;
}
@ -1585,9 +1586,9 @@ PlacesToolbar.prototype = {
translateX = 0 - this._rootElt.getBoundingClientRect().left +
halfInd;
if (this._rootElt.firstElementChild) {
if (dropPoint.beforeIndex == -1)
if (dropPoint.beforeIndex == -1) {
translateX += this._rootElt.lastElementChild.getBoundingClientRect().right;
else {
} else {
translateX += this._rootElt.children[dropPoint.beforeIndex]
.getBoundingClientRect().left;
}

Просмотреть файл

@ -443,8 +443,9 @@
elt = elt.nextElementSibling;
newMarginTop = elt ? elt.screenY - this._scrollBox.screenY :
scrollbox.height;
} else if (scrollDir == 1)
} else if (scrollDir == 1) {
newMarginTop = scrollbox.height;
}
// Set the new marginTop based on arrowscrollbox.
newMarginTop += scrollbox.y - this._scrollBox.boxObject.y;

Просмотреть файл

@ -460,9 +460,9 @@
for (var i = 0; i < container.childCount; ++i) {
var child = container.getChild(i);
var childURI = child.uri;
if (childURI == placeURI)
if (childURI == placeURI) {
return child;
else if (PlacesUtils.nodeIsContainer(child)) {
} else if (PlacesUtils.nodeIsContainer(child)) {
var nested = findNode(PlacesUtils.asContainer(child), nodesURIChecked);
if (nested)
return nested;
@ -481,9 +481,9 @@
return;
var child = findNode(container, []);
if (child)
if (child) {
this.selectNode(child);
else {
} else {
// If the specified child could not be located, clear the selection
var selection = this.view.selection;
selection.clearSelection();

Просмотреть файл

@ -66,8 +66,9 @@ PlacesTreeView.prototype = {
// This triggers containerStateChanged which then builds the visible
// section.
this._rootNode.containerOpen = true;
} else
} else {
this.invalidateContainer(this._rootNode);
}
// "Activate" the sorting column and update commands.
this.sortingChanged(this._result.sortingMode);
@ -1191,9 +1192,9 @@ PlacesTreeView.prototype = {
break;
}
}
} else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
} else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
properties += " separator";
else if (PlacesUtils.nodeIsURI(node)) {
} else if (PlacesUtils.nodeIsURI(node)) {
properties += " " + PlacesUIUtils.guessUrlSchemeForUI(node.uri);
}

Просмотреть файл

@ -436,8 +436,9 @@ function open_properties_dialog(test) {
command = "placesCmd_new:bookmark";
else
Assert.ok(false, "You didn't set a valid itemType for adding an item");
} else
} else {
command = "placesCmd_createBookmark";
}
break;
default:
Assert.ok(false, "You didn't set a valid action for this test");

Просмотреть файл

@ -138,9 +138,9 @@ var pktApi = (function() {
// TODO : Move this to sqlite or a local file so it's not editable (and is safer)
// https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/Local_Storage
if (!value)
if (!value) {
prefBranch.clearUserPref(key);
else {
} else {
// We use complexValue as tags can have utf-8 characters in them
prefBranch.setStringPref(key, value);
}

Просмотреть файл

@ -1552,9 +1552,9 @@ var gMainPane = {
let type = wrappedHandlerInfo.type;
let handlerInfoWrapper;
if (type in this._handledTypes)
if (type in this._handledTypes) {
handlerInfoWrapper = this._handledTypes[type];
else {
} else {
handlerInfoWrapper = new HandlerInfoWrapper(type, wrappedHandlerInfo);
this._handledTypes[type] = handlerInfoWrapper;
}

Просмотреть файл

@ -660,15 +660,16 @@ var gPrivacyPane = {
let mode;
let getVal = aPref => Preferences.get(aPref).value;
if (getVal("privacy.history.custom"))
if (getVal("privacy.history.custom")) {
mode = "custom";
else if (this._checkHistoryValues(this.prefsForKeepingHistory)) {
} else if (this._checkHistoryValues(this.prefsForKeepingHistory)) {
if (getVal("browser.privatebrowsing.autostart"))
mode = "dontremember";
else
mode = "remember";
} else
} else {
mode = "custom";
}
document.getElementById("historyMode").value = mode;
},

Просмотреть файл

@ -186,9 +186,9 @@ var gLanguagesDialog = {
this._selectedItemID = selectedID;
if (preference.value == "")
if (preference.value == "") {
preference.value = selectedID;
else {
} else {
arrayOfPrefs.unshift(selectedID);
preference.value = arrayOfPrefs.join(",");
}

Просмотреть файл

@ -357,8 +357,9 @@ class MozSearchbar extends MozXULElement {
// Select the installed engine if the installation succeeds.
Services.search.addEngine(target.getAttribute("uri"), null,
target.getAttribute("src"), false).then(engine => this.currentEngine = engine);
} else
} else {
return;
}
this.focus();
this.select();

Просмотреть файл

@ -95,8 +95,9 @@ function nextTest() {
gCurrentTest = gTests.shift();
info("Running " + gCurrentTest.name);
gCurrentTest.run();
} else
} else {
executeSoon(finish);
}
}
function test() {

Просмотреть файл

@ -18,8 +18,6 @@ ChromeUtils.defineModuleGetter(this, "ContentRestore",
"resource:///modules/sessionstore/ContentRestore.jsm");
ChromeUtils.defineModuleGetter(this, "SessionHistory",
"resource://gre/modules/sessionstore/SessionHistory.jsm");
ChromeUtils.defineModuleGetter(this, "Utils",
"resource://gre/modules/sessionstore/Utils.jsm");
// A bound to the size of data to store for DOM Storage.
const DOM_STORAGE_LIMIT_PREF = "browser.sessionstore.dom_storage_limit";
@ -33,15 +31,6 @@ const PREF_INTERVAL = "browser.sessionstore.interval";
const kNoIndex = Number.MAX_SAFE_INTEGER;
const kLastIndex = Number.MAX_SAFE_INTEGER - 1;
/**
* A function that will recursively call |cb| to collect data for all
* non-dynamic frames in the current frame/docShell tree.
*/
function mapFrameTree(mm, callback) {
let [data] = Utils.mapFrameTree(mm.content, callback);
return data;
}
class Handler {
constructor(store) {
this.store = store;
@ -341,7 +330,7 @@ class ScrollPositionListener extends Handler {
}
collect() {
return mapFrameTree(this.mm, SessionStoreUtils.collectScrollPosition);
return SessionStoreUtils.collectScrollPosition(this.mm.content);
}
}
@ -379,7 +368,7 @@ class FormDataListener extends Handler {
}
collect() {
return mapFrameTree(this.mm, SessionStoreUtils.collectFormData);
return SessionStoreUtils.collectFormData(this.mm.content);
}
}

Просмотреть файл

@ -207,8 +207,9 @@ function onListClick(aEvent) {
!treeView.isContainer(cell.row)) {
restoreSingleTab(cell.row, aEvent.shiftKey);
aEvent.stopPropagation();
} else if (cell.col.id == "restore")
} else if (cell.col.id == "restore") {
toggleRowChecked(cell.row);
}
}
}

Просмотреть файл

@ -81,9 +81,9 @@ var workerManager = {
// results. Otherwise, reschedule termination until after the next
// idle timeout.
_flushWorker() {
if (this.detectionQueue.length)
if (this.detectionQueue.length) {
this.flushWorker();
else {
} else {
if (this._worker)
this._worker.terminate();

Просмотреть файл

@ -281,9 +281,9 @@ class MozTranslationNotification extends MozElements.Notification {
optionsShowing() {
// Get the source language name.
let lang;
if (this.state == Translation.STATE_OFFER)
if (this.state == Translation.STATE_OFFER) {
lang = this._getAnonElt("detectedLanguage").value;
else {
} else {
lang = this._getAnonElt("fromLanguage").value;
// If we have never attempted to translate the page before the

Просмотреть файл

@ -13,6 +13,7 @@ const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
AppConstants: "resource://gre/modules/AppConstants.jsm",
BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.jsm",
ExtensionSearchHandler: "resource://gre/modules/ExtensionSearchHandler.jsm",
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
UrlbarProvidersManager: "resource:///modules/UrlbarProvidersManager.jsm",
@ -108,9 +109,12 @@ class UrlbarController {
/**
* Cancels an in-progress query. Note, queries may continue running if they
* can't be canceled.
* can't be cancelled.
*
* @param {UrlbarUtils.CANCEL_REASON} [reason]
* The reason the query was cancelled.
*/
cancelQuery() {
cancelQuery(reason) {
if (!this._lastQueryContext) {
return;
}
@ -121,6 +125,11 @@ class UrlbarController {
this.manager.cancelQuery(this._lastQueryContext);
this._notify("onQueryCancelled", this._lastQueryContext);
delete this._lastQueryContext;
if (reason == UrlbarUtils.CANCEL_REASON.BLUR &&
ExtensionSearchHandler.hasActiveInputSession()) {
ExtensionSearchHandler.handleInputCancelled();
}
}
/**

Просмотреть файл

@ -153,7 +153,6 @@ class UrlbarInput {
}
closePopup() {
this.controller.cancelQuery();
this.view.close();
}
@ -371,6 +370,9 @@ class UrlbarInput {
break;
}
case UrlbarUtils.RESULT_TYPE.OMNIBOX: {
// The urlbar needs to revert to the loaded url when a command is
// handled by the extension.
this.handleRevert();
// We don't directly handle a load when an Omnibox API result is picked,
// instead we forward the request to the WebExtension itself, because
// the value may not even be a url.
@ -950,7 +952,7 @@ class UrlbarInput {
_on_blur(event) {
this.formatValue();
this.closePopup();
this.view.close(UrlbarUtils.CANCEL_REASON.BLUR);
}
_on_focus(event) {

Просмотреть файл

@ -114,6 +114,12 @@ var UrlbarUtils = {
COMMIT: 3,
},
// This defines possible reasons for canceling a query.
CANCEL_REASON: {
// 1 is intentionally left in case we want a none/undefined/other later.
BLUR: 2,
},
/**
* Adds a url to history as long as it isn't in a private browsing window,
* and it is valid.

Просмотреть файл

@ -172,9 +172,14 @@ class UrlbarView {
}
/**
* Closes the autocomplete results popup.
* Closes the autocomplete popup, cancelling the query if necessary.
*
* @param {UrlbarUtils.CANCEL_REASON} [cancelReason]
* Indicates if this close is being triggered as a result of a user action
* which would cancel a query, e.g. on blur.
*/
close() {
close(cancelReason) {
this.controller.cancelQuery(cancelReason);
this.panel.hidePopup();
}
@ -464,6 +469,9 @@ class UrlbarView {
setAction(bundle.GetStringFromName("visit"));
}
break;
case UrlbarUtils.RESULT_TYPE.OMNIBOX:
setAction(result.payload.content);
break;
default:
if (result.heuristic) {
setAction(bundle.GetStringFromName("visit"));

Просмотреть файл

@ -299,7 +299,7 @@ class UrlbarAbstraction {
return BrowserTestUtils.waitForCondition(
() => this.urlbar.controller.searchStatus >=
Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH,
"waiting urlbar search to complete");
"waiting urlbar search to complete", 100, 50);
}
async promiseResultAt(index) {

Просмотреть файл

@ -44,9 +44,9 @@ async function clickURLBarSuggestion(resultTitle, button = 1) {
if (result.displayed.title == resultTitle) {
// This entry is the search suggestion we're looking for.
let element = await UrlbarTestUtils.waitForAutocompleteResultAt(window, i);
if (button == 1)
if (button == 1) {
EventUtils.synthesizeMouseAtCenter(element, {});
else if (button == 2) {
} else if (button == 2) {
EventUtils.synthesizeMouseAtCenter(element, {type: "mousedown", button: 2});
}
return;

Просмотреть файл

@ -676,7 +676,7 @@
.tabbrowser-arrowscrollbox > .scrollbutton-down {
list-style-image: url(chrome://browser/skin/arrow-left.svg) !important;
-moz-context-properties: fill, fill-opacity;
fill: currentColor;
fill: var(--lwt-toolbarbutton-icon-fill, currentColor);
fill-opacity: var(--toolbarbutton-icon-fill-opacity);
color: inherit;
}

Просмотреть файл

@ -11,9 +11,6 @@
},
"homepage": "https://github.com/firefox-devtools/debugger.html#readme",
"engineStrict": true,
"engines": {
"node": ">=10.15.0"
},
"scripts": {
"start": "node bin/dev-server",
"start-app": "TARGET=application node bin/dev-server",

Просмотреть файл

@ -42,11 +42,12 @@ env.testing = true;
const rootPath = path.join(__dirname, "../../");
function getL10nBundle() {
const read = file => readFileSync(path.join(__dirname, file));
const read = file => readFileSync(path.join(rootPath, file));
try {
return read("../../assets/panel/debugger.properties");
return read("./assets/panel/debugger.properties");
} catch (e) {
return read("../../../../locales/en-us/debugger.properties");
return read("../../locales/en-US/debugger.properties");
}
}
@ -111,3 +112,20 @@ function mockIndexeddDB() {
}
};
}
// NOTE: We polyfill finally because TRY uses node 8
if (!global.Promise.prototype.finally) {
global.Promise.prototype.finally = function finallyPolyfill(callback) {
var constructor = this.constructor;
return this.then(function(value) {
return constructor.resolve(callback()).then(function() {
return value;
});
}, function(reason) {
return constructor.resolve(callback()).then(function() {
throw reason;
});
});
};
}

Просмотреть файл

@ -62,6 +62,9 @@ class FontInspector {
this.inspector = inspector;
// Set of unique keyword values supported by designated font properties.
this.keywordValues = new Set(this.getFontPropertyValueKeywords());
// Selected node in the markup view. For text nodes, this points to their parent node
// element. Font faces and font properties for this node will be shown in the editor.
this.node = null;
this.nodeComputedStyle = {};
this.pageStyle = this.inspector.pageStyle;
this.ruleViewTool = this.inspector.getPanel("ruleview");
@ -162,8 +165,8 @@ class FontInspector {
const fromPx = fromUnit === "px";
// Determine the target CSS unit for conversion.
const unit = toUnit === "px" ? fromUnit : toUnit;
// NodeFront instance of selected element.
const node = this.inspector.selection.nodeFront;
// NodeFront instance of selected/target element.
const node = this.node;
// Reference node based on which to convert relative sizes like "em" and "%".
const referenceNode = (property === "line-height") ? node : node.parentNode();
// Default output value to input value for a 1-to-1 conversion as a guard against
@ -296,6 +299,7 @@ class FontInspector {
this.document = null;
this.inspector = null;
this.node = null;
this.nodeComputedStyle = {};
this.pageStyle = null;
this.ruleView = null;
@ -540,17 +544,6 @@ class FontInspector {
this.inspector.sidebar &&
this.inspector.sidebar.getCurrentTabID() === "fontinspector";
}
/**
* Check if a selected node exists and fonts can apply to it.
*
* @return {Boolean}
*/
isSelectedNodeValid() {
return this.inspector &&
this.inspector.selection.nodeFront &&
this.inspector.selection.isConnected() &&
this.inspector.selection.isElementNode();
}
/**
* Upon a new node selection, log some interesting telemetry probes.
@ -654,10 +647,30 @@ class FontInspector {
}
/**
* Selection 'new-node' event handler.
* Event handler for "new-node-front" event fired when a new node is selected in the
* markup view.
*
* Sets the selected node for which font faces and font properties will be
* shown in the font editor. If the selection is a text node, use its parent element.
*
* Triggers a refresh of the font editor and font overview if the panel is visible.
*/
onNewNode() {
this.ruleView.off("property-value-updated", this.onRulePropertyUpdated);
// First, reset the selected node.
this.node = null;
// Then attempt to assign a selected node according to its type.
const selection = this.inspector && this.inspector.selection;
if (selection && selection.isConnected()) {
if (selection.isElementNode()) {
this.node = selection.nodeFront;
}
if (selection.isTextNode()) {
this.node = selection.nodeFront.parentNode();
}
}
if (this.isPanelVisible()) {
Promise.all([this.update(), this.refreshFontEditor()]).then(() => {
this.logTelemetryProbesOnNewNode();
@ -753,9 +766,7 @@ class FontInspector {
try {
if (show) {
const node = isForCurrentElement
? this.inspector.selection.nodeFront
: this.inspector.walker.rootNode;
const node = isForCurrentElement ? this.node : this.inspector.walker.rootNode;
await this.fontsHighlighter.show(node, {
CSSFamilyName: font.CSSFamilyName,
@ -785,21 +796,13 @@ class FontInspector {
* - the computed style CSS font properties of the current node.
*
* This method is called:
* - during initial setup;
* - when a new node is selected;
* - when any property is changed in the Rule view.
* For the latter case, we compare between the latest computed style font properties
* and the ones already in the store to decide if to update the font editor state.
*/
async refreshFontEditor() {
if (!this.store || !this.isSelectedNodeValid()) {
// If the selection is a TextNode, switch selection to be its parent node.
if (this.inspector.selection.isTextNode()) {
const selection = this.inspector.selection;
selection.setNodeFront(selection.nodeFront.parentNode());
return;
}
if (!this.node) {
this.store.dispatch(resetFontEditor());
return;
}
@ -809,12 +812,11 @@ class FontInspector {
options.includeVariations = true;
}
const node = this.inspector.selection.nodeFront;
const fonts = await this.getFontsForNode(node, options);
const fonts = await this.getFontsForNode(this.node, options);
try {
// Get computed styles for the selected node, but filter by CSS font properties.
this.nodeComputedStyle = await this.pageStyle.getComputed(node, {
this.nodeComputedStyle = await this.pageStyle.getComputed(this.node, {
filterProperties: FONT_PROPERTIES,
});
} catch (e) {
@ -842,7 +844,7 @@ class FontInspector {
// been created yet. For example, in 2-pane mode when Fonts is opened as the default
// panel. Select the current node to force the Rule view to create the rule models.
if (!this.ruleViewTool.isSidebarActive()) {
await this.ruleView.selectElement(node, false);
await this.ruleView.selectElement(this.node, false);
}
// Select the node's inline style as the rule where to write property value changes.
@ -856,9 +858,8 @@ class FontInspector {
this.writers.set(axis, this.getWriterForAxis(axis));
});
this.store.dispatch(updateFontEditor(fonts, properties, node.actorID));
const isPseudo = this.inspector.selection.isPseudoElementNode();
this.store.dispatch(setEditorDisabled(isPseudo));
this.store.dispatch(updateFontEditor(fonts, properties, this.node.actorID));
this.store.dispatch(setEditorDisabled(this.node.isPseudoElement));
this.inspector.emit("fonteditor-updated");
// Listen to manual changes in the Rule view that could update the Font Editor state
@ -882,7 +883,7 @@ class FontInspector {
let allFonts = [];
if (!this.isSelectedNodeValid()) {
if (!this.node) {
this.store.dispatch(updateFonts(allFonts));
return;
}

Просмотреть файл

@ -16,6 +16,7 @@ add_task(async function() {
const bodyNode = await getNodeFront("body", inspector);
const { nodes } = await inspector.walker.children(bodyNode);
const onInspectorUpdated = inspector.once("fontinspector-updated");
info("Select the text node");
await selectNode(nodes[0], inspector);
info("Waiting for font editor to render");

Просмотреть файл

@ -936,7 +936,7 @@ netmonitor.context.copyRequestHeaders=Copy Request Headers
# LOCALIZATION NOTE (netmonitor.context.copyRequestHeaders.accesskey): This is the access key
# for the Copy Request Headers menu item displayed in the context menu for a request
netmonitor.context.copyRequestHeaders.accesskey=Q
netmonitor.context.copyRequestHeaders.accesskey=q
# LOCALIZATION NOTE (netmonitor.context.copyResponseHeaders): This is the label displayed
# on the context menu that copies the selected item's response headers
@ -944,7 +944,7 @@ netmonitor.context.copyResponseHeaders=Copy Response Headers
# LOCALIZATION NOTE (netmonitor.context.copyResponseHeaders.accesskey): This is the access key
# for the Copy Response Headers menu item displayed in the context menu for a response
netmonitor.context.copyResponseHeaders.accesskey=S
netmonitor.context.copyResponseHeaders.accesskey=s
# LOCALIZATION NOTE (netmonitor.context.copyResponse): This is the label displayed
# on the context menu that copies the selected response as a string
@ -968,7 +968,7 @@ netmonitor.context.saveImageAs=Save Image As
# LOCALIZATION NOTE (netmonitor.context.saveImageAs.accesskey): This is the access key
# for the Copy Image As Data URI menu item displayed in the context menu for a request
netmonitor.context.saveImageAs.accesskey=V
netmonitor.context.saveImageAs.accesskey=v
# LOCALIZATION NOTE (netmonitor.context.copyAllAsHar): This is the label displayed
# on the context menu that copies all as HAR format
@ -976,7 +976,7 @@ netmonitor.context.copyAllAsHar=Copy All As HAR
# LOCALIZATION NOTE (netmonitor.context.copyAllAsHar.accesskey): This is the access key
# for the Copy All As HAR menu item displayed in the context menu for a network panel
netmonitor.context.copyAllAsHar.accesskey=O
netmonitor.context.copyAllAsHar.accesskey=o
# LOCALIZATION NOTE (netmonitor.context.saveAllAsHar): This is the label displayed
# on the context menu that saves all as HAR format

Просмотреть файл

@ -27,6 +27,7 @@
* [`xpcshell`](tests/xpcshell.md)
* [Chrome mochitests](tests/mochitest-chrome.md)
* [DevTools mochitests](tests/mochitest-devtools.md)
* [Tips](tests/tips.md)
* [Writing tests](tests/writing-tests.md)
* [Debugging intermittent failures](tests/debugging-intermittents.md)
* [Performance tests (DAMP)](tests/performance-tests.md)

Просмотреть файл

@ -0,0 +1,22 @@
# Automated tests: Tips
If you run tests in debug mode, e.g. when debugging memory leaks, the test logs are often dominated by `++DOMWINDOW`, `++DOCSHELL`, `--DOMWINDOW`, `--DOCSHELL` lines.
These lines pollute the test logs making it difficult to find real problems. They also slow down our tests because they are not useful for debugging DevTools issues.
You can add this to your `.zshrc` or `.bashrc` to disable them:
```bash
# Disable those annoying +++DOMWINDOW and +++DOCSHELL printfs from Firefox logs
export MOZ_QUIET=1
```
You can also send `MOZ_QUIET` when you push to try&hellip; it makes the logs easier to read and makes the tests run faster because there is so much less logging.
Example try syntax containing `MOZ_QUIET`:
```
./mach try -b do -p linux,linux64,macosx64,win32,win64 \
-u xpcshell,mochitest-bc,mochitest-e10s-bc,mochitest-dt,mochitest-chrome \
-t damp-e10s --setenv MOZ_QUIET=1
```

Просмотреть файл

@ -30,6 +30,17 @@ const addonTargetSpec = generateActorSpec({
response: RetVal("json"),
},
},
events: {
// The thread actor is no longer emitting newSource event in the name of the target
// actor (bug 1269919), but as we may still connect to older servers which still do,
// we have to keep it being mentioned here. Otherwise the event is considered as a
// response to a request and confuses the packet ordering.
// We can remove that once FF57 is no longer supported.
newSource: {
type: "newSource",
},
},
});
exports.addonTargetSpec = addonTargetSpec;

Просмотреть файл

@ -136,6 +136,15 @@ const browsingContextTargetSpecPrototype = {
workerListChanged: {
type: "workerListChanged",
},
// The thread actor is no longer emitting newSource event in the name of the target
// actor (bug 1269919), but as we may still connect to older servers which still do,
// we have to keep it being mentioned here. Otherwise the event is considered as a
// response to a request and confuses the packet ordering.
// We can remove that once FF57 is no longer supported.
newSource: {
type: "newSource",
},
},
};

Просмотреть файл

@ -24,6 +24,15 @@ const contentProcessTargetSpec = generateActorSpec({
workerListChanged: {
type: "workerListChanged",
},
// The thread actor is no longer emitting newSource event in the name of the target
// actor (bug 1269919), but as we may still connect to older servers which still do,
// we have to keep it being mentioned here. Otherwise the event is considered as a
// response to a request and confuses the packet ordering.
// We can remove that once FF57 is no longer supported.
newSource: {
type: "newSource",
},
},
});

Просмотреть файл

@ -36,6 +36,15 @@ const workerTargetSpec = generateActorSpec({
"worker-close": {
type: "close",
},
// The thread actor is no longer emitting newSource event in the name of the target
// actor (bug 1269919), but as we may still connect to older servers which still do,
// we have to keep it being mentioned here. Otherwise the event is considered as a
// response to a request and confuses the packet ordering.
// We can remove that once FF57 is no longer supported.
newSource: {
type: "newSource",
},
},
});

Просмотреть файл

@ -77,7 +77,7 @@ namespace SessionStoreUtils {
* Returns null when there is no scroll data we want to store for the
* given |frame|.
*/
SSScrollPositionDict collectScrollPosition(Document document);
CollectedData? collectScrollPosition(WindowProxy window);
/**
* Restores scroll position data for any given |frame| in the frame hierarchy.
@ -85,7 +85,7 @@ namespace SessionStoreUtils {
* @param frame (DOMWindow)
* @param value (object, see collectScrollPosition())
*/
void restoreScrollPosition(Window frame, optional SSScrollPositionDict data);
void restoreScrollPosition(Window frame, optional CollectedData data);
/**
* Collect form data for a given |frame| *not* including any subframes.
@ -105,13 +105,12 @@ namespace SessionStoreUtils {
* }
* }
*
* @param doc
* DOMDocument instance to obtain form data for.
* @return object
* Form data encoded in an object.
* Returns null when there is no scroll data
*/
CollectedFormData collectFormData(Document document);
boolean restoreFormData(Document document, optional CollectedFormData data);
CollectedData? collectFormData(WindowProxy window);
boolean restoreFormData(Document document, optional CollectedData data);
/**
* Updates all sessionStorage "super cookies"
@ -135,10 +134,6 @@ namespace SessionStoreUtils {
void restoreSessionStorage(nsIDocShell docShell, record<DOMString, record<DOMString, DOMString>> data);
};
dictionary SSScrollPositionDict {
ByteString scroll;
};
dictionary CollectedFileListValue
{
required DOMString type;
@ -154,10 +149,13 @@ dictionary CollectedNonMultipleSelectValue
// object contains either a CollectedFileListValue or a CollectedNonMultipleSelectValue or Sequence<DOMString>
typedef (DOMString or boolean or object) CollectedFormDataValue;
dictionary CollectedFormData
dictionary CollectedData
{
ByteString scroll;
record<DOMString, CollectedFormDataValue> id;
record<DOMString, CollectedFormDataValue> xpath;
DOMString innerHTML;
ByteString url;
// mChildren contains CollectedData instances
sequence<object?> children;
};

Просмотреть файл

@ -1979,6 +1979,10 @@ bool nsGenericHTMLFormElement::IsElementDisabledForEvents(WidgetEvent* aEvent,
case ePointerOut:
case ePointerEnter:
case ePointerLeave:
case eTransitionCancel:
case eTransitionEnd:
case eTransitionRun:
case eTransitionStart:
case eWheel:
case eLegacyMouseLineOrPageScroll:
case eLegacyMousePixelScroll:

Просмотреть файл

@ -67,14 +67,15 @@ bool AudioData::AdjustForStartTime(int64_t aStartTime) {
}
bool AudioData::SetTrimWindow(const media::TimeInterval& aTrim) {
MOZ_DIAGNOSTIC_ASSERT(aTrim.mStart.IsValid() && aTrim.mEnd.IsValid(),
"An overflow occurred on the provided TimeInterval");
if (!mAudioData) {
// MoveableData got called. Can no longer work on it.
return false;
}
const size_t originalFrames = mAudioData.Length() / mChannels;
const TimeUnit originalDuration = FramesToTimeUnit(originalFrames, mRate);
if (!aTrim.mStart.IsValid() || !aTrim.mEnd.IsValid() ||
aTrim.mStart < mOriginalTime ||
if (aTrim.mStart < mOriginalTime ||
aTrim.mEnd > mOriginalTime + originalDuration) {
return false;
}

Просмотреть файл

@ -409,7 +409,10 @@ Index::Index(const IndiceWrapper& aIndices, ByteStream* aSource,
if (!haveSync) {
continue;
}
if (indice.start_composition == indice.end_composition) {
// Ignore this sample as it doesn't account for the buffered range.
continue;
}
Sample sample;
sample.mByteRange =
MediaByteRange(indice.start_offset, indice.end_offset);

Просмотреть файл

@ -142,9 +142,9 @@ function runTest() {
}
var isMac = ("nsILocalFileMac" in SpecialPowers.Ci);
if (isMac)
if (isMac) {
SimpleTest.waitForFocus(runTest);
else {
} else {
// This test is not yet supported on non-Mac platforms, see bug 574005.
todo(false, "Test not supported on this platform");
SimpleTest.finish();

Просмотреть файл

@ -539,9 +539,9 @@ var tests = [
function doNextTest() {
/* global testCounter:true */
if (typeof testCounter == "undefined")
if (typeof testCounter == "undefined") {
testCounter = 0;
else if (++testCounter == tests.length) {
} else if (++testCounter == tests.length) {
SimpleTest.finish();
return;
}
@ -561,8 +561,9 @@ function runTest(test) {
if ("isIFrame" in test) {
elem.contentDocument.designMode = "on";
elem.contentWindow.focus();
} else
} else {
elem.focus();
}
var trans = SpecialPowers.Cc["@mozilla.org/widget/transferable;1"]
.createInstance(SpecialPowers.Ci.nsITransferable);

Просмотреть файл

@ -1468,6 +1468,7 @@ nsEventStatus APZCTreeManager::ReceiveInputEvent(
break;
}
case KEYBOARD_INPUT: {
aEvent.mLayersId = mFocusState.GetFocusLayersId();
// Disable async keyboard scrolling when accessibility.browsewithcaret is
// enabled
if (!gfxPrefs::APZKeyboardEnabled() ||

Просмотреть файл

@ -184,6 +184,7 @@ nsEventStatus APZInputBridge::ReceiveInputEvent(
keyboardEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
keyboardEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
aEvent.mLayersId = input.mLayersId;
return status;
}
default: {

Просмотреть файл

@ -220,5 +220,11 @@ bool FocusState::CanIgnoreKeyboardShortcutMisses() const {
return IsCurrent(lock) && !mFocusHasKeyEventListeners;
}
LayersId FocusState::GetFocusLayersId() const {
MutexAutoLock lock(mMutex);
return mFocusLayersId;
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -125,6 +125,8 @@ class FocusState final {
*/
bool CanIgnoreKeyboardShortcutMisses() const;
LayersId GetFocusLayersId() const;
private:
/**
* Whether the current focus state is known to be current or else if an event

Просмотреть файл

@ -23,10 +23,10 @@ function ArrayIndexOf(searchElement/*, fromIndex*/) {
var k;
/* Step 7. */
if (n >= 0)
if (n >= 0) {
k = n;
/* Step 8. */
else {
} else {
/* Step a. */
k = len + n;
/* Step b. */

Просмотреть файл

@ -1939,8 +1939,7 @@ bool ASTSerializer::variableDeclarator(ParseNode* pn, MutableHandleValue dst) {
if (pn->isKind(ParseNodeKind::Name)) {
patternNode = pn;
initNode = pn->as<NameNode>().initializer();
MOZ_ASSERT_IF(initNode, pn->pn_pos.encloses(initNode->pn_pos));
initNode = nullptr;
} else if (pn->isKind(ParseNodeKind::AssignExpr)) {
AssignmentNode* assignNode = &pn->as<AssignmentNode>();
patternNode = assignNode->left();

Просмотреть файл

@ -2629,7 +2629,11 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerGetter(
ListNode* body;
MOZ_TRY(parseGetterContents(length, &params, &body));
MOZ_TRY(prependDirectivesToBody(body, directives));
BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body));
BINJS_TRY_DECL(lexicalScopeData,
NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
BINJS_MOZ_TRY_DECL(method,
buildFunction(start, kind, name, params, bodyScope));
BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
name, method, accessorType));
return result;
@ -2691,7 +2695,11 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerMethod(
ListNode* body;
MOZ_TRY(parseFunctionOrMethodContents(length, &params, &body));
MOZ_TRY(prependDirectivesToBody(body, directives));
BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body));
BINJS_TRY_DECL(lexicalScopeData,
NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
BINJS_MOZ_TRY_DECL(method,
buildFunction(start, kind, name, params, bodyScope));
BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
name, method, accessorType));
return result;
@ -2746,7 +2754,11 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceEagerSetter(
ListNode* body;
MOZ_TRY(parseSetterContents(length, &params, &body));
MOZ_TRY(prependDirectivesToBody(body, directives));
BINJS_MOZ_TRY_DECL(method, buildFunction(start, kind, name, params, body));
BINJS_TRY_DECL(lexicalScopeData,
NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
BINJS_TRY_DECL(bodyScope, handler_.newLexicalScope(*lexicalScopeData, body));
BINJS_MOZ_TRY_DECL(method,
buildFunction(start, kind, name, params, bodyScope));
BINJS_TRY_DECL(result, handler_.newObjectMethodOrPropertyDefinition(
name, method, accessorType));
return result;
@ -4244,9 +4256,11 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceVariableDeclarator(
// `var foo [= bar]``
NameNode* bindingNameNode = &binding->template as<NameNode>();
MOZ_TRY(checkBinding(bindingNameNode->atom()->asPropertyName()));
result = bindingNameNode;
if (init) {
BINJS_TRY(handler_.finishInitializerAssignment(bindingNameNode, init));
BINJS_TRY_VAR(
result, handler_.finishInitializerAssignment(bindingNameNode, init));
} else {
result = bindingNameNode;
}
} else {
// `var pattern = bar`

Просмотреть файл

@ -1006,8 +1006,12 @@ EagerMethod:
const auto accessorType = AccessorType::None;
inherits: EagerFunctionExpression
build: |
BINJS_TRY_DECL(lexicalScopeData,
NewLexicalScopeData(cx_, lexicalScope, alloc_, pc_));
BINJS_TRY_DECL(bodyScope,
handler_.newLexicalScope(*lexicalScopeData, body));
BINJS_MOZ_TRY_DECL(method,
buildFunction(start, kind, name, params, body));
buildFunction(start, kind, name, params, bodyScope));
BINJS_TRY_DECL(result,
handler_.newObjectMethodOrPropertyDefinition(name, method,
accessorType));
@ -1603,9 +1607,11 @@ VariableDeclarator:
// `var foo [= bar]``
NameNode* bindingNameNode = &binding->template as<NameNode>();
MOZ_TRY(checkBinding(bindingNameNode->atom()->asPropertyName()));
result = bindingNameNode;
if (init) {
BINJS_TRY(handler_.finishInitializerAssignment(bindingNameNode, init));
BINJS_TRY_VAR(result,
handler_.finishInitializerAssignment(bindingNameNode, init));
} else {
result = bindingNameNode;
}
} else {
// `var pattern = bar`

Просмотреть файл

@ -4025,36 +4025,49 @@ bool BytecodeEmitter::emitDeclarationList(ListNode* declList) {
MOZ_ASSERT(declList->isOp(JSOP_NOP));
for (ParseNode* decl : declList->contents()) {
if (decl->isKind(ParseNodeKind::AssignExpr)) {
ParseNode* pattern;
ParseNode* initializer;
if (decl->isKind(ParseNodeKind::Name)) {
pattern = decl;
initializer = nullptr;
} else {
MOZ_ASSERT(decl->isOp(JSOP_NOP));
AssignmentNode* assignNode = &decl->as<AssignmentNode>();
ListNode* pattern = &assignNode->left()->as<ListNode>();
pattern = assignNode->left();
initializer = assignNode->right();
}
if (pattern->isKind(ParseNodeKind::Name)) {
// initializer can be null here.
if (!emitSingleDeclaration(declList, &pattern->as<NameNode>(),
initializer)) {
return false;
}
} else {
MOZ_ASSERT(decl->isOp(JSOP_NOP));
MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr) ||
pattern->isKind(ParseNodeKind::ObjectExpr));
MOZ_ASSERT(initializer != nullptr);
if (!updateSourceCoordNotes(assignNode->right()->pn_pos.begin)) {
if (!updateSourceCoordNotes(initializer->pn_pos.begin)) {
return false;
}
if (!markStepBreakpoint()) {
return false;
}
if (!emitTree(assignNode->right())) {
if (!emitTree(initializer)) {
return false;
}
if (!emitDestructuringOps(pattern, DestructuringDeclaration)) {
if (!emitDestructuringOps(&pattern->as<ListNode>(),
DestructuringDeclaration)) {
return false;
}
if (!emit1(JSOP_POP)) {
return false;
}
} else {
NameNode* name = &decl->as<NameNode>();
if (!emitSingleDeclaration(declList, name, name->initializer())) {
return false;
}
}
}
return true;
@ -5306,8 +5319,17 @@ bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
target = parser->astGenerator().singleBindingFromDeclaration(
&target->as<ListNode>());
NameNode* nameNode = nullptr;
if (target->isKind(ParseNodeKind::Name)) {
NameNode* nameNode = &target->as<NameNode>();
nameNode = &target->as<NameNode>();
} else if (target->isKind(ParseNodeKind::AssignExpr)) {
AssignmentNode* assignNode = &target->as<AssignmentNode>();
if (assignNode->left()->is<NameNode>()) {
nameNode = &assignNode->left()->as<NameNode>();
}
}
if (nameNode) {
NameOpEmitter noe(this, nameNode->name(), NameOpEmitter::Kind::Initialize);
if (!noe.prepareForRhs()) {
return false;
@ -5440,8 +5462,11 @@ bool BytecodeEmitter::emitForIn(ForNode* forInLoop,
if (parser->astGenerator().isDeclarationList(forInTarget)) {
ParseNode* decl = parser->astGenerator().singleBindingFromDeclaration(
&forInTarget->as<ListNode>());
if (decl->isKind(ParseNodeKind::Name)) {
if (ParseNode* initializer = decl->as<NameNode>().initializer()) {
if (decl->isKind(ParseNodeKind::AssignExpr)) {
AssignmentNode* assignNode = &decl->as<AssignmentNode>();
if (assignNode->left()->is<NameNode>()) {
NameNode* nameNode = &assignNode->left()->as<NameNode>();
ParseNode* initializer = assignNode->right();
MOZ_ASSERT(
forInTarget->isKind(ParseNodeKind::VarStmt),
"for-in initializers are only permitted for |var| declarations");
@ -5450,13 +5475,12 @@ bool BytecodeEmitter::emitForIn(ForNode* forInLoop,
return false;
}
NameNode* nameNode = &decl->as<NameNode>();
NameOpEmitter noe(this, nameNode->name(),
NameOpEmitter::Kind::Initialize);
if (!noe.prepareForRhs()) {
return false;
}
if (!emitInitializer(initializer, decl)) {
if (!emitInitializer(initializer, nameNode)) {
return false;
}
if (!noe.emitAssignment()) {

Просмотреть файл

@ -879,8 +879,15 @@ class FullParseHandler {
node->isKind(ParseNodeKind::ComputedName);
}
inline MOZ_MUST_USE bool finishInitializerAssignment(NameNodeType nameNode,
Node init);
AssignmentNodeType finishInitializerAssignment(NameNodeType nameNode,
Node init) {
MOZ_ASSERT(nameNode->isKind(ParseNodeKind::Name));
MOZ_ASSERT(!nameNode->isInParens());
checkAndSetIsDirectRHSAnonFunction(init);
return newAssignment(ParseNodeKind::AssignExpr, nameNode, init);
}
void setBeginPosition(Node pn, Node oth) {
setBeginPosition(pn, oth->pn_pos.begin);
@ -1027,21 +1034,6 @@ inline bool FullParseHandler::setLastFunctionFormalParameterDefault(
return true;
}
inline bool FullParseHandler::finishInitializerAssignment(NameNodeType nameNode,
Node init) {
MOZ_ASSERT(nameNode->isKind(ParseNodeKind::Name));
MOZ_ASSERT(!nameNode->isInParens());
checkAndSetIsDirectRHSAnonFunction(init);
nameNode->setInitializer(init);
nameNode->setOp(JSOP_SETNAME);
/* The declarator's position must include the initializer. */
nameNode->pn_pos.end = init->pn_pos.end;
return true;
}
} // namespace frontend
} // namespace js

Просмотреть файл

@ -419,9 +419,7 @@ class NameResolver : public ParseNodeVisitor<NameResolver> {
MOZ_ASSERT(spec->isKind(isImport ? ParseNodeKind::ImportSpec
: ParseNodeKind::ExportSpec));
MOZ_ASSERT(spec->left()->isKind(ParseNodeKind::Name));
MOZ_ASSERT(!spec->left()->as<NameNode>().initializer());
MOZ_ASSERT(spec->right()->isKind(ParseNodeKind::Name));
MOZ_ASSERT(!spec->right()->as<NameNode>().initializer());
}
}
#endif

Просмотреть файл

@ -311,12 +311,8 @@ void NameNode::dumpImpl(GenericPrinter& out, int indent) {
out.put("#<null name>");
} else if (getOp() == JSOP_GETARG && atom()->length() == 0) {
// Dump destructuring parameter.
static const char ZeroLengthPrefix[] = "(#<zero-length name> ";
constexpr size_t ZeroLengthPrefixLength =
ArrayLength(ZeroLengthPrefix) - 1;
out.put(ZeroLengthPrefix);
DumpParseTree(initializer(), out, indent + ZeroLengthPrefixLength);
out.printf(")");
static const char ZeroLengthName[] = "(#<zero-length name>)";
out.put(ZeroLengthName);
} else {
JS::AutoCheckCannotGC nogc;
if (atom()->hasLatin1Chars()) {
@ -328,26 +324,28 @@ void NameNode::dumpImpl(GenericPrinter& out, int indent) {
return;
case ParseNodeKind::LabelStmt: {
const char* name = parseNodeNames[size_t(getKind())];
out.printf("(%s ", name);
atom()->dumpCharsNoNewline(out);
indent += strlen(name) + atom()->length() + 2;
DumpParseTree(initializer(), out, indent);
out.printf(")");
this->as<LabeledStatement>().dumpImpl(out, indent);
return;
}
default: {
const char* name = parseNodeNames[size_t(getKind())];
out.printf("(%s ", name);
indent += strlen(name) + 2;
DumpParseTree(initializer(), out, indent);
out.printf(")");
out.printf("(%s)", name);
return;
}
}
}
void LabeledStatement::dumpImpl(GenericPrinter& out, int indent) {
const char* name = parseNodeNames[size_t(getKind())];
out.printf("(%s ", name);
atom()->dumpCharsNoNewline(out);
out.printf(" ");
indent += strlen(name) + atom()->length() + 3;
DumpParseTree(statement(), out, indent);
out.printf(")");
}
void LexicalScopeNode::dumpImpl(GenericPrinter& out, int indent) {
const char* name = parseNodeNames[size_t(getKind())];
out.printf("(%s [", name);

Просмотреть файл

@ -796,20 +796,11 @@ class NullaryNode : public ParseNode {
};
class NameNode : public ParseNode {
JSAtom* atom_; /* lexical name or label atom */
ParseNode* initOrStmt; /* var initializer, argument default, or label
statement target */
protected:
NameNode(ParseNodeKind kind, JSOp op, JSAtom* atom, ParseNode* initOrStmt,
const TokenPos& pos)
: ParseNode(kind, op, pos), atom_(atom), initOrStmt(initOrStmt) {
MOZ_ASSERT(is<NameNode>());
}
JSAtom* atom_; /* lexical name or label atom */
public:
NameNode(ParseNodeKind kind, JSOp op, JSAtom* atom, const TokenPos& pos)
: ParseNode(kind, op, pos), atom_(atom), initOrStmt(nullptr) {
: ParseNode(kind, op, pos), atom_(atom) {
MOZ_ASSERT(is<NameNode>());
}
@ -821,11 +812,6 @@ class NameNode : public ParseNode {
template <typename Visitor>
bool accept(Visitor& visitor) {
if (initOrStmt) {
if (!visitor.visit(initOrStmt)) {
return false;
}
}
return true;
}
@ -840,11 +826,7 @@ class NameNode : public ParseNode {
return atom()->asPropertyName();
}
ParseNode* initializer() const { return initOrStmt; }
void setAtom(JSAtom* atom) { atom_ = atom; }
void setInitializer(ParseNode* init) { initOrStmt = init; }
};
inline bool ParseNode::isName(PropertyName* name) const {
@ -1596,18 +1578,35 @@ class LexicalScopeNode : public ParseNode {
};
class LabeledStatement : public NameNode {
ParseNode* statement_;
public:
LabeledStatement(PropertyName* label, ParseNode* stmt, uint32_t begin)
: NameNode(ParseNodeKind::LabelStmt, JSOP_NOP, label, stmt,
TokenPos(begin, stmt->pn_pos.end)) {}
: NameNode(ParseNodeKind::LabelStmt, JSOP_NOP, label,
TokenPos(begin, stmt->pn_pos.end)),
statement_(stmt) {}
PropertyName* label() const { return atom()->asPropertyName(); }
ParseNode* statement() const { return initializer(); }
ParseNode* statement() const { return statement_; }
static bool test(const ParseNode& node) {
return node.isKind(ParseNodeKind::LabelStmt);
}
template <typename Visitor>
bool accept(Visitor& visitor) {
if (statement_) {
if (!visitor.visit(statement_)) {
return false;
}
}
return true;
}
#ifdef DEBUG
void dumpImpl(GenericPrinter& out, int indent);
#endif
};
// Inside a switch statement, a CaseClause is a case-label and the subsequent

Просмотреть файл

@ -4097,7 +4097,8 @@ GeneralParser<ParseHandler, Unit>::declarationPattern(
}
template <class ParseHandler, typename Unit>
bool GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(
typename ParseHandler::Node
GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(
NameNodeType binding, DeclarationKind declKind, bool initialDeclaration,
YieldHandling yieldHandling, ParseNodeKind* forHeadKind,
Node* forInOrOfExpression) {
@ -4105,19 +4106,19 @@ bool GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(
uint32_t initializerOffset;
if (!tokenStream.peekOffset(&initializerOffset, TokenStream::Operand)) {
return false;
return null();
}
Node initializer = assignExpr(forHeadKind ? InProhibited : InAllowed,
yieldHandling, TripledotProhibited);
if (!initializer) {
return false;
return null();
}
if (forHeadKind && initialDeclaration) {
bool isForIn, isForOf;
if (!matchInOrOf(&isForIn, &isForOf)) {
return false;
return null();
}
// An initialized declaration can't appear in a for-of:
@ -4125,7 +4126,7 @@ bool GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(
// for (var/let/const x = ... of ...); // BAD
if (isForOf) {
errorAt(initializerOffset, JSMSG_OF_AFTER_FOR_LOOP_DECL);
return false;
return null();
}
if (isForIn) {
@ -4134,7 +4135,7 @@ bool GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(
// for (let/const x = ... in ...); // BAD
if (DeclarationKindIsLexical(declKind)) {
errorAt(initializerOffset, JSMSG_IN_AFTER_LEXICAL_FOR_DECL);
return false;
return null();
}
// This leaves only initialized for-in |var| declarations. ES6
@ -4142,13 +4143,13 @@ bool GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(
*forHeadKind = ParseNodeKind::ForIn;
if (!strictModeErrorAt(initializerOffset,
JSMSG_INVALID_FOR_IN_DECL_WITH_INIT)) {
return false;
return null();
}
*forInOrOfExpression =
expressionAfterForInOrOf(ParseNodeKind::ForIn, yieldHandling);
if (!*forInOrOfExpression) {
return false;
return null();
}
} else {
*forHeadKind = ParseNodeKind::ForHead;
@ -4159,13 +4160,10 @@ bool GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(
}
template <class ParseHandler, typename Unit>
typename ParseHandler::NameNodeType
GeneralParser<ParseHandler, Unit>::declarationName(DeclarationKind declKind,
TokenKind tt,
bool initialDeclaration,
YieldHandling yieldHandling,
ParseNodeKind* forHeadKind,
Node* forInOrOfExpression) {
typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::declarationName(
DeclarationKind declKind, TokenKind tt, bool initialDeclaration,
YieldHandling yieldHandling, ParseNodeKind* forHeadKind,
Node* forInOrOfExpression) {
// Anything other than possible identifier is an error.
if (!TokenKindIsPossibleIdentifier(tt)) {
error(JSMSG_NO_VARIABLE_NAME);
@ -4197,13 +4195,17 @@ GeneralParser<ParseHandler, Unit>::declarationName(DeclarationKind declKind,
return null();
}
Node declaration;
if (matched) {
if (!initializerInNameDeclaration(binding, declKind, initialDeclaration,
yieldHandling, forHeadKind,
forInOrOfExpression)) {
declaration = initializerInNameDeclaration(
binding, declKind, initialDeclaration, yieldHandling, forHeadKind,
forInOrOfExpression);
if (!declaration) {
return null();
}
} else {
declaration = binding;
if (initialDeclaration && forHeadKind) {
bool isForIn, isForOf;
if (!matchInOrOf(&isForIn, &isForOf)) {
@ -4241,7 +4243,7 @@ GeneralParser<ParseHandler, Unit>::declarationName(DeclarationKind declKind,
return null();
}
return binding;
return declaration;
}
template <class ParseHandler, typename Unit>

Просмотреть файл

@ -1200,18 +1200,16 @@ class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
bool initialDeclaration, YieldHandling yieldHandling,
ParseNodeKind* forHeadKind,
Node* forInOrOfExpression);
NameNodeType declarationName(DeclarationKind declKind, TokenKind tt,
bool initialDeclaration,
YieldHandling yieldHandling,
ParseNodeKind* forHeadKind,
Node* forInOrOfExpression);
Node declarationName(DeclarationKind declKind, TokenKind tt,
bool initialDeclaration, YieldHandling yieldHandling,
ParseNodeKind* forHeadKind, Node* forInOrOfExpression);
// Having parsed a name (not found in a destructuring pattern) declared by
// a declaration, with the current token being the '=' separating the name
// from its initializer, parse and bind that initializer -- and possibly
// consume trailing in/of and subsequent expression, if so directed by
// |forHeadKind|.
bool initializerInNameDeclaration(NameNodeType binding,
Node initializerInNameDeclaration(NameNodeType binding,
DeclarationKind declKind,
bool initialDeclaration,
YieldHandling yieldHandling,

Просмотреть файл

@ -517,9 +517,9 @@ class SyntaxParseHandler {
return NodeGeneric;
}
MOZ_MUST_USE bool finishInitializerAssignment(NameNodeType nameNode,
Node init) {
return true;
AssignmentNodeType finishInitializerAssignment(NameNodeType nameNode,
Node init) {
return NodeUnparenthesizedAssignment;
}
void setBeginPosition(Node pn, Node oth) {}

Просмотреть файл

@ -31,6 +31,7 @@
#include "jit/BaselineFrameInfo-inl.h"
#include "jit/MacroAssembler-inl.h"
#include "jit/VMFunctionList-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/JSScript-inl.h"
#include "vm/NativeObject-inl.h"
@ -584,10 +585,8 @@ void BaselineInterpreterCodeGen::storeFrameSizeAndPushDescriptor(
}
template <typename Handler>
bool BaselineCodeGen<Handler>::callVM(const VMFunction& fun,
CallVMPhase phase) {
TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
bool BaselineCodeGen<Handler>::callVM(const VMFunctionData& fun,
TrampolinePtr code, CallVMPhase phase) {
#ifdef DEBUG
// Assert prepareVMCall() has been called.
MOZ_ASSERT(inCall_);
@ -665,6 +664,21 @@ bool BaselineCodeGen<Handler>::callVM(const VMFunction& fun,
return handler.appendRetAddrEntry(cx, RetAddrEntry::Kind::CallVM, callOffset);
}
template <typename Handler>
bool BaselineCodeGen<Handler>::callVM(const VMFunction& fun,
CallVMPhase phase) {
TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
return callVM(fun, code, phase);
}
template <typename Handler>
template <typename Fn, Fn fn>
bool BaselineCodeGen<Handler>::callVM(CallVMPhase phase) {
VMFunctionId fnId = VMFunctionToId<Fn, fn>::id;
TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fnId);
return callVM(GetVMFunction(fnId), code, phase);
}
typedef bool (*CheckOverRecursedBaselineFn)(JSContext*, BaselineFrame*);
static const VMFunction CheckOverRecursedBaselineInfo =
FunctionInfo<CheckOverRecursedBaselineFn>(CheckOverRecursedBaseline,
@ -887,10 +901,6 @@ void BaselineInterpreterCodeGen::loadResumeIndexBytecodeOperand(Register dest) {
MOZ_CRASH("NYI: interpreter loadResumeIndexBytecodeOperand");
}
typedef bool (*DebugPrologueFn)(JSContext*, BaselineFrame*, jsbytecode*, bool*);
static const VMFunction DebugPrologueInfo =
FunctionInfo<DebugPrologueFn>(jit::DebugPrologue, "DebugPrologue");
template <typename Handler>
bool BaselineCodeGen<Handler>::emitDebugPrologue() {
auto ifDebuggee = [this]() {
@ -900,7 +910,9 @@ bool BaselineCodeGen<Handler>::emitDebugPrologue() {
prepareVMCall();
pushBytecodePCArg();
pushArg(R0.scratchReg());
if (!callVM(DebugPrologueInfo)) {
using Fn = bool (*)(JSContext*, BaselineFrame*, jsbytecode*, bool*);
if (!callVM<Fn, jit::DebugPrologue>()) {
return false;
}
@ -1009,10 +1021,6 @@ bool BaselineInterpreterCodeGen::initEnvironmentChain() {
MOZ_CRASH("NYI: interpreter initEnvironmentChain");
}
typedef bool (*InterruptCheckFn)(JSContext*);
static const VMFunction InterruptCheckInfo =
FunctionInfo<InterruptCheckFn>(InterruptCheck, "InterruptCheck");
template <typename Handler>
bool BaselineCodeGen<Handler>::emitInterruptCheck() {
frame.syncStack(0);
@ -1022,7 +1030,9 @@ bool BaselineCodeGen<Handler>::emitInterruptCheck() {
Imm32(0), &done);
prepareVMCall();
if (!callVM(InterruptCheckInfo)) {
using Fn = bool (*)(JSContext*);
if (!callVM<Fn, InterruptCheck>()) {
return false;
}
@ -1030,12 +1040,6 @@ bool BaselineCodeGen<Handler>::emitInterruptCheck() {
return true;
}
typedef bool (*IonCompileScriptForBaselineFn)(JSContext*, BaselineFrame*,
jsbytecode*);
static const VMFunction IonCompileScriptForBaselineInfo =
FunctionInfo<IonCompileScriptForBaselineFn>(IonCompileScriptForBaseline,
"IonCompileScriptForBaseline");
template <>
bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() {
// Emit no warm-up counter increments or bailouts if Ion is not
@ -1099,7 +1103,8 @@ bool BaselineCompilerCodeGen::emitWarmUpCounterIncrement() {
pushBytecodePCArg();
masm.PushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
if (!callVM(IonCompileScriptForBaselineInfo)) {
using Fn = bool (*)(JSContext*, BaselineFrame*, jsbytecode*);
if (!callVM<Fn, IonCompileScriptForBaseline>()) {
return false;
}
@ -1782,11 +1787,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_NULL() {
return true;
}
typedef bool (*ThrowCheckIsObjectFn)(JSContext*, CheckIsObjectKind);
static const VMFunction ThrowCheckIsObjectInfo =
FunctionInfo<ThrowCheckIsObjectFn>(ThrowCheckIsObject,
"ThrowCheckIsObject");
template <typename Handler>
bool BaselineCodeGen<Handler>::emit_JSOP_CHECKISOBJ() {
frame.syncStack(0);
@ -1798,7 +1798,9 @@ bool BaselineCodeGen<Handler>::emit_JSOP_CHECKISOBJ() {
prepareVMCall();
pushUint8BytecodeOperandArg();
if (!callVM(ThrowCheckIsObjectInfo)) {
using Fn = bool (*)(JSContext*, CheckIsObjectKind);
if (!callVM<Fn, ThrowCheckIsObject>()) {
return false;
}
@ -1806,10 +1808,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_CHECKISOBJ() {
return true;
}
typedef bool (*CheckIsCallableFn)(JSContext*, HandleValue, CheckIsCallableKind);
static const VMFunction CheckIsCallableInfo =
FunctionInfo<CheckIsCallableFn>(CheckIsCallable, "CheckIsCallable");
template <typename Handler>
bool BaselineCodeGen<Handler>::emit_JSOP_CHECKISCALLABLE() {
frame.syncStack(0);
@ -1819,23 +1817,15 @@ bool BaselineCodeGen<Handler>::emit_JSOP_CHECKISCALLABLE() {
pushUint8BytecodeOperandArg();
pushArg(R0);
if (!callVM(CheckIsCallableInfo)) {
using Fn = bool (*)(JSContext*, HandleValue, CheckIsCallableKind);
if (!callVM<Fn, CheckIsCallable>()) {
return false;
}
return true;
}
typedef bool (*ThrowUninitializedThisFn)(JSContext*, BaselineFrame* frame);
static const VMFunction ThrowUninitializedThisInfo =
FunctionInfo<ThrowUninitializedThisFn>(BaselineThrowUninitializedThis,
"BaselineThrowUninitializedThis");
typedef bool (*ThrowInitializedThisFn)(JSContext*);
static const VMFunction ThrowInitializedThisInfo =
FunctionInfo<ThrowInitializedThisFn>(BaselineThrowInitializedThis,
"BaselineThrowInitializedThis");
template <typename Handler>
bool BaselineCodeGen<Handler>::emit_JSOP_CHECKTHIS() {
frame.syncStack(0);
@ -1864,14 +1854,16 @@ bool BaselineCodeGen<Handler>::emitCheckThis(ValueOperand val, bool reinit) {
prepareVMCall();
if (reinit) {
if (!callVM(ThrowInitializedThisInfo)) {
using Fn = bool (*)(JSContext*);
if (!callVM<Fn, BaselineThrowInitializedThis>()) {
return false;
}
} else {
masm.loadBaselineFramePtr(BaselineFrameReg, val.scratchReg());
pushArg(val.scratchReg());
if (!callVM(ThrowUninitializedThisInfo)) {
using Fn = bool (*)(JSContext*, BaselineFrame*);
if (!callVM<Fn, BaselineThrowUninitializedThis>()) {
return false;
}
}
@ -1880,11 +1872,6 @@ bool BaselineCodeGen<Handler>::emitCheckThis(ValueOperand val, bool reinit) {
return true;
}
typedef bool (*ThrowBadDerivedReturnFn)(JSContext*, HandleValue);
static const VMFunction ThrowBadDerivedReturnInfo =
FunctionInfo<ThrowBadDerivedReturnFn>(jit::ThrowBadDerivedReturn,
"ThrowBadDerivedReturn");
template <typename Handler>
bool BaselineCodeGen<Handler>::emit_JSOP_CHECKRETURN() {
MOZ_ASSERT_IF(handler.maybeScript(),
@ -1900,7 +1887,9 @@ bool BaselineCodeGen<Handler>::emit_JSOP_CHECKRETURN() {
prepareVMCall();
pushArg(R1);
if (!callVM(ThrowBadDerivedReturnInfo)) {
using Fn = bool (*)(JSContext*, HandleValue);
if (!callVM<Fn, ThrowBadDerivedReturn>()) {
return false;
}
masm.assumeUnreachable("Should throw on bad derived constructor return");
@ -1919,11 +1908,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_CHECKRETURN() {
return true;
}
typedef bool (*GetFunctionThisFn)(JSContext*, BaselineFrame*,
MutableHandleValue);
static const VMFunction GetFunctionThisInfo = FunctionInfo<GetFunctionThisFn>(
jit::BaselineGetFunctionThis, "BaselineGetFunctionThis");
template <typename Handler>
bool BaselineCodeGen<Handler>::emit_JSOP_FUNCTIONTHIS() {
MOZ_ASSERT_IF(handler.maybeFunction(), !handler.maybeFunction()->isArrow());
@ -1941,7 +1925,8 @@ bool BaselineCodeGen<Handler>::emit_JSOP_FUNCTIONTHIS() {
pushArg(R1.scratchReg());
if (!callVM(GetFunctionThisInfo)) {
using Fn = bool (*)(JSContext*, BaselineFrame*, MutableHandleValue);
if (!callVM<Fn, BaselineGetFunctionThis>()) {
return false;
}
@ -1955,12 +1940,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_FUNCTIONTHIS() {
R2.scratchReg());
}
typedef void (*GetNonSyntacticGlobalThisFn)(JSContext*, HandleObject,
MutableHandleValue);
static const VMFunction GetNonSyntacticGlobalThisInfo =
FunctionInfo<GetNonSyntacticGlobalThisFn>(js::GetNonSyntacticGlobalThis,
"GetNonSyntacticGlobalThis");
template <typename Handler>
bool BaselineCodeGen<Handler>::emit_JSOP_GLOBALTHIS() {
frame.syncStack(0);
@ -1971,7 +1950,8 @@ bool BaselineCodeGen<Handler>::emit_JSOP_GLOBALTHIS() {
masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
pushArg(R0.scratchReg());
if (!callVM(GetNonSyntacticGlobalThisInfo)) {
using Fn = void (*)(JSContext*, HandleObject, MutableHandleValue);
if (!callVM<Fn, GetNonSyntacticGlobalThis>()) {
return false;
}

Просмотреть файл

@ -346,8 +346,13 @@ class BaselineCodeGen {
Register scratch1, Register scratch2);
enum CallVMPhase { POST_INITIALIZE, CHECK_OVER_RECURSED };
bool callVM(const VMFunctionData& fun, TrampolinePtr code,
CallVMPhase phase = POST_INITIALIZE);
bool callVM(const VMFunction& fun, CallVMPhase phase = POST_INITIALIZE);
template <typename Fn, Fn fn>
bool callVM(CallVMPhase phase = POST_INITIALIZE);
bool callVMNonOp(const VMFunction& fun, CallVMPhase phase = POST_INITIALIZE) {
if (!callVM(fun, phase)) {
return false;

Просмотреть файл

@ -8912,8 +8912,8 @@ void JitRuntime::generateDoubleToInt32ValueStub(MacroAssembler& masm) {
masm.abiret();
}
bool JitRuntime::generateTLEventVM(MacroAssembler& masm, const VMFunction& f,
bool enter) {
bool JitRuntime::generateTLEventVM(MacroAssembler& masm,
const VMFunctionData& f, bool enter) {
#ifdef JS_TRACE_LOGGING
bool vmEventEnabled = TraceLogTextIdEnabled(TraceLogger_VM);
bool vmSpecificEventEnabled = TraceLogTextIdEnabled(TraceLogger_VMSpecific);

Просмотреть файл

@ -286,13 +286,22 @@ bool JitRuntime::initialize(JSContext* cx) {
generateDoubleToInt32ValueStub(masm);
JitSpew(JitSpew_Codegen, "# Emitting VM function wrappers");
if (!generateVMWrappers(cx, masm)) {
return false;
}
// TODO(bug 1530937): remove this after converting all VM functions.
for (VMFunction* fun = VMFunction::functions; fun; fun = fun->next) {
if (functionWrappers_->has(fun)) {
// Duplicate VMFunction definition. See VMFunction::hash.
continue;
}
JitSpew(JitSpew_Codegen, "# VM function wrapper (%s)", fun->name());
if (!generateVMWrapper(cx, masm, *fun)) {
uint32_t offset;
if (!generateVMWrapper(cx, masm, *fun, &offset)) {
return false;
}
if (!functionWrappers_->putNew(fun, offset)) {
return false;
}
}

Просмотреть файл

@ -1022,7 +1022,8 @@ uint8_t* alignDoubleSpillWithOffset(uint8_t* pointer, int32_t offset) {
return reinterpret_cast<uint8_t*>(address);
}
static void TraceJitExitFrameCopiedArguments(JSTracer* trc, const VMFunction* f,
static void TraceJitExitFrameCopiedArguments(JSTracer* trc,
const VMFunctionData* f,
ExitFooterFrame* footer) {
uint8_t* doubleArgs = reinterpret_cast<uint8_t*>(footer);
doubleArgs = alignDoubleSpillWithOffset(doubleArgs, sizeof(intptr_t));
@ -1044,7 +1045,8 @@ static void TraceJitExitFrameCopiedArguments(JSTracer* trc, const VMFunction* f,
}
}
#else
static void TraceJitExitFrameCopiedArguments(JSTracer* trc, const VMFunction* f,
static void TraceJitExitFrameCopiedArguments(JSTracer* trc,
const VMFunctionData* f,
ExitFooterFrame* footer) {
// This is NO-OP on other platforms.
}
@ -1127,7 +1129,7 @@ static void TraceJitExitFrame(JSTracer* trc, const JSJitFrameIter& frame) {
MOZ_ASSERT(frame.exitFrame()->isWrapperExit());
const VMFunction* f = footer->function();
const VMFunctionData* f = footer->function();
MOZ_ASSERT(f);
// Trace arguments of the VM wrapper.

Просмотреть файл

@ -17,6 +17,7 @@ namespace js {
namespace jit {
struct SafepointSlotEntry;
struct VMFunctionData;
enum CalleeTokenTag {
CalleeToken_Function = 0x0, // untagged
@ -418,7 +419,7 @@ enum class ExitFrameType : uint8_t {
// GC related data used to keep alive data surrounding the Exit frame.
class ExitFooterFrame {
// Stores the ExitFrameType or, for ExitFrameType::VMFunction, the
// VMFunction*.
// VMFunctionData*.
uintptr_t data_;
public:
@ -433,9 +434,9 @@ class ExitFooterFrame {
MOZ_ASSERT(ExitFrameType(data_) != ExitFrameType::VMFunction);
return ExitFrameType(data_);
}
inline const VMFunction* function() const {
inline const VMFunctionData* function() const {
MOZ_ASSERT(type() == ExitFrameType::VMFunction);
return reinterpret_cast<const VMFunction*>(data_);
return reinterpret_cast<const VMFunctionData*>(data_);
}
// This should only be called for function()->outParam == Type_Handle

Просмотреть файл

@ -28,6 +28,8 @@ namespace js {
namespace jit {
class FrameSizeClass;
struct VMFunctionData;
enum class VMFunctionId;
struct EnterJitData {
explicit EnterJitData(JSContext* cx)
@ -143,6 +145,10 @@ class JitRuntime {
using VMWrapperMap = HashMap<const VMFunction*, uint32_t, VMFunction>;
WriteOnceData<VMWrapperMap*> functionWrappers_;
// Maps VMFunctionId to the offset of the wrapper code in trampolineCode_.
using VMWrapperOffsets = Vector<uint32_t, 0, SystemAllocPolicy>;
VMWrapperOffsets functionWrapperOffsets_;
// Global table of jitcode native address => bytecode address mappings.
UnprotectedData<JitcodeGlobalTable*> jitcodeGlobalTable_;
@ -190,15 +196,18 @@ class JitRuntime {
JitCode* generateDebugTrapHandler(JSContext* cx);
JitCode* generateBaselineDebugModeOSRHandler(
JSContext* cx, uint32_t* noFrameRegPopOffsetOut);
bool generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunction& f);
const VMFunctionData& f, uint32_t* wrapperOffset);
bool generateVMWrappers(JSContext* cx, MacroAssembler& masm);
bool generateTLEventVM(MacroAssembler& masm, const VMFunction& f, bool enter);
bool generateTLEventVM(MacroAssembler& masm, const VMFunctionData& f,
bool enter);
inline bool generateTLEnterVM(MacroAssembler& masm, const VMFunction& f) {
inline bool generateTLEnterVM(MacroAssembler& masm, const VMFunctionData& f) {
return generateTLEventVM(masm, f, /* enter = */ true);
}
inline bool generateTLExitVM(MacroAssembler& masm, const VMFunction& f) {
inline bool generateTLExitVM(MacroAssembler& masm, const VMFunctionData& f) {
return generateTLEventVM(masm, f, /* enter = */ false);
}
@ -227,6 +236,12 @@ class JitRuntime {
}
TrampolinePtr getVMWrapper(const VMFunction& f) const;
TrampolinePtr getVMWrapper(const VMFunctionId funId) const {
MOZ_ASSERT(trampolineCode_);
return trampolineCode(functionWrapperOffsets_[size_t(funId)]);
}
JitCode* debugTrapHandler(JSContext* cx);
JitCode* getBaselineDebugModeOSRHandler(JSContext* cx);
void* getBaselineDebugModeOSRHandlerAddress(JSContext* cx, bool popFrameReg);

Просмотреть файл

@ -260,7 +260,7 @@ uint32_t MacroAssembler::buildFakeExitFrame(Register scratch) {
// Exit frame footer.
void MacroAssembler::enterExitFrame(Register cxreg, Register scratch,
const VMFunction* f) {
const VMFunctionData* f) {
MOZ_ASSERT(f);
linkExitFrame(cxreg, scratch);
// Push VMFunction pointer, to mark arguments.

Просмотреть файл

@ -714,9 +714,9 @@ class MacroAssembler : public MacroAssemblerSpecific {
//
// See JitFrames.h, and MarkJitExitFrame in JitFrames.cpp.
// Push stub code and the VMFunction pointer.
// Push stub code and the VMFunctionData pointer.
inline void enterExitFrame(Register cxreg, Register scratch,
const VMFunction* f);
const VMFunctionData* f);
// Push an exit frame token to identify which fake exit frame this footer
// corresponds to.

Просмотреть файл

@ -0,0 +1,69 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* 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/. */
#include "jit/BaselineIC.h"
#include "jit/JitRealm.h"
#include "jit/VMFunctions.h"
#include "vm/Interpreter.h"
#include "jit/BaselineFrame-inl.h"
#include "vm/Interpreter-inl.h"
namespace js {
namespace jit {
// List of all VM functions to be used with callVM. Each entry stores the name
// (must be unique, used for the VMFunctionId enum and profiling) and the C++
// function to be called. This list must be sorted on the name field.
#define VMFUNCTION_LIST(_) \
_(BaselineDebugPrologue, js::jit::DebugPrologue) \
_(BaselineGetFunctionThis, js::jit::BaselineGetFunctionThis) \
_(BaselineThrowInitializedThis, js::jit::BaselineThrowInitializedThis) \
_(BaselineThrowUninitializedThis, js::jit::BaselineThrowUninitializedThis) \
_(CheckIsCallable, js::jit::CheckIsCallable) \
_(CheckOverRecursedBaseline, js::jit::CheckOverRecursedBaseline) \
_(GetNonSyntacticGlobalThis, js::GetNonSyntacticGlobalThis) \
_(InterruptCheck, js::jit::InterruptCheck) \
_(IonCompileScriptForBaseline, js::jit::IonCompileScriptForBaseline) \
_(ThrowBadDerivedReturn, js::jit::ThrowBadDerivedReturn) \
_(ThrowCheckIsObject, js::ThrowCheckIsObject)
enum class VMFunctionId {
#define DEF_ID(name, fp) name,
VMFUNCTION_LIST(DEF_ID)
#undef DEF_ID
Count
};
// Define the VMFunctionToId template to map from signature + function to
// the VMFunctionId. This lets us verify the consumer/codegen code matches
// the C++ signature.
template <typename Function, Function fun>
struct VMFunctionToId; // Error on this line? Forgot to update VMFUNCTION_LIST?
// GCC warns when the signature does not have matching attributes (for example
// MOZ_MUST_USE). Squelch this warning to avoid a GCC-only footgun.
#if MOZ_IS_GCC
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wignored-attributes"
#endif
// Note: the use of ::fp instead of fp is intentional to enforce use of
// fully-qualified names in the list above.
#define DEF_TEMPLATE(name, fp) \
template <> \
struct VMFunctionToId<decltype(&(::fp)), ::fp> { \
static constexpr VMFunctionId id = VMFunctionId::name; \
};
VMFUNCTION_LIST(DEF_TEMPLATE)
#undef DEF_TEMPLATE
#if MOZ_IS_GCC
# pragma GCC diagnostic pop
#endif
} // namespace jit
} // namespace js

Просмотреть файл

@ -24,6 +24,7 @@
#include "jit/BaselineFrame-inl.h"
#include "jit/JitFrames-inl.h"
#include "jit/VMFunctionList-inl.h"
#include "vm/Debugger-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/NativeObject-inl.h"
@ -37,6 +38,113 @@ using namespace js::jit;
namespace js {
namespace jit {
// Helper template to build the VMFunctionData for a function.
template <typename... Args>
struct VMFunctionDataHelper;
template <class R, typename... Args>
struct VMFunctionDataHelper<R (*)(JSContext*, Args...)>
: public VMFunctionData {
using Fun = R (*)(JSContext*, Args...);
static constexpr DataType returnType() { return TypeToDataType<R>::result; }
static constexpr DataType outParam() {
return OutParamToDataType<typename LastArg<Args...>::Type>::result;
}
static constexpr RootType outParamRootType() {
return OutParamToRootType<typename LastArg<Args...>::Type>::result;
}
static constexpr size_t NbArgs() { return LastArg<Args...>::nbArgs; }
static constexpr size_t explicitArgs() {
return NbArgs() - (outParam() != Type_Void ? 1 : 0);
}
static constexpr uint32_t argumentProperties() {
return BitMask<TypeToArgProperties, uint32_t, 2, Args...>::result;
}
static constexpr uint32_t argumentPassedInFloatRegs() {
return BitMask<TypeToPassInFloatReg, uint32_t, 2, Args...>::result;
}
static constexpr uint64_t argumentRootTypes() {
return BitMask<TypeToRootType, uint64_t, 3, Args...>::result;
}
constexpr VMFunctionDataHelper(Fun fun, const char* name,
PopValues extraValuesToPop = PopValues(0))
: VMFunctionData((void*)fun, name, explicitArgs(), argumentProperties(),
argumentPassedInFloatRegs(), argumentRootTypes(),
outParam(), outParamRootType(), returnType(),
extraValuesToPop.numValues, NonTailCall) {}
constexpr VMFunctionDataHelper(Fun fun, const char* name,
MaybeTailCall expectTailCall,
PopValues extraValuesToPop = PopValues(0))
: VMFunctionData((void*)fun, name, explicitArgs(), argumentProperties(),
argumentPassedInFloatRegs(), argumentRootTypes(),
outParam(), outParamRootType(), returnType(),
extraValuesToPop.numValues, expectTailCall) {}
};
// GCC warns when the signature does not have matching attributes (for example
// MOZ_MUST_USE). Squelch this warning to avoid a GCC-only footgun.
#if MOZ_IS_GCC
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wignored-attributes"
#endif
// Generate VMFunctionData array.
static constexpr VMFunctionData vmFunctions[] = {
#define DEF_VMFUNCTION(name, fp) \
VMFunctionDataHelper<decltype(&(::fp))>(::fp, #name),
VMFUNCTION_LIST(DEF_VMFUNCTION)
#undef DEF_VMFUNCTION
};
#if MOZ_IS_GCC
# pragma GCC diagnostic pop
#endif
const VMFunctionData& GetVMFunction(VMFunctionId id) {
return vmFunctions[size_t(id)];
}
bool JitRuntime::generateVMWrappers(JSContext* cx, MacroAssembler& masm) {
// Generate all VM function wrappers.
static constexpr size_t NumVMFunctions = size_t(VMFunctionId::Count);
if (!functionWrapperOffsets_.reserve(NumVMFunctions)) {
return false;
}
#ifdef DEBUG
const char* lastName = nullptr;
#endif
for (size_t i = 0; i < NumVMFunctions; i++) {
VMFunctionId id = VMFunctionId(i);
const VMFunctionData& fun = GetVMFunction(id);
#ifdef DEBUG
// Assert the list is sorted by name.
if (lastName) {
MOZ_ASSERT(strcmp(lastName, fun.name()) < 0,
"VM function list must be sorted by name");
}
lastName = fun.name();
#endif
JitSpew(JitSpew_Codegen, "# VM function wrapper (%s)", fun.name());
uint32_t offset;
if (!generateVMWrapper(cx, masm, fun, &offset)) {
return false;
}
MOZ_ASSERT(functionWrapperOffsets_.length() == size_t(id));
functionWrapperOffsets_.infallibleAppend(offset);
}
return true;
}
// Statics are initialized to null.
/* static */ VMFunction* VMFunction::functions;

Просмотреть файл

@ -55,6 +55,8 @@ enum MaybeTailCall : bool { TailCall, NonTailCall };
// [SMDOC] JIT-to-C++ Function Calls. (callVM)
//
// TODO(bug 1530937): update this comment after converting all VM functions.
//
// Sometimes it is easier to reuse C++ code by calling VM's functions. Calling a
// function from the VM can be achieved with the use of callWithABI but this is
// discouraged when the called functions might trigger exceptions and/or
@ -123,11 +125,9 @@ enum MaybeTailCall : bool { TailCall, NonTailCall };
// }
//
// After this, the result value is in the return value register.
struct VMFunction {
// Global linked list of all VMFunctions.
static VMFunction* functions;
VMFunction* next;
// Data for a VM function. All VMFunctionDatas are stored in a constexpr array.
struct VMFunctionData {
// Address of the C function.
void* wrapped;
@ -293,15 +293,14 @@ struct VMFunction {
return count;
}
constexpr VMFunction(void* wrapped, const char* name, uint32_t explicitArgs,
uint32_t argumentProperties,
uint32_t argumentPassedInFloatRegs,
uint64_t argRootTypes, DataType outParam,
RootType outParamRootType, DataType returnType,
uint8_t extraValuesToPop = 0,
MaybeTailCall expectTailCall = NonTailCall)
: next(nullptr),
wrapped(wrapped),
constexpr VMFunctionData(void* wrapped, const char* name,
uint32_t explicitArgs, uint32_t argumentProperties,
uint32_t argumentPassedInFloatRegs,
uint64_t argRootTypes, DataType outParam,
RootType outParamRootType, DataType returnType,
uint8_t extraValuesToPop = 0,
MaybeTailCall expectTailCall = NonTailCall)
: wrapped(wrapped),
#if defined(JS_JITSPEW) || defined(JS_TRACE_LOGGING)
name_(name),
#endif
@ -314,11 +313,18 @@ struct VMFunction {
returnType(returnType),
extraValuesToPop(extraValuesToPop),
expectTailCall(expectTailCall) {
// Check for valid failure/return type.
MOZ_ASSERT_IF(outParam != Type_Void,
returnType == Type_Void || returnType == Type_Bool);
MOZ_ASSERT(returnType == Type_Void || returnType == Type_Bool ||
returnType == Type_Object);
}
VMFunction(const VMFunction& o)
: next(functions),
wrapped(o.wrapped),
// Note: clang-tidy suggests using |= auto| here but that generates extra
// static initializers for old-style VMFunction definitions with Clang. We can
// do this after bug 1530937 converts all of them.
constexpr VMFunctionData(const VMFunctionData& o)
: wrapped(o.wrapped),
#if defined(JS_JITSPEW) || defined(JS_TRACE_LOGGING)
name_(o.name_),
#endif
@ -331,14 +337,32 @@ struct VMFunction {
returnType(o.returnType),
extraValuesToPop(o.extraValuesToPop),
expectTailCall(o.expectTailCall) {
}
};
// TODO(bug 1530937): remove VMFunction and FunctionInfo after converting all VM
// functions to the new design.
struct VMFunction : public VMFunctionData {
// Global linked list of all VMFunctions.
static VMFunction* functions;
VMFunction* next;
constexpr VMFunction(void* wrapped, const char* name, uint32_t explicitArgs,
uint32_t argumentProperties,
uint32_t argumentPassedInFloatRegs,
uint64_t argRootTypes, DataType outParam,
RootType outParamRootType, DataType returnType,
uint8_t extraValuesToPop = 0,
MaybeTailCall expectTailCall = NonTailCall)
: VMFunctionData(wrapped, name, explicitArgs, argumentProperties,
argumentPassedInFloatRegs, argRootTypes, outParam,
outParamRootType, returnType, extraValuesToPop,
expectTailCall),
next(nullptr) {}
VMFunction(const VMFunction& o) : VMFunctionData(o), next(functions) {
// Add this to the global list of VMFunctions.
functions = this;
// Check for valid failure/return type.
MOZ_ASSERT_IF(outParam != Type_Void,
returnType == Type_Void || returnType == Type_Bool);
MOZ_ASSERT(returnType == Type_Void || returnType == Type_Bool ||
returnType == Type_Object);
}
typedef const VMFunction* Lookup;
@ -781,13 +805,6 @@ struct OutParamToRootType<MutableHandleString> {
static const VMFunction::RootType result = VMFunction::RootString;
};
template <class>
struct MatchContext {};
template <>
struct MatchContext<JSContext*> {
static const bool valid = true;
};
// Extract the last element of a list of types.
template <typename... ArgTypes>
struct LastArg;
@ -844,9 +861,9 @@ struct BitMask<Each, ResultType, Shift, HeadType, TailTypes...> {
template <typename... Args>
struct FunctionInfo;
template <class R, class Context, typename... Args>
struct FunctionInfo<R (*)(Context, Args...)> : public VMFunction {
typedef R (*pf)(Context, Args...);
template <class R, typename... Args>
struct FunctionInfo<R (*)(JSContext*, Args...)> : public VMFunction {
using pf = R (*)(JSContext*, Args...);
static DataType returnType() { return TypeToDataType<R>::result; }
static DataType outParam() {
@ -874,8 +891,6 @@ struct FunctionInfo<R (*)(Context, Args...)> : public VMFunction {
argumentProperties(), argumentPassedInFloatRegs(),
argumentRootTypes(), outParam(), outParamRootType(),
returnType(), extraValuesToPop.numValues, NonTailCall) {
static_assert(MatchContext<Context>::valid,
"Invalid cx type in VMFunction");
}
explicit FunctionInfo(pf fun, const char* name, MaybeTailCall expectTailCall,
PopValues extraValuesToPop = PopValues(0))
@ -883,8 +898,6 @@ struct FunctionInfo<R (*)(Context, Args...)> : public VMFunction {
argumentProperties(), argumentPassedInFloatRegs(),
argumentRootTypes(), outParam(), outParamRootType(),
returnType(), extraValuesToPop.numValues, expectTailCall) {
static_assert(MatchContext<Context>::valid,
"Invalid cx type in VMFunction");
}
};
@ -1226,6 +1239,10 @@ extern const VMFunction ToNumericInfo;
// TailCall VMFunctions
extern const VMFunction DoConcatStringObjectInfo;
enum class VMFunctionId;
extern const VMFunctionData& GetVMFunction(VMFunctionId id);
} // namespace jit
} // namespace js

Просмотреть файл

@ -704,10 +704,11 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunction& f) {
const VMFunctionData& f,
uint32_t* wrapperOffset) {
MOZ_ASSERT(functionWrappers_);
uint32_t wrapperOffset = startTrampolineCode(masm);
*wrapperOffset = startTrampolineCode(masm);
AllocatableGeneralRegisterSet regs(Register::Codes::WrapperMask);
@ -893,7 +894,7 @@ bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
f.explicitStackSlots() * sizeof(void*) +
f.extraValuesToPop * sizeof(Value)));
return functionWrappers_->putNew(&f, wrapperOffset);
return true;
}
uint32_t JitRuntime::generatePreBarrier(JSContext* cx, MacroAssembler& masm,

Просмотреть файл

@ -533,10 +533,11 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunction& f) {
const VMFunctionData& f,
uint32_t* wrapperOffset) {
MOZ_ASSERT(functionWrappers_);
uint32_t wrapperOffset = startTrampolineCode(masm);
*wrapperOffset = startTrampolineCode(masm);
// Avoid conflicts with argument registers while discarding the result after
// the function call.
@ -733,7 +734,7 @@ bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
f.explicitStackSlots() * sizeof(void*) +
f.extraValuesToPop * sizeof(Value)));
return functionWrappers_->putNew(&f, wrapperOffset);
return true;
}
uint32_t JitRuntime::generatePreBarrier(JSContext* cx, MacroAssembler& masm,

Просмотреть файл

@ -40,7 +40,7 @@ void JitRuntime::generateProfilerExitFrameTailStub(MacroAssembler&, Label*) {
}
bool JitRuntime::generateVMWrapper(JSContext*, MacroAssembler&,
const VMFunction&) {
const VMFunctionData&, uint32_t*) {
MOZ_CRASH();
}

Просмотреть файл

@ -591,10 +591,11 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunction& f) {
const VMFunctionData& f,
uint32_t* wrapperOffset) {
MOZ_ASSERT(functionWrappers_);
uint32_t wrapperOffset = startTrampolineCode(masm);
*wrapperOffset = startTrampolineCode(masm);
// Avoid conflicts with argument registers while discarding the result after
// the function call.
@ -772,7 +773,7 @@ bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
f.explicitStackSlots() * sizeof(void*) +
f.extraValuesToPop * sizeof(Value)));
return functionWrappers_->putNew(&f, wrapperOffset);
return true;
}
uint32_t JitRuntime::generatePreBarrier(JSContext* cx, MacroAssembler& masm,

Просмотреть файл

@ -608,10 +608,11 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunction& f) {
const VMFunctionData& f,
uint32_t* wrapperOffset) {
MOZ_ASSERT(functionWrappers_);
uint32_t wrapperOffset = startTrampolineCode(masm);
*wrapperOffset = startTrampolineCode(masm);
// Avoid conflicts with argument registers while discarding the result after
// the function call.
@ -786,7 +787,7 @@ bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
f.explicitStackSlots() * sizeof(void*) +
f.extraValuesToPop * sizeof(Value)));
return functionWrappers_->putNew(&f, wrapperOffset);
return true;
}
uint32_t JitRuntime::generatePreBarrier(JSContext* cx, MacroAssembler& masm,

Просмотреть файл

@ -36,7 +36,16 @@ inline double NumberMod(double a, double b) {
if (b == 0) {
return JS::GenericNaN();
}
return fmod(a, b);
double r = fmod(a, b);
#if defined(XP_WIN)
// Some versions of Windows (Win 10 v1803, v1809) miscompute the sign of zero
// results from fmod. The sign should match the sign of the LHS. This bug
// only affects 64-bit builds. See bug 1527007.
if (mozilla::IsPositiveZero(r) && mozilla::IsNegative(a)) {
return -0.0;
}
#endif
return r;
}
} // namespace js

Просмотреть файл

@ -0,0 +1,14 @@
var BUGNUMBER = 1499448;
var summary = "Constant folder should fold labeled statements";
print(BUGNUMBER + ": " + summary);
if (typeof disassemble === "function") {
var code = disassemble(() => { x: 2+2; });
if (typeof reportCompare === "function")
reportCompare(true, /int8 4/.test(code));
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -609,10 +609,6 @@ static inline ParseNode* ObjectNormalFieldInitializer(ParseNode* pn) {
return BinaryRight(pn);
}
static inline ParseNode* MaybeInitializer(ParseNode* pn) {
return pn->as<NameNode>().initializer();
}
static inline bool IsUseOfName(ParseNode* pn, PropertyName* name) {
return pn->isName(name);
}
@ -3040,8 +3036,15 @@ static bool CheckGlobalDotImport(ModuleValidatorShared& m,
return m.addFFI(varName, field);
}
static bool CheckModuleGlobal(ModuleValidatorShared& m, ParseNode* var,
static bool CheckModuleGlobal(ModuleValidatorShared& m, ParseNode* decl,
bool isConst) {
if (!decl->isKind(ParseNodeKind::AssignExpr)) {
return m.fail(decl, "module import needs initializer");
}
AssignmentNode* assignNode = &decl->as<AssignmentNode>();
ParseNode* var = assignNode->left();
if (!var->isKind(ParseNodeKind::Name)) {
return m.fail(var, "import variable is not a plain name");
}
@ -3051,10 +3054,7 @@ static bool CheckModuleGlobal(ModuleValidatorShared& m, ParseNode* var,
return false;
}
ParseNode* initNode = MaybeInitializer(var);
if (!initNode) {
return m.fail(var, "module import needs initializer");
}
ParseNode* initNode = assignNode->right();
if (IsNumericLiteral(m, initNode)) {
return CheckGlobalVariableInitConstant(m, varName, initNode, isConst);
@ -3254,8 +3254,17 @@ static bool CheckFinalReturn(FunctionValidatorShared& f,
return true;
}
static bool CheckVariable(FunctionValidatorShared& f, ParseNode* var,
static bool CheckVariable(FunctionValidatorShared& f, ParseNode* decl,
ValTypeVector* types, Vector<NumLit>* inits) {
if (!decl->isKind(ParseNodeKind::AssignExpr)) {
return f.failName(
decl, "var '%s' needs explicit type declaration via an initial value",
decl->as<NameNode>().name());
}
AssignmentNode* assignNode = &decl->as<AssignmentNode>();
ParseNode* var = assignNode->left();
if (!var->isKind(ParseNodeKind::Name)) {
return f.fail(var, "local variable is not a plain name");
}
@ -3266,12 +3275,7 @@ static bool CheckVariable(FunctionValidatorShared& f, ParseNode* var,
return false;
}
ParseNode* initNode = MaybeInitializer(var);
if (!initNode) {
return f.failName(
var, "var '%s' needs explicit type declaration via an initial value",
name);
}
ParseNode* initNode = assignNode->right();
NumLit lit;
if (!IsLiteralOrConst(f, initNode, &lit)) {
@ -6154,13 +6158,21 @@ static bool CheckFunctions(ModuleValidator<Unit>& m) {
}
template <typename Unit>
static bool CheckFuncPtrTable(ModuleValidator<Unit>& m, ParseNode* var) {
static bool CheckFuncPtrTable(ModuleValidator<Unit>& m, ParseNode* decl) {
if (!decl->isKind(ParseNodeKind::AssignExpr)) {
return m.fail(decl, "function-pointer table must have initializer");
}
AssignmentNode* assignNode = &decl->as<AssignmentNode>();
ParseNode* var = assignNode->left();
if (!var->isKind(ParseNodeKind::Name)) {
return m.fail(var, "function-pointer table name is not a plain name");
}
ParseNode* arrayLiteral = MaybeInitializer(var);
if (!arrayLiteral || !arrayLiteral->isKind(ParseNodeKind::ArrayExpr)) {
ParseNode* arrayLiteral = assignNode->right();
if (!arrayLiteral->isKind(ParseNodeKind::ArrayExpr)) {
return m.fail(
var, "function-pointer table's initializer must be an array literal");
}

Просмотреть файл

@ -14,6 +14,7 @@
#include "js/PropertySpec.h"
#include "mozilla/ChaosMode.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/IOInterposer.h"
#include "mozilla/Preferences.h"
#include "nsServiceManagerUtils.h"
#include "nsComponentManagerUtils.h"
@ -1075,6 +1076,10 @@ int XRE_XPCShellMain(int argc, char** argv, char** envp,
mozilla::LogModule::Init(argc, argv);
// This guard ensures that all threads that attempt to register themselves
// with the IOInterposer will be properly tracked.
mozilla::IOInterposerInit ioInterposerGuard;
#ifdef MOZ_GECKO_PROFILER
char aLocal;
profiler_init(&aLocal);

Просмотреть файл

@ -183,7 +183,7 @@ class InfallibleAllocPolicy {
}
template <class T, typename P1>
static T* new_(P1 aP1) {
static T* new_(const P1& aP1) {
void* mem = malloc_(sizeof(T));
return new (mem) T(aP1);
}

Просмотреть файл

@ -94,9 +94,8 @@ class GeckoViewContentChild extends GeckoViewChildModule {
collectSessionState() {
let history = SessionHistory.collect(docShell);
let [formdata, scrolldata] = this.Utils.mapFrameTree(
content, SessionStoreUtils.collectFormData,
SessionStoreUtils.collectScrollPosition);
let formdata = SessionStoreUtils.collectFormData(content);
let scrolldata = SessionStoreUtils.collectScrollPosition(content);
// Save the current document resolution.
let zoom = 1;

Просмотреть файл

@ -877,7 +877,7 @@ SessionStore.prototype = {
// Store the form data.
let content = aBrowser.contentWindow;
let [formdata] = Utils.mapFrameTree(content, SessionStoreUtils.collectFormData);
let formdata = SessionStoreUtils.collectFormData(content);
formdata = PrivacyFilter.filterFormData(formdata || {});
// If we found any form data, main content or frames, let's save it
@ -916,8 +916,7 @@ SessionStore.prototype = {
// Save the scroll position itself.
let content = aBrowser.contentWindow;
let [scrolldata] =
Utils.mapFrameTree(content, SessionStoreUtils.collectScrollPosition);
let scrolldata = SessionStoreUtils.collectScrollPosition(content);
scrolldata = scrolldata || {};
// Save the current document resolution.

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше