mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Merge inbound to central, a=merge
MozReview-Commit-ID: 96co4Bbby7W
This commit is contained in:
commit
dac8dc0c7b
@ -11,6 +11,7 @@ module.exports = {
|
||||
"mozilla/no-import-into-var-and-global": "error",
|
||||
"mozilla/no-useless-parameters": "error",
|
||||
"mozilla/no-useless-removeEventListener": "error",
|
||||
"mozilla/use-default-preference-values": "error",
|
||||
"mozilla/use-ownerGlobal": "error",
|
||||
|
||||
// No (!foo in bar) or (!object instanceof Class)
|
||||
|
@ -15,6 +15,10 @@ this.EXPORTED_SYMBOLS = ['AccessFu']; // jshint ignore:line
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
|
||||
|
||||
if (Utils.MozBuildApp === 'mobile/android') {
|
||||
Cu.import('resource://gre/modules/Messaging.jsm');
|
||||
}
|
||||
|
||||
const ACCESSFU_DISABLE = 0; // jshint ignore:line
|
||||
const ACCESSFU_ENABLE = 1;
|
||||
const ACCESSFU_AUTO = 2;
|
||||
@ -32,11 +36,9 @@ this.AccessFu = { // jshint ignore:line
|
||||
attach: function attach(aWindow) {
|
||||
Utils.init(aWindow);
|
||||
|
||||
try {
|
||||
Services.androidBridge.dispatch('Accessibility:Ready');
|
||||
Services.obs.addObserver(this, 'Accessibility:Settings', false);
|
||||
} catch (x) {
|
||||
// Not on Android
|
||||
if (Utils.MozBuildApp === 'mobile/android') {
|
||||
EventDispatcher.instance.dispatch('Accessibility:Ready');
|
||||
EventDispatcher.instance.registerListener(this, 'Accessibility:Settings');
|
||||
}
|
||||
|
||||
this._activatePref = new PrefCache(
|
||||
@ -54,7 +56,7 @@ this.AccessFu = { // jshint ignore:line
|
||||
this._disable();
|
||||
}
|
||||
if (Utils.MozBuildApp === 'mobile/android') {
|
||||
Services.obs.removeObserver(this, 'Accessibility:Settings');
|
||||
EventDispatcher.instance.unregisterListener(this, 'Accessibility:Settings');
|
||||
}
|
||||
delete this._activatePref;
|
||||
Utils.uninit();
|
||||
@ -120,16 +122,21 @@ this.AccessFu = { // jshint ignore:line
|
||||
Output.start();
|
||||
PointerAdapter.start();
|
||||
|
||||
if (Utils.MozBuildApp === 'mobile/android') {
|
||||
EventDispatcher.instance.registerListener(this, [
|
||||
'Accessibility:ActivateObject',
|
||||
'Accessibility:Focus',
|
||||
'Accessibility:LongPress',
|
||||
'Accessibility:MoveByGranularity',
|
||||
'Accessibility:NextObject',
|
||||
'Accessibility:PreviousObject',
|
||||
'Accessibility:ScrollBackward',
|
||||
'Accessibility:ScrollForward',
|
||||
]);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, 'remote-browser-shown', false);
|
||||
Services.obs.addObserver(this, 'inprocess-browser-shown', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:NextObject', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:Focus', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:ActivateObject', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:LongPress', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:ScrollForward', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:ScrollBackward', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:MoveByGranularity', false);
|
||||
Utils.win.addEventListener('TabOpen', this);
|
||||
Utils.win.addEventListener('TabClose', this);
|
||||
Utils.win.addEventListener('TabSelect', this);
|
||||
@ -169,14 +176,19 @@ this.AccessFu = { // jshint ignore:line
|
||||
|
||||
Services.obs.removeObserver(this, 'remote-browser-shown');
|
||||
Services.obs.removeObserver(this, 'inprocess-browser-shown');
|
||||
Services.obs.removeObserver(this, 'Accessibility:NextObject');
|
||||
Services.obs.removeObserver(this, 'Accessibility:PreviousObject');
|
||||
Services.obs.removeObserver(this, 'Accessibility:Focus');
|
||||
Services.obs.removeObserver(this, 'Accessibility:ActivateObject');
|
||||
Services.obs.removeObserver(this, 'Accessibility:LongPress');
|
||||
Services.obs.removeObserver(this, 'Accessibility:ScrollForward');
|
||||
Services.obs.removeObserver(this, 'Accessibility:ScrollBackward');
|
||||
Services.obs.removeObserver(this, 'Accessibility:MoveByGranularity');
|
||||
|
||||
if (Utils.MozBuildApp === 'mobile/android') {
|
||||
EventDispatcher.instance.unregisterListener(this, [
|
||||
'Accessibility:ActivateObject',
|
||||
'Accessibility:Focus',
|
||||
'Accessibility:LongPress',
|
||||
'Accessibility:MoveByGranularity',
|
||||
'Accessibility:NextObject',
|
||||
'Accessibility:PreviousObject',
|
||||
'Accessibility:ScrollBackward',
|
||||
'Accessibility:ScrollForward',
|
||||
]);
|
||||
}
|
||||
|
||||
delete this._quicknavModesPref;
|
||||
delete this._notifyOutputPref;
|
||||
@ -288,24 +300,23 @@ this.AccessFu = { // jshint ignore:line
|
||||
this._loadFrameScript(aMessageManager);
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
onEvent: function (event, data, callback) {
|
||||
switch (event) {
|
||||
case 'Accessibility:Settings':
|
||||
this._systemPref = JSON.parse(aData).enabled;
|
||||
this._systemPref = data.enabled;
|
||||
this._enableOrDisable();
|
||||
break;
|
||||
case 'Accessibility:NextObject':
|
||||
case 'Accessibility:PreviousObject':
|
||||
{
|
||||
let rule = aData ?
|
||||
aData.substr(0, 1).toUpperCase() + aData.substr(1).toLowerCase() :
|
||||
case 'Accessibility:PreviousObject': {
|
||||
let rule = data ?
|
||||
data.rule.substr(0, 1).toUpperCase() + data.rule.substr(1).toLowerCase() :
|
||||
'Simple';
|
||||
let method = aTopic.replace(/Accessibility:(\w+)Object/, 'move$1');
|
||||
let method = event.replace(/Accessibility:(\w+)Object/, 'move$1');
|
||||
this.Input.moveCursor(method, rule, 'gesture');
|
||||
break;
|
||||
}
|
||||
case 'Accessibility:ActivateObject':
|
||||
this.Input.activateCurrent(JSON.parse(aData));
|
||||
this.Input.activateCurrent(data);
|
||||
break;
|
||||
case 'Accessibility:LongPress':
|
||||
this.Input.sendContextMenuMessage();
|
||||
@ -317,14 +328,19 @@ this.AccessFu = { // jshint ignore:line
|
||||
this.Input.androidScroll('backward');
|
||||
break;
|
||||
case 'Accessibility:Focus':
|
||||
this._focused = JSON.parse(aData);
|
||||
this._focused = data.gainFocus;
|
||||
if (this._focused) {
|
||||
this.autoMove({ forcePresent: true, noOpIfOnScreen: true });
|
||||
}
|
||||
break;
|
||||
case 'Accessibility:MoveByGranularity':
|
||||
this.Input.moveByGranularity(JSON.parse(aData));
|
||||
this.Input.moveByGranularity(data);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case 'remote-browser-shown':
|
||||
case 'inprocess-browser-shown':
|
||||
{
|
||||
|
@ -60,6 +60,7 @@ function testObjectOutput(aAccOrElmOrID, aGenerator) {
|
||||
var context = new PivotContext(accessible);
|
||||
var output = aGenerator.genForObject(accessible, context);
|
||||
var outputOrder;
|
||||
// eslint-disable-next-line mozilla/use-default-preference-values
|
||||
try {
|
||||
outputOrder = SpecialPowers.getIntPref(PREF_UTTERANCE_ORDER);
|
||||
} catch (ex) {
|
||||
|
@ -81,31 +81,31 @@ exports['test adding non object or null item'] = function(assert) {
|
||||
assert.throws(() => {
|
||||
add(items, 'foo');
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
|
||||
assert.throws(() => {
|
||||
add(items, 0);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
|
||||
assert.throws(() => {
|
||||
add(items, undefined);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
|
||||
assert.throws(() => {
|
||||
add(items, null);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
|
||||
assert.throws(() => {
|
||||
add(items, true);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
};
|
||||
|
||||
@ -115,31 +115,31 @@ exports['test adding to non object or null item'] = function(assert) {
|
||||
assert.throws(() => {
|
||||
add('foo', item);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
|
||||
assert.throws(() => {
|
||||
add(0, item);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
|
||||
assert.throws(() => {
|
||||
add(undefined, item);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
|
||||
assert.throws(() => {
|
||||
add(null, item);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
|
||||
assert.throws(() => {
|
||||
add(true, item);
|
||||
},
|
||||
/^\w+ is not a non-null object/,
|
||||
TypeError,
|
||||
'only non-null object are allowed');
|
||||
};
|
||||
|
||||
|
@ -46,6 +46,7 @@ var AdbController = {
|
||||
this.disableAdbTimer.cancel();
|
||||
} else {
|
||||
this.disableAdbTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
// eslint-disable-next-line mozilla/use-default-preference-values
|
||||
try {
|
||||
this.disableAdbTimeoutHours =
|
||||
Services.prefs.getIntPref("b2g.adb.timeout-hours");
|
||||
|
@ -427,12 +427,8 @@ setUpdateTrackingId();
|
||||
return;
|
||||
}
|
||||
// Gaia setting has not been set; set the gaia setting to default.
|
||||
let prefValue = AppConstants.MOZ_TELEMETRY_ON_BY_DEFAULT;
|
||||
try {
|
||||
prefValue = Services.prefs.getBoolPref(geckoPrefName);
|
||||
} catch (e) {
|
||||
// Pref not set; use default value.
|
||||
}
|
||||
let prefValue = Services.prefs.getBoolPref(geckoPrefName,
|
||||
AppConstants.MOZ_TELEMETRY_ON_BY_DEFAULT);
|
||||
let setting = {};
|
||||
setting[gaiaSettingName] = prefValue;
|
||||
window.navigator.mozSettings.createLock().set(setting);
|
||||
|
@ -256,15 +256,11 @@ var shell = {
|
||||
// If --start-manifest hasn't been specified, we re-use the latest specified manifest.
|
||||
// If it's the first launch, we will fallback to b2g.default.start_manifest_url
|
||||
if (AppConstants.MOZ_GRAPHENE && !startManifestURL) {
|
||||
try {
|
||||
startManifestURL = Services.prefs.getCharPref("b2g.system_manifest_url");
|
||||
} catch(e) {}
|
||||
startManifestURL = Services.prefs.getCharPref("b2g.system_manifest_url", "");
|
||||
}
|
||||
|
||||
if (!startManifestURL) {
|
||||
try {
|
||||
startManifestURL = Services.prefs.getCharPref("b2g.default.start_manifest_url");
|
||||
} catch(e) {}
|
||||
startManifestURL = Services.prefs.getCharPref("b2g.default.start_manifest_url", "");
|
||||
}
|
||||
|
||||
if (startManifestURL) {
|
||||
|
@ -47,10 +47,7 @@ this.AboutServiceWorkers = {
|
||||
if (this._enabled) {
|
||||
return this._enabled;
|
||||
}
|
||||
this._enabled = false;
|
||||
try {
|
||||
this._enabled = Services.prefs.getBoolPref("dom.serviceWorkers.enabled");
|
||||
} catch(e) {}
|
||||
this._enabled = Services.prefs.getBoolPref("dom.serviceWorkers.enabled", false);
|
||||
return this._enabled;
|
||||
},
|
||||
|
||||
|
@ -75,6 +75,7 @@ this.Bootstraper = {
|
||||
return Promise.resolve();
|
||||
|
||||
let oldManifestURL;
|
||||
// eslint-disable-next-line mozilla/use-default-preference-values
|
||||
try{
|
||||
oldManifestURL = Services.prefs.getCharPref("b2g.system_manifest_url");
|
||||
} catch(e) {
|
||||
|
@ -113,13 +113,7 @@ DirectoryProvider.prototype = {
|
||||
// path from the parent, and it is then used to build
|
||||
// jar:remoteopenfile:// uris.
|
||||
if (prop == "coreAppsDir") {
|
||||
let coreAppsDirPref;
|
||||
try {
|
||||
coreAppsDirPref = Services.prefs.getCharPref(COREAPPSDIR_PREF);
|
||||
} catch (e) {
|
||||
// coreAppsDirPref may not exist if we're on an older version
|
||||
// of gaia, so just fail silently.
|
||||
}
|
||||
let coreAppsDirPref = Services.prefs.getCharPref(COREAPPSDIR_PREF, "");
|
||||
let appsDir;
|
||||
// If pref doesn't exist or isn't set, default to old value
|
||||
if (!coreAppsDirPref || coreAppsDirPref == "") {
|
||||
|
@ -94,12 +94,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
|
||||
// There's no point in setting up an observer to monitor the pref, as b2g prefs
|
||||
// can only be overwritten when the profie is recreated. So just get the value
|
||||
// on start-up.
|
||||
var kPersonaUri = "https://firefoxos.persona.org";
|
||||
try {
|
||||
kPersonaUri = Services.prefs.getCharPref("toolkit.identity.uri");
|
||||
} catch(noSuchPref) {
|
||||
// stick with the default value
|
||||
}
|
||||
var kPersonaUri = Services.prefs.getCharPref("toolkit.identity.uri",
|
||||
"https://firefoxos.persona.org");
|
||||
|
||||
// JS shim that contains the callback functions that
|
||||
// live within the identity UI provisioning frame.
|
||||
|
@ -432,14 +432,9 @@ function migrateToDevEdition(urlParams) {
|
||||
try {
|
||||
defaultProfilePath = window.getDefaultProfilePath();
|
||||
} catch (e) {} // no default profile.
|
||||
let migrateSyncCreds = false;
|
||||
if (defaultProfilePath) {
|
||||
try {
|
||||
migrateSyncCreds = Services.prefs.getBoolPref("identity.fxaccounts.migrateToDevEdition");
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (!migrateSyncCreds) {
|
||||
if (!defaultProfilePath ||
|
||||
!Services.prefs.getBoolPref("identity.fxaccounts.migrateToDevEdition", false)) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
|
@ -157,10 +157,7 @@ var gFxAccounts = {
|
||||
|
||||
// Note that updateUI() returns a Promise that's only used by tests.
|
||||
updateUI() {
|
||||
let profileInfoEnabled = false;
|
||||
try {
|
||||
profileInfoEnabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled");
|
||||
} catch (e) { }
|
||||
let profileInfoEnabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled", false);
|
||||
|
||||
this.panelUIFooter.hidden = false;
|
||||
|
||||
|
@ -297,10 +297,7 @@ var gSyncUI = {
|
||||
*/
|
||||
maybeMoveSyncedTabsButton() {
|
||||
const prefName = "browser.migrated-sync-button";
|
||||
let migrated = false;
|
||||
try {
|
||||
migrated = Services.prefs.getBoolPref(prefName);
|
||||
} catch (_) {}
|
||||
let migrated = Services.prefs.getBoolPref(prefName, false);
|
||||
if (migrated) {
|
||||
return;
|
||||
}
|
||||
|
@ -2793,15 +2793,10 @@ var gMenuButtonUpdateBadge = {
|
||||
cancelObserverRegistered: false,
|
||||
|
||||
init() {
|
||||
try {
|
||||
this.enabled = Services.prefs.getBoolPref("app.update.badge");
|
||||
} catch (e) {}
|
||||
this.enabled = Services.prefs.getBoolPref("app.update.badge", false);
|
||||
if (this.enabled) {
|
||||
try {
|
||||
this.badgeWaitTime = Services.prefs.getIntPref("app.update.badgeWaitTime");
|
||||
} catch (e) {
|
||||
this.badgeWaitTime = 345600; // 4 days
|
||||
}
|
||||
this.badgeWaitTime = Services.prefs.getIntPref("app.update.badgeWaitTime",
|
||||
345600); // 4 days
|
||||
Services.obs.addObserver(this, "update-staged", false);
|
||||
Services.obs.addObserver(this, "update-downloaded", false);
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
hidden="true"
|
||||
orient="vertical"
|
||||
noautofocus="true"
|
||||
followanchor="false"
|
||||
role="alert"/>
|
||||
|
||||
<popupnotification id="webRTC-shareDevices-notification" hidden="true">
|
||||
|
@ -302,12 +302,7 @@ var RemoteTabViewer = {
|
||||
_refetchTabs(force) {
|
||||
if (!force) {
|
||||
// Don't bother refetching tabs if we already did so recently
|
||||
let lastFetch = 0;
|
||||
try {
|
||||
lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch");
|
||||
} catch (e) {
|
||||
/* Just use the default value of 0 */
|
||||
}
|
||||
let lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch", 0);
|
||||
|
||||
let now = Math.floor(Date.now() / 1000);
|
||||
if (now - lastFetch < 30) {
|
||||
|
@ -4470,11 +4470,7 @@
|
||||
return true;
|
||||
if (this._logInit)
|
||||
return this._shouldLog;
|
||||
let result = false;
|
||||
try {
|
||||
result = Services.prefs.getBoolPref("browser.tabs.remote.logSwitchTiming");
|
||||
} catch (ex) {
|
||||
}
|
||||
let result = Services.prefs.getBoolPref("browser.tabs.remote.logSwitchTiming", false);
|
||||
this._shouldLog = result;
|
||||
this._logInit = true;
|
||||
return this._shouldLog;
|
||||
@ -5647,11 +5643,7 @@
|
||||
window.addEventListener("resize", this);
|
||||
window.addEventListener("load", this);
|
||||
|
||||
try {
|
||||
this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled");
|
||||
} catch (ex) {
|
||||
this._tabAnimationLoggingEnabled = false;
|
||||
}
|
||||
this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled", false);
|
||||
this._browserNewtabpageEnabled = Services.prefs.getBoolPref("browser.newtabpage.enabled");
|
||||
Services.prefs.addObserver("privacy.userContext", this, false);
|
||||
this.observe(null, "nsPref:changed", "privacy.userContext.enabled");
|
||||
|
@ -2,11 +2,7 @@ var offlineByDefault = {
|
||||
defaultValue: false,
|
||||
prefBranch: SpecialPowers.Cc["@mozilla.org/preferences-service;1"].getService(SpecialPowers.Ci.nsIPrefBranch),
|
||||
set(allow) {
|
||||
try {
|
||||
this.defaultValue = this.prefBranch.getBoolPref("offline-apps.allow_by_default");
|
||||
} catch (e) {
|
||||
this.defaultValue = false
|
||||
}
|
||||
this.defaultValue = this.prefBranch.getBoolPref("offline-apps.allow_by_default", false);
|
||||
this.prefBranch.setBoolPref("offline-apps.allow_by_default", allow);
|
||||
},
|
||||
reset() {
|
||||
|
@ -158,10 +158,7 @@ var gUIStateBeforeReset = {
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let scope = {};
|
||||
Cu.import("resource://gre/modules/Console.jsm", scope);
|
||||
let debug;
|
||||
try {
|
||||
debug = Services.prefs.getBoolPref(kPrefCustomizationDebug);
|
||||
} catch (ex) {}
|
||||
let debug = Services.prefs.getBoolPref(kPrefCustomizationDebug, false);
|
||||
let consoleOptions = {
|
||||
maxLogLevel: debug ? "all" : "log",
|
||||
prefix: "CustomizableUI",
|
||||
@ -1926,16 +1923,10 @@ var CustomizableUIInternal = {
|
||||
// state immediately when a browser window opens, which is important for
|
||||
// other consumers of this API.
|
||||
loadSavedState() {
|
||||
let state = null;
|
||||
try {
|
||||
state = Services.prefs.getCharPref(kPrefCustomizationState);
|
||||
} catch (e) {
|
||||
log.debug("No saved state found");
|
||||
// This will fail if nothing has been customized, so silently fall back to
|
||||
// the defaults.
|
||||
}
|
||||
|
||||
let state = Services.prefs.getCharPref(kPrefCustomizationState, "");
|
||||
if (!state) {
|
||||
log.debug("No saved state found");
|
||||
// Nothing has been customized, so silently fall back to the defaults.
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@ -2220,10 +2211,7 @@ var CustomizableUIInternal = {
|
||||
this.notifyListeners("onWidgetAdded", widget.id, widget.currentArea,
|
||||
widget.currentPosition);
|
||||
} else if (widgetMightNeedAutoAdding) {
|
||||
let autoAdd = true;
|
||||
try {
|
||||
autoAdd = Services.prefs.getBoolPref(kPrefCustomizationAutoAdd);
|
||||
} catch (e) {}
|
||||
let autoAdd = Services.prefs.getBoolPref(kPrefCustomizationAutoAdd, true);
|
||||
|
||||
// If the widget doesn't have an existing placement, and it hasn't been
|
||||
// seen before, then add it to its default area so it can be used.
|
||||
|
@ -46,10 +46,7 @@ const kWidePanelItemClass = "panel-wide-item";
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let scope = {};
|
||||
Cu.import("resource://gre/modules/Console.jsm", scope);
|
||||
let debug;
|
||||
try {
|
||||
debug = Services.prefs.getBoolPref(kPrefCustomizationDebug);
|
||||
} catch (ex) {}
|
||||
let debug = Services.prefs.getBoolPref(kPrefCustomizationDebug, false);
|
||||
let consoleOptions = {
|
||||
maxLogLevel: debug ? "all" : "log",
|
||||
prefix: "CustomizableWidgets",
|
||||
|
@ -42,9 +42,7 @@ let gDebug;
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let scope = {};
|
||||
Cu.import("resource://gre/modules/Console.jsm", scope);
|
||||
try {
|
||||
gDebug = Services.prefs.getBoolPref(kPrefCustomizationDebug);
|
||||
} catch (ex) {}
|
||||
gDebug = Services.prefs.getBoolPref(kPrefCustomizationDebug, false);
|
||||
let consoleOptions = {
|
||||
maxLogLevel: gDebug ? "all" : "log",
|
||||
prefix: "CustomizeMode",
|
||||
@ -624,11 +622,8 @@ CustomizeMode.prototype = {
|
||||
},
|
||||
|
||||
maybeShowTip(aAnchor) {
|
||||
let shown = false;
|
||||
const kShownPref = "browser.customizemode.tip0.shown";
|
||||
try {
|
||||
shown = Services.prefs.getBoolPref(kShownPref);
|
||||
} catch (ex) {}
|
||||
let shown = Services.prefs.getBoolPref(kShownPref, false);
|
||||
if (shown)
|
||||
return;
|
||||
|
||||
@ -1502,10 +1497,7 @@ CustomizeMode.prototype = {
|
||||
if (!AppConstants.CAN_DRAW_IN_TITLEBAR) {
|
||||
return;
|
||||
}
|
||||
let drawInTitlebar = true;
|
||||
try {
|
||||
drawInTitlebar = Services.prefs.getBoolPref(kDrawInTitlebarPref);
|
||||
} catch (ex) { }
|
||||
let drawInTitlebar = Services.prefs.getBoolPref(kDrawInTitlebarPref, true);
|
||||
let button = this.document.getElementById("customization-titlebar-visibility-button");
|
||||
// Drawing in the titlebar means 'hiding' the titlebar:
|
||||
if (drawInTitlebar) {
|
||||
|
@ -81,10 +81,7 @@ function test() {
|
||||
continue;
|
||||
}
|
||||
let pref = "browser.toolbarbuttons.introduced." + placements[i];
|
||||
let introduced = false;
|
||||
try {
|
||||
introduced = Services.prefs.getBoolPref(pref);
|
||||
} catch (ex) {}
|
||||
let introduced = Services.prefs.getBoolPref(pref, false);
|
||||
if (!introduced) {
|
||||
i++;
|
||||
continue;
|
||||
|
@ -22,10 +22,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
this.DistributionCustomizer = function DistributionCustomizer() {
|
||||
// For parallel xpcshell testing purposes allow loading the distribution.ini
|
||||
// file from the profile folder through an hidden pref.
|
||||
let loadFromProfile = false;
|
||||
try {
|
||||
loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile");
|
||||
} catch (ex) {}
|
||||
let loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile", false);
|
||||
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
try {
|
||||
@ -60,12 +57,7 @@ DistributionCustomizer.prototype = {
|
||||
},
|
||||
|
||||
get _locale() {
|
||||
let locale;
|
||||
try {
|
||||
locale = this._prefs.getCharPref("general.useragent.locale");
|
||||
} catch (e) {
|
||||
locale = "en-US";
|
||||
}
|
||||
let locale = this._prefs.getCharPref("general.useragent.locale", "en-US");
|
||||
this.__defineGetter__("_locale", () => locale);
|
||||
return this._locale;
|
||||
},
|
||||
@ -289,10 +281,7 @@ DistributionCustomizer.prototype = {
|
||||
this._ini.getString("Global", "id") + ".bookmarksProcessed";
|
||||
}
|
||||
|
||||
let bmProcessed = false;
|
||||
try {
|
||||
bmProcessed = this._prefs.getBoolPref(bmProcessedPref);
|
||||
} catch (e) {}
|
||||
let bmProcessed = this._prefs.getBoolPref(bmProcessedPref, false);
|
||||
|
||||
if (!bmProcessed) {
|
||||
if (sections["BookmarksMenu"])
|
||||
|
@ -19,11 +19,7 @@ function LOG(str) {
|
||||
let prefB = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
|
||||
let shouldLog = false;
|
||||
try {
|
||||
shouldLog = prefB.getBoolPref("feeds.log");
|
||||
} catch (ex) {
|
||||
}
|
||||
let shouldLog = prefB.getBoolPref("feeds.log", false);
|
||||
|
||||
if (shouldLog)
|
||||
dump("*** Feeds: " + str + "\n");
|
||||
@ -697,10 +693,7 @@ FeedWriter.prototype = {
|
||||
|
||||
_setSelectedHandler(feedType) {
|
||||
let prefs = Services.prefs;
|
||||
let handler = "bookmarks";
|
||||
try {
|
||||
handler = prefs.getCharPref(getPrefReaderForType(feedType));
|
||||
} catch (ex) { }
|
||||
let handler = prefs.getCharPref(getPrefReaderForType(feedType), "bookmarks");
|
||||
|
||||
switch (handler) {
|
||||
case "web": {
|
||||
@ -835,10 +828,7 @@ FeedWriter.prototype = {
|
||||
.addEventListener("click", this);
|
||||
|
||||
// first-run ui
|
||||
let showFirstRunUI = true;
|
||||
try {
|
||||
showFirstRunUI = Services.prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI);
|
||||
} catch (ex) { }
|
||||
let showFirstRunUI = Services.prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI, true);
|
||||
if (showFirstRunUI) {
|
||||
let textfeedinfo1, textfeedinfo2;
|
||||
switch (feedType) {
|
||||
|
@ -183,12 +183,9 @@ const Utils = {
|
||||
|
||||
// check if it is in the black list
|
||||
let pb = Services.prefs;
|
||||
let allowed;
|
||||
try {
|
||||
allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol);
|
||||
} catch (e) {
|
||||
allowed = pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default");
|
||||
}
|
||||
let allowed =
|
||||
pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "." + aProtocol,
|
||||
pb.getBoolPref(PREF_HANDLER_EXTERNAL_PREFIX + "-default"));
|
||||
if (!allowed) {
|
||||
throw this.getSecurityError(
|
||||
`Not allowed to register a protocol handler for ${aProtocol}`,
|
||||
|
@ -98,20 +98,14 @@ const OVERRIDE_NEW_BUILD_ID = 3;
|
||||
* OVERRIDE_NONE otherwise.
|
||||
*/
|
||||
function needHomepageOverride(prefb) {
|
||||
var savedmstone = null;
|
||||
try {
|
||||
savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone");
|
||||
} catch (e) {}
|
||||
var savedmstone = prefb.getCharPref("browser.startup.homepage_override.mstone", "");
|
||||
|
||||
if (savedmstone == "ignore")
|
||||
return OVERRIDE_NONE;
|
||||
|
||||
var mstone = Services.appinfo.platformVersion;
|
||||
|
||||
var savedBuildID = null;
|
||||
try {
|
||||
savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID");
|
||||
} catch (e) {}
|
||||
var savedBuildID = prefb.getCharPref("browser.startup.homepage_override.buildID", "");
|
||||
|
||||
var buildID = Services.appinfo.platformBuildID;
|
||||
|
||||
@ -484,10 +478,7 @@ nsBrowserContentHandler.prototype = {
|
||||
// URL if we do end up showing an overridePage. This makes it possible
|
||||
// to have the overridePage's content vary depending on the version we're
|
||||
// upgrading from.
|
||||
let old_mstone = "unknown";
|
||||
try {
|
||||
old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
|
||||
} catch (ex) {}
|
||||
let old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone", "unknown");
|
||||
override = needHomepageOverride(prefb);
|
||||
if (override != OVERRIDE_NONE) {
|
||||
switch (override) {
|
||||
|
@ -935,10 +935,7 @@ BrowserGlue.prototype = {
|
||||
// Offer to reset a user's profile if it hasn't been used for 60 days.
|
||||
const OFFER_PROFILE_RESET_INTERVAL_MS = 60 * 24 * 60 * 60 * 1000;
|
||||
let lastUse = Services.appinfo.replacedLockTime;
|
||||
let disableResetPrompt = false;
|
||||
try {
|
||||
disableResetPrompt = Services.prefs.getBoolPref("browser.disableResetPrompt");
|
||||
} catch (e) {}
|
||||
let disableResetPrompt = Services.prefs.getBoolPref("browser.disableResetPrompt", false);
|
||||
|
||||
if (!disableResetPrompt && lastUse &&
|
||||
Date.now() - lastUse >= OFFER_PROFILE_RESET_INTERVAL_MS) {
|
||||
@ -1456,10 +1453,7 @@ BrowserGlue.prototype = {
|
||||
} catch (ex) {}
|
||||
|
||||
// Support legacy bookmarks.html format for apps that depend on that format.
|
||||
let autoExportHTML = false;
|
||||
try {
|
||||
autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML");
|
||||
} catch (ex) {} // Do not export.
|
||||
let autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML", false); // Do not export.
|
||||
if (autoExportHTML) {
|
||||
// Sqlite.jsm and Places shutdown happen at profile-before-change, thus,
|
||||
// to be on the safe side, this should run earlier.
|
||||
@ -1526,10 +1520,7 @@ BrowserGlue.prototype = {
|
||||
// An import operation is about to run.
|
||||
// Don't try to recreate smart bookmarks if autoExportHTML is true or
|
||||
// smart bookmarks are disabled.
|
||||
let smartBookmarksVersion = 0;
|
||||
try {
|
||||
smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion");
|
||||
} catch (ex) {}
|
||||
let smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion", 0);
|
||||
if (!autoExportHTML && smartBookmarksVersion != -1)
|
||||
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
|
||||
|
||||
@ -1876,10 +1867,7 @@ BrowserGlue.prototype = {
|
||||
// Refactor urlbar suggestion preferences to make it extendable and
|
||||
// allow new suggestion types (e.g: search suggestions).
|
||||
let types = ["history", "bookmark", "openpage"];
|
||||
let defaultBehavior = 0;
|
||||
try {
|
||||
defaultBehavior = Services.prefs.getIntPref("browser.urlbar.default.behavior");
|
||||
} catch (ex) {}
|
||||
let defaultBehavior = Services.prefs.getIntPref("browser.urlbar.default.behavior", 0);
|
||||
try {
|
||||
let autocompleteEnabled = Services.prefs.getBoolPref("browser.urlbar.autocomplete.enabled");
|
||||
if (!autocompleteEnabled) {
|
||||
@ -2018,10 +2006,7 @@ BrowserGlue.prototype = {
|
||||
}
|
||||
|
||||
if (currentUIVersion < 43) {
|
||||
let currentTheme = null;
|
||||
try {
|
||||
currentTheme = Services.prefs.getCharPref("lightweightThemes.selectedThemeID");
|
||||
} catch (e) {}
|
||||
let currentTheme = Services.prefs.getCharPref("lightweightThemes.selectedThemeID", "");
|
||||
if (currentTheme == "firefox-devedition@mozilla.org") {
|
||||
let newTheme = Services.prefs.getCharPref("devtools.theme") == "dark" ?
|
||||
"firefox-compact-dark@mozilla.org" : "firefox-compact-light@mozilla.org";
|
||||
@ -2099,10 +2084,7 @@ BrowserGlue.prototype = {
|
||||
const MAX_RESULTS = 10;
|
||||
|
||||
// Get current smart bookmarks version. If not set, create them.
|
||||
let smartBookmarksCurrentVersion = 0;
|
||||
try {
|
||||
smartBookmarksCurrentVersion = Services.prefs.getIntPref(SMART_BOOKMARKS_PREF);
|
||||
} catch (ex) {}
|
||||
let smartBookmarksCurrentVersion = Services.prefs.getIntPref(SMART_BOOKMARKS_PREF, 0);
|
||||
|
||||
// If version is current, or smart bookmarks are disabled, bail out.
|
||||
if (smartBookmarksCurrentVersion == -1 ||
|
||||
|
@ -74,22 +74,14 @@ var gSyncPane = {
|
||||
},
|
||||
|
||||
_showLoadPage(xps) {
|
||||
let username;
|
||||
try {
|
||||
username = Services.prefs.getCharPref("services.sync.username");
|
||||
} catch (e) {}
|
||||
let username = Services.prefs.getCharPref("services.sync.username", "");
|
||||
if (!username) {
|
||||
this.page = FXA_PAGE_LOGGED_OUT;
|
||||
return;
|
||||
}
|
||||
|
||||
// Use cached values while we wait for the up-to-date values
|
||||
let cachedComputerName;
|
||||
try {
|
||||
cachedComputerName = Services.prefs.getCharPref("services.sync.client.name");
|
||||
} catch (e) {
|
||||
cachedComputerName = "";
|
||||
}
|
||||
let cachedComputerName = Services.prefs.getCharPref("services.sync.client.name", "");
|
||||
document.getElementById("fxaEmailAddress1").textContent = username;
|
||||
this._populateComputerName(cachedComputerName);
|
||||
this.page = FXA_PAGE_LOGGED_IN;
|
||||
@ -251,10 +243,7 @@ var gSyncPane = {
|
||||
fxaEmailAddress1Label.hidden = false;
|
||||
displayNameLabel.hidden = true;
|
||||
|
||||
let profileInfoEnabled;
|
||||
try {
|
||||
profileInfoEnabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled");
|
||||
} catch (ex) {}
|
||||
let profileInfoEnabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled", false);
|
||||
|
||||
// determine the fxa status...
|
||||
this._showLoadPage(service);
|
||||
|
@ -26,7 +26,6 @@ tags = trackingprotection
|
||||
[browser_privatebrowsing_cache.js]
|
||||
[browser_privatebrowsing_certexceptionsui.js]
|
||||
[browser_privatebrowsing_concurrent.js]
|
||||
skip-if = e10s # Bug 1315042
|
||||
[browser_privatebrowsing_context_and_chromeFlags.js]
|
||||
[browser_privatebrowsing_crh.js]
|
||||
[browser_privatebrowsing_downloadLastDir.js]
|
||||
|
@ -62,7 +62,7 @@ add_task(function* test() {
|
||||
private_browser = private_window.getBrowser().selectedBrowser;
|
||||
|
||||
private_browser.loadURI(prefix + "?action=get&name=test2");
|
||||
yield BrowserTestUtils.browserLoaded(private_browser);
|
||||
yield BrowserTestUtils.browserLoaded(private_browser, false, prefix + "?action=get&name=test2");
|
||||
elts = yield getElts(private_browser);
|
||||
isnot(elts[0], "value2", "public window shouldn't see cleared private storage");
|
||||
is(elts[1], "1", "public window should only see public items");
|
||||
|
@ -1795,10 +1795,8 @@ this.UITour = {
|
||||
// Identifier of the partner repack, as stored in preference "distribution.id"
|
||||
// and included in Firefox and other update pings. Note this is not the same as
|
||||
// Services.appinfo.distributionID (value of MOZ_DISTRIBUTION_ID is set at build time).
|
||||
let distribution = "default";
|
||||
try {
|
||||
distribution = Services.prefs.getDefaultBranch("distribution.").getCharPref("id");
|
||||
} catch (e) {}
|
||||
let distribution =
|
||||
Services.prefs.getDefaultBranch("distribution.").getCharPref("id", "default");
|
||||
appinfo["distribution"] = distribution;
|
||||
|
||||
let isDefaultBrowser = null;
|
||||
|
@ -600,10 +600,7 @@ this.BrowserUITelemetry = {
|
||||
getSyncState() {
|
||||
let result = {};
|
||||
for (let sub of ["desktop", "mobile"]) {
|
||||
let count = 0;
|
||||
try {
|
||||
count = Services.prefs.getIntPref("services.sync.clients.devices." + sub);
|
||||
} catch (ex) {}
|
||||
let count = Services.prefs.getIntPref("services.sync.clients.devices." + sub, 0);
|
||||
result[sub] = count;
|
||||
}
|
||||
return result;
|
||||
|
@ -188,10 +188,7 @@ var DirectoryLinksProvider = {
|
||||
* @return the selected locale or "en-US" if none is selected
|
||||
*/
|
||||
get locale() {
|
||||
let matchOS;
|
||||
try {
|
||||
matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE);
|
||||
} catch (e) {}
|
||||
let matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE, false);
|
||||
|
||||
if (matchOS) {
|
||||
return Cc["@mozilla.org/intl/ospreferences;1"].
|
||||
|
@ -211,16 +211,11 @@ var ActiveProviders = {
|
||||
};
|
||||
|
||||
function migrateSettings() {
|
||||
let activeProviders, enabled;
|
||||
try {
|
||||
activeProviders = Services.prefs.getCharPref("social.activeProviders");
|
||||
} catch (e) {
|
||||
// not set, we'll check if we need to migrate older prefs
|
||||
}
|
||||
let enabled;
|
||||
if (Services.prefs.prefHasUserValue("social.enabled")) {
|
||||
enabled = Services.prefs.getBoolPref("social.enabled");
|
||||
}
|
||||
if (activeProviders) {
|
||||
if (Services.prefs.getCharPref("social.activeProviders", "")) {
|
||||
// migration from fx21 to fx22 or later
|
||||
// ensure any *builtin* provider in activeproviders is in user level prefs
|
||||
for (let origin in ActiveProviders._providers) {
|
||||
@ -284,10 +279,7 @@ function migrateSettings() {
|
||||
}
|
||||
|
||||
// primary migration from pre-fx21
|
||||
let active;
|
||||
try {
|
||||
active = Services.prefs.getBoolPref("social.active");
|
||||
} catch (e) {}
|
||||
let active = Services.prefs.getBoolPref("social.active", false);
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
|
@ -193,12 +193,7 @@ DevTools.prototype = {
|
||||
return tool;
|
||||
}
|
||||
|
||||
let enabled;
|
||||
try {
|
||||
enabled = Services.prefs.getBoolPref(tool.visibilityswitch);
|
||||
} catch (e) {
|
||||
enabled = true;
|
||||
}
|
||||
let enabled = Services.prefs.getBoolPref(tool.visibilityswitch, true);
|
||||
|
||||
return enabled ? tool : null;
|
||||
},
|
||||
|
@ -100,17 +100,13 @@ function openToolbox({ form, chrome, isTabActor }) {
|
||||
};
|
||||
TargetFactory.forRemoteTab(options).then(target => {
|
||||
let frame = document.getElementById("toolbox-iframe");
|
||||
let selectedTool = "jsdebugger";
|
||||
|
||||
try {
|
||||
// Remember the last panel that was used inside of this profile.
|
||||
selectedTool = Services.prefs.getCharPref("devtools.toolbox.selectedTool");
|
||||
} catch(e) {}
|
||||
|
||||
try {
|
||||
// But if we are testing, then it should always open the debugger panel.
|
||||
selectedTool = Services.prefs.getCharPref("devtools.browsertoolbox.panel");
|
||||
} catch(e) {}
|
||||
// Remember the last panel that was used inside of this profile.
|
||||
// But if we are testing, then it should always open the debugger panel.
|
||||
let selectedTool =
|
||||
Services.prefs.getCharPref("devtools.browsertoolbox.panel",
|
||||
Services.prefs.getCharPref("devtools.toolbox.selectedTool",
|
||||
"jsdebugger"));
|
||||
|
||||
let options = { customIframe: frame };
|
||||
gDevTools.showToolbox(target,
|
||||
|
@ -1226,12 +1226,7 @@ Toolbox.prototype = {
|
||||
visibilityswitch
|
||||
} = button;
|
||||
|
||||
let visible = true;
|
||||
try {
|
||||
visible = Services.prefs.getBoolPref(visibilityswitch);
|
||||
} catch (ex) {
|
||||
// Do nothing.
|
||||
}
|
||||
let visible = Services.prefs.getBoolPref(visibilityswitch, true);
|
||||
|
||||
if (isTargetSupported) {
|
||||
return visible && isTargetSupported(this.target);
|
||||
|
@ -71,11 +71,8 @@ function MarkupView(inspector, frame, controllerWindow) {
|
||||
this.doc = this._frame.contentDocument;
|
||||
this._elt = this.doc.querySelector("#root");
|
||||
|
||||
try {
|
||||
this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize");
|
||||
} catch (ex) {
|
||||
this.maxChildren = DEFAULT_MAX_CHILDREN;
|
||||
}
|
||||
this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize",
|
||||
DEFAULT_MAX_CHILDREN);
|
||||
|
||||
this.collapseAttributes =
|
||||
Services.prefs.getBoolPref(ATTR_COLLAPSE_ENABLED_PREF);
|
||||
|
@ -21,19 +21,8 @@ var systemAppOrigin = (function () {
|
||||
return systemOrigin;
|
||||
})();
|
||||
|
||||
var threshold = 25;
|
||||
try {
|
||||
threshold = Services.prefs.getIntPref("ui.dragThresholdX");
|
||||
} catch (e) {
|
||||
// Fall back to default value
|
||||
}
|
||||
|
||||
var delay = 500;
|
||||
try {
|
||||
delay = Services.prefs.getIntPref("ui.click_hold_context_menus.delay");
|
||||
} catch (e) {
|
||||
// Fall back to default value
|
||||
}
|
||||
var threshold = Services.prefs.getIntPref("ui.dragThresholdX", 25);
|
||||
var delay = Services.prefs.getIntPref("ui.click_hold_context_menus.delay", 500);
|
||||
|
||||
function SimulatorCore(simulatorTarget) {
|
||||
this.simulatorTarget = simulatorTarget;
|
||||
|
@ -10385,10 +10385,13 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
* call OnNewURI() so that, this traversal will be
|
||||
* recorded in session and global history.
|
||||
*/
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal, principalToInherit;
|
||||
nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit;
|
||||
if (mOSHE) {
|
||||
mOSHE->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
|
||||
mOSHE->GetPrincipalToInherit(getter_AddRefs(principalToInherit));
|
||||
mOSHE->GetTriggeringPrincipal(getter_AddRefs(newURITriggeringPrincipal));
|
||||
mOSHE->GetPrincipalToInherit(getter_AddRefs(newURIPrincipalToInherit));
|
||||
} else {
|
||||
newURITriggeringPrincipal = aTriggeringPrincipal;
|
||||
newURIPrincipalToInherit = doc->NodePrincipal();
|
||||
}
|
||||
// Pass true for aCloneSHChildren, since we're not
|
||||
// changing documents here, so all of our subframes are
|
||||
@ -10398,7 +10401,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
// flag on firing onLocationChange(...).
|
||||
// Anyway, aCloneSHChildren param is simply reflecting
|
||||
// doShortCircuitedLoad in this scope.
|
||||
OnNewURI(aURI, nullptr, triggeringPrincipal, principalToInherit,
|
||||
OnNewURI(aURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
|
||||
mLoadType, true, true, true);
|
||||
|
||||
nsCOMPtr<nsIInputStream> postData;
|
||||
|
6
docshell/test/dummy_page.html
Normal file
6
docshell/test/dummy_page.html
Normal file
@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
just a dummy html file
|
||||
</body>
|
||||
</html>
|
@ -11,6 +11,7 @@ support-files =
|
||||
bug668513_redirect.html
|
||||
bug668513_redirect.html^headers^
|
||||
bug691547_frame.html
|
||||
dummy_page.html
|
||||
file_anchor_scroll_after_document_open.html
|
||||
file_bug385434_1.html
|
||||
file_bug385434_2.html
|
||||
@ -92,3 +93,4 @@ skip-if = toolkit == 'android' # bug 784321
|
||||
support-files = file_framedhistoryframes.html
|
||||
[test_pushState_after_document_open.html]
|
||||
[test_windowedhistoryframes.html]
|
||||
[test_triggeringprincipal_location_seturi.html]
|
||||
|
102
docshell/test/test_triggeringprincipal_location_seturi.html
Normal file
102
docshell/test/test_triggeringprincipal_location_seturi.html
Normal file
@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const SAME_ORIGIN_URI = "http://mochi.test:8888/tests/docshell/test/dummy_page.html";
|
||||
const CROSS_ORIGIN_URI = "http://example.com/tests/docshell/test/dummy_page.html";
|
||||
const NUMBER_OF_TESTS = 3;
|
||||
let testCounter = 0;
|
||||
|
||||
function checkFinish() {
|
||||
testCounter++;
|
||||
if (testCounter < NUMBER_OF_TESTS) {
|
||||
return;
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// ---- test 1 ----
|
||||
|
||||
let myFrame1 = document.createElement("iframe");
|
||||
myFrame1.src = SAME_ORIGIN_URI;
|
||||
myFrame1.addEventListener("load", checkLoadFrame1);
|
||||
document.documentElement.appendChild(myFrame1);
|
||||
|
||||
function checkLoadFrame1() {
|
||||
myFrame1.removeEventListener('load', checkLoadFrame1, false);
|
||||
// window.location.href is no longer cross-origin accessible in gecko.
|
||||
is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, SAME_ORIGIN_URI,
|
||||
"initial same origin dummy loaded into frame1");
|
||||
|
||||
SpecialPowers.wrap(myFrame1.contentWindow).location.hash = "#bar";
|
||||
is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, SAME_ORIGIN_URI + "#bar",
|
||||
"initial same origin dummy#bar loaded into iframe1");
|
||||
|
||||
myFrame1.addEventListener("load", checkNavFrame1);
|
||||
myFrame1.src = CROSS_ORIGIN_URI;
|
||||
}
|
||||
|
||||
function checkNavFrame1() {
|
||||
myFrame1.removeEventListener('load', checkNavFrame1, false);
|
||||
is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, CROSS_ORIGIN_URI,
|
||||
"cross origin dummy loaded into frame1");
|
||||
|
||||
myFrame1.addEventListener("load", checkBackNavFrame1);
|
||||
myFrame1.src = SAME_ORIGIN_URI + "#bar";
|
||||
}
|
||||
|
||||
function checkBackNavFrame1() {
|
||||
myFrame1.removeEventListener('load', checkBackNavFrame1, false);
|
||||
is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, SAME_ORIGIN_URI + "#bar",
|
||||
"navagiating back to same origin dummy for frame1");
|
||||
checkFinish();
|
||||
}
|
||||
|
||||
// ---- test 2 ----
|
||||
|
||||
let myFrame2 = document.createElement("iframe");
|
||||
myFrame2.src = "about:blank";
|
||||
myFrame2.addEventListener("load", checkLoadFrame2);
|
||||
document.documentElement.appendChild(myFrame2);
|
||||
|
||||
function checkLoadFrame2() {
|
||||
myFrame2.removeEventListener('load', checkLoadFrame2, false);
|
||||
is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank",
|
||||
"initial about:blank frame loaded");
|
||||
|
||||
myFrame2.contentWindow.location.hash = "#foo";
|
||||
is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank#foo",
|
||||
"about:blank#foo frame loaded");
|
||||
|
||||
myFrame2.addEventListener('load', checkHistoryFrame2);
|
||||
myFrame2.src = "about:blank";
|
||||
}
|
||||
|
||||
function checkHistoryFrame2() {
|
||||
myFrame2.removeEventListener('load', checkHistoryFrame2, false);
|
||||
is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank",
|
||||
"about:blank frame loaded again");
|
||||
checkFinish();
|
||||
}
|
||||
|
||||
// ---- test 3 ----
|
||||
|
||||
let myFrame3 = document.createElement("frame");
|
||||
document.documentElement.appendChild(myFrame3);
|
||||
myFrame3.contentWindow.location.hash = "#foo";
|
||||
|
||||
is(myFrame3.contentWindow.location.href, "about:blank#foo",
|
||||
"created history entry with about:blank#foo");
|
||||
checkFinish();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -12,20 +12,10 @@ const PREF_BRANCH = BASE_PREF + ".";
|
||||
|
||||
// Utilities:
|
||||
function getMaxContentParents(processType) {
|
||||
let maxContentParents = -1;
|
||||
try {
|
||||
maxContentParents = Services.prefs.getIntPref(PREF_BRANCH + processType);
|
||||
} catch (e) {
|
||||
// Pref probably didn't exist, get the default number of processes.
|
||||
try {
|
||||
maxContentParents = Services.prefs.getIntPref(BASE_PREF);
|
||||
} catch (e) {
|
||||
// No prefs? That's odd, use only one process.
|
||||
maxContentParents = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return maxContentParents;
|
||||
// If the pref doesn't exist, get the default number of processes.
|
||||
// If there's no pref, use only one process.
|
||||
return Services.prefs.getIntPref(PREF_BRANCH + processType,
|
||||
Services.prefs.getIntPref(BASE_PREF, 1));
|
||||
}
|
||||
|
||||
// Fills up aProcesses until max and then selects randomly from the available
|
||||
@ -58,5 +48,36 @@ RandomSelector.prototype = {
|
||||
},
|
||||
};
|
||||
|
||||
var components = [RandomSelector];
|
||||
// Fills up aProcesses until max and then selects one from the available
|
||||
// ones that host the least number of tabs.
|
||||
function MinTabSelector() {
|
||||
}
|
||||
|
||||
MinTabSelector.prototype = {
|
||||
classID: Components.ID("{2dc08eaf-6eef-4394-b1df-a3a927c1290b}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentProcessProvider]),
|
||||
|
||||
provideProcess(aType, aOpener, aProcesses, aCount) {
|
||||
let maxContentParents = getMaxContentParents(aType);
|
||||
if (aCount < maxContentParents) {
|
||||
return Ci.nsIContentProcessProvider.NEW_PROCESS;
|
||||
}
|
||||
|
||||
let min = Number.MAX_VALUE;
|
||||
let candidate = Ci.nsIContentProcessProvider.NEW_PROCESS;
|
||||
|
||||
for (let i = 0; i < maxContentParents; i++) {
|
||||
let process = aProcesses[i];
|
||||
let tabCount = process.tabCount;
|
||||
if (process.opener === aOpener && tabCount < min) {
|
||||
min = tabCount;
|
||||
candidate = i;
|
||||
}
|
||||
}
|
||||
|
||||
return candidate;
|
||||
},
|
||||
};
|
||||
|
||||
var components = [RandomSelector, MinTabSelector];
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
||||
|
@ -1,2 +1,3 @@
|
||||
component {c616fcfd-9737-41f1-aa74-cee72a38f91b} ProcessSelector.js
|
||||
contract @mozilla.org/ipc/processselector;1 {c616fcfd-9737-41f1-aa74-cee72a38f91b}
|
||||
component {2dc08eaf-6eef-4394-b1df-a3a927c1290b} ProcessSelector.js
|
||||
contract @mozilla.org/ipc/processselector;1 {2dc08eaf-6eef-4394-b1df-a3a927c1290b}
|
||||
|
@ -2408,8 +2408,13 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument)
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(NS_IsAboutBlank(mDoc->GetDocumentURI()),
|
||||
"How'd this happen?");
|
||||
#ifdef DEBUG
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mDoc->GetDocumentURI()->CloneIgnoringRef(getter_AddRefs(uri));
|
||||
NS_ASSERTION(NS_IsAboutBlank(uri), "How'd this happen?");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Great, we're the original document, check for one of the other
|
||||
// conditions.
|
||||
|
@ -964,11 +964,7 @@ BrowserElementChild.prototype = {
|
||||
self._takeScreenshot(maxWidth, maxHeight, mimeType, domRequestID);
|
||||
};
|
||||
|
||||
let maxDelayMS = 2000;
|
||||
try {
|
||||
maxDelayMS = Services.prefs.getIntPref('dom.browserElement.maxScreenshotDelayMS');
|
||||
}
|
||||
catch(e) {}
|
||||
let maxDelayMS = Services.prefs.getIntPref('dom.browserElement.maxScreenshotDelayMS', 2000);
|
||||
|
||||
// Try to wait for the event loop to go idle before we take the screenshot,
|
||||
// but once we've waited maxDelayMS milliseconds, go ahead and take it
|
||||
@ -1649,10 +1645,7 @@ BrowserElementChild.prototype = {
|
||||
// certerror? If yes, maybe we should add a property to the
|
||||
// event to to indicate whether there is a custom page. That would
|
||||
// let the embedder have more control over the desired behavior.
|
||||
let errorPage = null;
|
||||
try {
|
||||
errorPage = Services.prefs.getCharPref(CERTIFICATE_ERROR_PAGE_PREF);
|
||||
} catch (e) {}
|
||||
let errorPage = Services.prefs.getCharPref(CERTIFICATE_ERROR_PAGE_PREF, "");
|
||||
|
||||
if (errorPage == 'certerror') {
|
||||
sendAsyncMsg('error', { type: 'certerror' });
|
||||
|
@ -31,14 +31,8 @@
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
for (var stage of [ "install", "startup", "shutdown", "uninstall" ]) {
|
||||
for (var symbol of [ "IDBKeyRange", "indexedDB" ]) {
|
||||
let pref;
|
||||
try {
|
||||
pref = Services.prefs.getBoolPref("indexeddbtest.bootstrap." + stage +
|
||||
"." + symbol);
|
||||
}
|
||||
catch(ex) {
|
||||
pref = false;
|
||||
}
|
||||
let pref = Services.prefs.getBoolPref("indexeddbtest.bootstrap." + stage +
|
||||
"." + symbol, false);
|
||||
ok(pref, "Symbol '" + symbol + "' present during '" + stage + "'");
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,11 @@ interface nsIContentProcessInfo : nsISupports
|
||||
*/
|
||||
readonly attribute nsIContentProcessInfo opener;
|
||||
|
||||
/**
|
||||
* Number of opened tabs living in this content process.
|
||||
*/
|
||||
readonly attribute int32_t tabCount;
|
||||
|
||||
/**
|
||||
* The process manager for this ContentParent (so a process message manager
|
||||
* as opposed to a frame message manager.
|
||||
|
@ -603,10 +603,6 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
||||
|
||||
SetProcessName(NS_LITERAL_STRING("Web Content"), true);
|
||||
|
||||
nsTArray<mozilla::dom::GfxInfoFeatureStatus> featureStatus;
|
||||
SendGetGfxInfoFeatureStatus(&featureStatus);
|
||||
GfxInfoBase::SetFeatureStatus(featureStatus);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1033,6 +1029,8 @@ ContentChild::InitXPCOM(const XPCOMInitData& aXPCOMInit,
|
||||
|
||||
// This will register cross-process observer.
|
||||
mozilla::dom::time::InitializeDateCacheCleaner();
|
||||
|
||||
GfxInfoBase::SetFeatureStatus(aXPCOMInit.gfxFeatureStatus());
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
|
@ -505,6 +505,19 @@ ScriptableCPInfo::GetOpener(nsIContentProcessInfo** aInfo)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScriptableCPInfo::GetTabCount(int32_t* aTabCount)
|
||||
{
|
||||
if (!mContentParent) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
*aTabCount = cpm->GetTabParentCountByProcessId(mContentParent->ChildID());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScriptableCPInfo::GetMessageManager(nsIMessageSender** aMessenger)
|
||||
{
|
||||
@ -757,23 +770,28 @@ ContentParent::ReleaseCachedProcesses()
|
||||
}
|
||||
|
||||
/*static*/ already_AddRefed<ContentParent>
|
||||
ContentParent::RandomSelect(const nsTArray<ContentParent*>& aContentParents,
|
||||
ContentParent::MinTabSelect(const nsTArray<ContentParent*>& aContentParents,
|
||||
ContentParent* aOpener, int32_t aMaxContentParents)
|
||||
{
|
||||
uint32_t maxSelectable = std::min(static_cast<uint32_t>(aContentParents.Length()),
|
||||
static_cast<uint32_t>(aMaxContentParents));
|
||||
uint32_t startIdx = rand() % maxSelectable;
|
||||
uint32_t currIdx = startIdx;
|
||||
do {
|
||||
RefPtr<ContentParent> p = aContentParents[currIdx];
|
||||
uint32_t min = INT_MAX;
|
||||
RefPtr<ContentParent> candidate;
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
|
||||
for (uint32_t i = 0; i < maxSelectable; i++) {
|
||||
ContentParent* p = aContentParents[i];
|
||||
NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in sBrowserContentParents?");
|
||||
if (p->mOpener == aOpener) {
|
||||
return p.forget();
|
||||
uint32_t tabCount = cpm->GetTabParentCountByProcessId(p->ChildID());
|
||||
if (tabCount < min) {
|
||||
candidate = p;
|
||||
min = tabCount;
|
||||
}
|
||||
}
|
||||
currIdx = (currIdx + 1) % maxSelectable;
|
||||
} while (currIdx != startIdx);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return candidate.forget();
|
||||
}
|
||||
|
||||
/*static*/ already_AddRefed<ContentParent>
|
||||
@ -816,7 +834,7 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
|
||||
NS_WARNING("nsIContentProcessProvider failed to return a process");
|
||||
RefPtr<ContentParent> random;
|
||||
if (contentParents.Length() >= maxContentParents &&
|
||||
(random = RandomSelect(contentParents, aOpener, maxContentParents))) {
|
||||
(random = MinTabSelect(contentParents, aOpener, maxContentParents))) {
|
||||
return random.forget();
|
||||
}
|
||||
}
|
||||
@ -2174,6 +2192,20 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
|
||||
SerializeURI(nullptr, xpcomInit.userContentSheetURL());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
if (gfxInfo) {
|
||||
for (int32_t i = 1; i <= nsIGfxInfo::FEATURE_MAX_VALUE; ++i) {
|
||||
int32_t status = 0;
|
||||
nsAutoCString failureId;
|
||||
gfxInfo->GetFeatureStatus(i, failureId, &status);
|
||||
dom::GfxInfoFeatureStatus gfxFeatureStatus;
|
||||
gfxFeatureStatus.feature() = i;
|
||||
gfxFeatureStatus.status() = status;
|
||||
gfxFeatureStatus.failureId() = failureId;
|
||||
xpcomInit.gfxFeatureStatus().AppendElement(gfxFeatureStatus);
|
||||
}
|
||||
}
|
||||
|
||||
Unused << SendSetXPCOMProcessAttributes(xpcomInit, initialData, lnfCache);
|
||||
|
||||
if (aSendRegisteredChrome) {
|
||||
@ -4017,25 +4049,6 @@ ContentParent::RecvRecordingDeviceEvents(const nsString& aRecordingStatus,
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvGetGfxInfoFeatureStatus(nsTArray<mozilla::dom::GfxInfoFeatureStatus>* aFS)
|
||||
{
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
if (!gfxInfo) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
for (int32_t i = 1; i <= nsIGfxInfo::FEATURE_MAX_VALUE; ++i) {
|
||||
int32_t status = 0;
|
||||
nsAutoCString failureId;
|
||||
gfxInfo->GetFeatureStatus(i, failureId, &status);
|
||||
mozilla::dom::GfxInfoFeatureStatus fs(i, status, failureId);
|
||||
aFS->AppendElement(Move(fs));
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvAddIdleObserver(const uint64_t& aObserver,
|
||||
const uint32_t& aIdleTimeInS)
|
||||
|
@ -159,7 +159,7 @@ public:
|
||||
* Returns null if non available.
|
||||
*/
|
||||
static already_AddRefed<ContentParent>
|
||||
RandomSelect(const nsTArray<ContentParent*>& aContentParents,
|
||||
MinTabSelect(const nsTArray<ContentParent*>& aContentParents,
|
||||
ContentParent* aOpener,
|
||||
int32_t maxContentParents);
|
||||
|
||||
@ -469,8 +469,6 @@ public:
|
||||
const bool& aIsAudio,
|
||||
const bool& aIsVideo) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGetGfxInfoFeatureStatus(nsTArray<mozilla::dom::GfxInfoFeatureStatus>* aFS) override;
|
||||
|
||||
bool CycleCollectWithLogs(bool aDumpAllTraces,
|
||||
nsICycleCollectorLogSink* aSink,
|
||||
nsIDumpGCAndCCLogsCallback* aCallback);
|
||||
|
@ -354,5 +354,18 @@ ContentProcessManager::GetTabParentsByProcessId(const ContentParentId& aChildCpI
|
||||
return Move(tabIdList);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ContentProcessManager::GetTabParentCountByProcessId(const ContentParentId& aChildCpId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
auto iter = mContentParentMap.find(aChildCpId);
|
||||
if (NS_WARN_IF(iter == mContentParentMap.end())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iter->second.mRemoteFrames.size();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -117,6 +117,13 @@ public:
|
||||
nsTArray<TabId>
|
||||
GetTabParentsByProcessId(const ContentParentId& aChildCpId);
|
||||
|
||||
/**
|
||||
* Get the number of TabParents managed by the givent content process.
|
||||
* Return 0 when TabParent couldn't be found via aChildCpId.
|
||||
*/
|
||||
uint32_t
|
||||
GetTabParentCountByProcessId(const ContentParentId& aChildCpId);
|
||||
|
||||
/**
|
||||
* Get the TabParent by the given content process and tab id.
|
||||
* Return nullptr when TabParent couldn't be found via aChildCpId
|
||||
|
@ -350,6 +350,13 @@ struct GMPCapabilityData
|
||||
GMPAPITags[] capabilities;
|
||||
};
|
||||
|
||||
struct GfxInfoFeatureStatus
|
||||
{
|
||||
int32_t feature;
|
||||
int32_t status;
|
||||
nsCString failureId;
|
||||
};
|
||||
|
||||
struct XPCOMInitData
|
||||
{
|
||||
bool isOffline;
|
||||
@ -364,13 +371,7 @@ struct XPCOMInitData
|
||||
FontFamilyListEntry[] fontFamilies;
|
||||
OptionalURIParams userContentSheetURL;
|
||||
PrefSetting[] prefs;
|
||||
};
|
||||
|
||||
struct GfxInfoFeatureStatus
|
||||
{
|
||||
int32_t feature;
|
||||
int32_t status;
|
||||
nsCString failureId;
|
||||
GfxInfoFeatureStatus[] gfxFeatureStatus;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -964,8 +965,6 @@ parent:
|
||||
bool isAudio,
|
||||
bool isVideo);
|
||||
|
||||
sync GetGfxInfoFeatureStatus() returns (GfxInfoFeatureStatus[] features);
|
||||
|
||||
// Graphics errors
|
||||
async GraphicsError(nsCString aError);
|
||||
|
||||
|
@ -48,12 +48,10 @@ function tryToCreateNodeOnClosedContext(ctx) {
|
||||
}
|
||||
|
||||
function loadFile(url, callback) {
|
||||
todo(false, "loadFile: " + url);
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", url, true);
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.onload = function() {
|
||||
todo(false, "loadFile: " + url + " calling callback...");
|
||||
callback(xhr.response);
|
||||
};
|
||||
xhr.send();
|
||||
@ -393,13 +391,18 @@ function finish() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
var tests = [
|
||||
testAudioContext,
|
||||
testOfflineAudioContext,
|
||||
testScriptProcessNodeSuspended,
|
||||
testMultiContextOutput,
|
||||
testMultiContextInput,
|
||||
testSuspendResumeEventLoop
|
||||
];
|
||||
|
||||
// See Bug 1305136, many intermittent failures on Linux
|
||||
if (!navigator.platform.startsWith("Linux")) {
|
||||
tests.push(testAudioContext);
|
||||
}
|
||||
|
||||
remaining = tests.length;
|
||||
tests.forEach(function(f) { f() });
|
||||
});
|
||||
|
@ -109,13 +109,7 @@ PresentationTransportBuilder.prototype = {
|
||||
|
||||
// TODO bug 1228235 we should have a way to let device providers customize
|
||||
// the time-out duration.
|
||||
let timeout;
|
||||
try {
|
||||
timeout = Services.prefs.getIntPref("presentation.receiver.loading.timeout");
|
||||
} catch (e) {
|
||||
// This happens if the pref doesn't exist, so we have a default value.
|
||||
timeout = 10000;
|
||||
}
|
||||
let timeout = Services.prefs.getIntPref("presentation.receiver.loading.timeout", 10000);
|
||||
|
||||
// The timer is to check if the negotiation finishes on time.
|
||||
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
|
@ -358,12 +358,11 @@ ChromecastRemoteDisplayDevice.prototype = {
|
||||
};
|
||||
|
||||
function AndroidCastDeviceProvider() {
|
||||
this._listener = null;
|
||||
this._deviceList = new Map();
|
||||
}
|
||||
|
||||
AndroidCastDeviceProvider.prototype = {
|
||||
_listener: null,
|
||||
_deviceList: new Map(),
|
||||
|
||||
onSessionRequest: function APDP_onSessionRequest(aDeviceId,
|
||||
aUrl,
|
||||
aPresentationId,
|
||||
@ -403,18 +402,23 @@ AndroidCastDeviceProvider.prototype = {
|
||||
// When unload this provider.
|
||||
if (!this._listener) {
|
||||
// remove observer
|
||||
Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_ADDED);
|
||||
Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_CHANGED);
|
||||
Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_REMOVED);
|
||||
EventDispatcher.instance.unregisterListener(this, [
|
||||
TOPIC_ANDROID_CAST_DEVICE_ADDED,
|
||||
TOPIC_ANDROID_CAST_DEVICE_CHANGED,
|
||||
TOPIC_ANDROID_CAST_DEVICE_REMOVED,
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Observer registration
|
||||
EventDispatcher.instance.registerListener(this, [
|
||||
TOPIC_ANDROID_CAST_DEVICE_ADDED,
|
||||
TOPIC_ANDROID_CAST_DEVICE_CHANGED,
|
||||
TOPIC_ANDROID_CAST_DEVICE_REMOVED,
|
||||
]);
|
||||
|
||||
// Sync all device already found by Android.
|
||||
EventDispatcher.instance.sendRequest({ type: TOPIC_ANDROID_CAST_DEVICE_SYNCDEVICE });
|
||||
// Observer registration
|
||||
Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_ADDED, false);
|
||||
Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_CHANGED, false);
|
||||
Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_REMOVED, false);
|
||||
},
|
||||
|
||||
get listener() {
|
||||
@ -425,13 +429,11 @@ AndroidCastDeviceProvider.prototype = {
|
||||
// There is no API to do force discovery in Android SDK.
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function APDP_observe(aSubject, aTopic, aData) {
|
||||
log('observe ' + aTopic + ': ' + aData);
|
||||
switch (aTopic) {
|
||||
onEvent: function APDP_onEvent(event, data, callback) {
|
||||
switch (event) {
|
||||
case TOPIC_ANDROID_CAST_DEVICE_ADDED:
|
||||
case TOPIC_ANDROID_CAST_DEVICE_CHANGED: {
|
||||
let deviceInfo = JSON.parse(aData);
|
||||
let deviceInfo = data;
|
||||
let deviceId = deviceInfo.uuid;
|
||||
|
||||
if (!this._deviceList.has(deviceId)) {
|
||||
@ -449,7 +451,7 @@ AndroidCastDeviceProvider.prototype = {
|
||||
break;
|
||||
}
|
||||
case TOPIC_ANDROID_CAST_DEVICE_REMOVED: {
|
||||
let deviceId = aData;
|
||||
let deviceId = data.id;
|
||||
if (!this._deviceList.has(deviceId)) {
|
||||
break;
|
||||
}
|
||||
|
@ -39,12 +39,7 @@ var DEBUG = RIL.DEBUG_RIL;
|
||||
|
||||
function updateDebugFlag() {
|
||||
// Read debug setting from pref
|
||||
let debugPref;
|
||||
try {
|
||||
debugPref = Services.prefs.getBoolPref(PREF_RIL_DEBUG_ENABLED);
|
||||
} catch (e) {
|
||||
debugPref = false;
|
||||
}
|
||||
let debugPref = Services.prefs.getBoolPref(PREF_RIL_DEBUG_ENABLED, false);
|
||||
DEBUG = debugPref || RIL.DEBUG_RIL;
|
||||
}
|
||||
updateDebugFlag();
|
||||
|
@ -85,12 +85,7 @@ var DEBUG = RIL.DEBUG_RIL;
|
||||
|
||||
function updateDebugFlag() {
|
||||
// Read debug setting from pref
|
||||
let debugPref;
|
||||
try {
|
||||
debugPref = Services.prefs.getBoolPref(PREF_RIL_DEBUG_ENABLED);
|
||||
} catch (e) {
|
||||
debugPref = false;
|
||||
}
|
||||
let debugPref = Services.prefs.getBoolPref(PREF_RIL_DEBUG_ENABLED, false);
|
||||
DEBUG = debugPref || RIL.DEBUG_RIL;
|
||||
}
|
||||
updateDebugFlag();
|
||||
|
@ -68,12 +68,7 @@ var DEBUG = RIL.DEBUG_RIL;
|
||||
|
||||
function updateDebugFlag() {
|
||||
// Read debug setting from pref
|
||||
let debugPref;
|
||||
try {
|
||||
debugPref = Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
|
||||
} catch (e) {
|
||||
debugPref = false;
|
||||
}
|
||||
let debugPref = Services.prefs.getBoolPref(kPrefRilDebuggingEnabled, false);
|
||||
DEBUG = RIL.DEBUG_RIL || debugPref;
|
||||
}
|
||||
updateDebugFlag();
|
||||
|
@ -14,13 +14,7 @@ const Ci = Components.interfaces;
|
||||
const CONTENT_PAGE = "http://mochi.test:8888/chrome/dom/tests/mochitest/localstorage/page_blank.html";
|
||||
const slavePath = "/chrome/dom/tests/mochitest/localstorage/";
|
||||
var currentTest = 1;
|
||||
var quota;
|
||||
|
||||
try {
|
||||
quota = Services.prefs.getIntPref("dom.storage.default_quota");
|
||||
} catch (ex) {
|
||||
quota = 5 * 1024;
|
||||
}
|
||||
var quota = Services.prefs.getIntPref("dom.storage.default_quota", 5 * 1024);
|
||||
Services.prefs.setIntPref("browser.startup.page", 0);
|
||||
Services.prefs.setIntPref("dom.storage.default_quota", 1);
|
||||
|
||||
|
@ -86,6 +86,7 @@ class JS_PUBLIC_API(JSTracer)
|
||||
bool isTenuringTracer() const { return tag_ == TracerKindTag::Tenuring; }
|
||||
bool isCallbackTracer() const { return tag_ == TracerKindTag::Callback; }
|
||||
inline JS::CallbackTracer* asCallbackTracer();
|
||||
bool traceWeakEdges() const { return traceWeakEdges_; }
|
||||
#ifdef DEBUG
|
||||
bool checkEdges() { return checkEdges_; }
|
||||
#endif
|
||||
@ -99,6 +100,7 @@ class JS_PUBLIC_API(JSTracer)
|
||||
, checkEdges_(true)
|
||||
#endif
|
||||
, tag_(tag)
|
||||
, traceWeakEdges_(true)
|
||||
{}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -117,6 +119,7 @@ class JS_PUBLIC_API(JSTracer)
|
||||
|
||||
protected:
|
||||
TracerKindTag tag_;
|
||||
bool traceWeakEdges_;
|
||||
};
|
||||
|
||||
namespace JS {
|
||||
@ -232,6 +235,11 @@ class JS_PUBLIC_API(CallbackTracer) : public JSTracer
|
||||
void dispatchToOnEdge(js::LazyScript** lazyp) { onLazyScriptEdge(lazyp); }
|
||||
void dispatchToOnEdge(js::Scope** scopep) { onScopeEdge(scopep); }
|
||||
|
||||
protected:
|
||||
void setTraceWeakEdges(bool value) {
|
||||
traceWeakEdges_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class AutoTracingName;
|
||||
const char* contextName_;
|
||||
|
@ -26,7 +26,8 @@ Reflect_defineProperty(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject obj(cx, NonNullObject(cx, args.get(0)));
|
||||
RootedObject obj(cx, NonNullObjectArg(cx, "`target`", "Reflect.defineProperty",
|
||||
args.get(0)));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
@ -56,7 +57,8 @@ Reflect_deleteProperty(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject target(cx, NonNullObject(cx, args.get(0)));
|
||||
RootedObject target(cx, NonNullObjectArg(cx, "`target`", "Reflect.deleteProperty",
|
||||
args.get(0)));
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
@ -81,7 +83,7 @@ Reflect_get(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject obj(cx, NonNullObject(cx, args.get(0)));
|
||||
RootedObject obj(cx, NonNullObjectArg(cx, "`target`", "Reflect.get", args.get(0)));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
@ -104,7 +106,7 @@ Reflect_getOwnPropertyDescriptor(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
// Step 1.
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!NonNullObject(cx, args.get(0)))
|
||||
if (!NonNullObjectArg(cx, "`target`", "Reflect.getOwnPropertyDescriptor", args.get(0)))
|
||||
return false;
|
||||
|
||||
// The other steps are identical to ES6 draft rev 32 (2015 Feb 2) 19.1.2.6
|
||||
@ -119,7 +121,8 @@ js::Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject target(cx, NonNullObject(cx, args.get(0)));
|
||||
RootedObject target(cx, NonNullObjectArg(cx, "`target`", "Reflect.getPrototypeOf",
|
||||
args.get(0)));
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
@ -138,7 +141,7 @@ js::Reflect_isExtensible(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject target(cx, NonNullObject(cx, args.get(0)));
|
||||
RootedObject target(cx, NonNullObjectArg(cx, "`target`", "Reflect.isExtensible", args.get(0)));
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
@ -157,7 +160,7 @@ Reflect_ownKeys(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
if (!NonNullObject(cx, args.get(0)))
|
||||
if (!NonNullObjectArg(cx, "`target`", "Reflect.ownKeys", args.get(0)))
|
||||
return false;
|
||||
|
||||
// Steps 2-4.
|
||||
@ -171,7 +174,8 @@ Reflect_preventExtensions(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject target(cx, NonNullObject(cx, args.get(0)));
|
||||
RootedObject target(cx, NonNullObjectArg(cx, "`target`", "Reflect.preventExtensions",
|
||||
args.get(0)));
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
@ -190,7 +194,7 @@ Reflect_set(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject target(cx, NonNullObject(cx, args.get(0)));
|
||||
RootedObject target(cx, NonNullObjectArg(cx, "`target`", "Reflect.set", args.get(0)));
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
@ -224,7 +228,7 @@ Reflect_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
RootedObject obj(cx, NonNullObject(cx, args.get(0)));
|
||||
RootedObject obj(cx, NonNullObjectArg(cx, "`target`", "Reflect.setPrototypeOf", args.get(0)));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
@ -34,8 +34,10 @@ function Reflect_apply(target, thisArgument, argumentsList) {
|
||||
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, target));
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(argumentsList))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, DecompileArg(2, argumentsList));
|
||||
if (!IsObject(argumentsList)) {
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_ARG, "`argumentsList`", "Reflect.apply",
|
||||
ToSource(argumentsList));
|
||||
}
|
||||
|
||||
// Steps 2-4.
|
||||
return callFunction(std_Function_apply, target, thisArgument, argumentsList);
|
||||
@ -59,8 +61,10 @@ function Reflect_construct(target, argumentsList/*, newTarget*/) {
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
if (!IsObject(argumentsList))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, DecompileArg(1, argumentsList));
|
||||
if (!IsObject(argumentsList)) {
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_ARG, "`argumentsList`", "Reflect.construct",
|
||||
ToSource(argumentsList));
|
||||
}
|
||||
|
||||
// Fast path when we can avoid calling CreateListFromArrayLikeForArgs().
|
||||
var args = (IsPackedArray(argumentsList) && argumentsList.length <= MAX_ARGS_LENGTH)
|
||||
@ -105,7 +109,8 @@ function Reflect_construct(target, argumentsList/*, newTarget*/) {
|
||||
function Reflect_has(target, propertyKey) {
|
||||
// Step 1.
|
||||
if (!IsObject(target))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, DecompileArg(0, target));
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_ARG, "`target`", "Reflect.has",
|
||||
ToSource(target));
|
||||
|
||||
// Steps 2-3 are identical to the runtime semantics of the "in" operator.
|
||||
return propertyKey in target;
|
||||
|
@ -169,11 +169,7 @@ WeakMap_set_impl(JSContext* cx, const CallArgs& args)
|
||||
MOZ_ASSERT(IsWeakMap(args.thisv()));
|
||||
|
||||
if (!args.get(0).isObject()) {
|
||||
UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, args.get(0), nullptr);
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT,
|
||||
bytes.get());
|
||||
ReportNotObjectWithName(cx, "WeakMap key", args.get(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ function WeakSet_add(value) {
|
||||
|
||||
// Step 5.
|
||||
if (!IsObject(value))
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, DecompileArg(0, value));
|
||||
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_NAME, "WeakSet value", ToSource(value));
|
||||
|
||||
// Steps 7-8.
|
||||
callFunction(std_WeakMap_set, entries, value, true);
|
||||
|
@ -118,12 +118,7 @@ WeakSetObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE));
|
||||
|
||||
if (keyVal.isPrimitive()) {
|
||||
UniqueChars bytes =
|
||||
DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, keyVal, nullptr);
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_NOT_NONNULL_OBJECT, bytes.get());
|
||||
ReportNotObjectWithName(cx, "WeakSet value", keyVal);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -64,29 +64,32 @@ using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
|
||||
|
||||
// Read a token. Report an error and return null() if that token doesn't match
|
||||
// to the condition. Do not use MUST_MATCH_TOKEN_INTERNAL directly.
|
||||
#define MUST_MATCH_TOKEN_INTERNAL(cond, modifier, errorNumber) \
|
||||
#define MUST_MATCH_TOKEN_INTERNAL(cond, modifier, errorReport) \
|
||||
JS_BEGIN_MACRO \
|
||||
TokenKind token; \
|
||||
if (!tokenStream.getToken(&token, modifier)) \
|
||||
return null(); \
|
||||
if (!(cond)) { \
|
||||
error(errorNumber); \
|
||||
errorReport; \
|
||||
return null(); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
#define MUST_MATCH_TOKEN_MOD(tt, modifier, errorNumber) \
|
||||
MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, errorNumber)
|
||||
MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, error(errorNumber))
|
||||
|
||||
#define MUST_MATCH_TOKEN(tt, errorNumber) \
|
||||
MUST_MATCH_TOKEN_MOD(tt, TokenStream::None, errorNumber)
|
||||
|
||||
#define MUST_MATCH_TOKEN_FUNC_MOD(func, modifier, errorNumber) \
|
||||
MUST_MATCH_TOKEN_INTERNAL((func)(token), modifier, errorNumber)
|
||||
MUST_MATCH_TOKEN_INTERNAL((func)(token), modifier, error(errorNumber))
|
||||
|
||||
#define MUST_MATCH_TOKEN_FUNC(func, errorNumber) \
|
||||
MUST_MATCH_TOKEN_FUNC_MOD(func, TokenStream::None, errorNumber)
|
||||
|
||||
#define MUST_MATCH_TOKEN_MOD_WITH_REPORT(tt, modifier, errorReport) \
|
||||
MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, errorReport)
|
||||
|
||||
template <class T, class U>
|
||||
static inline void
|
||||
PropagateTransitiveParseFlags(const T* inner, U* outer)
|
||||
@ -1001,6 +1004,35 @@ Parser<ParseHandler>::hasValidSimpleStrictParameterNames()
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
void
|
||||
Parser<ParseHandler>::reportMissingClosing(unsigned errorNumber, unsigned noteNumber,
|
||||
uint32_t openedPos)
|
||||
{
|
||||
auto notes = MakeUnique<JSErrorNotes>();
|
||||
if (!notes)
|
||||
return;
|
||||
|
||||
uint32_t line, column;
|
||||
tokenStream.srcCoords.lineNumAndColumnIndex(openedPos, &line, &column);
|
||||
|
||||
const size_t MaxWidth = sizeof("4294967295");
|
||||
char columnNumber[MaxWidth];
|
||||
SprintfLiteral(columnNumber, "%" PRIu32, column);
|
||||
char lineNumber[MaxWidth];
|
||||
SprintfLiteral(lineNumber, "%" PRIu32, line);
|
||||
|
||||
if (!notes->addNoteASCII(pc->sc()->context,
|
||||
getFilename(), line, column,
|
||||
GetErrorMessage, nullptr,
|
||||
noteNumber, lineNumber, columnNumber))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
errorWithNotes(Move(notes), errorNumber);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
void
|
||||
Parser<ParseHandler>::reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind,
|
||||
@ -1028,11 +1060,11 @@ Parser<ParseHandler>::reportRedeclaration(HandlePropertyName name, DeclarationKi
|
||||
char lineNumber[MaxWidth];
|
||||
SprintfLiteral(lineNumber, "%" PRIu32, line);
|
||||
|
||||
if (!notes->addNoteLatin1(pc->sc()->context,
|
||||
getFilename(), line, column,
|
||||
GetErrorMessage, nullptr,
|
||||
JSMSG_REDECLARED_PREV,
|
||||
lineNumber, columnNumber))
|
||||
if (!notes->addNoteASCII(pc->sc()->context,
|
||||
getFilename(), line, column,
|
||||
GetErrorMessage, nullptr,
|
||||
JSMSG_REDECLARED_PREV,
|
||||
lineNumber, columnNumber))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -3607,6 +3639,7 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
|
||||
TokenKind tt;
|
||||
if (!tokenStream.getToken(&tt, TokenStream::Operand))
|
||||
return false;
|
||||
uint32_t openedPos = 0;
|
||||
if (tt != TOK_LC) {
|
||||
if (funbox->isStarGenerator() || kind == Method ||
|
||||
kind == GetterNoExpressionClosure || kind == SetterNoExpressionClosure ||
|
||||
@ -3629,6 +3662,8 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
|
||||
tokenStream.ungetToken();
|
||||
bodyType = ExpressionBody;
|
||||
funbox->setIsExprBody();
|
||||
} else {
|
||||
openedPos = pos().begin;
|
||||
}
|
||||
|
||||
// Arrow function parameters inherit yieldHandling from the enclosing
|
||||
@ -3666,13 +3701,9 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
|
||||
}
|
||||
|
||||
if (bodyType == StatementListBody) {
|
||||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_RC, TokenStream::Operand))
|
||||
return false;
|
||||
if (!matched) {
|
||||
error(JSMSG_CURLY_AFTER_BODY);
|
||||
return false;
|
||||
}
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_BODY,
|
||||
JSMSG_CURLY_OPENED, openedPos));
|
||||
funbox->bufEnd = pos().end;
|
||||
} else {
|
||||
#if !JS_HAS_EXPR_CLOSURES
|
||||
@ -4446,6 +4477,7 @@ typename ParseHandler::Node
|
||||
Parser<ParseHandler>::blockStatement(YieldHandling yieldHandling, unsigned errorNumber)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
|
||||
uint32_t openedPos = pos().begin;
|
||||
|
||||
ParseContext::Statement stmt(pc, StatementKind::Block);
|
||||
ParseContext::Scope scope(this);
|
||||
@ -4456,7 +4488,9 @@ Parser<ParseHandler>::blockStatement(YieldHandling yieldHandling, unsigned error
|
||||
if (!list)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, errorNumber);
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(errorNumber, JSMSG_CURLY_OPENED,
|
||||
openedPos));
|
||||
|
||||
return finishLexicalScope(scope, list);
|
||||
}
|
||||
@ -6705,6 +6739,8 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
||||
{
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY);
|
||||
|
||||
uint32_t openedPos = pos().begin;
|
||||
|
||||
ParseContext::Statement stmt(pc, StatementKind::Try);
|
||||
ParseContext::Scope scope(this);
|
||||
if (!scope.init(pc))
|
||||
@ -6718,7 +6754,9 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
||||
if (!innerBlock)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_TRY);
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_TRY,
|
||||
JSMSG_CURLY_OPENED, openedPos));
|
||||
}
|
||||
|
||||
bool hasUnconditionalCatch = false;
|
||||
@ -6834,6 +6872,8 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
||||
if (tt == TOK_FINALLY) {
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY);
|
||||
|
||||
uint32_t openedPos = pos().begin;
|
||||
|
||||
ParseContext::Statement stmt(pc, StatementKind::Finally);
|
||||
ParseContext::Scope scope(this);
|
||||
if (!scope.init(pc))
|
||||
@ -6847,7 +6887,9 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
||||
if (!finallyBlock)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_FINALLY);
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_FINALLY,
|
||||
JSMSG_CURLY_OPENED, openedPos));
|
||||
} else {
|
||||
tokenStream.ungetToken();
|
||||
}
|
||||
@ -6864,6 +6906,8 @@ typename ParseHandler::Node
|
||||
Parser<ParseHandler>::catchBlockStatement(YieldHandling yieldHandling,
|
||||
ParseContext::Scope& catchParamScope)
|
||||
{
|
||||
uint32_t openedPos = pos().begin;
|
||||
|
||||
ParseContext::Statement stmt(pc, StatementKind::Block);
|
||||
|
||||
// ES 13.15.7 CatchClauseEvaluation
|
||||
@ -6883,7 +6927,9 @@ Parser<ParseHandler>::catchBlockStatement(YieldHandling yieldHandling,
|
||||
if (!list)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_CATCH);
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_CATCH,
|
||||
JSMSG_CURLY_OPENED, openedPos));
|
||||
|
||||
// The catch parameter names are not bound in the body scope, so remove
|
||||
// them before generating bindings.
|
||||
@ -9219,7 +9265,9 @@ Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleErro
|
||||
}
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN_MOD(TOK_RB, modifier, JSMSG_BRACKET_AFTER_LIST);
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RB, modifier,
|
||||
reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
|
||||
JSMSG_BRACKET_OPENED, begin));
|
||||
}
|
||||
handler.setEndPosition(literal, pos().end);
|
||||
return literal;
|
||||
@ -9440,6 +9488,8 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
|
||||
|
||||
uint32_t openedPos = pos().begin;
|
||||
|
||||
Node literal = handler.newObjectLiteral(pos().begin);
|
||||
if (!literal)
|
||||
return null();
|
||||
@ -9602,7 +9652,7 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
|
||||
if (tt == TOK_RC)
|
||||
break;
|
||||
if (tt != TOK_COMMA) {
|
||||
error(JSMSG_CURLY_AFTER_LIST);
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_LIST, JSMSG_CURLY_OPENED, openedPos);
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
@ -1448,6 +1448,8 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
||||
|
||||
bool hasValidSimpleStrictParameterNames();
|
||||
|
||||
void reportMissingClosing(unsigned errorNumber, unsigned noteNumber, uint32_t openedPos);
|
||||
|
||||
void reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind, TokenPos pos,
|
||||
uint32_t prevPos);
|
||||
bool notePositionalFormalParameter(Node fn, HandlePropertyName name, uint32_t beginPos,
|
||||
|
@ -979,7 +979,7 @@ class GCRuntime
|
||||
|
||||
void beginSweepPhase(bool lastGC, AutoLockForExclusiveAccess& lock);
|
||||
void findZoneGroups(AutoLockForExclusiveAccess& lock);
|
||||
MOZ_MUST_USE bool findZoneEdgesForWeakMaps();
|
||||
MOZ_MUST_USE bool findInterZoneEdges();
|
||||
void getNextZoneGroup();
|
||||
void endMarkingZoneGroup();
|
||||
void beginSweepingZoneGroup(AutoLockForExclusiveAccess& lock);
|
||||
|
@ -479,9 +479,12 @@ template <typename T>
|
||||
void
|
||||
js::TraceWeakEdge(JSTracer* trc, WeakRef<T>* thingp, const char* name)
|
||||
{
|
||||
// Non-marking tracers treat the edge strongly.
|
||||
if (!trc->isMarkingTracer())
|
||||
return DispatchToTracer(trc, ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name);
|
||||
if (!trc->isMarkingTracer()) {
|
||||
// Non-marking tracers can select whether or not they see weak edges.
|
||||
if (trc->traceWeakEdges())
|
||||
DispatchToTracer(trc, ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name);
|
||||
return;
|
||||
}
|
||||
|
||||
NoteWeakEdge(GCMarker::fromTracer(trc),
|
||||
ConvertToBase(thingp->unsafeUnbarrieredForTracing()));
|
||||
|
@ -449,14 +449,24 @@ js::gc::GCRuntime::finishVerifier()
|
||||
|
||||
#endif /* JS_GC_ZEAL */
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
#if defined(JSGC_HASH_TABLE_CHECKS) || defined(DEBUG)
|
||||
|
||||
class CheckHeapTracer : public JS::CallbackTracer
|
||||
class HeapCheckTracerBase : public JS::CallbackTracer
|
||||
{
|
||||
public:
|
||||
explicit CheckHeapTracer(JSRuntime* rt);
|
||||
explicit HeapCheckTracerBase(JSRuntime* rt, WeakMapTraceKind weakTraceKind);
|
||||
bool init();
|
||||
void check(AutoLockForExclusiveAccess& lock);
|
||||
bool traceHeap(AutoLockForExclusiveAccess& lock);
|
||||
virtual void checkCell(Cell* cell) = 0;
|
||||
|
||||
protected:
|
||||
void dumpCellPath();
|
||||
|
||||
Cell* parentCell() {
|
||||
return parentIndex == -1 ? nullptr : stack[parentIndex].thing.asCell();
|
||||
}
|
||||
|
||||
size_t failures;
|
||||
|
||||
private:
|
||||
void onChild(const JS::GCCellPtr& thing) override;
|
||||
@ -474,17 +484,16 @@ class CheckHeapTracer : public JS::CallbackTracer
|
||||
|
||||
JSRuntime* rt;
|
||||
bool oom;
|
||||
size_t failures;
|
||||
HashSet<Cell*, DefaultHasher<Cell*>, SystemAllocPolicy> visited;
|
||||
Vector<WorkItem, 0, SystemAllocPolicy> stack;
|
||||
int parentIndex;
|
||||
};
|
||||
|
||||
CheckHeapTracer::CheckHeapTracer(JSRuntime* rt)
|
||||
: CallbackTracer(rt, TraceWeakMapKeysValues),
|
||||
HeapCheckTracerBase::HeapCheckTracerBase(JSRuntime* rt, WeakMapTraceKind weakTraceKind)
|
||||
: CallbackTracer(rt, weakTraceKind),
|
||||
failures(0),
|
||||
rt(rt),
|
||||
oom(false),
|
||||
failures(0),
|
||||
parentIndex(-1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -493,21 +502,17 @@ CheckHeapTracer::CheckHeapTracer(JSRuntime* rt)
|
||||
}
|
||||
|
||||
bool
|
||||
CheckHeapTracer::init()
|
||||
HeapCheckTracerBase::init()
|
||||
{
|
||||
return visited.init();
|
||||
}
|
||||
|
||||
inline static bool
|
||||
IsValidGCThingPointer(Cell* cell)
|
||||
{
|
||||
return (uintptr_t(cell) & CellMask) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
CheckHeapTracer::onChild(const JS::GCCellPtr& thing)
|
||||
HeapCheckTracerBase::onChild(const JS::GCCellPtr& thing)
|
||||
{
|
||||
Cell* cell = thing.asCell();
|
||||
checkCell(cell);
|
||||
|
||||
if (visited.lookup(cell))
|
||||
return;
|
||||
|
||||
@ -516,57 +521,98 @@ CheckHeapTracer::onChild(const JS::GCCellPtr& thing)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValidGCThingPointer(cell) || !IsGCThingValidAfterMovingGC(cell))
|
||||
{
|
||||
failures++;
|
||||
fprintf(stderr, "Bad pointer %p\n", cell);
|
||||
const char* name = contextName();
|
||||
for (int index = parentIndex; index != -1; index = stack[index].parentIndex) {
|
||||
const WorkItem& parent = stack[index];
|
||||
cell = parent.thing.asCell();
|
||||
fprintf(stderr, " from %s %p %s edge\n",
|
||||
GCTraceKindToAscii(cell->getTraceKind()), cell, name);
|
||||
name = parent.name;
|
||||
}
|
||||
fprintf(stderr, " from root %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't trace into GC things owned by another runtime.
|
||||
if (cell->runtimeFromAnyThread() != rt)
|
||||
return;
|
||||
|
||||
// Don't trace into GC in zones being used by helper threads.
|
||||
Zone* zone = thing.is<JSObject>() ? thing.as<JSObject>().zone() : cell->asTenured().zone();
|
||||
if (zone->group() && zone->group()->usedByHelperThread)
|
||||
return;
|
||||
|
||||
WorkItem item(thing, contextName(), parentIndex);
|
||||
if (!stack.append(item))
|
||||
oom = true;
|
||||
}
|
||||
|
||||
void
|
||||
CheckHeapTracer::check(AutoLockForExclusiveAccess& lock)
|
||||
bool
|
||||
HeapCheckTracerBase::traceHeap(AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
// The analysis thinks that traceRuntime might GC by calling a GC callback.
|
||||
JS::AutoSuppressGCAnalysis nogc;
|
||||
if (!rt->isBeingDestroyed())
|
||||
rt->gc.traceRuntime(this, lock);
|
||||
|
||||
while (!stack.empty()) {
|
||||
while (!stack.empty() && !oom) {
|
||||
WorkItem item = stack.back();
|
||||
if (item.processed) {
|
||||
stack.popBack();
|
||||
} else {
|
||||
parentIndex = stack.length() - 1;
|
||||
TraceChildren(this, item.thing);
|
||||
stack.back().processed = true;
|
||||
TraceChildren(this, item.thing);
|
||||
}
|
||||
}
|
||||
|
||||
if (oom)
|
||||
return !oom;
|
||||
}
|
||||
|
||||
void
|
||||
HeapCheckTracerBase::dumpCellPath()
|
||||
{
|
||||
const char* name = contextName();
|
||||
for (int index = parentIndex; index != -1; index = stack[index].parentIndex) {
|
||||
const WorkItem& parent = stack[index];
|
||||
Cell* cell = parent.thing.asCell();
|
||||
fprintf(stderr, " from %s %p %s edge\n",
|
||||
GCTraceKindToAscii(cell->getTraceKind()), cell, name);
|
||||
name = parent.name;
|
||||
}
|
||||
fprintf(stderr, " from root %s\n", name);
|
||||
}
|
||||
|
||||
#endif // defined(JSGC_HASH_TABLE_CHECKS) || defined(DEBUG)
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
|
||||
class CheckHeapTracer final : public HeapCheckTracerBase
|
||||
{
|
||||
public:
|
||||
explicit CheckHeapTracer(JSRuntime* rt);
|
||||
void check(AutoLockForExclusiveAccess& lock);
|
||||
|
||||
private:
|
||||
void checkCell(Cell* cell) override;
|
||||
};
|
||||
|
||||
CheckHeapTracer::CheckHeapTracer(JSRuntime* rt)
|
||||
: HeapCheckTracerBase(rt, TraceWeakMapKeysValues)
|
||||
{}
|
||||
|
||||
inline static bool
|
||||
IsValidGCThingPointer(Cell* cell)
|
||||
{
|
||||
return (uintptr_t(cell) & CellMask) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
CheckHeapTracer::checkCell(Cell* cell)
|
||||
{
|
||||
if (!IsValidGCThingPointer(cell) || !IsGCThingValidAfterMovingGC(cell)) {
|
||||
failures++;
|
||||
fprintf(stderr, "Bad pointer %p\n", cell);
|
||||
dumpCellPath();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CheckHeapTracer::check(AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
if (!traceHeap(lock))
|
||||
return;
|
||||
|
||||
if (failures) {
|
||||
fprintf(stderr, "Heap check: %" PRIuSIZE " failure(s) out of %" PRIu32 " pointers checked\n",
|
||||
failures, visited.count());
|
||||
}
|
||||
if (failures)
|
||||
fprintf(stderr, "Heap check: %" PRIuSIZE " failure(s)\n", failures);
|
||||
MOZ_RELEASE_ASSERT(failures == 0);
|
||||
}
|
||||
|
||||
@ -580,3 +626,69 @@ js::gc::CheckHeapAfterGC(JSRuntime* rt)
|
||||
}
|
||||
|
||||
#endif /* JSGC_HASH_TABLE_CHECKS */
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
class CheckGrayMarkingTracer final : public HeapCheckTracerBase
|
||||
{
|
||||
public:
|
||||
explicit CheckGrayMarkingTracer(JSRuntime* rt);
|
||||
bool check(AutoLockForExclusiveAccess& lock);
|
||||
|
||||
private:
|
||||
void checkCell(Cell* cell) override;
|
||||
};
|
||||
|
||||
CheckGrayMarkingTracer::CheckGrayMarkingTracer(JSRuntime* rt)
|
||||
: HeapCheckTracerBase(rt, DoNotTraceWeakMaps)
|
||||
{
|
||||
// Weak gray->black edges are allowed.
|
||||
setTraceWeakEdges(false);
|
||||
}
|
||||
|
||||
void
|
||||
CheckGrayMarkingTracer::checkCell(Cell* cell)
|
||||
{
|
||||
Cell* parent = parentCell();
|
||||
if (!cell->isTenured() || !parent || !parent->isTenured())
|
||||
return;
|
||||
|
||||
TenuredCell* tenuredCell = &cell->asTenured();
|
||||
TenuredCell* tenuredParent = &parent->asTenured();
|
||||
if (tenuredParent->isMarked(BLACK) && !tenuredParent->isMarked(GRAY) &&
|
||||
tenuredCell->isMarked(GRAY))
|
||||
{
|
||||
failures++;
|
||||
fprintf(stderr, "Found black to gray edge %p\n", cell);
|
||||
dumpCellPath();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CheckGrayMarkingTracer::check(AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
if (!traceHeap(lock))
|
||||
return true; // Ignore failure.
|
||||
|
||||
return failures == 0;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::CheckGrayMarkingState(JSContext* cx)
|
||||
{
|
||||
JSRuntime* rt = cx->runtime();
|
||||
MOZ_ASSERT(!JS::CurrentThreadIsHeapCollecting());
|
||||
MOZ_ASSERT(!rt->gc.isIncrementalGCInProgress());
|
||||
if (!rt->gc.areGrayBitsValid())
|
||||
return true;
|
||||
|
||||
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PHASE_TRACE_HEAP);
|
||||
AutoTraceSession session(rt, JS::HeapState::Tracing);
|
||||
CheckGrayMarkingTracer tracer(rt);
|
||||
if (!tracer.init())
|
||||
return true; // Ignore failure
|
||||
|
||||
return tracer.check(session.lock);
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
@ -38,6 +38,7 @@ JS::Zone::Zone(JSRuntime* rt, ZoneGroup* group)
|
||||
weakCaches_(group),
|
||||
gcWeakKeys_(group, SystemAllocPolicy(), rt->randomHashCodeScrambler()),
|
||||
gcZoneGroupEdges_(group),
|
||||
hasDeadProxies_(group),
|
||||
typeDescrObjects_(group, this, SystemAllocPolicy()),
|
||||
markedAtoms_(group),
|
||||
usage(&rt->gc.usage),
|
||||
|
@ -371,9 +371,17 @@ struct Zone : public JS::shadow::Zone,
|
||||
// This is used during GC while calculating zone groups to record edges that
|
||||
// can't be determined by examining this zone by itself.
|
||||
js::ZoneGroupData<ZoneSet> gcZoneGroupEdges_;
|
||||
|
||||
// Zones with dead proxies require an extra scan through the wrapper map,
|
||||
// so track whether any dead proxies are known to exist.
|
||||
js::ZoneGroupData<bool> hasDeadProxies_;
|
||||
|
||||
public:
|
||||
ZoneSet& gcZoneGroupEdges() { return gcZoneGroupEdges_.ref(); }
|
||||
|
||||
bool hasDeadProxies() { return hasDeadProxies_; }
|
||||
void setHasDeadProxies(bool b) { hasDeadProxies_ = b; }
|
||||
|
||||
// Keep track of all TypeDescr and related objects in this compartment.
|
||||
// This is used by the GC to trace them all first when compacting, since the
|
||||
// TypedObject trace hook may access these objects.
|
||||
|
14
js/src/jit-test/tests/baseline/bug1344334.js
Normal file
14
js/src/jit-test/tests/baseline/bug1344334.js
Normal file
@ -0,0 +1,14 @@
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
function f(s) {
|
||||
s + "x";
|
||||
s.indexOf("y") === 0;
|
||||
oomTest(new Function(s));
|
||||
}
|
||||
var s = `
|
||||
class TestClass { constructor() {} }
|
||||
for (var fun of hasPrototype) {}
|
||||
`;
|
||||
if (s.length)
|
||||
f(s);
|
@ -1,6 +1,6 @@
|
||||
var wrapper = evaluate("({a: 15, b: {c: 42}})", {global: newGlobal({sameZoneAs: this})});
|
||||
function testNuke() {
|
||||
var wrapper = evaluate("({a: 15, b: {c: 42}})", {global: newGlobal({sameZoneAs: this})});
|
||||
|
||||
function test() {
|
||||
var i, error;
|
||||
try {
|
||||
for (i = 0; i < 150; i++) {
|
||||
@ -20,4 +20,19 @@ function test() {
|
||||
assertEq(i, 143);
|
||||
}
|
||||
|
||||
test();
|
||||
function testSweep() {
|
||||
var wrapper = evaluate("({a: 15, b: {c: 42}})", {global: newGlobal({})});
|
||||
var error;
|
||||
nukeCCW(wrapper);
|
||||
gczeal(8, 1); // Sweep zones separately
|
||||
try {
|
||||
// Next access to wrapper.b should throw.
|
||||
wrapper.x = 4;
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
assertEq(error.message.includes("dead object"), true);
|
||||
}
|
||||
|
||||
testNuke();
|
||||
testSweep();
|
||||
|
90
js/src/jit-test/tests/parser/missing-closing-brace.js
Normal file
90
js/src/jit-test/tests/parser/missing-closing-brace.js
Normal file
@ -0,0 +1,90 @@
|
||||
function test(source, [lineNumber, columnNumber], openType = "{", closeType = "}") {
|
||||
let caught = false;
|
||||
try {
|
||||
Reflect.parse(source, { source: "foo.js" });
|
||||
} catch (e) {
|
||||
assertEq(e.message.includes("missing " + closeType + " "), true);
|
||||
let notes = getErrorNotes(e);
|
||||
assertEq(notes.length, 1);
|
||||
let note = notes[0];
|
||||
assertEq(note.message, openType + " opened at line " + lineNumber + ", column " + columnNumber);
|
||||
assertEq(note.fileName, "foo.js");
|
||||
assertEq(note.lineNumber, lineNumber);
|
||||
assertEq(note.columnNumber, columnNumber);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(caught, true);
|
||||
}
|
||||
|
||||
// Function
|
||||
|
||||
test(`
|
||||
function test1() {
|
||||
}
|
||||
function test2() {
|
||||
if (true) {
|
||||
//}
|
||||
}
|
||||
function test3() {
|
||||
}
|
||||
`, [4, 17]);
|
||||
|
||||
// Block statement.
|
||||
test(`
|
||||
{
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 0]);
|
||||
test(`
|
||||
if (true) {
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 10]);
|
||||
test(`
|
||||
for (;;) {
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 9]);
|
||||
test(`
|
||||
while (true) {
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 13]);
|
||||
test(`
|
||||
do {
|
||||
do {
|
||||
} while(true);
|
||||
`, [2, 3]);
|
||||
|
||||
// try-catch-finally.
|
||||
test(`
|
||||
try {
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 4]);
|
||||
test(`
|
||||
try {
|
||||
} catch (e) {
|
||||
if (true) {
|
||||
}
|
||||
`, [3, 12]);
|
||||
test(`
|
||||
try {
|
||||
} finally {
|
||||
if (true) {
|
||||
}
|
||||
`, [3, 10]);
|
||||
|
||||
// Object literal.
|
||||
test(`
|
||||
var x = {
|
||||
foo: {
|
||||
};
|
||||
`, [2, 8]);
|
||||
|
||||
// Array literal.
|
||||
test(`
|
||||
var x = [
|
||||
[
|
||||
];
|
||||
`, [2, 8], "[", "]");
|
@ -141,6 +141,7 @@ GetObject(const MDefinition* ins)
|
||||
case MDefinition::Op_AtomicTypedArrayElementBinop:
|
||||
case MDefinition::Op_AsmJSLoadHeap:
|
||||
case MDefinition::Op_AsmJSStoreHeap:
|
||||
case MDefinition::Op_WasmLoadTls:
|
||||
case MDefinition::Op_WasmLoad:
|
||||
case MDefinition::Op_WasmStore:
|
||||
case MDefinition::Op_AsmJSCompareExchangeHeap:
|
||||
|
@ -329,7 +329,14 @@ DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame, ICUpdatedStub* stub, H
|
||||
MOZ_CRASH("Invalid stub");
|
||||
}
|
||||
|
||||
return stub->addUpdateStubForValue(cx, script /* = outerScript */, obj, id, value);
|
||||
if (!stub->addUpdateStubForValue(cx, script /* = outerScript */, obj, id, value)) {
|
||||
// The calling JIT code assumes this function is infallible (for
|
||||
// instance we may reallocate dynamic slots before calling this),
|
||||
// so ignore OOMs if we failed to attach a stub.
|
||||
cx->recoverFromOutOfMemory();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*DoTypeUpdateFallbackFn)(JSContext*, BaselineFrame*, ICUpdatedStub*, HandleValue,
|
||||
|
@ -12005,9 +12005,32 @@ CodeGenerator::visitWasmTrap(LWasmTrap* lir)
|
||||
void
|
||||
CodeGenerator::visitWasmBoundsCheck(LWasmBoundsCheck* ins)
|
||||
{
|
||||
#ifdef WASM_HUGE_MEMORY
|
||||
MOZ_CRASH("No wasm bounds check for huge memory");
|
||||
#else
|
||||
const MWasmBoundsCheck* mir = ins->mir();
|
||||
Register ptr = ToRegister(ins->ptr());
|
||||
masm.wasmBoundsCheck(Assembler::AboveOrEqual, ptr, trap(mir, wasm::Trap::OutOfBounds));
|
||||
Register boundsCheckLimit = ToRegister(ins->boundsCheckLimit());
|
||||
masm.wasmBoundsCheck(Assembler::AboveOrEqual, ptr, boundsCheckLimit,
|
||||
trap(mir, wasm::Trap::OutOfBounds));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitWasmLoadTls(LWasmLoadTls* ins)
|
||||
{
|
||||
switch (ins->mir()->type()) {
|
||||
case MIRType::Pointer:
|
||||
masm.loadPtr(Address(ToRegister(ins->tlsPtr()), ins->mir()->offset()),
|
||||
ToRegister(ins->output()));
|
||||
break;
|
||||
case MIRType::Int32:
|
||||
masm.load32(Address(ToRegister(ins->tlsPtr()), ins->mir()->offset()),
|
||||
ToRegister(ins->output()));
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("MIRType not supported in WasmLoadTls");
|
||||
}
|
||||
}
|
||||
|
||||
typedef bool (*RecompileFn)(JSContext*);
|
||||
|
@ -437,6 +437,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
||||
void visitInterruptCheck(LInterruptCheck* lir);
|
||||
void visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit* ins);
|
||||
void visitWasmTrap(LWasmTrap* lir);
|
||||
void visitWasmLoadTls(LWasmLoadTls* ins);
|
||||
void visitWasmBoundsCheck(LWasmBoundsCheck* ins);
|
||||
void visitRecompileCheck(LRecompileCheck* ins);
|
||||
void visitRotate(LRotate* ins);
|
||||
|
@ -937,7 +937,7 @@ ControlFlowGenerator::processWhileOrForInLoop(jssrcnote* sn)
|
||||
|
||||
size_t stackPhiCount;
|
||||
if (SN_TYPE(sn) == SRC_FOR_OF)
|
||||
stackPhiCount = 2;
|
||||
stackPhiCount = 3;
|
||||
else if (SN_TYPE(sn) == SRC_FOR_IN)
|
||||
stackPhiCount = 1;
|
||||
else
|
||||
|
@ -874,6 +874,14 @@ enum class BarrierKind : uint32_t {
|
||||
|
||||
enum ReprotectCode { Reprotect = true, DontReprotect = false };
|
||||
|
||||
// Rounding modes for round instructions.
|
||||
enum class RoundingMode {
|
||||
Down,
|
||||
Up,
|
||||
NearestTiesToEven,
|
||||
TowardsZero
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
@ -1432,6 +1432,22 @@ LIRGenerator::visitRound(MRound* ins)
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitNearbyInt(MNearbyInt* ins)
|
||||
{
|
||||
MIRType inputType = ins->input()->type();
|
||||
MOZ_ASSERT(IsFloatingPointType(inputType));
|
||||
MOZ_ASSERT(ins->type() == inputType);
|
||||
|
||||
LInstructionHelper<1, 1, 0>* lir;
|
||||
if (inputType == MIRType::Double)
|
||||
lir = new(alloc()) LNearbyInt(useRegisterAtStart(ins->input()));
|
||||
else
|
||||
lir = new(alloc()) LNearbyIntF(useRegisterAtStart(ins->input()));
|
||||
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitMinMax(MMinMax* ins)
|
||||
{
|
||||
@ -4254,19 +4270,39 @@ LIRGenerator::visitWasmAddOffset(MWasmAddOffset* ins)
|
||||
define(new(alloc()) LWasmAddOffset(useRegisterAtStart(ins->base())), ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitWasmLoadTls(MWasmLoadTls* ins)
|
||||
{
|
||||
#ifdef WASM_HUGE_MEMORY
|
||||
// This will disappear once we remove HeapReg and replace it with a load
|
||||
// from Tls, but in the mean time it keeps us sane.
|
||||
MOZ_CRASH("No WasmLoadTls here at the moment");
|
||||
#endif
|
||||
auto* lir = new(alloc()) LWasmLoadTls(useRegisterAtStart(ins->tlsPtr()));
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitWasmBoundsCheck(MWasmBoundsCheck* ins)
|
||||
{
|
||||
#ifdef WASM_HUGE_MEMORY
|
||||
MOZ_CRASH("No bounds checking on huge memory");
|
||||
#else
|
||||
if (ins->isRedundant()) {
|
||||
if (MOZ_LIKELY(!JitOptions.wasmAlwaysCheckBounds))
|
||||
return;
|
||||
}
|
||||
|
||||
MDefinition* input = ins->input();
|
||||
MOZ_ASSERT(input->type() == MIRType::Int32);
|
||||
MDefinition* index = ins->index();
|
||||
MOZ_ASSERT(index->type() == MIRType::Int32);
|
||||
|
||||
auto* lir = new(alloc()) LWasmBoundsCheck(useRegisterAtStart(input));
|
||||
MDefinition* boundsCheckLimit = ins->boundsCheckLimit();
|
||||
MOZ_ASSERT(boundsCheckLimit->type() == MIRType::Int32);
|
||||
|
||||
auto* lir = new(alloc()) LWasmBoundsCheck(useRegisterAtStart(index),
|
||||
useRegisterAtStart(boundsCheckLimit));
|
||||
add(lir, ins);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -135,6 +135,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
void visitFloor(MFloor* ins);
|
||||
void visitCeil(MCeil* ins);
|
||||
void visitRound(MRound* ins);
|
||||
void visitNearbyInt(MNearbyInt* ins);
|
||||
void visitMinMax(MMinMax* ins);
|
||||
void visitAbs(MAbs* ins);
|
||||
void visitClz(MClz* ins);
|
||||
@ -292,6 +293,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
void visitIsObject(MIsObject* ins);
|
||||
void visitHasClass(MHasClass* ins);
|
||||
void visitWasmAddOffset(MWasmAddOffset* ins);
|
||||
void visitWasmLoadTls(MWasmLoadTls* ins);
|
||||
void visitWasmBoundsCheck(MWasmBoundsCheck* ins);
|
||||
void visitWasmLoadGlobalVar(MWasmLoadGlobalVar* ins);
|
||||
void visitWasmStoreGlobalVar(MWasmStoreGlobalVar* ins);
|
||||
|
@ -986,20 +986,30 @@ IonBuilder::inlineMathFloor(CallInfo& callInfo)
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
if (IsFloatingPointType(argType) && returnType == MIRType::Int32) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
MFloor* ins = MFloor::New(alloc(), callInfo.getArg(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
if (IsFloatingPointType(argType)) {
|
||||
if (returnType == MIRType::Int32) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
MFloor* ins = MFloor::New(alloc(), callInfo.getArg(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
if (IsFloatingPointType(argType) && returnType == MIRType::Double) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
MMathFunction* ins = MMathFunction::New(alloc(), callInfo.getArg(0), MMathFunction::Floor, nullptr);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
if (returnType == MIRType::Double) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MInstruction* ins = nullptr;
|
||||
if (MNearbyInt::HasAssemblerSupport(RoundingMode::Down)) {
|
||||
ins = MNearbyInt::New(alloc(), callInfo.getArg(0), argType, RoundingMode::Down);
|
||||
} else {
|
||||
ins = MMathFunction::New(alloc(), callInfo.getArg(0), MMathFunction::Floor,
|
||||
/* cache */ nullptr);
|
||||
}
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
}
|
||||
|
||||
return InliningStatus_NotInlined;
|
||||
@ -1030,20 +1040,30 @@ IonBuilder::inlineMathCeil(CallInfo& callInfo)
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
if (IsFloatingPointType(argType) && returnType == MIRType::Int32) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
MCeil* ins = MCeil::New(alloc(), callInfo.getArg(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
if (IsFloatingPointType(argType)) {
|
||||
if (returnType == MIRType::Int32) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
MCeil* ins = MCeil::New(alloc(), callInfo.getArg(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
if (IsFloatingPointType(argType) && returnType == MIRType::Double) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
MMathFunction* ins = MMathFunction::New(alloc(), callInfo.getArg(0), MMathFunction::Ceil, nullptr);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
if (returnType == MIRType::Double) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MInstruction* ins = nullptr;
|
||||
if (MNearbyInt::HasAssemblerSupport(RoundingMode::Up)) {
|
||||
ins = MNearbyInt::New(alloc(), callInfo.getArg(0), argType, RoundingMode::Up);
|
||||
} else {
|
||||
ins = MMathFunction::New(alloc(), callInfo.getArg(0), MMathFunction::Ceil,
|
||||
/* cache */ nullptr);
|
||||
}
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
}
|
||||
|
||||
return InliningStatus_NotInlined;
|
||||
@ -1108,7 +1128,8 @@ IonBuilder::inlineMathRound(CallInfo& callInfo)
|
||||
|
||||
if (IsFloatingPointType(argType) && returnType == MIRType::Double) {
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
MMathFunction* ins = MMathFunction::New(alloc(), callInfo.getArg(0), MMathFunction::Round, nullptr);
|
||||
MMathFunction* ins = MMathFunction::New(alloc(), callInfo.getArg(0), MMathFunction::Round,
|
||||
/* cache */ nullptr);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return InliningStatus_Inlined;
|
||||
|
@ -1778,6 +1778,19 @@ MAssertRange::printOpcode(GenericPrinter& out) const
|
||||
assertedRange()->dump(out);
|
||||
}
|
||||
|
||||
void MNearbyInt::printOpcode(GenericPrinter& out) const
|
||||
{
|
||||
MDefinition::printOpcode(out);
|
||||
const char* roundingModeStr = nullptr;
|
||||
switch (roundingMode_) {
|
||||
case RoundingMode::Up: roundingModeStr = "(up)"; break;
|
||||
case RoundingMode::Down: roundingModeStr = "(down)"; break;
|
||||
case RoundingMode::NearestTiesToEven: roundingModeStr = "(nearest ties even)"; break;
|
||||
case RoundingMode::TowardsZero: roundingModeStr = "(towards zero)"; break;
|
||||
}
|
||||
out.printf(" %s", roundingModeStr);
|
||||
}
|
||||
|
||||
const char*
|
||||
MMathFunction::FunctionName(Function function)
|
||||
{
|
||||
@ -2153,6 +2166,13 @@ MRound::trySpecializeFloat32(TempAllocator& alloc)
|
||||
specialization_ = MIRType::Float32;
|
||||
}
|
||||
|
||||
void
|
||||
MNearbyInt::trySpecializeFloat32(TempAllocator& alloc)
|
||||
{
|
||||
if (EnsureFloatInputOrConvert(this, alloc))
|
||||
specialization_ = MIRType::Float32;
|
||||
}
|
||||
|
||||
MTableSwitch*
|
||||
MTableSwitch::New(TempAllocator& alloc, MDefinition* ins, int32_t low, int32_t high)
|
||||
{
|
||||
|
354
js/src/jit/MIR.h
354
js/src/jit/MIR.h
@ -385,11 +385,13 @@ class AliasSet {
|
||||
FrameArgument = 1 << 6, // An argument kept on the stack frame
|
||||
WasmGlobalVar = 1 << 7, // An asm.js/wasm global var
|
||||
WasmHeap = 1 << 8, // An asm.js/wasm heap load
|
||||
TypedArrayLength = 1 << 9,// A typed array's length
|
||||
WasmHeapMeta = 1 << 9, // The asm.js/wasm heap base pointer and
|
||||
// bounds check limit, in Tls.
|
||||
TypedArrayLength = 1 << 10,// A typed array's length
|
||||
Last = TypedArrayLength,
|
||||
Any = Last | (Last - 1),
|
||||
|
||||
NumCategories = 10,
|
||||
NumCategories = 11,
|
||||
|
||||
// Indicates load or store.
|
||||
Store_ = 1 << 31
|
||||
@ -12190,7 +12192,7 @@ class MStringLength
|
||||
ALLOW_CLONE(MStringLength)
|
||||
};
|
||||
|
||||
// Inlined version of Math.floor().
|
||||
// Inlined assembly for Math.floor(double | float32) -> int32.
|
||||
class MFloor
|
||||
: public MUnaryInstruction,
|
||||
public FloatingPointPolicy<0>::Data
|
||||
@ -12231,7 +12233,7 @@ class MFloor
|
||||
ALLOW_CLONE(MFloor)
|
||||
};
|
||||
|
||||
// Inlined version of Math.ceil().
|
||||
// Inlined assembly version for Math.ceil(double | float32) -> int32.
|
||||
class MCeil
|
||||
: public MUnaryInstruction,
|
||||
public FloatingPointPolicy<0>::Data
|
||||
@ -12272,7 +12274,7 @@ class MCeil
|
||||
ALLOW_CLONE(MCeil)
|
||||
};
|
||||
|
||||
// Inlined version of Math.round().
|
||||
// Inlined version of Math.round(double | float32) -> int32.
|
||||
class MRound
|
||||
: public MUnaryInstruction,
|
||||
public FloatingPointPolicy<0>::Data
|
||||
@ -12314,6 +12316,61 @@ class MRound
|
||||
ALLOW_CLONE(MRound)
|
||||
};
|
||||
|
||||
// NearbyInt rounds the floating-point input to the nearest integer, according
|
||||
// to the RoundingMode.
|
||||
class MNearbyInt
|
||||
: public MUnaryInstruction,
|
||||
public FloatingPointPolicy<0>::Data
|
||||
{
|
||||
RoundingMode roundingMode_;
|
||||
|
||||
explicit MNearbyInt(MDefinition* num, MIRType resultType, RoundingMode roundingMode)
|
||||
: MUnaryInstruction(num),
|
||||
roundingMode_(roundingMode)
|
||||
{
|
||||
MOZ_ASSERT(HasAssemblerSupport(roundingMode));
|
||||
|
||||
MOZ_ASSERT(IsFloatingPointType(resultType));
|
||||
setResultType(resultType);
|
||||
specialization_ = resultType;
|
||||
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NearbyInt)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
static bool HasAssemblerSupport(RoundingMode mode) {
|
||||
return Assembler::HasRoundInstruction(mode);
|
||||
}
|
||||
|
||||
RoundingMode roundingMode() const { return roundingMode_; }
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
||||
bool isFloat32Commutative() const override {
|
||||
return true;
|
||||
}
|
||||
void trySpecializeFloat32(TempAllocator& alloc) override;
|
||||
#ifdef DEBUG
|
||||
bool isConsistentFloat32Use(MUse* use) const override {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins) &&
|
||||
ins->toNearbyInt()->roundingMode() == roundingMode_;
|
||||
}
|
||||
|
||||
void printOpcode(GenericPrinter& out) const override;
|
||||
|
||||
ALLOW_CLONE(MNearbyInt)
|
||||
};
|
||||
|
||||
class MIteratorStart
|
||||
: public MUnaryInstruction,
|
||||
public BoxExceptPolicy<0, MIRType::Object>::Data
|
||||
@ -13617,15 +13674,62 @@ class MAsmJSNeg
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
};
|
||||
|
||||
class MWasmBoundsCheck
|
||||
class MWasmLoadTls
|
||||
: public MUnaryInstruction,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
uint32_t offset_;
|
||||
AliasSet aliases_;
|
||||
|
||||
explicit MWasmLoadTls(MDefinition* tlsPointer, uint32_t offset, MIRType type, AliasSet aliases)
|
||||
: MUnaryInstruction(tlsPointer),
|
||||
offset_(offset),
|
||||
aliases_(aliases)
|
||||
{
|
||||
// Different Tls data have different alias classes and only those classes are allowed.
|
||||
MOZ_ASSERT(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() ||
|
||||
aliases_.flags() == AliasSet::None().flags());
|
||||
|
||||
// The only types supported at the moment.
|
||||
MOZ_ASSERT(type == MIRType::Pointer || type == MIRType::Int32);
|
||||
|
||||
setMovable();
|
||||
setResultType(type);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(WasmLoadTls)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, tlsPtr))
|
||||
|
||||
uint32_t offset() const {
|
||||
return offset_;
|
||||
}
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return op() == ins->op() &&
|
||||
offset() == ins->toWasmLoadTls()->offset() &&
|
||||
type() == ins->type();
|
||||
}
|
||||
|
||||
HashNumber valueHash() const override {
|
||||
return op() + offset();
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return aliases_;
|
||||
}
|
||||
};
|
||||
|
||||
class MWasmBoundsCheck
|
||||
: public MBinaryInstruction,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
bool redundant_;
|
||||
wasm::TrapOffset trapOffset_;
|
||||
|
||||
explicit MWasmBoundsCheck(MDefinition* index, wasm::TrapOffset trapOffset)
|
||||
: MUnaryInstruction(index),
|
||||
explicit MWasmBoundsCheck(MDefinition* index, MDefinition* boundsCheckLimit, wasm::TrapOffset trapOffset)
|
||||
: MBinaryInstruction(index, boundsCheckLimit),
|
||||
redundant_(false),
|
||||
trapOffset_(trapOffset)
|
||||
{
|
||||
@ -13635,6 +13739,7 @@ class MWasmBoundsCheck
|
||||
public:
|
||||
INSTRUCTION_HEADER(WasmBoundsCheck)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, index), (1, boundsCheckLimit))
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
@ -13689,14 +13794,13 @@ class MWasmAddOffset
|
||||
};
|
||||
|
||||
class MWasmLoad
|
||||
: public MUnaryInstruction,
|
||||
: public MVariadicInstruction, // memoryBase is nullptr on some platforms
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
wasm::MemoryAccessDesc access_;
|
||||
|
||||
MWasmLoad(MDefinition* base, const wasm::MemoryAccessDesc& access, MIRType resultType)
|
||||
: MUnaryInstruction(base),
|
||||
access_(access)
|
||||
explicit MWasmLoad(const wasm::MemoryAccessDesc& access, MIRType resultType)
|
||||
: access_(access)
|
||||
{
|
||||
setGuard();
|
||||
setResultType(resultType);
|
||||
@ -13704,8 +13808,24 @@ class MWasmLoad
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(WasmLoad)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, base))
|
||||
NAMED_OPERANDS((0, base), (1, memoryBase));
|
||||
|
||||
static MWasmLoad* New(TempAllocator& alloc,
|
||||
MDefinition* memoryBase,
|
||||
MDefinition* base,
|
||||
const wasm::MemoryAccessDesc& access,
|
||||
MIRType resultType)
|
||||
{
|
||||
MWasmLoad* load = new(alloc) MWasmLoad(access, resultType);
|
||||
if (!load->init(alloc, 1 + !!memoryBase))
|
||||
return nullptr;
|
||||
|
||||
load->initOperand(0, base);
|
||||
if (memoryBase)
|
||||
load->initOperand(1, memoryBase);
|
||||
|
||||
return load;
|
||||
}
|
||||
|
||||
const wasm::MemoryAccessDesc& access() const {
|
||||
return access_;
|
||||
@ -13721,22 +13841,38 @@ class MWasmLoad
|
||||
};
|
||||
|
||||
class MWasmStore
|
||||
: public MBinaryInstruction,
|
||||
: public MVariadicInstruction,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
wasm::MemoryAccessDesc access_;
|
||||
|
||||
MWasmStore(MDefinition* base, const wasm::MemoryAccessDesc& access, MDefinition* value)
|
||||
: MBinaryInstruction(base, value),
|
||||
access_(access)
|
||||
explicit MWasmStore(const wasm::MemoryAccessDesc& access)
|
||||
: access_(access)
|
||||
{
|
||||
setGuard();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(WasmStore)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, base), (1, value))
|
||||
NAMED_OPERANDS((0, base), (1, value), (2, memoryBase))
|
||||
|
||||
static MWasmStore* New(TempAllocator& alloc,
|
||||
MDefinition* memoryBase,
|
||||
MDefinition* base,
|
||||
const wasm::MemoryAccessDesc& access,
|
||||
MDefinition* value)
|
||||
{
|
||||
MWasmStore* store = new(alloc) MWasmStore(access);
|
||||
if (!store->init(alloc, 2 + !!memoryBase))
|
||||
return nullptr;
|
||||
|
||||
store->initOperand(0, base);
|
||||
store->initOperand(1, value);
|
||||
if (memoryBase)
|
||||
store->initOperand(2, memoryBase);
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
const wasm::MemoryAccessDesc& access() const {
|
||||
return access_;
|
||||
@ -13779,23 +13915,53 @@ class MAsmJSMemoryAccess
|
||||
};
|
||||
|
||||
class MAsmJSLoadHeap
|
||||
: public MUnaryInstruction,
|
||||
: public MVariadicInstruction, // 1 plus optional memoryBase and boundsCheckLimit
|
||||
public MAsmJSMemoryAccess,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
MAsmJSLoadHeap(MDefinition* base, Scalar::Type accessType)
|
||||
: MUnaryInstruction(base),
|
||||
MAsmJSMemoryAccess(accessType)
|
||||
uint32_t memoryBaseIndex_;
|
||||
uint32_t boundsCheckIndex_;
|
||||
|
||||
explicit MAsmJSLoadHeap(uint32_t memoryBaseIndex, uint32_t boundsCheckIndex,
|
||||
Scalar::Type accessType)
|
||||
: MAsmJSMemoryAccess(accessType),
|
||||
memoryBaseIndex_(memoryBaseIndex),
|
||||
boundsCheckIndex_(boundsCheckIndex)
|
||||
{
|
||||
setResultType(ScalarTypeToMIRType(accessType));
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmJSLoadHeap)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
static MAsmJSLoadHeap* New(TempAllocator& alloc,
|
||||
MDefinition* memoryBase,
|
||||
MDefinition* base,
|
||||
MDefinition* boundsCheckLimit,
|
||||
Scalar::Type accessType)
|
||||
{
|
||||
uint32_t nextIndex = 1;
|
||||
uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX;
|
||||
uint32_t boundsCheckIndex = boundsCheckLimit ? nextIndex++ : UINT32_MAX;
|
||||
|
||||
MAsmJSLoadHeap* load = new(alloc) MAsmJSLoadHeap(memoryBaseIndex, boundsCheckIndex,
|
||||
accessType);
|
||||
if (!load->init(alloc, nextIndex))
|
||||
return nullptr;
|
||||
|
||||
load->initOperand(0, base);
|
||||
if (memoryBase)
|
||||
load->initOperand(memoryBaseIndex, memoryBase);
|
||||
if (boundsCheckLimit)
|
||||
load->initOperand(boundsCheckIndex, boundsCheckLimit);
|
||||
|
||||
return load;
|
||||
}
|
||||
|
||||
MDefinition* base() const { return getOperand(0); }
|
||||
void replaceBase(MDefinition* newBase) { replaceOperand(0, newBase); }
|
||||
MDefinition* memoryBase() const { return getOperand(memoryBaseIndex_); }
|
||||
MDefinition* boundsCheckLimit() const { return getOperand(boundsCheckIndex_); }
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override;
|
||||
AliasSet getAliasSet() const override {
|
||||
@ -13805,22 +13971,55 @@ class MAsmJSLoadHeap
|
||||
};
|
||||
|
||||
class MAsmJSStoreHeap
|
||||
: public MBinaryInstruction,
|
||||
: public MVariadicInstruction, // 2 plus optional memoryBase and boundsCheckLimit
|
||||
public MAsmJSMemoryAccess,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
MAsmJSStoreHeap(MDefinition* base, Scalar::Type accessType, MDefinition* v)
|
||||
: MBinaryInstruction(base, v),
|
||||
MAsmJSMemoryAccess(accessType)
|
||||
{}
|
||||
uint32_t memoryBaseIndex_;
|
||||
uint32_t boundsCheckIndex_;
|
||||
|
||||
explicit MAsmJSStoreHeap(uint32_t memoryBaseIndex, uint32_t boundsCheckIndex,
|
||||
Scalar::Type accessType)
|
||||
: MAsmJSMemoryAccess(accessType),
|
||||
memoryBaseIndex_(memoryBaseIndex),
|
||||
boundsCheckIndex_(boundsCheckIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmJSStoreHeap)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
static MAsmJSStoreHeap* New(TempAllocator& alloc,
|
||||
MDefinition* memoryBase,
|
||||
MDefinition* base,
|
||||
MDefinition* boundsCheckLimit,
|
||||
Scalar::Type accessType,
|
||||
MDefinition* v)
|
||||
{
|
||||
uint32_t nextIndex = 2;
|
||||
uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX;
|
||||
uint32_t boundsCheckIndex = boundsCheckLimit ? nextIndex++ : UINT32_MAX;
|
||||
|
||||
MAsmJSStoreHeap* store = new(alloc) MAsmJSStoreHeap(memoryBaseIndex, boundsCheckIndex,
|
||||
accessType);
|
||||
if (!store->init(alloc, nextIndex))
|
||||
return nullptr;
|
||||
|
||||
store->initOperand(0, base);
|
||||
store->initOperand(1, v);
|
||||
if (memoryBase)
|
||||
store->initOperand(memoryBaseIndex, memoryBase);
|
||||
if (boundsCheckLimit)
|
||||
store->initOperand(boundsCheckIndex, boundsCheckLimit);
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
MDefinition* base() const { return getOperand(0); }
|
||||
void replaceBase(MDefinition* newBase) { replaceOperand(0, newBase); }
|
||||
MDefinition* value() const { return getOperand(1); }
|
||||
MDefinition* memoryBase() const { return getOperand(memoryBaseIndex_); }
|
||||
MDefinition* boundsCheckLimit() const { return getOperand(boundsCheckIndex_); }
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Store(AliasSet::WasmHeap);
|
||||
@ -13828,15 +14027,13 @@ class MAsmJSStoreHeap
|
||||
};
|
||||
|
||||
class MAsmJSCompareExchangeHeap
|
||||
: public MQuaternaryInstruction,
|
||||
: public MVariadicInstruction,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
wasm::MemoryAccessDesc access_;
|
||||
|
||||
MAsmJSCompareExchangeHeap(MDefinition* base, const wasm::MemoryAccessDesc& access,
|
||||
MDefinition* oldv, MDefinition* newv, MDefinition* tls)
|
||||
: MQuaternaryInstruction(base, oldv, newv, tls),
|
||||
access_(access)
|
||||
explicit MAsmJSCompareExchangeHeap(const wasm::MemoryAccessDesc& access)
|
||||
: access_(access)
|
||||
{
|
||||
setGuard(); // Not removable
|
||||
setResultType(MIRType::Int32);
|
||||
@ -13844,7 +14041,28 @@ class MAsmJSCompareExchangeHeap
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmJSCompareExchangeHeap)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
static MAsmJSCompareExchangeHeap* New(TempAllocator& alloc,
|
||||
MDefinition* memoryBase,
|
||||
MDefinition* base,
|
||||
const wasm::MemoryAccessDesc& access,
|
||||
MDefinition* oldv,
|
||||
MDefinition* newv,
|
||||
MDefinition* tls)
|
||||
{
|
||||
MAsmJSCompareExchangeHeap* cas = new(alloc) MAsmJSCompareExchangeHeap(access);
|
||||
if (!cas->init(alloc, 4 + !!memoryBase))
|
||||
return nullptr;
|
||||
|
||||
cas->initOperand(0, base);
|
||||
cas->initOperand(1, oldv);
|
||||
cas->initOperand(2, newv);
|
||||
cas->initOperand(3, tls);
|
||||
if (memoryBase)
|
||||
cas->initOperand(4, memoryBase);
|
||||
|
||||
return cas;
|
||||
}
|
||||
|
||||
const wasm::MemoryAccessDesc& access() const { return access_; }
|
||||
|
||||
@ -13852,6 +14070,7 @@ class MAsmJSCompareExchangeHeap
|
||||
MDefinition* oldValue() const { return getOperand(1); }
|
||||
MDefinition* newValue() const { return getOperand(2); }
|
||||
MDefinition* tls() const { return getOperand(3); }
|
||||
MDefinition* memoryBase() const { return getOperand(4); }
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Store(AliasSet::WasmHeap);
|
||||
@ -13859,15 +14078,13 @@ class MAsmJSCompareExchangeHeap
|
||||
};
|
||||
|
||||
class MAsmJSAtomicExchangeHeap
|
||||
: public MTernaryInstruction,
|
||||
: public MVariadicInstruction,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
wasm::MemoryAccessDesc access_;
|
||||
|
||||
MAsmJSAtomicExchangeHeap(MDefinition* base, const wasm::MemoryAccessDesc& access,
|
||||
MDefinition* value, MDefinition* tls)
|
||||
: MTernaryInstruction(base, value, tls),
|
||||
access_(access)
|
||||
explicit MAsmJSAtomicExchangeHeap(const wasm::MemoryAccessDesc& access)
|
||||
: access_(access)
|
||||
{
|
||||
setGuard(); // Not removable
|
||||
setResultType(MIRType::Int32);
|
||||
@ -13875,13 +14092,33 @@ class MAsmJSAtomicExchangeHeap
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmJSAtomicExchangeHeap)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
static MAsmJSAtomicExchangeHeap* New(TempAllocator& alloc,
|
||||
MDefinition* memoryBase,
|
||||
MDefinition* base,
|
||||
const wasm::MemoryAccessDesc& access,
|
||||
MDefinition* value,
|
||||
MDefinition* tls)
|
||||
{
|
||||
MAsmJSAtomicExchangeHeap* xchg = new(alloc) MAsmJSAtomicExchangeHeap(access);
|
||||
if (!xchg->init(alloc, 3 + !!memoryBase))
|
||||
return nullptr;
|
||||
|
||||
xchg->initOperand(0, base);
|
||||
xchg->initOperand(1, value);
|
||||
xchg->initOperand(2, tls);
|
||||
if (memoryBase)
|
||||
xchg->initOperand(3, memoryBase);
|
||||
|
||||
return xchg;
|
||||
}
|
||||
|
||||
const wasm::MemoryAccessDesc& access() const { return access_; }
|
||||
|
||||
MDefinition* base() const { return getOperand(0); }
|
||||
MDefinition* value() const { return getOperand(1); }
|
||||
MDefinition* tls() const { return getOperand(2); }
|
||||
MDefinition* memoryBase() const { return getOperand(3); }
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Store(AliasSet::WasmHeap);
|
||||
@ -13889,16 +14126,14 @@ class MAsmJSAtomicExchangeHeap
|
||||
};
|
||||
|
||||
class MAsmJSAtomicBinopHeap
|
||||
: public MTernaryInstruction,
|
||||
: public MVariadicInstruction,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
AtomicOp op_;
|
||||
wasm::MemoryAccessDesc access_;
|
||||
|
||||
MAsmJSAtomicBinopHeap(AtomicOp op, MDefinition* base, const wasm::MemoryAccessDesc& access,
|
||||
MDefinition* v, MDefinition* tls)
|
||||
: MTernaryInstruction(base, v, tls),
|
||||
op_(op),
|
||||
explicit MAsmJSAtomicBinopHeap(AtomicOp op, const wasm::MemoryAccessDesc& access)
|
||||
: op_(op),
|
||||
access_(access)
|
||||
{
|
||||
setGuard(); // Not removable
|
||||
@ -13907,7 +14142,27 @@ class MAsmJSAtomicBinopHeap
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmJSAtomicBinopHeap)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
static MAsmJSAtomicBinopHeap* New(TempAllocator& alloc,
|
||||
AtomicOp op,
|
||||
MDefinition* memoryBase,
|
||||
MDefinition* base,
|
||||
const wasm::MemoryAccessDesc& access,
|
||||
MDefinition* v,
|
||||
MDefinition* tls)
|
||||
{
|
||||
MAsmJSAtomicBinopHeap* binop = new(alloc) MAsmJSAtomicBinopHeap(op, access);
|
||||
if (!binop->init(alloc, 3 + !!memoryBase))
|
||||
return nullptr;
|
||||
|
||||
binop->initOperand(0, base);
|
||||
binop->initOperand(1, v);
|
||||
binop->initOperand(2, tls);
|
||||
if (memoryBase)
|
||||
binop->initOperand(3, memoryBase);
|
||||
|
||||
return binop;
|
||||
}
|
||||
|
||||
AtomicOp operation() const { return op_; }
|
||||
const wasm::MemoryAccessDesc& access() const { return access_; }
|
||||
@ -13915,6 +14170,7 @@ class MAsmJSAtomicBinopHeap
|
||||
MDefinition* base() const { return getOperand(0); }
|
||||
MDefinition* value() const { return getOperand(1); }
|
||||
MDefinition* tls() const { return getOperand(2); }
|
||||
MDefinition* memoryBase() const { return getOperand(3); }
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Store(AliasSet::WasmHeap);
|
||||
|
@ -263,6 +263,7 @@ namespace jit {
|
||||
_(Floor) \
|
||||
_(Ceil) \
|
||||
_(Round) \
|
||||
_(NearbyInt) \
|
||||
_(In) \
|
||||
_(InstanceOf) \
|
||||
_(CallInstanceOf) \
|
||||
@ -297,6 +298,7 @@ namespace jit {
|
||||
_(AsmJSAtomicExchangeHeap) \
|
||||
_(AsmJSAtomicBinopHeap) \
|
||||
_(WasmBoundsCheck) \
|
||||
_(WasmLoadTls) \
|
||||
_(WasmAddOffset) \
|
||||
_(WasmLoad) \
|
||||
_(WasmStore) \
|
||||
|
@ -1360,14 +1360,15 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
// ========================================================================
|
||||
// wasm support
|
||||
|
||||
// Emit a bounds check against the (dynamically-patched) wasm bounds check
|
||||
// limit, jumping to 'label' if 'cond' holds.
|
||||
// Emit a bounds check against the wasm heap limit, jumping to 'label' if 'cond' holds.
|
||||
// Required when WASM_HUGE_MEMORY is not defined.
|
||||
template <class L>
|
||||
inline void wasmBoundsCheck(Condition cond, Register index, L label) PER_ARCH;
|
||||
inline void wasmBoundsCheck(Condition cond, Register index, Register boundsCheckLimit, L label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86);
|
||||
|
||||
// Called after compilation completes to patch the given limit into the
|
||||
// given instruction's immediate.
|
||||
static inline void wasmPatchBoundsCheck(uint8_t* patchAt, uint32_t limit) PER_ARCH;
|
||||
template <class L>
|
||||
inline void wasmBoundsCheck(Condition cond, Register index, Address boundsCheckLimit, L label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86);
|
||||
|
||||
// On x86, each instruction adds its own wasm::MemoryAccess's to the
|
||||
// wasm::MemoryAccessVector (there can be multiple when i64 is involved).
|
||||
|
@ -1747,6 +1747,8 @@ class Assembler : public AssemblerShared
|
||||
return js::jit::SupportsSimd;
|
||||
}
|
||||
|
||||
static bool HasRoundInstruction(RoundingMode mode) { return false; }
|
||||
|
||||
protected:
|
||||
void addPendingJump(BufferOffset src, ImmPtr target, Relocation::Kind kind) {
|
||||
enoughMemory_ &= jumps_.append(RelativePatch(target.value, kind));
|
||||
|
@ -2292,6 +2292,7 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins)
|
||||
MOZ_ASSERT(mir->offset() == 0);
|
||||
|
||||
const LAllocation* ptr = ins->ptr();
|
||||
const LAllocation* boundsCheckLimit = ins->boundsCheckLimit();
|
||||
|
||||
bool isSigned;
|
||||
int size;
|
||||
@ -2325,7 +2326,6 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins)
|
||||
ToRegister(ins->output()), scratch, Offset, Assembler::Always);
|
||||
}
|
||||
} else {
|
||||
ScratchRegisterScope scratch(masm);
|
||||
Register ptrReg = ToRegister(ptr);
|
||||
if (isFloat) {
|
||||
FloatRegister output = ToFloatRegister(ins->output());
|
||||
@ -2334,8 +2334,8 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins)
|
||||
|
||||
Assembler::Condition cond = Assembler::Always;
|
||||
if (mir->needsBoundsCheck()) {
|
||||
BufferOffset cmp = masm.as_cmp(ptrReg, Imm8(0));
|
||||
masm.append(wasm::BoundsCheck(cmp.getOffset()));
|
||||
Register boundsCheckLimitReg = ToRegister(boundsCheckLimit);
|
||||
masm.as_cmp(ptrReg, O2Reg(boundsCheckLimitReg));
|
||||
if (size == 32)
|
||||
masm.ma_vimm_f32(GenericNaN(), output, Assembler::AboveOrEqual);
|
||||
else
|
||||
@ -2343,19 +2343,20 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins)
|
||||
cond = Assembler::Below;
|
||||
}
|
||||
|
||||
ScratchRegisterScope scratch(masm);
|
||||
masm.ma_vldr(output, HeapReg, ptrReg, scratch, 0, cond);
|
||||
} else {
|
||||
Register output = ToRegister(ins->output());
|
||||
|
||||
Assembler::Condition cond = Assembler::Always;
|
||||
if (mir->needsBoundsCheck()) {
|
||||
uint32_t cmpOffset = masm.as_cmp(ptrReg, Imm8(0)).getOffset();
|
||||
masm.append(wasm::BoundsCheck(cmpOffset));
|
||||
|
||||
Register boundsCheckLimitReg = ToRegister(boundsCheckLimit);
|
||||
masm.as_cmp(ptrReg, O2Reg(boundsCheckLimitReg));
|
||||
masm.ma_mov(Imm32(0), output, Assembler::AboveOrEqual);
|
||||
cond = Assembler::Below;
|
||||
}
|
||||
|
||||
ScratchRegisterScope scratch(masm);
|
||||
masm.ma_dataTransferN(IsLoad, size, isSigned, HeapReg, ptrReg, output, scratch, Offset, cond);
|
||||
}
|
||||
}
|
||||
@ -2517,6 +2518,7 @@ CodeGeneratorARM::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins)
|
||||
MOZ_ASSERT(mir->offset() == 0);
|
||||
|
||||
const LAllocation* ptr = ins->ptr();
|
||||
const LAllocation* boundsCheckLimit = ins->boundsCheckLimit();
|
||||
|
||||
bool isSigned;
|
||||
int size;
|
||||
@ -2554,9 +2556,8 @@ CodeGeneratorARM::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins)
|
||||
|
||||
Assembler::Condition cond = Assembler::Always;
|
||||
if (mir->needsBoundsCheck()) {
|
||||
BufferOffset cmp = masm.as_cmp(ptrReg, Imm8(0));
|
||||
masm.append(wasm::BoundsCheck(cmp.getOffset()));
|
||||
|
||||
Register boundsCheckLimitReg = ToRegister(boundsCheckLimit);
|
||||
masm.as_cmp(ptrReg, O2Reg(boundsCheckLimitReg));
|
||||
cond = Assembler::Below;
|
||||
}
|
||||
|
||||
|
@ -612,7 +612,7 @@ class LWasmUnalignedLoadBase : public details::LWasmLoadBase<NumDefs, 4>
|
||||
explicit LWasmUnalignedLoadBase(const LAllocation& ptr, const LDefinition& ptrCopy,
|
||||
const LDefinition& temp1, const LDefinition& temp2,
|
||||
const LDefinition& temp3)
|
||||
: Base(ptr)
|
||||
: Base(ptr, LAllocation())
|
||||
{
|
||||
Base::setTemp(0, ptrCopy);
|
||||
Base::setTemp(1, temp1);
|
||||
|
@ -712,15 +712,22 @@ LIRGeneratorARM::visitAsmJSLoadHeap(MAsmJSLoadHeap* ins)
|
||||
|
||||
// For the ARM it is best to keep the 'base' in a register if a bounds check is needed.
|
||||
LAllocation baseAlloc;
|
||||
LAllocation limitAlloc;
|
||||
|
||||
if (base->isConstant() && !ins->needsBoundsCheck()) {
|
||||
// A bounds check is only skipped for a positive index.
|
||||
MOZ_ASSERT(base->toConstant()->toInt32() >= 0);
|
||||
baseAlloc = LAllocation(base->toConstant());
|
||||
} else {
|
||||
baseAlloc = useRegisterAtStart(base);
|
||||
if (ins->needsBoundsCheck()) {
|
||||
MDefinition* boundsCheckLimit = ins->boundsCheckLimit();
|
||||
MOZ_ASSERT(boundsCheckLimit->type() == MIRType::Int32);
|
||||
limitAlloc = useRegisterAtStart(boundsCheckLimit);
|
||||
}
|
||||
}
|
||||
|
||||
define(new(alloc()) LAsmJSLoadHeap(baseAlloc), ins);
|
||||
define(new(alloc()) LAsmJSLoadHeap(baseAlloc, limitAlloc), ins);
|
||||
}
|
||||
|
||||
void
|
||||
@ -730,16 +737,24 @@ LIRGeneratorARM::visitAsmJSStoreHeap(MAsmJSStoreHeap* ins)
|
||||
|
||||
MDefinition* base = ins->base();
|
||||
MOZ_ASSERT(base->type() == MIRType::Int32);
|
||||
|
||||
LAllocation baseAlloc;
|
||||
LAllocation limitAlloc;
|
||||
|
||||
if (base->isConstant() && !ins->needsBoundsCheck()) {
|
||||
MOZ_ASSERT(base->toConstant()->toInt32() >= 0);
|
||||
baseAlloc = LAllocation(base->toConstant());
|
||||
} else {
|
||||
baseAlloc = useRegisterAtStart(base);
|
||||
if (ins->needsBoundsCheck()) {
|
||||
MDefinition* boundsCheckLimit = ins->boundsCheckLimit();
|
||||
MOZ_ASSERT(boundsCheckLimit->type() == MIRType::Int32);
|
||||
limitAlloc = useRegisterAtStart(boundsCheckLimit);
|
||||
}
|
||||
}
|
||||
|
||||
add(new(alloc()) LAsmJSStoreHeap(baseAlloc, useRegisterAtStart(ins->value())), ins);
|
||||
add(new(alloc()) LAsmJSStoreHeap(baseAlloc, useRegisterAtStart(ins->value()), limitAlloc),
|
||||
ins);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2127,31 +2127,21 @@ MacroAssembler::clampIntToUint8(Register reg)
|
||||
|
||||
template <class L>
|
||||
void
|
||||
MacroAssembler::wasmBoundsCheck(Condition cond, Register index, L label)
|
||||
MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Register boundsCheckLimit, L label)
|
||||
{
|
||||
BufferOffset bo = as_cmp(index, Imm8(0));
|
||||
append(wasm::BoundsCheck(bo.getOffset()));
|
||||
|
||||
as_cmp(index, O2Reg(boundsCheckLimit));
|
||||
as_b(label, cond);
|
||||
}
|
||||
|
||||
template <class L>
|
||||
void
|
||||
MacroAssembler::wasmPatchBoundsCheck(uint8_t* patchAt, uint32_t limit)
|
||||
MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Address boundsCheckLimit, L label)
|
||||
{
|
||||
Instruction* inst = (Instruction*) patchAt;
|
||||
MOZ_ASSERT(inst->is<InstCMP>());
|
||||
InstCMP* cmp = inst->as<InstCMP>();
|
||||
|
||||
Register index;
|
||||
cmp->extractOp1(&index);
|
||||
|
||||
MOZ_ASSERT(cmp->extractOp2().isImm8());
|
||||
|
||||
Imm8 imm8 = Imm8(limit);
|
||||
MOZ_RELEASE_ASSERT(!imm8.invalid());
|
||||
|
||||
*inst = InstALU(InvalidReg, index, imm8, OpCmp, SetCC, Always);
|
||||
// Don't call Auto Flush Cache; the wasm caller has done this for us.
|
||||
ScratchRegisterScope scratch(*this);
|
||||
MOZ_ASSERT(boundsCheckLimit.offset == offsetof(wasm::TlsData, boundsCheckLimit));
|
||||
ma_ldr(DTRAddr(boundsCheckLimit.base, DtrOffImm(boundsCheckLimit.offset)), scratch);
|
||||
as_cmp(index, O2Reg(scratch));
|
||||
as_b(label, cond);
|
||||
}
|
||||
|
||||
//}}} check_macroassembler_style
|
||||
|
@ -297,6 +297,8 @@ class Assembler : public vixl::Assembler
|
||||
static bool SupportsUnalignedAccesses() { return true; }
|
||||
static bool SupportsSimd() { return js::jit::SupportsSimd; }
|
||||
|
||||
static bool HasRoundInstruction(RoundingMode mode) { return false; }
|
||||
|
||||
// Tracks a jump that is patchable after finalization.
|
||||
void addJumpRelocation(BufferOffset src, Relocation::Kind reloc);
|
||||
|
||||
|
@ -1708,13 +1708,14 @@ MacroAssembler::clampIntToUint8(Register reg)
|
||||
|
||||
template <class L>
|
||||
void
|
||||
MacroAssembler::wasmBoundsCheck(Condition cond, Register index, L label)
|
||||
MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Register boundsCheckLimit, L label)
|
||||
{
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
template <class L>
|
||||
void
|
||||
MacroAssembler::wasmPatchBoundsCheck(uint8_t* patchAt, uint32_t limit)
|
||||
MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Address boundsCheckLimit, L label)
|
||||
{
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
@ -1238,6 +1238,10 @@ class AssemblerMIPSShared : public AssemblerShared
|
||||
return js::jit::SupportsSimd;
|
||||
}
|
||||
|
||||
static bool HasRoundInstruction(RoundingMode mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
InstImm invertBranch(InstImm branch, BOffImm16 skipOffset);
|
||||
void addPendingJump(BufferOffset src, ImmPtr target, Relocation::Kind kind) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user