зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
3ccafa2b66
|
@ -1047,11 +1047,7 @@ pref("dom.ipc.plugins.sandbox-level.flash", 0);
|
||||||
// On windows these levels are:
|
// On windows these levels are:
|
||||||
// See - security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
|
// See - security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
|
||||||
// SetSecurityLevelForContentProcess() for what the different settings mean.
|
// SetSecurityLevelForContentProcess() for what the different settings mean.
|
||||||
#if defined(NIGHTLY_BUILD)
|
|
||||||
pref("security.sandbox.content.level", 5);
|
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
|
// 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
|
// logging is turned on. This is only currently available for the content
|
||||||
|
|
|
@ -6,13 +6,11 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const { gDevTools } = require("devtools/client/framework/devtools");
|
||||||
const { getColor } = require("devtools/client/shared/theme");
|
const { getColor } = require("devtools/client/shared/theme");
|
||||||
|
|
||||||
const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
|
const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
|
||||||
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
||||||
|
|
||||||
const { gDevTools } = require("devtools/client/framework/devtools");
|
|
||||||
|
|
||||||
const FontsApp = createFactory(require("./components/FontsApp"));
|
const FontsApp = createFactory(require("./components/FontsApp"));
|
||||||
|
|
||||||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
const { LocalizationHelper } = require("devtools/shared/l10n");
|
||||||
|
@ -193,6 +191,11 @@ class FontInspector {
|
||||||
previewFillStyle: getColor("body-color")
|
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);
|
fonts = await this.getFontsForNode(node, options);
|
||||||
otherFonts = await this.getFontsNotInNode(fonts, options);
|
otherFonts = await this.getFontsNotInNode(fonts, options);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,45 @@
|
||||||
|
|
||||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
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.
|
* A single font.
|
||||||
*/
|
*/
|
||||||
|
@ -27,6 +66,12 @@ const font = exports.font = {
|
||||||
|
|
||||||
// The URI of the font file
|
// The URI of the font file
|
||||||
URI: PropTypes.string,
|
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 = {
|
exports.fontOptions = {
|
||||||
|
@ -35,7 +80,7 @@ exports.fontOptions = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Font data
|
* Font data.
|
||||||
*/
|
*/
|
||||||
exports.fontData = {
|
exports.fontData = {
|
||||||
// The fonts used in the current element.
|
// The fonts used in the current element.
|
||||||
|
|
|
@ -91,7 +91,7 @@ class SnapshotListItem extends Component {
|
||||||
className: "save",
|
className: "save",
|
||||||
}, L10N.getStr("snapshot.io.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),
|
onClick: () => onDelete(snapshot),
|
||||||
className: "delete",
|
className: "delete",
|
||||||
title: L10N.getStr("snapshot.io.delete")
|
title: L10N.getStr("snapshot.io.delete")
|
||||||
|
|
|
@ -811,7 +811,7 @@ class TreeNodeClass extends Component {
|
||||||
id: this.props.id,
|
id: this.props.id,
|
||||||
className: classList.join(" "),
|
className: classList.join(" "),
|
||||||
role: "treeitem",
|
role: "treeitem",
|
||||||
"aria-level": this.props.depth,
|
"aria-level": this.props.depth + 1,
|
||||||
onClick: this.props.onClick,
|
onClick: this.props.onClick,
|
||||||
"aria-expanded": ariaExpanded,
|
"aria-expanded": ariaExpanded,
|
||||||
"data-expanded": this.props.expanded ? "" : undefined,
|
"data-expanded": this.props.expanded ? "" : undefined,
|
||||||
|
|
|
@ -96,7 +96,9 @@ function isAccessibleTree(tree, options = {}) {
|
||||||
for (let node of treeNodes) {
|
for (let node of treeNodes) {
|
||||||
ok(node.id, "TreeNode has an id");
|
ok(node.id, "TreeNode has an id");
|
||||||
is(node.getAttribute("role"), "treeitem", "Tree item semantics is present");
|
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 {
|
.snapshot-list-item .delete {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
min-width: 1.3em;
|
min-width: 1.3em;
|
||||||
|
color: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.snapshot-list-item .delete::before {
|
.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(
|
DevToolsModules(
|
||||||
|
'accessibility-parent.js',
|
||||||
'accessibility.js',
|
'accessibility.js',
|
||||||
'actor-registry.js',
|
'actor-registry.js',
|
||||||
'addon.js',
|
'addon.js',
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const {Ci} = require("chrome");
|
const {Ci} = require("chrome");
|
||||||
|
const Services = require("Services");
|
||||||
const protocol = require("devtools/shared/protocol");
|
const protocol = require("devtools/shared/protocol");
|
||||||
const {LongStringActor} = require("devtools/server/actors/string");
|
const {LongStringActor} = require("devtools/server/actors/string");
|
||||||
const InspectorUtils = require("InspectorUtils");
|
const InspectorUtils = require("InspectorUtils");
|
||||||
|
@ -29,6 +30,9 @@ loader.lazyRequireGetter(this, "UPDATE_GENERAL",
|
||||||
loader.lazyGetter(this, "PSEUDO_ELEMENTS", () => {
|
loader.lazyGetter(this, "PSEUDO_ELEMENTS", () => {
|
||||||
return InspectorUtils.getCSSPseudoElementNames();
|
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 XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||||
const FONT_PREVIEW_TEXT = "Abc";
|
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.
|
// been fixed must make sure cssLogic.highlight(node) was called before.
|
||||||
getAppliedCreatesStyleCache: true,
|
getAppliedCreatesStyleCache: true,
|
||||||
// Whether addNewRule accepts the editAuthored argument.
|
// 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
|
size: size
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.includeVariations && FONT_VARIATIONS_ENABLED) {
|
||||||
|
fontFace.variationAxes = font.getVariationAxes();
|
||||||
|
fontFace.variationInstances = font.getVariationInstances();
|
||||||
|
}
|
||||||
|
|
||||||
fontsArray.push(fontFace);
|
fontsArray.push(fontFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ support-files =
|
||||||
!/devtools/server/tests/mochitest/hello-actor.js
|
!/devtools/server/tests/mochitest/hello-actor.js
|
||||||
!/devtools/client/framework/test/shared-head.js
|
!/devtools/client/framework/test/shared-head.js
|
||||||
|
|
||||||
[browser_accessibility_node_events.js]
|
|
||||||
[browser_accessibility_node.js]
|
[browser_accessibility_node.js]
|
||||||
|
[browser_accessibility_node_events.js]
|
||||||
[browser_accessibility_simple.js]
|
[browser_accessibility_simple.js]
|
||||||
[browser_accessibility_walker.js]
|
[browser_accessibility_walker.js]
|
||||||
[browser_animation_emitMutations.js]
|
[browser_animation_emitMutations.js]
|
||||||
|
|
|
@ -10,7 +10,8 @@ add_task(async function () {
|
||||||
let {client, walker, accessibility} =
|
let {client, walker, accessibility} =
|
||||||
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility.html");
|
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 buttonNode = await walker.querySelector(walker.rootNode, "#button");
|
||||||
let accessibleFront = await a11yWalker.getAccessibleFor(buttonNode);
|
let accessibleFront = await a11yWalker.getAccessibleFor(buttonNode);
|
||||||
|
|
||||||
|
@ -22,38 +23,23 @@ add_task(async function () {
|
||||||
help: "",
|
help: "",
|
||||||
keyboardShortcut: "",
|
keyboardShortcut: "",
|
||||||
childCount: 1,
|
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");
|
info("Children");
|
||||||
let children = await accessibleFront.children();
|
let children = await accessibleFront.children();
|
||||||
is(children.length, 1, "Accessible Front has correct number of children");
|
is(children.length, 1, "Accessible Front has correct number of children");
|
||||||
|
@ -62,13 +48,8 @@ add_task(async function () {
|
||||||
role: "text leaf"
|
role: "text leaf"
|
||||||
});
|
});
|
||||||
|
|
||||||
info("DOM Node");
|
await accessibility.disable();
|
||||||
let node = await accessibleFront.getDOMNode(walker);
|
await waitForA11yShutdown();
|
||||||
is(node, buttonNode, "Accessible Front has correct DOM node");
|
|
||||||
|
|
||||||
let a11yShutdown = waitForA11yShutdown();
|
|
||||||
await client.close();
|
await client.close();
|
||||||
forceCollections();
|
|
||||||
await a11yShutdown;
|
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,8 +10,10 @@ add_task(async function () {
|
||||||
let {client, walker, accessibility} =
|
let {client, walker, accessibility} =
|
||||||
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility.html");
|
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility.html");
|
||||||
|
|
||||||
let a11yWalker = await accessibility.getWalker(walker);
|
let a11yWalker = await accessibility.getWalker();
|
||||||
let a11yDoc = await a11yWalker.getDocument();
|
await accessibility.enable();
|
||||||
|
let rootNode = await walker.getRootNode();
|
||||||
|
let a11yDoc = await a11yWalker.getAccessibleFor(rootNode);
|
||||||
let buttonNode = await walker.querySelector(walker.rootNode, "#button");
|
let buttonNode = await walker.querySelector(walker.rootNode, "#button");
|
||||||
let accessibleFront = await a11yWalker.getAccessibleFor(buttonNode);
|
let accessibleFront = await a11yWalker.getAccessibleFor(buttonNode);
|
||||||
let sliderNode = await walker.querySelector(walker.rootNode, "#slider");
|
let sliderNode = await walker.querySelector(walker.rootNode, "#slider");
|
||||||
|
@ -26,7 +28,21 @@ add_task(async function () {
|
||||||
help: "",
|
help: "",
|
||||||
keyboardShortcut: "",
|
keyboardShortcut: "",
|
||||||
childCount: 1,
|
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");
|
info("Name change event");
|
||||||
|
@ -45,27 +61,35 @@ add_task(async function () {
|
||||||
content.document.getElementById("button").removeAttribute("aria-describedby")));
|
content.document.getElementById("button").removeAttribute("aria-describedby")));
|
||||||
|
|
||||||
info("State change event");
|
info("State change event");
|
||||||
let states = await accessibleFront.getState();
|
|
||||||
let expectedStates = ["unavailable", "selectable text", "opaque"];
|
let expectedStates = ["unavailable", "selectable text", "opaque"];
|
||||||
SimpleTest.isDeeply(states, ["focusable", "selectable text", "opaque",
|
await emitA11yEvent(accessibleFront, "states-change",
|
||||||
"enabled", "sensitive"], "States are correct");
|
newStates => {
|
||||||
await emitA11yEvent(accessibleFront, "state-change",
|
checkA11yFront(accessibleFront, { states: expectedStates });
|
||||||
newStates => SimpleTest.isDeeply(newStates, expectedStates,
|
SimpleTest.isDeeply(newStates, expectedStates, "States are updated");
|
||||||
"States are updated"),
|
}, () => ContentTask.spawn(browser, null, () =>
|
||||||
() => ContentTask.spawn(browser, null, () =>
|
|
||||||
content.document.getElementById("button").setAttribute("disabled", true)));
|
content.document.getElementById("button").setAttribute("disabled", true)));
|
||||||
states = await accessibleFront.getState();
|
|
||||||
SimpleTest.isDeeply(states, expectedStates, "States are updated");
|
|
||||||
|
|
||||||
info("Attributes change event");
|
info("Attributes change event");
|
||||||
let attrs = await accessibleFront.getAttributes();
|
|
||||||
ok(!attrs.live, "Attribute is not present");
|
|
||||||
await emitA11yEvent(accessibleFront, "attributes-change",
|
await emitA11yEvent(accessibleFront, "attributes-change",
|
||||||
newAttrs => is(newAttrs.live, "polite", "Attributes are updated"),
|
newAttrs => {
|
||||||
() => ContentTask.spawn(browser, null, () =>
|
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")));
|
content.document.getElementById("button").setAttribute("aria-live", "polite")));
|
||||||
attrs = await accessibleFront.getAttributes();
|
|
||||||
is(attrs.live, "polite", "Attributes are updated");
|
|
||||||
|
|
||||||
info("Value change event");
|
info("Value change event");
|
||||||
checkA11yFront(accessibleSliderFront, { value: "5" });
|
checkA11yFront(accessibleSliderFront, { value: "5" });
|
||||||
|
@ -76,18 +100,29 @@ add_task(async function () {
|
||||||
|
|
||||||
info("Reorder event");
|
info("Reorder event");
|
||||||
is(accessibleSliderFront.childCount, 1, "Slider has only 1 child");
|
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",
|
await emitA11yEvent(accessibleSliderFront, "reorder",
|
||||||
childCount => is(childCount, 2, "Child count is updated"),
|
childCount => {
|
||||||
() => ContentTask.spawn(browser, null, () => {
|
is(childCount, 2, "Child count is updated");
|
||||||
let button = content.document.createElement("button");
|
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";
|
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();
|
await client.close();
|
||||||
forceCollections();
|
|
||||||
await a11yShutdown;
|
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,10 +4,19 @@
|
||||||
|
|
||||||
"use strict";
|
"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
|
// Simple checks for the AccessibilityActor and AccessibleWalkerActor
|
||||||
|
|
||||||
add_task(async function () {
|
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>");
|
"data:text/html;charset=utf-8,<title>test</title><div></div>");
|
||||||
|
|
||||||
ok(accessibility, "The AccessibilityFront was created");
|
ok(accessibility, "The AccessibilityFront was created");
|
||||||
|
@ -16,6 +25,44 @@ add_task(async function () {
|
||||||
let a11yWalker = await accessibility.getWalker();
|
let a11yWalker = await accessibility.getWalker();
|
||||||
ok(a11yWalker, "The AccessibleWalkerFront was returned");
|
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();
|
await client.close();
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,10 +10,12 @@ add_task(async function () {
|
||||||
let {client, walker, accessibility} =
|
let {client, walker, accessibility} =
|
||||||
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility.html");
|
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility.html");
|
||||||
|
|
||||||
let a11yWalker = await accessibility.getWalker(walker);
|
let a11yWalker = await accessibility.getWalker();
|
||||||
ok(a11yWalker, "The AccessibleWalkerFront was returned");
|
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");
|
ok(a11yDoc, "The AccessibleFront for root doc is created");
|
||||||
|
|
||||||
let children = await a11yWalker.children();
|
let children = await a11yWalker.children();
|
||||||
|
@ -30,6 +32,15 @@ add_task(async function () {
|
||||||
role: "pushbutton"
|
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;
|
let browser = gBrowser.selectedBrowser;
|
||||||
|
|
||||||
// Ensure name-change event is emitted by walker when cached accessible's name
|
// 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, () =>
|
() => ContentTask.spawn(browser, null, () =>
|
||||||
content.document.getElementById("button").remove()));
|
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();
|
await client.close();
|
||||||
forceCollections();
|
|
||||||
await a11yShutdown;
|
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
});
|
});
|
||||||
|
|
|
@ -89,6 +89,8 @@ async function initAccessibilityFrontForUrl(url) {
|
||||||
let walker = await inspector.getWalker();
|
let walker = await inspector.getWalker();
|
||||||
let accessibility = AccessibilityFront(client, form);
|
let accessibility = AccessibilityFront(client, form);
|
||||||
|
|
||||||
|
await accessibility.bootstrap();
|
||||||
|
|
||||||
return {inspector, walker, accessibility, client};
|
return {inspector, walker, accessibility, client};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,24 +310,47 @@ function checkA11yFront(front, expected, expectedFront) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let key in expected) {
|
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
|
* 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".
|
* an "a11y-init-or-shutdown" event is received with a value of "0".
|
||||||
*/
|
*/
|
||||||
async function waitForA11yShutdown() {
|
async function waitForA11yShutdown() {
|
||||||
await ContentTask.spawn(gBrowser.selectedBrowser, {}, () =>
|
if (!Services.appinfo.accessibilityEnabled) {
|
||||||
new Promise(resolve => {
|
return;
|
||||||
let observe = (subject, topic, data) => {
|
}
|
||||||
Services.obs.removeObserver(observe, "a11y-init-or-shutdown");
|
|
||||||
|
|
||||||
if (data === "0") {
|
await getA11yInitOrShutdownPromise().then(data =>
|
||||||
resolve();
|
data === "0" ? Promise.resolve() : Promise.reject());
|
||||||
}
|
}
|
||||||
};
|
|
||||||
Services.obs.addObserver(observe, "a11y-init-or-shutdown");
|
/**
|
||||||
}));
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
|
||||||
const {
|
const {
|
||||||
|
custom,
|
||||||
Front,
|
Front,
|
||||||
FrontClassWithSpec,
|
FrontClassWithSpec,
|
||||||
preEvent,
|
preEvent
|
||||||
types
|
|
||||||
} = require("devtools/shared/protocol.js");
|
} = require("devtools/shared/protocol.js");
|
||||||
const {
|
const {
|
||||||
accessibleSpec,
|
accessibleSpec,
|
||||||
accessibleWalkerSpec,
|
accessibleWalkerSpec,
|
||||||
accessibilitySpec
|
accessibilitySpec
|
||||||
} = require("devtools/shared/specs/accessibility");
|
} = require("devtools/shared/specs/accessibility");
|
||||||
|
|
||||||
const events = require("devtools/shared/event-emitter");
|
const events = require("devtools/shared/event-emitter");
|
||||||
const ACCESSIBLE_PROPERTIES = [
|
|
||||||
"role",
|
|
||||||
"name",
|
|
||||||
"value",
|
|
||||||
"description",
|
|
||||||
"help",
|
|
||||||
"keyboardShortcut",
|
|
||||||
"childCount",
|
|
||||||
"domNodeType"
|
|
||||||
];
|
|
||||||
|
|
||||||
const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
|
const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
|
||||||
initialize(client, form) {
|
initialize(client, form) {
|
||||||
Front.prototype.initialize.call(this, 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() {
|
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) {
|
form(form, detail) {
|
||||||
|
@ -57,25 +81,14 @@ const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
|
||||||
|
|
||||||
this.actorID = form.actor;
|
this.actorID = form.actor;
|
||||||
this._form = form;
|
this._form = form;
|
||||||
DevToolsUtils.defineLazyGetter(this, "walker", () =>
|
|
||||||
types.getType("accessiblewalker").read(this._form.walker, this));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
nameChange: preEvent("name-change", function (name, parent, walker) {
|
||||||
* 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) {
|
|
||||||
this._form.name = name;
|
this._form.name = name;
|
||||||
// Name change event affects the tree rendering, we fire this event on
|
// Name change event affects the tree rendering, we fire this event on
|
||||||
// accessibility walker as the point of interaction for UI.
|
// accessibility walker as the point of interaction for UI.
|
||||||
if (this.walker) {
|
if (walker) {
|
||||||
events.emit(this.walker, "name-change", this, parent);
|
events.emit(walker, "name-change", this, parent);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -95,21 +108,37 @@ const AccessibleFront = FrontClassWithSpec(accessibleSpec, {
|
||||||
this._form.keyboardShortcut = keyboardShortcut;
|
this._form.keyboardShortcut = keyboardShortcut;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
reorder: preEvent("reorder", function (childCount) {
|
reorder: preEvent("reorder", function (childCount, walker) {
|
||||||
this._form.childCount = childCount;
|
this._form.childCount = childCount;
|
||||||
// Reorder event affects the tree rendering, we fire this event on
|
// Reorder event affects the tree rendering, we fire this event on
|
||||||
// accessibility walker as the point of interaction for UI.
|
// accessibility walker as the point of interaction for UI.
|
||||||
if (this.walker) {
|
if (walker) {
|
||||||
events.emit(this.walker, "reorder", this);
|
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
|
// Text event affects the tree rendering, we fire this event on
|
||||||
// accessibility walker as the point of interaction for UI.
|
// accessibility walker as the point of interaction for UI.
|
||||||
if (this.walker) {
|
if (walker) {
|
||||||
events.emit(this.walker, "text-change", this);
|
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) {
|
form(json) {
|
||||||
this.actorID = json.actor;
|
this.actorID = json.actor;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
pick: custom(function (doFocus) {
|
||||||
|
if (doFocus) {
|
||||||
|
return this.pickAndFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._pick();
|
||||||
|
}, {
|
||||||
|
impl: "_pick"
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const AccessibilityFront = FrontClassWithSpec(accessibilitySpec, {
|
const AccessibilityFront = FrontClassWithSpec(accessibilitySpec, {
|
||||||
|
@ -128,7 +167,33 @@ const AccessibilityFront = FrontClassWithSpec(accessibilitySpec, {
|
||||||
Front.prototype.initialize.call(this, client, form);
|
Front.prototype.initialize.call(this, client, form);
|
||||||
this.actorID = form.accessibilityActor;
|
this.actorID = form.accessibilityActor;
|
||||||
this.manage(this);
|
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;
|
exports.AccessibleFront = AccessibleFront;
|
||||||
|
|
|
@ -47,6 +47,10 @@ const PageStyleFront = FrontClassWithSpec(pageStyleSpec, {
|
||||||
return this._form.traits && this._form.traits.authoredStyles;
|
return this._form.traits && this._form.traits.authoredStyles;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get supportsFontVariations() {
|
||||||
|
return this._form.traits && this._form.traits.fontVariations;
|
||||||
|
},
|
||||||
|
|
||||||
getMatchedSelectors: custom(function (node, property, options) {
|
getMatchedSelectors: custom(function (node, property, options) {
|
||||||
return this._getMatchedSelectors(node, property, options).then(ret => {
|
return this._getMatchedSelectors(node, property, options).then(ret => {
|
||||||
return ret.matched;
|
return ret.matched;
|
||||||
|
|
|
@ -9,6 +9,17 @@ const { Arg, generateActorSpec, RetVal, types } = protocol;
|
||||||
|
|
||||||
types.addActorType("accessible");
|
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({
|
const accessibleSpec = generateActorSpec({
|
||||||
typeName: "accessible",
|
typeName: "accessible",
|
||||||
|
|
||||||
|
@ -20,7 +31,8 @@ const accessibleSpec = generateActorSpec({
|
||||||
"name-change": {
|
"name-change": {
|
||||||
type: "nameChange",
|
type: "nameChange",
|
||||||
name: Arg(0, "string"),
|
name: Arg(0, "string"),
|
||||||
parent: Arg(1, "nullable:accessible")
|
parent: Arg(1, "nullable:accessible"),
|
||||||
|
walker: Arg(2, "nullable:accessiblewalker")
|
||||||
},
|
},
|
||||||
"value-change": {
|
"value-change": {
|
||||||
type: "valueChange",
|
type: "valueChange",
|
||||||
|
@ -30,13 +42,13 @@ const accessibleSpec = generateActorSpec({
|
||||||
type: "descriptionChange",
|
type: "descriptionChange",
|
||||||
description: Arg(0, "string")
|
description: Arg(0, "string")
|
||||||
},
|
},
|
||||||
"state-change": {
|
"states-change": {
|
||||||
type: "stateChange",
|
type: "statesChange",
|
||||||
states: Arg(0, "array:string")
|
states: Arg(0, "array:string")
|
||||||
},
|
},
|
||||||
"attributes-change": {
|
"attributes-change": {
|
||||||
type: "attributesChange",
|
type: "attributesChange",
|
||||||
states: Arg(0, "json")
|
attributes: Arg(0, "json")
|
||||||
},
|
},
|
||||||
"help-change": {
|
"help-change": {
|
||||||
type: "helpChange",
|
type: "helpChange",
|
||||||
|
@ -48,38 +60,20 @@ const accessibleSpec = generateActorSpec({
|
||||||
},
|
},
|
||||||
"reorder": {
|
"reorder": {
|
||||||
type: "reorder",
|
type: "reorder",
|
||||||
childCount: Arg(0, "number")
|
childCount: Arg(0, "number"),
|
||||||
|
walker: Arg(1, "nullable:accessiblewalker")
|
||||||
},
|
},
|
||||||
"text-change": {
|
"text-change": {
|
||||||
type: "textChange"
|
type: "textChange",
|
||||||
|
walker: Arg(0, "nullable:accessiblewalker")
|
||||||
|
},
|
||||||
|
"index-in-parent-change": {
|
||||||
|
type: "indexInParentChange",
|
||||||
|
indexInParent: Arg(0, "number")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
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: {
|
children: {
|
||||||
request: {},
|
request: {},
|
||||||
response: {
|
response: {
|
||||||
|
@ -96,6 +90,24 @@ const accessibleWalkerSpec = generateActorSpec({
|
||||||
"accessible-destroy": {
|
"accessible-destroy": {
|
||||||
type: "accessibleDestroy",
|
type: "accessibleDestroy",
|
||||||
accessible: Arg(0, "accessible")
|
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")
|
children: RetVal("array:accessible")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getDocument: {
|
|
||||||
request: {},
|
|
||||||
response: {
|
|
||||||
document: RetVal("accessible")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getAccessibleFor: {
|
getAccessibleFor: {
|
||||||
request: { node: Arg(0, "domnode") },
|
request: { node: Arg(0, "domnode") },
|
||||||
response: {
|
response: {
|
||||||
accessible: RetVal("accessible")
|
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({
|
const accessibilitySpec = generateActorSpec({
|
||||||
typeName: "accessibility",
|
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: {
|
methods: {
|
||||||
|
bootstrap: {
|
||||||
|
request: {},
|
||||||
|
response: {
|
||||||
|
state: RetVal("json")
|
||||||
|
}
|
||||||
|
},
|
||||||
getWalker: {
|
getWalker: {
|
||||||
request: {},
|
request: {},
|
||||||
response: {
|
response: {
|
||||||
walker: RetVal("accessiblewalker")
|
walker: RetVal("accessiblewalker")
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
enable: {
|
||||||
|
request: {},
|
||||||
|
response: {}
|
||||||
|
},
|
||||||
|
disable: {
|
||||||
|
request: {},
|
||||||
|
response: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -58,6 +58,24 @@ types.addDictType("fontpreview", {
|
||||||
size: "json"
|
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", {
|
types.addDictType("fontface", {
|
||||||
name: "string",
|
name: "string",
|
||||||
CSSFamilyName: "string",
|
CSSFamilyName: "string",
|
||||||
|
@ -67,7 +85,9 @@ types.addDictType("fontface", {
|
||||||
format: "string",
|
format: "string",
|
||||||
preview: "nullable:fontpreview",
|
preview: "nullable:fontpreview",
|
||||||
localName: "string",
|
localName: "string",
|
||||||
metadata: "string"
|
metadata: "string",
|
||||||
|
variationAxes: "array:fontvariationaxis",
|
||||||
|
variationInstances: "array:fontvariationinstance"
|
||||||
});
|
});
|
||||||
|
|
||||||
const pageStyleSpec = generateActorSpec({
|
const pageStyleSpec = generateActorSpec({
|
||||||
|
@ -95,6 +115,7 @@ const pageStyleSpec = generateActorSpec({
|
||||||
getAllUsedFontFaces: {
|
getAllUsedFontFaces: {
|
||||||
request: {
|
request: {
|
||||||
includePreviews: Option(0, "boolean"),
|
includePreviews: Option(0, "boolean"),
|
||||||
|
includeVariations: Option(1, "boolean"),
|
||||||
previewText: Option(0, "string"),
|
previewText: Option(0, "string"),
|
||||||
previewFontSize: Option(0, "string"),
|
previewFontSize: Option(0, "string"),
|
||||||
previewFillStyle: Option(0, "string")
|
previewFillStyle: Option(0, "string")
|
||||||
|
@ -107,6 +128,7 @@ const pageStyleSpec = generateActorSpec({
|
||||||
request: {
|
request: {
|
||||||
node: Arg(0, "domnode"),
|
node: Arg(0, "domnode"),
|
||||||
includePreviews: Option(1, "boolean"),
|
includePreviews: Option(1, "boolean"),
|
||||||
|
includeVariations: Option(1, "boolean"),
|
||||||
previewText: Option(1, "string"),
|
previewText: Option(1, "string"),
|
||||||
previewFontSize: Option(1, "string"),
|
previewFontSize: Option(1, "string"),
|
||||||
previewFillStyle: Option(1, "string")
|
previewFillStyle: Option(1, "string")
|
||||||
|
|
|
@ -423,6 +423,11 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
|
||||||
definition->mLocalName != aCustomElement->NodeInfo()->NameAtom()) {
|
definition->mLocalName != aCustomElement->NodeInfo()->NameAtom()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!definition->mCallbacks) {
|
||||||
|
// definition has been unlinked. Don't try to mess with it.
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto callback =
|
auto callback =
|
||||||
|
|
|
@ -1102,7 +1102,12 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
nsContentUtils::Retarget(relatedTargetAsNode, this);
|
nsContentUtils::Retarget(relatedTargetAsNode, this);
|
||||||
nsCOMPtr<nsINode> targetInKnownToBeHandledScope =
|
nsCOMPtr<nsINode> targetInKnownToBeHandledScope =
|
||||||
FindChromeAccessOnlySubtreeOwner(aVisitor.mTargetInKnownToBeHandledScope);
|
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())) {
|
this, targetInKnownToBeHandledScope->SubtreeRoot())) {
|
||||||
// Part of step 11.4.
|
// Part of step 11.4.
|
||||||
// "If target's root is a shadow-including inclusive ancestor of
|
// "If target's root is a shadow-including inclusive ancestor of
|
||||||
|
|
|
@ -1445,8 +1445,8 @@ nsIDocument::nsIDocument()
|
||||||
mHasHadScriptHandlingObject(false),
|
mHasHadScriptHandlingObject(false),
|
||||||
mIsBeingUsedAsImage(false),
|
mIsBeingUsedAsImage(false),
|
||||||
mIsSyntheticDocument(false),
|
mIsSyntheticDocument(false),
|
||||||
mHasLinksToUpdate(false),
|
|
||||||
mHasLinksToUpdateRunnable(false),
|
mHasLinksToUpdateRunnable(false),
|
||||||
|
mFlushingPendingLinkUpdates(false),
|
||||||
mMayHaveDOMMutationObservers(false),
|
mMayHaveDOMMutationObservers(false),
|
||||||
mMayHaveAnimationObservers(false),
|
mMayHaveAnimationObservers(false),
|
||||||
mHasMixedActiveContentLoaded(false),
|
mHasMixedActiveContentLoaded(false),
|
||||||
|
@ -1491,7 +1491,6 @@ nsIDocument::nsIDocument()
|
||||||
mType(eUnknown),
|
mType(eUnknown),
|
||||||
mDefaultElementType(0),
|
mDefaultElementType(0),
|
||||||
mAllowXULXBL(eTriUnset),
|
mAllowXULXBL(eTriUnset),
|
||||||
mIsLinkUpdateRegistrationsForbidden(false),
|
|
||||||
mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
|
mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
|
||||||
mSandboxFlags(0),
|
mSandboxFlags(0),
|
||||||
mPartID(0),
|
mPartID(0),
|
||||||
|
@ -9612,15 +9611,13 @@ nsIDocument::EnumerateActivityObservers(ActivityObserverEnumerator aEnumerator,
|
||||||
void
|
void
|
||||||
nsIDocument::RegisterPendingLinkUpdate(Link* aLink)
|
nsIDocument::RegisterPendingLinkUpdate(Link* aLink)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(!mIsLinkUpdateRegistrationsForbidden);
|
|
||||||
|
|
||||||
if (aLink->HasPendingLinkUpdate()) {
|
if (aLink->HasPendingLinkUpdate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
aLink->SetHasPendingLinkUpdate();
|
aLink->SetHasPendingLinkUpdate();
|
||||||
|
|
||||||
if (!mHasLinksToUpdateRunnable) {
|
if (!mHasLinksToUpdateRunnable && !mFlushingPendingLinkUpdates) {
|
||||||
nsCOMPtr<nsIRunnable> event =
|
nsCOMPtr<nsIRunnable> event =
|
||||||
NewRunnableMethod("nsIDocument::FlushPendingLinkUpdatesFromRunnable",
|
NewRunnableMethod("nsIDocument::FlushPendingLinkUpdatesFromRunnable",
|
||||||
this,
|
this,
|
||||||
|
@ -9637,7 +9634,6 @@ nsIDocument::RegisterPendingLinkUpdate(Link* aLink)
|
||||||
}
|
}
|
||||||
|
|
||||||
mLinksToUpdate.InfallibleAppend(aLink);
|
mLinksToUpdate.InfallibleAppend(aLink);
|
||||||
mHasLinksToUpdate = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -9651,24 +9647,26 @@ nsIDocument::FlushPendingLinkUpdatesFromRunnable()
|
||||||
void
|
void
|
||||||
nsIDocument::FlushPendingLinkUpdates()
|
nsIDocument::FlushPendingLinkUpdates()
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(!mIsLinkUpdateRegistrationsForbidden);
|
if (mFlushingPendingLinkUpdates) {
|
||||||
if (!mHasLinksToUpdate)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AutoRestore<bool> saved(mIsLinkUpdateRegistrationsForbidden);
|
auto restore = MakeScopeExit([&] { mFlushingPendingLinkUpdates = false; });
|
||||||
mIsLinkUpdateRegistrationsForbidden = true;
|
mFlushingPendingLinkUpdates = true;
|
||||||
for (auto iter = mLinksToUpdate.Iter(); !iter.Done(); iter.Next()) {
|
|
||||||
Link* link = iter.Get();
|
while (!mLinksToUpdate.IsEmpty()) {
|
||||||
Element* element = link->GetElement();
|
LinksToUpdateList links(Move(mLinksToUpdate));
|
||||||
if (element->OwnerDoc() == this) {
|
for (auto iter = links.Iter(); !iter.Done(); iter.Next()) {
|
||||||
link->ClearHasPendingLinkUpdate();
|
Link* link = iter.Get();
|
||||||
if (element->IsInComposedDoc()) {
|
Element* element = link->GetElement();
|
||||||
element->UpdateLinkState(link->LinkState());
|
if (element->OwnerDoc() == this) {
|
||||||
|
link->ClearHasPendingLinkUpdate();
|
||||||
|
if (element->IsInComposedDoc()) {
|
||||||
|
element->UpdateLinkState(link->LinkState());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mLinksToUpdate.Clear();
|
|
||||||
mHasLinksToUpdate = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIDocument>
|
already_AddRefed<nsIDocument>
|
||||||
|
|
|
@ -3344,10 +3344,13 @@ protected:
|
||||||
// The array of all links that need their status resolved. Links must add themselves
|
// 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.
|
// to this set by calling RegisterPendingLinkUpdate when added to a document.
|
||||||
static const size_t kSegmentSize = 128;
|
static const size_t kSegmentSize = 128;
|
||||||
mozilla::SegmentedVector<nsCOMPtr<mozilla::dom::Link>,
|
|
||||||
kSegmentSize,
|
typedef mozilla::SegmentedVector<nsCOMPtr<mozilla::dom::Link>,
|
||||||
InfallibleAllocPolicy>
|
kSegmentSize,
|
||||||
mLinksToUpdate;
|
InfallibleAllocPolicy>
|
||||||
|
LinksToUpdateList;
|
||||||
|
|
||||||
|
LinksToUpdateList mLinksToUpdate;
|
||||||
|
|
||||||
// SMIL Animation Controller, lazily-initialized in GetAnimationController
|
// SMIL Animation Controller, lazily-initialized in GetAnimationController
|
||||||
RefPtr<nsSMILAnimationController> mAnimationController;
|
RefPtr<nsSMILAnimationController> mAnimationController;
|
||||||
|
@ -3441,12 +3444,12 @@ protected:
|
||||||
// file, etc.
|
// file, etc.
|
||||||
bool mIsSyntheticDocument : 1;
|
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().
|
// True is there is a pending runnable which will call FlushPendingLinkUpdates().
|
||||||
bool mHasLinksToUpdateRunnable : 1;
|
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.
|
// True if a DOMMutationObserver is perhaps attached to a node in the document.
|
||||||
bool mMayHaveDOMMutationObservers : 1;
|
bool mMayHaveDOMMutationObservers : 1;
|
||||||
|
|
||||||
|
@ -3595,12 +3598,6 @@ protected:
|
||||||
|
|
||||||
Tri mAllowXULXBL;
|
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
|
// The document's script global object, the object from which the
|
||||||
// document can get its script context and scope. This is the
|
// document can get its script context and scope. This is the
|
||||||
// *inner* window object.
|
// *inner* window object.
|
||||||
|
|
|
@ -23,10 +23,6 @@ class nsICycleCollectorListener;
|
||||||
class nsScriptNameSpaceManager;
|
class nsScriptNameSpaceManager;
|
||||||
class nsIDocShell;
|
class nsIDocShell;
|
||||||
|
|
||||||
namespace JS {
|
|
||||||
class AutoValueVector;
|
|
||||||
} // namespace JS
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
template <class> class Maybe;
|
template <class> class Maybe;
|
||||||
struct CycleCollectorResults;
|
struct CycleCollectorResults;
|
||||||
|
|
|
@ -208,7 +208,9 @@ ClientSource::WorkerExecutionReady(WorkerPrivate* aWorkerPrivate)
|
||||||
// execution ready. We can't reliably determine what our storage policy
|
// execution ready. We can't reliably determine what our storage policy
|
||||||
// is before execution ready, unfortunately.
|
// is before execution ready, unfortunately.
|
||||||
if (mController.isSome()) {
|
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
|
// Its safe to store the WorkerPrivate* here because the ClientSource
|
||||||
|
@ -236,34 +238,36 @@ ClientSource::WindowExecutionReady(nsPIDOMWindowInner* aInnerWindow)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIDocument* doc = aInnerWindow->GetExtantDoc();
|
nsIDocument* doc = aInnerWindow->GetExtantDoc();
|
||||||
if (NS_WARN_IF(!doc)) {
|
NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
|
||||||
return 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 client without access to storage should never be controlled by
|
||||||
// a service worker. Check this here in case we were controlled before
|
// a service worker. Check this here in case we were controlled before
|
||||||
// execution ready. We can't reliably determine what our storage policy
|
// execution ready. We can't reliably determine what our storage policy
|
||||||
// is before execution ready, unfortunately.
|
// 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()) {
|
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);
|
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();
|
nsPIDOMWindowOuter* outer = aInnerWindow->GetOuterWindow();
|
||||||
if (NS_WARN_IF(!outer)) {
|
NS_ENSURE_TRUE(outer, NS_ERROR_UNEXPECTED);
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameType frameType = FrameType::Top_level;
|
FrameType frameType = FrameType::Top_level;
|
||||||
if (!outer->IsTopLevelWindow()) {
|
if (!outer->IsTopLevelWindow()) {
|
||||||
|
@ -386,11 +390,19 @@ ClientSource::SetController(const ServiceWorkerDescriptor& aServiceWorker)
|
||||||
// A client without access to storage should never be controlled a
|
// A client without access to storage should never be controlled a
|
||||||
// a service worker. If we are already execution ready with a real
|
// a service worker. If we are already execution ready with a real
|
||||||
// window or worker, then verify assert the storage policy is correct.
|
// 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()) {
|
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);
|
nsContentUtils::StorageAccess::eAllow);
|
||||||
} else if (GetWorkerPrivate()) {
|
} 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) {
|
if (mController.isSome() && mController.ref() == aServiceWorker) {
|
||||||
|
|
|
@ -2074,7 +2074,9 @@ ScriptLoader::FillCompileOptionsForRequest(const AutoJSAPI&jsapi,
|
||||||
aOptions->setMutedErrors(!subsumes);
|
aOptions->setMutedErrors(!subsumes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aRequest->IsModuleRequest()) {
|
if (aRequest->IsModuleRequest()) {
|
||||||
|
aOptions->hideScriptFromDebugger = true;
|
||||||
|
} else {
|
||||||
JSContext* cx = jsapi.cx();
|
JSContext* cx = jsapi.cx();
|
||||||
JS::Rooted<JS::Value> elementVal(cx);
|
JS::Rooted<JS::Value> elementVal(cx);
|
||||||
MOZ_ASSERT(aRequest->mElement);
|
MOZ_ASSERT(aRequest->mElement);
|
||||||
|
@ -2245,6 +2247,10 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
|
||||||
rv = nsJSUtils::InitModuleSourceElement(cx, module, aRequest->mElement);
|
rv = nsJSUtils::InitModuleSourceElement(cx, module, aRequest->mElement);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
moduleScript->SetSourceElementAssociated();
|
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);
|
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.
|
// Helper function to identify protocols and content types not subject to CSP.
|
||||||
bool
|
bool
|
||||||
subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
|
subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
|
||||||
|
|
||||||
|
nsContentPolicyType contentType =
|
||||||
|
nsContentUtils::InternalContentPolicyTypeToExternal(aContentType);
|
||||||
|
|
||||||
// These content types are not subject to CSP content policy checks:
|
// These content types are not subject to CSP content policy checks:
|
||||||
// TYPE_CSP_REPORT -- csp can't block csp reports
|
// TYPE_CSP_REPORT -- csp can't block csp reports
|
||||||
// TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl)
|
// TYPE_REFRESH -- never passed to ShouldLoad (see nsIContentPolicy.idl)
|
||||||
// TYPE_DOCUMENT -- used for frame-ancestors
|
// TYPE_DOCUMENT -- used for frame-ancestors
|
||||||
if (aContentType == nsIContentPolicy::TYPE_CSP_REPORT ||
|
if (contentType == nsIContentPolicy::TYPE_CSP_REPORT ||
|
||||||
aContentType == nsIContentPolicy::TYPE_REFRESH ||
|
contentType == nsIContentPolicy::TYPE_REFRESH ||
|
||||||
aContentType == nsIContentPolicy::TYPE_DOCUMENT) {
|
contentType == nsIContentPolicy::TYPE_DOCUMENT) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,12 +94,16 @@ subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
|
||||||
// hence we use protocol flags to accomplish that, but we also
|
// hence we use protocol flags to accomplish that, but we also
|
||||||
// want resource:, chrome: and moz-icon to be subject to CSP
|
// want resource:, chrome: and moz-icon to be subject to CSP
|
||||||
// (which also use URI_IS_LOCAL_RESOURCE).
|
// (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);
|
rv = aURI->SchemeIs("resource", &match);
|
||||||
if (NS_SUCCEEDED(rv) && match) {
|
if (NS_SUCCEEDED(rv) && match && !isImgOrStyle) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
rv = aURI->SchemeIs("chrome", &match);
|
rv = aURI->SchemeIs("chrome", &match);
|
||||||
if (NS_SUCCEEDED(rv) && match) {
|
if (NS_SUCCEEDED(rv) && match && !isImgOrStyle) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
rv = aURI->SchemeIs("moz-icon", &match);
|
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");
|
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() {
|
add_task(async function cleanup() {
|
||||||
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
|
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,22 @@
|
||||||
// ];
|
// ];
|
||||||
//
|
//
|
||||||
// See createInterfaceMap() below for a complete list of properties.
|
// 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
|
// IMPORTANT: Do not change this list without review from
|
||||||
// a JavaScript Engine peer!
|
// a JavaScript Engine peer!
|
||||||
|
@ -29,8 +45,8 @@ var ecmaGlobals =
|
||||||
{name: "ArrayBuffer", insecureContext: true},
|
{name: "ArrayBuffer", insecureContext: true},
|
||||||
{name: "Atomics", insecureContext: true, disabled: true},
|
{name: "Atomics", insecureContext: true, disabled: true},
|
||||||
{name: "Boolean", insecureContext: true},
|
{name: "Boolean", insecureContext: true},
|
||||||
{name: "ByteLengthQueuingStrategy", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
|
{name: "ByteLengthQueuingStrategy", insecureContext: true, disabled: true},
|
||||||
{name: "CountQueuingStrategy", insecureContext: true, disabled: !SpecialPowers.Cu.getJSTestingFunctions().streamsAreEnabled()},
|
{name: "CountQueuingStrategy", insecureContext: true, disabled: true},
|
||||||
{name: "DataView", insecureContext: true},
|
{name: "DataView", insecureContext: true},
|
||||||
{name: "Date", insecureContext: true},
|
{name: "Date", insecureContext: true},
|
||||||
{name: "Error", insecureContext: true},
|
{name: "Error", insecureContext: true},
|
||||||
|
@ -56,7 +72,7 @@ var ecmaGlobals =
|
||||||
{name: "Promise", insecureContext: true},
|
{name: "Promise", insecureContext: true},
|
||||||
{name: "Proxy", insecureContext: true},
|
{name: "Proxy", insecureContext: true},
|
||||||
{name: "RangeError", 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: "ReferenceError", insecureContext: true},
|
||||||
{name: "Reflect", insecureContext: true},
|
{name: "Reflect", insecureContext: true},
|
||||||
{name: "RegExp", insecureContext: true},
|
{name: "RegExp", insecureContext: true},
|
||||||
|
@ -75,7 +91,7 @@ var ecmaGlobals =
|
||||||
{name: "URIError", insecureContext: true},
|
{name: "URIError", insecureContext: true},
|
||||||
{name: "WeakMap", insecureContext: true},
|
{name: "WeakMap", insecureContext: true},
|
||||||
{name: "WeakSet", 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
|
// IMPORTANT: Do not change the list above without review from
|
||||||
// a JavaScript Engine peer!
|
// a JavaScript Engine peer!
|
||||||
|
@ -723,7 +739,7 @@ var interfaceNamesInGlobalScope =
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
{name: "OfflineAudioContext", insecureContext: true},
|
{name: "OfflineAudioContext", insecureContext: true},
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// 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!
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
{name: "Option", insecureContext: true},
|
{name: "Option", insecureContext: true},
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// 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!
|
// IMPORTANT: Do not change the list above without review from a DOM peer!
|
||||||
|
|
||||||
function createInterfaceMap(isXBLScope) {
|
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 = {};
|
var interfaceMap = {};
|
||||||
|
|
||||||
function addInterfaces(interfaces)
|
function addInterfaces(interfaces)
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
// ];
|
// ];
|
||||||
//
|
//
|
||||||
// See createInterfaceMap() below for a complete list of properties.
|
// 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
|
// IMPORTANT: Do not change this list without review from
|
||||||
// a JavaScript Engine peer!
|
// a JavaScript Engine peer!
|
||||||
|
@ -27,8 +33,8 @@ var ecmaGlobals =
|
||||||
{name: "ArrayBuffer", insecureContext: true},
|
{name: "ArrayBuffer", insecureContext: true},
|
||||||
{name: "Atomics", insecureContext: true, disabled: true},
|
{name: "Atomics", insecureContext: true, disabled: true},
|
||||||
{name: "Boolean", insecureContext: true},
|
{name: "Boolean", insecureContext: true},
|
||||||
{name: "ByteLengthQueuingStrategy", insecureContext: true, optional: true},
|
{name: "ByteLengthQueuingStrategy", insecureContext: true, disabled: true},
|
||||||
{name: "CountQueuingStrategy", insecureContext: true, optional: true},
|
{name: "CountQueuingStrategy", insecureContext: true, disabled: true},
|
||||||
{name: "DataView", insecureContext: true},
|
{name: "DataView", insecureContext: true},
|
||||||
{name: "Date", insecureContext: true},
|
{name: "Date", insecureContext: true},
|
||||||
{name: "Error", insecureContext: true},
|
{name: "Error", insecureContext: true},
|
||||||
|
@ -51,7 +57,7 @@ var ecmaGlobals =
|
||||||
{name: "Promise", insecureContext: true},
|
{name: "Promise", insecureContext: true},
|
||||||
{name: "Proxy", insecureContext: true},
|
{name: "Proxy", insecureContext: true},
|
||||||
{name: "RangeError", insecureContext: true},
|
{name: "RangeError", insecureContext: true},
|
||||||
{name: "ReadableStream", insecureContext: true, optional: true},
|
{name: "ReadableStream", insecureContext: true, disabled: true},
|
||||||
{name: "ReferenceError", insecureContext: true},
|
{name: "ReferenceError", insecureContext: true},
|
||||||
{name: "Reflect", insecureContext: true},
|
{name: "Reflect", insecureContext: true},
|
||||||
{name: "RegExp", insecureContext: true},
|
{name: "RegExp", insecureContext: true},
|
||||||
|
@ -70,7 +76,11 @@ var ecmaGlobals =
|
||||||
{name: "URIError", insecureContext: true},
|
{name: "URIError", insecureContext: true},
|
||||||
{name: "WeakMap", insecureContext: true},
|
{name: "WeakMap", insecureContext: true},
|
||||||
{name: "WeakSet", 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
|
// IMPORTANT: Do not change the list above without review from
|
||||||
// a JavaScript Engine peer!
|
// a JavaScript Engine peer!
|
||||||
|
|
|
@ -94,8 +94,8 @@ txExprLexer::nextIsOperatorToken(Token* aToken)
|
||||||
nsresult
|
nsresult
|
||||||
txExprLexer::parse(const nsAString& aPattern)
|
txExprLexer::parse(const nsAString& aPattern)
|
||||||
{
|
{
|
||||||
iterator start, end;
|
iterator end;
|
||||||
start = aPattern.BeginReading(mPosition);
|
aPattern.BeginReading(mPosition);
|
||||||
aPattern.EndReading(end);
|
aPattern.EndReading(end);
|
||||||
|
|
||||||
//-- initialize previous token, this will automatically get
|
//-- initialize previous token, this will automatically get
|
||||||
|
@ -125,7 +125,7 @@ txExprLexer::parse(const nsAString& aPattern)
|
||||||
// NCName, can get QName or OperatorName;
|
// NCName, can get QName or OperatorName;
|
||||||
// FunctionName, NodeName, and AxisSpecifier may want whitespace,
|
// FunctionName, NodeName, and AxisSpecifier may want whitespace,
|
||||||
// and are dealt with below
|
// and are dealt with below
|
||||||
start = mPosition;
|
iterator start = mPosition;
|
||||||
while (++mPosition < end && XMLUtils::isNCNameChar(*mPosition)) {
|
while (++mPosition < end && XMLUtils::isNCNameChar(*mPosition)) {
|
||||||
/* just go */
|
/* just go */
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ txExprLexer::parse(const nsAString& aPattern)
|
||||||
newToken = new Token(start, mPosition, defType);
|
newToken = new Token(start, mPosition, defType);
|
||||||
}
|
}
|
||||||
else if (isXPathDigit(*mPosition)) {
|
else if (isXPathDigit(*mPosition)) {
|
||||||
start = mPosition;
|
iterator start = mPosition;
|
||||||
while (++mPosition < end && isXPathDigit(*mPosition)) {
|
while (++mPosition < end && isXPathDigit(*mPosition)) {
|
||||||
/* just go */
|
/* just go */
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,8 @@ txExprLexer::parse(const nsAString& aPattern)
|
||||||
break;
|
break;
|
||||||
case S_QUOTE :
|
case S_QUOTE :
|
||||||
case D_QUOTE :
|
case D_QUOTE :
|
||||||
start = mPosition;
|
{
|
||||||
|
iterator start = mPosition;
|
||||||
while (++mPosition < end && *mPosition != *start) {
|
while (++mPosition < end && *mPosition != *start) {
|
||||||
// eat literal
|
// eat literal
|
||||||
}
|
}
|
||||||
|
@ -203,14 +204,15 @@ txExprLexer::parse(const nsAString& aPattern)
|
||||||
}
|
}
|
||||||
newToken = new Token(start + 1, mPosition, Token::LITERAL);
|
newToken = new Token(start + 1, mPosition, Token::LITERAL);
|
||||||
++mPosition;
|
++mPosition;
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
case PERIOD:
|
case PERIOD:
|
||||||
// period can be .., .(DIGITS)+ or ., check next
|
// period can be .., .(DIGITS)+ or ., check next
|
||||||
if (++mPosition == end) {
|
if (++mPosition == end) {
|
||||||
newToken = new Token(mPosition - 1, Token::SELF_NODE);
|
newToken = new Token(mPosition - 1, Token::SELF_NODE);
|
||||||
}
|
}
|
||||||
else if (isXPathDigit(*mPosition)) {
|
else if (isXPathDigit(*mPosition)) {
|
||||||
start = mPosition - 1;
|
iterator start = mPosition - 1;
|
||||||
while (++mPosition < end && isXPathDigit(*mPosition)) {
|
while (++mPosition < end && isXPathDigit(*mPosition)) {
|
||||||
/* just go */
|
/* just go */
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,13 @@ gfxFT2FontBase::GetCharWidth(char aChar, gfxFloat* aWidth)
|
||||||
{
|
{
|
||||||
FT_UInt gid = GetGlyph(aChar);
|
FT_UInt gid = GetGlyph(aChar);
|
||||||
if (gid) {
|
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;
|
return gid;
|
||||||
}
|
}
|
||||||
|
@ -526,35 +532,42 @@ gfxFT2FontBase::GetGlyph(uint32_t unicode, uint32_t variation_selector)
|
||||||
return GetGlyph(unicode);
|
return GetGlyph(unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Fixed
|
bool
|
||||||
gfxFT2FontBase::GetFTGlyphAdvance(uint16_t aGID)
|
gfxFT2FontBase::GetFTGlyphAdvance(uint16_t aGID, int32_t* aAdvance)
|
||||||
{
|
{
|
||||||
gfxFT2LockedFace face(this);
|
gfxFT2LockedFace face(this);
|
||||||
MOZ_ASSERT(face.get());
|
MOZ_ASSERT(face.get());
|
||||||
if (!face.get()) {
|
if (!face.get()) {
|
||||||
// Failed to get the FT_Face? Give up already.
|
// 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();
|
bool hinting = gfxPlatform::GetPlatform()->FontHintingEnabled();
|
||||||
int32_t flags =
|
int32_t flags =
|
||||||
hinting ? FT_LOAD_ADVANCE_ONLY
|
hinting ? FT_LOAD_ADVANCE_ONLY
|
||||||
: FT_LOAD_ADVANCE_ONLY | FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
|
: FT_LOAD_ADVANCE_ONLY | FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
|
||||||
FT_Error ftError = FT_Load_Glyph(face.get(), aGID, flags);
|
FT_Error ftError = FT_Load_Glyph(face.get(), aGID, flags);
|
||||||
MOZ_ASSERT(!ftError);
|
|
||||||
if (ftError != FT_Err_Ok) {
|
if (ftError != FT_Err_Ok) {
|
||||||
// FT_Face was somehow broken/invalid? Don't try to access glyph slot.
|
// 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
|
// 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
|
// dealing with a variation font. (And other fonts would have returned
|
||||||
// applying hinting. Otherwise, prefer hinted width from glyph->advance.x.
|
// earlier, so only variation fonts currently reach here.)
|
||||||
if ((face.get()->face_flags & FT_FACE_FLAG_SCALABLE) &&
|
FT_Fixed advance = face.get()->glyph->linearHoriAdvance;
|
||||||
(!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
|
|
||||||
}
|
|
||||||
|
|
||||||
// If freetype emboldening is being used, and it's not a zero-width glyph,
|
// If freetype emboldening is being used, and it's not a zero-width glyph,
|
||||||
// adjust the advance to account for the increased width.
|
// 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
|
// Round the 16.16 fixed-point value to whole pixels for better consistency
|
||||||
// with how cairo renders the glyphs.
|
// with how cairo renders the glyphs.
|
||||||
advance = (advance + 0x8000) & 0xffff0000u;
|
*aAdvance = (advance + 0x8000) & 0xffff0000u;
|
||||||
|
|
||||||
return advance;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
|
@ -587,7 +600,11 @@ gfxFT2FontBase::GetGlyphWidth(DrawTarget& aDrawTarget, uint16_t aGID)
|
||||||
return width;
|
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);
|
mGlyphWidths->Put(aGID, width);
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
|
|
|
@ -45,7 +45,12 @@ public:
|
||||||
private:
|
private:
|
||||||
uint32_t GetCharExtents(char aChar, cairo_text_extents_t* aExtents);
|
uint32_t GetCharExtents(char aChar, cairo_text_extents_t* aExtents);
|
||||||
uint32_t GetCharWidth(char aChar, gfxFloat* aWidth);
|
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();
|
void InitMetrics();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -701,7 +701,30 @@ MessageChannel::Clear()
|
||||||
if (!Unsound_IsClosed()) {
|
if (!Unsound_IsClosed()) {
|
||||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProtocolName"),
|
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProtocolName"),
|
||||||
nsDependentCString(mName));
|
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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,6 @@ extern JS_FRIEND_DATA(const js::Class* const) FunctionClassPtr;
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
class AutoIdVector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The answer to a successful query as to whether an object is an Array per
|
* 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|).
|
* ES6's internal |IsArray| operation (as exposed by |Array.isArray|).
|
||||||
|
|
|
@ -99,14 +99,14 @@ class GCVector
|
||||||
return vector.infallibleAppend(aBegin, aLength);
|
return vector.infallibleAppend(aBegin, aLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, size_t O, class BP>
|
template<typename U>
|
||||||
MOZ_MUST_USE bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vector.appendAll(aU); }
|
MOZ_MUST_USE bool appendAll(const U& aU) {
|
||||||
template<typename U, size_t O, class BP>
|
return vector.append(aU.begin(), aU.end());
|
||||||
MOZ_MUST_USE bool appendAll(const GCVector<U, O, BP>& aU) {
|
|
||||||
return vector.append(aU.begin(), aU.length());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>
|
template<typename U>
|
||||||
MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd) {
|
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) {
|
MOZ_MUST_USE bool emplaceBack(Args&&... aArgs) {
|
||||||
return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
|
return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
|
||||||
}
|
}
|
||||||
template<typename U, size_t O, class BP>
|
template<typename U>
|
||||||
MOZ_MUST_USE bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vec().appendAll(aU); }
|
MOZ_MUST_USE bool appendAll(const U& 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); }
|
|
||||||
MOZ_MUST_USE bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
|
MOZ_MUST_USE bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
|
||||||
template<typename U>
|
template<typename U>
|
||||||
MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd) {
|
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
|
||||||
|
|
||||||
|
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
|
#endif // js_GCVector_h
|
||||||
|
|
|
@ -895,19 +895,12 @@ class JS_PUBLIC_API(AutoGCRooter)
|
||||||
#if defined(JS_BUILD_BINAST)
|
#if defined(JS_BUILD_BINAST)
|
||||||
BINPARSER = -4, /* js::frontend::BinSource */
|
BINPARSER = -4, /* js::frontend::BinSource */
|
||||||
#endif // defined(JS_BUILD_BINAST)
|
#endif // defined(JS_BUILD_BINAST)
|
||||||
VALVECTOR = -10, /* js::AutoValueVector */
|
|
||||||
IDVECTOR = -11, /* js::AutoIdVector */
|
|
||||||
OBJVECTOR = -14, /* js::AutoObjectVector */
|
|
||||||
IONMASM = -19, /* js::jit::MacroAssembler */
|
IONMASM = -19, /* js::jit::MacroAssembler */
|
||||||
WRAPVECTOR = -20, /* js::AutoWrapperVector */
|
WRAPVECTOR = -20, /* js::AutoWrapperVector */
|
||||||
WRAPPER = -21, /* js::AutoWrapperRooter */
|
WRAPPER = -21, /* js::AutoWrapperRooter */
|
||||||
CUSTOM = -26 /* js::CustomAutoRooter */
|
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:
|
private:
|
||||||
AutoGCRooter ** const stackTop;
|
AutoGCRooter ** const stackTop;
|
||||||
|
|
||||||
|
|
|
@ -475,6 +475,7 @@ const OPAQUE_TYPES: &'static [&'static str] = &[
|
||||||
"mozilla::BufferList",
|
"mozilla::BufferList",
|
||||||
"mozilla::UniquePtr.*",
|
"mozilla::UniquePtr.*",
|
||||||
"JS::Rooted<JS::Auto.*Vector.*>",
|
"JS::Rooted<JS::Auto.*Vector.*>",
|
||||||
|
"JS::Auto.*Vector"
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Types for which we should NEVER generate bindings, even if it is used within
|
/// Types for which we should NEVER generate bindings, even if it is used within
|
||||||
|
|
|
@ -30,9 +30,9 @@ class TwoByteCharsZ;
|
||||||
class UTF8Chars;
|
class UTF8Chars;
|
||||||
class UTF8CharsZ;
|
class UTF8CharsZ;
|
||||||
|
|
||||||
class AutoValueVector;
|
using AutoValueVector = AutoVector<Value>;
|
||||||
class AutoIdVector;
|
using AutoIdVector = AutoVector<jsid>;
|
||||||
class AutoObjectVector;
|
using AutoObjectVector = AutoVector<JSObject*>;
|
||||||
|
|
||||||
using ValueVector = JS::GCVector<JS::Value>;
|
using ValueVector = JS::GCVector<JS::Value>;
|
||||||
using IdVector = JS::GCVector<jsid>;
|
using IdVector = JS::GCVector<jsid>;
|
||||||
|
|
|
@ -529,6 +529,14 @@ WasmIsSupported(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
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
|
static bool
|
||||||
WasmDebuggingIsSupported(JSContext* cx, unsigned argc, Value* vp)
|
WasmDebuggingIsSupported(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
@ -5375,6 +5383,10 @@ gc::ZealModeHelpText),
|
||||||
"wasmIsSupported()",
|
"wasmIsSupported()",
|
||||||
" Returns a boolean indicating whether WebAssembly is supported on the current device."),
|
" 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,
|
JS_FN_HELP("wasmDebuggingIsSupported", WasmDebuggingIsSupported, 0, 0,
|
||||||
"wasmDebuggingIsSupported()",
|
"wasmDebuggingIsSupported()",
|
||||||
" Returns a boolean indicating whether WebAssembly debugging is supported on the current device;\n"
|
" 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))
|
if (!rt->gc.checkAllocatorState<allowGC>(cx, kind))
|
||||||
return nullptr;
|
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));
|
auto str = static_cast<StringAllocT*>(rt->gc.tryNewNurseryString<allowGC>(cx, size, kind));
|
||||||
if (str)
|
if (str)
|
||||||
return str;
|
return str;
|
||||||
|
|
|
@ -2777,18 +2777,21 @@ js::gc::StoreBuffer::SlotsEdge::trace(TenuringTracer& mover) const
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (kind() == ElementKind) {
|
if (kind() == ElementKind) {
|
||||||
int32_t initLen = obj->getDenseInitializedLength();
|
uint32_t initLen = obj->getDenseInitializedLength();
|
||||||
int32_t numShifted = obj->getElementsHeader()->numShiftedElements();
|
uint32_t numShifted = obj->getElementsHeader()->numShiftedElements();
|
||||||
int32_t clampedStart = Min(Max(0, start_ - numShifted), initLen);
|
uint32_t clampedStart = start_;
|
||||||
int32_t clampedEnd = Min(Max(0, start_ + count_ - numShifted), initLen);
|
clampedStart = numShifted < clampedStart ? clampedStart - numShifted : 0;
|
||||||
MOZ_ASSERT(clampedStart >= 0);
|
clampedStart = Min(clampedStart, initLen);
|
||||||
|
uint32_t clampedEnd = start_ + count_;
|
||||||
|
clampedEnd = numShifted < clampedEnd ? clampedEnd - numShifted : 0;
|
||||||
|
clampedEnd = Min(clampedEnd, initLen);
|
||||||
MOZ_ASSERT(clampedStart <= clampedEnd);
|
MOZ_ASSERT(clampedStart <= clampedEnd);
|
||||||
mover.traceSlots(static_cast<HeapSlot*>(obj->getDenseElements() + clampedStart)
|
mover.traceSlots(static_cast<HeapSlot*>(obj->getDenseElements() + clampedStart)
|
||||||
->unsafeUnbarrieredForTracing(), clampedEnd - clampedStart);
|
->unsafeUnbarrieredForTracing(), clampedEnd - clampedStart);
|
||||||
} else {
|
} else {
|
||||||
int32_t start = Min(uint32_t(start_), obj->slotSpan());
|
uint32_t start = Min(start_, obj->slotSpan());
|
||||||
int32_t end = Min(uint32_t(start_) + count_, obj->slotSpan());
|
uint32_t end = Min(start_ + count_, obj->slotSpan());
|
||||||
MOZ_ASSERT(end >= start);
|
MOZ_ASSERT(start <= end);
|
||||||
mover.traceObjectSlots(obj, start, end - start);
|
mover.traceObjectSlots(obj, start, end - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3200,6 +3203,7 @@ js::TenuringTracer::moveToTenured(JSString* src)
|
||||||
|
|
||||||
AllocKind dstKind = src->getAllocKind();
|
AllocKind dstKind = src->getAllocKind();
|
||||||
Zone* zone = src->zone();
|
Zone* zone = src->zone();
|
||||||
|
zone->tenuredStrings++;
|
||||||
|
|
||||||
TenuredCell* t = zone->arenas.allocateFromFreeList(dstKind, Arena::thingSize(dstKind));
|
TenuredCell* t = zone->arenas.allocateFromFreeList(dstKind, Arena::thingSize(dstKind));
|
||||||
if (!t) {
|
if (!t) {
|
||||||
|
|
|
@ -132,9 +132,9 @@ js::Nursery::Nursery(JSRuntime* rt)
|
||||||
, lastCanary_(nullptr)
|
, lastCanary_(nullptr)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
const char* env = getenv("MOZ_ENABLE_NURSERY_STRINGS");
|
const char* env = getenv("MOZ_NURSERY_STRINGS");
|
||||||
if (env && *env)
|
if (env && *env)
|
||||||
canAllocateStrings_ = true;
|
canAllocateStrings_ = (*env == '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -738,21 +738,40 @@ js::Nursery::collect(JS::gcreason::Reason reason)
|
||||||
bool validPromotionRate;
|
bool validPromotionRate;
|
||||||
const float promotionRate = calcPromotionRate(&validPromotionRate);
|
const float promotionRate = calcPromotionRate(&validPromotionRate);
|
||||||
uint32_t pretenureCount = 0;
|
uint32_t pretenureCount = 0;
|
||||||
if (validPromotionRate) {
|
bool shouldPretenure = (validPromotionRate && promotionRate > 0.6) ||
|
||||||
if (promotionRate > 0.8 || IsFullStoreBufferReason(reason)) {
|
IsFullStoreBufferReason(reason);
|
||||||
JSContext* cx = TlsContext.get();
|
|
||||||
for (auto& entry : tenureCounts.entries) {
|
if (shouldPretenure) {
|
||||||
if (entry.count >= 3000) {
|
JSContext* cx = TlsContext.get();
|
||||||
ObjectGroup* group = entry.group;
|
for (auto& entry : tenureCounts.entries) {
|
||||||
if (group->canPreTenure() && group->zone()->group()->canEnterWithoutYielding(cx)) {
|
if (entry.count >= 3000) {
|
||||||
AutoCompartment ac(cx, group);
|
ObjectGroup* group = entry.group;
|
||||||
group->setShouldPreTenure(cx);
|
if (group->canPreTenure() && group->zone()->group()->canEnterWithoutYielding(cx)) {
|
||||||
pretenureCount++;
|
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);
|
endProfile(ProfileKey::Pretenure);
|
||||||
|
|
||||||
// We ignore gcMaxBytes when allocating for minor collection. However, if we
|
// We ignore gcMaxBytes when allocating for minor collection. However, if we
|
||||||
|
@ -1086,7 +1105,7 @@ js::Nursery::setStartPosition()
|
||||||
void
|
void
|
||||||
js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason)
|
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;
|
static const double ShrinkThreshold = 0.01;
|
||||||
unsigned newMaxNurseryChunks;
|
unsigned newMaxNurseryChunks;
|
||||||
|
|
||||||
|
|
|
@ -179,13 +179,13 @@ AutoGCRooter::trace(JSTracer* trc)
|
||||||
}
|
}
|
||||||
|
|
||||||
case WRAPVECTOR: {
|
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
|
* We need to use TraceManuallyBarrieredEdge here because we trace
|
||||||
* wrapper roots in every slice. This is because of some rule-breaking
|
* wrapper roots in every slice. This is because of some rule-breaking
|
||||||
* in RemapAllWrappersForObject; see comment there.
|
* 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");
|
TraceManuallyBarrieredEdge(trc, &p->get(), "js::AutoWrapperVector.vector");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,17 +276,17 @@ class StoreBuffer
|
||||||
const static int ElementKind = 1;
|
const static int ElementKind = 1;
|
||||||
|
|
||||||
uintptr_t objectAndKind_; // NativeObject* | Kind
|
uintptr_t objectAndKind_; // NativeObject* | Kind
|
||||||
int32_t start_;
|
uint32_t start_;
|
||||||
int32_t count_;
|
uint32_t count_;
|
||||||
|
|
||||||
SlotsEdge() : objectAndKind_(0), start_(0), count_(0) {}
|
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)
|
: objectAndKind_(uintptr_t(object) | kind), start_(start), count_(count)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT((uintptr_t(object) & 1) == 0);
|
MOZ_ASSERT((uintptr_t(object) & 1) == 0);
|
||||||
MOZ_ASSERT(kind <= 1);
|
MOZ_ASSERT(kind <= 1);
|
||||||
MOZ_ASSERT(start >= 0);
|
|
||||||
MOZ_ASSERT(count > 0);
|
MOZ_ASSERT(count > 0);
|
||||||
|
MOZ_ASSERT(start + count > start);
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeObject* object() const { return reinterpret_cast<NativeObject*>(objectAndKind_ & ~1); }
|
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
|
// is particularly useful for coalescing a series of increasing or
|
||||||
// decreasing single index writes 0, 1, 2, ..., N into a SlotsEdge
|
// decreasing single index writes 0, 1, 2, ..., N into a SlotsEdge
|
||||||
// range of elements [0, N].
|
// range of elements [0, N].
|
||||||
auto end = start_ + count_ + 1;
|
uint32_t end = start_ + count_ + 1;
|
||||||
auto start = start_ - 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) ||
|
return (start <= other.start_ && other.start_ <= end) ||
|
||||||
(start <= otherEnd && otherEnd <= end);
|
(start <= otherEnd && otherEnd <= end);
|
||||||
}
|
}
|
||||||
|
@ -326,7 +328,7 @@ class StoreBuffer
|
||||||
// overlap.
|
// overlap.
|
||||||
void merge(const SlotsEdge& other) {
|
void merge(const SlotsEdge& other) {
|
||||||
MOZ_ASSERT(overlaps(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_);
|
start_ = Min(start_, other.start_);
|
||||||
count_ = end - start_;
|
count_ = end - start_;
|
||||||
}
|
}
|
||||||
|
@ -416,7 +418,7 @@ class StoreBuffer
|
||||||
void unputValue(JS::Value* vp) { unput(bufferVal, ValueEdge(vp)); }
|
void unputValue(JS::Value* vp) { unput(bufferVal, ValueEdge(vp)); }
|
||||||
void putCell(Cell** cellp) { put(bufferCell, CellPtrEdge(cellp)); }
|
void putCell(Cell** cellp) { put(bufferCell, CellPtrEdge(cellp)); }
|
||||||
void unputCell(Cell** cellp) { unput(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);
|
SlotsEdge edge(obj, kind, start, count);
|
||||||
if (bufferSlot.last_.overlaps(edge))
|
if (bufferSlot.last_.overlaps(edge))
|
||||||
bufferSlot.last_.merge(edge);
|
bufferSlot.last_.merge(edge);
|
||||||
|
|
|
@ -46,6 +46,8 @@ JS::Zone::Zone(JSRuntime* rt, ZoneGroup* group)
|
||||||
usage(&rt->gc.usage),
|
usage(&rt->gc.usage),
|
||||||
threshold(),
|
threshold(),
|
||||||
gcDelayBytes(0),
|
gcDelayBytes(0),
|
||||||
|
tenuredStrings(group, 0),
|
||||||
|
allocNurseryStrings(group, true),
|
||||||
propertyTree_(group, this),
|
propertyTree_(group, this),
|
||||||
baseShapes_(group, this),
|
baseShapes_(group, this),
|
||||||
initialShapes_(group, this),
|
initialShapes_(group, this),
|
||||||
|
|
|
@ -482,6 +482,9 @@ struct Zone : public JS::shadow::Zone,
|
||||||
// the current GC.
|
// the current GC.
|
||||||
js::UnprotectedData<size_t> gcDelayBytes;
|
js::UnprotectedData<size_t> gcDelayBytes;
|
||||||
|
|
||||||
|
js::ZoneGroupData<uint32_t> tenuredStrings;
|
||||||
|
js::ZoneGroupData<bool> allocNurseryStrings;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Shared Shape property tree.
|
// Shared Shape property tree.
|
||||||
js::ZoneGroupData<js::PropertyTree> propertyTree_;
|
js::ZoneGroupData<js::PropertyTree> propertyTree_;
|
||||||
|
|
|
@ -283,9 +283,7 @@ BaselineCacheIRCompiler::emitGuardCompartment()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Address addr(stubAddress(reader.stubOffset()));
|
Address addr(stubAddress(reader.stubOffset()));
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
|
masm.branchTestObjCompartment(Assembler::NotEqual, obj, addr, scratch, failure->label());
|
||||||
masm.loadPtr(Address(scratch, ObjectGroup::offsetOfCompartment()), scratch);
|
|
||||||
masm.branchPtr(Assembler::NotEqual, addr, scratch, failure->label());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,10 +298,7 @@ BaselineCacheIRCompiler::emitGuardAnyClass()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Address testAddr(stubAddress(reader.stubOffset()));
|
Address testAddr(stubAddress(reader.stubOffset()));
|
||||||
|
masm.branchTestObjClass(Assembler::NotEqual, obj, scratch, testAddr, failure->label());
|
||||||
masm.loadObjGroup(obj, scratch);
|
|
||||||
masm.loadPtr(Address(scratch, ObjectGroup::offsetOfClasp()), scratch);
|
|
||||||
masm.branchPtr(Assembler::NotEqual, testAddr, scratch, failure->label());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,9 +523,7 @@ BaselineCacheIRCompiler::emitMegamorphicLoadSlotResult()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// The object must be Native.
|
// The object must be Native.
|
||||||
masm.loadObjClass(obj, scratch3);
|
masm.branchIfNonNativeObj(obj, scratch3, failure->label());
|
||||||
masm.branchTest32(Assembler::NonZero, Address(scratch3, Class::offsetOfFlags()),
|
|
||||||
Imm32(Class::NON_NATIVE), failure->label());
|
|
||||||
|
|
||||||
masm.Push(UndefinedValue());
|
masm.Push(UndefinedValue());
|
||||||
masm.moveStackPtrTo(scratch3.get());
|
masm.moveStackPtrTo(scratch3.get());
|
||||||
|
@ -1176,27 +1169,22 @@ BaselineCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
|
||||||
// per the acquired properties analysis. Only change the group if the
|
// per the acquired properties analysis. Only change the group if the
|
||||||
// old group still has a newScript. This only applies to PlainObjects.
|
// old group still has a newScript. This only applies to PlainObjects.
|
||||||
Label noGroupChange;
|
Label noGroupChange;
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch1);
|
masm.branchIfObjGroupHasNoAddendum(obj, scratch1, &noGroupChange);
|
||||||
masm.branchPtr(Assembler::Equal,
|
|
||||||
Address(scratch1, ObjectGroup::offsetOfAddendum()),
|
|
||||||
ImmWord(0),
|
|
||||||
&noGroupChange);
|
|
||||||
|
|
||||||
// Reload the new group from the cache.
|
// Update the object's group.
|
||||||
masm.loadPtr(newGroupAddr, scratch1);
|
masm.loadPtr(newGroupAddr, scratch1);
|
||||||
|
masm.storeObjGroup(scratch1, obj, [](MacroAssembler& masm, const Address& addr) {
|
||||||
Address groupAddr(obj, JSObject::offsetOfGroup());
|
EmitPreBarrier(masm, addr, MIRType::ObjectGroup);
|
||||||
EmitPreBarrier(masm, groupAddr, MIRType::ObjectGroup);
|
});
|
||||||
masm.storePtr(scratch1, groupAddr);
|
|
||||||
|
|
||||||
masm.bind(&noGroupChange);
|
masm.bind(&noGroupChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the object's shape.
|
// Update the object's shape.
|
||||||
Address shapeAddr(obj, ShapedObject::offsetOfShape());
|
|
||||||
masm.loadPtr(newShapeAddr, scratch1);
|
masm.loadPtr(newShapeAddr, scratch1);
|
||||||
EmitPreBarrier(masm, shapeAddr, MIRType::Shape);
|
masm.storeObjShape(scratch1, obj, [](MacroAssembler& masm, const Address& addr) {
|
||||||
masm.storePtr(scratch1, shapeAddr);
|
EmitPreBarrier(masm, addr, MIRType::Shape);
|
||||||
|
});
|
||||||
|
|
||||||
// Perform the store. No pre-barrier required since this is a new
|
// Perform the store. No pre-barrier required since this is a new
|
||||||
// initialization.
|
// initialization.
|
||||||
|
|
|
@ -426,11 +426,10 @@ ICTypeUpdate_ObjectGroup::Compiler::generateStubCode(MacroAssembler& masm)
|
||||||
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||||
|
|
||||||
// Guard on the object's ObjectGroup.
|
// Guard on the object's ObjectGroup.
|
||||||
Register obj = masm.extractObject(R0, R1.scratchReg());
|
Register scratch = R1.scratchReg();
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), R1.scratchReg());
|
Register obj = masm.extractObject(R0, scratch);
|
||||||
|
|
||||||
Address expectedGroup(ICStubReg, ICTypeUpdate_ObjectGroup::offsetOfGroup());
|
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.
|
// Group matches, load true into R1.scratchReg() and return.
|
||||||
masm.mov(ImmWord(1), R1.scratchReg());
|
masm.mov(ImmWord(1), R1.scratchReg());
|
||||||
|
@ -775,9 +774,7 @@ LoadTypedThingLength(MacroAssembler& masm, TypedThingLayout layout, Register obj
|
||||||
break;
|
break;
|
||||||
case Layout_OutlineTypedObject:
|
case Layout_OutlineTypedObject:
|
||||||
case Layout_InlineTypedObject:
|
case Layout_InlineTypedObject:
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), result);
|
masm.loadTypedObjectLength(obj, result);
|
||||||
masm.loadPtr(Address(result, ObjectGroup::offsetOfAddendum()), result);
|
|
||||||
masm.unboxInt32(Address(result, ArrayTypeDescr::offsetOfLength()), result);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
|
@ -3432,11 +3429,9 @@ ICCall_ClassHook::Compiler::generateStubCode(MacroAssembler& masm)
|
||||||
// Ensure the callee's class matches the one in this stub.
|
// Ensure the callee's class matches the one in this stub.
|
||||||
Register callee = masm.extractObject(R1, ExtractTemp0);
|
Register callee = masm.extractObject(R1, ExtractTemp0);
|
||||||
Register scratch = regs.takeAny();
|
Register scratch = regs.takeAny();
|
||||||
masm.loadObjClass(callee, scratch);
|
masm.branchTestObjClass(Assembler::NotEqual, callee, scratch,
|
||||||
masm.branchPtr(Assembler::NotEqual,
|
Address(ICStubReg, ICCall_ClassHook::offsetOfClass()),
|
||||||
Address(ICStubReg, ICCall_ClassHook::offsetOfClass()),
|
&failure);
|
||||||
scratch, &failure);
|
|
||||||
|
|
||||||
regs.add(R1);
|
regs.add(R1);
|
||||||
regs.takeUnchecked(callee);
|
regs.takeUnchecked(callee);
|
||||||
|
|
||||||
|
|
|
@ -1472,9 +1472,7 @@ CacheIRCompiler::emitGuardIsNativeObject()
|
||||||
if (!addFailurePath(&failure))
|
if (!addFailurePath(&failure))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
masm.loadObjClass(obj, scratch);
|
masm.branchIfNonNativeObj(obj, scratch, failure->label());
|
||||||
masm.branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()),
|
|
||||||
Imm32(Class::NON_NATIVE), failure->label());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2668,9 +2666,7 @@ CacheIRCompiler::emitMegamorphicLoadSlotByValueResult()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// The object must be Native.
|
// The object must be Native.
|
||||||
masm.loadObjClass(obj, scratch);
|
masm.branchIfNonNativeObj(obj, scratch, failure->label());
|
||||||
masm.branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()),
|
|
||||||
Imm32(Class::NON_NATIVE), failure->label());
|
|
||||||
|
|
||||||
// idVal will be in vp[0], result will be stored in vp[1].
|
// idVal will be in vp[0], result will be stored in vp[1].
|
||||||
masm.reserveStack(sizeof(Value));
|
masm.reserveStack(sizeof(Value));
|
||||||
|
|
|
@ -959,8 +959,7 @@ CodeGenerator::visitFunctionDispatch(LFunctionDispatch* lir)
|
||||||
MOZ_ASSERT(i < mir->numCases());
|
MOZ_ASSERT(i < mir->numCases());
|
||||||
LBlock* target = skipTrivialBlocks(mir->getCaseBlock(i))->lir();
|
LBlock* target = skipTrivialBlocks(mir->getCaseBlock(i))->lir();
|
||||||
if (ObjectGroup* funcGroup = mir->getCaseObjectGroup(i)) {
|
if (ObjectGroup* funcGroup = mir->getCaseObjectGroup(i)) {
|
||||||
masm.branchPtr(Assembler::Equal, Address(input, JSObject::offsetOfGroup()),
|
masm.branchTestObjGroup(Assembler::Equal, input, funcGroup, target->label());
|
||||||
ImmGCPtr(funcGroup), target->label());
|
|
||||||
} else {
|
} else {
|
||||||
JSFunction* func = mir->getCase(i);
|
JSFunction* func = mir->getCase(i);
|
||||||
masm.branchPtr(Assembler::Equal, input, ImmGCPtr(func), target->label());
|
masm.branchPtr(Assembler::Equal, input, ImmGCPtr(func), target->label());
|
||||||
|
@ -979,7 +978,7 @@ CodeGenerator::visitObjectGroupDispatch(LObjectGroupDispatch* lir)
|
||||||
Register temp = ToRegister(lir->temp());
|
Register temp = ToRegister(lir->temp());
|
||||||
|
|
||||||
// Load the incoming ObjectGroup in temp.
|
// Load the incoming ObjectGroup in temp.
|
||||||
masm.loadPtr(Address(input, JSObject::offsetOfGroup()), temp);
|
masm.loadObjGroupUnsafe(input, temp);
|
||||||
|
|
||||||
// Compare ObjectGroups.
|
// Compare ObjectGroups.
|
||||||
MacroAssembler::BranchGCPtr lastBranch;
|
MacroAssembler::BranchGCPtr lastBranch;
|
||||||
|
@ -2518,8 +2517,7 @@ CodeGenerator::visitRegExpPrototypeOptimizable(LRegExpPrototypeOptimizable* ins)
|
||||||
RegExpCompartment::offsetOfOptimizableRegExpPrototypeShape();
|
RegExpCompartment::offsetOfOptimizableRegExpPrototypeShape();
|
||||||
masm.loadPtr(Address(temp, offset), temp);
|
masm.loadPtr(Address(temp, offset), temp);
|
||||||
|
|
||||||
masm.loadPtr(Address(object, ShapedObject::offsetOfShape()), output);
|
masm.branchTestObjShape(Assembler::NotEqual, object, temp, ool->entry());
|
||||||
masm.branchPtr(Assembler::NotEqual, output, temp, ool->entry());
|
|
||||||
masm.move32(Imm32(0x1), output);
|
masm.move32(Imm32(0x1), output);
|
||||||
|
|
||||||
masm.bind(ool->rejoin());
|
masm.bind(ool->rejoin());
|
||||||
|
@ -2579,8 +2577,7 @@ CodeGenerator::visitRegExpInstanceOptimizable(LRegExpInstanceOptimizable* ins)
|
||||||
RegExpCompartment::offsetOfOptimizableRegExpInstanceShape();
|
RegExpCompartment::offsetOfOptimizableRegExpInstanceShape();
|
||||||
masm.loadPtr(Address(temp, offset), temp);
|
masm.loadPtr(Address(temp, offset), temp);
|
||||||
|
|
||||||
masm.loadPtr(Address(object, ShapedObject::offsetOfShape()), output);
|
masm.branchTestObjShape(Assembler::NotEqual, object, temp, ool->entry());
|
||||||
masm.branchPtr(Assembler::NotEqual, output, temp, ool->entry());
|
|
||||||
masm.move32(Imm32(0x1), output);
|
masm.move32(Imm32(0x1), output);
|
||||||
|
|
||||||
masm.bind(ool->rejoin());
|
masm.bind(ool->rejoin());
|
||||||
|
@ -3716,11 +3713,8 @@ CodeGenerator::visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite* lir)
|
||||||
OutOfLineCode* ool = oolCallVM(CopyElementsForWriteInfo, lir,
|
OutOfLineCode* ool = oolCallVM(CopyElementsForWriteInfo, lir,
|
||||||
ArgList(object), StoreNothing());
|
ArgList(object), StoreNothing());
|
||||||
|
|
||||||
if (lir->mir()->checkNative()) {
|
if (lir->mir()->checkNative())
|
||||||
masm.loadObjClass(object, temp);
|
masm.branchIfNonNativeObj(object, temp, ool->rejoin());
|
||||||
masm.branchTest32(Assembler::NonZero, Address(temp, Class::offsetOfFlags()),
|
|
||||||
Imm32(Class::NON_NATIVE), ool->rejoin());
|
|
||||||
}
|
|
||||||
|
|
||||||
masm.loadPtr(Address(object, NativeObject::offsetOfElements()), temp);
|
masm.loadPtr(Address(object, NativeObject::offsetOfElements()), temp);
|
||||||
masm.branchTest32(Assembler::NonZero,
|
masm.branchTest32(Assembler::NonZero,
|
||||||
|
@ -4302,17 +4296,8 @@ LoadDOMPrivate(MacroAssembler& masm, Register obj, Register priv, DOMObjectKind
|
||||||
masm.branchTestObjectIsProxy(true, obj, priv, &isProxy);
|
masm.branchTestObjectIsProxy(true, obj, priv, &isProxy);
|
||||||
|
|
||||||
if (kind != DOMObjectKind::Proxy) {
|
if (kind != DOMObjectKind::Proxy) {
|
||||||
#ifdef DEBUG
|
|
||||||
// If it's a native object, the value must be in a fixed slot.
|
// If it's a native object, the value must be in a fixed slot.
|
||||||
Label hasFixedSlots;
|
masm.debugAssertObjHasFixedSlots(obj, priv);
|
||||||
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.loadPrivate(Address(obj, NativeObject::getFixedSlotOffset(0)), priv);
|
masm.loadPrivate(Address(obj, NativeObject::getFixedSlotOffset(0)), priv);
|
||||||
if (kind == DOMObjectKind::Unknown)
|
if (kind == DOMObjectKind::Unknown)
|
||||||
masm.jump(&done);
|
masm.jump(&done);
|
||||||
|
@ -4888,10 +4873,10 @@ CodeGenerator::emitApplyGeneric(T* apply)
|
||||||
|
|
||||||
// Unless already known, guard that calleereg is actually a function object.
|
// Unless already known, guard that calleereg is actually a function object.
|
||||||
if (!apply->hasSingleTarget()) {
|
if (!apply->hasSingleTarget()) {
|
||||||
masm.loadObjClass(calleereg, objreg);
|
Label bail;
|
||||||
|
masm.branchTestObjClass(Assembler::NotEqual, calleereg, objreg, &JSFunction::class_,
|
||||||
ImmPtr ptr = ImmPtr(&JSFunction::class_);
|
&bail);
|
||||||
bailoutCmpPtr(Assembler::NotEqual, objreg, ptr, apply->snapshot());
|
bailoutFrom(&bail, apply->snapshot());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the arguments of the current function.
|
// Copy the arguments of the current function.
|
||||||
|
@ -6378,38 +6363,7 @@ CodeGenerator::visitSimdUnbox(LSimdUnbox* lir)
|
||||||
Register temp = ToRegister(lir->temp());
|
Register temp = ToRegister(lir->temp());
|
||||||
Label bail;
|
Label bail;
|
||||||
|
|
||||||
// obj->group()
|
masm.branchIfNotSimdObject(object, temp, lir->mir()->simdType(), &bail);
|
||||||
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);
|
|
||||||
|
|
||||||
// Load the value from the data of the InlineTypedObject.
|
// Load the value from the data of the InlineTypedObject.
|
||||||
Address objectData(object, InlineTypedObject::offsetOfDataStart());
|
Address objectData(object, InlineTypedObject::offsetOfDataStart());
|
||||||
|
@ -7095,9 +7049,7 @@ CodeGenerator::visitTypedObjectDescr(LTypedObjectDescr* lir)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(lir->object());
|
Register obj = ToRegister(lir->object());
|
||||||
Register out = ToRegister(lir->output());
|
Register out = ToRegister(lir->output());
|
||||||
|
masm.loadTypedObjectDescr(obj, out);
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), out);
|
|
||||||
masm.loadPtr(Address(out, ObjectGroup::offsetOfAddendum()), out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -7110,9 +7062,7 @@ CodeGenerator::visitTypedObjectElements(LTypedObjectElements* lir)
|
||||||
masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out);
|
masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out);
|
||||||
} else {
|
} else {
|
||||||
Label inlineObject, done;
|
Label inlineObject, done;
|
||||||
masm.loadObjClass(obj, out);
|
masm.branchIfInlineTypedObject(obj, out, &inlineObject);
|
||||||
masm.branchPtr(Assembler::Equal, out, ImmPtr(&InlineOpaqueTypedObject::class_), &inlineObject);
|
|
||||||
masm.branchPtr(Assembler::Equal, out, ImmPtr(&InlineTransparentTypedObject::class_), &inlineObject);
|
|
||||||
|
|
||||||
masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out);
|
masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out);
|
||||||
masm.jump(&done);
|
masm.jump(&done);
|
||||||
|
@ -7135,9 +7085,7 @@ CodeGenerator::visitSetTypedObjectOffset(LSetTypedObjectOffset* lir)
|
||||||
masm.loadPtr(Address(object, OutlineTypedObject::offsetOfOwner()), temp0);
|
masm.loadPtr(Address(object, OutlineTypedObject::offsetOfOwner()), temp0);
|
||||||
|
|
||||||
Label inlineObject, done;
|
Label inlineObject, done;
|
||||||
masm.loadObjClass(temp0, temp1);
|
masm.branchIfInlineTypedObject(temp0, temp1, &inlineObject);
|
||||||
masm.branchPtr(Assembler::Equal, temp1, ImmPtr(&InlineOpaqueTypedObject::class_), &inlineObject);
|
|
||||||
masm.branchPtr(Assembler::Equal, temp1, ImmPtr(&InlineTransparentTypedObject::class_), &inlineObject);
|
|
||||||
|
|
||||||
masm.loadPrivate(Address(temp0, ArrayBufferObject::offsetOfDataSlot()), temp0);
|
masm.loadPrivate(Address(temp0, ArrayBufferObject::offsetOfDataSlot()), temp0);
|
||||||
masm.jump(&done);
|
masm.jump(&done);
|
||||||
|
@ -9323,8 +9271,7 @@ CodeGenerator::visitConvertUnboxedObjectToNative(LConvertUnboxedObjectToNative*
|
||||||
OutOfLineCode* ool = oolCallVM(ConvertUnboxedPlainObjectToNativeInfo,
|
OutOfLineCode* ool = oolCallVM(ConvertUnboxedPlainObjectToNativeInfo,
|
||||||
lir, ArgList(object), StoreNothing());
|
lir, ArgList(object), StoreNothing());
|
||||||
|
|
||||||
masm.branchPtr(Assembler::Equal, Address(object, JSObject::offsetOfGroup()),
|
masm.branchTestObjGroup(Assembler::Equal, object, lir->mir()->group(), ool->entry());
|
||||||
ImmGCPtr(lir->mir()->group()), ool->entry());
|
|
||||||
masm.bind(ool->rejoin());
|
masm.bind(ool->rejoin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9521,8 +9468,7 @@ CodeGenerator::visitArraySlice(LArraySlice* lir)
|
||||||
masm.createGCObject(temp1, temp2, lir->mir()->templateObj(), lir->mir()->initialHeap(), &fail);
|
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.
|
// Fixup the group of the result in case it doesn't match the template object.
|
||||||
masm.loadPtr(Address(object, JSObject::offsetOfGroup()), temp2);
|
masm.copyObjGroupNoPreBarrier(object, temp1, temp2);
|
||||||
masm.storePtr(temp2, Address(temp1, JSObject::offsetOfGroup()));
|
|
||||||
|
|
||||||
masm.jump(&call);
|
masm.jump(&call);
|
||||||
{
|
{
|
||||||
|
@ -12140,7 +12086,7 @@ void
|
||||||
CodeGenerator::emitIsCallableOrConstructor(Register object, Register output, Label* failure)
|
CodeGenerator::emitIsCallableOrConstructor(Register object, Register output, Label* failure)
|
||||||
{
|
{
|
||||||
Label notFunction, hasCOps, done;
|
Label notFunction, hasCOps, done;
|
||||||
masm.loadObjClass(object, output);
|
masm.loadObjClassUnsafe(object, output);
|
||||||
|
|
||||||
// Just skim proxies off. Their notion of isCallable()/isConstructor() is
|
// Just skim proxies off. Their notion of isCallable()/isConstructor() is
|
||||||
// more complicated.
|
// more complicated.
|
||||||
|
@ -12319,7 +12265,7 @@ static void
|
||||||
EmitObjectIsArray(MacroAssembler& masm, OutOfLineCode* ool, Register obj, Register output,
|
EmitObjectIsArray(MacroAssembler& masm, OutOfLineCode* ool, Register obj, Register output,
|
||||||
Label* notArray = nullptr)
|
Label* notArray = nullptr)
|
||||||
{
|
{
|
||||||
masm.loadObjClass(obj, output);
|
masm.loadObjClassUnsafe(obj, output);
|
||||||
|
|
||||||
Label isArray;
|
Label isArray;
|
||||||
masm.branchPtr(Assembler::Equal, output, ImmPtr(&ArrayObject::class_), &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* firstTypedArrayClass = TypedArrayObject::classForType(Scalar::Int8);
|
||||||
const Class* lastTypedArrayClass = TypedArrayObject::classForType(Scalar::Uint8Clamped);
|
const Class* lastTypedArrayClass = TypedArrayObject::classForType(Scalar::Uint8Clamped);
|
||||||
|
|
||||||
masm.loadObjClass(object, output);
|
masm.loadObjClassUnsafe(object, output);
|
||||||
masm.branchPtr(Assembler::Below, output, ImmPtr(firstTypedArrayClass), ¬TypedArray);
|
masm.branchPtr(Assembler::Below, output, ImmPtr(firstTypedArrayClass), ¬TypedArray);
|
||||||
masm.branchPtr(Assembler::Above, output, ImmPtr(lastTypedArrayClass), ¬TypedArray);
|
masm.branchPtr(Assembler::Above, output, ImmPtr(lastTypedArrayClass), ¬TypedArray);
|
||||||
|
|
||||||
|
@ -12434,7 +12380,7 @@ CodeGenerator::visitHasClass(LHasClass* ins)
|
||||||
Register lhs = ToRegister(ins->lhs());
|
Register lhs = ToRegister(ins->lhs());
|
||||||
Register output = ToRegister(ins->output());
|
Register output = ToRegister(ins->output());
|
||||||
|
|
||||||
masm.loadObjClass(lhs, output);
|
masm.loadObjClassUnsafe(lhs, output);
|
||||||
masm.cmpPtrSet(Assembler::Equal, output, ImmPtr(ins->mir()->getClass()), output);
|
masm.cmpPtrSet(Assembler::Equal, output, ImmPtr(ins->mir()->getClass()), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,9 @@ CompileZone::addressOfStringNurseryCurrentEnd()
|
||||||
bool
|
bool
|
||||||
CompileZone::canNurseryAllocateStrings()
|
CompileZone::canNurseryAllocateStrings()
|
||||||
{
|
{
|
||||||
return nurseryExists() && zone()->group()->nursery().canAllocateStrings();
|
return nurseryExists() &&
|
||||||
|
zone()->group()->nursery().canAllocateStrings() &&
|
||||||
|
zone()->allocNurseryStrings;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -2229,6 +2229,12 @@ IsRegExpHoistable(MIRGenerator* mir, MDefinition* regexp, MDefinitionVector& wor
|
||||||
bool
|
bool
|
||||||
jit::MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph)
|
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());
|
MDefinitionVector worklist(graph.alloc());
|
||||||
|
|
||||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||||
|
|
|
@ -699,9 +699,8 @@ IonCacheIRCompiler::emitGuardCompartment()
|
||||||
if (!addFailurePath(&failure))
|
if (!addFailurePath(&failure))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
|
masm.branchTestObjCompartment(Assembler::NotEqual, obj, compartment, scratch,
|
||||||
masm.loadPtr(Address(scratch, ObjectGroup::offsetOfCompartment()), scratch);
|
failure->label());
|
||||||
masm.branchPtr(Assembler::NotEqual, scratch, ImmPtr(compartment), failure->label());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,9 +934,7 @@ IonCacheIRCompiler::emitMegamorphicLoadSlotResult()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// The object must be Native.
|
// The object must be Native.
|
||||||
masm.loadObjClass(obj, scratch3);
|
masm.branchIfNonNativeObj(obj, scratch3, failure->label());
|
||||||
masm.branchTest32(Assembler::NonZero, Address(scratch3, Class::offsetOfFlags()),
|
|
||||||
Imm32(Class::NON_NATIVE), failure->label());
|
|
||||||
|
|
||||||
masm.Push(UndefinedValue());
|
masm.Push(UndefinedValue());
|
||||||
masm.moveStackPtrTo(scratch3.get());
|
masm.moveStackPtrTo(scratch3.get());
|
||||||
|
@ -1652,23 +1649,20 @@ IonCacheIRCompiler::emitAddAndStoreSlotShared(CacheOp op)
|
||||||
// per the acquired properties analysis. Only change the group if the
|
// per the acquired properties analysis. Only change the group if the
|
||||||
// old group still has a newScript. This only applies to PlainObjects.
|
// old group still has a newScript. This only applies to PlainObjects.
|
||||||
Label noGroupChange;
|
Label noGroupChange;
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch1);
|
masm.branchIfObjGroupHasNoAddendum(obj, scratch1, &noGroupChange);
|
||||||
masm.branchPtr(Assembler::Equal,
|
|
||||||
Address(scratch1, ObjectGroup::offsetOfAddendum()),
|
|
||||||
ImmWord(0),
|
|
||||||
&noGroupChange);
|
|
||||||
|
|
||||||
Address groupAddr(obj, JSObject::offsetOfGroup());
|
// Update the object's group.
|
||||||
EmitPreBarrier(masm, groupAddr, MIRType::ObjectGroup);
|
masm.storeObjGroup(newGroup, obj, [](MacroAssembler& masm, const Address& addr) {
|
||||||
masm.storePtr(ImmGCPtr(newGroup), groupAddr);
|
EmitPreBarrier(masm, addr, MIRType::ObjectGroup);
|
||||||
|
});
|
||||||
|
|
||||||
masm.bind(&noGroupChange);
|
masm.bind(&noGroupChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the object's shape.
|
// Update the object's shape.
|
||||||
Address shapeAddr(obj, ShapedObject::offsetOfShape());
|
masm.storeObjShape(newShape, obj, [](MacroAssembler& masm, const Address& addr) {
|
||||||
EmitPreBarrier(masm, shapeAddr, MIRType::Shape);
|
EmitPreBarrier(masm, addr, MIRType::Shape);
|
||||||
masm.storePtr(ImmGCPtr(newShape), shapeAddr);
|
});
|
||||||
|
|
||||||
// Perform the store. No pre-barrier required since this is a new
|
// Perform the store. No pre-barrier required since this is a new
|
||||||
// initialization.
|
// initialization.
|
||||||
|
|
|
@ -621,6 +621,11 @@ class JitCompartment
|
||||||
|
|
||||||
void sweep(JSCompartment* compartment);
|
void sweep(JSCompartment* compartment);
|
||||||
|
|
||||||
|
void discardStubs() {
|
||||||
|
for (ReadBarrieredJitCode& stubRef : stubs_)
|
||||||
|
stubRef = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
JitCode* stringConcatStubNoBarrier(uint32_t* requiredBarriersOut) const {
|
JitCode* stringConcatStubNoBarrier(uint32_t* requiredBarriersOut) const {
|
||||||
return getStubNoBarrier(StringConcat, requiredBarriersOut);
|
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
|
// The branches to out-of-line code here implement a conservative version
|
||||||
// of the JSObject::isWrapper test performed in EmulatesUndefined.
|
// of the JSObject::isWrapper test performed in EmulatesUndefined.
|
||||||
loadObjClass(objReg, scratch);
|
loadObjClassUnsafe(objReg, scratch);
|
||||||
|
|
||||||
branchTestClassIsProxy(true, scratch, slowCheck);
|
branchTestClassIsProxy(true, scratch, slowCheck);
|
||||||
|
|
||||||
|
@ -492,13 +492,22 @@ MacroAssembler::branchFunctionKind(Condition cond, JSFunction::FunctionKind kind
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MacroAssembler::branchTestObjClass(Condition cond, Register obj, Register scratch, const js::Class* clasp,
|
MacroAssembler::branchTestObjClass(Condition cond, Register obj, Register scratch,
|
||||||
Label* label)
|
const js::Class* clasp, Label* label)
|
||||||
{
|
{
|
||||||
loadObjGroup(obj, scratch);
|
loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
|
||||||
branchPtr(cond, Address(scratch, ObjectGroup::offsetOfClasp()), ImmPtr(clasp), label);
|
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
|
void
|
||||||
MacroAssembler::branchTestObjShape(Condition cond, Register obj, const Shape* shape, Label* label)
|
MacroAssembler::branchTestObjShape(Condition cond, Register obj, const Shape* shape, Label* label)
|
||||||
{
|
{
|
||||||
|
@ -512,7 +521,8 @@ MacroAssembler::branchTestObjShape(Condition cond, Register obj, Register shape,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), ImmGCPtr(group), label);
|
||||||
}
|
}
|
||||||
|
@ -534,7 +544,7 @@ MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp, Label* label)
|
||||||
void
|
void
|
||||||
MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label)
|
MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label)
|
||||||
{
|
{
|
||||||
loadObjClass(object, scratch);
|
loadObjClassUnsafe(object, scratch);
|
||||||
branchTestClassIsProxy(proxy, scratch, label);
|
branchTestClassIsProxy(proxy, scratch, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,6 +743,44 @@ MacroAssembler::reserveStack(uint32_t amount)
|
||||||
}
|
}
|
||||||
#endif // !JS_CODEGEN_ARM64
|
#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>
|
template <typename T>
|
||||||
void
|
void
|
||||||
MacroAssembler::storeObjectOrNull(Register src, const T& dest)
|
MacroAssembler::storeObjectOrNull(Register src, const T& dest)
|
||||||
|
|
|
@ -1751,7 +1751,7 @@ void
|
||||||
MacroAssembler::typeOfObject(Register obj, Register scratch, Label* slow,
|
MacroAssembler::typeOfObject(Register obj, Register scratch, Label* slow,
|
||||||
Label* isObject, Label* isCallable, Label* isUndefined)
|
Label* isObject, Label* isCallable, Label* isUndefined)
|
||||||
{
|
{
|
||||||
loadObjClass(obj, scratch);
|
loadObjClassUnsafe(obj, scratch);
|
||||||
|
|
||||||
// Proxies can emulate undefined and have complex isCallable behavior.
|
// Proxies can emulate undefined and have complex isCallable behavior.
|
||||||
branchTestClassIsProxy(true, scratch, slow);
|
branchTestClassIsProxy(true, scratch, slow);
|
||||||
|
@ -3200,6 +3200,128 @@ MacroAssembler::branchIfNotInterpretedConstructor(Register fun, Register scratch
|
||||||
branchTest32(Assembler::Zero, scratch, Imm32(bits), label);
|
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
|
void
|
||||||
MacroAssembler::maybeBranchTestType(MIRType type, MDefinition* maybeDef, Register tag, Label* label)
|
MacroAssembler::maybeBranchTestType(MIRType type, MDefinition* maybeDef, Register tag, Label* label)
|
||||||
{
|
{
|
||||||
|
@ -3570,6 +3692,21 @@ MacroAssembler::debugAssertIsObject(const ValueOperand& val)
|
||||||
#endif
|
#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
|
void
|
||||||
MacroAssembler::spectreMaskIndex(Register index, Register length, Register output)
|
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,
|
inline void branchIfObjectEmulatesUndefined(Register objReg, Register scratch, Label* slowCheck,
|
||||||
Label* label);
|
Label* label);
|
||||||
|
|
||||||
inline void branchTestObjClass(Condition cond, Register obj, Register scratch, const js::Class* clasp,
|
inline void branchTestObjClass(Condition cond, Register obj, Register scratch,
|
||||||
Label* label);
|
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, const Shape* shape, Label* label);
|
||||||
inline void branchTestObjShape(Condition cond, Register obj, Register 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);
|
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 branchTestClassIsProxy(bool proxy, Register clasp, Label* label);
|
||||||
|
|
||||||
inline void branchTestObjectIsProxy(bool proxy, Register object, Register scratch, 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,
|
inline void branchTestProxyHandlerFamily(Condition cond, Register proxy, Register scratch,
|
||||||
const void* handlerp, Label* label);
|
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
|
// Emit type case branch on tag matching if the type tag in the definition
|
||||||
// might actually be that type.
|
// might actually be that type.
|
||||||
void maybeBranchTestType(MIRType type, MDefinition* maybeDef, Register tag, Label* label);
|
void maybeBranchTestType(MIRType type, MDefinition* maybeDef, Register tag, Label* label);
|
||||||
|
@ -1951,21 +1975,25 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||||
Label* label);
|
Label* label);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void loadObjShape(Register objReg, Register dest) {
|
// Unsafe here means the caller is responsible for Spectre mitigations if
|
||||||
loadPtr(Address(objReg, ShapedObject::offsetOfShape()), dest);
|
// 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) {
|
void loadObjClassUnsafe(Register obj, Register dest) {
|
||||||
loadPtr(Address(objReg, JSObject::offsetOfGroup()), dest);
|
loadPtr(Address(obj, 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);
|
|
||||||
loadPtr(Address(dest, ObjectGroup::offsetOfClasp()), 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) {
|
void loadObjPrivate(Register obj, uint32_t nfixed, Register dest) {
|
||||||
loadPtr(Address(obj, NativeObject::getPrivateDataOffset(nfixed)), dest);
|
loadPtr(Address(obj, NativeObject::getPrivateDataOffset(nfixed)), dest);
|
||||||
}
|
}
|
||||||
|
@ -2192,6 +2220,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||||
const ConstantOrRegister& value, Label* failure);
|
const ConstantOrRegister& value, Label* failure);
|
||||||
|
|
||||||
void debugAssertIsObject(const ValueOperand& val);
|
void debugAssertIsObject(const ValueOperand& val);
|
||||||
|
void debugAssertObjHasFixedSlots(Register obj, Register scratch);
|
||||||
|
|
||||||
using MacroAssemblerSpecific::extractTag;
|
using MacroAssemblerSpecific::extractTag;
|
||||||
Register extractTag(const TypedOrValueRegister& reg, Register scratch) {
|
Register extractTag(const TypedOrValueRegister& reg, Register scratch) {
|
||||||
|
|
|
@ -2540,10 +2540,9 @@ ICTypeMonitor_ObjectGroup::Compiler::generateStubCode(MacroAssembler& masm)
|
||||||
|
|
||||||
// Guard on the object's ObjectGroup.
|
// Guard on the object's ObjectGroup.
|
||||||
Register obj = masm.extractObject(R0, ExtractTemp0);
|
Register obj = masm.extractObject(R0, ExtractTemp0);
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), R1.scratchReg());
|
|
||||||
|
|
||||||
Address expectedGroup(ICStubReg, ICTypeMonitor_ObjectGroup::offsetOfGroup());
|
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);
|
MaybeWorkAroundAmdBug(masm);
|
||||||
|
|
||||||
EmitReturnFromIC(masm);
|
EmitReturnFromIC(masm);
|
||||||
|
@ -2765,9 +2764,7 @@ GenerateNewObjectWithTemplateCode(JSContext* cx, JSObject* templateObject)
|
||||||
Label failure;
|
Label failure;
|
||||||
Register objReg = R0.scratchReg();
|
Register objReg = R0.scratchReg();
|
||||||
Register tempReg = R1.scratchReg();
|
Register tempReg = R1.scratchReg();
|
||||||
masm.movePtr(ImmGCPtr(templateObject->group()), tempReg);
|
masm.branchIfPretenuredGroup(templateObject->group(), tempReg, &failure);
|
||||||
masm.branchTest32(Assembler::NonZero, Address(tempReg, ObjectGroup::offsetOfFlags()),
|
|
||||||
Imm32(OBJECT_FLAG_PRE_TENURE), &failure);
|
|
||||||
masm.branchPtr(Assembler::NotEqual, AbsoluteAddress(cx->compartment()->addressOfMetadataBuilder()),
|
masm.branchPtr(Assembler::NotEqual, AbsoluteAddress(cx->compartment()->addressOfMetadataBuilder()),
|
||||||
ImmWord(0), &failure);
|
ImmWord(0), &failure);
|
||||||
masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, &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) {
|
if (InBounds == IndexInBounds::Yes) {
|
||||||
MOZ_ASSERT(uint32_t(index) < obj->as<NativeObject>().getDenseInitializedLength());
|
MOZ_ASSERT(uint32_t(index) < obj->as<NativeObject>().getDenseInitializedLength());
|
||||||
} else {
|
} 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);
|
rt->gc.storeBuffer().putWholeCell(obj);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1746,29 +1746,20 @@ void
|
||||||
CodeGeneratorARM::visitGuardShape(LGuardShape* guard)
|
CodeGeneratorARM::visitGuardShape(LGuardShape* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
Register obj = ToRegister(guard->input());
|
||||||
Register tmp = ToRegister(guard->tempInt());
|
Label bail;
|
||||||
|
masm.branchTestObjShape(Assembler::NotEqual, obj, guard->mir()->shape(), &bail);
|
||||||
ScratchRegisterScope scratch(masm);
|
bailoutFrom(&bail, guard->snapshot());
|
||||||
masm.ma_ldr(DTRAddr(obj, DtrOffImm(ShapedObject::offsetOfShape())), tmp);
|
|
||||||
masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->shape()), scratch);
|
|
||||||
|
|
||||||
bailoutIf(Assembler::NotEqual, guard->snapshot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CodeGeneratorARM::visitGuardObjectGroup(LGuardObjectGroup* guard)
|
CodeGeneratorARM::visitGuardObjectGroup(LGuardObjectGroup* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
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 =
|
Assembler::Condition cond =
|
||||||
guard->mir()->bailOnEquality() ? Assembler::Equal : Assembler::NotEqual;
|
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
|
void
|
||||||
|
@ -1776,12 +1767,9 @@ CodeGeneratorARM::visitGuardClass(LGuardClass* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
Register obj = ToRegister(guard->input());
|
||||||
Register tmp = ToRegister(guard->tempInt());
|
Register tmp = ToRegister(guard->tempInt());
|
||||||
|
Label bail;
|
||||||
ScratchRegisterScope scratch(masm);
|
masm.branchTestObjClass(Assembler::NotEqual, obj, tmp, guard->mir()->getClass(), &bail);
|
||||||
|
bailoutFrom(&bail, guard->snapshot());
|
||||||
masm.loadObjClass(obj, tmp);
|
|
||||||
masm.ma_cmp(tmp, Imm32((uint32_t)guard->mir()->getClass()), scratch);
|
|
||||||
bailoutIf(Assembler::NotEqual, guard->snapshot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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:
|
public:
|
||||||
LIR_HEADER(GuardShape);
|
LIR_HEADER(GuardShape);
|
||||||
|
|
||||||
LGuardShape(const LAllocation& in, const LDefinition& temp) {
|
explicit LGuardShape(const LAllocation& in) {
|
||||||
setOperand(0, in);
|
setOperand(0, in);
|
||||||
setTemp(0, temp);
|
|
||||||
}
|
}
|
||||||
const MGuardShape* mir() const {
|
const MGuardShape* mir() const {
|
||||||
return mir_->toGuardShape();
|
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:
|
public:
|
||||||
LIR_HEADER(GuardObjectGroup);
|
LIR_HEADER(GuardObjectGroup);
|
||||||
|
|
||||||
LGuardObjectGroup(const LAllocation& in, const LDefinition& temp) {
|
explicit LGuardObjectGroup(const LAllocation& in) {
|
||||||
setOperand(0, in);
|
setOperand(0, in);
|
||||||
setTemp(0, temp);
|
|
||||||
}
|
}
|
||||||
const MGuardObjectGroup* mir() const {
|
const MGuardObjectGroup* mir() const {
|
||||||
return mir_->toGuardObjectGroup();
|
return mir_->toGuardObjectGroup();
|
||||||
|
|
|
@ -485,8 +485,7 @@ LIRGeneratorARM::visitGuardShape(MGuardShape* ins)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
||||||
|
|
||||||
LDefinition tempObj = temp(LDefinition::OBJECT);
|
LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->object()));
|
||||||
LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->object()), tempObj);
|
|
||||||
assignSnapshot(guard, ins->bailoutKind());
|
assignSnapshot(guard, ins->bailoutKind());
|
||||||
add(guard, ins);
|
add(guard, ins);
|
||||||
redefine(ins, ins->object());
|
redefine(ins, ins->object());
|
||||||
|
@ -497,8 +496,7 @@ LIRGeneratorARM::visitGuardObjectGroup(MGuardObjectGroup* ins)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
||||||
|
|
||||||
LDefinition tempObj = temp(LDefinition::OBJECT);
|
LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->object()));
|
||||||
LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->object()), tempObj);
|
|
||||||
assignSnapshot(guard, ins->bailoutKind());
|
assignSnapshot(guard, ins->bailoutKind());
|
||||||
add(guard, ins);
|
add(guard, ins);
|
||||||
redefine(ins, ins->object());
|
redefine(ins, ins->object());
|
||||||
|
|
|
@ -1772,25 +1772,20 @@ void
|
||||||
CodeGeneratorMIPSShared::visitGuardShape(LGuardShape* guard)
|
CodeGeneratorMIPSShared::visitGuardShape(LGuardShape* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
Register obj = ToRegister(guard->input());
|
||||||
Register tmp = ToRegister(guard->tempInt());
|
Label bail;
|
||||||
|
masm.branchTestObjShape(Assembler::NotEqual, obj, guard->mir()->shape(), &bail);
|
||||||
masm.loadPtr(Address(obj, ShapedObject::offsetOfShape()), tmp);
|
bailoutFrom(&bail, guard->snapshot());
|
||||||
bailoutCmpPtr(Assembler::NotEqual, tmp, ImmGCPtr(guard->mir()->shape()),
|
|
||||||
guard->snapshot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CodeGeneratorMIPSShared::visitGuardObjectGroup(LGuardObjectGroup* guard)
|
CodeGeneratorMIPSShared::visitGuardObjectGroup(LGuardObjectGroup* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
Register obj = ToRegister(guard->input());
|
||||||
Register tmp = ToRegister(guard->tempInt());
|
Assembler::Condition cond =
|
||||||
MOZ_ASSERT(obj != tmp);
|
guard->mir()->bailOnEquality() ? Assembler::Equal : Assembler::NotEqual;
|
||||||
|
Label bail;
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), tmp);
|
masm.branchTestObjGroup(cond, obj, guard->mir()->group(), &bail);
|
||||||
Assembler::Condition cond = guard->mir()->bailOnEquality()
|
bailoutFrom(&bail, guard->snapshot());
|
||||||
? Assembler::Equal
|
|
||||||
: Assembler::NotEqual;
|
|
||||||
bailoutCmpPtr(cond, tmp, ImmGCPtr(guard->mir()->group()), guard->snapshot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1798,10 +1793,9 @@ CodeGeneratorMIPSShared::visitGuardClass(LGuardClass* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
Register obj = ToRegister(guard->input());
|
||||||
Register tmp = ToRegister(guard->tempInt());
|
Register tmp = ToRegister(guard->tempInt());
|
||||||
|
Label bail;
|
||||||
masm.loadObjClass(obj, tmp);
|
masm.branchTestObjClass(Assembler::NotEqual, obj, tmp, guard->mir()->getClass(), &bail);
|
||||||
bailoutCmpPtr(Assembler::NotEqual, tmp, ImmPtr(guard->mir()->getClass()),
|
bailoutFrom(&bail, guard->snapshot());
|
||||||
guard->snapshot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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:
|
public:
|
||||||
LIR_HEADER(GuardShape);
|
LIR_HEADER(GuardShape);
|
||||||
|
|
||||||
LGuardShape(const LAllocation& in, const LDefinition& temp) {
|
explicit LGuardShape(const LAllocation& in) {
|
||||||
setOperand(0, in);
|
setOperand(0, in);
|
||||||
setTemp(0, temp);
|
|
||||||
}
|
}
|
||||||
const MGuardShape* mir() const {
|
const MGuardShape* mir() const {
|
||||||
return mir_->toGuardShape();
|
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:
|
public:
|
||||||
LIR_HEADER(GuardObjectGroup);
|
LIR_HEADER(GuardObjectGroup);
|
||||||
|
|
||||||
LGuardObjectGroup(const LAllocation& in, const LDefinition& temp) {
|
explicit LGuardObjectGroup(const LAllocation& in) {
|
||||||
setOperand(0, in);
|
setOperand(0, in);
|
||||||
setTemp(0, temp);
|
|
||||||
}
|
}
|
||||||
const MGuardObjectGroup* mir() const {
|
const MGuardObjectGroup* mir() const {
|
||||||
return mir_->toGuardObjectGroup();
|
return mir_->toGuardObjectGroup();
|
||||||
|
|
|
@ -292,8 +292,7 @@ LIRGeneratorMIPSShared::visitGuardShape(MGuardShape* ins)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
||||||
|
|
||||||
LDefinition tempObj = temp(LDefinition::OBJECT);
|
LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->object()));
|
||||||
LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->object()), tempObj);
|
|
||||||
assignSnapshot(guard, ins->bailoutKind());
|
assignSnapshot(guard, ins->bailoutKind());
|
||||||
add(guard, ins);
|
add(guard, ins);
|
||||||
redefine(ins, ins->object());
|
redefine(ins, ins->object());
|
||||||
|
@ -304,8 +303,7 @@ LIRGeneratorMIPSShared::visitGuardObjectGroup(MGuardObjectGroup* ins)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
||||||
|
|
||||||
LDefinition tempObj = temp(LDefinition::OBJECT);
|
LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->object()));
|
||||||
LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->object()), tempObj);
|
|
||||||
assignSnapshot(guard, ins->bailoutKind());
|
assignSnapshot(guard, ins->bailoutKind());
|
||||||
add(guard, ins);
|
add(guard, ins);
|
||||||
redefine(ins, ins->object());
|
redefine(ins, ins->object());
|
||||||
|
|
|
@ -2376,21 +2376,20 @@ void
|
||||||
CodeGeneratorX86Shared::visitGuardShape(LGuardShape* guard)
|
CodeGeneratorX86Shared::visitGuardShape(LGuardShape* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
Register obj = ToRegister(guard->input());
|
||||||
masm.cmpPtr(Operand(obj, ShapedObject::offsetOfShape()), ImmGCPtr(guard->mir()->shape()));
|
Label bail;
|
||||||
|
masm.branchTestObjShape(Assembler::NotEqual, obj, guard->mir()->shape(), &bail);
|
||||||
bailoutIf(Assembler::NotEqual, guard->snapshot());
|
bailoutFrom(&bail, guard->snapshot());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CodeGeneratorX86Shared::visitGuardObjectGroup(LGuardObjectGroup* guard)
|
CodeGeneratorX86Shared::visitGuardObjectGroup(LGuardObjectGroup* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
Register obj = ToRegister(guard->input());
|
||||||
|
|
||||||
masm.cmpPtr(Operand(obj, JSObject::offsetOfGroup()), ImmGCPtr(guard->mir()->group()));
|
|
||||||
|
|
||||||
Assembler::Condition cond =
|
Assembler::Condition cond =
|
||||||
guard->mir()->bailOnEquality() ? Assembler::Equal : Assembler::NotEqual;
|
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
|
void
|
||||||
|
@ -2398,10 +2397,9 @@ CodeGeneratorX86Shared::visitGuardClass(LGuardClass* guard)
|
||||||
{
|
{
|
||||||
Register obj = ToRegister(guard->input());
|
Register obj = ToRegister(guard->input());
|
||||||
Register tmp = ToRegister(guard->tempInt());
|
Register tmp = ToRegister(guard->tempInt());
|
||||||
|
Label bail;
|
||||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), tmp);
|
masm.branchTestObjClass(Assembler::NotEqual, obj, tmp, guard->mir()->getClass(), &bail);
|
||||||
masm.cmpPtr(Operand(tmp, ObjectGroup::offsetOfClasp()), ImmPtr(guard->mir()->getClass()));
|
bailoutFrom(&bail, guard->snapshot());
|
||||||
bailoutIf(Assembler::NotEqual, guard->snapshot());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -3993,6 +3993,7 @@ JS::TransitiveCompileOptions::copyPODTransitiveOptions(const TransitiveCompileOp
|
||||||
introductionOffset = rhs.introductionOffset;
|
introductionOffset = rhs.introductionOffset;
|
||||||
hasIntroductionInfo = rhs.hasIntroductionInfo;
|
hasIntroductionInfo = rhs.hasIntroductionInfo;
|
||||||
isProbablySystemOrAddonCode = rhs.isProbablySystemOrAddonCode;
|
isProbablySystemOrAddonCode = rhs.isProbablySystemOrAddonCode;
|
||||||
|
hideScriptFromDebugger = rhs.hideScriptFromDebugger;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -4678,6 +4679,17 @@ JS::InitScriptSourceElement(JSContext* cx, HandleScript script,
|
||||||
return ScriptSourceObject::initElementProperties(cx, sso, element, elementAttrName);
|
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_PUBLIC_API(JSString*)
|
||||||
JS_DecompileScript(JSContext* cx, HandleScript script)
|
JS_DecompileScript(JSContext* cx, HandleScript script)
|
||||||
{
|
{
|
||||||
|
|
136
js/src/jsapi.h
136
js/src/jsapi.h
|
@ -102,133 +102,6 @@ class MOZ_RAII AutoValueArray : public AutoGCRooter
|
||||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
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 ValueVector = JS::GCVector<JS::Value>;
|
||||||
using IdVector = JS::GCVector<jsid>;
|
using IdVector = JS::GCVector<jsid>;
|
||||||
using ScriptVector = JS::GCVector<JSScript*>;
|
using ScriptVector = JS::GCVector<JSScript*>;
|
||||||
|
@ -3692,6 +3565,7 @@ class JS_FRIEND_API(TransitiveCompileOptions)
|
||||||
sourceIsLazy(false),
|
sourceIsLazy(false),
|
||||||
allowHTMLComments(true),
|
allowHTMLComments(true),
|
||||||
isProbablySystemOrAddonCode(false),
|
isProbablySystemOrAddonCode(false),
|
||||||
|
hideScriptFromDebugger(false),
|
||||||
introductionType(nullptr),
|
introductionType(nullptr),
|
||||||
introductionLineno(0),
|
introductionLineno(0),
|
||||||
introductionOffset(0),
|
introductionOffset(0),
|
||||||
|
@ -3727,6 +3601,7 @@ class JS_FRIEND_API(TransitiveCompileOptions)
|
||||||
bool sourceIsLazy;
|
bool sourceIsLazy;
|
||||||
bool allowHTMLComments;
|
bool allowHTMLComments;
|
||||||
bool isProbablySystemOrAddonCode;
|
bool isProbablySystemOrAddonCode;
|
||||||
|
bool hideScriptFromDebugger;
|
||||||
|
|
||||||
// |introductionType| is a statically allocated C string:
|
// |introductionType| is a statically allocated C string:
|
||||||
// one of "eval", "Function", or "GeneratorFunction".
|
// one of "eval", "Function", or "GeneratorFunction".
|
||||||
|
@ -4134,6 +4009,13 @@ extern JS_PUBLIC_API(bool)
|
||||||
InitScriptSourceElement(JSContext* cx, HandleScript script,
|
InitScriptSourceElement(JSContext* cx, HandleScript script,
|
||||||
HandleObject element, HandleString elementAttrName = nullptr);
|
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 */
|
} /* namespace JS */
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSString*)
|
extern JS_PUBLIC_API(JSString*)
|
||||||
|
|
|
@ -29,7 +29,11 @@
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
class AutoIdVector;
|
template <typename T> class AutoVector;
|
||||||
|
using AutoIdVector = AutoVector<jsid>;
|
||||||
|
using AutoValueVector = AutoVector<Value>;
|
||||||
|
using AutoObjectVector = AutoVector<JSObject*>;
|
||||||
|
|
||||||
class CallArgs;
|
class CallArgs;
|
||||||
|
|
||||||
class JS_FRIEND_API(CompileOptions);
|
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-ggc", "Disable Generational GC")
|
||||||
|| !op.addBoolOption('\0', "no-cgc", "Disable Compacting GC")
|
|| !op.addBoolOption('\0', "no-cgc", "Disable Compacting GC")
|
||||||
|| !op.addBoolOption('\0', "no-incremental-gc", "Disable Incremental 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",
|
|| !op.addIntOption('\0', "available-memory", "SIZE",
|
||||||
"Select GC settings based on available memory (MB)", 0)
|
"Select GC settings based on available memory (MB)", 0)
|
||||||
|| !op.addStringOption('\0', "arm-hwcap", "[features]",
|
|| !op.addStringOption('\0', "arm-hwcap", "[features]",
|
||||||
|
@ -9233,8 +9234,14 @@ main(int argc, char** argv, char** envp)
|
||||||
|
|
||||||
js::UseInternalJobQueues(cx);
|
js::UseInternalJobQueues(cx);
|
||||||
|
|
||||||
if (op.getBoolOption("nursery-strings"))
|
if (const char* opt = op.getStringOption("nursery-strings")) {
|
||||||
cx->runtime()->gc.nursery().enableStrings();
|
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))
|
if (!JS::InitSelfHostedCode(cx))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -1800,6 +1800,11 @@ Debugger::onNewScript(JSContext* cx, HandleScript script)
|
||||||
MOZ_ASSERT_IF(!script->compartment()->creationOptions().invisibleToDebugger() &&
|
MOZ_ASSERT_IF(!script->compartment()->creationOptions().invisibleToDebugger() &&
|
||||||
!script->selfHosted(),
|
!script->selfHosted(),
|
||||||
script->compartment()->firedOnNewGlobalObject);
|
script->compartment()->firedOnNewGlobalObject);
|
||||||
|
|
||||||
|
// The script may not be ready to be interrogated by the debugger.
|
||||||
|
if (script->hideScriptFromDebugger())
|
||||||
|
return;
|
||||||
|
|
||||||
if (script->compartment()->isDebuggee())
|
if (script->compartment()->isDebuggee())
|
||||||
slowPathOnNewScript(cx, script);
|
slowPathOnNewScript(cx, script);
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,6 +218,7 @@ GetSelectorRuntime(const CompilationSelector& selector)
|
||||||
{
|
{
|
||||||
JSRuntime* match(JSScript* script) { return script->runtimeFromActiveCooperatingThread(); }
|
JSRuntime* match(JSScript* script) { return script->runtimeFromActiveCooperatingThread(); }
|
||||||
JSRuntime* match(JSCompartment* comp) { return comp->runtimeFromActiveCooperatingThread(); }
|
JSRuntime* match(JSCompartment* comp) { return comp->runtimeFromActiveCooperatingThread(); }
|
||||||
|
JSRuntime* match(Zone* zone) { return zone->runtimeFromActiveCooperatingThread(); }
|
||||||
JSRuntime* match(ZonesInState zbs) { return zbs.runtime; }
|
JSRuntime* match(ZonesInState zbs) { return zbs.runtime; }
|
||||||
JSRuntime* match(JSRuntime* runtime) { return runtime; }
|
JSRuntime* match(JSRuntime* runtime) { return runtime; }
|
||||||
JSRuntime* match(AllCompilations all) { return nullptr; }
|
JSRuntime* match(AllCompilations all) { return nullptr; }
|
||||||
|
@ -234,6 +235,7 @@ JitDataStructuresExist(const CompilationSelector& selector)
|
||||||
{
|
{
|
||||||
bool match(JSScript* script) { return !!script->compartment()->jitCompartment(); }
|
bool match(JSScript* script) { return !!script->compartment()->jitCompartment(); }
|
||||||
bool match(JSCompartment* comp) { return !!comp->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(ZonesInState zbs) { return zbs.runtime->hasJitRuntime(); }
|
||||||
bool match(JSRuntime* runtime) { return runtime->hasJitRuntime(); }
|
bool match(JSRuntime* runtime) { return runtime->hasJitRuntime(); }
|
||||||
bool match(AllCompilations all) { return true; }
|
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(JSScript* script) { return script == builder_->script(); }
|
||||||
bool match(JSCompartment* comp) { return comp == builder_->script()->compartment(); }
|
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(JSRuntime* runtime) { return runtime == builder_->script()->runtimeFromAnyThread(); }
|
||||||
bool match(AllCompilations all) { return true; }
|
bool match(AllCompilations all) { return true; }
|
||||||
bool match(ZonesInState zbs) {
|
bool match(ZonesInState zbs) {
|
||||||
|
|
|
@ -516,6 +516,7 @@ struct CompilationsUsingNursery { JSRuntime* runtime; };
|
||||||
|
|
||||||
using CompilationSelector = mozilla::Variant<JSScript*,
|
using CompilationSelector = mozilla::Variant<JSScript*,
|
||||||
JSCompartment*,
|
JSCompartment*,
|
||||||
|
Zone*,
|
||||||
ZonesInState,
|
ZonesInState,
|
||||||
JSRuntime*,
|
JSRuntime*,
|
||||||
CompilationsUsingNursery,
|
CompilationsUsingNursery,
|
||||||
|
@ -539,6 +540,12 @@ CancelOffThreadIonCompile(JSCompartment* comp)
|
||||||
CancelOffThreadIonCompile(CompilationSelector(comp), true);
|
CancelOffThreadIonCompile(CompilationSelector(comp), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
CancelOffThreadIonCompile(Zone* zone)
|
||||||
|
{
|
||||||
|
CancelOffThreadIonCompile(CompilationSelector(zone), true);
|
||||||
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
CancelOffThreadIonCompile(JSRuntime* runtime, JS::Zone::GCState state)
|
CancelOffThreadIonCompile(JSRuntime* runtime, JS::Zone::GCState state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1384,16 +1384,20 @@ struct WrapperValue
|
||||||
Value value;
|
Value value;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MOZ_RAII AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue>
|
class MOZ_RAII AutoWrapperVector : public JS::GCVector<WrapperValue, 8>,
|
||||||
|
private JS::AutoGCRooter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AutoWrapperVector(JSContext* cx
|
explicit AutoWrapperVector(JSContext* cx
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
: AutoVectorRooterBase<WrapperValue>(cx, WRAPVECTOR)
|
: JS::GCVector<WrapperValue, 8>(cx),
|
||||||
|
JS::AutoGCRooter(cx, WRAPVECTOR)
|
||||||
{
|
{
|
||||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend void AutoGCRooter::trace(JSTracer* trc);
|
||||||
|
|
||||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -541,7 +541,15 @@ class JSObject : public js::gc::Cell
|
||||||
void dump() const;
|
void dump() const;
|
||||||
#endif
|
#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() {
|
static constexpr size_t offsetOfGroup() {
|
||||||
return offsetof(JSObject, group_);
|
return offsetof(JSObject, group_);
|
||||||
|
@ -550,9 +558,6 @@ class JSObject : public js::gc::Cell
|
||||||
return offsetof(JSObject, shapeOrExpando_);
|
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:
|
private:
|
||||||
JSObject() = delete;
|
JSObject() = delete;
|
||||||
JSObject(const JSObject& other) = delete;
|
JSObject(const JSObject& other) = delete;
|
||||||
|
|
|
@ -2732,6 +2732,8 @@ JSScript::Create(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
script->toStringStart_ = toStringStart;
|
script->toStringStart_ = toStringStart;
|
||||||
script->toStringEnd_ = toStringEnd;
|
script->toStringEnd_ = toStringEnd;
|
||||||
|
|
||||||
|
script->hideScriptFromDebugger_ = options.hideScriptFromDebugger;
|
||||||
|
|
||||||
#ifdef MOZ_VTUNE
|
#ifdef MOZ_VTUNE
|
||||||
script->vtuneMethodId_ = vtune::GenerateUniqueMethodID();
|
script->vtuneMethodId_ = vtune::GenerateUniqueMethodID();
|
||||||
#endif
|
#endif
|
||||||
|
@ -3625,6 +3627,7 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
||||||
dst->isAsync_ = src->isAsync_;
|
dst->isAsync_ = src->isAsync_;
|
||||||
dst->hasRest_ = src->hasRest_;
|
dst->hasRest_ = src->hasRest_;
|
||||||
dst->isExprBody_ = src->isExprBody_;
|
dst->isExprBody_ = src->isExprBody_;
|
||||||
|
dst->hideScriptFromDebugger_ = src->hideScriptFromDebugger_;
|
||||||
|
|
||||||
if (nconsts != 0) {
|
if (nconsts != 0) {
|
||||||
GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->consts()->vector);
|
GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->consts()->vector);
|
||||||
|
|
|
@ -1142,6 +1142,9 @@ class JSScript : public js::gc::TenuredCell
|
||||||
bool hasRest_:1;
|
bool hasRest_:1;
|
||||||
bool isExprBody_: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
|
// Add padding so JSScript is gc::Cell aligned. Make padding protected
|
||||||
// instead of private to suppress -Wunused-private-field compiler warnings.
|
// instead of private to suppress -Wunused-private-field compiler warnings.
|
||||||
protected:
|
protected:
|
||||||
|
@ -1463,6 +1466,13 @@ class JSScript : public js::gc::TenuredCell
|
||||||
isExprBody_ = true;
|
isExprBody_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hideScriptFromDebugger() const {
|
||||||
|
return hideScriptFromDebugger_;
|
||||||
|
}
|
||||||
|
void clearHideScriptFromDebugger() {
|
||||||
|
hideScriptFromDebugger_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
void setNeedsHomeObject() {
|
void setNeedsHomeObject() {
|
||||||
needsHomeObject_ = true;
|
needsHomeObject_ = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -459,6 +459,10 @@ class ObjectGroup : public gc::TenuredCell
|
||||||
|
|
||||||
static const JS::TraceKind TraceKind = JS::TraceKind::ObjectGroup;
|
static const JS::TraceKind TraceKind = JS::TraceKind::ObjectGroup;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// See JSObject::offsetOfGroup() comment.
|
||||||
|
friend class js::jit::MacroAssembler;
|
||||||
|
|
||||||
static inline uint32_t offsetOfClasp() {
|
static inline uint32_t offsetOfClasp() {
|
||||||
return offsetof(ObjectGroup, clasp_);
|
return offsetof(ObjectGroup, clasp_);
|
||||||
}
|
}
|
||||||
|
@ -479,6 +483,7 @@ class ObjectGroup : public gc::TenuredCell
|
||||||
return offsetof(ObjectGroup, flags_);
|
return offsetof(ObjectGroup, flags_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
const ObjectGroupFlags* addressOfFlags() const {
|
const ObjectGroupFlags* addressOfFlags() const {
|
||||||
return &flags_;
|
return &flags_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1800,12 +1800,12 @@ Shape::fixupDictionaryShapeAfterMovingGC()
|
||||||
|
|
||||||
if (listpPointsIntoShape) {
|
if (listpPointsIntoShape) {
|
||||||
// listp points to the parent field of the next shape.
|
// 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))
|
if (gc::IsForwarded(next))
|
||||||
listp = &gc::Forwarded(next)->parent;
|
listp = &gc::Forwarded(next)->parent;
|
||||||
} else {
|
} else {
|
||||||
// listp points to the shape_ field of an object.
|
// 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))
|
if (gc::IsForwarded(last))
|
||||||
listp = gc::Forwarded(last)->as<NativeObject>().shapePtr();
|
listp = gc::Forwarded(last)->as<NativeObject>().shapePtr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1169,15 +1169,20 @@ class Shape : public gc::TenuredCell
|
||||||
void fixupGetterSetterForBarrier(JSTracer* trc);
|
void fixupGetterSetterForBarrier(JSTracer* trc);
|
||||||
void updateBaseShapeAfterMovingGC();
|
void updateBaseShapeAfterMovingGC();
|
||||||
|
|
||||||
/* For JIT usage */
|
#ifdef DEBUG
|
||||||
static inline size_t offsetOfBase() { return offsetof(Shape, base_); }
|
// For JIT usage.
|
||||||
static inline size_t offsetOfSlotInfo() { return offsetof(Shape, slotInfo); }
|
static inline size_t offsetOfSlotInfo() { return offsetof(Shape, slotInfo); }
|
||||||
static inline uint32_t fixedSlotsMask() { return FIXED_SLOTS_MASK; }
|
static inline uint32_t fixedSlotsMask() { return FIXED_SLOTS_MASK; }
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fixupDictionaryShapeAfterMovingGC();
|
void fixupDictionaryShapeAfterMovingGC();
|
||||||
void fixupShapeTreeAfterMovingGC();
|
void fixupShapeTreeAfterMovingGC();
|
||||||
|
|
||||||
|
static Shape* fromParentFieldPointer(uintptr_t p) {
|
||||||
|
return reinterpret_cast<Shape*>(p - offsetof(Shape, parent));
|
||||||
|
}
|
||||||
|
|
||||||
static void staticAsserts() {
|
static void staticAsserts() {
|
||||||
JS_STATIC_ASSERT(offsetof(Shape, base_) == offsetof(js::shadow::Shape, base));
|
JS_STATIC_ASSERT(offsetof(Shape, base_) == offsetof(js::shadow::Shape, base));
|
||||||
JS_STATIC_ASSERT(offsetof(Shape, slotInfo) == offsetof(js::shadow::Shape, slotInfo));
|
JS_STATIC_ASSERT(offsetof(Shape, slotInfo) == offsetof(js::shadow::Shape, slotInfo));
|
||||||
|
|
|
@ -50,6 +50,14 @@ class ShapedObject : public JSObject
|
||||||
TraceEdge(trc, shapePtr(), "shape");
|
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 constexpr size_t offsetOfShape() {
|
||||||
static_assert(offsetOfShapeOrExpando() == offsetof(shadow::Object, shape),
|
static_assert(offsetOfShapeOrExpando() == offsetof(shadow::Object, shape),
|
||||||
"shadow shape must match actual shape");
|
"shadow shape must match actual shape");
|
||||||
|
|
|
@ -525,7 +525,8 @@ JSRope::flattenInternal(JSContext* maybecx)
|
||||||
Nursery& nursery = zone()->group()->nursery();
|
Nursery& nursery = zone()->group()->nursery();
|
||||||
if (!nursery.registerMallocedBuffer(wholeChars)) {
|
if (!nursery.registerMallocedBuffer(wholeChars)) {
|
||||||
js_free(wholeChars);
|
js_free(wholeChars);
|
||||||
ReportOutOfMemory(maybecx);
|
if (maybecx)
|
||||||
|
ReportOutOfMemory(maybecx);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,15 +87,25 @@ wasm::HasCompilerSupport(JSContext* cx)
|
||||||
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
|
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
|
||||||
return false;
|
return false;
|
||||||
#else
|
#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()) ||
|
return (cx->options().wasmBaseline() && BaselineCanCompile()) ||
|
||||||
(cx->options().wasmIon() && IonCanCompile());
|
(cx->options().wasmIon() && IonCanCompile());
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm::HasSupport(JSContext* cx)
|
wasm::HasSupport(JSContext* cx)
|
||||||
{
|
{
|
||||||
return cx->options().wasm() && HasCompilerSupport(cx);
|
return cx->options().wasm() &&
|
||||||
|
HasCompilerSupport(cx) &&
|
||||||
|
HasAvailableCompilerTier(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -12,10 +12,6 @@
|
||||||
#include "js/CallNonGenericMethod.h"
|
#include "js/CallNonGenericMethod.h"
|
||||||
#include "js/Wrapper.h"
|
#include "js/Wrapper.h"
|
||||||
|
|
||||||
namespace JS {
|
|
||||||
class AutoIdVector;
|
|
||||||
} // namespace JS
|
|
||||||
|
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
||||||
template <typename Base, typename Policy>
|
template <typename Base, typename Policy>
|
||||||
|
|
|
@ -200,12 +200,6 @@ IsReversedDirectionFrame(nsIFrame* aFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "nsILineIterator.h"
|
#include "nsILineIterator.h"
|
||||||
|
|
||||||
//non Hack prototypes
|
|
||||||
#if 0
|
|
||||||
static void RefreshContentFrames(nsPresContext* aPresContext, nsIContent * aStartContent, nsIContent * aEndContent);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "prenv.h"
|
#include "prenv.h"
|
||||||
|
|
||||||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(BoxMetricsProperty, nsBoxLayoutMetrics)
|
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-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-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
|
== 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
|
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-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
|
== 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-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-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
|
== 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
|
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-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
|
== 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
|
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-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
|
== 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
|
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-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
|
== 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-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-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
|
== 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
|
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-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
|
== 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));
|
aIdealSegmentSize - sizeof(Segment) < sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SegmentedVector(SegmentedVector&& aOther)
|
||||||
|
: mSegments(mozilla::Move(aOther.mSegments))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~SegmentedVector() { Clear(); }
|
~SegmentedVector() { Clear(); }
|
||||||
|
|
||||||
bool IsEmpty() const { return !mSegments.getFirst(); }
|
bool IsEmpty() const { return !mSegments.getFirst(); }
|
||||||
|
|
|
@ -3596,7 +3596,7 @@ public class BrowserApp extends GeckoApp
|
||||||
super.closeOptionsMenu();
|
super.closeOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoView.ContentListener
|
@Override // GeckoView.ContentDelegate
|
||||||
public void onFullScreen(final GeckoSession session, final boolean fullscreen) {
|
public void onFullScreen(final GeckoSession session, final boolean fullscreen) {
|
||||||
super.onFullScreen(session, fullscreen);
|
super.onFullScreen(session, fullscreen);
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ public abstract class GeckoApp extends GeckoActivity
|
||||||
BundleEventListener,
|
BundleEventListener,
|
||||||
GeckoMenu.Callback,
|
GeckoMenu.Callback,
|
||||||
GeckoMenu.MenuPresenter,
|
GeckoMenu.MenuPresenter,
|
||||||
GeckoSession.ContentListener,
|
GeckoSession.ContentDelegate,
|
||||||
ScreenOrientationDelegate,
|
ScreenOrientationDelegate,
|
||||||
Tabs.OnTabsChangedListener,
|
Tabs.OnTabsChangedListener,
|
||||||
ViewTreeObserver.OnGlobalLayoutListener {
|
ViewTreeObserver.OnGlobalLayoutListener {
|
||||||
|
@ -873,19 +873,19 @@ public abstract class GeckoApp extends GeckoActivity
|
||||||
return inSampleSize;
|
return inSampleSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onTitleChange(final GeckoSession session, final String title) {
|
public void onTitleChange(final GeckoSession session, final String title) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onFocusRequest(final GeckoSession session) {
|
public void onFocusRequest(final GeckoSession session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onCloseRequest(final GeckoSession session) {
|
public void onCloseRequest(final GeckoSession session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onFullScreen(final GeckoSession session, final boolean fullScreen) {
|
public void onFullScreen(final GeckoSession session, final boolean fullScreen) {
|
||||||
if (fullScreen) {
|
if (fullScreen) {
|
||||||
SnackbarBuilder.builder(this)
|
SnackbarBuilder.builder(this)
|
||||||
|
@ -1087,7 +1087,7 @@ public abstract class GeckoApp extends GeckoActivity
|
||||||
|
|
||||||
session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
|
session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
|
||||||
"chrome://browser/content/browser.xul");
|
"chrome://browser/content/browser.xul");
|
||||||
session.setContentListener(this);
|
session.setContentDelegate(this);
|
||||||
|
|
||||||
GeckoAccessibility.setDelegate(mLayerView);
|
GeckoAccessibility.setDelegate(mLayerView);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.mozilla.gecko.SiteIdentity;
|
||||||
import org.mozilla.gecko.Tab;
|
import org.mozilla.gecko.Tab;
|
||||||
import org.mozilla.gecko.toolbar.SecurityModeUtil;
|
import org.mozilla.gecko.toolbar.SecurityModeUtil;
|
||||||
import org.mozilla.gecko.util.ColorUtil;
|
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;
|
import org.mozilla.geckoview.GeckoView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -73,9 +73,9 @@ import java.util.List;
|
||||||
public class CustomTabsActivity extends AppCompatActivity
|
public class CustomTabsActivity extends AppCompatActivity
|
||||||
implements ActionModePresenter,
|
implements ActionModePresenter,
|
||||||
GeckoMenu.Callback,
|
GeckoMenu.Callback,
|
||||||
GeckoSession.ContentListener,
|
GeckoSession.ContentDelegate,
|
||||||
GeckoSession.NavigationListener,
|
GeckoSession.NavigationDelegate,
|
||||||
GeckoSession.ProgressListener {
|
GeckoSession.ProgressDelegate {
|
||||||
|
|
||||||
private static final String LOGTAG = "CustomTabsActivity";
|
private static final String LOGTAG = "CustomTabsActivity";
|
||||||
|
|
||||||
|
@ -134,9 +134,9 @@ public class CustomTabsActivity extends AppCompatActivity
|
||||||
mGeckoSession = new GeckoSession();
|
mGeckoSession = new GeckoSession();
|
||||||
mGeckoView.setSession(mGeckoSession);
|
mGeckoView.setSession(mGeckoSession);
|
||||||
|
|
||||||
mGeckoSession.setNavigationListener(this);
|
mGeckoSession.setNavigationDelegate(this);
|
||||||
mGeckoSession.setProgressListener(this);
|
mGeckoSession.setProgressDelegate(this);
|
||||||
mGeckoSession.setContentListener(this);
|
mGeckoSession.setContentDelegate(this);
|
||||||
|
|
||||||
mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
|
mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
|
||||||
mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());
|
mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());
|
||||||
|
@ -591,7 +591,7 @@ public class CustomTabsActivity extends AppCompatActivity
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GeckoSession.NavigationListener */
|
/* GeckoSession.NavigationDelegate */
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChange(GeckoSession session, String url) {
|
public void onLocationChange(GeckoSession session, String url) {
|
||||||
mCurrentUrl = url;
|
mCurrentUrl = url;
|
||||||
|
@ -656,7 +656,7 @@ public class CustomTabsActivity extends AppCompatActivity
|
||||||
throw new IllegalStateException("Unexpected new session");
|
throw new IllegalStateException("Unexpected new session");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GeckoSession.ProgressListener */
|
/* GeckoSession.ProgressDelegate */
|
||||||
@Override
|
@Override
|
||||||
public void onPageStart(GeckoSession session, String url) {
|
public void onPageStart(GeckoSession session, String url) {
|
||||||
mCurrentUrl = url;
|
mCurrentUrl = url;
|
||||||
|
@ -679,7 +679,7 @@ public class CustomTabsActivity extends AppCompatActivity
|
||||||
updateActionBar();
|
updateActionBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GeckoSession.ContentListener */
|
/* GeckoSession.ContentDelegate */
|
||||||
@Override
|
@Override
|
||||||
public void onTitleChange(GeckoSession session, String title) {
|
public void onTitleChange(GeckoSession session, String title) {
|
||||||
mCurrentTitle = title;
|
mCurrentTitle = title;
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.mozilla.gecko.util.ThreadUtils;
|
||||||
import org.mozilla.gecko.widget.AnchoredPopup;
|
import org.mozilla.gecko.widget.AnchoredPopup;
|
||||||
import org.mozilla.gecko.widget.DoorHanger;
|
import org.mozilla.gecko.widget.DoorHanger;
|
||||||
import org.mozilla.gecko.widget.DoorHanger.OnButtonClickListener;
|
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 org.mozilla.geckoview.GeckoView;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
|
|
@ -53,8 +53,8 @@ import org.mozilla.geckoview.GeckoView;
|
||||||
|
|
||||||
public class WebAppActivity extends AppCompatActivity
|
public class WebAppActivity extends AppCompatActivity
|
||||||
implements ActionModePresenter,
|
implements ActionModePresenter,
|
||||||
GeckoSession.ContentListener,
|
GeckoSession.ContentDelegate,
|
||||||
GeckoSession.NavigationListener {
|
GeckoSession.NavigationDelegate {
|
||||||
private static final String LOGTAG = "WebAppActivity";
|
private static final String LOGTAG = "WebAppActivity";
|
||||||
|
|
||||||
public static final String MANIFEST_PATH = "MANIFEST_PATH";
|
public static final String MANIFEST_PATH = "MANIFEST_PATH";
|
||||||
|
@ -103,9 +103,9 @@ public class WebAppActivity extends AppCompatActivity
|
||||||
mGeckoSession = new GeckoSession();
|
mGeckoSession = new GeckoSession();
|
||||||
mGeckoView.setSession(mGeckoSession);
|
mGeckoView.setSession(mGeckoSession);
|
||||||
|
|
||||||
mGeckoSession.setNavigationListener(this);
|
mGeckoSession.setNavigationDelegate(this);
|
||||||
mGeckoSession.setContentListener(this);
|
mGeckoSession.setContentDelegate(this);
|
||||||
mGeckoSession.setProgressListener(new GeckoSession.ProgressListener() {
|
mGeckoSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
|
||||||
@Override
|
@Override
|
||||||
public void onPageStart(GeckoSession session, String url) {
|
public void onPageStart(GeckoSession session, String url) {
|
||||||
|
|
||||||
|
@ -332,36 +332,36 @@ public class WebAppActivity extends AppCompatActivity
|
||||||
mGeckoView.getSettings().setInt(GeckoSessionSettings.DISPLAY_MODE, mode);
|
mGeckoView.getSettings().setInt(GeckoSessionSettings.DISPLAY_MODE, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.NavigationListener
|
@Override // GeckoSession.NavigationDelegate
|
||||||
public void onLocationChange(GeckoSession session, String url) {
|
public void onLocationChange(GeckoSession session, String url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.NavigationListener
|
@Override // GeckoSession.NavigationDelegate
|
||||||
public void onCanGoBack(GeckoSession session, boolean canGoBack) {
|
public void onCanGoBack(GeckoSession session, boolean canGoBack) {
|
||||||
mCanGoBack = canGoBack;
|
mCanGoBack = canGoBack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.NavigationListener
|
@Override // GeckoSession.NavigationDelegate
|
||||||
public void onCanGoForward(GeckoSession session, boolean canGoForward) {
|
public void onCanGoForward(GeckoSession session, boolean canGoForward) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onTitleChange(GeckoSession session, String title) {
|
public void onTitleChange(GeckoSession session, String title) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onFocusRequest(GeckoSession session) {
|
public void onFocusRequest(GeckoSession session) {
|
||||||
Intent intent = new Intent(getIntent());
|
Intent intent = new Intent(getIntent());
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onCloseRequest(GeckoSession session) {
|
public void onCloseRequest(GeckoSession session) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onContextMenu(GeckoSession session, int screenX, int screenY,
|
public void onContextMenu(GeckoSession session, int screenX, int screenY,
|
||||||
String uri, String elementSrc) {
|
String uri, String elementSrc) {
|
||||||
final String content = uri != null ? uri : elementSrc != null ? elementSrc : "";
|
final String content = uri != null ? uri : elementSrc != null ? elementSrc : "";
|
||||||
|
@ -373,7 +373,7 @@ public class WebAppActivity extends AppCompatActivity
|
||||||
WebApps.openInFennec(validUri, WebAppActivity.this);
|
WebApps.openInFennec(validUri, WebAppActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // GeckoSession.ContentListener
|
@Override // GeckoSession.ContentDelegate
|
||||||
public void onFullScreen(GeckoSession session, boolean fullScreen) {
|
public void onFullScreen(GeckoSession session, boolean fullScreen) {
|
||||||
updateFullScreenContent(fullScreen);
|
updateFullScreenContent(fullScreen);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class BaseGeckoViewTest {
|
||||||
|
|
||||||
protected void loadTestPage(final String url, final Runnable finished) {
|
protected void loadTestPage(final String url, final Runnable finished) {
|
||||||
final String path = Uri.parse(url).getPath();
|
final String path = Uri.parse(url).getPath();
|
||||||
mSession.setProgressListener(new GeckoSession.ProgressListener() {
|
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
|
||||||
@Override
|
@Override
|
||||||
public void onPageStart(GeckoSession session, String loadingUrl) {
|
public void onPageStart(GeckoSession session, String loadingUrl) {
|
||||||
assertTrue("Loaded url should end with " + path, loadingUrl.endsWith(path));
|
assertTrue("Loaded url should end with " + path, loadingUrl.endsWith(path));
|
||||||
|
@ -72,7 +72,7 @@ public class BaseGeckoViewTest {
|
||||||
@Override
|
@Override
|
||||||
public void onPageStop(GeckoSession session, boolean success) {
|
public void onPageStop(GeckoSession session, boolean success) {
|
||||||
assertTrue("Load should succeed", success);
|
assertTrue("Load should succeed", success);
|
||||||
mSession.setProgressListener(null);
|
mSession.setProgressDelegate(null);
|
||||||
finished.run();
|
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
|
* 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.
|
* callbacks.
|
||||||
*/
|
*/
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@ -75,9 +75,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
@Test fun includesAllCallbacks() {
|
@Test fun includesAllCallbacks() {
|
||||||
for (ifce in GeckoSession::class.java.classes) {
|
for (ifce in GeckoSession::class.java.classes) {
|
||||||
if (!ifce.isInterface || (
|
if (!ifce.isInterface || !ifce.simpleName.endsWith("Delegate")) {
|
||||||
!ifce.simpleName.endsWith("Listener") &&
|
|
||||||
!ifce.simpleName.endsWith("Delegate"))) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
assertThat("Callbacks.All should include interface " + ifce.simpleName,
|
assertThat("Callbacks.All should include interface " + ifce.simpleName,
|
||||||
|
@ -91,7 +89,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
|
@ -102,7 +100,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
@Test(expected = AssertionError::class)
|
@Test(expected = AssertionError::class)
|
||||||
fun waitForPageStop_throwOnChangedCallback() {
|
fun waitForPageStop_throwOnChangedCallback() {
|
||||||
sessionRule.session.progressListener = Callbacks.Default
|
sessionRule.session.progressDelegate = Callbacks.Default
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
}
|
}
|
||||||
|
@ -114,7 +112,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
|
@ -125,11 +123,11 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
@Test fun waitUntilCalled_anyInterfaceMethod() {
|
@Test fun waitUntilCalled_anyInterfaceMethod() {
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitUntilCalled(GeckoSession.ProgressListener::class)
|
sessionRule.waitUntilCalled(GeckoSession.ProgressDelegate::class)
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
|
@ -139,7 +137,7 @@ class GeckoSessionTestRuleTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSecurityChange(session: GeckoSession,
|
override fun onSecurityChange(session: GeckoSession,
|
||||||
securityInfo: GeckoSession.ProgressListener.SecurityInformation) {
|
securityInfo: GeckoSession.ProgressDelegate.SecurityInformation) {
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -149,12 +147,12 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
@Test fun waitUntilCalled_specificInterfaceMethod() {
|
@Test fun waitUntilCalled_specificInterfaceMethod() {
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitUntilCalled(GeckoSession.ProgressListener::class,
|
sessionRule.waitUntilCalled(GeckoSession.ProgressDelegate::class,
|
||||||
"onPageStart", "onPageStop")
|
"onPageStart", "onPageStop")
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
|
@ -178,7 +176,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.waitUntilCalled(object : Callbacks.ProgressListener {
|
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
|
@ -188,7 +186,7 @@ class GeckoSessionTestRuleTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSecurityChange(session: GeckoSession,
|
override fun onSecurityChange(session: GeckoSession,
|
||||||
securityInfo: GeckoSession.ProgressListener.SecurityInformation) {
|
securityInfo: GeckoSession.ProgressDelegate.SecurityInformation) {
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -201,7 +199,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.waitUntilCalled(object : Callbacks.ProgressListener {
|
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled
|
@AssertCalled
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
|
@ -222,7 +220,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.waitUntilCalled(object : Callbacks.ProgressListener {
|
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 2)
|
@AssertCalled(count = 2)
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
|
@ -243,7 +241,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.waitUntilCalled(object : Callbacks.ProgressListener {
|
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 2, order = intArrayOf(1, 2))
|
@AssertCalled(count = 2, order = intArrayOf(1, 2))
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
val info = sessionRule.currentCall
|
val info = sessionRule.currentCall
|
||||||
|
@ -265,7 +263,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
|
@ -279,7 +277,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(GeckoSession.ScrollListener { _, _, _ -> })
|
sessionRule.forCallbacksDuringWait(GeckoSession.ScrollDelegate { _, _, _ -> })
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun forCallbacksDuringWait_specificMethod() {
|
@Test fun forCallbacksDuringWait_specificMethod() {
|
||||||
|
@ -288,7 +286,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled
|
@AssertCalled
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
|
@ -310,7 +308,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled
|
@AssertCalled
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
|
@ -331,7 +329,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(
|
sessionRule.forCallbacksDuringWait(
|
||||||
GeckoSession.ScrollListener @AssertCalled { _, _, _ -> })
|
GeckoSession.ScrollDelegate @AssertCalled { _, _, _ -> })
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun forCallbacksDuringWait_specificCount() {
|
@Test fun forCallbacksDuringWait_specificCount() {
|
||||||
|
@ -341,7 +339,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 2)
|
@AssertCalled(count = 2)
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
|
@ -362,7 +360,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.session.reload()
|
sessionRule.session.reload()
|
||||||
sessionRule.waitForPageStops(2)
|
sessionRule.waitForPageStops(2)
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1)
|
@AssertCalled(count = 1)
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
}
|
}
|
||||||
|
@ -377,7 +375,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(order = intArrayOf(1))
|
@AssertCalled(order = intArrayOf(1))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
}
|
}
|
||||||
|
@ -393,7 +391,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(order = intArrayOf(2))
|
@AssertCalled(order = intArrayOf(2))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
}
|
}
|
||||||
|
@ -409,7 +407,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.session.reload()
|
sessionRule.session.reload()
|
||||||
sessionRule.waitForPageStops(2)
|
sessionRule.waitForPageStops(2)
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(order = intArrayOf(1, 3, 1))
|
@AssertCalled(order = intArrayOf(1, 3, 1))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
}
|
}
|
||||||
|
@ -426,7 +424,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.session.reload()
|
sessionRule.session.reload()
|
||||||
sessionRule.waitForPageStops(2)
|
sessionRule.waitForPageStops(2)
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(order = intArrayOf(1, 2, 1))
|
@AssertCalled(order = intArrayOf(1, 2, 1))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
}
|
}
|
||||||
|
@ -442,7 +440,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(
|
sessionRule.forCallbacksDuringWait(
|
||||||
GeckoSession.ScrollListener @AssertCalled(false) { _, _, _ -> })
|
GeckoSession.ScrollDelegate @AssertCalled(false) { _, _, _ -> })
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = AssertionError::class)
|
@Test(expected = AssertionError::class)
|
||||||
|
@ -450,7 +448,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(false)
|
@AssertCalled(false)
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
}
|
}
|
||||||
|
@ -472,7 +470,7 @@ class GeckoSessionTestRuleTest {
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
// assert should only apply to callbacks within range (loadUri, first reload].
|
// assert should only apply to callbacks within range (loadUri, first reload].
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1)
|
@AssertCalled(count = 1)
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
|
@ -491,7 +489,7 @@ class GeckoSessionTestRuleTest {
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1)
|
@AssertCalled(count = 1)
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
val info = sessionRule.currentCall
|
val info = sessionRule.currentCall
|
||||||
|
@ -512,7 +510,7 @@ class GeckoSessionTestRuleTest {
|
||||||
@Test fun delegateUntilTestEnd() {
|
@Test fun delegateUntilTestEnd() {
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener {
|
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
|
@ -532,19 +530,19 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
@Test fun delegateUntilTestEnd_notCalled() {
|
@Test fun delegateUntilTestEnd_notCalled() {
|
||||||
sessionRule.delegateUntilTestEnd(
|
sessionRule.delegateUntilTestEnd(
|
||||||
GeckoSession.ScrollListener @AssertCalled(false) { _, _, _ -> })
|
GeckoSession.ScrollDelegate @AssertCalled(false) { _, _, _ -> })
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = AssertionError::class)
|
@Test(expected = AssertionError::class)
|
||||||
fun delegateUntilTestEnd_throwOnNotCalled() {
|
fun delegateUntilTestEnd_throwOnNotCalled() {
|
||||||
sessionRule.delegateUntilTestEnd(
|
sessionRule.delegateUntilTestEnd(
|
||||||
GeckoSession.ScrollListener @AssertCalled(count = 1) { _, _, _ -> })
|
GeckoSession.ScrollDelegate @AssertCalled(count = 1) { _, _, _ -> })
|
||||||
sessionRule.performTestEndCheck()
|
sessionRule.performTestEndCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = AssertionError::class)
|
@Test(expected = AssertionError::class)
|
||||||
fun delegateUntilTestEnd_throwOnCallingNoCall() {
|
fun delegateUntilTestEnd_throwOnCallingNoCall() {
|
||||||
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener {
|
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(false)
|
@AssertCalled(false)
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
}
|
}
|
||||||
|
@ -556,7 +554,7 @@ class GeckoSessionTestRuleTest {
|
||||||
|
|
||||||
@Test(expected = AssertionError::class)
|
@Test(expected = AssertionError::class)
|
||||||
fun delegateUntilTestEnd_throwOnWrongOrder() {
|
fun delegateUntilTestEnd_throwOnWrongOrder() {
|
||||||
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener {
|
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(2))
|
@AssertCalled(count = 1, order = intArrayOf(2))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
}
|
}
|
||||||
|
@ -571,7 +569,7 @@ class GeckoSessionTestRuleTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun delegateUntilTestEnd_currentCall() {
|
@Test fun delegateUntilTestEnd_currentCall() {
|
||||||
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener {
|
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1)
|
@AssertCalled(count = 1)
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
val info = sessionRule.currentCall
|
val info = sessionRule.currentCall
|
||||||
|
@ -590,7 +588,7 @@ class GeckoSessionTestRuleTest {
|
||||||
@Test fun delegateDuringNextWait() {
|
@Test fun delegateDuringNextWait() {
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
sessionRule.delegateDuringNextWait(object : Callbacks.ProgressListener {
|
sessionRule.delegateDuringNextWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
counter++
|
counter++
|
||||||
|
@ -616,7 +614,7 @@ class GeckoSessionTestRuleTest {
|
||||||
@Test(expected = AssertionError::class)
|
@Test(expected = AssertionError::class)
|
||||||
fun delegateDuringNextWait_throwOnNotCalled() {
|
fun delegateDuringNextWait_throwOnNotCalled() {
|
||||||
sessionRule.delegateDuringNextWait(
|
sessionRule.delegateDuringNextWait(
|
||||||
GeckoSession.ScrollListener @AssertCalled(count = 1) { _, _, _ -> })
|
GeckoSession.ScrollDelegate @AssertCalled(count = 1) { _, _, _ -> })
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
}
|
}
|
||||||
|
@ -624,7 +622,7 @@ class GeckoSessionTestRuleTest {
|
||||||
@Test(expected = AssertionError::class)
|
@Test(expected = AssertionError::class)
|
||||||
fun delegateDuringNextWait_throwOnNotCalledAtTestEnd() {
|
fun delegateDuringNextWait_throwOnNotCalledAtTestEnd() {
|
||||||
sessionRule.delegateDuringNextWait(
|
sessionRule.delegateDuringNextWait(
|
||||||
GeckoSession.ScrollListener @AssertCalled(count = 1) { _, _, _ -> })
|
GeckoSession.ScrollDelegate @AssertCalled(count = 1) { _, _, _ -> })
|
||||||
sessionRule.performTestEndCheck()
|
sessionRule.performTestEndCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,8 +630,8 @@ class GeckoSessionTestRuleTest {
|
||||||
var testCounter = 0
|
var testCounter = 0
|
||||||
var waitCounter = 0
|
var waitCounter = 0
|
||||||
|
|
||||||
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressListener,
|
sessionRule.delegateUntilTestEnd(object : Callbacks.ProgressDelegate,
|
||||||
Callbacks.NavigationListener {
|
Callbacks.NavigationDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(2))
|
@AssertCalled(count = 1, order = intArrayOf(2))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
testCounter++
|
testCounter++
|
||||||
|
@ -655,7 +653,7 @@ class GeckoSessionTestRuleTest {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
sessionRule.delegateDuringNextWait(object : Callbacks.ProgressListener {
|
sessionRule.delegateDuringNextWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
waitCounter++
|
waitCounter++
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class NavigationListenerTest {
|
class NavigationDelegateTest {
|
||||||
companion object {
|
companion object {
|
||||||
const val HELLO_HTML_PATH = "/assets/www/hello.html";
|
const val HELLO_HTML_PATH = "/assets/www/hello.html";
|
||||||
const val HELLO2_HTML_PATH = "/assets/www/hello2.html";
|
const val HELLO2_HTML_PATH = "/assets/www/hello2.html";
|
||||||
|
@ -39,16 +39,16 @@ class NavigationListenerTest {
|
||||||
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||||
override fun onLoadUri(session: GeckoSession, uri: String,
|
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("Session should not be null", session, notNullValue())
|
||||||
assertThat("URI should not be null", uri, notNullValue())
|
assertThat("URI should not be null", uri, notNullValue())
|
||||||
assertThat("URI should match", uri, endsWith(HELLO_HTML_PATH))
|
assertThat("URI should match", uri, endsWith(HELLO_HTML_PATH))
|
||||||
assertThat("Where should not be null", where, notNullValue())
|
assertThat("Where should not be null", where, notNullValue())
|
||||||
assertThat("Where should match", where,
|
assertThat("Where should match", where,
|
||||||
equalTo(GeckoSession.NavigationListener.TargetWindow.CURRENT))
|
equalTo(GeckoSession.NavigationDelegate.TargetWindow.CURRENT))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,13 +85,13 @@ class NavigationListenerTest {
|
||||||
sessionRule.session.reload()
|
sessionRule.session.reload()
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||||
override fun onLoadUri(session: GeckoSession, uri: String,
|
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("URI should match", uri, endsWith(HELLO_HTML_PATH))
|
||||||
assertThat("Where should match", where,
|
assertThat("Where should match", where,
|
||||||
equalTo(GeckoSession.NavigationListener.TargetWindow.CURRENT))
|
equalTo(GeckoSession.NavigationDelegate.TargetWindow.CURRENT))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ class NavigationListenerTest {
|
||||||
sessionRule.session.loadTestPath(HELLO2_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO2_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
|
||||||
@AssertCalled(count = 1)
|
@AssertCalled(count = 1)
|
||||||
override fun onLocationChange(session: GeckoSession, url: String) {
|
override fun onLocationChange(session: GeckoSession, url: String) {
|
||||||
assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH))
|
assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH))
|
||||||
|
@ -134,13 +134,13 @@ class NavigationListenerTest {
|
||||||
sessionRule.session.goBack()
|
sessionRule.session.goBack()
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||||
override fun onLoadUri(session: GeckoSession, uri: String,
|
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("URI should match", uri, endsWith(HELLO_HTML_PATH))
|
||||||
assertThat("Where should match", where,
|
assertThat("Where should match", where,
|
||||||
equalTo(GeckoSession.NavigationListener.TargetWindow.CURRENT))
|
equalTo(GeckoSession.NavigationDelegate.TargetWindow.CURRENT))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,13 +168,13 @@ class NavigationListenerTest {
|
||||||
sessionRule.session.goForward()
|
sessionRule.session.goForward()
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||||
override fun onLoadUri(session: GeckoSession, uri: String,
|
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("URI should match", uri, endsWith(HELLO2_HTML_PATH))
|
||||||
assertThat("Where should match", where,
|
assertThat("Where should match", where,
|
||||||
equalTo(GeckoSession.NavigationListener.TargetWindow.CURRENT))
|
equalTo(GeckoSession.NavigationDelegate.TargetWindow.CURRENT))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,10 +201,10 @@ class NavigationListenerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun onLoadUri_returnTrueCancelsLoad() {
|
@Test fun onLoadUri_returnTrueCancelsLoad() {
|
||||||
sessionRule.delegateDuringNextWait(object : Callbacks.NavigationListener {
|
sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
|
||||||
@AssertCalled(count = 2)
|
@AssertCalled(count = 2)
|
||||||
override fun onLoadUri(session: GeckoSession, uri: String,
|
override fun onLoadUri(session: GeckoSession, uri: String,
|
||||||
where: GeckoSession.NavigationListener.TargetWindow): Boolean {
|
where: GeckoSession.NavigationDelegate.TargetWindow): Boolean {
|
||||||
return uri.endsWith(HELLO_HTML_PATH)
|
return uri.endsWith(HELLO_HTML_PATH)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -213,7 +213,7 @@ class NavigationListenerTest {
|
||||||
sessionRule.session.loadTestPath(HELLO2_HTML_PATH)
|
sessionRule.session.loadTestPath(HELLO2_HTML_PATH)
|
||||||
sessionRule.waitForPageStop()
|
sessionRule.waitForPageStop()
|
||||||
|
|
||||||
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressListener {
|
sessionRule.forCallbacksDuringWait(object : Callbacks.ProgressDelegate {
|
||||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||||
override fun onPageStart(session: GeckoSession, url: String) {
|
override fun onPageStart(session: GeckoSession, url: String) {
|
||||||
assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH))
|
assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH))
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class NavigationTests extends BaseGeckoViewTest {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
loadTestPath("hello2.html", new Runnable() {
|
loadTestPath("hello2.html", new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
mSession.setNavigationListener(new GeckoSession.NavigationListener() {
|
mSession.setNavigationDelegate(new GeckoSession.NavigationDelegate() {
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChange(GeckoSession session, String url) {
|
public void onLocationChange(GeckoSession session, String url) {
|
||||||
assertTrue("URL should end with " + startPath + ", got " + url, url.endsWith(startPath));
|
assertTrue("URL should end with " + startPath + ", got " + url, url.endsWith(startPath));
|
||||||
|
@ -78,7 +78,7 @@ public class NavigationTests extends BaseGeckoViewTest {
|
||||||
public void testReload() {
|
public void testReload() {
|
||||||
loadTestPath("hello.html", new Runnable() {
|
loadTestPath("hello.html", new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
mSession.setProgressListener(new GeckoSession.ProgressListener() {
|
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
|
||||||
@Override
|
@Override
|
||||||
public void onPageStart(GeckoSession session, String url) {
|
public void onPageStart(GeckoSession session, String url) {
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ public class NavigationTests extends BaseGeckoViewTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpiredCert() {
|
public void testExpiredCert() {
|
||||||
mSession.setProgressListener(new GeckoSession.ProgressListener() {
|
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
|
||||||
private boolean mNotBlank;
|
private boolean mNotBlank;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -133,7 +133,7 @@ public class NavigationTests extends BaseGeckoViewTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidTLS() {
|
public void testValidTLS() {
|
||||||
mSession.setProgressListener(new GeckoSession.ProgressListener() {
|
mSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
|
||||||
private boolean mNotBlank;
|
private boolean mNotBlank;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -162,7 +162,7 @@ public class NavigationTests extends BaseGeckoViewTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnNewSession() {
|
public void testOnNewSession() {
|
||||||
mSession.setNavigationListener(new GeckoSession.NavigationListener() {
|
mSession.setNavigationDelegate(new GeckoSession.NavigationDelegate() {
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChange(GeckoSession session, String url) {
|
public void onLocationChange(GeckoSession session, String url) {
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ public class NavigationTests extends BaseGeckoViewTest {
|
||||||
@Override
|
@Override
|
||||||
public void onNewSession(GeckoSession session, String uri, GeckoSession.Response<GeckoSession> response) {
|
public void onNewSession(GeckoSession session, String uri, GeckoSession.Response<GeckoSession> response) {
|
||||||
final GeckoSession newSession = new GeckoSession(session.getSettings());
|
final GeckoSession newSession = new GeckoSession(session.getSettings());
|
||||||
newSession.setContentListener(new GeckoSession.ContentListener() {
|
newSession.setContentDelegate(new GeckoSession.ContentDelegate() {
|
||||||
@Override
|
@Override
|
||||||
public void onTitleChange(GeckoSession session, String title) {
|
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
|
@Override
|
||||||
public void onPageStart(GeckoSession session, String url) {
|
public void onPageStart(GeckoSession session, String url) {
|
||||||
|
|
||||||
|
@ -245,10 +245,10 @@ public class NavigationTests extends BaseGeckoViewTest {
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testOnNewSessionNoExisting() {
|
public void testOnNewSessionNoExisting() {
|
||||||
// This makes sure that we get an exception if you try to return
|
// 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.
|
// implementation.
|
||||||
|
|
||||||
mSession.setNavigationListener(new GeckoSession.NavigationListener() {
|
mSession.setNavigationDelegate(new GeckoSession.NavigationDelegate() {
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChange(GeckoSession session, String url) {
|
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
|
@Override
|
||||||
public void onPageStart(GeckoSession session, String url) {
|
public void onPageStart(GeckoSession session, String url) {
|
||||||
|
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче