diff --git a/browser/base/content/sanitize.js b/browser/base/content/sanitize.js
index 95a10f831b1c..faafaa686299 100644
--- a/browser/base/content/sanitize.js
+++ b/browser/base/content/sanitize.js
@@ -19,6 +19,14 @@ XPCOMUtils.defineLazyModuleGetters(this, {
setTimeout: "resource://gre/modules/Timer.jsm",
});
+
+XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
+ "@mozilla.org/serviceworkers/manager;1",
+ "nsIServiceWorkerManager");
+XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",
+ "@mozilla.org/dom/quota-manager-service;1",
+ "nsIQuotaManagerService");
+
var {classes: Cc, interfaces: Ci} = Components;
/**
@@ -280,9 +288,41 @@ Sanitizer.prototype = {
offlineApps: {
async clear(range) {
+ // AppCache
Components.utils.import("resource:///modules/offlineAppCache.jsm");
// This doesn't wait for the cleanup to be complete.
OfflineAppCacheHelper.clear();
+
+ // LocalStorage
+ Services.obs.notifyObservers(null, "extension:purge-localStorage");
+
+ // ServiceWorkers
+ let serviceWorkers = serviceWorkerManager.getAllRegistrations();
+ for (let i = 0; i < serviceWorkers.length; i++) {
+ let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
+ let host = sw.principal.URI.host;
+ serviceWorkerManager.removeAndPropagate(host);
+ }
+
+ // QuotaManager
+ let promises = [];
+ await new Promise(resolve => {
+ quotaManagerService.getUsage(request => {
+ for (let item of request.result) {
+ let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
+ let uri = principal.URI;
+ if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") {
+ promises.push(new Promise(r => {
+ let req = quotaManagerService.clearStoragesForPrincipal(principal, null, true);
+ req.callback = () => { r(); };
+ }));
+ }
+ }
+ resolve();
+ });
+ });
+
+ return Promise.all(promises);
}
},
diff --git a/browser/components/extensions/ext-browsingData.js b/browser/components/extensions/ext-browsingData.js
index e313319333a0..0424d415d48d 100644
--- a/browser/components/extensions/ext-browsingData.js
+++ b/browser/components/extensions/ext-browsingData.js
@@ -17,6 +17,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
"@mozilla.org/serviceworkers/manager;1",
"nsIServiceWorkerManager");
+XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",
+ "@mozilla.org/dom/quota-manager-service;1",
+ "nsIQuotaManagerService");
/**
* A number of iterations after which to yield time back
@@ -80,6 +83,29 @@ const clearHistory = options => {
return sanitizer.items.history.clear(makeRange(options));
};
+const clearIndexedDB = async function(options) {
+ let promises = [];
+
+ await new Promise(resolve => {
+ quotaManagerService.getUsage(request => {
+ for (let item of request.result) {
+ let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
+ let uri = principal.URI;
+ if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") {
+ promises.push(new Promise(r => {
+ let req = quotaManagerService.clearStoragesForPrincipal(principal, null, true);
+ req.callback = () => { r(); };
+ }));
+ }
+ }
+
+ resolve();
+ });
+ });
+
+ return Promise.all(promises);
+};
+
const clearLocalStorage = async function(options) {
Services.obs.notifyObservers(null, "extension:purge-localStorage");
};
@@ -153,6 +179,9 @@ const doRemoval = (options, dataToRemove, extension) => {
case "history":
removalPromises.push(clearHistory(options));
break;
+ case "indexedDB":
+ removalPromises.push(clearIndexedDB(options));
+ break;
case "localStorage":
removalPromises.push(clearLocalStorage(options));
break;
@@ -229,6 +258,9 @@ this.browsingData = class extends ExtensionAPI {
removeHistory(options) {
return doRemoval(options, {history: true});
},
+ removeIndexedDB(options) {
+ return doRemoval(options, {indexedDB: true});
+ },
removeLocalStorage(options) {
return doRemoval(options, {localStorage: true});
},
diff --git a/browser/components/extensions/test/browser/browser-common.ini b/browser/components/extensions/test/browser/browser-common.ini
index 73f8bef4cdd5..2c3d43b20a53 100644
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -22,6 +22,7 @@ support-files =
file_dummy.html
file_title.html
file_inspectedwindow_reload_target.sjs
+ file_indexedDB.html
file_serviceWorker.html
locale/chrome.manifest
webNav_createdTarget.html
@@ -50,6 +51,7 @@ skip-if = (os == 'win' && !debug) # bug 1352668
[browser_ext_browserAction_theme_icons.js]
[browser_ext_browsingData_formData.js]
[browser_ext_browsingData_history.js]
+[browser_ext_browsingData_indexedDB.js]
[browser_ext_browsingData_localStorage.js]
[browser_ext_browsingData_pluginData.js]
[browser_ext_browsingData_serviceWorkers.js]
diff --git a/browser/components/extensions/test/browser/browser_ext_browsingData_indexedDB.js b/browser/components/extensions/test/browser/browser_ext_browsingData_indexedDB.js
new file mode 100644
index 000000000000..c10d1642d6ca
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_browsingData_indexedDB.js
@@ -0,0 +1,81 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
+"use strict";
+
+add_task(async function testIndexedDB() {
+ function background() {
+ const PAGE = "/browser/browser/components/extensions/test/browser/file_indexedDB.html";
+
+ browser.test.onMessage.addListener(async (msg) => {
+ await browser.browsingData.remove({}, {indexedDB: true});
+ browser.test.sendMessage("indexedDBRemoved");
+ });
+
+ // Create two tabs.
+ browser.tabs.create({url: `http://mochi.test:8888${PAGE}`});
+ browser.tabs.create({url: `http://example.com${PAGE}`});
+ }
+
+ function contentScript() {
+ window.addEventListener("message", msg => { // eslint-disable-line mozilla/balanced-listeners
+ browser.test.sendMessage("indexedDBCreated");
+ }, true);
+ }
+
+ let extension = ExtensionTestUtils.loadExtension({
+ background,
+ manifest: {
+ permissions: ["browsingData", "tabs"],
+ "content_scripts": [{
+ "matches": [
+ "http://mochi.test/*/file_indexedDB.html",
+ "http://example.com/*/file_indexedDB.html",
+ ],
+ "js": ["script.js"],
+ "run_at": "document_start",
+ }],
+ },
+ files: {
+ "script.js": contentScript,
+ },
+ });
+
+ let win = await BrowserTestUtils.openNewBrowserWindow();
+ await focusWindow(win);
+
+ await extension.startup();
+ await extension.awaitMessage("indexedDBCreated");
+ await extension.awaitMessage("indexedDBCreated");
+
+ let qms = SpecialPowers.Cc["@mozilla.org/dom/quota-manager-service;1"]
+ .getService(Ci.nsIQuotaManagerService);
+
+ function getOrigins() {
+ return new Promise(resolve => {
+ let origins = [];
+ qms.getUsage(request => {
+ for (let i = 0; i < request.result.length; ++i) {
+ if (request.result[i].origin.startsWith("http://mochi.test") ||
+ request.result[i].origin.startsWith("http://example.com")) {
+ origins.push(request.result[i].origin);
+ }
+ }
+ resolve(origins);
+ });
+ });
+ }
+
+ let origins = await getOrigins();
+ is(origins.length, 2, "IndexedDB databases have been populated.");
+
+ extension.sendMessage();
+
+ await extension.awaitMessage("indexedDBRemoved");
+
+ origins = await getOrigins();
+ is(origins.length, 0, "IndexedDB data has been removed.");
+
+ await extension.unload();
+ await BrowserTestUtils.closeWindow(win);
+});
diff --git a/browser/components/extensions/test/browser/file_indexedDB.html b/browser/components/extensions/test/browser/file_indexedDB.html
new file mode 100644
index 000000000000..65b7e0ad2f4f
--- /dev/null
+++ b/browser/components/extensions/test/browser/file_indexedDB.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+ This is a test page.
+
+
diff --git a/browser/components/extensions/test/xpcshell/test_ext_browsingData.js b/browser/components/extensions/test/xpcshell/test_ext_browsingData.js
index 0b8972058e64..bb5cea4ba703 100644
--- a/browser/components/extensions/test/xpcshell/test_ext_browsingData.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_browsingData.js
@@ -41,26 +41,3 @@ add_task(async function testInvalidArguments() {
await extension.awaitFinish("invalidArguments");
await extension.unload();
});
-
-add_task(async function testUnimplementedDataType() {
- function background() {
- browser.browsingData.remove({}, {indexedDB: true});
- browser.test.sendMessage("finished");
- }
-
- let {messages} = await promiseConsoleOutput(async function() {
- let extension = ExtensionTestUtils.loadExtension({
- background: background,
- manifest: {
- permissions: ["browsingData"],
- },
- });
-
- await extension.startup();
- await extension.awaitMessage("finished");
- await extension.unload();
- });
-
- let warningObserved = messages.find(line => /Firefox does not support dataTypes: indexedDB/.test(line));
- ok(warningObserved, "Warning issued when calling remove with an unimplemented dataType.");
-});
diff --git a/browser/components/preferences/SiteDataManager.jsm b/browser/components/preferences/SiteDataManager.jsm
index d6dd5c78656a..8f2ac2a34188 100644
--- a/browser/components/preferences/SiteDataManager.jsm
+++ b/browser/components/preferences/SiteDataManager.jsm
@@ -9,6 +9,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "OfflineAppCacheHelper",
"resource:///modules/offlineAppCache.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
"resource://gre/modules/ContextualIdentityService.jsm");
+XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
+ "@mozilla.org/serviceworkers/manager;1",
+ "nsIServiceWorkerManager");
this.EXPORTED_SYMBOLS = [
"SiteDataManager"
@@ -217,6 +220,19 @@ this.SiteDataManager = {
}
},
+ _removeServiceWorkers(site) {
+ let serviceWorkers = serviceWorkerManager.getAllRegistrations();
+ for (let i = 0; i < serviceWorkers.length; i++) {
+ let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
+ for (let principal of site.principals) {
+ if (sw.principal.equals(principal)) {
+ serviceWorkerManager.removeAndPropagate(sw.principal.URI.host);
+ break;
+ }
+ }
+ }
+ },
+
remove(hosts) {
let promises = [];
let unknownHost = "";
@@ -226,6 +242,7 @@ this.SiteDataManager = {
this._removePermission(site);
this._removeAppCache(site);
this._removeCookie(site);
+ this._removeServiceWorkers(site);
promises.push(this._removeQuotaUsage(site));
} else {
unknownHost = host;
@@ -244,6 +261,15 @@ this.SiteDataManager = {
Services.cache2.clear();
Services.cookies.removeAll();
OfflineAppCacheHelper.clear();
+
+ // Iterate through the service workers and remove them.
+ let serviceWorkers = serviceWorkerManager.getAllRegistrations();
+ for (let i = 0; i < serviceWorkers.length; i++) {
+ let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
+ let host = sw.principal.URI.host;
+ serviceWorkerManager.removeAndPropagate(host);
+ }
+
// Refresh sites using quota usage again.
// This is for the case:
// 1. User goes to the about:preferences Site Data section.
diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js
index f0edd6df662e..b58389d026c8 100644
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -1647,6 +1647,13 @@ var gPrivacyPane = {
},
updateA11yPrefs(checked) {
- Services.prefs.setIntPref("accessibility.force_disabled", checked ? 1 : 0);
+ let buttonIndex = confirmRestartPrompt(checked, 0, true, false);
+ if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
+ Services.prefs.setIntPref("accessibility.force_disabled", checked ? 1 : 0);
+ Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
+ }
+
+ // Revert the checkbox in case we didn't quit
+ document.getElementById("a11yPrivacyCheckbox").checked = !checked;
}
};
diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
index ae397f77fd12..c336d1abdd7d 100755
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -702,11 +702,17 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
host_or_target)
# Check that the additional flags we got are enough to not require any
- # more flags.
- if info.flags:
- flags += info.flags
- info = check_compiler(wrapper + [compiler] + flags, language,
- host_or_target)
+ # more flags. If we get an exception, just ignore it; it's liable to be
+ # invalid command-line flags, which means the compiler we're checking
+ # doesn't support those command-line flags and will fail one or more of
+ # the checks below.
+ try:
+ if info.flags:
+ flags += info.flags
+ info = check_compiler(wrapper + [compiler] + flags, language,
+ host_or_target)
+ except FatalCheckError:
+ pass
if not info.target_cpu or info.target_cpu != host_or_target.cpu:
raise FatalCheckError(
@@ -732,10 +738,6 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
info.target_endianness or 'unknown', host_or_target_str,
host_or_target.endianness))
- if info.flags:
- raise FatalCheckError(
- 'Unknown compiler or compiler not supported.')
-
# Compiler version checks
# ===================================================
# Check the compiler version here instead of in `compiler_version` so
@@ -747,7 +749,7 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
% info.version)
# If you want to bump the version check here search for
- # __cpp_static_assert above, and see the associated comment.
+ # cxx_alignof above, and see the associated comment.
if info.type == 'clang' and not info.version:
raise FatalCheckError(
'Only clang/llvm 3.6 or newer is supported.')
@@ -762,6 +764,10 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
'See https://developer.mozilla.org/en/'
'Windows_Build_Prerequisites' % info.version)
+ if info.flags:
+ raise FatalCheckError(
+ 'Unknown compiler or compiler not supported.')
+
return namespace(
wrapper=wrapper,
compiler=compiler,
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 6748a2722e5a..d566bdde944d 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1609,7 +1609,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
flags,
target,
nullptr, // No type hint
- NullString(), // No forced download
+ VoidString(), // No forced download
postStream,
headersStream,
loadType,
@@ -5488,8 +5488,8 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
mozilla::net::RP_Unset,
nsContentUtils::GetSystemPrincipal(), nullptr,
INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
- nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
- nullptr, true, NullString(), this, nullptr, false,
+ nullptr, VoidString(), nullptr, nullptr, LOAD_ERROR_PAGE,
+ nullptr, true, VoidString(), this, nullptr, false,
nullptr, nullptr);
}
@@ -5589,7 +5589,7 @@ nsDocShell::Reload(uint32_t aReloadFlags)
flags,
EmptyString(), // No window target
NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
- NullString(), // No forced download
+ VoidString(), // No forced download
nullptr, // No post data
nullptr, // No headers data
loadType, // Load type
@@ -9757,7 +9757,7 @@ public:
mFlags, EmptyString(),
mTypeHint.IsVoid() ? nullptr
: mTypeHint.get(),
- NullString(), mPostData, mHeadersData,
+ VoidString(), mPostData, mHeadersData,
mLoadType, mSHEntry, mFirstParty,
mSrcdoc, mSourceDocShell, mBaseURI,
mCheckForPrerender, nullptr, nullptr);
@@ -10226,7 +10226,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
aFlags,
EmptyString(), // No window target
aTypeHint,
- NullString(), // No forced download
+ VoidString(), // No forced download
aPostData,
aHeadersData,
aLoadType,
@@ -10837,7 +10837,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
if (aFlags & INTERNAL_LOAD_FLAGS_IS_SRCDOC) {
srcdoc = aSrcdoc;
} else {
- srcdoc = NullString();
+ srcdoc = VoidString();
}
bool isTopLevelDoc = mItemType == typeContent &&
@@ -12860,7 +12860,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
aEntry->GetBaseURI(getter_AddRefs(baseURI));
flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
} else {
- srcdoc = NullString();
+ srcdoc = VoidString();
}
if (!triggeringPrincipal) {
@@ -12884,7 +12884,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
flags,
EmptyString(), // No window target
contentType.get(), // Type hint
- NullString(), // No forced file download
+ VoidString(), // No forced file download
postData, // Post data stream
nullptr, // No headers stream
aLoadType, // Load type
@@ -14454,7 +14454,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
LOAD_LINK, // Load type
nullptr, // No SHEntry
true, // first party site
- NullString(), // No srcdoc
+ VoidString(), // No srcdoc
this, // We are the source
nullptr, // baseURI not needed
true, // Check for prerendered doc
diff --git a/docshell/shistory/nsSHEntry.cpp b/docshell/shistory/nsSHEntry.cpp
index 2ada9d07261a..5bae3bb3feab 100644
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -476,7 +476,7 @@ nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
mShared->mExpired = false;
mIsSrcdocEntry = false;
- mSrcdocData = NullString();
+ mSrcdocData = VoidString();
mLoadedInThisProcess = true;
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
index e5b8520fff16..5299d500cb1a 100644
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -593,6 +593,9 @@ CustomElementRegistry::Define(const nsAString& aName,
}
JSContext *cx = jsapi.cx();
+ // Note: No calls that might run JS or trigger CC before this point, or
+ // there's a (vanishingly small) chance of our constructor being nulled
+ // before we access it.
JS::Rooted constructor(cx, aFunctionConstructor.CallableOrNull());
/**
@@ -878,7 +881,7 @@ CustomElementRegistry::Get(JSContext* aCx, const nsAString& aName,
return;
}
- aRetVal.setObjectOrNull(data->mConstructor->CallableOrNull());
+ aRetVal.setObject(*data->mConstructor->Callback(aCx));
}
already_AddRefed
@@ -970,9 +973,9 @@ CustomElementRegistry::Upgrade(Element* aElement,
LifecycleCallbackArgs args = {
nsDependentAtomString(attrName),
- NullString(),
- (attrValue.IsEmpty() ? NullString() : attrValue),
- (namespaceURI.IsEmpty() ? NullString() : namespaceURI)
+ VoidString(),
+ (attrValue.IsEmpty() ? VoidString() : attrValue),
+ (namespaceURI.IsEmpty() ? VoidString() : namespaceURI)
};
EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, aElement,
&args, aDefinition);
diff --git a/dom/base/DOMImplementation.cpp b/dom/base/DOMImplementation.cpp
index 65fd8a5cbdda..24fe7ca3798c 100644
--- a/dom/base/DOMImplementation.cpp
+++ b/dom/base/DOMImplementation.cpp
@@ -70,7 +70,7 @@ DOMImplementation::CreateDocumentType(const nsAString& aQualifiedName,
// Indicate that there is no internal subset (not just an empty one)
RefPtr docType =
NS_NewDOMDocumentType(mOwner->NodeInfoManager(), name, aPublicId,
- aSystemId, NullString(), aRv);
+ aSystemId, VoidString(), aRv);
return docType.forget();
}
@@ -188,7 +188,7 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
nsGkAtoms::html, // aName
EmptyString(), // aPublicId
EmptyString(), // aSystemId
- NullString()); // aInternalSubset
+ VoidString()); // aInternalSubset
NS_ENSURE_SUCCESS(rv, rv);
@@ -249,8 +249,7 @@ DOMImplementation::CreateHTMLDocument(const Optional& aTitle,
{
nsCOMPtr document;
nsCOMPtr domDocument;
- aRv = CreateHTMLDocument(aTitle.WasPassed() ? aTitle.Value()
- : NullString(),
+ aRv = CreateHTMLDocument(aTitle.WasPassed() ? aTitle.Value() : VoidString(),
getter_AddRefs(document),
getter_AddRefs(domDocument));
return document.forget();
diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp
index 606a1de5ed8c..1ca909e3cfbf 100644
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -308,7 +308,11 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
}
root = rootFrame->GetContent()->AsElement();
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
- rootRect = scrollFrame->GetScrollPortRect();
+ // If we end up with a null root frame for some reason, we'll proceed
+ // with an empty root intersection rect.
+ if (scrollFrame) {
+ rootRect = scrollFrame->GetScrollPortRect();
+ }
}
}
}
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index fe666c633009..fa2221077767 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -2642,9 +2642,9 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
LifecycleCallbackArgs args = {
nsDependentAtomString(aName),
aModType == nsIDOMMutationEvent::ADDITION ?
- NullString() : nsDependentAtomString(oldValueAtom),
+ VoidString() : nsDependentAtomString(oldValueAtom),
nsDependentAtomString(newValueAtom),
- (ns.IsEmpty() ? NullString() : ns)
+ (ns.IsEmpty() ? VoidString() : ns)
};
nsContentUtils::EnqueueLifecycleCallback(
@@ -2938,8 +2938,8 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
LifecycleCallbackArgs args = {
nsDependentAtomString(aName),
nsDependentAtomString(oldValueAtom),
- NullString(),
- (ns.IsEmpty() ? NullString() : ns)
+ VoidString(),
+ (ns.IsEmpty() ? VoidString() : ns)
};
nsContentUtils::EnqueueLifecycleCallback(
diff --git a/dom/base/nsDOMMutationObserver.h b/dom/base/nsDOMMutationObserver.h
index 98fdffc2ba9b..d386b6466e34 100644
--- a/dom/base/nsDOMMutationObserver.h
+++ b/dom/base/nsDOMMutationObserver.h
@@ -39,7 +39,7 @@ public:
typedef nsTArray> AnimationArray;
nsDOMMutationRecord(nsIAtom* aType, nsISupports* aOwner)
- : mType(aType), mAttrNamespace(NullString()), mPrevValue(NullString()), mOwner(aOwner)
+ : mType(aType), mAttrNamespace(VoidString()), mPrevValue(VoidString()), mOwner(aOwner)
{
}
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 55198595d0ec..335f0b305dc6 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3584,7 +3584,7 @@ nsIDocument::GetSrcdocData(nsAString &aSrcdocData)
return inStrmChan->GetSrcdocData(aSrcdocData);
}
}
- aSrcdocData = NullString();
+ aSrcdocData = VoidString();
return NS_OK;
}
@@ -6549,6 +6549,9 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
options.mExtends.Construct(lcName);
}
+ // Note: No calls that might run JS or trigger CC after this, or there's a
+ // (vanishingly small) risk of our constructor being nulled before Define()
+ // can access it.
RefPtr functionConstructor =
new Function(aCx, wrappedConstructor, sgo);
@@ -9793,7 +9796,7 @@ nsDocument::PreloadPictureImageSource(const nsAString& aSrcsetAttr,
//