Merge inbound to central, a=merge

MozReview-Commit-ID: Fq7B78wD7Wv
This commit is contained in:
Wes Kocher 2017-03-17 11:03:59 -07:00
commit ee28f4ee71
263 changed files with 3347 additions and 1362 deletions

View File

@ -7,6 +7,7 @@ module.exports = {
],
"rules": {
"mozilla/avoid-removeChild": "error",
"mozilla/avoid-nsISupportsString-preferences": "error",
"mozilla/import-globals": "warn",
"mozilla/no-import-into-var-and-global": "error",
"mozilla/no-useless-parameters": "error",

View File

@ -12,29 +12,20 @@ function init(aEvent) {
if (aEvent.target != document)
return;
try {
var distroId = Services.prefs.getCharPref("distribution.id");
if (distroId) {
var distroVersion = Services.prefs.getCharPref("distribution.version");
var distroId = Services.prefs.getCharPref("distribution.id", "");
if (distroId) {
var distroVersion = Services.prefs.getCharPref("distribution.version");
var distroIdField = document.getElementById("distributionId");
distroIdField.value = distroId + " - " + distroVersion;
distroIdField.style.display = "block";
var distroIdField = document.getElementById("distributionId");
distroIdField.value = distroId + " - " + distroVersion;
distroIdField.style.display = "block";
try {
// This is in its own try catch due to bug 895473 and bug 900925.
var distroAbout = Services.prefs.getComplexValue("distribution.about",
Components.interfaces.nsISupportsString);
var distroField = document.getElementById("distribution");
distroField.value = distroAbout;
distroField.style.display = "block";
} catch (ex) {
// Pref is unset
Components.utils.reportError(ex);
}
var distroAbout = Services.prefs.getStringPref("distribution.about", "");
if (distroAbout) {
var distroField = document.getElementById("distribution");
distroField.value = distroAbout;
distroField.style.display = "block";
}
} catch (e) {
// Pref is unset
}
// Include the build ID and display warning if this is an "a#" (nightly or aurora) build

View File

@ -30,17 +30,14 @@ function log(msg) {
function getPreviousAccountNameHash() {
try {
return Services.prefs.getComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString).data;
return Services.prefs.getStringPref(PREF_LAST_FXA_USER);
} catch (_) {
return "";
}
}
function setPreviousAccountNameHash(acctName) {
let string = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
string.data = sha256(acctName);
Services.prefs.setComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString, string);
Services.prefs.setStringPref(PREF_LAST_FXA_USER, sha256(acctName));
}
function needRelinkWarning(acctName) {

View File

@ -335,10 +335,7 @@ var FeedHandler = {
Services.prefs.setCharPref(msg.data.pref, msg.data.value);
break;
case "FeedWriter:SetFeedComplexString": {
let supportsString = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
supportsString.data = msg.data.value;
Services.prefs.setComplexValue(msg.data.pref, Ci.nsISupportsString, supportsString);
Services.prefs.setStringPref(msg.data.pref, msg.data.value);
break;
}
case "FeedConverter:ExecuteClientApp":

View File

@ -3611,11 +3611,7 @@ function openHomeDialog(aURL) {
if (pressedVal == 0) {
try {
var homepageStr = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
homepageStr.data = aURL;
gPrefService.setComplexValue("browser.startup.homepage",
Components.interfaces.nsISupportsString, homepageStr);
gPrefService.setStringPref("browser.startup.homepage", aURL);
} catch (ex) {
dump("Failed to set the home page.\n" + ex + "\n");
}
@ -4478,7 +4474,7 @@ var XULBrowserWindow = {
},
// Check whether this URI should load in the current process
shouldLoadURI(aDocShell, aURI, aReferrer, aTriggeringPrincipal) {
shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal) {
if (!gMultiProcessBrowser)
return true;
@ -4491,7 +4487,10 @@ var XULBrowserWindow = {
if (browser.localName != "browser" || !browser.getTabBrowser || browser.getTabBrowser() != gBrowser)
return true;
if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer)) {
if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData)) {
// XXX: Do we want to complain if we have post data but are still
// redirecting the load? Perhaps a telemetry probe? Theoretically we
// shouldn't do this, as it throws out data. See bug 1348018.
E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false);
return false;
}

View File

@ -17,7 +17,6 @@ support-files =
browser_tab_dragdrop2_frame1.xul
browser_web_channel.html
browser_web_channel_iframe.html
bug1262648_string_with_newlines.dtd
bug592338.html
bug792517-2.html
bug792517.html
@ -51,7 +50,6 @@ support-files =
offlineQuotaNotification.cacheManifest
offlineQuotaNotification.html
page_style_sample.html
parsingTestHelpers.jsm
pinning_headers.sjs
ssl_error_reports.sjs
popup_blocker.html
@ -267,7 +265,6 @@ skip-if = os != "win" # The Fitts Law menu button is only supported on Windows (
[browser_middleMouse_noJSPaste.js]
subsuite = clipboard
[browser_minimize.js]
[browser_misused_characters_in_strings.js]
[browser_modifiedclick_inherit_principal.js]
[browser_new_http_window_opened_from_file_tab.js]
[browser_offlineQuotaNotification.js]
@ -279,10 +276,6 @@ support-files = test_offline_gzip.html gZipOfflineChild.cacheManifest gZipOfflin
[browser_overflowScroll.js]
[browser_page_style_menu.js]
[browser_page_style_menu_update.js]
[browser_parsable_css.js]
skip-if = debug # no point in running on both opt and debug, and will likely intermittently timeout on debug
[browser_parsable_script.js]
skip-if = asan || (os == 'linux' && !debug && (bits == 32)) # disabled on asan because of timeouts, and bug 1172468 for the linux 32-bit pgo issue.
[browser_permissions.js]
support-files =
permissions.html

View File

@ -35,13 +35,11 @@ add_task(function*() {
observe(subject, topic, data) {
is(topic, "nsPref:changed", "observed correct topic");
is(data, HOMEPAGE_PREF, "observed correct data");
let modified = Services.prefs.getComplexValue(HOMEPAGE_PREF,
Ci.nsISupportsString);
is(modified.data, homepage, "homepage is set correctly");
let modified = Services.prefs.getStringPref(HOMEPAGE_PREF);
is(modified, homepage, "homepage is set correctly");
Services.prefs.removeObserver(HOMEPAGE_PREF, observer);
Services.prefs.setComplexValue(HOMEPAGE_PREF,
Ci.nsISupportsString, homepageStr);
Services.prefs.setStringPref(HOMEPAGE_PREF, "about:mozilla;");
resolve();
}
@ -87,4 +85,3 @@ add_task(function*() {
"http://mochi.test:8888/|http://mochi.test:8888/b|http://mochi.test:8888/c");
yield dropInvalidURI();
});

View File

@ -253,11 +253,7 @@ function setPinnedLinks(aLinks) {
});
}
let string = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(links);
Services.prefs.setComplexValue("browser.newtabpage.pinned",
Ci.nsISupportsString, string);
Services.prefs.setStringPref("browser.newtabpage.pinned", JSON.stringify(links));
NewTabUtils.pinnedLinks.resetCache();
NewTabUtils.allPages.update();

View File

@ -203,10 +203,7 @@ function checkSocialUI(win) {
}
function setManifestPref(name, manifest) {
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(manifest);
Services.prefs.setComplexValue(name, Ci.nsISupportsString, string);
Services.prefs.setStringPref(name, JSON.stringify(manifest));
}
function getManifestPrefname(aManifest) {

View File

@ -0,0 +1,13 @@
[DEFAULT]
support-files =
head.js
[browser_misused_characters_in_strings.js]
support-files =
bug1262648_string_with_newlines.dtd
[browser_parsable_css.js]
support-files =
dummy_page.html
skip-if = debug # no point in running on both opt and debug, and will likely intermittently timeout on debug
[browser_parsable_script.js]
skip-if = asan || (os == 'linux' && !debug && (bits == 32)) # disabled on asan because of timeouts, and bug 1172468 for the linux 32-bit pgo issue.

View File

@ -107,9 +107,6 @@ let gWhitelist = [{
}
];
var moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
var {generateURIsFromDirTree} = Cu.import(moduleLocation, {});
/**
* Check if an error should be ignored due to matching one of the whitelist
* objects defined in gWhitelist.
@ -135,6 +132,7 @@ function ignoredError(filepath, key, type) {
function fetchFile(uri) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.responseType = "text";
xhr.open("GET", uri, true);
xhr.onreadystatechange = function() {
if (this.readyState != this.DONE) {

View File

@ -67,9 +67,6 @@ let allowedImageReferences = [
isFromDevTools: true},
];
var moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
var {generateURIsFromDirTree} = Cu.import(moduleLocation, {});
// Add suffix to stylesheets' URI so that we always load them here and
// have them parsed. Add a random number so that even if we run this
// test multiple times, it would be unlikely to affect each other.
@ -300,25 +297,25 @@ add_task(function* checkAllTheCSS() {
for (let uri of uris) {
let linkEl = doc.createElement("link");
linkEl.setAttribute("rel", "stylesheet");
let promiseForThisSpec = Promise.defer();
let onLoad = (e) => {
processCSSRules(linkEl.sheet);
promiseForThisSpec.resolve();
linkEl.removeEventListener("load", onLoad);
linkEl.removeEventListener("error", onError);
};
let onError = (e) => {
ok(false, "Loading " + linkEl.getAttribute("href") + " threw an error!");
promiseForThisSpec.resolve();
linkEl.removeEventListener("load", onLoad);
linkEl.removeEventListener("error", onError);
};
linkEl.addEventListener("load", onLoad);
linkEl.addEventListener("error", onError);
linkEl.setAttribute("type", "text/css");
let chromeUri = convertToChromeUri(uri);
linkEl.setAttribute("href", chromeUri.spec + kPathSuffix);
allPromises.push(promiseForThisSpec.promise);
allPromises.push(new Promise(resolve => {
let onLoad = (e) => {
processCSSRules(linkEl.sheet);
resolve();
linkEl.removeEventListener("load", onLoad);
linkEl.removeEventListener("error", onError);
};
let onError = (e) => {
ok(false, "Loading " + linkEl.getAttribute("href") + " threw an error!");
resolve();
linkEl.removeEventListener("load", onLoad);
linkEl.removeEventListener("error", onError);
};
linkEl.addEventListener("load", onLoad);
linkEl.addEventListener("error", onError);
linkEl.setAttribute("type", "text/css");
let chromeUri = convertToChromeUri(uri);
linkEl.setAttribute("href", chromeUri.spec + kPathSuffix);
}));
doc.head.appendChild(linkEl);
}

View File

@ -10,10 +10,6 @@ const kWhitelist = new Set([
/browser\/content\/browser\/places\/controller.js$/,
]);
var moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
var {generateURIsFromDirTree} = Cu.import(moduleLocation, {});
// Normally we would use reflect.jsm to get Reflect.parse. However, if
// we do that, then all the AST data is allocated in reflect.jsm's
// zone. That exposes a bug in our GC. The GC collects reflect.jsm's
@ -50,7 +46,7 @@ function parsePromise(uri) {
let scriptText = this.responseText;
try {
info("Checking " + uri);
Reflect.parse(scriptText);
Reflect.parse(scriptText, {source: uri});
resolve(true);
} catch (ex) {
let errorMsg = "Script error reading " + uri + ": " + ex;
@ -95,7 +91,7 @@ add_task(function* checkAllTheJS() {
if (parseValue && parseValue.includes(":")) {
uris = [NetUtil.newURI(parseValue)];
} else {
let appDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
let appDir = Services.dirsvc.get("GreD", Ci.nsIFile);
// This asynchronously produces a list of URLs (sadly, mostly sync on our
// test infrastructure because it runs against jarfiles there, and
// our zipreader APIs are all sync)

View File

@ -0,0 +1,9 @@
<html>
<head>
<title>Dummy test page</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
</head>
<body>
<p>Dummy test page</p>
</body>
</html>

View File

@ -3,8 +3,6 @@
"use strict";
this.EXPORTED_SYMBOLS = ["generateURIsFromDirTree"];
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
/* Shorthand constructors to construct an nsI(Local)File and zip reader: */
@ -127,5 +125,3 @@ function* generateEntriesFromJarFile(jarFile, extension) {
}
zr.close();
}

View File

@ -26,6 +26,7 @@ BROWSER_CHROME_MANIFESTS += [
'content/test/referrer/browser.ini',
'content/test/siteIdentity/browser.ini',
'content/test/social/browser.ini',
'content/test/static/browser.ini',
'content/test/tabcrashed/browser.ini',
'content/test/tabPrompts/browser.ini',
'content/test/tabs/browser.ini',

View File

@ -1076,10 +1076,7 @@ const CustomizableWidgets = [
} else {
// Set the detector pref.
try {
let str = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
str.data = value;
Services.prefs.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
Services.prefs.setStringPref("intl.charset.detector", value);
} catch (e) {
Cu.reportError("Failed to set the intl.charset.detector preference.");
}

View File

@ -1368,8 +1368,7 @@ CustomizeMode.prototype = {
}
let lwthemePrefs = Services.prefs.getBranch("lightweightThemes.");
let recommendedThemes = lwthemePrefs.getComplexValue("recommendedThemes",
Ci.nsISupportsString).data;
let recommendedThemes = lwthemePrefs.getStringPref("recommendedThemes");
recommendedThemes = JSON.parse(recommendedThemes);
let sb = Services.strings.createBundle("chrome://browser/locale/lightweightThemes.properties");
for (let theme of recommendedThemes) {
@ -1379,11 +1378,8 @@ CustomizeMode.prototype = {
button.addEventListener("command", () => {
LightweightThemeManager.setLocalTheme(button.theme);
recommendedThemes = recommendedThemes.filter((aTheme) => { return aTheme.id != button.theme.id; });
let string = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(recommendedThemes);
lwthemePrefs.setComplexValue("recommendedThemes",
Ci.nsISupportsString, string);
lwthemePrefs.setStringPref("recommendedThemes",
JSON.stringify(recommendedThemes));
onThemeSelected(panel);
});
panel.insertBefore(button, footer);

View File

@ -700,7 +700,7 @@ FeedWriter.prototype = {
if (this._handlersList) {
let url;
try {
url = prefs.getComplexValue(getPrefWebForType(feedType), Ci.nsISupportsString).data;
url = prefs.getStringPref(getPrefWebForType(feedType));
} catch (ex) {
LOG("FeedWriter._setSelectedHandler: invalid or no handler in prefs");
return;

View File

@ -696,12 +696,7 @@ WebContentConverterRegistrar.prototype = {
let pb = Services.prefs.getBranch(null);
pb.setCharPref(PREF_SELECTED_READER, "web");
let supportsString =
Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
supportsString.data = uri;
pb.setComplexValue(PREF_SELECTED_WEB, Ci.nsISupportsString,
supportsString);
pb.setStringPref(PREF_SELECTED_WEB, uri);
pb.setCharPref(PREF_SELECTED_ACTION, "ask");
this._setAutoHandler(TYPE_MAYBE_FEED, null);
}

View File

@ -426,12 +426,8 @@ var MigrationWizard = { /* exported MigrationWizard */
if (this._newHomePage == "DEFAULT") {
prefBranch.clearUserPref("browser.startup.homepage");
} else {
var str = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
str.data = this._newHomePage;
prefBranch.setComplexValue("browser.startup.homepage",
Components.interfaces.nsISupportsString,
str);
prefBranch.setStringPref("browser.startup.homepage",
this._newHomePage);
}
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]

View File

@ -1838,19 +1838,16 @@ BrowserGlue.prototype = {
const DEFAULT =
Services.prefs.getDefaultBranch(HOMEPAGE_PREF)
.getComplexValue("", Ci.nsIPrefLocalizedString).data;
let value =
Services.prefs.getComplexValue(HOMEPAGE_PREF, Ci.nsISupportsString);
let value = Services.prefs.getStringPref(HOMEPAGE_PREF);
let updated =
value.data.replace(/https?:\/\/start\.mozilla\.org[^|]*/i, DEFAULT)
.replace(/https?:\/\/(www\.)?google\.[a-z.]+\/firefox[^|]*/i,
DEFAULT);
if (updated != value.data) {
value.replace(/https?:\/\/start\.mozilla\.org[^|]*/i, DEFAULT)
.replace(/https?:\/\/(www\.)?google\.[a-z.]+\/firefox[^|]*/i,
DEFAULT);
if (updated != value) {
if (updated == DEFAULT) {
Services.prefs.clearUserPref(HOMEPAGE_PREF);
} else {
value.data = updated;
Services.prefs.setComplexValue(HOMEPAGE_PREF,
Ci.nsISupportsString, value);
Services.prefs.setStringPref(HOMEPAGE_PREF, updated);
}
}
}

View File

@ -97,7 +97,7 @@ add_task(function* () {
Assert.equal(defaultBranch.getCharPref("distribution.id"), "disttest");
Assert.equal(defaultBranch.getCharPref("distribution.version"), "1.0");
Assert.equal(defaultBranch.getComplexValue("distribution.about", Ci.nsISupportsString).data, "Tèƨƭ δïƨƭřïβúƭïôñ ƒïℓè");
Assert.equal(defaultBranch.getStringPref("distribution.about"), "Tèƨƭ δïƨƭřïβúƭïôñ ƒïℓè");
Assert.equal(defaultBranch.getCharPref("distribution.test.string"), "Test String");
Assert.equal(defaultBranch.getCharPref("distribution.test.string.noquotes"), "Test String");

View File

@ -583,10 +583,7 @@ this.UITour = {
case "setTreatmentTag": {
let name = data.name;
let value = data.value;
let string = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
string.data = value;
Services.prefs.setComplexValue("browser.uitour.treatment." + name,
Ci.nsISupportsString, string);
Services.prefs.setStringPref("browser.uitour.treatment." + name, value);
// The notification is only meant to be used in tests.
UITourHealthReport.recordTreatmentTag(name, value)
.then(() => this.notify("TreatmentTag:TelemetrySent"));
@ -597,8 +594,7 @@ this.UITour = {
let name = data.name;
let value;
try {
value = Services.prefs.getComplexValue("browser.uitour.treatment." + name,
Ci.nsISupportsString).data;
value = Services.prefs.getStringPref("browser.uitour.treatment." + name);
} catch (ex) {}
this.sendPageCallback(messageManager, data.callbackID, { value });
break;

View File

@ -93,7 +93,7 @@ function getIntPref(pref, def) {
function getStringPref(pref, def) {
try {
return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
return Services.prefs.getStringPref(pref);
} catch (ex) {
return def;
}

View File

@ -290,10 +290,7 @@ var PdfjsChromeUtils = {
_setStringPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
let str = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
str.data = aPrefValue;
Services.prefs.setComplexValue(aPrefName, Ci.nsISupportsString, str);
Services.prefs.setStringPref(aPrefName, aPrefValue);
},
/*

View File

@ -146,10 +146,7 @@ function CreatePocketWidget(reason) {
if (provider) {
let pref = "social.backup.getpocket-com";
if (!Services.prefs.prefHasUserValue(pref)) {
let str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
str.data = JSON.stringify(provider.manifest);
Services.prefs.setComplexValue(pref, Ci.nsISupportsString, str);
Services.prefs.setStringPref(pref, JSON.stringify(provider.manifest));
SocialService.uninstallProvider(origin, () => {});
}
}

View File

@ -124,7 +124,7 @@ var pktApi = (function() {
if (!prefBranch.prefHasUserValue(key))
return undefined;
return prefBranch.getComplexValue(key, Components.interfaces.nsISupportsString).data;
return prefBranch.getStringPref(key);
}
/**
@ -142,9 +142,7 @@ var pktApi = (function() {
prefBranch.clearUserPref(key);
else {
// We use complexValue as tags can have utf-8 characters in them
var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
str.data = value;
prefBranch.setComplexValue(key, Components.interfaces.nsISupportsString, str);
prefBranch.setStringPref(key, value);
}
}

View File

@ -194,15 +194,17 @@ this.E10SUtils = {
return remoteType == this.getRemoteTypeForURIObject(aURI, true, remoteType);
},
shouldLoadURI(aDocShell, aURI, aReferrer) {
shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData) {
// Inner frames should always load in the current process
if (aDocShell.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeParent)
return true;
// If we are in a Large-Allocation process, and it wouldn't be content visible
// to change processes, we want to load into a new process so that we can throw
// this one out.
if (Services.appinfo.remoteType == LARGE_ALLOCATION_REMOTE_TYPE &&
// this one out. We don't want to move into a new process if we have post data,
// because we would accidentally throw out that data.
if (!aHasPostData &&
Services.appinfo.remoteType == LARGE_ALLOCATION_REMOTE_TYPE &&
!aDocShell.awaitingLargeAlloc &&
aDocShell.isOnlyToplevelInTabGroup) {
return false;

View File

@ -46,7 +46,7 @@ var SocialServiceInternal = {
if (!MANIFEST_PREFS.prefHasUserValue(pref))
continue;
try {
var manifest = JSON.parse(MANIFEST_PREFS.getComplexValue(pref, Ci.nsISupportsString).data);
var manifest = JSON.parse(MANIFEST_PREFS.getStringPref(pref));
if (manifest && typeof(manifest) == "object" && manifest.origin)
yield manifest;
} catch (err) {
@ -65,7 +65,7 @@ var SocialServiceInternal = {
let prefs = MANIFEST_PREFS.getChildList("", []);
for (let pref of prefs) {
try {
var manifest = JSON.parse(MANIFEST_PREFS.getComplexValue(pref, Ci.nsISupportsString).data);
var manifest = JSON.parse(MANIFEST_PREFS.getStringPref(pref));
if (manifest.origin == origin) {
return pref;
}
@ -170,8 +170,7 @@ var ActiveProviders = {
delete this._providers;
this._providers = {};
try {
let pref = Services.prefs.getComplexValue("social.activeProviders",
Ci.nsISupportsString);
let pref = Services.prefs.getStringPref("social.activeProviders");
this._providers = JSON.parse(pref);
} catch (ex) {}
return this._providers;
@ -202,11 +201,8 @@ var ActiveProviders = {
},
_persist() {
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(this._providers);
Services.prefs.setComplexValue("social.activeProviders",
Ci.nsISupportsString, string);
Services.prefs.setStringPref("social.activeProviders",
JSON.stringify(this._providers));
}
};
@ -224,7 +220,7 @@ function migrateSettings() {
let defaultManifest;
try {
prefname = getPrefnameFromOrigin(origin);
manifest = JSON.parse(Services.prefs.getComplexValue(prefname, Ci.nsISupportsString).data);
manifest = JSON.parse(Services.prefs.getStringPref(prefname));
} catch (e) {
// Our preference is missing or bad, remove from ActiveProviders and
// continue. This is primarily an error-case and should only be
@ -237,8 +233,7 @@ function migrateSettings() {
let needsUpdate = !manifest.updateDate;
// fx23 may have built-ins with shareURL
try {
defaultManifest = Services.prefs.getDefaultBranch(null)
.getComplexValue(prefname, Ci.nsISupportsString).data;
defaultManifest = Services.prefs.getDefaultBranch(null).getStringPref(prefname);
defaultManifest = JSON.parse(defaultManifest);
} catch (e) {
// not a built-in, continue
@ -262,10 +257,7 @@ function migrateSettings() {
if (!manifest.installDate)
manifest.installDate = 0; // we don't know when it was installed
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(manifest);
Services.prefs.setComplexValue(prefname, Ci.nsISupportsString, string);
Services.prefs.setStringPref(prefname, JSON.stringify(manifest));
}
// as of fx 29, we no longer rely on social.enabled. migration from prior
// versions should disable all service addons if social.enabled=false
@ -291,7 +283,7 @@ function migrateSettings() {
try {
let manifest;
try {
manifest = JSON.parse(manifestPrefs.getComplexValue(pref, Ci.nsISupportsString).data);
manifest = JSON.parse(manifestPrefs.getStringPref(pref));
} catch (e) {
// bad or missing preference, we wont update this one.
continue;
@ -305,10 +297,9 @@ function migrateSettings() {
manifest.installDate = 0; // we don't know when it was installed
}
let string = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(manifest);
// pref here is just the branch name, set the full pref name
Services.prefs.setComplexValue("social.manifest." + pref, Ci.nsISupportsString, string);
Services.prefs.setStringPref("social.manifest." + pref,
JSON.stringify(manifest));
ActiveProviders.add(manifest.origin);
ActiveProviders.flush();
// social.active was used at a time that there was only one
@ -642,10 +633,8 @@ this.SocialService = {
throw new Error("SocialService.installProvider: service configuration is invalid from " + aUpdateOrigin);
// overwrite the preference
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(manifest);
Services.prefs.setComplexValue(getPrefnameFromOrigin(manifest.origin), Ci.nsISupportsString, string);
Services.prefs.setStringPref(getPrefnameFromOrigin(manifest.origin),
JSON.stringify(manifest));
// overwrite the existing provider then notify the front end so it can
// handle any reload that might be necessary.
@ -829,10 +818,8 @@ function AddonInstaller(sourceURI, aManifest, installCallback) {
AddonManagerPrivate.callAddonListeners("onInstalling", addon, false);
}
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(aManifest);
Services.prefs.setComplexValue(getPrefnameFromOrigin(aManifest.origin), Ci.nsISupportsString, string);
Services.prefs.setStringPref(getPrefnameFromOrigin(aManifest.origin),
JSON.stringify(aManifest));
if (isNewInstall) {
AddonManagerPrivate.callAddonListeners("onInstalled", addon);

View File

@ -57,10 +57,8 @@ function initApp() {
}
function setManifestPref(manifest) {
let string = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
string.data = JSON.stringify(manifest);
Services.prefs.setComplexValue("social.manifest." + manifest.origin, Ci.nsISupportsString, string);
Services.prefs.setStringPref("social.manifest." + manifest.origin,
JSON.stringify(manifest));
}
function do_wait_observer(obsTopic, cb) {
@ -91,14 +89,11 @@ function do_initialize_social(enabledOnStartup, cb) {
setManifestPref(manifest);
});
// Set both providers active and flag the first one as "current"
let activeVal = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
let active = {};
for (let m of manifests)
active[m.origin] = 1;
activeVal.data = JSON.stringify(active);
Services.prefs.setComplexValue("social.activeProviders",
Ci.nsISupportsString, activeVal);
Services.prefs.setStringPref("social.activeProviders",
JSON.stringify(active));
do_register_cleanup(function() {
manifests.forEach(function(manifest) {

View File

@ -39,10 +39,8 @@ function* testMigration(manifest, next) {
do_check_true(SocialService.enabled);
do_check_true(Services.prefs.prefHasUserValue("social.activeProviders"));
let activeProviders;
let pref = Services.prefs.getComplexValue("social.activeProviders",
Ci.nsISupportsString);
activeProviders = JSON.parse(pref);
let activeProviders =
JSON.parse(Services.prefs.getStringPref("social.activeProviders"));
do_check_true(activeProviders[manifest.origin]);
do_check_true(MANIFEST_PREFS.prefHasUserValue(manifest.origin));
do_check_true(JSON.parse(DEFAULT_PREFS.getCharPref(manifest.origin)).builtin);

View File

@ -22,15 +22,12 @@ function run_test() {
DEFAULT_PREFS.setCharPref(manifest.origin, JSON.stringify(manifest));
// Set both providers active and flag the first one as "current"
let activeVal = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
let active = {};
active[manifest.origin] = 1;
// bad.origin tests that a missing manifest does not break migration, bug 859715
active["bad.origin"] = 1;
activeVal.data = JSON.stringify(active);
Services.prefs.setComplexValue("social.activeProviders",
Ci.nsISupportsString, activeVal);
Services.prefs.setStringPref("social.activeProviders",
JSON.stringify(active));
Cu.import("resource:///modules/SocialService.jsm");
@ -49,10 +46,8 @@ function* testMigration(manifest, next) {
do_check_true(SocialService.enabled);
do_check_true(Services.prefs.prefHasUserValue("social.activeProviders"));
let activeProviders;
let pref = Services.prefs.getComplexValue("social.activeProviders",
Ci.nsISupportsString);
activeProviders = JSON.parse(pref);
let activeProviders =
JSON.parse(Services.prefs.getStringPref("social.activeProviders"));
do_check_true(activeProviders[manifest.origin]);
do_check_true(MANIFEST_PREFS.prefHasUserValue(manifest.origin));
do_check_true(JSON.parse(DEFAULT_PREFS.getCharPref(manifest.origin)).builtin);

View File

@ -20,13 +20,10 @@ function run_test() {
MANIFEST_PREFS.setCharPref(manifest.origin, JSON.stringify(manifest));
// Set both providers active and flag the first one as "current"
let activeVal = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
let active = {};
active[manifest.origin] = 1;
activeVal.data = JSON.stringify(active);
Services.prefs.setComplexValue("social.activeProviders",
Ci.nsISupportsString, activeVal);
Services.prefs.setStringPref("social.activeProviders",
JSON.stringify(active));
// social.enabled pref is the key focus of this test. We set the user pref,
// and then migration should a) remove the provider from activeProviders and
@ -53,8 +50,7 @@ function* testMigration(manifest, next) {
do_check_true(Services.prefs.prefHasUserValue("social.activeProviders"));
let activeProviders;
let pref = Services.prefs.getComplexValue("social.activeProviders",
Ci.nsISupportsString).data;
let pref = Services.prefs.getStringPref("social.activeProviders");
activeProviders = JSON.parse(pref);
do_check_true(activeProviders[manifest.origin] == undefined);
do_check_true(MANIFEST_PREFS.prefHasUserValue(manifest.origin));

View File

@ -30,6 +30,7 @@ public class AnnotationInfo {
public enum DispatchTarget {
GECKO,
GECKO_PRIORITY,
PROXY,
CURRENT;

View File

@ -20,8 +20,7 @@ function* spawnTest() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
let remoteHostOrig = prefBranch.getComplexValue("devtools.debugger.remote-host",
Ci.nsISupportsString).data;
let remoteHostOrig = prefBranch.getStringPref("devtools.debugger.remote-host");
info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
yield helpers.audit(options, [
@ -65,8 +64,7 @@ function* spawnTest() {
output: new RegExp("^devtools\.debugger\.remote-host: e.com$"),
},
post: function () {
var ecom = prefBranch.getComplexValue("devtools.debugger.remote-host",
Ci.nsISupportsString).data;
var ecom = prefBranch.getStringPref("devtools.debugger.remote-host");
is(ecom, "e.com", "devtools.debugger.remote-host is e.com");
}
},
@ -97,8 +95,7 @@ function* spawnTest() {
output: new RegExp("^devtools\.debugger\.remote-host: moz.foo$"),
},
post: function () {
var mozfoo = prefBranch.getComplexValue("devtools.debugger.remote-host",
Ci.nsISupportsString).data;
var mozfoo = prefBranch.getStringPref("devtools.debugger.remote-host");
is(mozfoo, "moz.foo", "devtools.debugger.remote-host is moz.foo");
}
},

View File

@ -35,9 +35,8 @@ function* spawnTest() {
let hideIntroOrig = prefBranch.getBoolPref("devtools.gcli.hideIntro");
let tabSizeOrig = prefBranch.getIntPref("devtools.editor.tabsize");
let remoteHostOrig = prefBranch.getComplexValue(
"devtools.debugger.remote-host",
Components.interfaces.nsISupportsString).data;
let remoteHostOrig = prefBranch.getStringPref(
"devtools.debugger.remote-host");
info("originally: devtools.gcli.hideIntro = " + hideIntroOrig);
info("originally: devtools.editor.tabsize = " + tabSizeOrig);

View File

@ -95,4 +95,4 @@ skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5
[browser_toolbox_zoom.js]
[browser_two_tabs.js]
# We want this test to run for mochitest-dt as well, so we include it here:
[../../../../browser/base/content/test/general/browser_parsable_css.js]
[../../../../browser/base/content/test/static/browser_parsable_css.js]

View File

@ -158,6 +158,7 @@ skip-if = (os == "win" && debug) # bug 963492: win.
[browser_rules_grid-toggle_01b.js]
[browser_rules_grid-toggle_02.js]
[browser_rules_grid-toggle_03.js]
[browser_rules_grid-toggle_04.js]
[browser_rules_guessIndentation.js]
[browser_rules_inherited-properties_01.js]
[browser_rules_inherited-properties_02.js]

View File

@ -0,0 +1,64 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test toggling the grid highlighter in the rule view from a 'display: grid !important'
// declaration.
const TEST_URI = `
<style type='text/css'>
#grid {
display: grid !important;
}
</style>
<div id="grid">
<div id="cell1">cell1</div>
<div id="cell2">cell2</div>
</div>
`;
const HIGHLIGHTER_TYPE = "CssGridHighlighter";
add_task(function* () {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
let highlighters = view.highlighters;
yield selectNode("#grid", inspector);
let container = getRuleViewProperty(view, "#grid", "display").valueSpan;
let gridToggle = container.querySelector(".ruleview-grid");
info("Checking the initial state of the CSS grid toggle in the rule-view.");
ok(gridToggle, "Grid highlighter toggle is visible.");
ok(!gridToggle.classList.contains("active"),
"Grid highlighter toggle button is not active.");
ok(!highlighters.highlighters[HIGHLIGHTER_TYPE],
"No CSS grid highlighter exists in the rule-view.");
ok(!highlighters.gridHighlighterShown, "No CSS grid highlighter is shown.");
info("Toggling ON the CSS grid highlighter from the rule-view.");
let onHighlighterShown = highlighters.once("grid-highlighter-shown");
gridToggle.click();
yield onHighlighterShown;
info("Checking the CSS grid highlighter is created and toggle button is active in " +
"the rule-view.");
ok(gridToggle.classList.contains("active"),
"Grid highlighter toggle is active.");
ok(highlighters.highlighters[HIGHLIGHTER_TYPE],
"CSS grid highlighter created in the rule-view.");
ok(highlighters.gridHighlighterShown, "CSS grid highlighter is shown.");
info("Toggling OFF the CSS grid highlighter from the rule-view.");
let onHighlighterHidden = highlighters.once("grid-highlighter-hidden");
gridToggle.click();
yield onHighlighterHidden;
info("Checking the CSS grid highlighter is not shown and toggle button is not active " +
"in the rule-view.");
ok(!gridToggle.classList.contains("active"),
"Grid highlighter toggle button is not active.");
ok(!highlighters.gridHighlighterShown, "No CSS grid highlighter is shown.");
});

View File

@ -1288,8 +1288,7 @@ var Scratchpad = {
// Unicode strings.
if (branch.prefHasUserValue("recentFilePaths")) {
let data = branch.getComplexValue("recentFilePaths",
Ci.nsISupportsString).data;
let data = branch.getStringPref("recentFilePaths");
filePaths = JSON.parse(data);
}
@ -1336,16 +1335,8 @@ var Scratchpad = {
filePaths.push(aFile.path);
// WARNING: Do not use setCharPref here, it doesn't play nicely with
// Unicode strings.
let str = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
str.data = JSON.stringify(filePaths);
let branch = Services.prefs.getBranch("devtools.scratchpad.");
branch.setComplexValue("recentFilePaths",
Ci.nsISupportsString, str);
Services.prefs.getBranch("devtools.scratchpad.")
.setStringPref("recentFilePaths", JSON.stringify(filePaths));
},
/**
@ -1412,16 +1403,8 @@ var Scratchpad = {
let filePaths = this.getRecentFiles();
filePaths.splice(aIndex, aLength);
// WARNING: Do not use setCharPref here, it doesn't play nicely with
// Unicode strings.
let str = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
str.data = JSON.stringify(filePaths);
let branch = Services.prefs.getBranch("devtools.scratchpad.");
branch.setComplexValue("recentFilePaths",
Ci.nsISupportsString, str);
Services.prefs.getBranch("devtools.scratchpad.")
.setStringPref("recentFilePaths", JSON.stringify(filePaths));
},
/**

View File

@ -81,6 +81,23 @@ function isRenderedTree(actual, expectedDescription, msg) {
is(actual, expected, msg);
}
function isAccessibleTree(tree, options = {}) {
const treeNode = tree.refs.tree;
is(treeNode.getAttribute("tabindex"), "0", "Tab index is set");
is(treeNode.getAttribute("role"), "tree", "Tree semantics is present");
if (options.hasActiveDescendant) {
ok(treeNode.hasAttribute("aria-activedescendant"),
"Tree has an active descendant set");
}
const treeNodes = [...treeNode.querySelectorAll(".tree-node")];
for (let node of treeNodes) {
ok(node.id, "TreeNode has an id");
is(node.getAttribute("role"), "treeitem", "Tree item semantics is present");
ok(node.hasAttribute("aria-level"), "Aria level attribute is set");
}
}
// Encoding of the following tree/forest:
//
// A

View File

@ -31,6 +31,7 @@ window.onload = Task.async(function* () {
const tree = ReactDOM.render(t, window.document.body);
ok(tree, "Should be able to mount Tree instances");
isAccessibleTree(tree);
TEST_TREE.expanded = new Set("ABCDEFGHIJKLMNO".split(""));
yield forceRender(tree);

View File

@ -24,6 +24,7 @@ window.onload = Task.async(function* () {
const tree = ReactDOM.render(Tree(TEST_TREE_INTERFACE), window.document.body);
isAccessibleTree(tree);
TEST_TREE.expanded = new Set("MNO".split(""));
yield forceRender(tree);

View File

@ -26,6 +26,7 @@ window.onload = Task.async(function* () {
autoExpandDepth: 1
})), window.document.body);
isAccessibleTree(tree);
isRenderedTree(document.body.textContent, [
"A:false",
"-B:false",

View File

@ -42,6 +42,7 @@ window.onload = Task.async(function* () {
scroll: 1 * ITEM_HEIGHT
});
isAccessibleTree(tree);
isRenderedTree(document.body.textContent, [
"A:false",
"-B:false",
@ -59,6 +60,7 @@ window.onload = Task.async(function* () {
scroll: 3 * ITEM_HEIGHT
});
isAccessibleTree(tree);
isRenderedTree(document.body.textContent, [
"--E:false",
"---K:false",

View File

@ -35,9 +35,11 @@ window.onload = Task.async(function* () {
const tree = renderTree();
isAccessibleTree(tree);
TEST_TREE.expanded = new Set("ABCDEFGHIJKLMNO".split(""));
renderTree({ focused: "G" });
isAccessibleTree(tree, { hasActiveDescendant: true });
isRenderedTree(document.body.textContent, [
"A:false",

View File

@ -34,6 +34,7 @@ window.onload = Task.async(function* () {
const tree = renderTree();
isAccessibleTree(tree);
TEST_TREE.expanded = new Set("ABCDEFGHIJKLMNO".split(""));
// UP ----------------------------------------------------------------------

View File

@ -198,6 +198,14 @@ module.exports = createClass({
// The depth to which we should automatically expand new items.
autoExpandDepth: PropTypes.number,
// Note: the two properties below are mutually exclusive. Only one of the
// label properties is necessary.
// ID of an element whose textual content serves as an accessible label for
// a tree.
labelledby: PropTypes.string,
// Accessibility label for a tree widget.
label: PropTypes.string,
// Optional event handlers for when items are expanded or collapsed. Useful
// for dispatching redux events and updating application state, maybe lazily
// loading subtrees from a worker, etc.
@ -555,7 +563,7 @@ module.exports = createClass({
// the top and bottom of the page are filled with the `NUMBER_OF_OFFSCREEN_ITEMS`
// previous and next items respectively, which helps the user to see fewer empty
// gaps when scrolling quickly.
const { itemHeight } = this.props;
const { itemHeight, focused } = this.props;
const { scroll, height } = this.state;
const begin = Math.max(((scroll / itemHeight) | 0) - NUMBER_OF_OFFSCREEN_ITEMS, 0);
const end = Math.ceil((scroll + height) / itemHeight) + NUMBER_OF_OFFSCREEN_ITEMS;
@ -566,6 +574,7 @@ module.exports = createClass({
const nodes = [
dom.div({
key: "top-spacer",
role: "presentation",
style: {
padding: 0,
margin: 0,
@ -579,26 +588,30 @@ module.exports = createClass({
const first = index == 0;
const last = index == traversal.length - 1;
const { item, depth } = toRender[i];
const key = this.props.getKey(item);
nodes.push(TreeNode({
key: this.props.getKey(item),
key,
index,
first,
last,
item,
depth,
id: key,
renderItem: this.props.renderItem,
focused: this.props.focused === item,
focused: focused === item,
expanded: this.props.isExpanded(item),
hasChildren: !!this.props.getChildren(item).length,
onExpand: this._onExpand,
onCollapse: this._onCollapse,
onFocus: () => this._focus(begin + i, item),
onFocusedNodeUnmount: () => this.refs.tree && this.refs.tree.focus(),
onClick: () => this._focus(begin + i, item),
// Focus on the previous node if focused node is unmounted.
onFocusedNodeUnmount: () => this._focusPrevNode(),
}));
}
nodes.push(dom.div({
key: "bottom-spacer",
role: "presentation",
style: {
padding: 0,
margin: 0,
@ -610,10 +623,33 @@ module.exports = createClass({
{
className: "tree",
ref: "tree",
role: "tree",
tabIndex: "0",
onKeyDown: this._onKeyDown,
onKeyPress: this._preventArrowKeyScrolling,
onKeyUp: this._preventArrowKeyScrolling,
onScroll: this._onScroll,
onFocus: ({nativeEvent}) => {
if (focused || !nativeEvent || !this.refs.tree) {
return;
}
let { explicitOriginalTarget } = nativeEvent;
// Only set default focus to the first tree node if the focus came
// from outside the tree (e.g. by tabbing to the tree from other
// external elements).
if (explicitOriginalTarget !== this.refs.tree &&
!this.refs.tree.contains(explicitOriginalTarget)) {
this._focus(begin, toRender[0].item);
}
},
onClick: () => {
// Focus should always remain on the tree container itself.
this.refs.tree.focus();
},
"aria-label": this.props.label,
"aria-labelledby": this.props.labelledby,
"aria-activedescendant": focused && this.props.getKey(focused),
style: {
padding: 0,
margin: 0
@ -669,6 +705,7 @@ const ArrowExpander = createFactory(createClass({
const TreeNode = createFactory(createClass({
propTypes: {
id: PropTypes.any.isRequired,
focused: PropTypes.bool.isRequired,
onFocusedNodeUnmount: PropTypes.func,
item: PropTypes.any.isRequired,
@ -678,55 +715,20 @@ const TreeNode = createFactory(createClass({
index: PropTypes.number.isRequired,
first: PropTypes.bool,
last: PropTypes.bool,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
onClick: PropTypes.func,
onCollapse: PropTypes.func.isRequired,
depth: PropTypes.number.isRequired,
renderItem: PropTypes.func.isRequired,
},
componentDidMount() {
if (this.props.focused) {
this.refs.button.focus();
}
},
componentDidUpdate() {
if (this.props.focused) {
this.refs.button.focus();
}
},
componentWillUnmount() {
// If this node is being destroyed and has focus, transfer the focus manually
// to the parent tree component. Otherwise, the focus will get lost and keyboard
// navigation in the tree will stop working. This is a workaround for a XUL bug.
// See bugs 1259228 and 1152441 for details.
// DE-XUL: Remove this hack once all usages are only in HTML documents.
if (this.props.focused) {
this.refs.button.blur();
if (this.props.onFocusedNodeUnmount) {
this.props.onFocusedNodeUnmount();
}
}
},
_buttonAttrs: {
ref: "button",
style: {
opacity: 0,
width: "0 !important",
height: "0 !important",
padding: "0 !important",
outline: "none",
MozAppearance: "none",
// XXX: Despite resetting all of the above properties (and margin), the
// button still ends up with ~79px width, so we set a large negative
// margin to completely hide it.
MozMarginStart: "-1000px !important",
}
},
render() {
const arrow = ArrowExpander({
item: this.props.item,
@ -747,12 +749,22 @@ const TreeNode = createFactory(createClass({
classList.push("tree-node-last");
}
let ariaExpanded;
if (this.props.hasChildren) {
ariaExpanded = false;
}
if (this.props.expanded) {
ariaExpanded = true;
}
return dom.div(
{
id: this.props.id,
className: classList.join(" "),
onFocus: this.props.onFocus,
onClick: this.props.onFocus,
onBlur: this.props.onBlur,
role: "treeitem",
"aria-level": this.props.depth,
onClick: this.props.onClick,
"aria-expanded": ariaExpanded,
"data-expanded": this.props.expanded ? "" : undefined,
"data-depth": this.props.depth,
style: {
@ -766,10 +778,6 @@ const TreeNode = createFactory(createClass({
this.props.focused,
arrow,
this.props.expanded),
// XXX: OSX won't focus/blur regular elements even if you set tabindex
// unless there is an input/button child.
dom.button(this._buttonAttrs)
);
}
}));

View File

@ -289,17 +289,14 @@ OutputParser.prototype = {
*
* @param {String} text
* the parsed text.
*
* @param {Object} token
* the parsed token.
*
* @param {Object} options
* the options given to _parse.
*/
_isDisplayGrid: function (text, token, options) {
return options.expectDisplay &&
(token.text === "grid" || token.text === "inline-grid") &&
text === token.text;
(token.text === "grid" || token.text === "inline-grid");
},
/**

View File

@ -234,7 +234,7 @@
.boxmodel-position.boxmodel-top,
.boxmodel-position.boxmodel-bottom {
border-left: 1px solid var(--theme-highlight-purple);
left: 49.5%;
left: calc(50% - 1px);
padding-left: 1px;
}
@ -242,7 +242,7 @@
.boxmodel-position.boxmodel-left {
border-top: 1px solid var(--theme-highlight-purple);
line-height: 15px;
top: 49.5%;
top: calc(50% - 1px);
width: 30px;
}

View File

@ -17,10 +17,6 @@ loader.lazyGetter(this, "prefBranch", function () {
return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
});
loader.lazyGetter(this, "supportsString", function () {
return Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
});
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
const PREF_DIR = "devtools.commands.dir";
@ -31,8 +27,7 @@ const PREF_DIR = "devtools.commands.dir";
* using in gcli.addItemsByModule
*/
function loadItemsFromMozDir() {
let dirName = prefBranch.getComplexValue(PREF_DIR,
Ci.nsISupportsString).data.trim();
let dirName = prefBranch.getStringPref(PREF_DIR).trim();
if (dirName == "") {
return Promise.resolve([]);
}
@ -143,8 +138,7 @@ exports.items = [
exec: function (args, context) {
gcli.load();
let dirName = prefBranch.getComplexValue(PREF_DIR,
Ci.nsISupportsString).data.trim();
let dirName = prefBranch.getStringPref(PREF_DIR).trim();
return l10n.lookupFormat("cmdStatus3", [ dirName ]);
}
},
@ -172,8 +166,7 @@ exports.items = [
return true;
},
exec: function (args, context) {
supportsString.data = args.directory;
prefBranch.setComplexValue(PREF_DIR, Ci.nsISupportsString, supportsString);
prefBranch.setStringPref(PREF_DIR, args.directory);
gcli.load();

View File

@ -238,8 +238,7 @@ Object.defineProperty(Setting.prototype, 'value', {
return imports.prefBranch.getIntPref(this.name);
case imports.prefBranch.PREF_STRING:
var value = imports.prefBranch.getComplexValue(this.name,
Ci.nsISupportsString).data;
var value = imports.prefBranch.getStringPref(this.name);
// In case of a localized string
if (/^chrome:\/\/.+\/locale\/.+\.properties/.test(value)) {
value = imports.prefBranch.getComplexValue(this.name,

View File

@ -10611,7 +10611,8 @@ nsDocShell::InternalLoad(nsIURI* aURI,
nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
if (browserChrome3) {
bool shouldLoad;
rv = browserChrome3->ShouldLoadURI(this, aURI, aReferrer, aTriggeringPrincipal, &shouldLoad);
rv = browserChrome3->ShouldLoadURI(this, aURI, aReferrer, !!aPostData,
aTriggeringPrincipal, &shouldLoad);
if (NS_SUCCEEDED(rv) && !shouldLoad) {
return NS_OK;
}

View File

@ -40,7 +40,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
var gTestNum = -1;
var gTest = null;
window.onload = goNext();
window.onload = goNext;
function goNext() {
gTestNum++;

View File

@ -21,6 +21,8 @@ class HeapSnapshot;
namespace dom {
class ArrayBufferViewOrArrayBuffer;
class PrecompiledScript;
class Promise;
class ThreadSafeChromeUtils
{
@ -101,6 +103,13 @@ public:
aA.mUserContextId == aB.mUserContextId &&
aA.mPrivateBrowsingId == aB.mPrivateBrowsingId;
}
// Implemented in js/xpconnect/loader/ChromeScriptLoader.cpp
static already_AddRefed<Promise>
CompileScript(GlobalObject& aGlobal,
const nsAString& aUrl,
const dom::CompileScriptOptionsDictionary& aOptions,
ErrorResult& aRv);
};
} // namespace dom

View File

@ -2320,6 +2320,9 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
uint8_t modType;
bool hasListeners;
// We don't want to spend time preparsing class attributes if the value is not
// changing, so just init our nsAttrValueOrString with aValue for the
// OnlyNotifySameValueSet call.
nsAttrValueOrString value(aValue);
nsAttrValue oldValue;
@ -2328,25 +2331,30 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
return NS_OK;
}
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
nsAttrValue* preparsedAttrValue = value.GetStoredAttrValue();
nsAttrValue attrValue;
nsAttrValue* preparsedAttrValue;
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::_class) {
attrValue.ParseAtomArray(aValue);
value.ResetToAttrValue(attrValue);
preparsedAttrValue = &attrValue;
} else {
preparsedAttrValue = nullptr;
}
if (aNotify) {
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
preparsedAttrValue);
}
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
// Hold a script blocker while calling ParseAttribute since that can call
// out to id-observers
nsAutoScriptBlocker scriptBlocker;
nsAttrValue attrValue;
if (preparsedAttrValue) {
attrValue.SwapValueWith(*preparsedAttrValue);
}
// Even the value was pre-parsed in BeforeSetAttr, we still need to call
// ParseAttribute because it can have side effects.
// Even the value was pre-parsed, we still need to call ParseAttribute because
// it can have side effects.
if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
attrValue.SetTo(aValue);
}
@ -2382,14 +2390,14 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
return NS_OK;
}
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNotify) {
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
&aParsedValue);
}
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
aParsedValue, modType, hasListeners, aNotify,
kCallAfterSetAttr);
@ -2458,8 +2466,6 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
}
}
UpdateState(aNotify);
nsIDocument* ownerDoc = OwnerDoc();
if (ownerDoc && GetCustomElementData()) {
nsCOMPtr<nsIAtom> oldValueAtom = oldValue->GetAsAtom();
@ -2485,6 +2491,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
}
}
UpdateState(aNotify);
if (aNotify) {
// Don't pass aOldValue to AttributeChanged since it may not be reliable.
// Callers only compute aOldValue under certain conditions which may not
@ -2520,25 +2528,6 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
return NS_OK;
}
nsresult
Element::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::_class) {
// aValue->GetAttrValue will only be non-null here when this is called
// via Element::SetParsedAttr. This shouldn't happen for "class", but
// this will handle it.
if (aValue && !aValue->GetAttrValue()) {
nsAttrValue attr;
attr.ParseAtomArray(aValue->String());
aValue->TakeParsedValue(attr);
}
}
}
return NS_OK;
}
bool
Element::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
@ -2655,9 +2644,6 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
return NS_OK;
}
nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
nsIDocument *document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
@ -2667,6 +2653,9 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nullptr);
}
nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
bool hasMutationListeners = aNotify &&
nsContentUtils::HasMutationListeners(this,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
@ -2715,8 +2704,6 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
}
UpdateState(aNotify);
nsIDocument* ownerDoc = OwnerDoc();
if (ownerDoc && GetCustomElementData()) {
nsCOMPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom();
@ -2730,6 +2717,11 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
ownerDoc, nsIDocument::eAttributeChanged, this, &args);
}
rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
UpdateState(aNotify);
if (aNotify) {
// We can always pass oldValue here since there is no new value which could
// have corrupted it.
@ -2737,9 +2729,6 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsIDOMMutationEvent::REMOVAL, &oldValue);
}
rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
OnSetDirAttr(this, nullptr, hadValidDir, hadDirAuto, aNotify);
}

View File

@ -1380,16 +1380,17 @@ protected:
* @param aName the localname of the attribute being set
* @param aValue the value it's being set to represented as either a string or
* a parsed nsAttrValue. Alternatively, if the attr is being removed it
* will be null. BeforeSetAttr is allowed to modify aValue by parsing
* the string to an nsAttrValue (to avoid having to reparse it in
* ParseAttribute).
* will be null.
* @param aNotify Whether we plan to notify document observers.
*/
// Note that this is inlined so that when subclasses call it it gets
// inlined. Those calls don't go through a vtable.
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
bool aNotify);
const nsAttrValueOrString* aValue,
bool aNotify)
{
return NS_OK;
}
/**
* Hook that is called by Element::SetAttr to allow subclasses to

View File

@ -49,20 +49,13 @@ public:
, mCheapString(nullptr)
{ }
void TakeParsedValue(nsAttrValue& aValue)
void ResetToAttrValue(const nsAttrValue& aValue)
{
mStoredAttrValue.SwapValueWith(aValue);
mAttrValue = &mStoredAttrValue;
mAttrValue = &aValue;
mStringPtr = nullptr;
// No need to touch mCheapString here. If we need to use it, we will reset
// it to the rigthe value anyway.
}
/**
* If TakeParsedValue has been called, returns the value that it set.
*/
nsAttrValue* GetStoredAttrValue()
{
return mAttrValue == &mStoredAttrValue ? &mStoredAttrValue : nullptr;
}
const nsAttrValue* GetAttrValue() { return mAttrValue; }
/**
* Returns a reference to the string value of the contents of this object.
@ -89,7 +82,6 @@ protected:
const nsAttrValue* mAttrValue;
mutable const nsAString* mStringPtr;
mutable nsCheapString mCheapString;
nsAttrValue mStoredAttrValue;
};
#endif // nsAttrValueOrString_h___

View File

@ -75,6 +75,8 @@
#include "nsIDOMComment.h"
#include "mozilla/dom/DocumentType.h"
#include "mozilla/dom/NodeIterator.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/TreeWalker.h"
#include "nsIServiceManager.h"
@ -2744,6 +2746,13 @@ nsDocument::InitCSP(nsIChannel* aChannel)
return NS_OK;
}
already_AddRefed<nsIParser>
nsDocument::CreatorParserOrNull()
{
nsCOMPtr<nsIParser> parser = mParser;
return parser.forget();
}
void
nsDocument::StopDocumentLoad()
{
@ -10514,6 +10523,78 @@ nsIDocument::ObsoleteSheet(const nsAString& aSheetURI, ErrorResult& rv)
}
}
class UnblockParsingPromiseHandler final : public PromiseNativeHandler
{
public:
NS_DECL_ISUPPORTS
explicit UnblockParsingPromiseHandler(nsIDocument* aDocument, Promise* aPromise)
: mDocument(aDocument)
, mPromise(aPromise)
{
nsCOMPtr<nsIParser> parser = mDocument->CreatorParserOrNull();
if (parser) {
parser->BlockParser();
} else {
mDocument = nullptr;
}
}
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
MaybeUnblockParser();
mPromise->MaybeResolve(aCx, aValue);
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
MaybeUnblockParser();
mPromise->MaybeReject(aCx, aValue);
}
protected:
virtual ~UnblockParsingPromiseHandler()
{
MaybeUnblockParser();
}
private:
void MaybeUnblockParser() {
if (mDocument) {
nsCOMPtr<nsIParser> parser = mDocument->CreatorParserOrNull();
if (parser) {
parser->UnblockParser();
parser->ContinueInterruptedParsingAsync();
}
mDocument = nullptr;
}
}
RefPtr<nsIDocument> mDocument;
RefPtr<Promise> mPromise;
};
NS_IMPL_ISUPPORTS0(UnblockParsingPromiseHandler)
already_AddRefed<Promise>
nsIDocument::BlockParsing(OwningNonNull<Promise> aPromise,
ErrorResult& aRv)
{
RefPtr<Promise> resultPromise = Promise::Create(aPromise->GetParentObject(), aRv);
if (aRv.Failed()) {
return nullptr;
}
RefPtr<PromiseNativeHandler> promiseHandler = new UnblockParsingPromiseHandler(this, resultPromise);
aPromise->AppendNativeHandler(promiseHandler);
return resultPromise.forget();
}
already_AddRefed<nsIURI>
nsIDocument::GetMozDocumentURIIfNotForErrorPages()
{

View File

@ -537,6 +537,8 @@ public:
virtual void ApplySettingsFromCSP(bool aSpeculative) override;
virtual already_AddRefed<nsIParser> CreatorParserOrNull() override;
/**
* Set the principal responsible for this document.
*/

View File

@ -56,7 +56,10 @@ public:
}
return nsXMLElement::GetEventTargetParent(aVisitor);
}
protected:
nsIContent* AsContent() override { return this; }
private:
virtual ~nsGenConImageContent();

View File

@ -14743,6 +14743,10 @@ nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
const Sequence<ChannelPixelLayout>& aLayout,
ErrorResult& aRv)
{
if (!ImageBitmap::ExtensionsEnabled(nullptr, nullptr)) {
aRv.Throw(NS_ERROR_TYPE_ERR);
return nullptr;
}
if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
aRv);

View File

@ -15,6 +15,7 @@
#include "nsIDocumentObserver.h" // for typedef (nsUpdateType)
#include "nsILoadGroup.h" // for member (in nsCOMPtr)
#include "nsINode.h" // for base class
#include "nsIParser.h"
#include "nsIScriptGlobalObject.h" // for member (in nsCOMPtr)
#include "nsIServiceManager.h"
#include "nsIUUIDGenerator.h"
@ -359,6 +360,8 @@ public:
*/
virtual void ApplySettingsFromCSP(bool aSpeculative) = 0;
virtual already_AddRefed<nsIParser> CreatorParserOrNull() = 0;
/**
* Return the referrer policy of the document. Return "default" if there's no
* valid meta referrer tag found in the document.
@ -1977,7 +1980,7 @@ public:
return mMayStartLayout;
}
void SetMayStartLayout(bool aMayStartLayout)
virtual void SetMayStartLayout(bool aMayStartLayout)
{
mMayStartLayout = aMayStartLayout;
}
@ -2784,6 +2787,9 @@ public:
void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv);
already_AddRefed<mozilla::dom::Promise> BlockParsing(mozilla::OwningNonNull<mozilla::dom::Promise> aPromise,
mozilla::ErrorResult& aRv);
already_AddRefed<nsIURI> GetMozDocumentURIIfNotForErrorPages();
// ParentNode

View File

@ -836,9 +836,8 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
// We use the principal of aDocument to avoid having to QI |this| an extra
// time. It should always be the same as the principal of this node.
#ifdef DEBUG
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
MOZ_ASSERT(thisContent &&
thisContent->NodePrincipal() == aDocument->NodePrincipal(),
nsIContent* thisContent = AsContent();
MOZ_ASSERT(thisContent->NodePrincipal() == aDocument->NodePrincipal(),
"Principal mismatch?");
#endif
@ -1023,10 +1022,7 @@ nsImageLoadingContent::UpdateImageState(bool aNotify)
return;
}
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
if (!thisContent) {
return;
}
nsIContent* thisContent = AsContent();
mLoading = mBroken = mUserDisabled = mSuppressed = false;
@ -1090,29 +1086,19 @@ nsImageLoadingContent::UseAsPrimaryRequest(imgRequestProxy* aRequest,
nsIDocument*
nsImageLoadingContent::GetOurOwnerDoc()
{
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
NS_ENSURE_TRUE(thisContent, nullptr);
return thisContent->OwnerDoc();
return AsContent()->OwnerDoc();
}
nsIDocument*
nsImageLoadingContent::GetOurCurrentDoc()
{
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
NS_ENSURE_TRUE(thisContent, nullptr);
return thisContent->GetComposedDoc();
return AsContent()->GetComposedDoc();
}
nsIFrame*
nsImageLoadingContent::GetOurPrimaryFrame()
{
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
return thisContent->GetPrimaryFrame();
return AsContent()->GetPrimaryFrame();
}
nsPresContext* nsImageLoadingContent::GetFramePresContext()
@ -1134,8 +1120,7 @@ nsImageLoadingContent::StringToURI(const nsAString& aSpec,
NS_PRECONDITION(aURI, "Null out param");
// (1) Get the base URI
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
NS_ASSERTION(thisContent, "An image loading content must be an nsIContent");
nsIContent* thisContent = AsContent();
nsCOMPtr<nsIURI> baseURL = thisContent->GetBaseURI();
// (2) Get the charset

View File

@ -219,6 +219,10 @@ protected:
void AsyncEventRunning(mozilla::AsyncEventDispatcher* aEvent);
// Get ourselves as an nsIContent*. Not const because some of the callers
// want a non-const nsIContent.
virtual nsIContent* AsContent() = 0;
private:
/**
* Struct used to manage the image observers.

View File

@ -13,6 +13,7 @@
#include "prsystem.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/Utility.h"
#include "xpcpublic.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIContent.h"

View File

@ -407,6 +407,21 @@ public:
nsIDocument* aDocument,
char16_t*& aBufOut, size_t& aLengthOut);
static inline nsresult
ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
uint32_t aLength, const nsAString& aHintCharset,
nsIDocument* aDocument,
JS::UniqueTwoByteChars& aBufOut, size_t& aLengthOut)
{
char16_t* bufOut;
nsresult rv = ConvertToUTF16(aChannel, aData, aLength, aHintCharset, aDocument,
bufOut, aLengthOut);
if (NS_SUCCEEDED(rv)) {
aBufOut.reset(bufOut);
}
return rv;
};
/**
* Handle the completion of a stream. This is called by the
* nsScriptLoadHandler object which observes the IncrementalStreamLoader

View File

@ -5,9 +5,15 @@ support-files =
file_bug945152.jar
file_bug945152_worker.js
file_bug1008126_worker.js
file_inline_script.html
file_inline_script.xhtml
file_external_script.html
file_external_script.xhtml
file_script.js
mozbrowser_api_utils.js
[test_anonymousContent_xul_window.xul]
[test_blockParsing.html]
[test_bug715041.xul]
[test_bug715041_removal.xul]
[test_bug945152.html]

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="file_script.js"></script>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p>Hello Mochitest</p>
</body>
</html>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="file_script.js"/>
<title/>
</head>
<body>
<p>Hello Mochitest</p>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script>window.scriptRan = true;</script>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p>Hello Mochitest</p>
</body>
</html>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>window.scriptRan = true;</script>
<title/>
</head>
<body>
<p>Hello Mochitest</p>
</body>
</html>

View File

@ -0,0 +1 @@
window.scriptRan = true;

View File

@ -0,0 +1,88 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for document.blockParsing</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script>
Components.utils.import("resource://testing-common/TestUtils.jsm");
function* runTest(url, initialHTML, finalHTML) {
let iframe = document.createElement("iframe");
iframe.src = url;
let blockerPromise;
let promise = TestUtils.topicObserved("document-element-inserted", document => {
blockerPromise = new Promise(resolve => {
setTimeout(resolve, 0);
}).then(() => {
return new Promise(resolve => setTimeout(resolve, 0));
}).then(() => {
return new Promise(resolve => setTimeout(resolve, 0));
});
is(document.documentElement.outerHTML, initialHTML,
"Should have initial HTML during document-element-inserted");
is(document.defaultView.wrappedJSObject.scriptRan, undefined,
"Script node should not have run");
document.blockParsing(blockerPromise);
return true;
}).then(([document]) => {
return document;
});
document.body.appendChild(iframe);
// Wait for document-element-inserted to fire.
let doc = yield promise;
let win = doc.defaultView.wrappedJSObject;
let root = doc.documentElement;
// At this point, if the parser was successfully blocked, we should still
// have the initial skeleton HTML for the page.
is(root.outerHTML, initialHTML, "Should have initial HTML after document-element-inserted returns");
is(win.scriptRan, undefined, "Script node should still not have run");
yield blockerPromise;
// Just after the promise that's blocking the parser fires, we shouldn't have
// returned to the main event loop, so we should still have the initial HTML.
is(root.outerHTML, initialHTML, "Should still have initial HTML");
is(win.scriptRan, undefined, "Script node should still not have run");
yield new Promise(resolve => win.addEventListener("DOMContentLoaded", resolve, {once: true}));
// Parsing should have resumed, and we should have finished loading the document.
is(root.outerHTML, finalHTML, "Should have final HTML");
is(win.scriptRan, true, "Script node should have run");
iframe.remove();
}
add_task(function* () {
yield runTest("http://mochi.test:8888/chrome/dom/base/test/file_inline_script.html",
'<html lang="en"></html>',
'<html lang="en"><head>\n <script>window.scriptRan = true;<\/script>\n <meta charset="utf-8">\n <title></title>\n</head>\n<body>\n <p>Hello Mochitest</p>\n\n\n</body></html>');
yield runTest("http://mochi.test:8888/chrome/dom/base/test/file_inline_script.xhtml",
'<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"></html>',
'<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">\n<head>\n <script>window.scriptRan = true;<\/script>\n <title></title>\n</head>\n<body>\n <p>Hello Mochitest</p>\n</body>\n</html>');
yield runTest("http://mochi.test:8888/chrome/dom/base/test/file_external_script.html",
'<html lang="en"></html>',
'<html lang="en"><head>\n <script src="file_script.js"><\/script>\n <meta charset="utf-8">\n <title></title>\n</head>\n<body>\n <p>Hello Mochitest</p>\n\n\n</body></html>');
yield runTest("http://mochi.test:8888/chrome/dom/base/test/file_external_script.xhtml",
'<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"></html>',
'<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">\n<head>\n <script src="file_script.js"><\/script>\n <title></title>\n</head>\n<body>\n <p>Hello Mochitest</p>\n</body>\n</html>');
});
</script>
</body>
</html>

View File

@ -4852,9 +4852,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
# optional arguments must be optional.
if (not argument.optional and
all(arg.optional for arg in arguments[idx+1:])):
raise WebIDLError("Dictionary argument or union "
"argument containing a dictionary "
"not followed by a required argument "
raise WebIDLError("Dictionary argument without any "
"required fields or union argument "
"containing such dictionary not "
"followed by a required argument "
"must be optional",
[argument.location])

View File

@ -423,7 +423,7 @@ HTMLButtonElement::DoneCreatingElement()
nsresult
HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNotify && aName == nsGkAtoms::disabled &&
@ -448,7 +448,6 @@ HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
if (aName == nsGkAtoms::type || aName == nsGkAtoms::disabled) {
UpdateBarredFromConstraintValidation();
UpdateState(aNotify);
}
}

View File

@ -81,7 +81,7 @@ public:
* Called when an attribute is about to be changed
*/
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
/**
* Called when an attribute has just been changed

View File

@ -46,7 +46,7 @@ HTMLDetailsElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
nsresult
HTMLDetailsElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify)
const nsAttrValueOrString* aValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::open) {
bool setOpen = aValue != nullptr;

View File

@ -38,7 +38,8 @@ public:
int32_t aModType) const override;
nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify) override;
const nsAttrValueOrString* aValue,
bool aNotify) override;
// HTMLDetailsElement WebIDL
bool Open() const { return GetBoolAttr(nsGkAtoms::open); }

View File

@ -368,7 +368,7 @@ HTMLImageElement::GetAttributeMappingFunction() const
nsresult
HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify)
{

View File

@ -344,12 +344,15 @@ protected:
void UpdateFormOwner();
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;
// Override for nsImageLoadingContent.
nsIContent* AsContent() override { return this; }
// This is a weak reference that this element and the HTMLFormElement
// cooperate in maintaining.
HTMLFormElement* mForm;

View File

@ -178,15 +178,18 @@ static const nsAttrValue::EnumTable kInputTypeTable[] = {
{ "search", NS_FORM_INPUT_SEARCH },
{ "submit", NS_FORM_INPUT_SUBMIT },
{ "tel", NS_FORM_INPUT_TEL },
{ "text", NS_FORM_INPUT_TEXT },
{ "time", NS_FORM_INPUT_TIME },
{ "url", NS_FORM_INPUT_URL },
{ "week", NS_FORM_INPUT_WEEK },
// "text" must be last for ParseAttribute to work right. If you add things
// before it, please update kInputDefaultType.
{ "text", NS_FORM_INPUT_TEXT },
{ nullptr, 0 }
};
// Default type is 'text'.
static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[18];
static const nsAttrValue::EnumTable* kInputDefaultType =
&kInputTypeTable[ArrayLength(kInputTypeTable) - 2];
static const uint8_t NS_INPUT_INPUTMODE_AUTO = 0;
static const uint8_t NS_INPUT_INPUTMODE_NUMERIC = 1;
@ -1358,7 +1361,7 @@ HTMLInputElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) co
nsresult
HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
@ -1449,36 +1452,15 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
if (aName == nsGkAtoms::type) {
uint8_t newType;
if (!aValue) {
// We're now a text input. Note that we have to handle this manually,
// since removing an attribute (which is what happened, since aValue is
// null) doesn't call ParseAttribute.
HandleTypeChange(kInputDefaultType->value);
// We're now a text input.
newType = kInputDefaultType->value;
} else {
newType = aValue->GetEnumValue();
}
UpdateBarredFromConstraintValidation();
if (mType != NS_FORM_INPUT_IMAGE) {
// We're no longer an image input. Cancel our image requests, if we have
// any. Note that doing this when we already weren't an image is ok --
// just does nothing.
CancelImageRequests(aNotify);
} else if (aNotify) {
// We just got switched to be an image input; we should see
// whether we have an image to load;
nsAutoString src;
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
LoadImage(src, false, aNotify, eImageLoadType_Normal);
}
}
if (mType == NS_FORM_INPUT_PASSWORD && IsInComposedDoc()) {
AsyncEventDispatcher* dispatcher =
new AsyncEventDispatcher(this,
NS_LITERAL_STRING("DOMInputPasswordAdded"),
true,
true);
dispatcher->PostDOMEvent();
if (newType != mType) {
HandleTypeChange(newType, aNotify);
}
}
@ -1577,8 +1559,6 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
// Clear the cached @autocomplete attribute state.
mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
}
UpdateState(aNotify);
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
@ -5121,14 +5101,23 @@ HTMLInputElement::UnbindFromTree(bool aDeep, bool aNullParent)
}
void
HTMLInputElement::HandleTypeChange(uint8_t aNewType)
HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify)
{
if (mType == NS_FORM_INPUT_RANGE && mIsDraggingRange) {
uint8_t oldType = mType;
MOZ_ASSERT(oldType != aNewType);
if (aNewType == NS_FORM_INPUT_FILE || oldType == NS_FORM_INPUT_FILE) {
// Strictly speaking, we only need to clear files on going _to_ or _from_
// the NS_FORM_INPUT_FILE type, not both, since we'll never confuse values
// and filenames. But this is safer.
ClearFiles(false);
}
if (oldType == NS_FORM_INPUT_RANGE && mIsDraggingRange) {
CancelRangeThumbDrag(false);
}
ValueModeType aOldValueMode = GetValueMode();
uint8_t oldType = mType;
nsAutoString aOldValue;
if (aOldValueMode == VALUE_MODE_VALUE) {
@ -5212,6 +5201,30 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType)
UpdateAllValidityStates(false);
UpdateApzAwareFlag();
UpdateBarredFromConstraintValidation();
if (oldType == NS_FORM_INPUT_IMAGE) {
// We're no longer an image input. Cancel our image requests, if we have
// any.
CancelImageRequests(aNotify);
} else if (aNotify && mType == NS_FORM_INPUT_IMAGE) {
// We just got switched to be an image input; we should see
// whether we have an image to load;
nsAutoString src;
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
LoadImage(src, false, aNotify, eImageLoadType_Normal);
}
}
if (mType == NS_FORM_INPUT_PASSWORD && IsInComposedDoc()) {
AsyncEventDispatcher* dispatcher =
new AsyncEventDispatcher(this,
NS_LITERAL_STRING("DOMInputPasswordAdded"),
true,
true);
dispatcher->PostDOMEvent();
}
}
void
@ -5935,45 +5948,34 @@ HTMLInputElement::ParseAttribute(int32_t aNamespaceID,
const nsAString& aValue,
nsAttrValue& aResult)
{
// We can't make these static_asserts because kInputDefaultType and
// kInputTypeTable aren't constexpr.
MOZ_ASSERT(kInputDefaultType->value == NS_FORM_INPUT_TEXT,
"Someone forgot to update kInputDefaultType when adding a new "
"input type.");
MOZ_ASSERT(kInputTypeTable[ArrayLength(kInputTypeTable) - 1].tag == nullptr,
"Last entry in the table must be the nullptr guard");
MOZ_ASSERT(kInputTypeTable[ArrayLength(kInputTypeTable) - 2].value ==
NS_FORM_INPUT_TEXT,
"Next to last entry in the table must be the \"text\" entry");
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::type) {
// XXX ARG!! This is major evilness. ParseAttribute
// shouldn't set members. Override SetAttr instead
int32_t newType;
bool success = aResult.ParseEnumValue(aValue, kInputTypeTable, false);
if (success) {
newType = aResult.GetEnumValue();
if ((IsExperimentalMobileType(newType) &&
!IsExperimentalFormsEnabled()) ||
(newType == NS_FORM_INPUT_NUMBER && !IsInputNumberEnabled()) ||
(newType == NS_FORM_INPUT_COLOR && !IsInputColorEnabled()) ||
(IsDateTimeInputType(newType) &&
!IsDateTimeTypeSupported(newType))) {
newType = kInputDefaultType->value;
aResult.SetTo(newType, &aValue);
}
} else {
newType = kInputDefaultType->value;
aResult.ParseEnumValue(aValue, kInputTypeTable, false, kInputDefaultType);
int32_t newType = aResult.GetEnumValue();
if ((IsExperimentalMobileType(newType) &&
!IsExperimentalFormsEnabled()) ||
(newType == NS_FORM_INPUT_NUMBER && !IsInputNumberEnabled()) ||
(newType == NS_FORM_INPUT_COLOR && !IsInputColorEnabled()) ||
(IsDateTimeInputType(newType) &&
!IsDateTimeTypeSupported(newType))) {
// There's no public way to set an nsAttrValue to an enum value, but we
// can just re-parse with a table that doesn't have any types other than
// "text" in it.
aResult.ParseEnumValue(aValue, kInputDefaultType, false, kInputDefaultType);
}
if (newType != mType) {
// Make sure to do the check for newType being NS_FORM_INPUT_FILE and
// the corresponding SetValueInternal() call _before_ we set mType.
// That way the logic in SetValueInternal() will work right (that logic
// makes assumptions about our frame based on mType, but we won't have
// had time to recreate frames yet -- that happens later in the
// SetAttr() process).
if (newType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_FILE) {
// This call isn't strictly needed any more since we'll never
// confuse values and filenames. However it's there for backwards
// compat.
ClearFiles(false);
}
HandleTypeChange(newType);
}
return success;
return true;
}
if (aAttribute == nsGkAtoms::width) {
return aResult.ParseSpecialIntValue(aValue);

View File

@ -965,7 +965,7 @@ protected:
* Called when an attribute is about to be changed
*/
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
/**
* Called when an attribute has just been changed
@ -1107,7 +1107,7 @@ protected:
/**
* Manages the internal data storage across type changes.
*/
void HandleTypeChange(uint8_t aNewType);
void HandleTypeChange(uint8_t aNewType, bool aNotify);
/**
* Sanitize the value of the element depending of its current type.
@ -1495,6 +1495,11 @@ protected:
uint32_t* aSelectionEnd,
ErrorResult& aRv);
/**
* Override for nsImageLoadingContent.
*/
nsIContent* AsContent() override { return this; }
nsCOMPtr<nsIControllers> mControllers;
/*

View File

@ -333,7 +333,7 @@ HTMLLinkElement::UpdateImport()
nsresult
HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue, bool aNotify)
const nsAttrValueOrString* aValue, bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None &&
(aName == nsGkAtoms::href || aName == nsGkAtoms::rel)) {

View File

@ -62,7 +62,7 @@ public:
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true) override;
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,

View File

@ -252,6 +252,10 @@ public:
*/
void StartObjectLoad(bool aNotify, bool aForceLoad);
protected:
// Override for nsImageLoadingContent.
nsIContent* AsContent() override { return this; }
private:
/**
* Returns if the element is currently focusable regardless of it's tabindex

View File

@ -181,7 +181,7 @@ HTMLOptionElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
nsresult
HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify)
{
nsresult rv = nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName,

View File

@ -47,7 +47,7 @@ public:
int32_t aModType) const override;
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;

View File

@ -1296,7 +1296,7 @@ HTMLSelectElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult
HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNotify && aName == nsGkAtoms::disabled &&
@ -1321,8 +1321,6 @@ HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
// Clear the cached @autocomplete attribute state
mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
}
UpdateState(aNotify);
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,

View File

@ -382,7 +382,7 @@ public:
bool aCompileEventHandlers) override;
virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify) override;

View File

@ -200,6 +200,11 @@ public:
* Calls LoadObject with the correct arguments to start the plugin load.
*/
void StartObjectLoad(bool aNotify, bool aForceLoad);
protected:
// Override for nsImageLoadingContent.
nsIContent* AsContent() override { return this; }
private:
virtual ~HTMLSharedObjectElement();

View File

@ -937,7 +937,7 @@ HTMLTableElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult
HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify)
{
if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {

View File

@ -202,7 +202,7 @@ public:
* Called when an attribute is about to be changed
*/
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
/**
* Called when an attribute has just been changed

View File

@ -985,7 +985,7 @@ HTMLTextAreaElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult
HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNotify && aName == nsGkAtoms::disabled &&
@ -1063,8 +1063,6 @@ HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} else if (aName == nsGkAtoms::minlength) {
UpdateTooShortValidityState();
}
UpdateState(aNotify);
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,

View File

@ -147,7 +147,7 @@ public:
* Called when an attribute is about to be changed
*/
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
// nsIMutationObserver

View File

@ -1929,7 +1929,7 @@ nsGenericHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
nsresult
nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
@ -1959,13 +1959,6 @@ nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
mForm->RemoveElement(this, false);
// Removing the element from the form can make it not be the default
// control anymore. Go ahead and notify on that change, though we might
// end up readding and becoming the default control again in
// AfterSetAttr.
// FIXME: Bug 656197
UpdateState(aNotify);
}
if (aName == nsGkAtoms::form) {
@ -2015,12 +2008,6 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
mForm->AddElement(this, false, aNotify);
// Adding the element to the form can make it be the default control .
// Go ahead and notify on that change.
// Note: no need to notify on CanBeDisabled(), since type attr
// changes can't affect that.
UpdateState(aNotify);
}
if (aName == nsGkAtoms::form) {

View File

@ -1296,7 +1296,7 @@ protected:
virtual ~nsGenericHTMLFormElement();
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsAttrValueOrString* aValue,
const nsAttrValueOrString* aValue,
bool aNotify) override;
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,

View File

@ -2411,7 +2411,7 @@ nsHTMLDocument::GetDesignMode(nsAString& aDesignMode)
void
nsHTMLDocument::MaybeEditingStateChanged()
{
if (!mPendingMaybeEditingStateChanged &&
if (!mPendingMaybeEditingStateChanged && mMayStartLayout &&
mUpdateNestLevel == 0 && (mContentEditableCount > 0) != IsEditingOn()) {
if (nsContentUtils::IsSafeToRunScript()) {
EditingStateChanged();
@ -2434,6 +2434,15 @@ nsHTMLDocument::EndUpdate(nsUpdateType aUpdateType)
MaybeEditingStateChanged();
}
void
nsHTMLDocument::SetMayStartLayout(bool aMayStartLayout)
{
nsIDocument::SetMayStartLayout(aMayStartLayout);
MaybeEditingStateChanged();
}
// Helper class, used below in ChangeContentEditableCount().
class DeferredContentEditableCountChangeEvent : public Runnable

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