diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp
index 20fa9e042768..2b1cee4029bb 100644
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -2448,6 +2448,9 @@ void
DocAccessible::DispatchScrollingEvent(uint32_t aEventType)
{
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollable();
+ if (!sf) {
+ return;
+ }
int32_t appUnitsPerDevPixel = mPresShell->GetPresContext()->AppUnitsPerDevPixel();
LayoutDevicePoint scrollPoint = LayoutDevicePoint::FromAppUnits(
diff --git a/accessible/jsat/AccessFu.jsm b/accessible/jsat/AccessFu.jsm
index 894a919476b1..ab4177fd9dbd 100644
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -67,9 +67,8 @@ var AccessFu = {
Services.obs.addObserver(this, "inprocess-browser-shown");
Services.ww.registerNotification(this);
- let windows = Services.wm.getEnumerator(null);
- while (windows.hasMoreElements()) {
- this._attachWindow(windows.getNext());
+ for (let win of Services.wm.getEnumerator(null)) {
+ this._attachWindow(win);
}
Logger.info("AccessFu:Enabled");
@@ -89,9 +88,8 @@ var AccessFu = {
Services.obs.removeObserver(this, "inprocess-browser-shown");
Services.ww.unregisterNotification(this);
- let windows = Services.wm.getEnumerator(null);
- while (windows.hasMoreElements()) {
- this._detachWindow(windows.getNext());
+ for (let win of Services.wm.getEnumerator(null)) {
+ this._detachWindow(win);
}
delete this._notifyOutputPref;
diff --git a/accessible/jsat/Utils.jsm b/accessible/jsat/Utils.jsm
index 9d2769d80da3..c6d17095d5f0 100644
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -160,13 +160,9 @@ var Utils = { // jshint ignore:line
let attributes = {};
if (aAccessible && aAccessible.attributes) {
- let attributesEnum = aAccessible.attributes.enumerate();
-
// Populate |attributes| object with |aAccessible|'s attribute key-value
// pairs.
- while (attributesEnum.hasMoreElements()) {
- let attribute = attributesEnum.getNext().QueryInterface(
- Ci.nsIPropertyElement);
+ for (let attribute of aAccessible.attributes.enumerate()) {
attributes[attribute.key] = attribute.value;
}
}
@@ -757,9 +753,8 @@ PivotContext.prototype = {
}
};
let getHeaders = function* getHeaders(aHeaderCells) {
- let enumerator = aHeaderCells.enumerate();
- while (enumerator.hasMoreElements()) {
- yield enumerator.getNext().QueryInterface(Ci.nsIAccessible).name;
+ for (let {name} of aHeaderCells.enumerate(Ci.nsIAccessible)) {
+ yield name;
}
};
diff --git a/accessible/tests/browser/shared-head.js b/accessible/tests/browser/shared-head.js
index 55fe7ecd7685..0c73ba455a5c 100644
--- a/accessible/tests/browser/shared-head.js
+++ b/accessible/tests/browser/shared-head.js
@@ -246,11 +246,8 @@ function addAccessibleTask(doc, task) {
}
registerCleanupFunction(() => {
- let observers = Services.obs.enumerateObservers("accessible-event");
- while (observers.hasMoreElements()) {
- Services.obs.removeObserver(
- observers.getNext().QueryInterface(Ci.nsIObserver),
- "accessible-event");
+ for (let observer of Services.obs.enumerateObservers("accessible-event")) {
+ Services.obs.removeObserver(observer, "accessible-event");
}
});
diff --git a/accessible/tests/crashtests/1484778.html b/accessible/tests/crashtests/1484778.html
new file mode 100644
index 000000000000..9d3fc33f5985
--- /dev/null
+++ b/accessible/tests/crashtests/1484778.html
@@ -0,0 +1,26 @@
+
+
+
+
diff --git a/accessible/tests/crashtests/crashtests.list b/accessible/tests/crashtests/crashtests.list
index f28c3273622e..2210d0945603 100644
--- a/accessible/tests/crashtests/crashtests.list
+++ b/accessible/tests/crashtests/crashtests.list
@@ -6,6 +6,7 @@ load 893515.html
load 1072792.xhtml
load 1380199.html
load 1402999.html
+load 1484778.html
# last_test_to_unload_testsuite.xul MUST be the last test in the list because it
# is responsible for shutting down accessibility service affecting later tests.
diff --git a/accessible/tests/mochitest/attributes.js b/accessible/tests/mochitest/attributes.js
index accaf66bec08..711f2623d3ff 100644
--- a/accessible/tests/mochitest/attributes.js
+++ b/accessible/tests/mochitest/attributes.js
@@ -319,10 +319,7 @@ function testAttrsInternal(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs,
function compareAttrs(aErrorMsg, aAttrs, aExpectedAttrs, aSkipUnexpectedAttrs,
aAbsentAttrs) {
// Check if all obtained attributes are expected and have expected value.
- var enumerate = aAttrs.enumerate();
- while (enumerate.hasMoreElements()) {
- let prop = enumerate.getNext().QueryInterface(nsIPropertyElement);
-
+ for (let prop of aAttrs.enumerate()) {
if (!(prop.key in aExpectedAttrs)) {
if (!aSkipUnexpectedAttrs)
ok(false, "Unexpected attribute '" + prop.key + "' having '" +
@@ -355,9 +352,7 @@ function compareAttrs(aErrorMsg, aAttrs, aExpectedAttrs, aSkipUnexpectedAttrs,
for (var name in aAbsentAttrs) {
var wasFound = false;
- enumerate = aAttrs.enumerate();
- while (enumerate.hasMoreElements()) {
- let prop = enumerate.getNext().QueryInterface(nsIPropertyElement);
+ for (let prop of aAttrs.enumerate()) {
if (prop.key == name)
wasFound = true;
}
diff --git a/accessible/tests/mochitest/relations.js b/accessible/tests/mochitest/relations.js
index 767e468f9c42..4c4fc830925d 100644
--- a/accessible/tests/mochitest/relations.js
+++ b/accessible/tests/mochitest/relations.js
@@ -76,9 +76,7 @@ function testRelation(aIdentifier, aRelType, aRelatedIdentifiers) {
// Check if all given related accessibles are targets of obtained relation.
for (let idx = 0; idx < targets.length; idx++) {
var isFound = false;
- let enumerate = actualTargets.enumerate();
- while (enumerate.hasMoreElements()) {
- let relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible);
+ for (let relatedAcc of actualTargets.enumerate(Ci.nsIAccessible)) {
if (targets[idx] == relatedAcc) {
isFound = true;
break;
@@ -89,9 +87,7 @@ function testRelation(aIdentifier, aRelType, aRelatedIdentifiers) {
}
// Check if all obtained targets are given related accessibles.
- let enumerate = actualTargets.enumerate();
- while (enumerate.hasMoreElements()) {
- let relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible);
+ for (let relatedAcc of actualTargets.enumerate(Ci.nsIAccessible)) {
let idx;
for (idx = 0; idx < targets.length && relatedAcc != targets[idx]; idx++);
@@ -140,9 +136,7 @@ function testAbsentRelation(aIdentifier, aRelType, aUnrelatedIdentifiers) {
// Any found targets that match given accessibles should be called out.
for (let idx = 0; idx < targets.length; idx++) {
var notFound = true;
- var enumerate = actualTargets.enumerate();
- while (enumerate.hasMoreElements()) {
- var relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible);
+ for (let relatedAcc of actualTargets.enumerate(Ci.nsIAccessible)) {
if (targets[idx] == relatedAcc) {
notFound = false;
break;
diff --git a/browser/actors/NetErrorChild.jsm b/browser/actors/NetErrorChild.jsm
index 2bdc279ddee3..5c3d10ac6306 100644
--- a/browser/actors/NetErrorChild.jsm
+++ b/browser/actors/NetErrorChild.jsm
@@ -83,12 +83,9 @@ class NetErrorChild extends ActorChild {
_getCertValidityRange(docShell) {
let {securityInfo} = docShell.failedChannel;
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
- let certs = securityInfo.failedCertChain.getEnumerator();
let notBefore = 0;
let notAfter = Number.MAX_SAFE_INTEGER;
- while (certs.hasMoreElements()) {
- let cert = certs.getNext();
- cert.QueryInterface(Ci.nsIX509Cert);
+ for (let cert of securityInfo.failedCertChain.getEnumerator()) {
notBefore = Math.max(notBefore, cert.validity.notBefore);
notAfter = Math.min(notAfter, cert.validity.notAfter);
}
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index b3457200cdaf..b62f57e3ba75 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -336,10 +336,8 @@ function isInitialPage(url) {
return gInitialPages.includes(url) || url == BROWSER_NEW_TAB_URL;
}
-function* browserWindows() {
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements())
- yield windows.getNext();
+function browserWindows() {
+ return Services.wm.getEnumerator("navigator:browser");
}
function UpdateBackForwardCommands(aWebNavigation) {
@@ -2636,13 +2634,11 @@ function BrowserPageInfo(documentURL, initialTab, imageElement, frameOuterWindow
}
let args = { initialTab, imageElement, frameOuterWindowID, browser };
- var windows = Services.wm.getEnumerator("Browser:page-info");
documentURL = documentURL || window.gBrowser.selectedBrowser.currentURI.spec;
// Check for windows matching the url
- while (windows.hasMoreElements()) {
- var currentWindow = windows.getNext();
+ for (let currentWindow of Services.wm.getEnumerator("Browser:page-info")) {
if (currentWindow.closed) {
continue;
}
@@ -3309,10 +3305,7 @@ function getDetailedCertErrorInfo(location, securityInfo) {
let certChain = "";
if (securityInfo.failedCertChain) {
- let certs = securityInfo.failedCertChain.getEnumerator();
- while (certs.hasMoreElements()) {
- let cert = certs.getNext();
- cert.QueryInterface(Ci.nsIX509Cert);
+ for (let cert of securityInfo.failedCertChain.getEnumerator()) {
certChain += getPEMString(cert);
}
}
diff --git a/browser/base/content/test/about/browser_aboutCertError.js b/browser/base/content/test/about/browser_aboutCertError.js
index d23a38128200..f8a99e1817a6 100644
--- a/browser/base/content/test/about/browser_aboutCertError.js
+++ b/browser/base/content/test/about/browser_aboutCertError.js
@@ -496,10 +496,7 @@ function getCertChain(securityInfoAsString) {
.getService(Ci.nsISerializationHelper);
let securityInfo = serhelper.deserializeObject(securityInfoAsString);
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
- let certs = securityInfo.failedCertChain.getEnumerator();
- while (certs.hasMoreElements()) {
- let cert = certs.getNext();
- cert.QueryInterface(Ci.nsIX509Cert);
+ for (let cert of securityInfo.failedCertChain.getEnumerator()) {
certChain += getPEMString(cert);
}
return certChain;
diff --git a/browser/base/content/test/general/browser_bug484315.js b/browser/base/content/test/general/browser_bug484315.js
index 79ab5fdb3148..779741480b62 100644
--- a/browser/base/content/test/general/browser_bug484315.js
+++ b/browser/base/content/test/general/browser_bug484315.js
@@ -1,9 +1,6 @@
function test() {
var contentWin = window.open("about:blank", "", "width=100,height=100");
- var enumerator = Services.wm.getEnumerator("navigator:browser");
-
- while (enumerator.hasMoreElements()) {
- let win = enumerator.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (win.content == contentWin) {
Services.prefs.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
win.gBrowser.removeCurrentTab();
diff --git a/browser/base/content/test/general/browser_save_link_when_window_navigates.js b/browser/base/content/test/general/browser_save_link_when_window_navigates.js
index d8010074bd88..3b6c0090fc3e 100644
--- a/browser/base/content/test/general/browser_save_link_when_window_navigates.js
+++ b/browser/base/content/test/general/browser_save_link_when_window_navigates.js
@@ -65,9 +65,7 @@ function triggerSave(aWindow, aCallback) {
}
function continueDownloading() {
- let windows = Services.wm.getEnumerator("");
- while (windows.hasMoreElements()) {
- let win = windows.getNext();
+ for (let win of Services.wm.getEnumerator("")) {
if (win.location && win.location.href == UCT_URI) {
win.document.documentElement._fireButtonEvent("accept");
win.close();
diff --git a/browser/base/content/test/general/head.js b/browser/base/content/test/general/head.js
index 4ddeb0c49131..36e1ddb2a1a2 100644
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -533,24 +533,13 @@ async function loadBadCertPage(url) {
// Utility function to get a handle on the certificate exception dialog.
// Modified from toolkit/components/passwordmgr/test/prompt_common.js
function getCertExceptionDialog(aLocation) {
- let enumerator = Services.wm.getXULWindowEnumerator(null);
-
- while (enumerator.hasMoreElements()) {
- let win = enumerator.getNext();
- let windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
-
- let containedDocShells = windowDocShell.getDocShellEnumerator(
- Ci.nsIDocShellTreeItem.typeChrome,
- Ci.nsIDocShell.ENUMERATE_FORWARDS);
- while (containedDocShells.hasMoreElements()) {
- // Get the corresponding document for this docshell
- let childDocShell = containedDocShells.getNext();
- let childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
- .contentViewer
- .DOMDocument;
-
- if (childDoc.location.href == aLocation) {
- return childDoc;
+ for (let {docShell} of Services.wm.getXULWindowEnumerator(null)) {
+ let containedDocShells = docShell.getDocShellEnumerator(
+ docShell.typeChrome,
+ docShell.ENUMERATE_FORWARDS);
+ for (let {domWindow} of containedDocShells) {
+ if (domWindow.location.href == aLocation) {
+ return domWindow.document;
}
}
}
diff --git a/browser/base/content/test/plugins/browser_CTP_crashreporting.js b/browser/base/content/test/plugins/browser_CTP_crashreporting.js
index 2772a4eb4662..b8aa1af9a5a2 100644
--- a/browser/base/content/test/plugins/browser_CTP_crashreporting.js
+++ b/browser/base/content/test/plugins/browser_CTP_crashreporting.js
@@ -17,9 +17,7 @@ const PLUGIN_SMALL_PAGE = gTestRoot + "plugin_small.html";
*/
function convertPropertyBag(aBag) {
let result = {};
- let enumerator = aBag.enumerator;
- while (enumerator.hasMoreElements()) {
- let { name, value } = enumerator.getNext().QueryInterface(Ci.nsIProperty);
+ for (let { name, value } of aBag.enumerator) {
if (value instanceof Ci.nsIPropertyBag) {
value = convertPropertyBag(value);
}
diff --git a/browser/base/content/test/siteIdentity/head.js b/browser/base/content/test/siteIdentity/head.js
index c3ab3bc092de..0b9c6c945cc7 100644
--- a/browser/base/content/test/siteIdentity/head.js
+++ b/browser/base/content/test/siteIdentity/head.js
@@ -294,24 +294,15 @@ async function loadBadCertPage(url) {
// Utility function to get a handle on the certificate exception dialog.
// Modified from toolkit/components/passwordmgr/test/prompt_common.js
function getCertExceptionDialog(aLocation) {
- let enumerator = Services.wm.getXULWindowEnumerator(null);
-
- while (enumerator.hasMoreElements()) {
- let win = enumerator.getNext();
- let windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
+ for (let win of Services.wm.getXULWindowEnumerator(null)) {
+ let windowDocShell = win.docShell;
let containedDocShells = windowDocShell.getDocShellEnumerator(
Ci.nsIDocShellTreeItem.typeChrome,
Ci.nsIDocShell.ENUMERATE_FORWARDS);
- while (containedDocShells.hasMoreElements()) {
- // Get the corresponding document for this docshell
- let childDocShell = containedDocShells.getNext();
- let childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
- .contentViewer
- .DOMDocument;
-
- if (childDoc.location.href == aLocation) {
- return childDoc;
+ for (let {domWindow} of containedDocShells) {
+ if (domWindow.location.href == aLocation) {
+ return domWindow.document;
}
}
}
diff --git a/browser/base/content/test/static/browser_misused_characters_in_strings.js b/browser/base/content/test/static/browser_misused_characters_in_strings.js
index 50c4e4621370..a9d8043b2493 100644
--- a/browser/base/content/test/static/browser_misused_characters_in_strings.js
+++ b/browser/base/content/test/static/browser_misused_characters_in_strings.js
@@ -219,10 +219,8 @@ add_task(async function checkAllTheProperties() {
for (let uri of uris) {
let bundle = Services.strings.createBundle(uri.spec);
- let enumerator = bundle.getSimpleEnumeration();
- while (enumerator.hasMoreElements()) {
- let entity = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
+ for (let entity of bundle.getSimpleEnumeration()) {
testForErrors(uri.spec, entity.key, entity.value);
}
}
diff --git a/browser/base/content/test/tabcrashed/head.js b/browser/base/content/test/tabcrashed/head.js
index 8a2f25014d68..c14db54dd8fb 100644
--- a/browser/base/content/test/tabcrashed/head.js
+++ b/browser/base/content/test/tabcrashed/head.js
@@ -54,9 +54,7 @@ function promiseCrashReport(expectedExtra = {}) {
}
info("Iterating crash report extra keys");
- let enumerator = extra.enumerator;
- while (enumerator.hasMoreElements()) {
- let key = enumerator.getNext().QueryInterface(Ci.nsIProperty).name;
+ for (let {name: key} of extra.enumerator) {
let value = extra.getPropertyAsAString(key);
if (key in expectedExtra) {
if (expectedExtra[key] == null) {
diff --git a/browser/base/content/test/urlbar/browser_tabMatchesInAwesomebar.js b/browser/base/content/test/urlbar/browser_tabMatchesInAwesomebar.js
index 737060851c6d..985fb33cd358 100644
--- a/browser/base/content/test/urlbar/browser_tabMatchesInAwesomebar.js
+++ b/browser/base/content/test/urlbar/browser_tabMatchesInAwesomebar.js
@@ -139,9 +139,7 @@ function loadTab(tab, url) {
function ensure_opentabs_match_db() {
var tabs = {};
- var winEnum = Services.wm.getEnumerator("navigator:browser");
- while (winEnum.hasMoreElements()) {
- let browserWin = winEnum.getNext();
+ for (let browserWin of Services.wm.getEnumerator("navigator:browser")) {
// skip closed-but-not-destroyed windows
if (browserWin.closed)
continue;
diff --git a/browser/base/content/test/webrtc/head.js b/browser/base/content/test/webrtc/head.js
index 7fb6790b3e7c..0bd80238e491 100644
--- a/browser/base/content/test/webrtc/head.js
+++ b/browser/base/content/test/webrtc/head.js
@@ -110,9 +110,7 @@ async function assertWebRTCIndicatorStatus(expected) {
is(ui.showMicrophoneIndicator, expectAudio, "microphone global indicator as expected");
is(ui.showScreenSharingIndicator, expectScreen, "screen global indicator as expected");
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- let win = windows.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
let menu = win.document.getElementById("tabSharingMenu");
is(!!menu && !menu.hidden, !!expected, "WebRTC menu should be " + expectedState);
}
diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js
index 97eea3cda9c9..6320128e3087 100644
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -790,10 +790,8 @@ function isBidiEnabled() {
}
function openAboutDialog() {
- var enumerator = Services.wm.getEnumerator("Browser:About");
- while (enumerator.hasMoreElements()) {
+ for (let win of Services.wm.getEnumerator("Browser:About")) {
// Only open one about window (Bug 599573)
- let win = enumerator.getNext();
if (win.closed) {
continue;
}
diff --git a/browser/components/contextualidentity/test/browser/browser_forgetAPI_cookie_getCookiesWithOriginAttributes.js b/browser/components/contextualidentity/test/browser/browser_forgetAPI_cookie_getCookiesWithOriginAttributes.js
index 4baa015263bf..ef773ac02fcb 100644
--- a/browser/components/contextualidentity/test/browser/browser_forgetAPI_cookie_getCookiesWithOriginAttributes.js
+++ b/browser/components/contextualidentity/test/browser/browser_forgetAPI_cookie_getCookiesWithOriginAttributes.js
@@ -72,9 +72,7 @@ add_task(async function test_cookie_getCookiesWithOriginAttributes() {
// Using getCookiesWithOriginAttributes() to get all cookies for a certain
// domain by using the originAttributes pattern, and clear all these cookies.
- let enumerator = Services.cookies.getCookiesWithOriginAttributes(JSON.stringify({}), TEST_HOST);
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ for (let cookie of Services.cookies.getCookiesWithOriginAttributes(JSON.stringify({}), TEST_HOST)) {
Services.cookies.remove(cookie.host, cookie.name, cookie.path, false, cookie.originAttributes);
}
diff --git a/browser/components/contextualidentity/test/browser/browser_restore_getCookiesWithOriginAttributes.js b/browser/components/contextualidentity/test/browser/browser_restore_getCookiesWithOriginAttributes.js
index 1e9bcbbebc3c..485d2da726dc 100644
--- a/browser/components/contextualidentity/test/browser/browser_restore_getCookiesWithOriginAttributes.js
+++ b/browser/components/contextualidentity/test/browser/browser_restore_getCookiesWithOriginAttributes.js
@@ -65,9 +65,7 @@ function checkCookies(ignoreContext = null) {
function deleteCookies(onlyContext = null) {
// Using getCookiesWithOriginAttributes() to get all cookies for a certain
// domain by using the originAttributes pattern, and clear all these cookies.
- let enumerator = Services.cookies.getCookiesWithOriginAttributes(JSON.stringify({}), TEST_HOST);
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ for (let cookie of Services.cookies.getCookiesWithOriginAttributes(JSON.stringify({}), TEST_HOST)) {
if (!onlyContext || cookie.originAttributes.userContextId == onlyContext) {
Services.cookies.remove(cookie.host, cookie.name, cookie.path, false, cookie.originAttributes);
}
diff --git a/browser/components/customizableui/PanelMultiView.jsm b/browser/components/customizableui/PanelMultiView.jsm
index a242de3b6138..6b2d195abe6e 100644
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -516,6 +516,15 @@ var PanelMultiView = class extends AssociatedToNode {
try {
canCancel = false;
this._panel.openPopup(...args);
+
+ // On Windows, if another popup is hiding while we call openPopup, the
+ // call won't fail but the popup won't open. In this case, we have to
+ // dispatch an artificial "popuphidden" event to reset our state.
+ if (this._panel.state == "closed" && this.openViews.length) {
+ this.dispatchCustomEvent("popuphidden");
+ return false;
+ }
+
return true;
} catch (ex) {
this.dispatchCustomEvent("popuphidden");
@@ -1056,8 +1065,10 @@ var PanelMultiView = class extends AssociatedToNode {
}
handleEvent(aEvent) {
- if (aEvent.type.startsWith("popup") && aEvent.target != this._panel) {
- // Shouldn't act on e.g. context menus being shown from within the panel.
+ // Only process actual popup events from the panel or events we generate
+ // ourselves, but not from menus being shown from within the panel.
+ if (aEvent.type.startsWith("popup") && aEvent.target != this._panel &&
+ aEvent.target != this.node) {
return;
}
switch (aEvent.type) {
diff --git a/browser/components/customizableui/test/browser.ini b/browser/components/customizableui/test/browser.ini
index 0947cf716551..3ce405ba5820 100644
--- a/browser/components/customizableui/test/browser.ini
+++ b/browser/components/customizableui/test/browser.ini
@@ -144,6 +144,7 @@ skip-if = os == "mac"
[browser_1096763_seen_widgets_post_reset.js]
[browser_1161838_inserted_new_default_buttons.js]
skip-if = verify
+[browser_1484275_PanelMultiView_toggle_with_other_popup.js]
[browser_allow_dragging_removable_false.js]
[browser_bootstrapped_custom_toolbar.js]
[browser_currentset_post_reset.js]
diff --git a/browser/components/customizableui/test/browser_1484275_PanelMultiView_toggle_with_other_popup.js b/browser/components/customizableui/test/browser_1484275_PanelMultiView_toggle_with_other_popup.js
new file mode 100644
index 000000000000..d3e0e1f49124
--- /dev/null
+++ b/browser/components/customizableui/test/browser_1484275_PanelMultiView_toggle_with_other_popup.js
@@ -0,0 +1,87 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_URL = "data:text/html,";
+
+// This code can be consolidated in the EventUtils module (bug 1126772).
+const isWindows = AppConstants.platform == "win";
+const isMac = AppConstants.platform == "macosx";
+const mouseDown = isWindows ? 2 : isMac ? 1 : 4; // eslint-disable-line no-nested-ternary
+const mouseUp = isWindows ? 4 : isMac ? 2 : 7; // eslint-disable-line no-nested-ternary
+const utils = window.windowUtils;
+const scale = utils.screenPixelsPerCSSPixel;
+function synthesizeNativeMouseClick(aElement) {
+ let rect = aElement.getBoundingClientRect();
+ let win = aElement.ownerGlobal;
+ let x = win.mozInnerScreenX + (rect.left + rect.right) / 2;
+ let y = win.mozInnerScreenY + (rect.top + rect.bottom) / 2;
+
+ // Wait for the mouseup event to occur before continuing.
+ return new Promise((resolve, reject) => {
+ function eventOccurred(e) {
+ aElement.removeEventListener("mouseup", eventOccurred, true);
+ resolve();
+ }
+
+ aElement.addEventListener("mouseup", eventOccurred, true);
+
+ utils.sendNativeMouseEvent(x * scale, y * scale, mouseDown, 0, null);
+ utils.sendNativeMouseEvent(x * scale, y * scale, mouseUp, 0, null);
+ });
+}
+
+/**
+ * Test steps that may lead to the panel being stuck on Windows (bug 1484275).
+ */
+add_task(async function test_PanelMultiView_toggle_with_other_popup() {
+ // For proper cleanup, create a bookmark that we will remove later.
+ let bookmark = await PlacesUtils.bookmarks.insert({
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ url: TEST_URL,
+ });
+ registerCleanupFunction(() => PlacesUtils.bookmarks.remove(bookmark));
+
+ await BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: TEST_URL,
+ }, async function(browser) {
+ // 1. Open the main menu.
+ await gCUITestUtils.openMainMenu();
+
+ // 2. Open another popup not managed by PanelMultiView.
+ let bookmarkPanel = document.getElementById("editBookmarkPanel");
+ let shown = BrowserTestUtils.waitForEvent(bookmarkPanel, "popupshown");
+ let hidden = BrowserTestUtils.waitForEvent(bookmarkPanel, "popuphidden");
+ EventUtils.synthesizeKey("D", { accelKey: true });
+ await shown;
+
+ // 3. Click the button to which the main menu is anchored. We need a native
+ // mouse event to simulate the exact platform behavior with popups.
+ let clickFn = () => synthesizeNativeMouseClick(
+ document.getElementById("PanelUI-button"));
+
+ if (AppConstants.platform == "win") {
+ // On Windows, the operation will close both popups.
+ await gCUITestUtils.hidePanelMultiView(PanelUI.panel, clickFn);
+ await new Promise(resolve => executeSoon(resolve));
+
+ // 4. Test that the popup can be opened again after it's been closed.
+ await gCUITestUtils.openMainMenu();
+ Assert.equal(PanelUI.panel.state, "open");
+ } else {
+ // On other platforms, the operation will close both popups and reopen the
+ // main menu immediately, so we wait for the reopen to occur.
+ shown = BrowserTestUtils.waitForEvent(PanelUI.mainView, "ViewShown");
+ clickFn();
+ await shown;
+ }
+
+ await gCUITestUtils.hideMainMenu();
+
+ // Make sure the events for the bookmarks panel have also been processed
+ // before closing the tab and removing the bookmark.
+ await hidden;
+ });
+});
diff --git a/browser/components/customizableui/test/browser_PanelMultiView.js b/browser/components/customizableui/test/browser_PanelMultiView.js
index f8cb0d2276ec..54fe4c691f19 100644
--- a/browser/components/customizableui/test/browser_PanelMultiView.js
+++ b/browser/components/customizableui/test/browser_PanelMultiView.js
@@ -406,6 +406,7 @@ add_task(async function test_cancel_mainview_event_sequence() {
Assert.deepEqual(recordArray, [
"panelview-0: ViewShowing",
"panelview-0: ViewHiding",
+ "panelmultiview-0: PanelMultiViewHidden",
"panelmultiview-0: popuphidden",
]);
});
@@ -475,8 +476,9 @@ add_task(async function test_close_while_showing_mainview_event_sequence() {
Assert.deepEqual(recordArray, [
"panelview-0: ViewShowing",
- "panelview-0: ViewShowing > panelmultiview-0: popuphidden",
"panelview-0: ViewShowing > panelview-0: ViewHiding",
+ "panelview-0: ViewShowing > panelmultiview-0: PanelMultiViewHidden",
+ "panelview-0: ViewShowing > panelmultiview-0: popuphidden",
]);
});
diff --git a/browser/components/dirprovider/DirectoryProvider.cpp b/browser/components/dirprovider/DirectoryProvider.cpp
index e711ccbcc019..4dde0ef92ee1 100644
--- a/browser/components/dirprovider/DirectoryProvider.cpp
+++ b/browser/components/dirprovider/DirectoryProvider.cpp
@@ -140,14 +140,12 @@ DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult)
nsCOMArray distroFiles;
AppendDistroSearchDirs(dirSvc, distroFiles);
- return NS_NewArrayEnumerator(aResult, distroFiles);
+ return NS_NewArrayEnumerator(aResult, distroFiles, NS_GET_IID(nsIFile));
}
return NS_ERROR_FAILURE;
}
-NS_IMPL_ISUPPORTS(DirectoryProvider::AppendingEnumerator, nsISimpleEnumerator)
-
NS_IMETHODIMP
DirectoryProvider::AppendingEnumerator::HasMoreElements(bool *aResult)
{
diff --git a/browser/components/dirprovider/DirectoryProvider.h b/browser/components/dirprovider/DirectoryProvider.h
index 43fa85ab9387..138546ecee7d 100644
--- a/browser/components/dirprovider/DirectoryProvider.h
+++ b/browser/components/dirprovider/DirectoryProvider.h
@@ -7,8 +7,8 @@
#include "nsIDirectoryService.h"
#include "nsComponentManagerUtils.h"
-#include "nsISimpleEnumerator.h"
#include "nsIFile.h"
+#include "nsSimpleEnumerator.h"
#include "mozilla/Attributes.h"
#define NS_BROWSERDIRECTORYPROVIDER_CONTRACTID \
@@ -27,17 +27,16 @@ public:
private:
~DirectoryProvider() {}
- class AppendingEnumerator final : public nsISimpleEnumerator
+ class AppendingEnumerator final : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
AppendingEnumerator(nsISimpleEnumerator* aBase,
char const *const *aAppendList);
private:
- ~AppendingEnumerator() {}
+ ~AppendingEnumerator() override = default;
nsCOMPtr mBase;
char const *const *const mAppendList;
diff --git a/browser/components/downloads/DownloadsCommon.jsm b/browser/components/downloads/DownloadsCommon.jsm
index 3c60e0e4e072..d4401cb516bb 100644
--- a/browser/components/downloads/DownloadsCommon.jsm
+++ b/browser/components/downloads/DownloadsCommon.jsm
@@ -142,9 +142,7 @@ var DownloadsCommon = {
get strings() {
let strings = {};
let sb = Services.strings.createBundle(kDownloadsStringBundleUrl);
- let enumerator = sb.getSimpleEnumeration();
- while (enumerator.hasMoreElements()) {
- let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
+ for (let string of sb.getSimpleEnumeration()) {
let stringName = string.key;
if (stringName in kDownloadsStringsRequiringFormatting) {
strings[stringName] = function() {
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_clear_blocked_cookies.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_clear_blocked_cookies.js
index 01fc3971fe6e..9877abf36ce5 100644
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_clear_blocked_cookies.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_clear_blocked_cookies.js
@@ -26,9 +26,7 @@ add_task(async function setup() {
function retrieve_all_cookies(host) {
const values = [];
- const cookies = Services.cookies.getCookiesFromHost(host, {});
- while (cookies.hasMoreElements()) {
- const cookie = cookies.getNext().QueryInterface(Ci.nsICookie);
+ for (let cookie of Services.cookies.getCookiesFromHost(host, {})) {
values.push({
host: cookie.host,
name: cookie.name,
diff --git a/browser/components/extensions/parent/ext-browsingData.js b/browser/components/extensions/parent/ext-browsingData.js
index ad1ec81fa8e0..8b6f811d2b11 100644
--- a/browser/components/extensions/parent/ext-browsingData.js
+++ b/browser/components/extensions/parent/ext-browsingData.js
@@ -44,7 +44,7 @@ const clearCookies = async function(options) {
if (options.since || options.hostnames) {
// Iterate through the cookies and delete any created after our cutoff.
- for (const cookie of XPCOMUtils.IterSimpleEnumerator(cookieMgr.enumerator, Ci.nsICookie2)) {
+ for (const cookie of cookieMgr.enumerator) {
if ((!options.since || cookie.creationTime >= PlacesUtils.toPRTime(options.since)) &&
(!options.hostnames || options.hostnames.includes(cookie.host.replace(/^\./, "")))) {
// This cookie was created after our cutoff, clear it.
diff --git a/browser/components/extensions/parent/ext-pkcs11.js b/browser/components/extensions/parent/ext-pkcs11.js
index 827acf3b9d4a..a40acc718263 100644
--- a/browser/components/extensions/parent/ext-pkcs11.js
+++ b/browser/components/extensions/parent/ext-pkcs11.js
@@ -13,8 +13,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "pkcs11db",
var {DefaultMap} = ExtensionUtils;
const findModuleByPath = function(path) {
- let modules = pkcs11db.listModules();
- for (let module of XPCOMUtils.IterSimpleEnumerator(modules, Ci.nsIPKCS11Module)) {
+ for (let module of pkcs11db.listModules()) {
if (module && module.libName === path) {
return module;
}
@@ -118,7 +117,7 @@ this.pkcs11 = class extends ExtensionAPI {
return Promise.reject({message: `The module ${name} is not installed`});
}
let rv = [];
- for (let slot of XPCOMUtils.IterSimpleEnumerator(module.listSlots(), Ci.nsIPKCS11Slot)) {
+ for (let slot of module.listSlots()) {
let token = slot.getToken();
let slotobj = {
name: slot.name,
diff --git a/browser/components/extensions/parent/ext-tabs.js b/browser/components/extensions/parent/ext-tabs.js
index 7d7d605e6db1..b8176e6ecf03 100644
--- a/browser/components/extensions/parent/ext-tabs.js
+++ b/browser/components/extensions/parent/ext-tabs.js
@@ -50,9 +50,7 @@ XPCOMUtils.defineLazyGetter(this, "tabHidePopup", () => {
});
function showHiddenTabs(id) {
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while (windowsEnum.hasMoreElements()) {
- let win = windowsEnum.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (win.closed || !win.gBrowser) {
continue;
}
diff --git a/browser/components/extensions/test/browser/browser-common.ini b/browser/components/extensions/test/browser/browser-common.ini
index 450ff262d5fb..b7f18fceeaf8 100644
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -28,6 +28,8 @@ support-files =
file_inspectedwindow_reload_target.sjs
file_indexedDB.html
file_serviceWorker.html
+ install_other-1.0-fx.xpi
+ install_theme-1.0-fx.xpi
webNav_createdTarget.html
webNav_createdTargetSource.html
webNav_createdTargetSource_subframe.html
@@ -105,6 +107,7 @@ skip-if = (verify && (os == 'linux' || os == 'mac'))
[browser_ext_incognito_views.js]
[browser_ext_incognito_popup.js]
[browser_ext_lastError.js]
+[browser_ext_management.js]
[browser_ext_menus.js]
[browser_ext_menus_accesskey.js]
[browser_ext_menus_activeTab.js]
diff --git a/browser/components/extensions/test/browser/browser_ext_management.js b/browser/components/extensions/test/browser/browser_ext_management.js
new file mode 100644
index 000000000000..5252f7a4a028
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_management.js
@@ -0,0 +1,80 @@
+"use strict";
+
+const BASE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/";
+
+function waitForTransition(element, propertyName) {
+ return BrowserTestUtils.waitForEvent(element, "transitionend", false, event => {
+ return event.target == element && event.propertyName == propertyName;
+ });
+}
+
+add_task(async function test_management_install() {
+ await SpecialPowers.pushPrefEnv({set: [
+ ["xpinstall.signatures.required", false],
+ ]});
+
+ registerCleanupFunction(async () => {
+ await SpecialPowers.popPrefEnv();
+ });
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ browser_action: {
+ "browser_style": false,
+ },
+ permissions: ["management"],
+ },
+ background() {
+ let addons;
+ browser.test.onMessage.addListener((msg, init) => {
+ addons = init;
+ browser.test.sendMessage("ready");
+ });
+ browser.browserAction.onClicked.addListener(async () => {
+ try {
+ let {url, hash} = addons.shift();
+ browser.test.log(`Installing XPI from ${url} with hash ${hash || "missing"}`);
+ let {id} = await browser.management.install({url, hash});
+ let {type} = await browser.management.get(id);
+ browser.test.sendMessage("installed", {id, type});
+ } catch (e) {
+ browser.test.log(`management.install() throws ${e}`);
+ browser.test.sendMessage("failed", e.message);
+ }
+ });
+ },
+ });
+
+ let addons = [{
+ url: BASE + "install_theme-1.0-fx.xpi",
+ hash: "sha256:aa232d8391d82a9c1014364efbe1657ff6d8dfc88b3c71e99881b1f3843fdad3",
+ }, {
+ url: BASE + "install_other-1.0-fx.xpi",
+ }];
+
+ await extension.startup();
+ extension.sendMessage("addons", addons);
+ await extension.awaitMessage("ready");
+
+ // Test installing a static WE theme.
+ let transitionDone = waitForTransition(document.documentElement, "background-color");
+ clickBrowserAction(extension);
+
+ let {id, type} = await extension.awaitMessage("installed");
+ is(id, "tiger@persona.beard", "Static web extension theme installed");
+ is(type, "theme", "Extension type is correct");
+
+ await transitionDone;
+ let style = window.getComputedStyle(document.documentElement);
+ is(style.backgroundColor, "rgb(255, 165, 0)", "Background is the new black");
+
+ let addon = await AddonManager.getAddonByID("tiger@persona.beard");
+ await addon.uninstall();
+
+ // Test installing a standard WE.
+ clickBrowserAction(extension);
+ let error = await extension.awaitMessage("failed");
+ is(error, "Incompatible addon", "Standard web extension rejected");
+
+ await extension.unload();
+});
diff --git a/browser/components/extensions/test/browser/head.js b/browser/components/extensions/test/browser/head.js
index f0204f810b36..854d56e8d885 100644
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -508,9 +508,7 @@ function awaitEvent(eventName, id) {
}
function* BrowserWindowIterator() {
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while (windowsEnum.hasMoreElements()) {
- let currentWindow = windowsEnum.getNext();
+ for (let currentWindow of Services.wm.getEnumerator("navigator:browser")) {
if (!currentWindow.closed) {
yield currentWindow;
}
diff --git a/browser/components/extensions/test/browser/install_other-1.0-fx.xpi b/browser/components/extensions/test/browser/install_other-1.0-fx.xpi
new file mode 100644
index 000000000000..66be85efd590
Binary files /dev/null and b/browser/components/extensions/test/browser/install_other-1.0-fx.xpi differ
diff --git a/browser/components/extensions/test/browser/install_theme-1.0-fx.xpi b/browser/components/extensions/test/browser/install_theme-1.0-fx.xpi
new file mode 100644
index 000000000000..0ef2b3d67222
Binary files /dev/null and b/browser/components/extensions/test/browser/install_theme-1.0-fx.xpi differ
diff --git a/browser/components/migration/AutoMigrate.jsm b/browser/components/migration/AutoMigrate.jsm
index a54d0df1fc6f..d8c141facbbe 100644
--- a/browser/components/migration/AutoMigrate.jsm
+++ b/browser/components/migration/AutoMigrate.jsm
@@ -276,9 +276,7 @@ const AutoMigrate = {
},
_removeNotificationBars() {
- let browserWindows = Services.wm.getEnumerator("navigator:browser");
- while (browserWindows.hasMoreElements()) {
- let win = browserWindows.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (!win.closed) {
for (let browser of win.gBrowser.browsers) {
let nb = win.gBrowser.getNotificationBox(browser);
diff --git a/browser/components/migration/FirefoxProfileMigrator.js b/browser/components/migration/FirefoxProfileMigrator.js
index 38fef70aa804..a7151f6fabb2 100644
--- a/browser/components/migration/FirefoxProfileMigrator.js
+++ b/browser/components/migration/FirefoxProfileMigrator.js
@@ -37,12 +37,9 @@ FirefoxProfileMigrator.prototype = Object.create(MigratorPrototype);
FirefoxProfileMigrator.prototype._getAllProfiles = function() {
let allProfiles = new Map();
- let profiles =
- Cc["@mozilla.org/toolkit/profile-service;1"]
- .getService(Ci.nsIToolkitProfileService)
- .profiles;
- while (profiles.hasMoreElements()) {
- let profile = profiles.getNext().QueryInterface(Ci.nsIToolkitProfile);
+ let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]
+ .getService(Ci.nsIToolkitProfileService);
+ for (let profile of profileService.profiles) {
let rootDir = profile.rootDir;
if (rootDir.exists() && rootDir.isReadable() &&
diff --git a/browser/components/migration/IEProfileMigrator.js b/browser/components/migration/IEProfileMigrator.js
index ff258d4e1983..2a22ffc0b939 100644
--- a/browser/components/migration/IEProfileMigrator.js
+++ b/browser/components/migration/IEProfileMigrator.js
@@ -38,10 +38,8 @@ History.prototype = {
migrate: function H_migrate(aCallback) {
let pageInfos = [];
let typedURLs = MSMigrationUtils.getTypedURLs("Software\\Microsoft\\Internet Explorer");
- let historyEnumerator = Cc["@mozilla.org/profile/migrator/iehistoryenumerator;1"].
- createInstance(Ci.nsISimpleEnumerator);
- while (historyEnumerator.hasMoreElements()) {
- let entry = historyEnumerator.getNext().QueryInterface(Ci.nsIPropertyBag2);
+ for (let entry of Cc["@mozilla.org/profile/migrator/iehistoryenumerator;1"]
+ .createInstance(Ci.nsISimpleEnumerator)) {
let url = entry.get("uri").QueryInterface(Ci.nsIURI);
// MSIE stores some types of URLs in its history that we don't handle,
// like HTMLHelp and others. Since we don't properly map handling for
@@ -115,11 +113,9 @@ IE7FormPasswords.prototype = {
},
async migrate(aCallback) {
- let historyEnumerator = Cc["@mozilla.org/profile/migrator/iehistoryenumerator;1"].
- createInstance(Ci.nsISimpleEnumerator);
let uris = []; // the uris of the websites that are going to be migrated
- while (historyEnumerator.hasMoreElements()) {
- let entry = historyEnumerator.getNext().QueryInterface(Ci.nsIPropertyBag2);
+ for (let entry of Cc["@mozilla.org/profile/migrator/iehistoryenumerator;1"]
+ .createInstance(Ci.nsISimpleEnumerator)) {
let uri = entry.get("uri").QueryInterface(Ci.nsIURI);
// MSIE stores some types of URLs in its history that we don't handle, like HTMLHelp
// and others. Since we are not going to import the logins that are performed in these URLs
diff --git a/browser/components/migration/nsIEHistoryEnumerator.cpp b/browser/components/migration/nsIEHistoryEnumerator.cpp
index 116e9a860860..ba1fe4c5d204 100644
--- a/browser/components/migration/nsIEHistoryEnumerator.cpp
+++ b/browser/components/migration/nsIEHistoryEnumerator.cpp
@@ -19,8 +19,6 @@
////////////////////////////////////////////////////////////////////////////////
//// nsIEHistoryEnumerator
-NS_IMPL_ISUPPORTS(nsIEHistoryEnumerator, nsISimpleEnumerator)
-
nsIEHistoryEnumerator::nsIEHistoryEnumerator()
{
::CoInitialize(nullptr);
diff --git a/browser/components/migration/nsIEHistoryEnumerator.h b/browser/components/migration/nsIEHistoryEnumerator.h
index 1572a8dd5b8d..2e28c816d978 100644
--- a/browser/components/migration/nsIEHistoryEnumerator.h
+++ b/browser/components/migration/nsIEHistoryEnumerator.h
@@ -9,19 +9,23 @@
#include "mozilla/Attributes.h"
#include "nsCOMPtr.h"
-#include "nsISimpleEnumerator.h"
#include "nsIWritablePropertyBag2.h"
+#include "nsSimpleEnumerator.h"
-class nsIEHistoryEnumerator final : public nsISimpleEnumerator
+class nsIEHistoryEnumerator final : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
nsIEHistoryEnumerator();
+ const nsID& DefaultInterface() override
+ {
+ return NS_GET_IID(nsIWritablePropertyBag2);
+ }
+
private:
- ~nsIEHistoryEnumerator();
+ ~nsIEHistoryEnumerator() override;
/**
* Initializes the history reader, if needed.
diff --git a/browser/components/migration/tests/unit/test_fx_telemetry.js b/browser/components/migration/tests/unit/test_fx_telemetry.js
index 556a8b33ba61..43d1c96e50f4 100644
--- a/browser/components/migration/tests/unit/test_fx_telemetry.js
+++ b/browser/components/migration/tests/unit/test_fx_telemetry.js
@@ -19,9 +19,7 @@ function readFile(file) {
function checkDirectoryContains(dir, files) {
print("checking " + dir.path + " - should contain " + Object.keys(files));
let seen = new Set();
- let enumerator = dir.directoryEntries;
- while (enumerator.hasMoreElements()) {
- let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
+ for (let file of dir.directoryEntries) {
print("found file: " + file.path);
Assert.ok(file.leafName in files, file.leafName + " exists, but shouldn't");
diff --git a/browser/components/newtab/lib/ASRouterTriggerListeners.jsm b/browser/components/newtab/lib/ASRouterTriggerListeners.jsm
index 7241ec87e93b..0d99f9113960 100644
--- a/browser/components/newtab/lib/ASRouterTriggerListeners.jsm
+++ b/browser/components/newtab/lib/ASRouterTriggerListeners.jsm
@@ -36,9 +36,7 @@ this.ASRouterTriggerListeners = new Map([
Services.ww.registerNotification(this);
// Add listeners to all existing browser windows
- const winEnum = Services.wm.getEnumerator("navigator:browser");
- while (winEnum.hasMoreElements()) {
- let win = winEnum.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (win.closed || PrivateBrowsingUtils.isWindowPrivate(win)) {
continue;
}
@@ -59,9 +57,7 @@ this.ASRouterTriggerListeners = new Map([
if (this._initialized) {
Services.ww.unregisterNotification(this);
- const winEnum = Services.wm.getEnumerator("navigator:browser");
- while (winEnum.hasMoreElements()) {
- let win = winEnum.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (win.closed || PrivateBrowsingUtils.isWindowPrivate(win)) {
continue;
}
diff --git a/browser/components/newtab/lib/Screenshots.jsm b/browser/components/newtab/lib/Screenshots.jsm
index 541eb3c8bbc2..58a1fac2f154 100644
--- a/browser/components/newtab/lib/Screenshots.jsm
+++ b/browser/components/newtab/lib/Screenshots.jsm
@@ -66,9 +66,8 @@ this.Screenshots = {
* we are ok to collect screenshots.
*/
_shouldGetScreenshots() {
- const windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- if (!PrivateBrowsingUtils.isWindowPrivate(windows.getNext())) {
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ if (!PrivateBrowsingUtils.isWindowPrivate(win)) {
// As soon as we encounter 1 non-private window, screenshots are fair game.
return true;
}
diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js
index 96692f6b9221..1f2234879bd4 100644
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -642,9 +642,8 @@ BrowserGlue.prototype = {
// delays are in seconds
const MAX_DELAY = 300;
let delay = 3;
- let browserEnum = Services.wm.getEnumerator("navigator:browser");
- while (browserEnum.hasMoreElements()) {
- delay += browserEnum.getNext().gBrowser.tabs.length;
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ delay += win.gBrowser.tabs.length;
}
delay = delay <= MAX_DELAY ? delay : MAX_DELAY;
diff --git a/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js b/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js
index 06bc21255a94..da45c95ce3e5 100644
--- a/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js
+++ b/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js
@@ -47,11 +47,9 @@ add_task(async function cookie_test() {
let tab = BrowserTestUtils.addTab(gBrowser, BASE_URL + "test_firstParty_cookie.html");
await BrowserTestUtils.browserLoaded(tab.linkedBrowser, true);
- let iter = Services.cookies.enumerator;
let count = 0;
- while (iter.hasMoreElements()) {
+ for (let cookie of Services.cookies.enumerator) {
count++;
- let cookie = iter.getNext().QueryInterface(Ci.nsICookie2);
Assert.equal(cookie.value, "foo", "Cookie value should be foo");
Assert.equal(cookie.originAttributes.firstPartyDomain, BASE_DOMAIN, "Cookie's origin attributes should be " + BASE_DOMAIN);
}
diff --git a/browser/components/payments/paymentUIService.js b/browser/components/payments/paymentUIService.js
index 56e8e0a7f13a..d6d2649aafb7 100644
--- a/browser/components/payments/paymentUIService.js
+++ b/browser/components/payments/paymentUIService.js
@@ -154,9 +154,7 @@ PaymentUIService.prototype = {
},
findDialog(requestId) {
- let enu = Services.wm.getEnumerator(null);
- let win;
- while ((win = enu.getNext())) {
+ for (let win of Services.wm.getEnumerator(null)) {
if (win.name == `${this.REQUEST_ID_PREFIX}${requestId}`) {
return win;
}
diff --git a/browser/components/payments/test/browser/head.js b/browser/components/payments/test/browser/head.js
index 3f67d2f95f95..257074e46364 100644
--- a/browser/components/payments/test/browser/head.js
+++ b/browser/components/payments/test/browser/head.js
@@ -24,12 +24,7 @@ const {PaymentTestUtils: PTU} = ChromeUtils.import(
"resource://testing-common/PaymentTestUtils.jsm", {});
function getPaymentRequests() {
- let requestsEnum = paymentSrv.enumerate();
- let requests = [];
- while (requestsEnum.hasMoreElements()) {
- requests.push(requestsEnum.getNext().QueryInterface(Ci.nsIPaymentRequest));
- }
- return requests;
+ return Array.from(paymentSrv.enumerate());
}
/**
diff --git a/browser/components/preferences/applicationManager.js b/browser/components/preferences/applicationManager.js
index ea1419907b1b..f52caef40041 100644
--- a/browser/components/preferences/applicationManager.js
+++ b/browser/components/preferences/applicationManager.js
@@ -30,14 +30,10 @@ var gAppManagerDialog = {
}
var list = document.getElementById("appList");
- var apps = this.handlerInfo.possibleApplicationHandlers.enumerate();
- while (apps.hasMoreElements()) {
- let app = apps.getNext();
+ for (let app of this.handlerInfo.possibleApplicationHandlers.enumerate()) {
if (!gMainPane.isValidHandlerApp(app))
continue;
- app.QueryInterface(Ci.nsIHandlerApp);
-
// Ensure the XBL binding is created eagerly.
// eslint-disable-next-line no-undef
list.appendChild(MozXULElement.parseXULToFragment(""));
diff --git a/browser/components/preferences/in-content/main.js b/browser/components/preferences/in-content/main.js
index 3c455a991e36..d42faac78350 100644
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -1397,10 +1397,7 @@ var gMainPane = {
* Load the set of handlers defined by the application datastore.
*/
_loadApplicationHandlers() {
- var wrappedHandlerInfos = gHandlerService.enumerate();
- while (wrappedHandlerInfos.hasMoreElements()) {
- let wrappedHandlerInfo =
- wrappedHandlerInfos.getNext().QueryInterface(Ci.nsIHandlerInfo);
+ for (let wrappedHandlerInfo of gHandlerService.enumerate()) {
let type = wrappedHandlerInfo.type;
let handlerInfoWrapper;
@@ -1661,10 +1658,8 @@ var gMainPane = {
// Create menu items for possible handlers.
let preferredApp = handlerInfo.preferredApplicationHandler;
- let possibleApps = handlerInfo.possibleApplicationHandlers.enumerate();
var possibleAppMenuItems = [];
- while (possibleApps.hasMoreElements()) {
- let possibleApp = possibleApps.getNext();
+ for (let possibleApp of handlerInfo.possibleApplicationHandlers.enumerate()) {
if (!this.isValidHandlerApp(possibleApp))
continue;
@@ -1692,10 +1687,8 @@ var gMainPane = {
let gIOSvc = Cc["@mozilla.org/gio-service;1"].
getService(Ci.nsIGIOService);
var gioApps = gIOSvc.getAppsForURIScheme(handlerInfo.type);
- let enumerator = gioApps.enumerate();
let possibleHandlers = handlerInfo.possibleApplicationHandlers;
- while (enumerator.hasMoreElements()) {
- let handler = enumerator.getNext().QueryInterface(Ci.nsIHandlerApp);
+ for (let handler of gioApps.enumerate()) {
// OS handler share the same name, it's most likely the same app, skipping...
if (handler.name == handlerInfo.defaultDescription) {
continue;
@@ -2400,6 +2393,10 @@ function ArrayEnumerator(aItems) {
ArrayEnumerator.prototype = {
_index: 0,
+ [Symbol.iterator]() {
+ return this._contents.values();
+ },
+
hasMoreElements() {
return this._index < this._contents.length;
},
@@ -2710,9 +2707,8 @@ class HandlerInfoWrapper {
}
addPossibleApplicationHandler(aNewHandler) {
- var possibleApps = this.possibleApplicationHandlers.enumerate();
- while (possibleApps.hasMoreElements()) {
- if (possibleApps.getNext().equals(aNewHandler))
+ for (let app of this.possibleApplicationHandlers.enumerate()) {
+ if (app.equals(aNewHandler))
return;
}
this.possibleApplicationHandlers.appendElement(aNewHandler);
diff --git a/browser/components/preferences/languages.js b/browser/components/preferences/languages.js
index 2062630d3e57..08594fbd5008 100644
--- a/browser/components/preferences/languages.js
+++ b/browser/components/preferences/languages.js
@@ -54,15 +54,10 @@ var gLanguagesDialog = {
}
// 1) Read the available languages out of language.properties
- var strings = bundleAccepted.strings;
let localeCodes = [];
let localeValues = [];
- while (strings.hasMoreElements()) {
- var currString = strings.getNext();
- if (!(currString instanceof Ci.nsIPropertyElement))
- break;
-
+ for (let currString of bundleAccepted.strings) {
var property = currString.key.split("."); // ab[-cd].accept
if (property[1] == "accept") {
localeCodes.push(property[0]);
diff --git a/browser/components/preferences/permissions.js b/browser/components/preferences/permissions.js
index 46ecfb52db59..27e231c0f9c6 100644
--- a/browser/components/preferences/permissions.js
+++ b/browser/components/preferences/permissions.js
@@ -260,9 +260,7 @@ var gPermissionManager = {
_loadPermissions() {
// load permissions into a table.
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let nextPermission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let nextPermission of Services.perms.enumerator) {
this._addPermissionToList(nextPermission);
}
},
diff --git a/browser/components/preferences/sitePermissions.js b/browser/components/preferences/sitePermissions.js
index fcf2e09cbc20..5a470bc60b99 100644
--- a/browser/components/preferences/sitePermissions.js
+++ b/browser/components/preferences/sitePermissions.js
@@ -192,9 +192,7 @@ var gSitePermissionsManager = {
_loadPermissions() {
// load permissions into a table.
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let nextPermission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let nextPermission of Services.perms.enumerator) {
this._addPermissionToList(nextPermission);
}
},
diff --git a/browser/components/preferences/translation.js b/browser/components/preferences/translation.js
index 9080802bc5d1..a0fc3efb6696 100644
--- a/browser/components/preferences/translation.js
+++ b/browser/components/preferences/translation.js
@@ -93,10 +93,7 @@ var gTranslationExceptions = {
// Load site permissions into an array.
this._sites = [];
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
-
+ for (let perm of Services.perms.enumerator) {
if (perm.type == kPermissionType &&
perm.capability == Services.perms.DENY_ACTION) {
this._sites.push(perm.principal.origin);
diff --git a/browser/components/sessionstore/SessionCookies.jsm b/browser/components/sessionstore/SessionCookies.jsm
index bf944d7b51e7..2e26b2767d5f 100644
--- a/browser/components/sessionstore/SessionCookies.jsm
+++ b/browser/components/sessionstore/SessionCookies.jsm
@@ -176,9 +176,8 @@ var SessionCookiesInternal = {
return;
}
- let iter = Services.cookies.sessionEnumerator;
- while (iter.hasMoreElements()) {
- this._addCookie(iter.getNext());
+ for (let cookie of Services.cookies.sessionEnumerator) {
+ this._addCookie(cookie);
}
}
};
diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm
index 3c707f8601f3..ec6f26ba6aad 100644
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -597,9 +597,7 @@ var SessionStoreInternal = {
// in one of the currently open windows that was closed after the
// last-closed window.
let tabTimestamps = [];
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while (windowsEnum.hasMoreElements()) {
- let window = windowsEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
let windowState = this._windows[window.__SSi];
if (windowState && windowState._closedTabs[0]) {
tabTimestamps.push(windowState._closedTabs[0].closedAt);
@@ -2722,9 +2720,7 @@ var SessionStoreInternal = {
}
// Check for a tab.
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while (windowsEnum.hasMoreElements()) {
- let window = windowsEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
let windowState = this._windows[window.__SSi];
if (windowState) {
for (let j = 0, l = windowState._closedTabs.length; j < l; j++) {
@@ -2785,9 +2781,7 @@ var SessionStoreInternal = {
// This method deletes all the closedTabs matching userContextId.
_forgetTabsWithUserContextId(userContextId) {
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while (windowsEnum.hasMoreElements()) {
- let window = windowsEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
let windowState = this._windows[window.__SSi];
if (windowState) {
// In order to remove the tabs in the correct order, we store the
@@ -2972,9 +2966,7 @@ var SessionStoreInternal = {
* Revive all crashed tabs and reset the crashed tabs count to 0.
*/
reviveAllCrashedTabs() {
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while (windowsEnum.hasMoreElements()) {
- let window = windowsEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
for (let tab of window.gBrowser.tabs) {
this.reviveCrashedTab(tab);
}
@@ -4329,11 +4321,8 @@ var SessionStoreInternal = {
* setBrowserState to treat them as open windows.
*/
_handleClosedWindows: function ssi_handleClosedWindows() {
- var windowsEnum = Services.wm.getEnumerator("navigator:browser");
-
let promises = [];
- while (windowsEnum.hasMoreElements()) {
- var window = windowsEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (window.closed) {
promises.push(this.onClose(window));
}
diff --git a/browser/components/sessionstore/test/browser_354894_perwindowpb.js b/browser/components/sessionstore/test/browser_354894_perwindowpb.js
index 6f7b483bceb1..b9641be1fc67 100644
--- a/browser/components/sessionstore/test/browser_354894_perwindowpb.js
+++ b/browser/components/sessionstore/test/browser_354894_perwindowpb.js
@@ -59,9 +59,8 @@ const IS_MAC = navigator.platform.match(/Mac/);
*/
function getBrowserWindowsCount() {
let open = 0;
- let e = Services.wm.getEnumerator("navigator:browser");
- while (e.hasMoreElements()) {
- if (!e.getNext().closed)
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ if (!win.closed)
++open;
}
diff --git a/browser/components/sessionstore/test/browser_423132.js b/browser/components/sessionstore/test/browser_423132.js
index e44eea1df73e..1ca79a931f7d 100644
--- a/browser/components/sessionstore/test/browser_423132.js
+++ b/browser/components/sessionstore/test/browser_423132.js
@@ -23,11 +23,8 @@ add_task(async function() {
let state = ss.getBrowserState();
// verify our cookie got set during pageload
- let enumerator = Services.cookies.enumerator;
- let cookie;
let i = 0;
- while (enumerator.hasMoreElements()) {
- cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ for (var cookie of Services.cookies.enumerator) {
i++;
}
Assert.equal(i, 1, "expected one cookie");
@@ -39,10 +36,7 @@ add_task(async function() {
await setBrowserState(state);
// at this point, the cookie should be restored...
- enumerator = Services.cookies.enumerator;
- let cookie2;
- while (enumerator.hasMoreElements()) {
- cookie2 = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ for (var cookie2 of Services.cookies.enumerator) {
if (cookie.name == cookie2.name)
break;
}
diff --git a/browser/components/sessionstore/test/browser_526613.js b/browser/components/sessionstore/test/browser_526613.js
index dbf6a37dd8e1..85a7af51865f 100644
--- a/browser/components/sessionstore/test/browser_526613.js
+++ b/browser/components/sessionstore/test/browser_526613.js
@@ -10,9 +10,8 @@ function test() {
function browserWindowsCount(expected) {
let count = 0;
- let e = Services.wm.getEnumerator("navigator:browser");
- while (e.hasMoreElements()) {
- if (!e.getNext().closed)
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ if (!win.closed)
++count;
}
is(count, expected,
diff --git a/browser/components/sessionstore/test/browser_528776.js b/browser/components/sessionstore/test/browser_528776.js
index d2b69ec63760..72586be64e69 100644
--- a/browser/components/sessionstore/test/browser_528776.js
+++ b/browser/components/sessionstore/test/browser_528776.js
@@ -1,8 +1,7 @@
function browserWindowsCount(expected) {
var count = 0;
- var e = Services.wm.getEnumerator("navigator:browser");
- while (e.hasMoreElements()) {
- if (!e.getNext().closed)
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ if (!win.closed)
++count;
}
is(count, expected,
diff --git a/browser/components/sessionstore/test/browser_600545.js b/browser/components/sessionstore/test/browser_600545.js
index ceceef9b0b01..b53c5b520bd9 100644
--- a/browser/components/sessionstore/test/browser_600545.js
+++ b/browser/components/sessionstore/test/browser_600545.js
@@ -67,10 +67,8 @@ function testBug600545() {
function done() {
// Enumerate windows and close everything but our primary window. We can't
// use waitForFocus() because apparently it's buggy. See bug 599253.
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
let closeWinPromises = [];
- while (windowsEnum.hasMoreElements()) {
- let currentWindow = windowsEnum.getNext();
+ for (let currentWindow of Services.wm.getEnumerator("navigator:browser")) {
if (currentWindow != window)
closeWinPromises.push(BrowserTestUtils.closeWindow(currentWindow));
}
diff --git a/browser/components/sessionstore/test/browser_618151.js b/browser/components/sessionstore/test/browser_618151.js
index 85e49c3aa255..a8f89fc50913 100644
--- a/browser/components/sessionstore/test/browser_618151.js
+++ b/browser/components/sessionstore/test/browser_618151.js
@@ -26,10 +26,8 @@ function runNextTest() {
if (tests.length) {
// Enumerate windows and close everything but our primary window. We can't
// use waitForFocus() because apparently it's buggy. See bug 599253.
- var windowsEnum = Services.wm.getEnumerator("navigator:browser");
let closeWinPromises = [];
- while (windowsEnum.hasMoreElements()) {
- var currentWindow = windowsEnum.getNext();
+ for (let currentWindow of Services.wm.getEnumerator("navigator:browser")) {
if (currentWindow != window) {
closeWinPromises.push(BrowserTestUtils.closeWindow(currentWindow));
}
diff --git a/browser/components/sessionstore/test/browser_636279.js b/browser/components/sessionstore/test/browser_636279.js
index 5102bd9459cc..0890cd73800c 100644
--- a/browser/components/sessionstore/test/browser_636279.js
+++ b/browser/components/sessionstore/test/browser_636279.js
@@ -50,10 +50,7 @@ function test() {
function countTabs() {
let needsRestore = 0, isRestoring = 0;
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
-
- while (windowsEnum.hasMoreElements()) {
- let window = windowsEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (window.closed)
continue;
diff --git a/browser/components/sessionstore/test/browser_restore_cookies_noOriginAttributes.js b/browser/components/sessionstore/test/browser_restore_cookies_noOriginAttributes.js
index de21a947b353..6d916eb23587 100644
--- a/browser/components/sessionstore/test/browser_restore_cookies_noOriginAttributes.js
+++ b/browser/components/sessionstore/test/browser_restore_cookies_noOriginAttributes.js
@@ -136,11 +136,8 @@ add_task(async function run_test() {
// Restore window with session cookies that have no originAttributes.
await setWindowState(win, SESSION_DATA, true);
- let enumerator = Services.cookies.getCookiesFromHost(TEST_HOST, {});
- let cookie;
let cookieCount = 0;
- while (enumerator.hasMoreElements()) {
- cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ for (var cookie of Services.cookies.getCookiesFromHost(TEST_HOST, {})) {
cookieCount++;
}
@@ -156,10 +153,8 @@ add_task(async function run_test() {
// Restore window with session cookies that have originAttributes within.
await setWindowState(win, SESSION_DATA_OA, true);
- enumerator = Services.cookies.getCookiesFromHost(TEST_HOST, {});
cookieCount = 0;
- while (enumerator.hasMoreElements()) {
- cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ for (cookie of Services.cookies.getCookiesFromHost(TEST_HOST, {})) {
cookieCount++;
}
diff --git a/browser/components/sessionstore/test/head.js b/browser/components/sessionstore/test/head.js
index 51a12b8791e3..5790c1d5254a 100644
--- a/browser/components/sessionstore/test/head.js
+++ b/browser/components/sessionstore/test/head.js
@@ -318,9 +318,7 @@ function r() {
}
function* BrowserWindowIterator() {
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while (windowsEnum.hasMoreElements()) {
- let currentWindow = windowsEnum.getNext();
+ for (let currentWindow of Services.wm.getEnumerator("navigator:browser")) {
if (!currentWindow.closed) {
yield currentWindow;
}
diff --git a/browser/components/translation/test/browser_translation_exceptions.js b/browser/components/translation/test/browser_translation_exceptions.js
index fb3d7795ec7e..07fdeb6155a1 100644
--- a/browser/components/translation/test/browser_translation_exceptions.js
+++ b/browser/components/translation/test/browser_translation_exceptions.js
@@ -43,10 +43,7 @@ function getLanguageExceptions() {
function getDomainExceptions() {
let results = [];
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
-
+ for (let perm of Services.perms.enumerator) {
if (perm.type == "translate" &&
perm.capability == Services.perms.DENY_ACTION)
results.push(perm.principal);
diff --git a/browser/components/uitour/UITour.jsm b/browser/components/uitour/UITour.jsm
index 8008a3158e8c..b3f3cd36eff9 100644
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -652,9 +652,7 @@ var UITour = {
// The browser message manager is disconnected when the is
// destroyed and we want to teardown at that point.
case "message-manager-close": {
- let winEnum = Services.wm.getEnumerator("navigator:browser");
- while (winEnum.hasMoreElements()) {
- let window = winEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (window.closed)
continue;
@@ -1683,9 +1681,7 @@ var UITour = {
},
notify(eventName, params) {
- let winEnum = Services.wm.getEnumerator("navigator:browser");
- while (winEnum.hasMoreElements()) {
- let window = winEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (window.closed)
continue;
diff --git a/browser/components/uitour/test/browser_UITour_modalDialog.js b/browser/components/uitour/test/browser_UITour_modalDialog.js
index ab826e4109fc..42d87b1ff294 100644
--- a/browser/components/uitour/test/browser_UITour_modalDialog.js
+++ b/browser/components/uitour/test/browser_UITour_modalDialog.js
@@ -47,24 +47,16 @@ function getDialogDoc() {
// through all the open windows and all the in each.
// var enumerator = wm.getEnumerator("navigator:browser");
- var enumerator = Services.wm.getXULWindowEnumerator(null);
-
- while (enumerator.hasMoreElements()) {
- var win = enumerator.getNext();
- var windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
-
- var containedDocShells = windowDocShell.getDocShellEnumerator(
- Ci.nsIDocShellTreeItem.typeChrome,
- Ci.nsIDocShell.ENUMERATE_FORWARDS);
- while (containedDocShells.hasMoreElements()) {
+ for (let {docShell} of Services.wm.getEnumerator(null)) {
+ var containedDocShells = docShell.getDocShellEnumerator(
+ docShell.typeChrome,
+ docShell.ENUMERATE_FORWARDS);
+ for (let childDocShell of containedDocShells) {
// Get the corresponding document for this docshell
- var childDocShell = containedDocShells.getNext();
// We don't want it if it's not done loading.
if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
continue;
- var childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
- .contentViewer
- .DOMDocument;
+ var childDoc = childDocShell.contentViewer.DOMDocument;
// ok(true, "Got window: " + childDoc.location.href);
if (childDoc.location.href == "chrome://global/content/commonDialog.xul")
diff --git a/browser/extensions/formautofill/api.js b/browser/extensions/formautofill/api.js
index 2dfbd54063f8..85ad442f064a 100644
--- a/browser/extensions/formautofill/api.js
+++ b/browser/extensions/formautofill/api.js
@@ -128,11 +128,8 @@ this.formautofill = class extends ExtensionAPI {
Services.mm.removeMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
- let enumerator = Services.wm.getEnumerator("navigator:browser");
- while (enumerator.hasMoreElements()) {
- let win = enumerator.getNext();
- let domWindow = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
- let cachedStyleSheets = CACHED_STYLESHEETS.get(domWindow);
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ let cachedStyleSheets = CACHED_STYLESHEETS.get(win);
if (!cachedStyleSheets) {
continue;
diff --git a/browser/extensions/formautofill/test/unit/head.js b/browser/extensions/formautofill/test/unit/head.js
index f0d4c7fd5af1..cad8bbbafe23 100644
--- a/browser/extensions/formautofill/test/unit/head.js
+++ b/browser/extensions/formautofill/test/unit/head.js
@@ -36,6 +36,7 @@ Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js",
const EXTENSION_ID = "formautofill@mozilla.org";
AddonTestUtils.init(this);
+AddonTestUtils.overrideCertDB();
async function loadExtension() {
AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
diff --git a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
index 7e50b5b7aac4..386df8a9ec4b 100644
--- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
+++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
@@ -99,9 +99,7 @@ function getLocalizedStrings(path) {
Services.strings.createBundle("chrome://pdf.js/locale/" + path);
var map = {};
- var enumerator = stringBundle.getSimpleEnumeration();
- while (enumerator.hasMoreElements()) {
- var string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
+ for (let string of stringBundle.getSimpleEnumeration()) {
var key = string.key, property = "textContent";
var i = key.lastIndexOf(".");
if (i >= 0) {
diff --git a/browser/extensions/pocket/bootstrap.js b/browser/extensions/pocket/bootstrap.js
index c88b403a592a..46cdd5c87fec 100644
--- a/browser/extensions/pocket/bootstrap.js
+++ b/browser/extensions/pocket/bootstrap.js
@@ -538,9 +538,6 @@ function install() {
function uninstall() {
}
-function* browserWindows() {
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- yield windows.getNext();
- }
+function browserWindows() {
+ return Services.wm.getEnumerator("navigator:browser");
}
diff --git a/browser/extensions/pocket/content/main.js b/browser/extensions/pocket/content/main.js
index 71adcd23426c..040c823066e7 100644
--- a/browser/extensions/pocket/content/main.js
+++ b/browser/extensions/pocket/content/main.js
@@ -530,9 +530,7 @@ var pktUI = (function() {
pktUIMessaging.addMessageListener(iframe, _initL10NMessageId, function(panelId, data) {
var strings = {};
var bundle = Services.strings.createBundle("chrome://pocket/locale/pocket.properties");
- var e = bundle.getSimpleEnumeration();
- while (e.hasMoreElements()) {
- var str = e.getNext().QueryInterface(Ci.nsIPropertyElement);
+ for (let str of bundle.getSimpleEnumeration()) {
if (str.key in data) {
strings[str.key] = bundle.formatStringFromName(str.key, data[str.key], data[str.key].length);
} else {
@@ -568,9 +566,7 @@ var pktUI = (function() {
return;
}
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- let win = windows.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (!PrivateBrowsingUtils.isWindowPrivate(win)) {
win.openWebLinkIn(url, "tab", {
triggeringPrincipal: aTriggeringPrincipal
diff --git a/browser/extensions/pocket/content/pktApi.jsm b/browser/extensions/pocket/content/pktApi.jsm
index 25bae563a29b..fee16b0e1994 100644
--- a/browser/extensions/pocket/content/pktApi.jsm
+++ b/browser/extensions/pocket/content/pktApi.jsm
@@ -155,10 +155,8 @@ var pktApi = (function() {
* The return format: { cookieName:cookieValue, cookieName:cookieValue, ... }
*/
function getCookiesFromPocket() {
- var pocketCookies = Services.cookies.getCookiesFromHost(pocketSiteHost, {});
var cookies = {};
- while (pocketCookies.hasMoreElements()) {
- var cookie = pocketCookies.getNext().QueryInterface(Ci.nsICookie2);
+ for (let cookie of Services.cookies.getCookiesFromHost(pocketSiteHost, {})) {
cookies[cookie.name] = cookie.value;
}
return cookies;
diff --git a/browser/modules/BrowserUsageTelemetry.jsm b/browser/modules/BrowserUsageTelemetry.jsm
index c5c832b8629c..bb8eafd837b6 100644
--- a/browser/modules/BrowserUsageTelemetry.jsm
+++ b/browser/modules/BrowserUsageTelemetry.jsm
@@ -95,9 +95,7 @@ function getOpenTabsAndWinsCounts() {
let tabCount = 0;
let winCount = 0;
- let browserEnum = Services.wm.getEnumerator("navigator:browser");
- while (browserEnum.hasMoreElements()) {
- let win = browserEnum.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
winCount++;
tabCount += win.gBrowser.tabs.length;
}
@@ -659,9 +657,8 @@ let BrowserUsageTelemetry = {
Services.obs.addObserver(this, TELEMETRY_SUBSESSIONSPLIT_TOPIC, true);
// Attach the tabopen handlers to the existing Windows.
- let browserEnum = Services.wm.getEnumerator("navigator:browser");
- while (browserEnum.hasMoreElements()) {
- this._registerWindow(browserEnum.getNext());
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ this._registerWindow(win);
}
// Get the initial tab and windows max counts.
diff --git a/browser/modules/BrowserWindowTracker.jsm b/browser/modules/BrowserWindowTracker.jsm
index a4dccb7dc793..a010a439984c 100644
--- a/browser/modules/BrowserWindowTracker.jsm
+++ b/browser/modules/BrowserWindowTracker.jsm
@@ -169,19 +169,15 @@ var WindowHelper = {
// if we're lucky, this isn't a popup, and we can just return this
if (win && !isSuitableBrowserWindow(win)) {
win = null;
- let windowList = Services.wm.getEnumerator("navigator:browser");
// this is oldest to newest, so this gets a bit ugly
- while (windowList.hasMoreElements()) {
- let nextWin = windowList.getNext();
+ for (let nextWin of Services.wm.getEnumerator("navigator:browser")) {
if (isSuitableBrowserWindow(nextWin))
win = nextWin;
}
}
return win;
}
- let windowList = Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
- while (windowList.hasMoreElements()) {
- let win = windowList.getNext();
+ for (let win of Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", true)) {
if (isSuitableBrowserWindow(win))
return win;
}
diff --git a/browser/modules/ContentCrashHandlers.jsm b/browser/modules/ContentCrashHandlers.jsm
index f3fadc46b10b..c33b5f804b89 100644
--- a/browser/modules/ContentCrashHandlers.jsm
+++ b/browser/modules/ContentCrashHandlers.jsm
@@ -458,9 +458,7 @@ var TabCrashHandler = {
},
removeSubmitCheckboxesForSameCrash(childID) {
- let enumerator = Services.wm.getEnumerator("navigator:browser");
- while (enumerator.hasMoreElements()) {
- let window = enumerator.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (!window.gMultiProcessBrowser)
continue;
@@ -1069,9 +1067,7 @@ var PluginCrashReporter = {
},
broadcastState(runID, state) {
- let enumerator = Services.wm.getEnumerator("navigator:browser");
- while (enumerator.hasMoreElements()) {
- let window = enumerator.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
let mm = window.messageManager;
mm.broadcastAsyncMessage("BrowserPlugins:CrashReportSubmitted",
{ runID, state });
diff --git a/browser/modules/PageActions.jsm b/browser/modules/PageActions.jsm
index f09f4f962bfd..2a3d33448035 100644
--- a/browser/modules/PageActions.jsm
+++ b/browser/modules/PageActions.jsm
@@ -1204,10 +1204,7 @@ function* allBrowserWindows(browserWindow = null) {
yield browserWindow;
return;
}
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- yield windows.getNext();
- }
+ yield* Services.wm.getEnumerator("navigator:browser");
}
/**
diff --git a/browser/modules/ProcessHangMonitor.jsm b/browser/modules/ProcessHangMonitor.jsm
index e6f6d1a3a7b7..12599f95fc75 100644
--- a/browser/modules/ProcessHangMonitor.jsm
+++ b/browser/modules/ProcessHangMonitor.jsm
@@ -391,9 +391,7 @@ var ProcessHangMonitor = {
return;
}
- while (e.hasMoreElements()) {
- let win = e.getNext();
-
+ for (let win of e) {
this.updateWindow(win);
// Only listen for these events if there are active hang reports.
diff --git a/browser/modules/Sanitizer.jsm b/browser/modules/Sanitizer.jsm
index 534b8b4c2428..a4fed5f65014 100644
--- a/browser/modules/Sanitizer.jsm
+++ b/browser/modules/Sanitizer.jsm
@@ -351,9 +351,7 @@ var Sanitizer = {
TelemetryStopwatch.start("FX_SANITIZE_FORMDATA", refObj);
try {
// Clear undo history of all search bars.
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- let currentWindow = windows.getNext();
+ for (let currentWindow of Services.wm.getEnumerator("navigator:browser")) {
let currentDocument = currentWindow.document;
// searchBar.textbox may not exist due to the search bar binding
@@ -466,10 +464,8 @@ var Sanitizer = {
let startDate = existingWindow.performance.now();
// First check if all these windows are OK with being closed:
- let windowEnumerator = Services.wm.getEnumerator("navigator:browser");
let windowList = [];
- while (windowEnumerator.hasMoreElements()) {
- let someWin = windowEnumerator.getNext();
+ for (let someWin of Services.wm.getEnumerator("navigator:browser")) {
windowList.push(someWin);
// If someone says "no" to a beforeunload prompt, we abort here:
if (!this._canCloseWindow(someWin)) {
@@ -690,9 +686,7 @@ async function sanitizeOnShutdown(progress) {
await sanitizeSessionPrincipals();
// Let's see if we have to forget some particular site.
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let permission of Services.perms.enumerator) {
if (permission.type == "cookie" && permission.capability == Ci.nsICookiePermission.ACCESS_SESSION) {
await sanitizeSessionPrincipal(permission.principal);
}
diff --git a/browser/modules/SavantShieldStudy.jsm b/browser/modules/SavantShieldStudy.jsm
index 6d2d20f2d797..9a29dae41a7c 100644
--- a/browser/modules/SavantShieldStudy.jsm
+++ b/browser/modules/SavantShieldStudy.jsm
@@ -459,9 +459,7 @@ class WindowWatcher {
this._errorCallback = errorCallback;
// Add loadCallback to existing windows
- const windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- const win = windows.getNext();
+ for (const win of Services.wm.getEnumerator("navigator:browser")) {
try {
this._loadCallback(win);
} catch (ex) {
@@ -480,9 +478,7 @@ class WindowWatcher {
return;
}
- const windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- const win = windows.getNext();
+ for (const win of Services.wm.getEnumerator("navigator:browser")) {
try {
this._unloadCallback(win);
} catch (ex) {
diff --git a/browser/modules/SiteDataManager.jsm b/browser/modules/SiteDataManager.jsm
index 9e08e00c38c5..91f88aaadf3c 100644
--- a/browser/modules/SiteDataManager.jsm
+++ b/browser/modules/SiteDataManager.jsm
@@ -173,9 +173,7 @@ var SiteDataManager = {
},
_getAllCookies() {
- let cookiesEnum = Services.cookies.enumerator;
- while (cookiesEnum.hasMoreElements()) {
- let cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2);
+ for (let cookie of Services.cookies.enumerator) {
let site = this._getOrInsertSite(cookie.rawHost);
site.cookies.push(cookie);
if (site.lastAccessed < cookie.lastAccessed) {
diff --git a/browser/modules/WindowsPreviewPerTab.jsm b/browser/modules/WindowsPreviewPerTab.jsm
index ad029caee749..fccf1ce14e17 100644
--- a/browser/modules/WindowsPreviewPerTab.jsm
+++ b/browser/modules/WindowsPreviewPerTab.jsm
@@ -729,9 +729,7 @@ var AeroPeek = {
// (rather than this code running on startup because the pref was
// already set to true), we must initialize previews for open windows:
if (this.initialized) {
- let browserWindows = Services.wm.getEnumerator("navigator:browser");
- while (browserWindows.hasMoreElements()) {
- let win = browserWindows.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (!win.closed) {
this.onOpenWindow(win);
}
diff --git a/browser/modules/test/browser/head.js b/browser/modules/test/browser/head.js
index 26ff653c26d1..cd3732bc01bf 100644
--- a/browser/modules/test/browser/head.js
+++ b/browser/modules/test/browser/head.js
@@ -169,7 +169,7 @@ function checkEvents(events, expectedEvents) {
*/
function makeMockPermissionRequest(browser) {
let type = {
- options: [],
+ options: Cc["@mozilla.org/array;1"].createInstance(Ci.nsIArray),
QueryInterface: ChromeUtils.generateQI([Ci.nsIContentPermissionType]),
};
let types = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
diff --git a/browser/modules/webrtcUI.jsm b/browser/modules/webrtcUI.jsm
index a479beaf3731..2959ffdd1b23 100644
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -1090,9 +1090,7 @@ function updateIndicators(data, target) {
indicators.showScreenSharingIndicator = data.showScreenSharingIndicator;
}
- let browserWindowEnum = Services.wm.getEnumerator("navigator:browser");
- while (browserWindowEnum.hasMoreElements()) {
- let chromeWin = browserWindowEnum.getNext();
+ for (let chromeWin of Services.wm.getEnumerator("navigator:browser")) {
if (webrtcUI.showGlobalIndicator) {
showOrCreateMenuForWindow(chromeWin);
} else {
diff --git a/build/autoconf/frameptr.m4 b/build/autoconf/frameptr.m4
index e7e50330eea5..4efe32c3be18 100644
--- a/build/autoconf/frameptr.m4
+++ b/build/autoconf/frameptr.m4
@@ -30,13 +30,15 @@ AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
fi
# If we are debugging, profiling, using sanitizers, or on win32 we want a
- # frame pointer.
+ # frame pointer. It is not required to enable frame pointers on AArch64
+ # Windows, but we enable it for compatibility with ETW.
if test -z "$MOZ_OPTIMIZE" -o \
-n "$MOZ_PROFILING" -o \
-n "$MOZ_DEBUG" -o \
-n "$MOZ_MSAN" -o \
-n "$MOZ_ASAN" -o \
- "$OS_ARCH:$CPU_ARCH" = "WINNT:x86"; then
+ "$OS_ARCH:$CPU_ARCH" = "WINNT:x86" -o \
+ "$OS_ARCH:$CPU_ARCH" = "WINNT:aarch64"; then
MOZ_FRAMEPTR_FLAGS="$MOZ_ENABLE_FRAME_PTR"
else
MOZ_FRAMEPTR_FLAGS="$MOZ_DISABLE_FRAME_PTR"
diff --git a/build/build-clang/clang-7-pre-linux64.json b/build/build-clang/clang-7-pre-linux64.json
index 75032df694d3..a201218b4056 100644
--- a/build/build-clang/clang-7-pre-linux64.json
+++ b/build/build-clang/clang-7-pre-linux64.json
@@ -1,15 +1,15 @@
{
- "llvm_revision": "338869",
+ "llvm_revision": "340494",
"stages": "3",
"build_libcxx": true,
"build_type": "Release",
"assertions": false,
- "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_700/rc1",
- "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_700/rc1",
- "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_700/rc1",
- "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_700/rc1",
- "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_700/rc1",
- "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_700/rc1",
+ "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_700/rc2",
+ "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_700/rc2",
+ "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_700/rc2",
+ "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_700/rc2",
+ "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_700/rc2",
+ "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_700/rc2",
"python_path": "/usr/bin/python2.7",
"gcc_dir": "/builds/worker/workspace/build/src/gcc",
"cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",
@@ -17,7 +17,6 @@
"as": "/builds/worker/workspace/build/src/gcc/bin/gcc",
"patches": [
"find_symbolizer_linux.patch",
- "rename_gcov_flush.patch",
- "r339636.patch"
+ "rename_gcov_flush.patch"
]
}
diff --git a/build/build-clang/clang-7-pre-mingw.json b/build/build-clang/clang-7-pre-mingw.json
index ce89196543f2..3132dbcc0170 100644
--- a/build/build-clang/clang-7-pre-mingw.json
+++ b/build/build-clang/clang-7-pre-mingw.json
@@ -1,21 +1,18 @@
{
- "llvm_revision": "338869",
+ "llvm_revision": "340494",
"stages": "3",
"build_libcxx": true,
"build_type": "Release",
"assertions": false,
- "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_700/rc1",
- "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_700/rc1",
- "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_700/rc1",
- "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_700/rc1",
- "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_700/rc1",
- "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_700/rc1",
+ "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_700/rc2",
+ "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_700/rc2",
+ "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_700/rc2",
+ "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_700/rc2",
+ "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_700/rc2",
+ "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_700/rc2",
"python_path": "/usr/bin/python2.7",
"gcc_dir": "/builds/worker/workspace/build/src/gcc",
"cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",
"cxx": "/builds/worker/workspace/build/src/gcc/bin/g++",
- "as": "/builds/worker/workspace/build/src/gcc/bin/gcc",
- "patches": [
- "r339636.patch"
- ]
+ "as": "/builds/worker/workspace/build/src/gcc/bin/gcc"
}
diff --git a/build/unix/mozconfig.lto b/build/unix/mozconfig.lto
index d825ac6158a7..c62104f8c857 100644
--- a/build/unix/mozconfig.lto
+++ b/build/unix/mozconfig.lto
@@ -17,5 +17,8 @@ if [ -e "$topsrcdir/gcc/bin/ld" ]; then
fi
ac_add_options --enable-lto
+# Until it's either made the default or we figure a way to remove the
+# copy locations that LTO induces in non-PIE executables.
+ac_add_options --enable-pie
. "$topsrcdir/build/unix/mozconfig.stdcxx"
diff --git a/devtools/client/debugger/new/src/actions/expressions.js b/devtools/client/debugger/new/src/actions/expressions.js
index 2ccb0317ee39..52ca43c3648f 100644
--- a/devtools/client/debugger/new/src/actions/expressions.js
+++ b/devtools/client/debugger/new/src/actions/expressions.js
@@ -217,9 +217,15 @@ function getMappedExpression(expression) {
sourceMaps
}) {
const mappings = (0, _selectors.getSelectedScopeMappings)(getState());
- const bindings = (0, _selectors.getSelectedFrameBindings)(getState());
+ const bindings = (0, _selectors.getSelectedFrameBindings)(getState()); // We bail early if we do not need to map the expression. This is important
+ // because mapping an expression can be slow if the parser worker is
+ // busy doing other work.
+ //
+ // 1. there are no mappings - we do not need to map original expressions
+ // 2. does not contain `await` - we do not need to map top level awaits
+ // 3. does not contain `=` - we do not need to map assignments
- if (!mappings && !bindings && !expression.includes("await")) {
+ if (!mappings && !expression.match(/(await|=)/)) {
return expression;
}
diff --git a/devtools/client/debugger/new/src/reducers/pause.js b/devtools/client/debugger/new/src/reducers/pause.js
index 47d7dffe7f03..516529751cf7 100644
--- a/devtools/client/debugger/new/src/reducers/pause.js
+++ b/devtools/client/debugger/new/src/reducers/pause.js
@@ -410,12 +410,20 @@ function getFrameScope(state, sourceId, frameId) {
}
function getSelectedScope(state) {
- const sourceRecord = (0, _sources.getSelectedSource)(state);
+ const source = (0, _sources.getSelectedSource)(state);
const frameId = getSelectedFrameId(state);
- const {
- scope
- } = getFrameScope(state, sourceRecord && sourceRecord.id, frameId) || {};
- return scope || null;
+
+ if (!source) {
+ return null;
+ }
+
+ const frameScope = getFrameScope(state, source.id, frameId);
+
+ if (!frameScope) {
+ return null;
+ }
+
+ return frameScope.scope || null;
}
function getSelectedScopeMappings(state) {
diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js
index b6b37c1331fc..277ac7757802 100644
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js
@@ -49,7 +49,7 @@ add_task(async function() {
info(`Test previewing in the original location`);
await assertPreviews(dbg, [
- { line: 2, column: 10, result: 4, expression: "x;" }
+ { line: 2, column: 10, result: 4, expression: "x" }
]);
info(`Test previewing in the generated location`);
diff --git a/devtools/client/framework/devtools-browser.js b/devtools/client/framework/devtools-browser.js
index e3e0a995d563..54a1377f84fa 100644
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -743,9 +743,7 @@ Services.obs.addObserver(gDevToolsBrowser, "devtools:loader:destroy");
// Fake end of browser window load event for all already opened windows
// that is already fully loaded.
-const enumerator = Services.wm.getEnumerator(gDevTools.chromeWindowType);
-while (enumerator.hasMoreElements()) {
- const win = enumerator.getNext();
+for (const win of Services.wm.getEnumerator(gDevTools.chromeWindowType)) {
if (win.gBrowserInit && win.gBrowserInit.delayedStartupFinished) {
gDevToolsBrowser._registerBrowserWindow(win);
}
diff --git a/devtools/client/framework/test/browser_toolbox_dynamic_registration.js b/devtools/client/framework/test/browser_toolbox_dynamic_registration.js
index 8be72b6a5afa..c605a63ce5e7 100644
--- a/devtools/client/framework/test/browser_toolbox_dynamic_registration.js
+++ b/devtools/client/framework/test/browser_toolbox_dynamic_registration.js
@@ -50,12 +50,7 @@ function toolRegistered(toolId) {
}
function getAllBrowserWindows() {
- const wins = [];
- const enumerator = Services.wm.getEnumerator("navigator:browser");
- while (enumerator.hasMoreElements()) {
- wins.push(enumerator.getNext());
- }
- return wins;
+ return Array.from(Services.wm.getEnumerator("navigator:browser"));
}
function testUnregister() {
diff --git a/devtools/client/framework/test/browser_toolbox_tools_per_toolbox_registration.js b/devtools/client/framework/test/browser_toolbox_tools_per_toolbox_registration.js
index dd2d360f4c2c..451b3232e04a 100644
--- a/devtools/client/framework/test/browser_toolbox_tools_per_toolbox_registration.js
+++ b/devtools/client/framework/test/browser_toolbox_tools_per_toolbox_registration.js
@@ -97,12 +97,7 @@ function testToolRegistered() {
}
function getAllBrowserWindows() {
- const wins = [];
- const enumerator = Services.wm.getEnumerator("navigator:browser");
- while (enumerator.hasMoreElements()) {
- wins.push(enumerator.getNext());
- }
- return wins;
+ return Array.from(Services.wm.getEnumerator("navigator:browser"));
}
function testUnregister() {
diff --git a/devtools/client/scratchpad/scratchpad-manager.jsm b/devtools/client/scratchpad/scratchpad-manager.jsm
index 8507e9d2429b..d926537ee60d 100644
--- a/devtools/client/scratchpad/scratchpad-manager.jsm
+++ b/devtools/client/scratchpad/scratchpad-manager.jsm
@@ -87,9 +87,7 @@ this.ScratchpadManager = {
// such objects are not primitive-values-only anymore so they
// can leak.
- const enumerator = Services.wm.getEnumerator("devtools:scratchpad");
- while (enumerator.hasMoreElements()) {
- const win = enumerator.getNext();
+ for (const win of Services.wm.getEnumerator("devtools:scratchpad")) {
if (!win.closed && win.Scratchpad.initialized) {
this._scratchpads.push(clone(win.Scratchpad.getState()));
}
diff --git a/devtools/client/shared/view-source.js b/devtools/client/shared/view-source.js
index 98d6545ac29d..450e985f9fc7 100644
--- a/devtools/client/shared/view-source.js
+++ b/devtools/client/shared/view-source.js
@@ -132,11 +132,7 @@ exports.viewSourceInDebugger = async function(toolbox, sourceURL, sourceLine,
*/
exports.viewSourceInScratchpad = async function(sourceURL, sourceLine) {
// Check for matching top level scratchpad window.
- const wins = Services.wm.getEnumerator("devtools:scratchpad");
-
- while (wins.hasMoreElements()) {
- const win = wins.getNext();
-
+ for (const win of Services.wm.getEnumerator("devtools:scratchpad")) {
if (!win.closed && win.Scratchpad.uniqueName === sourceURL) {
win.focus();
win.Scratchpad.editor.setCursor({ line: sourceLine, ch: 0 });
diff --git a/devtools/server/actors/accessibility.js b/devtools/server/actors/accessibility.js
index 47115b0e3bad..58e04f8a70a5 100644
--- a/devtools/server/actors/accessibility.js
+++ b/devtools/server/actors/accessibility.js
@@ -25,7 +25,6 @@ const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled";
const nsIAccessibleEvent = Ci.nsIAccessibleEvent;
const nsIAccessibleStateChangeEvent = Ci.nsIAccessibleStateChangeEvent;
-const nsIPropertyElement = Ci.nsIPropertyElement;
const nsIAccessibleRole = Ci.nsIAccessibleRole;
const {
@@ -322,10 +321,7 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
}
const attributes = {};
- const attrsEnum = this.rawAccessible.attributes.enumerate();
- while (attrsEnum.hasMoreElements()) {
- const { key, value } = attrsEnum.getNext().QueryInterface(
- nsIPropertyElement);
+ for (const { key, value } of this.rawAccessible.attributes.enumerate()) {
attributes[key] = value;
}
diff --git a/devtools/server/actors/inspector/walker.js b/devtools/server/actors/inspector/walker.js
index 129626a8fa77..35729a832693 100644
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -186,9 +186,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
* enumerator of nsIEventListenerChange
*/
_onEventListenerChange: function(changesEnum) {
- const changes = changesEnum.enumerate();
- while (changes.hasMoreElements()) {
- const current = changes.getNext().QueryInterface(Ci.nsIEventListenerChange);
+ for (const current of changesEnum.enumerate(Ci.nsIEventListenerChange)) {
const target = current.target;
if (this._refMap.has(target)) {
diff --git a/devtools/server/actors/replay/graphics.js b/devtools/server/actors/replay/graphics.js
index 06045f3f5d50..d546746a288f 100644
--- a/devtools/server/actors/replay/graphics.js
+++ b/devtools/server/actors/replay/graphics.js
@@ -51,9 +51,7 @@ function updateWindow(window, buffer, width, height) {
function Update(buffer, width, height) {
try {
// Paint to all windows we can find. Hopefully there is only one.
- const windowEnumerator = Services.ww.getWindowEnumerator();
- while (windowEnumerator.hasMoreElements()) {
- const window = windowEnumerator.getNext().QueryInterface(Ci.nsIDOMWindow);
+ for (const window of Services.ww.getWindowEnumerator()) {
updateWindow(window, buffer, width, height);
}
} catch (e) {
diff --git a/devtools/server/actors/storage.js b/devtools/server/actors/storage.js
index e9bae7708e58..30be3ef38257 100644
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -810,16 +810,8 @@ var cookieHelpers = {
host = trimHttpHttpsPort(host);
- const cookies = Services.cookies.getCookiesFromHost(host, originAttributes);
- const store = [];
-
- while (cookies.hasMoreElements()) {
- const cookie = cookies.getNext().QueryInterface(Ci.nsICookie2);
-
- store.push(cookie);
- }
-
- return store;
+ return Array.from(
+ Services.cookies.getCookiesFromHost(host, originAttributes));
},
/**
@@ -854,11 +846,9 @@ var cookieHelpers = {
const origPath = field === "path" ? oldValue : data.items.path;
let cookie = null;
- const enumerator =
- Services.cookies.getCookiesFromHost(origHost, data.originAttributes || {});
-
- while (enumerator.hasMoreElements()) {
- const nsiCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+ const cookies = Services.cookies.getCookiesFromHost(origHost,
+ data.originAttributes || {});
+ for (const nsiCookie of cookies) {
if (nsiCookie.name === origName &&
nsiCookie.host === origHost &&
nsiCookie.path === origPath) {
@@ -956,11 +946,9 @@ var cookieHelpers = {
return cookieHost == host;
}
- const enumerator =
- Services.cookies.getCookiesFromHost(host, opts.originAttributes || {});
-
- while (enumerator.hasMoreElements()) {
- const cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+ const cookies = Services.cookies.getCookiesFromHost(host,
+ opts.originAttributes || {});
+ for (const cookie of cookies) {
if (hostMatches(cookie.host, host) &&
(!opts.name || cookie.name === opts.name) &&
(!opts.domain || cookie.host === opts.domain) &&
diff --git a/devtools/server/actors/targets/addon.js b/devtools/server/actors/targets/addon.js
index 5d2db5b06237..bbbd48282929 100644
--- a/devtools/server/actors/targets/addon.js
+++ b/devtools/server/actors/targets/addon.js
@@ -185,20 +185,14 @@ AddonTargetActor.prototype = {
},
preNest: function() {
- const e = Services.wm.getEnumerator(null);
- while (e.hasMoreElements()) {
- const win = e.getNext();
- const windowUtils = win.windowUtils;
+ for (const {windowUtils} of Services.wm.getEnumerator(null)) {
windowUtils.suppressEventHandling(true);
windowUtils.suspendTimeouts();
}
},
postNest: function() {
- const e = Services.wm.getEnumerator(null);
- while (e.hasMoreElements()) {
- const win = e.getNext();
- const windowUtils = win.windowUtils;
+ for (const {windowUtils} of Services.wm.getEnumerator(null)) {
windowUtils.resumeTimeouts();
windowUtils.suppressEventHandling(false);
}
diff --git a/devtools/server/actors/targets/browsing-context.js b/devtools/server/actors/targets/browsing-context.js
index 930166586dc6..211a9454be0a 100644
--- a/devtools/server/actors/targets/browsing-context.js
+++ b/devtools/server/actors/targets/browsing-context.js
@@ -77,9 +77,7 @@ function getChildDocShells(parentDocShell) {
);
const docShells = [];
- while (docShellsEnum.hasMoreElements()) {
- const docShell = docShellsEnum.getNext();
- docShell.QueryInterface(Ci.nsIDocShell);
+ for (const docShell of docShellsEnum) {
docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
docShells.push(docShell);
diff --git a/devtools/server/actors/targets/content-process.js b/devtools/server/actors/targets/content-process.js
index 92366fcb40f5..f1c786de434b 100644
--- a/devtools/server/actors/targets/content-process.js
+++ b/devtools/server/actors/targets/content-process.js
@@ -38,14 +38,8 @@ function ContentProcessTargetActor(connection) {
const sandboxPrototype = {
get tabs() {
- const tabs = [];
- const windowEnumerator = Services.ww.getWindowEnumerator();
- while (windowEnumerator.hasMoreElements()) {
- const window = windowEnumerator.getNext().QueryInterface(Ci.nsIDOMWindow);
- const tabChildGlobal = window.docShell.messageManager;
- tabs.push(tabChildGlobal);
- }
- return tabs;
+ return Array.from(Services.ww.getWindowEnumerator(),
+ win => win.docShell.messageManager);
},
};
diff --git a/devtools/server/actors/targets/parent-process.js b/devtools/server/actors/targets/parent-process.js
index 6770e1f86c25..925418e3b0b5 100644
--- a/devtools/server/actors/targets/parent-process.js
+++ b/devtools/server/actors/targets/parent-process.js
@@ -93,10 +93,7 @@ Object.defineProperty(parentProcessTargetPrototype, "docShells", {
get: function() {
// Iterate over all top-level windows and all their docshells.
let docShells = [];
- const e = Services.ww.getWindowEnumerator();
- while (e.hasMoreElements()) {
- const window = e.getNext();
- const docShell = window.docShell;
+ for (const {docShell} of Services.ww.getWindowEnumerator()) {
docShells = docShells.concat(getChildDocShells(docShell));
}
@@ -131,10 +128,7 @@ parentProcessTargetPrototype._attach = function() {
Services.obs.addObserver(this, "chrome-webnavigation-destroy");
// Iterate over all top-level windows.
- const e = Services.ww.getWindowEnumerator();
- while (e.hasMoreElements()) {
- const window = e.getNext();
- const docShell = window.docShell;
+ for (const {docShell} of Services.ww.getWindowEnumerator()) {
if (docShell == this.docShell) {
continue;
}
@@ -152,10 +146,7 @@ parentProcessTargetPrototype._detach = function() {
Services.obs.removeObserver(this, "chrome-webnavigation-destroy");
// Iterate over all top-level windows.
- const e = Services.ww.getWindowEnumerator();
- while (e.hasMoreElements()) {
- const window = e.getNext();
- const docShell = window.docShell;
+ for (const {docShell} of Services.ww.getWindowEnumerator()) {
if (docShell == this.docShell) {
continue;
}
@@ -173,10 +164,7 @@ parentProcessTargetPrototype._detach = function() {
*/
parentProcessTargetPrototype.preNest = function() {
// Disable events in all open windows.
- const e = Services.wm.getEnumerator(null);
- while (e.hasMoreElements()) {
- const win = e.getNext();
- const windowUtils = win.windowUtils;
+ for (const {windowUtils} of Services.wm.getEnumerator(null)) {
windowUtils.suppressEventHandling(true);
windowUtils.suspendTimeouts();
}
@@ -187,10 +175,7 @@ parentProcessTargetPrototype.preNest = function() {
*/
parentProcessTargetPrototype.postNest = function(nestData) {
// Enable events in all open windows.
- const e = Services.wm.getEnumerator(null);
- while (e.hasMoreElements()) {
- const win = e.getNext();
- const windowUtils = win.windowUtils;
+ for (const {windowUtils} of Services.wm.getEnumerator(null)) {
windowUtils.resumeTimeouts();
windowUtils.suppressEventHandling(false);
}
diff --git a/devtools/server/actors/targets/webextension.js b/devtools/server/actors/targets/webextension.js
index 3fe9a0e6438e..d6abce8bdbbc 100644
--- a/devtools/server/actors/targets/webextension.js
+++ b/devtools/server/actors/targets/webextension.js
@@ -188,10 +188,7 @@ webExtensionTargetPrototype._destroyFallbackWindow = function() {
// windowless browser when running in non-oop mode, and the background page
// is set later using _onNewExtensionWindow.
webExtensionTargetPrototype._searchForExtensionWindow = function() {
- const e = Services.ww.getWindowEnumerator(null);
- while (e.hasMoreElements()) {
- const window = e.getNext();
-
+ for (const window of Services.ww.getWindowEnumerator(null)) {
if (window.document.nodePrincipal.addonId == this.id) {
return window;
}
diff --git a/devtools/server/actors/webbrowser.js b/devtools/server/actors/webbrowser.js
index fb302022b553..ba8beb1b9c92 100644
--- a/devtools/server/actors/webbrowser.js
+++ b/devtools/server/actors/webbrowser.js
@@ -24,20 +24,6 @@ loader.lazyImporter(this, "AddonManager", "resource://gre/modules/AddonManager.j
* Browser-specific actors.
*/
-/**
- * Yield all windows of type |windowType|, from the oldest window to the
- * youngest, using nsIWindowMediator::getEnumerator. We're usually
- * interested in "navigator:browser" windows.
- */
-function* allAppShellDOMWindows(windowType) {
- const e = Services.wm.getEnumerator(windowType);
- while (e.hasMoreElements()) {
- yield e.getNext();
- }
-}
-
-exports.allAppShellDOMWindows = allAppShellDOMWindows;
-
/**
* Retrieve the window type of the top-level window |window|.
*/
@@ -50,7 +36,7 @@ function appShellDOMWindowType(window) {
* Send Debugger:Shutdown events to all "navigator:browser" windows.
*/
function sendShutdownEvent() {
- for (const win of allAppShellDOMWindows(DebuggerServer.chromeWindowType)) {
+ for (const win of Services.wm.getEnumerator(DebuggerServer.chromeWindowType)) {
const evt = win.document.createEvent("Event");
evt.initEvent("Debugger:Shutdown", true, false);
win.document.documentElement.dispatchEvent(evt);
@@ -228,7 +214,7 @@ BrowserTabList.prototype._getSelectedBrowser = function(window) {
*/
BrowserTabList.prototype._getBrowsers = function* () {
// Iterate over all navigator:browser XUL windows.
- for (const win of allAppShellDOMWindows(DebuggerServer.chromeWindowType)) {
+ for (const win of Services.wm.getEnumerator(DebuggerServer.chromeWindowType)) {
// For each tab in this XUL window, ensure that we have an actor for
// it, reusing existing actors where possible.
for (const browser of this._getChildren(win)) {
@@ -488,7 +474,7 @@ BrowserTabList.prototype._listenForEventsIf =
function(shouldListen, guard, eventNames) {
if (!shouldListen !== !this[guard]) {
const op = shouldListen ? "addEventListener" : "removeEventListener";
- for (const win of allAppShellDOMWindows(DebuggerServer.chromeWindowType)) {
+ for (const win of Services.wm.getEnumerator(DebuggerServer.chromeWindowType)) {
for (const name of eventNames) {
win[op](name, this, false);
}
@@ -512,7 +498,7 @@ BrowserTabList.prototype._listenForMessagesIf =
function(shouldListen, guard, messageNames) {
if (!shouldListen !== !this[guard]) {
const op = shouldListen ? "addMessageListener" : "removeMessageListener";
- for (const win of allAppShellDOMWindows(DebuggerServer.chromeWindowType)) {
+ for (const win of Services.wm.getEnumerator(DebuggerServer.chromeWindowType)) {
for (const name of messageNames) {
win.messageManager[op](name, this);
}
diff --git a/devtools/server/actors/worker/worker-list.js b/devtools/server/actors/worker/worker-list.js
index 1b8f4e216d43..5f6038ce1159 100644
--- a/devtools/server/actors/worker/worker-list.js
+++ b/devtools/server/actors/worker/worker-list.js
@@ -53,9 +53,7 @@ WorkerTargetActorList.prototype = {
getList() {
// Create a set of debuggers.
const dbgs = new Set();
- const e = wdm.getWorkerDebuggerEnumerator();
- while (e.hasMoreElements()) {
- const dbg = e.getNext().QueryInterface(Ci.nsIWorkerDebugger);
+ for (const dbg of wdm.getWorkerDebuggerEnumerator()) {
if (matchWorkerDebugger(dbg, this._options)) {
dbgs.add(dbg);
}
diff --git a/devtools/server/performance/timeline.js b/devtools/server/performance/timeline.js
index 537a50d1a827..1e0ec86fe166 100644
--- a/devtools/server/performance/timeline.js
+++ b/devtools/server/performance/timeline.js
@@ -75,7 +75,6 @@ Timeline.prototype = {
*/
get docShells() {
let originalDocShell;
- const docShells = [];
if (this.targetActor.isRootActor) {
originalDocShell = this.targetActor.docShell;
@@ -84,7 +83,7 @@ Timeline.prototype = {
}
if (!originalDocShell) {
- return docShells;
+ return [];
}
const docShellsEnum = originalDocShell.getDocShellEnumerator(
@@ -92,12 +91,7 @@ Timeline.prototype = {
Ci.nsIDocShell.ENUMERATE_FORWARDS
);
- while (docShellsEnum.hasMoreElements()) {
- const docShell = docShellsEnum.getNext();
- docShells.push(docShell.QueryInterface(Ci.nsIDocShell));
- }
-
- return docShells;
+ return Array.from(docShellsEnum);
},
/**
diff --git a/devtools/shared/system.js b/devtools/shared/system.js
index d67aeee06781..b44565216581 100644
--- a/devtools/shared/system.js
+++ b/devtools/shared/system.js
@@ -175,9 +175,7 @@ function getProfileLocation() {
const profd = Services.dirsvc.get("ProfD", Ci.nsIFile);
const profservice = Cc["@mozilla.org/toolkit/profile-service;1"]
.getService(Ci.nsIToolkitProfileService);
- const profiles = profservice.profiles;
- while (profiles.hasMoreElements()) {
- const profile = profiles.getNext().QueryInterface(Ci.nsIToolkitProfile);
+ for (const profile of profservice.profiles) {
if (profile.rootDir.path == profd.path) {
return profile.name;
}
diff --git a/devtools/startup/devtools-startup.js b/devtools/startup/devtools-startup.js
index 1fddcbadcd34..0e24e8e8f25d 100644
--- a/devtools/startup/devtools-startup.js
+++ b/devtools/startup/devtools-startup.js
@@ -500,9 +500,7 @@ DevToolsStartup.prototype = {
* item.
*/
onEnabledPrefChanged() {
- const enumerator = Services.wm.getEnumerator("navigator:browser");
- while (enumerator.hasMoreElements()) {
- const window = enumerator.getNext();
+ for (const window of Services.wm.getEnumerator("navigator:browser")) {
if (window.gBrowserInit && window.gBrowserInit.delayedStartupFinished) {
this.updateDevToolsMenuItems(window);
}
diff --git a/docshell/base/nsDocShellEnumerator.cpp b/docshell/base/nsDocShellEnumerator.cpp
index 1f870cd01feb..5d68907f9b64 100644
--- a/docshell/base/nsDocShellEnumerator.cpp
+++ b/docshell/base/nsDocShellEnumerator.cpp
@@ -21,8 +21,6 @@ nsDocShellEnumerator::~nsDocShellEnumerator()
{
}
-NS_IMPL_ISUPPORTS(nsDocShellEnumerator, nsISimpleEnumerator)
-
NS_IMETHODIMP
nsDocShellEnumerator::GetNext(nsISupports** aResult)
{
diff --git a/docshell/base/nsDocShellEnumerator.h b/docshell/base/nsDocShellEnumerator.h
index c7e3dc215231..94f5db6aa05b 100644
--- a/docshell/base/nsDocShellEnumerator.h
+++ b/docshell/base/nsDocShellEnumerator.h
@@ -7,7 +7,7 @@
#ifndef nsDocShellEnumerator_h___
#define nsDocShellEnumerator_h___
-#include "nsISimpleEnumerator.h"
+#include "nsSimpleEnumerator.h"
#include "nsTArray.h"
#include "nsIWeakReferenceUtils.h"
@@ -29,7 +29,7 @@ class nsIDocShellTreeItem;
"@mozilla.org/docshell/enumerator-backwards;1"
*/
-class nsDocShellEnumerator : public nsISimpleEnumerator
+class nsDocShellEnumerator : public nsSimpleEnumerator
{
protected:
enum
@@ -43,12 +43,11 @@ protected:
public:
explicit nsDocShellEnumerator(int32_t aEnumerationDirection);
- // nsISupports
- NS_DECL_ISUPPORTS
-
// nsISimpleEnumerator
NS_DECL_NSISIMPLEENUMERATOR
+ const nsID& DefaultInterface() override { return NS_GET_IID(nsIDocShell); }
+
public:
nsresult GetEnumerationRootItem(nsIDocShellTreeItem** aEnumerationRootItem);
nsresult SetEnumerationRootItem(nsIDocShellTreeItem* aEnumerationRootItem);
diff --git a/docshell/shistory/nsSHistory.h b/docshell/shistory/nsSHistory.h
index 52d8bc3e84f2..4c054cdb445f 100644
--- a/docshell/shistory/nsSHistory.h
+++ b/docshell/shistory/nsSHistory.h
@@ -11,9 +11,9 @@
#include "nsExpirationTracker.h"
#include "nsISHistory.h"
#include "nsISHistoryInternal.h"
-#include "nsISimpleEnumerator.h"
#include "nsIWebNavigation.h"
#include "nsSHEntryShared.h"
+#include "nsSimpleEnumerator.h"
#include "nsTObserverArray.h"
#include "nsWeakReference.h"
diff --git a/docshell/test/browser/file_bug1328501_framescript.js b/docshell/test/browser/file_bug1328501_framescript.js
index 1107f5ad4092..bf76711e2100 100644
--- a/docshell/test/browser/file_bug1328501_framescript.js
+++ b/docshell/test/browser/file_bug1328501_framescript.js
@@ -31,10 +31,5 @@ function getChildDocShells() {
Ci.nsIDocShell.ENUMERATE_FORWARDS
);
- let docShells = [];
- while (docShellsEnum.hasMoreElements()) {
- let ds = docShellsEnum.getNext();
- docShells.push(ds);
- }
- return docShells;
+ return Array.from(docShellsEnum);
}
diff --git a/docshell/test/navigation/NavigationUtils.js b/docshell/test/navigation/NavigationUtils.js
index 4822ff0e6ade..219c5cbabf39 100644
--- a/docshell/test/navigation/NavigationUtils.js
+++ b/docshell/test/navigation/NavigationUtils.js
@@ -102,12 +102,10 @@ function xpcEnumerateContentWindows(callback) {
var Ci = SpecialPowers.Ci;
var ww = SpecialPowers.Cc["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Ci.nsIWindowWatcher);
- var enumerator = ww.getWindowEnumerator();
var contentWindows = [];
- while (enumerator.hasMoreElements()) {
- var win = enumerator.getNext();
+ for (let win of ww.getWindowEnumerator()) {
if (win.isChromeWindow) {
var docshellTreeNode = win.docShell;
var childCount = docshellTreeNode.childCount;
diff --git a/dom/base/ContentFrameMessageManager.h b/dom/base/ContentFrameMessageManager.h
index 7c6f4bad8314..b4660b15a9fd 100644
--- a/dom/base/ContentFrameMessageManager.h
+++ b/dom/base/ContentFrameMessageManager.h
@@ -16,6 +16,10 @@
namespace mozilla {
namespace dom {
+#define NS_CONTENTFRAMEMESSAGEMANAGER_IID \
+{ 0x97e192a6, 0xab7a, 0x4c8f, \
+ { 0xb7, 0xdd, 0xf7, 0xec, 0x36, 0x38, 0x71, 0xb5 } }
+
/**
* Base class for implementing the WebIDL ContentFrameMessageManager class.
*/
@@ -26,6 +30,8 @@ public:
using DOMEventTargetHelper::AddRef;
using DOMEventTargetHelper::Release;
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_CONTENTFRAMEMESSAGEMANAGER_IID)
+
virtual already_AddRefed GetContent(ErrorResult& aError) = 0;
virtual already_AddRefed GetDocShell(ErrorResult& aError) = 0;
virtual already_AddRefed GetTabEventTarget() = 0;
@@ -50,6 +56,8 @@ protected:
{}
};
+NS_DEFINE_STATIC_IID_ACCESSOR(ContentFrameMessageManager, NS_CONTENTFRAMEMESSAGEMANAGER_IID)
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/base/InProcessTabChildMessageManager.cpp b/dom/base/InProcessTabChildMessageManager.cpp
index 0d2ab0be19d3..50dc6a79e45d 100644
--- a/dom/base/InProcessTabChildMessageManager.cpp
+++ b/dom/base/InProcessTabChildMessageManager.cpp
@@ -147,6 +147,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InProcessTabChildMessageManager)
NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
+ NS_INTERFACE_MAP_ENTRY(ContentFrameMessageManager)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
index f5423ab28dd4..3863bcc22f6f 100644
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2938,7 +2938,13 @@ NS_IMETHODIMP nsJSArgArray::IndexOf(uint32_t startIndex, nsISupports *element, u
return NS_ERROR_NOT_IMPLEMENTED;
}
-NS_IMETHODIMP nsJSArgArray::Enumerate(nsISimpleEnumerator **_retval)
+NS_IMETHODIMP nsJSArgArray::ScriptedEnumerate(nsIJSIID* aElemIID, uint8_t aArgc,
+ nsISimpleEnumerator** aResult)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsJSArgArray::EnumerateImpl(const nsID& aEntryIID, nsISimpleEnumerator **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
diff --git a/dom/browser-element/mochitest/browserElement_ExecuteScript.js b/dom/browser-element/mochitest/browserElement_ExecuteScript.js
index b6b0b842bcc9..334a4f8791cd 100644
--- a/dom/browser-element/mochitest/browserElement_ExecuteScript.js
+++ b/dom/browser-element/mochitest/browserElement_ExecuteScript.js
@@ -91,7 +91,7 @@ function runTest() {
ok(c(rv, 'YQ=='), `scriptId: ${scriptId++}`);
return iframe.executeScript('window.wrappedJSObject.btoa("a")', {url})
}, bail).then(bail, (error) => {
- is(error.message, 'TypeError: window.wrappedJSObject is undefined', `scriptId: ${scriptId++}`);
+ is(error.message, `TypeError: window.wrappedJSObject is undefined, can't access property "btoa" of it`, `scriptId: ${scriptId++}`);
return iframe.executeScript('42', {})
}).then(bail, error => {
is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`);
diff --git a/dom/chrome-webidl/IteratorResult.webidl b/dom/chrome-webidl/IteratorResult.webidl
new file mode 100644
index 000000000000..1fdd26810e07
--- /dev/null
+++ b/dom/chrome-webidl/IteratorResult.webidl
@@ -0,0 +1,14 @@
+/* -*- 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 https://mozilla.org/MPL/2.0/. */
+
+/**
+ * A dictionary which represents the result of a call to a next() method on a
+ * JS iterator object.
+ */
+dictionary IteratorResult {
+ required boolean done;
+ any value;
+};
diff --git a/dom/chrome-webidl/WebExtensionContentScript.webidl b/dom/chrome-webidl/WebExtensionContentScript.webidl
index 6b5d36b3c4ea..488bd82b104d 100644
--- a/dom/chrome-webidl/WebExtensionContentScript.webidl
+++ b/dom/chrome-webidl/WebExtensionContentScript.webidl
@@ -6,6 +6,9 @@ interface LoadInfo;
interface URI;
interface WindowProxy;
+typedef (MatchPatternSet or sequence) MatchPatternSetOrStringSequence;
+typedef (MatchGlob or DOMString) MatchGlobOrString;
+
[Constructor(MozDocumentMatcherInit options), ChromeOnly, Exposed=System]
interface MozDocumentMatcher {
/**
@@ -94,13 +97,13 @@ dictionary MozDocumentMatcherInit {
unsigned long long? frameID = null;
- required MatchPatternSet matches;
+ required MatchPatternSetOrStringSequence matches;
- MatchPatternSet? excludeMatches = null;
+ MatchPatternSetOrStringSequence? excludeMatches = null;
- sequence? includeGlobs = null;
+ sequence? includeGlobs = null;
- sequence? excludeGlobs = null;
+ sequence? excludeGlobs = null;
boolean hasActiveTabPermission = false;
};
diff --git a/dom/chrome-webidl/WebExtensionPolicy.webidl b/dom/chrome-webidl/WebExtensionPolicy.webidl
index b65757c34620..6fc51046eb82 100644
--- a/dom/chrome-webidl/WebExtensionPolicy.webidl
+++ b/dom/chrome-webidl/WebExtensionPolicy.webidl
@@ -134,6 +134,12 @@ interface WebExtensionPolicy {
[Throws]
void unregisterContentScript(WebExtensionContentScript script);
+ /**
+ * Injects the extension's content script into all existing matching windows.
+ */
+ [Throws]
+ void injectContentScripts();
+
/**
* Returns the list of currently active extension policies.
*/
@@ -176,11 +182,11 @@ dictionary WebExtensionInit {
required WebExtensionLocalizeCallback localizeCallback;
- required MatchPatternSet allowedOrigins;
+ required MatchPatternSetOrStringSequence allowedOrigins;
sequence permissions = [];
- sequence webAccessibleResources = [];
+ sequence webAccessibleResources = [];
sequence contentScripts = [];
diff --git a/dom/chrome-webidl/moz.build b/dom/chrome-webidl/moz.build
index d7b6b43274b9..071cbb8b88f8 100644
--- a/dom/chrome-webidl/moz.build
+++ b/dom/chrome-webidl/moz.build
@@ -34,6 +34,7 @@ WEBIDL_FILES = [
'DominatorTree.webidl',
'HeapSnapshot.webidl',
'InspectorUtils.webidl',
+ 'IteratorResult.webidl',
'MatchGlob.webidl',
'MatchPattern.webidl',
'MessageManager.webidl',
diff --git a/dom/commandhandler/nsCommandGroup.cpp b/dom/commandhandler/nsCommandGroup.cpp
index 5175ef0a3ea9..a81e11daec33 100644
--- a/dom/commandhandler/nsCommandGroup.cpp
+++ b/dom/commandhandler/nsCommandGroup.cpp
@@ -7,7 +7,7 @@
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsTArray.h"
-#include "nsISimpleEnumerator.h"
+#include "nsSimpleEnumerator.h"
#include "nsXPCOM.h"
#include "nsSupportsPrimitives.h"
#include "nsIComponentManager.h"
@@ -15,17 +15,21 @@
#include "nsIControllerCommand.h"
#include "nsCRT.h"
-class nsGroupsEnumerator : public nsISimpleEnumerator
+class nsGroupsEnumerator : public nsSimpleEnumerator
{
public:
explicit nsGroupsEnumerator(
nsControllerCommandGroup::GroupsHashtable& aInHashTable);
- NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
+ const nsID& DefaultInterface() override
+ {
+ return NS_GET_IID(nsISupportsCString);
+ }
+
protected:
- virtual ~nsGroupsEnumerator();
+ ~nsGroupsEnumerator() override;
nsresult Initialize();
@@ -36,9 +40,6 @@ protected:
bool mInitted;
};
-/* Implementation file */
-NS_IMPL_ISUPPORTS(nsGroupsEnumerator, nsISimpleEnumerator)
-
nsGroupsEnumerator::nsGroupsEnumerator(
nsControllerCommandGroup::GroupsHashtable& aInHashTable)
: mHashTable(aInHashTable)
@@ -125,16 +126,20 @@ nsGroupsEnumerator::Initialize()
return NS_OK;
}
-class nsNamedGroupEnumerator : public nsISimpleEnumerator
+class nsNamedGroupEnumerator : public nsSimpleEnumerator
{
public:
explicit nsNamedGroupEnumerator(nsTArray* aInArray);
- NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
+ const nsID& DefaultInterface() override
+ {
+ return NS_GET_IID(nsISupportsCString);
+ }
+
protected:
- virtual ~nsNamedGroupEnumerator();
+ ~nsNamedGroupEnumerator() override;
nsTArray* mGroupArray;
int32_t mIndex;
@@ -150,8 +155,6 @@ nsNamedGroupEnumerator::~nsNamedGroupEnumerator()
{
}
-NS_IMPL_ISUPPORTS(nsNamedGroupEnumerator, nsISimpleEnumerator)
-
NS_IMETHODIMP
nsNamedGroupEnumerator::HasMoreElements(bool* aResult)
{
diff --git a/dom/html/test/file_cookiemanager.js b/dom/html/test/file_cookiemanager.js
index 281d2a8dc5dc..c8f9cfd0f249 100644
--- a/dom/html/test/file_cookiemanager.js
+++ b/dom/html/test/file_cookiemanager.js
@@ -3,9 +3,7 @@ addMessageListener("getCookieFromManager", ({ host, path }) => {
.getService(Ci.nsICookieManager);
let values = [];
path = path.substring(0, path.lastIndexOf("/") + 1);
- let e = cm.enumerator;
- while (e.hasMoreElements()) {
- let cookie = e.getNext().QueryInterface(Ci.nsICookie);
+ for (let cookie of cm.enumerator) {
if (!cookie) {
break;
}
diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
index 22038a36b20f..58ce9c672263 100644
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -17124,7 +17124,7 @@ FileManager::InitDirectory(nsIFile* aDirectory,
return NS_ERROR_FAILURE;
}
- nsCOMPtr entries;
+ nsCOMPtr entries;
rv = journalDirectory->GetDirectoryEntries(getter_AddRefs(entries));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp
index 511ebf884c21..ea3998f9f22f 100644
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -90,6 +90,7 @@
#include "nsISimpleEnumerator.h"
#include "nsIStringBundle.h"
#include "nsIWorkerDebuggerManager.h"
+#include "nsGeolocation.h"
#if !defined(XP_WIN)
#include "mozilla/Omnijar.h"
@@ -2626,8 +2627,8 @@ ContentChild::RecvUpdateSharedData(const FileDescriptor& aMapFile,
mozilla::ipc::IPCResult
ContentChild::RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition)
{
- nsCOMPtr gs =
- do_GetService("@mozilla.org/geolocation/service;1");
+ RefPtr gs =
+ nsGeolocationService::GetGeolocationService();
if (!gs) {
return IPC_OK();
}
@@ -2638,8 +2639,8 @@ ContentChild::RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition)
mozilla::ipc::IPCResult
ContentChild::RecvGeolocationError(const uint16_t& errorCode)
{
- nsCOMPtr gs =
- do_GetService("@mozilla.org/geolocation/service;1");
+ RefPtr gs =
+ nsGeolocationService::GetGeolocationService();
if (!gs) {
return IPC_OK();
}
diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp
index f138e7f72d83..0f07c36d5582 100644
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -3563,6 +3563,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildMessageManager)
NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
+ NS_INTERFACE_MAP_ENTRY(ContentFrameMessageManager)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
diff --git a/dom/media/gmp/GMPUtils.h b/dom/media/gmp/GMPUtils.h
index 628b68561797..c6f9d18a6053 100644
--- a/dom/media/gmp/GMPUtils.h
+++ b/dom/media/gmp/GMPUtils.h
@@ -18,7 +18,7 @@
#define CHROMIUM_CDM_API "chromium-cdm9-host4"
class nsIFile;
-class nsISimpleEnumerator;
+class nsIDirectoryEnumerator;
namespace mozilla {
@@ -62,7 +62,7 @@ public:
private:
Mode mMode;
- nsCOMPtr mIter;
+ nsCOMPtr mIter;
};
class GMPInfoFileParser {
diff --git a/dom/payments/PaymentRequestService.cpp b/dom/payments/PaymentRequestService.cpp
index ee37fc8aaf33..a54b82f3989f 100644
--- a/dom/payments/PaymentRequestService.cpp
+++ b/dom/payments/PaymentRequestService.cpp
@@ -8,6 +8,7 @@
#include "PaymentRequestData.h"
#include "PaymentRequestService.h"
#include "BasicCardPayment.h"
+#include "nsSimpleEnumerator.h"
namespace mozilla {
namespace dom {
@@ -16,22 +17,25 @@ StaticRefPtr gPaymentService;
namespace {
-class PaymentRequestEnumerator final : public nsISimpleEnumerator
+class PaymentRequestEnumerator final : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
PaymentRequestEnumerator()
: mIndex(0)
{}
+
+ const nsID& DefaultInterface() override
+ {
+ return NS_GET_IID(nsIPaymentRequest);
+ }
+
private:
- ~PaymentRequestEnumerator() = default;
+ ~PaymentRequestEnumerator() override = default;
uint32_t mIndex;
};
-NS_IMPL_ISUPPORTS(PaymentRequestEnumerator, nsISimpleEnumerator)
-
NS_IMETHODIMP
PaymentRequestEnumerator::HasMoreElements(bool* aReturn)
{
diff --git a/dom/payments/test/CleanupChromeScript.js b/dom/payments/test/CleanupChromeScript.js
index 301c2f105d0f..44fa195518ba 100644
--- a/dom/payments/test/CleanupChromeScript.js
+++ b/dom/payments/test/CleanupChromeScript.js
@@ -28,20 +28,16 @@ var setPaymentNums = 0;
addMessageListener("payment-num-set", function() {
setPaymentNums = 0;
- const paymentEnum = paymentSrv.enumerate();
- while (paymentEnum.hasMoreElements()) {
+ for (let payment of paymentSrv.enumerate()) {
setPaymentNums = setPaymentNums + 1;
- paymentEnum.getNext();
}
sendAsyncMessage("payment-num-set-complete");
});
addMessageListener("payment-num-check", function(expectedNumPayments) {
- const paymentEnum = paymentSrv.enumerate();
let numPayments = 0;
- while (paymentEnum.hasMoreElements()) {
+ for (let payment of paymentSrv.enumerate()) {
numPayments = numPayments + 1;
- paymentEnum.getNext();
}
if (numPayments !== expectedNumPayments + setPaymentNums) {
emitTestFail("Expected '" + expectedNumPayments +
diff --git a/dom/payments/test/ConstructorChromeScript.js b/dom/payments/test/ConstructorChromeScript.js
index bb1990425b62..9ce4448db547 100644
--- a/dom/payments/test/ConstructorChromeScript.js
+++ b/dom/payments/test/ConstructorChromeScript.js
@@ -353,8 +353,7 @@ function checkSimplestRequestHandler() {
if (!paymentEnum.hasMoreElements()) {
emitTestFail("PaymentRequestService should have at least one payment request.");
}
- while (paymentEnum.hasMoreElements()) {
- let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ for (let payRequest of paymentEnum) {
if (!payRequest) {
emitTestFail("Fail to get existing payment request.");
break;
@@ -370,8 +369,7 @@ function checkComplexRequestHandler() {
if (!paymentEnum.hasMoreElements()) {
emitTestFail("PaymentRequestService should have at least one payment request.");
}
- while (paymentEnum.hasMoreElements()) {
- let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ for (let payRequest of paymentEnum) {
if (!payRequest) {
emitTestFail("Fail to get existing payment request.");
break;
@@ -387,8 +385,7 @@ function checkNonBasicCardRequestHandler() {
if (!paymentEnum.hasMoreElements()) {
emitTestFail("PaymentRequestService should have at least one payment request.");
}
- while (paymentEnum.hasMoreElements()) {
- let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ for (let payRequest of paymentEnum) {
if (!payRequest) {
emitTestFail("Fail to get existing payment request.");
break;
@@ -404,8 +401,7 @@ function checkMultipleRequestsHandler () {
if (!paymentEnum.hasMoreElements()) {
emitTestFail("PaymentRequestService should have at least one payment request.");
}
- while (paymentEnum.hasMoreElements()) {
- let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ for (let payRequest of paymentEnum) {
if (!payRequest) {
emitTestFail("Fail to get existing payment request.");
break;
@@ -425,8 +421,7 @@ function checkCrossOriginTopLevelPrincipalHandler() {
if (!paymentEnum.hasMoreElements()) {
emitTestFail("PaymentRequestService should have at least one payment request.");
}
- while (paymentEnum.hasMoreElements()) {
- let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ for (let payRequest of paymentEnum) {
if (!payRequest) {
emitTestFail("Fail to get existing payment request.");
break;
diff --git a/dom/payments/test/CurrencyAmountValidationChromeScript.js b/dom/payments/test/CurrencyAmountValidationChromeScript.js
index 3a24c813c4bb..3ff74c3a77de 100644
--- a/dom/payments/test/CurrencyAmountValidationChromeScript.js
+++ b/dom/payments/test/CurrencyAmountValidationChromeScript.js
@@ -36,10 +36,7 @@ function checkLowerCaseCurrency() {
"PaymentRequestService should have at least one payment request.";
sendAsyncMessage("test-fail", msg);
}
- while (paymentEnum.hasMoreElements()) {
- const payRequest = paymentEnum
- .getNext()
- .QueryInterface(Ci.nsIPaymentRequest);
+ for (let payRequest of paymentEnum) {
if (!payRequest) {
sendAsyncMessage("test-fail", "Fail to get existing payment request.");
break;
diff --git a/dom/payments/test/browser_payment_in_different_tabs.js b/dom/payments/test/browser_payment_in_different_tabs.js
index 515fc328c77d..5cc68b65a486 100644
--- a/dom/payments/test/browser_payment_in_different_tabs.js
+++ b/dom/payments/test/browser_payment_in_different_tabs.js
@@ -17,15 +17,13 @@ add_task(async () => {
const paymentSrv = Cc[
"@mozilla.org/dom/payments/payment-request-service;1"
].getService(Ci.nsIPaymentRequestService);
- ok(paymentSrv, "Fail to get PaymentRequestService.");
const paymentEnum = paymentSrv.enumerate();
ok(
paymentEnum.hasMoreElements(),
"PaymentRequestService should have at least one payment request."
);
const payments = new Set();
- while (paymentEnum.hasMoreElements()) {
- const payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ for (let payment of paymentEnum) {
ok(payment, "Fail to get existing payment request.");
checkSimplePayment(payment);
payments.add(payment);
diff --git a/dom/plugins/base/nsPluginDirServiceProvider.cpp b/dom/plugins/base/nsPluginDirServiceProvider.cpp
index abd76237c68a..15372a2ad807 100644
--- a/dom/plugins/base/nsPluginDirServiceProvider.cpp
+++ b/dom/plugins/base/nsPluginDirServiceProvider.cpp
@@ -62,7 +62,7 @@ nsPluginDirServiceProvider::GetPLIDDirectories(nsISimpleEnumerator **aEnumerator
GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, dirs);
GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, dirs);
- return NS_NewArrayEnumerator(aEnumerator, dirs);
+ return NS_NewArrayEnumerator(aEnumerator, dirs, NS_GET_IID(nsIFile));
}
nsresult
diff --git a/dom/plugins/test/unit/head_plugins.js b/dom/plugins/test/unit/head_plugins.js
index 8acaa902b247..c545cd532be7 100644
--- a/dom/plugins/test/unit/head_plugins.js
+++ b/dom/plugins/test/unit/head_plugins.js
@@ -16,9 +16,7 @@ function allow_all_plugins() {
// Finds the test plugin library
function get_test_plugin(secondplugin=false) {
- var pluginEnum = gDirSvc.get("APluginsDL", Ci.nsISimpleEnumerator);
- while (pluginEnum.hasMoreElements()) {
- let dir = pluginEnum.getNext().QueryInterface(Ci.nsIFile);
+ for (let dir of gDirSvc.get("APluginsDL", Ci.nsISimpleEnumerator)) {
let name = get_platform_specific_plugin_name(secondplugin);
let plugin = dir.clone();
plugin.append(name);
@@ -100,9 +98,7 @@ function get_platform_specific_plugin_suffix() {
function get_test_plugin_no_symlink() {
let dirSvc = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties);
- let pluginEnum = dirSvc.get("APluginsDL", Ci.nsISimpleEnumerator);
- while (pluginEnum.hasMoreElements()) {
- let dir = pluginEnum.getNext().QueryInterface(Ci.nsIFile);
+ for (let dir of dirSvc.get("APluginsDL", Ci.nsISimpleEnumerator)) {
let plugin = dir.clone();
plugin.append(get_platform_specific_plugin_name());
if (plugin.exists()) {
diff --git a/dom/promise/Promise-inl.h b/dom/promise/Promise-inl.h
new file mode 100644
index 000000000000..b96f2efcb543
--- /dev/null
+++ b/dom/promise/Promise-inl.h
@@ -0,0 +1,166 @@
+/* -*- 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/. */
+
+#ifndef mozilla_dom_Promise_inl_h
+#define mozilla_dom_Promise_inl_h
+
+#include "mozilla/TupleCycleCollection.h"
+#include "mozilla/TypeTraits.h"
+#include "mozilla/ResultExtensions.h"
+#include "mozilla/dom/PromiseNativeHandler.h"
+
+namespace mozilla {
+namespace dom {
+
+class PromiseNativeThenHandlerBase : public PromiseNativeHandler
+{
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(PromiseNativeThenHandlerBase)
+
+ PromiseNativeThenHandlerBase(Promise& aPromise)
+ : mPromise(&aPromise)
+ {}
+
+ void
+ ResolvedCallback(JSContext* aCx, JS::Handle aValue) override;
+
+ void
+ RejectedCallback(JSContext* aCx, JS::Handle aValue) override;
+
+protected:
+ virtual ~PromiseNativeThenHandlerBase() = default;
+
+ virtual already_AddRefed
+ CallResolveCallback(JSContext* aCx, JS::Handle aValue) = 0;
+
+ virtual void Traverse(nsCycleCollectionTraversalCallback&) = 0;
+ virtual void Unlink() = 0;
+
+ RefPtr mPromise;
+};
+
+namespace {
+
+template ::Type>::value,
+ bool = (IsConvertible::value ||
+ IsConvertible::value)>
+struct StorageTypeHelper
+{
+ using Type = T;
+};
+
+template
+struct StorageTypeHelper
+{
+ using Type = nsCOMPtr;
+};
+
+template
+struct StorageTypeHelper, true, true>
+{
+ using Type = nsCOMPtr;
+};
+
+template
+struct StorageTypeHelper
+{
+ using Type = RefPtr;
+};
+
+template class SmartPtr, typename T>
+struct StorageTypeHelper, true, false>
+ : EnableIf, T*>::value,
+ RefPtr>
+{
+};
+
+template
+using StorageType = typename StorageTypeHelper::Type>::Type;
+
+using ::ImplCycleCollectionUnlink;
+
+template
+class NativeThenHandler final : public PromiseNativeThenHandlerBase
+{
+public:
+ NativeThenHandler(Promise& aPromise, Callback&& aOnResolve,
+ Args&&... aArgs)
+ : PromiseNativeThenHandlerBase(aPromise)
+ , mOnResolve(std::forward(aOnResolve))
+ , mArgs(std::forward(aArgs)...)
+ {}
+
+protected:
+ void Traverse(nsCycleCollectionTraversalCallback& cb) override
+ {
+ auto* tmp = this;
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArgs)
+ }
+
+ void Unlink() override
+ {
+ auto* tmp = this;
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mArgs)
+ }
+
+ already_AddRefed
+ CallResolveCallback(JSContext* aCx, JS::Handle aValue) override
+ {
+ return CallCallback(aCx, mOnResolve, aValue);
+ }
+
+ template
+ already_AddRefed
+ CallCallback(JSContext* aCx, const Callback& aHandler, JS::Handle aValue,
+ std::index_sequence)
+ {
+ return mOnResolve(aCx, aValue, std::forward(Get(mArgs))...);
+ }
+
+ already_AddRefed
+ CallCallback(JSContext* aCx, const Callback& aHandler, JS::Handle aValue)
+ {
+ return CallCallback(aCx, aHandler, aValue, std::index_sequence_for{});
+ }
+
+ Callback mOnResolve;
+
+ Tuple...> mArgs;
+};
+
+} // anonymous namespace
+
+template
+typename EnableIf<
+ Promise::IsHandlerCallback::value,
+ Result, nsresult>>::Type
+Promise::ThenWithCycleCollectedArgs(Callback&& aOnResolve, Args&&... aArgs)
+{
+ using HandlerType = NativeThenHandler;
+
+ ErrorResult rv;
+ RefPtr promise = Promise::Create(GetParentObject(), rv);
+ if (rv.Failed()) {
+ return Err(rv.StealNSResult());
+ }
+
+ auto* handler = new (fallible) HandlerType(
+ *promise, std::forward(aOnResolve),
+ std::forward(aArgs)...);
+
+ if (!handler) {
+ return Err(NS_ERROR_OUT_OF_MEMORY);
+ }
+
+ AppendNativeHandler(handler);
+ return std::move(promise);
+}
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_Promise_inl_h
diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp
index 7895de1e0234..635742b04f28 100644
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/Promise-inl.h"
#include "js/Debug.h"
@@ -12,6 +13,7 @@
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/Preferences.h"
+#include "mozilla/ResultExtensions.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMException.h"
@@ -226,6 +228,48 @@ Promise::Then(JSContext* aCx,
aRetval.setObject(*retval);
}
+void
+PromiseNativeThenHandlerBase::ResolvedCallback(JSContext* aCx,
+ JS::Handle aValue)
+{
+ RefPtr promise = CallResolveCallback(aCx, aValue);
+ mPromise->MaybeResolve(promise);
+}
+
+void
+PromiseNativeThenHandlerBase::RejectedCallback(JSContext* aCx,
+ JS::Handle aValue)
+{
+ mPromise->MaybeReject(aCx, aValue);
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(PromiseNativeThenHandlerBase)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PromiseNativeThenHandlerBase)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
+ tmp->Traverse(cb);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PromiseNativeThenHandlerBase)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
+ tmp->Unlink();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseNativeThenHandlerBase)
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseNativeThenHandlerBase)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseNativeThenHandlerBase)
+
+Result, nsresult>
+Promise::ThenWithoutCycleCollection(
+ const std::function(JSContext* aCx,
+ JS::HandleValue aValue)>& aCallback)
+{
+ return ThenWithCycleCollectedArgs(aCallback);
+}
+
void
Promise::CreateWrapper(JS::Handle aDesiredProto, ErrorResult& aRv)
{
diff --git a/dom/promise/Promise.h b/dom/promise/Promise.h
index 5670fdfdc8ca..fb90094a3ff5 100644
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -25,6 +25,7 @@
class nsIGlobalObject;
namespace mozilla {
+
namespace dom {
class AnyCallback;
@@ -142,6 +143,40 @@ public:
JS::MutableHandle aRetval,
ErrorResult& aRv);
+ template
+ using IsHandlerCallback =
+ IsSame,
+ decltype(DeclVal()(
+ (JSContext*)(nullptr),
+ DeclVal>(),
+ DeclVal()...))>;
+
+ // Similar to the JavaScript Then() function. Accepts a single lambda function
+ // argument, which it attaches as a native resolution handler, and returns a
+ // new promise which resolves with that handler's return value, or propagates
+ // any rejections from this promise.
+ //
+ // Any additional arguments passed after the callback function are stored and
+ // passed as additional arguments to the function when it is called. These
+ // values will participate in cycle collection for the promise handler, and
+ // therefore may safely form reference cycles with the promise chain.
+ //
+ // Any strong references required by the callback should be passed in this
+ // manner, rather than using lambda capture, lambda captures do not support
+ // cycle collection, and can easily lead to leaks.
+ //
+ // Does not currently support rejection handlers.
+ template
+ typename EnableIf<
+ IsHandlerCallback::value,
+ Result, nsresult>>::Type
+ ThenWithCycleCollectedArgs(Callback&& aOnResolve, Args&&... aArgs);
+
+ Result, nsresult>
+ ThenWithoutCycleCollection(
+ const std::function(JSContext*,
+ JS::HandleValue)>& aCallback);
+
JSObject* PromiseObj() const
{
return mPromiseObj;
diff --git a/dom/promise/moz.build b/dom/promise/moz.build
index 03f38c35dc1c..c465dc7b961b 100644
--- a/dom/promise/moz.build
+++ b/dom/promise/moz.build
@@ -8,6 +8,7 @@ with Files("**"):
BUG_COMPONENT = ("Core", "DOM")
EXPORTS.mozilla.dom += [
+ 'Promise-inl.h',
'Promise.h',
'PromiseDebugging.h',
'PromiseNativeHandler.h',
diff --git a/dom/push/PushRecord.jsm b/dom/push/PushRecord.jsm
index 99cdc36de9dc..c38ba89b6a09 100644
--- a/dom/push/PushRecord.jsm
+++ b/dom/push/PushRecord.jsm
@@ -182,9 +182,7 @@ PushRecord.prototype = {
},
isTabOpen() {
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- let window = windows.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (window.closed || PrivateBrowsingUtils.isWindowPrivate(window)) {
continue;
}
diff --git a/dom/quota/ActorsParent.cpp b/dom/quota/ActorsParent.cpp
index 0bf8985ea467..8af6361370e9 100644
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -4883,7 +4883,7 @@ QuotaManager::MaybeRemoveLocalStorageDirectories()
return NS_OK;
}
- nsCOMPtr entries;
+ nsCOMPtr entries;
rv = defaultStorageDir->GetDirectoryEntries(getter_AddRefs(entries));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
diff --git a/dom/u2f/tests/frame_appid_facet_insecure.html b/dom/u2f/tests/frame_appid_facet_insecure.html
index 01d29e8d75e2..562e28afbb4f 100644
--- a/dom/u2f/tests/frame_appid_facet_insecure.html
+++ b/dom/u2f/tests/frame_appid_facet_insecure.html
@@ -33,7 +33,7 @@ async function doTests() {
local_ok(false, "Callbacks should not be called.");
});
} catch (err) {
- local_ok(err == "TypeError: window.u2f is undefined", "accessing window.u2f should have thrown from an insecure origin");
+ local_ok(err.toString().includes("TypeError: window.u2f is undefined"), "accessing window.u2f should have thrown from an insecure origin");
}
try {
diff --git a/dom/workers/WorkerDebuggerManager.cpp b/dom/workers/WorkerDebuggerManager.cpp
index d624f0f85a50..f928ec79f34b 100644
--- a/dom/workers/WorkerDebuggerManager.cpp
+++ b/dom/workers/WorkerDebuggerManager.cpp
@@ -6,7 +6,7 @@
#include "WorkerDebuggerManager.h"
-#include "nsISimpleEnumerator.h"
+#include "nsSimpleEnumerator.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/StaticPtr.h"
@@ -76,7 +76,7 @@ static StaticRefPtr gWorkerDebuggerManager;
} /* anonymous namespace */
-class WorkerDebuggerEnumerator final : public nsISimpleEnumerator
+class WorkerDebuggerEnumerator final : public nsSimpleEnumerator
{
nsTArray> mDebuggers;
uint32_t mIndex;
@@ -88,14 +88,16 @@ public:
{
}
- NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
-private:
- ~WorkerDebuggerEnumerator() {}
-};
+ const nsID& DefaultInterface() override
+ {
+ return NS_GET_IID(nsIWorkerDebugger);
+ }
-NS_IMPL_ISUPPORTS(WorkerDebuggerEnumerator, nsISimpleEnumerator);
+private:
+ ~WorkerDebuggerEnumerator() override = default;
+};
NS_IMETHODIMP
WorkerDebuggerEnumerator::HasMoreElements(bool* aResult)
diff --git a/dom/workers/test/dom_worker_helper.js b/dom/workers/test/dom_worker_helper.js
index a457d9457264..76695d556023 100644
--- a/dom/workers/test/dom_worker_helper.js
+++ b/dom/workers/test/dom_worker_helper.js
@@ -38,12 +38,8 @@ function assertThrows(fun, message) {
ok(throws, message);
}
-function* generateDebuggers() {
- let e = wdm.getWorkerDebuggerEnumerator();
- while (e.hasMoreElements()) {
- let dbg = e.getNext().QueryInterface(Ci.nsIWorkerDebugger);
- yield dbg;
- }
+function generateDebuggers() {
+ return wdm.getWorkerDebuggerEnumerator();
}
function findDebugger(url) {
diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp
index 865d1f1b219a..06596bcd49fc 100644
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -2611,7 +2611,7 @@ NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum)
}
}
- return NS_NewArrayEnumerator(aEnum, array);
+ return NS_NewArrayEnumerator(aEnum, array, NS_GET_IID(nsIPermission));
}
NS_IMETHODIMP nsPermissionManager::GetAllForURI(nsIURI* aURI, nsISimpleEnumerator **aEnum)
@@ -2660,7 +2660,7 @@ nsPermissionManager::GetAllForPrincipal(nsIPrincipal* aPrincipal,
}
}
- return NS_NewArrayEnumerator(aEnum, array);
+ return NS_NewArrayEnumerator(aEnum, array, NS_GET_IID(nsIPermission));
}
NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
diff --git a/extensions/cookie/test/file_chromecommon.js b/extensions/cookie/test/file_chromecommon.js
index abc15eed6977..5b38ee0ffcf4 100644
--- a/extensions/cookie/test/file_chromecommon.js
+++ b/extensions/cookie/test/file_chromecommon.js
@@ -3,7 +3,7 @@ let cs = Cc["@mozilla.org/cookiemanager;1"]
addMessageListener("getCookieCountAndClear", () => {
let count = 0;
- for (let list = cs.enumerator; list.hasMoreElements(); list.getNext())
+ for (let cookie of cs.enumerator)
++count;
cs.removeAll();
diff --git a/extensions/cookie/test/file_testloadflags_chromescript.js b/extensions/cookie/test/file_testloadflags_chromescript.js
index f14996ab31ad..26619c1cadfa 100644
--- a/extensions/cookie/test/file_testloadflags_chromescript.js
+++ b/extensions/cookie/test/file_testloadflags_chromescript.js
@@ -62,9 +62,7 @@ obs.prototype = {
function getCookieCount(cs) {
let count = 0;
- let list = cs.enumerator;
- while (list.hasMoreElements()) {
- let cookie = list.getNext().QueryInterface(Ci.nsICookie);
+ for (let cookie of cs.enumerator) {
info("cookie: " + cookie);
info("cookie host " + cookie.host + " path " + cookie.path + " name " + cookie.name +
" value " + cookie.value + " isSecure " + cookie.isSecure + " expires " + cookie.expires);
diff --git a/extensions/cookie/test/unit/head_cookies.js b/extensions/cookie/test/unit/head_cookies.js
index 9890868aa356..d08d67cb6521 100644
--- a/extensions/cookie/test/unit/head_cookies.js
+++ b/extensions/cookie/test/unit/head_cookies.js
@@ -123,8 +123,8 @@ function do_set_cookies(uri, channel, session, expected) {
function do_count_enumerator(enumerator) {
let i = 0;
- while (enumerator.hasMoreElements()) {
- enumerator.getNext();
+ for (let cookie of enumerator) {
+ void cookie;
++i;
}
return i;
diff --git a/extensions/cookie/test/unit/test_bug526789.js b/extensions/cookie/test/unit/test_bug526789.js
index ff630d3cd209..57704b0ff081 100644
--- a/extensions/cookie/test/unit/test_bug526789.js
+++ b/extensions/cookie/test/unit/test_bug526789.js
@@ -185,10 +185,7 @@ function run_test() {
function getCookieCount() {
var count = 0;
var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
- var enumerator = cm.enumerator;
- while (enumerator.hasMoreElements()) {
- if (!(enumerator.getNext() instanceof Ci.nsICookie2))
- throw new Error("not a cookie");
+ for (let cookie of cm.enumerator) {
++count;
}
return count;
diff --git a/extensions/cookie/test/unit/test_domain_eviction.js b/extensions/cookie/test/unit/test_domain_eviction.js
index 50bc25f12d58..17783fc4fad5 100644
--- a/extensions/cookie/test/unit/test_domain_eviction.js
+++ b/extensions/cookie/test/unit/test_domain_eviction.js
@@ -56,10 +56,7 @@ function* do_run_test()
setCookies("tasty.horse.radish", 50, futureExpiry);
Assert.equal(countCookies("horse.radish", "horse.radish"), 50);
- let enumerator = Services.cookiemgr.enumerator;
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
-
+ for (let cookie of Services.cookiemgr.enumerator) {
if (cookie.host == "horse.radish")
do_throw("cookies not evicted by lastAccessed order");
}
@@ -77,9 +74,7 @@ function* do_run_test()
false, false, false, futureExpiry, {});
Assert.equal(countCookies("captchart.com", "captchart.com"), 50);
- enumerator = Services.cookiemgr.getCookiesFromHost("captchart.com", {});
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+ for (let cookie of Services.cookiemgr.getCookiesFromHost("captchart.com", {})) {
Assert.ok(cookie.expiry == futureExpiry);
}
@@ -104,14 +99,10 @@ setCookies(aHost, aNumber, aExpiry)
function
countCookies(aBaseDomain, aHost)
{
- let enumerator = Services.cookiemgr.enumerator;
-
// count how many cookies are within domain 'aBaseDomain' using the cookie
// enumerator.
let cookies = [];
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
-
+ for (let cookie of Services.cookiemgr.enumerator) {
if (cookie.host.length >= aBaseDomain.length &&
cookie.host.slice(cookie.host.length - aBaseDomain.length) == aBaseDomain)
cookies.push(cookie);
@@ -123,10 +114,7 @@ countCookies(aBaseDomain, aHost)
cookies.length);
Assert.equal(Services.cookiemgr.countCookiesFromHost(aHost), cookies.length);
- enumerator = Services.cookiemgr.getCookiesFromHost(aHost, {});
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
-
+ for (let cookie of Services.cookiemgr.getCookiesFromHost(aHost, {})) {
if (cookie.host.length >= aBaseDomain.length &&
cookie.host.slice(cookie.host.length - aBaseDomain.length) == aBaseDomain) {
let found = false;
diff --git a/extensions/cookie/test/unit/test_eviction.js b/extensions/cookie/test/unit/test_eviction.js
index e59797871c2f..415b3b9b673f 100644
--- a/extensions/cookie/test/unit/test_eviction.js
+++ b/extensions/cookie/test/unit/test_eviction.js
@@ -231,11 +231,8 @@ function get_creationTime(i)
// time, if both the limit on total cookies (maxNumber + 10%) and the purge age
// + 10% are exceeded.
function check_remaining_cookies(aNumberTotal, aNumberOld, aNumberToExpect) {
- var enumerator = Services.cookiemgr.enumerator;
-
let i = 0;
- while (enumerator.hasMoreElements()) {
- var cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+ for (let cookie of Services.cookiemgr.enumerator) {
++i;
if (aNumberTotal != aNumberToExpect) {
diff --git a/extensions/cookie/test/unit/test_permmanager_defaults.js b/extensions/cookie/test/unit/test_permmanager_defaults.js
index 38c526773e09..50e74ff9c36a 100644
--- a/extensions/cookie/test/unit/test_permmanager_defaults.js
+++ b/extensions/cookie/test/unit/test_permmanager_defaults.js
@@ -215,9 +215,7 @@ add_task(async function do_test() {
// be found.
function findCapabilityViaEnum(origin = TEST_ORIGIN, type = TEST_PERMISSION) {
let result = undefined;
- let e = Services.perms.enumerator;
- while (e.hasMoreElements()) {
- let perm = e.getNext().QueryInterface(Ci.nsIPermission);
+ for (let perm of Services.perms.enumerator) {
if (perm.matchesURI(origin, true) &&
perm.type == type) {
if (result !== undefined) {
diff --git a/extensions/cookie/test/unit/test_permmanager_migrate_4-7.js b/extensions/cookie/test/unit/test_permmanager_migrate_4-7.js
index 3e87d03e6a92..ba8f03cd6d17 100644
--- a/extensions/cookie/test/unit/test_permmanager_migrate_4-7.js
+++ b/extensions/cookie/test/unit/test_permmanager_migrate_4-7.js
@@ -159,9 +159,7 @@ add_task(async function test() {
await PlacesTestUtils.addVisits(Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory"));
// Force initialization of the nsPermissionManager
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let permission of Services.perms.enumerator) {
let isExpected = false;
expected.forEach((it, i) => {
diff --git a/extensions/cookie/test/unit/test_permmanager_migrate_4-7_no_history.js b/extensions/cookie/test/unit/test_permmanager_migrate_4-7_no_history.js
index e19e4fa8b9b3..a62def2d89e7 100644
--- a/extensions/cookie/test/unit/test_permmanager_migrate_4-7_no_history.js
+++ b/extensions/cookie/test/unit/test_permmanager_migrate_4-7_no_history.js
@@ -176,9 +176,7 @@ add_task(function test() {
let found = expected.map((it) => 0);
// Force initialization of the nsPermissionManager
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let permission of Services.perms.enumerator) {
let isExpected = false;
expected.forEach((it, i) => {
diff --git a/extensions/cookie/test/unit/test_permmanager_migrate_5-7a.js b/extensions/cookie/test/unit/test_permmanager_migrate_5-7a.js
index 51165a47184a..45de4c1a86d8 100644
--- a/extensions/cookie/test/unit/test_permmanager_migrate_5-7a.js
+++ b/extensions/cookie/test/unit/test_permmanager_migrate_5-7a.js
@@ -218,9 +218,7 @@ add_task(async function test() {
await PlacesTestUtils.addVisits(Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory"));
// Force initialization of the nsPermissionManager
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let permission of Services.perms.enumerator) {
let isExpected = false;
expected.forEach((it, i) => {
diff --git a/extensions/cookie/test/unit/test_permmanager_migrate_5-7b.js b/extensions/cookie/test/unit/test_permmanager_migrate_5-7b.js
index c1a32e236116..0949887a2dcc 100644
--- a/extensions/cookie/test/unit/test_permmanager_migrate_5-7b.js
+++ b/extensions/cookie/test/unit/test_permmanager_migrate_5-7b.js
@@ -100,9 +100,7 @@ add_task(function test() {
let found = expected.map((it) => 0);
// Force initialization of the nsPermissionManager
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let permission of Services.perms.enumerator) {
let isExpected = false;
expected.forEach((it, i) => {
diff --git a/extensions/cookie/test/unit/test_permmanager_migrate_6-7a.js b/extensions/cookie/test/unit/test_permmanager_migrate_6-7a.js
index e99298ea6f9b..d5392f90e88d 100644
--- a/extensions/cookie/test/unit/test_permmanager_migrate_6-7a.js
+++ b/extensions/cookie/test/unit/test_permmanager_migrate_6-7a.js
@@ -218,9 +218,7 @@ add_task(async function test() {
await PlacesTestUtils.addVisits(Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory"));
// Force initialization of the nsPermissionManager
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let permission of Services.perms.enumerator) {
let isExpected = false;
expected.forEach((it, i) => {
diff --git a/extensions/cookie/test/unit/test_permmanager_migrate_6-7b.js b/extensions/cookie/test/unit/test_permmanager_migrate_6-7b.js
index b0b42339461d..0e7e53b46969 100644
--- a/extensions/cookie/test/unit/test_permmanager_migrate_6-7b.js
+++ b/extensions/cookie/test/unit/test_permmanager_migrate_6-7b.js
@@ -94,9 +94,7 @@ add_task(function test() {
let found = expected.map((it) => 0);
// Force initialization of the nsPermissionManager
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let permission of Services.perms.enumerator) {
let isExpected = false;
expected.forEach((it, i) => {
diff --git a/extensions/cookie/test/unit/test_permmanager_migrate_7-8.js b/extensions/cookie/test/unit/test_permmanager_migrate_7-8.js
index 8f026c22fb3d..808c0a40fca0 100644
--- a/extensions/cookie/test/unit/test_permmanager_migrate_7-8.js
+++ b/extensions/cookie/test/unit/test_permmanager_migrate_7-8.js
@@ -198,9 +198,7 @@ add_task(async function test() {
await PlacesTestUtils.addVisits(Services.io.newURI("https://localhost:8080"));
// Force initialization of the nsPermissionManager
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let permission of Services.perms.enumerator) {
let isExpected = false;
expected.forEach((it, i) => {
diff --git a/gfx/2d/CaptureCommandList.h b/gfx/2d/CaptureCommandList.h
index 602a374645ae..f40ba4065388 100644
--- a/gfx/2d/CaptureCommandList.h
+++ b/gfx/2d/CaptureCommandList.h
@@ -13,7 +13,6 @@
#include "DrawCommand.h"
#include "Logging.h"
-#include "RwAssert.h"
namespace mozilla {
namespace gfx {
@@ -33,7 +32,6 @@ public:
~CaptureCommandList();
CaptureCommandList& operator=(CaptureCommandList&& aOther) {
- RwAssert::Writer lock(mAssert);
mStorage = std::move(aOther.mStorage);
mLastCommand = aOther.mLastCommand;
aOther.mLastCommand = nullptr;
@@ -42,7 +40,6 @@ public:
template
T* Append() {
- RwAssert::Writer lock(mAssert);
size_t oldSize = mStorage.size();
mStorage.resize(mStorage.size() + sizeof(T) + sizeof(uint32_t));
uint8_t* nextDrawLocation = &mStorage.front() + oldSize;
@@ -55,7 +52,6 @@ public:
template
T* ReuseOrAppend() {
{ // Scope lock
- RwAssert::Writer lock(mAssert);
if (mLastCommand != nullptr &&
mLastCommand->GetType() == T::Type) {
return reinterpret_cast(mLastCommand);
@@ -87,16 +83,11 @@ public:
mCurrent(nullptr),
mEnd(nullptr)
{
- mParent.mAssert.BeginReading();
if (!mParent.mStorage.empty()) {
mCurrent = &mParent.mStorage.front();
mEnd = mCurrent + mParent.mStorage.size();
}
}
- ~iterator()
- {
- mParent.mAssert.EndReading();
- }
bool Done() const {
return mCurrent >= mEnd;
@@ -132,7 +123,6 @@ private:
private:
std::vector mStorage;
DrawingCommand* mLastCommand;
- RwAssert mAssert;
};
} // namespace gfx
diff --git a/gfx/2d/RwAssert.h b/gfx/2d/RwAssert.h
deleted file mode 100644
index 4fc52a27f2b6..000000000000
--- a/gfx/2d/RwAssert.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- 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/. */
-
-#ifndef mozilla_gfx_2d_RwAssert_h
-#define mozilla_gfx_2d_RwAssert_h
-
-#include "mozilla/Attributes.h"
-#include "mozilla/Mutex.h"
-
-namespace mozilla {
-namespace gfx {
-
-class RwAssert {
-public:
- RwAssert()
- : mLock("RwAssert::mLock")
- , mReaders(0)
- , mWriting(false)
- { }
-
- ~RwAssert()
- {
- MOZ_RELEASE_ASSERT(!mReaders && !mWriting);
- }
-
- class MOZ_RAII Writer {
- public:
- MOZ_IMPLICIT Writer(RwAssert& aAssert)
- : mAssert(aAssert)
- {
- mAssert.BeginWriting();
- }
- ~Writer()
- {
- mAssert.EndWriting();
- }
-
- private:
- RwAssert& mAssert;
- };
-
- class MOZ_RAII Reader {
- public:
- MOZ_IMPLICIT Reader(RwAssert& aAssert)
- : mAssert(aAssert)
- {
- mAssert.BeginReading();
- }
- ~Reader()
- {
- mAssert.EndReading();
- }
-
- private:
- RwAssert& mAssert;
- };
-
- void BeginWriting()
- {
- MutexAutoLock lock(mLock);
- MOZ_RELEASE_ASSERT(!mReaders && !mWriting);
- mWriting = true;
- }
-
- void EndWriting()
- {
- MutexAutoLock lock(mLock);
- MOZ_ASSERT(mWriting);
- mWriting = false;
- }
-
- void BeginReading()
- {
- MutexAutoLock lock(mLock);
- MOZ_RELEASE_ASSERT(!mWriting);
- mReaders += 1;
- }
-
- void EndReading()
- {
- MutexAutoLock lock(mLock);
- MOZ_ASSERT(mReaders > 0);
- mReaders -= 1;
- }
-
-private:
- Mutex mLock;
- uint32_t mReaders;
- bool mWriting;
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif // mozilla_gfx_2d_RwAssert_h
diff --git a/gfx/2d/ScaledFontBase.cpp b/gfx/2d/ScaledFontBase.cpp
index d36a2130b475..1a93208230cd 100644
--- a/gfx/2d/ScaledFontBase.cpp
+++ b/gfx/2d/ScaledFontBase.cpp
@@ -54,7 +54,7 @@ ScaledFont::GetDefaultAAMode()
ScaledFontBase::~ScaledFontBase()
{
#ifdef USE_SKIA
- SkSafeUnref(mTypeface);
+ SkSafeUnref(mTypeface);
#endif
#ifdef USE_CAIRO_SCALED_FONT
cairo_scaled_font_destroy(mScaledFont);
@@ -64,16 +64,30 @@ ScaledFontBase::~ScaledFontBase()
ScaledFontBase::ScaledFontBase(const RefPtr& aUnscaledFont,
Float aSize)
: ScaledFont(aUnscaledFont)
- , mSize(aSize)
-{
#ifdef USE_SKIA
- mTypeface = nullptr;
+ , mTypeface(nullptr)
#endif
#ifdef USE_CAIRO_SCALED_FONT
- mScaledFont = nullptr;
+ , mScaledFont(nullptr)
#endif
+ , mSize(aSize)
+{
}
+#ifdef USE_SKIA
+SkTypeface*
+ScaledFontBase::GetSkTypeface()
+{
+ if (!mTypeface) {
+ SkTypeface* typeface = CreateSkTypeface();
+ if (!mTypeface.compareExchange(nullptr, typeface)) {
+ SkSafeUnref(typeface);
+ }
+ }
+ return mTypeface;
+}
+#endif
+
#ifdef USE_CAIRO_SCALED_FONT
bool
ScaledFontBase::PopulateCairoScaledFont()
diff --git a/gfx/2d/ScaledFontBase.h b/gfx/2d/ScaledFontBase.h
index b442342187ef..d0adcde7751f 100644
--- a/gfx/2d/ScaledFontBase.h
+++ b/gfx/2d/ScaledFontBase.h
@@ -42,7 +42,7 @@ public:
virtual Float GetSize() const override { return mSize; }
#ifdef USE_SKIA
- virtual SkTypeface* GetSkTypeface() { return mTypeface; }
+ SkTypeface* GetSkTypeface();
#endif
#ifdef USE_CAIRO_SCALED_FONT
@@ -54,7 +54,8 @@ public:
protected:
friend class DrawTargetSkia;
#ifdef USE_SKIA
- SkTypeface* mTypeface;
+ Atomic mTypeface;
+ virtual SkTypeface* CreateSkTypeface() { return nullptr; }
SkPath GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer);
#endif
#ifdef USE_CAIRO_SCALED_FONT
diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp
index 335045b1e437..dac5ef60ce0f 100644
--- a/gfx/2d/ScaledFontDWrite.cpp
+++ b/gfx/2d/ScaledFontDWrite.cpp
@@ -172,29 +172,26 @@ ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget
#ifdef USE_SKIA
SkTypeface*
-ScaledFontDWrite::GetSkTypeface()
+ScaledFontDWrite::CreateSkTypeface()
{
- if (!mTypeface) {
- RefPtr factory = Factory::GetDWriteFactory();
- if (!factory) {
- return nullptr;
- }
-
- Float gamma = mGamma;
- // Skia doesn't support a gamma value outside of 0-4, so default to 2.2
- if (gamma < 0.0f || gamma > 4.0f) {
- gamma = 2.2f;
- }
-
- Float contrast = mContrast;
- // Skia doesn't support a contrast value outside of 0-1, so default to 1.0
- if (contrast < 0.0f || contrast > 1.0f) {
- contrast = 1.0f;
- }
-
- mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mStyle, mForceGDIMode, gamma, contrast);
+ RefPtr factory = Factory::GetDWriteFactory();
+ if (!factory) {
+ return nullptr;
}
- return mTypeface;
+
+ Float gamma = mGamma;
+ // Skia doesn't support a gamma value outside of 0-4, so default to 2.2
+ if (gamma < 0.0f || gamma > 4.0f) {
+ gamma = 2.2f;
+ }
+
+ Float contrast = mContrast;
+ // Skia doesn't support a contrast value outside of 0-1, so default to 1.0
+ if (contrast < 0.0f || contrast > 1.0f) {
+ contrast = 1.0f;
+ }
+
+ return SkCreateTypefaceFromDWriteFont(factory, mFontFace, mStyle, mForceGDIMode, gamma, contrast);
}
#endif
diff --git a/gfx/2d/ScaledFontDWrite.h b/gfx/2d/ScaledFontDWrite.h
index 47e2f38fc83b..ead945cda5c1 100644
--- a/gfx/2d/ScaledFontDWrite.h
+++ b/gfx/2d/ScaledFontDWrite.h
@@ -67,7 +67,7 @@ public:
bool ForceGDIMode() { return mForceGDIMode; }
#ifdef USE_SKIA
- SkTypeface* GetSkTypeface() override;
+ SkTypeface* CreateSkTypeface() override;
SkFontStyle mStyle;
#endif
diff --git a/gfx/2d/ScaledFontFontconfig.cpp b/gfx/2d/ScaledFontFontconfig.cpp
index 612a4dd68604..2046971c003c 100644
--- a/gfx/2d/ScaledFontFontconfig.cpp
+++ b/gfx/2d/ScaledFontFontconfig.cpp
@@ -43,13 +43,9 @@ ScaledFontFontconfig::~ScaledFontFontconfig()
}
#ifdef USE_SKIA
-SkTypeface* ScaledFontFontconfig::GetSkTypeface()
+SkTypeface* ScaledFontFontconfig::CreateSkTypeface()
{
- if (!mTypeface) {
- mTypeface = SkCreateTypefaceFromCairoFTFontWithFontconfig(mScaledFont, mPattern);
- }
-
- return mTypeface;
+ return SkCreateTypefaceFromCairoFTFontWithFontconfig(mScaledFont, mPattern);
}
#endif
diff --git a/gfx/2d/ScaledFontFontconfig.h b/gfx/2d/ScaledFontFontconfig.h
index 23b720cf991c..9e78fe1ac9e5 100644
--- a/gfx/2d/ScaledFontFontconfig.h
+++ b/gfx/2d/ScaledFontFontconfig.h
@@ -28,7 +28,7 @@ public:
FontType GetType() const override { return FontType::FONTCONFIG; }
#ifdef USE_SKIA
- SkTypeface* GetSkTypeface() override;
+ SkTypeface* CreateSkTypeface() override;
#endif
bool CanSerialize() override { return true; }
diff --git a/gfx/2d/ScaledFontFreeType.cpp b/gfx/2d/ScaledFontFreeType.cpp
index 82e15541b4e5..4aca29c2c94b 100644
--- a/gfx/2d/ScaledFontFreeType.cpp
+++ b/gfx/2d/ScaledFontFreeType.cpp
@@ -35,13 +35,9 @@ ScaledFontFreeType::ScaledFontFreeType(cairo_scaled_font_t* aScaledFont,
}
#ifdef USE_SKIA
-SkTypeface* ScaledFontFreeType::GetSkTypeface()
+SkTypeface* ScaledFontFreeType::CreateSkTypeface()
{
- if (!mTypeface) {
- mTypeface = SkCreateTypefaceFromCairoFTFont(mScaledFont);
- }
-
- return mTypeface;
+ return SkCreateTypefaceFromCairoFTFont(mScaledFont);
}
#endif
diff --git a/gfx/2d/ScaledFontFreeType.h b/gfx/2d/ScaledFontFreeType.h
index 26c2cc552f37..5ab161733fcf 100644
--- a/gfx/2d/ScaledFontFreeType.h
+++ b/gfx/2d/ScaledFontFreeType.h
@@ -27,7 +27,7 @@ public:
FontType GetType() const override { return FontType::FREETYPE; }
#ifdef USE_SKIA
- virtual SkTypeface* GetSkTypeface() override;
+ virtual SkTypeface* CreateSkTypeface() override;
#endif
bool CanSerialize() override { return true; }
diff --git a/gfx/2d/ScaledFontMac.cpp b/gfx/2d/ScaledFontMac.cpp
index 435759d45948..e97faa7b5e2e 100644
--- a/gfx/2d/ScaledFontMac.cpp
+++ b/gfx/2d/ScaledFontMac.cpp
@@ -177,21 +177,19 @@ ScaledFontMac::~ScaledFontMac()
}
#ifdef USE_SKIA
-SkTypeface* ScaledFontMac::GetSkTypeface()
+SkTypeface* ScaledFontMac::CreateSkTypeface()
{
- if (!mTypeface) {
- if (mCTFont) {
- mTypeface = SkCreateTypefaceFromCTFont(mCTFont);
- } else {
- auto unscaledMac = static_cast(GetUnscaledFont().get());
- bool dataFont = unscaledMac->IsDataFont();
- CTFontRef fontFace =
- CreateCTFontFromCGFontWithVariations(mFont, mSize, !dataFont);
- mTypeface = SkCreateTypefaceFromCTFont(fontFace);
- CFRelease(fontFace);
- }
+ if (mCTFont) {
+ return SkCreateTypefaceFromCTFont(mCTFont);
+ } else {
+ auto unscaledMac = static_cast(GetUnscaledFont().get());
+ bool dataFont = unscaledMac->IsDataFont();
+ CTFontRef fontFace =
+ CreateCTFontFromCGFontWithVariations(mFont, mSize, !dataFont);
+ SkTypeface* typeface = SkCreateTypefaceFromCTFont(fontFace);
+ CFRelease(fontFace);
+ return typeface;
}
- return mTypeface;
}
#endif
diff --git a/gfx/2d/ScaledFontMac.h b/gfx/2d/ScaledFontMac.h
index 0e3d2cadd1d9..a68a747cb243 100644
--- a/gfx/2d/ScaledFontMac.h
+++ b/gfx/2d/ScaledFontMac.h
@@ -34,7 +34,7 @@ public:
FontType GetType() const override { return FontType::MAC; }
#ifdef USE_SKIA
- SkTypeface* GetSkTypeface() override;
+ SkTypeface* CreateSkTypeface() override;
#endif
already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) override;
diff --git a/gfx/2d/ScaledFontWin.cpp b/gfx/2d/ScaledFontWin.cpp
index b5c3b2b31b06..f776ed3a1b42 100644
--- a/gfx/2d/ScaledFontWin.cpp
+++ b/gfx/2d/ScaledFontWin.cpp
@@ -122,12 +122,9 @@ ScaledFontWin::GetDefaultAAMode()
}
#ifdef USE_SKIA
-SkTypeface* ScaledFontWin::GetSkTypeface()
+SkTypeface* ScaledFontWin::CreateSkTypeface()
{
- if (!mTypeface) {
- mTypeface = SkCreateTypefaceFromLOGFONT(mLogFont);
- }
- return mTypeface;
+ return SkCreateTypefaceFromLOGFONT(mLogFont);
}
#endif
diff --git a/gfx/2d/ScaledFontWin.h b/gfx/2d/ScaledFontWin.h
index 581f3ffcbebd..79fb8d6b1bc7 100644
--- a/gfx/2d/ScaledFontWin.h
+++ b/gfx/2d/ScaledFontWin.h
@@ -28,7 +28,7 @@ public:
AntialiasMode GetDefaultAAMode() override;
#ifdef USE_SKIA
- SkTypeface* GetSkTypeface() override;
+ SkTypeface* CreateSkTypeface() override;
#endif
protected:
diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp
index 5c4cae5c78d5..31cdec52fe4a 100644
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -1896,9 +1896,9 @@ private:
RefPtr mFactory;
- nsCOMPtr mFontDir;
- nsCOMPtr mEntries;
- nsCOMPtr mCurrent;
+ nsCOMPtr mFontDir;
+ nsCOMPtr mEntries;
+ nsCOMPtr mCurrent;
};
BundledFontFileEnumerator::BundledFontFileEnumerator(IDWriteFactory *aFactory,
diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp
index d07640006be1..bf62658f7186 100644
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -602,6 +602,7 @@ WebRenderDebugPrefChangeCallback(const char* aPrefName, void*)
GFX_WEBRENDER_DEBUG(".echo-driver-messages", 1 << 8)
GFX_WEBRENDER_DEBUG(".new-frame-indicator", 1 << 9)
GFX_WEBRENDER_DEBUG(".new-scene-indicator", 1 << 10)
+ GFX_WEBRENDER_DEBUG(".show-overdraw", 1 << 11)
#undef GFX_WEBRENDER_DEBUG
gfx::gfxVars::SetWebRenderDebugFlags(flags);
diff --git a/gfx/webrender/src/clip.rs b/gfx/webrender/src/clip.rs
index 933d95588e52..e4584abad823 100644
--- a/gfx/webrender/src/clip.rs
+++ b/gfx/webrender/src/clip.rs
@@ -7,14 +7,13 @@ use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D, L
use api::{BoxShadowClipMode, LayoutToWorldScale, LineOrientation, LineStyle, LayoutTransform};
use border::{ensure_no_corner_overlap};
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
-use clip_scroll_tree::{CoordinateSystemId, SpatialNodeIndex};
+use clip_scroll_tree::{ClipScrollTree, CoordinateSystemId, SpatialNodeIndex};
use ellipse::Ellipse;
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use gpu_types::BoxShadowStretchMode;
use prim_store::{BrushClipMaskKind, ClipData, ImageMaskData};
use render_task::to_cache_size;
use resource_cache::{ImageRequest, ResourceCache};
-use spatial_node::SpatialNode;
use std::u32;
use util::{extract_inner_rect_safe, pack_as_float, recycle_vec, MatrixHelpers};
@@ -449,7 +448,7 @@ impl ClipStore {
local_prim_rect: LayoutRect,
local_prim_clip_rect: LayoutRect,
spatial_node_index: SpatialNodeIndex,
- spatial_nodes: &[SpatialNode],
+ clip_scroll_tree: &ClipScrollTree,
gpu_cache: &mut GpuCache,
resource_cache: &mut ResourceCache,
device_pixel_scale: DevicePixelScale,
@@ -461,6 +460,7 @@ impl ClipStore {
None => return None,
};
let mut current_local_clip_rect = local_prim_clip_rect;
+ let spatial_nodes = &clip_scroll_tree.spatial_nodes;
// Walk the clip chain to build local rects, and collect the
// smallest possible local clip area.
@@ -489,26 +489,16 @@ impl ClipStore {
ref_spatial_node.coordinate_system_relative_offset;
Some(ClipSpaceConversion::Offset(offset))
} else {
- // TODO(gw): We still have issues with clip nodes and primitives where
- // there is a perspective transform. We intend to fix these
- // cases as a follow up.
- let relative_transform = ref_spatial_node
- .world_content_transform
- .to_transform()
- .inverse()
- .map(|inv| {
- inv.pre_mul(&clip_spatial_node.world_content_transform.to_transform())
- });
- let inv_relative_transform = relative_transform
- .and_then(|rt| rt.inverse());
- match (relative_transform, inv_relative_transform) {
- (Some(relative_transform), Some(inv_relative_transform)) => {
- Some(ClipSpaceConversion::Transform(relative_transform, inv_relative_transform))
- }
- _ => {
- None
- }
- }
+ let xf = clip_scroll_tree.get_relative_transform(
+ clip_node.spatial_node_index,
+ spatial_node_index,
+ );
+
+ xf.and_then(|xf| {
+ xf.inverse().map(|inv| {
+ ClipSpaceConversion::Transform(xf, inv)
+ })
+ })
};
// If we can convert spaces, try to reduce the size of the region
diff --git a/gfx/webrender/src/clip_scroll_tree.rs b/gfx/webrender/src/clip_scroll_tree.rs
index 2063d0ff5b8d..2aa22290911d 100644
--- a/gfx/webrender/src/clip_scroll_tree.rs
+++ b/gfx/webrender/src/clip_scroll_tree.rs
@@ -10,6 +10,7 @@ use gpu_types::TransformPalette;
use internal_types::{FastHashMap, FastHashSet};
use print_tree::{PrintTree, PrintTreePrinter};
use scene::SceneProperties;
+use smallvec::SmallVec;
use spatial_node::{ScrollFrameInfo, SpatialNode, SpatialNodeType, StickyFrameInfo};
use util::LayoutToWorldFastTransform;
@@ -112,35 +113,54 @@ impl ClipScrollTree {
/// panic if that invariant isn't true!
pub fn get_relative_transform(
&self,
- ref_node_index: SpatialNodeIndex,
- target_node_index: SpatialNodeIndex,
- ) -> LayoutTransform {
- let ref_node = &self.spatial_nodes[ref_node_index.0];
- let target_node = &self.spatial_nodes[target_node_index.0];
+ from_node_index: SpatialNodeIndex,
+ to_node_index: SpatialNodeIndex,
+ ) -> Option {
+ let from_node = &self.spatial_nodes[from_node_index.0];
+ let to_node = &self.spatial_nodes[to_node_index.0];
- let mut offset = LayoutVector3D::new(
- target_node.coordinate_system_relative_offset.x,
- target_node.coordinate_system_relative_offset.y,
- 0.0,
- );
- let mut transform = LayoutTransform::identity();
+ let (child, parent, inverse) = if from_node_index.0 > to_node_index.0 {
+ (from_node, to_node, false)
+ } else {
+ (to_node, from_node, true)
+ };
- // Walk up the tree of coordinate systems, accumulating each
- // relative transform.
- let mut current_coordinate_system_id = target_node.coordinate_system_id;
- while current_coordinate_system_id != ref_node.coordinate_system_id {
- let coord_system = &self.coord_systems[current_coordinate_system_id.0 as usize];
+ let mut coordinate_system_id = child.coordinate_system_id;
+ let mut nodes: SmallVec<[_; 16]> = SmallVec::new();
- let relative_transform = coord_system
- .transform
- .post_translate(offset);
- transform = transform.pre_mul(&relative_transform);
-
- offset = coord_system.offset;
- current_coordinate_system_id = coord_system.parent.expect("invalid parent!");
+ while coordinate_system_id != parent.coordinate_system_id {
+ nodes.push(coordinate_system_id);
+ let coord_system = &self.coord_systems[coordinate_system_id.0 as usize];
+ coordinate_system_id = coord_system.parent.expect("invalid parent!");
}
- transform
+ nodes.reverse();
+
+ let mut transform = LayoutTransform::create_translation(
+ -parent.coordinate_system_relative_offset.x,
+ -parent.coordinate_system_relative_offset.y,
+ 0.0,
+ );
+
+ for node in nodes {
+ let coord_system = &self.coord_systems[node.0 as usize];
+ transform = transform.pre_translate(coord_system.offset)
+ .pre_mul(&coord_system.transform);
+ }
+
+ let transform = transform.post_translate(
+ LayoutVector3D::new(
+ child.coordinate_system_relative_offset.x,
+ child.coordinate_system_relative_offset.y,
+ 0.0,
+ )
+ );
+
+ if inverse {
+ transform.inverse()
+ } else {
+ Some(transform)
+ }
}
/// The root reference frame, which is the true root of the ClipScrollTree. Initially
@@ -442,3 +462,219 @@ impl ClipScrollTree {
}
}
}
+
+#[cfg(test)]
+fn add_reference_frame(
+ cst: &mut ClipScrollTree,
+ parent: Option,
+ transform: LayoutTransform,
+ origin_in_parent_reference_frame: LayoutVector2D,
+) -> SpatialNodeIndex {
+ cst.add_reference_frame(
+ parent,
+ Some(PropertyBinding::Value(transform)),
+ None,
+ origin_in_parent_reference_frame,
+ PipelineId::dummy(),
+ )
+}
+
+#[cfg(test)]
+fn test_pt(
+ px: f32,
+ py: f32,
+ cst: &ClipScrollTree,
+ from: SpatialNodeIndex,
+ to: SpatialNodeIndex,
+ expected_x: f32,
+ expected_y: f32,
+) {
+ use euclid::approxeq::ApproxEq;
+ const EPSILON: f32 = 0.0001;
+
+ let p = LayoutPoint::new(px, py);
+ let m = cst.get_relative_transform(from, to).unwrap();
+ let pt = m.transform_point2d(&p).unwrap();
+ assert!(pt.x.approx_eq_eps(&expected_x, &EPSILON) &&
+ pt.y.approx_eq_eps(&expected_y, &EPSILON),
+ "p: {:?} -> {:?}\nm={:?}",
+ p, pt, m,
+ );
+}
+
+#[test]
+fn test_cst_simple_translation() {
+ // Basic translations only
+
+ let mut cst = ClipScrollTree::new();
+
+ let root = add_reference_frame(
+ &mut cst,
+ None,
+ LayoutTransform::identity(),
+ LayoutVector2D::zero(),
+ );
+
+ let child1 = add_reference_frame(
+ &mut cst,
+ Some(root),
+ LayoutTransform::create_translation(100.0, 0.0, 0.0),
+ LayoutVector2D::zero(),
+ );
+
+ let child2 = add_reference_frame(
+ &mut cst,
+ Some(child1),
+ LayoutTransform::create_translation(0.0, 50.0, 0.0),
+ LayoutVector2D::zero(),
+ );
+
+ let child3 = add_reference_frame(
+ &mut cst,
+ Some(child2),
+ LayoutTransform::create_translation(200.0, 200.0, 0.0),
+ LayoutVector2D::zero(),
+ );
+
+ cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
+
+ test_pt(100.0, 100.0, &cst, child1, root, 200.0, 100.0);
+ test_pt(100.0, 100.0, &cst, root, child1, 0.0, 100.0);
+ test_pt(100.0, 100.0, &cst, child2, root, 200.0, 150.0);
+ test_pt(100.0, 100.0, &cst, root, child2, 0.0, 50.0);
+ test_pt(100.0, 100.0, &cst, child2, child1, 100.0, 150.0);
+ test_pt(100.0, 100.0, &cst, child1, child2, 100.0, 50.0);
+ test_pt(100.0, 100.0, &cst, child3, root, 400.0, 350.0);
+}
+
+#[test]
+fn test_cst_simple_scale() {
+ // Basic scale only
+
+ let mut cst = ClipScrollTree::new();
+
+ let root = add_reference_frame(
+ &mut cst,
+ None,
+ LayoutTransform::identity(),
+ LayoutVector2D::zero(),
+ );
+
+ let child1 = add_reference_frame(
+ &mut cst,
+ Some(root),
+ LayoutTransform::create_scale(4.0, 1.0, 1.0),
+ LayoutVector2D::zero(),
+ );
+
+ let child2 = add_reference_frame(
+ &mut cst,
+ Some(child1),
+ LayoutTransform::create_scale(1.0, 2.0, 1.0),
+ LayoutVector2D::zero(),
+ );
+
+ let child3 = add_reference_frame(
+ &mut cst,
+ Some(child2),
+ LayoutTransform::create_scale(2.0, 2.0, 1.0),
+ LayoutVector2D::zero(),
+ );
+
+ cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
+
+ test_pt(100.0, 100.0, &cst, child1, root, 400.0, 100.0);
+ test_pt(100.0, 100.0, &cst, root, child1, 25.0, 100.0);
+ test_pt(100.0, 100.0, &cst, child2, root, 400.0, 200.0);
+ test_pt(100.0, 100.0, &cst, root, child2, 25.0, 50.0);
+ test_pt(100.0, 100.0, &cst, child3, root, 800.0, 400.0);
+ test_pt(100.0, 100.0, &cst, child2, child1, 100.0, 200.0);
+ test_pt(100.0, 100.0, &cst, child1, child2, 100.0, 50.0);
+ test_pt(100.0, 100.0, &cst, child3, child1, 200.0, 400.0);
+ test_pt(100.0, 100.0, &cst, child1, child3, 50.0, 25.0);
+}
+
+#[test]
+fn test_cst_scale_translation() {
+ // Scale + translation
+
+ let mut cst = ClipScrollTree::new();
+
+ let root = add_reference_frame(
+ &mut cst,
+ None,
+ LayoutTransform::identity(),
+ LayoutVector2D::zero(),
+ );
+
+ let child1 = add_reference_frame(
+ &mut cst,
+ Some(root),
+ LayoutTransform::create_translation(100.0, 50.0, 0.0),
+ LayoutVector2D::zero(),
+ );
+
+ let child2 = add_reference_frame(
+ &mut cst,
+ Some(child1),
+ LayoutTransform::create_scale(2.0, 4.0, 1.0),
+ LayoutVector2D::zero(),
+ );
+
+ let child3 = add_reference_frame(
+ &mut cst,
+ Some(child2),
+ LayoutTransform::create_translation(200.0, -100.0, 0.0),
+ LayoutVector2D::zero(),
+ );
+
+ let child4 = add_reference_frame(
+ &mut cst,
+ Some(child3),
+ LayoutTransform::create_scale(3.0, 2.0, 1.0),
+ LayoutVector2D::zero(),
+ );
+
+ cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
+
+ test_pt(100.0, 100.0, &cst, child1, root, 200.0, 150.0);
+ test_pt(100.0, 100.0, &cst, child2, root, 300.0, 450.0);
+ test_pt(100.0, 100.0, &cst, root, child1, 0.0, 50.0);
+ test_pt(100.0, 100.0, &cst, root, child2, 0.0, 12.5);
+ test_pt(100.0, 100.0, &cst, child4, root, 1100.0, 450.0);
+ test_pt(1100.0, 450.0, &cst, root, child4, 100.0, 100.0);
+
+ test_pt(0.0, 0.0, &cst, child4, child1, 400.0, -400.0);
+ test_pt(100.0, 100.0, &cst, child4, child1, 1000.0, 400.0);
+ test_pt(100.0, 100.0, &cst, child2, child1, 200.0, 400.0);
+ test_pt(200.0, 400.0, &cst, child1, child2, 100.0, 100.0);
+
+ test_pt(100.0, 100.0, &cst, child3, child1, 400.0, 300.0);
+ test_pt(400.0, 300.0, &cst, child1, child3, 100.0, 100.0);
+}
+
+#[test]
+fn test_cst_translation_rotate() {
+ // Rotation + translation
+ use euclid::Angle;
+
+ let mut cst = ClipScrollTree::new();
+
+ let root = add_reference_frame(
+ &mut cst,
+ None,
+ LayoutTransform::identity(),
+ LayoutVector2D::zero(),
+ );
+
+ let child1 = add_reference_frame(
+ &mut cst,
+ Some(root),
+ LayoutTransform::create_rotation(0.0, 0.0, 1.0, Angle::degrees(90.0)),
+ LayoutVector2D::zero(),
+ );
+
+ cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
+
+ test_pt(100.0, 0.0, &cst, child1, root, 0.0, -100.0);
+}
diff --git a/gfx/webrender/src/glyph_rasterizer/mod.rs b/gfx/webrender/src/glyph_rasterizer/mod.rs
index 03301abfdff9..d8cefe6498a4 100644
--- a/gfx/webrender/src/glyph_rasterizer/mod.rs
+++ b/gfx/webrender/src/glyph_rasterizer/mod.rs
@@ -15,7 +15,7 @@ use rayon::ThreadPool;
use std::cmp;
use std::hash::{Hash, Hasher};
use std::mem;
-use std::sync::{Arc, Mutex, MutexGuard};
+use std::sync::{Arc, Condvar, Mutex, MutexGuard};
use std::sync::mpsc::{channel, Receiver, Sender};
#[cfg(feature = "pathfinder")]
@@ -451,6 +451,8 @@ pub struct FontContexts {
// Stored here as a convenience to get the current thread index.
#[allow(dead_code)]
workers: Arc,
+ locked_mutex: Mutex,
+ locked_cond: Condvar,
}
impl FontContexts {
@@ -478,6 +480,46 @@ impl FontContexts {
}
}
+pub trait ForEach {
+ fn for_each) + Send + 'static>(&self, f: F);
+}
+
+impl ForEach for Arc {
+ fn for_each) + Send + 'static>(&self, f: F) {
+ // Reset the locked condition.
+ let mut locked = self.locked_mutex.lock().unwrap();
+ *locked = false;
+
+ // Arc that can be safely moved into a spawn closure.
+ let font_contexts = self.clone();
+ // Spawn a new thread on which to run the for-each off the main thread.
+ self.workers.spawn(move || {
+ // Lock the shared and worker contexts up front.
+ let mut locks = Vec::with_capacity(font_contexts.num_worker_contexts() + 1);
+ locks.push(font_contexts.lock_shared_context());
+ for i in 0 .. font_contexts.num_worker_contexts() {
+ locks.push(font_contexts.lock_context(Some(i)));
+ }
+
+ // Signal the locked condition now that all contexts are locked.
+ *font_contexts.locked_mutex.lock().unwrap() = true;
+ font_contexts.locked_cond.notify_all();
+
+ // Now that everything is locked, proceed to processing each locked context.
+ for context in locks {
+ f(context);
+ }
+ });
+
+ // Wait for locked condition before resuming. Safe to proceed thereafter
+ // since any other thread that needs to use a FontContext will try to lock
+ // it first.
+ while !*locked {
+ locked = self.locked_cond.wait(locked).unwrap();
+ }
+ }
+}
+
pub struct GlyphRasterizer {
#[allow(dead_code)]
workers: Arc,
@@ -527,6 +569,8 @@ impl GlyphRasterizer {
#[cfg(feature = "pathfinder")]
pathfinder_context: create_pathfinder_font_context()?,
workers: Arc::clone(&workers),
+ locked_mutex: Mutex::new(false),
+ locked_cond: Condvar::new(),
};
Ok(GlyphRasterizer {
@@ -541,27 +585,12 @@ impl GlyphRasterizer {
}
pub fn add_font(&mut self, font_key: FontKey, template: FontTemplate) {
- let font_contexts = Arc::clone(&self.font_contexts);
- // It's important to synchronously add the font for the shared context because
- // we use it to check that fonts have been properly added when requesting glyphs.
- font_contexts
- .lock_shared_context()
- .add_font(&font_key, &template);
-
- // TODO: this locks each font context while adding the font data, probably not a big deal,
- // but if there is contention on this lock we could easily have a queue of per-context
- // operations to add and delete fonts, and have these queues lazily processed by each worker
- // before rendering a glyph.
- // We can also move this into a worker to free up some cycles in the calling (render backend)
- // thread.
- for i in 0 .. font_contexts.num_worker_contexts() {
- font_contexts
- .lock_context(Some(i))
- .add_font(&font_key, &template);
- }
-
#[cfg(feature = "pathfinder")]
self.add_font_to_pathfinder(&font_key, &template);
+
+ self.font_contexts.for_each(move |mut context| {
+ context.add_font(&font_key, &template);
+ });
}
pub fn delete_font(&mut self, font_key: FontKey) {
@@ -599,18 +628,10 @@ impl GlyphRasterizer {
return
}
- let font_contexts = Arc::clone(&self.font_contexts);
let fonts_to_remove = mem::replace(&mut self.fonts_to_remove, Vec::new());
-
- self.workers.spawn(move || {
+ self.font_contexts.for_each(move |mut context| {
for font_key in &fonts_to_remove {
- font_contexts.lock_shared_context().delete_font(font_key);
- }
- for i in 0 .. font_contexts.num_worker_contexts() {
- let mut context = font_contexts.lock_context(Some(i));
- for font_key in &fonts_to_remove {
- context.delete_font(font_key);
- }
+ context.delete_font(font_key);
}
});
}
diff --git a/gfx/webrender/src/prim_store.rs b/gfx/webrender/src/prim_store.rs
index f0021b2be124..c5826e081e89 100644
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -162,9 +162,9 @@ impl LocalRectBuilder {
CoordinateSpaceMapping::Offset(offset)
} else {
let transform = clip_scroll_tree.get_relative_transform(
- self.ref_spatial_node_index,
target_node_index,
- );
+ self.ref_spatial_node_index,
+ ).expect("bug: should have already been culled");
CoordinateSpaceMapping::Transform(transform)
};
}
@@ -1620,7 +1620,7 @@ impl PrimitiveStore {
local_rect,
prim.metadata.local_clip_rect,
prim_context.spatial_node_index,
- &frame_context.clip_scroll_tree.spatial_nodes,
+ &frame_context.clip_scroll_tree,
frame_state.gpu_cache,
frame_state.resource_cache,
frame_context.device_pixel_scale,
diff --git a/gfx/webrender_bindings/revision.txt b/gfx/webrender_bindings/revision.txt
index bea06dc48312..13626b8c2628 100644
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1 +1 @@
-e70bae07664def86aefd11c86dac818ab7ea64ea
+93997662842b6d8bafbdb3dde79009c930db66ca
diff --git a/gfx/webrender_bindings/webrender_ffi_generated.h b/gfx/webrender_bindings/webrender_ffi_generated.h
index 0c2def61b539..db42b13aab92 100644
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -2,7 +2,7 @@
* 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/. */
-/* Generated with cbindgen:0.6.0 */
+/* Generated with cbindgen:0.6.2 */
/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
* To generate this file:
@@ -240,9 +240,9 @@ struct Tiles;
// A Transaction is a group of commands to apply atomically to a document.
//
// This mechanism ensures that:
-// - no other message can be interleaved between two commands that need to be applied together.
-// - no redundant work is performed if two commands in the same transaction cause the scene or
-// the frame to be rebuilt.
+// - no other message can be interleaved between two commands that need to be applied together.
+// - no redundant work is performed if two commands in the same transaction cause the scene or
+// the frame to be rebuilt.
struct Transaction;
// The default unit.
@@ -715,8 +715,7 @@ union GlyphRasterSpace {
float _0;
bool operator==(const Local_Body& aOther) const {
- return tag == aOther.tag &&
- _0 == aOther._0;
+ return _0 == aOther._0;
}
};
@@ -745,6 +744,16 @@ union GlyphRasterSpace {
bool IsScreen() const {
return tag == Tag::Screen;
}
+
+ bool operator==(const GlyphRasterSpace& aOther) const {
+ if (tag != aOther.tag) {
+ return false;
+ }
+ switch (tag) {
+ case Tag::Local: return local == aOther.local;
+ default: return true;
+ }
+ }
};
struct FontInstanceKey {
@@ -972,13 +981,6 @@ struct WrOpacityProperty {
extern "C" {
-/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
- * To generate this file:
- * 1. Get the latest cbindgen using `cargo install --force cbindgen`
- * a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release
- * 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate webrender_bindings -o gfx/webrender_bindings/webrender_ffi_generated.h`
- */
-
extern void AddFontData(WrFontKey aKey,
const uint8_t *aData,
uintptr_t aSize,
@@ -1296,7 +1298,7 @@ void wr_dp_push_image(WrState *aState,
ImageRendering aImageRendering,
WrImageKey aKey,
bool aPremultipliedAlpha,
- ColorF color)
+ ColorF aColor)
WR_FUNC;
WR_INLINE
@@ -1763,10 +1765,3 @@ WR_FUNC;
} // namespace wr
} // namespace mozilla
-
-/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
- * To generate this file:
- * 1. Get the latest cbindgen using `cargo install --force cbindgen`
- * a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release
- * 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate webrender_bindings -o gfx/webrender_bindings/webrender_ffi_generated.h`
- */
diff --git a/intl/strres/nsStringBundle.cpp b/intl/strres/nsStringBundle.cpp
index ea54dcb4ed43..3ff3722550b3 100644
--- a/intl/strres/nsStringBundle.cpp
+++ b/intl/strres/nsStringBundle.cpp
@@ -26,6 +26,7 @@
#include "nsContentUtils.h"
#include "nsPersistentProperties.h"
#include "nsQueryObject.h"
+#include "nsSimpleEnumerator.h"
#include "nsStringStream.h"
#include "mozilla/BinarySearch.h"
#include "mozilla/ResultExtensions.h"
@@ -261,15 +262,20 @@ private:
NS_DEFINE_STATIC_IID_ACCESSOR(SharedStringBundle, SHAREDSTRINGBUNDLE_IID)
-class StringMapEnumerator final : public nsISimpleEnumerator
+class StringMapEnumerator final : public nsSimpleEnumerator
{
- NS_DECL_ISUPPORTS
+public:
NS_DECL_NSISIMPLEENUMERATOR
explicit StringMapEnumerator(SharedStringMap* aStringMap)
: mStringMap(aStringMap)
{}
+ const nsID& DefaultInterface() override
+ {
+ return NS_GET_IID(nsIPropertyElement);
+ }
+
protected:
virtual ~StringMapEnumerator() = default;
@@ -279,8 +285,6 @@ private:
uint32_t mIndex = 0;
};
-NS_IMPL_ISUPPORTS(StringMapEnumerator, nsISimpleEnumerator)
-
template
already_AddRefed
MakeBundle(Args... args)
diff --git a/js/src/jit-test/tests/basic/bug827104.js b/js/src/jit-test/tests/basic/bug827104.js
index bed6466b45dc..343fcebcd596 100644
--- a/js/src/jit-test/tests/basic/bug827104.js
+++ b/js/src/jit-test/tests/basic/bug827104.js
@@ -10,4 +10,4 @@ var e;
try {
f();
} catch (error) {e = error;}
-assertEq(e.toString(), 'TypeError: a[i] is undefined');
\ No newline at end of file
+assertEq(e.toString(), `TypeError: a[i] is undefined, can't access property 0 of it`);
diff --git a/js/src/jit-test/tests/basic/expression-autopsy.js b/js/src/jit-test/tests/basic/expression-autopsy.js
index 9b638f7c2f3d..c3a145827ff1 100644
--- a/js/src/jit-test/tests/basic/expression-autopsy.js
+++ b/js/src/jit-test/tests/basic/expression-autopsy.js
@@ -18,7 +18,7 @@ function check_one(expected, f, err) {
ieval = eval;
function check(expr, expected=expr, testStrict=true) {
var end, err;
- for ([end, err] of [[".random_prop", " is undefined"], ["()", " is not a function"]]) {
+ for ([end, err] of [[".random_prop", ` is undefined, can't access property \"random_prop" of it`], ["()", " is not a function"]]) {
var statement = "o = {};" + expr + end, f;
var cases = [
// Global scope
@@ -102,7 +102,7 @@ check_one("6", (function () { 6() }), " is not a function");
check_one("4", (function() { (4||eval)(); }), " is not a function");
check_one("0", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
check_one("[...][Symbol.iterator](...).next(...).value",
- function () { ieval("{ let x; var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined");
+ function () { ieval("{ let x; var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined, can't access property Symbol.iterator of it");
check_one("(void 1)", function() { (void 1)(); }, " is not a function");
check_one("(void o[1])", function() { var o = []; (void o[1])() }, " is not a function");
diff --git a/js/src/jit-test/tests/basic/iterable-error-messages.js b/js/src/jit-test/tests/basic/iterable-error-messages.js
index 4d10f92b2210..d783d15900c3 100644
--- a/js/src/jit-test/tests/basic/iterable-error-messages.js
+++ b/js/src/jit-test/tests/basic/iterable-error-messages.js
@@ -15,7 +15,7 @@ function testForOf(val) {
for (v of [{}, Math, new Proxy({}, {})]) {
assertThrowsMsg(() => testForOf(v), "val is not iterable");
}
-assertThrowsMsg(() => testForOf(null), "val is null");
+assertThrowsMsg(() => testForOf(null), "val is null, can't access property Symbol.iterator of it");
assertThrowsMsg(() => { for (var x of () => 1) {}}, "() => 1 is not iterable");
// Destructuring
@@ -25,7 +25,7 @@ function testDestr(val) {
for (v of [{}, Math, new Proxy({}, {})]) {
assertThrowsMsg(() => testDestr(v), "val is not iterable");
}
-assertThrowsMsg(() => testDestr(null), "val is null");
+assertThrowsMsg(() => testDestr(null), "val is null, can't access property Symbol.iterator of it");
assertThrowsMsg(() => { [a, b] = () => 1; }, "() => 1 is not iterable");
// Spread
@@ -35,5 +35,5 @@ function testSpread(val) {
for (v of [{}, Math, new Proxy({}, {})]) {
assertThrowsMsg(() => testSpread(v), "val is not iterable");
}
-assertThrowsMsg(() => testSpread(null), "val is null");
+assertThrowsMsg(() => testSpread(null), "val is null, can't access property Symbol.iterator of it");
assertThrowsMsg(() => { [...() => 1]; }, "() => 1 is not iterable");
diff --git a/js/src/jit-test/tests/basic/testBug604210.js b/js/src/jit-test/tests/basic/testBug604210.js
index 3f333ec540d9..bb96e7c4963f 100644
--- a/js/src/jit-test/tests/basic/testBug604210.js
+++ b/js/src/jit-test/tests/basic/testBug604210.js
@@ -6,6 +6,6 @@ function f() {
} catch (e) {
msg = '' + e;
}
- assertEq(msg, "TypeError: x is undefined");
+ assertEq(msg, `TypeError: x is undefined, can't access property "foo" of it`);
}
f();
diff --git a/js/src/jit-test/tests/debug/bug1275001.js b/js/src/jit-test/tests/debug/bug1275001.js
index e25ac7ac3908..868a7bda2cf5 100644
--- a/js/src/jit-test/tests/debug/bug1275001.js
+++ b/js/src/jit-test/tests/debug/bug1275001.js
@@ -17,7 +17,7 @@ function check_one(expected, f, err) {
ieval = eval
function check(expr, expected = expr) {
var end, err
- for ([end, err] of[[".random_prop", " is undefined" ]])
+ for ([end, err] of[[".random_prop", ` is undefined, can't access property \"random_prop" of it` ]])
statement = "o = {};" + expr + end;
cases = [
function() { return ieval("var undef;" + statement); },
diff --git a/js/src/jit-test/tests/ion/bug913749.js b/js/src/jit-test/tests/ion/bug913749.js
index fd7475359567..bece1e07d37c 100644
--- a/js/src/jit-test/tests/ion/bug913749.js
+++ b/js/src/jit-test/tests/ion/bug913749.js
@@ -15,7 +15,7 @@ for (var i = 0; i < 3; i++) {
x.toString();
assertEq(0, 1);
} catch (e) {
- assertEq(e.message === "y is undefined" ||
+ assertEq(e.message === `y is undefined, can't access property "length" of it` ||
e.message === "undefined has no properties", true);
}
}
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 4e301cea8294..a9103af53607 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1880,7 +1880,7 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
op == JSOP_INITELEM_ARRAY ||
op == JSOP_INITELEM_INC);
- RootedObject obj(cx, ToObjectFromStack(cx, objv));
+ RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, objv, index));
if (!obj)
return false;
@@ -2769,7 +2769,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
name = script->getName(pc);
RootedId id(cx, NameToId(name));
- RootedObject obj(cx, ToObjectFromStack(cx, lhs));
+ RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, lhs, id));
if (!obj)
return false;
RootedShape oldShape(cx, obj->maybeShape());
diff --git a/js/src/jit/arm64/CodeGenerator-arm64.cpp b/js/src/jit/arm64/CodeGenerator-arm64.cpp
index 153b26be79bf..43980c93b109 100644
--- a/js/src/jit/arm64/CodeGenerator-arm64.cpp
+++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -76,13 +76,42 @@ OutOfLineBailout::accept(CodeGeneratorARM64* codegen)
void
CodeGenerator::visitTestIAndBranch(LTestIAndBranch* test)
{
- MOZ_CRASH("visitTestIAndBranch");
+ Register input = ToRegister(test->input());
+ MBasicBlock* mirTrue = test->ifTrue();
+ MBasicBlock* mirFalse = test->ifFalse();
+
+ masm.test32(input, input);
+
+ // Jump to the True block if NonZero.
+ // Jump to the False block if Zero.
+ if (isNextBlock(mirFalse->lir())) {
+ jumpToBlock(mirTrue, Assembler::NonZero);
+ } else {
+ jumpToBlock(mirFalse, Assembler::Zero);
+ if (!isNextBlock(mirTrue->lir()))
+ jumpToBlock(mirTrue);
+ }
}
void
CodeGenerator::visitCompare(LCompare* comp)
{
- MOZ_CRASH("visitCompare");
+ const MCompare* mir = comp->mir();
+ const MCompare::CompareType type = mir->compareType();
+ const Assembler::Condition cond = JSOpToCondition(type, comp->jsop());
+ const Register leftreg = ToRegister(comp->getOperand(0));
+ const LAllocation* right = comp->getOperand(1);
+ const Register defreg = ToRegister(comp->getDef(0));
+
+ if (type == MCompare::Compare_Object || type == MCompare::Compare_Symbol) {
+ masm.cmpPtrSet(cond, leftreg, ToRegister(right), defreg);
+ return;
+ }
+
+ if (right->isConstant())
+ masm.cmp32Set(cond, leftreg, Imm32(ToInt32(right)), defreg);
+ else
+ masm.cmp32Set(cond, leftreg, ToRegister(right), defreg);
}
void
@@ -209,12 +238,12 @@ toXRegister(const T* a)
return ARMRegister(ToRegister(a), 64);
}
-js::jit::Operand
+Operand
toWOperand(const LAllocation* a)
{
if (a->isConstant())
- return js::jit::Operand(ToInt32(a));
- return js::jit::Operand(toWRegister(a));
+ return Operand(ToInt32(a));
+ return Operand(toWRegister(a));
}
vixl::CPURegister
@@ -256,13 +285,94 @@ CodeGenerator::visitAddI(LAddI* ins)
void
CodeGenerator::visitSubI(LSubI* ins)
{
- MOZ_CRASH("visitSubI");
+ const LAllocation* lhs = ins->getOperand(0);
+ const LAllocation* rhs = ins->getOperand(1);
+ const LDefinition* dest = ins->getDef(0);
+
+ // Platforms with three-operand arithmetic ops don't need recovery.
+ MOZ_ASSERT(!ins->recoversInput());
+
+ if (ins->snapshot()) {
+ masm.Subs(toWRegister(dest), toWRegister(lhs), toWOperand(rhs));
+ bailoutIf(Assembler::Overflow, ins->snapshot());
+ } else {
+ masm.Sub(toWRegister(dest), toWRegister(lhs), toWOperand(rhs));
+ }
}
void
CodeGenerator::visitMulI(LMulI* ins)
{
- MOZ_CRASH("visitMulI");
+ const LAllocation* lhs = ins->getOperand(0);
+ const LAllocation* rhs = ins->getOperand(1);
+ const LDefinition* dest = ins->getDef(0);
+ MMul* mul = ins->mir();
+ MOZ_ASSERT_IF(mul->mode() == MMul::Integer, !mul->canBeNegativeZero() && !mul->canOverflow());
+
+ Register lhsreg = ToRegister(lhs);
+
+ if (rhs->isConstant()) {
+ // Bailout on -0.0.
+ int32_t constant = ToInt32(rhs);
+ if (mul->canBeNegativeZero() && constant <= 0) {
+ Assembler::Condition bailoutCond = (constant == 0) ? Assembler::LessThan : Assembler::Equal;
+ masm.Cmp(toWRegister(lhs), Operand(0));
+ bailoutIf(bailoutCond, ins->snapshot());
+ }
+
+ switch (constant) {
+ case -1:
+ masm.neg32(lhsreg);
+ break;
+ case 0:
+ masm.Mov(ARMRegister(lhsreg, 32), wzr);
+ return; // escape overflow check;
+ case 1:
+ // nop
+ return; // escape overflow check;
+ case 2:
+ masm.add32(lhsreg, lhsreg);
+ break;
+ default:
+ // Use shift if cannot overflow and constant is a power of 2
+ if (!mul->canOverflow() && constant > 0) {
+ int32_t shift = FloorLog2(constant);
+ if ((1 << shift) == constant) {
+ masm.lshift32(Imm32(shift), lhsreg);
+ return;
+ }
+ }
+
+ // Otherwise, just multiply.
+ Label bailout;
+ Label* onZero = mul->canBeNegativeZero() ? &bailout : nullptr;
+ Label* onOverflow = mul->canOverflow() ? &bailout : nullptr;
+
+ vixl::UseScratchRegisterScope temps(&masm.asVIXL());
+ const Register scratch = temps.AcquireW().asUnsized();
+
+ masm.move32(Imm32(constant), scratch);
+ masm.mul32(lhsreg, scratch, ToRegister(dest), onOverflow, onZero);
+ if (onZero || onOverflow)
+ bailoutFrom(&bailout, ins->snapshot());
+ return; // escape overflow check;
+ }
+
+ // Overflow check.
+ if (mul->canOverflow())
+ bailoutIf(Assembler::Overflow, ins->snapshot());
+ } else {
+ Register rhsreg = ToRegister(rhs);
+
+ Label bailout;
+ // TODO: x64 (but not other platforms) have an OOL path for onZero.
+ Label* onZero = mul->canBeNegativeZero() ? &bailout : nullptr;
+ Label* onOverflow = mul->canOverflow() ? &bailout : nullptr;
+
+ masm.mul32(lhsreg, rhsreg, ToRegister(dest), onOverflow, onZero);
+ if (onZero || onOverflow)
+ bailoutFrom(&bailout, ins->snapshot());
+ }
}
@@ -270,6 +380,7 @@ void
CodeGenerator::visitDivI(LDivI* ins)
{
MOZ_CRASH("visitDivI");
+
}
void
@@ -294,7 +405,42 @@ CodeGenerator::visitModI(LModI* ins)
void
CodeGenerator::visitModPowTwoI(LModPowTwoI* ins)
{
- MOZ_CRASH("visitModPowTwoI");
+ Register lhs = ToRegister(ins->getOperand(0));
+ ARMRegister lhsw = toWRegister(ins->getOperand(0));
+ ARMRegister outw = toWRegister(ins->output());
+
+ int32_t shift = ins->shift();
+ bool canBeNegative = !ins->mir()->isUnsigned() && ins->mir()->canBeNegativeDividend();
+
+ Label negative;
+ if (canBeNegative) {
+ // Switch based on sign of the lhs.
+ // Positive numbers are just a bitmask.
+ masm.branchTest32(Assembler::Signed, lhs, lhs, &negative);
+ }
+
+ masm.And(outw, lhsw, Operand((uint32_t(1) << shift) - 1));
+
+ if (canBeNegative) {
+ Label done;
+ masm.jump(&done);
+
+ // Negative numbers need a negate, bitmask, negate.
+ masm.bind(&negative);
+ masm.Neg(outw, Operand(lhsw));
+ masm.And(outw, outw, Operand((uint32_t(1) << shift) - 1));
+
+ // Since a%b has the same sign as b, and a is negative in this branch,
+ // an answer of 0 means the correct result is actually -0. Bail out.
+ if (!ins->mir()->isTruncated()) {
+ masm.Negs(outw, Operand(outw));
+ bailoutIf(Assembler::Zero, ins->snapshot());
+ } else {
+ masm.Neg(outw, Operand(outw));
+ }
+
+ masm.bind(&done);
+ }
}
void
@@ -306,13 +452,31 @@ CodeGenerator::visitModMaskI(LModMaskI* ins)
void
CodeGenerator::visitBitNotI(LBitNotI* ins)
{
- MOZ_CRASH("visitBitNotI");
+ const LAllocation* input = ins->getOperand(0);
+ const LDefinition* output = ins->getDef(0);
+ masm.Mvn(toWRegister(output), toWOperand(input));
}
void
CodeGenerator::visitBitOpI(LBitOpI* ins)
{
- MOZ_CRASH("visitBitOpI");
+ const ARMRegister lhs = toWRegister(ins->getOperand(0));
+ const Operand rhs = toWOperand(ins->getOperand(1));
+ const ARMRegister dest = toWRegister(ins->getDef(0));
+
+ switch (ins->bitop()) {
+ case JSOP_BITOR:
+ masm.Orr(dest, lhs, rhs);
+ break;
+ case JSOP_BITXOR:
+ masm.Eor(dest, lhs, rhs);
+ break;
+ case JSOP_BITAND:
+ masm.And(dest, lhs, rhs);
+ break;
+ default:
+ MOZ_CRASH("unexpected binary opcode");
+ }
}
void
@@ -336,7 +500,11 @@ CodeGenerator::visitPowHalfD(LPowHalfD* ins)
MoveOperand
CodeGeneratorARM64::toMoveOperand(const LAllocation a) const
{
- MOZ_CRASH("toMoveOperand");
+ if (a.isGeneralReg())
+ return MoveOperand(ToRegister(a));
+ if (a.isFloatReg())
+ return MoveOperand(ToFloatRegister(a));
+ return MoveOperand(AsRegister(masm.getStackPointer()), ToStackOffset(a));
}
class js::jit::OutOfLineTableSwitch : public OutOfLineCodeBase
@@ -393,25 +561,45 @@ CodeGenerator::visitMathF(LMathF* math)
void
CodeGenerator::visitFloor(LFloor* lir)
{
- MOZ_CRASH("visitFloor");
+ FloatRegister input = ToFloatRegister(lir->input());
+ Register output = ToRegister(lir->output());
+
+ Label bailout;
+ masm.floor(input, output, &bailout);
+ bailoutFrom(&bailout, lir->snapshot());
}
void
CodeGenerator::visitFloorF(LFloorF* lir)
{
- MOZ_CRASH("visitFloorF");
+ FloatRegister input = ToFloatRegister(lir->input());
+ Register output = ToRegister(lir->output());
+
+ Label bailout;
+ masm.floorf(input, output, &bailout);
+ bailoutFrom(&bailout, lir->snapshot());
}
void
CodeGenerator::visitCeil(LCeil* lir)
{
- MOZ_CRASH("visitCeil");
+ FloatRegister input = ToFloatRegister(lir->input());
+ Register output = ToRegister(lir->output());
+
+ Label bailout;
+ masm.ceil(input, output, &bailout);
+ bailoutFrom(&bailout, lir->snapshot());
}
void
CodeGenerator::visitCeilF(LCeilF* lir)
{
- MOZ_CRASH("visitCeilF");
+ FloatRegister input = ToFloatRegister(lir->input());
+ Register output = ToRegister(lir->output());
+
+ Label bailout;
+ masm.ceilf(input, output, &bailout);
+ bailoutFrom(&bailout, lir->snapshot());
}
void
@@ -441,7 +629,9 @@ CodeGenerator::visitTruncF(LTruncF* lir)
void
CodeGenerator::visitClzI(LClzI* lir)
{
- MOZ_CRASH("visitClzI");
+ ARMRegister input = toWRegister(lir->input());
+ ARMRegister output = toWRegister(lir->output());
+ masm.Clz(output, input);
}
void
@@ -503,7 +693,8 @@ CodeGeneratorARM64::ToTempValue(LInstruction* ins, size_t pos)
void
CodeGenerator::visitValue(LValue* value)
{
- MOZ_CRASH("visitValue");
+ ValueOperand result = ToOutValue(value);
+ masm.moveValue(value->value(), result);
}
void
@@ -583,13 +774,15 @@ CodeGenerator::visitUnbox(LUnbox* unbox)
void
CodeGenerator::visitDouble(LDouble* ins)
{
- MOZ_CRASH("visitDouble");
+ ARMFPRegister output(ToFloatRegister(ins->getDef(0)), 64);
+ masm.Fmov(output, ins->getDouble());
}
void
CodeGenerator::visitFloat32(LFloat32* ins)
{
- MOZ_CRASH("visitFloat32");
+ ARMFPRegister output(ToFloatRegister(ins->getDef(0)), 32);
+ masm.Fmov(output, ins->getFloat());
}
void
@@ -613,25 +806,49 @@ CodeGenerator::visitTestFAndBranch(LTestFAndBranch* test)
void
CodeGenerator::visitCompareD(LCompareD* comp)
{
- MOZ_CRASH("visitCompareD");
+ const FloatRegister left = ToFloatRegister(comp->left());
+ const FloatRegister right = ToFloatRegister(comp->right());
+ ARMRegister output = toWRegister(comp->output());
+ Assembler::DoubleCondition cond = JSOpToDoubleCondition(comp->mir()->jsop());
+
+ masm.compareDouble(cond, left, right);
+ masm.cset(output, Assembler::ConditionFromDoubleCondition(cond));
}
void
CodeGenerator::visitCompareF(LCompareF* comp)
{
- MOZ_CRASH("visitCompareF");
+ const FloatRegister left = ToFloatRegister(comp->left());
+ const FloatRegister right = ToFloatRegister(comp->right());
+ ARMRegister output = toWRegister(comp->output());
+ Assembler::DoubleCondition cond = JSOpToDoubleCondition(comp->mir()->jsop());
+
+ masm.compareFloat(cond, left, right);
+ masm.cset(output, Assembler::ConditionFromDoubleCondition(cond));
}
void
CodeGenerator::visitCompareDAndBranch(LCompareDAndBranch* comp)
{
- MOZ_CRASH("visitCompareDAndBranch");
+ const FloatRegister left = ToFloatRegister(comp->left());
+ const FloatRegister right = ToFloatRegister(comp->right());
+ Assembler::DoubleCondition doubleCond = JSOpToDoubleCondition(comp->cmpMir()->jsop());
+ Assembler::Condition cond = Assembler::ConditionFromDoubleCondition(doubleCond);
+
+ masm.compareDouble(doubleCond, left, right);
+ emitBranch(cond, comp->ifTrue(), comp->ifFalse());
}
void
CodeGenerator::visitCompareFAndBranch(LCompareFAndBranch* comp)
{
- MOZ_CRASH("visitCompareFAndBranch");
+ const FloatRegister left = ToFloatRegister(comp->left());
+ const FloatRegister right = ToFloatRegister(comp->right());
+ Assembler::DoubleCondition doubleCond = JSOpToDoubleCondition(comp->cmpMir()->jsop());
+ Assembler::Condition cond = Assembler::ConditionFromDoubleCondition(doubleCond);
+
+ masm.compareFloat(doubleCond, left, right);
+ emitBranch(cond, comp->ifTrue(), comp->ifFalse());
}
void
diff --git a/js/src/jit/arm64/Lowering-arm64.cpp b/js/src/jit/arm64/Lowering-arm64.cpp
index 9b015c935d51..bd2c7e102829 100644
--- a/js/src/jit/arm64/Lowering-arm64.cpp
+++ b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -82,7 +82,10 @@ LIRGenerator::visitUnbox(MUnbox* unbox)
// avoid multiple loads.
lir = new(alloc()) LUnbox(useRegisterAtStart(box));
} else {
- lir = new(alloc()) LUnbox(useAtStart(box));
+ // FIXME: It should be possible to useAtStart() here, but the DEBUG
+ // code in CodeGenerator::visitUnbox() needs to handle non-Register
+ // cases. ARM64 doesn't have an Operand type.
+ lir = new(alloc()) LUnbox(useRegisterAtStart(box));
}
if (unbox->fallible())
@@ -178,21 +181,23 @@ LIRGeneratorARM64::lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction*
void
LIRGeneratorARM64::defineUntypedPhi(MPhi* phi, size_t lirIndex)
{
- MOZ_CRASH("defineUntypedPhi");
+ defineTypedPhi(phi, lirIndex);
}
void
LIRGeneratorARM64::lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition,
LBlock* block, size_t lirIndex)
{
- MOZ_CRASH("lowerUntypedPhiInput");
+ lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
}
void
LIRGeneratorARM64::lowerForShift(LInstructionHelper<1, 2, 0>* ins,
MDefinition* mir, MDefinition* lhs, MDefinition* rhs)
{
- MOZ_CRASH("lowerForShift");
+ ins->setOperand(0, useRegister(lhs));
+ ins->setOperand(1, useRegisterOrConstant(rhs));
+ define(ins, mir);
}
void
diff --git a/js/src/js.msg b/js/src/js.msg
index 1248b773e585..60b97f434888 100644
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -54,6 +54,8 @@ MSG_DEF(JSMSG_CANT_CONVERT_TO, 2, JSEXN_TYPEERR, "can't convert {0} to {
MSG_DEF(JSMSG_TOPRIMITIVE_NOT_CALLABLE, 2, JSEXN_TYPEERR, "can't convert {0} to {1}: its [Symbol.toPrimitive] property is not a function")
MSG_DEF(JSMSG_TOPRIMITIVE_RETURNED_OBJECT, 2, JSEXN_TYPEERR, "can't convert {0} to {1}: its [Symbol.toPrimitive] method returned an object")
MSG_DEF(JSMSG_NO_PROPERTIES, 1, JSEXN_TYPEERR, "{0} has no properties")
+MSG_DEF(JSMSG_PROPERTY_FAIL, 2, JSEXN_TYPEERR, "can't access property {0} of {1}")
+MSG_DEF(JSMSG_PROPERTY_FAIL_EXPR, 3, JSEXN_TYPEERR, "{0} is {1}, can't access property {2} of it")
MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}")
MSG_DEF(JSMSG_INVALID_DATA_VIEW_LENGTH, 0, JSEXN_RANGEERR, "invalid data view length")
MSG_DEF(JSMSG_OFFSET_LARGER_THAN_FILESIZE, 0, JSEXN_RANGEERR, "offset is larger than filesize")
diff --git a/js/src/jsapi-tests/testErrorInterceptor.cpp b/js/src/jsapi-tests/testErrorInterceptor.cpp
index e2dfefefcd09..71a446f5b726 100644
--- a/js/src/jsapi-tests/testErrorInterceptor.cpp
+++ b/js/src/jsapi-tests/testErrorInterceptor.cpp
@@ -52,7 +52,7 @@ BEGIN_TEST(testErrorInterceptor)
"ReferenceError: I am a ReferenceError\0",
"SyntaxError: I am a SyntaxError\0",
"5\0",
- "TypeError: undefined has no properties\0",
+ "TypeError: can't access property 0 of undefined\0",
"ReferenceError: foo is not defined\0",
"SyntaxError: expected expression, got end of script\0",
};
diff --git a/js/src/old-configure.in b/js/src/old-configure.in
index ba016082eec6..70dd46dc7319 100644
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -485,6 +485,13 @@ if test "$GNU_CC"; then
AC_MSG_RESULT([no])
LDFLAGS=$_SAVE_LDFLAGS)
+ AC_MSG_CHECKING([for -z nocopyreloc option to ld])
+ _SAVE_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-z,nocopyreloc"
+ AC_TRY_LINK(,,AC_MSG_RESULT([yes]),
+ AC_MSG_RESULT([no])
+ LDFLAGS=$_SAVE_LDFLAGS)
+
AC_MSG_CHECKING([for --build-id option to ld])
_SAVE_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,--build-id"
diff --git a/js/src/tests/non262/extensions/regress-353116.js b/js/src/tests/non262/extensions/regress-353116.js
index 6380bb2d689f..0ec70e977b78 100644
--- a/js/src/tests/non262/extensions/regress-353116.js
+++ b/js/src/tests/non262/extensions/regress-353116.js
@@ -19,7 +19,7 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
- expect = 'TypeError: undefined has no properties';
+ expect = `TypeError: can't access property "y" of undefined`;
actual = 'No Error';
try
@@ -32,7 +32,7 @@ function test()
}
reportCompare(expect, actual, summary);
- expect = 'TypeError: null has no properties';
+ expect = `TypeError: can't access property "y" of null`;
actual = 'No Error';
try
@@ -45,7 +45,7 @@ function test()
}
reportCompare(expect, actual, summary);
- expect = 'TypeError: x is undefined';
+ expect = `TypeError: x is undefined, can't access property "y" of it`;
actual = 'No Error';
try
@@ -59,7 +59,7 @@ function test()
}
reportCompare(expect, actual, summary);
- expect = 'TypeError: x is null';
+ expect = `TypeError: x is null, can't access property "y" of it`;
actual = 'No Error';
try
diff --git a/js/src/tests/non262/regress/regress-469625-03.js b/js/src/tests/non262/regress/regress-469625-03.js
index 5eaf7fa875e6..a210b0625b11 100644
--- a/js/src/tests/non262/regress/regress-469625-03.js
+++ b/js/src/tests/non262/regress/regress-469625-03.js
@@ -25,7 +25,7 @@ function test()
var [a, b, [c0, c1]] = [x, x, x];
}
- expect = `TypeError: [...][Symbol.iterator](...).next(...).value is null`;
+ expect = `TypeError: [...][Symbol.iterator](...).next(...).value is null, can't access property Symbol.iterator of it`;
actual = 'No Error';
try
{
diff --git a/js/src/tests/non262/regress/regress-469758.js b/js/src/tests/non262/regress/regress-469758.js
index 27fa1ed8a751..9fe08149d781 100644
--- a/js/src/tests/non262/regress/regress-469758.js
+++ b/js/src/tests/non262/regress/regress-469758.js
@@ -9,6 +9,6 @@ try {
err = e;
}
assertEq(err instanceof TypeError, true);
-assertEq(err.message, "[][j] is undefined");
+assertEq(err.message, "[][j] is undefined, can't access property 2 of it");
reportCompare(0, 0, 'ok');
diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
index 6f5e023fc69a..6e3f7e48fc8b 100644
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -538,7 +538,7 @@ GetPrimitiveElementOperation(JSContext* cx, JSOp op, JS::HandleValue receiver,
MOZ_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
// FIXME: Bug 1234324 We shouldn't be boxing here.
- RootedObject boxed(cx, ToObjectFromStack(cx, receiver));
+ RootedObject boxed(cx, ToObjectFromStackForPropertyAccess(cx, receiver, key));
if (!boxed)
return false;
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 9666f3bd50db..6d65e2ee0a22 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -263,7 +263,7 @@ SetPropertyOperation(JSContext* cx, JSOp op, HandleValue lval, HandleId id, Hand
{
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
- RootedObject obj(cx, ToObjectFromStack(cx, lval));
+ RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, lval, id));
if (!obj)
return false;
@@ -1518,10 +1518,10 @@ HandleError(JSContext* cx, InterpreterRegs& regs)
#define POP_COPY_TO(v) (v) = *--REGS.sp
#define POP_RETURN_VALUE() REGS.fp()->setReturnValue(*--REGS.sp)
-#define FETCH_OBJECT(cx, n, obj) \
+#define FETCH_OBJECT(cx, n, obj, key) \
JS_BEGIN_MACRO \
HandleValue val = REGS.stackHandleAt(n); \
- obj = ToObjectFromStack((cx), (val)); \
+ obj = ToObjectFromStackForPropertyAccess((cx), (val), (key)); \
if (!obj) \
goto error; \
JS_END_MACRO
@@ -2824,7 +2824,7 @@ CASE(JSOP_STRICTDELPROP)
"delprop and strictdelprop must be the same size");
ReservedRooted id(&rootId0, NameToId(script->getName(REGS.pc)));
ReservedRooted obj(&rootObject0);
- FETCH_OBJECT(cx, -1, obj);
+ FETCH_OBJECT(cx, -1, obj, id);
ObjectOpResult result;
if (!DeleteProperty(cx, obj, id, result))
@@ -2845,9 +2845,8 @@ CASE(JSOP_STRICTDELELEM)
"delelem and strictdelelem must be the same size");
/* Fetch the left part and resolve it to a non-null object. */
ReservedRooted obj(&rootObject0);
- FETCH_OBJECT(cx, -2, obj);
-
ReservedRooted propval(&rootValue0, REGS.sp[-1]);
+ FETCH_OBJECT(cx, -2, obj, propval);
ObjectOpResult result;
ReservedRooted id(&rootId0);
@@ -3111,7 +3110,7 @@ CASE(JSOP_STRICTSETELEM)
"setelem and strictsetelem must be the same size");
HandleValue receiver = REGS.stackHandleAt(-3);
ReservedRooted obj(&rootObject0);
- obj = ToObjectFromStack(cx, receiver);
+ obj = ToObjectFromStackForPropertyAccess(cx, receiver, REGS.stackHandleAt(-2));
if (!obj)
goto error;
ReservedRooted id(&rootId0);
@@ -4614,7 +4613,7 @@ js::GetProperty(JSContext* cx, HandleValue v, HandlePropertyName name, MutableHa
}
RootedValue receiver(cx, v);
- RootedObject obj(cx, ToObjectFromStack(cx, v));
+ RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, v, name));
if (!obj)
return false;
@@ -4759,7 +4758,7 @@ template
bool
js::DeletePropertyJit(JSContext* cx, HandleValue v, HandlePropertyName name, bool* bp)
{
- RootedObject obj(cx, ToObjectFromStack(cx, v));
+ RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, v, name));
if (!obj)
return false;
@@ -4787,7 +4786,7 @@ template
bool
js::DeleteElementJit(JSContext* cx, HandleValue val, HandleValue index, bool* bp)
{
- RootedObject obj(cx, ToObjectFromStack(cx, val));
+ RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, val, index));
if (!obj)
return false;
diff --git a/js/src/vm/JSContext.cpp b/js/src/vm/JSContext.cpp
index ffb7f4c6b2bd..c94970d85b74 100644
--- a/js/src/vm/JSContext.cpp
+++ b/js/src/vm/JSContext.cpp
@@ -910,11 +910,17 @@ js::ReportIsNotDefined(JSContext* cx, HandlePropertyName name)
}
void
-js::ReportIsNullOrUndefined(JSContext* cx, int spindex, HandleValue v)
+js::ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx, HandleValue v, bool reportScanStack)
{
MOZ_ASSERT(v.isNullOrUndefined());
- UniqueChars bytes = DecompileValueGenerator(cx, spindex, v, nullptr);
+ if (!reportScanStack) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
+ v.isNull() ? "null" : "undefined", "object");
+ return;
+ }
+
+ UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, nullptr);
if (!bytes)
return;
@@ -931,6 +937,51 @@ js::ReportIsNullOrUndefined(JSContext* cx, int spindex, HandleValue v)
}
}
+char*
+EncodeIdAsLatin1(JSContext* cx, HandleId id, JSAutoByteString& bytes)
+{
+ RootedValue idVal(cx, IdToValue(id));
+ RootedString idStr(cx, ValueToSource(cx, idVal));
+ if (!idStr)
+ return nullptr;
+
+ return bytes.encodeLatin1(cx, idStr);
+}
+
+void
+js::ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx, HandleValue v, HandleId key,
+ bool reportScanStack)
+{
+ MOZ_ASSERT(v.isNullOrUndefined());
+
+ JSAutoByteString keyBytes;
+ if (!EncodeIdAsLatin1(cx, key, keyBytes))
+ return;
+
+ if (!reportScanStack) {
+ JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_PROPERTY_FAIL,
+ keyBytes.ptr(),
+ v.isUndefined() ? js_undefined_str : js_null_str);
+ return;
+ }
+
+ UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, nullptr);
+ if (!bytes)
+ return;
+
+ if (strcmp(bytes.get(), js_undefined_str) == 0 || strcmp(bytes.get(), js_null_str) == 0) {
+ JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_PROPERTY_FAIL,
+ keyBytes.ptr(), bytes.get());
+ } else if (v.isUndefined()) {
+ JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_PROPERTY_FAIL_EXPR,
+ bytes.get(), js_undefined_str, keyBytes.ptr());
+ } else {
+ MOZ_ASSERT(v.isNull());
+ JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_PROPERTY_FAIL_EXPR,
+ bytes.get(), js_null_str, keyBytes.ptr());
+ }
+}
+
void
js::ReportMissingArg(JSContext* cx, HandleValue v, unsigned arg)
{
diff --git a/js/src/vm/JSContext.h b/js/src/vm/JSContext.h
index 8bef2eb5d839..34fbabb5c3e5 100644
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -1107,7 +1107,10 @@ ReportIsNotDefined(JSContext* cx, HandleId id);
* Report an attempt to access the property of a null or undefined value (v).
*/
extern void
-ReportIsNullOrUndefined(JSContext* cx, int spindex, HandleValue v);
+ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx, HandleValue v, bool reportScanStack);
+extern void
+ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx, HandleValue v, HandleId key,
+ bool reportScanStack);
extern void
ReportMissingArg(JSContext* cx, js::HandleValue v, unsigned arg);
diff --git a/js/src/vm/JSObject.cpp b/js/src/vm/JSObject.cpp
index c6887baf0821..dc4eafb62e29 100644
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -3240,11 +3240,59 @@ js::ToObjectSlow(JSContext* cx, JS::HandleValue val, bool reportScanStack)
MOZ_ASSERT(!val.isObject());
if (val.isNullOrUndefined()) {
- if (reportScanStack) {
- ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, val);
+ ReportIsNullOrUndefinedForPropertyAccess(cx, val, reportScanStack);
+ return nullptr;
+ }
+
+ return PrimitiveToObject(cx, val);
+}
+
+JSObject*
+js::ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandleId key,
+ bool reportScanStack)
+{
+ MOZ_ASSERT(!val.isMagic());
+ MOZ_ASSERT(!val.isObject());
+
+ if (val.isNullOrUndefined()) {
+ ReportIsNullOrUndefinedForPropertyAccess(cx, val, key, reportScanStack);
+ return nullptr;
+ }
+
+ return PrimitiveToObject(cx, val);
+}
+
+JSObject*
+js::ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandlePropertyName key,
+ bool reportScanStack)
+{
+ MOZ_ASSERT(!val.isMagic());
+ MOZ_ASSERT(!val.isObject());
+
+ if (val.isNullOrUndefined()) {
+ RootedId keyId(cx, NameToId(key));
+ ReportIsNullOrUndefinedForPropertyAccess(cx, val, keyId, reportScanStack);
+ return nullptr;
+ }
+
+ return PrimitiveToObject(cx, val);
+}
+
+JSObject*
+js::ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandleValue keyValue,
+ bool reportScanStack)
+{
+ MOZ_ASSERT(!val.isMagic());
+ MOZ_ASSERT(!val.isObject());
+
+ if (val.isNullOrUndefined()) {
+ RootedId key(cx);
+ if (keyValue.isPrimitive()) {
+ if (!ValueToId(cx, keyValue, &key))
+ return nullptr;
+ ReportIsNullOrUndefinedForPropertyAccess(cx, val, key, reportScanStack);
} else {
- JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
- val.isNull() ? "null" : "undefined", "object");
+ ReportIsNullOrUndefinedForPropertyAccess(cx, val, reportScanStack);
}
return nullptr;
}
diff --git a/js/src/vm/JSObject.h b/js/src/vm/JSObject.h
index 105dc997980d..fa394de1b728 100644
--- a/js/src/vm/JSObject.h
+++ b/js/src/vm/JSObject.h
@@ -1206,6 +1206,38 @@ ToObjectFromStack(JSContext* cx, HandleValue vp)
return js::ToObjectSlow(cx, vp, true);
}
+JSObject*
+ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandleId key,
+ bool reportScanStack);
+JSObject*
+ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandlePropertyName key,
+ bool reportScanStack);
+JSObject*
+ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandleValue keyValue,
+ bool reportScanStack);
+
+MOZ_ALWAYS_INLINE JSObject*
+ToObjectFromStackForPropertyAccess(JSContext* cx, HandleValue vp, HandleId key)
+{
+ if (vp.isObject())
+ return &vp.toObject();
+ return js::ToObjectSlowForPropertyAccess(cx, vp, key, true);
+}
+MOZ_ALWAYS_INLINE JSObject*
+ToObjectFromStackForPropertyAccess(JSContext* cx, HandleValue vp, HandlePropertyName key)
+{
+ if (vp.isObject())
+ return &vp.toObject();
+ return js::ToObjectSlowForPropertyAccess(cx, vp, key, true);
+}
+MOZ_ALWAYS_INLINE JSObject*
+ToObjectFromStackForPropertyAccess(JSContext* cx, HandleValue vp, HandleValue key)
+{
+ if (vp.isObject())
+ return &vp.toObject();
+ return js::ToObjectSlowForPropertyAccess(cx, vp, key, true);
+}
+
template
XDRResult
XDRObjectLiteral(XDRState* xdr, MutableHandleObject obj);
diff --git a/js/xpconnect/loader/XPCOMUtils.jsm b/js/xpconnect/loader/XPCOMUtils.jsm
index 8647a212f3d5..a63cf038e45a 100644
--- a/js/xpconnect/loader/XPCOMUtils.jsm
+++ b/js/xpconnect/loader/XPCOMUtils.jsm
@@ -408,17 +408,6 @@ var XPCOMUtils = {
});
},
- /**
- * Helper which iterates over a nsISimpleEnumerator.
- * @param e The nsISimpleEnumerator to iterate over.
- * @param i The expected interface for each element.
- */
- IterSimpleEnumerator: function* XPCU_IterSimpleEnumerator(e, i)
- {
- while (e.hasMoreElements())
- yield e.getNext().QueryInterface(i);
- },
-
/**
* Helper which iterates over a string enumerator.
* @param e The string enumerator (nsIUTF8StringEnumerator or
@@ -437,7 +426,7 @@ var XPCOMUtils = {
enumerateCategoryEntries: function* XPCOMUtils_enumerateCategoryEntries(aCategory)
{
let category = this.categoryManager.enumerateCategory(aCategory);
- for (let entry of this.IterSimpleEnumerator(category, Ci.nsISupportsCString)) {
+ for (let entry of category) {
yield [entry.data, this.categoryManager.getCategoryEntry(aCategory, entry.data)];
}
},
diff --git a/js/xpconnect/src/XPCShellImpl.cpp b/js/xpconnect/src/XPCShellImpl.cpp
index 7bc3eb2c9b10..74e9dfc5aef9 100644
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1513,7 +1513,7 @@ XPCShellDirProvider::GetFiles(const char* prop, nsISimpleEnumerator* *result)
if (NS_SUCCEEDED(rv))
dirs.AppendObject(file);
- return NS_NewArrayEnumerator(result, dirs);
+ return NS_NewArrayEnumerator(result, dirs, NS_GET_IID(nsIFile));
} else if (!strcmp(prop, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
nsCOMArray dirs;
nsCOMPtr appDir;
@@ -1524,7 +1524,7 @@ XPCShellDirProvider::GetFiles(const char* prop, nsISimpleEnumerator* *result)
NS_SUCCEEDED(appDir->AppendNative(NS_LITERAL_CSTRING("preferences"))) &&
NS_SUCCEEDED(appDir->Exists(&exists)) && exists) {
dirs.AppendObject(appDir);
- return NS_NewArrayEnumerator(result, dirs);
+ return NS_NewArrayEnumerator(result, dirs, NS_GET_IID(nsIFile));
}
return NS_ERROR_FAILURE;
} else if (!strcmp(prop, NS_APP_PLUGINS_DIR_LIST)) {
@@ -1549,7 +1549,7 @@ XPCShellDirProvider::GetFiles(const char* prop, nsISimpleEnumerator* *result)
}
}
}
- return NS_NewArrayEnumerator(result, dirs);
+ return NS_NewArrayEnumerator(result, dirs, NS_GET_IID(nsIFile));
}
return NS_ERROR_FAILURE;
}
diff --git a/js/xpconnect/src/XPCWrappedJSClass.cpp b/js/xpconnect/src/XPCWrappedJSClass.cpp
index ae0430287b4f..7087d07b8ee1 100644
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -398,7 +398,7 @@ nsXPCWrappedJSClass::BuildPropertyEnumerator(XPCCallContext& ccx,
return NS_ERROR_FAILURE;
}
- return NS_NewArrayEnumerator(aEnumerate, propertyArray);
+ return NS_NewArrayEnumerator(aEnumerate, propertyArray, NS_GET_IID(nsIProperty));
}
/***************************************************************************/
@@ -943,7 +943,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
bool success;
bool readyToDoTheCall = false;
nsID param_iid;
- const char* name = info->GetName();
bool foundDependentParam;
// We're about to call into script via an XPCWrappedJS, so we need an
@@ -962,6 +961,19 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
if (!cx || !IsReflectable(methodIndex))
return NS_ERROR_FAILURE;
+ JS::RootedId id(cx);
+ const char* name;
+ nsAutoCString symbolName;
+ if (info->IsSymbol()) {
+ info->GetSymbolDescription(cx, symbolName);
+ name = symbolName.get();
+ id = SYMBOL_TO_JSID(info->GetSymbol(cx));
+ } else {
+ name = info->GetName();
+ if (!AtomizeAndPinJSString(cx, id.get(), name))
+ return NS_ERROR_FAILURE;
+ }
+
// We passed the unwrapped object's global to AutoEntryScript so we now need
// to enter the realm corresponding with the (maybe wrapper) object.
RootedObject scope(cx, wrapper->GetJSObjectGlobal());
@@ -1030,7 +1042,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
fval = ObjectValue(*obj);
if (!isFunction || JS_TypeOfValue(ccx, fval) != JSTYPE_FUNCTION) {
- if (!JS_GetProperty(cx, obj, name, &fval))
+ if (!JS_GetPropertyById(cx, obj, id, &fval))
goto pre_call_clean_up;
// XXX We really want to factor out the error reporting better and
// specifically report the failure to find a function with this name.
diff --git a/js/xpconnect/src/XPCWrappedNativeInfo.cpp b/js/xpconnect/src/XPCWrappedNativeInfo.cpp
index d13cc4b3f5ff..ae880c6434ad 100644
--- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp
@@ -87,7 +87,13 @@ XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
callback = XPC_WN_GetterSetter;
}
- JSFunction* fun = js::NewFunctionByIdWithReserved(ccx, callback, argc, 0, GetName());
+ JSFunction* fun;
+ jsid name = GetName();
+ if (JSID_IS_STRING(name)) {
+ fun = js::NewFunctionByIdWithReserved(ccx, callback, argc, 0, GetName());
+ } else {
+ fun = js::NewFunctionWithReserved(ccx, callback, argc, 0, nullptr);
+ }
if (!fun)
return false;
@@ -292,13 +298,18 @@ XPCNativeInterface::NewInstance(const nsXPTInterfaceInfo* aInfo)
if (!XPCConvert::IsMethodReflectable(*info))
continue;
- str = JS_AtomizeAndPinString(cx, info->GetName());
- if (!str) {
- NS_ERROR("bad method name");
- failed = true;
- break;
+ jsid name;
+ if (info->IsSymbol()) {
+ name = SYMBOL_TO_JSID(info->GetSymbol(cx));
+ } else {
+ str = JS_AtomizeAndPinString(cx, info->GetName());
+ if (!str) {
+ NS_ERROR("bad method name");
+ failed = true;
+ break;
+ }
+ name = INTERNED_STRING_TO_JSID(cx, str);
}
- jsid name = INTERNED_STRING_TO_JSID(cx, str);
if (info->IsSetter()) {
MOZ_ASSERT(realTotalCount,"bad setter");
diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp
index f84d45bf8e62..a8ec89d1b65d 100644
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -429,17 +429,12 @@ _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(Geolocation, Geolocation::NonWindowSingleton)
-#define NS_GEOLOCATION_SERVICE_CID \
- { 0x404d02a, 0x1CA, 0xAAAB, { 0x47, 0x62, 0x94, 0x4b, 0x1b, 0xf2, 0xf7, 0xb5 } }
-
#define NS_AUDIOCHANNEL_SERVICE_CID \
{ 0xf712e983, 0x048a, 0x443f, { 0x88, 0x02, 0xfc, 0xc3, 0xd9, 0x27, 0xce, 0xac }}
#define NS_WEBSOCKETEVENT_SERVICE_CID \
{ 0x31689828, 0xda66, 0x49a6, { 0x87, 0x0c, 0xdf, 0x62, 0xb8, 0x3f, 0xe7, 0x89 }}
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationService::GetGeolocationService)
-
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AudioChannelService, AudioChannelService::GetOrCreate)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WebSocketEventService, WebSocketEventService::GetOrCreate)
@@ -552,7 +547,6 @@ NS_DEFINE_NAMED_CID(NS_EDITORCONTROLLER_CID);
NS_DEFINE_NAMED_CID(NS_EDITINGCONTROLLER_CID);
NS_DEFINE_NAMED_CID(NS_EDITORCOMMANDTABLE_CID);
NS_DEFINE_NAMED_CID(NS_EDITINGCOMMANDTABLE_CID);
-NS_DEFINE_NAMED_CID(NS_GEOLOCATION_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_GEOLOCATION_CID);
NS_DEFINE_NAMED_CID(NS_AUDIOCHANNEL_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_WEBSOCKETEVENT_SERVICE_CID);
@@ -790,7 +784,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_EDITINGCONTROLLER_CID, false, nullptr, nsEditingControllerConstructor },
{ &kNS_EDITORCOMMANDTABLE_CID, false, nullptr, nsEditorCommandTableConstructor },
{ &kNS_EDITINGCOMMANDTABLE_CID, false, nullptr, nsEditingCommandTableConstructor },
- { &kNS_GEOLOCATION_SERVICE_CID, false, nullptr, nsGeolocationServiceConstructor },
{ &kNS_GEOLOCATION_CID, false, nullptr, GeolocationConstructor },
{ &kNS_AUDIOCHANNEL_SERVICE_CID, false, nullptr, AudioChannelServiceConstructor },
{ &kNS_WEBSOCKETEVENT_SERVICE_CID, false, nullptr, WebSocketEventServiceConstructor },
@@ -891,7 +884,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ "@mozilla.org/editor/htmleditor;1", &kNS_HTMLEDITOR_CID },
{ "@mozilla.org/editor/editorcontroller;1", &kNS_EDITORCONTROLLER_CID },
{ "@mozilla.org/editor/editingcontroller;1", &kNS_EDITINGCONTROLLER_CID },
- { "@mozilla.org/geolocation/service;1", &kNS_GEOLOCATION_SERVICE_CID },
{ "@mozilla.org/geolocation;1", &kNS_GEOLOCATION_CID },
{ "@mozilla.org/audiochannel/service;1", &kNS_AUDIOCHANNEL_SERVICE_CID },
{ "@mozilla.org/websocketevent/service;1", &kNS_WEBSOCKETEVENT_SERVICE_CID },
diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp
index e501fa4a001c..f5f5716afb69 100644
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -273,6 +273,13 @@ nsFieldSetFrame::PaintBorder(
// border looks.
nsRect legendRect = legend->GetNormalRect() + aPt;
+ // Make sure we clip all of the border in case the legend is smaller.
+ nscoord borderTopWidth = GetUsedBorder().top;
+ if (legendRect.height < borderTopWidth) {
+ legendRect.height = borderTopWidth;
+ legendRect.y = aPt.y;
+ }
+
DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
// We set up a clip path which has our rect clockwise and the legend rect
// counterclockwise, with FILL_WINDING as the fill rule. That will allow us
diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list
index 5d4345dd80e0..fe670e6452bb 100644
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1866,7 +1866,7 @@ test-pref(dom.webcomponents.shadowdom.enabled,true) == 1066554-1.html 1066554-1-
== 1069716-1.html 1069716-1-ref.html
== 1078262-1.html about:blank
test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html
-== 1081185-1.html 1081185-1-ref.html
+fails-if(webrender) == 1081185-1.html 1081185-1-ref.html
== 1097437-1.html 1097437-1-ref.html
== 1103258-1.html 1103258-1-ref.html # assertion crash test with layers culling test
== 1105137-1.html 1105137-1-ref.html
diff --git a/layout/tools/reftest/bootstrap.js b/layout/tools/reftest/bootstrap.js
index 07d290af6e78..40118f222e45 100644
--- a/layout/tools/reftest/bootstrap.js
+++ b/layout/tools/reftest/bootstrap.js
@@ -24,9 +24,7 @@ var WindowListener = {
let win = xulWin.docShell.domWindow;
win.addEventListener("load", function listener() {
// Load into any existing windows.
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- win = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
+ for (win of Services.wm.getEnumerator("navigator:browser")) {
break;
}
diff --git a/mfbt/Tuple.h b/mfbt/Tuple.h
index d99ea5c7c415..334439e9c2cd 100644
--- a/mfbt/Tuple.h
+++ b/mfbt/Tuple.h
@@ -100,6 +100,9 @@ struct TupleImpl {
{
return true;
}
+
+ template
+ void ForEach(const F& aFunc) {}
};
/*
@@ -191,6 +194,27 @@ struct TupleImpl
{
return Head(*this) == Head(aOther) && Tail(*this) == Tail(aOther);
}
+
+ template
+ void ForEach(const F& aFunc) const &
+ {
+ aFunc(Head(*this));
+ Tail(*this).ForEach(aFunc);
+ }
+
+ template
+ void ForEach(const F& aFunc) &
+ {
+ aFunc(Head(*this));
+ Tail(*this).ForEach(aFunc);
+ }
+
+ template
+ void ForEach(const F& aFunc) &&
+ {
+ aFunc(std::move(Head(*this)));
+ std::move(Tail(*this)).ForEach(aFunc);
+ }
private:
HeadT mHead; // The element stored at this index in the tuple.
};
@@ -420,6 +444,50 @@ auto Get(Tuple&& aTuple)
return std::move(mozilla::Get(aTuple));
}
+/**
+ * Helpers which call a function for each member of the tuple in turn. This will
+ * typically be used with a lambda function with an `auto&` argument:
+ *
+ * Tuple> tuple{a, b, c};
+ *
+ * ForEach(tuple, [](auto& aElem) {
+ * aElem = nullptr;
+ * });
+ */
+
+template
+inline void
+ForEach(const Tuple<>& aTuple, const F& aFunc)
+{
+}
+
+template
+inline void
+ForEach(Tuple<>& aTuple, const F& aFunc)
+{
+}
+
+template
+void
+ForEach(const Tuple& aTuple, const F& aFunc)
+{
+ aTuple.ForEach(aTuple, aFunc);
+}
+
+template
+void
+ForEach(Tuple& aTuple, const F& aFunc)
+{
+ aTuple.ForEach(aFunc);
+}
+
+template
+void
+ForEach(Tuple&& aTuple, const F& aFunc)
+{
+ std::forward>(aTuple).ForEach(aFunc);
+}
+
/**
* A convenience function for constructing a tuple out of a sequence of
* values without specifying the type of the tuple.
diff --git a/mobile/android/components/DirectoryProvider.js b/mobile/android/components/DirectoryProvider.js
index ab29676bf1bc..f9715afe59bc 100644
--- a/mobile/android/components/DirectoryProvider.js
+++ b/mobile/android/components/DirectoryProvider.js
@@ -140,6 +140,9 @@ DirectoryProvider.prototype = {
return {
QueryInterface: ChromeUtils.generateQI([Ci.nsISimpleEnumerator]),
+ [Symbol.iterator]() {
+ return result.values();
+ },
hasMoreElements: function() {
return result.length > 0;
},
diff --git a/mobile/android/components/SessionStore.js b/mobile/android/components/SessionStore.js
index 6839e1530222..5b1ae10af7c9 100644
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -1180,9 +1180,7 @@ SessionStore.prototype = {
},
_forEachBrowserWindow: function ss_forEachBrowserWindow(aFunc) {
- let windowsEnum = Services.wm.getEnumerator("navigator:browser");
- while (windowsEnum.hasMoreElements()) {
- let window = windowsEnum.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (window.__SSID && !window.closed) {
aFunc.call(this, window);
}
diff --git a/mobile/android/components/extensions/ext-browsingData.js b/mobile/android/components/extensions/ext-browsingData.js
index 3a1569cb5f0a..2d0141bc603c 100644
--- a/mobile/android/components/extensions/ext-browsingData.js
+++ b/mobile/android/components/extensions/ext-browsingData.js
@@ -23,10 +23,7 @@ const clearCookies = async function(options) {
// Convert it to microseconds
let since = options.since * 1000;
// Iterate through the cookies and delete any created after our cutoff.
- let cookiesEnum = cookieMgr.enumerator;
- while (cookiesEnum.hasMoreElements()) {
- let cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2);
-
+ for (let cookie of cookieMgr.enumerator) {
if (cookie.creationTime >= since) {
// This cookie was created after our cutoff, clear it.
cookieMgr.remove(cookie.host, cookie.name, cookie.path,
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt
index 2ad3c3105b75..5d0696dd98bd 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt
@@ -4,6 +4,8 @@
package org.mozilla.geckoview.test
+import android.app.assist.AssistStructure
+import android.os.Build
import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
@@ -16,7 +18,13 @@ import org.mozilla.geckoview.test.util.UiThreadUtils
import android.os.Looper
import android.support.test.filters.MediumTest
+import android.support.test.filters.SdkSuppress
import android.support.test.runner.AndroidJUnit4
+import android.text.InputType
+import android.util.SparseArray
+import android.view.View
+import android.view.ViewStructure
+import android.widget.EditText
import org.hamcrest.Matchers.*
import org.junit.Assume.assumeThat
import org.junit.Test
@@ -184,4 +192,227 @@ class ContentDelegateTest : BaseSessionTest() {
throw UiThreadUtils.TimeoutException("Timed out")
}
}
+
+ val ViewNode by lazy {
+ AssistStructure.ViewNode::class.java.getDeclaredConstructor().apply { isAccessible = true }
+ }
+
+ val ViewNodeBuilder by lazy {
+ Class.forName("android.app.assist.AssistStructure\$ViewNodeBuilder")
+ .getDeclaredConstructor(AssistStructure::class.java,
+ AssistStructure.ViewNode::class.java,
+ Boolean::class.javaPrimitiveType)
+ .apply { isAccessible = true }
+ }
+
+ // TextInputDelegateTest is parameterized, so we put this test under ContentDelegateTest.
+ @SdkSuppress(minSdkVersion = 23)
+ @WithDevToolsAPI
+ @Test fun autofill() {
+ // Test parts of the Oreo auto-fill API; there is another autofill test in
+ // SessionAccessibility for a11y auto-fill support.
+ mainSession.loadTestPath(FORMS_HTML_PATH)
+ // Wait for the auto-fill nodes to populate.
+ sessionRule.waitUntilCalled(object : Callbacks.TextInputDelegate {
+ // For the root document and the iframe document, each has a form group and
+ // a group for inputs outside of forms, so the total count is 4.
+ @AssertCalled(count = 4)
+ override fun notifyAutoFill(session: GeckoSession, notification: Int, virtualId: Int) {
+ }
+ })
+
+ val autoFills = mapOf(
+ "#user1" to "bar", "#user2" to "bar") +
+ if (Build.VERSION.SDK_INT >= 26) mapOf(
+ "#pass1" to "baz", "#pass2" to "baz", "#email1" to "a@b.c",
+ "#number1" to "24", "#tel1" to "42")
+ else mapOf(
+ "#pass1" to "bar", "#pass2" to "bar", "#email1" to "bar",
+ "#number1" to "", "#tel1" to "bar")
+
+ // Set up promises to monitor the values changing.
+ val promises = autoFills.flatMap { entry ->
+ // Repeat each test with both the top document and the iframe document.
+ arrayOf("document", "$('#iframe').contentDocument").map { doc ->
+ mainSession.evaluateJS("""new Promise(resolve =>
+ $doc.querySelector('${entry.key}').addEventListener(
+ 'input', event => resolve([event.target.value, '${entry.value}']),
+ { once: true }))""").asJSPromise()
+ }
+ }
+
+ val rootNode = ViewNode.newInstance()
+ val rootStructure = ViewNodeBuilder.newInstance(AssistStructure(), rootNode,
+ /* async */ false) as ViewStructure
+ val autoFillValues = SparseArray()
+
+ // Perform auto-fill and return number of auto-fills performed.
+ fun checkAutoFillChild(child: AssistStructure.ViewNode) {
+ // Seal the node info instance so we can perform actions on it.
+ if (child.childCount > 0) {
+ for (i in 0 until child.childCount) {
+ checkAutoFillChild(child.getChildAt(i))
+ }
+ }
+
+ if (child === rootNode) {
+ return
+ }
+
+ assertThat("ID should be valid", child.id, not(equalTo(View.NO_ID)))
+
+ if (Build.VERSION.SDK_INT >= 26) {
+ assertThat("Should have HTML tag",
+ child.htmlInfo.tag, not(isEmptyOrNullString()))
+ assertThat("Web domain should match",
+ child.webDomain, equalTo("android"))
+ }
+
+ if (EditText::class.java.name == child.className) {
+ assertThat("Input should be enabled", child.isEnabled, equalTo(true))
+ assertThat("Input should be focusable",
+ child.isFocusable, equalTo(true))
+ assertThat("Input should be visible",
+ child.visibility, equalTo(View.VISIBLE))
+
+ if (Build.VERSION.SDK_INT < 26) {
+ autoFillValues.append(child.id, "bar")
+ return
+ }
+
+ val htmlInfo = child.htmlInfo
+ assertThat("Should have HTML tag", htmlInfo.tag, equalTo("input"))
+ assertThat("Should have ID attribute",
+ htmlInfo.attributes.map { it.first }, hasItem("id"))
+
+ assertThat("Autofill type should match",
+ child.autofillType, equalTo(View.AUTOFILL_TYPE_TEXT))
+
+ assertThat("Autofill hints should match", child.autofillHints, equalTo(
+ when (child.inputType) {
+ InputType.TYPE_CLASS_TEXT or
+ InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD ->
+ arrayOf(View.AUTOFILL_HINT_PASSWORD)
+ InputType.TYPE_CLASS_TEXT or
+ InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS ->
+ arrayOf(View.AUTOFILL_HINT_EMAIL_ADDRESS)
+ InputType.TYPE_CLASS_PHONE -> arrayOf(View.AUTOFILL_HINT_PHONE)
+ else -> null
+ }))
+
+ autoFillValues.append(child.id, when (child.inputType) {
+ InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD -> "baz"
+ InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS -> "a@b.c"
+ InputType.TYPE_CLASS_NUMBER -> "24"
+ InputType.TYPE_CLASS_PHONE -> "42"
+ else -> "bar"
+ })
+ }
+ }
+
+ mainSession.textInput.onProvideAutofillVirtualStructure(rootStructure, 0)
+ checkAutoFillChild(rootNode)
+ mainSession.textInput.autofill(autoFillValues)
+
+ // Wait on the promises and check for correct values.
+ for ((actual, expected) in promises.map { it.value.asJSList() }) {
+ assertThat("Auto-filled value must match", actual, equalTo(expected))
+ }
+ }
+
+ // TextInputDelegateTest is parameterized, so we put this test under ContentDelegateTest.
+ @SdkSuppress(minSdkVersion = 23)
+ @WithDevToolsAPI
+ @WithDisplay(width = 100, height = 100)
+ @Test fun autoFill_navigation() {
+
+ fun countAutoFillNodes(cond: (AssistStructure.ViewNode) -> Boolean =
+ { it.className == "android.widget.EditText" },
+ root: AssistStructure.ViewNode? = null): Int {
+ val node = if (root !== null) root else ViewNode.newInstance().also {
+ // Fill the nodes first.
+ val structure = ViewNodeBuilder.newInstance(
+ AssistStructure(), it, /* async */ false) as ViewStructure
+ mainSession.textInput.onProvideAutofillVirtualStructure(structure, 0)
+ }
+ return (if (cond(node)) 1 else 0) +
+ (if (node.childCount > 0) (0 until node.childCount).sumBy {
+ countAutoFillNodes(cond, node.getChildAt(it)) } else 0)
+ }
+
+ // Wait for the accessibility nodes to populate.
+ mainSession.loadTestPath(FORMS_HTML_PATH)
+ sessionRule.waitUntilCalled(object : Callbacks.TextInputDelegate {
+ @AssertCalled(count = 4)
+ override fun notifyAutoFill(session: GeckoSession, notification: Int, virtualId: Int) {
+ assertThat("Should be starting auto-fill", notification, equalTo(forEachCall(
+ GeckoSession.TextInputDelegate.AUTO_FILL_NOTIFY_STARTED,
+ GeckoSession.TextInputDelegate.AUTO_FILL_NOTIFY_VIEW_ADDED)))
+ assertThat("ID should be valid", virtualId, not(equalTo(View.NO_ID)))
+ }
+ })
+ assertThat("Initial auto-fill count should match",
+ countAutoFillNodes(), equalTo(14))
+
+ // Now wait for the nodes to clear.
+ mainSession.loadTestPath(HELLO_HTML_PATH)
+ sessionRule.waitUntilCalled(object : Callbacks.TextInputDelegate {
+ @AssertCalled(count = 1)
+ override fun notifyAutoFill(session: GeckoSession, notification: Int, virtualId: Int) {
+ assertThat("Should be canceling auto-fill",
+ notification,
+ equalTo(GeckoSession.TextInputDelegate.AUTO_FILL_NOTIFY_CANCELED))
+ assertThat("ID should be valid", virtualId, equalTo(View.NO_ID))
+ }
+ })
+ assertThat("Should not have auto-fill fields",
+ countAutoFillNodes(), equalTo(0))
+
+ // Now wait for the nodes to reappear.
+ mainSession.waitForPageStop()
+ mainSession.goBack()
+ sessionRule.waitUntilCalled(object : Callbacks.TextInputDelegate {
+ @AssertCalled(count = 4)
+ override fun notifyAutoFill(session: GeckoSession, notification: Int, virtualId: Int) {
+ assertThat("Should be starting auto-fill", notification, equalTo(forEachCall(
+ GeckoSession.TextInputDelegate.AUTO_FILL_NOTIFY_STARTED,
+ GeckoSession.TextInputDelegate.AUTO_FILL_NOTIFY_VIEW_ADDED)))
+ assertThat("ID should be valid", virtualId, not(equalTo(View.NO_ID)))
+ }
+ })
+ assertThat("Should have auto-fill fields again",
+ countAutoFillNodes(), equalTo(14))
+ assertThat("Should not have focused field",
+ countAutoFillNodes({ it.isFocused }), equalTo(0))
+
+ mainSession.evaluateJS("$('#pass1').focus()")
+ sessionRule.waitUntilCalled(object : Callbacks.TextInputDelegate {
+ @AssertCalled(count = 1)
+ override fun notifyAutoFill(session: GeckoSession, notification: Int, virtualId: Int) {
+ assertThat("Should be entering auto-fill view",
+ notification,
+ equalTo(GeckoSession.TextInputDelegate.AUTO_FILL_NOTIFY_VIEW_ENTERED))
+ assertThat("ID should be valid", virtualId, not(equalTo(View.NO_ID)))
+ }
+ })
+ assertThat("Should have one focused field",
+ countAutoFillNodes({ it.isFocused }), equalTo(1))
+ // The focused field, its siblings, and its parent should be visible.
+ assertThat("Should have at least six visible fields",
+ countAutoFillNodes({ node -> node.width > 0 && node.height > 0 }),
+ greaterThanOrEqualTo(6))
+
+ mainSession.evaluateJS("$('#pass1').blur()")
+ sessionRule.waitUntilCalled(object : Callbacks.TextInputDelegate {
+ @AssertCalled(count = 1)
+ override fun notifyAutoFill(session: GeckoSession, notification: Int, virtualId: Int) {
+ assertThat("Should be exiting auto-fill view",
+ notification,
+ equalTo(GeckoSession.TextInputDelegate.AUTO_FILL_NOTIFY_VIEW_EXITED))
+ assertThat("ID should be valid", virtualId, not(equalTo(View.NO_ID)))
+ }
+ })
+ assertThat("Should not have focused field",
+ countAutoFillNodes({ it.isFocused }), equalTo(0))
+ }
}
diff --git a/mobile/android/modules/geckoview/GeckoViewUtils.jsm b/mobile/android/modules/geckoview/GeckoViewUtils.jsm
index d64df8133e55..c5063f11b07e 100644
--- a/mobile/android/modules/geckoview/GeckoViewUtils.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewUtils.jsm
@@ -345,9 +345,7 @@ var GeckoViewUtils = {
return [dispatcher, win];
}
- let iter = Services.wm.getEnumerator(/* windowType */ null);
- while (iter.hasMoreElements()) {
- win = iter.getNext().QueryInterface(Ci.nsIDOMWindow);
+ for (let win of Services.wm.getEnumerator(/* windowType */ null)) {
dispatcher = this.getDispatcherForWindow(win);
if (dispatcher) {
return [dispatcher, win];
diff --git a/mobile/android/tests/browser/robocop/testFilePicker.js b/mobile/android/tests/browser/robocop/testFilePicker.js
index 8b874fe5649d..222c3d07f518 100644
--- a/mobile/android/tests/browser/robocop/testFilePicker.js
+++ b/mobile/android/tests/browser/robocop/testFilePicker.js
@@ -24,9 +24,7 @@ add_test(function filepicker_open() {
do_print("File: " + fp.file.path);
is(fp.file.path, "/mnt/sdcard/my-favorite-martian.png", "Retrieve the right martian file!");
- let files = fp.files;
- while (files.hasMoreElements()) {
- let file = files.getNext().QueryInterface(Ci.nsIFile);
+ for (let file of fp.files) {
do_print("File: " + file.path);
is(file.path, "/mnt/sdcard/my-favorite-martian.png", "Retrieve the right martian file from array!");
}
@@ -35,9 +33,7 @@ add_test(function filepicker_open() {
do_print("DOMFile: " + file.mozFullPath);
is(file.mozFullPath, "/mnt/sdcard/my-favorite-martian.png", "Retrieve the right martian DOM File!");
- let e = fp.domFileOrDirectoryEnumerator;
- while (e.hasMoreElements()) {
- let domFile = e.getNext();
+ for (let domFile of fp.domFileOrDirectoryEnumerator) {
do_print("DOMFile: " + domFile.mozFullPath);
is(domFile.mozFullPath, "/mnt/sdcard/my-favorite-martian.png", "Retrieve the right martian file from domFileOrDirectoryEnumerator array!");
}
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 7c68fdd48d77..cb3154df3749 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -924,6 +924,7 @@ pref("gfx.webrender.debug.compact-profiler", false);
pref("gfx.webrender.debug.echo-driver-messages", false);
pref("gfx.webrender.debug.new-frame-indicator", false);
pref("gfx.webrender.debug.new-scene-indicator", false);
+pref("gfx.webrender.debug.show-overdraw", false);
pref("gfx.webrender.dl.dump-parent", false);
pref("gfx.webrender.dl.dump-content", false);
diff --git a/mozglue/misc/StackWalk.cpp b/mozglue/misc/StackWalk.cpp
index 58cd5fc65dd0..a3c226daafcc 100644
--- a/mozglue/misc/StackWalk.cpp
+++ b/mozglue/misc/StackWalk.cpp
@@ -207,7 +207,7 @@ WalkStackMain64(struct WalkStackData* aData)
context = aData->context;
}
-#if defined(_M_IX86) || defined(_M_IA64)
+#if defined(_M_IX86) || defined(_M_IA64) || defined(_M_ARM64)
// Setup initial stack frame to walk from.
STACKFRAME64 frame64;
memset(&frame64, 0, sizeof(frame64));
@@ -219,6 +219,10 @@ WalkStackMain64(struct WalkStackData* aData)
frame64.AddrPC.Offset = context->StIIP;
frame64.AddrStack.Offset = context->SP;
frame64.AddrFrame.Offset = context->RsBSP;
+#elif defined _M_ARM64
+ frame64.AddrPC.Offset = context->Pc;
+ frame64.AddrStack.Offset = context->Sp;
+ frame64.AddrFrame.Offset = context->Fp;
#endif
frame64.AddrPC.Mode = AddrModeFlat;
frame64.AddrStack.Mode = AddrModeFlat;
@@ -226,7 +230,7 @@ WalkStackMain64(struct WalkStackData* aData)
frame64.AddrReturn.Mode = AddrModeFlat;
#endif
-#ifdef _WIN64
+#ifdef _M_AMD64
// If there are any active suppressions, then at least one thread (we don't
// know which) is holding a lock that can deadlock RtlVirtualUnwind. Since
// that thread may be the one that we're trying to unwind, we can't proceed.
@@ -254,7 +258,7 @@ WalkStackMain64(struct WalkStackData* aData)
DWORD64 addr;
DWORD64 spaddr;
-#if defined(_M_IX86) || defined(_M_IA64)
+#if defined(_M_IX86) || defined(_M_IA64) || defined(_M_ARM64)
// 32-bit frame unwinding.
// Debug routines are not threadsafe, so grab the lock.
EnterCriticalSection(&gDbgHelpCS);
@@ -263,6 +267,8 @@ WalkStackMain64(struct WalkStackData* aData)
IMAGE_FILE_MACHINE_IA64,
#elif defined _M_IX86
IMAGE_FILE_MACHINE_I386,
+#elif defined _M_ARM64
+ IMAGE_FILE_MACHINE_ARM64,
#endif
aData->process,
aData->thread,
diff --git a/mozglue/misc/StackWalk.h b/mozglue/misc/StackWalk.h
index 5ae6a0371d69..eea01be4582f 100644
--- a/mozglue/misc/StackWalk.h
+++ b/mozglue/misc/StackWalk.h
@@ -47,7 +47,8 @@ MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure);
#if defined(_WIN32) && \
- (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64))
+ (defined(_M_IX86) || defined(_M_AMD64) || \
+ defined(_M_IA64) || defined(_M_ARM64))
#include
diff --git a/netwerk/base/nsLoadGroup.cpp b/netwerk/base/nsLoadGroup.cpp
index 40b9154fda10..75d8c9570f65 100644
--- a/netwerk/base/nsLoadGroup.cpp
+++ b/netwerk/base/nsLoadGroup.cpp
@@ -654,7 +654,7 @@ nsLoadGroup::GetRequests(nsISimpleEnumerator * *aRequests)
requests.AppendObject(e->mKey);
}
- return NS_NewArrayEnumerator(aRequests, requests);
+ return NS_NewArrayEnumerator(aRequests, requests, NS_GET_IID(nsIRequest));
}
NS_IMETHODIMP
diff --git a/netwerk/cache2/CacheFileIOManager.cpp b/netwerk/cache2/CacheFileIOManager.cpp
index a24abf9b2782..64616fd60235 100644
--- a/netwerk/cache2/CacheFileIOManager.cpp
+++ b/netwerk/cache2/CacheFileIOManager.cpp
@@ -3854,7 +3854,7 @@ CacheFileIOManager::IsEmptyDirectory(nsIFile *aFile, bool *_retval)
nsresult rv;
- nsCOMPtr enumerator;
+ nsCOMPtr enumerator;
rv = aFile->GetDirectoryEntries(getter_AddRefs(enumerator));
NS_ENSURE_SUCCESS(rv, rv);
diff --git a/netwerk/cookie/nsCookieService.cpp b/netwerk/cookie/nsCookieService.cpp
index b22a46a86d10..bffcd71c362f 100644
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -2493,7 +2493,7 @@ nsCookieService::GetEnumerator(nsISimpleEnumerator **aEnumerator)
}
}
- return NS_NewArrayEnumerator(aEnumerator, cookieList);
+ return NS_NewArrayEnumerator(aEnumerator, cookieList, NS_GET_IID(nsICookie2));
}
NS_IMETHODIMP
@@ -2518,7 +2518,7 @@ nsCookieService::GetSessionEnumerator(nsISimpleEnumerator **aEnumerator)
}
}
- return NS_NewArrayEnumerator(aEnumerator, cookieList);
+ return NS_NewArrayEnumerator(aEnumerator, cookieList, NS_GET_IID(nsICookie2));
}
static nsresult
@@ -4928,7 +4928,7 @@ nsCookieService::GetCookiesFromHost(const nsACString &aHost,
cookieList.AppendObject(cookies[i]);
}
- return NS_NewArrayEnumerator(aEnumerator, cookieList);
+ return NS_NewArrayEnumerator(aEnumerator, cookieList, NS_GET_IID(nsICookie2));
}
NS_IMETHODIMP
@@ -4987,7 +4987,7 @@ nsCookieService::GetCookiesWithOriginAttributes(
}
}
- return NS_NewArrayEnumerator(aEnumerator, cookies);
+ return NS_NewArrayEnumerator(aEnumerator, cookies, NS_GET_IID(nsICookie2));
}
NS_IMETHODIMP
diff --git a/netwerk/cookie/test/browser/browser_originattributes.js b/netwerk/cookie/test/browser/browser_originattributes.js
index 40be81800671..e60c6c5a0713 100644
--- a/netwerk/cookie/test/browser/browser_originattributes.js
+++ b/netwerk/cookie/test/browser/browser_originattributes.js
@@ -84,8 +84,7 @@ async function checkCookies(expectedValues, time) {
function getCookiesFromManager(userContextId) {
let cookies = {};
let enumerator = cm.getCookiesWithOriginAttributes(JSON.stringify({userContextId}));
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ for (let cookie of enumerator) {
cookies[cookie.name] = cookie.value;
}
return cookies;
diff --git a/netwerk/cookie/test/unit/test_bug1267910.js b/netwerk/cookie/test/unit/test_bug1267910.js
index 6d7ee25ad6b5..8ad734994005 100644
--- a/netwerk/cookie/test/unit/test_bug1267910.js
+++ b/netwerk/cookie/test/unit/test_bug1267910.js
@@ -55,12 +55,10 @@ function checkCookie(cookie, cookieObj) {
function countCookies(enumerator) {
let cnt = 0;
-
- while (enumerator.hasMoreElements()) {
+ for (let cookie of enumerator) {
+ void cookie;
cnt++;
- enumerator.getNext();
}
-
return cnt;
}
diff --git a/netwerk/cookie/test/unit/test_eviction.js b/netwerk/cookie/test/unit/test_eviction.js
index cd8f5e2c1f20..7c5abd6e714e 100644
--- a/netwerk/cookie/test/unit/test_eviction.js
+++ b/netwerk/cookie/test/unit/test_eviction.js
@@ -223,10 +223,8 @@ async function test_basic_eviction(base_host, subdomain_host, other_subdomain_ho
// Verify that the given cookie names exist, and are ordered from least to most recently accessed
function verifyCookies(names, uri) {
Assert.equal(cm.countCookiesFromHost(uri.host), names.length);
- let cookies = cm.getCookiesFromHost(uri.host, {});
let actual_cookies = [];
- while (cookies.hasMoreElements()) {
- let cookie = cookies.getNext().QueryInterface(Ci.nsICookie2);
+ for (let cookie of cm.getCookiesFromHost(uri.host, {})) {
actual_cookies.push(cookie);
}
if (names.length != actual_cookies.length) {
diff --git a/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm b/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm
index a1155e1e1e12..abe231ba3974 100644
--- a/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm
+++ b/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm
@@ -146,9 +146,7 @@ function parsePropertyBag2(bag) {
}
let attributes = [];
- let enumerator = bag.enumerator;
- while (enumerator.hasMoreElements()) {
- let name = enumerator.getNext().QueryInterface(Ci.nsIProperty).name;
+ for (let {name} of bag.enumerator) {
let value = bag.getPropertyAsACString(name);
attributes.push({
"name": name,
diff --git a/netwerk/dns/mdns/libmdns/fallback/MulticastDNS.jsm b/netwerk/dns/mdns/libmdns/fallback/MulticastDNS.jsm
index e2e04a9ba398..4998772ad7c6 100644
--- a/netwerk/dns/mdns/libmdns/fallback/MulticastDNS.jsm
+++ b/netwerk/dns/mdns/libmdns/fallback/MulticastDNS.jsm
@@ -838,9 +838,7 @@ function _propertyBagToObject(propBag) {
let result = {};
if (propBag.QueryInterface) {
propBag.QueryInterface(Ci.nsIPropertyBag2);
- let propEnum = propBag.enumerator;
- while (propEnum.hasMoreElements()) {
- let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
+ for (let prop of propBag.enumerator) {
result[prop.name] = prop.value.toString();
}
} else {
diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h
index 56230ce245c1..0e3bd5a4ccd5 100644
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -453,6 +453,7 @@ protected:
// bundle calling OMR observers and marking flag into one function
inline void CallOnModifyRequestObservers() {
gHttpHandler->OnModifyRequest(this);
+ MOZ_ASSERT(!mRequestObserversCalled);
mRequestObserversCalled = true;
}
diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp
index e805e1b86a4c..ca77764042a2 100644
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -7062,6 +7062,8 @@ nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
nsresult rv;
+ MOZ_ASSERT(mRequestObserversCalled);
+
AUTO_PROFILER_LABEL("nsHttpChannel::OnStartRequest", NETWORK);
if (!(mCanceled || NS_FAILED(mStatus)) && !WRONG_RACING_RESPONSE_SOURCE(request)) {
@@ -8251,6 +8253,10 @@ nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn)
// the request headers (bug 95044).
mIsPending = false;
+ // Reset mRequestObserversCalled because we've probably called the request
+ // observers once already.
+ mRequestObserversCalled = false;
+
// fetch cookies, and add them to the request header.
// the server response could have included cookies that must be sent with
// this authentication attempt (bug 84794).
diff --git a/netwerk/test/httpserver/httpd.js b/netwerk/test/httpserver/httpd.js
index 9e5a19073557..e5115d44cad3 100644
--- a/netwerk/test/httpserver/httpd.js
+++ b/netwerk/test/httpserver/httpd.js
@@ -5130,6 +5130,9 @@ nsSimpleEnumerator.prototype =
return this._items[this._nextIndex++];
},
+ [Symbol.iterator]() {
+ return this._items.values();
+ },
QueryInterface: function(aIID)
{
if (Ci.nsISimpleEnumerator.equals(aIID) ||
diff --git a/netwerk/test/unit/test_bug411952.js b/netwerk/test/unit/test_bug411952.js
index e83413fb36ed..393614cf4753 100644
--- a/netwerk/test/unit/test_bug411952.js
+++ b/netwerk/test/unit/test_bug411952.js
@@ -8,9 +8,8 @@ function run_test() {
cm.add("example.com", "/", "C", "V", false, true, false, time, {});
const now = Math.floor((new Date()).getTime() / 1000);
- var enumerator = cm.enumerator, found = false;
- while (enumerator.hasMoreElements()) {
- var cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+ var found = false;
+ for (let cookie of cm.enumerator) {
if (cookie.host == "example.com" &&
cookie.path == "/" &&
cookie.name == "C") {
diff --git a/netwerk/test/unit/test_network_activity.js b/netwerk/test/unit/test_network_activity.js
index 19458f6f182b..4729b09a0b57 100644
--- a/netwerk/test/unit/test_network_activity.js
+++ b/netwerk/test/unit/test_network_activity.js
@@ -44,10 +44,7 @@ function run_test() {
// setting up an observer
let networkActivity = function(subject, topic, value) {
subject.QueryInterface(Ci.nsIMutableArray);
- let enumerator = subject.enumerate();
- while (enumerator.hasMoreElements()) {
- let data = enumerator.getNext();
- data.QueryInterface(Ci.nsINetworkActivityData);
+ for (let data of subject.enumerate()) {
results.push(data);
}
};
diff --git a/netwerk/test/unit/test_permmgr.js b/netwerk/test/unit/test_permmgr.js
index 3b6adb8a7fad..29b56f45a042 100644
--- a/netwerk/test/unit/test_permmgr.js
+++ b/netwerk/test/unit/test_permmgr.js
@@ -61,13 +61,7 @@ function run_test() {
}
// test the enumerator ...
- var j = 0;
- var perms = new Array();
- var enumerator = pm.enumerator;
- while (enumerator.hasMoreElements()) {
- perms[j] = enumerator.getNext().QueryInterface(Ci.nsIPermission);
- ++j;
- }
+ var perms = Array.from(pm.enumerator);
Assert.equal(perms.length, hosts.length);
// ... remove all the hosts ...
diff --git a/old-configure.in b/old-configure.in
index 30ed601d8423..880def074ddc 100644
--- a/old-configure.in
+++ b/old-configure.in
@@ -545,6 +545,13 @@ if test "$GNU_CC"; then
AC_MSG_RESULT([no])
LDFLAGS=$_SAVE_LDFLAGS)
+ AC_MSG_CHECKING([for -z nocopyreloc option to ld])
+ _SAVE_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-z,nocopyreloc"
+ AC_TRY_LINK(,,AC_MSG_RESULT([yes]),
+ AC_MSG_RESULT([no])
+ LDFLAGS=$_SAVE_LDFLAGS)
+
AC_MSG_CHECKING([for --build-id option to ld])
_SAVE_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,--build-id"
diff --git a/security/manager/pki/resources/content/device_manager.js b/security/manager/pki/resources/content/device_manager.js
index 368e8672cd3d..7873971048aa 100644
--- a/security/manager/pki/resources/content/device_manager.js
+++ b/security/manager/pki/resources/content/device_manager.js
@@ -40,9 +40,7 @@ function doConfirm(msg) {
}
function RefreshDeviceList() {
- let modules = secmoddb.listModules();
- for (let module of XPCOMUtils.IterSimpleEnumerator(modules,
- Ci.nsIPKCS11Module)) {
+ for (let module of secmoddb.listModules()) {
let slots = module.listSlots();
AddModule(module, slots);
}
@@ -81,7 +79,7 @@ function AddModule(module, slots) {
row.appendChild(cell);
item.appendChild(row);
var parent = document.createElement("treechildren");
- for (let slot of XPCOMUtils.IterSimpleEnumerator(slots, Ci.nsIPKCS11Slot)) {
+ for (let slot of slots) {
var child_item = document.createElement("treeitem");
var child_row = document.createElement("treerow");
var child_cell = document.createElement("treecell");
diff --git a/security/manager/pki/resources/content/pippki.js b/security/manager/pki/resources/content/pippki.js
index d16475a05ca3..db438395bafe 100644
--- a/security/manager/pki/resources/content/pippki.js
+++ b/security/manager/pki/resources/content/pippki.js
@@ -288,13 +288,7 @@ function getChainForUsage(results, usage) {
for (let result of results) {
if (certificateUsages[result.usageString] == usage &&
result.errorCode == PRErrorCodeSuccess) {
- let array = [];
- let enumerator = result.chain.getEnumerator();
- while (enumerator.hasMoreElements()) {
- let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
- array.push(cert);
- }
- return array;
+ return Array.from(result.chain.getEnumerator());
}
}
return null;
diff --git a/security/manager/ssl/PKCS11ModuleDB.cpp b/security/manager/ssl/PKCS11ModuleDB.cpp
index 0d9bf9ba2a7b..da9f9d6185a0 100644
--- a/security/manager/ssl/PKCS11ModuleDB.cpp
+++ b/security/manager/ssl/PKCS11ModuleDB.cpp
@@ -192,7 +192,7 @@ PKCS11ModuleDB::ListModules(nsISimpleEnumerator** _retval)
}
}
- return array->Enumerate(_retval);
+ return array->Enumerate(_retval, NS_GET_IID(nsIPKCS11Module));
}
NS_IMETHODIMP
diff --git a/security/manager/ssl/nsNSSCertificate.cpp b/security/manager/ssl/nsNSSCertificate.cpp
index 724be3e667fa..db3db682f143 100644
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -1220,8 +1220,6 @@ nsNSSCertList::GetRootCertificate(/* out */ nsCOMPtr& aRoot)
return NS_OK;
}
-NS_IMPL_ISUPPORTS(nsNSSCertListEnumerator, nsISimpleEnumerator)
-
nsNSSCertListEnumerator::nsNSSCertListEnumerator(
const UniqueCERTCertList& certList)
{
diff --git a/security/manager/ssl/nsNSSCertificate.h b/security/manager/ssl/nsNSSCertificate.h
index 152f2d1461c2..898d695b1fc2 100644
--- a/security/manager/ssl/nsNSSCertificate.h
+++ b/security/manager/ssl/nsNSSCertificate.h
@@ -15,10 +15,10 @@
#include "nsIASN1Object.h"
#include "nsIClassInfo.h"
#include "nsISerializable.h"
-#include "nsISimpleEnumerator.h"
#include "nsIX509Cert.h"
#include "nsIX509CertDB.h"
#include "nsIX509CertList.h"
+#include "nsSimpleEnumerator.h"
#include "nsStringFwd.h"
namespace mozilla { namespace pkix { class DERArray; } }
@@ -123,12 +123,13 @@ private:
void operator=(const nsNSSCertList&) = delete;
};
-class nsNSSCertListEnumerator : public nsISimpleEnumerator
+class nsNSSCertListEnumerator : public nsSimpleEnumerator
{
public:
- NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
+ const nsID& DefaultInterface() override { return NS_GET_IID(nsIX509Cert); }
+
explicit nsNSSCertListEnumerator(const mozilla::UniqueCERTCertList& certList);
private:
virtual ~nsNSSCertListEnumerator() {}
diff --git a/security/manager/ssl/nsPKCS11Slot.cpp b/security/manager/ssl/nsPKCS11Slot.cpp
index 644bc741bd51..157c8bd29f21 100644
--- a/security/manager/ssl/nsPKCS11Slot.cpp
+++ b/security/manager/ssl/nsPKCS11Slot.cpp
@@ -290,5 +290,5 @@ nsPKCS11Module::ListSlots(nsISimpleEnumerator** _retval)
}
}
- return array->Enumerate(_retval);
+ return array->Enumerate(_retval, NS_GET_IID(nsIPKCS11Slot));
}
diff --git a/security/manager/ssl/nsSiteSecurityService.cpp b/security/manager/ssl/nsSiteSecurityService.cpp
index 3a9e81183b67..202ebdd65d28 100644
--- a/security/manager/ssl/nsSiteSecurityService.cpp
+++ b/security/manager/ssl/nsSiteSecurityService.cpp
@@ -473,7 +473,7 @@ SiteHPKPState::GetSha256Keys(nsISimpleEnumerator** aSha256Keys)
return NS_ERROR_FAILURE;
}
}
- return NS_NewArrayEnumerator(aSha256Keys, keys);
+ return NS_NewArrayEnumerator(aSha256Keys, keys, NS_GET_IID(nsIVariant));
}
NS_IMETHODIMP
@@ -1895,7 +1895,7 @@ nsSiteSecurityService::Enumerate(uint32_t aType,
states.AppendObject(state);
}
- NS_NewArrayEnumerator(aEnumerator, states);
+ NS_NewArrayEnumerator(aEnumerator, states, NS_GET_IID(nsISiteSecurityState));
return NS_OK;
}
diff --git a/security/manager/ssl/tests/mochitest/browser/browser_clientAuth_ui.js b/security/manager/ssl/tests/mochitest/browser/browser_clientAuth_ui.js
index 15bb0056435f..7903b41c4e07 100644
--- a/security/manager/ssl/tests/mochitest/browser/browser_clientAuth_ui.js
+++ b/security/manager/ssl/tests/mochitest/browser/browser_clientAuth_ui.js
@@ -90,9 +90,7 @@ function checkDialogContents(win, notBefore, notAfter) {
}
function findCertByCommonName(commonName) {
- let certEnumerator = certDB.getCerts().getEnumerator();
- while (certEnumerator.hasMoreElements()) {
- let cert = certEnumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of certDB.getCerts().getEnumerator()) {
if (cert.commonName == commonName) {
return cert;
}
diff --git a/security/manager/ssl/tests/unit/test_certDB_export_pkcs12.js b/security/manager/ssl/tests/unit/test_certDB_export_pkcs12.js
index 0d9aaa817c20..89d7ffd5d52e 100644
--- a/security/manager/ssl/tests/unit/test_certDB_export_pkcs12.js
+++ b/security/manager/ssl/tests/unit/test_certDB_export_pkcs12.js
@@ -17,9 +17,7 @@ const TEST_CERT_PASSWORD = "黒い";
const TEST_OUTPUT_PASSWORD = "other password";
function findCertByCommonName(commonName) {
- let certEnumerator = gCertDB.getCerts().getEnumerator();
- while (certEnumerator.hasMoreElements()) {
- let cert = certEnumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of gCertDB.getCerts().getEnumerator()) {
if (cert.commonName == commonName) {
return cert;
}
diff --git a/security/manager/ssl/tests/unit/test_certDB_export_pkcs12_with_master_password.js b/security/manager/ssl/tests/unit/test_certDB_export_pkcs12_with_master_password.js
index 0db86ee8140b..94e2670557c3 100644
--- a/security/manager/ssl/tests/unit/test_certDB_export_pkcs12_with_master_password.js
+++ b/security/manager/ssl/tests/unit/test_certDB_export_pkcs12_with_master_password.js
@@ -45,9 +45,7 @@ const gPromptFactory = {
};
function findCertByCommonName(commonName) {
- let certEnumerator = gCertDB.getCerts().getEnumerator();
- while (certEnumerator.hasMoreElements()) {
- let cert = certEnumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of gCertDB.getCerts().getEnumerator()) {
if (cert.commonName == commonName) {
return cert;
}
diff --git a/security/manager/ssl/tests/unit/test_certDB_import.js b/security/manager/ssl/tests/unit/test_certDB_import.js
index 8d258933918f..e80798dc128b 100644
--- a/security/manager/ssl/tests/unit/test_certDB_import.js
+++ b/security/manager/ssl/tests/unit/test_certDB_import.js
@@ -65,9 +65,7 @@ function getCertAsByteArray(certPath) {
}
function commonFindCertBy(propertyName, value) {
- let certEnumerator = gCertDB.getCerts().getEnumerator();
- while (certEnumerator.hasMoreElements()) {
- let cert = certEnumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of gCertDB.getCerts().getEnumerator()) {
if (cert[propertyName] == value) {
return cert;
}
diff --git a/security/manager/ssl/tests/unit/test_certDB_import_pkcs12.js b/security/manager/ssl/tests/unit/test_certDB_import_pkcs12.js
index ef83c042e8be..dc2668b7602a 100644
--- a/security/manager/ssl/tests/unit/test_certDB_import_pkcs12.js
+++ b/security/manager/ssl/tests/unit/test_certDB_import_pkcs12.js
@@ -74,9 +74,7 @@ let gTestcases = [
function doesCertExist(commonName) {
let allCerts = gCertDB.getCerts();
- let enumerator = allCerts.getEnumerator();
- while (enumerator.hasMoreElements()) {
- let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of allCerts.getEnumerator()) {
if (cert.isBuiltInRoot) {
continue;
}
diff --git a/security/manager/ssl/tests/unit/test_certDB_import_with_master_password.js b/security/manager/ssl/tests/unit/test_certDB_import_with_master_password.js
index cfc420d90a81..8164d1b04d88 100644
--- a/security/manager/ssl/tests/unit/test_certDB_import_with_master_password.js
+++ b/security/manager/ssl/tests/unit/test_certDB_import_with_master_password.js
@@ -82,9 +82,7 @@ function getCertAsByteArray(certPath) {
}
function findCertByCommonName(commonName) {
- let certEnumerator = gCertDB.getCerts().getEnumerator();
- while (certEnumerator.hasMoreElements()) {
- let cert = certEnumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of gCertDB.getCerts().getEnumerator()) {
if (cert.commonName == commonName) {
return cert;
}
diff --git a/security/manager/ssl/tests/unit/test_enterprise_roots.js b/security/manager/ssl/tests/unit/test_enterprise_roots.js
index 940969e66393..2d04c34b424a 100644
--- a/security/manager/ssl/tests/unit/test_enterprise_roots.js
+++ b/security/manager/ssl/tests/unit/test_enterprise_roots.js
@@ -31,11 +31,9 @@ function check_no_enterprise_roots_imported(certDB, dbKey = undefined) {
function check_some_enterprise_roots_imported(certDB) {
let enterpriseRoots = certDB.getEnterpriseRoots();
notEqual(enterpriseRoots, null, "should have imported some enterprise roots");
- let enumerator = enterpriseRoots.getEnumerator();
let foundNonBuiltIn = false;
let savedDBKey = null;
- while (enumerator.hasMoreElements()) {
- let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of enterpriseRoots.getEnumerator()) {
if (!cert.isBuiltInRoot && !savedDBKey) {
foundNonBuiltIn = true;
savedDBKey = cert.dbKey;
diff --git a/security/manager/ssl/tests/unit/test_pkcs11_module.js b/security/manager/ssl/tests/unit/test_pkcs11_module.js
index ef7d6037a634..2c9f4b97528f 100644
--- a/security/manager/ssl/tests/unit/test_pkcs11_module.js
+++ b/security/manager/ssl/tests/unit/test_pkcs11_module.js
@@ -16,8 +16,7 @@ function checkTestModuleNotPresent() {
let modules = gModuleDB.listModules();
ok(modules.hasMoreElements(),
"One or more modules should be present with test module not present");
- while (modules.hasMoreElements()) {
- let module = modules.getNext().QueryInterface(Ci.nsIPKCS11Module);
+ for (let module of modules) {
notEqual(module.name, "PKCS11 Test Module",
"Non-test module name shouldn't equal 'PKCS11 Test Module'");
ok(!(module.libName && module.libName.includes("pkcs11testmodule")),
@@ -37,8 +36,7 @@ function checkTestModuleExists() {
ok(modules.hasMoreElements(),
"One or more modules should be present with test module present");
let testModule = null;
- while (modules.hasMoreElements()) {
- let module = modules.getNext().QueryInterface(Ci.nsIPKCS11Module);
+ for (let module of modules) {
if (module.name == "PKCS11 Test Module") {
testModule = module;
break;
@@ -90,12 +88,8 @@ function run_test() {
let testModule = checkTestModuleExists();
// Check that listing the slots for the test module works.
- let slots = testModule.listSlots();
- let testModuleSlotNames = [];
- while (slots.hasMoreElements()) {
- let slot = slots.getNext().QueryInterface(Ci.nsIPKCS11Slot);
- testModuleSlotNames.push(slot.name);
- }
+ let testModuleSlotNames = Array.from(testModule.listSlots(),
+ slot => slot.name);
testModuleSlotNames.sort();
const expectedSlotNames = ["Empty PKCS11 Slot", "Test PKCS11 Slot", "Test PKCS11 Slot 二"];
deepEqual(testModuleSlotNames, expectedSlotNames,
diff --git a/security/manager/ssl/tests/unit/test_pkcs11_moduleDB.js b/security/manager/ssl/tests/unit/test_pkcs11_moduleDB.js
index 48f8f955e7c0..f0775fca791e 100644
--- a/security/manager/ssl/tests/unit/test_pkcs11_moduleDB.js
+++ b/security/manager/ssl/tests/unit/test_pkcs11_moduleDB.js
@@ -30,8 +30,7 @@ function run_test() {
Services.strings.createBundle("chrome://pipnss/locale/pipnss.properties");
let rootsModuleName = bundle.GetStringFromName("RootCertModuleName");
let foundRootsModule = false;
- for (let module of XPCOMUtils.IterSimpleEnumerator(moduleDB.listModules(),
- Ci.nsIPKCS11Module)) {
+ for (let module of moduleDB.listModules()) {
if (module.name == rootsModuleName) {
foundRootsModule = true;
break;
diff --git a/security/manager/ssl/tests/unit/test_pkcs11_slot.js b/security/manager/ssl/tests/unit/test_pkcs11_slot.js
index ee332c2947a8..eaee4a54c562 100644
--- a/security/manager/ssl/tests/unit/test_pkcs11_slot.js
+++ b/security/manager/ssl/tests/unit/test_pkcs11_slot.js
@@ -9,8 +9,7 @@
do_get_profile();
function find_slot_by_name(module, name) {
- for (let slot of XPCOMUtils.IterSimpleEnumerator(module.listSlots(),
- Ci.nsIPKCS11Slot)) {
+ for (let slot of module.listSlots()) {
if (slot.name == name) {
return slot;
}
@@ -19,8 +18,7 @@ function find_slot_by_name(module, name) {
}
function find_module_by_name(moduleDB, name) {
- for (let slot of XPCOMUtils.IterSimpleEnumerator(moduleDB.listModules(),
- Ci.nsIPKCS11Module)) {
+ for (let slot of moduleDB.listModules()) {
if (slot.name == name) {
return slot;
}
diff --git a/security/manager/ssl/tests/unit/test_sss_enumerate.js b/security/manager/ssl/tests/unit/test_sss_enumerate.js
index 6daff17a5e8b..c258554a69c7 100644
--- a/security/manager/ssl/tests/unit/test_sss_enumerate.js
+++ b/security/manager/ssl/tests/unit/test_sss_enumerate.js
@@ -64,13 +64,7 @@ function insertEntries() {
}
function getEntries(type) {
- let entryEnumerator = sss.enumerate(type);
- let entries = [];
- while (entryEnumerator.hasMoreElements()) {
- let entry = entryEnumerator.getNext();
- entries.push(entry.QueryInterface(Ci.nsISiteSecurityState));
- }
- return entries;
+ return Array.from(sss.enumerate(type));
}
function checkSiteSecurityStateAttrs(entries) {
@@ -92,11 +86,9 @@ function checkSiteSecurityStateAttrs(entries) {
function checkSha256Keys(hpkpEntries) {
for (let hpkpEntry of hpkpEntries) {
- let enumerator = hpkpEntry.QueryInterface(Ci.nsISiteHPKPState).sha256Keys;
- let keys = [];
- while (enumerator.hasMoreElements()) {
- keys.push(enumerator.getNext().QueryInterface(Ci.nsIVariant));
- }
+ let keys = Array.from(hpkpEntry.QueryInterface(Ci.nsISiteHPKPState).sha256Keys,
+ key => key.QueryInterface(Ci.nsIVariant));
+
equal(keys.length, KEY_HASHES.length, "Should get correct number of keys");
keys.sort();
for (let i = 0; i < KEY_HASHES.length; i++) {
diff --git a/security/manager/tools/genHPKPStaticPins.js b/security/manager/tools/genHPKPStaticPins.js
index aab462cb2c71..fe0e47a93770 100644
--- a/security/manager/tools/genHPKPStaticPins.js
+++ b/security/manager/tools/genHPKPStaticPins.js
@@ -375,11 +375,9 @@ function downloadAndParseChromePins(filename,
// nicknames and digests of the SPKInfo for the mozilla trust store
function loadNSSCertinfo(extraCertificates) {
let allCerts = gCertDB.getCerts();
- let enumerator = allCerts.getEnumerator();
let certNameToSKD = {};
let certSKDToName = {};
- while (enumerator.hasMoreElements()) {
- let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of allCerts.getEnumerator()) {
if (!cert.isBuiltInRoot) {
continue;
}
diff --git a/security/manager/tools/genRootCAHashes.js b/security/manager/tools/genRootCAHashes.js
index b6e71e51b14f..83e61df77967 100644
--- a/security/manager/tools/genRootCAHashes.js
+++ b/security/manager/tools/genRootCAHashes.js
@@ -172,10 +172,7 @@ function insertTrustAnchorsFromDatabase() {
const TRUST_TYPE = Ci.nsIX509CertDB.TRUSTED_SSL;
// Iterate through the whole Cert DB
- let enumerator = CertDb.getCerts().getEnumerator();
- while (enumerator.hasMoreElements()) {
- let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
-
+ for (let cert of CertDb.getCerts().getEnumerator()) {
// Find the certificate in our existing list. Do it here because we need to check if
// it's untrusted too.
diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO
index d21b9db7baba..e1d634b4a012 100644
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1 +1 @@
-d3f512d4f76e
+5bc69334e84f
diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep
index 5182f75552c8..590d1bfaeee3 100644
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -10,3 +10,4 @@
*/
#error "Do not include this header file."
+
diff --git a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
index 2f26d5509fdf..98310e8cc536 100644
--- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
@@ -276,8 +276,13 @@ TEST_P(TlsConnectGeneric, ConnectResumeCorruptTicket) {
ASSERT_NE(nullptr, hmac_key);
SSLInt_SetSelfEncryptMacKey(hmac_key);
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
- ConnectExpectAlert(server_, illegal_parameter);
- server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+ if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ ExpectResumption(RESUME_NONE);
+ Connect();
+ } else {
+ ConnectExpectAlert(server_, illegal_parameter);
+ server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+ }
}
// This callback switches out the "server" cert used on the server with
diff --git a/security/nss/lib/ssl/ssl3exthandle.c b/security/nss/lib/ssl/ssl3exthandle.c
index d1f286dc3c50..dfedf636ad3d 100644
--- a/security/nss/lib/ssl/ssl3exthandle.c
+++ b/security/nss/lib/ssl/ssl3exthandle.c
@@ -1174,17 +1174,18 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, const SECItem *ticket,
&decryptedTicket.len,
decryptedTicket.len);
if (rv != SECSuccess) {
- SECITEM_ZfreeItem(&decryptedTicket, PR_FALSE);
-
- /* Fail with no ticket if we're not a recipient. Otherwise
- * it's a hard failure. */
- if (PORT_GetError() != SEC_ERROR_NOT_A_RECIPIENT) {
- SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
- return SECFailure;
+ /* Ignore decryption failure if we are doing TLS 1.3; that
+ * means the server rejects the client's resumption
+ * attempt. In TLS 1.2, however, it's a hard failure, unless
+ * it's just because we're not the recipient of the ticket. */
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ||
+ PORT_GetError() == SEC_ERROR_NOT_A_RECIPIENT) {
+ SECITEM_ZfreeItem(&decryptedTicket, PR_FALSE);
+ return SECSuccess;
}
- /* We didn't have the right key, so pretend we don't have a
- * ticket. */
+ SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
+ goto loser;
}
rv = ssl_ParseSessionTicket(ss, &decryptedTicket, &parsedTicket);
diff --git a/services/common/tests/unit/test_logmanager.js b/services/common/tests/unit/test_logmanager.js
index 5d707a5cb8c1..4d6fea809458 100644
--- a/services/common/tests/unit/test_logmanager.js
+++ b/services/common/tests/unit/test_logmanager.js
@@ -227,10 +227,9 @@ add_task(async function test_logFileError() {
function countLogFiles() {
let logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
let count = 0;
- let entries = logsdir.directoryEntries;
- while (entries.hasMoreElements()) {
+ for (let entry of logsdir.directoryEntries) {
+ void entry;
count += 1;
- entries.getNext();
}
return count;
}
diff --git a/services/sync/modules/engines/tabs.js b/services/sync/modules/engines/tabs.js
index 675554e65a70..da0f01daaadc 100644
--- a/services/sync/modules/engines/tabs.js
+++ b/services/sync/modules/engines/tabs.js
@@ -135,9 +135,7 @@ TabStore.prototype = {
let allTabs = [];
- let winEnum = this.getWindowEnumerator();
- while (winEnum.hasMoreElements()) {
- let win = winEnum.getNext();
+ for (let win of this.getWindowEnumerator()) {
if (this.shouldSkipWindow(win)) {
continue;
}
@@ -235,9 +233,8 @@ TabStore.prototype = {
// first syncs.
let ids = {};
let allWindowsArePrivate = false;
- let wins = Services.wm.getEnumerator("navigator:browser");
- while (wins.hasMoreElements()) {
- if (PrivateBrowsingUtils.isWindowPrivate(wins.getNext())) {
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ if (PrivateBrowsingUtils.isWindowPrivate(win)) {
// Ensure that at least there is a private window.
allWindowsArePrivate = true;
} else {
@@ -320,17 +317,15 @@ TabTracker.prototype = {
onStart() {
Svc.Obs.add("domwindowopened", this.asyncObserver);
- let wins = Services.wm.getEnumerator("navigator:browser");
- while (wins.hasMoreElements()) {
- this._registerListenersForWindow(wins.getNext());
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ this._registerListenersForWindow(win);
}
},
onStop() {
Svc.Obs.remove("domwindowopened", this.asyncObserver);
- let wins = Services.wm.getEnumerator("navigator:browser");
- while (wins.hasMoreElements()) {
- this._unregisterListenersForWindow(wins.getNext());
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
+ this._unregisterListenersForWindow(win);
}
},
diff --git a/services/sync/tests/unit/head_helpers.js b/services/sync/tests/unit/head_helpers.js
index 00a154ce38a3..81bdd39e08fc 100644
--- a/services/sync/tests/unit/head_helpers.js
+++ b/services/sync/tests/unit/head_helpers.js
@@ -241,14 +241,7 @@ function mockGetWindowEnumerator(url, numWindows, numTabs, indexes, moreURLs) {
},
});
- return {
- hasMoreElements() {
- return elements.length;
- },
- getNext() {
- return elements.shift();
- },
- };
+ return elements.values();
}
// Helper function to get the sync telemetry and add the typically used test
diff --git a/services/sync/tests/unit/test_tab_tracker.js b/services/sync/tests/unit/test_tab_tracker.js
index 56ae7ed7eb1c..cc6d44e50d03 100644
--- a/services/sync/tests/unit/test_tab_tracker.js
+++ b/services/sync/tests/unit/test_tab_tracker.js
@@ -16,34 +16,31 @@ function fakeSvcWinMediator() {
// actions on windows are captured in logs
let logs = [];
delete Services.wm;
+
+ function getNext() {
+ let elt = {addTopics: [], remTopics: [], numAPL: 0, numRPL: 0};
+ logs.push(elt);
+ return {
+ addEventListener(topic) {
+ elt.addTopics.push(topic);
+ },
+ removeEventListener(topic) {
+ elt.remTopics.push(topic);
+ },
+ gBrowser: {
+ addProgressListener() {
+ elt.numAPL++;
+ },
+ removeProgressListener() {
+ elt.numRPL++;
+ },
+ },
+ };
+ }
+
Services.wm = {
getEnumerator() {
- return {
- cnt: 2,
- hasMoreElements() {
- return this.cnt-- > 0;
- },
- getNext() {
- let elt = {addTopics: [], remTopics: [], numAPL: 0, numRPL: 0};
- logs.push(elt);
- return {
- addEventListener(topic) {
- elt.addTopics.push(topic);
- },
- removeEventListener(topic) {
- elt.remTopics.push(topic);
- },
- gBrowser: {
- addProgressListener() {
- elt.numAPL++;
- },
- removeProgressListener() {
- elt.numRPL++;
- },
- },
- };
- }
- };
+ return [getNext(), getNext()];
}
};
return logs;
diff --git a/storage/test/unit/test_vacuum.js b/storage/test/unit/test_vacuum.js
index 884671fff0cd..d2c422279b31 100644
--- a/storage/test/unit/test_vacuum.js
+++ b/storage/test/unit/test_vacuum.js
@@ -23,9 +23,7 @@ function load_test_vacuum_component() {
let catMan = Cc["@mozilla.org/categorymanager;1"].
getService(Ci.nsICategoryManager);
let found = false;
- let entries = catMan.enumerateCategory(CATEGORY_NAME);
- while (entries.hasMoreElements()) {
- let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
+ for (let {data: entry} of catMan.enumerateCategory(CATEGORY_NAME)) {
print("Check if the found category entry (" + entry + ") is expected.");
if (EXPECTED_ENTRIES.includes(entry)) {
print("Check that only one test entry exists.");
diff --git a/taskcluster/docker/periodic-updates/scripts/genHPKPStaticPins.js b/taskcluster/docker/periodic-updates/scripts/genHPKPStaticPins.js
index 1b96a18fc071..843fad31250a 100644
--- a/taskcluster/docker/periodic-updates/scripts/genHPKPStaticPins.js
+++ b/taskcluster/docker/periodic-updates/scripts/genHPKPStaticPins.js
@@ -370,11 +370,9 @@ function downloadAndParseChromePins(filename,
// nicknames and digests of the SPKInfo for the mozilla trust store
function loadNSSCertinfo(extraCertificates) {
let allCerts = gCertDB.getCerts();
- let enumerator = allCerts.getEnumerator();
let certNameToSKD = {};
let certSKDToName = {};
- while (enumerator.hasMoreElements()) {
- let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ for (let cert of allCerts.getEnumerator()) {
if (!cert.isBuiltInRoot) {
continue;
}
diff --git a/taskcluster/scripts/misc/build-cctools-port-macosx.sh b/taskcluster/scripts/misc/build-cctools-port-macosx.sh
index 10659c442e6b..dd583b22131e 100755
--- a/taskcluster/scripts/misc/build-cctools-port-macosx.sh
+++ b/taskcluster/scripts/misc/build-cctools-port-macosx.sh
@@ -26,8 +26,9 @@ mkdir -p $CROSSTOOLS_BUILD_DIR
git clone --no-checkout $CROSSTOOL_PORT_REPOSITORY $CROSSTOOLS_SOURCE_DIR
cd $CROSSTOOLS_SOURCE_DIR
git checkout $CROSSTOOL_PORT_REV
-# Cherry pick a fix for LTO.
+# Cherry pick two fixes for LTO.
git cherry-pick -n 82381f5038a340025ae145745ae5b325cd1b749a
+git cherry-pick -n 328c7371008a854af30823adcd4ec1e763054a1d
echo "Building from commit hash `git rev-parse $CROSSTOOL_PORT_REV`..."
# Fetch clang from tooltool
diff --git a/taskcluster/scripts/misc/build-cctools-port.sh b/taskcluster/scripts/misc/build-cctools-port.sh
index 257ac14049e1..92e41c953cc1 100755
--- a/taskcluster/scripts/misc/build-cctools-port.sh
+++ b/taskcluster/scripts/misc/build-cctools-port.sh
@@ -22,8 +22,9 @@ mkdir -p $CROSSTOOLS_BUILD_DIR
git clone --no-checkout $CROSSTOOL_PORT_REPOSITORY $CROSSTOOLS_SOURCE_DIR
cd $CROSSTOOLS_SOURCE_DIR
git checkout $CROSSTOOL_PORT_REV
-# Cherry pick a fix for LTO.
+# Cherry pick two fixes for LTO.
git cherry-pick -n 82381f5038a340025ae145745ae5b325cd1b749a
+git cherry-pick -n 328c7371008a854af30823adcd4ec1e763054a1d
echo "Building from commit hash `git rev-parse $CROSSTOOL_PORT_REV`..."
# Fetch clang from tooltool
diff --git a/testing/marionette/components/marionette.js b/testing/marionette/components/marionette.js
index 860ec9e7937b..296cec662801 100644
--- a/testing/marionette/components/marionette.js
+++ b/testing/marionette/components/marionette.js
@@ -383,9 +383,7 @@ class MarionetteParentProcess {
// When Firefox starts on Windows, an additional GFX sanity test
// window may appear off-screen. Marionette should wait for it
// to close.
- let winEn = Services.wm.getEnumerator(null);
- while (winEn.hasMoreElements()) {
- let win = winEn.getNext();
+ for (let win of Services.wm.getEnumerator(null)) {
if (win.document.documentURI == "chrome://gfxsanity/content/sanityparent.html") {
this.gfxWindow = win;
break;
diff --git a/testing/marionette/cookie.js b/testing/marionette/cookie.js
index eb8c2b626c44..9037d6ac799d 100644
--- a/testing/marionette/cookie.js
+++ b/testing/marionette/cookie.js
@@ -209,9 +209,8 @@ cookie.iter = function* (host, currentPath = "/") {
const isForCurrentPath = path => currentPath.includes(path);
- let en = cookie.manager.getCookiesFromHost(host, {});
- while (en.hasMoreElements()) {
- let cookie = en.getNext().QueryInterface(Ci.nsICookie2);
+ let cookies = cookie.manager.getCookiesFromHost(host, {});
+ for (let cookie of cookies) {
// take the hostname and progressively shorten
let hostname = host;
do {
diff --git a/testing/marionette/driver.js b/testing/marionette/driver.js
index 2e761cd49bc2..81de638f47fe 100644
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -92,24 +92,6 @@ const globalMessageManager = Services.mm;
* @namespace driver
*/
-/**
- * Helper function for converting a {@link nsISimpleEnumerator} to a
- * JavaScript iterator.
- *
- * @memberof driver
- *
- * @param {nsISimpleEnumerator} enumerator
- * Enumerator to turn into iterator.
- *
- * @return {Iterable}
- * Iterator.
- */
-function* enumeratorIterator(enumerator) {
- while (enumerator.hasMoreElements()) {
- yield enumerator.getNext();
- }
-}
-
/**
* Implements (parts of) the W3C WebDriver protocol. GeckoDriver lives
* in chrome space and mediates calls to the message listener of the current
@@ -243,7 +225,7 @@ Object.defineProperty(GeckoDriver.prototype, "timeouts", {
Object.defineProperty(GeckoDriver.prototype, "windows", {
get() {
- return enumeratorIterator(Services.wm.getEnumerator(null));
+ return Services.wm.getEnumerator(null);
},
});
diff --git a/testing/marionette/modal.js b/testing/marionette/modal.js
index a7723afec373..70c91d035338 100644
--- a/testing/marionette/modal.js
+++ b/testing/marionette/modal.js
@@ -62,10 +62,7 @@ modal.addHandler = function(handler) {
modal.findModalDialogs = function(context) {
// First check if there is a modal dialog already present for the
// current browser window.
- let winEn = Services.wm.getEnumerator(null);
- while (winEn.hasMoreElements()) {
- let win = winEn.getNext();
-
+ for (let win of Services.wm.getEnumerator(null)) {
// Modal dialogs which do not have an opener set, we cannot detect
// as long as GetZOrderDOMWindowEnumerator doesn't work on Linux
// (Bug 156333).
diff --git a/testing/marionette/test/unit/test_cookie.js b/testing/marionette/test/unit/test_cookie.js
index 77340002ee63..3a3a2c770eb2 100644
--- a/testing/marionette/test/unit/test_cookie.js
+++ b/testing/marionette/test/unit/test_cookie.js
@@ -42,21 +42,8 @@ cookie.manager = {
getCookiesFromHost(host) {
let hostCookies = this.cookies.filter(c => c.host === host ||
c.host === "." + host);
- let nextIndex = 0;
- return {
- hasMoreElements() {
- return nextIndex < hostCookies.length;
- },
-
- getNext() {
- return {
- QueryInterface() {
- return hostCookies[nextIndex++];
- },
- };
- },
- };
+ return hostCookies;
},
};
diff --git a/testing/mochitest/api.js b/testing/mochitest/api.js
index 2cdcb42a22d4..b1a79e90d438 100644
--- a/testing/mochitest/api.js
+++ b/testing/mochitest/api.js
@@ -129,9 +129,7 @@ this.mochikit = class extends ExtensionAPI {
onShutdown() {
if (AppConstants.platform != "android") {
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- let win = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
WindowListener.tearDownWindow(win);
}
diff --git a/testing/mochitest/browser-test.js b/testing/mochitest/browser-test.js
index 1b296fd6e14d..80ddf88701e4 100644
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -537,9 +537,7 @@ Tester.prototype = {
},
waitForGraphicsTestWindowToBeGone(aCallback) {
- let windowsEnum = Services.wm.getEnumerator(null);
- while (windowsEnum.hasMoreElements()) {
- let win = windowsEnum.getNext();
+ for (let win of Services.wm.getEnumerator(null)) {
if (win != window && !win.closed &&
win.document.documentURI == "chrome://gfxsanity/content/sanityparent.html") {
this.BrowserTestUtils.domWindowClosed(win).then(aCallback);
@@ -586,9 +584,7 @@ Tester.prototype = {
// Remove stale windows
this.structuredLogger.info("checking window state");
- let windowsEnum = Services.wm.getEnumerator(null);
- while (windowsEnum.hasMoreElements()) {
- let win = windowsEnum.getNext();
+ for (let win of Services.wm.getEnumerator(null)) {
if (win != window && !win.closed &&
win.document.documentElement.getAttribute("id") != "browserTestHarness") {
let type = win.document.documentElement.getAttribute("windowtype");
diff --git a/testing/specialpowers/content/MockFilePicker.jsm b/testing/specialpowers/content/MockFilePicker.jsm
index a44338848630..30ac42144bbc 100644
--- a/testing/specialpowers/content/MockFilePicker.jsm
+++ b/testing/specialpowers/content/MockFilePicker.jsm
@@ -214,12 +214,15 @@ MockFilePickerInstance.prototype = {
return {
index: 0,
QueryInterface: ChromeUtils.generateQI([Ci.nsISimpleEnumerator]),
+ [Symbol.iterator]() {
+ return Array.from(MockFilePicker.returnData, d => d.nsIFile).values();
+ },
hasMoreElements() {
return this.index < MockFilePicker.returnData.length;
},
getNext() {
if (!MockFilePicker.returnData[this.index].nsIFile) {
- return null;
+ throw Components.Exception("", Cr.NS_ERROR_FAILURE);
}
return MockFilePicker.returnData[this.index++].nsIFile;
}
diff --git a/testing/specialpowers/content/SpecialPowersObserverAPI.js b/testing/specialpowers/content/SpecialPowersObserverAPI.js
index 740ab5f54478..9e2c722a9a5a 100644
--- a/testing/specialpowers/content/SpecialPowersObserverAPI.js
+++ b/testing/specialpowers/content/SpecialPowersObserverAPI.js
@@ -262,13 +262,10 @@ SpecialPowersObserverAPI.prototype = {
// First create observers from the category manager.
let cm =
Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
- let enumerator = cm.enumerateCategory(topic);
let observers = [];
- while (enumerator.hasMoreElements()) {
- let entry =
- enumerator.getNext().QueryInterface(Ci.nsISupportsCString).data;
+ for (let {data: entry} of cm.enumerateCategory(topic)) {
let contractID = cm.getCategoryEntry(topic, entry);
let factoryFunction;
@@ -289,14 +286,11 @@ SpecialPowersObserverAPI.prototype = {
}
// Next enumerate the registered observers.
- enumerator = Services.obs.enumerateObservers(topic);
- while (enumerator.hasMoreElements()) {
- try {
- let observer = enumerator.getNext().QueryInterface(Ci.nsIObserver);
- if (!observers.includes(observer)) {
- observers.push(observer);
- }
- } catch (e) { }
+ for (let observer of Services.obs.enumerateObservers(topic)) {
+ if (observer instanceof Ci.nsIObserver &&
+ !observers.includes(observer)) {
+ observers.push(observer);
+ }
}
observers.forEach(function(observer) {
diff --git a/testing/talos/talos/talos-powers/bootstrap.js b/testing/talos/talos/talos-powers/bootstrap.js
index d8cf85456e53..1f7f7c158aae 100644
--- a/testing/talos/talos/talos-powers/bootstrap.js
+++ b/testing/talos/talos/talos-powers/bootstrap.js
@@ -245,9 +245,7 @@ TalosPowersService.prototype = {
});
}
- let enumerator = Services.wm.getEnumerator(null);
- while (enumerator.hasMoreElements()) {
- let domWindow = enumerator.getNext();
+ for (let domWindow of Services.wm.getEnumerator(null)) {
domWindow.close();
}
diff --git a/testing/web-platform/meta/html/rendering/non-replaced-elements/the-fieldset-element-0/legend-position-relative.html.ini b/testing/web-platform/meta/html/rendering/non-replaced-elements/the-fieldset-element-0/legend-position-relative.html.ini
deleted file mode 100644
index f1efd104b956..000000000000
--- a/testing/web-platform/meta/html/rendering/non-replaced-elements/the-fieldset-element-0/legend-position-relative.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[legend-position-relative.html]
- expected: FAIL
diff --git a/testing/web-platform/tests/css/css-values/reference/vh_not_refreshing_on_chrome-ref.html b/testing/web-platform/tests/css/css-values/reference/vh_not_refreshing_on_chrome-ref.html
index 32ce9ada1556..279d1c69b9f7 100644
--- a/testing/web-platform/tests/css/css-values/reference/vh_not_refreshing_on_chrome-ref.html
+++ b/testing/web-platform/tests/css/css-values/reference/vh_not_refreshing_on_chrome-ref.html
@@ -36,10 +36,10 @@
var frameTest = document.getElementById('frameTest');
// let's resize the iframe vertically only, showing that the vh sizes is not updated.
- if (height <= 300) {
+ if (height < 300) {
//frameTest.style.width = height++ + "px";
- frameTest.style.height = height++ + "px";
+ frameTest.style.height = ++height + "px";
setTimeout(resizeReference, 10);
diff --git a/testing/web-platform/tests/css/css-values/support/vh_not_refreshing_on_chrome_iframe.html b/testing/web-platform/tests/css/css-values/support/vh_not_refreshing_on_chrome_iframe.html
index c58ec57a58f2..8d8e9b49d4aa 100644
--- a/testing/web-platform/tests/css/css-values/support/vh_not_refreshing_on_chrome_iframe.html
+++ b/testing/web-platform/tests/css/css-values/support/vh_not_refreshing_on_chrome_iframe.html
@@ -78,8 +78,12 @@
setTimeout(animate, 20);
- addEventListener('transitionend', function() {
- parent.postMessage('testBoxWithTransition', '*');
+ addEventListener('transitionend', event => {
+ if (event.propertyName == 'width') {
+ // Stop any further transitons.
+ testBoxWithTransition.style.transitionProperty = 'none';
+ parent.postMessage('testBoxWithTransition', '*');
+ }
}, false);
var transitionedTestBoxStyle = document.getElementById('testBoxWithTransition').style;
transitionedTestBoxStyle.height = "60px";
diff --git a/testing/web-platform/tests/css/css-values/vh_not_refreshing_on_chrome.html b/testing/web-platform/tests/css/css-values/vh_not_refreshing_on_chrome.html
index b4e0a413ab97..52a45a114c85 100644
--- a/testing/web-platform/tests/css/css-values/vh_not_refreshing_on_chrome.html
+++ b/testing/web-platform/tests/css/css-values/vh_not_refreshing_on_chrome.html
@@ -39,10 +39,10 @@
var frameTest = document.getElementById('frameTest');
// let's resize the iframe vertically only, showing that the vh sizes is not updated.
- if (height <= 300) {
+ if (height < 300) {
//frameTest.style.width = height++ + "px";
- frameTest.style.height = height++ + "px";
+ frameTest.style.height = ++height + "px";
setTimeout(resizeReference, 10);
diff --git a/toolkit/components/aboutperformance/content/aboutPerformance.js b/toolkit/components/aboutperformance/content/aboutPerformance.js
index 7b70986719c0..08ae793bbce6 100644
--- a/toolkit/components/aboutperformance/content/aboutPerformance.js
+++ b/toolkit/components/aboutperformance/content/aboutPerformance.js
@@ -75,9 +75,7 @@ function performanceCountersEnabled() {
let tabFinder = {
update() {
this._map = new Map();
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- let win = windows.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
let tabbrowser = win.gBrowser;
for (let browser of tabbrowser.browsers) {
let id = browser.outerWindowID; // May be `null` if the browser isn't loaded yet
diff --git a/toolkit/components/alerts/resources/content/alert.js b/toolkit/components/alerts/resources/content/alert.js
index 787142f8771c..ab5ccdf14e9a 100644
--- a/toolkit/components/alerts/resources/content/alert.js
+++ b/toolkit/components/alerts/resources/content/alert.js
@@ -200,9 +200,7 @@ function moveWindowToReplace(aReplacedAlert) {
// Move windows that come after the replaced alert if the height is different.
if (heightDelta != 0) {
- let windows = Services.wm.getEnumerator("alert:alert");
- while (windows.hasMoreElements()) {
- let alertWindow = windows.getNext();
+ for (let alertWindow of Services.wm.getEnumerator("alert:alert")) {
// boolean to determine if the alert window is after the replaced alert.
let alertIsAfter = gOrigin & NS_ALERT_TOP ?
alertWindow.screenY > aReplacedAlert.screenY :
@@ -230,9 +228,7 @@ function moveWindowToEnd() {
screen.availTop + screen.availHeight - window.outerHeight;
// Position the window at the end of all alerts.
- let windows = Services.wm.getEnumerator("alert:alert");
- while (windows.hasMoreElements()) {
- let alertWindow = windows.getNext();
+ for (let alertWindow of Services.wm.getEnumerator("alert:alert")) {
if (alertWindow != window) {
if (gOrigin & NS_ALERT_TOP) {
y = Math.max(y, alertWindow.screenY + alertWindow.outerHeight - WINDOW_SHADOW_SPREAD);
@@ -253,9 +249,7 @@ function onAlertBeforeUnload() {
if (!gIsReplaced) {
// Move other alert windows to fill the gap left by closing alert.
let heightDelta = window.outerHeight + WINDOW_MARGIN - WINDOW_SHADOW_SPREAD;
- let windows = Services.wm.getEnumerator("alert:alert");
- while (windows.hasMoreElements()) {
- let alertWindow = windows.getNext();
+ for (let alertWindow of Services.wm.getEnumerator("alert:alert")) {
if (alertWindow != window) {
if (gOrigin & NS_ALERT_TOP) {
if (alertWindow.screenY > window.screenY) {
diff --git a/toolkit/components/asyncshutdown/nsAsyncShutdown.js b/toolkit/components/asyncshutdown/nsAsyncShutdown.js
index 642244b1f4d7..d89ac39d660e 100644
--- a/toolkit/components/asyncshutdown/nsAsyncShutdown.js
+++ b/toolkit/components/asyncshutdown/nsAsyncShutdown.js
@@ -23,9 +23,7 @@ var PropertyBagConverter = {
throw new TypeError("Not a property bag");
}
let result = {};
- let enumerator = bag.enumerator;
- while (enumerator.hasMoreElements()) {
- let {name, value: property} = enumerator.getNext().QueryInterface(Ci.nsIProperty);
+ for (let {name, value: property} of bag.enumerator) {
let value = this.toValue(property);
result[name] = value;
}
diff --git a/toolkit/components/cleardata/ClearDataService.js b/toolkit/components/cleardata/ClearDataService.js
index 967dae182e18..41b86c5bf351 100644
--- a/toolkit/components/cleardata/ClearDataService.js
+++ b/toolkit/components/cleardata/ClearDataService.js
@@ -64,8 +64,7 @@ const CookieCleaner = {
return new Promise((aResolve, aReject) => {
let count = 0;
- while (aEnumerator.hasMoreElements()) {
- let cookie = aEnumerator.getNext().QueryInterface(Ci.nsICookie2);
+ for (let cookie of aEnumerator) {
if (aCb(cookie)) {
Services.cookies.remove(cookie.host, cookie.name, cookie.path,
false, cookie.originAttributes);
@@ -514,9 +513,7 @@ const AuthCacheCleaner = {
const PermissionsCleaner = {
deleteByHost(aHost, aOriginAttributes) {
return new Promise(aResolve => {
- let enumerator = Services.perms.enumerator;
- while (enumerator.hasMoreElements()) {
- let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
+ for (let perm of Services.perms.enumerator) {
try {
if (eTLDService.hasRootDomain(perm.principal.URI.host, aHost)) {
Services.perms.removePermission(perm);
@@ -590,10 +587,8 @@ const SecuritySettingsCleaner = {
Ci.nsISiteSecurityService.HEADER_HPKP]) {
// Also remove HSTS/HPKP/OMS information for subdomains by enumerating
// the information in the site security service.
- let enumerator = sss.enumerate(type);
- while (enumerator.hasMoreElements()) {
- let entry = enumerator.getNext();
- let hostname = entry.QueryInterface(Ci.nsISiteSecurityState).hostname;
+ for (let entry of sss.enumerate(type)) {
+ let hostname = entry.hostname;
if (eTLDService.hasRootDomain(hostname, aHost)) {
// This uri is used as a key to remove the state.
let uri = Services.io.newURI("https://" + hostname);
diff --git a/toolkit/components/contextualidentity/ContextualIdentityService.jsm b/toolkit/components/contextualidentity/ContextualIdentityService.jsm
index ec343c35e266..0a5c4600519a 100644
--- a/toolkit/components/contextualidentity/ContextualIdentityService.jsm
+++ b/toolkit/components/contextualidentity/ContextualIdentityService.jsm
@@ -473,10 +473,7 @@ _ContextualIdentityService.prototype = {
},
_forEachContainerTab(callback, userContextId = 0) {
- let windowList = Services.wm.getEnumerator("navigator:browser");
- while (windowList.hasMoreElements()) {
- let win = windowList.getNext();
-
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (win.closed || !win.gBrowser) {
continue;
}
@@ -530,10 +527,7 @@ _ContextualIdentityService.prototype = {
// Collect the userContextIds currently used by any stored cookie.
let cookiesUserContextIds = new Set();
- const enumerator = Services.cookies.enumerator;
- while (enumerator.hasMoreElements()) {
- const cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
-
+ for (let cookie of Services.cookies.enumerator) {
// Skip any userContextIds that should not be cleared.
if (cookie.originAttributes.userContextId >= minUserContextId &&
!keepDataContextIds.includes(cookie.originAttributes.userContextId)) {
diff --git a/toolkit/components/contextualidentity/tests/unit/test_corruptedFile.js b/toolkit/components/contextualidentity/tests/unit/test_corruptedFile.js
index 475307bb1d2f..fc21621ce9a3 100644
--- a/toolkit/components/contextualidentity/tests/unit/test_corruptedFile.js
+++ b/toolkit/components/contextualidentity/tests/unit/test_corruptedFile.js
@@ -35,9 +35,7 @@ function createCookie(userContextId) {
function hasCookie(userContextId) {
let found = false;
- let enumerator = Services.cookies.getCookiesFromHost(BASE_URL, {userContextId});
- while (enumerator.hasMoreElements()) {
- let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ for (let cookie of Services.cookies.getCookiesFromHost(BASE_URL, {userContextId})) {
if (cookie.originAttributes.userContextId == userContextId) {
found = true;
break;
diff --git a/toolkit/components/downloads/DownloadUIHelper.jsm b/toolkit/components/downloads/DownloadUIHelper.jsm
index 367ab7d6bfe8..ec65eb746933 100644
--- a/toolkit/components/downloads/DownloadUIHelper.jsm
+++ b/toolkit/components/downloads/DownloadUIHelper.jsm
@@ -63,9 +63,7 @@ var DownloadUIHelper = {
XPCOMUtils.defineLazyGetter(DownloadUIHelper, "strings", function() {
let strings = {};
let sb = Services.strings.createBundle(kStringBundleUrl);
- let enumerator = sb.getSimpleEnumeration();
- while (enumerator.hasMoreElements()) {
- let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
+ for (let string of sb.getSimpleEnumeration()) {
let stringName = string.key;
if (stringName in kStringsRequiringFormatting) {
strings[stringName] = function() {
diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm
index 07f2b63a92cd..2ab44e737d44 100644
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -680,6 +680,24 @@ class ExtensionData {
return manager.initModuleJSON([modules]);
};
+ result.contentScripts = [];
+ for (let options of manifest.content_scripts || []) {
+ result.contentScripts.push({
+ allFrames: options.all_frames,
+ matchAboutBlank: options.match_about_blank,
+ frameID: options.frame_id,
+ runAt: options.run_at,
+
+ matches: options.matches,
+ excludeMatches: options.exclude_matches || [],
+ includeGlobs: options.include_globs,
+ excludeGlobs: options.exclude_globs,
+
+ jsPaths: options.js || [],
+ cssPaths: options.css || [],
+ });
+ }
+
if (this.canUseExperiment(manifest)) {
let parentModules = {};
let childModules = {};
@@ -820,6 +838,7 @@ class ExtensionData {
this.manifest = manifestData.manifest;
this.apiNames = manifestData.apiNames;
+ this.contentScripts = manifestData.contentScripts;
this.dependencies = manifestData.dependencies;
this.permissions = manifestData.permissions;
this.schemaURLs = manifestData.schemaURLs;
@@ -1533,6 +1552,10 @@ class Extension extends ExtensionData {
this.manifest.background.scripts);
}
+ get optionalPermissions() {
+ return this.manifest.optional_permissions;
+ }
+
// Representation of the extension to send to content
// processes. This should include anything the content process might
// need.
@@ -1548,7 +1571,7 @@ class Extension extends ExtensionData {
webAccessibleResources: this.webAccessibleResources.map(res => res.glob),
whiteListedHosts: this.whiteListedHosts.patterns.map(pat => pat.pattern),
permissions: this.permissions,
- optionalPermissions: this.manifest.optional_permissions,
+ optionalPermissions: this.optionalPermissions,
};
}
@@ -1563,10 +1586,6 @@ class Extension extends ExtensionData {
};
}
- get contentScripts() {
- return this.manifest.content_scripts || [];
- }
-
broadcast(msg, data) {
return new Promise(resolve => {
let {ppmm} = Services;
diff --git a/toolkit/components/extensions/ExtensionChild.jsm b/toolkit/components/extensions/ExtensionChild.jsm
index 9edd6f35336b..88b788824221 100644
--- a/toolkit/components/extensions/ExtensionChild.jsm
+++ b/toolkit/components/extensions/ExtensionChild.jsm
@@ -594,13 +594,12 @@ var ExtensionManager = {
// Represents a browser extension in the content process.
class BrowserExtensionContent extends EventEmitter {
- constructor(data) {
+ constructor(policy) {
super();
- this.data = data;
- this.id = data.id;
- this.uuid = data.uuid;
- this.instanceId = data.instanceId;
+ this.policy = policy;
+ this.instanceId = policy.instanceId;
+ this.optionalPermissions = policy.optionalPermissions;
if (WebExtensionPolicy.isExtensionProcess) {
Object.assign(this, this.getSharedData("extendedData"));
@@ -609,14 +608,8 @@ class BrowserExtensionContent extends EventEmitter {
this.MESSAGE_EMIT_EVENT = `Extension:EmitEvent:${this.instanceId}`;
Services.cpmm.addMessageListener(this.MESSAGE_EMIT_EVENT, this);
- this.webAccessibleResources = data.webAccessibleResources.map(res => new MatchGlob(res));
- this.permissions = data.permissions;
- this.optionalPermissions = data.optionalPermissions;
-
let restrictSchemes = !this.hasPermission("mozillaAddons");
- this.whiteListedHosts = new MatchPatternSet(data.whiteListedHosts, {restrictSchemes, ignorePath: true});
-
this.apiManager = this.getAPIManager();
this._manifest = null;
@@ -637,50 +630,65 @@ class BrowserExtensionContent extends EventEmitter {
/* eslint-disable mozilla/balanced-listeners */
this.on("add-permissions", (ignoreEvent, permissions) => {
if (permissions.permissions.length > 0) {
+ let perms = new Set(this.policy.permissions);
for (let perm of permissions.permissions) {
- this.permissions.add(perm);
+ perms.add(perm);
}
+ this.policy.permissions = perms;
}
if (permissions.origins.length > 0) {
let patterns = this.whiteListedHosts.patterns.map(host => host.pattern);
- this.whiteListedHosts = new MatchPatternSet([...patterns, ...permissions.origins],
- {restrictSchemes, ignorePath: true});
- }
-
- if (this.policy) {
- this.policy.permissions = Array.from(this.permissions);
- this.policy.allowedOrigins = this.whiteListedHosts;
+ this.policy.allowedOrigins =
+ new MatchPatternSet([...patterns, ...permissions.origins],
+ {restrictSchemes, ignorePath: true});
}
});
this.on("remove-permissions", (ignoreEvent, permissions) => {
if (permissions.permissions.length > 0) {
+ let perms = new Set(this.policy.permissions);
for (let perm of permissions.permissions) {
- this.permissions.delete(perm);
+ perms.delete(perm);
}
+ this.policy.permissions = perms;
}
if (permissions.origins.length > 0) {
let origins = permissions.origins.map(
origin => new MatchPattern(origin, {ignorePath: true}).pattern);
- this.whiteListedHosts = new MatchPatternSet(
+ this.policy.allowedOrigins = new MatchPatternSet(
this.whiteListedHosts.patterns
.filter(host => !origins.includes(host.pattern)));
}
-
- if (this.policy) {
- this.policy.permissions = Array.from(this.permissions);
- this.policy.allowedOrigins = this.whiteListedHosts;
- }
});
/* eslint-enable mozilla/balanced-listeners */
ExtensionManager.extensions.set(this.id, this);
}
+ get id() {
+ return this.policy.id;
+ }
+
+ get uuid() {
+ return this.policy.mozExtensionHostname;
+ }
+
+ get permissions() {
+ return new Set(this.policy.permissions);
+ }
+
+ get whiteListedHosts() {
+ return this.policy.allowedOrigins;
+ }
+
+ get webAccessibleResources() {
+ return this.policy.webAccessibleResources;
+ }
+
getSharedData(key, value) {
return sharedData.get(`extension/${this.id}/${key}`);
}
diff --git a/toolkit/components/extensions/ExtensionContent.jsm b/toolkit/components/extensions/ExtensionContent.jsm
index ef375794790e..3fe239f10af3 100644
--- a/toolkit/components/extensions/ExtensionContent.jsm
+++ b/toolkit/components/extensions/ExtensionContent.jsm
@@ -24,6 +24,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "styleSheetService",
"@mozilla.org/content/style-sheet-service;1",
"nsIStyleSheetService");
+XPCOMUtils.defineLazyServiceGetter(this, "processScript",
+ "@mozilla.org/webextensions/extension-process-script;1");
+
const DocumentEncoder = Components.Constructor(
"@mozilla.org/layout/documentEncoder;1?type=text/plain",
"nsIDocumentEncoder", "init");
@@ -510,6 +513,10 @@ class Script {
}
}
+var contentScripts = new DefaultWeakMap(matcher => {
+ return new Script(processScript.extensions.get(matcher.extension), matcher);
+});
+
/**
* An execution context for semi-privileged extension content scripts.
*
@@ -782,7 +789,8 @@ DocumentManager = {
var ExtensionContent = {
BrowserExtensionContent,
- Script,
+
+ contentScripts,
shutdownExtension(extension) {
DocumentManager.shutdownExtension(extension);
@@ -880,14 +888,14 @@ var ExtensionContent = {
}
if (!promises.length) {
- if (options.frame_id) {
+ if (options.frameID) {
return Promise.reject({message: `Frame not found, or missing host permission`});
}
- let frames = options.all_frames ? ", and any iframes" : "";
+ let frames = options.allFrames ? ", and any iframes" : "";
return Promise.reject({message: `Missing host permission for the tab${frames}`});
}
- if (!options.all_frames && promises.length > 1) {
+ if (!options.allFrames && promises.length > 1) {
return Promise.reject({message: `Internal error: Script matched multiple windows`});
}
@@ -898,8 +906,8 @@ var ExtensionContent = {
// we try to send it back over the message manager.
Cu.cloneInto(result, target);
} catch (e) {
- const {js} = options;
- const fileName = js.length ? js[js.length - 1] : "";
+ const {jsPaths} = options;
+ const fileName = jsPaths.length ? jsPaths[jsPaths.length - 1] : "";
const message = `Script '${fileName}' result is non-structured-clonable data`;
return Promise.reject({message, fileName});
}
@@ -915,13 +923,46 @@ var ExtensionContent = {
return WebNavigationFrames.getAllFrames(global.docShell);
},
+ async receiveMessage(global, name, target, data, recipient) {
+ switch (name) {
+ case "Extension:Capture":
+ return this.handleExtensionCapture(global, data.width, data.height, data.options);
+ case "Extension:DetectLanguage":
+ return this.handleDetectLanguage(global, target);
+ case "Extension:Execute":
+ let policy = WebExtensionPolicy.getByID(recipient.extensionId);
+
+ let matcher = new WebExtensionContentScript(policy, data.options);
+
+ Object.assign(matcher, {
+ wantReturnValue: data.options.wantReturnValue,
+ removeCSS: data.options.removeCSS,
+ cssOrigin: data.options.cssOrigin,
+ jsCode: data.options.jsCode,
+ });
+
+ let script = contentScripts.get(matcher);
+
+ // Add the cssCode to the script, so that it can be converted into a cached URL.
+ await script.addCSSCode(data.options.cssCode);
+ delete data.options.cssCode;
+
+ return this.handleExtensionExecute(global, target, data.options, script);
+ case "WebNavigation:GetFrame":
+ return this.handleWebNavigationGetFrame(global, data.options);
+ case "WebNavigation:GetAllFrames":
+ return this.handleWebNavigationGetAllFrames(global);
+ }
+ return null;
+ },
+
// Helpers
* enumerateWindows(docShell) {
let enum_ = docShell.getDocShellEnumerator(docShell.typeContent,
docShell.ENUMERATE_FORWARDS);
- for (let docShell of XPCOMUtils.IterSimpleEnumerator(enum_, Ci.nsIDocShell)) {
+ for (let docShell of enum_) {
try {
yield docShell.domWindow;
} catch (e) {
diff --git a/toolkit/components/extensions/ExtensionPolicyService.cpp b/toolkit/components/extensions/ExtensionPolicyService.cpp
index 3ad8915c3f64..867fa1044aac 100644
--- a/toolkit/components/extensions/ExtensionPolicyService.cpp
+++ b/toolkit/components/extensions/ExtensionPolicyService.cpp
@@ -12,24 +12,35 @@
#include "mozilla/Preferences.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/Services.h"
+#include "mozilla/SimpleEnumerator.h"
#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentFrameMessageManager.h"
#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/Promise-inl.h"
#include "mozIExtensionProcessScript.h"
#include "nsEscape.h"
#include "nsGkAtoms.h"
#include "nsIChannel.h"
#include "nsIContentPolicy.h"
+#include "nsIDocShell.h"
#include "nsIDocument.h"
+#include "nsGlobalWindowOuter.h"
#include "nsILoadInfo.h"
#include "nsIXULRuntime.h"
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"
#include "nsXULAppAPI.h"
+#include "nsQueryObject.h"
namespace mozilla {
using namespace extensions;
+using dom::AutoJSAPI;
+using dom::ContentFrameMessageManager;
+using dom::Promise;
+
#define DEFAULT_BASE_CSP \
"script-src 'self' https://* moz-extension: blob: filesystem: 'unsafe-eval' 'unsafe-inline'; " \
"object-src 'self' https://* moz-extension: blob: filesystem:;"
@@ -251,6 +262,7 @@ ExtensionPolicyService::RegisterObservers()
{
mObs->AddObserver(this, "content-document-global-created", false);
mObs->AddObserver(this, "document-element-inserted", false);
+ mObs->AddObserver(this, "tab-content-frameloader-created", false);
if (XRE_IsContentProcess()) {
mObs->AddObserver(this, "http-on-opening-request", false);
}
@@ -261,6 +273,7 @@ ExtensionPolicyService::UnregisterObservers()
{
mObs->RemoveObserver(this, "content-document-global-created");
mObs->RemoveObserver(this, "document-element-inserted");
+ mObs->RemoveObserver(this, "tab-content-frameloader-created");
if (XRE_IsContentProcess()) {
mObs->RemoveObserver(this, "http-on-opening-request");
}
@@ -284,6 +297,129 @@ ExtensionPolicyService::Observe(nsISupports* aSubject, const char* aTopic, const
if (chan) {
CheckRequest(chan);
}
+ } else if (!strcmp(aTopic, "tab-content-frameloader-created")) {
+ RefPtr mm = do_QueryObject(aSubject);
+ NS_ENSURE_TRUE(mm, NS_ERROR_UNEXPECTED);
+
+ mMessageManagers.PutEntry(mm);
+
+ mm->AddSystemEventListener(NS_LITERAL_STRING("unload"), this,
+ false, false);
+ }
+ return NS_OK;
+}
+
+nsresult
+ExtensionPolicyService::HandleEvent(dom::Event* aEvent)
+{
+ RefPtr mm = do_QueryObject(aEvent->GetTarget());
+ MOZ_ASSERT(mm);
+ if (mm) {
+ mMessageManagers.RemoveEntry(mm);
+ }
+ return NS_OK;
+}
+
+nsresult
+ForEachDocShell(nsIDocShell* aDocShell,
+ const std::function& aCallback)
+{
+ nsCOMPtr iter;
+ MOZ_TRY(aDocShell->GetDocShellEnumerator(nsIDocShell::typeContent,
+ nsIDocShell::ENUMERATE_FORWARDS,
+ getter_AddRefs(iter)));
+
+ for (nsIDocShell& docShell : SimpleEnumerator(iter)) {
+ MOZ_TRY(aCallback(&docShell));
+ }
+ return NS_OK;
+}
+
+
+already_AddRefed
+ExtensionPolicyService::ExecuteContentScript(nsPIDOMWindowInner* aWindow,
+ WebExtensionContentScript& aScript)
+{
+ if (!aWindow->IsCurrentInnerWindow()) {
+ return nullptr;
+ }
+
+ RefPtr promise;
+ ProcessScript().LoadContentScript(&aScript, aWindow, getter_AddRefs(promise));
+ return promise.forget();
+}
+
+RefPtr
+ExtensionPolicyService::ExecuteContentScripts(JSContext* aCx, nsPIDOMWindowInner* aWindow,
+ const nsTArray>& aScripts)
+{
+ AutoTArray, 8> promises;
+
+ for (auto& script : aScripts) {
+ promises.AppendElement(ExecuteContentScript(aWindow, *script));
+ }
+
+ RefPtr promise = Promise::All(aCx, promises, IgnoreErrors());
+ MOZ_RELEASE_ASSERT(promise);
+ return promise;
+}
+
+nsresult
+ExtensionPolicyService::InjectContentScripts(WebExtensionPolicy* aExtension)
+{
+ AutoJSAPI jsapi;
+ MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()));
+
+ for (auto iter = mMessageManagers.ConstIter(); !iter.Done(); iter.Next()) {
+ ContentFrameMessageManager* mm = iter.Get()->GetKey();
+
+ nsCOMPtr docShell = mm->GetDocShell(IgnoreErrors());
+ NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED);
+
+ auto result = ForEachDocShell(docShell, [&](nsIDocShell* aDocShell) -> nsresult {
+ nsCOMPtr win = aDocShell->GetWindow();
+ DocInfo docInfo(win);
+
+ using RunAt = dom::ContentScriptRunAt;
+ using Scripts = AutoTArray, 8>;
+
+ constexpr uint8_t n = uint8_t(RunAt::EndGuard_);
+ Scripts scripts[n];
+
+ auto GetScripts = [&](RunAt aRunAt) -> Scripts&& {
+ return std::move(scripts[uint8_t(aRunAt)]);
+ };
+
+ for (const auto& script : aExtension->ContentScripts()) {
+ if (script->Matches(docInfo)) {
+ GetScripts(script->RunAt()).AppendElement(script);
+ }
+ }
+
+ nsCOMPtr inner = win->GetCurrentInnerWindow();
+
+ MOZ_TRY(ExecuteContentScripts(jsapi.cx(), inner, GetScripts(RunAt::Document_start))
+ ->ThenWithCycleCollectedArgs([](JSContext* aCx, JS::HandleValue aValue,
+ ExtensionPolicyService* aSelf,
+ nsPIDOMWindowInner* aInner,
+ Scripts&& aScripts) {
+ return aSelf->ExecuteContentScripts(aCx, aInner, aScripts).forget();
+ },
+ this, inner, GetScripts(RunAt::Document_end))
+ .andThen([&](auto aPromise) {
+ return aPromise->ThenWithCycleCollectedArgs([](JSContext* aCx,
+ JS::HandleValue aValue,
+ ExtensionPolicyService* aSelf,
+ nsPIDOMWindowInner* aInner,
+ Scripts&& aScripts) {
+ return aSelf->ExecuteContentScripts(aCx, aInner, aScripts).forget();
+ },
+ this, inner, GetScripts(RunAt::Document_idle));
+ }));
+
+ return NS_OK;
+ });
+ MOZ_TRY(result);
}
return NS_OK;
}
@@ -312,6 +448,37 @@ ExtensionPolicyService::CheckRequest(nsIChannel* aChannel)
CheckContentScripts({uri.get(), loadInfo}, true);
}
+static bool
+CheckParentFrames(nsPIDOMWindowOuter* aWindow, WebExtensionPolicy& aPolicy)
+{
+ nsCOMPtr aboutAddons;
+ if (NS_FAILED(NS_NewURI(getter_AddRefs(aboutAddons), "about:addons"))) {
+ return false;
+ }
+
+ auto* piWin = aWindow;
+ while ((piWin = piWin->GetScriptableParentOrNull())) {
+ auto* win = nsGlobalWindowOuter::Cast(piWin);
+
+ auto* principal = BasePrincipal::Cast(win->GetPrincipal());
+ if (nsContentUtils::IsSystemPrincipal(principal)) {
+ // The add-on manager is a special case, since it contains extension
+ // options pages in same-type frames.
+ bool equals;
+ if (NS_SUCCEEDED(win->GetDocumentURI()->Equals(aboutAddons, &equals)) &&
+ equals) {
+ return true;
+ }
+ }
+
+ if (principal->AddonPolicy() != &aPolicy) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
// Checks a document, just after the document element has been inserted, for
// matching content scripts or extension principals, and loads them if
// necessary.
@@ -320,6 +487,12 @@ ExtensionPolicyService::CheckDocument(nsIDocument* aDocument)
{
nsCOMPtr win = aDocument->GetWindow();
if (win) {
+ nsIDocShell* docShell = win->GetDocShell();
+ RefPtr mm = docShell->GetMessageManager();
+ if (!mm || !mMessageManagers.Contains(mm)) {
+ return;
+ }
+
if (win->GetDocumentURI()) {
CheckContentScripts(win.get(), false);
}
@@ -328,7 +501,9 @@ ExtensionPolicyService::CheckDocument(nsIDocument* aDocument)
RefPtr policy = BasePrincipal::Cast(principal)->AddonPolicy();
if (policy) {
- ProcessScript().InitExtensionDocument(policy, aDocument);
+ bool privileged = IsExtensionProcess() && CheckParentFrames(win, *policy);
+
+ ProcessScript().InitExtensionDocument(policy, aDocument, privileged);
}
}
}
@@ -355,12 +530,22 @@ ExtensionPolicyService::CheckWindow(nsPIDOMWindowOuter* aWindow)
return;
}
- CheckContentScripts(aWindow, false);
+ nsIDocShell* docShell = aWindow->GetDocShell();
+ if (RefPtr mm = docShell->GetMessageManager()) {
+ if (mMessageManagers.Contains(mm)) {
+ CheckContentScripts(aWindow, false);
+ }
+ }
}
void
ExtensionPolicyService::CheckContentScripts(const DocInfo& aDocInfo, bool aIsPreload)
{
+ nsCOMPtr win;
+ if (!aIsPreload) {
+ win = aDocInfo.GetWindow()->GetCurrentInnerWindow();
+ }
+
for (auto iter = mExtensions.Iter(); !iter.Done(); iter.Next()) {
RefPtr policy = iter.Data();
@@ -369,7 +554,11 @@ ExtensionPolicyService::CheckContentScripts(const DocInfo& aDocInfo, bool aIsPre
if (aIsPreload) {
ProcessScript().PreloadContentScript(script);
} else {
- ProcessScript().LoadContentScript(script, aDocInfo.GetWindow());
+ if (!win->IsCurrentInnerWindow()) {
+ break;
+ }
+ RefPtr promise;
+ ProcessScript().LoadContentScript(script, win, getter_AddRefs(promise));
}
}
}
@@ -503,6 +692,7 @@ NS_IMPL_CYCLE_COLLECTION(ExtensionPolicyService, mExtensions, mExtensionHosts,
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionPolicyService)
NS_INTERFACE_MAP_ENTRY(nsIAddonPolicyService)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
+ NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAddonPolicyService)
NS_INTERFACE_MAP_END
diff --git a/toolkit/components/extensions/ExtensionPolicyService.h b/toolkit/components/extensions/ExtensionPolicyService.h
index 1cf41df1537c..0dadc5b44871 100644
--- a/toolkit/components/extensions/ExtensionPolicyService.h
+++ b/toolkit/components/extensions/ExtensionPolicyService.h
@@ -13,22 +13,30 @@
#include "nsHashKeys.h"
#include "nsIAddonPolicyService.h"
#include "nsAtom.h"
+#include "nsIDOMEventListener.h"
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsISupports.h"
#include "nsPointerHashKeys.h"
#include "nsRefPtrHashtable.h"
+#include "nsTHashtable.h"
class nsIChannel;
class nsIObserverService;
class nsIDocument;
+class nsIPIDOMWindowInner;
class nsIPIDOMWindowOuter;
namespace mozilla {
+namespace dom {
+ class ContentFrameMessageManager;
+ class Promise;
+}
namespace extensions {
class DocInfo;
class DocumentObserver;
+ class WebExtensionContentScript;
}
using extensions::DocInfo;
@@ -36,6 +44,7 @@ using extensions::WebExtensionPolicy;
class ExtensionPolicyService final : public nsIAddonPolicyService
, public nsIObserver
+ , public nsIDOMEventListener
, public nsIMemoryReporter
{
public:
@@ -44,6 +53,7 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIADDONPOLICYSERVICE
NS_DECL_NSIOBSERVER
+ NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_NSIMEMORYREPORTER
static ExtensionPolicyService& GetSingleton();
@@ -86,6 +96,8 @@ public:
bool UseRemoteExtensions() const;
bool IsExtensionProcess() const;
+ nsresult InjectContentScripts(WebExtensionPolicy* aExtension);
+
protected:
virtual ~ExtensionPolicyService();
@@ -101,9 +113,19 @@ private:
void CheckContentScripts(const DocInfo& aDocInfo, bool aIsPreload);
+ already_AddRefed
+ ExecuteContentScript(nsPIDOMWindowInner* aWindow,
+ extensions::WebExtensionContentScript& aScript);
+
+ RefPtr
+ ExecuteContentScripts(JSContext* aCx, nsPIDOMWindowInner* aWindow,
+ const nsTArray>& aScripts);
+
nsRefPtrHashtable, WebExtensionPolicy> mExtensions;
nsRefPtrHashtable mExtensionHosts;
+ nsTHashtable> mMessageManagers;
+
nsRefPtrHashtable,
extensions::DocumentObserver> mObservers;
diff --git a/toolkit/components/extensions/WebExtensionContentScript.h b/toolkit/components/extensions/WebExtensionContentScript.h
index 29f3cb05f516..bda2410ef92b 100644
--- a/toolkit/components/extensions/WebExtensionContentScript.h
+++ b/toolkit/components/extensions/WebExtensionContentScript.h
@@ -148,8 +148,9 @@ protected:
virtual ~MozDocumentMatcher() = default;
- MozDocumentMatcher(const dom::MozDocumentMatcherInit& aInit,
- ErrorResult& aRv);
+ MozDocumentMatcher(dom::GlobalObject& aGlobal,
+ const dom::MozDocumentMatcherInit& aInit,
+ bool aRestricted, ErrorResult& aRv);
RefPtr mExtension;
@@ -210,7 +211,8 @@ protected:
virtual ~WebExtensionContentScript() = default;
- WebExtensionContentScript(WebExtensionPolicy& aExtension,
+ WebExtensionContentScript(dom::GlobalObject& aGlobal,
+ WebExtensionPolicy& aExtension,
const ContentScriptInit& aInit,
ErrorResult& aRv);
diff --git a/toolkit/components/extensions/WebExtensionPolicy.cpp b/toolkit/components/extensions/WebExtensionPolicy.cpp
index 1d63e073d8be..39154afd50b7 100644
--- a/toolkit/components/extensions/WebExtensionPolicy.cpp
+++ b/toolkit/components/extensions/WebExtensionPolicy.cpp
@@ -67,6 +67,68 @@ Proto()
}
+bool
+ParseGlobs(GlobalObject& aGlobal, Sequence aGlobs,
+ nsTArray>& aResult, ErrorResult& aRv)
+{
+ for (auto& elem : aGlobs) {
+ if (elem.IsMatchGlob()) {
+ aResult.AppendElement(elem.GetAsMatchGlob());
+ } else {
+ RefPtr glob = MatchGlob::Constructor(aGlobal,
+ elem.GetAsString(),
+ true, aRv);
+ if (aRv.Failed()) {
+ return false;
+ }
+ aResult.AppendElement(glob);
+ }
+ }
+ return true;
+}
+
+enum class ErrorBehavior {
+ CreateEmptyPattern,
+ Fail,
+};
+
+already_AddRefed
+ParseMatches(GlobalObject& aGlobal,
+ const OwningMatchPatternSetOrStringSequence& aMatches,
+ const MatchPatternOptions& aOptions,
+ ErrorBehavior aErrorBehavior,
+ ErrorResult& aRv)
+{
+ if (aMatches.IsMatchPatternSet()) {
+ return do_AddRef(aMatches.GetAsMatchPatternSet().get());
+ }
+
+ const auto& strings = aMatches.GetAsStringSequence();
+
+ nsTArray patterns;
+ if (!patterns.SetCapacity(strings.Length(), fallible)) {
+ aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+
+ for (auto& string : strings) {
+ OwningStringOrMatchPattern elt;
+ elt.SetAsString() = string;
+ patterns.AppendElement(elt);
+ }
+
+ RefPtr result = MatchPatternSet::Constructor(
+ aGlobal, patterns, aOptions, aRv);
+
+ if (aRv.Failed() && aErrorBehavior == ErrorBehavior::CreateEmptyPattern) {
+ aRv.SuppressException();
+ result = MatchPatternSet::Constructor(aGlobal, {}, aOptions, aRv);
+ }
+
+ return result.forget();
+}
+
+
/*****************************************************************************
* WebExtensionPolicy
*****************************************************************************/
@@ -80,9 +142,20 @@ WebExtensionPolicy::WebExtensionPolicy(GlobalObject& aGlobal,
, mContentSecurityPolicy(aInit.mContentSecurityPolicy)
, mLocalizeCallback(aInit.mLocalizeCallback)
, mPermissions(new AtomSet(aInit.mPermissions))
- , mHostPermissions(aInit.mAllowedOrigins)
{
- mWebAccessiblePaths.AppendElements(aInit.mWebAccessibleResources);
+ if (!ParseGlobs(aGlobal, aInit.mWebAccessibleResources, mWebAccessiblePaths,
+ aRv)) {
+ return;
+ }
+
+ MatchPatternOptions options;
+ options.mRestrictSchemes = HasPermission(nsGkAtoms::mozillaAddons);
+
+ mHostPermissions = ParseMatches(aGlobal, aInit.mAllowedOrigins, options,
+ ErrorBehavior::CreateEmptyPattern, aRv);
+ if (aRv.Failed()) {
+ return;
+ }
if (!aInit.mBackgroundScripts.IsNull()) {
mBackgroundScripts.SetValue().AppendElements(aInit.mBackgroundScripts.Value());
@@ -102,7 +175,7 @@ WebExtensionPolicy::WebExtensionPolicy(GlobalObject& aGlobal,
}
RefPtr contentScript =
- new WebExtensionContentScript(*this, scriptInit, aRv);
+ new WebExtensionContentScript(aGlobal, *this, scriptInit, aRv);
if (aRv.Failed()) {
return;
}
@@ -258,6 +331,15 @@ WebExtensionPolicy::UnregisterContentScript(const WebExtensionContentScript& scr
WebExtensionPolicy_Binding::ClearCachedContentScriptsValue(this);
}
+void
+WebExtensionPolicy::InjectContentScripts(ErrorResult& aRv)
+{
+ nsresult rv = EPS().InjectContentScripts(this);
+ if (NS_FAILED(rv)) {
+ aRv.Throw(rv);
+ }
+}
+
/* static */ bool
WebExtensionPolicy::UseRemoteWebExtensions(GlobalObject& aGlobal)
{
@@ -437,7 +519,8 @@ MozDocumentMatcher::Constructor(GlobalObject& aGlobal,
const dom::MozDocumentMatcherInit& aInit,
ErrorResult& aRv)
{
- RefPtr matcher = new MozDocumentMatcher(aInit, aRv);
+ RefPtr matcher = new MozDocumentMatcher(aGlobal, aInit,
+ false, aRv);
if (aRv.Failed()) {
return nullptr;
}
@@ -450,42 +533,67 @@ WebExtensionContentScript::Constructor(GlobalObject& aGlobal,
const ContentScriptInit& aInit,
ErrorResult& aRv)
{
- RefPtr script = new WebExtensionContentScript(aExtension, aInit, aRv);
+ RefPtr script = new WebExtensionContentScript(
+ aGlobal, aExtension, aInit, aRv);
if (aRv.Failed()) {
return nullptr;
}
return script.forget();
}
-MozDocumentMatcher::MozDocumentMatcher(const dom::MozDocumentMatcherInit& aInit,
+MozDocumentMatcher::MozDocumentMatcher(GlobalObject& aGlobal,
+ const dom::MozDocumentMatcherInit& aInit,
+ bool aRestricted,
ErrorResult& aRv)
: mHasActiveTabPermission(aInit.mHasActiveTabPermission)
- , mRestricted(false)
- , mMatches(aInit.mMatches)
- , mExcludeMatches(aInit.mExcludeMatches)
+ , mRestricted(aRestricted)
, mAllFrames(aInit.mAllFrames)
, mFrameID(aInit.mFrameID)
, mMatchAboutBlank(aInit.mMatchAboutBlank)
{
+ MatchPatternOptions options;
+ options.mRestrictSchemes = mRestricted;
+
+ mMatches = ParseMatches(aGlobal, aInit.mMatches, options,
+ ErrorBehavior::CreateEmptyPattern, aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
+ if (!aInit.mExcludeMatches.IsNull()) {
+ mExcludeMatches = ParseMatches(aGlobal, aInit.mExcludeMatches.Value(),
+ options, ErrorBehavior::CreateEmptyPattern,
+ aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+ }
+
if (!aInit.mIncludeGlobs.IsNull()) {
- mIncludeGlobs.SetValue().AppendElements(aInit.mIncludeGlobs.Value());
+ if (!ParseGlobs(aGlobal, aInit.mIncludeGlobs.Value(), mIncludeGlobs.SetValue(),
+ aRv)) {
+ return;
+ }
}
if (!aInit.mExcludeGlobs.IsNull()) {
- mExcludeGlobs.SetValue().AppendElements(aInit.mExcludeGlobs.Value());
+ if (!ParseGlobs(aGlobal, aInit.mExcludeGlobs.Value(), mExcludeGlobs.SetValue(),
+ aRv)) {
+ return;
+ }
}
}
-WebExtensionContentScript::WebExtensionContentScript(WebExtensionPolicy& aExtension,
+WebExtensionContentScript::WebExtensionContentScript(GlobalObject& aGlobal,
+ WebExtensionPolicy& aExtension,
const ContentScriptInit& aInit,
ErrorResult& aRv)
- : MozDocumentMatcher(aInit, aRv)
+ : MozDocumentMatcher(aGlobal, aInit, !aExtension.HasPermission(nsGkAtoms::mozillaAddons), aRv)
, mCssPaths(aInit.mCssPaths)
, mJsPaths(aInit.mJsPaths)
, mRunAt(aInit.mRunAt)
{
mExtension = &aExtension;
- mRestricted = !aExtension.HasPermission(nsGkAtoms::mozillaAddons);
}
bool
diff --git a/toolkit/components/extensions/WebExtensionPolicy.h b/toolkit/components/extensions/WebExtensionPolicy.h
index 3265036740a4..15edc9854897 100644
--- a/toolkit/components/extensions/WebExtensionPolicy.h
+++ b/toolkit/components/extensions/WebExtensionPolicy.h
@@ -67,6 +67,8 @@ public:
void UnregisterContentScript(const WebExtensionContentScript& script,
ErrorResult& aRv);
+ void InjectContentScripts(ErrorResult& aRv);
+
bool CanAccessURI(const URLInfo& aURI, bool aExplicit = false, bool aCheckRestricted = true) const
{
return (!aCheckRestricted || !IsRestrictedURI(aURI)) &&
diff --git a/toolkit/components/extensions/extension-process-script.js b/toolkit/components/extensions/extension-process-script.js
index 2fadc239ff67..db78a7436f25 100644
--- a/toolkit/components/extensions/extension-process-script.js
+++ b/toolkit/components/extensions/extension-process-script.js
@@ -42,53 +42,10 @@ function getData(extension, key = "") {
const appinfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
const isContentProcess = appinfo.processType == appinfo.PROCESS_TYPE_CONTENT;
-function tryMatchPatternSet(patterns, options) {
- try {
- return new MatchPatternSet(patterns, options);
- } catch (e) {
- Cu.reportError(e);
- return new MatchPatternSet([]);
- }
-}
-
-function parseScriptOptions(options, restrictSchemes = true) {
- return {
- allFrames: options.all_frames,
- matchAboutBlank: options.match_about_blank,
- frameID: options.frame_id,
- runAt: options.run_at,
- hasActiveTabPermission: options.hasActiveTabPermission,
-
- matches: tryMatchPatternSet(options.matches, {restrictSchemes}),
- excludeMatches: tryMatchPatternSet(options.exclude_matches || [], {restrictSchemes}),
- includeGlobs: options.include_globs && options.include_globs.map(glob => new MatchGlob(glob)),
- excludeGlobs: options.exclude_globs && options.exclude_globs.map(glob => new MatchGlob(glob)),
-
- jsPaths: options.js || [],
- cssPaths: options.css || [],
- };
-}
-
var extensions = new DefaultWeakMap(policy => {
- let data = policy.initData;
- if (data.serialize) {
- // We have an actual Extension rather than serialized extension
- // data, so serialize it now to make sure we have consistent inputs
- // between parent and child processes.
- data = data.serialize();
- }
-
- let extension = new ExtensionChild.BrowserExtensionContent(data);
- extension.policy = policy;
- return extension;
+ return new ExtensionChild.BrowserExtensionContent(policy);
});
-var contentScripts = new DefaultWeakMap(matcher => {
- return new ExtensionContent.Script(extensions.get(matcher.extension),
- matcher);
-});
-
-var DocumentManager;
var ExtensionManager;
class ExtensionGlobal {
@@ -118,7 +75,7 @@ class ExtensionGlobal {
return this.frameData;
}
- async receiveMessage({target, messageName, recipient, data, name}) {
+ receiveMessage({target, messageName, recipient, data, name}) {
switch (name) {
case "Extension:SetFrameData":
if (this.frameData) {
@@ -132,162 +89,16 @@ class ExtensionGlobal {
return;
}
- switch (messageName) {
- case "Extension:Capture":
- return ExtensionContent.handleExtensionCapture(this.global, data.width, data.height, data.options);
- case "Extension:DetectLanguage":
- return ExtensionContent.handleDetectLanguage(this.global, target);
- case "Extension:Execute":
- let policy = WebExtensionPolicy.getByID(recipient.extensionId);
-
- let matcher = new WebExtensionContentScript(policy, parseScriptOptions(data.options, !policy.hasPermission("mozillaAddons")));
-
- Object.assign(matcher, {
- wantReturnValue: data.options.wantReturnValue,
- removeCSS: data.options.remove_css,
- cssOrigin: data.options.css_origin,
- jsCode: data.options.jsCode,
- });
-
- let script = contentScripts.get(matcher);
-
- // Add the cssCode to the script, so that it can be converted into a cached URL.
- await script.addCSSCode(data.options.cssCode);
- delete data.options.cssCode;
-
- return ExtensionContent.handleExtensionExecute(this.global, target, data.options, script);
- case "WebNavigation:GetFrame":
- return ExtensionContent.handleWebNavigationGetFrame(this.global, data.options);
- case "WebNavigation:GetAllFrames":
- return ExtensionContent.handleWebNavigationGetAllFrames(this.global);
- }
+ return ExtensionContent.receiveMessage(this.global, messageName, target, data, recipient);
}
}
-// Responsible for creating ExtensionContexts and injecting content
-// scripts into them when new documents are created.
-DocumentManager = {
- globals: new Map(),
-
- // Initialize listeners that we need regardless of whether extensions are
- // enabled.
- earlyInit() {
- Services.obs.addObserver(this, "tab-content-frameloader-created"); // eslint-disable-line mozilla/balanced-listeners
- },
-
- // Initialize a frame script global which extension contexts may be loaded
- // into.
- initGlobal(global) {
- this.globals.set(global, new ExtensionGlobal(global));
- // eslint-disable-next-line mozilla/balanced-listeners
- global.addEventListener("unload", () => {
- this.globals.delete(global);
- });
- },
-
- initExtension(policy) {
- this.injectExtensionScripts(policy);
- },
-
- // Listeners
-
- observe(subject, topic, data) {
- if (topic == "tab-content-frameloader-created") {
- this.initGlobal(subject);
- }
- },
-
- // Script loading
-
- injectExtensionScripts(policy) {
- for (let window of this.enumerateWindows()) {
- let runAt = {document_start: [], document_end: [], document_idle: []};
-
- for (let script of policy.contentScripts) {
- if (script.matchesWindow(window)) {
- runAt[script.runAt].push(script);
- }
- }
-
- let inject = matcher => contentScripts.get(matcher).injectInto(window);
- let injectAll = matchers => Promise.all(matchers.map(inject));
-
- // Intentionally using `.then` instead of `await`, we only need to
- // chain injecting other scripts into *this* window, not all windows.
- injectAll(runAt.document_start)
- .then(() => injectAll(runAt.document_end))
- .then(() => injectAll(runAt.document_idle));
- }
- },
-
- /**
- * Checks that all parent frames for the given withdow either have the
- * same add-on ID, or are special chrome-privileged documents such as
- * about:addons or developer tools panels.
- *
- * @param {Window} window
- * The window to check.
- * @param {string} addonId
- * The add-on ID to check.
- * @returns {boolean}
- */
- checkParentFrames(window, addonId) {
- while (window.parent !== window) {
- window = window.parent;
-
- let principal = window.document.nodePrincipal;
-
- if (Services.scriptSecurityManager.isSystemPrincipal(principal)) {
- // The add-on manager is a special case, since it contains extension
- // options pages in same-type frames.
- if (window.location.href === "about:addons") {
- return true;
- }
- }
-
- if (principal.addonId !== addonId) {
- return false;
- }
- }
-
- return true;
- },
-
- loadInto(policy, window) {
- let extension = extensions.get(policy);
- if (WebExtensionPolicy.isExtensionProcess && this.checkParentFrames(window, policy.id)) {
- // We're in a top-level extension frame, or a sub-frame thereof,
- // in the extension process. Inject the full extension page API.
- ExtensionPageChild.initExtensionContext(extension, window);
- } else {
- // We're in a content sub-frame or not in the extension process.
- // Only inject a minimal content script API.
- ExtensionContent.initExtensionContext(extension, window);
- }
- },
-
- // Helpers
-
- * enumerateWindows(docShell) {
- if (docShell) {
- let enum_ = docShell.getDocShellEnumerator(docShell.typeContent,
- docShell.ENUMERATE_FORWARDS);
-
- for (let docShell of XPCOMUtils.IterSimpleEnumerator(enum_, Ci.nsIDocShell)) {
- yield docShell.domWindow;
- }
- } else {
- for (let global of this.globals.keys()) {
- yield* this.enumerateWindows(global.docShell);
- }
- }
- },
-};
-
ExtensionManager = {
// WeakMap>
registeredContentScripts: new DefaultWeakMap((policy) => new Map()),
+ globals: new WeakMap(),
+
init() {
MessageChannel.setupMessageManagers([Services.cpmm]);
@@ -297,6 +108,11 @@ ExtensionManager = {
Services.cpmm.addMessageListener("Extension:RegisterContentScript", this);
Services.cpmm.addMessageListener("Extension:UnregisterContentScripts", this);
+ // eslint-disable-next-line mozilla/balanced-listeners
+ Services.obs.addObserver(
+ global => this.globals.set(global, new ExtensionGlobal(global)),
+ "tab-content-frameloader-created");
+
for (let id of sharedData.get("extensions/activeIDs") || []) {
this.initExtension(getData({id}));
}
@@ -305,19 +121,13 @@ ExtensionManager = {
initExtensionPolicy(extension) {
let policy = WebExtensionPolicy.getByID(extension.id);
if (!policy) {
- let localizeCallback, allowedOrigins, webAccessibleResources;
- let restrictSchemes = !extension.permissions.has("mozillaAddons");
-
+ let localizeCallback;
if (extension.localize) {
// We have a real Extension object.
localizeCallback = extension.localize.bind(extension);
- allowedOrigins = extension.whiteListedHosts;
- webAccessibleResources = extension.webAccessibleResources;
} else {
// We have serialized extension data;
localizeCallback = str => extensions.get(policy).localize(str);
- allowedOrigins = new MatchPatternSet(extension.whiteListedHosts, {restrictSchemes});
- webAccessibleResources = extension.webAccessibleResources.map(host => new MatchGlob(host));
}
let {backgroundScripts} = extension;
@@ -331,9 +141,9 @@ ExtensionManager = {
name: extension.name,
baseURL: extension.resourceURL,
- permissions: Array.from(extension.permissions),
- allowedOrigins,
- webAccessibleResources,
+ permissions: extension.permissions,
+ allowedOrigins: extension.whiteListedHosts,
+ webAccessibleResources: extension.webAccessibleResources,
contentSecurityPolicy: extension.contentSecurityPolicy,
@@ -341,7 +151,7 @@ ExtensionManager = {
backgroundScripts,
- contentScripts: extension.contentScripts.map(script => parseScriptOptions(script, restrictSchemes)),
+ contentScripts: extension.contentScripts,
});
policy.debugName = `${JSON.stringify(policy.name)} (ID: ${policy.id}, ${policy.getURL()})`;
@@ -352,14 +162,14 @@ ExtensionManager = {
const registeredContentScripts = this.registeredContentScripts.get(policy);
for (let [scriptId, options] of getData(extension, "contentScripts") || []) {
- const parsedOptions = parseScriptOptions(options, restrictSchemes);
- const script = new WebExtensionContentScript(policy, parsedOptions);
+ const script = new WebExtensionContentScript(policy, options);
policy.registerContentScript(script);
registeredContentScripts.set(scriptId, script);
}
policy.active = true;
- policy.initData = extension;
+ policy.instanceId = extension.instanceId;
+ policy.optionalPermissions = extension.optionalPermissions;
}
return policy;
},
@@ -370,108 +180,91 @@ ExtensionManager = {
}
let policy = this.initExtensionPolicy(data);
- DocumentManager.initExtension(policy);
+ policy.injectContentScripts();
},
receiveMessage({name, data}) {
- switch (name) {
- case "Extension:Startup": {
- this.initExtension(data);
+ try {
+ switch (name) {
+ case "Extension:Startup":
+ this.initExtension(data);
+ break;
- Services.cpmm.sendAsyncMessage("Extension:StartupComplete");
- break;
- }
+ case "Extension:Shutdown": {
+ let policy = WebExtensionPolicy.getByID(data.id);
+ if (policy) {
+ if (extensions.has(policy)) {
+ extensions.get(policy).shutdown();
+ }
- case "Extension:Shutdown": {
- let policy = WebExtensionPolicy.getByID(data.id);
-
- if (policy) {
- if (extensions.has(policy)) {
- extensions.get(policy).shutdown();
- }
-
- if (isContentProcess) {
- policy.active = false;
- }
- }
- Services.cpmm.sendAsyncMessage("Extension:ShutdownComplete");
- break;
- }
-
- case "Extension:FlushJarCache": {
- ExtensionUtils.flushJarCache(data.path);
- Services.cpmm.sendAsyncMessage("Extension:FlushJarCacheComplete");
- break;
- }
-
- case "Extension:RegisterContentScript": {
- let policy = WebExtensionPolicy.getByID(data.id);
-
- if (policy) {
- const registeredContentScripts = this.registeredContentScripts.get(policy);
-
- if (registeredContentScripts.has(data.scriptId)) {
- Cu.reportError(new Error(
- `Registering content script ${data.scriptId} on ${data.id} more than once`));
- } else {
- try {
- const parsedOptions = parseScriptOptions(data.options, !policy.hasPermission("mozillaAddons"));
- const script = new WebExtensionContentScript(policy, parsedOptions);
- policy.registerContentScript(script);
- registeredContentScripts.set(data.scriptId, script);
- } catch (e) {
- Cu.reportError(e);
+ if (isContentProcess) {
+ policy.active = false;
}
}
+ break;
}
- Services.cpmm.sendAsyncMessage("Extension:RegisterContentScriptComplete");
- break;
- }
+ case "Extension:FlushJarCache":
+ ExtensionUtils.flushJarCache(data.path);
+ break;
- case "Extension:UnregisterContentScripts": {
- let policy = WebExtensionPolicy.getByID(data.id);
+ case "Extension:RegisterContentScript": {
+ let policy = WebExtensionPolicy.getByID(data.id);
- if (policy) {
- const registeredContentScripts = this.registeredContentScripts.get(policy);
+ if (policy) {
+ const registeredContentScripts = this.registeredContentScripts.get(policy);
- for (const scriptId of data.scriptIds) {
- const script = registeredContentScripts.get(scriptId);
- if (script) {
- try {
+ if (registeredContentScripts.has(data.scriptId)) {
+ Cu.reportError(new Error(
+ `Registering content script ${data.scriptId} on ${data.id} more than once`));
+ } else {
+ const script = new WebExtensionContentScript(policy, data.options);
+ policy.registerContentScript(script);
+ registeredContentScripts.set(data.scriptId, script);
+ }
+ }
+ break;
+ }
+
+ case "Extension:UnregisterContentScripts": {
+ let policy = WebExtensionPolicy.getByID(data.id);
+
+ if (policy) {
+ const registeredContentScripts = this.registeredContentScripts.get(policy);
+
+ for (const scriptId of data.scriptIds) {
+ const script = registeredContentScripts.get(scriptId);
+ if (script) {
policy.unregisterContentScript(script);
registeredContentScripts.delete(scriptId);
- } catch (e) {
- Cu.reportError(e);
}
}
}
+ break;
}
-
- Services.cpmm.sendAsyncMessage("Extension:UnregisterContentScriptsComplete");
- break;
}
+ } catch (e) {
+ Cu.reportError(e);
}
+ Services.cpmm.sendAsyncMessage(`${name}Complete`);
},
};
function ExtensionProcessScript() {
- if (!ExtensionProcessScript.singleton) {
- ExtensionProcessScript.singleton = this;
- }
- return ExtensionProcessScript.singleton;
}
-ExtensionProcessScript.singleton = null;
-
ExtensionProcessScript.prototype = {
classID: Components.ID("{21f9819e-4cdf-49f9-85a0-850af91a5058}"),
QueryInterface: ChromeUtils.generateQI([Ci.mozIExtensionProcessScript]),
+ _xpcom_factory: XPCOMUtils.generateSingletonFactory(ExtensionProcessScript),
+
get wrappedJSObject() { return this; },
+ extensions,
+
getFrameData(global, force) {
- let extGlobal = DocumentManager.globals.get(global);
+ let extGlobal = ExtensionManager.globals.get(global);
return extGlobal && extGlobal.getFrameData(force);
},
@@ -479,9 +272,12 @@ ExtensionProcessScript.prototype = {
return ExtensionManager.initExtensionPolicy(extension);
},
- initExtensionDocument(policy, doc) {
- if (DocumentManager.globals.has(doc.defaultView.docShell.messageManager)) {
- DocumentManager.loadInto(policy, doc.defaultView);
+ initExtensionDocument(policy, doc, privileged) {
+ let extension = extensions.get(policy);
+ if (privileged) {
+ ExtensionPageChild.initExtensionContext(extension, doc.defaultView);
+ } else {
+ ExtensionContent.initExtensionContext(extension, doc.defaultView);
}
},
@@ -493,17 +289,14 @@ ExtensionProcessScript.prototype = {
},
preloadContentScript(contentScript) {
- contentScripts.get(contentScript).preload();
+ ExtensionContent.contentScripts.get(contentScript).preload();
},
loadContentScript(contentScript, window) {
- if (DocumentManager.globals.has(window.docShell.messageManager)) {
- contentScripts.get(contentScript).injectInto(window);
- }
+ return ExtensionContent.contentScripts.get(contentScript).injectInto(window);
},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ExtensionProcessScript]);
-DocumentManager.earlyInit();
ExtensionManager.init();
diff --git a/toolkit/components/extensions/mozIExtensionProcessScript.idl b/toolkit/components/extensions/mozIExtensionProcessScript.idl
index 968d997decfc..77df945d9086 100644
--- a/toolkit/components/extensions/mozIExtensionProcessScript.idl
+++ b/toolkit/components/extensions/mozIExtensionProcessScript.idl
@@ -4,15 +4,18 @@
#include "nsISupports.idl"
-interface mozIDOMWindowProxy;
+interface mozIDOMWindow;
webidl Document;
+webidl WebExtensionContentScript;
[scriptable,uuid(6b09dc51-6caa-4ca7-9d6d-30c87258a630)]
interface mozIExtensionProcessScript : nsISupports
{
void preloadContentScript(in nsISupports contentScript);
- void loadContentScript(in nsISupports contentScript, in mozIDOMWindowProxy window);
+ Promise loadContentScript(in WebExtensionContentScript contentScript,
+ in mozIDOMWindow window);
- void initExtensionDocument(in nsISupports extension, in Document doc);
+ void initExtensionDocument(in nsISupports extension, in Document doc,
+ in bool privileged);
};
diff --git a/toolkit/components/extensions/parent/ext-contentScripts.js b/toolkit/components/extensions/parent/ext-contentScripts.js
index bca0e9faaf80..045d7d4c880a 100644
--- a/toolkit/components/extensions/parent/ext-contentScripts.js
+++ b/toolkit/components/extensions/parent/ext-contentScripts.js
@@ -63,14 +63,14 @@ class ContentScriptParent {
const options = {
matches: details.matches,
- exclude_matches: details.excludeMatches,
- include_globs: details.includeGlobs,
- exclude_globs: details.excludeGlobs,
- all_frames: details.allFrames,
- match_about_blank: details.matchAboutBlank,
- run_at: details.runAt || "document_idle",
- js: [],
- css: [],
+ excludeMatches: details.excludeMatches,
+ includeGlobs: details.includeGlobs,
+ excludeGlobs: details.excludeGlobs,
+ allFrames: details.allFrames,
+ matchAboutBlank: details.matchAboutBlank,
+ runAt: details.runAt || "document_idle",
+ jsPaths: [],
+ cssPaths: [],
};
const convertCodeToURL = (data, mime) => {
@@ -83,7 +83,7 @@ class ContentScriptParent {
};
if (details.js && details.js.length > 0) {
- options.js = details.js.map(data => {
+ options.jsPaths = details.js.map(data => {
if (data.file) {
return data.file;
}
@@ -93,7 +93,7 @@ class ContentScriptParent {
}
if (details.css && details.css.length > 0) {
- options.css = details.css.map(data => {
+ options.cssPaths = details.css.map(data => {
if (data.file) {
return data.file;
}
diff --git a/toolkit/components/extensions/parent/ext-cookies.js b/toolkit/components/extensions/parent/ext-cookies.js
index 96650384440a..566b7f8345b6 100644
--- a/toolkit/components/extensions/parent/ext-cookies.js
+++ b/toolkit/components/extensions/parent/ext-cookies.js
@@ -278,7 +278,7 @@ const query = function* (detailsIn, props, context) {
return true;
}
- for (const cookie of XPCOMUtils.IterSimpleEnumerator(enumerator, Ci.nsICookie2)) {
+ for (const cookie of enumerator) {
if (matches(cookie)) {
yield {cookie, isPrivate, storeId};
}
diff --git a/toolkit/components/extensions/parent/ext-management.js b/toolkit/components/extensions/parent/ext-management.js
index 420240b6baf6..288b9a271598 100644
--- a/toolkit/components/extensions/parent/ext-management.js
+++ b/toolkit/components/extensions/parent/ext-management.js
@@ -187,6 +187,28 @@ this.management = class extends ExtensionAPI {
});
},
+ async install({url, hash}) {
+ let listener = {
+ onDownloadEnded(install) {
+ if (install.addon.appDisabled || install.addon.type !== "theme") {
+ install.cancel();
+ return false;
+ }
+ },
+ };
+
+ let install = await AddonManager.getInstallForURL(url, "application/x-xpinstall", hash);
+ install.addListener(listener);
+ try {
+ await install.install();
+ } catch (e) {
+ Cu.reportError(e);
+ throw new ExtensionError("Incompatible addon");
+ }
+ await install.addon.enable();
+ return {id: install.addon.id};
+ },
+
async getSelf() {
let addon = await AddonManager.getAddonByID(extension.id);
return getExtensionInfoForAddon(extension, addon);
diff --git a/toolkit/components/extensions/parent/ext-tabs-base.js b/toolkit/components/extensions/parent/ext-tabs-base.js
index 8babc590f06b..0f1d7e4d56d1 100644
--- a/toolkit/components/extensions/parent/ext-tabs-base.js
+++ b/toolkit/components/extensions/parent/ext-tabs-base.js
@@ -648,9 +648,9 @@ class TabBase {
*/
_execute(context, details, kind, method) {
let options = {
- js: [],
- css: [],
- remove_css: method == "removeCSS",
+ jsPaths: [],
+ cssPaths: [],
+ removeCSS: method == "removeCSS",
};
// We require a `code` or a `file` property, but we can't accept both.
@@ -673,26 +673,26 @@ class TabBase {
if (!this.extension.isExtensionURL(url)) {
return Promise.reject({message: "Files to be injected must be within the extension"});
}
- options[kind].push(url);
+ options[`${kind}Paths`].push(url);
}
if (details.allFrames) {
- options.all_frames = details.allFrames;
+ options.allFrames = details.allFrames;
}
if (details.frameId !== null) {
- options.frame_id = details.frameId;
+ options.frameID = details.frameId;
}
if (details.matchAboutBlank) {
- options.match_about_blank = details.matchAboutBlank;
+ options.matchAboutBlank = details.matchAboutBlank;
}
if (details.runAt !== null) {
- options.run_at = details.runAt;
+ options.runAt = details.runAt;
} else {
- options.run_at = "document_idle";
+ options.runAt = "document_idle";
}
if (details.cssOrigin !== null) {
- options.css_origin = details.cssOrigin;
+ options.cssOrigin = details.cssOrigin;
} else {
- options.css_origin = "author";
+ options.cssOrigin = "author";
}
options.wantReturnValue = true;
@@ -1354,10 +1354,7 @@ class WindowTrackerBase extends EventEmitter {
// fires for browser windows when they're in that in-between state, and just
// before we register our own "domwindowcreated" listener.
- let e = Services.wm.getEnumerator("");
- while (e.hasMoreElements()) {
- let window = e.getNext();
-
+ for (let window of Services.wm.getEnumerator("")) {
let ok = includeIncomplete;
if (window.document.readyState === "complete") {
ok = this.isBrowserWindow(window);
diff --git a/toolkit/components/extensions/schemas/management.json b/toolkit/components/extensions/schemas/management.json
index f00fade4a983..c42f03bbc3e9 100644
--- a/toolkit/components/extensions/schemas/management.json
+++ b/toolkit/components/extensions/schemas/management.json
@@ -44,7 +44,7 @@
},
{
"id": "ExtensionType",
- "description": "The type of this extension. Will always be 'extension'.",
+ "description": "The type of this extension, 'extension' or 'theme'.",
"type": "string",
"enum": ["extension", "theme"]
},
@@ -99,7 +99,7 @@
"optional": true
},
"type": {
- "description": "The type of this extension. Will always return 'extension'.",
+ "description": "The type of this extension, 'extension' or 'theme'.",
"$ref": "ExtensionType"
},
"homepageUrl": {
@@ -196,6 +196,48 @@
}
]
},
+ {
+ "name": "install",
+ "type": "function",
+ "requireUserInput": true,
+ "permissions": ["management"],
+ "description": "Installs and enables a theme extension from the given url.",
+ "async": "callback",
+ "parameters": [
+ {
+ "name": "options",
+ "type": "object",
+ "properties": {
+ "url": {
+ "$ref": "manifest.HttpURL",
+ "description": "URL pointing to the XPI file on addons.mozilla.org or similar."
+ },
+ "hash": {
+ "type": "string",
+ "optional": true,
+ "pattern": "^(sha256|sha512):[0-9a-fA-F]{64,128}$",
+ "description": "A hash of the XPI file, using sha256 or stronger."
+ }
+ }
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": true,
+ "parameters": [
+ {
+ "name": "result",
+ "type": "object",
+ "properties": {
+ "id": {
+ "$ref": "manifest.ExtensionID"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
{
"name": "getSelf",
"type": "function",
diff --git a/toolkit/components/extensions/test/mochitest/chrome_cleanup_script.js b/toolkit/components/extensions/test/mochitest/chrome_cleanup_script.js
index 5b1af5c85eae..0c0d528784f0 100644
--- a/toolkit/components/extensions/test/mochitest/chrome_cleanup_script.js
+++ b/toolkit/components/extensions/test/mochitest/chrome_cleanup_script.js
@@ -22,9 +22,7 @@ if (AppConstants.MOZ_BUILD_APP === "mobile/android") {
}
function* iterBrowserWindows() {
- let enm = Services.wm.getEnumerator("navigator:browser");
- while (enm.hasMoreElements()) {
- let win = enm.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
if (!win.closed && getBrowserApp(win)) {
yield win;
}
diff --git a/toolkit/components/extensions/test/mochitest/head_cookies.js b/toolkit/components/extensions/test/mochitest/head_cookies.js
index 3c48407f149e..ca857f7a4df1 100644
--- a/toolkit/components/extensions/test/mochitest/head_cookies.js
+++ b/toolkit/components/extensions/test/mochitest/head_cookies.js
@@ -139,9 +139,8 @@ async function testCookies(options) {
function getCookies(host) {
let cookies = [];
- let enum_ = cookieSvc.getCookiesFromHost(host, {});
- while (enum_.hasMoreElements()) {
- cookies.push(enum_.getNext().QueryInterface(Ci.nsICookie2));
+ for (let cookie of cookieSvc.getCookiesFromHost(host, {})) {
+ cookies.push(cookie);
}
return cookies.sort((a, b) => a.name.localeCompare(b.name));
}
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_create_iframe.js b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_create_iframe.js
index 00dfeb4b8987..bd53c5e8896c 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_create_iframe.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_create_iframe.js
@@ -124,7 +124,8 @@ add_task(async function test_contentscript_create_iframe() {
Assert.ok(!manifest, "manifest should be undefined");
- Assert.equal(String(manifestException), "TypeError: win.browser.runtime is undefined",
+ Assert.equal(String(manifestException),
+ `TypeError: win.browser.runtime is undefined, can't access property "getManifest" of it`,
"expected exception received");
let getManifestException = win.testGetManifestException();
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js b/toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js
index dcba6cb46430..cd4d3219fc2f 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js
@@ -153,14 +153,10 @@ add_task(async function test_localStorage_on_session_lifetimePolicy() {
domStorageStoredValue,
} = await ContentTask.spawn(addonBrowser, {uuid, isRemoteBrowser}, (params) => {
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
- let windowEnumerator = Services.ww.getWindowEnumerator();
-
let bgPageWindow;
// Search the background page window in the process where the extension is running.
- while (windowEnumerator.hasMoreElements()) {
- let win = windowEnumerator.getNext();
-
+ for (let win of Services.ww.getWindowEnumerator()) {
// When running in remote-webextension mode the window enumerator
// will only include top level windows related to the extension process
// (the background page and the "about:blank" related to the addonBrowser
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js b/toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js
index 4ca09cc6dd19..a2050b16b7b2 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_permission_xhr.js
@@ -12,9 +12,7 @@ server.registerPathHandler("/return_headers.sjs", (request, response) => {
response.setHeader("Content-Type", "text/plain", false);
let headers = {};
- // Why on earth is this a nsISimpleEnumerator...
- for (let {data: header} of XPCOMUtils.IterSimpleEnumerator(request.headers,
- Ci.nsISupportsString)) {
+ for (let {data: header} of request.headers) {
headers[header.toLowerCase()] = request.getHeader(header);
}
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_suspend.js b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_suspend.js
index ea656c841938..aff203d9dbb1 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_suspend.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_suspend.js
@@ -15,9 +15,7 @@ server.registerPathHandler("/return_headers.sjs", (request, response) => {
response.setHeader("Content-Type", "text/plain", false);
let headers = {};
- // Why on earth is this a nsISimpleEnumerator...
- for (let {data: header} of XPCOMUtils.IterSimpleEnumerator(request.headers,
- Ci.nsISupportsString)) {
+ for (let {data: header} of request.headers) {
headers[header.toLowerCase()] = request.getHeader(header);
}
@@ -184,7 +182,6 @@ add_task(async function test_set_responseHeaders() {
let headerPromise = new Promise(resolve => { resolveHeaderPromise = resolve; });
{
ChromeUtils.import("resource://gre/modules/Services.jsm");
- ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
let ssm = Services.scriptSecurityManager;
diff --git a/toolkit/components/normandy/content/ShieldFrameChild.jsm b/toolkit/components/normandy/content/ShieldFrameChild.jsm
index 0345a63ab7c6..d73f5bf4f042 100644
--- a/toolkit/components/normandy/content/ShieldFrameChild.jsm
+++ b/toolkit/components/normandy/content/ShieldFrameChild.jsm
@@ -68,9 +68,7 @@ class ShieldFrameChild extends ActorChild {
break;
case "GetRemoteValue:ShieldTranslations":
const strings = {};
- const e = gStringBundle.getSimpleEnumeration();
- while (e.hasMoreElements()) {
- var str = e.getNext().QueryInterface(Ci.nsIPropertyElement);
+ for (let str of gStringBundle.getSimpleEnumeration()) {
strings[str.key] = str.value;
}
const brandName = gBrandBundle.GetStringFromName("brandShortName");
diff --git a/toolkit/components/normandy/lib/Heartbeat.jsm b/toolkit/components/normandy/lib/Heartbeat.jsm
index 46bff11113a1..eaa0b685b6b1 100644
--- a/toolkit/components/normandy/lib/Heartbeat.jsm
+++ b/toolkit/components/normandy/lib/Heartbeat.jsm
@@ -30,9 +30,7 @@ let anyWindowsWithInjectedCss = false;
// Add cleanup handler for CSS injected into windows by Heartbeat
CleanupManager.addCleanupHandler(() => {
if (anyWindowsWithInjectedCss) {
- const windowEnumerator = Services.wm.getEnumerator("navigator:browser");
- while (windowEnumerator.hasMoreElements()) {
- const window = windowEnumerator.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (windowsWithInjectedCss.has(window)) {
const utils = window.windowUtils;
utils.removeSheet(HEARTBEAT_CSS_URI, window.AGENT_SHEET);
diff --git a/toolkit/components/nsDefaultCLH.js b/toolkit/components/nsDefaultCLH.js
index 83bf8d212d43..fa00b57391e7 100644
--- a/toolkit/components/nsDefaultCLH.js
+++ b/toolkit/components/nsDefaultCLH.js
@@ -61,10 +61,8 @@ nsDefaultCLH.prototype = {
false))) {
out = "print-xpcom-dirlist(\"" + printDirList + "\"): ";
try {
- var list = getDirectoryService().get(printDirList,
- nsISimpleEnumerator);
- while (list.hasMoreElements())
- out += list.getNext().QueryInterface(nsIFile).path + ";";
+ for (let file of getDirectoryService().get(printDirList, nsISimpleEnumerator))
+ out += file.path + ";";
} catch (e) {
out += "";
}
diff --git a/toolkit/components/passwordmgr/LoginHelper.jsm b/toolkit/components/passwordmgr/LoginHelper.jsm
index 2345f58f156f..5399b0ff9048 100644
--- a/toolkit/components/passwordmgr/LoginHelper.jsm
+++ b/toolkit/components/passwordmgr/LoginHelper.jsm
@@ -336,9 +336,7 @@ var LoginHelper = {
}
}
- let propEnum = aNewLoginData.enumerator;
- while (propEnum.hasMoreElements()) {
- let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
+ for (let prop of aNewLoginData.enumerator) {
switch (prop.name) {
// nsILoginInfo
case "hostname":
diff --git a/toolkit/components/passwordmgr/nsLoginManager.js b/toolkit/components/passwordmgr/nsLoginManager.js
index 5cbfe6fd6a15..84b9c712b749 100644
--- a/toolkit/components/passwordmgr/nsLoginManager.js
+++ b/toolkit/components/passwordmgr/nsLoginManager.js
@@ -402,10 +402,7 @@ LoginManager.prototype = {
log.debug("Getting a list of all disabled origins");
let disabledHosts = [];
- let enumerator = Services.perms.enumerator;
-
- while (enumerator.hasMoreElements()) {
- let perm = enumerator.getNext();
+ for (let perm of Services.perms.enumerator) {
if (perm.type == PERMISSION_SAVE_LOGINS && perm.capability == Services.perms.DENY_ACTION) {
disabledHosts.push(perm.principal.URI.displayPrePath);
}
diff --git a/toolkit/components/passwordmgr/nsLoginManagerPrompter.js b/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
index 9845a3289491..d3b14934f430 100644
--- a/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
+++ b/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
@@ -1435,9 +1435,7 @@ LoginManagerPrompter.prototype = {
return { win: chromeWin, browser };
}
- let windows = Services.wm.getEnumerator(null);
- while (windows.hasMoreElements()) {
- let win = windows.getNext();
+ for (let win of Services.wm.getEnumerator(null)) {
let tabbrowser = win.gBrowser || win.getBrowser();
let browser = tabbrowser.getBrowserForContentWindow(aWindow);
if (browser) {
diff --git a/toolkit/components/passwordmgr/storage-json.js b/toolkit/components/passwordmgr/storage-json.js
index c3faff03e58d..7ef424b341dc 100644
--- a/toolkit/components/passwordmgr/storage-json.js
+++ b/toolkit/components/passwordmgr/storage-json.js
@@ -260,9 +260,7 @@ this.LoginManagerStorage_json.prototype = {
let realMatchData = {};
let options = {};
// Convert nsIPropertyBag to normal JS object
- let propEnum = matchData.enumerator;
- while (propEnum.hasMoreElements()) {
- let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
+ for (let prop of matchData.enumerator) {
switch (prop.name) {
// Some property names aren't field names but are special options to affect the search.
case "schemeUpgrades": {
diff --git a/toolkit/components/passwordmgr/storage-mozStorage.js b/toolkit/components/passwordmgr/storage-mozStorage.js
index 2df031f2d8a8..09411903a15d 100644
--- a/toolkit/components/passwordmgr/storage-mozStorage.js
+++ b/toolkit/components/passwordmgr/storage-mozStorage.js
@@ -402,9 +402,7 @@ LoginManagerStorage_mozStorage.prototype = {
let realMatchData = {};
let options = {};
// Convert nsIPropertyBag to normal JS object
- let propEnum = matchData.enumerator;
- while (propEnum.hasMoreElements()) {
- let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
+ for (let prop of matchData.enumerator) {
switch (prop.name) {
// Some property names aren't field names but are special options to affect the search.
case "schemeUpgrades": {
diff --git a/toolkit/components/passwordmgr/test/browser/browser_username_select_dialog.js b/toolkit/components/passwordmgr/test/browser/browser_username_select_dialog.js
index fb6b8c39685b..86b2287ad31b 100644
--- a/toolkit/components/passwordmgr/test/browser/browser_username_select_dialog.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_username_select_dialog.js
@@ -8,24 +8,15 @@ function getSelectDialogDoc() {
// Trudge through all the open windows, until we find the one
// that has selectDialog.xul loaded.
// var enumerator = Services.wm.getEnumerator("navigator:browser");
- var enumerator = Services.wm.getXULWindowEnumerator(null);
-
- while (enumerator.hasMoreElements()) {
- var win = enumerator.getNext();
- var windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
-
- var containedDocShells = windowDocShell.getDocShellEnumerator(
- Ci.nsIDocShellTreeItem.typeChrome,
- Ci.nsIDocShell.ENUMERATE_FORWARDS);
- while (containedDocShells.hasMoreElements()) {
- // Get the corresponding document for this docshell
- var childDocShell = containedDocShells.getNext();
+ for (let {docShell} of Services.wm.getEnumerator(null)) {
+ var containedDocShells = docShell.getDocShellEnumerator(
+ docShell.typeChrome,
+ docShell.ENUMERATE_FORWARDS);
+ for (let childDocShell of containedDocShells) {
// We don't want it if it's not done loading.
if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
continue;
- var childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
- .contentViewer
- .DOMDocument;
+ var childDoc = childDocShell.contentViewer.DOMDocument;
if (childDoc.location.href == "chrome://global/content/selectDialog.xul")
return childDoc;
diff --git a/toolkit/components/passwordmgr/test/prompt_common.js b/toolkit/components/passwordmgr/test/prompt_common.js
index 739179450ad3..3a607268721f 100644
--- a/toolkit/components/passwordmgr/test/prompt_common.js
+++ b/toolkit/components/passwordmgr/test/prompt_common.js
@@ -49,24 +49,15 @@ function getDialogDoc() {
// Find the which contains notifyWindow, by looking
// through all the open windows and all the in each.
// var enumerator = SpecialPowers.Services.wm.getEnumerator("navigator:browser");
- var enumerator = SpecialPowers.Services.wm.getXULWindowEnumerator(null);
-
- while (enumerator.hasMoreElements()) {
- var win = enumerator.getNext();
- var windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
-
- var containedDocShells = windowDocShell.getDocShellEnumerator(
- Ci.nsIDocShellTreeItem.typeChrome,
- Ci.nsIDocShell.ENUMERATE_FORWARDS);
- while (containedDocShells.hasMoreElements()) {
- // Get the corresponding document for this docshell
- var childDocShell = containedDocShells.getNext();
+ for (let {docShell} of SpecialPowers.Services.wm.getXULWindowEnumerator(null)) {
+ var containedDocShells = docShell.getDocShellEnumerator(
+ docShell.typeChrome,
+ docShell.ENUMERATE_FORWARDS);
+ for (let childDocShell of containedDocShells) {
// We don't want it if it's not done loading.
if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
continue;
- var childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
- .contentViewer
- .DOMDocument;
+ var childDoc = childDocShell.contentViewer.DOMDocument;
// ok(true, "Got window: " + childDoc.location.href);
if (childDoc.location.href == "chrome://global/content/commonDialog.xul")
diff --git a/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js b/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js
index d4a511c1ada6..c901e59b735e 100644
--- a/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js
+++ b/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js
@@ -68,10 +68,7 @@ function checkStorageData(storage, ref_disabledHosts, ref_logins)
function getAllDisabledHostsFromPermissionManager() {
let disabledHosts = [];
- let enumerator = Services.perms.enumerator;
-
- while (enumerator.hasMoreElements()) {
- let perm = enumerator.getNext();
+ for (let perm of Services.perms.enumerator) {
if (perm.type == PERMISSION_SAVE_LOGINS && perm.capability == Services.perms.DENY_ACTION) {
disabledHosts.push(perm.principal.URI.prePath);
}
diff --git a/toolkit/components/perfmonitoring/PerformanceStats.jsm b/toolkit/components/perfmonitoring/PerformanceStats.jsm
index 8e75501d48d4..8c06aee502f1 100644
--- a/toolkit/components/perfmonitoring/PerformanceStats.jsm
+++ b/toolkit/components/perfmonitoring/PerformanceStats.jsm
@@ -808,17 +808,15 @@ function ProcessSnapshot({xpcom, probes}) {
this.componentsData = [];
let subgroups = new Map();
- let enumeration = xpcom.getComponentsData().enumerate();
- while (enumeration.hasMoreElements()) {
- let xpcom = enumeration.getNext().QueryInterface(Ci.nsIPerformanceStats);
- let stat = (new PerformanceDataLeaf({xpcom, probes}));
+ for (let data of xpcom.getComponentsData().enumerate(Ci.nsIPerformanceStats)) {
+ let stat = (new PerformanceDataLeaf({xpcom: data, probes}));
- if (!xpcom.parentId) {
+ if (!data.parentId) {
this.componentsData.push(stat);
} else {
- let siblings = subgroups.get(xpcom.parentId);
+ let siblings = subgroups.get(data.parentId);
if (!siblings) {
- subgroups.set(xpcom.parentId, (siblings = []));
+ subgroups.set(data.parentId, (siblings = []));
}
siblings.push(stat);
}
diff --git a/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js b/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
index 35860706b0b6..d95e1676c2e0 100644
--- a/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
+++ b/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
@@ -245,9 +245,7 @@ add_task(async function test() {
// Attach titles to components.
let titles = [];
let map = new Map();
- let windows = Services.wm.getEnumerator("navigator:browser");
- while (windows.hasMoreElements()) {
- let window = windows.getNext();
+ for (let window of Services.wm.getEnumerator("navigator:browser")) {
let tabbrowser = window.gBrowser;
for (let browser of tabbrowser.browsers) {
let id = browser.outerWindowID; // May be `null` if the browser isn't loaded yet
diff --git a/toolkit/components/prompts/content/commonDialog.js b/toolkit/components/prompts/content/commonDialog.js
index dff55ddfec82..0ee0d9779292 100644
--- a/toolkit/components/prompts/content/commonDialog.js
+++ b/toolkit/components/prompts/content/commonDialog.js
@@ -12,9 +12,7 @@ function commonDialogOnLoad() {
.QueryInterface(Ci.nsIWritablePropertyBag);
// Convert to a JS object
args = {};
- let propEnum = propBag.enumerator;
- while (propEnum.hasMoreElements()) {
- let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
+ for (let prop of propBag.enumerator) {
args[prop.name] = prop.value;
}
diff --git a/toolkit/components/prompts/test/chromeScript.js b/toolkit/components/prompts/test/chromeScript.js
index 0915190e7441..f9bda7ae5629 100644
--- a/toolkit/components/prompts/test/chromeScript.js
+++ b/toolkit/components/prompts/test/chromeScript.js
@@ -200,24 +200,16 @@ function getDialogDoc() {
// Trudge through all the open windows, until we find the one
// that has either commonDialog.xul or selectDialog.xul loaded.
// var enumerator = Services.wm.getEnumerator("navigator:browser");
- var enumerator = Services.wm.getXULWindowEnumerator(null);
-
- while (enumerator.hasMoreElements()) {
- var win = enumerator.getNext();
- var windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
-
- var containedDocShells = windowDocShell.getDocShellEnumerator(
- Ci.nsIDocShellTreeItem.typeChrome,
- Ci.nsIDocShell.ENUMERATE_FORWARDS);
- while (containedDocShells.hasMoreElements()) {
+ for (let {docShell} of Services.wm.getEnumerator(null)) {
+ var containedDocShells = docShell.getDocShellEnumerator(
+ docShell.typeChrome,
+ docShell.ENUMERATE_FORWARDS);
+ for (let childDocShell of containedDocShells) {
// Get the corresponding document for this docshell
- var childDocShell = containedDocShells.getNext();
// We don't want it if it's not done loading.
if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
continue;
- var childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
- .contentViewer
- .DOMDocument;
+ var childDoc = childDocShell.contentViewer.DOMDocument;
if (childDoc.location.href != "chrome://global/content/commonDialog.xul" &&
childDoc.location.href != "chrome://global/content/selectDialog.xul")
diff --git a/toolkit/components/protobuf/m-c-changes.patch b/toolkit/components/protobuf/m-c-changes.patch
index 5b28653c635a..ed7c64cb14f2 100644
--- a/toolkit/components/protobuf/m-c-changes.patch
+++ b/toolkit/components/protobuf/m-c-changes.patch
@@ -43,3 +43,25 @@ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/atomicops.h b
// return result;
//
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
+diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h b/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
+--- a/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
++++ b/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
+@@ -45,17 +45,17 @@
+ #define GOOGLE_PROTOBUF_ARCH_IA32 1
+ #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+ #elif defined(__QNX__)
+ #define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1
+ #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+ #elif defined(_M_ARM) || defined(__ARMEL__)
+ #define GOOGLE_PROTOBUF_ARCH_ARM 1
+ #define GOOGLE_PROTOBUF_ARCH_32_BIT 1
+-#elif defined(__aarch64__)
++#elif defined(__aarch64__) || defined(_M_ARM64)
+ #define GOOGLE_PROTOBUF_ARCH_AARCH64 1
+ #define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+ #elif defined(__MIPSEL__)
+ #if defined(__LP64__)
+ #define GOOGLE_PROTOBUF_ARCH_MIPS64 1
+ #define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+ #else
+ #define GOOGLE_PROTOBUF_ARCH_MIPS 1
diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h b/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
index 7a54060dfa31..3ab43a42ef06 100644
--- a/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
+++ b/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h
@@ -50,7 +50,7 @@
#elif defined(_M_ARM) || defined(__ARMEL__)
#define GOOGLE_PROTOBUF_ARCH_ARM 1
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || defined(_M_ARM64)
#define GOOGLE_PROTOBUF_ARCH_AARCH64 1
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
#elif defined(__MIPSEL__)
diff --git a/toolkit/components/search/nsSearchService.js b/toolkit/components/search/nsSearchService.js
index 9d008ded66d1..56a8e6d5ccd8 100644
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -2807,11 +2807,10 @@ SearchService.prototype = {
} catch (e) {
// NS_APP_DISTRIBUTION_SEARCH_DIR_LIST is defined by each app
// so this throws during unit tests (but not xpcshell tests).
- locations = {hasMoreElements: () => false};
+ locations = [];
}
- while (locations.hasMoreElements()) {
- let dir = locations.getNext().QueryInterface(Ci.nsIFile);
+ for (let dir of locations) {
if (dir.directoryEntries.nextFile)
distDirs.push(dir);
}
@@ -2873,10 +2872,9 @@ SearchService.prototype = {
} catch (e) {
// NS_APP_DISTRIBUTION_SEARCH_DIR_LIST is defined by each app
// so this throws during unit tests (but not xpcshell tests).
- locations = {hasMoreElements: () => false};
+ locations = [];
}
- while (locations.hasMoreElements()) {
- let dir = locations.getNext().QueryInterface(Ci.nsIFile);
+ for (let dir of locations) {
let iterator = new OS.File.DirectoryIterator(dir.path,
{ winPattern: "*.xml" });
try {
diff --git a/toolkit/components/securityreporter/SecurityReporter.js b/toolkit/components/securityreporter/SecurityReporter.js
index 70189d60e129..c3bf9b8d5c22 100644
--- a/toolkit/components/securityreporter/SecurityReporter.js
+++ b/toolkit/components/securityreporter/SecurityReporter.js
@@ -62,10 +62,7 @@ SecurityReporter.prototype = {
let asciiCertChain = [];
if (transportSecurityInfo.failedCertChain) {
- let certs = transportSecurityInfo.failedCertChain.getEnumerator();
- while (certs.hasMoreElements()) {
- let cert = certs.getNext();
- cert.QueryInterface(Ci.nsIX509Cert);
+ for (let cert of transportSecurityInfo.failedCertChain.getEnumerator()) {
asciiCertChain.push(btoa(getDERString(cert)));
}
}
diff --git a/toolkit/components/telemetry/TelemetrySession.jsm b/toolkit/components/telemetry/TelemetrySession.jsm
index 0f55d1387077..46b28099c15d 100644
--- a/toolkit/components/telemetry/TelemetrySession.jsm
+++ b/toolkit/components/telemetry/TelemetrySession.jsm
@@ -1400,9 +1400,7 @@ var Impl = {
getOpenTabsCount: function getOpenTabsCount() {
let tabCount = 0;
- let browserEnum = Services.wm.getEnumerator("navigator:browser");
- while (browserEnum.hasMoreElements()) {
- let win = browserEnum.getNext();
+ for (let win of Services.wm.getEnumerator("navigator:browser")) {
tabCount += win.gBrowser.tabs.length;
}
diff --git a/toolkit/components/timermanager/nsUpdateTimerManager.js b/toolkit/components/timermanager/nsUpdateTimerManager.js
index dbdff37dbad5..522c1136dea1 100644
--- a/toolkit/components/timermanager/nsUpdateTimerManager.js
+++ b/toolkit/components/timermanager/nsUpdateTimerManager.js
@@ -153,9 +153,7 @@ TimerManager.prototype = {
var catMan = Cc["@mozilla.org/categorymanager;1"].
getService(Ci.nsICategoryManager);
- var entries = catMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
- while (entries.hasMoreElements()) {
- let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
+ for (let {data: entry} of catMan.enumerateCategory(CATEGORY_UPDATE_TIMER)) {
let value = catMan.getCategoryEntry(CATEGORY_UPDATE_TIMER, entry);
let [cid, method, timerID, prefInterval, defaultInterval, maxInterval] = value.split(",");
diff --git a/toolkit/components/timermanager/tests/unit/consumerNotifications.js b/toolkit/components/timermanager/tests/unit/consumerNotifications.js
index 451aad595a1b..f1116097f9ec 100644
--- a/toolkit/components/timermanager/tests/unit/consumerNotifications.js
+++ b/toolkit/components/timermanager/tests/unit/consumerNotifications.js
@@ -332,9 +332,7 @@ function run_test() {
gPref.setBoolPref(PREF_APP_UPDATE_LOG_ALL, true);
// Remove existing update timers to prevent them from being notified
- let entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
- while (entries.hasMoreElements()) {
- let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
+ for (let {data: entry} of gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER)) {
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false);
}
@@ -474,13 +472,11 @@ function check_test0thru7() {
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc, true);
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc, true);
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc, true);
- let entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
- while (entries.hasMoreElements()) {
- let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
+ for (let {data: entry} of gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER)) {
gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false);
}
- entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
+ let entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER);
Assert.ok(!entries.hasMoreElements(),
"no " + CATEGORY_UPDATE_TIMER + " categories should still be " +
"registered");
diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
index b866c0bace0a..f29d8b444fe9 100644
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
@@ -58,6 +58,7 @@
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsSandboxFlags.h"
+#include "nsSimpleEnumerator.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Element.h"
@@ -146,7 +147,7 @@ nsWatcherWindowEntry::ReferenceSelf()
****************** nsWatcherWindowEnumerator *******************
****************************************************************/
-class nsWatcherWindowEnumerator : public nsISimpleEnumerator
+class nsWatcherWindowEnumerator : public nsSimpleEnumerator
{
public:
@@ -154,10 +155,8 @@ public:
NS_IMETHOD HasMoreElements(bool* aResult) override;
NS_IMETHOD GetNext(nsISupports** aResult) override;
- NS_DECL_ISUPPORTS
-
protected:
- virtual ~nsWatcherWindowEnumerator();
+ ~nsWatcherWindowEnumerator() override;
private:
friend class nsWindowWatcher;
@@ -169,10 +168,6 @@ private:
nsWatcherWindowEntry* mCurrentPosition;
};
-NS_IMPL_ADDREF(nsWatcherWindowEnumerator)
-NS_IMPL_RELEASE(nsWatcherWindowEnumerator)
-NS_IMPL_QUERY_INTERFACE(nsWatcherWindowEnumerator, nsISimpleEnumerator)
-
nsWatcherWindowEnumerator::nsWatcherWindowEnumerator(nsWindowWatcher* aWatcher)
: mWindowWatcher(aWatcher)
, mCurrentPosition(aWatcher->mOldestWindow)
@@ -210,8 +205,9 @@ nsWatcherWindowEnumerator::GetNext(nsISupports** aResult)
if (mCurrentPosition) {
CallQueryInterface(mCurrentPosition->mWindow, aResult);
mCurrentPosition = FindNext();
+ return NS_OK;
}
- return NS_OK;
+ return NS_ERROR_FAILURE;
}
nsWatcherWindowEntry*
diff --git a/toolkit/content/aboutProfiles.js b/toolkit/content/aboutProfiles.js
index 7434445b5939..9a133f0813ef 100644
--- a/toolkit/content/aboutProfiles.js
+++ b/toolkit/content/aboutProfiles.js
@@ -29,9 +29,7 @@ function findCurrentProfile() {
} catch (e) {}
if (cpd) {
- let itr = ProfileService.profiles;
- while (itr.hasMoreElements()) {
- let profile = itr.getNext().QueryInterface(Ci.nsIToolkitProfile);
+ for (let profile of ProfileService.profiles) {
if (profile.rootDir.path == cpd.path) {
return profile;
}
@@ -60,9 +58,7 @@ function refreshUI() {
let currentProfile = findCurrentProfile();
- let iter = ProfileService.profiles;
- while (iter.hasMoreElements()) {
- let profile = iter.getNext().QueryInterface(Ci.nsIToolkitProfile);
+ for (let profile of ProfileService.profiles) {
let isCurrentProfile = profile == currentProfile;
let isInUse = isCurrentProfile;
if (!isInUse) {
@@ -290,9 +286,7 @@ function removeProfile(profile) {
} catch (e) {}
if (isSelected || isDefault) {
- let itr = ProfileService.profiles;
- while (itr.hasMoreElements()) {
- let p = itr.getNext().QueryInterface(Ci.nsIToolkitProfile);
+ for (let p of ProfileService.profiles) {
if (profile == p) {
continue;
}
diff --git a/toolkit/content/globalOverlay.js b/toolkit/content/globalOverlay.js
index cc3d51b4c38e..a5d118533bc7 100644
--- a/toolkit/content/globalOverlay.js
+++ b/toolkit/content/globalOverlay.js
@@ -8,10 +8,7 @@ function closeWindow(aClose, aPromptFunction) {
// Closing the last window doesn't quit the application on OS X.
if (AppConstants.platform != "macosx") {
var windowCount = 0;
- var e = Services.wm.getEnumerator(null);
-
- while (e.hasMoreElements()) {
- var w = e.getNext();
+ for (let w of Services.wm.getEnumerator(null)) {
if (w.closed) {
continue;
}
diff --git a/toolkit/content/macWindowMenu.js b/toolkit/content/macWindowMenu.js
index a85dbbcb331d..216e9dc9ba8e 100644
--- a/toolkit/content/macWindowMenu.js
+++ b/toolkit/content/macWindowMenu.js
@@ -5,10 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function macWindowMenuDidShow() {
- let windows = Services.wm.getEnumerator("");
let frag = document.createDocumentFragment();
- while (windows.hasMoreElements()) {
- let win = windows.getNext();
+ for (let win of Services.wm.getEnumerator("")) {
if (win.document.documentElement.getAttribute("inwindowmenu") == "false") {
continue;
}
diff --git a/toolkit/modules/CertUtils.jsm b/toolkit/modules/CertUtils.jsm
index 252b319b43fc..b168fa2fa176 100644
--- a/toolkit/modules/CertUtils.jsm
+++ b/toolkit/modules/CertUtils.jsm
@@ -7,7 +7,6 @@ var EXPORTED_SYMBOLS = ["CertUtils"];
const Ce = Components.Exception;
ChromeUtils.import("resource://gre/modules/Services.jsm");
-const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", {});
/**
* Reads a set of expected certificate attributes from preferences. The returned
@@ -153,10 +152,8 @@ function checkCert(aChannel, aAllowNonBuiltInCerts, aCerts) {
return;
}
- let certEnumerator = sslStatus.succeededCertChain.getEnumerator();
let issuerCert = null;
- for (issuerCert of XPCOMUtils.IterSimpleEnumerator(certEnumerator,
- Ci.nsIX509Cert));
+ for (issuerCert of sslStatus.succeededCertChain.getEnumerator());
const certNotBuiltInErr = "Certificate issuer is not built-in.";
if (!issuerCert) {
diff --git a/toolkit/modules/ResetProfile.jsm b/toolkit/modules/ResetProfile.jsm
index 1282dbce13d4..f635bb6e0301 100644
--- a/toolkit/modules/ResetProfile.jsm
+++ b/toolkit/modules/ResetProfile.jsm
@@ -32,9 +32,7 @@ var ResetProfile = {
let profileService = Cc["@mozilla.org/toolkit/profile-service;1"].
getService(Ci.nsIToolkitProfileService);
let currentProfileDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
- let profileEnumerator = profileService.profiles;
- while (profileEnumerator.hasMoreElements()) {
- let profile = profileEnumerator.getNext().QueryInterface(Ci.nsIToolkitProfile);
+ for (let profile of profileService.profiles) {
if (profile.rootDir && profile.rootDir.equals(currentProfileDir)) {
return true;
}
diff --git a/toolkit/modules/Troubleshoot.jsm b/toolkit/modules/Troubleshoot.jsm
index 49bc0dc9376b..815fab76585c 100644
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -186,12 +186,10 @@ var dataProviders = {
data.numTotalWindows = 0;
data.numRemoteWindows = 0;
- let winEnumer = Services.wm.getEnumerator("navigator:browser");
- while (winEnumer.hasMoreElements()) {
+ for (let {docShell} of Services.wm.getEnumerator("navigator:browser")) {
data.numTotalWindows++;
- let remote = winEnumer.getNext().docShell.
- QueryInterface(Ci.nsILoadContext).
- useRemoteTabs;
+ let remote = docShell.QueryInterface(Ci.nsILoadContext)
+ .useRemoteTabs;
if (remote) {
data.numRemoteWindows++;
}
@@ -357,9 +355,8 @@ var dataProviders = {
data.numTotalWindows = 0;
data.numAcceleratedWindows = 0;
- let winEnumer = Services.ww.getWindowEnumerator();
- while (winEnumer.hasMoreElements()) {
- let winUtils = winEnumer.getNext().windowUtils;
+ for (let win of Services.ww.getWindowEnumerator()) {
+ let winUtils = win.windowUtils;
try {
// NOTE: windowless browser's windows should not be reported in the graphics troubleshoot report
if (winUtils.layerManagerType == "None" || !winUtils.layerManagerRemote) {
diff --git a/toolkit/modules/addons/SecurityInfo.jsm b/toolkit/modules/addons/SecurityInfo.jsm
index 44cbe1c33492..e7f8f587981e 100644
--- a/toolkit/modules/addons/SecurityInfo.jsm
+++ b/toolkit/modules/addons/SecurityInfo.jsm
@@ -183,7 +183,7 @@ const SecurityInfo = {
getCertificateChain(certChain, options = {}) {
let certificates = [];
- for (let cert of XPCOMUtils.IterSimpleEnumerator(certChain.getEnumerator(), Ci.nsIX509Cert)) {
+ for (let cert of certChain.getEnumerator()) {
certificates.push(this.parseCertificateInfo(cert, options));
}
return certificates;
diff --git a/toolkit/modules/addons/WebNavigationFrames.jsm b/toolkit/modules/addons/WebNavigationFrames.jsm
index 5fa400a8ddf8..5fc57147539e 100644
--- a/toolkit/modules/addons/WebNavigationFrames.jsm
+++ b/toolkit/modules/addons/WebNavigationFrames.jsm
@@ -24,14 +24,11 @@ const EXPORTED_SYMBOLS = ["WebNavigationFrames"];
* A generator function which iterates over a docShell tree, given a root docShell.
*
* @param {nsIDocShell} docShell - the root docShell object
+ * @returns {Iterator}
*/
-function* iterateDocShellTree(docShell) {
- let docShellsEnum = docShell.getDocShellEnumerator(
+function iterateDocShellTree(docShell) {
+ return docShell.getDocShellEnumerator(
docShell.typeContent, docShell.ENUMERATE_FORWARDS);
-
- while (docShellsEnum.hasMoreElements()) {
- yield docShellsEnum.getNext().QueryInterface(Ci.nsIDocShell);
- }
}
/**
diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js
index 38164856d09c..aad167300bdb 100644
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -217,9 +217,7 @@ nsUnknownContentTypeDialog.prototype = {
// because the original one is definitely gone (and nsIFilePicker doesn't like
// a null parent):
gDownloadLastDir = this._mDownloadDir;
- let windowsEnum = Services.wm.getEnumerator("");
- while (windowsEnum.hasMoreElements()) {
- let someWin = windowsEnum.getNext();
+ for (let someWin of Services.wm.getEnumerator("")) {
// We need to make sure we don't end up with this dialog, because otherwise
// that's going to go away when the user clicks "Save", and that breaks the
// windows file picker that's supposed to show up if we let the user choose
diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm
index 29767fe4a169..a828499e2d10 100644
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -785,9 +785,7 @@ var AddonManagerInternal = {
// Load any providers registered in the category manager
let catman = Cc["@mozilla.org/categorymanager;1"].
getService(Ci.nsICategoryManager);
- let entries = catman.enumerateCategory(CATEGORY_PROVIDER_MODULE);
- while (entries.hasMoreElements()) {
- let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
+ for (let {data: entry} of catman.enumerateCategory(CATEGORY_PROVIDER_MODULE)) {
let url = catman.getCategoryEntry(CATEGORY_PROVIDER_MODULE, entry);
try {
diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js
index d25c07781e5e..5e0558eb0580 100644
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -1242,9 +1242,7 @@ var gViewController = {
return;
let browser = getBrowserElement();
- let files = fp.files;
- while (files.hasMoreElements()) {
- let file = files.getNext();
+ for (let file of fp.files) {
let install = await AddonManager.getInstallForFile(file);
AddonManager.installAddonFromAOM(browser, document.documentURIObject, install);
}
diff --git a/toolkit/mozapps/extensions/test/browser/browser_webext_options.js b/toolkit/mozapps/extensions/test/browser/browser_webext_options.js
index ab14beca20c8..ee031e1aa56a 100644
--- a/toolkit/mozapps/extensions/test/browser/browser_webext_options.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_webext_options.js
@@ -31,13 +31,17 @@ async function runTest(installer) {
"Current view should scroll to preferences");
var browser = mgrWindow.document.querySelector("#detail-grid > rows > stack > .inline-options-browser");
- var rows = browser.parentNode;
-
- let url = await ContentTask.spawn(browser, {}, () => content.location.href);
-
ok(browser, "Grid should have a browser descendant");
is(browser.localName, "browser", "Grid should have a browser descendant");
- is(url, element.mAddon.optionsURL, "Browser has the expected options URL loaded");
+
+ var rows = browser.parentNode;
+
+ await ContentTask.spawn(browser, element.mAddon.optionsURL,
+ async url => {
+ await ContentTaskUtils.waitForCondition(() =>
+ content.location.href == url,
+ "Browser has the expected options URL loaded");
+ });
is(browser.clientWidth, browser.parentNode.clientWidth,
"Browser should be the same width as its direct parent");
diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js
index 0aa18be62e61..fff237fda479 100644
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -95,10 +95,8 @@ function promiseFocus(window) {
// Helper to register test failures and close windows if any are left open
function checkOpenWindows(aWindowID) {
- let windows = Services.wm.getEnumerator(aWindowID);
let found = false;
- while (windows.hasMoreElements()) {
- let win = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
+ for (let win of Services.wm.getEnumerator(aWindowID)) {
if (!win.closed) {
found = true;
win.close();
diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js b/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js
index 4de796590f97..897715eeea39 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js
@@ -37,9 +37,7 @@ async function run_test() {
// Finds the test plugin library
function get_test_plugin() {
- var pluginEnum = Services.dirsvc.get("APluginsDL", Ci.nsISimpleEnumerator);
- while (pluginEnum.hasMoreElements()) {
- let dir = pluginEnum.getNext().QueryInterface(Ci.nsIFile);
+ for (let dir of Services.dirsvc.get("APluginsDL", Ci.nsISimpleEnumerator)) {
let plugin = dir.clone();
// OSX plugin
plugin.append("npswftest.plugin");
diff --git a/toolkit/mozapps/handling/content/dialog.js b/toolkit/mozapps/handling/content/dialog.js
index cc41a1d3f39f..02fc68f835ae 100644
--- a/toolkit/mozapps/handling/content/dialog.js
+++ b/toolkit/mozapps/handling/content/dialog.js
@@ -154,9 +154,7 @@ var dialog = {
let gIOSvc = Cc["@mozilla.org/gio-service;1"]
.getService(Ci.nsIGIOService);
var gioApps = gIOSvc.getAppsForURIScheme(this._URI.scheme);
- let enumerator = gioApps.enumerate();
- while (enumerator.hasMoreElements()) {
- let handler = enumerator.getNext().QueryInterface(Ci.nsIHandlerApp);
+ for (let handler of gioApps.enumerate()) {
// OS handler share the same name, it's most likely the same app, skipping...
if (handler.name == this._handlerInfo.defaultDescription) {
continue;
diff --git a/toolkit/profile/content/createProfileWizard.js b/toolkit/profile/content/createProfileWizard.js
index 92292c930b25..67e9aeea7767 100644
--- a/toolkit/profile/content/createProfileWizard.js
+++ b/toolkit/profile/content/createProfileWizard.js
@@ -156,9 +156,7 @@ function checkProfileName(profileNameToCheck) {
}
function profileExists(aName) {
- var profiles = gProfileService.profiles;
- while (profiles.hasMoreElements()) {
- var profile = profiles.getNext().QueryInterface(I.nsIToolkitProfile);
+ for (let profile of gProfileService.profiles) {
if (profile.name.toLowerCase() == aName.toLowerCase())
return true;
}
diff --git a/toolkit/profile/content/profileSelection.js b/toolkit/profile/content/profileSelection.js
index 507aeb9c5b26..7a35ec2bb19d 100644
--- a/toolkit/profile/content/profileSelection.js
+++ b/toolkit/profile/content/profileSelection.js
@@ -31,10 +31,7 @@ function startup() {
var profilesElement = document.getElementById("profiles");
- var profileList = gProfileService.profiles;
- while (profileList.hasMoreElements()) {
- var profile = profileList.getNext().QueryInterface(I.nsIToolkitProfile);
-
+ for (let profile of gProfileService.profiles.entries(I.nsIToolkitProfile)) {
var listitem = profilesElement.appendItem(profile.name, "");
var tooltiptext =
diff --git a/toolkit/profile/nsToolkitProfileService.cpp b/toolkit/profile/nsToolkitProfileService.cpp
index d34f73058be5..16de4dbea5d9 100644
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -24,7 +24,7 @@
#include "nsIToolkitProfile.h"
#include "nsIFactory.h"
#include "nsIFile.h"
-#include "nsISimpleEnumerator.h"
+#include "nsSimpleEnumerator.h"
#ifdef XP_MACOSX
#include
@@ -144,16 +144,19 @@ private:
static nsToolkitProfileService *gService;
- class ProfileEnumerator final : public nsISimpleEnumerator
+ class ProfileEnumerator final : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
+ const nsID& DefaultInterface() override
+ {
+ return NS_GET_IID(nsIToolkitProfile);
+ }
+
explicit ProfileEnumerator(nsToolkitProfile *first)
{ mCurrent = first; }
private:
- ~ProfileEnumerator() { }
RefPtr mCurrent;
};
};
@@ -595,9 +598,6 @@ nsToolkitProfileService::GetProfiles(nsISimpleEnumerator* *aResult)
return NS_OK;
}
-NS_IMPL_ISUPPORTS(nsToolkitProfileService::ProfileEnumerator,
- nsISimpleEnumerator)
-
NS_IMETHODIMP
nsToolkitProfileService::ProfileEnumerator::HasMoreElements(bool* aResult)
{
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index ee57e55bf4da..70370e68669d 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -854,7 +854,7 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty,
LoadDirsIntoArray(mAppBundleDirectories,
kAppendNothing, directories);
- rv = NS_NewArrayEnumerator(aResult, directories);
+ rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
}
else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
nsCOMArray directories;
@@ -863,7 +863,7 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty,
LoadDirsIntoArray(mAppBundleDirectories,
kAppendPrefDir, directories);
- rv = NS_NewArrayEnumerator(aResult, directories);
+ rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
}
else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
// NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
@@ -878,7 +878,7 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty,
kAppendChromeDir,
directories);
- rv = NS_NewArrayEnumerator(aResult, directories);
+ rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
}
else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
nsCOMArray directories;
@@ -908,7 +908,7 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty,
directories);
}
- rv = NS_NewArrayEnumerator(aResult, directories);
+ rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_SUCCESS_AGGREGATE_RESULT;
diff --git a/tools/profiler/core/PlatformMacros.h b/tools/profiler/core/PlatformMacros.h
index 1028f6f0bb49..ace0e3827110 100644
--- a/tools/profiler/core/PlatformMacros.h
+++ b/tools/profiler/core/PlatformMacros.h
@@ -23,6 +23,7 @@
#undef GP_PLAT_amd64_darwin
#undef GP_PLAT_x86_windows
#undef GP_PLAT_amd64_windows
+#undef GP_PLAT_arm64_windows
#undef GP_ARCH_x86
#undef GP_ARCH_amd64
@@ -95,6 +96,11 @@
# define GP_ARCH_amd64 1
# define GP_OS_windows 1
+#elif defined(_MSC_VER) && defined(_M_ARM64)
+# define GP_PLAT_arm64_windows 1
+# define GP_ARCH_arm64 1
+# define GP_OS_windows 1
+
#else
# error "Unsupported platform"
#endif
diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp
index 4eb9d8425c91..d249c9df3e66 100644
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -102,6 +102,12 @@
# define USE_MOZ_STACK_WALK
#endif
+// AArch64 Win64 builds use frame pointers.
+#if defined(GP_PLAT_arm64_windows)
+# define HAVE_NATIVE_UNWIND
+# define USE_FRAME_POINTER_STACK_WALK
+#endif
+
// Mac builds only have frame pointers when MOZ_PROFILING is specified, so
// FramePointerStackWalk() only works in that case. We don't use MozStackWalk()
// on Mac.
diff --git a/uriloader/exthandler/HandlerService.js b/uriloader/exthandler/HandlerService.js
index ec9a053672f3..83ab7b885de3 100644
--- a/uriloader/exthandler/HandlerService.js
+++ b/uriloader/exthandler/HandlerService.js
@@ -217,7 +217,7 @@ HandlerService.prototype = {
);
handlers.appendElement(handler);
}
- return handlers.enumerate();
+ return handlers.enumerate(Ci.nsIHandlerInfo);
},
// nsIHandlerService
@@ -252,9 +252,7 @@ HandlerService.prototype = {
if (handlerInfo.preferredApplicationHandler) {
handlers.push(handlerInfo.preferredApplicationHandler);
}
- let enumerator = handlerInfo.possibleApplicationHandlers.enumerate();
- while (enumerator.hasMoreElements()) {
- let handler = enumerator.getNext().QueryInterface(Ci.nsIHandlerApp);
+ for (let handler of handlerInfo.possibleApplicationHandlers.enumerate(Ci.nsIHandlerApp)) {
// If the caller stored duplicate handlers, we save them only once.
if (!handlers.some(h => h.equals(handler))) {
handlers.push(handler);
diff --git a/uriloader/exthandler/tests/HandlerServiceTestUtils.jsm b/uriloader/exthandler/tests/HandlerServiceTestUtils.jsm
index c94758a0498b..f43c2b7a86e8 100644
--- a/uriloader/exthandler/tests/HandlerServiceTestUtils.jsm
+++ b/uriloader/exthandler/tests/HandlerServiceTestUtils.jsm
@@ -35,14 +35,9 @@ var HandlerServiceTestUtils = {
* alphabetically regardless of category.
*/
getAllHandlerInfoTypes() {
- let handlerInfoTypes = [];
- let handlerInfoEnumerator = gHandlerService.enumerate();
- while (handlerInfoEnumerator.hasMoreElements()) {
- let handlerInfo = handlerInfoEnumerator.getNext()
- .QueryInterface(Ci.nsIHandlerInfo);
- handlerInfoTypes.push(handlerInfo.type);
- }
- return handlerInfoTypes.sort();
+ return Array.from(gHandlerService.enumerate(),
+ info => info.type)
+ .sort();
},
/**
diff --git a/uriloader/exthandler/tests/mochitest/browser_remember_download_option.js b/uriloader/exthandler/tests/mochitest/browser_remember_download_option.js
index d81fc37bad4e..fe7f11d5705d 100644
--- a/uriloader/exthandler/tests/mochitest/browser_remember_download_option.js
+++ b/uriloader/exthandler/tests/mochitest/browser_remember_download_option.js
@@ -29,9 +29,7 @@ add_task(async function() {
// check the extension.
var mimeType = gHandlerSvc.getTypeFromExtension("abc");
is(mimeType, launcher.MIMEInfo.type, "Got correct mime type.");
- var handlerInfos = gHandlerSvc.enumerate();
- while (handlerInfos.hasMoreElements()) {
- let handlerInfo = handlerInfos.getNext().QueryInterface(Ci.nsIHandlerInfo);
+ for (let handlerInfo of gHandlerSvc.enumerate()) {
if (handlerInfo.type == launcher.MIMEInfo.type) {
// check the alwaysAskBeforeHandling
ok(!handlerInfo.alwaysAskBeforeHandling,
diff --git a/uriloader/exthandler/tests/unit/test_handlerService.js b/uriloader/exthandler/tests/unit/test_handlerService.js
index b24ead758fe9..4ec927f280c1 100644
--- a/uriloader/exthandler/tests/unit/test_handlerService.js
+++ b/uriloader/exthandler/tests/unit/test_handlerService.js
@@ -240,9 +240,7 @@ function run_test() {
handlerTypes.push("irc");
handlerTypes.push("ircs");
}
- var handlers = handlerSvc.enumerate();
- while (handlers.hasMoreElements()) {
- var handler = handlers.getNext().QueryInterface(Ci.nsIHandlerInfo);
+ for (let handler of handlerSvc.enumerate()) {
Assert.notEqual(handlerTypes.indexOf(handler.type), -1);
handlerTypes.splice(handlerTypes.indexOf(handler.type), 1);
}
diff --git a/uriloader/exthandler/win/nsMIMEInfoWin.cpp b/uriloader/exthandler/win/nsMIMEInfoWin.cpp
index 261d3a8d4696..bf65463b7570 100644
--- a/uriloader/exthandler/win/nsMIMEInfoWin.cpp
+++ b/uriloader/exthandler/win/nsMIMEInfoWin.cpp
@@ -167,7 +167,7 @@ nsMIMEInfoWin::GetEnumerator(nsISimpleEnumerator* *_retval)
if (variant)
properties.AppendObject(variant);
- return NS_NewArrayEnumerator(_retval, properties);
+ return NS_NewArrayEnumerator(_retval, properties, NS_GET_IID(nsIVariant));
}
static nsresult GetIconURLVariant(nsIFile* aApplication, nsIVariant* *_retval)
diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp
index b990a6b751b8..5caa99b71bf6 100644
--- a/widget/gtk/nsFilePicker.cpp
+++ b/widget/gtk/nsFilePicker.cpp
@@ -346,7 +346,7 @@ nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
NS_ENSURE_ARG_POINTER(aFiles);
if (mMode == nsIFilePicker::modeOpenMultiple) {
- return NS_NewArrayEnumerator(aFiles, mFiles);
+ return NS_NewArrayEnumerator(aFiles, mFiles, NS_GET_IID(nsIFile));
}
return NS_ERROR_FAILURE;
diff --git a/widget/nsBaseFilePicker.cpp b/widget/nsBaseFilePicker.cpp
index 9cbdf39d3f8b..f22bc505dcdf 100644
--- a/widget/nsBaseFilePicker.cpp
+++ b/widget/nsBaseFilePicker.cpp
@@ -21,6 +21,7 @@
#include "mozilla/dom/File.h"
#include "mozilla/Services.h"
#include "WidgetUtils.h"
+#include "nsSimpleEnumerator.h"
#include "nsThreadUtils.h"
#include "nsBaseFilePicker.h"
@@ -100,11 +101,9 @@ private:
RefPtr mCallback;
};
-class nsBaseFilePickerEnumerator : public nsISimpleEnumerator
+class nsBaseFilePickerEnumerator : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
-
nsBaseFilePickerEnumerator(nsPIDOMWindowOuter* aParent,
nsISimpleEnumerator* iterator,
int16_t aMode)
@@ -113,6 +112,8 @@ public:
, mMode(aMode)
{}
+ const nsID& DefaultInterface() override { return NS_GET_IID(nsIFile); }
+
NS_IMETHOD
GetNext(nsISupports** aResult) override
{
@@ -141,18 +142,12 @@ public:
return mIterator->HasMoreElements(aResult);
}
-protected:
- virtual ~nsBaseFilePickerEnumerator()
- {}
-
private:
nsCOMPtr mIterator;
nsCOMPtr mParent;
int16_t mMode;
};
-NS_IMPL_ISUPPORTS(nsBaseFilePickerEnumerator, nsISimpleEnumerator)
-
nsBaseFilePicker::nsBaseFilePicker()
: mAddToRecentDocs(true)
, mMode(nsIFilePicker::modeOpen)
@@ -290,7 +285,7 @@ NS_IMETHODIMP nsBaseFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
files.AppendObject(file);
- return NS_NewArrayEnumerator(aFiles, files);
+ return NS_NewArrayEnumerator(aFiles, files, NS_GET_IID(nsIFile));
}
// Set the display directory
diff --git a/widget/nsFilePickerProxy.cpp b/widget/nsFilePickerProxy.cpp
index 4497023ef996..7b39c8742f49 100644
--- a/widget/nsFilePickerProxy.cpp
+++ b/widget/nsFilePickerProxy.cpp
@@ -7,6 +7,7 @@
#include "nsFilePickerProxy.h"
#include "nsComponentManagerUtils.h"
#include "nsIFile.h"
+#include "nsSimpleEnumerator.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/TabChild.h"
@@ -220,11 +221,9 @@ nsFilePickerProxy::GetDomFileOrDirectory(nsISupports** aValue)
namespace {
-class SimpleEnumerator final : public nsISimpleEnumerator
+class SimpleEnumerator final : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
-
explicit
SimpleEnumerator(const nsTArray& aFilesOrDirectories)
: mFilesOrDirectories(aFilesOrDirectories)
@@ -259,15 +258,10 @@ public:
}
private:
- ~SimpleEnumerator()
- {}
-
nsTArray mFilesOrDirectories;
uint32_t mIndex;
};
-NS_IMPL_ISUPPORTS(SimpleEnumerator, nsISimpleEnumerator)
-
} // namespace
NS_IMETHODIMP
diff --git a/widget/windows/nsFilePicker.cpp b/widget/windows/nsFilePicker.cpp
index da628ae88d21..0e1d15d9c2e8 100644
--- a/widget/windows/nsFilePicker.cpp
+++ b/widget/windows/nsFilePicker.cpp
@@ -688,7 +688,7 @@ NS_IMETHODIMP
nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
{
NS_ENSURE_ARG_POINTER(aFiles);
- return NS_NewArrayEnumerator(aFiles, mFiles);
+ return NS_NewArrayEnumerator(aFiles, mFiles, NS_GET_IID(nsIFile));
}
// Get the file + path
diff --git a/xpcom/base/TupleCycleCollection.h b/xpcom/base/TupleCycleCollection.h
new file mode 100644
index 000000000000..3eac110fe6c8
--- /dev/null
+++ b/xpcom/base/TupleCycleCollection.h
@@ -0,0 +1,35 @@
+/* -*- 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/. */
+
+#ifndef TupleCycleCollection_h
+#define TupleCycleCollection_h
+
+#include "mozilla/Tuple.h"
+#include "nsCycleCollectionTraversalCallback.h"
+
+template
+inline void
+ImplCycleCollectionUnlink(mozilla::Tuple& aField)
+{
+ ForEach(aField, [](auto& aElem) {
+ ImplCycleCollectionUnlink(aElem);
+ });
+}
+
+template
+inline void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
+ mozilla::Tuple& aField,
+ const char* aName,
+ uint32_t aFlags = 0)
+{
+ aFlags |= CycleCollectionEdgeNameArrayFlag;
+ ForEach(aField, [&](auto& aElem) {
+ ImplCycleCollectionTraverse(aCallback, aElem, aName, aFlags);
+ });
+}
+
+#endif // TupleCycleCollection_h
diff --git a/xpcom/base/moz.build b/xpcom/base/moz.build
index c2dbba28fddc..d17973c7ffa1 100644
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -122,6 +122,7 @@ EXPORTS.mozilla += [
'StaticMonitor.h',
'StaticMutex.h',
'StaticPtr.h',
+ 'TupleCycleCollection.h',
]
# nsDebugImpl isn't unified because we disable PGO so that NS_ABORT_OOM isn't
diff --git a/xpcom/components/nsCategoryManager.cpp b/xpcom/components/nsCategoryManager.cpp
index b96187ecc65c..526c64e78d59 100644
--- a/xpcom/components/nsCategoryManager.cpp
+++ b/xpcom/components/nsCategoryManager.cpp
@@ -29,7 +29,7 @@
#include "mozilla/Services.h"
#include "ManifestParser.h"
-#include "nsISimpleEnumerator.h"
+#include "nsSimpleEnumerator.h"
using namespace mozilla;
class nsIComponentLoaderManager;
@@ -51,14 +51,19 @@ class nsIComponentLoaderManager;
// CategoryEnumerator
//
class BaseStringEnumerator
- : public nsISimpleEnumerator
+ : public nsSimpleEnumerator
, private nsIUTF8StringEnumerator
{
public:
- NS_DECL_ISUPPORTS
+ NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSISIMPLEENUMERATOR
NS_DECL_NSIUTF8STRINGENUMERATOR
+ const nsID& DefaultInterface() override
+ {
+ return NS_GET_IID(nsISupportsCString);
+ }
+
protected:
// Callback function for NS_QuickSort to sort mArray
static int SortCallback(const void*, const void*, void*);
@@ -87,8 +92,8 @@ protected:
uint32_t mStringCurItem;
};
-NS_IMPL_ISUPPORTS(BaseStringEnumerator, nsISimpleEnumerator,
- nsIUTF8StringEnumerator)
+NS_IMPL_ISUPPORTS_INHERITED(BaseStringEnumerator, nsSimpleEnumerator,
+ nsIUTF8StringEnumerator)
NS_IMETHODIMP
BaseStringEnumerator::HasMoreElements(bool* aResult)
diff --git a/xpcom/ds/SimpleEnumerator.h b/xpcom/ds/SimpleEnumerator.h
new file mode 100644
index 000000000000..78f964b80bf8
--- /dev/null
+++ b/xpcom/ds/SimpleEnumerator.h
@@ -0,0 +1,92 @@
+/* -*- 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/. */
+
+#ifndef mozilla_SimpleEnumerator_h
+#define mozilla_SimpleEnumerator_h
+
+#include "nsCOMPtr.h"
+#include "nsISimpleEnumerator.h"
+
+namespace mozilla {
+
+/**
+ * A wrapper class around nsISimpleEnumerator to support ranged iteration. This
+ * requires every element in the enumeration to implement the same interface, T.
+ * If any element does not implement this interface, the enumeration ends at
+ * that element, and triggers an assertion in debug builds.
+ *
+ * Typical usage looks something like:
+ *
+ * for (auto& docShell : SimpleEnumerator(docShellEnum)) {
+ * docShell.LoadURI(...);
+ * }
+ */
+
+template
+class SimpleEnumerator final
+{
+public:
+ explicit SimpleEnumerator(nsISimpleEnumerator* aEnum)
+ : mEnum(aEnum)
+ {}
+
+ class Entry
+ {
+ public:
+ explicit Entry(T* aPtr)
+ : mPtr(aPtr)
+ {}
+
+ explicit Entry(nsISimpleEnumerator& aEnum)
+ : mEnum(&aEnum)
+ {
+ ++*this;
+ }
+
+ T& operator*()
+ {
+ MOZ_ASSERT(mPtr);
+ return *mPtr;
+ }
+
+ Entry& operator++()
+ {
+ MOZ_ASSERT(mEnum);
+ nsCOMPtr next;
+ if (NS_SUCCEEDED(mEnum->GetNext(getter_AddRefs(next)))) {
+ mPtr = do_QueryInterface(next);
+ MOZ_ASSERT(mPtr);
+ } else {
+ mPtr = nullptr;
+ }
+ return *this;
+ }
+
+ bool operator!=(const Entry& aOther) const
+ {
+ return mPtr != aOther.mPtr;
+ }
+
+ private:
+ nsCOMPtr mPtr;
+ nsCOMPtr mEnum;
+ };
+
+ Entry begin() {
+ return Entry(*mEnum);
+ }
+
+ Entry end() {
+ return Entry(nullptr);
+ }
+
+private:
+ nsCOMPtr mEnum;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_SimpleEnumerator_h
diff --git a/xpcom/ds/moz.build b/xpcom/ds/moz.build
index 257eb4f7ebf4..09de9afdd10e 100644
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -64,6 +64,7 @@ EXPORTS += [
'nsPointerHashKeys.h',
'nsQuickSort.h',
'nsRefPtrHashtable.h',
+ 'nsSimpleEnumerator.h',
'nsStaticAtomUtils.h',
'nsStaticNameTable.h',
'nsStringEnumerator.h',
@@ -87,6 +88,7 @@ EXPORTS.mozilla += [
'Dafsa.h',
'IncrementalTokenizer.h',
'Observer.h',
+ 'SimpleEnumerator.h',
'StickyTimeDuration.h',
'Tokenizer.h',
]
@@ -109,6 +111,7 @@ UNIFIED_SOURCES += [
'nsPersistentProperties.cpp',
'nsProperties.cpp',
'nsQuickSort.cpp',
+ 'nsSimpleEnumerator.cpp',
'nsStaticNameTable.cpp',
'nsStringEnumerator.cpp',
'nsSupportsPrimitives.cpp',
diff --git a/xpcom/ds/nsArray.cpp b/xpcom/ds/nsArray.cpp
index e31a646bb0ea..f40ca313dfbb 100644
--- a/xpcom/ds/nsArray.cpp
+++ b/xpcom/ds/nsArray.cpp
@@ -7,6 +7,7 @@
#include "nsArray.h"
#include "nsArrayEnumerator.h"
#include "nsThreadUtils.h"
+#include "xpcjsid.h"
NS_INTERFACE_MAP_BEGIN(nsArray)
NS_INTERFACE_MAP_ENTRY(nsIArray)
@@ -79,11 +80,22 @@ nsArrayBase::IndexOf(uint32_t aStartIndex, nsISupports* aElement,
}
NS_IMETHODIMP
-nsArrayBase::Enumerate(nsISimpleEnumerator** aResult)
+nsArrayBase::ScriptedEnumerate(nsIJSIID* aElemIID, uint8_t aArgc,
+ nsISimpleEnumerator** aResult)
{
+ if (aArgc > 0 && aElemIID) {
+ return NS_NewArrayEnumerator(aResult, static_cast(this), *aElemIID->GetID());
+ }
return NS_NewArrayEnumerator(aResult, static_cast(this));
}
+
+NS_IMETHODIMP
+nsArrayBase::EnumerateImpl(const nsID& aElemIID, nsISimpleEnumerator** aResult)
+{
+ return NS_NewArrayEnumerator(aResult, static_cast(this), aElemIID);
+}
+
// nsIMutableArray implementation
NS_IMETHODIMP
diff --git a/xpcom/ds/nsArrayEnumerator.cpp b/xpcom/ds/nsArrayEnumerator.cpp
index f72cd154a4ad..1a12dd4c2451 100644
--- a/xpcom/ds/nsArrayEnumerator.cpp
+++ b/xpcom/ds/nsArrayEnumerator.cpp
@@ -9,39 +9,38 @@
#include "nsArrayEnumerator.h"
#include "nsIArray.h"
-#include "nsISimpleEnumerator.h"
+#include "nsSimpleEnumerator.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/RefPtr.h"
-class nsSimpleArrayEnumerator final : public nsISimpleEnumerator
+class nsSimpleArrayEnumerator final : public nsSimpleEnumerator
{
public:
- // nsISupports interface
- NS_DECL_ISUPPORTS
-
// nsISimpleEnumerator interface
NS_DECL_NSISIMPLEENUMERATOR
// nsSimpleArrayEnumerator methods
- explicit nsSimpleArrayEnumerator(nsIArray* aValueArray)
+ explicit nsSimpleArrayEnumerator(nsIArray* aValueArray, const nsID& aEntryIID)
: mValueArray(aValueArray)
+ , mEntryIID(aEntryIID)
, mIndex(0)
{
}
+ const nsID& DefaultInterface() override { return mEntryIID; }
+
private:
- ~nsSimpleArrayEnumerator() = default;
+ ~nsSimpleArrayEnumerator() override = default;
protected:
nsCOMPtr mValueArray;
+ const nsID mEntryIID;
uint32_t mIndex;
};
-NS_IMPL_ISUPPORTS(nsSimpleArrayEnumerator, nsISimpleEnumerator)
-
NS_IMETHODIMP
nsSimpleArrayEnumerator::HasMoreElements(bool* aResult)
{
@@ -91,9 +90,10 @@ nsSimpleArrayEnumerator::GetNext(nsISupports** aResult)
}
nsresult
-NS_NewArrayEnumerator(nsISimpleEnumerator** aResult, nsIArray* aArray)
+NS_NewArrayEnumerator(nsISimpleEnumerator** aResult, nsIArray* aArray,
+ const nsID& aEntryIID)
{
- RefPtr enumer = new nsSimpleArrayEnumerator(aArray);
+ RefPtr enumer = new nsSimpleArrayEnumerator(aArray, aEntryIID);
enumer.forget(aResult);
return NS_OK;
}
@@ -104,42 +104,42 @@ NS_NewArrayEnumerator(nsISimpleEnumerator** aResult, nsIArray* aArray)
// creates a snapshot of the array in question
// you MUST use NS_NewArrayEnumerator to create this, so that
// allocation is done correctly
-class nsCOMArrayEnumerator final : public nsISimpleEnumerator
+class nsCOMArrayEnumerator final : public nsSimpleEnumerator
{
public:
- // nsISupports interface
- NS_DECL_ISUPPORTS
-
// nsISimpleEnumerator interface
NS_DECL_NSISIMPLEENUMERATOR
// Use this instead of `new`.
- static nsCOMArrayEnumerator* Allocate(const nsCOMArray_base& aArray);
+ static nsCOMArrayEnumerator* Allocate(const nsCOMArray_base& aArray, const nsID& aEntryIID);
// specialized operator to make sure we make room for mValues
void operator delete(void* aPtr) { free(aPtr); }
+ const nsID& DefaultInterface() override { return mEntryIID; }
+
private:
// nsSimpleArrayEnumerator methods
- nsCOMArrayEnumerator()
+ explicit nsCOMArrayEnumerator(const nsID& aEntryIID)
: mIndex(0)
, mArraySize(0)
+ , mEntryIID(aEntryIID)
{
mValueArray[0] = nullptr;
}
- ~nsCOMArrayEnumerator(void);
+ ~nsCOMArrayEnumerator(void) override;
protected:
uint32_t mIndex; // current position
uint32_t mArraySize; // size of the array
+ const nsID& mEntryIID;
+
// this is actually bigger
nsISupports* mValueArray[1];
};
-NS_IMPL_ISUPPORTS(nsCOMArrayEnumerator, nsISimpleEnumerator)
-
nsCOMArrayEnumerator::~nsCOMArrayEnumerator()
{
// only release the entries that we haven't visited yet
@@ -185,7 +185,7 @@ nsCOMArrayEnumerator::GetNext(nsISupports** aResult)
}
nsCOMArrayEnumerator*
-nsCOMArrayEnumerator::Allocate(const nsCOMArray_base& aArray)
+nsCOMArrayEnumerator::Allocate(const nsCOMArray_base& aArray, const nsID& aEntryIID)
{
// create enough space such that mValueArray points to a large
// enough value. Note that the initial value of aSize gives us
@@ -201,7 +201,7 @@ nsCOMArrayEnumerator::Allocate(const nsCOMArray_base& aArray)
// Allocate a buffer large enough to contain our object and its array.
void* mem = moz_xmalloc(size);
- auto result = new (mozilla::KnownNotNull, mem) nsCOMArrayEnumerator();
+ auto result = new (mozilla::KnownNotNull, mem) nsCOMArrayEnumerator(aEntryIID);
result->mArraySize = count;
@@ -219,9 +219,10 @@ nsCOMArrayEnumerator::Allocate(const nsCOMArray_base& aArray)
nsresult
NS_NewArrayEnumerator(nsISimpleEnumerator** aResult,
- const nsCOMArray_base& aArray)
+ const nsCOMArray_base& aArray,
+ const nsID& aEntryIID)
{
- RefPtr enumerator = nsCOMArrayEnumerator::Allocate(aArray);
+ RefPtr enumerator = nsCOMArrayEnumerator::Allocate(aArray, aEntryIID);
enumerator.forget(aResult);
return NS_OK;
}
diff --git a/xpcom/ds/nsArrayEnumerator.h b/xpcom/ds/nsArrayEnumerator.h
index 341ae86edab4..dd4dd5093444 100644
--- a/xpcom/ds/nsArrayEnumerator.h
+++ b/xpcom/ds/nsArrayEnumerator.h
@@ -9,7 +9,7 @@
// enumerator implementation for nsIArray
-#include "nscore.h"
+#include "nsISupports.h"
class nsISimpleEnumerator;
class nsIArray;
@@ -19,7 +19,8 @@ class nsCOMArray_base;
// The enumerator holds an owning reference to the array.
nsresult
NS_NewArrayEnumerator(nsISimpleEnumerator** aResult,
- nsIArray* aArray);
+ nsIArray* aArray,
+ const nsID& aEntryIID = NS_GET_IID(nsISupports));
// create an enumerator for an existing nsCOMArray implementation
// The enumerator will hold an owning reference to each ELEMENT in
@@ -27,6 +28,7 @@ NS_NewArrayEnumerator(nsISimpleEnumerator** aResult,
// without its objects going away.
nsresult
NS_NewArrayEnumerator(nsISimpleEnumerator** aResult,
- const nsCOMArray_base& aArray);
+ const nsCOMArray_base& aArray,
+ const nsID& aEntryIID = NS_GET_IID(nsISupports));
#endif
diff --git a/xpcom/ds/nsEnumeratorUtils.cpp b/xpcom/ds/nsEnumeratorUtils.cpp
index 36e00ae89ff7..c4d4c0729e1f 100644
--- a/xpcom/ds/nsEnumeratorUtils.cpp
+++ b/xpcom/ds/nsEnumeratorUtils.cpp
@@ -8,14 +8,14 @@
#include "nsEnumeratorUtils.h"
-#include "nsISimpleEnumerator.h"
#include "nsIStringEnumerator.h"
+#include "nsSimpleEnumerator.h"
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
class EmptyEnumeratorImpl
- : public nsISimpleEnumerator
+ : public nsSimpleEnumerator
, public nsIUTF8StringEnumerator
, public nsIStringEnumerator
{
@@ -52,7 +52,7 @@ EmptyEnumeratorImpl::Release(void)
return 1;
}
-NS_IMPL_QUERY_INTERFACE(EmptyEnumeratorImpl, nsISimpleEnumerator,
+NS_IMPL_QUERY_INTERFACE_INHERITED(EmptyEnumeratorImpl, nsSimpleEnumerator,
nsIUTF8StringEnumerator, nsIStringEnumerator)
// nsISimpleEnumerator interface
@@ -73,7 +73,7 @@ EmptyEnumeratorImpl::HasMore(bool* aResult)
NS_IMETHODIMP
EmptyEnumeratorImpl::GetNext(nsISupports** aResult)
{
- return NS_ERROR_UNEXPECTED;
+ return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@@ -97,11 +97,9 @@ NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult)
////////////////////////////////////////////////////////////////////////////////
-class nsSingletonEnumerator final : public nsISimpleEnumerator
+class nsSingletonEnumerator final : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
-
// nsISimpleEnumerator methods
NS_IMETHOD HasMoreElements(bool* aResult) override;
NS_IMETHOD GetNext(nsISupports** aResult) override;
@@ -109,7 +107,7 @@ public:
explicit nsSingletonEnumerator(nsISupports* aValue);
private:
- ~nsSingletonEnumerator();
+ ~nsSingletonEnumerator() override;
protected:
nsCOMPtr mValue;
@@ -124,8 +122,6 @@ nsSingletonEnumerator::nsSingletonEnumerator(nsISupports* aValue)
nsSingletonEnumerator::~nsSingletonEnumerator() = default;
-NS_IMPL_ISUPPORTS(nsSingletonEnumerator, nsISimpleEnumerator)
-
NS_IMETHODIMP
nsSingletonEnumerator::HasMoreElements(bool* aResult)
{
@@ -148,7 +144,7 @@ nsSingletonEnumerator::GetNext(nsISupports** aResult)
}
if (mConsumed) {
- return NS_ERROR_UNEXPECTED;
+ return NS_ERROR_FAILURE;
}
mConsumed = true;
@@ -169,11 +165,9 @@ NS_NewSingletonEnumerator(nsISimpleEnumerator** aResult,
////////////////////////////////////////////////////////////////////////////////
-class nsUnionEnumerator final : public nsISimpleEnumerator
+class nsUnionEnumerator final : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
-
// nsISimpleEnumerator methods
NS_IMETHOD HasMoreElements(bool* aResult) override;
NS_IMETHOD GetNext(nsISupports** aResult) override;
@@ -182,7 +176,7 @@ public:
nsISimpleEnumerator* aSecondEnumerator);
private:
- ~nsUnionEnumerator();
+ ~nsUnionEnumerator() override;
protected:
nsCOMPtr mFirstEnumerator, mSecondEnumerator;
@@ -201,8 +195,6 @@ nsUnionEnumerator::nsUnionEnumerator(nsISimpleEnumerator* aFirstEnumerator,
nsUnionEnumerator::~nsUnionEnumerator() = default;
-NS_IMPL_ISUPPORTS(nsUnionEnumerator, nsISimpleEnumerator)
-
NS_IMETHODIMP
nsUnionEnumerator::HasMoreElements(bool* aResult)
{
@@ -254,7 +246,7 @@ nsUnionEnumerator::GetNext(nsISupports** aResult)
}
if (mConsumed) {
- return NS_ERROR_UNEXPECTED;
+ return NS_ERROR_FAILURE;
}
if (!mAtSecond) {
diff --git a/xpcom/ds/nsHashPropertyBag.cpp b/xpcom/ds/nsHashPropertyBag.cpp
index 15e28fbdc8c0..7a38553bd7db 100644
--- a/xpcom/ds/nsHashPropertyBag.cpp
+++ b/xpcom/ds/nsHashPropertyBag.cpp
@@ -120,7 +120,8 @@ nsHashPropertyBagBase::GetEnumerator(nsISimpleEnumerator** aResult)
propertyArray->AppendElement(sprop);
}
- return NS_NewArrayEnumerator(aResult, propertyArray);
+ return NS_NewArrayEnumerator(aResult, propertyArray,
+ NS_GET_IID(nsIProperty));
}
#define IMPL_GETSETPROPERTY_AS(Name, Type) \
diff --git a/xpcom/ds/nsIArray.idl b/xpcom/ds/nsIArray.idl
index d591253e9ac8..bf1b955abcfe 100644
--- a/xpcom/ds/nsIArray.idl
+++ b/xpcom/ds/nsIArray.idl
@@ -5,6 +5,7 @@
#include "nsISupports.idl"
+interface nsIJSIID;
interface nsISimpleEnumerator;
/**
@@ -31,7 +32,7 @@ interface nsISimpleEnumerator;
* null is a valid entry in the array, and as such any nsISupports
* parameters may be null, except where noted.
*/
-[scriptable, uuid(114744d9-c369-456e-b55a-52fe52880d2d)]
+[scriptable, builtinclass, uuid(114744d9-c369-456e-b55a-52fe52880d2d)]
interface nsIArray : nsISupports
{
/**
@@ -87,5 +88,17 @@ interface nsIArray : nsISupports
* @throws NS_ERROR_FAILURE if the array is empty (to make it easy
* to detect errors), or NS_ERROR_OUT_OF_MEMORY if out of memory.
*/
- nsISimpleEnumerator enumerate();
+ [binaryname(ScriptedEnumerate), optional_argc]
+ nsISimpleEnumerator enumerate([optional] in nsIJSIID aElemIID);
+
+ [noscript]
+ nsISimpleEnumerator enumerateImpl(in nsIDRef aElemIID);
+
+ %{C++
+ nsresult
+ Enumerate(nsISimpleEnumerator** aRetVal, const nsID& aElemIID = NS_GET_IID(nsISupports))
+ {
+ return EnumerateImpl(aElemIID, aRetVal);
+ }
+ %}
};
diff --git a/xpcom/ds/nsIArrayExtensions.idl b/xpcom/ds/nsIArrayExtensions.idl
index 3682d2ee70ae..872a5c018d8d 100644
--- a/xpcom/ds/nsIArrayExtensions.idl
+++ b/xpcom/ds/nsIArrayExtensions.idl
@@ -24,7 +24,7 @@
* itself, possibly getting rid of the Count() method, as it duplicates
* nsIArray functionality.
*/
-[scriptable, uuid(261d442e-050c-453d-8aaa-b3f23bcc528b)]
+[scriptable, builtinclass, uuid(261d442e-050c-453d-8aaa-b3f23bcc528b)]
interface nsIArrayExtensions : nsIArray
{
/**
diff --git a/xpcom/ds/nsIMutableArray.idl b/xpcom/ds/nsIMutableArray.idl
index 73f629412263..0308aa814b4a 100644
--- a/xpcom/ds/nsIMutableArray.idl
+++ b/xpcom/ds/nsIMutableArray.idl
@@ -20,7 +20,7 @@
* Any of these methods may throw NS_ERROR_OUT_OF_MEMORY when the
* array must grow to complete the call, but the allocation fails.
*/
-[scriptable, uuid(af059da0-c85b-40ec-af07-ae4bfdc192cc)]
+[scriptable, builtinclass, uuid(af059da0-c85b-40ec-af07-ae4bfdc192cc)]
interface nsIMutableArray : nsIArrayExtensions
{
/**
diff --git a/xpcom/ds/nsISimpleEnumerator.idl b/xpcom/ds/nsISimpleEnumerator.idl
index cbb0cd2000c6..1a2b47705dbe 100644
--- a/xpcom/ds/nsISimpleEnumerator.idl
+++ b/xpcom/ds/nsISimpleEnumerator.idl
@@ -14,8 +14,39 @@
* @version 1.0
*/
+/**
+ * A wrapper for an nsISimpleEnumerator instance which implements the
+ * JavaScript iteration protocol.
+ */
+[scriptable, uuid(4432e8ae-d4d3-42a6-a4d1-829f1c29512b)]
+interface nsIJSEnumerator : nsISupports {
+ [symbol]
+ nsIJSEnumerator iterator();
+
+ [implicit_jscontext]
+ jsval next();
+};
+
+[scriptable, uuid(796f340d-0a2a-490b-9c60-640765e99782)]
+interface nsISimpleEnumeratorBase : nsISupports {
+ /**
+ * Returns a JavaScript iterator for all remaining entries in the enumerator.
+ * Each entry is typically queried to the appropriate interface for the
+ * enumerator.
+ */
+ [symbol]
+ nsIJSEnumerator iterator();
+
+ /**
+ * Returns JavaScript iterator for all remaining entries in the enumerator.
+ * Each entry is queried only to the supplied interface. If any element
+ * fails to query to that interface, the error is propagated to the caller.
+ */
+ nsIJSEnumerator entries(in nsIIDRef aIface);
+};
+
[scriptable, uuid(D1899240-F9D2-11D2-BDD6-000064657374)]
-interface nsISimpleEnumerator : nsISupports {
+interface nsISimpleEnumerator : nsISimpleEnumeratorBase {
/**
* Called to determine whether or not the enumerator has
* any elements that can be returned via getNext(). This method
@@ -27,7 +58,7 @@ interface nsISimpleEnumerator : nsISupports {
* @see getNext()
* @return true if there are remaining elements in the enumerator.
* false if there are no more elements in the enumerator.
- */
+ */
boolean hasMoreElements();
/**
diff --git a/xpcom/ds/nsObserverList.cpp b/xpcom/ds/nsObserverList.cpp
index fef8831b8ce3..5a7c8a4706e0 100644
--- a/xpcom/ds/nsObserverList.cpp
+++ b/xpcom/ds/nsObserverList.cpp
@@ -8,7 +8,6 @@
#include "nsAutoPtr.h"
#include "nsCOMArray.h"
-#include "nsISimpleEnumerator.h"
#include "xpcpublic.h"
nsresult
@@ -113,8 +112,6 @@ nsObserverList::NotifyObservers(nsISupports* aSubject,
}
}
-NS_IMPL_ISUPPORTS(nsObserverEnumerator, nsISimpleEnumerator)
-
nsObserverEnumerator::nsObserverEnumerator(nsObserverList* aObserverList)
: mIndex(0)
{
@@ -132,8 +129,7 @@ NS_IMETHODIMP
nsObserverEnumerator::GetNext(nsISupports** aResult)
{
if (mIndex == mObservers.Count()) {
- NS_ERROR("Enumerating after HasMoreElements returned false.");
- return NS_ERROR_UNEXPECTED;
+ return NS_ERROR_FAILURE;
}
NS_ADDREF(*aResult = mObservers[mIndex]);
diff --git a/xpcom/ds/nsObserverList.h b/xpcom/ds/nsObserverList.h
index 90a685ea60d8..3174669e2d7a 100644
--- a/xpcom/ds/nsObserverList.h
+++ b/xpcom/ds/nsObserverList.h
@@ -14,7 +14,7 @@
#include "nsIObserver.h"
#include "nsIWeakReference.h"
#include "nsHashKeys.h"
-#include "nsISimpleEnumerator.h"
+#include "nsSimpleEnumerator.h"
#include "mozilla/Attributes.h"
struct ObserverRef
@@ -75,16 +75,17 @@ private:
nsTArray mObservers;
};
-class nsObserverEnumerator final : public nsISimpleEnumerator
+class nsObserverEnumerator final : public nsSimpleEnumerator
{
public:
- NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
explicit nsObserverEnumerator(nsObserverList* aObserverList);
+ const nsID& DefaultInterface() override { return NS_GET_IID(nsIObserver); }
+
private:
- ~nsObserverEnumerator() {}
+ ~nsObserverEnumerator() override = default;
int32_t mIndex; // Counts up from 0
nsCOMArray mObservers;
diff --git a/xpcom/ds/nsPersistentProperties.cpp b/xpcom/ds/nsPersistentProperties.cpp
index ff9b22c06a22..433b00960e48 100644
--- a/xpcom/ds/nsPersistentProperties.cpp
+++ b/xpcom/ds/nsPersistentProperties.cpp
@@ -570,7 +570,7 @@ nsPersistentProperties::Enumerate(nsISimpleEnumerator** aResult)
}
}
- return NS_NewArrayEnumerator(aResult, props);
+ return NS_NewArrayEnumerator(aResult, props, NS_GET_IID(nsIPropertyElement));
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/xpcom/ds/nsSimpleEnumerator.cpp b/xpcom/ds/nsSimpleEnumerator.cpp
new file mode 100644
index 000000000000..be8c14896a1b
--- /dev/null
+++ b/xpcom/ds/nsSimpleEnumerator.cpp
@@ -0,0 +1,87 @@
+/* -*- 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 "nsSimpleEnumerator.h"
+
+#include "mozilla/dom/IteratorResultBinding.h"
+#include "mozilla/dom/RootedDictionary.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "mozilla/ResultExtensions.h"
+#include "nsContentUtils.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+namespace {
+
+class JSEnumerator final : public nsIJSEnumerator
+{
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIJSENUMERATOR
+
+ explicit JSEnumerator(nsISimpleEnumerator* aEnumerator, const nsID& aIID)
+ : mEnumerator(aEnumerator)
+ , mIID(aIID)
+ {}
+
+private:
+ ~JSEnumerator() = default;
+
+ nsCOMPtr mEnumerator;
+ const nsID mIID;
+};
+
+} // anonymous namespace
+
+nsresult
+JSEnumerator::Iterator(nsIJSEnumerator** aResult)
+{
+ RefPtr result(this);
+ result.forget(aResult);
+ return NS_OK;
+}
+
+nsresult
+JSEnumerator::Next(JSContext* aCx, JS::MutableHandleValue aResult)
+{
+ RootedDictionary result(aCx);
+
+ nsCOMPtr elem;
+ if (NS_FAILED(mEnumerator->GetNext(getter_AddRefs(elem)))) {
+ result.mDone = true;
+ } else {
+ result.mDone = false;
+
+ JS::RootedValue value(aCx);
+ MOZ_TRY(nsContentUtils::WrapNative(aCx, elem, &mIID, &value));
+ result.mValue = value;
+ }
+
+ if (!ToJSValue(aCx, result, aResult)) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(JSEnumerator, nsIJSEnumerator)
+
+nsresult
+nsSimpleEnumerator::Iterator(nsIJSEnumerator **aResult)
+{
+ auto result = MakeRefPtr(this, DefaultInterface());
+ result.forget(aResult);
+ return NS_OK;
+}
+
+nsresult
+nsSimpleEnumerator::Entries(const nsIID& aIface, nsIJSEnumerator **aResult)
+{
+ auto result = MakeRefPtr(this, aIface);
+ result.forget(aResult);
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(nsSimpleEnumerator, nsISimpleEnumerator, nsISimpleEnumeratorBase)
diff --git a/xpcom/ds/nsSimpleEnumerator.h b/xpcom/ds/nsSimpleEnumerator.h
new file mode 100644
index 000000000000..e54e6a3ecd6a
--- /dev/null
+++ b/xpcom/ds/nsSimpleEnumerator.h
@@ -0,0 +1,23 @@
+/* -*- 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/. */
+
+#ifndef nsSimpleEnumerator_h
+#define nsSimpleEnumerator_h
+
+#include "nsISimpleEnumerator.h"
+
+class nsSimpleEnumerator : public nsISimpleEnumerator
+{
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATORBASE
+
+ virtual const nsID& DefaultInterface() { return NS_GET_IID(nsISupports); }
+
+protected:
+ virtual ~nsSimpleEnumerator() = default;
+};
+
+#endif
diff --git a/xpcom/ds/nsStringEnumerator.cpp b/xpcom/ds/nsStringEnumerator.cpp
index bdcd53e1a81b..9dd7aba1670d 100644
--- a/xpcom/ds/nsStringEnumerator.cpp
+++ b/xpcom/ds/nsStringEnumerator.cpp
@@ -6,7 +6,7 @@
#include "nsStringEnumerator.h"
-#include "nsISimpleEnumerator.h"
+#include "nsSimpleEnumerator.h"
#include "nsSupportsPrimitives.h"
#include "mozilla/Attributes.h"
#include "nsTArray.h"
@@ -16,9 +16,9 @@
//
class nsStringEnumerator final
- : public nsIStringEnumerator
+ : public nsSimpleEnumerator
+ , public nsIStringEnumerator
, public nsIUTF8StringEnumerator
- , public nsISimpleEnumerator
{
public:
nsStringEnumerator(const nsTArray