зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b-i a=merge
This commit is contained in:
Коммит
196212ea47
|
@ -11,15 +11,12 @@
|
|||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
DIRS += ["source/modules/system"]
|
||||
|
||||
EXTRA_JS_MODULES.sdk += [
|
||||
'source/app-extension/bootstrap.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.sdk.system += [
|
||||
'source/modules/system/Startup.js',
|
||||
'source/modules/system/XulApp.js',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk":
|
||||
EXTRA_JS_MODULES.commonjs.method.test += [
|
||||
'source/lib/method/test/browser.js',
|
||||
|
|
|
@ -14,25 +14,74 @@ module.metadata = {
|
|||
require('chrome') // Otherwise CFX will complain about Components
|
||||
require('toolkit/loader') // Otherwise CFX will stip out loader.js
|
||||
require('sdk/addon/runner') // Otherwise CFX will stip out addon/runner.js
|
||||
require('sdk/system/xul-app') // Otherwise CFX will stip out sdk/system/xul-app
|
||||
*/
|
||||
|
||||
const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
const {
|
||||
incompatibility
|
||||
} = Cu.import("resource://gre/modules/sdk/system/XulApp.js", {}).XulApp;
|
||||
|
||||
// `loadSandbox` is exposed by bootstrap.js
|
||||
const loaderURI = module.uri.replace("sdk/loader/cuddlefish.js",
|
||||
"toolkit/loader.js");
|
||||
const xulappURI = module.uri.replace("loader/cuddlefish.js",
|
||||
"system/xul-app.js");
|
||||
// We need to keep a reference to the sandbox in order to unload it in
|
||||
// bootstrap.js
|
||||
|
||||
const loaderSandbox = loadSandbox(loaderURI);
|
||||
const loaderModule = loaderSandbox.exports;
|
||||
|
||||
const xulappSandbox = loadSandbox(xulappURI);
|
||||
const xulappModule = xulappSandbox.exports;
|
||||
|
||||
const { override, load } = loaderModule;
|
||||
|
||||
/**
|
||||
* Ensure the current application satisfied the requirements specified in the
|
||||
* module given. If not, an exception related to the incompatibility is
|
||||
* returned; `null` otherwise.
|
||||
*
|
||||
* @param {Object} module
|
||||
* The module to check
|
||||
* @returns {Error}
|
||||
*/
|
||||
function incompatibility(module) {
|
||||
let { metadata, id } = module;
|
||||
|
||||
// if metadata or engines are not specified we assume compatibility is not
|
||||
// an issue.
|
||||
if (!metadata || !("engines" in metadata))
|
||||
return null;
|
||||
|
||||
let { engines } = metadata;
|
||||
|
||||
if (engines === null || typeof(engines) !== "object")
|
||||
return new Error("Malformed engines' property in metadata");
|
||||
|
||||
let applications = Object.keys(engines);
|
||||
|
||||
let versionRange;
|
||||
applications.forEach(function(name) {
|
||||
if (xulappModule.is(name)) {
|
||||
versionRange = engines[name];
|
||||
// Continue iteration. We want to ensure the module doesn't
|
||||
// contain a typo in the applications' name or some unknown
|
||||
// application - `is` function throws an exception in that case.
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof(versionRange) === "string") {
|
||||
if (xulappModule.satisfiesVersion(versionRange))
|
||||
return null;
|
||||
|
||||
return new Error("Unsupported Application version: The module " + id +
|
||||
" currently supports only version " + versionRange + " of " +
|
||||
xulappModule.name + ".");
|
||||
}
|
||||
|
||||
return new Error("Unsupported Application: The module " + id +
|
||||
" currently supports only " + applications.join(", ") + ".")
|
||||
}
|
||||
|
||||
function CuddlefishLoader(options) {
|
||||
let { manifest } = options;
|
||||
|
||||
|
@ -41,7 +90,8 @@ function CuddlefishLoader(options) {
|
|||
// cache to avoid subsequent loads via `require`.
|
||||
modules: override({
|
||||
'toolkit/loader': loaderModule,
|
||||
'sdk/loader/cuddlefish': exports
|
||||
'sdk/loader/cuddlefish': exports,
|
||||
'sdk/system/xul-app': xulappModule
|
||||
}, options.modules),
|
||||
resolve: function resolve(id, requirer) {
|
||||
let entry = requirer && requirer in manifest && manifest[requirer];
|
||||
|
|
|
@ -42,9 +42,6 @@ const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
|||
const { Reflect } = Cu.import("resource://gre/modules/reflect.jsm", {});
|
||||
const { ConsoleAPI } = Cu.import("resource://gre/modules/devtools/Console.jsm");
|
||||
const { join: pathJoin, normalize, dirname } = Cu.import("resource://gre/modules/osfile/ospath_unix.jsm");
|
||||
const {
|
||||
incompatibility
|
||||
} = Cu.import("resource://gre/modules/sdk/system/XulApp.js", {}).XulApp;
|
||||
|
||||
// Define some shortcuts.
|
||||
const bind = Function.call.bind(Function.bind);
|
||||
|
@ -352,12 +349,6 @@ const load = iced(function load(loader, module) {
|
|||
});
|
||||
}
|
||||
|
||||
let (error = incompatibility(module)) {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
if (module.exports && typeof(module.exports) === 'object')
|
||||
freeze(module.exports);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Startup"];
|
||||
var EXPORTED_SYMBOLS = ["Startup"];
|
||||
|
||||
const { utils: Cu, interfaces: Ci, classes: Cc } = Components;
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
@ -20,10 +20,10 @@ const NAME2TOPIC = {
|
|||
'Thunderbird': 'mail-startup-done'
|
||||
};
|
||||
|
||||
var exports = {
|
||||
var Startup = {
|
||||
initialized: !appStartupSrv.startingUp
|
||||
};
|
||||
this.Startup = exports;
|
||||
var exports = Startup;
|
||||
|
||||
let gOnceInitializedDeferred = defer();
|
||||
exports.onceInitialized = gOnceInitializedDeferred.promise;
|
||||
|
|
|
@ -3,16 +3,15 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["XulApp"];
|
||||
var EXPORTED_SYMBOLS = ["XulApp"];
|
||||
|
||||
var { classes: Cc, interfaces: Ci } = Components;
|
||||
|
||||
var exports = {};
|
||||
this.XulApp = exports;
|
||||
|
||||
var appInfo = Cc["@mozilla.org/xre/app-info;1"].
|
||||
getService(Ci.nsIXULAppInfo);
|
||||
var XulApp = exports;
|
||||
|
||||
var appInfo = Cc["@mozilla.org/xre/app-info;1"]
|
||||
.getService(Ci.nsIXULAppInfo);
|
||||
var vc = Cc["@mozilla.org/xpcom/version-comparator;1"]
|
||||
.getService(Ci.nsIVersionComparator);
|
||||
|
||||
|
@ -184,51 +183,3 @@ function satisfiesVersion(version, versionRange) {
|
|||
});
|
||||
}
|
||||
exports.satisfiesVersion = satisfiesVersion;
|
||||
|
||||
/**
|
||||
* Ensure the current application satisfied the requirements specified in the
|
||||
* module given. If not, an exception related to the incompatibility is
|
||||
* returned; `null` otherwise.
|
||||
*
|
||||
* @param {Object} module
|
||||
* The module to check
|
||||
* @returns {Error}
|
||||
*/
|
||||
function incompatibility(module) {
|
||||
let { metadata, id } = module;
|
||||
|
||||
// if metadata or engines are not specified we assume compatibility is not
|
||||
// an issue.
|
||||
if (!metadata || !("engines" in metadata))
|
||||
return null;
|
||||
|
||||
let { engines } = metadata;
|
||||
|
||||
if (engines === null || typeof(engines) !== "object")
|
||||
return new Error("Malformed engines' property in metadata");
|
||||
|
||||
let applications = Object.keys(engines);
|
||||
|
||||
let versionRange;
|
||||
applications.forEach(function(name) {
|
||||
if (is(name)) {
|
||||
versionRange = engines[name];
|
||||
// Continue iteration. We want to ensure the module doesn't
|
||||
// contain a typo in the applications' name or some unknown
|
||||
// application - `is` function throws an exception in that case.
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof(versionRange) === "string") {
|
||||
if (satisfiesVersion(versionRange))
|
||||
return null;
|
||||
|
||||
return new Error("Unsupported Application version: The module " + id +
|
||||
" currently supports only version " + versionRange + " of " +
|
||||
name + ".");
|
||||
}
|
||||
|
||||
return new Error("Unsupported Application: The module " + id +
|
||||
" currently supports only " + applications.join(", ") + ".")
|
||||
}
|
||||
exports.incompatibility = incompatibility;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_JS_MODULES.sdk.system += [
|
||||
'Startup.js',
|
||||
'XulApp.js',
|
||||
]
|
|
@ -1,10 +1,10 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { Loader, Require, unload, override } = require('sdk/loader/cuddlefish');
|
||||
const app = require('sdk/system/xul-app');
|
||||
const packaging = require('@loader/options');
|
||||
|
||||
exports['test loader'] = function(assert) {
|
||||
|
@ -44,19 +44,4 @@ exports['test loader'] = function(assert) {
|
|||
'loader.unload() must call listeners in LIFO order.');
|
||||
};
|
||||
|
||||
exports['test loader on unsupported modules'] = function(assert) {
|
||||
let loader = Loader({});
|
||||
let err = "";
|
||||
assert.throws(() => {
|
||||
if (!app.is('Firefox')) {
|
||||
require('./fixtures/loader/unsupported/firefox');
|
||||
}
|
||||
else {
|
||||
require('./fixtures/loader/unsupported/fennec');
|
||||
}
|
||||
}, /^Unsupported Application/, "throws Unsupported Application");
|
||||
|
||||
unload(loader);
|
||||
};
|
||||
|
||||
require('sdk/test').run(exports);
|
||||
require('test').run(exports);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
let {
|
||||
|
@ -10,10 +11,9 @@ let { readURI } = require('sdk/net/url');
|
|||
|
||||
let root = module.uri.substr(0, module.uri.lastIndexOf('/'))
|
||||
|
||||
|
||||
// The following adds Debugger constructor to the global namespace.
|
||||
const { Cu } = require('chrome');
|
||||
const app = require('sdk/system/xul-app');
|
||||
|
||||
const { addDebuggerToGlobal } = Cu.import('resource://gre/modules/jsdebugger.jsm', {});
|
||||
addDebuggerToGlobal(this);
|
||||
|
||||
|
@ -374,19 +374,4 @@ exports["test require#resolve"] = function(assert) {
|
|||
assert.equal(root + "toolkit/loader.js", require.resolve("toolkit/loader"), "correct resolution of sdk module");
|
||||
};
|
||||
|
||||
exports['test loader on unsupported modules'] = function(assert) {
|
||||
let loader = Loader({});
|
||||
let err = "";
|
||||
assert.throws(() => {
|
||||
if (!app.is('Firefox')) {
|
||||
require('./fixtures/loader/unsupported/firefox');
|
||||
}
|
||||
else {
|
||||
require('./fixtures/loader/unsupported/fennec');
|
||||
}
|
||||
}, /^Unsupported Application/, "throws Unsupported Application");
|
||||
|
||||
unload(loader);
|
||||
};
|
||||
|
||||
require('sdk/test').run(exports);
|
||||
require('test').run(exports);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -258,12 +258,6 @@ XPCOMUtils.defineLazyGetter(this, "PageMenu", function() {
|
|||
*/
|
||||
function pageShowEventHandlers(persisted) {
|
||||
XULBrowserWindow.asyncUpdateUI();
|
||||
|
||||
// The PluginClickToPlay events are not fired when navigating using the
|
||||
// BF cache. |persisted| is true when the page is loaded from the
|
||||
// BF cache, so this code reshows the notification if necessary.
|
||||
if (persisted)
|
||||
gPluginHandler.reshowClickToPlayNotification();
|
||||
}
|
||||
|
||||
function UpdateBackForwardCommands(aWebNavigation) {
|
||||
|
@ -682,7 +676,7 @@ function gKeywordURIFixup({ target: browser, data: fixupInfo }) {
|
|||
// whether the original input would be vaguely interpretable as a URL,
|
||||
// so figure that out first.
|
||||
let alternativeURI = deserializeURI(fixupInfo.fixedURI);
|
||||
if (!fixupInfo.fixupUsedKeyword || !alternativeURI) {
|
||||
if (!fixupInfo.fixupUsedKeyword || !alternativeURI || !alternativeURI.host) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -780,13 +774,6 @@ var gBrowserInit = {
|
|||
|
||||
gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
|
||||
|
||||
// Note that the XBL binding is untrusted
|
||||
gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
|
||||
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginInstantiated", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginRemoved", gPluginHandler, true);
|
||||
|
||||
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
|
||||
|
||||
Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false);
|
||||
|
|
|
@ -16,6 +16,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent",
|
|||
"resource://gre/modules/LoginManagerContent.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "InsecurePasswordUtils",
|
||||
"resource://gre/modules/InsecurePasswordUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluginContent",
|
||||
"resource:///modules/PluginContent.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
|
||||
|
@ -493,6 +495,9 @@ ClickEventHandler.init();
|
|||
|
||||
ContentLinkHandler.init(this);
|
||||
|
||||
// TODO: Load this lazily so the JSM is run only if a relevant event/message fires.
|
||||
let pluginContent = new PluginContent(global);
|
||||
|
||||
addEventListener("DOMWebNotificationClicked", function(event) {
|
||||
sendAsyncMessage("DOMWebNotificationClicked", {});
|
||||
}, false);
|
||||
|
|
|
@ -1315,11 +1315,11 @@ nsContextMenu.prototype = {
|
|||
},
|
||||
|
||||
playPlugin: function() {
|
||||
gPluginHandler._showClickToPlayNotification(this.browser, this.target, true);
|
||||
gPluginHandler.contextMenuCommand(this.browser, this.target, "play");
|
||||
},
|
||||
|
||||
hidePlugin: function() {
|
||||
gPluginHandler.hideClickToPlayOverlay(this.target);
|
||||
gPluginHandler.contextMenuCommand(this.browser, this.target, "hide");
|
||||
},
|
||||
|
||||
// Generate email address and put it on clipboard.
|
||||
|
|
|
@ -19,7 +19,11 @@ function testVal(aExpected) {
|
|||
is(result, aExpected);
|
||||
}
|
||||
|
||||
function test() {
|
||||
add_task(function* () {
|
||||
return new Promise(resolve => Services.search.init(resolve));
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
const prefname = "browser.urlbar.formatting.enabled";
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
|
@ -109,4 +113,4 @@ function test() {
|
|||
Services.prefs.setBoolPref(prefname, false);
|
||||
|
||||
testVal("https://mozilla.org");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -8,6 +8,72 @@ const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browse
|
|||
const gTestRoot = getRootDirectory(gTestPath);
|
||||
var gTestBrowser = null;
|
||||
|
||||
/**
|
||||
* Frame script that will be injected into the test browser
|
||||
* to cause the crash, and then manipulate the crashed plugin
|
||||
* UI. Specifically, after the crash, we ensure that the
|
||||
* crashed plugin UI is using the right style rules and that
|
||||
* the submit URL opt-in defaults to checked. Then, we fill in
|
||||
* a comment with the crash report, uncheck the submit URL
|
||||
* opt-in, and send the crash reports.
|
||||
*/
|
||||
function frameScript() {
|
||||
function fail(reason) {
|
||||
sendAsyncMessage("test:crash-plugin:fail", {
|
||||
reason: `Failure from frameScript: ${reason}`,
|
||||
});
|
||||
}
|
||||
|
||||
addMessageListener("test:crash-plugin", () => {
|
||||
let doc = content.document;
|
||||
|
||||
addEventListener("PluginCrashed", (event) => {
|
||||
let plugin = doc.getElementById("test");
|
||||
if (!plugin) {
|
||||
fail("Could not find plugin element");
|
||||
return;
|
||||
}
|
||||
|
||||
let getUI = (anonid) => {
|
||||
return doc.getAnonymousElementByAttribute(plugin, "anonid", anonid);
|
||||
};
|
||||
|
||||
let style = content.getComputedStyle(getUI("pleaseSubmit"));
|
||||
if (style.display != "block") {
|
||||
fail("Submission UI visibility is not correct. Expected block, "
|
||||
+ " got " + style.display);
|
||||
return;
|
||||
}
|
||||
|
||||
getUI("submitComment").value = "a test comment";
|
||||
if (!getUI("submitURLOptIn").checked) {
|
||||
fail("URL opt-in should default to true.");
|
||||
return;
|
||||
}
|
||||
|
||||
getUI("submitURLOptIn").click();
|
||||
getUI("submitButton").click();
|
||||
});
|
||||
|
||||
let plugin = doc.getElementById("test");
|
||||
try {
|
||||
plugin.crash()
|
||||
} catch(e) {
|
||||
}
|
||||
});
|
||||
|
||||
addMessageListener("test:plugin-submit-status", () => {
|
||||
let doc = content.document;
|
||||
let plugin = doc.getElementById("test");
|
||||
let submitStatusEl =
|
||||
doc.getAnonymousElementByAttribute(plugin, "anonid", "submitStatus");
|
||||
let submitStatus = submitStatusEl.getAttribute("status");
|
||||
sendAsyncMessage("test:plugin-submit-status:result", {
|
||||
submitStatus: submitStatus,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Test that plugin crash submissions still work properly after
|
||||
// click-to-play activation.
|
||||
|
||||
|
@ -31,14 +97,18 @@ function test() {
|
|||
|
||||
let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
|
||||
gTestBrowser = gBrowser.getBrowserForTab(tab);
|
||||
gTestBrowser.addEventListener("PluginCrashed", onCrash, false);
|
||||
let mm = gTestBrowser.messageManager;
|
||||
mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", false);
|
||||
mm.addMessageListener("test:crash-plugin:fail", (message) => {
|
||||
ok(false, message.data.reason);
|
||||
});
|
||||
|
||||
gTestBrowser.addEventListener("load", onPageLoad, true);
|
||||
Services.obs.addObserver(onSubmitStatus, "crash-report-status", false);
|
||||
|
||||
registerCleanupFunction(function cleanUp() {
|
||||
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
|
||||
env.set("MOZ_CRASHREPORTER_URL", serverURL);
|
||||
gTestBrowser.removeEventListener("PluginCrashed", onCrash, false);
|
||||
gTestBrowser.removeEventListener("load", onPageLoad, true);
|
||||
Services.obs.removeObserver(onSubmitStatus, "crash-report-status");
|
||||
gBrowser.removeCurrentTab();
|
||||
|
@ -70,31 +140,8 @@ function afterBindingAttached() {
|
|||
}
|
||||
|
||||
function pluginActivated() {
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
try {
|
||||
plugin.crash();
|
||||
} catch (e) {
|
||||
// The plugin crashed in the above call, an exception is expected.
|
||||
}
|
||||
}
|
||||
|
||||
function onCrash() {
|
||||
try {
|
||||
let plugin = gBrowser.contentDocument.getElementById("test");
|
||||
let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin);
|
||||
let style =
|
||||
gBrowser.contentWindow.getComputedStyle(elt("pleaseSubmit"));
|
||||
is(style.display, "block", "Submission UI visibility should be correct");
|
||||
|
||||
elt("submitComment").value = "a test comment";
|
||||
is(elt("submitURLOptIn").checked, true, "URL opt-in should default to true");
|
||||
EventUtils.synthesizeMouseAtCenter(elt("submitURLOptIn"), {}, gTestBrowser.contentWindow);
|
||||
EventUtils.synthesizeMouseAtCenter(elt("submitButton"), {}, gTestBrowser.contentWindow);
|
||||
// And now wait for the submission status notification.
|
||||
}
|
||||
catch (err) {
|
||||
failWithException(err);
|
||||
}
|
||||
let mm = gTestBrowser.messageManager;
|
||||
mm.sendAsyncMessage("test:crash-plugin");
|
||||
}
|
||||
|
||||
function onSubmitStatus(subj, topic, data) {
|
||||
|
@ -128,19 +175,23 @@ function onSubmitStatus(subj, topic, data) {
|
|||
ok(val === undefined,
|
||||
"URL should be absent from extra data when opt-in not checked");
|
||||
|
||||
// Execute this later in case the event to change submitStatus has not
|
||||
// have been dispatched yet.
|
||||
executeSoon(function () {
|
||||
let plugin = gBrowser.contentDocument.getElementById("test");
|
||||
let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin);
|
||||
is(elt("submitStatus").getAttribute("status"), data,
|
||||
"submitStatus data should match");
|
||||
let submitStatus = null;
|
||||
let mm = gTestBrowser.messageManager;
|
||||
mm.addMessageListener("test:plugin-submit-status:result", (message) => {
|
||||
submitStatus = message.data.submitStatus;
|
||||
});
|
||||
|
||||
mm.sendAsyncMessage("test:plugin-submit-status");
|
||||
|
||||
let condition = () => submitStatus;
|
||||
waitForCondition(condition, () => {
|
||||
is(submitStatus, data, "submitStatus data should match");
|
||||
finish();
|
||||
}, "Waiting for submitStatus to be reported from frame script");
|
||||
}
|
||||
catch (err) {
|
||||
failWithException(err);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
function getPropertyBagValue(bag, key) {
|
||||
|
|
|
@ -29,11 +29,11 @@ function handleEvent() {
|
|||
|
||||
function part1() {
|
||||
gBrowser.selectedBrowser.removeEventListener("PluginBindingAttached", handleEvent);
|
||||
ok(PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser), "Should have a click-to-play notification in the initial tab");
|
||||
|
||||
waitForNotificationPopup("click-to-play-plugins", gBrowser.selectedBrowser, () => {
|
||||
gNextTest = part2;
|
||||
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
|
||||
gNewWindow.addEventListener("load", handleEvent, true);
|
||||
});
|
||||
}
|
||||
|
||||
function part2() {
|
||||
|
@ -62,10 +62,10 @@ function part4() {
|
|||
|
||||
function part5() {
|
||||
gBrowser.selectedBrowser.removeEventListener("PluginBindingAttached", handleEvent);
|
||||
ok(PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser), "Should have a click-to-play notification in the initial tab");
|
||||
|
||||
waitForNotificationPopup("click-to-play-plugins", gBrowser.selectedBrowser, () => {
|
||||
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
|
||||
waitForFocus(part6, gNewWindow);
|
||||
});
|
||||
}
|
||||
|
||||
function part6() {
|
||||
|
@ -92,8 +92,10 @@ function part8() {
|
|||
|
||||
let plugin = gNewWindow.gBrowser.selectedBrowser.contentDocument.getElementById("test");
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "plugin should be activated now");
|
||||
waitForCondition(() => objLoadingContent.activated, shutdown, "plugin should be activated now");
|
||||
}
|
||||
|
||||
function shutdown() {
|
||||
gNewWindow.close();
|
||||
gNewWindow = null;
|
||||
finish();
|
||||
|
|
|
@ -74,13 +74,15 @@ function test1() {
|
|||
let plugin = doc.getElementById("test");
|
||||
ok(plugin, "Test 1, Found plugin in page");
|
||||
|
||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
|
||||
ok(overlay.classList.contains("visible"), "Test 1, Plugin overlay should exist, not be hidden");
|
||||
let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon")
|
||||
let closeIcon = doc.getAnonymousElementByAttribute(plugin, "anonid", "closeIcon");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(closeIcon, {}, frame.contentWindow);
|
||||
let condition = () => !overlay.classList.contains("visible");
|
||||
waitForCondition(condition, test2, "Test 1, Waited too long for the overlay to become invisible.");
|
||||
});
|
||||
}
|
||||
|
||||
function test2() {
|
||||
|
|
|
@ -63,25 +63,20 @@ function runAfterPluginBindingAttached(func) {
|
|||
// Tests for the notification bar for hidden plugins.
|
||||
|
||||
function test1() {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||
ok(notification, "Test 1: There should be a plugin notification");
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
|
||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||
() => {
|
||||
info("Test 1 - expecting a notification bar for hidden plugins.");
|
||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
||||
waitForNotificationBar("plugin-hidden", gTestBrowser, () => {
|
||||
// Don't use setTestPluginEnabledState here because we already saved the
|
||||
// prior value
|
||||
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
||||
prepareTest(test2, gTestRoot + "plugin_small.html");
|
||||
},
|
||||
"Test 1, expected to have a plugin notification bar");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test2() {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||
ok(notification, "Test 2: There should be a plugin notification");
|
||||
|
||||
info("Test 2 - expecting no plugin notification bar on visible plugins.");
|
||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
|
||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
|
||||
|
@ -89,17 +84,16 @@ function test2() {
|
|||
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
|
||||
prepareTest(test3, gTestRoot + "plugin_overlayed.html");
|
||||
},
|
||||
"Test 2, expected to not have a plugin notification bar");
|
||||
"expected to not have a plugin notification bar"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function test3() {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||
ok(notification, "Test 3: There should be a plugin notification");
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||
test3b,
|
||||
"Test 3, expected the plugin infobar to be triggered when plugin was overlayed");
|
||||
info("Test 3 - expecting a plugin notification bar when plugins are overlaid");
|
||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
||||
waitForNotificationBar("plugin-hidden", gTestBrowser, test3b);
|
||||
});
|
||||
}
|
||||
|
||||
function test3b()
|
||||
|
@ -118,13 +112,10 @@ function test3b()
|
|||
}
|
||||
|
||||
function test4() {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||
ok(notification, "Test 4: There should be a plugin notification");
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||
test4b,
|
||||
"Test 4, expected the plugin infobar to be triggered when plugin was overlayed");
|
||||
info("Test 4 - expecting a plugin notification bar when plugins are overlaid offscreen")
|
||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, () => {
|
||||
waitForNotificationBar("plugin-hidden", gTestBrowser, test4b);
|
||||
});
|
||||
}
|
||||
|
||||
function test4b() {
|
||||
|
@ -141,9 +132,6 @@ function test4b() {
|
|||
prepareTest(runAfterPluginBindingAttached(test5), gHttpTestRoot + "plugin_small.html");
|
||||
}
|
||||
|
||||
// Test that the notification bar is getting dismissed when directly activating plugins
|
||||
// via the doorhanger.
|
||||
|
||||
function test5() {
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") !== null,
|
||||
|
@ -151,9 +139,12 @@ function test5() {
|
|||
"Test 5, expected a notification bar for hidden plugins");
|
||||
}
|
||||
|
||||
// Test that the notification bar is getting dismissed when directly activating plugins
|
||||
// via the doorhanger.
|
||||
|
||||
function test6() {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(notification, "Test 6, Should have a click-to-play notification");
|
||||
info("Test 6 - expecting the doorhanger to be dismissed when directly activating plugins.");
|
||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, (notification) => {
|
||||
let plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
ok(plugin, "Test 6, Found plugin in page");
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
|
@ -168,6 +159,7 @@ function test6() {
|
|||
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
|
||||
test7,
|
||||
"Test 6, expected the notification bar for hidden plugins to get dismissed");
|
||||
});
|
||||
}
|
||||
|
||||
function test7() {
|
||||
|
|
|
@ -60,10 +60,8 @@ function test1b() {
|
|||
// Click the activate button on doorhanger to make sure it works
|
||||
popupNotification.reshow();
|
||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||
|
||||
ok(objLoadingContent.activated, "Test 1b, Doorhanger should activate plugin");
|
||||
|
||||
test1c();
|
||||
var condition = function() objLoadingContent.activated;
|
||||
waitForCondition(condition, test1c, "Test 1b, Waited too long for plugin activation");
|
||||
}
|
||||
|
||||
function test1c() {
|
||||
|
|
|
@ -36,12 +36,14 @@ function pluginBindingAttached() {
|
|||
ok(testplugin, "should have test plugin");
|
||||
var secondtestplugin = doc.getElementById("secondtest");
|
||||
ok(!secondtestplugin, "should not yet have second test plugin");
|
||||
var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
var notification;
|
||||
waitForNotificationPopup("click-to-play-plugins", gTestBrowser, (notification => {
|
||||
ok(notification, "should have popup notification");
|
||||
// We don't set up the action list until the notification is shown
|
||||
notification.reshow();
|
||||
is(notification.options.pluginData.size, 1, "should be 1 type of plugin in the popup notification");
|
||||
XPCNativeWrapper.unwrap(gTestBrowser.contentWindow).addSecondPlugin();
|
||||
}));
|
||||
} else if (gNumPluginBindingsAttached == 2) {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var testplugin = doc.getElementById("test");
|
||||
|
@ -51,8 +53,8 @@ function pluginBindingAttached() {
|
|||
var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(notification, "should have popup notification");
|
||||
notification.reshow();
|
||||
is(notification.options.pluginData.size, 2, "should be 2 types of plugin in the popup notification");
|
||||
finish();
|
||||
let condition = () => (notification.options.pluginData.size == 2);
|
||||
waitForCondition(condition, finish, "Waited too long for 2 types of plugins in popup notification");
|
||||
} else {
|
||||
ok(false, "if we've gotten here, something is quite wrong");
|
||||
}
|
||||
|
|
|
@ -59,11 +59,11 @@ function onCrash(event) {
|
|||
is (propVal, val, "Correct property in detail propBag: " + name + ".");
|
||||
}
|
||||
|
||||
waitForNotificationBar("plugin-crashed", gTestBrowser, (notification) => {
|
||||
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
|
||||
let notification = notificationBox.getNotificationWithValue("plugin-crashed");
|
||||
|
||||
ok(notification, "Infobar was shown.");
|
||||
is(notification.priority, notificationBox.PRIORITY_WARNING_MEDIUM, "Correct priority.");
|
||||
is(notification.getAttribute("label"), "The GlobalTestPlugin plugin has crashed.", "Correct message.");
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,9 +6,80 @@ Cu.import("resource://gre/modules/CrashSubmit.jsm", this);
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const CRASH_URL = "http://example.com/browser/browser/base/content/test/plugins/plugin_crashCommentAndURL.html";
|
||||
|
||||
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
|
||||
|
||||
/**
|
||||
* Frame script that will be injected into the test browser
|
||||
* to cause plugin crashes, and then manipulate the crashed plugin
|
||||
* UI. The specific actions and checks that occur in the frame
|
||||
* script for the crashed plugin UI are set in the
|
||||
* test:crash-plugin message object sent from the parent. The actions
|
||||
* and checks that the parent can specify are:
|
||||
*
|
||||
* pleaseSubmitStyle: the display style that the pleaseSubmit anonymous element
|
||||
* should have - example "block", "none".
|
||||
* submitComment: the comment that should be put into the crash report
|
||||
* urlOptIn: true if the submitURLOptIn element should be checked.
|
||||
* sendCrashMessage: if true, the frame script will send a
|
||||
* test:crash-plugin:crashed message when the plugin has
|
||||
* crashed. This is used for the last test case, and
|
||||
* causes the frame script to skip any of the crashed
|
||||
* plugin UI manipulation, since the last test shows
|
||||
* no crashed plugin UI.
|
||||
*/
|
||||
function frameScript() {
|
||||
function fail(reason) {
|
||||
sendAsyncMessage("test:crash-plugin:fail", {
|
||||
reason: `Failure from frameScript: ${reason}`,
|
||||
});
|
||||
}
|
||||
|
||||
addMessageListener("test:crash-plugin", (message) => {
|
||||
addEventListener("PluginCrashed", function onPluginCrashed(event) {
|
||||
removeEventListener("PluginCrashed", onPluginCrashed);
|
||||
|
||||
let doc = content.document;
|
||||
let plugin = doc.getElementById("plugin");
|
||||
if (!plugin) {
|
||||
fail("Could not find plugin element");
|
||||
return;
|
||||
}
|
||||
|
||||
let getUI = (anonid) => {
|
||||
return doc.getAnonymousElementByAttribute(plugin, "anonid", anonid);
|
||||
};
|
||||
|
||||
let style = content.getComputedStyle(getUI("pleaseSubmit"));
|
||||
if (style.display != message.data.pleaseSubmitStyle) {
|
||||
fail("Submission UI visibility is not correct. Expected " +
|
||||
`${message.data.pleaseSubmitStyle} and got ${style.display}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.data.sendCrashMessage) {
|
||||
let propBag = event.detail.QueryInterface(Ci.nsIPropertyBag2);
|
||||
let crashID = propBag.getPropertyAsAString("pluginDumpID");
|
||||
sendAsyncMessage("test:crash-plugin:crashed", {
|
||||
crashID: crashID,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.data.submitComment) {
|
||||
getUI("submitComment").value = message.data.submitComment;
|
||||
}
|
||||
getUI("submitURLOptIn").checked = message.data.urlOptIn;
|
||||
getUI("submitButton").click();
|
||||
});
|
||||
|
||||
let plugin = content.document.getElementById("test");
|
||||
try {
|
||||
plugin.crash()
|
||||
} catch(e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function test() {
|
||||
// Crashing the plugin takes up a lot of time, so extend the test timeout.
|
||||
requestLongerTimeout(runs.length);
|
||||
|
@ -29,14 +100,18 @@ function test() {
|
|||
|
||||
let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
|
||||
let browser = gBrowser.getBrowserForTab(tab);
|
||||
browser.addEventListener("PluginCrashed", onCrash, false);
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
|
||||
|
||||
mm.addMessageListener("test:crash-plugin:fail", (message) => {
|
||||
ok(false, message.data.reason);
|
||||
});
|
||||
|
||||
Services.obs.addObserver(onSubmitStatus, "crash-report-status", false);
|
||||
|
||||
registerCleanupFunction(function cleanUp() {
|
||||
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
|
||||
env.set("MOZ_CRASHREPORTER_URL", serverURL);
|
||||
gBrowser.selectedBrowser.removeEventListener("PluginCrashed", onCrash,
|
||||
false);
|
||||
Services.obs.removeObserver(onSubmitStatus, "crash-report-status");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
@ -76,6 +151,24 @@ function doNextRun() {
|
|||
memo[arg] = currentRun[arg];
|
||||
return memo;
|
||||
}, {});
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
|
||||
if (!currentRun.shouldSubmittionUIBeVisible) {
|
||||
mm.addMessageListener("test:crash-plugin:crash", function onCrash(message) {
|
||||
mm.removeMessageListener("test:crash-plugin:crash", onCrash);
|
||||
|
||||
ok(!!message.data.crashID, "pluginDumpID should be set");
|
||||
CrashSubmit.delete(message.data.crashID);
|
||||
doNextRun();
|
||||
});
|
||||
}
|
||||
|
||||
mm.sendAsyncMessage("test:crash-plugin", {
|
||||
pleaseSubmitStyle: currentRun.shouldSubmissionUIBeVisible ? "block" : "none",
|
||||
submitComment: currentRun.comment,
|
||||
urlOptIn: currentRun.urlOptIn,
|
||||
sendOnCrashMessage: !currentRun.shouldSubmissionUIBeVisible,
|
||||
});
|
||||
gBrowser.loadURI(CRASH_URL + "?" +
|
||||
encodeURIComponent(JSON.stringify(args)));
|
||||
// And now wait for the crash.
|
||||
|
@ -86,37 +179,6 @@ function doNextRun() {
|
|||
}
|
||||
}
|
||||
|
||||
function onCrash(event) {
|
||||
try {
|
||||
let plugin = gBrowser.contentDocument.getElementById("plugin");
|
||||
let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin);
|
||||
let style =
|
||||
gBrowser.contentWindow.getComputedStyle(elt("pleaseSubmit"));
|
||||
is(style.display,
|
||||
currentRun.shouldSubmissionUIBeVisible ? "block" : "none",
|
||||
"Submission UI visibility should be correct");
|
||||
if (!currentRun.shouldSubmissionUIBeVisible) {
|
||||
// Done with this run. We don't submit the crash, so we will have to
|
||||
// remove the dump manually.
|
||||
let propBag = event.detail.QueryInterface(Ci.nsIPropertyBag2);
|
||||
let crashID = propBag.getPropertyAsAString("pluginDumpID");
|
||||
ok(!!crashID, "pluginDumpID should be set");
|
||||
CrashSubmit.delete(crashID);
|
||||
|
||||
doNextRun();
|
||||
return;
|
||||
}
|
||||
elt("submitComment").value = currentRun.comment;
|
||||
elt("submitURLOptIn").checked = currentRun.urlOptIn;
|
||||
elt("submitButton").click();
|
||||
// And now wait for the submission status notification.
|
||||
}
|
||||
catch (err) {
|
||||
failWithException(err);
|
||||
doNextRun();
|
||||
}
|
||||
}
|
||||
|
||||
function onSubmitStatus(subj, topic, data) {
|
||||
try {
|
||||
// Wait for success or failed, doesn't matter which.
|
||||
|
|
|
@ -56,6 +56,7 @@ TabOpenListener.prototype = {
|
|||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
SimpleTest.requestCompleteLog();
|
||||
requestLongerTimeout(2);
|
||||
registerCleanupFunction(function() {
|
||||
clearAllPluginPermissions();
|
||||
|
@ -797,7 +798,10 @@ function test24a() {
|
|||
// simulate "always allow"
|
||||
notification.reshow();
|
||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||
waitForCondition(() => objLoadingContent.activated, () => {
|
||||
prepareTest(test24b, gHttpTestRoot + "plugin_test.html");
|
||||
}, "Test 24a, plugin should now be activated.");
|
||||
|
||||
}
|
||||
|
||||
// did the "always allow" work as intended?
|
||||
|
@ -805,11 +809,11 @@ function test24b() {
|
|||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
ok(plugin, "Test 24b, Found plugin in page");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 24b, plugin should be activated");
|
||||
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
|
||||
function() {
|
||||
waitForCondition(() => objLoadingContent.activated, () => {
|
||||
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml", () => {
|
||||
prepareTest(runAfterPluginBindingAttached(test24c), gHttpTestRoot + "plugin_test.html");
|
||||
});
|
||||
}, "Test 24b, plugin should be activated");
|
||||
}
|
||||
|
||||
// the plugin is now blocklisted, so it should not automatically load
|
||||
|
@ -820,13 +824,13 @@ function test24c() {
|
|||
ok(plugin, "Test 24c, Found plugin in page");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "Test 24c, Plugin should be vulnerable/updatable");
|
||||
ok(!objLoadingContent.activated, "Test 24c, plugin should not be activated");
|
||||
|
||||
waitForCondition(() => !objLoadingContent.activated, () => {
|
||||
// simulate "always allow"
|
||||
notification.reshow();
|
||||
PopupNotifications.panel.firstChild._primaryButton.click();
|
||||
|
||||
prepareTest(test24d, gHttpTestRoot + "plugin_test.html");
|
||||
}, "Test 24c, plugin should not be activated");
|
||||
}
|
||||
|
||||
// We should still be able to always allow a plugin after we've seen that it's
|
||||
|
@ -835,15 +839,14 @@ function test24d() {
|
|||
var plugin = gTestBrowser.contentDocument.getElementById("test");
|
||||
ok(plugin, "Test 24d, Found plugin in page");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 24d, plugin should be activated");
|
||||
|
||||
waitForCondition(() => objLoadingContent.activated, () => {
|
||||
// this resets the vulnerable plugin permission
|
||||
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml",
|
||||
function() {
|
||||
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", () => {
|
||||
clearAllPluginPermissions();
|
||||
resetBlocklist();
|
||||
prepareTest(test25, gTestRoot + "plugin_syncRemoved.html");
|
||||
});
|
||||
}, "Test 24d, plugin should be activated");
|
||||
}
|
||||
|
||||
function test25() {
|
||||
|
|
|
@ -108,3 +108,28 @@ function setAndUpdateBlocklist(aURL, aCallback) {
|
|||
function resetBlocklist() {
|
||||
Services.prefs.setCharPref("extensions.blocklist.url", _originalTestBlocklistURL);
|
||||
}
|
||||
|
||||
function waitForNotificationPopup(notificationID, browser, callback) {
|
||||
let notification;
|
||||
waitForCondition(
|
||||
() => (notification = PopupNotifications.getNotification(notificationID, browser)),
|
||||
() => {
|
||||
ok(notification, `Successfully got the ${notificationID} notification popup`);
|
||||
callback(notification);
|
||||
},
|
||||
`Waited too long for the ${notificationID} notification popup`
|
||||
);
|
||||
}
|
||||
|
||||
function waitForNotificationBar(notificationID, browser, callback) {
|
||||
let notification;
|
||||
let notificationBox = gBrowser.getNotificationBox(browser);
|
||||
waitForCondition(
|
||||
() => (notification = notificationBox.getNotificationWithValue(notificationID)),
|
||||
() => {
|
||||
ok(notification, `Successfully got the ${notificationID} notification bar`);
|
||||
callback(notification);
|
||||
},
|
||||
`Waited too long for the ${notificationID} notification bar`
|
||||
);
|
||||
}
|
||||
|
|
|
@ -174,11 +174,23 @@
|
|||
</method>
|
||||
|
||||
<field name="_formattingEnabled">true</field>
|
||||
<field name="_searchServiceInitialized">false</field>
|
||||
<method name="formatValue">
|
||||
<body><![CDATA[
|
||||
if (!this._formattingEnabled || this.focused)
|
||||
return;
|
||||
|
||||
// Initialize the search service asynchronously if that hasn't
|
||||
// happened yet. We will need it to highlight search terms later.
|
||||
if (!this._searchServiceInitialized) {
|
||||
Services.search.init(() => {
|
||||
this._searchServiceInitialized = true;
|
||||
this.formatValue();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let controller = this.editor.selectionController;
|
||||
let selection = controller.getSelection(controller.SELECTION_URLSECONDARY);
|
||||
selection.removeAllRanges();
|
||||
|
@ -213,20 +225,29 @@
|
|||
subDomain = domain.slice(0, -baseDomain.length);
|
||||
}
|
||||
|
||||
let rangeLength = preDomain.length + subDomain.length;
|
||||
if (rangeLength) {
|
||||
function addSelectionRange(start, end) {
|
||||
let range = document.createRange();
|
||||
range.setStart(textNode, 0);
|
||||
range.setEnd(textNode, rangeLength);
|
||||
range.setStart(textNode, start);
|
||||
range.setEnd(textNode, end);
|
||||
selection.addRange(range);
|
||||
}
|
||||
|
||||
let rangeLength = preDomain.length + subDomain.length;
|
||||
if (rangeLength) {
|
||||
addSelectionRange(0, rangeLength);
|
||||
}
|
||||
|
||||
let result = Services.search.parseSubmissionURL(value);
|
||||
let startRest = preDomain.length + domain.length;
|
||||
|
||||
// Format search terms in the URL, if any.
|
||||
if (result.termsOffset > -1 && result.termsLength) {
|
||||
addSelectionRange(startRest, result.termsOffset);
|
||||
startRest = result.termsOffset + result.termsLength;
|
||||
}
|
||||
|
||||
if (startRest < value.length) {
|
||||
let range = document.createRange();
|
||||
range.setStart(textNode, startRest);
|
||||
range.setEnd(textNode, value.length);
|
||||
selection.addRange(range);
|
||||
addSelectionRange(startRest, value.length);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
@ -606,6 +627,7 @@
|
|||
this.timeout = this._prefs.getIntPref(aData);
|
||||
break;
|
||||
case "formatting.enabled":
|
||||
this._clearFormatting();
|
||||
this._formattingEnabled = this._prefs.getBoolPref(aData);
|
||||
break;
|
||||
case "trimURLs":
|
||||
|
@ -1954,7 +1976,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
let host = gPluginHandler._getHostFromPrincipal(this.notification.browser.contentWindow.document.nodePrincipal);
|
||||
let host = this.notification.options.host;
|
||||
this._setupDescription("pluginActivateMultiple.message", null, host);
|
||||
|
||||
var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox");
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
// We also need a valid nsIXulAppInfo service as Webapps.jsm is querying it
|
||||
Cu.import("resource://testing-common/AppInfo.jsm");
|
||||
updateAppInfo();
|
||||
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let require = devtools.require;
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
// Tests the BezierCanvas API in the CubicBezierWidget module
|
||||
|
||||
const Cu = Components.utils;
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let require = devtools.require;
|
||||
let {CubicBezier, BezierCanvas} = require("devtools/shared/widgets/CubicBezierWidget");
|
||||
|
||||
function run_test() {
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
// Tests the CubicBezier API in the CubicBezierWidget module
|
||||
|
||||
const Cu = Components.utils;
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let require = devtools.require;
|
||||
let {CubicBezier} = require("devtools/shared/widgets/CubicBezierWidget");
|
||||
|
||||
function run_test() {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const Cu = Components.utils;
|
||||
let {Loader} = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
|
||||
|
||||
let loader = new Loader.Loader({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[DEFAULT]
|
||||
head = head.js
|
||||
head =
|
||||
tail =
|
||||
firefox-appdir = browser
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
// We also need a valid nsIXulAppInfo
|
||||
Cu.import("resource://testing-common/AppInfo.jsm");
|
||||
updateAppInfo();
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
|
@ -3,6 +3,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
const {parseDeclarations} = devtools.require("devtools/styleinspector/css-parsing-utils");
|
||||
|
||||
const TEST_DATA = [
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
const {parseSingleValue} = devtools.require("devtools/styleinspector/css-parsing-utils");
|
||||
|
||||
const TEST_DATA = [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[DEFAULT]
|
||||
head = head.js
|
||||
head =
|
||||
tail =
|
||||
firefox-appdir = browser
|
||||
|
||||
|
|
|
@ -368,7 +368,7 @@ Experiments.Experiments = function (policy=new Experiments.Policy()) {
|
|||
// crashes. For forensics purposes, keep the last few log
|
||||
// messages in memory and upload them in case of crash.
|
||||
this._forensicsLogs = [];
|
||||
this._forensicsLogs.length = 10;
|
||||
this._forensicsLogs.length = 20;
|
||||
this._log = Object.create(log);
|
||||
this._log.log = (level, string, params) => {
|
||||
this._forensicsLogs.shift();
|
||||
|
|
|
@ -0,0 +1,992 @@
|
|||
# -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "PluginContent" ];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gNavigatorBundle", function() {
|
||||
const url = "chrome://browser/locale/browser.properties";
|
||||
return Services.strings.createBundle(url);
|
||||
});
|
||||
|
||||
this.PluginContent = function (global) {
|
||||
this.init(global);
|
||||
}
|
||||
|
||||
PluginContent.prototype = {
|
||||
init: function (global) {
|
||||
this.global = global;
|
||||
// Need to hold onto the content window or else it'll get destroyed
|
||||
this.content = this.global.content;
|
||||
// Cache of plugin actions for the current page.
|
||||
this.pluginData = new Map();
|
||||
|
||||
// Note that the XBL binding is untrusted
|
||||
global.addEventListener("PluginBindingAttached", this, true, true);
|
||||
global.addEventListener("PluginCrashed", this, true);
|
||||
global.addEventListener("PluginOutdated", this, true);
|
||||
global.addEventListener("PluginInstantiated", this, true);
|
||||
global.addEventListener("PluginRemoved", this, true);
|
||||
global.addEventListener("unload", this);
|
||||
|
||||
global.addEventListener("pageshow", (event) => this.onPageShow(event), true);
|
||||
|
||||
global.addMessageListener("BrowserPlugins:ActivatePlugins", this);
|
||||
global.addMessageListener("BrowserPlugins:NotificationRemoved", this);
|
||||
global.addMessageListener("BrowserPlugins:NotificationShown", this);
|
||||
global.addMessageListener("BrowserPlugins:ContextMenuCommand", this);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
delete this.global;
|
||||
delete this.content;
|
||||
},
|
||||
|
||||
receiveMessage: function (msg) {
|
||||
switch (msg.name) {
|
||||
case "BrowserPlugins:ActivatePlugins":
|
||||
this.activatePlugins(msg.data.pluginInfo, msg.data.newState);
|
||||
break;
|
||||
case "BrowserPlugins:NotificationRemoved":
|
||||
this.clearPluginDataCache();
|
||||
break;
|
||||
case "BrowserPlugins:NotificationShown":
|
||||
setTimeout(() => this.updateNotificationUI(), 0);
|
||||
break;
|
||||
case "BrowserPlugins:ContextMenuCommand":
|
||||
switch (msg.data.command) {
|
||||
case "play":
|
||||
this._showClickToPlayNotification(msg.objects.plugin, true);
|
||||
break;
|
||||
case "hide":
|
||||
this.hideClickToPlayOverlay(msg.objects.plugin);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onPageShow: function (event) {
|
||||
// Ignore events that aren't from the main document.
|
||||
if (this.global.content && event.target != this.global.content.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The PluginClickToPlay events are not fired when navigating using the
|
||||
// BF cache. |persisted| is true when the page is loaded from the
|
||||
// BF cache, so this code reshows the notification if necessary.
|
||||
if (event.persisted) {
|
||||
this.reshowClickToPlayNotification();
|
||||
}
|
||||
},
|
||||
|
||||
getPluginUI: function (plugin, anonid) {
|
||||
return plugin.ownerDocument.
|
||||
getAnonymousElementByAttribute(plugin, "anonid", anonid);
|
||||
},
|
||||
|
||||
_getPluginInfo: function (pluginElement) {
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
pluginElement.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
|
||||
let tagMimetype;
|
||||
let pluginName = gNavigatorBundle.GetStringFromName("pluginInfo.unknownPlugin");
|
||||
let pluginTag = null;
|
||||
let permissionString = null;
|
||||
let fallbackType = null;
|
||||
let blocklistState = null;
|
||||
|
||||
tagMimetype = pluginElement.actualType;
|
||||
if (tagMimetype == "") {
|
||||
tagMimetype = pluginElement.type;
|
||||
}
|
||||
|
||||
if (this.isKnownPlugin(pluginElement)) {
|
||||
pluginTag = pluginHost.getPluginTagForType(pluginElement.actualType);
|
||||
pluginName = this.makeNicePluginName(pluginTag.name);
|
||||
|
||||
permissionString = pluginHost.getPermissionStringForType(pluginElement.actualType);
|
||||
fallbackType = pluginElement.defaultFallbackType;
|
||||
blocklistState = pluginHost.getBlocklistStateForType(pluginElement.actualType);
|
||||
// Make state-softblocked == state-notblocked for our purposes,
|
||||
// they have the same UI. STATE_OUTDATED should not exist for plugin
|
||||
// items, but let's alias it anyway, just in case.
|
||||
if (blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED ||
|
||||
blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
|
||||
blocklistState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
return { mimetype: tagMimetype,
|
||||
pluginName: pluginName,
|
||||
pluginTag: pluginTag,
|
||||
permissionString: permissionString,
|
||||
fallbackType: fallbackType,
|
||||
blocklistState: blocklistState,
|
||||
};
|
||||
},
|
||||
|
||||
// Map the plugin's name to a filtered version more suitable for user UI.
|
||||
makeNicePluginName : function (aName) {
|
||||
if (aName == "Shockwave Flash")
|
||||
return "Adobe Flash";
|
||||
|
||||
// Clean up the plugin name by stripping off parenthetical clauses,
|
||||
// trailing version numbers or "plugin".
|
||||
// EG, "Foo Bar (Linux) Plugin 1.23_02" --> "Foo Bar"
|
||||
// Do this by first stripping the numbers, etc. off the end, and then
|
||||
// removing "Plugin" (and then trimming to get rid of any whitespace).
|
||||
// (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled)
|
||||
let newName = aName.replace(/\(.*?\)/g, "").
|
||||
replace(/[\s\d\.\-\_\(\)]+$/, "").
|
||||
replace(/\bplug-?in\b/i, "").trim();
|
||||
return newName;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the visibility of the plugin overlay.
|
||||
*/
|
||||
setVisibility : function (plugin, overlay, shouldShow) {
|
||||
overlay.classList.toggle("visible", shouldShow);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether the plugin should be visible on the page. A plugin should
|
||||
* not be visible if the overlay is too big, or if any other page content
|
||||
* overlays it.
|
||||
*
|
||||
* This function will handle showing or hiding the overlay.
|
||||
* @returns true if the plugin is invisible.
|
||||
*/
|
||||
shouldShowOverlay : function (plugin, overlay) {
|
||||
// If the overlay size is 0, we haven't done layout yet. Presume that
|
||||
// plugins are visible until we know otherwise.
|
||||
if (overlay.scrollWidth == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Is the <object>'s size too small to hold what we want to show?
|
||||
let pluginRect = plugin.getBoundingClientRect();
|
||||
// XXX bug 446693. The text-shadow on the submitted-report text at
|
||||
// the bottom causes scrollHeight to be larger than it should be.
|
||||
let overflows = (overlay.scrollWidth > Math.ceil(pluginRect.width)) ||
|
||||
(overlay.scrollHeight - 5 > Math.ceil(pluginRect.height));
|
||||
if (overflows) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the plugin covered up by other content so that it is not clickable?
|
||||
// Floating point can confuse .elementFromPoint, so inset just a bit
|
||||
let left = pluginRect.left + 2;
|
||||
let right = pluginRect.right - 2;
|
||||
let top = pluginRect.top + 2;
|
||||
let bottom = pluginRect.bottom - 2;
|
||||
let centerX = left + (right - left) / 2;
|
||||
let centerY = top + (bottom - top) / 2;
|
||||
let points = [[left, top],
|
||||
[left, bottom],
|
||||
[right, top],
|
||||
[right, bottom],
|
||||
[centerX, centerY]];
|
||||
|
||||
if (right <= 0 || top <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let contentWindow = plugin.ownerDocument.defaultView;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
for (let [x, y] of points) {
|
||||
let el = cwu.elementFromPoint(x, y, true, true);
|
||||
if (el !== plugin) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
addLinkClickCallback: function (linkNode, callbackName /*callbackArgs...*/) {
|
||||
// XXX just doing (callback)(arg) was giving a same-origin error. bug?
|
||||
let self = this;
|
||||
let callbackArgs = Array.prototype.slice.call(arguments).slice(2);
|
||||
linkNode.addEventListener("click",
|
||||
function(evt) {
|
||||
if (!evt.isTrusted)
|
||||
return;
|
||||
evt.preventDefault();
|
||||
if (callbackArgs.length == 0)
|
||||
callbackArgs = [ evt ];
|
||||
(self[callbackName]).apply(self, callbackArgs);
|
||||
},
|
||||
true);
|
||||
|
||||
linkNode.addEventListener("keydown",
|
||||
function(evt) {
|
||||
if (!evt.isTrusted)
|
||||
return;
|
||||
if (evt.keyCode == evt.DOM_VK_RETURN) {
|
||||
evt.preventDefault();
|
||||
if (callbackArgs.length == 0)
|
||||
callbackArgs = [ evt ];
|
||||
evt.preventDefault();
|
||||
(self[callbackName]).apply(self, callbackArgs);
|
||||
}
|
||||
},
|
||||
true);
|
||||
},
|
||||
|
||||
// Helper to get the binding handler type from a plugin object
|
||||
_getBindingType : function(plugin) {
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return null;
|
||||
|
||||
switch (plugin.pluginFallbackType) {
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED:
|
||||
return "PluginNotFound";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_DISABLED:
|
||||
return "PluginDisabled";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED:
|
||||
return "PluginBlocklisted";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_OUTDATED:
|
||||
return "PluginOutdated";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
|
||||
return "PluginClickToPlay";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
|
||||
return "PluginVulnerableUpdatable";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
|
||||
return "PluginVulnerableNoUpdate";
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
|
||||
return "PluginPlayPreview";
|
||||
default:
|
||||
// Not all states map to a handler
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function (event) {
|
||||
let eventType = event.type;
|
||||
|
||||
if (eventType == "unload") {
|
||||
this.uninit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventType == "PluginRemoved") {
|
||||
this.updateNotificationUI();
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventType == "click") {
|
||||
this.onOverlayClick(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventType == "PluginCrashed" &&
|
||||
!(event.target instanceof Ci.nsIObjectLoadingContent)) {
|
||||
// If the event target is not a plugin object (i.e., an <object> or
|
||||
// <embed> element), this call is for a window-global plugin.
|
||||
this.pluginInstanceCrashed(event.target, event);
|
||||
return;
|
||||
}
|
||||
|
||||
let plugin = event.target;
|
||||
let doc = plugin.ownerDocument;
|
||||
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
|
||||
if (eventType == "PluginBindingAttached") {
|
||||
// The plugin binding fires this event when it is created.
|
||||
// As an untrusted event, ensure that this object actually has a binding
|
||||
// and make sure we don't handle it twice
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (!overlay || overlay._bindingHandled) {
|
||||
return;
|
||||
}
|
||||
overlay._bindingHandled = true;
|
||||
|
||||
// Lookup the handler for this binding
|
||||
eventType = this._getBindingType(plugin);
|
||||
if (!eventType) {
|
||||
// Not all bindings have handlers
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let shouldShowNotification = false;
|
||||
switch (eventType) {
|
||||
case "PluginCrashed":
|
||||
this.pluginInstanceCrashed(plugin, event);
|
||||
break;
|
||||
|
||||
case "PluginNotFound": {
|
||||
let installable = this.showInstallNotification(plugin, eventType);
|
||||
let contentWindow = plugin.ownerDocument.defaultView;
|
||||
// For non-object plugin tags, register a click handler to install the
|
||||
// plugin. Object tags can, and often do, deal with that themselves,
|
||||
// so don't stomp on the page developers toes.
|
||||
if (installable && !(plugin instanceof contentWindow.HTMLObjectElement)) {
|
||||
let installStatus = this.getPluginUI(plugin, "installStatus");
|
||||
installStatus.setAttribute("installable", "true");
|
||||
let iconStatus = this.getPluginUI(plugin, "icon");
|
||||
iconStatus.setAttribute("installable", "true");
|
||||
|
||||
let installLink = this.getPluginUI(plugin, "installPluginLink");
|
||||
this.addLinkClickCallback(installLink, "installSinglePlugin", plugin);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "PluginBlocklisted":
|
||||
case "PluginOutdated":
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
|
||||
case "PluginVulnerableUpdatable":
|
||||
let updateLink = this.getPluginUI(plugin, "checkForUpdatesLink");
|
||||
this.addLinkClickCallback(updateLink, "forwardCallback", "openPluginUpdatePage");
|
||||
/* FALLTHRU */
|
||||
|
||||
case "PluginVulnerableNoUpdate":
|
||||
case "PluginClickToPlay":
|
||||
this._handleClickToPlayEvent(plugin);
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
let pluginName = this._getPluginInfo(plugin).pluginName;
|
||||
let messageString = gNavigatorBundle.formatStringFromName("PluginClickToActivate", [pluginName], 1);
|
||||
let overlayText = this.getPluginUI(plugin, "clickToPlay");
|
||||
overlayText.textContent = messageString;
|
||||
if (eventType == "PluginVulnerableUpdatable" ||
|
||||
eventType == "PluginVulnerableNoUpdate") {
|
||||
let vulnerabilityString = gNavigatorBundle.GetStringFromName(eventType);
|
||||
let vulnerabilityText = this.getPluginUI(plugin, "vulnerabilityStatus");
|
||||
vulnerabilityText.textContent = vulnerabilityString;
|
||||
}
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
|
||||
case "PluginPlayPreview":
|
||||
this._handlePlayPreviewEvent(plugin);
|
||||
break;
|
||||
|
||||
case "PluginDisabled":
|
||||
let manageLink = this.getPluginUI(plugin, "managePluginsLink");
|
||||
this.addLinkClickCallback(manageLink, "forwardCallback", "managePlugins");
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
|
||||
case "PluginInstantiated":
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Show the in-content UI if it's not too big. The crashed plugin handler already did this.
|
||||
if (eventType != "PluginCrashed") {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (overlay != null) {
|
||||
this.setVisibility(plugin, overlay,
|
||||
this.shouldShowOverlay(plugin, overlay));
|
||||
let resizeListener = (event) => {
|
||||
this.setVisibility(plugin, overlay,
|
||||
this.shouldShowOverlay(plugin, overlay));
|
||||
this.updateNotificationUI();
|
||||
};
|
||||
plugin.addEventListener("overflow", resizeListener);
|
||||
plugin.addEventListener("underflow", resizeListener);
|
||||
}
|
||||
}
|
||||
|
||||
let closeIcon = this.getPluginUI(plugin, "closeIcon");
|
||||
if (closeIcon) {
|
||||
closeIcon.addEventListener("click", event => {
|
||||
if (event.button == 0 && event.isTrusted)
|
||||
this.hideClickToPlayOverlay(plugin);
|
||||
}, true);
|
||||
}
|
||||
|
||||
if (shouldShowNotification) {
|
||||
this._showClickToPlayNotification(plugin, false);
|
||||
}
|
||||
},
|
||||
|
||||
isKnownPlugin: function (objLoadingContent) {
|
||||
return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
|
||||
Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
||||
},
|
||||
|
||||
canActivatePlugin: function (objLoadingContent) {
|
||||
// if this isn't a known plugin, we can't activate it
|
||||
// (this also guards pluginHost.getPermissionStringForType against
|
||||
// unexpected input)
|
||||
if (!this.isKnownPlugin(objLoadingContent))
|
||||
return false;
|
||||
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
|
||||
let principal = objLoadingContent.ownerDocument.defaultView.top.document.nodePrincipal;
|
||||
let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString);
|
||||
|
||||
let isFallbackTypeValid =
|
||||
objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
|
||||
objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
|
||||
|
||||
if (objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW) {
|
||||
// checking if play preview is subject to CTP rules
|
||||
let playPreviewInfo = pluginHost.getPlayPreviewInfo(objLoadingContent.actualType);
|
||||
isFallbackTypeValid = !playPreviewInfo.ignoreCTP;
|
||||
}
|
||||
|
||||
return !objLoadingContent.activated &&
|
||||
pluginPermission != Ci.nsIPermissionManager.DENY_ACTION &&
|
||||
isFallbackTypeValid;
|
||||
},
|
||||
|
||||
hideClickToPlayOverlay: function (plugin) {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (overlay) {
|
||||
overlay.classList.remove("visible");
|
||||
}
|
||||
},
|
||||
|
||||
stopPlayPreview: function (plugin, playPlugin) {
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (objLoadingContent.activated)
|
||||
return;
|
||||
|
||||
if (playPlugin)
|
||||
objLoadingContent.playPlugin();
|
||||
else
|
||||
objLoadingContent.cancelPlayPreview();
|
||||
},
|
||||
|
||||
// Callback for user clicking on a missing (unsupported) plugin.
|
||||
installSinglePlugin: function (plugin) {
|
||||
this.global.sendAsyncMessage("PluginContent:InstallSinglePlugin", {
|
||||
pluginInfo: this._getPluginInfo(plugin),
|
||||
});
|
||||
},
|
||||
|
||||
// Forward a link click callback to the chrome process.
|
||||
forwardCallback: function (name) {
|
||||
this.global.sendAsyncMessage("PluginContent:LinkClickCallback", { name: name });
|
||||
},
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
submitReport: function submitReport(pluginDumpID, browserDumpID, plugin) {
|
||||
let keyVals = {};
|
||||
if (plugin) {
|
||||
let userComment = this.getPluginUI(plugin, "submitComment").value.trim();
|
||||
if (userComment)
|
||||
keyVals.PluginUserComment = userComment;
|
||||
if (this.getPluginUI(plugin, "submitURLOptIn").checked)
|
||||
keyVals.PluginContentURL = plugin.ownerDocument.URL;
|
||||
}
|
||||
|
||||
this.global.sendAsyncMessage("PluginContent:SubmitReport", {
|
||||
pluginDumpID: pluginDumpID,
|
||||
browserDumpID: browserDumpID,
|
||||
keyVals: keyVals,
|
||||
});
|
||||
},
|
||||
#endif
|
||||
|
||||
reloadPage: function () {
|
||||
this.global.content.location.reload();
|
||||
},
|
||||
|
||||
showInstallNotification: function (plugin) {
|
||||
let [shown] = this.global.sendSyncMessage("PluginContent:ShowInstallNotification", {
|
||||
pluginInfo: this._getPluginInfo(plugin),
|
||||
});
|
||||
return shown;
|
||||
},
|
||||
|
||||
// Event listener for click-to-play plugins.
|
||||
_handleClickToPlayEvent: function (plugin) {
|
||||
let doc = plugin.ownerDocument;
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
// guard against giving pluginHost.getPermissionStringForType a type
|
||||
// not associated with any known plugin
|
||||
if (!this.isKnownPlugin(objLoadingContent))
|
||||
return;
|
||||
let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
|
||||
let principal = doc.defaultView.top.document.nodePrincipal;
|
||||
let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString);
|
||||
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
|
||||
if (pluginPermission == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||
if (overlay) {
|
||||
overlay.classList.remove("visible");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (overlay) {
|
||||
overlay.addEventListener("click", this, true);
|
||||
}
|
||||
},
|
||||
|
||||
onOverlayClick: function (event) {
|
||||
let document = event.target.ownerDocument;
|
||||
let plugin = document.getBindingParent(event.target);
|
||||
let contentWindow = plugin.ownerDocument.defaultView.top;
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
// Have to check that the target is not the link to update the plugin
|
||||
if (!(event.originalTarget instanceof contentWindow.HTMLAnchorElement) &&
|
||||
(event.originalTarget.getAttribute('anonid') != 'closeIcon') &&
|
||||
event.button == 0 && event.isTrusted) {
|
||||
this._showClickToPlayNotification(plugin, true);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
_handlePlayPreviewEvent: function (plugin) {
|
||||
let doc = plugin.ownerDocument;
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let pluginInfo = this._getPluginInfo(plugin);
|
||||
let playPreviewInfo = pluginHost.getPlayPreviewInfo(pluginInfo.mimetype);
|
||||
|
||||
let previewContent = this.getPluginUI(plugin, "previewPluginContent");
|
||||
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
|
||||
if (!iframe) {
|
||||
// lazy initialization of the iframe
|
||||
iframe = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
|
||||
iframe.className = "previewPluginContentFrame";
|
||||
previewContent.appendChild(iframe);
|
||||
|
||||
// Force a style flush, so that we ensure our binding is attached.
|
||||
plugin.clientTop;
|
||||
}
|
||||
iframe.src = playPreviewInfo.redirectURL;
|
||||
|
||||
// MozPlayPlugin event can be dispatched from the extension chrome
|
||||
// code to replace the preview content with the native plugin
|
||||
let playPluginHandler = (event) => {
|
||||
if (!event.isTrusted)
|
||||
return;
|
||||
|
||||
previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true);
|
||||
|
||||
let playPlugin = !event.detail;
|
||||
this.stopPlayPreview(plugin, playPlugin);
|
||||
|
||||
// cleaning up: removes overlay iframe from the DOM
|
||||
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
|
||||
if (iframe)
|
||||
previewContent.removeChild(iframe);
|
||||
};
|
||||
|
||||
previewContent.addEventListener("MozPlayPlugin", playPluginHandler, true);
|
||||
|
||||
if (!playPreviewInfo.ignoreCTP) {
|
||||
this._showClickToPlayNotification(plugin, false);
|
||||
}
|
||||
},
|
||||
|
||||
reshowClickToPlayNotification: function () {
|
||||
let contentWindow = this.global.content;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let plugins = cwu.plugins;
|
||||
for (let plugin of plugins) {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (overlay)
|
||||
overlay.removeEventListener("click", this, true);
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (this.canActivatePlugin(objLoadingContent))
|
||||
this._handleClickToPlayEvent(plugin);
|
||||
}
|
||||
this._showClickToPlayNotification(null, false);
|
||||
},
|
||||
|
||||
// Match the behaviour of nsPermissionManager
|
||||
_getHostFromPrincipal: function (principal) {
|
||||
if (!principal.URI || principal.URI.schemeIs("moz-nullprincipal")) {
|
||||
return "(null)";
|
||||
}
|
||||
|
||||
try {
|
||||
if (principal.URI.host)
|
||||
return principal.URI.host;
|
||||
} catch (e) {}
|
||||
|
||||
return principal.origin;
|
||||
},
|
||||
|
||||
/**
|
||||
* Activate the plugins that the user has specified.
|
||||
*/
|
||||
activatePlugins: function (pluginInfo, newState) {
|
||||
let contentWindow = this.global.content;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let plugins = cwu.plugins;
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
|
||||
let pluginFound = false;
|
||||
for (let plugin of plugins) {
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (!this.isKnownPlugin(plugin)) {
|
||||
continue;
|
||||
}
|
||||
if (pluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
|
||||
pluginFound = true;
|
||||
if (newState == "block") {
|
||||
plugin.reload(true);
|
||||
} else {
|
||||
if (this.canActivatePlugin(plugin)) {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (overlay) {
|
||||
overlay.removeEventListener("click", this, true);
|
||||
}
|
||||
plugin.playPlugin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no instances of the plugin on the page any more, what the
|
||||
// user probably needs is for us to allow and then refresh.
|
||||
if (newState != "block" && !pluginFound) {
|
||||
this.reloadPage();
|
||||
}
|
||||
this.updateNotificationUI();
|
||||
},
|
||||
|
||||
_showClickToPlayNotification: function (plugin, showNow) {
|
||||
let plugins = [];
|
||||
|
||||
// If plugin is null, that means the user has navigated back to a page with
|
||||
// plugins, and we need to collect all the plugins.
|
||||
if (plugin === null) {
|
||||
let contentWindow = this.global.content;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
// cwu.plugins may contain non-plugin <object>s, filter them out
|
||||
plugins = cwu.plugins.filter((plugin) =>
|
||||
plugin.getContentTypeForMIMEType(plugin.actualType) == Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
||||
|
||||
if (plugins.length == 0) {
|
||||
this.removeNotification("click-to-play-plugins");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
plugins = [plugin];
|
||||
}
|
||||
|
||||
let pluginData = this.pluginData;
|
||||
|
||||
let principal = this.global.content.document.nodePrincipal;
|
||||
let principalHost = this._getHostFromPrincipal(principal);
|
||||
|
||||
for (let p of plugins) {
|
||||
let pluginInfo = this._getPluginInfo(p);
|
||||
if (pluginInfo.permissionString === null) {
|
||||
Cu.reportError("No permission string for active plugin.");
|
||||
continue;
|
||||
}
|
||||
if (pluginData.has(pluginInfo.permissionString)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let permissionObj = Services.perms.
|
||||
getPermissionObject(principal, pluginInfo.permissionString, false);
|
||||
if (permissionObj) {
|
||||
pluginInfo.pluginPermissionHost = permissionObj.host;
|
||||
pluginInfo.pluginPermissionType = permissionObj.expireType;
|
||||
}
|
||||
else {
|
||||
pluginInfo.pluginPermissionHost = principalHost;
|
||||
pluginInfo.pluginPermissionType = undefined;
|
||||
}
|
||||
|
||||
this.pluginData.set(pluginInfo.permissionString, pluginInfo);
|
||||
}
|
||||
|
||||
this.global.sendAsyncMessage("PluginContent:ShowClickToPlayNotification", {
|
||||
plugins: [... this.pluginData.values()],
|
||||
showNow: showNow,
|
||||
host: principalHost,
|
||||
}, null, principal);
|
||||
},
|
||||
|
||||
updateNotificationUI: function () {
|
||||
// Make a copy of the actions from the last popup notification.
|
||||
let haveInsecure = false;
|
||||
let actions = new Map();
|
||||
for (let action of this.pluginData.values()) {
|
||||
switch (action.fallbackType) {
|
||||
// haveInsecure will trigger the red flashing icon and the infobar
|
||||
// styling below
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
|
||||
haveInsecure = true;
|
||||
// fall through
|
||||
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
|
||||
actions.set(action.permissionString, action);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove plugins that are already active, or large enough to show an overlay.
|
||||
let contentWindow = this.global.content;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
for (let plugin of cwu.plugins) {
|
||||
let info = this._getPluginInfo(plugin);
|
||||
if (!actions.has(info.permissionString)) {
|
||||
continue;
|
||||
}
|
||||
let fallbackType = info.fallbackType;
|
||||
if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
actions.delete(info.permissionString);
|
||||
if (actions.size == 0) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
|
||||
fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE &&
|
||||
fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE) {
|
||||
continue;
|
||||
}
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (!overlay) {
|
||||
continue;
|
||||
}
|
||||
let shouldShow = this.shouldShowOverlay(plugin, overlay);
|
||||
this.setVisibility(plugin, overlay, shouldShow);
|
||||
if (shouldShow) {
|
||||
actions.delete(info.permissionString);
|
||||
if (actions.size == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any items remaining in `actions` now, they are hidden
|
||||
// plugins that need a notification bar.
|
||||
let principal = contentWindow.document.nodePrincipal;
|
||||
this.global.sendAsyncMessage("PluginContent:UpdateHiddenPluginUI", {
|
||||
haveInsecure: haveInsecure,
|
||||
actions: [... actions.values()],
|
||||
host: this._getHostFromPrincipal(principal),
|
||||
}, null, principal);
|
||||
},
|
||||
|
||||
removeNotification: function (name) {
|
||||
this.global.sendAsyncMessage("PluginContent:RemoveNotification", { name: name });
|
||||
},
|
||||
|
||||
clearPluginDataCache: function () {
|
||||
this.pluginData.clear();
|
||||
},
|
||||
|
||||
hideNotificationBar: function (name) {
|
||||
this.global.sendAsyncMessage("PluginContent:HideNotificationBar", { name: name });
|
||||
},
|
||||
|
||||
// Crashed-plugin event listener. Called for every instance of a
|
||||
// plugin in content.
|
||||
pluginInstanceCrashed: function (target, aEvent) {
|
||||
// Ensure the plugin and event are of the right type.
|
||||
if (!(aEvent instanceof Ci.nsIDOMCustomEvent))
|
||||
return;
|
||||
|
||||
let propBag = aEvent.detail.QueryInterface(Ci.nsIPropertyBag2);
|
||||
let submittedReport = propBag.getPropertyAsBool("submittedCrashReport");
|
||||
let doPrompt = true; // XXX followup for .getPropertyAsBool("doPrompt");
|
||||
let submitReports = true; // XXX followup for .getPropertyAsBool("submitReports");
|
||||
let pluginName = propBag.getPropertyAsAString("pluginName");
|
||||
let pluginDumpID = propBag.getPropertyAsAString("pluginDumpID");
|
||||
let browserDumpID = null;
|
||||
let gmpPlugin = false;
|
||||
|
||||
try {
|
||||
browserDumpID = propBag.getPropertyAsAString("browserDumpID");
|
||||
} catch (e) {
|
||||
// For GMP crashes we don't get a browser dump.
|
||||
}
|
||||
|
||||
try {
|
||||
gmpPlugin = propBag.getPropertyAsBool("gmpPlugin");
|
||||
} catch (e) {
|
||||
// This property is only set for GMP plugins.
|
||||
}
|
||||
|
||||
// For non-GMP plugins, remap the plugin name to a more user-presentable form.
|
||||
if (!gmpPlugin) {
|
||||
pluginName = this.makeNicePluginName(pluginName);
|
||||
}
|
||||
|
||||
let messageString = gNavigatorBundle.formatStringFromName("crashedpluginsMessage.title", [pluginName], 1);
|
||||
|
||||
let plugin = null, doc;
|
||||
if (target instanceof Ci.nsIObjectLoadingContent) {
|
||||
plugin = target;
|
||||
doc = plugin.ownerDocument;
|
||||
} else {
|
||||
doc = target.document;
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
// doPrompt is specific to the crashed plugin overlay, and
|
||||
// therefore is not applicable for window-global plugins.
|
||||
doPrompt = false;
|
||||
}
|
||||
|
||||
let status;
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
// Determine which message to show regarding crash reports.
|
||||
if (submittedReport) { // submitReports && !doPrompt, handled in observer
|
||||
status = "submitted";
|
||||
}
|
||||
else if (!submitReports && !doPrompt) {
|
||||
status = "noSubmit";
|
||||
}
|
||||
else if (!pluginDumpID) {
|
||||
// If we don't have a minidumpID, we can't (or didn't) submit anything.
|
||||
// This can happen if the plugin is killed from the task manager.
|
||||
status = "noReport";
|
||||
}
|
||||
else {
|
||||
status = "please";
|
||||
}
|
||||
|
||||
// If we don't have a minidumpID, we can't (or didn't) submit anything.
|
||||
// This can happen if the plugin is killed from the task manager.
|
||||
if (!pluginDumpID) {
|
||||
status = "noReport";
|
||||
}
|
||||
|
||||
// If we're showing the link to manually trigger report submission, we'll
|
||||
// want to be able to update all the instances of the UI for this crash to
|
||||
// show an updated message when a report is submitted.
|
||||
if (doPrompt) {
|
||||
let observer = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
observe : (subject, topic, data) => {
|
||||
let propertyBag = subject;
|
||||
if (!(propertyBag instanceof Ci.nsIPropertyBag2))
|
||||
return;
|
||||
// Ignore notifications for other crashes.
|
||||
if (propertyBag.get("minidumpID") != pluginDumpID)
|
||||
return;
|
||||
let statusDiv = this.getPluginUI(plugin, "submitStatus");
|
||||
statusDiv.setAttribute("status", data);
|
||||
},
|
||||
|
||||
handleEvent : function(event) {
|
||||
// Not expected to be called, just here for the closure.
|
||||
}
|
||||
}
|
||||
|
||||
// Use a weak reference, so we don't have to remove it...
|
||||
Services.obs.addObserver(observer, "crash-report-status", true);
|
||||
// ...alas, now we need something to hold a strong reference to prevent
|
||||
// it from being GC. But I don't want to manually manage the reference's
|
||||
// lifetime (which should be no greater than the page).
|
||||
// Clever solution? Use a closue with an event listener on the document.
|
||||
// When the doc goes away, so do the listener references and the closure.
|
||||
doc.addEventListener("mozCleverClosureHack", observer, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
let isShowing = false;
|
||||
|
||||
if (plugin) {
|
||||
// If there's no plugin (an <object> or <embed> element), this call is
|
||||
// for a window-global plugin. In this case, there's no overlay to show.
|
||||
isShowing = _setUpPluginOverlay.call(this, plugin, doPrompt);
|
||||
}
|
||||
|
||||
if (isShowing) {
|
||||
// If a previous plugin on the page was too small and resulted in adding a
|
||||
// notification bar, then remove it because this plugin instance it big
|
||||
// enough to serve as in-content notification.
|
||||
this.hideNotificationBar("plugin-crashed");
|
||||
doc.mozNoPluginCrashedNotification = true;
|
||||
} else {
|
||||
// If another plugin on the page was large enough to show our UI, we don't
|
||||
// want to show a notification bar.
|
||||
if (!doc.mozNoPluginCrashedNotification) {
|
||||
this.global.sendAsyncMessage("PluginContent:ShowPluginCrashedNotification", {
|
||||
messageString: messageString,
|
||||
pluginDumpID: pluginDumpID,
|
||||
browserDumpID: browserDumpID,
|
||||
});
|
||||
// Remove the notification when the page is reloaded.
|
||||
doc.defaultView.top.addEventListener("unload", event => {
|
||||
this.hideNotificationBar("plugin-crashed");
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the crashed-plugin placeholder.
|
||||
// Returns true if the plugin overlay is visible.
|
||||
function _setUpPluginOverlay(plugin, doPromptSubmit) {
|
||||
if (!plugin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Force a layout flush so the binding is attached.
|
||||
plugin.clientTop;
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
let statusDiv = this.getPluginUI(plugin, "submitStatus");
|
||||
|
||||
if (doPromptSubmit) {
|
||||
this.getPluginUI(plugin, "submitButton").addEventListener("click",
|
||||
function (event) {
|
||||
if (event.button != 0 || !event.isTrusted)
|
||||
return;
|
||||
this.submitReport(pluginDumpID, browserDumpID, plugin);
|
||||
pref.setBoolPref("", optInCB.checked);
|
||||
}.bind(this));
|
||||
let optInCB = this.getPluginUI(plugin, "submitURLOptIn");
|
||||
let pref = Services.prefs.getBranch("dom.ipc.plugins.reportCrashURL");
|
||||
optInCB.checked = pref.getBoolPref("");
|
||||
}
|
||||
|
||||
statusDiv.setAttribute("status", status);
|
||||
|
||||
let helpIcon = this.getPluginUI(plugin, "helpIcon");
|
||||
this.addLinkClickCallback(helpIcon, "openHelpPage");
|
||||
|
||||
let crashText = this.getPluginUI(plugin, "crashedText");
|
||||
crashText.textContent = messageString;
|
||||
|
||||
let link = this.getPluginUI(plugin, "reloadLink");
|
||||
this.addLinkClickCallback(link, "reloadPage");
|
||||
|
||||
let isShowing = this.shouldShowOverlay(plugin, overlay);
|
||||
|
||||
// Is the <object>'s size too small to hold what we want to show?
|
||||
if (!isShowing) {
|
||||
// First try hiding the crash report submission UI.
|
||||
statusDiv.removeAttribute("status");
|
||||
|
||||
isShowing = this.shouldShowOverlay(plugin, overlay);
|
||||
}
|
||||
this.setVisibility(plugin, overlay, isShowing);
|
||||
|
||||
return isShowing;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -44,6 +44,7 @@ if CONFIG['NIGHTLY_BUILD']:
|
|||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'AboutHome.jsm',
|
||||
'PluginContent.jsm',
|
||||
'RecentWindow.jsm',
|
||||
'UITour.jsm',
|
||||
'webrtcUI.jsm',
|
||||
|
|
|
@ -925,7 +925,6 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
|||
nsIPrincipal* aPrincipal,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
AutoSafeJSContext cx;
|
||||
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
|
||||
mListeners.Get(aMessage);
|
||||
if (listeners) {
|
||||
|
@ -956,11 +955,23 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
|||
if (!wrappedJS) {
|
||||
continue;
|
||||
}
|
||||
JS::Rooted<JSObject*> object(cx, wrappedJS->GetJSObject());
|
||||
if (!object) {
|
||||
|
||||
if (!wrappedJS->GetJSObject()) {
|
||||
continue;
|
||||
}
|
||||
JSAutoCompartment ac(cx, object);
|
||||
|
||||
// Note - The ergonomics here will get a lot better with bug 971673:
|
||||
//
|
||||
// AutoEntryScript aes;
|
||||
// if (!aes.Init(wrappedJS->GetJSObject())) {
|
||||
// continue;
|
||||
// }
|
||||
// JSContext* cx = aes.cx();
|
||||
nsIGlobalObject* nativeGlobal =
|
||||
xpc::GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(wrappedJS->GetJSObject()));
|
||||
AutoEntryScript aes(nativeGlobal);
|
||||
JSContext* cx = aes.cx();
|
||||
JS::Rooted<JSObject*> object(cx, wrappedJS->GetJSObject());
|
||||
|
||||
// The parameter for the listener function.
|
||||
JS::Rooted<JSObject*> param(cx,
|
||||
|
|
|
@ -9,6 +9,7 @@ var is_remote;
|
|||
(function start() {
|
||||
[is_remote] = sendSyncMessage("cpows:is_remote");
|
||||
parent_test();
|
||||
error_reporting_test();
|
||||
dom_test();
|
||||
xray_test();
|
||||
compartment_test();
|
||||
|
@ -89,6 +90,10 @@ function parent_test()
|
|||
sendSyncMessage("cpows:parent_test", {}, {func: f});
|
||||
}
|
||||
|
||||
function error_reporting_test() {
|
||||
sendSyncMessage("cpows:error_reporting_test", {}, {});
|
||||
}
|
||||
|
||||
function dom_test()
|
||||
{
|
||||
let element = content.document.createElement("div");
|
||||
|
|
|
@ -33,7 +33,12 @@
|
|||
}
|
||||
|
||||
// Make sure that an error in this file actually causes the test to fail.
|
||||
var gReceivedErrorProbe = false;
|
||||
window.onerror = function (msg, url, line) {
|
||||
if (/Test Error Probe/.test(msg)) {
|
||||
gReceivedErrorProbe = true;
|
||||
return;
|
||||
}
|
||||
ok(false, "Error while executing: \n" + msg + "\n" + url + ":" + line);
|
||||
};
|
||||
|
||||
|
@ -175,6 +180,11 @@
|
|||
savedMM.sendAsyncMessage("cpows:from_parent", {}, {obj: obj});
|
||||
}
|
||||
|
||||
// Make sure errors in this file actually hit window.onerror.
|
||||
function recvErrorReportingTest(message) {
|
||||
throw "Test Error Probe";
|
||||
}
|
||||
|
||||
let savedElement = null;
|
||||
function recvDomTest(message) {
|
||||
savedElement = message.objects.element;
|
||||
|
@ -271,6 +281,7 @@
|
|||
mm.addMessageListener("cpows:done", recvDoneMessage);
|
||||
mm.addMessageListener("cpows:fail", recvFailMessage);
|
||||
mm.addMessageListener("cpows:parent_test", recvParentTest);
|
||||
mm.addMessageListener("cpows:error_reporting_test", recvErrorReportingTest);
|
||||
mm.addMessageListener("cpows:dom_test", recvDomTest);
|
||||
mm.addMessageListener("cpows:dom_test_after_gc", recvDomTestAfterGC);
|
||||
mm.addMessageListener("cpows:xray_test", recvXrayTest);
|
||||
|
@ -285,6 +296,7 @@
|
|||
}
|
||||
|
||||
function finish() {
|
||||
ok(gReceivedErrorProbe, "Should have reported error probe");
|
||||
opener.setTimeout("done()", 0);
|
||||
window.close();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ support-files =
|
|||
|
||||
[test_BufferedSeek.html]
|
||||
[test_FrameSelection.html]
|
||||
skip-if = os == "mac"
|
||||
[test_MediaSource.html]
|
||||
[test_SplitAppendDelay.html]
|
||||
[test_SplitAppend.html]
|
||||
|
|
|
@ -49,10 +49,10 @@ runWithMSE(function () {
|
|||
first = false;
|
||||
} else {
|
||||
ms.endOfStream();
|
||||
}
|
||||
});
|
||||
target = targets.shift();
|
||||
v.currentTime = target.currentTime;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -114,6 +114,8 @@ GetValueFromString(const nsAString& aString,
|
|||
return IsValidUnitType(*aUnitType);
|
||||
}
|
||||
|
||||
static float GetMMPerPixel() { return MM_PER_INCH_FLOAT / 96; }
|
||||
|
||||
static float
|
||||
FixAxisLength(float aLength)
|
||||
{
|
||||
|
@ -124,22 +126,73 @@ FixAxisLength(float aLength)
|
|||
return aLength;
|
||||
}
|
||||
|
||||
float
|
||||
nsSVGLength2::GetAxisLength(SVGSVGElement *aCtx) const
|
||||
SVGElementMetrics::SVGElementMetrics(nsSVGElement* aSVGElement,
|
||||
SVGSVGElement* aCtx)
|
||||
: mSVGElement(aSVGElement)
|
||||
, mCtx(aCtx)
|
||||
{
|
||||
if (!aCtx)
|
||||
return 1;
|
||||
|
||||
return FixAxisLength(aCtx->GetLength(mCtxType));
|
||||
}
|
||||
|
||||
float
|
||||
nsSVGLength2::GetAxisLength(nsIFrame *aNonSVGFrame) const
|
||||
SVGElementMetrics::GetEmLength() const
|
||||
{
|
||||
gfx::Size size =
|
||||
nsSVGIntegrationUtils::GetSVGCoordContextForNonSVGFrame(aNonSVGFrame);
|
||||
return SVGContentUtils::GetFontSize(mSVGElement);
|
||||
}
|
||||
|
||||
float
|
||||
SVGElementMetrics::GetExLength() const
|
||||
{
|
||||
return SVGContentUtils::GetFontXHeight(mSVGElement);
|
||||
}
|
||||
|
||||
float
|
||||
SVGElementMetrics::GetAxisLength(uint8_t aCtxType) const
|
||||
{
|
||||
if (!EnsureCtx()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FixAxisLength(mCtx->GetLength(aCtxType));
|
||||
}
|
||||
|
||||
bool
|
||||
SVGElementMetrics::EnsureCtx() const
|
||||
{
|
||||
if (!mCtx && mSVGElement) {
|
||||
mCtx = mSVGElement->GetCtx();
|
||||
}
|
||||
return mCtx != nullptr;
|
||||
}
|
||||
|
||||
NonSVGFrameUserSpaceMetrics::NonSVGFrameUserSpaceMetrics(nsIFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
{
|
||||
}
|
||||
|
||||
float
|
||||
NonSVGFrameUserSpaceMetrics::GetEmLength() const
|
||||
{
|
||||
return SVGContentUtils::GetFontSize(mFrame);
|
||||
}
|
||||
|
||||
float
|
||||
NonSVGFrameUserSpaceMetrics::GetExLength() const
|
||||
{
|
||||
return SVGContentUtils::GetFontXHeight(mFrame);
|
||||
}
|
||||
|
||||
gfx::Size
|
||||
NonSVGFrameUserSpaceMetrics::GetSize() const
|
||||
{
|
||||
return nsSVGIntegrationUtils::GetSVGCoordContextForNonSVGFrame(mFrame);
|
||||
}
|
||||
|
||||
float
|
||||
UserSpaceMetricsWithSize::GetAxisLength(uint8_t aCtxType) const
|
||||
{
|
||||
gfx::Size size = GetSize();
|
||||
float length;
|
||||
switch (mCtxType) {
|
||||
switch (aCtxType) {
|
||||
case SVGContentUtils::X:
|
||||
length = size.width;
|
||||
break;
|
||||
|
@ -161,55 +214,28 @@ float
|
|||
nsSVGLength2::GetUnitScaleFactor(nsSVGElement *aSVGElement,
|
||||
uint8_t aUnitType) const
|
||||
{
|
||||
switch (aUnitType) {
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER:
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_PX:
|
||||
return 1;
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS:
|
||||
return 1 / GetEmLength(aSVGElement);
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS:
|
||||
return 1 / GetExLength(aSVGElement);
|
||||
}
|
||||
|
||||
return GetUnitScaleFactor(aSVGElement->GetCtx(), aUnitType);
|
||||
return GetUnitScaleFactor(SVGElementMetrics(aSVGElement), aUnitType);
|
||||
}
|
||||
|
||||
float
|
||||
nsSVGLength2::GetUnitScaleFactor(SVGSVGElement *aCtx, uint8_t aUnitType) const
|
||||
{
|
||||
switch (aUnitType) {
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER:
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_PX:
|
||||
return 1;
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_MM:
|
||||
return GetMMPerPixel();
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_CM:
|
||||
return GetMMPerPixel() / 10.0f;
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_IN:
|
||||
return GetMMPerPixel() / MM_PER_INCH_FLOAT;
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_PT:
|
||||
return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT;
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_PC:
|
||||
return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT / 12.0f;
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE:
|
||||
return 100.0f / GetAxisLength(aCtx);
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS:
|
||||
return 1 / GetEmLength(aCtx);
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS:
|
||||
return 1 / GetExLength(aCtx);
|
||||
default:
|
||||
NS_NOTREACHED("Unknown unit type");
|
||||
return 0;
|
||||
}
|
||||
return GetUnitScaleFactor(SVGElementMetrics(aCtx, aCtx), aUnitType);
|
||||
}
|
||||
|
||||
float
|
||||
nsSVGLength2::GetUnitScaleFactor(nsIFrame *aFrame, uint8_t aUnitType) const
|
||||
{
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
if (content->IsSVG())
|
||||
return GetUnitScaleFactor(static_cast<nsSVGElement*>(content), aUnitType);
|
||||
if (content->IsSVG()) {
|
||||
return GetUnitScaleFactor(SVGElementMetrics(static_cast<nsSVGElement*>(content)), aUnitType);
|
||||
}
|
||||
return GetUnitScaleFactor(NonSVGFrameUserSpaceMetrics(aFrame), aUnitType);
|
||||
}
|
||||
|
||||
float
|
||||
nsSVGLength2::GetUnitScaleFactor(const UserSpaceMetrics& aMetrics, uint8_t aUnitType) const
|
||||
{
|
||||
switch (aUnitType) {
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER:
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_PX:
|
||||
|
@ -225,11 +251,11 @@ nsSVGLength2::GetUnitScaleFactor(nsIFrame *aFrame, uint8_t aUnitType) const
|
|||
case nsIDOMSVGLength::SVG_LENGTHTYPE_PC:
|
||||
return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT / 12.0f;
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE:
|
||||
return 100.0f / GetAxisLength(aFrame);
|
||||
return 100.0f / aMetrics.GetAxisLength(mCtxType);
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS:
|
||||
return 1 / GetEmLength(aFrame);
|
||||
return 1 / aMetrics.GetEmLength();
|
||||
case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS:
|
||||
return 1 / GetExLength(aFrame);
|
||||
return 1 / aMetrics.GetExLength();
|
||||
default:
|
||||
NS_NOTREACHED("Unknown unit type");
|
||||
return 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsMathUtils.h"
|
||||
#include "nsSVGElement.h"
|
||||
#include "SVGContentUtils.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsSMILValue;
|
||||
|
@ -29,10 +30,64 @@ class SVGSVGElement;
|
|||
}
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class UserSpaceMetrics
|
||||
{
|
||||
public:
|
||||
virtual ~UserSpaceMetrics() {}
|
||||
|
||||
virtual float GetEmLength() const = 0;
|
||||
virtual float GetExLength() const = 0;
|
||||
virtual float GetAxisLength(uint8_t aCtxType) const = 0;
|
||||
};
|
||||
|
||||
class UserSpaceMetricsWithSize : public UserSpaceMetrics
|
||||
{
|
||||
public:
|
||||
virtual gfx::Size GetSize() const = 0;
|
||||
virtual float GetAxisLength(uint8_t aCtxType) const MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
class SVGElementMetrics : public UserSpaceMetrics
|
||||
{
|
||||
public:
|
||||
SVGElementMetrics(nsSVGElement* aSVGElement,
|
||||
mozilla::dom::SVGSVGElement* aCtx = nullptr);
|
||||
|
||||
virtual float GetEmLength() const MOZ_OVERRIDE;
|
||||
virtual float GetExLength() const MOZ_OVERRIDE;
|
||||
virtual float GetAxisLength(uint8_t aCtxType) const MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool EnsureCtx() const;
|
||||
|
||||
nsSVGElement* mSVGElement;
|
||||
mutable mozilla::dom::SVGSVGElement* mCtx;
|
||||
};
|
||||
|
||||
class NonSVGFrameUserSpaceMetrics : public UserSpaceMetricsWithSize
|
||||
{
|
||||
public:
|
||||
NonSVGFrameUserSpaceMetrics(nsIFrame* aFrame);
|
||||
|
||||
virtual float GetEmLength() const MOZ_OVERRIDE;
|
||||
virtual float GetExLength() const MOZ_OVERRIDE;
|
||||
virtual gfx::Size GetSize() const MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
nsIFrame* mFrame;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class nsSVGLength2
|
||||
{
|
||||
friend class mozilla::dom::SVGAnimatedLength;
|
||||
friend class mozilla::DOMSVGLength;
|
||||
typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics;
|
||||
public:
|
||||
void Init(uint8_t aCtxType = SVGContentUtils::XY,
|
||||
uint8_t aAttrEnum = 0xff,
|
||||
|
@ -63,10 +118,15 @@ public:
|
|||
|
||||
float GetBaseValue(nsSVGElement* aSVGElement) const
|
||||
{ return mBaseVal / GetUnitScaleFactor(aSVGElement, mSpecifiedUnitType); }
|
||||
|
||||
float GetAnimValue(nsSVGElement* aSVGElement) const
|
||||
{ return mAnimVal / GetUnitScaleFactor(aSVGElement, mSpecifiedUnitType); }
|
||||
float GetAnimValue(nsIFrame* aFrame) const
|
||||
{ return mAnimVal / GetUnitScaleFactor(aFrame, mSpecifiedUnitType); }
|
||||
float GetAnimValue(mozilla::dom::SVGSVGElement* aCtx) const
|
||||
{ return mAnimVal / GetUnitScaleFactor(aCtx, mSpecifiedUnitType); }
|
||||
float GetAnimValue(const UserSpaceMetrics& aMetrics) const
|
||||
{ return mAnimVal / GetUnitScaleFactor(aMetrics, mSpecifiedUnitType); }
|
||||
|
||||
uint8_t GetCtxType() const { return mCtxType; }
|
||||
uint8_t GetSpecifiedUnitType() const { return mSpecifiedUnitType; }
|
||||
|
@ -77,8 +137,6 @@ public:
|
|||
|
||||
float GetBaseValue(mozilla::dom::SVGSVGElement* aCtx) const
|
||||
{ return mBaseVal / GetUnitScaleFactor(aCtx, mSpecifiedUnitType); }
|
||||
float GetAnimValue(mozilla::dom::SVGSVGElement* aCtx) const
|
||||
{ return mAnimVal / GetUnitScaleFactor(aCtx, mSpecifiedUnitType); }
|
||||
|
||||
bool HasBaseVal() const {
|
||||
return mIsBaseSet;
|
||||
|
@ -107,20 +165,8 @@ private:
|
|||
bool mIsAnimated:1;
|
||||
bool mIsBaseSet:1;
|
||||
|
||||
static float GetMMPerPixel() { return MM_PER_INCH_FLOAT / 96; }
|
||||
float GetAxisLength(nsIFrame *aNonSVGFrame) const;
|
||||
static float GetEmLength(nsIFrame *aFrame)
|
||||
{ return SVGContentUtils::GetFontSize(aFrame); }
|
||||
static float GetExLength(nsIFrame *aFrame)
|
||||
{ return SVGContentUtils::GetFontXHeight(aFrame); }
|
||||
float GetUnitScaleFactor(nsIFrame *aFrame, uint8_t aUnitType) const;
|
||||
|
||||
float GetMMPerPixel(mozilla::dom::SVGSVGElement *aCtx) const;
|
||||
float GetAxisLength(mozilla::dom::SVGSVGElement *aCtx) const;
|
||||
static float GetEmLength(nsSVGElement *aSVGElement)
|
||||
{ return SVGContentUtils::GetFontSize(aSVGElement); }
|
||||
static float GetExLength(nsSVGElement *aSVGElement)
|
||||
{ return SVGContentUtils::GetFontXHeight(aSVGElement); }
|
||||
float GetUnitScaleFactor(const UserSpaceMetrics& aMetrics, uint8_t aUnitType) const;
|
||||
float GetUnitScaleFactor(nsSVGElement *aSVGElement, uint8_t aUnitType) const;
|
||||
float GetUnitScaleFactor(mozilla::dom::SVGSVGElement *aCtx, uint8_t aUnitType) const;
|
||||
|
||||
|
|
|
@ -117,9 +117,7 @@ public:
|
|||
* transparent one.
|
||||
*
|
||||
* Note: So ObjectIsNativeWrapper(cx, obj) check usually means "through xray
|
||||
* wrapper this part is not visible" while combined with
|
||||
* || xpc::WrapperFactory::XrayWrapperNotShadowing(obj) it means "through
|
||||
* xray wrapper it is visible only if it does not hide any native property."
|
||||
* wrapper this part is not visible".
|
||||
*/
|
||||
static bool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj);
|
||||
|
||||
|
|
|
@ -468,7 +468,22 @@ SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
|
|||
if (outer) {
|
||||
globalObject = static_cast<nsGlobalWindow*>(outer->GetCurrentInnerWindow());
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
// We run addons in a separate privileged compartment, but they still expect
|
||||
// to trigger the onerror handler of their associated DOMWindow.
|
||||
//
|
||||
// Note that the way we do this right now is sloppy. Error reporters can
|
||||
// theoretically be triggered at arbitrary times (not just immediately before
|
||||
// an AutoJSAPI comes off the stack), so we don't really have a way of knowing
|
||||
// that the global of the current compartment is the correct global with which
|
||||
// to report the error. But in practice this is probably fine for the time
|
||||
// being, and will get cleaned up soon when we fix bug 981187.
|
||||
if (!globalObject && JS::CurrentGlobalOrNull(cx)) {
|
||||
globalObject = xpc::AddonWindowOrNull(JS::CurrentGlobalOrNull(cx));
|
||||
}
|
||||
|
||||
if (!globalObject) {
|
||||
globalObject = xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope());
|
||||
}
|
||||
|
||||
|
|
|
@ -842,6 +842,10 @@ MaybeWrapValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
|
|||
// GetWrapperPreserveColor() which can return its existing wrapper, if any, and
|
||||
// a WrapObject() which will try to create a wrapper. Typically, this is done by
|
||||
// having "value" inherit from nsWrapperCache.
|
||||
//
|
||||
// The value stored in rval will be ready to be exposed to whatever JS
|
||||
// is running on cx right now. In particular, it will be in the
|
||||
// compartment of cx, and outerized as needed.
|
||||
template <class T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
WrapNewBindingObject(JSContext* cx, T* value, JS::MutableHandle<JS::Value> rval)
|
||||
|
|
|
@ -6,23 +6,37 @@
|
|||
#include "Principal.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
JSPrincipals*
|
||||
GetWorkerPrincipal()
|
||||
{
|
||||
static Atomic<bool> sInitialized(false);
|
||||
static JSPrincipals sPrincipal;
|
||||
|
||||
bool isInitialized = sInitialized.exchange(true);
|
||||
if (!isInitialized) {
|
||||
sPrincipal.refcount = 1;
|
||||
/*
|
||||
* To make sure the the principals refcount is initialized to one, atomically
|
||||
* increment it on every pass though this function. If we discover this wasn't
|
||||
* the first time, decrement it again. This avoids the need for
|
||||
* synchronization.
|
||||
*/
|
||||
int32_t prevRefcount = sPrincipal.refcount++;
|
||||
if (prevRefcount > 0) {
|
||||
--sPrincipal.refcount;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
sPrincipal.debugToken = kJSPrincipalsDebugToken;
|
||||
#endif
|
||||
}
|
||||
|
||||
return &sPrincipal;
|
||||
}
|
||||
|
||||
void
|
||||
DestroyWorkerPrincipals(JSPrincipals* aPrincipals)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Worker principals refcount should never fall below one");
|
||||
}
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
|
|
@ -13,6 +13,9 @@ BEGIN_WORKERS_NAMESPACE
|
|||
JSPrincipals*
|
||||
GetWorkerPrincipal();
|
||||
|
||||
void
|
||||
DestroyWorkerPrincipals(JSPrincipals* aPrincipals);
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_workers_principal_h__ */
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "nsThreadManager.h"
|
||||
#endif
|
||||
|
||||
#include "Principal.h"
|
||||
#include "ServiceWorker.h"
|
||||
#include "SharedWorker.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
@ -852,6 +853,7 @@ public:
|
|||
WORKER_DEFAULT_NURSERY_SIZE),
|
||||
mWorkerPrivate(aWorkerPrivate)
|
||||
{
|
||||
JS_InitDestroyPrincipalsCallback(Runtime(), DestroyWorkerPrincipals);
|
||||
}
|
||||
|
||||
~WorkerJSRuntime()
|
||||
|
|
|
@ -351,9 +351,10 @@ ConvertOmxYUVFormatToRGB565(android::sp<GraphicBuffer>& aBuffer,
|
|||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
uint32_t pixelStride = aMappedSurface->mStride/gfx::BytesPerPixel(gfx::SurfaceFormat::R5G6B5);
|
||||
rv = colorConverter.convert(buffer, width, height,
|
||||
0, 0, width - 1, height - 1 /* source crop */,
|
||||
aMappedSurface->mData, width, height,
|
||||
aMappedSurface->mData, pixelStride, height,
|
||||
0, 0, width - 1, height - 1 /* dest crop */);
|
||||
if (rv) {
|
||||
NS_WARNING("OMX color conversion failed");
|
||||
|
|
|
@ -31,7 +31,7 @@ static inline float sk_float_pow(float base, float exp) {
|
|||
|
||||
static inline float sk_float_copysign(float x, float y) {
|
||||
// c++11 contains a 'float copysign(float, float)' function in <cmath>.
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#if (!defined(_MSC_VER) && __cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
return copysign(x, y);
|
||||
|
||||
// Posix has demanded 'float copysignf(float, float)' (from C99) since Issue 6.
|
||||
|
|
|
@ -438,7 +438,7 @@ ComputeColorMatrix(uint32_t aColorMatrixType, const nsTArray<float>& aValues,
|
|||
|
||||
aOutMatrix[5] = lumR - lumR * c + hueRotateR * s;
|
||||
aOutMatrix[6] = lumG + oneMinusLumG * c + hueRotateG * s;
|
||||
aOutMatrix[7] = lumB - oneMinusLumB * c - hueRotateB * s;
|
||||
aOutMatrix[7] = lumB - lumB * c - hueRotateB * s;
|
||||
|
||||
aOutMatrix[10] = lumR - lumR * c - oneMinusLumR * s;
|
||||
aOutMatrix[11] = lumG - lumG * c + lumG * s;
|
||||
|
|
|
@ -586,20 +586,13 @@ gfxContext::PixelSnappedRectangleAndSetPattern(const gfxRect& rect,
|
|||
void
|
||||
gfxContext::SetAntialiasMode(AntialiasMode mode)
|
||||
{
|
||||
if (mode == MODE_ALIASED) {
|
||||
CurrentState().aaMode = gfx::AntialiasMode::NONE;
|
||||
} else if (mode == MODE_COVERAGE) {
|
||||
CurrentState().aaMode = gfx::AntialiasMode::SUBPIXEL;
|
||||
}
|
||||
CurrentState().aaMode = mode;
|
||||
}
|
||||
|
||||
gfxContext::AntialiasMode
|
||||
AntialiasMode
|
||||
gfxContext::CurrentAntialiasMode() const
|
||||
{
|
||||
if (CurrentState().aaMode == gfx::AntialiasMode::NONE) {
|
||||
return MODE_ALIASED;
|
||||
}
|
||||
return MODE_COVERAGE;
|
||||
return CurrentState().aaMode;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -529,17 +529,8 @@ public:
|
|||
void SetOperator(GraphicsOperator op);
|
||||
GraphicsOperator CurrentOperator() const;
|
||||
|
||||
/**
|
||||
* MODE_ALIASED means that only pixels whose centers are in the drawn area
|
||||
* should be modified, and they should be modified to take the value drawn
|
||||
* at the pixel center.
|
||||
*/
|
||||
enum AntialiasMode {
|
||||
MODE_ALIASED,
|
||||
MODE_COVERAGE
|
||||
};
|
||||
void SetAntialiasMode(AntialiasMode mode);
|
||||
AntialiasMode CurrentAntialiasMode() const;
|
||||
void SetAntialiasMode(mozilla::gfx::AntialiasMode mode);
|
||||
mozilla::gfx::AntialiasMode CurrentAntialiasMode() const;
|
||||
|
||||
/**
|
||||
** Clipping
|
||||
|
|
|
@ -93,12 +93,10 @@ gfxSurfaceDrawable::DrawInternal(gfxContext* aContext,
|
|||
dt->ClearRect(fillRect);
|
||||
dt->FillRect(fillRect, pattern);
|
||||
} else {
|
||||
CompositionOp op = CompositionOpForOp(aContext->CurrentOperator());
|
||||
AntialiasMode aaMode =
|
||||
aContext->CurrentAntialiasMode() == gfxContext::MODE_ALIASED ?
|
||||
AntialiasMode::NONE :
|
||||
AntialiasMode::SUBPIXEL;
|
||||
dt->FillRect(fillRect, pattern, DrawOptions(aOpacity, op, aaMode));
|
||||
dt->FillRect(fillRect, pattern,
|
||||
DrawOptions(aOpacity,
|
||||
CompositionOpForOp(aContext->CurrentOperator()),
|
||||
aContext->CurrentAntialiasMode()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,12 +47,12 @@ gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
|
|||
}
|
||||
|
||||
// Azure
|
||||
gfxPattern::gfxPattern(SourceSurface *aSurface, const Matrix &aTransform)
|
||||
: mTransform(aTransform)
|
||||
gfxPattern::gfxPattern(SourceSurface *aSurface, const Matrix &aPatternToUserSpace)
|
||||
: mPatternToUserSpace(aPatternToUserSpace)
|
||||
, mExtend(EXTEND_NONE)
|
||||
{
|
||||
mGfxPattern = new (mSurfacePattern.addr())
|
||||
SurfacePattern(aSurface, ToExtendMode(mExtend), aTransform,
|
||||
SurfacePattern(aSurface, ToExtendMode(mExtend), Matrix(), // matrix is overridden in GetPattern()
|
||||
mozilla::gfx::Filter::GOOD);
|
||||
}
|
||||
|
||||
|
@ -100,13 +100,13 @@ gfxPattern::CacheColorStops(DrawTarget *aDT)
|
|||
}
|
||||
|
||||
void
|
||||
gfxPattern::SetMatrix(const gfxMatrix& matrix)
|
||||
gfxPattern::SetMatrix(const gfxMatrix& aPatternToUserSpace)
|
||||
{
|
||||
mTransform = ToMatrix(matrix);
|
||||
mPatternToUserSpace = ToMatrix(aPatternToUserSpace);
|
||||
// Cairo-pattern matrices specify the conversion from DrawTarget to pattern
|
||||
// space. Azure pattern matrices specify the conversion from pattern to
|
||||
// DrawTarget space.
|
||||
mTransform.Invert();
|
||||
mPatternToUserSpace.Invert();
|
||||
}
|
||||
|
||||
gfxMatrix
|
||||
|
@ -114,7 +114,7 @@ gfxPattern::GetMatrix() const
|
|||
{
|
||||
// invert at the higher precision of gfxMatrix
|
||||
// cause we need to convert at some point anyways
|
||||
gfxMatrix mat = ThebesMatrix(mTransform);
|
||||
gfxMatrix mat = ThebesMatrix(mPatternToUserSpace);
|
||||
mat.Invert();
|
||||
return mat;
|
||||
}
|
||||
|
@ -122,12 +122,33 @@ gfxPattern::GetMatrix() const
|
|||
gfxMatrix
|
||||
gfxPattern::GetInverseMatrix() const
|
||||
{
|
||||
return ThebesMatrix(mTransform);
|
||||
return ThebesMatrix(mPatternToUserSpace);
|
||||
}
|
||||
|
||||
Pattern*
|
||||
gfxPattern::GetPattern(DrawTarget *aTarget, Matrix *aPatternTransform)
|
||||
gfxPattern::GetPattern(DrawTarget *aTarget,
|
||||
Matrix *aOriginalUserToDevice)
|
||||
{
|
||||
Matrix patternToUser = mPatternToUserSpace;
|
||||
|
||||
if (aOriginalUserToDevice &&
|
||||
*aOriginalUserToDevice != aTarget->GetTransform()) {
|
||||
// mPatternToUserSpace maps from pattern space to the original user space,
|
||||
// but aTarget now has a transform to a different user space. In order for
|
||||
// the Pattern* that we return to be usable in aTarget's new user space we
|
||||
// need the Pattern's mMatrix to be the transform from pattern space to
|
||||
// aTarget's -new- user space. That transform is equivalent to the
|
||||
// transform from pattern space to original user space (patternToUser),
|
||||
// multiplied by the transform from original user space to device space,
|
||||
// multiplied by the transform from device space to current user space.
|
||||
|
||||
Matrix deviceToCurrentUser = aTarget->GetTransform();
|
||||
deviceToCurrentUser.Invert();
|
||||
|
||||
patternToUser = patternToUser * *aOriginalUserToDevice * deviceToCurrentUser;
|
||||
}
|
||||
patternToUser.NudgeToIntegers();
|
||||
|
||||
if (!mStops &&
|
||||
!mStopsList.IsEmpty()) {
|
||||
mStops = aTarget->CreateGradientStops(mStopsList.Elements(),
|
||||
|
@ -135,18 +156,17 @@ gfxPattern::GetPattern(DrawTarget *aTarget, Matrix *aPatternTransform)
|
|||
ToExtendMode(mExtend));
|
||||
}
|
||||
|
||||
Matrix* matrix = nullptr;
|
||||
switch (mGfxPattern->GetType()) {
|
||||
case PatternType::SURFACE:
|
||||
matrix = &mSurfacePattern.addr()->mMatrix;
|
||||
mSurfacePattern.addr()->mMatrix = patternToUser;
|
||||
mSurfacePattern.addr()->mExtendMode = ToExtendMode(mExtend);
|
||||
break;
|
||||
case PatternType::LINEAR_GRADIENT:
|
||||
matrix = &mLinearGradientPattern.addr()->mMatrix;
|
||||
mLinearGradientPattern.addr()->mMatrix = patternToUser;
|
||||
mLinearGradientPattern.addr()->mStops = mStops;
|
||||
break;
|
||||
case PatternType::RADIAL_GRADIENT:
|
||||
matrix = &mRadialGradientPattern.addr()->mMatrix;
|
||||
mRadialGradientPattern.addr()->mMatrix = patternToUser;
|
||||
mRadialGradientPattern.addr()->mStops = mStops;
|
||||
break;
|
||||
default:
|
||||
|
@ -154,15 +174,6 @@ gfxPattern::GetPattern(DrawTarget *aTarget, Matrix *aPatternTransform)
|
|||
break;
|
||||
}
|
||||
|
||||
if (matrix) {
|
||||
*matrix = mTransform;
|
||||
if (aPatternTransform) {
|
||||
AdjustTransformForPattern(*matrix,
|
||||
aTarget->GetTransform(),
|
||||
aPatternTransform);
|
||||
}
|
||||
}
|
||||
|
||||
return mGfxPattern;
|
||||
}
|
||||
|
||||
|
@ -233,29 +244,3 @@ gfxPattern::CairoStatus()
|
|||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPattern::AdjustTransformForPattern(Matrix &aPatternTransform,
|
||||
const Matrix &aCurrentTransform,
|
||||
const Matrix *aOriginalTransform)
|
||||
{
|
||||
aPatternTransform.Invert();
|
||||
if (!aOriginalTransform) {
|
||||
// User space is unchanged, so to get from pattern space to user space,
|
||||
// just invert the cairo matrix.
|
||||
aPatternTransform.NudgeToIntegers();
|
||||
return;
|
||||
}
|
||||
// aPatternTransform now maps from pattern space to the user space defined
|
||||
// by *aOriginalTransform.
|
||||
|
||||
Matrix mat = aCurrentTransform;
|
||||
mat.Invert();
|
||||
// mat maps from device space to current user space
|
||||
|
||||
// First, transform from pattern space to original user space. Then transform
|
||||
// from original user space to device space. Then transform from
|
||||
// device space to current user space.
|
||||
aPatternTransform = aPatternTransform * *aOriginalTransform * mat;
|
||||
aPatternTransform.NudgeToIntegers();
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
|
||||
gfxFloat cx1, gfxFloat cy1, gfxFloat radius1); // radial
|
||||
gfxPattern(mozilla::gfx::SourceSurface *aSurface,
|
||||
const mozilla::gfx::Matrix &aTransform); // Azure
|
||||
const mozilla::gfx::Matrix &aPatternToUserSpace);
|
||||
|
||||
void AddColorStop(gfxFloat offset, const gfxRGBA& c);
|
||||
void SetColorStops(mozilla::gfx::GradientStops* aStops);
|
||||
|
@ -52,7 +52,7 @@ public:
|
|||
* to the current transform.
|
||||
*/
|
||||
mozilla::gfx::Pattern *GetPattern(mozilla::gfx::DrawTarget *aTarget,
|
||||
mozilla::gfx::Matrix *aPatternTransform = nullptr);
|
||||
mozilla::gfx::Matrix *aOriginalUserToDevice = nullptr);
|
||||
bool IsOpaque();
|
||||
|
||||
enum GraphicsExtend {
|
||||
|
@ -97,21 +97,6 @@ private:
|
|||
// Private destructor, to discourage deletion outside of Release():
|
||||
~gfxPattern();
|
||||
|
||||
/**
|
||||
* aPatternTransform is the cairo pattern transform --- from user space at
|
||||
* the time the pattern was set, to pattern space.
|
||||
* aCurrentTransform is the DrawTarget's CTM --- from user space to device
|
||||
* space.
|
||||
* aOriginalTransform, if non-null, is the DrawTarget's TM when
|
||||
* aPatternTransform was set --- user space to device space. If null, then
|
||||
* the DrawTarget's CTM is the same as the TM when aPatternTransfrom was set.
|
||||
* This function sets aPatternTransform to the Azure pattern transform ---
|
||||
* from pattern space to current DrawTarget user space.
|
||||
*/
|
||||
void AdjustTransformForPattern(mozilla::gfx::Matrix &aPatternTransform,
|
||||
const mozilla::gfx::Matrix &aCurrentTransform,
|
||||
const mozilla::gfx::Matrix *aOriginalTransform);
|
||||
|
||||
union {
|
||||
mozilla::AlignedStorage2<mozilla::gfx::ColorPattern> mColorPattern;
|
||||
mozilla::AlignedStorage2<mozilla::gfx::LinearGradientPattern> mLinearGradientPattern;
|
||||
|
@ -122,7 +107,7 @@ private:
|
|||
mozilla::gfx::Pattern *mGfxPattern;
|
||||
|
||||
mozilla::RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
|
||||
mozilla::gfx::Matrix mTransform;
|
||||
mozilla::gfx::Matrix mPatternToUserSpace;
|
||||
mozilla::RefPtr<mozilla::gfx::GradientStops> mStops;
|
||||
nsTArray<mozilla::gfx::GradientStop> mStopsList;
|
||||
GraphicsExtend mExtend;
|
||||
|
|
|
@ -90,7 +90,7 @@ of values.
|
|||
nsIUGenCategory::nsUGenCategory sDetailedToGeneralCategory[] = {
|
||||
/*
|
||||
* The order here corresponds to the HB_UNICODE_GENERAL_CATEGORY_* constants
|
||||
* of the hb_unicode_general_category_t enum in gfx/harfbuzz/src/hb-common.h.
|
||||
* of the hb_unicode_general_category_t enum in gfx/harfbuzz/src/hb-unicode.h.
|
||||
*/
|
||||
/* CONTROL */ nsIUGenCategory::kOther,
|
||||
/* FORMAT */ nsIUGenCategory::kOther,
|
||||
|
|
|
@ -24,6 +24,8 @@ struct JSPrincipals {
|
|||
uint32_t debugToken;
|
||||
#endif
|
||||
|
||||
JSPrincipals() : refcount(0) {}
|
||||
|
||||
void setDebugToken(uint32_t token) {
|
||||
# ifdef JS_DEBUG
|
||||
debugToken = token;
|
||||
|
|
|
@ -426,6 +426,29 @@ class Type
|
|||
bool operator==(Type rhs) const { return which_ == rhs.which_; }
|
||||
bool operator!=(Type rhs) const { return which_ != rhs.which_; }
|
||||
|
||||
inline bool operator<=(Type rhs) const {
|
||||
switch (rhs.which_) {
|
||||
case Type::Signed: return isSigned();
|
||||
case Type::Unsigned: return isUnsigned();
|
||||
case Type::Double: return isDouble();
|
||||
case Type::Float: return isFloat();
|
||||
case Type::Int32x4: return isInt32x4();
|
||||
case Type::Float32x4: return isFloat32x4();
|
||||
case Type::MaybeDouble: return isMaybeDouble();
|
||||
case Type::MaybeFloat: return isMaybeFloat();
|
||||
case Type::Floatish: return isFloatish();
|
||||
case Type::Int: return isInt();
|
||||
case Type::Intish: return isIntish();
|
||||
case Type::Fixnum: return isFixnum();
|
||||
case Type::Void: return isVoid();
|
||||
}
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("unexpected this type");
|
||||
}
|
||||
|
||||
bool isFixnum() const {
|
||||
return which_ == Fixnum;
|
||||
}
|
||||
|
||||
bool isSigned() const {
|
||||
return which_ == Signed || which_ == Fixnum;
|
||||
}
|
||||
|
@ -535,6 +558,30 @@ class Type
|
|||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Invalid SIMD Type");
|
||||
}
|
||||
|
||||
Type simdToCoercedScalarType() const {
|
||||
JS_ASSERT(isSimd());
|
||||
switch (which_) {
|
||||
case Int32x4:
|
||||
return Intish;
|
||||
case Float32x4:
|
||||
return Floatish;
|
||||
// Scalar types
|
||||
case Double:
|
||||
case MaybeDouble:
|
||||
case Float:
|
||||
case MaybeFloat:
|
||||
case Floatish:
|
||||
case Fixnum:
|
||||
case Int:
|
||||
case Signed:
|
||||
case Unsigned:
|
||||
case Intish:
|
||||
case Void:
|
||||
break;
|
||||
}
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Invalid SIMD Type");
|
||||
}
|
||||
|
||||
AsmJSSimdType simdToSimdType() const {
|
||||
JS_ASSERT(isSimd());
|
||||
switch (which_) {
|
||||
|
@ -2444,6 +2491,17 @@ class FunctionCompiler
|
|||
return ins;
|
||||
}
|
||||
|
||||
MDefinition *splatSimd(MDefinition *v, MIRType type)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
JS_ASSERT(IsSimdType(type));
|
||||
MSimdSplatX4 *ins = MSimdSplatX4::New(alloc(), type, v);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
||||
MDefinition *minMax(MDefinition *lhs, MDefinition *rhs, MIRType type, bool isMax) {
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
@ -2620,18 +2678,6 @@ class FunctionCompiler
|
|||
return ins;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MDefinition *simdSplat(MDefinition *v, MIRType type)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
JS_ASSERT(IsSimdType(type));
|
||||
T *ins = T::New(alloc(), type, v);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
||||
/***************************************************************** Calls */
|
||||
|
||||
// The IonMonkey backend maintains a single stack offset (from the stack
|
||||
|
@ -4696,161 +4742,127 @@ CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltinF
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef Vector<MDefinition*, 4, SystemAllocPolicy> DefinitionVector;
|
||||
|
||||
namespace {
|
||||
|
||||
template<class CheckArgOp>
|
||||
static bool
|
||||
CheckUnarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
|
||||
MDefinition **def, Type *type)
|
||||
CheckSimdCallArgs(FunctionCompiler &f, ParseNode *call, unsigned expectedArity,
|
||||
const CheckArgOp &checkArg, DefinitionVector *defs)
|
||||
{
|
||||
unsigned numArgs = CallArgListLength(call);
|
||||
if (numArgs != 1)
|
||||
return f.failf(call, "expected 1 argument to unary arithmetic SIMD operation, got %u", numArgs);
|
||||
if (numArgs != expectedArity)
|
||||
return f.failf(call, "expected %u arguments to SIMD call, got %u", expectedArity, numArgs);
|
||||
|
||||
DefinitionVector &argDefs = *defs;
|
||||
if (!argDefs.resize(numArgs))
|
||||
return false;
|
||||
|
||||
ParseNode *arg = CallArgList(call);
|
||||
MDefinition *argDef;
|
||||
for (size_t i = 0; i < numArgs; i++, arg = NextNode(arg)) {
|
||||
MOZ_ASSERT(!!arg);
|
||||
|
||||
Type argType;
|
||||
if (!CheckExpr(f, arg, &argDef, &argType))
|
||||
if (!CheckExpr(f, arg, &argDefs[i], &argType))
|
||||
return false;
|
||||
|
||||
// For now, the only unary SIMD operation is splat(scalar).
|
||||
MOZ_ASSERT(global->simdOperation() == AsmJSSimdOperation_splat);
|
||||
switch (global->simdOperationType()) {
|
||||
case AsmJSSimdType_int32x4:
|
||||
if (!argType.isIntish())
|
||||
return f.failf(arg, "%s is not a subtype of intish", argType.toChars());
|
||||
break;
|
||||
case AsmJSSimdType_float32x4:
|
||||
if (!CheckFloatCoercionArg(f, arg, argType, argDef, &argDef))
|
||||
if (!checkArg(f, arg, i, argType, &argDefs[i]))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
*type = global->simdOperationType();
|
||||
*def = f.simdSplat<MSimdSplatX4>(argDef, type->toMIRType());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckBinarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
|
||||
MDefinition **def, Type *type)
|
||||
{
|
||||
unsigned numArgs = CallArgListLength(call);
|
||||
if (numArgs != 2)
|
||||
return f.failf(call, "expected 2 arguments to binary arithmetic SIMD operation, got %u", numArgs);
|
||||
|
||||
ParseNode *lhs = CallArgList(call);
|
||||
ParseNode *rhs = NextNode(lhs);
|
||||
|
||||
MDefinition *lhsDef, *rhsDef;
|
||||
Type lhsType, rhsType;
|
||||
if (!CheckExpr(f, lhs, &lhsDef, &lhsType))
|
||||
return false;
|
||||
if (!CheckExpr(f, rhs, &rhsDef, &rhsType))
|
||||
return false;
|
||||
|
||||
Type retType = global->simdOperationType();
|
||||
if (lhsType != retType || rhsType != retType)
|
||||
return f.failf(lhs, "arguments to SIMD binary op should both be %s", retType.toChars());
|
||||
|
||||
MIRType opType = retType.toMIRType();
|
||||
switch (global->simdOperation()) {
|
||||
case AsmJSSimdOperation_add:
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryArith::Add, opType);
|
||||
*type = retType;
|
||||
break;
|
||||
case AsmJSSimdOperation_sub:
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryArith::Sub, opType);
|
||||
*type = retType;
|
||||
break;
|
||||
case AsmJSSimdOperation_mul:
|
||||
JS_ASSERT(!retType.isInt32x4());
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryArith::Mul, opType);
|
||||
*type = retType;
|
||||
break;
|
||||
case AsmJSSimdOperation_div:
|
||||
JS_ASSERT(!retType.isInt32x4());
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryArith::Div, opType);
|
||||
*type = retType;
|
||||
break;
|
||||
case AsmJSSimdOperation_lessThan:
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::lessThan);
|
||||
*type = Type::Int32x4;
|
||||
break;
|
||||
case AsmJSSimdOperation_lessThanOrEqual:
|
||||
JS_ASSERT(!retType.isInt32x4());
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::lessThanOrEqual);
|
||||
*type = Type::Int32x4;
|
||||
break;
|
||||
case AsmJSSimdOperation_equal:
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::equal);
|
||||
*type = Type::Int32x4;
|
||||
break;
|
||||
case AsmJSSimdOperation_notEqual:
|
||||
JS_ASSERT(!retType.isInt32x4());
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::notEqual);
|
||||
*type = Type::Int32x4;
|
||||
break;
|
||||
case AsmJSSimdOperation_greaterThan:
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::greaterThan);
|
||||
*type = Type::Int32x4;
|
||||
break;
|
||||
case AsmJSSimdOperation_greaterThanOrEqual:
|
||||
JS_ASSERT(!retType.isInt32x4());
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::greaterThanOrEqual);
|
||||
*type = Type::Int32x4;
|
||||
break;
|
||||
case AsmJSSimdOperation_and:
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::and_, opType);
|
||||
*type = retType;
|
||||
break;
|
||||
case AsmJSSimdOperation_or:
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::or_, opType);
|
||||
*type = retType;
|
||||
break;
|
||||
case AsmJSSimdOperation_xor:
|
||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::xor_, opType);
|
||||
*type = retType;
|
||||
break;
|
||||
case AsmJSSimdOperation_splat:
|
||||
case AsmJSSimdOperation_select:
|
||||
MOZ_CRASH("unexpected SIMD binary operation");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckSimdSelect(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
|
||||
MDefinition **def, Type *type)
|
||||
class CheckSimdScalarArgs
|
||||
{
|
||||
MOZ_ASSERT(global->simdOperation() == AsmJSSimdOperation_select);
|
||||
Type formalType_;
|
||||
|
||||
unsigned numArgs = CallArgListLength(call);
|
||||
if (numArgs != 3)
|
||||
return f.failf(call, "expected 3 arguments to ternary SIMD operation, got %u", numArgs);
|
||||
public:
|
||||
explicit CheckSimdScalarArgs(Type t) : formalType_(t.simdToCoercedScalarType()) {}
|
||||
|
||||
ParseNode *mask = CallArgList(call);
|
||||
ParseNode *lhs = NextNode(mask);
|
||||
ParseNode *rhs = NextNode(lhs);
|
||||
bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
|
||||
MDefinition **argDef) const
|
||||
{
|
||||
if (formalType_ == Type::Floatish)
|
||||
return CheckFloatCoercionArg(f, arg, actualType, *argDef, argDef);
|
||||
|
||||
MDefinition *maskDef;
|
||||
Type maskType;
|
||||
if (!CheckExpr(f, mask, &maskDef, &maskType))
|
||||
if (!(actualType <= formalType_)) {
|
||||
return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
|
||||
formalType_.toChars());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CheckSimdVectorArgs
|
||||
{
|
||||
Type formalType_;
|
||||
|
||||
public:
|
||||
explicit CheckSimdVectorArgs(Type t) : formalType_(t) {}
|
||||
|
||||
bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
|
||||
MDefinition **argDef) const
|
||||
{
|
||||
if (!(actualType <= formalType_)) {
|
||||
return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
|
||||
formalType_.toChars());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CheckSimdSelectArgs
|
||||
{
|
||||
Type formalType_;
|
||||
|
||||
public:
|
||||
explicit CheckSimdSelectArgs(Type t) : formalType_(t) {}
|
||||
|
||||
bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
|
||||
MDefinition **argDef) const
|
||||
{
|
||||
if (argIndex == 0) {
|
||||
// First argument of select is an int32x4 mask.
|
||||
if (!(actualType <= Type::Int32x4))
|
||||
return f.failf(arg, "%s is not a subtype of Int32x4", actualType.toChars());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(actualType <= formalType_)) {
|
||||
return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
|
||||
formalType_.toChars());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
template<class OpEnum>
|
||||
static inline bool
|
||||
CheckSimdBinary(FunctionCompiler &f, ParseNode *call, Type retType, OpEnum op, MDefinition **def,
|
||||
Type *type)
|
||||
{
|
||||
DefinitionVector argDefs;
|
||||
if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorArgs(retType), &argDefs))
|
||||
return false;
|
||||
if (maskType != Type::Int32x4)
|
||||
return f.failf(mask, "%s is not a subtype of int32x4", maskType.toChars());
|
||||
|
||||
MDefinition *lhsDef, *rhsDef;
|
||||
Type lhsType, rhsType;
|
||||
if (!CheckExpr(f, lhs, &lhsDef, &lhsType))
|
||||
return false;
|
||||
if (!CheckExpr(f, rhs, &rhsDef, &rhsType))
|
||||
return false;
|
||||
|
||||
Type retType = global->simdOperationType();
|
||||
if (lhsType != retType || rhsType != retType)
|
||||
return f.failf(mask, "last two arguments to SIMD ternary op should both be %s", retType.toChars());
|
||||
|
||||
*def = f.binarySimd(argDefs[0], argDefs[1], op, retType.toMIRType());
|
||||
*type = retType;
|
||||
*def = f.ternarySimd(maskDef, lhsDef, rhsDef, MSimdTernaryBitwise::select, retType.toMIRType());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool
|
||||
CheckSimdBinary<MSimdBinaryComp::Operation>(FunctionCompiler &f, ParseNode *call, Type retType,
|
||||
MSimdBinaryComp::Operation op, MDefinition **def,
|
||||
Type *type)
|
||||
{
|
||||
DefinitionVector argDefs;
|
||||
if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorArgs(retType), &argDefs))
|
||||
return false;
|
||||
*def = f.binarySimd(argDefs[0], argDefs[1], op);
|
||||
*type = Type::Int32x4;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4858,26 +4870,58 @@ static bool
|
|||
CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
|
||||
MDefinition **def, Type *type)
|
||||
{
|
||||
JS_ASSERT(global->isSimdOperation());
|
||||
MOZ_ASSERT(global->isSimdOperation());
|
||||
|
||||
Type retType = global->simdOperationType();
|
||||
|
||||
switch (global->simdOperation()) {
|
||||
case AsmJSSimdOperation_splat:
|
||||
return CheckUnarySimd(f, call, global, def, type);
|
||||
case AsmJSSimdOperation_add:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Add, def, type);
|
||||
case AsmJSSimdOperation_sub:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Sub, def, type);
|
||||
case AsmJSSimdOperation_mul:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Mul, def, type);
|
||||
case AsmJSSimdOperation_div:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Div, def, type);
|
||||
|
||||
case AsmJSSimdOperation_lessThan:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryComp::lessThan, def, type);
|
||||
case AsmJSSimdOperation_lessThanOrEqual:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryComp::lessThanOrEqual, def, type);
|
||||
case AsmJSSimdOperation_equal:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryComp::equal, def, type);
|
||||
case AsmJSSimdOperation_notEqual:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryComp::notEqual, def, type);
|
||||
case AsmJSSimdOperation_greaterThan:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryComp::greaterThan, def, type);
|
||||
case AsmJSSimdOperation_greaterThanOrEqual:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryComp::greaterThanOrEqual, def, type);
|
||||
|
||||
case AsmJSSimdOperation_and:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::and_, def, type);
|
||||
case AsmJSSimdOperation_or:
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::or_, def, type);
|
||||
case AsmJSSimdOperation_xor:
|
||||
return CheckBinarySimd(f, call, global, def, type);
|
||||
case AsmJSSimdOperation_select:
|
||||
return CheckSimdSelect(f, call, global, def, type);
|
||||
return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::xor_, def, type);
|
||||
|
||||
case AsmJSSimdOperation_splat: {
|
||||
DefinitionVector defs;
|
||||
if (!CheckSimdCallArgs(f, call, 1, CheckSimdScalarArgs(retType), &defs))
|
||||
return false;
|
||||
*def = f.splatSimd(defs[0], retType.toMIRType());
|
||||
*type = retType;
|
||||
return true;
|
||||
}
|
||||
|
||||
case AsmJSSimdOperation_select: {
|
||||
DefinitionVector defs;
|
||||
if (!CheckSimdCallArgs(f, call, 3, CheckSimdSelectArgs(retType), &defs))
|
||||
return false;
|
||||
*def = f.ternarySimd(defs[0], defs[1], defs[2], MSimdTernaryBitwise::select,
|
||||
retType.toMIRType());
|
||||
*type = retType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
MOZ_CRASH("unexpected simd operation in CheckSimdOperationCall");
|
||||
}
|
||||
|
@ -4894,44 +4938,22 @@ CheckSimdCtorCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Gl
|
|||
return CheckCoercionArg(f, argNode, coercion, def, type);
|
||||
|
||||
AsmJSSimdType simdType = global->simdCtorType();
|
||||
unsigned numArgs = CallArgListLength(call);
|
||||
unsigned length = SimdTypeToLength(simdType);
|
||||
if (numArgs != length)
|
||||
return f.failName(call, "invalid number of arguments in call to '%s'", CallCallee(call)->name());
|
||||
Type retType = simdType;
|
||||
|
||||
Vector<MDefinition*, 4, SystemAllocPolicy> defs;
|
||||
if (!defs.resize(length))
|
||||
DefinitionVector defs;
|
||||
if (!CheckSimdCallArgs(f, call, length, CheckSimdScalarArgs(retType), &defs))
|
||||
return false;
|
||||
|
||||
argNode = CallArgList(call);
|
||||
size_t i = 0;
|
||||
for (; argNode; argNode = NextNode(argNode), ++i)
|
||||
{
|
||||
JS_ASSERT(i < length);
|
||||
|
||||
Type argType;
|
||||
if (!CheckExpr(f, argNode, &defs[i], &argType))
|
||||
return false;
|
||||
|
||||
switch (simdType) {
|
||||
case AsmJSSimdType_int32x4:
|
||||
if (!argType.isIntish())
|
||||
return f.failf(argNode, "argument %d of Int32x4 ctor isn't a subtype of intish", i);
|
||||
break;
|
||||
case AsmJSSimdType_float32x4:
|
||||
if (!CheckFloatCoercionArg(f, argNode, argType, defs[i], &defs[i]))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(i == length);
|
||||
|
||||
*type = simdType;
|
||||
// This code will need to be generalized when we handle float64x2
|
||||
MOZ_ASSERT(length == 4);
|
||||
|
||||
MIRType opType = retType.toMIRType();
|
||||
if (defs[1] == defs[0] && defs[2] == defs[0] && defs[3] == defs[0])
|
||||
*def = f.simdSplat<MSimdSplatX4>(defs[0], type->toMIRType());
|
||||
*def = f.splatSimd(defs[0], opType);
|
||||
else
|
||||
*def = f.constructSimd<MSimdValueX4>(defs[0], defs[1], defs[2], defs[3], type->toMIRType());
|
||||
*def = f.constructSimd<MSimdValueX4>(defs[0], defs[1], defs[2], defs[3], opType);
|
||||
*type = retType;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "builtin/SIMDShuffleMaskConstants.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "js/Value.h"
|
||||
|
||||
|
@ -372,6 +371,270 @@ const Class SIMDObject::class_ = {
|
|||
nullptr
|
||||
};
|
||||
|
||||
static JSConstIntegerSpec SHUFFLE_MASKS[] = {
|
||||
{"XXXX", 0x0},
|
||||
{"XXXY", 0x40},
|
||||
{"XXXZ", 0x80},
|
||||
{"XXXW", 0xC0},
|
||||
{"XXYX", 0x10},
|
||||
{"XXYY", 0x50},
|
||||
{"XXYZ", 0x90},
|
||||
{"XXYW", 0xD0},
|
||||
{"XXZX", 0x20},
|
||||
{"XXZY", 0x60},
|
||||
{"XXZZ", 0xA0},
|
||||
{"XXZW", 0xE0},
|
||||
{"XXWX", 0x30},
|
||||
{"XXWY", 0x70},
|
||||
{"XXWZ", 0xB0},
|
||||
{"XXWW", 0xF0},
|
||||
{"XYXX", 0x4},
|
||||
{"XYXY", 0x44},
|
||||
{"XYXZ", 0x84},
|
||||
{"XYXW", 0xC4},
|
||||
{"XYYX", 0x14},
|
||||
{"XYYY", 0x54},
|
||||
{"XYYZ", 0x94},
|
||||
{"XYYW", 0xD4},
|
||||
{"XYZX", 0x24},
|
||||
{"XYZY", 0x64},
|
||||
{"XYZZ", 0xA4},
|
||||
{"XYZW", 0xE4},
|
||||
{"XYWX", 0x34},
|
||||
{"XYWY", 0x74},
|
||||
{"XYWZ", 0xB4},
|
||||
{"XYWW", 0xF4},
|
||||
{"XZXX", 0x8},
|
||||
{"XZXY", 0x48},
|
||||
{"XZXZ", 0x88},
|
||||
{"XZXW", 0xC8},
|
||||
{"XZYX", 0x18},
|
||||
{"XZYY", 0x58},
|
||||
{"XZYZ", 0x98},
|
||||
{"XZYW", 0xD8},
|
||||
{"XZZX", 0x28},
|
||||
{"XZZY", 0x68},
|
||||
{"XZZZ", 0xA8},
|
||||
{"XZZW", 0xE8},
|
||||
{"XZWX", 0x38},
|
||||
{"XZWY", 0x78},
|
||||
{"XZWZ", 0xB8},
|
||||
{"XZWW", 0xF8},
|
||||
{"XWXX", 0xC},
|
||||
{"XWXY", 0x4C},
|
||||
{"XWXZ", 0x8C},
|
||||
{"XWXW", 0xCC},
|
||||
{"XWYX", 0x1C},
|
||||
{"XWYY", 0x5C},
|
||||
{"XWYZ", 0x9C},
|
||||
{"XWYW", 0xDC},
|
||||
{"XWZX", 0x2C},
|
||||
{"XWZY", 0x6C},
|
||||
{"XWZZ", 0xAC},
|
||||
{"XWZW", 0xEC},
|
||||
{"XWWX", 0x3C},
|
||||
{"XWWY", 0x7C},
|
||||
{"XWWZ", 0xBC},
|
||||
{"XWWW", 0xFC},
|
||||
{"YXXX", 0x1},
|
||||
{"YXXY", 0x41},
|
||||
{"YXXZ", 0x81},
|
||||
{"YXXW", 0xC1},
|
||||
{"YXYX", 0x11},
|
||||
{"YXYY", 0x51},
|
||||
{"YXYZ", 0x91},
|
||||
{"YXYW", 0xD1},
|
||||
{"YXZX", 0x21},
|
||||
{"YXZY", 0x61},
|
||||
{"YXZZ", 0xA1},
|
||||
{"YXZW", 0xE1},
|
||||
{"YXWX", 0x31},
|
||||
{"YXWY", 0x71},
|
||||
{"YXWZ", 0xB1},
|
||||
{"YXWW", 0xF1},
|
||||
{"YYXX", 0x5},
|
||||
{"YYXY", 0x45},
|
||||
{"YYXZ", 0x85},
|
||||
{"YYXW", 0xC5},
|
||||
{"YYYX", 0x15},
|
||||
{"YYYY", 0x55},
|
||||
{"YYYZ", 0x95},
|
||||
{"YYYW", 0xD5},
|
||||
{"YYZX", 0x25},
|
||||
{"YYZY", 0x65},
|
||||
{"YYZZ", 0xA5},
|
||||
{"YYZW", 0xE5},
|
||||
{"YYWX", 0x35},
|
||||
{"YYWY", 0x75},
|
||||
{"YYWZ", 0xB5},
|
||||
{"YYWW", 0xF5},
|
||||
{"YZXX", 0x9},
|
||||
{"YZXY", 0x49},
|
||||
{"YZXZ", 0x89},
|
||||
{"YZXW", 0xC9},
|
||||
{"YZYX", 0x19},
|
||||
{"YZYY", 0x59},
|
||||
{"YZYZ", 0x99},
|
||||
{"YZYW", 0xD9},
|
||||
{"YZZX", 0x29},
|
||||
{"YZZY", 0x69},
|
||||
{"YZZZ", 0xA9},
|
||||
{"YZZW", 0xE9},
|
||||
{"YZWX", 0x39},
|
||||
{"YZWY", 0x79},
|
||||
{"YZWZ", 0xB9},
|
||||
{"YZWW", 0xF9},
|
||||
{"YWXX", 0xD},
|
||||
{"YWXY", 0x4D},
|
||||
{"YWXZ", 0x8D},
|
||||
{"YWXW", 0xCD},
|
||||
{"YWYX", 0x1D},
|
||||
{"YWYY", 0x5D},
|
||||
{"YWYZ", 0x9D},
|
||||
{"YWYW", 0xDD},
|
||||
{"YWZX", 0x2D},
|
||||
{"YWZY", 0x6D},
|
||||
{"YWZZ", 0xAD},
|
||||
{"YWZW", 0xED},
|
||||
{"YWWX", 0x3D},
|
||||
{"YWWY", 0x7D},
|
||||
{"YWWZ", 0xBD},
|
||||
{"YWWW", 0xFD},
|
||||
{"ZXXX", 0x2},
|
||||
{"ZXXY", 0x42},
|
||||
{"ZXXZ", 0x82},
|
||||
{"ZXXW", 0xC2},
|
||||
{"ZXYX", 0x12},
|
||||
{"ZXYY", 0x52},
|
||||
{"ZXYZ", 0x92},
|
||||
{"ZXYW", 0xD2},
|
||||
{"ZXZX", 0x22},
|
||||
{"ZXZY", 0x62},
|
||||
{"ZXZZ", 0xA2},
|
||||
{"ZXZW", 0xE2},
|
||||
{"ZXWX", 0x32},
|
||||
{"ZXWY", 0x72},
|
||||
{"ZXWZ", 0xB2},
|
||||
{"ZXWW", 0xF2},
|
||||
{"ZYXX", 0x6},
|
||||
{"ZYXY", 0x46},
|
||||
{"ZYXZ", 0x86},
|
||||
{"ZYXW", 0xC6},
|
||||
{"ZYYX", 0x16},
|
||||
{"ZYYY", 0x56},
|
||||
{"ZYYZ", 0x96},
|
||||
{"ZYYW", 0xD6},
|
||||
{"ZYZX", 0x26},
|
||||
{"ZYZY", 0x66},
|
||||
{"ZYZZ", 0xA6},
|
||||
{"ZYZW", 0xE6},
|
||||
{"ZYWX", 0x36},
|
||||
{"ZYWY", 0x76},
|
||||
{"ZYWZ", 0xB6},
|
||||
{"ZYWW", 0xF6},
|
||||
{"ZZXX", 0xA},
|
||||
{"ZZXY", 0x4A},
|
||||
{"ZZXZ", 0x8A},
|
||||
{"ZZXW", 0xCA},
|
||||
{"ZZYX", 0x1A},
|
||||
{"ZZYY", 0x5A},
|
||||
{"ZZYZ", 0x9A},
|
||||
{"ZZYW", 0xDA},
|
||||
{"ZZZX", 0x2A},
|
||||
{"ZZZY", 0x6A},
|
||||
{"ZZZZ", 0xAA},
|
||||
{"ZZZW", 0xEA},
|
||||
{"ZZWX", 0x3A},
|
||||
{"ZZWY", 0x7A},
|
||||
{"ZZWZ", 0xBA},
|
||||
{"ZZWW", 0xFA},
|
||||
{"ZWXX", 0xE},
|
||||
{"ZWXY", 0x4E},
|
||||
{"ZWXZ", 0x8E},
|
||||
{"ZWXW", 0xCE},
|
||||
{"ZWYX", 0x1E},
|
||||
{"ZWYY", 0x5E},
|
||||
{"ZWYZ", 0x9E},
|
||||
{"ZWYW", 0xDE},
|
||||
{"ZWZX", 0x2E},
|
||||
{"ZWZY", 0x6E},
|
||||
{"ZWZZ", 0xAE},
|
||||
{"ZWZW", 0xEE},
|
||||
{"ZWWX", 0x3E},
|
||||
{"ZWWY", 0x7E},
|
||||
{"ZWWZ", 0xBE},
|
||||
{"ZWWW", 0xFE},
|
||||
{"WXXX", 0x3},
|
||||
{"WXXY", 0x43},
|
||||
{"WXXZ", 0x83},
|
||||
{"WXXW", 0xC3},
|
||||
{"WXYX", 0x13},
|
||||
{"WXYY", 0x53},
|
||||
{"WXYZ", 0x93},
|
||||
{"WXYW", 0xD3},
|
||||
{"WXZX", 0x23},
|
||||
{"WXZY", 0x63},
|
||||
{"WXZZ", 0xA3},
|
||||
{"WXZW", 0xE3},
|
||||
{"WXWX", 0x33},
|
||||
{"WXWY", 0x73},
|
||||
{"WXWZ", 0xB3},
|
||||
{"WXWW", 0xF3},
|
||||
{"WYXX", 0x7},
|
||||
{"WYXY", 0x47},
|
||||
{"WYXZ", 0x87},
|
||||
{"WYXW", 0xC7},
|
||||
{"WYYX", 0x17},
|
||||
{"WYYY", 0x57},
|
||||
{"WYYZ", 0x97},
|
||||
{"WYYW", 0xD7},
|
||||
{"WYZX", 0x27},
|
||||
{"WYZY", 0x67},
|
||||
{"WYZZ", 0xA7},
|
||||
{"WYZW", 0xE7},
|
||||
{"WYWX", 0x37},
|
||||
{"WYWY", 0x77},
|
||||
{"WYWZ", 0xB7},
|
||||
{"WYWW", 0xF7},
|
||||
{"WZXX", 0xB},
|
||||
{"WZXY", 0x4B},
|
||||
{"WZXZ", 0x8B},
|
||||
{"WZXW", 0xCB},
|
||||
{"WZYX", 0x1B},
|
||||
{"WZYY", 0x5B},
|
||||
{"WZYZ", 0x9B},
|
||||
{"WZYW", 0xDB},
|
||||
{"WZZX", 0x2B},
|
||||
{"WZZY", 0x6B},
|
||||
{"WZZZ", 0xAB},
|
||||
{"WZZW", 0xEB},
|
||||
{"WZWX", 0x3B},
|
||||
{"WZWY", 0x7B},
|
||||
{"WZWZ", 0xBB},
|
||||
{"WZWW", 0xFB},
|
||||
{"WWXX", 0xF},
|
||||
{"WWXY", 0x4F},
|
||||
{"WWXZ", 0x8F},
|
||||
{"WWXW", 0xCF},
|
||||
{"WWYX", 0x1F},
|
||||
{"WWYY", 0x5F},
|
||||
{"WWYZ", 0x9F},
|
||||
{"WWYW", 0xDF},
|
||||
{"WWZX", 0x2F},
|
||||
{"WWZY", 0x6F},
|
||||
{"WWZZ", 0xAF},
|
||||
{"WWZW", 0xEF},
|
||||
{"WWWX", 0x3F},
|
||||
{"WWWY", 0x7F},
|
||||
{"WWWZ", 0xBF},
|
||||
{"WWWW", 0xFF},
|
||||
{"XX", 0x0},
|
||||
{"XY", 0x2},
|
||||
{"YX", 0x1},
|
||||
{"YY", 0x3},
|
||||
{0,0}
|
||||
};
|
||||
|
||||
JSObject *
|
||||
SIMDObject::initClass(JSContext *cx, Handle<GlobalObject *> global)
|
||||
{
|
||||
|
@ -392,7 +655,8 @@ SIMDObject::initClass(JSContext *cx, Handle<GlobalObject *> global)
|
|||
if (!SIMD)
|
||||
return nullptr;
|
||||
|
||||
SET_ALL_SHUFFLE_MASKS;
|
||||
if (!JS_DefineConstIntegers(cx, SIMD, SHUFFLE_MASKS))
|
||||
return nullptr;
|
||||
|
||||
// float32x4
|
||||
RootedObject float32x4Object(cx);
|
||||
|
|
|
@ -1,284 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef builtin_SIMDShuffleMaskConstants_h
|
||||
#define builtin_SIMDShuffleMaskConstants_h
|
||||
|
||||
#define COMMON_PROPERTY_NAMES_MACRO(macro, mask, maskStr, value) macro(mask, mask, maskStr)
|
||||
|
||||
#define SET_SHUFFLE_MASK(macro, maskId, maskStr, value) \
|
||||
{ \
|
||||
RootedValue mask##maskId(cx, JS::Int32Value(value)); \
|
||||
JSObject::defineProperty(cx, SIMD, cx->names().maskId, \
|
||||
mask##maskId, nullptr, nullptr, \
|
||||
JSPROP_READONLY | JSPROP_PERMANENT); \
|
||||
}
|
||||
|
||||
#define SET_ALL_SHUFFLE_MASKS FOR_EACH_SIMD_SHUFFLE_MASK(SET_SHUFFLE_MASK, 0)
|
||||
|
||||
#define FOR_EACH_SIMD_SHUFFLE_MASK(macro, innerMacro) \
|
||||
macro(innerMacro, XXXX, "XXXX", 0x0) \
|
||||
macro(innerMacro, XXXY, "XXXY", 0x40) \
|
||||
macro(innerMacro, XXXZ, "XXXZ", 0x80) \
|
||||
macro(innerMacro, XXXW, "XXXW", 0xC0) \
|
||||
macro(innerMacro, XXYX, "XXYX", 0x10) \
|
||||
macro(innerMacro, XXYY, "XXYY", 0x50) \
|
||||
macro(innerMacro, XXYZ, "XXYZ", 0x90) \
|
||||
macro(innerMacro, XXYW, "XXYW", 0xD0) \
|
||||
macro(innerMacro, XXZX, "XXZX", 0x20) \
|
||||
macro(innerMacro, XXZY, "XXZY", 0x60) \
|
||||
macro(innerMacro, XXZZ, "XXZZ", 0xA0) \
|
||||
macro(innerMacro, XXZW, "XXZW", 0xE0) \
|
||||
macro(innerMacro, XXWX, "XXWX", 0x30) \
|
||||
macro(innerMacro, XXWY, "XXWY", 0x70) \
|
||||
macro(innerMacro, XXWZ, "XXWZ", 0xB0) \
|
||||
macro(innerMacro, XXWW, "XXWW", 0xF0) \
|
||||
macro(innerMacro, XYXX, "XYXX", 0x4) \
|
||||
macro(innerMacro, XYXY, "XYXY", 0x44) \
|
||||
macro(innerMacro, XYXZ, "XYXZ", 0x84) \
|
||||
macro(innerMacro, XYXW, "XYXW", 0xC4) \
|
||||
macro(innerMacro, XYYX, "XYYX", 0x14) \
|
||||
macro(innerMacro, XYYY, "XYYY", 0x54) \
|
||||
macro(innerMacro, XYYZ, "XYYZ", 0x94) \
|
||||
macro(innerMacro, XYYW, "XYYW", 0xD4) \
|
||||
macro(innerMacro, XYZX, "XYZX", 0x24) \
|
||||
macro(innerMacro, XYZY, "XYZY", 0x64) \
|
||||
macro(innerMacro, XYZZ, "XYZZ", 0xA4) \
|
||||
macro(innerMacro, XYZW, "XYZW", 0xE4) \
|
||||
macro(innerMacro, XYWX, "XYWX", 0x34) \
|
||||
macro(innerMacro, XYWY, "XYWY", 0x74) \
|
||||
macro(innerMacro, XYWZ, "XYWZ", 0xB4) \
|
||||
macro(innerMacro, XYWW, "XYWW", 0xF4) \
|
||||
macro(innerMacro, XZXX, "XZXX", 0x8) \
|
||||
macro(innerMacro, XZXY, "XZXY", 0x48) \
|
||||
macro(innerMacro, XZXZ, "XZXZ", 0x88) \
|
||||
macro(innerMacro, XZXW, "XZXW", 0xC8) \
|
||||
macro(innerMacro, XZYX, "XZYX", 0x18) \
|
||||
macro(innerMacro, XZYY, "XZYY", 0x58) \
|
||||
macro(innerMacro, XZYZ, "XZYZ", 0x98) \
|
||||
macro(innerMacro, XZYW, "XZYW", 0xD8) \
|
||||
macro(innerMacro, XZZX, "XZZX", 0x28) \
|
||||
macro(innerMacro, XZZY, "XZZY", 0x68) \
|
||||
macro(innerMacro, XZZZ, "XZZZ", 0xA8) \
|
||||
macro(innerMacro, XZZW, "XZZW", 0xE8) \
|
||||
macro(innerMacro, XZWX, "XZWX", 0x38) \
|
||||
macro(innerMacro, XZWY, "XZWY", 0x78) \
|
||||
macro(innerMacro, XZWZ, "XZWZ", 0xB8) \
|
||||
macro(innerMacro, XZWW, "XZWW", 0xF8) \
|
||||
macro(innerMacro, XWXX, "XWXX", 0xC) \
|
||||
macro(innerMacro, XWXY, "XWXY", 0x4C) \
|
||||
macro(innerMacro, XWXZ, "XWXZ", 0x8C) \
|
||||
macro(innerMacro, XWXW, "XWXW", 0xCC) \
|
||||
macro(innerMacro, XWYX, "XWYX", 0x1C) \
|
||||
macro(innerMacro, XWYY, "XWYY", 0x5C) \
|
||||
macro(innerMacro, XWYZ, "XWYZ", 0x9C) \
|
||||
macro(innerMacro, XWYW, "XWYW", 0xDC) \
|
||||
macro(innerMacro, XWZX, "XWZX", 0x2C) \
|
||||
macro(innerMacro, XWZY, "XWZY", 0x6C) \
|
||||
macro(innerMacro, XWZZ, "XWZZ", 0xAC) \
|
||||
macro(innerMacro, XWZW, "XWZW", 0xEC) \
|
||||
macro(innerMacro, XWWX, "XWWX", 0x3C) \
|
||||
macro(innerMacro, XWWY, "XWWY", 0x7C) \
|
||||
macro(innerMacro, XWWZ, "XWWZ", 0xBC) \
|
||||
macro(innerMacro, XWWW, "XWWW", 0xFC) \
|
||||
macro(innerMacro, YXXX, "YXXX", 0x1) \
|
||||
macro(innerMacro, YXXY, "YXXY", 0x41) \
|
||||
macro(innerMacro, YXXZ, "YXXZ", 0x81) \
|
||||
macro(innerMacro, YXXW, "YXXW", 0xC1) \
|
||||
macro(innerMacro, YXYX, "YXYX", 0x11) \
|
||||
macro(innerMacro, YXYY, "YXYY", 0x51) \
|
||||
macro(innerMacro, YXYZ, "YXYZ", 0x91) \
|
||||
macro(innerMacro, YXYW, "YXYW", 0xD1) \
|
||||
macro(innerMacro, YXZX, "YXZX", 0x21) \
|
||||
macro(innerMacro, YXZY, "YXZY", 0x61) \
|
||||
macro(innerMacro, YXZZ, "YXZZ", 0xA1) \
|
||||
macro(innerMacro, YXZW, "YXZW", 0xE1) \
|
||||
macro(innerMacro, YXWX, "YXWX", 0x31) \
|
||||
macro(innerMacro, YXWY, "YXWY", 0x71) \
|
||||
macro(innerMacro, YXWZ, "YXWZ", 0xB1) \
|
||||
macro(innerMacro, YXWW, "YXWW", 0xF1) \
|
||||
macro(innerMacro, YYXX, "YYXX", 0x5) \
|
||||
macro(innerMacro, YYXY, "YYXY", 0x45) \
|
||||
macro(innerMacro, YYXZ, "YYXZ", 0x85) \
|
||||
macro(innerMacro, YYXW, "YYXW", 0xC5) \
|
||||
macro(innerMacro, YYYX, "YYYX", 0x15) \
|
||||
macro(innerMacro, YYYY, "YYYY", 0x55) \
|
||||
macro(innerMacro, YYYZ, "YYYZ", 0x95) \
|
||||
macro(innerMacro, YYYW, "YYYW", 0xD5) \
|
||||
macro(innerMacro, YYZX, "YYZX", 0x25) \
|
||||
macro(innerMacro, YYZY, "YYZY", 0x65) \
|
||||
macro(innerMacro, YYZZ, "YYZZ", 0xA5) \
|
||||
macro(innerMacro, YYZW, "YYZW", 0xE5) \
|
||||
macro(innerMacro, YYWX, "YYWX", 0x35) \
|
||||
macro(innerMacro, YYWY, "YYWY", 0x75) \
|
||||
macro(innerMacro, YYWZ, "YYWZ", 0xB5) \
|
||||
macro(innerMacro, YYWW, "YYWW", 0xF5) \
|
||||
macro(innerMacro, YZXX, "YZXX", 0x9) \
|
||||
macro(innerMacro, YZXY, "YZXY", 0x49) \
|
||||
macro(innerMacro, YZXZ, "YZXZ", 0x89) \
|
||||
macro(innerMacro, YZXW, "YZXW", 0xC9) \
|
||||
macro(innerMacro, YZYX, "YZYX", 0x19) \
|
||||
macro(innerMacro, YZYY, "YZYY", 0x59) \
|
||||
macro(innerMacro, YZYZ, "YZYZ", 0x99) \
|
||||
macro(innerMacro, YZYW, "YZYW", 0xD9) \
|
||||
macro(innerMacro, YZZX, "YZZX", 0x29) \
|
||||
macro(innerMacro, YZZY, "YZZY", 0x69) \
|
||||
macro(innerMacro, YZZZ, "YZZZ", 0xA9) \
|
||||
macro(innerMacro, YZZW, "YZZW", 0xE9) \
|
||||
macro(innerMacro, YZWX, "YZWX", 0x39) \
|
||||
macro(innerMacro, YZWY, "YZWY", 0x79) \
|
||||
macro(innerMacro, YZWZ, "YZWZ", 0xB9) \
|
||||
macro(innerMacro, YZWW, "YZWW", 0xF9) \
|
||||
macro(innerMacro, YWXX, "YWXX", 0xD) \
|
||||
macro(innerMacro, YWXY, "YWXY", 0x4D) \
|
||||
macro(innerMacro, YWXZ, "YWXZ", 0x8D) \
|
||||
macro(innerMacro, YWXW, "YWXW", 0xCD) \
|
||||
macro(innerMacro, YWYX, "YWYX", 0x1D) \
|
||||
macro(innerMacro, YWYY, "YWYY", 0x5D) \
|
||||
macro(innerMacro, YWYZ, "YWYZ", 0x9D) \
|
||||
macro(innerMacro, YWYW, "YWYW", 0xDD) \
|
||||
macro(innerMacro, YWZX, "YWZX", 0x2D) \
|
||||
macro(innerMacro, YWZY, "YWZY", 0x6D) \
|
||||
macro(innerMacro, YWZZ, "YWZZ", 0xAD) \
|
||||
macro(innerMacro, YWZW, "YWZW", 0xED) \
|
||||
macro(innerMacro, YWWX, "YWWX", 0x3D) \
|
||||
macro(innerMacro, YWWY, "YWWY", 0x7D) \
|
||||
macro(innerMacro, YWWZ, "YWWZ", 0xBD) \
|
||||
macro(innerMacro, YWWW, "YWWW", 0xFD) \
|
||||
macro(innerMacro, ZXXX, "ZXXX", 0x2) \
|
||||
macro(innerMacro, ZXXY, "ZXXY", 0x42) \
|
||||
macro(innerMacro, ZXXZ, "ZXXZ", 0x82) \
|
||||
macro(innerMacro, ZXXW, "ZXXW", 0xC2) \
|
||||
macro(innerMacro, ZXYX, "ZXYX", 0x12) \
|
||||
macro(innerMacro, ZXYY, "ZXYY", 0x52) \
|
||||
macro(innerMacro, ZXYZ, "ZXYZ", 0x92) \
|
||||
macro(innerMacro, ZXYW, "ZXYW", 0xD2) \
|
||||
macro(innerMacro, ZXZX, "ZXZX", 0x22) \
|
||||
macro(innerMacro, ZXZY, "ZXZY", 0x62) \
|
||||
macro(innerMacro, ZXZZ, "ZXZZ", 0xA2) \
|
||||
macro(innerMacro, ZXZW, "ZXZW", 0xE2) \
|
||||
macro(innerMacro, ZXWX, "ZXWX", 0x32) \
|
||||
macro(innerMacro, ZXWY, "ZXWY", 0x72) \
|
||||
macro(innerMacro, ZXWZ, "ZXWZ", 0xB2) \
|
||||
macro(innerMacro, ZXWW, "ZXWW", 0xF2) \
|
||||
macro(innerMacro, ZYXX, "ZYXX", 0x6) \
|
||||
macro(innerMacro, ZYXY, "ZYXY", 0x46) \
|
||||
macro(innerMacro, ZYXZ, "ZYXZ", 0x86) \
|
||||
macro(innerMacro, ZYXW, "ZYXW", 0xC6) \
|
||||
macro(innerMacro, ZYYX, "ZYYX", 0x16) \
|
||||
macro(innerMacro, ZYYY, "ZYYY", 0x56) \
|
||||
macro(innerMacro, ZYYZ, "ZYYZ", 0x96) \
|
||||
macro(innerMacro, ZYYW, "ZYYW", 0xD6) \
|
||||
macro(innerMacro, ZYZX, "ZYZX", 0x26) \
|
||||
macro(innerMacro, ZYZY, "ZYZY", 0x66) \
|
||||
macro(innerMacro, ZYZZ, "ZYZZ", 0xA6) \
|
||||
macro(innerMacro, ZYZW, "ZYZW", 0xE6) \
|
||||
macro(innerMacro, ZYWX, "ZYWX", 0x36) \
|
||||
macro(innerMacro, ZYWY, "ZYWY", 0x76) \
|
||||
macro(innerMacro, ZYWZ, "ZYWZ", 0xB6) \
|
||||
macro(innerMacro, ZYWW, "ZYWW", 0xF6) \
|
||||
macro(innerMacro, ZZXX, "ZZXX", 0xA) \
|
||||
macro(innerMacro, ZZXY, "ZZXY", 0x4A) \
|
||||
macro(innerMacro, ZZXZ, "ZZXZ", 0x8A) \
|
||||
macro(innerMacro, ZZXW, "ZZXW", 0xCA) \
|
||||
macro(innerMacro, ZZYX, "ZZYX", 0x1A) \
|
||||
macro(innerMacro, ZZYY, "ZZYY", 0x5A) \
|
||||
macro(innerMacro, ZZYZ, "ZZYZ", 0x9A) \
|
||||
macro(innerMacro, ZZYW, "ZZYW", 0xDA) \
|
||||
macro(innerMacro, ZZZX, "ZZZX", 0x2A) \
|
||||
macro(innerMacro, ZZZY, "ZZZY", 0x6A) \
|
||||
macro(innerMacro, ZZZZ, "ZZZZ", 0xAA) \
|
||||
macro(innerMacro, ZZZW, "ZZZW", 0xEA) \
|
||||
macro(innerMacro, ZZWX, "ZZWX", 0x3A) \
|
||||
macro(innerMacro, ZZWY, "ZZWY", 0x7A) \
|
||||
macro(innerMacro, ZZWZ, "ZZWZ", 0xBA) \
|
||||
macro(innerMacro, ZZWW, "ZZWW", 0xFA) \
|
||||
macro(innerMacro, ZWXX, "ZWXX", 0xE) \
|
||||
macro(innerMacro, ZWXY, "ZWXY", 0x4E) \
|
||||
macro(innerMacro, ZWXZ, "ZWXZ", 0x8E) \
|
||||
macro(innerMacro, ZWXW, "ZWXW", 0xCE) \
|
||||
macro(innerMacro, ZWYX, "ZWYX", 0x1E) \
|
||||
macro(innerMacro, ZWYY, "ZWYY", 0x5E) \
|
||||
macro(innerMacro, ZWYZ, "ZWYZ", 0x9E) \
|
||||
macro(innerMacro, ZWYW, "ZWYW", 0xDE) \
|
||||
macro(innerMacro, ZWZX, "ZWZX", 0x2E) \
|
||||
macro(innerMacro, ZWZY, "ZWZY", 0x6E) \
|
||||
macro(innerMacro, ZWZZ, "ZWZZ", 0xAE) \
|
||||
macro(innerMacro, ZWZW, "ZWZW", 0xEE) \
|
||||
macro(innerMacro, ZWWX, "ZWWX", 0x3E) \
|
||||
macro(innerMacro, ZWWY, "ZWWY", 0x7E) \
|
||||
macro(innerMacro, ZWWZ, "ZWWZ", 0xBE) \
|
||||
macro(innerMacro, ZWWW, "ZWWW", 0xFE) \
|
||||
macro(innerMacro, WXXX, "WXXX", 0x3) \
|
||||
macro(innerMacro, WXXY, "WXXY", 0x43) \
|
||||
macro(innerMacro, WXXZ, "WXXZ", 0x83) \
|
||||
macro(innerMacro, WXXW, "WXXW", 0xC3) \
|
||||
macro(innerMacro, WXYX, "WXYX", 0x13) \
|
||||
macro(innerMacro, WXYY, "WXYY", 0x53) \
|
||||
macro(innerMacro, WXYZ, "WXYZ", 0x93) \
|
||||
macro(innerMacro, WXYW, "WXYW", 0xD3) \
|
||||
macro(innerMacro, WXZX, "WXZX", 0x23) \
|
||||
macro(innerMacro, WXZY, "WXZY", 0x63) \
|
||||
macro(innerMacro, WXZZ, "WXZZ", 0xA3) \
|
||||
macro(innerMacro, WXZW, "WXZW", 0xE3) \
|
||||
macro(innerMacro, WXWX, "WXWX", 0x33) \
|
||||
macro(innerMacro, WXWY, "WXWY", 0x73) \
|
||||
macro(innerMacro, WXWZ, "WXWZ", 0xB3) \
|
||||
macro(innerMacro, WXWW, "WXWW", 0xF3) \
|
||||
macro(innerMacro, WYXX, "WYXX", 0x7) \
|
||||
macro(innerMacro, WYXY, "WYXY", 0x47) \
|
||||
macro(innerMacro, WYXZ, "WYXZ", 0x87) \
|
||||
macro(innerMacro, WYXW, "WYXW", 0xC7) \
|
||||
macro(innerMacro, WYYX, "WYYX", 0x17) \
|
||||
macro(innerMacro, WYYY, "WYYY", 0x57) \
|
||||
macro(innerMacro, WYYZ, "WYYZ", 0x97) \
|
||||
macro(innerMacro, WYYW, "WYYW", 0xD7) \
|
||||
macro(innerMacro, WYZX, "WYZX", 0x27) \
|
||||
macro(innerMacro, WYZY, "WYZY", 0x67) \
|
||||
macro(innerMacro, WYZZ, "WYZZ", 0xA7) \
|
||||
macro(innerMacro, WYZW, "WYZW", 0xE7) \
|
||||
macro(innerMacro, WYWX, "WYWX", 0x37) \
|
||||
macro(innerMacro, WYWY, "WYWY", 0x77) \
|
||||
macro(innerMacro, WYWZ, "WYWZ", 0xB7) \
|
||||
macro(innerMacro, WYWW, "WYWW", 0xF7) \
|
||||
macro(innerMacro, WZXX, "WZXX", 0xB) \
|
||||
macro(innerMacro, WZXY, "WZXY", 0x4B) \
|
||||
macro(innerMacro, WZXZ, "WZXZ", 0x8B) \
|
||||
macro(innerMacro, WZXW, "WZXW", 0xCB) \
|
||||
macro(innerMacro, WZYX, "WZYX", 0x1B) \
|
||||
macro(innerMacro, WZYY, "WZYY", 0x5B) \
|
||||
macro(innerMacro, WZYZ, "WZYZ", 0x9B) \
|
||||
macro(innerMacro, WZYW, "WZYW", 0xDB) \
|
||||
macro(innerMacro, WZZX, "WZZX", 0x2B) \
|
||||
macro(innerMacro, WZZY, "WZZY", 0x6B) \
|
||||
macro(innerMacro, WZZZ, "WZZZ", 0xAB) \
|
||||
macro(innerMacro, WZZW, "WZZW", 0xEB) \
|
||||
macro(innerMacro, WZWX, "WZWX", 0x3B) \
|
||||
macro(innerMacro, WZWY, "WZWY", 0x7B) \
|
||||
macro(innerMacro, WZWZ, "WZWZ", 0xBB) \
|
||||
macro(innerMacro, WZWW, "WZWW", 0xFB) \
|
||||
macro(innerMacro, WWXX, "WWXX", 0xF) \
|
||||
macro(innerMacro, WWXY, "WWXY", 0x4F) \
|
||||
macro(innerMacro, WWXZ, "WWXZ", 0x8F) \
|
||||
macro(innerMacro, WWXW, "WWXW", 0xCF) \
|
||||
macro(innerMacro, WWYX, "WWYX", 0x1F) \
|
||||
macro(innerMacro, WWYY, "WWYY", 0x5F) \
|
||||
macro(innerMacro, WWYZ, "WWYZ", 0x9F) \
|
||||
macro(innerMacro, WWYW, "WWYW", 0xDF) \
|
||||
macro(innerMacro, WWZX, "WWZX", 0x2F) \
|
||||
macro(innerMacro, WWZY, "WWZY", 0x6F) \
|
||||
macro(innerMacro, WWZZ, "WWZZ", 0xAF) \
|
||||
macro(innerMacro, WWZW, "WWZW", 0xEF) \
|
||||
macro(innerMacro, WWWX, "WWWX", 0x3F) \
|
||||
macro(innerMacro, WWWY, "WWWY", 0x7F) \
|
||||
macro(innerMacro, WWWZ, "WWWZ", 0xBF) \
|
||||
macro(innerMacro, WWWW, "WWWW", 0xFF) \
|
||||
macro(innerMacro, XX, "XX", 0x0) \
|
||||
macro(innerMacro, XY, "XY", 0x2) \
|
||||
macro(innerMacro, YX, "YX", 0x1) \
|
||||
macro(innerMacro, YY, "YY", 0x3)
|
||||
|
||||
#endif
|
|
@ -459,7 +459,7 @@ namespace CDataFinalizer {
|
|||
*
|
||||
* Note that the jsval is actually not recorded, but converted back from C.
|
||||
*/
|
||||
static bool GetValue(JSContext *cx, JSObject *obj, jsval *result);
|
||||
static bool GetValue(JSContext *cx, JSObject *obj, MutableHandleValue result);
|
||||
|
||||
static JSObject* GetCData(JSContext *cx, JSObject *obj);
|
||||
}
|
||||
|
@ -1717,7 +1717,7 @@ jsvalToInteger(JSContext* cx, jsval val, IntegerType* result)
|
|||
|
||||
if (CDataFinalizer::IsCDataFinalizer(obj)) {
|
||||
RootedValue innerData(cx);
|
||||
if (!CDataFinalizer::GetValue(cx, obj, innerData.address())) {
|
||||
if (!CDataFinalizer::GetValue(cx, obj, &innerData)) {
|
||||
return false; // Nothing to convert
|
||||
}
|
||||
return jsvalToInteger(cx, innerData, result);
|
||||
|
@ -1908,7 +1908,7 @@ jsvalToBigInteger(JSContext* cx,
|
|||
|
||||
if (CDataFinalizer::IsCDataFinalizer(obj)) {
|
||||
RootedValue innerData(cx);
|
||||
if (!CDataFinalizer::GetValue(cx, obj, innerData.address())) {
|
||||
if (!CDataFinalizer::GetValue(cx, obj, &innerData)) {
|
||||
return false; // Nothing to convert
|
||||
}
|
||||
return jsvalToBigInteger(cx, innerData, allowString, result);
|
||||
|
@ -1973,14 +1973,14 @@ jsidToSize(JSContext* cx, jsid val, bool allowString, size_t* result)
|
|||
// Implicitly convert a size value to a jsval, ensuring that the size_t value
|
||||
// fits in a double.
|
||||
static bool
|
||||
SizeTojsval(JSContext* cx, size_t size, jsval* result)
|
||||
SizeTojsval(JSContext* cx, size_t size, MutableHandleValue result)
|
||||
{
|
||||
if (Convert<size_t>(double(size)) != size) {
|
||||
JS_ReportError(cx, "size overflow");
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = JS_NumberValue(double(size));
|
||||
result.setNumber(double(size));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2125,7 +2125,7 @@ ConvertToJS(JSContext* cx,
|
|||
void* data,
|
||||
bool wantPrimitive,
|
||||
bool ownResult,
|
||||
jsval* result)
|
||||
MutableHandleValue result)
|
||||
{
|
||||
JS_ASSERT(!parentObj || CData::IsCData(parentObj));
|
||||
JS_ASSERT(!parentObj || !ownResult);
|
||||
|
@ -2135,18 +2135,18 @@ ConvertToJS(JSContext* cx,
|
|||
|
||||
switch (typeCode) {
|
||||
case TYPE_void_t:
|
||||
*result = JSVAL_VOID;
|
||||
result.setUndefined();
|
||||
break;
|
||||
case TYPE_bool:
|
||||
*result = *static_cast<bool*>(data) ? JSVAL_TRUE : JSVAL_FALSE;
|
||||
result.setBoolean(*static_cast<bool*>(data));
|
||||
break;
|
||||
#define DEFINE_INT_TYPE(name, type, ffiType) \
|
||||
case TYPE_##name: { \
|
||||
type value = *static_cast<type*>(data); \
|
||||
if (sizeof(type) < 4) \
|
||||
*result = INT_TO_JSVAL(int32_t(value)); \
|
||||
result.setInt32(int32_t(value)); \
|
||||
else \
|
||||
*result = JS_NumberValue(double(value)); \
|
||||
result.setDouble(double(value)); \
|
||||
break; \
|
||||
}
|
||||
#define DEFINE_WRAPPED_INT_TYPE(name, type, ffiType) \
|
||||
|
@ -2172,20 +2172,20 @@ ConvertToJS(JSContext* cx,
|
|||
!NumericLimits<type>::is_signed); \
|
||||
if (!obj) \
|
||||
return false; \
|
||||
*result = OBJECT_TO_JSVAL(obj); \
|
||||
result.setObject(*obj); \
|
||||
break; \
|
||||
}
|
||||
#define DEFINE_FLOAT_TYPE(name, type, ffiType) \
|
||||
case TYPE_##name: { \
|
||||
type value = *static_cast<type*>(data); \
|
||||
*result = JS_NumberValue(double(value)); \
|
||||
result.setDouble(double(value)); \
|
||||
break; \
|
||||
}
|
||||
#define DEFINE_CHAR_TYPE(name, type, ffiType) \
|
||||
case TYPE_##name: \
|
||||
/* Convert to an integer. We have no idea what character encoding to */ \
|
||||
/* use, if any. */ \
|
||||
*result = INT_TO_JSVAL(*static_cast<type*>(data)); \
|
||||
result.setInt32(*static_cast<type*>(data)); \
|
||||
break;
|
||||
#include "ctypes/typedefs.h"
|
||||
case TYPE_char16_t: {
|
||||
|
@ -2194,7 +2194,7 @@ ConvertToJS(JSContext* cx,
|
|||
if (!str)
|
||||
return false;
|
||||
|
||||
*result = STRING_TO_JSVAL(str);
|
||||
result.setString(str);
|
||||
break;
|
||||
}
|
||||
case TYPE_pointer:
|
||||
|
@ -2211,7 +2211,7 @@ ConvertToJS(JSContext* cx,
|
|||
if (!obj)
|
||||
return false;
|
||||
|
||||
*result = OBJECT_TO_JSVAL(obj);
|
||||
result.setObject(*obj);
|
||||
break;
|
||||
}
|
||||
case TYPE_function:
|
||||
|
@ -2627,7 +2627,7 @@ ImplicitConvert(JSContext* cx,
|
|||
RootedId id(cx);
|
||||
size_t i = 0;
|
||||
while (1) {
|
||||
if (!JS_NextProperty(cx, iter, id.address()))
|
||||
if (!JS_NextProperty(cx, iter, &id))
|
||||
return false;
|
||||
if (JSID_IS_VOID(id))
|
||||
break;
|
||||
|
@ -4194,7 +4194,7 @@ PointerType::ContentsGetter(JSContext* cx, JS::CallArgs args)
|
|||
}
|
||||
|
||||
RootedValue result(cx);
|
||||
if (!ConvertToJS(cx, baseType, NullPtr(), data, false, false, result.address()))
|
||||
if (!ConvertToJS(cx, baseType, NullPtr(), data, false, false, &result))
|
||||
return false;
|
||||
|
||||
args.rval().set(result);
|
||||
|
@ -4290,8 +4290,8 @@ ArrayType::CreateInternal(JSContext* cx,
|
|||
JS_ReportError(cx, "size overflow");
|
||||
return nullptr;
|
||||
}
|
||||
if (!SizeTojsval(cx, size, sizeVal.address()) ||
|
||||
!SizeTojsval(cx, length, lengthVal.address()))
|
||||
if (!SizeTojsval(cx, size, &sizeVal) ||
|
||||
!SizeTojsval(cx, length, &lengthVal))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -4589,7 +4589,7 @@ ArrayType::Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandle
|
|||
RootedObject baseType(cx, GetBaseType(typeObj));
|
||||
size_t elementSize = CType::GetSize(baseType);
|
||||
char* data = static_cast<char*>(CData::GetData(obj)) + elementSize * index;
|
||||
return ConvertToJS(cx, baseType, obj, data, false, false, vp.address());
|
||||
return ConvertToJS(cx, baseType, obj, data, false, false, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4686,7 +4686,7 @@ ArrayType::AddressOfElement(JSContext* cx, unsigned argc, jsval* vp)
|
|||
// For a struct field descriptor 'val' of the form { name : type }, extract
|
||||
// 'name' and 'type'.
|
||||
static JSFlatString*
|
||||
ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
||||
ExtractStructField(JSContext* cx, jsval val, MutableHandleObject typeObj)
|
||||
{
|
||||
if (val.isPrimitive()) {
|
||||
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
||||
|
@ -4699,7 +4699,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
|||
return nullptr;
|
||||
|
||||
RootedId nameid(cx);
|
||||
if (!JS_NextProperty(cx, iter, nameid.address()))
|
||||
if (!JS_NextProperty(cx, iter, &nameid))
|
||||
return nullptr;
|
||||
if (JSID_IS_VOID(nameid)) {
|
||||
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
||||
|
@ -4712,7 +4712,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
|||
}
|
||||
|
||||
// make sure we have one, and only one, property
|
||||
jsid id;
|
||||
RootedId id(cx);
|
||||
if (!JS_NextProperty(cx, iter, &id))
|
||||
return nullptr;
|
||||
if (!JSID_IS_VOID(id)) {
|
||||
|
@ -4732,9 +4732,9 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
|||
// Undefined size or zero size struct members are illegal.
|
||||
// (Zero-size arrays are legal as struct members in C++, but libffi will
|
||||
// choke on a zero-size struct, so we disallow them.)
|
||||
*typeObj = &propVal.toObject();
|
||||
typeObj.set(&propVal.toObject());
|
||||
size_t size;
|
||||
if (!CType::GetSafeSize(*typeObj, &size) || size == 0) {
|
||||
if (!CType::GetSafeSize(typeObj, &size) || size == 0) {
|
||||
JS_ReportError(cx, "struct field types must have defined and nonzero size");
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -4746,7 +4746,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
|||
// { name : type }.
|
||||
static bool
|
||||
AddFieldToArray(JSContext* cx,
|
||||
jsval* element,
|
||||
MutableHandleValue element,
|
||||
JSFlatString* name_,
|
||||
JSObject* typeObj_)
|
||||
{
|
||||
|
@ -4756,7 +4756,7 @@ AddFieldToArray(JSContext* cx,
|
|||
if (!fieldObj)
|
||||
return false;
|
||||
|
||||
*element = OBJECT_TO_JSVAL(fieldObj);
|
||||
element.setObject(*fieldObj);
|
||||
|
||||
AutoStableStringChars nameChars(cx);
|
||||
if (!nameChars.initTwoByte(cx, name))
|
||||
|
@ -4882,7 +4882,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
|
|||
return false;
|
||||
|
||||
RootedObject fieldType(cx, nullptr);
|
||||
Rooted<JSFlatString*> name(cx, ExtractStructField(cx, item, fieldType.address()));
|
||||
Rooted<JSFlatString*> name(cx, ExtractStructField(cx, item, &fieldType));
|
||||
if (!name)
|
||||
return false;
|
||||
fieldRoots[i].setObject(*fieldType);
|
||||
|
@ -4948,7 +4948,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
|
|||
}
|
||||
|
||||
RootedValue sizeVal(cx);
|
||||
if (!SizeTojsval(cx, structSize, sizeVal.address()))
|
||||
if (!SizeTojsval(cx, structSize, &sizeVal))
|
||||
return false;
|
||||
|
||||
JS_SetReservedSlot(typeObj, SLOT_FIELDINFO, PRIVATE_TO_JSVAL(fields.forget()));
|
||||
|
@ -5197,7 +5197,7 @@ StructType::BuildFieldsArray(JSContext* cx, JSObject* obj)
|
|||
for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
|
||||
const FieldInfoHash::Entry& entry = r.front();
|
||||
// Add the field descriptor to the array.
|
||||
if (!AddFieldToArray(cx, fieldsVec[entry.value().mIndex].address(),
|
||||
if (!AddFieldToArray(cx, fieldsVec[entry.value().mIndex],
|
||||
entry.key(), entry.value().mType))
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -5269,7 +5269,7 @@ StructType::FieldGetter(JSContext* cx, HandleObject obj, HandleId idval, Mutable
|
|||
|
||||
char* data = static_cast<char*>(CData::GetData(obj)) + field->mOffset;
|
||||
RootedObject fieldType(cx, field->mType);
|
||||
return ConvertToJS(cx, fieldType, obj, data, false, false, vp.address());
|
||||
return ConvertToJS(cx, fieldType, obj, data, false, false, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -5962,7 +5962,7 @@ FunctionType::Call(JSContext* cx,
|
|||
|
||||
// prepare a JS object from the result
|
||||
RootedObject returnType(cx, fninfo->mReturnType);
|
||||
return ConvertToJS(cx, returnType, NullPtr(), returnValue.mData, false, true, vp);
|
||||
return ConvertToJS(cx, returnType, NullPtr(), returnValue.mData, false, true, args.rval());
|
||||
}
|
||||
|
||||
FunctionInfo*
|
||||
|
@ -6242,7 +6242,7 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData)
|
|||
// Convert each argument, and have any CData objects created depend on
|
||||
// the existing buffers.
|
||||
RootedObject argType(cx, fninfo->mArgTypes[i]);
|
||||
if (!ConvertToJS(cx, argType, NullPtr(), args[i], false, false, argv[i].address()))
|
||||
if (!ConvertToJS(cx, argType, NullPtr(), args[i], false, false, argv[i]))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6478,7 +6478,7 @@ CData::ValueGetter(JSContext* cx, JS::CallArgs args)
|
|||
|
||||
// Convert the value to a primitive; do not create a new CData object.
|
||||
RootedObject ctype(cx, GetCType(obj));
|
||||
return ConvertToJS(cx, ctype, NullPtr(), GetData(obj), true, false, args.rval().address());
|
||||
return ConvertToJS(cx, ctype, NullPtr(), GetData(obj), true, false, args.rval());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -6844,7 +6844,7 @@ CDataFinalizer::Methods::ToString(JSContext *cx, unsigned argc, jsval *vp)
|
|||
if (!strMessage) {
|
||||
return false;
|
||||
}
|
||||
} else if (!CDataFinalizer::GetValue(cx, objThis, value.address())) {
|
||||
} else if (!CDataFinalizer::GetValue(cx, objThis, &value)) {
|
||||
MOZ_CRASH("Could not convert an empty CDataFinalizer");
|
||||
} else {
|
||||
strMessage = ToString(cx, value);
|
||||
|
@ -6892,7 +6892,7 @@ CDataFinalizer::GetCData(JSContext *cx, JSObject *obj)
|
|||
return nullptr;
|
||||
}
|
||||
RootedValue val(cx);
|
||||
if (!CDataFinalizer::GetValue(cx, obj, val.address()) || val.isPrimitive()) {
|
||||
if (!CDataFinalizer::GetValue(cx, obj, &val) || val.isPrimitive()) {
|
||||
JS_ReportError(cx, "Empty CDataFinalizer");
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -6900,7 +6900,7 @@ CDataFinalizer::GetCData(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
bool
|
||||
CDataFinalizer::GetValue(JSContext *cx, JSObject *obj, jsval *aResult)
|
||||
CDataFinalizer::GetValue(JSContext *cx, JSObject *obj, MutableHandleValue aResult)
|
||||
{
|
||||
MOZ_ASSERT(IsCDataFinalizer(obj));
|
||||
|
||||
|
@ -7184,7 +7184,7 @@ CDataFinalizer::Methods::Forget(JSContext* cx, unsigned argc, jsval *vp)
|
|||
|
||||
RootedValue valJSData(cx);
|
||||
RootedObject ctype(cx, GetCType(cx, obj));
|
||||
if (!ConvertToJS(cx, ctype, NullPtr(), p->cargs, false, true, valJSData.address())) {
|
||||
if (!ConvertToJS(cx, ctype, NullPtr(), p->cargs, false, true, &valJSData)) {
|
||||
JS_ReportError(cx, "CDataFinalizer value cannot be represented");
|
||||
return false;
|
||||
}
|
||||
|
@ -7261,7 +7261,7 @@ CDataFinalizer::Methods::Dispose(JSContext* cx, unsigned argc, jsval *vp)
|
|||
JS_SetReservedSlot(objCTypes, SLOT_LASTERROR, INT_TO_JSVAL(lastErrorStatus));
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
if (ConvertToJS(cx, resultType, NullPtr(), p->rvalue, false, true, result.address())) {
|
||||
if (ConvertToJS(cx, resultType, NullPtr(), p->rvalue, false, true, &result)) {
|
||||
CDataFinalizer::Cleanup(p, obj);
|
||||
args.rval().set(result);
|
||||
return true;
|
||||
|
|
|
@ -546,6 +546,9 @@ class GCRuntime
|
|||
void checkForCompartmentMismatches();
|
||||
#endif
|
||||
|
||||
void callFinalizeCallbacks(FreeOp *fop, JSFinalizeStatus status) const;
|
||||
void callMovingGCCallbacks() const;
|
||||
|
||||
public:
|
||||
JSRuntime *rt;
|
||||
|
||||
|
|
|
@ -9838,7 +9838,7 @@ DoIteratorMoreFallback(JSContext *cx, BaselineFrame *frame, ICIteratorMore_Fallb
|
|||
FallbackICSpew(cx, stub, "IteratorMore");
|
||||
|
||||
bool cond;
|
||||
if (!js_IteratorMore(cx, iterObj, &cond))
|
||||
if (!IteratorMore(cx, iterObj, &cond))
|
||||
return false;
|
||||
res.setBoolean(cond);
|
||||
|
||||
|
|
|
@ -6370,7 +6370,7 @@ LoadNativeIterator(MacroAssembler &masm, Register obj, Register dest, Label *fai
|
|||
}
|
||||
|
||||
typedef bool (*IteratorNextFn)(JSContext *, HandleObject, MutableHandleValue);
|
||||
static const VMFunction IteratorNextInfo = FunctionInfo<IteratorNextFn>(js_IteratorNext);
|
||||
static const VMFunction IteratorNextInfo = FunctionInfo<IteratorNextFn>(IteratorNext);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitIteratorNext(LIteratorNext *lir)
|
||||
|
@ -6401,7 +6401,7 @@ CodeGenerator::visitIteratorNext(LIteratorNext *lir)
|
|||
}
|
||||
|
||||
typedef bool (*IteratorMoreFn)(JSContext *, HandleObject, bool *);
|
||||
static const VMFunction IteratorMoreInfo = FunctionInfo<IteratorMoreFn>(js_IteratorMore);
|
||||
static const VMFunction IteratorMoreInfo = FunctionInfo<IteratorMoreFn>(IteratorMore);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitIteratorMore(LIteratorMore *lir)
|
||||
|
|
|
@ -3218,26 +3218,43 @@ JS_DefineObject(JSContext *cx, HandleObject obj, const char *name, const JSClass
|
|||
return nobj;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefineConstDoubles(JSContext *cx, HandleObject obj, const JSConstDoubleSpec *cds)
|
||||
static inline Value
|
||||
ValueFromScalar(double x)
|
||||
{
|
||||
bool ok;
|
||||
unsigned attrs;
|
||||
return DoubleValue(x);
|
||||
}
|
||||
static inline Value
|
||||
ValueFromScalar(int32_t x)
|
||||
{
|
||||
return Int32Value(x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool
|
||||
DefineConstScalar(JSContext *cx, HandleObject obj, const JSConstScalarSpec<T> *cds)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
JSPropertyOpWrapper noget = GetterWrapper(nullptr);
|
||||
JSStrictPropertyOpWrapper noset = SetterWrapper(nullptr);
|
||||
for (ok = true; cds->name; cds++) {
|
||||
RootedValue value(cx, DoubleValue(cds->dval));
|
||||
attrs = cds->flags;
|
||||
if (!attrs)
|
||||
attrs = JSPROP_READONLY | JSPROP_PERMANENT;
|
||||
ok = DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0);
|
||||
if (!ok)
|
||||
break;
|
||||
unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT;
|
||||
for (; cds->name; cds++) {
|
||||
RootedValue value(cx, ValueFromScalar(cds->val));
|
||||
if (!DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0))
|
||||
return false;
|
||||
}
|
||||
return ok;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefineConstDoubles(JSContext *cx, HandleObject obj, const JSConstDoubleSpec *cds)
|
||||
{
|
||||
return DefineConstScalar(cx, obj, cds);
|
||||
}
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefineConstIntegers(JSContext *cx, HandleObject obj, const JSConstIntegerSpec *cis)
|
||||
{
|
||||
return DefineConstScalar(cx, obj, cis);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -3707,7 +3724,7 @@ JS_NewPropertyIterator(JSContext *cx, HandleObject obj)
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp)
|
||||
JS_NextProperty(JSContext *cx, HandleObject iterobj, MutableHandleId idp)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
@ -3723,10 +3740,10 @@ JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp)
|
|||
|
||||
if (!shape->previous()) {
|
||||
JS_ASSERT(shape->isEmptyShape());
|
||||
*idp = JSID_VOID;
|
||||
idp.set(JSID_VOID);
|
||||
} else {
|
||||
iterobj->setPrivateGCThing(const_cast<Shape *>(shape->previous().get()));
|
||||
*idp = shape->propid();
|
||||
idp.set(shape->propid());
|
||||
}
|
||||
} else {
|
||||
/* Non-native case: use the ida enumerated when iterobj was created. */
|
||||
|
@ -3734,9 +3751,9 @@ JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp)
|
|||
JS_ASSERT(i <= ida->length);
|
||||
STATIC_ASSUME(i <= ida->length);
|
||||
if (i == 0) {
|
||||
*idp = JSID_VOID;
|
||||
idp.set(JSID_VOID);
|
||||
} else {
|
||||
*idp = ida->vector[--i];
|
||||
idp.set(ida->vector[--i]);
|
||||
iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(i));
|
||||
}
|
||||
}
|
||||
|
@ -6143,7 +6160,7 @@ JS_PUBLIC_API(bool)
|
|||
JS_ThrowStopIteration(JSContext *cx)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
return js_ThrowStopIteration(cx);
|
||||
return ThrowStopIteration(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
|
|
@ -2303,13 +2303,15 @@ extern JS_PUBLIC_API(bool)
|
|||
JS_ConvertStub(JSContext *cx, JS::HandleObject obj, JSType type,
|
||||
JS::MutableHandleValue vp);
|
||||
|
||||
struct JSConstDoubleSpec {
|
||||
double dval;
|
||||
template<typename T>
|
||||
struct JSConstScalarSpec {
|
||||
const char *name;
|
||||
uint8_t flags;
|
||||
uint8_t spare[3];
|
||||
T val;
|
||||
};
|
||||
|
||||
typedef JSConstScalarSpec<double> JSConstDoubleSpec;
|
||||
typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
|
||||
|
||||
struct JSJitInfo;
|
||||
|
||||
/*
|
||||
|
@ -2766,6 +2768,9 @@ JS_DefineObject(JSContext *cx, JS::HandleObject obj, const char *name,
|
|||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineConstDoubles(JSContext *cx, JS::HandleObject obj, const JSConstDoubleSpec *cds);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineConstIntegers(JSContext *cx, JS::HandleObject obj, const JSConstIntegerSpec *cis);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperties(JSContext *cx, JS::HandleObject obj, const JSPropertySpec *ps);
|
||||
|
||||
|
@ -3286,7 +3291,7 @@ JS_NewPropertyIterator(JSContext *cx, JS::Handle<JSObject*> obj);
|
|||
* left to visit. Return false on error.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_NextProperty(JSContext *cx, JS::Handle<JSObject*> iterobj, jsid *idp);
|
||||
JS_NextProperty(JSContext *cx, JS::HandleObject iterobj, JS::MutableHandleId idp);
|
||||
|
||||
extern JS_PUBLIC_API(jsval)
|
||||
JS_GetReservedSlot(JSObject *obj, uint32_t index);
|
||||
|
|
|
@ -346,7 +346,7 @@ DeleteArrayElement(JSContext *cx, HandleObject obj, double index, bool *succeede
|
|||
obj->markDenseElementsNotPacked(cx);
|
||||
obj->setDenseElement(idx, MagicValue(JS_ELEMENTS_HOLE));
|
||||
}
|
||||
if (!js_SuppressDeletedElement(cx, obj, idx))
|
||||
if (!SuppressDeletedElement(cx, obj, idx))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1377,12 +1377,14 @@ array_reverse(JSContext *cx, unsigned argc, Value *vp)
|
|||
orighi = obj->getDenseElement(hi);
|
||||
obj->setDenseElement(lo, orighi);
|
||||
if (orighi.isMagic(JS_ELEMENTS_HOLE) &&
|
||||
!js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo))) {
|
||||
!SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
obj->setDenseElement(hi, origlo);
|
||||
if (origlo.isMagic(JS_ELEMENTS_HOLE) &&
|
||||
!js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi))) {
|
||||
!SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2211,7 +2213,7 @@ js::array_shift(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (!SetLengthProperty(cx, obj, newlen))
|
||||
return false;
|
||||
|
||||
return js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(newlen));
|
||||
return SuppressDeletedProperty(cx, obj, INT_TO_JSID(newlen));
|
||||
}
|
||||
|
||||
/* Steps 5, 10. */
|
||||
|
|
|
@ -1204,14 +1204,19 @@ date_now(JSContext *cx, unsigned argc, Value *vp)
|
|||
}
|
||||
|
||||
void
|
||||
DateObject::setUTCTime(double t, Value *vp)
|
||||
DateObject::setUTCTime(double t)
|
||||
{
|
||||
for (size_t ind = COMPONENTS_START_SLOT; ind < RESERVED_SLOTS; ind++)
|
||||
setReservedSlot(ind, UndefinedValue());
|
||||
|
||||
setFixedSlot(UTC_TIME_SLOT, DoubleValue(t));
|
||||
if (vp)
|
||||
vp->setDouble(t);
|
||||
}
|
||||
|
||||
void
|
||||
DateObject::setUTCTime(double t, MutableHandleValue vp)
|
||||
{
|
||||
setUTCTime(t);
|
||||
vp.setDouble(t);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1674,7 +1679,7 @@ date_setTime_impl(JSContext *cx, CallArgs args)
|
|||
{
|
||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||
if (args.length() == 0) {
|
||||
dateObj->setUTCTime(GenericNaN(), args.rval().address());
|
||||
dateObj->setUTCTime(GenericNaN(), args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1682,7 +1687,7 @@ date_setTime_impl(JSContext *cx, CallArgs args)
|
|||
if (!ToNumber(cx, args[0], &result))
|
||||
return false;
|
||||
|
||||
dateObj->setUTCTime(TimeClip(result), args.rval().address());
|
||||
dateObj->setUTCTime(TimeClip(result), args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1742,7 +1747,7 @@ date_setMilliseconds_impl(JSContext *cx, CallArgs args)
|
|||
double u = TimeClip(UTC(MakeDate(Day(t), time), &cx->runtime()->dateTimeInfo));
|
||||
|
||||
/* Steps 4-5. */
|
||||
dateObj->setUTCTime(u, args.rval().address());
|
||||
dateObj->setUTCTime(u, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1772,7 +1777,7 @@ date_setUTCMilliseconds_impl(JSContext *cx, CallArgs args)
|
|||
double v = TimeClip(MakeDate(Day(t), time));
|
||||
|
||||
/* Steps 4-5. */
|
||||
dateObj->setUTCTime(v, args.rval().address());
|
||||
dateObj->setUTCTime(v, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1809,7 +1814,7 @@ date_setSeconds_impl(JSContext *cx, CallArgs args)
|
|||
double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
|
||||
|
||||
/* Steps 6-7. */
|
||||
dateObj->setUTCTime(u, args.rval().address());
|
||||
dateObj->setUTCTime(u, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1846,7 +1851,7 @@ date_setUTCSeconds_impl(JSContext *cx, CallArgs args)
|
|||
double v = TimeClip(date);
|
||||
|
||||
/* Steps 6-7. */
|
||||
dateObj->setUTCTime(v, args.rval().address());
|
||||
dateObj->setUTCTime(v, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1888,7 +1893,7 @@ date_setMinutes_impl(JSContext *cx, CallArgs args)
|
|||
double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
|
||||
|
||||
/* Steps 7-8. */
|
||||
dateObj->setUTCTime(u, args.rval().address());
|
||||
dateObj->setUTCTime(u, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1930,7 +1935,7 @@ date_setUTCMinutes_impl(JSContext *cx, CallArgs args)
|
|||
double v = TimeClip(date);
|
||||
|
||||
/* Steps 7-8. */
|
||||
dateObj->setUTCTime(v, args.rval().address());
|
||||
dateObj->setUTCTime(v, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1977,7 +1982,7 @@ date_setHours_impl(JSContext *cx, CallArgs args)
|
|||
double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
|
||||
|
||||
/* Steps 7-8. */
|
||||
dateObj->setUTCTime(u, args.rval().address());
|
||||
dateObj->setUTCTime(u, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2024,7 +2029,7 @@ date_setUTCHours_impl(JSContext *cx, CallArgs args)
|
|||
double v = TimeClip(newDate);
|
||||
|
||||
/* Steps 8-9. */
|
||||
dateObj->setUTCTime(v, args.rval().address());
|
||||
dateObj->setUTCTime(v, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2056,7 +2061,7 @@ date_setDate_impl(JSContext *cx, CallArgs args)
|
|||
double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
|
||||
|
||||
/* Steps 5-6. */
|
||||
dateObj->setUTCTime(u, args.rval().address());
|
||||
dateObj->setUTCTime(u, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2088,7 +2093,7 @@ date_setUTCDate_impl(JSContext *cx, CallArgs args)
|
|||
double v = TimeClip(newDate);
|
||||
|
||||
/* Steps 5-6. */
|
||||
dateObj->setUTCTime(v, args.rval().address());
|
||||
dateObj->setUTCTime(v, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2145,7 +2150,7 @@ date_setMonth_impl(JSContext *cx, CallArgs args)
|
|||
double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
|
||||
|
||||
/* Steps 6-7. */
|
||||
dateObj->setUTCTime(u, args.rval().address());
|
||||
dateObj->setUTCTime(u, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2182,7 +2187,7 @@ date_setUTCMonth_impl(JSContext *cx, CallArgs args)
|
|||
double v = TimeClip(newDate);
|
||||
|
||||
/* Steps 6-7. */
|
||||
dateObj->setUTCTime(v, args.rval().address());
|
||||
dateObj->setUTCTime(v, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2240,7 +2245,7 @@ date_setFullYear_impl(JSContext *cx, CallArgs args)
|
|||
double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
|
||||
|
||||
/* Steps 7-8. */
|
||||
dateObj->setUTCTime(u, args.rval().address());
|
||||
dateObj->setUTCTime(u, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2282,7 +2287,7 @@ date_setUTCFullYear_impl(JSContext *cx, CallArgs args)
|
|||
double v = TimeClip(newDate);
|
||||
|
||||
/* Steps 7-8. */
|
||||
dateObj->setUTCTime(v, args.rval().address());
|
||||
dateObj->setUTCTime(v, args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2309,7 +2314,7 @@ date_setYear_impl(JSContext *cx, CallArgs args)
|
|||
|
||||
/* Step 3. */
|
||||
if (IsNaN(y)) {
|
||||
dateObj->setUTCTime(GenericNaN(), args.rval().address());
|
||||
dateObj->setUTCTime(GenericNaN(), args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2325,7 +2330,7 @@ date_setYear_impl(JSContext *cx, CallArgs args)
|
|||
double u = UTC(MakeDate(day, TimeWithinDay(t)), &cx->runtime()->dateTimeInfo);
|
||||
|
||||
/* Steps 7-8. */
|
||||
dateObj->setUTCTime(TimeClip(u), args.rval().address());
|
||||
dateObj->setUTCTime(TimeClip(u), args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -395,6 +395,14 @@ js::GetGlobalForObjectCrossCompartment(JSObject *obj)
|
|||
return &obj->global();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::GetPrototypeNoProxy(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(!obj->is<js::ProxyObject>());
|
||||
JS_ASSERT(!obj->getTaggedProto().isLazy());
|
||||
return obj->getTaggedProto().toObjectOrNull();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::SetPendingExceptionCrossContext(JSContext *cx, JS::HandleValue v)
|
||||
{
|
||||
|
|
|
@ -706,6 +706,9 @@ GetObjectParentMaybeScope(JSObject *obj);
|
|||
JS_FRIEND_API(JSObject *)
|
||||
GetGlobalForObjectCrossCompartment(JSObject *obj);
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
GetPrototypeNoProxy(JSObject *obj);
|
||||
|
||||
// Sidestep the activeContext checking implicitly performed in
|
||||
// JS_SetPendingException.
|
||||
JS_FRIEND_API(void)
|
||||
|
|
|
@ -1588,7 +1588,8 @@ void
|
|||
GCRuntime::removeFinalizeCallback(JSFinalizeCallback callback)
|
||||
{
|
||||
for (Callback<JSFinalizeCallback> *p = finalizeCallbacks.begin();
|
||||
p < finalizeCallbacks.end(); p++) {
|
||||
p < finalizeCallbacks.end(); p++)
|
||||
{
|
||||
if (p->op == callback) {
|
||||
finalizeCallbacks.erase(p);
|
||||
break;
|
||||
|
@ -1596,6 +1597,16 @@ GCRuntime::removeFinalizeCallback(JSFinalizeCallback callback)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::callFinalizeCallbacks(FreeOp *fop, JSFinalizeStatus status) const
|
||||
{
|
||||
for (const Callback<JSFinalizeCallback> *p = finalizeCallbacks.begin();
|
||||
p < finalizeCallbacks.end(); p++)
|
||||
{
|
||||
p->op(fop, status, !isFull, p->data);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GCRuntime::addMovingGCCallback(JSMovingGCCallback callback, void *data)
|
||||
{
|
||||
|
@ -1615,6 +1626,16 @@ GCRuntime::removeMovingGCCallback(JSMovingGCCallback callback)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::callMovingGCCallbacks() const
|
||||
{
|
||||
for (const Callback<JSMovingGCCallback> *p = movingCallbacks.begin();
|
||||
p < movingCallbacks.end(); p++)
|
||||
{
|
||||
p->op(rt, p->data);
|
||||
}
|
||||
}
|
||||
|
||||
JS::GCSliceCallback
|
||||
GCRuntime::setSliceCallback(JS::GCSliceCallback callback) {
|
||||
return stats.setSliceCallback(callback);
|
||||
|
@ -2438,11 +2459,7 @@ GCRuntime::updatePointersToRelocatedCells()
|
|||
MovingTracer::Sweep(&trc);
|
||||
|
||||
// Call callbacks to get the rest of the system to fixup other untraced pointers.
|
||||
for (Callback<JSMovingGCCallback> *p = rt->gc.movingCallbacks.begin();
|
||||
p < rt->gc.movingCallbacks.end(); p++)
|
||||
{
|
||||
p->op(rt, p->data);
|
||||
}
|
||||
callMovingGCCallbacks();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4623,11 +4640,7 @@ GCRuntime::beginSweepingZoneGroup()
|
|||
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_FINALIZE_START);
|
||||
for (Callback<JSFinalizeCallback> *p = rt->gc.finalizeCallbacks.begin();
|
||||
p < rt->gc.finalizeCallbacks.end(); p++)
|
||||
{
|
||||
p->op(&fop, JSFINALIZE_GROUP_START, !isFull /* unused */, p->data);
|
||||
}
|
||||
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_START);
|
||||
}
|
||||
|
||||
if (sweepingAtoms) {
|
||||
|
@ -4724,11 +4737,7 @@ GCRuntime::beginSweepingZoneGroup()
|
|||
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_FINALIZE_END);
|
||||
for (Callback<JSFinalizeCallback> *p = rt->gc.finalizeCallbacks.begin();
|
||||
p < rt->gc.finalizeCallbacks.end(); p++)
|
||||
{
|
||||
p->op(&fop, JSFINALIZE_GROUP_END, !isFull /* unused */, p->data);
|
||||
}
|
||||
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_END);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4962,12 +4971,7 @@ GCRuntime::endSweepPhase(bool lastGC)
|
|||
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_FINALIZE_END);
|
||||
|
||||
for (Callback<JSFinalizeCallback> *p = rt->gc.finalizeCallbacks.begin();
|
||||
p < rt->gc.finalizeCallbacks.end(); p++)
|
||||
{
|
||||
p->op(&fop, JSFINALIZE_COLLECTION_END, !isFull, p->data);
|
||||
}
|
||||
callFinalizeCallbacks(&fop, JSFINALIZE_COLLECTION_END);
|
||||
|
||||
/* If we finished a full GC, then the gray bits are correct. */
|
||||
if (isFull)
|
||||
|
|
|
@ -817,7 +817,7 @@ js::CreateItrResultObject(JSContext *cx, HandleValue value, bool done)
|
|||
}
|
||||
|
||||
bool
|
||||
js_ThrowStopIteration(JSContext *cx)
|
||||
js::ThrowStopIteration(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(!JS_IsExceptionPending(cx));
|
||||
|
||||
|
@ -865,15 +865,15 @@ iterator_next_impl(JSContext *cx, CallArgs args)
|
|||
RootedObject thisObj(cx, &args.thisv().toObject());
|
||||
|
||||
bool more;
|
||||
if (!js_IteratorMore(cx, thisObj, &more))
|
||||
if (!IteratorMore(cx, thisObj, &more))
|
||||
return false;
|
||||
|
||||
if (!more) {
|
||||
js_ThrowStopIteration(cx);
|
||||
ThrowStopIteration(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return js_IteratorNext(cx, thisObj, args.rval());
|
||||
return IteratorNext(cx, thisObj, args.rval());
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1209,7 +1209,7 @@ public:
|
|||
} /* anonymous namespace */
|
||||
|
||||
bool
|
||||
js_SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id)
|
||||
js::SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id)
|
||||
{
|
||||
if (JSID_IS_SYMBOL(id))
|
||||
return true;
|
||||
|
@ -1221,12 +1221,12 @@ js_SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id)
|
|||
}
|
||||
|
||||
bool
|
||||
js_SuppressDeletedElement(JSContext *cx, HandleObject obj, uint32_t index)
|
||||
js::SuppressDeletedElement(JSContext *cx, HandleObject obj, uint32_t index)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return js_SuppressDeletedProperty(cx, obj, id);
|
||||
return SuppressDeletedProperty(cx, obj, id);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -1248,13 +1248,13 @@ class IndexRangePredicate {
|
|||
} /* anonymous namespace */
|
||||
|
||||
bool
|
||||
js_SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end)
|
||||
js::SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end)
|
||||
{
|
||||
return SuppressDeletedPropertyHelper(cx, obj, IndexRangePredicate(begin, end));
|
||||
}
|
||||
|
||||
bool
|
||||
js_IteratorMore(JSContext *cx, HandleObject iterobj, bool *res)
|
||||
js::IteratorMore(JSContext *cx, HandleObject iterobj, bool *res)
|
||||
{
|
||||
/* Fast path for native iterators */
|
||||
NativeIterator *ni = nullptr;
|
||||
|
@ -1320,7 +1320,7 @@ js_IteratorMore(JSContext *cx, HandleObject iterobj, bool *res)
|
|||
}
|
||||
|
||||
bool
|
||||
js_IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
|
||||
js::IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
|
||||
{
|
||||
/* Fast path for native iterators */
|
||||
if (iterobj->is<PropertyIteratorObject>()) {
|
||||
|
@ -1888,7 +1888,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, HandleObject obj,
|
|||
// if needed.
|
||||
rval.setUndefined();
|
||||
if (op != JSGENOP_CLOSE)
|
||||
ok = js_ThrowStopIteration(cx);
|
||||
ok = ThrowStopIteration(cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1936,7 +1936,7 @@ legacy_generator_next(JSContext *cx, CallArgs args)
|
|||
|
||||
JSGenerator *gen = thisObj->as<LegacyGeneratorObject>().getGenerator();
|
||||
if (gen->state == JSGEN_CLOSED)
|
||||
return js_ThrowStopIteration(cx);
|
||||
return ThrowStopIteration(cx);
|
||||
|
||||
return SendToGenerator(cx, JSGENOP_SEND, thisObj, gen, args.get(0), LegacyGenerator,
|
||||
args.rval());
|
||||
|
|
|
@ -183,7 +183,7 @@ bool
|
|||
CloseIterator(JSContext *cx, HandleObject iterObj);
|
||||
|
||||
bool
|
||||
UnwindIteratorForException(JSContext *cx, js::HandleObject obj);
|
||||
UnwindIteratorForException(JSContext *cx, HandleObject obj);
|
||||
|
||||
void
|
||||
UnwindIteratorForUncatchableException(JSContext *cx, JSObject *obj);
|
||||
|
@ -191,16 +191,14 @@ UnwindIteratorForUncatchableException(JSContext *cx, JSObject *obj);
|
|||
bool
|
||||
IteratorConstructor(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
} /* namespace js */
|
||||
extern bool
|
||||
SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id);
|
||||
|
||||
extern bool
|
||||
js_SuppressDeletedProperty(JSContext *cx, js::HandleObject obj, jsid id);
|
||||
SuppressDeletedElement(JSContext *cx, HandleObject obj, uint32_t index);
|
||||
|
||||
extern bool
|
||||
js_SuppressDeletedElement(JSContext *cx, js::HandleObject obj, uint32_t index);
|
||||
|
||||
extern bool
|
||||
js_SuppressDeletedElements(JSContext *cx, js::HandleObject obj, uint32_t begin, uint32_t end);
|
||||
SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end);
|
||||
|
||||
/*
|
||||
* IteratorMore() indicates whether another value is available. It might
|
||||
|
@ -208,22 +206,20 @@ js_SuppressDeletedElements(JSContext *cx, js::HandleObject obj, uint32_t begin,
|
|||
* picked up by IteratorNext(). The value is cached in the current context.
|
||||
*/
|
||||
extern bool
|
||||
js_IteratorMore(JSContext *cx, js::HandleObject iterobj, bool *res);
|
||||
IteratorMore(JSContext *cx, HandleObject iterobj, bool *res);
|
||||
|
||||
extern bool
|
||||
js_IteratorNext(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval);
|
||||
IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval);
|
||||
|
||||
extern bool
|
||||
js_ThrowStopIteration(JSContext *cx);
|
||||
|
||||
namespace js {
|
||||
ThrowStopIteration(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Create an object of the form { value: VALUE, done: DONE }.
|
||||
* ES6 draft from 2013-09-05, section 25.4.3.4.
|
||||
*/
|
||||
extern JSObject *
|
||||
CreateItrResultObject(JSContext *cx, js::HandleValue value, bool done);
|
||||
CreateItrResultObject(JSContext *cx, HandleValue value, bool done);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
|
|
|
@ -50,15 +50,15 @@ using JS::ToNumber;
|
|||
using JS::GenericNaN;
|
||||
|
||||
static const JSConstDoubleSpec math_constants[] = {
|
||||
{M_E, "E", 0, {0,0,0}},
|
||||
{M_LOG2E, "LOG2E", 0, {0,0,0}},
|
||||
{M_LOG10E, "LOG10E", 0, {0,0,0}},
|
||||
{M_LN2, "LN2", 0, {0,0,0}},
|
||||
{M_LN10, "LN10", 0, {0,0,0}},
|
||||
{M_PI, "PI", 0, {0,0,0}},
|
||||
{M_SQRT2, "SQRT2", 0, {0,0,0}},
|
||||
{M_SQRT1_2, "SQRT1_2", 0, {0,0,0}},
|
||||
{0,0,0,{0,0,0}}
|
||||
{"E" , M_E },
|
||||
{"LOG2E" , M_LOG2E },
|
||||
{"LOG10E" , M_LOG10E },
|
||||
{"LN2" , M_LN2 },
|
||||
{"LN10" , M_LN10 },
|
||||
{"PI" , M_PI },
|
||||
{"SQRT2" , M_SQRT2 },
|
||||
{"SQRT1_2", M_SQRT1_2 },
|
||||
{0,0}
|
||||
};
|
||||
|
||||
MathCache::MathCache() {
|
||||
|
|
|
@ -1061,18 +1061,18 @@ enum nc_slot {
|
|||
* using union jsdpun.
|
||||
*/
|
||||
static JSConstDoubleSpec number_constants[] = {
|
||||
{0, "NaN", 0,{0,0,0}},
|
||||
{0, "POSITIVE_INFINITY", 0,{0,0,0}},
|
||||
{0, "NEGATIVE_INFINITY", 0,{0,0,0}},
|
||||
{1.7976931348623157E+308, "MAX_VALUE", 0,{0,0,0}},
|
||||
{0, "MIN_VALUE", 0,{0,0,0}},
|
||||
{"NaN", 0 },
|
||||
{"POSITIVE_INFINITY", 0 },
|
||||
{"NEGATIVE_INFINITY", 0 },
|
||||
{"MAX_VALUE", 1.7976931348623157E+308 },
|
||||
{"MIN_VALUE", 0 },
|
||||
/* ES6 (April 2014 draft) 20.1.2.6 */
|
||||
{9007199254740991, "MAX_SAFE_INTEGER", 0,{0,0,0}},
|
||||
{"MAX_SAFE_INTEGER", 9007199254740991 },
|
||||
/* ES6 (April 2014 draft) 20.1.2.10 */
|
||||
{-9007199254740991, "MIN_SAFE_INTEGER", 0,{0,0,0}},
|
||||
{"MIN_SAFE_INTEGER", -9007199254740991, },
|
||||
/* ES6 (May 2013 draft) 15.7.3.7 */
|
||||
{2.2204460492503130808472633361816e-16, "EPSILON", 0,{0,0,0}},
|
||||
{0,0,0,{0,0,0}}
|
||||
{"EPSILON", 2.2204460492503130808472633361816e-16},
|
||||
{0,0}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1101,12 +1101,12 @@ js::InitRuntimeNumberState(JSRuntime *rt)
|
|||
* Our NaN must be one particular canonical value, because we rely on NaN
|
||||
* encoding for our value representation. See Value.h.
|
||||
*/
|
||||
number_constants[NC_NaN].dval = GenericNaN();
|
||||
number_constants[NC_NaN].val = GenericNaN();
|
||||
|
||||
number_constants[NC_POSITIVE_INFINITY].dval = mozilla::PositiveInfinity<double>();
|
||||
number_constants[NC_NEGATIVE_INFINITY].dval = mozilla::NegativeInfinity<double>();
|
||||
number_constants[NC_POSITIVE_INFINITY].val = mozilla::PositiveInfinity<double>();
|
||||
number_constants[NC_NEGATIVE_INFINITY].val = mozilla::NegativeInfinity<double>();
|
||||
|
||||
number_constants[NC_MIN_VALUE].dval = MinNumberValue<double>();
|
||||
number_constants[NC_MIN_VALUE].val = MinNumberValue<double>();
|
||||
|
||||
// XXX If EXPOSE_INTL_API becomes true all the time at some point,
|
||||
// js::InitRuntimeNumberState is no longer fallible, and we should
|
||||
|
|
|
@ -5749,7 +5749,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe
|
|||
return false;
|
||||
|
||||
obj->setDenseElementHole(cx, JSID_TO_INT(id));
|
||||
return js_SuppressDeletedProperty(cx, obj, id);
|
||||
return SuppressDeletedProperty(cx, obj, id);
|
||||
}
|
||||
|
||||
if (!shape->configurable()) {
|
||||
|
@ -5763,7 +5763,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe
|
|||
if (!succeeded)
|
||||
return true;
|
||||
|
||||
return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id);
|
||||
return obj->removeProperty(cx, id) && SuppressDeletedProperty(cx, obj, id);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -124,7 +124,6 @@ enum JSGCTraceKind {
|
|||
/* Struct forward declarations. */
|
||||
struct JSClass;
|
||||
struct JSCompartment;
|
||||
struct JSConstDoubleSpec;
|
||||
struct JSCrossCompartmentCall;
|
||||
struct JSErrorReport;
|
||||
struct JSExceptionState;
|
||||
|
@ -148,6 +147,10 @@ class JSFlatString;
|
|||
typedef struct PRCallOnceType JSCallOnceType;
|
||||
typedef bool (*JSInitCallback)(void);
|
||||
|
||||
template<typename T> struct JSConstScalarSpec;
|
||||
typedef JSConstScalarSpec<double> JSConstDoubleSpec;
|
||||
typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
|
||||
|
||||
/*
|
||||
* Generic trace operation that calls JS_CallTracer on each traceable thing
|
||||
* stored in data.
|
||||
|
|
|
@ -712,7 +712,7 @@ js::proxy_DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succ
|
|||
if (!Proxy::delete_(cx, obj, id, &deleted))
|
||||
return false;
|
||||
*succeeded = deleted;
|
||||
return js_SuppressDeletedProperty(cx, obj, id);
|
||||
return SuppressDeletedProperty(cx, obj, id);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#define vm_CommonPropertyNames_h
|
||||
|
||||
#include "jsprototypes.h"
|
||||
#include "builtin/SIMDShuffleMaskConstants.h"
|
||||
|
||||
#define FOR_EACH_COMMON_PROPERTYNAME(macro) \
|
||||
macro(anonymous, anonymous, "anonymous") \
|
||||
|
@ -232,6 +231,5 @@
|
|||
macro(Symbol_toPrimitive, Symbol_toPrimitive, "Symbol.toPrimitive") \
|
||||
macro(Symbol_toStringTag, Symbol_toStringTag, "Symbol.toStringTag") \
|
||||
macro(Symbol_unscopables, Symbol_unscopables, "Symbol.unscopables") \
|
||||
FOR_EACH_SIMD_SHUFFLE_MASK(COMMON_PROPERTY_NAMES_MACRO, macro)
|
||||
|
||||
#endif /* vm_CommonPropertyNames_h */
|
||||
|
|
|
@ -46,7 +46,8 @@ class DateObject : public JSObject
|
|||
}
|
||||
|
||||
// Set UTC time to a given time and invalidate cached local time.
|
||||
void setUTCTime(double t, Value *vp = nullptr);
|
||||
void setUTCTime(double t);
|
||||
void setUTCTime(double t, MutableHandleValue vp);
|
||||
|
||||
inline double cachedLocalTime(DateTimeInfo *dtInfo);
|
||||
|
||||
|
|
|
@ -1116,21 +1116,6 @@ JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
|
|||
JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH);
|
||||
JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1);
|
||||
|
||||
bool
|
||||
js::IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
|
||||
{
|
||||
if (iterobj->is<PropertyIteratorObject>()) {
|
||||
NativeIterator *ni = iterobj->as<PropertyIteratorObject>().getNativeIterator();
|
||||
if (ni->isKeyIter()) {
|
||||
JS_ASSERT(ni->props_cursor < ni->props_end);
|
||||
rval.setString(*ni->current());
|
||||
ni->incCursor();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return js_IteratorNext(cx, iterobj, rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the implicit |this| parameter for a call expression where the callee
|
||||
* funval was resolved from an unqualified name reference to a property on obj
|
||||
|
@ -1909,7 +1894,7 @@ CASE(JSOP_MOREITER)
|
|||
RootedObject &obj = rootObject0;
|
||||
obj = ®S.sp[-2].toObject();
|
||||
bool cond;
|
||||
if (!js_IteratorMore(cx, obj, &cond))
|
||||
if (!IteratorMore(cx, obj, &cond))
|
||||
goto error;
|
||||
REGS.sp[-1].setBoolean(cond);
|
||||
}
|
||||
|
|
|
@ -439,9 +439,6 @@ bool
|
|||
ImplicitThisOperation(JSContext *cx, HandleObject scopeObj, HandlePropertyName name,
|
||||
MutableHandleValue res);
|
||||
|
||||
bool
|
||||
IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval);
|
||||
|
||||
bool
|
||||
RunOnceScriptPrologue(JSContext *cx, HandleScript script);
|
||||
|
||||
|
|
|
@ -637,22 +637,14 @@ xpc::SandboxProxyHandler::getPropertyDescriptor(JSContext *cx,
|
|||
if (!desc.object())
|
||||
return true; // No property, nothing to do
|
||||
|
||||
// Now fix up the getter/setter/value as needed to be bound to desc->obj
|
||||
// Don't mess with holder_get and holder_set, though, because those rely on
|
||||
// the "vp is prefilled with the value in the slot" behavior that property
|
||||
// ops can in theory rely on, but our property op forwarder doesn't know how
|
||||
// to make that happen. Since we really only need to rebind the DOM methods
|
||||
// here, not rebindings holder_get and holder_set is OK.
|
||||
// Now fix up the getter/setter/value as needed to be bound to desc->obj.
|
||||
//
|
||||
// Similarly, don't mess with XPC_WN_Helper_GetProperty and
|
||||
// XPC_WN_Helper_SetProperty, for the same reasons: that could confuse our
|
||||
// access to expandos when we're not doing Xrays.
|
||||
if (desc.getter() != xpc::holder_get &&
|
||||
desc.getter() != XPC_WN_Helper_GetProperty &&
|
||||
// Don't mess with XPC_WN_Helper_GetProperty and XPC_WN_Helper_SetProperty,
|
||||
// because that could confuse our access to expandos.
|
||||
if (desc.getter() != XPC_WN_Helper_GetProperty &&
|
||||
!BindPropertyOp(cx, desc.getter(), desc.address(), id, JSPROP_GETTER, proxy))
|
||||
return false;
|
||||
if (desc.setter() != xpc::holder_set &&
|
||||
desc.setter() != XPC_WN_Helper_SetProperty &&
|
||||
if (desc.setter() != XPC_WN_Helper_SetProperty &&
|
||||
!BindPropertyOp(cx, desc.setter(), desc.address(), id, JSPROP_SETTER, proxy))
|
||||
return false;
|
||||
if (desc.value().isObject()) {
|
||||
|
|
|
@ -575,6 +575,25 @@ WindowGlobalOrNull(JSObject *aObj)
|
|||
return WindowOrNull(glob);
|
||||
}
|
||||
|
||||
nsGlobalWindow*
|
||||
AddonWindowOrNull(JSObject *aObj)
|
||||
{
|
||||
if (!IsInAddonScope(aObj))
|
||||
return nullptr;
|
||||
|
||||
JSObject *global = js::GetGlobalForObjectCrossCompartment(aObj);
|
||||
JSObject *proto = js::GetPrototypeNoProxy(global);
|
||||
|
||||
// Addons could theoretically change the prototype of the addon scope, but
|
||||
// we pretty much just want to crash if that happens so that we find out
|
||||
// about it and get them to change their code.
|
||||
MOZ_RELEASE_ASSERT(js::IsCrossCompartmentWrapper(proto));
|
||||
JSObject *mainGlobal = js::UncheckedUnwrap(proto, /* stopAtOuter = */ false);
|
||||
MOZ_RELEASE_ASSERT(JS_IsGlobalObject(mainGlobal));
|
||||
|
||||
return WindowOrNull(mainGlobal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -70,8 +70,11 @@ nsXPCWrappedJS::CanSkip()
|
|||
|
||||
// For non-root wrappers, check if the root wrapper will be
|
||||
// added to the CC graph.
|
||||
if (!IsRootWrapper())
|
||||
if (!IsRootWrapper()) {
|
||||
// mRoot points to null after unlinking.
|
||||
NS_ENSURE_TRUE(mRoot, false);
|
||||
return mRoot->CanSkip();
|
||||
}
|
||||
|
||||
// For the root wrapper, check if there is an aggregated
|
||||
// native object that will be added to the CC graph.
|
||||
|
|
|
@ -472,6 +472,14 @@ WindowOrNull(JSObject *aObj);
|
|||
nsGlobalWindow*
|
||||
WindowGlobalOrNull(JSObject *aObj);
|
||||
|
||||
/**
|
||||
* If |aObj| is in an addon scope and that addon scope is associated with a
|
||||
* live DOM Window, returns the associated nsGlobalWindow. Otherwise, returns
|
||||
* null.
|
||||
*/
|
||||
nsGlobalWindow*
|
||||
AddonWindowOrNull(JSObject *aObj);
|
||||
|
||||
// Error reporter used when there is no associated DOM window on to which to
|
||||
// report errors and warnings.
|
||||
//
|
||||
|
|
|
@ -185,7 +185,7 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, HandleObject wrapper, H
|
|||
// Check for frame IDs. If we're resolving named frames, make sure to only
|
||||
// resolve ones that don't shadow native properties. See bug 860494.
|
||||
if (IsWindow(name)) {
|
||||
if (JSID_IS_STRING(id) && !XrayUtils::IsXrayResolving(cx, wrapper, id)) {
|
||||
if (JSID_IS_STRING(id)) {
|
||||
bool wouldShadow = false;
|
||||
if (!XrayUtils::HasNativeProperty(cx, wrapper, id, &wouldShadow) ||
|
||||
wouldShadow)
|
||||
|
|
|
@ -156,22 +156,6 @@ bool
|
|||
FilteringWrapper<Base, Policy>::enter(JSContext *cx, HandleObject wrapper,
|
||||
HandleId id, Wrapper::Action act, bool *bp) const
|
||||
{
|
||||
// This is a super ugly hacky to get around Xray Resolve wonkiness.
|
||||
//
|
||||
// Basically, XPCWN Xrays sometimes call into the Resolve hook of the
|
||||
// scriptable helper, and pass the wrapper itself as the object upon which
|
||||
// the resolve is happening. Then, special handling happens in
|
||||
// XrayWrapper::defineProperty to detect the resolve and redefine the
|
||||
// property on the holder. Really, we should just pass the holder itself to
|
||||
// NewResolve, but there's too much code in nsDOMClassInfo that assumes this
|
||||
// isn't the case (in particular, code expects to be able to look up
|
||||
// properties on the object, which doesn't work for the holder). Given that
|
||||
// these hooks are going away eventually with the new DOM bindings, let's
|
||||
// just hack around this for now.
|
||||
if (XrayUtils::IsXrayResolving(cx, wrapper, id)) {
|
||||
*bp = true;
|
||||
return true;
|
||||
}
|
||||
if (!Policy::check(cx, wrapper, id, act)) {
|
||||
*bp = JS_IsExceptionPending(cx) ? false : Policy::deny(act, id);
|
||||
return false;
|
||||
|
@ -240,11 +224,6 @@ CrossOriginXrayWrapper::defineProperty(JSContext *cx, JS::Handle<JSObject*> wrap
|
|||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc) const
|
||||
{
|
||||
// Until XPCWN Xrays go away, we'll have native resolves looping back
|
||||
// through here.
|
||||
if (XrayUtils::IsXrayResolving(cx, wrapper, id))
|
||||
return SecurityXrayDOM::defineProperty(cx, wrapper, id, desc);
|
||||
|
||||
JS_ReportError(cx, "Permission denied to define property on cross-origin object");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -596,13 +596,6 @@ WrapperFactory::WaiveXrayAndWrap(JSContext *cx, MutableHandleObject argObj)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperFactory::XrayWrapperNotShadowing(JSObject *wrapper, jsid id)
|
||||
{
|
||||
ResolvingId *rid = ResolvingId::getResolvingIdFromWrapper(wrapper);
|
||||
return rid->isXrayShadowing(id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calls to JS_TransplantObject* should go through these helpers here so that
|
||||
* waivers get fixed up properly.
|
||||
|
|
|
@ -52,9 +52,6 @@ class WrapperFactory {
|
|||
// Wrap wrapped object into a waiver wrapper and then re-wrap it.
|
||||
static bool WaiveXrayAndWrap(JSContext *cx, JS::MutableHandleValue vp);
|
||||
static bool WaiveXrayAndWrap(JSContext *cx, JS::MutableHandleObject object);
|
||||
|
||||
// Returns true if the wrapper is in not shadowing mode for the id.
|
||||
static bool XrayWrapperNotShadowing(JSObject *wrapper, jsid id);
|
||||
};
|
||||
|
||||
extern const js::Wrapper XrayWaiver;
|
||||
|
|
|
@ -126,62 +126,6 @@ XrayAwareCalleeGlobal(JSObject *fun)
|
|||
return js::GetGlobalForObjectCrossCompartment(scope);
|
||||
}
|
||||
|
||||
const uint32_t JSSLOT_RESOLVING = 0;
|
||||
ResolvingId::ResolvingId(JSContext *cx, HandleObject wrapper, HandleId id)
|
||||
: mId(id),
|
||||
mHolder(cx, getHolderObject(wrapper)),
|
||||
mPrev(getResolvingId(mHolder)),
|
||||
mXrayShadowing(false)
|
||||
{
|
||||
js::SetReservedSlot(mHolder, JSSLOT_RESOLVING, js::PrivateValue(this));
|
||||
}
|
||||
|
||||
ResolvingId::~ResolvingId()
|
||||
{
|
||||
MOZ_ASSERT(getResolvingId(mHolder) == this, "unbalanced ResolvingIds");
|
||||
js::SetReservedSlot(mHolder, JSSLOT_RESOLVING, js::PrivateValue(mPrev));
|
||||
}
|
||||
|
||||
bool
|
||||
ResolvingId::isXrayShadowing(jsid id)
|
||||
{
|
||||
if (!mXrayShadowing)
|
||||
return false;
|
||||
|
||||
return mId == id;
|
||||
}
|
||||
|
||||
bool
|
||||
ResolvingId::isResolving(jsid id)
|
||||
{
|
||||
for (ResolvingId *cur = this; cur; cur = cur->mPrev) {
|
||||
if (cur->mId == id)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ResolvingId *
|
||||
ResolvingId::getResolvingId(JSObject *holder)
|
||||
{
|
||||
MOZ_ASSERT(strcmp(JS_GetClass(holder)->name, "NativePropertyHolder") == 0);
|
||||
return (ResolvingId *)js::GetReservedSlot(holder, JSSLOT_RESOLVING).toPrivate();
|
||||
}
|
||||
|
||||
JSObject *
|
||||
ResolvingId::getHolderObject(JSObject *wrapper)
|
||||
{
|
||||
return &js::GetProxyExtra(wrapper, 0).toObject();
|
||||
}
|
||||
|
||||
ResolvingId *
|
||||
ResolvingId::getResolvingIdFromWrapper(JSObject *wrapper)
|
||||
{
|
||||
return getResolvingId(getHolderObject(wrapper));
|
||||
}
|
||||
|
||||
|
||||
JSObject *
|
||||
XrayTraits::getExpandoChain(HandleObject obj)
|
||||
{
|
||||
|
@ -203,8 +147,9 @@ XPCWrappedNativeXrayTraits::getWN(JSObject *wrapper)
|
|||
|
||||
const JSClass XPCWrappedNativeXrayTraits::HolderClass = {
|
||||
"NativePropertyHolder", JSCLASS_HAS_RESERVED_SLOTS(2),
|
||||
JS_PropertyStub, JS_DeletePropertyStub, holder_get, holder_set,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
|
||||
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub,
|
||||
JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub,
|
||||
JS_ConvertStub
|
||||
};
|
||||
|
||||
|
||||
|
@ -1087,16 +1032,6 @@ XrayTraits::ensureHolder(JSContext *cx, HandleObject wrapper)
|
|||
return holder;
|
||||
}
|
||||
|
||||
bool
|
||||
XPCWrappedNativeXrayTraits::isResolving(JSContext *cx, JSObject *holder,
|
||||
jsid id)
|
||||
{
|
||||
ResolvingId *cur = ResolvingId::getResolvingId(holder);
|
||||
if (!cur)
|
||||
return false;
|
||||
return cur->isResolving(id);
|
||||
}
|
||||
|
||||
namespace XrayUtils {
|
||||
|
||||
bool
|
||||
|
@ -1107,135 +1042,6 @@ IsXPCWNHolderClass(const JSClass *clasp)
|
|||
|
||||
}
|
||||
|
||||
|
||||
// Some DOM objects have shared properties that don't have an explicit
|
||||
// getter/setter and rely on the class getter/setter. We install a
|
||||
// class getter/setter on the holder object to trigger them.
|
||||
bool
|
||||
holder_get(JSContext *cx, HandleObject wrapper, HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
// JSClass::getProperty is wacky enough that it's hard to be sure someone
|
||||
// can't inherit this getter by prototyping a random object to an
|
||||
// XrayWrapper. Be safe.
|
||||
NS_ENSURE_TRUE(WrapperFactory::IsXrayWrapper(wrapper), true);
|
||||
JSObject *holder = GetHolder(wrapper);
|
||||
|
||||
XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
|
||||
if (NATIVE_HAS_FLAG(wn, WantGetProperty)) {
|
||||
JSAutoCompartment ac(cx, holder);
|
||||
bool retval = true;
|
||||
nsresult rv = wn->GetScriptableCallback()->GetProperty(wn, cx, wrapper,
|
||||
id, vp.address(), &retval);
|
||||
if (NS_FAILED(rv) || !retval) {
|
||||
if (retval)
|
||||
XPCThrower::Throw(rv, cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
holder_set(JSContext *cx, HandleObject wrapper, HandleId id, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
// JSClass::setProperty is wacky enough that it's hard to be sure someone
|
||||
// can't inherit this getter by prototyping a random object to an
|
||||
// XrayWrapper. Be safe.
|
||||
NS_ENSURE_TRUE(WrapperFactory::IsXrayWrapper(wrapper), true);
|
||||
JSObject *holder = GetHolder(wrapper);
|
||||
if (XPCWrappedNativeXrayTraits::isResolving(cx, holder, id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
|
||||
if (NATIVE_HAS_FLAG(wn, WantSetProperty)) {
|
||||
JSAutoCompartment ac(cx, holder);
|
||||
bool retval = true;
|
||||
nsresult rv = wn->GetScriptableCallback()->SetProperty(wn, cx, wrapper,
|
||||
id, vp.address(), &retval);
|
||||
if (NS_FAILED(rv) || !retval) {
|
||||
if (retval)
|
||||
XPCThrower::Throw(rv, cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class AutoSetWrapperNotShadowing
|
||||
{
|
||||
public:
|
||||
explicit AutoSetWrapperNotShadowing(ResolvingId *resolvingId MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
MOZ_ASSERT(resolvingId);
|
||||
mResolvingId = resolvingId;
|
||||
mResolvingId->mXrayShadowing = true;
|
||||
}
|
||||
|
||||
~AutoSetWrapperNotShadowing()
|
||||
{
|
||||
mResolvingId->mXrayShadowing = false;
|
||||
}
|
||||
|
||||
private:
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
ResolvingId *mResolvingId;
|
||||
};
|
||||
|
||||
// This is called after the resolveNativeProperty could not find any property
|
||||
// with the given id. At this point we can check for DOM specific collections
|
||||
// like document["formName"] because we already know that it is not shadowing
|
||||
// any native property.
|
||||
bool
|
||||
XPCWrappedNativeXrayTraits::resolveDOMCollectionProperty(JSContext *cx, HandleObject wrapper,
|
||||
HandleObject holder, HandleId id,
|
||||
MutableHandle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
// If we are not currently resolving this id and resolveNative is called
|
||||
// we don't do anything. (see defineProperty in case of shadowing is forbidden).
|
||||
ResolvingId *rid = ResolvingId::getResolvingId(holder);
|
||||
if (!rid || rid->mId != id)
|
||||
return true;
|
||||
|
||||
XPCWrappedNative *wn = getWN(wrapper);
|
||||
if (!wn) {
|
||||
// This should NEVER happen, but let's be extra careful here
|
||||
// because of the reported crashes (Bug 832091).
|
||||
XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
|
||||
return false;
|
||||
}
|
||||
if (!NATIVE_HAS_FLAG(wn, WantNewResolve))
|
||||
return true;
|
||||
|
||||
ResolvingId *resolvingId = ResolvingId::getResolvingIdFromWrapper(wrapper);
|
||||
if (!resolvingId) {
|
||||
// This should NEVER happen, but let's be extra careful here
|
||||
// becaue of the reported crashes (Bug 832091).
|
||||
XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setting the current ResolvingId in non-shadowing mode. So for this id
|
||||
// Xray won't ignore DOM specific collection properties temporarily.
|
||||
AutoSetWrapperNotShadowing asw(resolvingId);
|
||||
|
||||
bool retval = true;
|
||||
RootedObject pobj(cx);
|
||||
nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, wrapper, id,
|
||||
pobj.address(), &retval);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (retval)
|
||||
XPCThrower::Throw(rv, cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pobj && !JS_GetPropertyDescriptorById(cx, holder, id, desc))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static nsGlobalWindow*
|
||||
AsWindow(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
|
@ -1285,14 +1091,9 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr
|
|||
XPCCallContext ccx(JS_CALLER, cx, target, NullPtr(), id);
|
||||
|
||||
// There are no native numeric (or symbol-keyed) properties, so we can
|
||||
// shortcut here. We will not find the property. However we want to support
|
||||
// non shadowing dom specific collection properties like window.frames, so
|
||||
// we still have to check for those.
|
||||
if (!JSID_IS_STRING(id)) {
|
||||
/* Not found */
|
||||
return resolveDOMCollectionProperty(cx, wrapper, holder, id, desc);
|
||||
}
|
||||
|
||||
// shortcut here. We will not find the property.
|
||||
if (!JSID_IS_STRING(id))
|
||||
return true;
|
||||
|
||||
// The |controllers| property is accessible as a [ChromeOnly] property on
|
||||
// Window.WebIDL, and [noscript] in XPIDL. Chrome needs to see this over
|
||||
|
@ -1346,15 +1147,12 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr
|
|||
XPCWrappedNative *wn = getWN(wrapper);
|
||||
|
||||
if (ccx.GetWrapper() != wn || !wn->IsValid()) {
|
||||
// Something is wrong. If the wrapper is not even valid let's not risk
|
||||
// calling resolveDOMCollectionProperty.
|
||||
return true;
|
||||
} else if (!(iface = ccx.GetInterface()) ||
|
||||
!(member = ccx.GetMember())) {
|
||||
/* Not found */
|
||||
return resolveDOMCollectionProperty(cx, wrapper, holder, id, desc);
|
||||
}
|
||||
|
||||
if (!(iface = ccx.GetInterface()) || !(member = ccx.GetMember()))
|
||||
return true;
|
||||
|
||||
desc.object().set(holder);
|
||||
desc.setAttributes(JSPROP_ENUMERATE);
|
||||
desc.setGetter(nullptr);
|
||||
|
@ -1541,45 +1339,6 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsW
|
|||
// in the wrapper's compartment here, not the wrappee.
|
||||
MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
|
||||
|
||||
bool hasProp;
|
||||
if (!JS_HasPropertyById(cx, holder, id, &hasProp)) {
|
||||
return false;
|
||||
}
|
||||
if (!hasProp) {
|
||||
XPCWrappedNative *wn = getWN(wrapper);
|
||||
|
||||
// Run the resolve hook of the wrapped native.
|
||||
if (!NATIVE_HAS_FLAG(wn, WantNewResolve)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool retval = true;
|
||||
RootedObject pobj(cx);
|
||||
nsIXPCScriptable *callback = wn->GetScriptableInfo()->GetCallback();
|
||||
nsresult rv = callback->NewResolve(wn, cx, wrapper, id, pobj.address(),
|
||||
&retval);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (retval)
|
||||
XPCThrower::Throw(rv, cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!pobj || (JS_HasPropertyById(cx, holder, id, &hasProp) &&
|
||||
hasProp), "id got defined somewhere else?");
|
||||
}
|
||||
|
||||
// resolveOwnProperty must return a non-empty |desc| if and only if an |own|
|
||||
// property was found on the object. However, given how the NewResolve setup
|
||||
// works, we can't run the resolve hook if the holder already has a property
|
||||
// of the same name. So if there was a pre-existing property on the holder,
|
||||
// we have to use it. But we have no way of knowing if it corresponded to an
|
||||
// |own| or non-|own| property, since both get cached on the holder and the
|
||||
// |own|-ness information is lost.
|
||||
//
|
||||
// So we just over-zealously call things |own| here. This can cause us to
|
||||
// return non-|own| properties from Object.getOwnPropertyDescriptor if
|
||||
// lookups are performed in a certain order, but we can probably live with
|
||||
// that until XPCWN Xrays go away with the new DOM bindings.
|
||||
return JS_GetPropertyDescriptorById(cx, holder, id, desc);
|
||||
}
|
||||
|
||||
|
@ -1590,18 +1349,6 @@ XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper,
|
|||
{
|
||||
*defined = false;
|
||||
RootedObject holder(cx, singleton.ensureHolder(cx, wrapper));
|
||||
if (isResolving(cx, holder, id)) {
|
||||
if (!desc.hasAttributes(JSPROP_GETTER | JSPROP_SETTER)) {
|
||||
if (!desc.getter())
|
||||
desc.setGetter(holder_get);
|
||||
if (!desc.setter())
|
||||
desc.setSetter(holder_set);
|
||||
}
|
||||
|
||||
*defined = true;
|
||||
return JS_DefinePropertyById(cx, holder, id, desc.value(), desc.attributes(),
|
||||
desc.getter(), desc.setter());
|
||||
}
|
||||
|
||||
// Check for an indexed property on a Window. If that's happening, do
|
||||
// nothing but claim we defined it so it won't get added as an expando.
|
||||
|
@ -1647,13 +1394,7 @@ JSObject *
|
|||
XPCWrappedNativeXrayTraits::createHolder(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
RootedObject global(cx, JS_GetGlobalForObject(cx, wrapper));
|
||||
JSObject *holder = JS_NewObjectWithGivenProto(cx, &HolderClass, JS::NullPtr(),
|
||||
global);
|
||||
if (!holder)
|
||||
return nullptr;
|
||||
|
||||
js::SetReservedSlot(holder, JSSLOT_RESOLVING, PrivateValue(nullptr));
|
||||
return holder;
|
||||
return JS_NewObjectWithGivenProto(cx, &HolderClass, JS::NullPtr(), global);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1661,7 +1402,7 @@ XPCWrappedNativeXrayTraits::call(JSContext *cx, HandleObject wrapper,
|
|||
const JS::CallArgs &args,
|
||||
const js::Wrapper& baseInstance)
|
||||
{
|
||||
// Run the resolve hook of the wrapped native.
|
||||
// Run the call hook of the wrapped native.
|
||||
XPCWrappedNative *wn = getWN(wrapper);
|
||||
if (NATIVE_HAS_FLAG(wn, WantCall)) {
|
||||
XPCCallContext ccx(JS_CALLER, cx, wrapper, NullPtr(), JSID_VOIDHANDLE, args.length(),
|
||||
|
@ -1687,7 +1428,7 @@ XPCWrappedNativeXrayTraits::construct(JSContext *cx, HandleObject wrapper,
|
|||
const JS::CallArgs &args,
|
||||
const js::Wrapper& baseInstance)
|
||||
{
|
||||
// Run the resolve hook of the wrapped native.
|
||||
// Run the construct hook of the wrapped native.
|
||||
XPCWrappedNative *wn = getWN(wrapper);
|
||||
if (NATIVE_HAS_FLAG(wn, WantConstruct)) {
|
||||
XPCCallContext ccx(JS_CALLER, cx, wrapper, NullPtr(), JSID_VOIDHANDLE, args.length(),
|
||||
|
@ -1910,19 +1651,6 @@ GetNativePropertiesObject(JSContext *cx, JSObject *wrapper)
|
|||
return holder;
|
||||
}
|
||||
|
||||
bool
|
||||
IsXrayResolving(JSContext *cx, HandleObject wrapper, HandleId id)
|
||||
{
|
||||
if (!WrapperFactory::IsXrayWrapper(wrapper) ||
|
||||
GetXrayType(wrapper) != XrayForWrappedNative)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
JSObject *holder =
|
||||
XPCWrappedNativeXrayTraits::singleton.ensureHolder(cx, wrapper);
|
||||
return XPCWrappedNativeXrayTraits::isResolving(cx, holder, id);
|
||||
}
|
||||
|
||||
bool
|
||||
HasNativeProperty(JSContext *cx, HandleObject wrapper, HandleId id, bool *hasProp)
|
||||
{
|
||||
|
@ -1936,9 +1664,6 @@ HasNativeProperty(JSContext *cx, HandleObject wrapper, HandleId id, bool *hasPro
|
|||
const Wrapper *handler = Wrapper::wrapperHandler(wrapper);
|
||||
|
||||
// Try resolveOwnProperty.
|
||||
Maybe<ResolvingId> resolvingId;
|
||||
if (traits == &XPCWrappedNativeXrayTraits::singleton)
|
||||
resolvingId.emplace(cx, wrapper, id);
|
||||
if (!traits->resolveOwnProperty(cx, *handler, wrapper, holder, id, &desc))
|
||||
return false;
|
||||
if (desc.object()) {
|
||||
|
@ -2085,12 +1810,6 @@ XrayWrapper<Base, Traits>::getPropertyDescriptor(JSContext *cx, HandleObject wra
|
|||
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::GET | BaseProxyHandler::SET |
|
||||
BaseProxyHandler::GET_PROPERTY_DESCRIPTOR);
|
||||
RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper));
|
||||
if (Traits::isResolving(cx, holder, id)) {
|
||||
desc.object().set(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
typename Traits::ResolvingIdImpl resolving(cx, wrapper, id);
|
||||
|
||||
if (!holder)
|
||||
return false;
|
||||
|
@ -2218,15 +1937,6 @@ XrayWrapper<Base, Traits>::getOwnPropertyDescriptor(JSContext *cx, HandleObject
|
|||
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::GET | BaseProxyHandler::SET |
|
||||
BaseProxyHandler::GET_PROPERTY_DESCRIPTOR);
|
||||
RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper));
|
||||
if (Traits::isResolving(cx, holder, id)) {
|
||||
desc.object().set(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
typename Traits::ResolvingIdImpl resolving(cx, wrapper, id);
|
||||
|
||||
// NB: Nothing we do here acts on the wrapped native itself, so we don't
|
||||
// enter our policy.
|
||||
|
||||
if (!Traits::singleton.resolveOwnProperty(cx, *this, wrapper, holder, id, desc))
|
||||
return false;
|
||||
|
|
|
@ -24,12 +24,6 @@ class XPCWrappedNative;
|
|||
|
||||
namespace xpc {
|
||||
|
||||
bool
|
||||
holder_get(JSContext *cx, JS::HandleObject holder, JS::HandleId id, JS::MutableHandleValue vp);
|
||||
bool
|
||||
holder_set(JSContext *cx, JS::HandleObject holder, JS::HandleId id, bool strict,
|
||||
JS::MutableHandleValue vp);
|
||||
|
||||
namespace XrayUtils {
|
||||
|
||||
bool IsXPCWNHolderClass(const JSClass *clasp);
|
||||
|
@ -42,9 +36,6 @@ IsTransparent(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id);
|
|||
JSObject *
|
||||
GetNativePropertiesObject(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
bool
|
||||
IsXrayResolving(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id);
|
||||
|
||||
bool
|
||||
HasNativeProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
|
||||
bool *hasProp);
|
||||
|
@ -58,35 +49,6 @@ enum XrayType {
|
|||
NotXray
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS ResolvingId {
|
||||
public:
|
||||
ResolvingId(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id);
|
||||
~ResolvingId();
|
||||
|
||||
bool isXrayShadowing(jsid id);
|
||||
bool isResolving(jsid id);
|
||||
static ResolvingId* getResolvingId(JSObject *holder);
|
||||
static JSObject* getHolderObject(JSObject *wrapper);
|
||||
static ResolvingId *getResolvingIdFromWrapper(JSObject *wrapper);
|
||||
|
||||
private:
|
||||
friend class AutoSetWrapperNotShadowing;
|
||||
friend class XPCWrappedNativeXrayTraits;
|
||||
|
||||
JS::HandleId mId;
|
||||
JS::RootedObject mHolder;
|
||||
ResolvingId *mPrev;
|
||||
bool mXrayShadowing;
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS ResolvingIdDummy
|
||||
{
|
||||
public:
|
||||
ResolvingIdDummy(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class XrayTraits
|
||||
{
|
||||
public:
|
||||
|
@ -174,8 +136,6 @@ public:
|
|||
static bool construct(JSContext *cx, JS::HandleObject wrapper,
|
||||
const JS::CallArgs &args, const js::Wrapper& baseInstance);
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id);
|
||||
|
||||
static bool resolveDOMCollectionProperty(JSContext *cx, JS::HandleObject wrapper,
|
||||
JS::HandleObject holder, JS::HandleId id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
|
@ -184,8 +144,6 @@ public:
|
|||
|
||||
virtual void preserveWrapper(JSObject *target) MOZ_OVERRIDE;
|
||||
|
||||
typedef ResolvingId ResolvingIdImpl;
|
||||
|
||||
virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
|
||||
static const JSClass HolderClass;
|
||||
|
@ -219,13 +177,6 @@ public:
|
|||
static bool construct(JSContext *cx, JS::HandleObject wrapper,
|
||||
const JS::CallArgs &args, const js::Wrapper& baseInstance);
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef ResolvingIdDummy ResolvingIdImpl;
|
||||
|
||||
virtual void preserveWrapper(JSObject *target) MOZ_OVERRIDE;
|
||||
|
||||
virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
|
@ -287,13 +238,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef ResolvingIdDummy ResolvingIdImpl;
|
||||
|
||||
bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
|
||||
JS::HandleObject target,
|
||||
JS::MutableHandleObject protop)
|
||||
|
@ -408,13 +352,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef ResolvingIdDummy ResolvingIdImpl;
|
||||
|
||||
bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
|
||||
JS::HandleObject target,
|
||||
JS::MutableHandleObject protop)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <ctime>
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
|
@ -3598,8 +3599,8 @@ nsCSSRendering::DrawTableBorderSegment(nsRenderingContext& aContext,
|
|||
}
|
||||
|
||||
gfxContext *ctx = aContext.ThebesContext();
|
||||
gfxContext::AntialiasMode oldMode = ctx->CurrentAntialiasMode();
|
||||
ctx->SetAntialiasMode(gfxContext::MODE_ALIASED);
|
||||
AntialiasMode oldMode = ctx->CurrentAntialiasMode();
|
||||
ctx->SetAntialiasMode(AntialiasMode::NONE);
|
||||
|
||||
switch (aBorderStyle) {
|
||||
case NS_STYLE_BORDER_STYLE_NONE:
|
||||
|
@ -3932,12 +3933,12 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame,
|
|||
contextIsSaved = true;
|
||||
aGfxContext->Clip(rect);
|
||||
if (lineHeight > 2.0) {
|
||||
aGfxContext->SetAntialiasMode(gfxContext::MODE_COVERAGE);
|
||||
aGfxContext->SetAntialiasMode(AntialiasMode::SUBPIXEL);
|
||||
} else {
|
||||
// Don't use anti-aliasing here. Because looks like lighter color wavy
|
||||
// line at this case. And probably, users don't think the
|
||||
// non-anti-aliased wavy line is not pretty.
|
||||
aGfxContext->SetAntialiasMode(gfxContext::MODE_ALIASED);
|
||||
aGfxContext->SetAntialiasMode(AntialiasMode::NONE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1494,7 +1494,7 @@ nsCSSBorderRenderer::DrawBorders()
|
|||
|
||||
gfxFloat dash = mBorderWidths[0];
|
||||
mContext->SetDash(&dash, 1, 0.5);
|
||||
mContext->SetAntialiasMode(gfxContext::MODE_ALIASED);
|
||||
mContext->SetAntialiasMode(AntialiasMode::NONE);
|
||||
gfxRect rect = mOuterRect;
|
||||
rect.Deflate(mBorderWidths[0] / 2.0);
|
||||
mContext->NewPath();
|
||||
|
|
|
@ -6726,9 +6726,27 @@ bool
|
|||
ClusterIterator::IsPunctuation()
|
||||
{
|
||||
NS_ASSERTION(mCharIndex >= 0, "No cluster selected");
|
||||
nsIUGenCategory::nsUGenCategory c =
|
||||
mozilla::unicode::GetGenCategory(mFrag->CharAt(mCharIndex));
|
||||
return c == nsIUGenCategory::kPunctuation || c == nsIUGenCategory::kSymbol;
|
||||
// Return true for all Punctuation categories (Unicode general category P?),
|
||||
// and also for Symbol categories (S?) except for Modifier Symbol, which is
|
||||
// kept together with any adjacent letter/number. (Bug 1066756)
|
||||
uint8_t cat = unicode::GetGeneralCategory(mFrag->CharAt(mCharIndex));
|
||||
switch (cat) {
|
||||
case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION: /* Pd */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION: /* Pe */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION: /* Pf */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION: /* Po */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION: /* Ps */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL: /* Sc */
|
||||
// Deliberately omitted:
|
||||
// case HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL: /* Sk */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL: /* Sm */
|
||||
case HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL: /* So */
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<p id="catch">Catch-all
|
||||
<pre id="test"><script class="testbody" type="text/javascript;version=1.7">
|
||||
|
||||
/** Tests for bugs 384147 and 981281 **/
|
||||
/** Tests for bugs 384147, 981281, 1066756 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
|
@ -63,7 +63,8 @@ var ChineseChars = "漢字";
|
|||
var HiraganaChars = "ひらがな";
|
||||
var KatakanaChars = "カタカナ";
|
||||
var JapaneseFullStop = "。";
|
||||
var JapaneseComma = "、";
|
||||
var JapaneseComma = "、";
|
||||
var ModifierColon = "꞉";
|
||||
|
||||
function test() {
|
||||
setPrefs(false, true, test1);
|
||||
|
@ -176,6 +177,14 @@ function test1() {
|
|||
testLeft(editor.firstChild, 3);
|
||||
testLeft(editor.firstChild, 0);
|
||||
|
||||
// test for bug 1066756
|
||||
editor.innerHTML = "hello" + ModifierColon + " wo" + ModifierColon + "rld";
|
||||
sel.collapse(editor.firstChild, 0);
|
||||
testRight(editor.firstChild, 6);
|
||||
testRight(editor.firstChild, 13);
|
||||
testLeft(editor.firstChild, 7);
|
||||
testLeft(editor.firstChild, 0);
|
||||
|
||||
// test basic word movement with eat_space_next_to_word true.
|
||||
setPrefs(true, true, test2);
|
||||
}
|
||||
|
@ -285,6 +294,13 @@ function test2() {
|
|||
testLeft(editor.firstChild, 3);
|
||||
testLeft(editor.firstChild, 0);
|
||||
|
||||
editor.innerHTML = "hello" + ModifierColon + " wo" + ModifierColon + "rld";
|
||||
sel.collapse(editor.firstChild, 0);
|
||||
testRight(editor.firstChild, 7);
|
||||
testRight(editor.firstChild, 13);
|
||||
testLeft(editor.firstChild, 7);
|
||||
testLeft(editor.firstChild, 0);
|
||||
|
||||
// Test basic word movement with stop_at_punctuation false (bug 981281).
|
||||
setPrefs(false, false, test3);
|
||||
}
|
||||
|
@ -378,6 +394,13 @@ function test3() {
|
|||
testRight(editor.firstChild, 8);
|
||||
testLeft(editor.firstChild, 0);
|
||||
|
||||
editor.innerHTML = "hello" + ModifierColon + " wo" + ModifierColon + "rld";
|
||||
sel.collapse(editor.firstChild, 0);
|
||||
testRight(editor.firstChild, 6);
|
||||
testRight(editor.firstChild, 13);
|
||||
testLeft(editor.firstChild, 7);
|
||||
testLeft(editor.firstChild, 0);
|
||||
|
||||
// And again with eat_space_next_to_word true.
|
||||
setPrefs(true, false, test4);
|
||||
}
|
||||
|
@ -471,6 +494,13 @@ function test4() {
|
|||
testRight(editor.firstChild, 8);
|
||||
testLeft(editor.firstChild, 0);
|
||||
|
||||
editor.innerHTML = "hello" + ModifierColon + " wo" + ModifierColon + "rld";
|
||||
sel.collapse(editor.firstChild, 0);
|
||||
testRight(editor.firstChild, 7);
|
||||
testRight(editor.firstChild, 13);
|
||||
testLeft(editor.firstChild, 7);
|
||||
testLeft(editor.firstChild, 0);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Filters: Hue Rotate an HTML Element Containing Colors with Multiple RGB Channels</title>
|
||||
<link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
|
||||
<style type="text/css">
|
||||
#target {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.color-strip {
|
||||
height: 50px;
|
||||
}
|
||||
#color-strip-1 {
|
||||
background-color: rgb(64, 187, 46);
|
||||
}
|
||||
#color-strip-2 {
|
||||
background-color: rgb(64, 250, 255);
|
||||
}
|
||||
#color-strip-3 {
|
||||
background-color: rgb(255, 14, 109);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>You should see a horizontal green strip, followed by a cyan strip, followed by a magenta strip.</p>
|
||||
<div id="target">
|
||||
<div id="color-strip-1" class="color-strip"></div>
|
||||
<div id="color-strip-2" class="color-strip"></div>
|
||||
<div id="color-strip-3" class="color-strip"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче