Merge mozilla-inbound to mozilla-central. a=merge

This commit is contained in:
Dorel Luca 2018-03-02 00:09:29 +02:00
Родитель 109ad47bbf 8bbbdc6337
Коммит 3ccafa2b66
169 изменённых файлов: 5290 добавлений и 1286 удалений

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

@ -1047,11 +1047,7 @@ pref("dom.ipc.plugins.sandbox-level.flash", 0);
// On windows these levels are:
// See - security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
// SetSecurityLevelForContentProcess() for what the different settings mean.
#if defined(NIGHTLY_BUILD)
pref("security.sandbox.content.level", 5);
#else
pref("security.sandbox.content.level", 4);
#endif
// This controls the depth of stack trace that is logged when Windows sandbox
// logging is turned on. This is only currently available for the content

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

@ -6,13 +6,11 @@
"use strict";
const { gDevTools } = require("devtools/client/framework/devtools");
const { getColor } = require("devtools/client/shared/theme");
const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
const { Provider } = require("devtools/client/shared/vendor/react-redux");
const { gDevTools } = require("devtools/client/framework/devtools");
const FontsApp = createFactory(require("./components/FontsApp"));
const { LocalizationHelper } = require("devtools/shared/l10n");
@ -193,6 +191,11 @@ class FontInspector {
previewFillStyle: getColor("body-color")
};
// Add the includeVariations argument into the option to get font variation data.
if (this.pageStyle.supportsFontVariations) {
options.includeVariations = true;
}
fonts = await this.getFontsForNode(node, options);
otherFonts = await this.getFontsNotInNode(fonts, options);

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

@ -6,6 +6,45 @@
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
/**
* A font variation axis.
*/
const fontVariationAxis = exports.fontVariationAxis = {
// The OpenType tag name of the variation axis
tag: PropTypes.string,
// The axis name of the variation axis
name: PropTypes.string,
// The minimum value of the variation axis
minValue: PropTypes.number,
// The maximum value of the variation axis
maxValue: PropTypes.number,
// The default value of the variation axis
defaultValue: PropTypes.number,
};
const fontVariationInstanceValue = exports.fontVariationInstanceValue = {
// The axis name of the variation axis
axis: PropTypes.string,
// The value of the variation axis
value: PropTypes.number,
};
/**
* A font variation instance.
*/
const fontVariationInstance = exports.fontVariationInstance = {
// The variation instance name of the font
axis: PropTypes.string,
// The font variation values for the variation instance of the font
values: PropTypes.arrayOf(PropTypes.shape(fontVariationInstanceValue)),
};
/**
* A single font.
*/
@ -27,6 +66,12 @@ const font = exports.font = {
// The URI of the font file
URI: PropTypes.string,
// The variation axes of the font
variationAxes: PropTypes.arrayOf(PropTypes.shape(fontVariationAxis)),
// The variation instances of the font
variationInstances: PropTypes.arrayOf(PropTypes.shape(fontVariationInstance))
};
exports.fontOptions = {
@ -35,7 +80,7 @@ exports.fontOptions = {
};
/**
* Font data
* Font data.
*/
exports.fontData = {
// The fonts used in the current element.

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

@ -91,7 +91,7 @@ class SnapshotListItem extends Component {
className: "save",
}, L10N.getStr("snapshot.io.save"));
let deleteButton = !snapshot.path ? void 0 : dom.div({
let deleteButton = !snapshot.path ? void 0 : dom.button({
onClick: () => onDelete(snapshot),
className: "delete",
title: L10N.getStr("snapshot.io.delete")

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

@ -811,7 +811,7 @@ class TreeNodeClass extends Component {
id: this.props.id,
className: classList.join(" "),
role: "treeitem",
"aria-level": this.props.depth,
"aria-level": this.props.depth + 1,
onClick: this.props.onClick,
"aria-expanded": ariaExpanded,
"data-expanded": this.props.expanded ? "" : undefined,

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

@ -96,7 +96,9 @@ function isAccessibleTree(tree, options = {}) {
for (let node of treeNodes) {
ok(node.id, "TreeNode has an id");
is(node.getAttribute("role"), "treeitem", "Tree item semantics is present");
ok(node.hasAttribute("aria-level"), "Aria level attribute is set");
is(parseInt(node.getAttribute("aria-level"), 10),
parseInt(node.getAttribute("data-depth"), 10) + 1,
"Aria level attribute is set correctly");
}
}

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

@ -209,9 +209,13 @@ html, body, #app, #memory-tool {
.snapshot-list-item .delete {
cursor: pointer;
background-color: transparent;
border: 0;
padding: 0;
position: relative;
min-height: 1em;
min-width: 1.3em;
color: currentColor;
}
.snapshot-list-item .delete::before {

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

@ -0,0 +1,232 @@
/* 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 { Cc, Ci } = require("chrome");
const Services = require("Services");
const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled";
/**
* A helper class that does all the work related to accessibility service
* lifecycle (initialization, shutdown, consumer changes, etc) in parent
* parent process. It is not guaranteed that the AccessibilityActor starts in
* parent process and thus triggering these lifecycle functions directly is
* extremely unreliable.
*/
class AccessibilityParent {
constructor(mm, prefix) {
this._msgName = `debug:${prefix}accessibility`;
this.onAccessibilityMessage = this.onAccessibilityMessage.bind(this);
this.setMessageManager(mm);
this.userPref = Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED);
Services.obs.addObserver(this, "a11y-consumers-changed");
Services.prefs.addObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
if (this.enabled && !this.accService) {
// Set a local reference to an accessibility service if accessibility was
// started elsewhere to ensure that parent process a11y service does not
// get GC'ed away.
this.accService = Cc["@mozilla.org/accessibilityService;1"].getService(
Ci.nsIAccessibilityService);
}
this.messageManager.sendAsyncMessage(`${this._msgName}:event`, {
topic: "initialized",
data: {
canBeDisabled: this.canBeDisabled,
canBeEnabled: this.canBeEnabled
}
});
}
/**
* Set up message manager listener to listen for messages coming from the
* AccessibilityActor when it is instantiated in the child process.
*
* @param {Object} mm
* Message manager that corresponds to the current content tab.
*/
setMessageManager(mm) {
if (this.messageManager === mm) {
return;
}
if (this.messageManager) {
// If the browser was swapped we need to reset the message manager.
let oldMM = this.messageManager;
oldMM.removeMessageListener(this._msgName, this.onAccessibilityMessage);
}
this.messageManager = mm;
if (mm) {
mm.addMessageListener(this._msgName, this.onAccessibilityMessage);
}
}
/**
* Content AccessibilityActor message listener.
*
* @param {String} msg
* Name of the action to perform.
*/
onAccessibilityMessage(msg) {
let { action } = msg.json;
switch (action) {
case "enable":
this.enable();
break;
case "disable":
this.disable();
break;
case "disconnect":
this.destroy();
break;
default:
break;
}
}
observe(subject, topic, data) {
if (topic === "a11y-consumers-changed") {
// This event is fired when accessibility service consumers change. Since
// this observer lives in parent process there are 2 possible consumers of
// a11y service: XPCOM and PlatformAPI (e.g. screen readers). We only care
// about PlatformAPI consumer changes because when set, we can no longer
// disable accessibility service.
let { PlatformAPI } = JSON.parse(data);
this.messageManager.sendAsyncMessage(`${this._msgName}:event`, {
topic: "can-be-disabled-change",
data: !PlatformAPI
});
} else if (!this.disabling && topic === "nsPref:changed" &&
data === PREF_ACCESSIBILITY_FORCE_DISABLED) {
// PREF_ACCESSIBILITY_FORCE_DISABLED preference change event. When set to
// >=1, it means that the user wants to disable accessibility service and
// prevent it from starting in the future. Note: we also check
// this.disabling state when handling this pref change because this is how
// we disable the accessibility inspector itself.
this.messageManager.sendAsyncMessage(`${this._msgName}:event`, {
topic: "can-be-enabled-change",
data: Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED) < 1
});
}
}
/**
* A getter that indicates if accessibility service is enabled.
*
* @return {Boolean}
* True if accessibility service is on.
*/
get enabled() {
return Services.appinfo.accessibilityEnabled;
}
/**
* A getter that indicates if the accessibility service can be disabled.
*
* @return {Boolean}
* True if accessibility service can be disabled.
*/
get canBeDisabled() {
if (this.enabled) {
let a11yService = Cc["@mozilla.org/accessibilityService;1"].getService(
Ci.nsIAccessibilityService);
let { PlatformAPI } = JSON.parse(a11yService.getConsumers());
return !PlatformAPI;
}
return true;
}
/**
* A getter that indicates if the accessibility service can be enabled.
*
* @return {Boolean}
* True if accessibility service can be enabled.
*/
get canBeEnabled() {
return Services.prefs.getIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED) < 1;
}
/**
* Enable accessibility service (via XPCOM service).
*/
enable() {
if (this.enabled || !this.canBeEnabled) {
return;
}
this.accService = Cc["@mozilla.org/accessibilityService;1"].getService(
Ci.nsIAccessibilityService);
}
/**
* Force disable accessibility service. This method removes the reference to
* the XPCOM a11y service object and flips the
* PREF_ACCESSIBILITY_FORCE_DISABLED preference on and off to shutdown a11y
* service.
*/
disable() {
if (!this.enabled || !this.canBeDisabled) {
return;
}
this.disabling = true;
this.accService = null;
// Set PREF_ACCESSIBILITY_FORCE_DISABLED to 1 to force disable
// accessibility service. This is the only way to guarantee an immediate
// accessibility service shutdown in all processes. This also prevents
// accessibility service from starting up in the future.
Services.prefs.setIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED, 1);
// Set PREF_ACCESSIBILITY_FORCE_DISABLED back to previous default or user
// set value. This will not start accessibility service until the user
// activates it again. It simply ensures that accessibility service can
// start again (when value is below 1).
Services.prefs.setIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED, this.userPref);
delete this.disabling;
}
/**
* Destroy thie helper class, remove all listeners and if possible disable
* accessibility service in the parent process.
*/
destroy() {
Services.obs.removeObserver(this, "a11y-consumers-changed");
Services.prefs.removeObserver(PREF_ACCESSIBILITY_FORCE_DISABLED, this);
this.setMessageManager(null);
this.accService = null;
}
}
/**
* Setup function that runs in parent process and setups AccessibleActor bits
* that must always run in parent process.
*
* @param {Object} options.mm
* Message manager that corresponds to the current content tab.
* @param {String} options.prefix
* Unique prefix for message manager messages.
* @return {Object}
* Defines event listeners for when client disconnects or browser gets
* swapped.
*/
function setupParentProcess({ mm, prefix }) {
let accessibility = new AccessibilityParent(mm, prefix);
return {
onBrowserSwap: newMM => accessibility.setMessageManager(newMM),
onDisconnected: () => {
accessibility.destroy();
accessibility = null;
}
};
}
exports.setupParentProcess = setupParentProcess;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -13,6 +13,7 @@ DIRS += [
]
DevToolsModules(
'accessibility-parent.js',
'accessibility.js',
'actor-registry.js',
'addon.js',

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

@ -5,6 +5,7 @@
"use strict";
const {Ci} = require("chrome");
const Services = require("Services");
const protocol = require("devtools/shared/protocol");
const {LongStringActor} = require("devtools/server/actors/string");
const InspectorUtils = require("InspectorUtils");
@ -29,6 +30,9 @@ loader.lazyRequireGetter(this, "UPDATE_GENERAL",
loader.lazyGetter(this, "PSEUDO_ELEMENTS", () => {
return InspectorUtils.getCSSPseudoElementNames();
});
loader.lazyGetter(this, "FONT_VARIATIONS_ENABLED", () => {
return Services.prefs.getBoolPref("layout.css.font-variations.enabled");
});
const XHTML_NS = "http://www.w3.org/1999/xhtml";
const FONT_PREVIEW_TEXT = "Abc";
@ -115,7 +119,10 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
// been fixed must make sure cssLogic.highlight(node) was called before.
getAppliedCreatesStyleCache: true,
// Whether addNewRule accepts the editAuthored argument.
authoredStyles: true
authoredStyles: true,
// Whether getAllUsedFontFaces/getUsedFontFaces accepts the includeVariations
// argument.
fontVariations: FONT_VARIATIONS_ENABLED,
}
};
},
@ -320,6 +327,12 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
size: size
};
}
if (options.includeVariations && FONT_VARIATIONS_ENABLED) {
fontFace.variationAxes = font.getVariationAxes();
fontFace.variationInstances = font.getVariationInstances();
}
fontsArray.push(fontFace);
}

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

@ -27,8 +27,8 @@ support-files =
!/devtools/server/tests/mochitest/hello-actor.js
!/devtools/client/framework/test/shared-head.js
[browser_accessibility_node_events.js]
[browser_accessibility_node.js]
[browser_accessibility_node_events.js]
[browser_accessibility_simple.js]
[browser_accessibility_walker.js]
[browser_animation_emitMutations.js]

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

@ -10,7 +10,8 @@ add_task(async function () {
let {client, walker, accessibility} =
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility.html");
let a11yWalker = await accessibility.getWalker(walker);
let a11yWalker = await accessibility.getWalker();
await accessibility.enable();
let buttonNode = await walker.querySelector(walker.rootNode, "#button");
let accessibleFront = await a11yWalker.getAccessibleFor(buttonNode);
@ -22,38 +23,23 @@ add_task(async function () {
help: "",
keyboardShortcut: "",
childCount: 1,
domNodeType: 1
domNodeType: 1,
indexInParent: 1,
states: ["focusable", "selectable text", "opaque", "enabled", "sensitive"],
actions: [ "Press" ],
attributes: {
"margin-top": "0px",
display: "inline-block",
"text-align": "center",
"text-indent": "0px",
"margin-left": "0px",
tag: "button",
"margin-right": "0px",
id: "button",
"margin-bottom": "0px"
}
});
info("Actions");
let actions = await accessibleFront.getActions();
is(actions.length, 1, "Accessible Front has correct number of actions");
is(actions[0], "Press", "Accessible Front default action is correct");
info("Index in parent");
let index = await accessibleFront.getIndexInParent();
is(index, 1, "Accessible Front has correct index in parent");
info("State");
let state = await accessibleFront.getState();
SimpleTest.isDeeply(state,
["focusable", "selectable text", "opaque", "enabled", "sensitive"],
"Accessible Front has correct states");
info("Attributes");
let attributes = await accessibleFront.getAttributes();
SimpleTest.isDeeply(attributes, {
"margin-top": "0px",
display: "inline-block",
"text-align": "center",
"text-indent": "0px",
"margin-left": "0px",
tag: "button",
"margin-right": "0px",
id: "button",
"margin-bottom": "0px"
}, "Accessible Front has correct attributes");
info("Children");
let children = await accessibleFront.children();
is(children.length, 1, "Accessible Front has correct number of children");
@ -62,13 +48,8 @@ add_task(async function () {
role: "text leaf"
});
info("DOM Node");
let node = await accessibleFront.getDOMNode(walker);
is(node, buttonNode, "Accessible Front has correct DOM node");
let a11yShutdown = waitForA11yShutdown();
await accessibility.disable();
await waitForA11yShutdown();
await client.close();
forceCollections();
await a11yShutdown;
gBrowser.removeCurrentTab();
});

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

@ -10,8 +10,10 @@ add_task(async function () {
let {client, walker, accessibility} =
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility.html");
let a11yWalker = await accessibility.getWalker(walker);
let a11yDoc = await a11yWalker.getDocument();
let a11yWalker = await accessibility.getWalker();
await accessibility.enable();
let rootNode = await walker.getRootNode();
let a11yDoc = await a11yWalker.getAccessibleFor(rootNode);
let buttonNode = await walker.querySelector(walker.rootNode, "#button");
let accessibleFront = await a11yWalker.getAccessibleFor(buttonNode);
let sliderNode = await walker.querySelector(walker.rootNode, "#slider");
@ -26,7 +28,21 @@ add_task(async function () {
help: "",
keyboardShortcut: "",
childCount: 1,
domNodeType: 1
domNodeType: 1,
indexInParent: 1,
states: ["focusable", "selectable text", "opaque", "enabled", "sensitive"],
actions: [ "Press" ],
attributes: {
"margin-top": "0px",
display: "inline-block",
"text-align": "center",
"text-indent": "0px",
"margin-left": "0px",
tag: "button",
"margin-right": "0px",
id: "button",
"margin-bottom": "0px"
}
});
info("Name change event");
@ -45,27 +61,35 @@ add_task(async function () {
content.document.getElementById("button").removeAttribute("aria-describedby")));
info("State change event");
let states = await accessibleFront.getState();
let expectedStates = ["unavailable", "selectable text", "opaque"];
SimpleTest.isDeeply(states, ["focusable", "selectable text", "opaque",
"enabled", "sensitive"], "States are correct");
await emitA11yEvent(accessibleFront, "state-change",
newStates => SimpleTest.isDeeply(newStates, expectedStates,
"States are updated"),
() => ContentTask.spawn(browser, null, () =>
await emitA11yEvent(accessibleFront, "states-change",
newStates => {
checkA11yFront(accessibleFront, { states: expectedStates });
SimpleTest.isDeeply(newStates, expectedStates, "States are updated");
}, () => ContentTask.spawn(browser, null, () =>
content.document.getElementById("button").setAttribute("disabled", true)));
states = await accessibleFront.getState();
SimpleTest.isDeeply(states, expectedStates, "States are updated");
info("Attributes change event");
let attrs = await accessibleFront.getAttributes();
ok(!attrs.live, "Attribute is not present");
await emitA11yEvent(accessibleFront, "attributes-change",
newAttrs => is(newAttrs.live, "polite", "Attributes are updated"),
() => ContentTask.spawn(browser, null, () =>
newAttrs => {
checkA11yFront(accessibleFront, { attributes: {
"container-live": "polite",
display: "inline-block",
"event-from-input": "false",
"explicit-name": "true",
id: "button",
live: "polite",
"margin-bottom": "0px",
"margin-left": "0px",
"margin-right": "0px",
"margin-top": "0px",
tag: "button",
"text-align": "center",
"text-indent": "0px"
}});
is(newAttrs.live, "polite", "Attributes are updated");
}, () => ContentTask.spawn(browser, null, () =>
content.document.getElementById("button").setAttribute("aria-live", "polite")));
attrs = await accessibleFront.getAttributes();
is(attrs.live, "polite", "Attributes are updated");
info("Value change event");
checkA11yFront(accessibleSliderFront, { value: "5" });
@ -76,18 +100,29 @@ add_task(async function () {
info("Reorder event");
is(accessibleSliderFront.childCount, 1, "Slider has only 1 child");
let [firstChild, ] = await accessibleSliderFront.children();
is(firstChild.indexInParent, 0, "Slider's first child has correct index in parent");
await emitA11yEvent(accessibleSliderFront, "reorder",
childCount => is(childCount, 2, "Child count is updated"),
() => ContentTask.spawn(browser, null, () => {
let button = content.document.createElement("button");
childCount => {
is(childCount, 2, "Child count is updated");
is(accessibleSliderFront.childCount, 2, "Child count is updated");
is(firstChild.indexInParent, 1,
"Slider's first child has an updated index in parent");
}, () => ContentTask.spawn(browser, null, () => {
let doc = content.document;
let slider = doc.getElementById("slider");
let button = doc.createElement("button");
button.innerText = "Slider button";
content.document.getElementById("slider").appendChild(button);
content.document.getElementById("slider").insertBefore(button, slider.firstChild);
}));
is(accessibleSliderFront.childCount, 2, "Child count is updated");
let a11yShutdown = waitForA11yShutdown();
await emitA11yEvent(firstChild, "index-in-parent-change", indexInParent =>
is(indexInParent, 0, "Slider's first child has an updated index in parent"), () =>
ContentTask.spawn(browser, null, () =>
content.document.getElementById("slider").firstChild.remove()));
await accessibility.disable();
await waitForA11yShutdown();
await client.close();
forceCollections();
await a11yShutdown;
gBrowser.removeCurrentTab();
});

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

@ -4,10 +4,19 @@
"use strict";
const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled";
function checkAccessibilityState(accessibility, expected) {
let { enabled, canBeDisabled, canBeEnabled } = accessibility;
is(enabled, expected.enabled, "Enabled state is correct.");
is(canBeDisabled, expected.canBeDisabled, "canBeDisabled state is correct.");
is(canBeEnabled, expected.canBeEnabled, "canBeEnabled state is correct.");
}
// Simple checks for the AccessibilityActor and AccessibleWalkerActor
add_task(async function () {
let {client, accessibility} = await initAccessibilityFrontForUrl(
let { walker: domWalker, client, accessibility} = await initAccessibilityFrontForUrl(
"data:text/html;charset=utf-8,<title>test</title><div></div>");
ok(accessibility, "The AccessibilityFront was created");
@ -16,6 +25,44 @@ add_task(async function () {
let a11yWalker = await accessibility.getWalker();
ok(a11yWalker, "The AccessibleWalkerFront was returned");
checkAccessibilityState(accessibility,
{ enabled: false, canBeDisabled: true, canBeEnabled: true });
info("Force disable accessibility service: updates canBeEnabled flag");
let onEvent = accessibility.once("can-be-enabled-change");
Services.prefs.setIntPref(PREF_ACCESSIBILITY_FORCE_DISABLED, 1);
await onEvent;
checkAccessibilityState(accessibility,
{ enabled: false, canBeDisabled: true, canBeEnabled: false });
info("Clear force disable accessibility service: updates canBeEnabled flag");
onEvent = accessibility.once("can-be-enabled-change");
Services.prefs.clearUserPref(PREF_ACCESSIBILITY_FORCE_DISABLED);
await onEvent;
checkAccessibilityState(accessibility,
{ enabled: false, canBeDisabled: true, canBeEnabled: true });
info("Initialize accessibility service");
let initEvent = accessibility.once("init");
await accessibility.enable();
await waitForA11yInit();
await initEvent;
checkAccessibilityState(accessibility,
{ enabled: true, canBeDisabled: true, canBeEnabled: true });
a11yWalker = await accessibility.getWalker();
let rootNode = await domWalker.getRootNode();
let a11yDoc = await a11yWalker.getAccessibleFor(rootNode);
ok(a11yDoc, "Accessible document actor is created");
info("Shutdown accessibility service");
let shutdownEvent = accessibility.once("shutdown");
await accessibility.disable();
await waitForA11yShutdown();
await shutdownEvent;
checkAccessibilityState(accessibility,
{ enabled: false, canBeDisabled: true, canBeEnabled: true });
await client.close();
gBrowser.removeCurrentTab();
});

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

@ -10,10 +10,12 @@ add_task(async function () {
let {client, walker, accessibility} =
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility.html");
let a11yWalker = await accessibility.getWalker(walker);
let a11yWalker = await accessibility.getWalker();
ok(a11yWalker, "The AccessibleWalkerFront was returned");
let a11yDoc = await a11yWalker.getDocument();
await accessibility.enable();
let rootNode = await walker.getRootNode();
let a11yDoc = await a11yWalker.getAccessibleFor(rootNode);
ok(a11yDoc, "The AccessibleFront for root doc is created");
let children = await a11yWalker.children();
@ -30,6 +32,15 @@ add_task(async function () {
role: "pushbutton"
});
let ancestry = await a11yWalker.getAncestry(accessibleFront);
is(ancestry.length, 1, "Button is a direct child of a root document.");
is(ancestry[0].accessible, a11yDoc,
"Button's only ancestor is a root document");
is(ancestry[0].children.length, 3,
"Root doc should have correct number of children");
ok(ancestry[0].children.includes(accessibleFront),
"Button accessible front is in root doc's children");
let browser = gBrowser.selectedBrowser;
// Ensure name-change event is emitted by walker when cached accessible's name
@ -67,9 +78,55 @@ add_task(async function () {
() => ContentTask.spawn(browser, null, () =>
content.document.getElementById("button").remove()));
let a11yShutdown = waitForA11yShutdown();
let shown = await a11yWalker.highlightAccessible(docChildren[0]);
ok(shown, "AccessibleHighlighter highlighted the node");
shown = await a11yWalker.highlightAccessible(a11yDoc);
ok(!shown, "AccessibleHighlighter does not highlight an accessible with no bounds");
await a11yWalker.unhighlight();
info("Checking AccessibleWalker picker functionality");
ok(a11yWalker.pick, "AccessibleWalker pick method exists");
ok(a11yWalker.pickAndFocus, "AccessibleWalker pickAndFocus method exists");
ok(a11yWalker.cancelPick, "AccessibleWalker cancelPick method exists");
let onPickerEvent = a11yWalker.once("picker-accessible-hovered");
await a11yWalker.pick();
await BrowserTestUtils.synthesizeMouseAtCenter("#h1", { type: "mousemove" }, browser);
let acc = await onPickerEvent;
checkA11yFront(acc, { name: "Accessibility Test" }, docChildren[0]);
onPickerEvent = a11yWalker.once("picker-accessible-previewed");
await BrowserTestUtils.synthesizeMouseAtCenter("#h1", { shiftKey: true }, browser);
acc = await onPickerEvent;
checkA11yFront(acc, { name: "Accessibility Test" }, docChildren[0]);
onPickerEvent = a11yWalker.once("picker-accessible-canceled");
await BrowserTestUtils.synthesizeKey("VK_ESCAPE", { type: "keydown" }, browser);
await onPickerEvent;
onPickerEvent = a11yWalker.once("picker-accessible-hovered");
await a11yWalker.pick();
await BrowserTestUtils.synthesizeMouseAtCenter("#h1", { type: "mousemove" }, browser);
await onPickerEvent;
onPickerEvent = a11yWalker.once("picker-accessible-picked");
await BrowserTestUtils.synthesizeMouseAtCenter("#h1", { }, browser);
acc = await onPickerEvent;
checkA11yFront(acc, { name: "Accessibility Test" }, docChildren[0]);
await a11yWalker.cancelPick();
info("Checking document-ready event fired by walker when top level accessible " +
"document is recreated.");
let reloaded = BrowserTestUtils.browserLoaded(browser);
let documentReady = a11yWalker.once("document-ready");
browser.reload();
await reloaded;
await documentReady;
await accessibility.disable();
await waitForA11yShutdown();
await client.close();
forceCollections();
await a11yShutdown;
gBrowser.removeCurrentTab();
});

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

@ -89,6 +89,8 @@ async function initAccessibilityFrontForUrl(url) {
let walker = await inspector.getWalker();
let accessibility = AccessibilityFront(client, form);
await accessibility.bootstrap();
return {inspector, walker, accessibility, client};
}
@ -308,24 +310,47 @@ function checkA11yFront(front, expected, expectedFront) {
}
for (let key in expected) {
is(front[key], expected[key], `accessibility front has correct ${key}`);
if (["actions", "states", "attributes"].includes(key)) {
SimpleTest.isDeeply(front[key], expected[key],
`Accessible Front has correct ${key}`);
} else {
is(front[key], expected[key], `accessibility front has correct ${key}`);
}
}
}
function getA11yInitOrShutdownPromise() {
return new Promise(resolve => {
let observe = (subject, topic, data) => {
Services.obs.removeObserver(observe, "a11y-init-or-shutdown");
resolve(data);
};
Services.obs.addObserver(observe, "a11y-init-or-shutdown");
});
}
/**
* Wait for accessibility service to shut down. We consider it shut down when
* an "a11y-init-or-shutdown" event is received with a value of "0".
*/
async function waitForA11yShutdown() {
await ContentTask.spawn(gBrowser.selectedBrowser, {}, () =>
new Promise(resolve => {
let observe = (subject, topic, data) => {
Services.obs.removeObserver(observe, "a11y-init-or-shutdown");
if (!Services.appinfo.accessibilityEnabled) {
return;
}
if (data === "0") {
resolve();
}
};
Services.obs.addObserver(observe, "a11y-init-or-shutdown");
}));
await getA11yInitOrShutdownPromise().then(data =>
data === "0" ? Promise.resolve() : Promise.reject());
}
/**
* Wait for accessibility service to initialize. We consider it initialized when
* an "a11y-init-or-shutdown" event is received with a value of "1".
*/
async function waitForA11yInit() {
if (Services.appinfo.accessibilityEnabled) {
return;
}
await getA11yInitOrShutdownPromise().then(data =>
data === "1" ? Promise.resolve() : Promise.reject());
}

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

@ -3,50 +3,74 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const {
custom,
Front,
FrontClassWithSpec,
preEvent,
types
preEvent
} = require("devtools/shared/protocol.js");
const {
accessibleSpec,
accessibleWalkerSpec,
accessibilitySpec
} = require("devtools/shared/specs/accessibility");
const events = require("devtools/shared/event-emitter");
const ACCESSIBLE_PROPERTIES = [
"role",
"name",
"value",
"description",
"help",
"keyboardShortcut",
"childCount",
"domNodeType"
];
const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
initialize(client, form) {
Front.prototype.initialize.call(this, client, form);
// Define getters for accesible properties that are received from the actor.
// Note: we would like accessible properties to be iterable for a11y
// clients.
for (let key of ACCESSIBLE_PROPERTIES) {
Object.defineProperty(this, key, {
get() {
return this._form[key];
},
enumerable: true
});
}
},
marshallPool() {
return this.walker;
return this.parent();
},
get role() {
return this._form.role;
},
get name() {
return this._form.name;
},
get value() {
return this._form.value;
},
get description() {
return this._form.description;
},
get help() {
return this._form.help;
},
get keyboardShortcut() {
return this._form.keyboardShortcut;
},
get childCount() {
return this._form.childCount;
},
get domNodeType() {
return this._form.domNodeType;
},
get indexInParent() {
return this._form.indexInParent;
},
get states() {
return this._form.states;
},
get actions() {
return this._form.actions;
},
get attributes() {
return this._form.attributes;
},
form(form, detail) {
@ -57,25 +81,14 @@ const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
this.actorID = form.actor;
this._form = form;
DevToolsUtils.defineLazyGetter(this, "walker", () =>
types.getType("accessiblewalker").read(this._form.walker, this));
},
/**
* Get a dom node front from accessible actor's raw accessible object's
* DONNode property.
*/
getDOMNode(domWalker) {
return domWalker.getNodeFromActor(this.actorID,
["rawAccessible", "DOMNode"]);
},
nameChange: preEvent("name-change", function (name, parent) {
nameChange: preEvent("name-change", function (name, parent, walker) {
this._form.name = name;
// Name change event affects the tree rendering, we fire this event on
// accessibility walker as the point of interaction for UI.
if (this.walker) {
events.emit(this.walker, "name-change", this, parent);
if (walker) {
events.emit(walker, "name-change", this, parent);
}
}),
@ -95,21 +108,37 @@ const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
this._form.keyboardShortcut = keyboardShortcut;
}),
reorder: preEvent("reorder", function (childCount) {
reorder: preEvent("reorder", function (childCount, walker) {
this._form.childCount = childCount;
// Reorder event affects the tree rendering, we fire this event on
// accessibility walker as the point of interaction for UI.
if (this.walker) {
events.emit(this.walker, "reorder", this);
if (walker) {
events.emit(walker, "reorder", this);
}
}),
textChange: preEvent("text-change", function () {
textChange: preEvent("text-change", function (walker) {
// Text event affects the tree rendering, we fire this event on
// accessibility walker as the point of interaction for UI.
if (this.walker) {
events.emit(this.walker, "text-change", this);
if (walker) {
events.emit(walker, "text-change", this);
}
}),
indexInParentChange: preEvent("index-in-parent-change", function (indexInParent) {
this._form.indexInParent = indexInParent;
}),
statesChange: preEvent("states-change", function (states) {
this._form.states = states;
}),
actionsChange: preEvent("actions-change", function (actions) {
this._form.actions = actions;
}),
attributesChange: preEvent("attributes-change", function (attributes) {
this._form.attributes = attributes;
})
});
@ -120,7 +149,17 @@ const AccessibleWalkerFront = FrontClassWithSpec(accessibleWalkerSpec, {
form(json) {
this.actorID = json.actor;
}
},
pick: custom(function (doFocus) {
if (doFocus) {
return this.pickAndFocus();
}
return this._pick();
}, {
impl: "_pick"
})
});
const AccessibilityFront = FrontClassWithSpec(accessibilitySpec, {
@ -128,7 +167,33 @@ const AccessibilityFront = FrontClassWithSpec(accessibilitySpec, {
Front.prototype.initialize.call(this, client, form);
this.actorID = form.accessibilityActor;
this.manage(this);
}
},
bootstrap: custom(function () {
return this._bootstrap().then(state => {
this.enabled = state.enabled;
this.canBeEnabled = state.canBeEnabled;
this.canBeDisabled = state.canBeDisabled;
});
}, {
impl: "_bootstrap"
}),
init: preEvent("init", function () {
this.enabled = true;
}),
shutdown: preEvent("shutdown", function () {
this.enabled = false;
}),
canBeEnabled: preEvent("can-be-enabled-change", function (canBeEnabled) {
this.canBeEnabled = canBeEnabled;
}),
canBeDisabled: preEvent("can-be-disabled-change", function (canBeDisabled) {
this.canBeDisabled = canBeDisabled;
})
});
exports.AccessibleFront = AccessibleFront;

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

@ -47,6 +47,10 @@ const PageStyleFront = FrontClassWithSpec(pageStyleSpec, {
return this._form.traits && this._form.traits.authoredStyles;
},
get supportsFontVariations() {
return this._form.traits && this._form.traits.fontVariations;
},
getMatchedSelectors: custom(function (node, property, options) {
return this._getMatchedSelectors(node, property, options).then(ret => {
return ret.matched;

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

@ -9,6 +9,17 @@ const { Arg, generateActorSpec, RetVal, types } = protocol;
types.addActorType("accessible");
/**
* Accessible with children listed in the ancestry structure calculated by the
* walker.
*/
types.addDictType("accessibleWithChildren", {
// Accessible
accessible: "accessible",
// Accessible's children
children: "array:accessible"
});
const accessibleSpec = generateActorSpec({
typeName: "accessible",
@ -20,7 +31,8 @@ const accessibleSpec = generateActorSpec({
"name-change": {
type: "nameChange",
name: Arg(0, "string"),
parent: Arg(1, "nullable:accessible")
parent: Arg(1, "nullable:accessible"),
walker: Arg(2, "nullable:accessiblewalker")
},
"value-change": {
type: "valueChange",
@ -30,13 +42,13 @@ const accessibleSpec = generateActorSpec({
type: "descriptionChange",
description: Arg(0, "string")
},
"state-change": {
type: "stateChange",
"states-change": {
type: "statesChange",
states: Arg(0, "array:string")
},
"attributes-change": {
type: "attributesChange",
states: Arg(0, "json")
attributes: Arg(0, "json")
},
"help-change": {
type: "helpChange",
@ -48,38 +60,20 @@ const accessibleSpec = generateActorSpec({
},
"reorder": {
type: "reorder",
childCount: Arg(0, "number")
childCount: Arg(0, "number"),
walker: Arg(1, "nullable:accessiblewalker")
},
"text-change": {
type: "textChange"
type: "textChange",
walker: Arg(0, "nullable:accessiblewalker")
},
"index-in-parent-change": {
type: "indexInParentChange",
indexInParent: Arg(0, "number")
}
},
methods: {
getActions: {
request: {},
response: {
actions: RetVal("array:string")
}
},
getIndexInParent: {
request: {},
response: {
indexInParent: RetVal("number")
}
},
getState: {
request: {},
response: {
states: RetVal("array:string")
}
},
getAttributes: {
request: {},
response: {
attributes: RetVal("json")
}
},
children: {
request: {},
response: {
@ -96,6 +90,24 @@ const accessibleWalkerSpec = generateActorSpec({
"accessible-destroy": {
type: "accessibleDestroy",
accessible: Arg(0, "accessible")
},
"document-ready": {
type: "documentReady",
},
"picker-accessible-picked": {
type: "pickerAccessiblePicked",
accessible: Arg(0, "nullable:accessible")
},
"picker-accessible-previewed": {
type: "pickerAccessiblePreviewed",
accessible: Arg(0, "nullable:accessible")
},
"picker-accessible-hovered": {
type: "pickerAccessibleHovered",
accessible: Arg(0, "nullable:accessible")
},
"picker-accessible-canceled": {
type: "pickerAccessibleCanceled"
}
},
@ -106,30 +118,76 @@ const accessibleWalkerSpec = generateActorSpec({
children: RetVal("array:accessible")
}
},
getDocument: {
request: {},
response: {
document: RetVal("accessible")
}
},
getAccessibleFor: {
request: { node: Arg(0, "domnode") },
response: {
accessible: RetVal("accessible")
}
}
},
getAncestry: {
request: { accessible: Arg(0, "accessible") },
response: {
ancestry: RetVal("array:accessibleWithChildren")
}
},
highlightAccessible: {
request: {
accessible: Arg(0, "accessible"),
options: Arg(1, "nullable:json")
},
response: {
value: RetVal("nullable:boolean")
}
},
unhighlight: {
request: {}
},
pick: {},
pickAndFocus: {},
cancelPick: {}
}
});
const accessibilitySpec = generateActorSpec({
typeName: "accessibility",
events: {
"init": {
type: "init"
},
"shutdown": {
type: "shutdown"
},
"can-be-disabled-change": {
type: "canBeDisabledChange",
canBeDisabled: Arg(0, "boolean")
},
"can-be-enabled-change": {
type: "canBeEnabledChange",
canBeEnabled: Arg(0, "boolean")
}
},
methods: {
bootstrap: {
request: {},
response: {
state: RetVal("json")
}
},
getWalker: {
request: {},
response: {
walker: RetVal("accessiblewalker")
}
},
enable: {
request: {},
response: {}
},
disable: {
request: {},
response: {}
}
}
});

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

@ -58,6 +58,24 @@ types.addDictType("fontpreview", {
size: "json"
});
types.addDictType("fontvariationaxis", {
tag: "string",
name: "string",
minValue: "number",
maxValue: "number",
defaultValue: "number"
});
types.addDictType("fontvariationinstancevalue", {
axis: "string",
value: "number"
});
types.addDictType("fontvariationinstance", {
name: "string",
values: "array:fontvariationinstancevalue"
});
types.addDictType("fontface", {
name: "string",
CSSFamilyName: "string",
@ -67,7 +85,9 @@ types.addDictType("fontface", {
format: "string",
preview: "nullable:fontpreview",
localName: "string",
metadata: "string"
metadata: "string",
variationAxes: "array:fontvariationaxis",
variationInstances: "array:fontvariationinstance"
});
const pageStyleSpec = generateActorSpec({
@ -95,6 +115,7 @@ const pageStyleSpec = generateActorSpec({
getAllUsedFontFaces: {
request: {
includePreviews: Option(0, "boolean"),
includeVariations: Option(1, "boolean"),
previewText: Option(0, "string"),
previewFontSize: Option(0, "string"),
previewFillStyle: Option(0, "string")
@ -107,6 +128,7 @@ const pageStyleSpec = generateActorSpec({
request: {
node: Arg(0, "domnode"),
includePreviews: Option(1, "boolean"),
includeVariations: Option(1, "boolean"),
previewText: Option(1, "string"),
previewFontSize: Option(1, "string"),
previewFillStyle: Option(1, "string")

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

@ -423,6 +423,11 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
definition->mLocalName != aCustomElement->NodeInfo()->NameAtom()) {
return;
}
if (!definition->mCallbacks) {
// definition has been unlinked. Don't try to mess with it.
return;
}
}
auto callback =

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

@ -1102,7 +1102,12 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
nsContentUtils::Retarget(relatedTargetAsNode, this);
nsCOMPtr<nsINode> targetInKnownToBeHandledScope =
FindChromeAccessOnlySubtreeOwner(aVisitor.mTargetInKnownToBeHandledScope);
if (nsContentUtils::ContentIsShadowIncludingDescendantOf(
// If aVisitor.mTargetInKnownToBeHandledScope wasn't nsINode,
// targetInKnownToBeHandledScope will be null. This may happen when
// dispatching event to Window object in a content page and
// propagating the event to a chrome Element.
if (targetInKnownToBeHandledScope &&
nsContentUtils::ContentIsShadowIncludingDescendantOf(
this, targetInKnownToBeHandledScope->SubtreeRoot())) {
// Part of step 11.4.
// "If target's root is a shadow-including inclusive ancestor of

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

@ -1445,8 +1445,8 @@ nsIDocument::nsIDocument()
mHasHadScriptHandlingObject(false),
mIsBeingUsedAsImage(false),
mIsSyntheticDocument(false),
mHasLinksToUpdate(false),
mHasLinksToUpdateRunnable(false),
mFlushingPendingLinkUpdates(false),
mMayHaveDOMMutationObservers(false),
mMayHaveAnimationObservers(false),
mHasMixedActiveContentLoaded(false),
@ -1491,7 +1491,6 @@ nsIDocument::nsIDocument()
mType(eUnknown),
mDefaultElementType(0),
mAllowXULXBL(eTriUnset),
mIsLinkUpdateRegistrationsForbidden(false),
mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
mSandboxFlags(0),
mPartID(0),
@ -9612,15 +9611,13 @@ nsIDocument::EnumerateActivityObservers(ActivityObserverEnumerator aEnumerator,
void
nsIDocument::RegisterPendingLinkUpdate(Link* aLink)
{
MOZ_RELEASE_ASSERT(!mIsLinkUpdateRegistrationsForbidden);
if (aLink->HasPendingLinkUpdate()) {
return;
}
aLink->SetHasPendingLinkUpdate();
if (!mHasLinksToUpdateRunnable) {
if (!mHasLinksToUpdateRunnable && !mFlushingPendingLinkUpdates) {
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod("nsIDocument::FlushPendingLinkUpdatesFromRunnable",
this,
@ -9637,7 +9634,6 @@ nsIDocument::RegisterPendingLinkUpdate(Link* aLink)
}
mLinksToUpdate.InfallibleAppend(aLink);
mHasLinksToUpdate = true;
}
void
@ -9651,24 +9647,26 @@ nsIDocument::FlushPendingLinkUpdatesFromRunnable()
void
nsIDocument::FlushPendingLinkUpdates()
{
MOZ_RELEASE_ASSERT(!mIsLinkUpdateRegistrationsForbidden);
if (!mHasLinksToUpdate)
if (mFlushingPendingLinkUpdates) {
return;
}
AutoRestore<bool> saved(mIsLinkUpdateRegistrationsForbidden);
mIsLinkUpdateRegistrationsForbidden = true;
for (auto iter = mLinksToUpdate.Iter(); !iter.Done(); iter.Next()) {
Link* link = iter.Get();
Element* element = link->GetElement();
if (element->OwnerDoc() == this) {
link->ClearHasPendingLinkUpdate();
if (element->IsInComposedDoc()) {
element->UpdateLinkState(link->LinkState());
auto restore = MakeScopeExit([&] { mFlushingPendingLinkUpdates = false; });
mFlushingPendingLinkUpdates = true;
while (!mLinksToUpdate.IsEmpty()) {
LinksToUpdateList links(Move(mLinksToUpdate));
for (auto iter = links.Iter(); !iter.Done(); iter.Next()) {
Link* link = iter.Get();
Element* element = link->GetElement();
if (element->OwnerDoc() == this) {
link->ClearHasPendingLinkUpdate();
if (element->IsInComposedDoc()) {
element->UpdateLinkState(link->LinkState());
}
}
}
}
mLinksToUpdate.Clear();
mHasLinksToUpdate = false;
}
already_AddRefed<nsIDocument>

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

@ -3344,10 +3344,13 @@ protected:
// The array of all links that need their status resolved. Links must add themselves
// to this set by calling RegisterPendingLinkUpdate when added to a document.
static const size_t kSegmentSize = 128;
mozilla::SegmentedVector<nsCOMPtr<mozilla::dom::Link>,
kSegmentSize,
InfallibleAllocPolicy>
mLinksToUpdate;
typedef mozilla::SegmentedVector<nsCOMPtr<mozilla::dom::Link>,
kSegmentSize,
InfallibleAllocPolicy>
LinksToUpdateList;
LinksToUpdateList mLinksToUpdate;
// SMIL Animation Controller, lazily-initialized in GetAnimationController
RefPtr<nsSMILAnimationController> mAnimationController;
@ -3441,12 +3444,12 @@ protected:
// file, etc.
bool mIsSyntheticDocument : 1;
// True if this document has links whose state needs updating
bool mHasLinksToUpdate : 1;
// True is there is a pending runnable which will call FlushPendingLinkUpdates().
bool mHasLinksToUpdateRunnable : 1;
// True if we're flushing pending link updates.
bool mFlushingPendingLinkUpdates : 1;
// True if a DOMMutationObserver is perhaps attached to a node in the document.
bool mMayHaveDOMMutationObservers : 1;
@ -3595,12 +3598,6 @@ protected:
Tri mAllowXULXBL;
/**
* This is true while FlushPendingLinkUpdates executes. Calls to
* [Un]RegisterPendingLinkUpdate will assert when this is true.
*/
bool mIsLinkUpdateRegistrationsForbidden;
// The document's script global object, the object from which the
// document can get its script context and scope. This is the
// *inner* window object.

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

@ -23,10 +23,6 @@ class nsICycleCollectorListener;
class nsScriptNameSpaceManager;
class nsIDocShell;
namespace JS {
class AutoValueVector;
} // namespace JS
namespace mozilla {
template <class> class Maybe;
struct CycleCollectorResults;

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

@ -208,7 +208,9 @@ ClientSource::WorkerExecutionReady(WorkerPrivate* aWorkerPrivate)
// execution ready. We can't reliably determine what our storage policy
// is before execution ready, unfortunately.
if (mController.isSome()) {
MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate->IsStorageAllowed());
MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate->IsStorageAllowed() ||
StringBeginsWith(aWorkerPrivate->ScriptURL(),
NS_LITERAL_STRING("blob:")));
}
// Its safe to store the WorkerPrivate* here because the ClientSource
@ -236,34 +238,36 @@ ClientSource::WindowExecutionReady(nsPIDOMWindowInner* aInnerWindow)
}
nsIDocument* doc = aInnerWindow->GetExtantDoc();
if (NS_WARN_IF(!doc)) {
return NS_ERROR_UNEXPECTED;
}
NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
nsIURI* uri = doc->GetOriginalURI();
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
// Don't use nsAutoCString here since IPC requires a full nsCString anyway.
nsCString spec;
nsresult rv = uri->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
// A client without access to storage should never be controlled by
// a service worker. Check this here in case we were controlled before
// execution ready. We can't reliably determine what our storage policy
// is before execution ready, unfortunately.
//
// Note, explicitly avoid checking storage policy for windows that inherit
// service workers from their parent. If a user opens a controlled window
// and then blocks storage, that window will continue to be controlled by
// the SW until the window is closed. Any about:blank or blob URL should
// continue to inherit the SW as well. We need to avoid triggering the
// assertion in this corner case.
if (mController.isSome()) {
MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::StorageAllowedForWindow(aInnerWindow) ==
MOZ_DIAGNOSTIC_ASSERT(spec.LowerCaseEqualsLiteral("about:blank") ||
StringBeginsWith(spec, NS_LITERAL_CSTRING("blob:")) ||
nsContentUtils::StorageAllowedForWindow(aInnerWindow) ==
nsContentUtils::StorageAccess::eAllow);
}
// Don't use nsAutoCString here since IPC requires a full nsCString anyway.
nsCString spec;
nsIURI* uri = doc->GetOriginalURI();
if (uri) {
nsresult rv = uri->GetSpec(spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
nsPIDOMWindowOuter* outer = aInnerWindow->GetOuterWindow();
if (NS_WARN_IF(!outer)) {
return NS_ERROR_UNEXPECTED;
}
NS_ENSURE_TRUE(outer, NS_ERROR_UNEXPECTED);
FrameType frameType = FrameType::Top_level;
if (!outer->IsTopLevelWindow()) {
@ -386,11 +390,19 @@ ClientSource::SetController(const ServiceWorkerDescriptor& aServiceWorker)
// A client without access to storage should never be controlled a
// a service worker. If we are already execution ready with a real
// window or worker, then verify assert the storage policy is correct.
//
// Note, explicitly avoid checking storage policy for clients that inherit
// service workers from their parent. This basically means blob: URLs
// and about:blank windows.
if (GetInnerWindow()) {
MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::StorageAllowedForWindow(GetInnerWindow()) ==
MOZ_DIAGNOSTIC_ASSERT(Info().URL().LowerCaseEqualsLiteral("about:blank") ||
StringBeginsWith(Info().URL(), NS_LITERAL_CSTRING("blob:")) ||
nsContentUtils::StorageAllowedForWindow(GetInnerWindow()) ==
nsContentUtils::StorageAccess::eAllow);
} else if (GetWorkerPrivate()) {
MOZ_DIAGNOSTIC_ASSERT(GetWorkerPrivate()->IsStorageAllowed());
MOZ_DIAGNOSTIC_ASSERT(GetWorkerPrivate()->IsStorageAllowed() ||
StringBeginsWith(GetWorkerPrivate()->ScriptURL(),
NS_LITERAL_STRING("blob:")));
}
if (mController.isSome() && mController.ref() == aServiceWorker) {

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

@ -2074,7 +2074,9 @@ ScriptLoader::FillCompileOptionsForRequest(const AutoJSAPI&jsapi,
aOptions->setMutedErrors(!subsumes);
}
if (!aRequest->IsModuleRequest()) {
if (aRequest->IsModuleRequest()) {
aOptions->hideScriptFromDebugger = true;
} else {
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> elementVal(cx);
MOZ_ASSERT(aRequest->mElement);
@ -2245,6 +2247,10 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
rv = nsJSUtils::InitModuleSourceElement(cx, module, aRequest->mElement);
NS_ENSURE_SUCCESS(rv, rv);
moduleScript->SetSourceElementAssociated();
// The script is now ready to be exposed to the debugger.
JS::Rooted<JSScript*> script(cx, JS::GetModuleScript(module));
JS::ExposeScriptToDebugger(cx, script);
}
rv = nsJSUtils::ModuleEvaluate(cx, module);

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

@ -43,13 +43,17 @@ NS_IMPL_ISUPPORTS(CSPService, nsIContentPolicy, nsIChannelEventSink)
// Helper function to identify protocols and content types not subject to CSP.
bool
subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
nsContentPolicyType contentType =
nsContentUtils::InternalContentPolicyTypeToExternal(aContentType);
// These content types are not subject to CSP content policy checks:
// TYPE_CSP_REPORT -- csp can't block csp reports
// TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl)
// TYPE_DOCUMENT -- used for frame-ancestors
if (aContentType == nsIContentPolicy::TYPE_CSP_REPORT ||
aContentType == nsIContentPolicy::TYPE_REFRESH ||
aContentType == nsIContentPolicy::TYPE_DOCUMENT) {
if (contentType == nsIContentPolicy::TYPE_CSP_REPORT ||
contentType == nsIContentPolicy::TYPE_REFRESH ||
contentType == nsIContentPolicy::TYPE_DOCUMENT) {
return false;
}
@ -90,12 +94,16 @@ subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
// hence we use protocol flags to accomplish that, but we also
// want resource:, chrome: and moz-icon to be subject to CSP
// (which also use URI_IS_LOCAL_RESOURCE).
// Exception to the rule are images and styles using a scheme
// of resource: or chrome:
bool isImgOrStyle = contentType == nsIContentPolicy::TYPE_IMAGE ||
contentType == nsIContentPolicy::TYPE_STYLESHEET;
rv = aURI->SchemeIs("resource", &match);
if (NS_SUCCEEDED(rv) && match) {
if (NS_SUCCEEDED(rv) && match && !isImgOrStyle) {
return true;
}
rv = aURI->SchemeIs("chrome", &match);
if (NS_SUCCEEDED(rv) && match) {
if (NS_SUCCEEDED(rv) && match && !isImgOrStyle) {
return true;
}
rv = aURI->SchemeIs("moz-icon", &match);

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

@ -95,6 +95,148 @@ add_task(async function test_session_permission() {
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
});
// Test to verify an about:blank iframe successfully inherits the
// parent's controller when storage is blocked between opening the
// parent page and creating the iframe.
add_task(async function test_block_storage_before_blank_iframe() {
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
let controller = await ContentTask.spawn(browser, null, async function() {
return content.navigator.serviceWorker.controller;
});
ok(!!controller, "page should be controlled with storage allowed");
let controller2 = await ContentTask.spawn(browser, null, async function() {
let f = content.document.createElement("iframe");
content.document.body.appendChild(f);
await new Promise(resolve => f.onload = resolve);
return !!f.contentWindow.navigator.serviceWorker.controller;
});
ok(!!controller2, "page should be controlled with storage allowed");
await SpecialPowers.pushPrefEnv({"set": [
["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT],
]});
let controller3 = await ContentTask.spawn(browser, null, async function() {
let f = content.document.createElement("iframe");
content.document.body.appendChild(f);
await new Promise(resolve => f.onload = resolve);
return !!f.contentWindow.navigator.serviceWorker.controller;
});
ok(!!controller3, "page should be controlled with storage allowed");
await SpecialPowers.popPrefEnv();
await BrowserTestUtils.removeTab(tab);
});
// Test to verify a blob URL iframe successfully inherits the
// parent's controller when storage is blocked between opening the
// parent page and creating the iframe.
add_task(async function test_block_storage_before_blob_iframe() {
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
let controller = await ContentTask.spawn(browser, null, async function() {
return content.navigator.serviceWorker.controller;
});
ok(!!controller, "page should be controlled with storage allowed");
let controller2 = await ContentTask.spawn(browser, null, async function() {
let b = new content.Blob(["<!DOCTYPE html><html></html>"], { type: "text/html" });
let f = content.document.createElement("iframe");
// No need to call revokeObjectURL() since the window will be closed shortly.
f.src = content.URL.createObjectURL(b);
content.document.body.appendChild(f);
await new Promise(resolve => f.onload = resolve);
return !!f.contentWindow.navigator.serviceWorker.controller;
});
ok(!!controller2, "page should be controlled with storage allowed");
await SpecialPowers.pushPrefEnv({"set": [
["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT],
]});
let controller3 = await ContentTask.spawn(browser, null, async function() {
let b = new content.Blob(["<!DOCTYPE html><html></html>"], { type: "text/html" });
let f = content.document.createElement("iframe");
// No need to call revokeObjectURL() since the window will be closed shortly.
f.src = content.URL.createObjectURL(b);
content.document.body.appendChild(f);
await new Promise(resolve => f.onload = resolve);
return !!f.contentWindow.navigator.serviceWorker.controller;
});
ok(!!controller3, "page should be controlled with storage allowed");
await SpecialPowers.popPrefEnv();
await BrowserTestUtils.removeTab(tab);
});
// Test to verify a blob worker script does not hit our service
// worker storage assertions when storage is blocked between opening
// the parent page and creating the worker. Note, we cannot
// explicitly check if the worker is controlled since we don't expose
// WorkerNavigator.serviceWorkers.controller yet.
add_task(async function test_block_storage_before_blob_worker() {
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
let controller = await ContentTask.spawn(browser, null, async function() {
return content.navigator.serviceWorker.controller;
});
ok(!!controller, "page should be controlled with storage allowed");
let scriptURL = await ContentTask.spawn(browser, null, async function() {
let b = new content.Blob(["self.postMessage(self.location.href);self.close()"],
{ type: "application/javascript" });
// No need to call revokeObjectURL() since the window will be closed shortly.
let u = content.URL.createObjectURL(b);
let w = new content.Worker(u);
return await new Promise(resolve => {
w.onmessage = e => resolve(e.data);
});
});
ok(scriptURL.startsWith("blob:"), "blob URL worker should run");
await SpecialPowers.pushPrefEnv({"set": [
["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT],
]});
let scriptURL2 = await ContentTask.spawn(browser, null, async function() {
let b = new content.Blob(["self.postMessage(self.location.href);self.close()"],
{ type: "application/javascript" });
// No need to call revokeObjectURL() since the window will be closed shortly.
let u = content.URL.createObjectURL(b);
let w = new content.Worker(u);
return await new Promise(resolve => {
w.onmessage = e => resolve(e.data);
});
});
ok(scriptURL2.startsWith("blob:"), "blob URL worker should run");
await SpecialPowers.popPrefEnv();
await BrowserTestUtils.removeTab(tab);
});
add_task(async function cleanup() {
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");

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

@ -20,6 +20,22 @@
// ];
//
// See createInterfaceMap() below for a complete list of properties.
//
// The values of the properties need to be either literal true/false
// (e.g. indicating whether something is enabled on a particular
// channel/OS) or one of the is* constants below (in cases when
// exposure is affected by channel or OS in a nontrivial way).
const version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
const isNightly = version.endsWith("a1");
const isEarlyBetaOrEarlier = SpecialPowers.EARLY_BETA_OR_EARLIER;
const isRelease = !version.includes("a");
const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
const isMac = /Mac OS/.test(navigator.oscpu);
const isWindows = /Windows/.test(navigator.oscpu);
const isAndroid = navigator.userAgent.includes("Android");
const isLinux = /Linux/.test(navigator.oscpu) && !isAndroid;
const isInsecureContext = !window.isSecureContext;
// IMPORTANT: Do not change this list without review from
// a JavaScript Engine peer!
@ -29,8 +45,8 @@ var ecmaGlobals =
{name: "ArrayBuffer", insecureContext: true},
{name: "Atomics", insecureContext: true, disabled: true},
{name: "Boolean", insecureContext: true},
{name: "ByteLengthQueuingStrategy", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
{name: "CountQueuingStrategy", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
{name: "ByteLengthQueuingStrategy", insecureContext: true, disabled: true},
{name: "CountQueuingStrategy", insecureContext: true, disabled: true},
{name: "DataView", insecureContext: true},
{name: "Date", insecureContext: true},
{name: "Error", insecureContext: true},
@ -56,7 +72,7 @@ var ecmaGlobals =
{name: "Promise", insecureContext: true},
{name: "Proxy", insecureContext: true},
{name: "RangeError", insecureContext: true},
{name: "ReadableStream", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
{name: "ReadableStream", insecureContext: true, disabled: true},
{name: "ReferenceError", insecureContext: true},
{name: "Reflect", insecureContext: true},
{name: "RegExp", insecureContext: true},
@ -75,7 +91,7 @@ var ecmaGlobals =
{name: "URIError", insecureContext: true},
{name: "WeakMap", insecureContext: true},
{name: "WeakSet", insecureContext: true},
{name: "WebAssembly", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported()}
{name: "WebAssembly", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupportedByHardware()},
];
// IMPORTANT: Do not change the list above without review from
// a JavaScript Engine peer!
@ -723,7 +739,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "OfflineAudioContext", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "OfflineResourceList", insecureContext: SpecialPowers.getBoolPref("browser.cache.offline.insecure.enable")},
{name: "OfflineResourceList", insecureContext: !isEarlyBetaOrEarlier},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Option", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -1267,16 +1283,6 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change the list above without review from a DOM peer!
function createInterfaceMap(isXBLScope) {
var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
var isNightly = version.endsWith("a1");
var isRelease = !version.includes("a");
var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
var isMac = /Mac OS/.test(navigator.oscpu);
var isWindows = /Windows/.test(navigator.oscpu);
var isAndroid = navigator.userAgent.includes("Android");
var isLinux = /Linux/.test(navigator.oscpu) && !isAndroid;
var isInsecureContext = !window.isSecureContext;
var interfaceMap = {};
function addInterfaces(interfaces)

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

@ -18,6 +18,12 @@
// ];
//
// See createInterfaceMap() below for a complete list of properties.
//
// The values of the properties need to be literal true/false
// (e.g. indicating whether something is enabled on a particular
// channel/OS). If we ever end up in a situation where a propert
// value needs to depend on channel or OS, we will need to make sure
// we have that information before setting up the property lists.
// IMPORTANT: Do not change this list without review from
// a JavaScript Engine peer!
@ -27,8 +33,8 @@ var ecmaGlobals =
{name: "ArrayBuffer", insecureContext: true},
{name: "Atomics", insecureContext: true, disabled: true},
{name: "Boolean", insecureContext: true},
{name: "ByteLengthQueuingStrategy", insecureContext: true, optional: true},
{name: "CountQueuingStrategy", insecureContext: true, optional: true},
{name: "ByteLengthQueuingStrategy", insecureContext: true, disabled: true},
{name: "CountQueuingStrategy", insecureContext: true, disabled: true},
{name: "DataView", insecureContext: true},
{name: "Date", insecureContext: true},
{name: "Error", insecureContext: true},
@ -51,7 +57,7 @@ var ecmaGlobals =
{name: "Promise", insecureContext: true},
{name: "Proxy", insecureContext: true},
{name: "RangeError", insecureContext: true},
{name: "ReadableStream", insecureContext: true, optional: true},
{name: "ReadableStream", insecureContext: true, disabled: true},
{name: "ReferenceError", insecureContext: true},
{name: "Reflect", insecureContext: true},
{name: "RegExp", insecureContext: true},
@ -70,7 +76,11 @@ var ecmaGlobals =
{name: "URIError", insecureContext: true},
{name: "WeakMap", insecureContext: true},
{name: "WeakSet", insecureContext: true},
{name: "WebAssembly", insecureContext: true, optional: true}
// WebAssembly is not supported on some hardware configurations,
// but we have no way to check that from here. Just give up for
// now and don't check for it at all. Do NOT add any other uses
// of "optional"!
{name: "WebAssembly", insecureContext: true, optional: true},
];
// IMPORTANT: Do not change the list above without review from
// a JavaScript Engine peer!

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

@ -94,8 +94,8 @@ txExprLexer::nextIsOperatorToken(Token* aToken)
nsresult
txExprLexer::parse(const nsAString& aPattern)
{
iterator start, end;
start = aPattern.BeginReading(mPosition);
iterator end;
aPattern.BeginReading(mPosition);
aPattern.EndReading(end);
//-- initialize previous token, this will automatically get
@ -125,7 +125,7 @@ txExprLexer::parse(const nsAString& aPattern)
// NCName, can get QName or OperatorName;
// FunctionName, NodeName, and AxisSpecifier may want whitespace,
// and are dealt with below
start = mPosition;
iterator start = mPosition;
while (++mPosition < end && XMLUtils::isNCNameChar(*mPosition)) {
/* just go */
}
@ -170,7 +170,7 @@ txExprLexer::parse(const nsAString& aPattern)
newToken = new Token(start, mPosition, defType);
}
else if (isXPathDigit(*mPosition)) {
start = mPosition;
iterator start = mPosition;
while (++mPosition < end && isXPathDigit(*mPosition)) {
/* just go */
}
@ -193,7 +193,8 @@ txExprLexer::parse(const nsAString& aPattern)
break;
case S_QUOTE :
case D_QUOTE :
start = mPosition;
{
iterator start = mPosition;
while (++mPosition < end && *mPosition != *start) {
// eat literal
}
@ -203,14 +204,15 @@ txExprLexer::parse(const nsAString& aPattern)
}
newToken = new Token(start + 1, mPosition, Token::LITERAL);
++mPosition;
break;
}
break;
case PERIOD:
// period can be .., .(DIGITS)+ or ., check next
if (++mPosition == end) {
newToken = new Token(mPosition - 1, Token::SELF_NODE);
}
else if (isXPathDigit(*mPosition)) {
start = mPosition - 1;
iterator start = mPosition - 1;
while (++mPosition < end && isXPathDigit(*mPosition)) {
/* just go */
}

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

@ -174,7 +174,13 @@ gfxFT2FontBase::GetCharWidth(char aChar, gfxFloat* aWidth)
{
FT_UInt gid = GetGlyph(aChar);
if (gid) {
*aWidth = FLOAT_FROM_16_16(GetFTGlyphAdvance(gid));
int32_t width;
if (!GetFTGlyphAdvance(gid, &width)) {
cairo_text_extents_t extents;
GetGlyphExtents(gid, &extents);
width = NS_lround(0x10000 * extents.x_advance);
}
*aWidth = FLOAT_FROM_16_16(width);
}
return gid;
}
@ -526,35 +532,42 @@ gfxFT2FontBase::GetGlyph(uint32_t unicode, uint32_t variation_selector)
return GetGlyph(unicode);
}
FT_Fixed
gfxFT2FontBase::GetFTGlyphAdvance(uint16_t aGID)
bool
gfxFT2FontBase::GetFTGlyphAdvance(uint16_t aGID, int32_t* aAdvance)
{
gfxFT2LockedFace face(this);
MOZ_ASSERT(face.get());
if (!face.get()) {
// Failed to get the FT_Face? Give up already.
return 0;
NS_WARNING("failed to get FT_Face!");
return false;
}
// Due to bugs like 1435234 and 1440938, we currently prefer to fall back
// to reading the advance from cairo extents, unless we're dealing with
// a variation font (for which cairo metrics may be wrong, due to FreeType
// bug 52683).
if (!(face.get()->face_flags & FT_FACE_FLAG_SCALABLE) ||
!(face.get()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
return false;
}
bool hinting = gfxPlatform::GetPlatform()->FontHintingEnabled();
int32_t flags =
hinting ? FT_LOAD_ADVANCE_ONLY
: FT_LOAD_ADVANCE_ONLY | FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
FT_Error ftError = FT_Load_Glyph(face.get(), aGID, flags);
MOZ_ASSERT(!ftError);
if (ftError != FT_Err_Ok) {
// FT_Face was somehow broken/invalid? Don't try to access glyph slot.
return 0;
// This probably shouldn't happen, but does: see bug 1440938.
NS_WARNING("failed to load glyph!");
return false;
}
FT_Fixed advance = 0;
// Due to freetype bug 52683 we MUST use the linearHoriAdvance field when
// dealing with a variation font; also use it for scalable fonts when not
// applying hinting. Otherwise, prefer hinted width from glyph->advance.x.
if ((face.get()->face_flags & FT_FACE_FLAG_SCALABLE) &&
(!hinting || (face.get()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS))) {
advance = face.get()->glyph->linearHoriAdvance;
} else {
advance = face.get()->glyph->advance.x << 10; // convert 26.6 to 16.16
}
// dealing with a variation font. (And other fonts would have returned
// earlier, so only variation fonts currently reach here.)
FT_Fixed advance = face.get()->glyph->linearHoriAdvance;
// If freetype emboldening is being used, and it's not a zero-width glyph,
// adjust the advance to account for the increased width.
@ -569,9 +582,9 @@ gfxFT2FontBase::GetFTGlyphAdvance(uint16_t aGID)
// Round the 16.16 fixed-point value to whole pixels for better consistency
// with how cairo renders the glyphs.
advance = (advance + 0x8000) & 0xffff0000u;
*aAdvance = (advance + 0x8000) & 0xffff0000u;
return advance;
return true;
}
int32_t
@ -587,7 +600,11 @@ gfxFT2FontBase::GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID)
return width;
}
width = GetFTGlyphAdvance(aGID);
if (!GetFTGlyphAdvance(aGID, &width)) {
cairo_text_extents_t extents;
GetGlyphExtents(aGID, &extents);
width = NS_lround(0x10000 * extents.x_advance);
}
mGlyphWidths->Put(aGID, width);
return width;

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

@ -45,7 +45,12 @@ public:
private:
uint32_t GetCharExtents(char aChar, cairo_text_extents_t* aExtents);
uint32_t GetCharWidth(char aChar, gfxFloat* aWidth);
FT_Fixed GetFTGlyphAdvance(uint16_t aGID);
// Get advance of a single glyph from FreeType, and return true;
// or return false if we should fall back to getting the glyph
// extents from cairo instead.
bool GetFTGlyphAdvance(uint16_t aGID, int32_t* aWidth);
void InitMetrics();
protected:

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

@ -701,7 +701,30 @@ MessageChannel::Clear()
if (!Unsound_IsClosed()) {
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProtocolName"),
nsDependentCString(mName));
MOZ_CRASH("MessageChannel destroyed without being closed");
switch (mChannelState) {
case ChannelOpening:
MOZ_CRASH("MessageChannel destroyed without being closed " \
"(mChannelState == ChannelOpening).");
break;
case ChannelConnected:
MOZ_CRASH("MessageChannel destroyed without being closed " \
"(mChannelState == ChannelConnected).");
break;
case ChannelTimeout:
MOZ_CRASH("MessageChannel destroyed without being closed " \
"(mChannelState == ChannelTimeout).");
break;
case ChannelClosing:
MOZ_CRASH("MessageChannel destroyed without being closed " \
"(mChannelState == ChannelClosing).");
break;
case ChannelError:
MOZ_CRASH("MessageChannel destroyed without being closed " \
"(mChannelState == ChannelError).");
break;
default:
MOZ_CRASH("MessageChannel destroyed without being closed.");
}
}
#endif

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

@ -40,8 +40,6 @@ extern JS_FRIEND_DATA(const js::Class* const) FunctionClassPtr;
namespace JS {
class AutoIdVector;
/**
* The answer to a successful query as to whether an object is an Array per
* ES6's internal |IsArray| operation (as exposed by |Array.isArray|).

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

@ -99,14 +99,14 @@ class GCVector
return vector.infallibleAppend(aBegin, aLength);
}
template<typename U, size_t O, class BP>
MOZ_MUST_USE bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vector.appendAll(aU); }
template<typename U, size_t O, class BP>
MOZ_MUST_USE bool appendAll(const GCVector<U, O, BP>& aU) {
return vector.append(aU.begin(), aU.length());
template<typename U>
MOZ_MUST_USE bool appendAll(const U& aU) {
return vector.append(aU.begin(), aU.end());
}
MOZ_MUST_USE bool appendN(const T& val, size_t count) { return vector.appendN(val, count); }
MOZ_MUST_USE bool appendN(const T& val, size_t count) {
return vector.appendN(val, count);
}
template<typename U>
MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd) {
@ -219,10 +219,8 @@ class MutableWrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrappe
MOZ_MUST_USE bool emplaceBack(Args&&... aArgs) {
return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
}
template<typename U, size_t O, class BP>
MOZ_MUST_USE bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vec().appendAll(aU); }
template<typename U, size_t O, class BP>
MOZ_MUST_USE bool appendAll(const JS::GCVector<U, O, BP>& aU) { return vec().appendAll(aU); }
template<typename U>
MOZ_MUST_USE bool appendAll(const U& aU) { return vec().appendAll(aU); }
MOZ_MUST_USE bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
template<typename U>
MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd) {
@ -253,4 +251,17 @@ class MutableWrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrappe
} // namespace js
namespace JS {
// An automatically rooted vector for stack use.
template <typename T>
class AutoVector : public Rooted<GCVector<T, 8>> {
using Vec = GCVector<T, 8>;
using Base = Rooted<Vec>;
public:
explicit AutoVector(JSContext* cx) : Base(cx, Vec(cx)) {}
};
} // namespace JS
#endif // js_GCVector_h

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

@ -895,19 +895,12 @@ class JS_PUBLIC_API(AutoGCRooter)
#if defined(JS_BUILD_BINAST)
BINPARSER = -4, /* js::frontend::BinSource */
#endif // defined(JS_BUILD_BINAST)
VALVECTOR = -10, /* js::AutoValueVector */
IDVECTOR = -11, /* js::AutoIdVector */
OBJVECTOR = -14, /* js::AutoObjectVector */
IONMASM = -19, /* js::jit::MacroAssembler */
WRAPVECTOR = -20, /* js::AutoWrapperVector */
WRAPPER = -21, /* js::AutoWrapperRooter */
CUSTOM = -26 /* js::CustomAutoRooter */
};
static ptrdiff_t GetTag(const Value& value) { return VALVECTOR; }
static ptrdiff_t GetTag(const jsid& id) { return IDVECTOR; }
static ptrdiff_t GetTag(JSObject* obj) { return OBJVECTOR; }
private:
AutoGCRooter ** const stackTop;

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

@ -475,6 +475,7 @@ const OPAQUE_TYPES: &'static [&'static str] = &[
"mozilla::BufferList",
"mozilla::UniquePtr.*",
"JS::Rooted<JS::Auto.*Vector.*>",
"JS::Auto.*Vector"
];
/// Types for which we should NEVER generate bindings, even if it is used within

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

@ -30,9 +30,9 @@ class TwoByteCharsZ;
class UTF8Chars;
class UTF8CharsZ;
class AutoValueVector;
class AutoIdVector;
class AutoObjectVector;
using AutoValueVector = AutoVector<Value>;
using AutoIdVector = AutoVector<jsid>;
using AutoObjectVector = AutoVector<JSObject*>;
using ValueVector = JS::GCVector<JS::Value>;
using IdVector = JS::GCVector<jsid>;

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

@ -529,6 +529,14 @@ WasmIsSupported(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
WasmIsSupportedByHardware(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setBoolean(wasm::HasCompilerSupport(cx));
return true;
}
static bool
WasmDebuggingIsSupported(JSContext* cx, unsigned argc, Value* vp)
{
@ -5375,6 +5383,10 @@ gc::ZealModeHelpText),
"wasmIsSupported()",
" Returns a boolean indicating whether WebAssembly is supported on the current device."),
JS_FN_HELP("wasmIsSupportedByHardware", WasmIsSupportedByHardware, 0, 0,
"wasmIsSupportedByHardware()",
" Returns a boolean indicating whether WebAssembly is supported on the current hardware (regardless of whether we've enabled support)."),
JS_FN_HELP("wasmDebuggingIsSupported", WasmDebuggingIsSupported, 0, 0,
"wasmDebuggingIsSupported()",
" Returns a boolean indicating whether WebAssembly debugging is supported on the current device;\n"

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

@ -183,7 +183,11 @@ js::AllocateString(JSContext* cx, InitialHeap heap)
if (!rt->gc.checkAllocatorState<allowGC>(cx, kind))
return nullptr;
if (cx->nursery().isEnabled() && heap != TenuredHeap && cx->nursery().canAllocateStrings()) {
if (cx->nursery().isEnabled() &&
heap != TenuredHeap &&
cx->nursery().canAllocateStrings() &&
cx->zone()->allocNurseryStrings)
{
auto str = static_cast<StringAllocT*>(rt->gc.tryNewNurseryString<allowGC>(cx, size, kind));
if (str)
return str;

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

@ -2777,18 +2777,21 @@ js::gc::StoreBuffer::SlotsEdge::trace(TenuringTracer& mover) const
return;
if (kind() == ElementKind) {
int32_t initLen = obj->getDenseInitializedLength();
int32_t numShifted = obj->getElementsHeader()->numShiftedElements();
int32_t clampedStart = Min(Max(0, start_ - numShifted), initLen);
int32_t clampedEnd = Min(Max(0, start_ + count_ - numShifted), initLen);
MOZ_ASSERT(clampedStart >= 0);
uint32_t initLen = obj->getDenseInitializedLength();
uint32_t numShifted = obj->getElementsHeader()->numShiftedElements();
uint32_t clampedStart = start_;
clampedStart = numShifted < clampedStart ? clampedStart - numShifted : 0;
clampedStart = Min(clampedStart, initLen);
uint32_t clampedEnd = start_ + count_;
clampedEnd = numShifted < clampedEnd ? clampedEnd - numShifted : 0;
clampedEnd = Min(clampedEnd, initLen);
MOZ_ASSERT(clampedStart <= clampedEnd);
mover.traceSlots(static_cast<HeapSlot*>(obj->getDenseElements() + clampedStart)
->unsafeUnbarrieredForTracing(), clampedEnd - clampedStart);
} else {
int32_t start = Min(uint32_t(start_), obj->slotSpan());
int32_t end = Min(uint32_t(start_) + count_, obj->slotSpan());
MOZ_ASSERT(end >= start);
uint32_t start = Min(start_, obj->slotSpan());
uint32_t end = Min(start_ + count_, obj->slotSpan());
MOZ_ASSERT(start <= end);
mover.traceObjectSlots(obj, start, end - start);
}
}
@ -3200,6 +3203,7 @@ js::TenuringTracer::moveToTenured(JSString* src)
AllocKind dstKind = src->getAllocKind();
Zone* zone = src->zone();
zone->tenuredStrings++;
TenuredCell* t = zone->arenas.allocateFromFreeList(dstKind, Arena::thingSize(dstKind));
if (!t) {

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

@ -132,9 +132,9 @@ js::Nursery::Nursery(JSRuntime* rt)
, lastCanary_(nullptr)
#endif
{
const char* env = getenv("MOZ_ENABLE_NURSERY_STRINGS");
const char* env = getenv("MOZ_NURSERY_STRINGS");
if (env && *env)
canAllocateStrings_ = true;
canAllocateStrings_ = (*env == '1');
}
bool
@ -738,21 +738,40 @@ js::Nursery::collect(JS::gcreason::Reason reason)
bool validPromotionRate;
const float promotionRate = calcPromotionRate(&validPromotionRate);
uint32_t pretenureCount = 0;
if (validPromotionRate) {
if (promotionRate > 0.8 || IsFullStoreBufferReason(reason)) {
JSContext* cx = TlsContext.get();
for (auto& entry : tenureCounts.entries) {
if (entry.count >= 3000) {
ObjectGroup* group = entry.group;
if (group->canPreTenure() && group->zone()->group()->canEnterWithoutYielding(cx)) {
AutoCompartment ac(cx, group);
group->setShouldPreTenure(cx);
pretenureCount++;
}
bool shouldPretenure = (validPromotionRate && promotionRate > 0.6) ||
IsFullStoreBufferReason(reason);
if (shouldPretenure) {
JSContext* cx = TlsContext.get();
for (auto& entry : tenureCounts.entries) {
if (entry.count >= 3000) {
ObjectGroup* group = entry.group;
if (group->canPreTenure() && group->zone()->group()->canEnterWithoutYielding(cx)) {
AutoCompartment ac(cx, group);
group->setShouldPreTenure(cx);
pretenureCount++;
}
}
}
}
for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
if (shouldPretenure && zone->allocNurseryStrings && zone->tenuredStrings >= 30 * 1000) {
JSRuntime::AutoProhibitActiveContextChange apacc(rt);
CancelOffThreadIonCompile(zone);
bool preserving = zone->isPreservingCode();
zone->setPreservingCode(false);
zone->discardJitCode(rt->defaultFreeOp());
zone->setPreservingCode(preserving);
for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
if (jit::JitCompartment* jitComp = c->jitCompartment()) {
jitComp->discardStubs();
jitComp->stringsCanBeInNursery = false;
}
}
zone->allocNurseryStrings = false;
}
zone->tenuredStrings = 0;
}
endProfile(ProfileKey::Pretenure);
// We ignore gcMaxBytes when allocating for minor collection. However, if we
@ -1086,7 +1105,7 @@ js::Nursery::setStartPosition()
void
js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason)
{
static const double GrowThreshold = 0.05;
static const double GrowThreshold = 0.03;
static const double ShrinkThreshold = 0.01;
unsigned newMaxNurseryChunks;

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

@ -179,13 +179,13 @@ AutoGCRooter::trace(JSTracer* trc)
}
case WRAPVECTOR: {
AutoWrapperVector::VectorImpl& vector = static_cast<AutoWrapperVector*>(this)->vector;
auto vector = static_cast<AutoWrapperVector*>(this);
/*
* We need to use TraceManuallyBarrieredEdge here because we trace
* wrapper roots in every slice. This is because of some rule-breaking
* in RemapAllWrappersForObject; see comment there.
*/
for (WrapperValue* p = vector.begin(); p < vector.end(); p++)
for (WrapperValue* p = vector->begin(); p < vector->end(); p++)
TraceManuallyBarrieredEdge(trc, &p->get(), "js::AutoWrapperVector.vector");
return;
}

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

@ -276,17 +276,17 @@ class StoreBuffer
const static int ElementKind = 1;
uintptr_t objectAndKind_; // NativeObject* | Kind
int32_t start_;
int32_t count_;
uint32_t start_;
uint32_t count_;
SlotsEdge() : objectAndKind_(0), start_(0), count_(0) {}
SlotsEdge(NativeObject* object, int kind, int32_t start, int32_t count)
SlotsEdge(NativeObject* object, int kind, uint32_t start, uint32_t count)
: objectAndKind_(uintptr_t(object) | kind), start_(start), count_(count)
{
MOZ_ASSERT((uintptr_t(object) & 1) == 0);
MOZ_ASSERT(kind <= 1);
MOZ_ASSERT(start >= 0);
MOZ_ASSERT(count > 0);
MOZ_ASSERT(start + count > start);
}
NativeObject* object() const { return reinterpret_cast<NativeObject*>(objectAndKind_ & ~1); }
@ -313,10 +313,12 @@ class StoreBuffer
// is particularly useful for coalescing a series of increasing or
// decreasing single index writes 0, 1, 2, ..., N into a SlotsEdge
// range of elements [0, N].
auto end = start_ + count_ + 1;
auto start = start_ - 1;
uint32_t end = start_ + count_ + 1;
uint32_t start = start_ > 0 ? start_ - 1 : 0;
MOZ_ASSERT(start < end);
auto otherEnd = other.start_ + other.count_;
uint32_t otherEnd = other.start_ + other.count_;
MOZ_ASSERT(other.start_ <= otherEnd);
return (start <= other.start_ && other.start_ <= end) ||
(start <= otherEnd && otherEnd <= end);
}
@ -326,7 +328,7 @@ class StoreBuffer
// overlap.
void merge(const SlotsEdge& other) {
MOZ_ASSERT(overlaps(other));
auto end = Max(start_ + count_, other.start_ + other.count_);
uint32_t end = Max(start_ + count_, other.start_ + other.count_);
start_ = Min(start_, other.start_);
count_ = end - start_;
}
@ -416,7 +418,7 @@ class StoreBuffer
void unputValue(JS::Value* vp) { unput(bufferVal, ValueEdge(vp)); }
void putCell(Cell** cellp) { put(bufferCell, CellPtrEdge(cellp)); }
void unputCell(Cell** cellp) { unput(bufferCell, CellPtrEdge(cellp)); }
void putSlot(NativeObject* obj, int kind, int32_t start, int32_t count) {
void putSlot(NativeObject* obj, int kind, uint32_t start, uint32_t count) {
SlotsEdge edge(obj, kind, start, count);
if (bufferSlot.last_.overlaps(edge))
bufferSlot.last_.merge(edge);

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

@ -46,6 +46,8 @@ JS::Zone::Zone(JSRuntime* rt, ZoneGroup* group)
usage(&rt->gc.usage),
threshold(),
gcDelayBytes(0),
tenuredStrings(group, 0),
allocNurseryStrings(group, true),
propertyTree_(group, this),
baseShapes_(group, this),
initialShapes_(group, this),

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

@ -482,6 +482,9 @@ struct Zone : public JS::shadow::Zone,
// the current GC.
js::UnprotectedData<size_t> gcDelayBytes;
js::ZoneGroupData<uint32_t> tenuredStrings;
js::ZoneGroupData<bool> allocNurseryStrings;
private:
// Shared Shape property tree.
js::ZoneGroupData<js::PropertyTree> propertyTree_;

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

@ -283,9 +283,7 @@ BaselineCacheIRCompiler::emitGuardCompartment()
return false;
Address addr(stubAddress(reader.stubOffset()));
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
masm.loadPtr(Address(scratch, ObjectGroup::offsetOfCompartment()), scratch);
masm.branchPtr(Assembler::NotEqual, addr, scratch, failure->label());
masm.branchTestObjCompartment(Assembler::NotEqual, obj, addr, scratch, failure->label());
return true;
}
@ -300,10 +298,7 @@ BaselineCacheIRCompiler::emitGuardAnyClass()
return false;
Address testAddr(stubAddress(reader.stubOffset()));
masm.loadObjGroup(obj, scratch);
masm.loadPtr(Address(scratch, ObjectGroup::offsetOfClasp()), scratch);
masm.branchPtr(Assembler::NotEqual, testAddr, scratch, failure->label());
masm.branchTestObjClass(Assembler::NotEqual, obj, scratch, testAddr, failure->label());
return true;
}
@ -528,9 +523,7 @@ BaselineCacheIRCompiler::emitMegamorphicLoadSlotResult()
return false;
// The object must be Native.
masm.loadObjClass(obj, scratch3);
masm.branchTest32(Assembler::NonZero, Address(scratch3, Class::offsetOfFlags()),
Imm32(Class::NON_NATIVE), failure->label());
masm.branchIfNonNativeObj(obj, scratch3, failure->label());
masm.Push(UndefinedValue());
masm.moveStackPtrTo(scratch3.get());
@ -1176,27 +1169,22 @@ BaselineCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
// per the acquired properties analysis. Only change the group if the
// old group still has a newScript. This only applies to PlainObjects.
Label noGroupChange;
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch1);
masm.branchPtr(Assembler::Equal,
Address(scratch1, ObjectGroup::offsetOfAddendum()),
ImmWord(0),
&noGroupChange);
masm.branchIfObjGroupHasNoAddendum(obj, scratch1, &noGroupChange);
// Reload the new group from the cache.
// Update the object's group.
masm.loadPtr(newGroupAddr, scratch1);
Address groupAddr(obj, JSObject::offsetOfGroup());
EmitPreBarrier(masm, groupAddr, MIRType::ObjectGroup);
masm.storePtr(scratch1, groupAddr);
masm.storeObjGroup(scratch1, obj, [](MacroAssembler& masm, const Address& addr) {
EmitPreBarrier(masm, addr, MIRType::ObjectGroup);
});
masm.bind(&noGroupChange);
}
// Update the object's shape.
Address shapeAddr(obj, ShapedObject::offsetOfShape());
masm.loadPtr(newShapeAddr, scratch1);
EmitPreBarrier(masm, shapeAddr, MIRType::Shape);
masm.storePtr(scratch1, shapeAddr);
masm.storeObjShape(scratch1, obj, [](MacroAssembler& masm, const Address& addr) {
EmitPreBarrier(masm, addr, MIRType::Shape);
});
// Perform the store. No pre-barrier required since this is a new
// initialization.

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

@ -426,11 +426,10 @@ ICTypeUpdate_ObjectGroup::Compiler::generateStubCode(MacroAssembler& masm)
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
// Guard on the object's ObjectGroup.
Register obj = masm.extractObject(R0, R1.scratchReg());
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), R1.scratchReg());
Register scratch = R1.scratchReg();
Register obj = masm.extractObject(R0, scratch);
Address expectedGroup(ICStubReg, ICTypeUpdate_ObjectGroup::offsetOfGroup());
masm.branchPtr(Assembler::NotEqual, expectedGroup, R1.scratchReg(), &failure);
masm.branchTestObjGroup(Assembler::NotEqual, obj, expectedGroup, scratch, &failure);
// Group matches, load true into R1.scratchReg() and return.
masm.mov(ImmWord(1), R1.scratchReg());
@ -775,9 +774,7 @@ LoadTypedThingLength(MacroAssembler& masm, TypedThingLayout layout, Register obj
break;
case Layout_OutlineTypedObject:
case Layout_InlineTypedObject:
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), result);
masm.loadPtr(Address(result, ObjectGroup::offsetOfAddendum()), result);
masm.unboxInt32(Address(result, ArrayTypeDescr::offsetOfLength()), result);
masm.loadTypedObjectLength(obj, result);
break;
default:
MOZ_CRASH();
@ -3432,11 +3429,9 @@ ICCall_ClassHook::Compiler::generateStubCode(MacroAssembler& masm)
// Ensure the callee's class matches the one in this stub.
Register callee = masm.extractObject(R1, ExtractTemp0);
Register scratch = regs.takeAny();
masm.loadObjClass(callee, scratch);
masm.branchPtr(Assembler::NotEqual,
Address(ICStubReg, ICCall_ClassHook::offsetOfClass()),
scratch, &failure);
masm.branchTestObjClass(Assembler::NotEqual, callee, scratch,
Address(ICStubReg, ICCall_ClassHook::offsetOfClass()),
&failure);
regs.add(R1);
regs.takeUnchecked(callee);

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

@ -1472,9 +1472,7 @@ CacheIRCompiler::emitGuardIsNativeObject()
if (!addFailurePath(&failure))
return false;
masm.loadObjClass(obj, scratch);
masm.branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()),
Imm32(Class::NON_NATIVE), failure->label());
masm.branchIfNonNativeObj(obj, scratch, failure->label());
return true;
}
@ -2668,9 +2666,7 @@ CacheIRCompiler::emitMegamorphicLoadSlotByValueResult()
return false;
// The object must be Native.
masm.loadObjClass(obj, scratch);
masm.branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()),
Imm32(Class::NON_NATIVE), failure->label());
masm.branchIfNonNativeObj(obj, scratch, failure->label());
// idVal will be in vp[0], result will be stored in vp[1].
masm.reserveStack(sizeof(Value));

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

@ -959,8 +959,7 @@ CodeGenerator::visitFunctionDispatch(LFunctionDispatch* lir)
MOZ_ASSERT(i < mir->numCases());
LBlock* target = skipTrivialBlocks(mir->getCaseBlock(i))->lir();
if (ObjectGroup* funcGroup = mir->getCaseObjectGroup(i)) {
masm.branchPtr(Assembler::Equal, Address(input, JSObject::offsetOfGroup()),
ImmGCPtr(funcGroup), target->label());
masm.branchTestObjGroup(Assembler::Equal, input, funcGroup, target->label());
} else {
JSFunction* func = mir->getCase(i);
masm.branchPtr(Assembler::Equal, input, ImmGCPtr(func), target->label());
@ -979,7 +978,7 @@ CodeGenerator::visitObjectGroupDispatch(LObjectGroupDispatch* lir)
Register temp = ToRegister(lir->temp());
// Load the incoming ObjectGroup in temp.
masm.loadPtr(Address(input, JSObject::offsetOfGroup()), temp);
masm.loadObjGroupUnsafe(input, temp);
// Compare ObjectGroups.
MacroAssembler::BranchGCPtr lastBranch;
@ -2518,8 +2517,7 @@ CodeGenerator::visitRegExpPrototypeOptimizable(LRegExpPrototypeOptimizable* ins)
RegExpCompartment::offsetOfOptimizableRegExpPrototypeShape();
masm.loadPtr(Address(temp, offset), temp);
masm.loadPtr(Address(object, ShapedObject::offsetOfShape()), output);
masm.branchPtr(Assembler::NotEqual, output, temp, ool->entry());
masm.branchTestObjShape(Assembler::NotEqual, object, temp, ool->entry());
masm.move32(Imm32(0x1), output);
masm.bind(ool->rejoin());
@ -2579,8 +2577,7 @@ CodeGenerator::visitRegExpInstanceOptimizable(LRegExpInstanceOptimizable* ins)
RegExpCompartment::offsetOfOptimizableRegExpInstanceShape();
masm.loadPtr(Address(temp, offset), temp);
masm.loadPtr(Address(object, ShapedObject::offsetOfShape()), output);
masm.branchPtr(Assembler::NotEqual, output, temp, ool->entry());
masm.branchTestObjShape(Assembler::NotEqual, object, temp, ool->entry());
masm.move32(Imm32(0x1), output);
masm.bind(ool->rejoin());
@ -3716,11 +3713,8 @@ CodeGenerator::visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite* lir)
OutOfLineCode* ool = oolCallVM(CopyElementsForWriteInfo, lir,
ArgList(object), StoreNothing());
if (lir->mir()->checkNative()) {
masm.loadObjClass(object, temp);
masm.branchTest32(Assembler::NonZero, Address(temp, Class::offsetOfFlags()),
Imm32(Class::NON_NATIVE), ool->rejoin());
}
if (lir->mir()->checkNative())
masm.branchIfNonNativeObj(object, temp, ool->rejoin());
masm.loadPtr(Address(object, NativeObject::offsetOfElements()), temp);
masm.branchTest32(Assembler::NonZero,
@ -4302,17 +4296,8 @@ LoadDOMPrivate(MacroAssembler& masm, Register obj, Register priv, DOMObjectKind
masm.branchTestObjectIsProxy(true, obj, priv, &isProxy);
if (kind != DOMObjectKind::Proxy) {
#ifdef DEBUG
// If it's a native object, the value must be in a fixed slot.
Label hasFixedSlots;
masm.loadPtr(Address(obj, ShapedObject::offsetOfShape()), priv);
masm.branchTest32(Assembler::NonZero,
Address(priv, Shape::offsetOfSlotInfo()),
Imm32(Shape::fixedSlotsMask()),
&hasFixedSlots);
masm.assumeUnreachable("Expected a fixed slot");
masm.bind(&hasFixedSlots);
#endif
masm.debugAssertObjHasFixedSlots(obj, priv);
masm.loadPrivate(Address(obj, NativeObject::getFixedSlotOffset(0)), priv);
if (kind == DOMObjectKind::Unknown)
masm.jump(&done);
@ -4888,10 +4873,10 @@ CodeGenerator::emitApplyGeneric(T* apply)
// Unless already known, guard that calleereg is actually a function object.
if (!apply->hasSingleTarget()) {
masm.loadObjClass(calleereg, objreg);
ImmPtr ptr = ImmPtr(&JSFunction::class_);
bailoutCmpPtr(Assembler::NotEqual, objreg, ptr, apply->snapshot());
Label bail;
masm.branchTestObjClass(Assembler::NotEqual, calleereg, objreg, &JSFunction::class_,
&bail);
bailoutFrom(&bail, apply->snapshot());
}
// Copy the arguments of the current function.
@ -6378,38 +6363,7 @@ CodeGenerator::visitSimdUnbox(LSimdUnbox* lir)
Register temp = ToRegister(lir->temp());
Label bail;
// obj->group()
masm.loadPtr(Address(object, JSObject::offsetOfGroup()), temp);
// Guard that the object has the same representation as the one produced for
// SIMD value-type.
Address clasp(temp, ObjectGroup::offsetOfClasp());
static_assert(!SimdTypeDescr::Opaque, "SIMD objects are transparent");
masm.branchPtr(Assembler::NotEqual, clasp, ImmPtr(&InlineTransparentTypedObject::class_),
&bail);
// obj->type()->typeDescr()
// The previous class pointer comparison implies that the addendumKind is
// Addendum_TypeDescr.
masm.loadPtr(Address(temp, ObjectGroup::offsetOfAddendum()), temp);
// Check for the /Kind/ reserved slot of the TypeDescr. This is an Int32
// Value which is equivalent to the object class check.
static_assert(JS_DESCR_SLOT_KIND < NativeObject::MAX_FIXED_SLOTS, "Load from fixed slots");
Address typeDescrKind(temp, NativeObject::getFixedSlotOffset(JS_DESCR_SLOT_KIND));
masm.assertTestInt32(Assembler::Equal, typeDescrKind,
"MOZ_ASSERT(obj->type()->typeDescr()->getReservedSlot(JS_DESCR_SLOT_KIND).isInt32())");
masm.branch32(Assembler::NotEqual, masm.ToPayload(typeDescrKind), Imm32(js::type::Simd), &bail);
SimdType type = lir->mir()->simdType();
// Check if the SimdTypeDescr /Type/ match the specialization of this
// MSimdUnbox instruction.
static_assert(JS_DESCR_SLOT_TYPE < NativeObject::MAX_FIXED_SLOTS, "Load from fixed slots");
Address typeDescrType(temp, NativeObject::getFixedSlotOffset(JS_DESCR_SLOT_TYPE));
masm.assertTestInt32(Assembler::Equal, typeDescrType,
"MOZ_ASSERT(obj->type()->typeDescr()->getReservedSlot(JS_DESCR_SLOT_TYPE).isInt32())");
masm.branch32(Assembler::NotEqual, masm.ToPayload(typeDescrType), Imm32(int32_t(type)), &bail);
masm.branchIfNotSimdObject(object, temp, lir->mir()->simdType(), &bail);
// Load the value from the data of the InlineTypedObject.
Address objectData(object, InlineTypedObject::offsetOfDataStart());
@ -7095,9 +7049,7 @@ CodeGenerator::visitTypedObjectDescr(LTypedObjectDescr* lir)
{
Register obj = ToRegister(lir->object());
Register out = ToRegister(lir->output());
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), out);
masm.loadPtr(Address(out, ObjectGroup::offsetOfAddendum()), out);
masm.loadTypedObjectDescr(obj, out);
}
void
@ -7110,9 +7062,7 @@ CodeGenerator::visitTypedObjectElements(LTypedObjectElements* lir)
masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out);
} else {
Label inlineObject, done;
masm.loadObjClass(obj, out);
masm.branchPtr(Assembler::Equal, out, ImmPtr(&InlineOpaqueTypedObject::class_), &inlineObject);
masm.branchPtr(Assembler::Equal, out, ImmPtr(&InlineTransparentTypedObject::class_), &inlineObject);
masm.branchIfInlineTypedObject(obj, out, &inlineObject);
masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out);
masm.jump(&done);
@ -7135,9 +7085,7 @@ CodeGenerator::visitSetTypedObjectOffset(LSetTypedObjectOffset* lir)
masm.loadPtr(Address(object, OutlineTypedObject::offsetOfOwner()), temp0);
Label inlineObject, done;
masm.loadObjClass(temp0, temp1);
masm.branchPtr(Assembler::Equal, temp1, ImmPtr(&InlineOpaqueTypedObject::class_), &inlineObject);
masm.branchPtr(Assembler::Equal, temp1, ImmPtr(&InlineTransparentTypedObject::class_), &inlineObject);
masm.branchIfInlineTypedObject(temp0, temp1, &inlineObject);
masm.loadPrivate(Address(temp0, ArrayBufferObject::offsetOfDataSlot()), temp0);
masm.jump(&done);
@ -9323,8 +9271,7 @@ CodeGenerator::visitConvertUnboxedObjectToNative(LConvertUnboxedObjectToNative*
OutOfLineCode* ool = oolCallVM(ConvertUnboxedPlainObjectToNativeInfo,
lir, ArgList(object), StoreNothing());
masm.branchPtr(Assembler::Equal, Address(object, JSObject::offsetOfGroup()),
ImmGCPtr(lir->mir()->group()), ool->entry());
masm.branchTestObjGroup(Assembler::Equal, object, lir->mir()->group(), ool->entry());
masm.bind(ool->rejoin());
}
@ -9521,8 +9468,7 @@ CodeGenerator::visitArraySlice(LArraySlice* lir)
masm.createGCObject(temp1, temp2, lir->mir()->templateObj(), lir->mir()->initialHeap(), &fail);
// Fixup the group of the result in case it doesn't match the template object.
masm.loadPtr(Address(object, JSObject::offsetOfGroup()), temp2);
masm.storePtr(temp2, Address(temp1, JSObject::offsetOfGroup()));
masm.copyObjGroupNoPreBarrier(object, temp1, temp2);
masm.jump(&call);
{
@ -12140,7 +12086,7 @@ void
CodeGenerator::emitIsCallableOrConstructor(Register object, Register output, Label* failure)
{
Label notFunction, hasCOps, done;
masm.loadObjClass(object, output);
masm.loadObjClassUnsafe(object, output);
// Just skim proxies off. Their notion of isCallable()/isConstructor() is
// more complicated.
@ -12319,7 +12265,7 @@ static void
EmitObjectIsArray(MacroAssembler& masm, OutOfLineCode* ool, Register obj, Register output,
Label* notArray = nullptr)
{
masm.loadObjClass(obj, output);
masm.loadObjClassUnsafe(obj, output);
Label isArray;
masm.branchPtr(Assembler::Equal, output, ImmPtr(&ArrayObject::class_), &isArray);
@ -12380,7 +12326,7 @@ CodeGenerator::visitIsTypedArray(LIsTypedArray* lir)
const Class* firstTypedArrayClass = TypedArrayObject::classForType(Scalar::Int8);
const Class* lastTypedArrayClass = TypedArrayObject::classForType(Scalar::Uint8Clamped);
masm.loadObjClass(object, output);
masm.loadObjClassUnsafe(object, output);
masm.branchPtr(Assembler::Below, output, ImmPtr(firstTypedArrayClass), &notTypedArray);
masm.branchPtr(Assembler::Above, output, ImmPtr(lastTypedArrayClass), &notTypedArray);
@ -12434,7 +12380,7 @@ CodeGenerator::visitHasClass(LHasClass* ins)
Register lhs = ToRegister(ins->lhs());
Register output = ToRegister(ins->output());
masm.loadObjClass(lhs, output);
masm.loadObjClassUnsafe(lhs, output);
masm.cmpPtrSet(Assembler::Equal, output, ImmPtr(ins->mir()->getClass()), output);
}

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

@ -205,7 +205,9 @@ CompileZone::addressOfStringNurseryCurrentEnd()
bool
CompileZone::canNurseryAllocateStrings()
{
return nurseryExists() && zone()->group()->nursery().canAllocateStrings();
return nurseryExists() &&
zone()->group()->nursery().canAllocateStrings() &&
zone()->allocNurseryStrings;
}
bool

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

@ -2229,6 +2229,12 @@ IsRegExpHoistable(MIRGenerator* mir, MDefinition* regexp, MDefinitionVector& wor
bool
jit::MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph)
{
// If we are compiling try blocks, regular expressions may be observable
// from catch blocks (which Ion does not compile). For now just disable the
// pass in this case.
if (graph.hasTryBlock())
return true;
MDefinitionVector worklist(graph.alloc());
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {

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

@ -699,9 +699,8 @@ IonCacheIRCompiler::emitGuardCompartment()
if (!addFailurePath(&failure))
return false;
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
masm.loadPtr(Address(scratch, ObjectGroup::offsetOfCompartment()), scratch);
masm.branchPtr(Assembler::NotEqual, scratch, ImmPtr(compartment), failure->label());
masm.branchTestObjCompartment(Assembler::NotEqual, obj, compartment, scratch,
failure->label());
return true;
}
@ -935,9 +934,7 @@ IonCacheIRCompiler::emitMegamorphicLoadSlotResult()
return false;
// The object must be Native.
masm.loadObjClass(obj, scratch3);
masm.branchTest32(Assembler::NonZero, Address(scratch3, Class::offsetOfFlags()),
Imm32(Class::NON_NATIVE), failure->label());
masm.branchIfNonNativeObj(obj, scratch3, failure->label());
masm.Push(UndefinedValue());
masm.moveStackPtrTo(scratch3.get());
@ -1652,23 +1649,20 @@ IonCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
// per the acquired properties analysis. Only change the group if the
// old group still has a newScript. This only applies to PlainObjects.
Label noGroupChange;
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch1);
masm.branchPtr(Assembler::Equal,
Address(scratch1, ObjectGroup::offsetOfAddendum()),
ImmWord(0),
&noGroupChange);
masm.branchIfObjGroupHasNoAddendum(obj, scratch1, &noGroupChange);
Address groupAddr(obj, JSObject::offsetOfGroup());
EmitPreBarrier(masm, groupAddr, MIRType::ObjectGroup);
masm.storePtr(ImmGCPtr(newGroup), groupAddr);
// Update the object's group.
masm.storeObjGroup(newGroup, obj, [](MacroAssembler& masm, const Address& addr) {
EmitPreBarrier(masm, addr, MIRType::ObjectGroup);
});
masm.bind(&noGroupChange);
}
// Update the object's shape.
Address shapeAddr(obj, ShapedObject::offsetOfShape());
EmitPreBarrier(masm, shapeAddr, MIRType::Shape);
masm.storePtr(ImmGCPtr(newShape), shapeAddr);
masm.storeObjShape(newShape, obj, [](MacroAssembler& masm, const Address& addr) {
EmitPreBarrier(masm, addr, MIRType::Shape);
});
// Perform the store. No pre-barrier required since this is a new
// initialization.

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

@ -621,6 +621,11 @@ class JitCompartment
void sweep(JSCompartment* compartment);
void discardStubs() {
for (ReadBarrieredJitCode& stubRef : stubs_)
stubRef = nullptr;
}
JitCode* stringConcatStubNoBarrier(uint32_t* requiredBarriersOut) const {
return getStubNoBarrier(StringConcat, requiredBarriersOut);
}

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

@ -467,7 +467,7 @@ MacroAssembler::branchIfObjectEmulatesUndefined(Register objReg, Register scratc
{
// The branches to out-of-line code here implement a conservative version
// of the JSObject::isWrapper test performed in EmulatesUndefined.
loadObjClass(objReg, scratch);
loadObjClassUnsafe(objReg, scratch);
branchTestClassIsProxy(true, scratch, slowCheck);
@ -492,13 +492,22 @@ MacroAssembler::branchFunctionKind(Condition cond, JSFunction::FunctionKind kind
}
void
MacroAssembler::branchTestObjClass(Condition cond, Register obj, Register scratch, const js::Class* clasp,
Label* label)
MacroAssembler::branchTestObjClass(Condition cond, Register obj, Register scratch,
const js::Class* clasp, Label* label)
{
loadObjGroup(obj, scratch);
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
branchPtr(cond, Address(scratch, ObjectGroup::offsetOfClasp()), ImmPtr(clasp), label);
}
void
MacroAssembler::branchTestObjClass(Condition cond, Register obj, Register scratch,
const Address& clasp, Label* label)
{
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
loadPtr(Address(scratch, ObjectGroup::offsetOfClasp()), scratch);
branchPtr(cond, clasp, scratch, label);
}
void
MacroAssembler::branchTestObjShape(Condition cond, Register obj, const Shape* shape, Label* label)
{
@ -512,7 +521,8 @@ MacroAssembler::branchTestObjShape(Condition cond, Register obj, Register shape,
}
void
MacroAssembler::branchTestObjGroup(Condition cond, Register obj, ObjectGroup* group, Label* label)
MacroAssembler::branchTestObjGroup(Condition cond, Register obj, const ObjectGroup* group,
Label* label)
{
branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), ImmGCPtr(group), label);
}
@ -534,7 +544,7 @@ MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp, Label* label)
void
MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label)
{
loadObjClass(object, scratch);
loadObjClassUnsafe(object, scratch);
branchTestClassIsProxy(proxy, scratch, label);
}
@ -733,6 +743,44 @@ MacroAssembler::reserveStack(uint32_t amount)
}
#endif // !JS_CODEGEN_ARM64
template <typename EmitPreBarrier>
void
MacroAssembler::storeObjGroup(Register group, Register obj, EmitPreBarrier emitPreBarrier)
{
MOZ_ASSERT(group != obj);
Address groupAddr(obj, JSObject::offsetOfGroup());
emitPreBarrier(*this, groupAddr);
storePtr(group, groupAddr);
}
template <typename EmitPreBarrier>
void
MacroAssembler::storeObjGroup(ObjectGroup* group, Register obj, EmitPreBarrier emitPreBarrier)
{
Address groupAddr(obj, JSObject::offsetOfGroup());
emitPreBarrier(*this, groupAddr);
storePtr(ImmGCPtr(group), groupAddr);
}
template <typename EmitPreBarrier>
void
MacroAssembler::storeObjShape(Register shape, Register obj, EmitPreBarrier emitPreBarrier)
{
MOZ_ASSERT(shape != obj);
Address shapeAddr(obj, ShapedObject::offsetOfShape());
emitPreBarrier(*this, shapeAddr);
storePtr(shape, shapeAddr);
}
template <typename EmitPreBarrier>
void
MacroAssembler::storeObjShape(Shape* shape, Register obj, EmitPreBarrier emitPreBarrier)
{
Address shapeAddr(obj, ShapedObject::offsetOfShape());
emitPreBarrier(*this, shapeAddr);
storePtr(ImmGCPtr(shape), shapeAddr);
}
template <typename T>
void
MacroAssembler::storeObjectOrNull(Register src, const T& dest)

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

@ -1751,7 +1751,7 @@ void
MacroAssembler::typeOfObject(Register obj, Register scratch, Label* slow,
Label* isObject, Label* isCallable, Label* isUndefined)
{
loadObjClass(obj, scratch);
loadObjClassUnsafe(obj, scratch);
// Proxies can emulate undefined and have complex isCallable behavior.
branchTestClassIsProxy(true, scratch, slow);
@ -3200,6 +3200,128 @@ MacroAssembler::branchIfNotInterpretedConstructor(Register fun, Register scratch
branchTest32(Assembler::Zero, scratch, Imm32(bits), label);
}
void
MacroAssembler::branchTestObjGroup(Condition cond, Register obj, const Address& group,
Register scratch, Label* label)
{
// Note: obj and scratch registers may alias.
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
branchPtr(cond, group, scratch, label);
}
void
MacroAssembler::branchTestObjCompartment(Condition cond, Register obj, const Address& compartment,
Register scratch, Label* label)
{
MOZ_ASSERT(obj != scratch);
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
loadPtr(Address(scratch, ObjectGroup::offsetOfCompartment()), scratch);
branchPtr(cond, compartment, scratch, label);
}
void
MacroAssembler::branchTestObjCompartment(Condition cond, Register obj,
const JSCompartment* compartment, Register scratch,
Label* label)
{
MOZ_ASSERT(obj != scratch);
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
loadPtr(Address(scratch, ObjectGroup::offsetOfCompartment()), scratch);
branchPtr(cond, scratch, ImmPtr(compartment), label);
}
void
MacroAssembler::branchIfObjGroupHasNoAddendum(Register obj, Register scratch, Label* label)
{
MOZ_ASSERT(obj != scratch);
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
branchPtr(Assembler::Equal,
Address(scratch, ObjectGroup::offsetOfAddendum()),
ImmWord(0),
label);
}
void
MacroAssembler::branchIfPretenuredGroup(const ObjectGroup* group, Register scratch, Label* label)
{
movePtr(ImmGCPtr(group), scratch);
branchTest32(Assembler::NonZero, Address(scratch, ObjectGroup::offsetOfFlags()),
Imm32(OBJECT_FLAG_PRE_TENURE), label);
}
void
MacroAssembler::branchIfNonNativeObj(Register obj, Register scratch, Label* label)
{
loadObjClassUnsafe(obj, scratch);
branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()),
Imm32(Class::NON_NATIVE), label);
}
void
MacroAssembler::branchIfInlineTypedObject(Register obj, Register scratch, Label* label)
{
loadObjClassUnsafe(obj, scratch);
branchPtr(Assembler::Equal, scratch, ImmPtr(&InlineOpaqueTypedObject::class_), label);
branchPtr(Assembler::Equal, scratch, ImmPtr(&InlineTransparentTypedObject::class_), label);
}
void
MacroAssembler::branchIfNotSimdObject(Register obj, Register scratch, SimdType simdType,
Label* label)
{
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
// Guard that the object has the same representation as the one produced for
// SIMD value-type.
Address clasp(scratch, ObjectGroup::offsetOfClasp());
static_assert(!SimdTypeDescr::Opaque, "SIMD objects are transparent");
branchPtr(Assembler::NotEqual, clasp, ImmPtr(&InlineTransparentTypedObject::class_),
label);
// obj->type()->typeDescr()
// The previous class pointer comparison implies that the addendumKind is
// Addendum_TypeDescr.
loadPtr(Address(scratch, ObjectGroup::offsetOfAddendum()), scratch);
// Check for the /Kind/ reserved slot of the TypeDescr. This is an Int32
// Value which is equivalent to the object class check.
static_assert(JS_DESCR_SLOT_KIND < NativeObject::MAX_FIXED_SLOTS, "Load from fixed slots");
Address typeDescrKind(scratch, NativeObject::getFixedSlotOffset(JS_DESCR_SLOT_KIND));
assertTestInt32(Assembler::Equal, typeDescrKind,
"MOZ_ASSERT(obj->type()->typeDescr()->getReservedSlot(JS_DESCR_SLOT_KIND).isInt32())");
branch32(Assembler::NotEqual, ToPayload(typeDescrKind), Imm32(js::type::Simd), label);
// Check if the SimdTypeDescr /Type/ matches the specialization of this
// MSimdUnbox instruction.
static_assert(JS_DESCR_SLOT_TYPE < NativeObject::MAX_FIXED_SLOTS, "Load from fixed slots");
Address typeDescrType(scratch, NativeObject::getFixedSlotOffset(JS_DESCR_SLOT_TYPE));
assertTestInt32(Assembler::Equal, typeDescrType,
"MOZ_ASSERT(obj->type()->typeDescr()->getReservedSlot(JS_DESCR_SLOT_TYPE).isInt32())");
branch32(Assembler::NotEqual, ToPayload(typeDescrType), Imm32(int32_t(simdType)), label);
}
void
MacroAssembler::copyObjGroupNoPreBarrier(Register sourceObj, Register destObj, Register scratch)
{
loadPtr(Address(sourceObj, JSObject::offsetOfGroup()), scratch);
storePtr(scratch, Address(destObj, JSObject::offsetOfGroup()));
}
void
MacroAssembler::loadTypedObjectDescr(Register obj, Register dest)
{
loadPtr(Address(obj, JSObject::offsetOfGroup()), dest);
loadPtr(Address(dest, ObjectGroup::offsetOfAddendum()), dest);
}
void
MacroAssembler::loadTypedObjectLength(Register obj, Register dest)
{
loadTypedObjectDescr(obj, dest);
unboxInt32(Address(dest, ArrayTypeDescr::offsetOfLength()), dest);
}
void
MacroAssembler::maybeBranchTestType(MIRType type, MDefinition* maybeDef, Register tag, Label* label)
{
@ -3570,6 +3692,21 @@ MacroAssembler::debugAssertIsObject(const ValueOperand& val)
#endif
}
void
MacroAssembler::debugAssertObjHasFixedSlots(Register obj, Register scratch)
{
#ifdef DEBUG
Label hasFixedSlots;
loadPtr(Address(obj, ShapedObject::offsetOfShape()), scratch);
branchTest32(Assembler::NonZero,
Address(scratch, Shape::offsetOfSlotInfo()),
Imm32(Shape::fixedSlotsMask()),
&hasFixedSlots);
assumeUnreachable("Expected a fixed slot");
bind(&hasFixedSlots);
#endif
}
void
MacroAssembler::spectreMaskIndex(Register index, Register length, Register output)
{

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

@ -1177,13 +1177,32 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchIfObjectEmulatesUndefined(Register objReg, Register scratch, Label* slowCheck,
Label* label);
inline void branchTestObjClass(Condition cond, Register obj, Register scratch, const js::Class* clasp,
Label* label);
inline void branchTestObjClass(Condition cond, Register obj, Register scratch,
const js::Class* clasp, Label* label);
inline void branchTestObjClass(Condition cond, Register obj, Register scratch,
const Address& clasp, Label* label);
inline void branchTestObjShape(Condition cond, Register obj, const Shape* shape, Label* label);
inline void branchTestObjShape(Condition cond, Register obj, Register shape, Label* label);
inline void branchTestObjGroup(Condition cond, Register obj, ObjectGroup* group, Label* label);
inline void branchTestObjGroup(Condition cond, Register obj, const ObjectGroup* group,
Label* label);
inline void branchTestObjGroup(Condition cond, Register obj, Register group, Label* label);
void branchTestObjGroup(Condition cond, Register obj, const Address& group, Register scratch,
Label* label);
void branchTestObjCompartment(Condition cond, Register obj, const Address& compartment,
Register scratch, Label* label);
void branchTestObjCompartment(Condition cond, Register obj, const JSCompartment* compartment,
Register scratch, Label* label);
void branchIfObjGroupHasNoAddendum(Register obj, Register scratch, Label* label);
void branchIfPretenuredGroup(const ObjectGroup* group, Register scratch, Label* label);
void branchIfNonNativeObj(Register obj, Register scratch, Label* label);
void branchIfInlineTypedObject(Register obj, Register scratch, Label* label);
void branchIfNotSimdObject(Register obj, Register scratch, SimdType simdType, Label* label);
inline void branchTestClassIsProxy(bool proxy, Register clasp, Label* label);
inline void branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label);
@ -1191,6 +1210,11 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchTestProxyHandlerFamily(Condition cond, Register proxy, Register scratch,
const void* handlerp, Label* label);
void copyObjGroupNoPreBarrier(Register sourceObj, Register destObj, Register scratch);
void loadTypedObjectDescr(Register obj, Register dest);
void loadTypedObjectLength(Register obj, Register dest);
// Emit type case branch on tag matching if the type tag in the definition
// might actually be that type.
void maybeBranchTestType(MIRType type, MDefinition* maybeDef, Register tag, Label* label);
@ -1951,21 +1975,25 @@ class MacroAssembler : public MacroAssemblerSpecific
Label* label);
#endif
void loadObjShape(Register objReg, Register dest) {
loadPtr(Address(objReg, ShapedObject::offsetOfShape()), dest);
// Unsafe here means the caller is responsible for Spectre mitigations if
// needed. Prefer branchTestObjGroup or one of the other masm helpers!
void loadObjGroupUnsafe(Register obj, Register dest) {
loadPtr(Address(obj, JSObject::offsetOfGroup()), dest);
}
void loadObjGroup(Register objReg, Register dest) {
loadPtr(Address(objReg, JSObject::offsetOfGroup()), dest);
}
void loadBaseShape(Register objReg, Register dest) {
loadObjShape(objReg, dest);
loadPtr(Address(dest, Shape::offsetOfBase()), dest);
}
void loadObjClass(Register objReg, Register dest) {
loadObjGroup(objReg, dest);
void loadObjClassUnsafe(Register obj, Register dest) {
loadPtr(Address(obj, JSObject::offsetOfGroup()), dest);
loadPtr(Address(dest, ObjectGroup::offsetOfClasp()), dest);
}
template <typename EmitPreBarrier>
inline void storeObjGroup(Register group, Register obj, EmitPreBarrier emitPreBarrier);
template <typename EmitPreBarrier>
inline void storeObjGroup(ObjectGroup* group, Register obj, EmitPreBarrier emitPreBarrier);
template <typename EmitPreBarrier>
inline void storeObjShape(Register shape, Register obj, EmitPreBarrier emitPreBarrier);
template <typename EmitPreBarrier>
inline void storeObjShape(Shape* shape, Register obj, EmitPreBarrier emitPreBarrier);
void loadObjPrivate(Register obj, uint32_t nfixed, Register dest) {
loadPtr(Address(obj, NativeObject::getPrivateDataOffset(nfixed)), dest);
}
@ -2192,6 +2220,7 @@ class MacroAssembler : public MacroAssemblerSpecific
const ConstantOrRegister& value, Label* failure);
void debugAssertIsObject(const ValueOperand& val);
void debugAssertObjHasFixedSlots(Register obj, Register scratch);
using MacroAssemblerSpecific::extractTag;
Register extractTag(const TypedOrValueRegister& reg, Register scratch) {

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

@ -2540,10 +2540,9 @@ ICTypeMonitor_ObjectGroup::Compiler::generateStubCode(MacroAssembler& masm)
// Guard on the object's ObjectGroup.
Register obj = masm.extractObject(R0, ExtractTemp0);
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), R1.scratchReg());
Address expectedGroup(ICStubReg, ICTypeMonitor_ObjectGroup::offsetOfGroup());
masm.branchPtr(Assembler::NotEqual, expectedGroup, R1.scratchReg(), &failure);
masm.branchTestObjGroup(Assembler::NotEqual, obj, expectedGroup, R1.scratchReg(),
&failure);
MaybeWorkAroundAmdBug(masm);
EmitReturnFromIC(masm);
@ -2765,9 +2764,7 @@ GenerateNewObjectWithTemplateCode(JSContext* cx, JSObject* templateObject)
Label failure;
Register objReg = R0.scratchReg();
Register tempReg = R1.scratchReg();
masm.movePtr(ImmGCPtr(templateObject->group()), tempReg);
masm.branchTest32(Assembler::NonZero, Address(tempReg, ObjectGroup::offsetOfFlags()),
Imm32(OBJECT_FLAG_PRE_TENURE), &failure);
masm.branchIfPretenuredGroup(templateObject->group(), tempReg, &failure);
masm.branchPtr(Assembler::NotEqual, AbsoluteAddress(cx->compartment()->addressOfMetadataBuilder()),
ImmWord(0), &failure);
masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, &failure);

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

@ -721,7 +721,10 @@ PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index)
if (InBounds == IndexInBounds::Yes) {
MOZ_ASSERT(uint32_t(index) < obj->as<NativeObject>().getDenseInitializedLength());
} else {
if (MOZ_UNLIKELY(!obj->is<NativeObject>() || index < 0)) {
if (MOZ_UNLIKELY(!obj->is<NativeObject>() ||
index < 0 ||
uint32_t(index) >= NativeObject::MAX_DENSE_ELEMENTS_COUNT))
{
rt->gc.storeBuffer().putWholeCell(obj);
return;
}

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

@ -1746,29 +1746,20 @@ void
CodeGeneratorARM::visitGuardShape(LGuardShape* guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
ScratchRegisterScope scratch(masm);
masm.ma_ldr(DTRAddr(obj, DtrOffImm(ShapedObject::offsetOfShape())), tmp);
masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->shape()), scratch);
bailoutIf(Assembler::NotEqual, guard->snapshot());
Label bail;
masm.branchTestObjShape(Assembler::NotEqual, obj, guard->mir()->shape(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void
CodeGeneratorARM::visitGuardObjectGroup(LGuardObjectGroup* guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
MOZ_ASSERT(obj != tmp);
ScratchRegisterScope scratch(masm);
masm.ma_ldr(DTRAddr(obj, DtrOffImm(JSObject::offsetOfGroup())), tmp);
masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->group()), scratch);
Assembler::Condition cond =
guard->mir()->bailOnEquality() ? Assembler::Equal : Assembler::NotEqual;
bailoutIf(cond, guard->snapshot());
Label bail;
masm.branchTestObjGroup(cond, obj, guard->mir()->group(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void
@ -1776,12 +1767,9 @@ CodeGeneratorARM::visitGuardClass(LGuardClass* guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
ScratchRegisterScope scratch(masm);
masm.loadObjClass(obj, tmp);
masm.ma_cmp(tmp, Imm32((uint32_t)guard->mir()->getClass()), scratch);
bailoutIf(Assembler::NotEqual, guard->snapshot());
Label bail;
masm.branchTestObjClass(Assembler::NotEqual, obj, tmp, guard->mir()->getClass(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void

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

@ -383,14 +383,13 @@ class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
}
};
class LGuardShape : public LInstructionHelper<0, 1, 1>
class LGuardShape : public LInstructionHelper<0, 1, 0>
{
public:
LIR_HEADER(GuardShape);
LGuardShape(const LAllocation& in, const LDefinition& temp) {
explicit LGuardShape(const LAllocation& in) {
setOperand(0, in);
setTemp(0, temp);
}
const MGuardShape* mir() const {
return mir_->toGuardShape();
@ -400,14 +399,13 @@ class LGuardShape : public LInstructionHelper<0, 1, 1>
}
};
class LGuardObjectGroup : public LInstructionHelper<0, 1, 1>
class LGuardObjectGroup : public LInstructionHelper<0, 1, 0>
{
public:
LIR_HEADER(GuardObjectGroup);
LGuardObjectGroup(const LAllocation& in, const LDefinition& temp) {
explicit LGuardObjectGroup(const LAllocation& in) {
setOperand(0, in);
setTemp(0, temp);
}
const MGuardObjectGroup* mir() const {
return mir_->toGuardObjectGroup();

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

@ -485,8 +485,7 @@ LIRGeneratorARM::visitGuardShape(MGuardShape* ins)
{
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
LDefinition tempObj = temp(LDefinition::OBJECT);
LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->object()), tempObj);
LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->object()));
assignSnapshot(guard, ins->bailoutKind());
add(guard, ins);
redefine(ins, ins->object());
@ -497,8 +496,7 @@ LIRGeneratorARM::visitGuardObjectGroup(MGuardObjectGroup* ins)
{
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
LDefinition tempObj = temp(LDefinition::OBJECT);
LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->object()), tempObj);
LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->object()));
assignSnapshot(guard, ins->bailoutKind());
add(guard, ins);
redefine(ins, ins->object());

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

@ -1772,25 +1772,20 @@ void
CodeGeneratorMIPSShared::visitGuardShape(LGuardShape* guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
masm.loadPtr(Address(obj, ShapedObject::offsetOfShape()), tmp);
bailoutCmpPtr(Assembler::NotEqual, tmp, ImmGCPtr(guard->mir()->shape()),
guard->snapshot());
Label bail;
masm.branchTestObjShape(Assembler::NotEqual, obj, guard->mir()->shape(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void
CodeGeneratorMIPSShared::visitGuardObjectGroup(LGuardObjectGroup* guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
MOZ_ASSERT(obj != tmp);
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), tmp);
Assembler::Condition cond = guard->mir()->bailOnEquality()
? Assembler::Equal
: Assembler::NotEqual;
bailoutCmpPtr(cond, tmp, ImmGCPtr(guard->mir()->group()), guard->snapshot());
Assembler::Condition cond =
guard->mir()->bailOnEquality() ? Assembler::Equal : Assembler::NotEqual;
Label bail;
masm.branchTestObjGroup(cond, obj, guard->mir()->group(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void
@ -1798,10 +1793,9 @@ CodeGeneratorMIPSShared::visitGuardClass(LGuardClass* guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
masm.loadObjClass(obj, tmp);
bailoutCmpPtr(Assembler::NotEqual, tmp, ImmPtr(guard->mir()->getClass()),
guard->snapshot());
Label bail;
masm.branchTestObjClass(Assembler::NotEqual, obj, tmp, guard->mir()->getClass(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void

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

@ -210,14 +210,13 @@ class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
}
};
class LGuardShape : public LInstructionHelper<0, 1, 1>
class LGuardShape : public LInstructionHelper<0, 1, 0>
{
public:
LIR_HEADER(GuardShape);
LGuardShape(const LAllocation& in, const LDefinition& temp) {
explicit LGuardShape(const LAllocation& in) {
setOperand(0, in);
setTemp(0, temp);
}
const MGuardShape* mir() const {
return mir_->toGuardShape();
@ -227,14 +226,13 @@ class LGuardShape : public LInstructionHelper<0, 1, 1>
}
};
class LGuardObjectGroup : public LInstructionHelper<0, 1, 1>
class LGuardObjectGroup : public LInstructionHelper<0, 1, 0>
{
public:
LIR_HEADER(GuardObjectGroup);
LGuardObjectGroup(const LAllocation& in, const LDefinition& temp) {
explicit LGuardObjectGroup(const LAllocation& in) {
setOperand(0, in);
setTemp(0, temp);
}
const MGuardObjectGroup* mir() const {
return mir_->toGuardObjectGroup();

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

@ -292,8 +292,7 @@ LIRGeneratorMIPSShared::visitGuardShape(MGuardShape* ins)
{
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
LDefinition tempObj = temp(LDefinition::OBJECT);
LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->object()), tempObj);
LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->object()));
assignSnapshot(guard, ins->bailoutKind());
add(guard, ins);
redefine(ins, ins->object());
@ -304,8 +303,7 @@ LIRGeneratorMIPSShared::visitGuardObjectGroup(MGuardObjectGroup* ins)
{
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
LDefinition tempObj = temp(LDefinition::OBJECT);
LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->object()), tempObj);
LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->object()));
assignSnapshot(guard, ins->bailoutKind());
add(guard, ins);
redefine(ins, ins->object());

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

@ -2376,21 +2376,20 @@ void
CodeGeneratorX86Shared::visitGuardShape(LGuardShape* guard)
{
Register obj = ToRegister(guard->input());
masm.cmpPtr(Operand(obj, ShapedObject::offsetOfShape()), ImmGCPtr(guard->mir()->shape()));
bailoutIf(Assembler::NotEqual, guard->snapshot());
Label bail;
masm.branchTestObjShape(Assembler::NotEqual, obj, guard->mir()->shape(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void
CodeGeneratorX86Shared::visitGuardObjectGroup(LGuardObjectGroup* guard)
{
Register obj = ToRegister(guard->input());
masm.cmpPtr(Operand(obj, JSObject::offsetOfGroup()), ImmGCPtr(guard->mir()->group()));
Assembler::Condition cond =
guard->mir()->bailOnEquality() ? Assembler::Equal : Assembler::NotEqual;
bailoutIf(cond, guard->snapshot());
Label bail;
masm.branchTestObjGroup(cond, obj, guard->mir()->group(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void
@ -2398,10 +2397,9 @@ CodeGeneratorX86Shared::visitGuardClass(LGuardClass* guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), tmp);
masm.cmpPtr(Operand(tmp, ObjectGroup::offsetOfClasp()), ImmPtr(guard->mir()->getClass()));
bailoutIf(Assembler::NotEqual, guard->snapshot());
Label bail;
masm.branchTestObjClass(Assembler::NotEqual, obj, tmp, guard->mir()->getClass(), &bail);
bailoutFrom(&bail, guard->snapshot());
}
void

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

@ -3993,6 +3993,7 @@ JS::TransitiveCompileOptions::copyPODTransitiveOptions(const TransitiveCompileOp
introductionOffset = rhs.introductionOffset;
hasIntroductionInfo = rhs.hasIntroductionInfo;
isProbablySystemOrAddonCode = rhs.isProbablySystemOrAddonCode;
hideScriptFromDebugger = rhs.hideScriptFromDebugger;
};
void
@ -4678,6 +4679,17 @@ JS::InitScriptSourceElement(JSContext* cx, HandleScript script,
return ScriptSourceObject::initElementProperties(cx, sso, element, elementAttrName);
}
JS_PUBLIC_API(void)
JS::ExposeScriptToDebugger(JSContext* cx, HandleScript script)
{
MOZ_ASSERT(cx);
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
MOZ_ASSERT(script->hideScriptFromDebugger());
script->clearHideScriptFromDebugger();
Debugger::onNewScript(cx, script);
}
JS_PUBLIC_API(JSString*)
JS_DecompileScript(JSContext* cx, HandleScript script)
{

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

@ -102,133 +102,6 @@ class MOZ_RAII AutoValueArray : public AutoGCRooter
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
template<class T>
class MOZ_RAII AutoVectorRooterBase : protected AutoGCRooter
{
typedef js::Vector<T, 8> VectorImpl;
VectorImpl vector;
public:
explicit AutoVectorRooterBase(JSContext* cx, ptrdiff_t tag
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, tag), vector(cx)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
typedef T ElementType;
typedef typename VectorImpl::Range Range;
size_t length() const { return vector.length(); }
bool empty() const { return vector.empty(); }
MOZ_MUST_USE bool append(const T& v) { return vector.append(v); }
MOZ_MUST_USE bool appendN(const T& v, size_t len) { return vector.appendN(v, len); }
MOZ_MUST_USE bool append(const T* ptr, size_t len) { return vector.append(ptr, len); }
MOZ_MUST_USE bool appendAll(const AutoVectorRooterBase<T>& other) {
return vector.appendAll(other.vector);
}
MOZ_MUST_USE bool insert(T* p, const T& val) { return vector.insert(p, val); }
/* For use when space has already been reserved. */
void infallibleAppend(const T& v) { vector.infallibleAppend(v); }
void popBack() { vector.popBack(); }
T popCopy() { return vector.popCopy(); }
MOZ_MUST_USE bool growBy(size_t inc) {
size_t oldLength = vector.length();
if (!vector.growByUninitialized(inc))
return false;
makeRangeGCSafe(oldLength);
return true;
}
MOZ_MUST_USE bool resize(size_t newLength) {
size_t oldLength = vector.length();
if (newLength <= oldLength) {
vector.shrinkBy(oldLength - newLength);
return true;
}
if (!vector.growByUninitialized(newLength - oldLength))
return false;
makeRangeGCSafe(oldLength);
return true;
}
void clear() { vector.clear(); }
MOZ_MUST_USE bool reserve(size_t newLength) {
return vector.reserve(newLength);
}
JS::MutableHandle<T> operator[](size_t i) {
return JS::MutableHandle<T>::fromMarkedLocation(&vector[i]);
}
JS::Handle<T> operator[](size_t i) const {
return JS::Handle<T>::fromMarkedLocation(&vector[i]);
}
const T* begin() const { return vector.begin(); }
T* begin() { return vector.begin(); }
const T* end() const { return vector.end(); }
T* end() { return vector.end(); }
Range all() { return vector.all(); }
const T& back() const { return vector.back(); }
friend void AutoGCRooter::trace(JSTracer* trc);
private:
void makeRangeGCSafe(size_t oldLength) {
T* t = vector.begin() + oldLength;
for (size_t i = oldLength; i < vector.length(); ++i, ++t)
memset(t, 0, sizeof(T));
}
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
template <typename T>
class MOZ_RAII AutoVectorRooter : public AutoVectorRooterBase<T>
{
public:
explicit AutoVectorRooter(JSContext* cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoVectorRooterBase<T>(cx, this->GetTag(T()))
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoValueVector : public Rooted<GCVector<Value, 8>> {
using Vec = GCVector<Value, 8>;
using Base = Rooted<Vec>;
public:
explicit AutoValueVector(JSContext* cx) : Base(cx, Vec(cx)) {}
};
class AutoIdVector : public Rooted<GCVector<jsid, 8>> {
using Vec = GCVector<jsid, 8>;
using Base = Rooted<Vec>;
public:
explicit AutoIdVector(JSContext* cx) : Base(cx, Vec(cx)) {}
bool appendAll(const AutoIdVector& other) { return this->Base::appendAll(other.get()); }
};
class AutoObjectVector : public Rooted<GCVector<JSObject*, 8>> {
using Vec = GCVector<JSObject*, 8>;
using Base = Rooted<Vec>;
public:
explicit AutoObjectVector(JSContext* cx) : Base(cx, Vec(cx)) {}
};
using ValueVector = JS::GCVector<JS::Value>;
using IdVector = JS::GCVector<jsid>;
using ScriptVector = JS::GCVector<JSScript*>;
@ -3692,6 +3565,7 @@ class JS_FRIEND_API(TransitiveCompileOptions)
sourceIsLazy(false),
allowHTMLComments(true),
isProbablySystemOrAddonCode(false),
hideScriptFromDebugger(false),
introductionType(nullptr),
introductionLineno(0),
introductionOffset(0),
@ -3727,6 +3601,7 @@ class JS_FRIEND_API(TransitiveCompileOptions)
bool sourceIsLazy;
bool allowHTMLComments;
bool isProbablySystemOrAddonCode;
bool hideScriptFromDebugger;
// |introductionType| is a statically allocated C string:
// one of "eval", "Function", or "GeneratorFunction".
@ -4134,6 +4009,13 @@ extern JS_PUBLIC_API(bool)
InitScriptSourceElement(JSContext* cx, HandleScript script,
HandleObject element, HandleString elementAttrName = nullptr);
/*
* For a script compiled with the hideScriptFromDebugger option, expose the
* script to the debugger by calling the debugger's onNewScript hook.
*/
extern JS_PUBLIC_API(void)
ExposeScriptToDebugger(JSContext* cx, HandleScript script);
} /* namespace JS */
extern JS_PUBLIC_API(JSString*)

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

@ -29,7 +29,11 @@
namespace JS {
class AutoIdVector;
template <typename T> class AutoVector;
using AutoIdVector = AutoVector<jsid>;
using AutoValueVector = AutoVector<Value>;
using AutoObjectVector = AutoVector<JSObject*>;
class CallArgs;
class JS_FRIEND_API(CompileOptions);

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

@ -9085,7 +9085,8 @@ main(int argc, char** argv, char** envp)
|| !op.addBoolOption('\0', "no-ggc", "Disable Generational GC")
|| !op.addBoolOption('\0', "no-cgc", "Disable Compacting GC")
|| !op.addBoolOption('\0', "no-incremental-gc", "Disable Incremental GC")
|| !op.addBoolOption('\0', "nursery-strings", "Allocate strings in the nursery")
|| !op.addStringOption('\0', "nursery-strings", "on/off",
"Allocate strings in the nursery")
|| !op.addIntOption('\0', "available-memory", "SIZE",
"Select GC settings based on available memory (MB)", 0)
|| !op.addStringOption('\0', "arm-hwcap", "[features]",
@ -9233,8 +9234,14 @@ main(int argc, char** argv, char** envp)
js::UseInternalJobQueues(cx);
if (op.getBoolOption("nursery-strings"))
cx->runtime()->gc.nursery().enableStrings();
if (const char* opt = op.getStringOption("nursery-strings")) {
if (strcmp(opt, "on") == 0)
cx->runtime()->gc.nursery().enableStrings();
else if (strcmp(opt, "off") == 0)
cx->runtime()->gc.nursery().disableStrings();
else
MOZ_CRASH("invalid option value for --nursery-strings, must be on/off");
}
if (!JS::InitSelfHostedCode(cx))
return 1;

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

@ -1800,6 +1800,11 @@ Debugger::onNewScript(JSContext* cx, HandleScript script)
MOZ_ASSERT_IF(!script->compartment()->creationOptions().invisibleToDebugger() &&
!script->selfHosted(),
script->compartment()->firedOnNewGlobalObject);
// The script may not be ready to be interrogated by the debugger.
if (script->hideScriptFromDebugger())
return;
if (script->compartment()->isDebuggee())
slowPathOnNewScript(cx, script);
}

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

@ -218,6 +218,7 @@ GetSelectorRuntime(const CompilationSelector& selector)
{
JSRuntime* match(JSScript* script) { return script->runtimeFromActiveCooperatingThread(); }
JSRuntime* match(JSCompartment* comp) { return comp->runtimeFromActiveCooperatingThread(); }
JSRuntime* match(Zone* zone) { return zone->runtimeFromActiveCooperatingThread(); }
JSRuntime* match(ZonesInState zbs) { return zbs.runtime; }
JSRuntime* match(JSRuntime* runtime) { return runtime; }
JSRuntime* match(AllCompilations all) { return nullptr; }
@ -234,6 +235,7 @@ JitDataStructuresExist(const CompilationSelector& selector)
{
bool match(JSScript* script) { return !!script->compartment()->jitCompartment(); }
bool match(JSCompartment* comp) { return !!comp->jitCompartment(); }
bool match(Zone* zone) { return !!zone->jitZone(); }
bool match(ZonesInState zbs) { return zbs.runtime->hasJitRuntime(); }
bool match(JSRuntime* runtime) { return runtime->hasJitRuntime(); }
bool match(AllCompilations all) { return true; }
@ -252,6 +254,7 @@ IonBuilderMatches(const CompilationSelector& selector, jit::IonBuilder* builder)
bool match(JSScript* script) { return script == builder_->script(); }
bool match(JSCompartment* comp) { return comp == builder_->script()->compartment(); }
bool match(Zone* zone) { return zone == builder_->script()->zone(); }
bool match(JSRuntime* runtime) { return runtime == builder_->script()->runtimeFromAnyThread(); }
bool match(AllCompilations all) { return true; }
bool match(ZonesInState zbs) {

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

@ -516,6 +516,7 @@ struct CompilationsUsingNursery { JSRuntime* runtime; };
using CompilationSelector = mozilla::Variant<JSScript*,
JSCompartment*,
Zone*,
ZonesInState,
JSRuntime*,
CompilationsUsingNursery,
@ -539,6 +540,12 @@ CancelOffThreadIonCompile(JSCompartment* comp)
CancelOffThreadIonCompile(CompilationSelector(comp), true);
}
inline void
CancelOffThreadIonCompile(Zone* zone)
{
CancelOffThreadIonCompile(CompilationSelector(zone), true);
}
inline void
CancelOffThreadIonCompile(JSRuntime* runtime, JS::Zone::GCState state)
{

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

@ -1384,16 +1384,20 @@ struct WrapperValue
Value value;
};
class MOZ_RAII AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue>
class MOZ_RAII AutoWrapperVector : public JS::GCVector<WrapperValue, 8>,
private JS::AutoGCRooter
{
public:
explicit AutoWrapperVector(JSContext* cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoVectorRooterBase<WrapperValue>(cx, WRAPVECTOR)
: JS::GCVector<WrapperValue, 8>(cx),
JS::AutoGCRooter(cx, WRAPVECTOR)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
friend void AutoGCRooter::trace(JSTracer* trc);
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};

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

@ -541,7 +541,15 @@ class JSObject : public js::gc::Cell
void dump() const;
#endif
/* JIT Accessors */
// Maximum size in bytes of a JSObject.
static const size_t MAX_BYTE_SIZE = 4 * sizeof(void*) + 16 * sizeof(JS::Value);
protected:
// JIT Accessors.
//
// To help avoid writing Spectre-unsafe code, we only allow MacroAssembler
// to call the method below.
friend class js::jit::MacroAssembler;
static constexpr size_t offsetOfGroup() {
return offsetof(JSObject, group_);
@ -550,9 +558,6 @@ class JSObject : public js::gc::Cell
return offsetof(JSObject, shapeOrExpando_);
}
// Maximum size in bytes of a JSObject.
static const size_t MAX_BYTE_SIZE = 4 * sizeof(void*) + 16 * sizeof(JS::Value);
private:
JSObject() = delete;
JSObject(const JSObject& other) = delete;

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

@ -2732,6 +2732,8 @@ JSScript::Create(JSContext* cx, const ReadOnlyCompileOptions& options,
script->toStringStart_ = toStringStart;
script->toStringEnd_ = toStringEnd;
script->hideScriptFromDebugger_ = options.hideScriptFromDebugger;
#ifdef MOZ_VTUNE
script->vtuneMethodId_ = vtune::GenerateUniqueMethodID();
#endif
@ -3625,6 +3627,7 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
dst->isAsync_ = src->isAsync_;
dst->hasRest_ = src->hasRest_;
dst->isExprBody_ = src->isExprBody_;
dst->hideScriptFromDebugger_ = src->hideScriptFromDebugger_;
if (nconsts != 0) {
GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->consts()->vector);

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

@ -1142,6 +1142,9 @@ class JSScript : public js::gc::TenuredCell
bool hasRest_:1;
bool isExprBody_:1;
// True if the debugger's onNewScript hook has not yet been called.
bool hideScriptFromDebugger_:1;
// Add padding so JSScript is gc::Cell aligned. Make padding protected
// instead of private to suppress -Wunused-private-field compiler warnings.
protected:
@ -1463,6 +1466,13 @@ class JSScript : public js::gc::TenuredCell
isExprBody_ = true;
}
bool hideScriptFromDebugger() const {
return hideScriptFromDebugger_;
}
void clearHideScriptFromDebugger() {
hideScriptFromDebugger_ = false;
}
void setNeedsHomeObject() {
needsHomeObject_ = true;
}

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

@ -459,6 +459,10 @@ class ObjectGroup : public gc::TenuredCell
static const JS::TraceKind TraceKind = JS::TraceKind::ObjectGroup;
private:
// See JSObject::offsetOfGroup() comment.
friend class js::jit::MacroAssembler;
static inline uint32_t offsetOfClasp() {
return offsetof(ObjectGroup, clasp_);
}
@ -479,6 +483,7 @@ class ObjectGroup : public gc::TenuredCell
return offsetof(ObjectGroup, flags_);
}
public:
const ObjectGroupFlags* addressOfFlags() const {
return &flags_;
}

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

@ -1800,12 +1800,12 @@ Shape::fixupDictionaryShapeAfterMovingGC()
if (listpPointsIntoShape) {
// listp points to the parent field of the next shape.
Shape* next = reinterpret_cast<Shape*>(uintptr_t(listp) - offsetof(Shape, parent));
Shape* next = Shape::fromParentFieldPointer(uintptr_t(listp));
if (gc::IsForwarded(next))
listp = &gc::Forwarded(next)->parent;
} else {
// listp points to the shape_ field of an object.
JSObject* last = reinterpret_cast<JSObject*>(uintptr_t(listp) - ShapedObject::offsetOfShape());
JSObject* last = ShapedObject::fromShapeFieldPointer(uintptr_t(listp));
if (gc::IsForwarded(last))
listp = gc::Forwarded(last)->as<NativeObject>().shapePtr();
}

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

@ -1169,15 +1169,20 @@ class Shape : public gc::TenuredCell
void fixupGetterSetterForBarrier(JSTracer* trc);
void updateBaseShapeAfterMovingGC();
/* For JIT usage */
static inline size_t offsetOfBase() { return offsetof(Shape, base_); }
#ifdef DEBUG
// For JIT usage.
static inline size_t offsetOfSlotInfo() { return offsetof(Shape, slotInfo); }
static inline uint32_t fixedSlotsMask() { return FIXED_SLOTS_MASK; }
#endif
private:
void fixupDictionaryShapeAfterMovingGC();
void fixupShapeTreeAfterMovingGC();
static Shape* fromParentFieldPointer(uintptr_t p) {
return reinterpret_cast<Shape*>(p - offsetof(Shape, parent));
}
static void staticAsserts() {
JS_STATIC_ASSERT(offsetof(Shape, base_) == offsetof(js::shadow::Shape, base));
JS_STATIC_ASSERT(offsetof(Shape, slotInfo) == offsetof(js::shadow::Shape, slotInfo));

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

@ -50,6 +50,14 @@ class ShapedObject : public JSObject
TraceEdge(trc, shapePtr(), "shape");
}
static JSObject* fromShapeFieldPointer(uintptr_t p) {
return reinterpret_cast<JSObject*>(p - ShapedObject::offsetOfShape());
}
private:
// See JSObject::offsetOfGroup() comment.
friend class js::jit::MacroAssembler;
static constexpr size_t offsetOfShape() {
static_assert(offsetOfShapeOrExpando() == offsetof(shadow::Object, shape),
"shadow shape must match actual shape");

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

@ -525,7 +525,8 @@ JSRope::flattenInternal(JSContext* maybecx)
Nursery& nursery = zone()->group()->nursery();
if (!nursery.registerMallocedBuffer(wholeChars)) {
js_free(wholeChars);
ReportOutOfMemory(maybecx);
if (maybecx)
ReportOutOfMemory(maybecx);
return nullptr;
}
}

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

@ -87,15 +87,25 @@ wasm::HasCompilerSupport(JSContext* cx)
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
return false;
#else
return BaselineCanCompile() || IonCanCompile();
#endif
}
// Return whether wasm compilation is allowed by prefs. This check
// only makes sense if HasCompilerSupport() is true.
static bool
HasAvailableCompilerTier(JSContext* cx)
{
return (cx->options().wasmBaseline() && BaselineCanCompile()) ||
(cx->options().wasmIon() && IonCanCompile());
#endif
}
bool
wasm::HasSupport(JSContext* cx)
{
return cx->options().wasm() && HasCompilerSupport(cx);
return cx->options().wasm() &&
HasCompilerSupport(cx) &&
HasAvailableCompilerTier(cx);
}
bool

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

@ -12,10 +12,6 @@
#include "js/CallNonGenericMethod.h"
#include "js/Wrapper.h"
namespace JS {
class AutoIdVector;
} // namespace JS
namespace xpc {
template <typename Base, typename Policy>

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

@ -200,12 +200,6 @@ IsReversedDirectionFrame(nsIFrame* aFrame)
}
#include "nsILineIterator.h"
//non Hack prototypes
#if 0
static void RefreshContentFrames(nsPresContext* aPresContext, nsIContent * aStartContent, nsIContent * aEndContent);
#endif
#include "prenv.h"
NS_DECLARE_FRAME_PROPERTY_DELETABLE(BoxMetricsProperty, nsBoxLayoutMetrics)

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

@ -921,7 +921,7 @@ fails-if(Android) == css-writing-modes/sizing-orthog-htb-in-vlr-003.xht css-writ
== css-writing-modes/sizing-orthog-htb-in-vlr-004.xht css-writing-modes/sizing-orthog-htb-in-vlr-004-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vlr-006.xht css-writing-modes/sizing-orthog-htb-in-vlr-006-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vlr-007.xht css-writing-modes/sizing-orthog-htb-in-vlr-007-ref.xht
fails-if(OSX||winWidget) == css-writing-modes/sizing-orthog-htb-in-vlr-008.xht css-writing-modes/sizing-orthog-htb-in-vlr-008-ref.xht
fails-if(OSX||winWidget||Android) == css-writing-modes/sizing-orthog-htb-in-vlr-008.xht css-writing-modes/sizing-orthog-htb-in-vlr-008-ref.xht
fails-if(Android) == css-writing-modes/sizing-orthog-htb-in-vlr-009.xht css-writing-modes/sizing-orthog-htb-in-vlr-003-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vlr-010.xht css-writing-modes/sizing-orthog-htb-in-vlr-010-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vlr-011.xht css-writing-modes/sizing-orthog-htb-in-vlr-011-ref.xht
@ -931,7 +931,7 @@ fails-if(Android) == css-writing-modes/sizing-orthog-htb-in-vlr-015.xht css-writ
== css-writing-modes/sizing-orthog-htb-in-vlr-016.xht css-writing-modes/sizing-orthog-htb-in-vlr-016-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vlr-018.xht css-writing-modes/sizing-orthog-htb-in-vlr-018-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vlr-019.xht css-writing-modes/sizing-orthog-htb-in-vlr-019-ref.xht
fails-if(OSX||winWidget) == css-writing-modes/sizing-orthog-htb-in-vlr-020.xht css-writing-modes/sizing-orthog-htb-in-vlr-020-ref.xht
fails-if(OSX||winWidget||Android) == css-writing-modes/sizing-orthog-htb-in-vlr-020.xht css-writing-modes/sizing-orthog-htb-in-vlr-020-ref.xht
fails-if(Android) == css-writing-modes/sizing-orthog-htb-in-vlr-021.xht css-writing-modes/sizing-orthog-htb-in-vlr-015-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vlr-022.xht css-writing-modes/sizing-orthog-htb-in-vlr-022-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vlr-023.xht css-writing-modes/sizing-orthog-htb-in-vlr-023-ref.xht
@ -941,7 +941,7 @@ fails-if(Android) == css-writing-modes/sizing-orthog-htb-in-vrl-003.xht css-writ
fails == css-writing-modes/sizing-orthog-htb-in-vrl-004.xht css-writing-modes/sizing-orthog-htb-in-vlr-004-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vrl-006.xht css-writing-modes/sizing-orthog-htb-in-vrl-006-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vrl-007.xht css-writing-modes/sizing-orthog-htb-in-vrl-007-ref.xht
fails-if(OSX||winWidget) == css-writing-modes/sizing-orthog-htb-in-vrl-008.xht css-writing-modes/sizing-orthog-htb-in-vrl-008-ref.xht
fails-if(OSX||winWidget||Android) == css-writing-modes/sizing-orthog-htb-in-vrl-008.xht css-writing-modes/sizing-orthog-htb-in-vrl-008-ref.xht
fails-if(Android) == css-writing-modes/sizing-orthog-htb-in-vrl-009.xht css-writing-modes/sizing-orthog-htb-in-vrl-003-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vrl-010.xht css-writing-modes/sizing-orthog-htb-in-vrl-010-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vrl-011.xht css-writing-modes/sizing-orthog-htb-in-vrl-011-ref.xht
@ -951,7 +951,7 @@ fails-if(Android) == css-writing-modes/sizing-orthog-htb-in-vrl-015.xht css-writ
== css-writing-modes/sizing-orthog-htb-in-vrl-016.xht css-writing-modes/sizing-orthog-htb-in-vlr-016-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vrl-018.xht css-writing-modes/sizing-orthog-htb-in-vrl-018-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vrl-019.xht css-writing-modes/sizing-orthog-htb-in-vrl-019-ref.xht
fails-if(OSX||winWidget) == css-writing-modes/sizing-orthog-htb-in-vrl-020.xht css-writing-modes/sizing-orthog-htb-in-vrl-020-ref.xht
fails-if(OSX||winWidget||Android) == css-writing-modes/sizing-orthog-htb-in-vrl-020.xht css-writing-modes/sizing-orthog-htb-in-vrl-020-ref.xht
fails-if(Android) == css-writing-modes/sizing-orthog-htb-in-vrl-021.xht css-writing-modes/sizing-orthog-htb-in-vrl-015-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vrl-022.xht css-writing-modes/sizing-orthog-htb-in-vrl-022-ref.xht
== css-writing-modes/sizing-orthog-htb-in-vrl-023.xht css-writing-modes/sizing-orthog-htb-in-vrl-023-ref.xht

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

@ -139,6 +139,11 @@ public:
aIdealSegmentSize - sizeof(Segment) < sizeof(T));
}
SegmentedVector(SegmentedVector&& aOther)
: mSegments(mozilla::Move(aOther.mSegments))
{
}
~SegmentedVector() { Clear(); }
bool IsEmpty() const { return !mSegments.getFirst(); }

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

@ -3596,7 +3596,7 @@ public class BrowserApp extends GeckoApp
super.closeOptionsMenu();
}
@Override // GeckoView.ContentListener
@Override // GeckoView.ContentDelegate
public void onFullScreen(final GeckoSession session, final boolean fullscreen) {
super.onFullScreen(session, fullscreen);

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

@ -111,7 +111,7 @@ public abstract class GeckoApp extends GeckoActivity
BundleEventListener,
GeckoMenu.Callback,
GeckoMenu.MenuPresenter,
GeckoSession.ContentListener,
GeckoSession.ContentDelegate,
ScreenOrientationDelegate,
Tabs.OnTabsChangedListener,
ViewTreeObserver.OnGlobalLayoutListener {
@ -873,19 +873,19 @@ public abstract class GeckoApp extends GeckoActivity
return inSampleSize;
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onTitleChange(final GeckoSession session, final String title) {
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onFocusRequest(final GeckoSession session) {
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onCloseRequest(final GeckoSession session) {
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onFullScreen(final GeckoSession session, final boolean fullScreen) {
if (fullScreen) {
SnackbarBuilder.builder(this)
@ -1087,7 +1087,7 @@ public abstract class GeckoApp extends GeckoActivity
session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
"chrome://browser/content/browser.xul");
session.setContentListener(this);
session.setContentDelegate(this);
GeckoAccessibility.setDelegate(mLayerView);

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

@ -34,7 +34,7 @@ import org.mozilla.gecko.SiteIdentity;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.toolbar.SecurityModeUtil;
import org.mozilla.gecko.util.ColorUtil;
import org.mozilla.geckoview.GeckoSession.ProgressListener.SecurityInformation;
import org.mozilla.geckoview.GeckoSession.ProgressDelegate.SecurityInformation;
import org.mozilla.geckoview.GeckoView;
/**

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

@ -73,9 +73,9 @@ import java.util.List;
public class CustomTabsActivity extends AppCompatActivity
implements ActionModePresenter,
GeckoMenu.Callback,
GeckoSession.ContentListener,
GeckoSession.NavigationListener,
GeckoSession.ProgressListener {
GeckoSession.ContentDelegate,
GeckoSession.NavigationDelegate,
GeckoSession.ProgressDelegate {
private static final String LOGTAG = "CustomTabsActivity";
@ -134,9 +134,9 @@ public class CustomTabsActivity extends AppCompatActivity
mGeckoSession = new GeckoSession();
mGeckoView.setSession(mGeckoSession);
mGeckoSession.setNavigationListener(this);
mGeckoSession.setProgressListener(this);
mGeckoSession.setContentListener(this);
mGeckoSession.setNavigationDelegate(this);
mGeckoSession.setProgressDelegate(this);
mGeckoSession.setContentDelegate(this);
mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());
@ -591,7 +591,7 @@ public class CustomTabsActivity extends AppCompatActivity
return null;
}
/* GeckoSession.NavigationListener */
/* GeckoSession.NavigationDelegate */
@Override
public void onLocationChange(GeckoSession session, String url) {
mCurrentUrl = url;
@ -656,7 +656,7 @@ public class CustomTabsActivity extends AppCompatActivity
throw new IllegalStateException("Unexpected new session");
}
/* GeckoSession.ProgressListener */
/* GeckoSession.ProgressDelegate */
@Override
public void onPageStart(GeckoSession session, String url) {
mCurrentUrl = url;
@ -679,7 +679,7 @@ public class CustomTabsActivity extends AppCompatActivity
updateActionBar();
}
/* GeckoSession.ContentListener */
/* GeckoSession.ContentDelegate */
@Override
public void onTitleChange(GeckoSession session, String title) {
mCurrentTitle = title;

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

@ -33,7 +33,7 @@ import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.widget.AnchoredPopup;
import org.mozilla.gecko.widget.DoorHanger;
import org.mozilla.gecko.widget.DoorHanger.OnButtonClickListener;
import org.mozilla.geckoview.GeckoSession.ProgressListener.SecurityInformation;
import org.mozilla.geckoview.GeckoSession.ProgressDelegate.SecurityInformation;
import org.mozilla.geckoview.GeckoView;
import android.app.Activity;

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

@ -53,8 +53,8 @@ import org.mozilla.geckoview.GeckoView;
public class WebAppActivity extends AppCompatActivity
implements ActionModePresenter,
GeckoSession.ContentListener,
GeckoSession.NavigationListener {
GeckoSession.ContentDelegate,
GeckoSession.NavigationDelegate {
private static final String LOGTAG = "WebAppActivity";
public static final String MANIFEST_PATH = "MANIFEST_PATH";
@ -103,9 +103,9 @@ public class WebAppActivity extends AppCompatActivity
mGeckoSession = new GeckoSession();
mGeckoView.setSession(mGeckoSession);
mGeckoSession.setNavigationListener(this);
mGeckoSession.setContentListener(this);
mGeckoSession.setProgressListener(new GeckoSession.ProgressListener() {
mGeckoSession.setNavigationDelegate(this);
mGeckoSession.setContentDelegate(this);
mGeckoSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
@Override
public void onPageStart(GeckoSession session, String url) {
@ -332,36 +332,36 @@ public class WebAppActivity extends AppCompatActivity
mGeckoView.getSettings().setInt(GeckoSessionSettings.DISPLAY_MODE, mode);
}
@Override // GeckoSession.NavigationListener
@Override // GeckoSession.NavigationDelegate
public void onLocationChange(GeckoSession session, String url) {
}
@Override // GeckoSession.NavigationListener
@Override // GeckoSession.NavigationDelegate
public void onCanGoBack(GeckoSession session, boolean canGoBack) {
mCanGoBack = canGoBack;
}
@Override // GeckoSession.NavigationListener
@Override // GeckoSession.NavigationDelegate
public void onCanGoForward(GeckoSession session, boolean canGoForward) {
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onTitleChange(GeckoSession session, String title) {
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onFocusRequest(GeckoSession session) {
Intent intent = new Intent(getIntent());
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onCloseRequest(GeckoSession session) {
// Ignore
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onContextMenu(GeckoSession session, int screenX, int screenY,
String uri, String elementSrc) {
final String content = uri != null ? uri : elementSrc != null ? elementSrc : "";
@ -373,7 +373,7 @@ public class WebAppActivity extends AppCompatActivity
WebApps.openInFennec(validUri, WebAppActivity.this);
}
@Override // GeckoSession.ContentListener
@Override // GeckoSession.ContentDelegate
public void onFullScreen(GeckoSession session, boolean fullScreen) {
updateFullScreenContent(fullScreen);
}

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

@ -63,7 +63,7 @@ public class BaseGeckoViewTest {
protected void loadTestPage(final String url, final Runnable finished) {
final String path = Uri.parse(url).getPath();
mSession.setProgressListener(new GeckoSession.ProgressListener() {
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
@Override
public void onPageStart(GeckoSession session, String loadingUrl) {
assertTrue("Loaded url should end with " + path, loadingUrl.endsWith(path));
@ -72,7 +72,7 @@ public class BaseGeckoViewTest {
@Override
public void onPageStop(GeckoSession session, boolean success) {
assertTrue("Load should succeed", success);
mSession.setProgressListener(null);
mSession.setProgressDelegate(null);
finished.run();
}

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

@ -27,7 +27,7 @@ inline fun GeckoSession.loadTestPath(path: String) =
/**
* Test for the GeckoSessionTestRule class, to ensure it properly sets up a session for
* each test, and to ensure it can properly wait for and assert listener/delegate
* each test, and to ensure it can properly wait for and assert delegate
* callbacks.
*/
@RunWith(AndroidJUnit4::class)
@ -75,9 +75,7 @@ class GeckoSessionTestRuleTest {
@Test fun includesAllCallbacks() {
for (ifce in GeckoSession::class.java.classes) {
if (!ifce.isInterface || (
!ifce.simpleName.endsWith("Listener") &&
!ifce.simpleName.endsWith("Delegate"))) {
if (!ifce.isInterface || !ifce.simpleName.endsWith("Delegate")) {
continue
}
assertThat("Callbacks.All should include interface " + ifce.simpleName,
@ -91,7 +89,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
override fun onPageStop(session: GeckoSession, success: Boolean) {
counter++
}
@ -102,7 +100,7 @@ class GeckoSessionTestRuleTest {
@Test(expected = AssertionError::class)
fun waitForPageStop_throwOnChangedCallback() {
sessionRule.session.progressListener = Callbacks.Default
sessionRule.session.progressDelegate = Callbacks.Default
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
}
@ -114,7 +112,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
override fun onPageStop(session: GeckoSession, success: Boolean) {
counter++
}
@ -125,11 +123,11 @@ class GeckoSessionTestRuleTest {
@Test fun waitUntilCalled_anyInterfaceMethod() {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitUntilCalled(GeckoSession.ProgressListener::class)
sessionRule.waitUntilCalled(GeckoSession.ProgressDelegate::class)
var counter = 0
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
override fun onPageStart(session: GeckoSession, url: String) {
counter++
}
@ -139,7 +137,7 @@ class GeckoSessionTestRuleTest {
}
override fun onSecurityChange(session: GeckoSession,
securityInfo: GeckoSession.ProgressListener.SecurityInformation) {
securityInfo: GeckoSession.ProgressDelegate.SecurityInformation) {
counter++
}
})
@ -149,12 +147,12 @@ class GeckoSessionTestRuleTest {
@Test fun waitUntilCalled_specificInterfaceMethod() {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitUntilCalled(GeckoSession.ProgressListener::class,
sessionRule.waitUntilCalled(GeckoSession.ProgressDelegate::class,
"onPageStart", "onPageStop")
var counter = 0
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
override fun onPageStart(session: GeckoSession, url: String) {
counter++
}
@ -178,7 +176,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.waitUntilCalled(object : Callbacks.ProgressListener {
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
override fun onPageStart(session: GeckoSession, url: String) {
counter++
}
@ -188,7 +186,7 @@ class GeckoSessionTestRuleTest {
}
override fun onSecurityChange(session: GeckoSession,
securityInfo: GeckoSession.ProgressListener.SecurityInformation) {
securityInfo: GeckoSession.ProgressDelegate.SecurityInformation) {
counter++
}
})
@ -201,7 +199,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.waitUntilCalled(object : Callbacks.ProgressListener {
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
@AssertCalled
override fun onPageStart(session: GeckoSession, url: String) {
counter++
@ -222,7 +220,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.waitUntilCalled(object : Callbacks.ProgressListener {
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 2)
override fun onPageStart(session: GeckoSession, url: String) {
counter++
@ -243,7 +241,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.waitUntilCalled(object : Callbacks.ProgressListener {
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 2, order = intArrayOf(1, 2))
override fun onPageStop(session: GeckoSession, success: Boolean) {
val info = sessionRule.currentCall
@ -265,7 +263,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
override fun onPageStop(session: GeckoSession, success: Boolean) {
counter++
}
@ -279,7 +277,7 @@ class GeckoSessionTestRuleTest {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(GeckoSession.ScrollListener { _, _, _ -> })
sessionRule.forCallbacksDuringWait(GeckoSession.ScrollDelegate { _, _, _ -> })
}
@Test fun forCallbacksDuringWait_specificMethod() {
@ -288,7 +286,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled
override fun onPageStart(session: GeckoSession, url: String) {
counter++
@ -310,7 +308,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled
override fun onPageStart(session: GeckoSession, url: String) {
counter++
@ -331,7 +329,7 @@ class GeckoSessionTestRuleTest {
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(
GeckoSession.ScrollListener @AssertCalled { _, _, _ -> })
GeckoSession.ScrollDelegate @AssertCalled { _, _, _ -> })
}
@Test fun forCallbacksDuringWait_specificCount() {
@ -341,7 +339,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 2)
override fun onPageStart(session: GeckoSession, url: String) {
counter++
@ -362,7 +360,7 @@ class GeckoSessionTestRuleTest {
sessionRule.session.reload()
sessionRule.waitForPageStops(2)
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1)
override fun onPageStart(session: GeckoSession, url: String) {
}
@ -377,7 +375,7 @@ class GeckoSessionTestRuleTest {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(order = intArrayOf(1))
override fun onPageStart(session: GeckoSession, url: String) {
}
@ -393,7 +391,7 @@ class GeckoSessionTestRuleTest {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(order = intArrayOf(2))
override fun onPageStart(session: GeckoSession, url: String) {
}
@ -409,7 +407,7 @@ class GeckoSessionTestRuleTest {
sessionRule.session.reload()
sessionRule.waitForPageStops(2)
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(order = intArrayOf(1, 3, 1))
override fun onPageStart(session: GeckoSession, url: String) {
}
@ -426,7 +424,7 @@ class GeckoSessionTestRuleTest {
sessionRule.session.reload()
sessionRule.waitForPageStops(2)
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(order = intArrayOf(1, 2, 1))
override fun onPageStart(session: GeckoSession, url: String) {
}
@ -442,7 +440,7 @@ class GeckoSessionTestRuleTest {
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(
GeckoSession.ScrollListener @AssertCalled(false) { _, _, _ -> })
GeckoSession.ScrollDelegate @AssertCalled(false) { _, _, _ -> })
}
@Test(expected = AssertionError::class)
@ -450,7 +448,7 @@ class GeckoSessionTestRuleTest {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(false)
override fun onPageStop(session: GeckoSession, success: Boolean) {
}
@ -472,7 +470,7 @@ class GeckoSessionTestRuleTest {
var counter = 0
// assert should only apply to callbacks within range (loadUri, first reload].
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1)
override fun onPageStart(session: GeckoSession, url: String) {
counter++
@ -491,7 +489,7 @@ class GeckoSessionTestRuleTest {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1)
override fun onPageStop(session: GeckoSession, success: Boolean) {
val info = sessionRule.currentCall
@ -512,7 +510,7 @@ class GeckoSessionTestRuleTest {
@Test fun delegateUntilTestEnd() {
var counter = 0
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener {
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1, order = intArrayOf(1))
override fun onPageStart(session: GeckoSession, url: String) {
counter++
@ -532,19 +530,19 @@ class GeckoSessionTestRuleTest {
@Test fun delegateUntilTestEnd_notCalled() {
sessionRule.delegateUntilTestEnd(
GeckoSession.ScrollListener @AssertCalled(false) { _, _, _ -> })
GeckoSession.ScrollDelegate @AssertCalled(false) { _, _, _ -> })
}
@Test(expected = AssertionError::class)
fun delegateUntilTestEnd_throwOnNotCalled() {
sessionRule.delegateUntilTestEnd(
GeckoSession.ScrollListener @AssertCalled(count = 1) { _, _, _ -> })
GeckoSession.ScrollDelegate @AssertCalled(count = 1) { _, _, _ -> })
sessionRule.performTestEndCheck()
}
@Test(expected = AssertionError::class)
fun delegateUntilTestEnd_throwOnCallingNoCall() {
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener {
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate {
@AssertCalled(false)
override fun onPageStop(session: GeckoSession, success: Boolean) {
}
@ -556,7 +554,7 @@ class GeckoSessionTestRuleTest {
@Test(expected = AssertionError::class)
fun delegateUntilTestEnd_throwOnWrongOrder() {
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener {
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1, order = intArrayOf(2))
override fun onPageStart(session: GeckoSession, url: String) {
}
@ -571,7 +569,7 @@ class GeckoSessionTestRuleTest {
}
@Test fun delegateUntilTestEnd_currentCall() {
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener {
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1)
override fun onPageStop(session: GeckoSession, success: Boolean) {
val info = sessionRule.currentCall
@ -590,7 +588,7 @@ class GeckoSessionTestRuleTest {
@Test fun delegateDuringNextWait() {
var counter = 0
sessionRule.delegateDuringNextWait(object : Callbacks.ProgressListener {
sessionRule.delegateDuringNextWait(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1, order = intArrayOf(1))
override fun onPageStart(session: GeckoSession, url: String) {
counter++
@ -616,7 +614,7 @@ class GeckoSessionTestRuleTest {
@Test(expected = AssertionError::class)
fun delegateDuringNextWait_throwOnNotCalled() {
sessionRule.delegateDuringNextWait(
GeckoSession.ScrollListener @AssertCalled(count = 1) { _, _, _ -> })
GeckoSession.ScrollDelegate @AssertCalled(count = 1) { _, _, _ -> })
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
}
@ -624,7 +622,7 @@ class GeckoSessionTestRuleTest {
@Test(expected = AssertionError::class)
fun delegateDuringNextWait_throwOnNotCalledAtTestEnd() {
sessionRule.delegateDuringNextWait(
GeckoSession.ScrollListener @AssertCalled(count = 1) { _, _, _ -> })
GeckoSession.ScrollDelegate @AssertCalled(count = 1) { _, _, _ -> })
sessionRule.performTestEndCheck()
}
@ -632,8 +630,8 @@ class GeckoSessionTestRuleTest {
var testCounter = 0
var waitCounter = 0
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener,
Callbacks.NavigationListener {
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate,
Callbacks.NavigationDelegate {
@AssertCalled(count = 1, order = intArrayOf(2))
override fun onPageStart(session: GeckoSession, url: String) {
testCounter++
@ -655,7 +653,7 @@ class GeckoSessionTestRuleTest {
}
})
sessionRule.delegateDuringNextWait(object : Callbacks.ProgressListener {
sessionRule.delegateDuringNextWait(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1, order = intArrayOf(1))
override fun onPageStart(session: GeckoSession, url: String) {
waitCounter++

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

@ -20,7 +20,7 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@MediumTest
class NavigationListenerTest {
class NavigationDelegateTest {
companion object {
const val HELLO_HTML_PATH = "/assets/www/hello.html";
const val HELLO2_HTML_PATH = "/assets/www/hello2.html";
@ -39,16 +39,16 @@ class NavigationListenerTest {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
@AssertCalled(count = 1, order = intArrayOf(1))
override fun onLoadUri(session: GeckoSession, uri: String,
where: GeckoSession.NavigationListener.TargetWindow): Boolean {
where: GeckoSession.NavigationDelegate.TargetWindow): Boolean {
assertThat("Session should not be null", session, notNullValue())
assertThat("URI should not be null", uri, notNullValue())
assertThat("URI should match", uri, endsWith(HELLO_HTML_PATH))
assertThat("Where should not be null", where, notNullValue())
assertThat("Where should match", where,
equalTo(GeckoSession.NavigationListener.TargetWindow.CURRENT))
equalTo(GeckoSession.NavigationDelegate.TargetWindow.CURRENT))
return false
}
@ -85,13 +85,13 @@ class NavigationListenerTest {
sessionRule.session.reload()
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
@AssertCalled(count = 1, order = intArrayOf(1))
override fun onLoadUri(session: GeckoSession, uri: String,
where: GeckoSession.NavigationListener.TargetWindow): Boolean {
where: GeckoSession.NavigationDelegate.TargetWindow): Boolean {
assertThat("URI should match", uri, endsWith(HELLO_HTML_PATH))
assertThat("Where should match", where,
equalTo(GeckoSession.NavigationListener.TargetWindow.CURRENT))
equalTo(GeckoSession.NavigationDelegate.TargetWindow.CURRENT))
return false
}
@ -124,7 +124,7 @@ class NavigationListenerTest {
sessionRule.session.loadTestPath(HELLO2_HTML_PATH)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
@AssertCalled(count = 1)
override fun onLocationChange(session: GeckoSession, url: String) {
assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH))
@ -134,13 +134,13 @@ class NavigationListenerTest {
sessionRule.session.goBack()
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
@AssertCalled(count = 1, order = intArrayOf(1))
override fun onLoadUri(session: GeckoSession, uri: String,
where: GeckoSession.NavigationListener.TargetWindow): Boolean {
where: GeckoSession.NavigationDelegate.TargetWindow): Boolean {
assertThat("URI should match", uri, endsWith(HELLO_HTML_PATH))
assertThat("Where should match", where,
equalTo(GeckoSession.NavigationListener.TargetWindow.CURRENT))
equalTo(GeckoSession.NavigationDelegate.TargetWindow.CURRENT))
return false
}
@ -168,13 +168,13 @@ class NavigationListenerTest {
sessionRule.session.goForward()
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
@AssertCalled(count = 1, order = intArrayOf(1))
override fun onLoadUri(session: GeckoSession, uri: String,
where: GeckoSession.NavigationListener.TargetWindow): Boolean {
where: GeckoSession.NavigationDelegate.TargetWindow): Boolean {
assertThat("URI should match", uri, endsWith(HELLO2_HTML_PATH))
assertThat("Where should match", where,
equalTo(GeckoSession.NavigationListener.TargetWindow.CURRENT))
equalTo(GeckoSession.NavigationDelegate.TargetWindow.CURRENT))
return false
}
@ -201,10 +201,10 @@ class NavigationListenerTest {
}
@Test fun onLoadUri_returnTrueCancelsLoad() {
sessionRule.delegateDuringNextWait(object : Callbacks.NavigationListener {
sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
@AssertCalled(count = 2)
override fun onLoadUri(session: GeckoSession, uri: String,
where: GeckoSession.NavigationListener.TargetWindow): Boolean {
where: GeckoSession.NavigationDelegate.TargetWindow): Boolean {
return uri.endsWith(HELLO_HTML_PATH)
}
})
@ -213,7 +213,7 @@ class NavigationListenerTest {
sessionRule.session.loadTestPath(HELLO2_HTML_PATH)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
@AssertCalled(count = 1, order = intArrayOf(1))
override fun onPageStart(session: GeckoSession, url: String) {
assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH))

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

@ -37,7 +37,7 @@ public class NavigationTests extends BaseGeckoViewTest {
@Override public void run() {
loadTestPath("hello2.html", new Runnable() {
@Override public void run() {
mSession.setNavigationListener(new GeckoSession.NavigationListener() {
mSession.setNavigationDelegate(new GeckoSession.NavigationDelegate() {
@Override
public void onLocationChange(GeckoSession session, String url) {
assertTrue("URL should end with " + startPath + ", got " + url, url.endsWith(startPath));
@ -78,7 +78,7 @@ public class NavigationTests extends BaseGeckoViewTest {
public void testReload() {
loadTestPath("hello.html", new Runnable() {
@Override public void run() {
mSession.setProgressListener(new GeckoSession.ProgressListener() {
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
@Override
public void onPageStart(GeckoSession session, String url) {
}
@ -104,7 +104,7 @@ public class NavigationTests extends BaseGeckoViewTest {
@Test
public void testExpiredCert() {
mSession.setProgressListener(new GeckoSession.ProgressListener() {
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
private boolean mNotBlank;
@Override
@ -133,7 +133,7 @@ public class NavigationTests extends BaseGeckoViewTest {
@Test
public void testValidTLS() {
mSession.setProgressListener(new GeckoSession.ProgressListener() {
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
private boolean mNotBlank;
@Override
@ -162,7 +162,7 @@ public class NavigationTests extends BaseGeckoViewTest {
@Test
public void testOnNewSession() {
mSession.setNavigationListener(new GeckoSession.NavigationListener() {
mSession.setNavigationDelegate(new GeckoSession.NavigationDelegate() {
@Override
public void onLocationChange(GeckoSession session, String url) {
}
@ -185,7 +185,7 @@ public class NavigationTests extends BaseGeckoViewTest {
@Override
public void onNewSession(GeckoSession session, String uri, GeckoSession.Response<GeckoSession> response) {
final GeckoSession newSession = new GeckoSession(session.getSettings());
newSession.setContentListener(new GeckoSession.ContentListener() {
newSession.setContentDelegate(new GeckoSession.ContentDelegate() {
@Override
public void onTitleChange(GeckoSession session, String title) {
@ -218,7 +218,7 @@ public class NavigationTests extends BaseGeckoViewTest {
}
});
mSession.setProgressListener(new GeckoSession.ProgressListener() {
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
@Override
public void onPageStart(GeckoSession session, String url) {
@ -245,10 +245,10 @@ public class NavigationTests extends BaseGeckoViewTest {
@Test(expected = IllegalArgumentException.class)
public void testOnNewSessionNoExisting() {
// This makes sure that we get an exception if you try to return
// an existing GeckoSession instance from the NavigationListener.onNewSession()
// an existing GeckoSession instance from the NavigationDelegate.onNewSession()
// implementation.
mSession.setNavigationListener(new GeckoSession.NavigationListener() {
mSession.setNavigationDelegate(new GeckoSession.NavigationDelegate() {
@Override
public void onLocationChange(GeckoSession session, String url) {
}
@ -275,7 +275,7 @@ public class NavigationTests extends BaseGeckoViewTest {
}
});
mSession.setProgressListener(new GeckoSession.ProgressListener() {
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
@Override
public void onPageStart(GeckoSession session, String url) {

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