This commit is contained in:
Wes Kocher 2014-09-15 16:47:02 -07:00
Родитель 577218507d 293eb7ac77
Коммит 196212ea47
158 изменённых файлов: 5709 добавлений и 2803 удалений

Просмотреть файл

@ -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);
@ -331,7 +331,7 @@ exports['test console global by default'] = function (assert) {
let uri = root + '/fixtures/loader/globals/';
let loader = Loader({ paths: { '': uri }});
let program = main(loader, 'main');
assert.ok(typeof program.console === 'object', 'global `console` exists');
assert.ok(typeof program.console.log === 'function', 'global `console.log` exists');
@ -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");
gNextTest = part2;
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
gNewWindow.addEventListener("load", handleEvent, true);
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");
gNewWindow = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
waitForFocus(part6, gNewWindow);
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");
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")
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");
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.");
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,43 +63,37 @@ 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);
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
() => {
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
prepareTest(test3, gTestRoot + "plugin_overlayed.html");
},
"Test 2, expected to not have a plugin notification bar");
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
() => {
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
prepareTest(test3, gTestRoot + "plugin_overlayed.html");
},
"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,23 +139,27 @@ 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");
let plugin = gTestBrowser.contentDocument.getElementById("test");
ok(plugin, "Test 6, Found plugin in page");
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
"Test 6, Plugin should be click-to-play");
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);
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
"Test 6, Plugin should be click-to-play");
// simulate "always allow"
notification.reshow();
PopupNotifications.panel.firstChild._primaryButton.click();
// simulate "always allow"
notification.reshow();
PopupNotifications.panel.firstChild._primaryButton.click();
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
waitForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null,
test7,
"Test 6, expected the notification bar for hidden plugins to get dismissed");
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
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);
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();
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 + ".");
}
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();
waitForNotificationBar("plugin-crashed", gTestBrowser, (notification) => {
let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
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();
prepareTest(test24b, gHttpTestRoot + "plugin_test.html");
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() {
prepareTest(runAfterPluginBindingAttached(test24c), gHttpTestRoot + "plugin_test.html");
});
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();
// simulate "always allow"
notification.reshow();
PopupNotifications.panel.firstChild._primaryButton.click();
prepareTest(test24d, gHttpTestRoot + "plugin_test.html");
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");
// this resets the vulnerable plugin permission
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml",
function() {
clearAllPluginPermissions();
resetBlocklist();
prepareTest(test25, gTestRoot + "plugin_syncRemoved.html");
});
waitForCondition(() => objLoadingContent.activated, () => {
// this resets the vulnerable plugin permission
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;
}
});
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;
@ -106,21 +164,9 @@ private:
uint8_t mCtxType; // X, Y or Unspecified
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(nsIFrame *aFrame, uint8_t aUnitType) const;
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;
Type argType;
if (!CheckExpr(f, arg, &argDef, &argType))
return false;
for (size_t i = 0; i < numArgs; i++, arg = NextNode(arg)) {
MOZ_ASSERT(!!arg);
// 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))
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");
Type argType;
if (!CheckExpr(f, arg, &argDefs[i], &argType))
return false;
if (!checkArg(f, arg, i, argType, &argDefs[i]))
return false;
}
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;
const char *name;
uint8_t flags;
uint8_t spare[3];
template<typename T>
struct JSConstScalarSpec {
const char *name;
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 = &REGS.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 = "&#x6F22;&#x5B57;";
var HiraganaChars = "&#x3072;&#x3089;&#x304C;&#x306A;";
var KatakanaChars = "&#x30AB;&#x30BF;&#x30AB;&#x30CA;";
var JapaneseFullStop = "&#x3002;";
var JapaneseComma = "&#x3001";
var JapaneseComma = "&#x3001;";
var ModifierColon = "&#xA789;";
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>

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше