Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Noemi Erli 2018-06-01 00:58:09 +03:00
Родитель de808cbccf 54db5253b6
Коммит 614b78ae36
162 изменённых файлов: 2887 добавлений и 1296 удалений

4
Cargo.lock сгенерированный
Просмотреть файл

@ -2361,15 +2361,19 @@ name = "webrender_bindings"
version = "0.1.0"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nsstring 0.1.0",
"rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender 0.57.2",
]

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

@ -1253,15 +1253,6 @@ nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
// static
nsIPrincipal*
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
{
JSCompartment *compartment = js::GetObjectCompartment(aObj);
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
return nsJSPrincipals::get(principals);
}
NS_IMETHODIMP
nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
const nsIID &aIID,

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

@ -93,10 +93,6 @@ private:
static bool
JSPrincipalsSubsume(JSPrincipals *first, JSPrincipals *second);
// Returns null if a principal cannot be found; generally callers
// should error out at that point.
static nsIPrincipal* doGetObjectPrincipal(JSObject* obj);
nsresult
Init();

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

@ -1,9 +1,9 @@
This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html
Version 60
Version 61
Comparison: https://github.com/devtools-html/debugger.html/compare/release-59...release-60
Comparison: https://github.com/devtools-html/debugger.html/compare/release-60...release-61
Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.2

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

@ -2117,6 +2117,10 @@ menuseparator {
padding: 0 2px;
}
.objectBox-node.clickable {
cursor: pointer;
}
/******************************************************************************/
.objectBox-event,
@ -2223,6 +2227,7 @@ button.open-inspector {
height: 16px;
margin-left: 0.25em;
vertical-align: middle;
cursor: pointer;
}
.objectBox-node:hover .open-inspector,

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

@ -1222,7 +1222,7 @@ function isYieldExpression(path) {
}
function isObjectShorthand(parent) {
return t.isObjectProperty(parent) && parent.key.start == parent.value.start && parent.key.loc.identifierName === parent.value.loc.identifierName;
return t.isObjectProperty(parent) && parent.value && parent.key.start == parent.value.start && parent.key.loc.identifierName === parent.value.loc.identifierName;
}
function getObjectExpressionValue(node) {

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

@ -8174,7 +8174,7 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
// (eg. "my-module/Test") which is why they are nested in "vendored".
// The keys of the vendored object should match the module names
// !!! Should remain synchronized with .babel/transform-mc.js !!!
const vendored = {
const vendored = exports.vendored = {
classnames: _classnames2.default,
"devtools-components": devtoolsComponents,
"devtools-config": devtoolsConfig,
@ -8210,7 +8210,6 @@ const vendored = {
*/
// Modules imported with destructuring
exports.vendored = vendored;
/***/ }),

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

@ -91,7 +91,7 @@ function getExtra(expression, result) {
const selectedFrame = (0, _selectors.getSelectedFrame)(getState());
if (!selectedFrame) {
return;
return {};
}
const extra = await getExtraProps(getState, expression, result, expr => client.evaluateInFrame(expr, selectedFrame.id));

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

@ -3,7 +3,7 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.onConnect = undefined;
exports.onConnect = onConnect;
var _firefox = require("./firefox");
@ -68,6 +68,4 @@ async function onConnect(connection, {
selectors,
client: commands
};
}
exports.onConnect = onConnect;
}

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

@ -237,7 +237,7 @@ class Popup extends _react.Component {
roots = roots.filter(r => r.type != NODE_TYPES.PROTOTYPE);
}
if ((0, _preview.isReactComponent)(this.getObjectProperties())) {
if (extra.react && (0, _preview.isReactComponent)(this.getObjectProperties())) {
header = this.renderReact(extra.react);
roots = roots.filter(r => ["state", "props"].includes(r.name));
}

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

@ -124,6 +124,18 @@ class SourcesTree extends _react.Component {
}
}
// NOTE: we get the source from sources because item.contents is cached
getSource(item) {
return this.props.sources.get(item.contents.id);
}
isEmpty() {
const {
sourceTree
} = this.state;
return sourceTree.contents.length === 0;
}
renderItemName(name) {
const hosts = {
"ng://": "Angular",
@ -135,69 +147,56 @@ class SourcesTree extends _react.Component {
renderEmptyElement(message) {
return _react2.default.createElement("div", {
key: "empty",
className: "no-sources-message"
}, message);
}
render() {
renderProjectRootHeader() {
const {
expanded,
projectRoot
} = this.props;
const {
focusedItem,
highlightItems,
listItems,
parentMap,
sourceTree
} = this.state;
const onExpand = (item, expandedState) => {
this.props.setExpandedState(expandedState);
};
const onCollapse = (item, expandedState) => {
this.props.setExpandedState(expandedState);
};
const isEmpty = sourceTree.contents.length === 0;
const isCustomRoot = projectRoot !== "";
let roots = () => sourceTree.contents;
let clearProjectRootButton = null; // The "sourceTree.contents[0]" check ensures that there are contents
// A custom root with no existing sources will be ignored
if (isCustomRoot) {
const sourceContents = sourceTree.contents[0];
let rootLabel = projectRoot.split("/").pop();
roots = () => sourceContents.contents;
if (sourceContents && sourceContents.name !== rootLabel) {
rootLabel = sourceContents.contents[0].name;
roots = () => sourceContents.contents[0].contents;
}
clearProjectRootButton = _react2.default.createElement("button", {
className: "sources-clear-root",
onClick: () => this.props.clearProjectDirectoryRoot(),
title: L10N.getStr("removeDirectoryRoot.label")
}, _react2.default.createElement(_Svg2.default, {
name: "home"
}), _react2.default.createElement(_Svg2.default, {
name: "breadcrumb",
"class": true
}), _react2.default.createElement("span", {
className: "sources-clear-root-label"
}, rootLabel));
if (!projectRoot) {
return null;
}
if (isEmpty && !isCustomRoot) {
return this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailable"));
const sourceContents = sourceTree.contents[0];
let rootLabel = projectRoot.split("/").pop();
if (sourceContents && sourceContents.name !== rootLabel) {
rootLabel = sourceContents.contents[0].name;
}
return _react2.default.createElement("div", {
key: "root",
className: "sources-clear-root-container"
}, _react2.default.createElement("button", {
className: "sources-clear-root",
onClick: () => this.props.clearProjectDirectoryRoot(),
title: L10N.getStr("removeDirectoryRoot.label")
}, _react2.default.createElement(_Svg2.default, {
name: "home"
}), _react2.default.createElement(_Svg2.default, {
name: "breadcrumb",
"class": true
}), _react2.default.createElement("span", {
className: "sources-clear-root-label"
}, rootLabel)));
}
renderTree() {
const {
expanded
} = this.props;
const {
highlightItems,
listItems,
parentMap
} = this.state;
const treeProps = {
autoExpandAll: false,
autoExpandDepth: expanded ? 0 : 1,
@ -205,35 +204,49 @@ class SourcesTree extends _react.Component {
getChildren: item => (0, _sourcesTree.nodeHasChildren)(item) ? item.contents : [],
getParent: item => parentMap.get(item),
getPath: this.getPath,
getRoots: roots,
getRoots: this.getRoots,
highlightItems,
itemHeight: 21,
key: isEmpty ? "empty" : "full",
key: this.isEmpty() ? "empty" : "full",
listItems,
onCollapse,
onExpand,
onCollapse: this.onCollapse,
onExpand: this.onExpand,
onFocus: this.focusItem,
renderItem: this.renderItem
};
return _react2.default.createElement(_ManagedTree2.default, treeProps);
}
const tree = _react2.default.createElement(_ManagedTree2.default, treeProps);
const onKeyDown = e => {
if (e.keyCode === 13 && focusedItem) {
this.selectItem(focusedItem);
}
};
renderPane(...children) {
const {
projectRoot
} = this.props;
return _react2.default.createElement("div", {
key: "pane",
className: (0, _classnames2.default)("sources-pane", {
"sources-list-custom-root": isCustomRoot
"sources-list-custom-root": projectRoot
})
}, isCustomRoot ? _react2.default.createElement("div", {
className: "sources-clear-root-container"
}, clearProjectRootButton) : null, isEmpty ? this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailableRoot")) : _react2.default.createElement("div", {
}, children);
}
render() {
const {
projectRoot
} = this.props;
if (this.isEmpty()) {
if (projectRoot) {
return this.renderPane(this.renderProjectRootHeader(), this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailableRoot")));
}
return this.renderPane(this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailable")));
}
return this.renderPane(this.renderProjectRootHeader(), _react2.default.createElement("div", {
key: "tree",
className: "sources-list",
onKeyDown: onKeyDown
}, tree));
onKeyDown: this.onKeyDown
}, this.renderTree()));
}
}
@ -246,25 +259,21 @@ var _initialiseProps = function () {
};
this.selectItem = item => {
if (!(0, _sourcesTree.nodeHasChildren)(item)) {
this.props.selectLocation({
sourceId: item.contents.get("id")
});
if (!(0, _sourcesTree.isDirectory)(item)) {
this.props.selectSource(item.contents.id);
}
};
this.getPath = item => {
const {
sources
} = this.props;
const obj = item.contents.get && item.contents.get("id");
let blackBoxedPart = "";
const path = `${item.path}/${item.name}`;
if (typeof obj !== "undefined" && sources.has(obj) && sources.get(obj).get("isBlackBoxed")) {
blackBoxedPart = "update";
if ((0, _sourcesTree.isDirectory)(item)) {
return path;
}
return `${item.path}/${item.name}/${blackBoxedPart}`;
const source = this.getSource(item);
const blackBoxedPart = source.isBlackBoxed ? ":blackboxed" : "";
return `${path}${blackBoxedPart}`;
};
this.getIcon = (sources, item, depth) => {
@ -295,17 +304,15 @@ var _initialiseProps = function () {
});
}
if (!(0, _sourcesTree.nodeHasChildren)(item)) {
const obj = item.contents.get("id");
const source = sources.get(obj);
const className = (0, _classnames2.default)((0, _source.getSourceClassnames)(source), "source-icon");
if ((0, _sourcesTree.isDirectory)(item)) {
return _react2.default.createElement("img", {
className: className
className: "folder"
});
}
const source = this.getSource(item);
return _react2.default.createElement("img", {
className: "folder"
className: (0, _classnames2.default)((0, _source.getSourceClassnames)(source), "source-icon")
});
};
@ -320,13 +327,12 @@ var _initialiseProps = function () {
const menuOptions = [];
if (!(0, _sourcesTree.isDirectory)(item)) {
const source = item.contents.get("url");
const copySourceUri2 = {
id: "node-menu-copy-source",
label: copySourceUri2Label,
accesskey: copySourceUri2Key,
disabled: false,
click: () => (0, _clipboard.copyToTheClipboard)(source)
click: () => (0, _clipboard.copyToTheClipboard)(item.contents.url)
};
menuOptions.push(copySourceUri2);
}
@ -360,6 +366,24 @@ var _initialiseProps = function () {
(0, _devtoolsContextmenu.showMenu)(event, menuOptions);
};
this.onExpand = (item, expandedState) => {
this.props.setExpandedState(expandedState);
};
this.onCollapse = (item, expandedState) => {
this.props.setExpandedState(expandedState);
};
this.onKeyDown = e => {
const {
focusedItem
} = this.state;
if (e.keyCode === 13 && focusedItem) {
this.selectItem(focusedItem);
}
};
this.renderItem = (item, depth, focused, _, expanded, {
setExpanded
}) => {
@ -393,6 +417,28 @@ var _initialiseProps = function () {
className: "label"
}, " ", this.renderItemName(item.name), " "));
};
this.getRoots = () => {
const {
projectRoot
} = this.props;
const {
sourceTree
} = this.state;
const sourceContents = sourceTree.contents[0];
const rootLabel = projectRoot.split("/").pop(); // The "sourceTree.contents[0]" check ensures that there are contents
// A custom root with no existing sources will be ignored
if (projectRoot) {
if (sourceContents && sourceContents.name !== rootLabel) {
return sourceContents.contents[0].contents;
}
return sourceContents.contents;
}
return sourceTree.contents;
};
};
const mapStateToProps = state => {
@ -408,7 +454,7 @@ const mapStateToProps = state => {
const actionCreators = {
setExpandedState: _sourceTree.setExpandedState,
selectLocation: _sources.selectLocation,
selectSource: _sources.selectSource,
setProjectDirectoryRoot: _ui.setProjectDirectoryRoot,
clearProjectDirectoryRoot: _ui.clearProjectDirectoryRoot
};

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

@ -3,7 +3,17 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.showLoading = exports.showErrorMessage = exports.showSourceText = exports.clearEditor = exports.updateDocument = exports.updateLineNumberFormat = exports.clearDocuments = exports.removeDocument = exports.hasDocument = exports.setDocument = exports.getDocument = undefined;
exports.getDocument = getDocument;
exports.hasDocument = hasDocument;
exports.setDocument = setDocument;
exports.removeDocument = removeDocument;
exports.clearDocuments = clearDocuments;
exports.updateLineNumberFormat = updateLineNumberFormat;
exports.updateDocument = updateDocument;
exports.clearEditor = clearEditor;
exports.showLoading = showLoading;
exports.showErrorMessage = showErrorMessage;
exports.showSourceText = showSourceText;
var _source = require("../source");
@ -168,16 +178,4 @@ function showSourceText(editor, source, symbols) {
setEditorText(editor, source);
editor.setMode((0, _source.getMode)(source, symbols));
updateLineNumberFormat(editor, source.id);
}
exports.getDocument = getDocument;
exports.setDocument = setDocument;
exports.hasDocument = hasDocument;
exports.removeDocument = removeDocument;
exports.clearDocuments = clearDocuments;
exports.updateLineNumberFormat = updateLineNumberFormat;
exports.updateDocument = updateDocument;
exports.clearEditor = clearEditor;
exports.showSourceText = showSourceText;
exports.showErrorMessage = showErrorMessage;
exports.showLoading = showLoading;
}

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

@ -3,6 +3,11 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.basename = basename;
exports.dirname = dirname;
exports.isURL = isURL;
exports.isAbsolute = isAbsolute;
exports.join = join;
/* 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
@ -26,10 +31,4 @@ function isAbsolute(str) {
function join(base, dir) {
return `${base}/${dir}`;
}
exports.basename = basename;
exports.dirname = dirname;
exports.isURL = isURL;
exports.isAbsolute = isAbsolute;
exports.join = join;
}

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

@ -3,7 +3,7 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.scrollList = undefined;
exports.scrollList = scrollList;
var _devtoolsEnvironment = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-environment"];
@ -53,6 +53,4 @@ function chromeScrollList(elem, index) {
const itemOffset = resultsHeight % itemHeight;
const scroll = positionsToScroll * (itemHeight + 2) + itemOffset;
resultsEl.scrollTop = Math.max(0, scroll);
}
exports.scrollList = scrollList;
}

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

@ -426,17 +426,12 @@ function isLoading(source) {
}
function getTextAtPosition(source, location) {
if (!source || !source.text) {
if (!source || !source.text || source.isWasm) {
return "";
}
const line = location.line;
const column = location.column || 0;
if (source.isWasm) {
return "";
}
const lineText = source.text.split("\n")[line - 1];
if (!lineText) {
@ -466,5 +461,5 @@ function getSourceClassnames(source, sourceMetaData) {
return "blackBox";
}
return sourceTypes[(0, _sourcesTree.getExtension)(source.url)] || defaultClassName;
return sourceTypes[(0, _sourcesTree.getFileExtension)(source.url)] || defaultClassName;
}

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

@ -129,7 +129,7 @@ function addSourceToNode(node, url, source) {
function addToTree(tree, source, debuggeeUrl, projectRoot) {
const url = (0, _getURL.getURL)(source.get("url"), debuggeeUrl);
const url = (0, _getURL.getURL)(source.get ? source.get("url") : source.url, debuggeeUrl);
const debuggeeHost = (0, _treeOrder.getDomain)(debuggeeUrl);
if ((0, _utils.isInvalidUrl)(url, source) || !isUnderRoot(url, projectRoot)) {

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

@ -102,6 +102,12 @@ Object.defineProperty(exports, "createParentMap", {
return _utils.createParentMap;
}
});
Object.defineProperty(exports, "getFileExtension", {
enumerable: true,
get: function () {
return _utils.getFileExtension;
}
});
Object.defineProperty(exports, "getRelativePath", {
enumerable: true,
get: function () {
@ -131,10 +137,4 @@ Object.defineProperty(exports, "nodeHasChildren", {
get: function () {
return _utils.nodeHasChildren;
}
});
Object.defineProperty(exports, "getExtension", {
enumerable: true,
get: function () {
return _utils.getExtension;
}
});

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

@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
exports.nodeHasChildren = nodeHasChildren;
exports.isExactUrlMatch = isExactUrlMatch;
exports.isDirectory = isDirectory;
exports.getExtension = getExtension;
exports.getFileExtension = getFileExtension;
exports.isNotJavaScript = isNotJavaScript;
exports.isInvalidUrl = isInvalidUrl;
exports.partIsFile = partIsFile;
@ -47,7 +47,7 @@ function isDirectory(url) {
return (parts.length === 0 || url.path.slice(-1) === "/" || nodeHasChildren(url)) && url.name != "(index)";
}
function getExtension(url = "") {
function getFileExtension(url = "") {
const parsedUrl = (0, _url.parse)(url).pathname;
if (!parsedUrl) {
@ -58,11 +58,11 @@ function getExtension(url = "") {
}
function isNotJavaScript(source) {
return ["css", "svg", "png"].includes(getExtension(source.url));
return ["css", "svg", "png"].includes(getFileExtension(source.url));
}
function isInvalidUrl(url, source) {
return IGNORED_URLS.indexOf(url) != -1 || !source.get("url") || !url.group || (0, _source.isPretty)(source) || isNotJavaScript(source);
return IGNORED_URLS.indexOf(url) != -1 || !(source.get ? source.get("url") : source.url) || !url.group || (0, _source.isPretty)(source) || isNotJavaScript(source);
}
function partIsFile(index, parts, url) {

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

@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", {
/**
* This object provides the public module functions.
*/
const Task = {
const Task = exports.Task = {
// XXX: Not sure if this works in all cases...
async: function (task) {
return function () {
@ -49,5 +49,4 @@ const Task = {
callNext(undefined);
});
}
};
exports.Task = Task;
};

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

@ -3,7 +3,8 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.truncateMiddleText = exports.formatKeyShortcut = undefined;
exports.formatKeyShortcut = formatKeyShortcut;
exports.truncateMiddleText = truncateMiddleText;
var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
@ -59,7 +60,4 @@ function truncateMiddleText(sourceText, maxLength) {
}
return truncatedText;
}
exports.formatKeyShortcut = formatKeyShortcut;
exports.truncateMiddleText = truncateMiddleText;
}

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

@ -3,6 +3,10 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.handleError = handleError;
exports.promisify = promisify;
exports.endTruncateStr = endTruncateStr;
exports.waitForMs = waitForMs;
/* 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
@ -54,9 +58,4 @@ function endTruncateStr(str, size) {
function waitForMs(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
exports.handleError = handleError;
exports.promisify = promisify;
exports.endTruncateStr = endTruncateStr;
exports.waitForMs = waitForMs;
}

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

@ -3,7 +3,13 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.renderWasmText = exports.clearWasmStates = exports.wasmOffsetToLine = exports.lineToWasmOffset = exports.isWasm = exports.getWasmLineNumberFormatter = exports.getWasmText = undefined;
exports.getWasmText = getWasmText;
exports.getWasmLineNumberFormatter = getWasmLineNumberFormatter;
exports.isWasm = isWasm;
exports.lineToWasmOffset = lineToWasmOffset;
exports.wasmOffsetToLine = wasmOffsetToLine;
exports.clearWasmStates = clearWasmStates;
exports.renderWasmText = renderWasmText;
var _WasmParser = require("devtools/client/shared/vendor/WasmParser");
@ -179,12 +185,4 @@ function renderWasmText(sourceId, {
}
return lines;
}
exports.getWasmText = getWasmText;
exports.getWasmLineNumberFormatter = getWasmLineNumberFormatter;
exports.isWasm = isWasm;
exports.lineToWasmOffset = lineToWasmOffset;
exports.wasmOffsetToLine = wasmOffsetToLine;
exports.clearWasmStates = clearWasmStates;
exports.renderWasmText = renderWasmText;
}

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

@ -56,7 +56,7 @@ function isYieldExpression(path) {
}
function isObjectShorthand(parent) {
return t.isObjectProperty(parent) && parent.key.start == parent.value.start && parent.key.loc.identifierName === parent.value.loc.identifierName;
return t.isObjectProperty(parent) && parent.value && parent.key.start == parent.value.start && parent.key.loc.identifierName === parent.value.loc.identifierName;
}
function getObjectExpressionValue(node) {

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

@ -226,6 +226,10 @@ html[dir="rtl"] .tree-node img.arrow {
padding: 0 2px;
}
.objectBox-node.clickable {
cursor: pointer;
}
/******************************************************************************/
.objectBox-event,
@ -332,6 +336,7 @@ button.open-inspector {
height: 16px;
margin-left: 0.25em;
vertical-align: middle;
cursor: pointer;
}
.objectBox-node:hover .open-inspector,

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

@ -5680,7 +5680,8 @@ function ElementNode(props) {
if (isInTree) {
if (onDOMNodeClick) {
Object.assign(baseConfig, {
onClick: _ => onDOMNodeClick(object)
onClick: _ => onDOMNodeClick(object),
className: `${baseConfig.className} clickable`
});
}

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

@ -503,8 +503,15 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
* A helper method. Accessibility walker is assumed to have only 1 child which
* is the top level document.
*/
children() {
return Promise.all([this.getDocument()]);
async children() {
if (this._childrenPromise) {
return this._childrenPromise;
}
this._childrenPromise = Promise.all([this.getDocument()]);
let children = await this._childrenPromise;
this._childrenPromise = null;
return children;
},
/**

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

@ -162,7 +162,7 @@ SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
if (sm && info->referrer) {
bool referrerIsSecure;
uint32_t flags = nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
uint32_t flags = nsIProtocolHandler::URI_IS_POTENTIALLY_TRUSTWORTHY;
rv = NS_URIChainHasFlags(info->referrer, flags, &referrerIsSecure);
// Default to sending less data if NS_URIChainHasFlags() fails.

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

@ -184,5 +184,17 @@ DocGroup::MoveSignalSlotListTo(nsTArray<RefPtr<HTMLSlotElement>>& aDest)
mSignalSlotList.Clear();
}
bool
DocGroup::IsActive() const
{
for (nsIDocument* doc : mDocuments) {
if (doc->IsCurrentActiveDocument()) {
return true;
}
}
return false;
}
}
}

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

@ -122,6 +122,9 @@ public:
// List of DocGroups that has non-empty signal slot list.
static AutoTArray<RefPtr<DocGroup>, 2>* sPendingDocGroups;
// Returns true if any of its documents are active but not in the bfcache.
bool IsActive() const;
private:
DocGroup(TabGroup* aTabGroup, const nsACString& aKey);
~DocGroup();

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

@ -306,5 +306,22 @@ TabGroup::IsBackground() const
return mForegroundCount == 0;
}
uint32_t
TabGroup::Count(bool aActiveOnly) const
{
if (!aActiveOnly) {
return mDocGroups.Count();
}
uint32_t count = 0;
for (auto iter = mDocGroups.ConstIter(); !iter.Done(); iter.Next()) {
if (iter.Get()->mDocGroup->IsActive()) {
++count;
}
}
return count;
}
} // namespace dom
} // namespace mozilla

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

@ -100,6 +100,10 @@ public:
return mDocGroups.Iter();
}
// Returns the size of the set of "similar-origin" DocGroups. To
// only consider DocGroups with at least one active document, call
// Count with 'aActiveOnly' = true
uint32_t Count(bool aActiveOnly = false) const;
// Returns the nsIDocShellTreeItem with the given name, searching each of the
// docShell trees which are within this TabGroup. It will pass itself as

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

@ -172,7 +172,6 @@
#include "nsIStreamConverterService.h"
#include "nsIStringBundle.h"
#include "nsIURI.h"
#include "nsIURIWithPrincipal.h"
#include "nsIURL.h"
#include "nsIWebNavigation.h"
#include "nsIWindowMediator.h"
@ -3085,12 +3084,12 @@ nsContentUtils::SubjectPrincipal(JSContext* aCx)
MOZ_ASSERT(NS_IsMainThread());
// As opposed to SubjectPrincipal(), we do in fact assume that
// we're in a compartment here; anyone who calls this function
// in situations where that's not the case is doing it wrong.
JSCompartment* compartment = js::GetContextCompartment(aCx);
MOZ_ASSERT(compartment);
// we're in a realm here; anyone who calls this function in
// situations where that's not the case is doing it wrong.
JS::Realm* realm = js::GetContextRealm(aCx);
MOZ_ASSERT(realm);
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
JSPrincipals* principals = JS::GetRealmPrincipals(realm);
return nsJSPrincipals::get(principals);
}
@ -3105,9 +3104,9 @@ nsContentUtils::SubjectPrincipal()
MOZ_CRASH("Accessing the Subject Principal without an AutoJSAPI on the stack is forbidden");
}
JSCompartment *compartment = js::GetContextCompartment(cx);
JS::Realm* realm = js::GetContextRealm(cx);
// When an AutoJSAPI is instantiated, we are in a null compartment until the
// When an AutoJSAPI is instantiated, we are in a null realm until the
// first JSAutoRealm, which is kind of a purgatory as far as permissions
// go. It would be nice to just hard-abort if somebody does a security check
// in this purgatory zone, but that would be too fragile, since it could be
@ -3125,9 +3124,9 @@ nsContentUtils::SubjectPrincipal()
//
// So we use a singleton null principal. To avoid it being accidentally
// inherited and becoming a "real" subject or object principal, we do a
// release-mode assert during compartment creation against using this
// principal on an actual global.
if (!compartment) {
// release-mode assert during realm creation against using this principal on
// an actual global.
if (!realm) {
return sNullSubjectPrincipal;
}
@ -6285,21 +6284,24 @@ nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin)
{
MOZ_ASSERT(aURI, "missing uri");
// For Blob URI we have to return the origin of page using its principal.
nsCOMPtr<nsIURIWithPrincipal> uriWithPrincipal = do_QueryInterface(aURI);
if (uriWithPrincipal) {
nsCOMPtr<nsIPrincipal> principal;
uriWithPrincipal->GetPrincipal(getter_AddRefs(principal));
bool isBlobURL = false;
nsresult rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
NS_ENSURE_SUCCESS(rv, rv);
if (principal) {
nsCOMPtr<nsIURI> uri;
nsresult rv = principal->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
// For Blob URI, the path is the URL of the owning page.
if (isBlobURL) {
nsAutoCString path;
rv = aURI->GetPathQueryRef(path);
NS_ENSURE_SUCCESS(rv, rv);
if (uri && uri != aURI) {
return GetASCIIOrigin(uri, aOrigin);
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), path);
if (NS_FAILED(rv)) {
aOrigin.AssignLiteral("null");
return NS_OK;
}
return GetASCIIOrigin(uri, aOrigin);
}
aOrigin.Truncate();
@ -6308,7 +6310,7 @@ nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin)
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
nsCString host;
nsresult rv = uri->GetAsciiHost(host);
rv = uri->GetAsciiHost(host);
if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
nsCString scheme;

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

@ -2364,9 +2364,9 @@ nsIDocument::ResetToURI(nsIURI* aURI,
mFontFaceSet->RefreshStandardFontLoadPrincipal();
}
// Refresh the principal on the compartment.
// Refresh the principal on the realm.
if (nsPIDOMWindowInner* win = GetInnerWindow()) {
nsGlobalWindowInner::Cast(win)->RefreshCompartmentPrincipal();
nsGlobalWindowInner::Cast(win)->RefreshRealmPrincipal();
}
}
@ -8495,6 +8495,18 @@ static void ClearPendingFullscreenRequests(nsIDocument* aDoc);
void
nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget)
{
if (mDocGroup && Telemetry::CanRecordExtended() &&
IsTopLevelContentDocument()) {
TabGroup* tabGroup = mDocGroup->GetTabGroup();
if (tabGroup) {
Telemetry::Accumulate(Telemetry::ACTIVE_DOCGROUPS_PER_TABGROUP,
tabGroup->Count(true /* aActiveOnly */));
Telemetry::Accumulate(Telemetry::TOTAL_DOCGROUPS_PER_TABGROUP,
tabGroup->Count());
}
}
// Send out notifications that our <link> elements are detached,
// but only if this is not a full unload.
Element* root = GetRootElement();

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

@ -3632,10 +3632,10 @@ nsGlobalWindowInner::GetChildWindow(const nsAString& aName)
}
void
nsGlobalWindowInner::RefreshCompartmentPrincipal()
nsGlobalWindowInner::RefreshRealmPrincipal()
{
JS_SetCompartmentPrincipals(js::GetObjectCompartment(GetWrapperPreserveColor()),
nsJSPrincipals::get(mDoc->NodePrincipal()));
JS::SetRealmPrincipals(js::GetNonCCWObjectRealm(GetWrapperPreserveColor()),
nsJSPrincipals::get(mDoc->NodePrincipal()));
}
already_AddRefed<nsIWidget>

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

@ -377,7 +377,7 @@ public:
virtual void MaybeUpdateTouchState() override;
// Inner windows only.
void RefreshCompartmentPrincipal();
void RefreshRealmPrincipal();
// For accessing protected field mFullScreen
friend class FullscreenTransitionTask;

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

@ -1747,24 +1747,26 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
}
// Inner windows are only reused for same-origin principals, but the principals
// don't necessarily match exactly. Update the principal on the compartment to
// match the new document.
// NB: We don't just call currentInner->RefreshCompartmentPrincipals() here
// don't necessarily match exactly. Update the principal on the realm to match
// the new document.
// NB: We don't just call currentInner->RefreshRealmPrincipals() here
// because we haven't yet set its mDoc to aDocument.
JSCompartment *compartment = js::GetObjectCompartment(newInnerGlobal);
JS::Realm* realm = js::GetNonCCWObjectRealm(newInnerGlobal);
#ifdef DEBUG
bool sameOrigin = false;
nsIPrincipal *existing =
nsJSPrincipals::get(JS_GetCompartmentPrincipals(compartment));
nsJSPrincipals::get(JS::GetRealmPrincipals(realm));
aDocument->NodePrincipal()->Equals(existing, &sameOrigin);
MOZ_ASSERT(sameOrigin);
#endif
JSCompartment* compartment = JS::GetCompartmentForRealm(realm);
MOZ_ASSERT_IF(aDocument == oldDoc,
xpc::GetCompartmentPrincipal(compartment) ==
aDocument->NodePrincipal());
#endif
if (aDocument != oldDoc) {
JS_SetCompartmentPrincipals(compartment,
nsJSPrincipals::get(aDocument->NodePrincipal()));
JS::SetRealmPrincipals(realm,
nsJSPrincipals::get(aDocument->NodePrincipal()));
// Make sure we clear out the old content XBL scope, so the new one will
// get created with a principal that subsumes our new principal.
xpc::ClearContentXBLScope(newInnerGlobal);
@ -1980,13 +1982,13 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
currentInner = nullptr;
// Ask the JS engine to assert that it's valid to access our DocGroup whenever
// it runs JS code for this compartment. We skip the check if this window is
// for chrome JS or an add-on.
// it runs JS code for this realm. We skip the check if this window is for
// chrome JS or an add-on.
nsCOMPtr<nsIPrincipal> principal = mDoc->NodePrincipal();
if (GetDocGroup() && !nsContentUtils::IsSystemPrincipal(principal) &&
!BasePrincipal::Cast(principal)->AddonPolicy()) {
js::SetCompartmentValidAccessPtr(cx, newInnerGlobal,
newInnerWindow->GetDocGroup()->GetValidAccessPtr());
js::SetRealmValidAccessPtr(cx, newInnerGlobal,
newInnerWindow->GetDocGroup()->GetValidAccessPtr());
}
kungFuDeathGrip->DidInitializeContext();

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

@ -2563,7 +2563,7 @@ AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
intptr_t *aHandle)
{
nsIPrincipal* principal =
nsJSPrincipals::get(JS_GetCompartmentPrincipals(js::GetObjectCompartment(aGlobal)));
nsJSPrincipals::get(JS::GetRealmPrincipals(js::GetNonCCWObjectRealm(aGlobal)));
return asmjscache::OpenEntryForRead(principal, aBegin, aLimit, aSize, aMemory,
aHandle);
}
@ -2577,7 +2577,7 @@ AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
intptr_t* aHandle)
{
nsIPrincipal* principal =
nsJSPrincipals::get(JS_GetCompartmentPrincipals(js::GetObjectCompartment(aGlobal)));
nsJSPrincipals::get(JS::GetRealmPrincipals(js::GetNonCCWObjectRealm(aGlobal)));
return asmjscache::OpenEntryForWrite(principal, aBegin, aEnd, aSize, aMemory,
aHandle);
}

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

@ -2462,9 +2462,9 @@ GlobalObject::GetSubjectPrincipal() const
return nullptr;
}
JSCompartment* compartment = js::GetContextCompartment(mCx);
MOZ_ASSERT(compartment);
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
JS::Realm* realm = js::GetContextRealm(mCx);
MOZ_ASSERT(realm);
JSPrincipals* principals = JS::GetRealmPrincipals(realm);
return nsJSPrincipals::get(principals);
}

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

@ -133,10 +133,10 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
ErrorResult& aRv,
const char* aExecutionReason,
ExceptionHandling aExceptionHandling,
JSCompartment* aCompartment,
JS::Realm* aRealm,
bool aIsJSImplementedWebIDL)
: mCx(nullptr)
, mCompartment(aCompartment)
, mRealm(aRealm)
, mErrorResult(aRv)
, mExceptionHandling(aExceptionHandling)
, mIsMainThread(NS_IsMainThread())
@ -261,35 +261,35 @@ bool
CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aException)
{
if (mExceptionHandling == eRethrowExceptions) {
if (!mCompartment) {
if (!mRealm) {
// Caller didn't ask us to filter for only exceptions we subsume.
return true;
}
// On workers, we don't have nsIPrincipals to work with. But we also only
// have one compartment, so check whether mCompartment is the same as the
// current compartment of mCx.
if (mCompartment == js::GetContextCompartment(mCx)) {
// have one realm, so check whether mRealm is the same as the current realm
// of mCx.
if (mRealm == js::GetContextRealm(mCx)) {
return true;
}
MOZ_ASSERT(NS_IsMainThread());
// At this point mCx is in the compartment of our unwrapped callback, so
// just check whether the principal of mCompartment subsumes that of the
// current compartment/global of mCx.
// At this point mCx is in the realm of our unwrapped callback, so just
// check whether the principal of mRealm subsumes that of the current
// realm/global of mCx.
nsIPrincipal* callerPrincipal =
nsJSPrincipals::get(JS_GetCompartmentPrincipals(mCompartment));
nsJSPrincipals::get(JS::GetRealmPrincipals(mRealm));
nsIPrincipal* calleePrincipal = nsContentUtils::SubjectPrincipal();
if (callerPrincipal->SubsumesConsideringDomain(calleePrincipal)) {
return true;
}
}
MOZ_ASSERT(mCompartment);
MOZ_ASSERT(mRealm);
// Now we only want to throw an exception to the caller if the object that was
// thrown is in the caller compartment (which we stored in mCompartment).
// thrown is in the caller realm (which we stored in mRealm).
if (!aException.isObject()) {
return false;
@ -297,7 +297,7 @@ CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aExcepti
JS::Rooted<JSObject*> obj(mCx, &aException.toObject());
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
return js::GetObjectCompartment(obj) == mCompartment;
return js::GetNonCCWObjectRealm(obj) == mRealm;
}
CallbackObject::CallSetup::~CallSetup()
@ -313,7 +313,7 @@ CallbackObject::CallSetup::~CallSetup()
// were told to re-throw them.
if (mCx) {
bool needToDealWithException = mAutoEntryScript->HasException();
if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
if ((mRealm && mExceptionHandling == eRethrowContentExceptions) ||
mExceptionHandling == eRethrowExceptions) {
mErrorResult.MightThrowJSException();
if (needToDealWithException) {
@ -349,7 +349,7 @@ CallbackObject::CallSetup::~CallSetup()
mAutoEntryScript.reset();
// It is important that this is the last thing we do, after leaving the
// compartment and undoing all our entry/incumbent script changes
// realm and undoing all our entry/incumbent script changes
CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
if (ccjs) {
ccjs->LeaveMicroTask();

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

@ -94,7 +94,7 @@ public:
}
// Like CallbackOrNull(), but will return a new dead proxy object in the
// caller's compartment if the callback is null.
// caller's realm if the callback is null.
JSObject* Callback(JSContext* aCx);
JSObject* GetCreationStack() const
@ -146,10 +146,9 @@ public:
// binding object for a DOMException from the caller's scope, otherwise
// report it.
eRethrowContentExceptions,
// Throw exceptions to the caller code, unless the caller compartment is
// Throw exceptions to the caller code, unless the caller realm is
// provided, the exception is not a DOMException from the caller
// compartment, and the caller compartment does not subsume our unwrapped
// callback.
// realm, and the caller realm does not subsume our unwrapped callback.
eRethrowExceptions
};
@ -295,17 +294,17 @@ protected:
* non-null.
*/
public:
// If aExceptionHandling == eRethrowContentExceptions then aCompartment
// needs to be set to the compartment in which exceptions will be rethrown.
// If aExceptionHandling == eRethrowContentExceptions then aRealm
// needs to be set to the realm in which exceptions will be rethrown.
//
// If aExceptionHandling == eRethrowExceptions then aCompartment may be set
// to the compartment in which exceptions will be rethrown. In that case
// they will only be rethrown if that compartment's principal subsumes the
// If aExceptionHandling == eRethrowExceptions then aRealm may be set
// to the realm in which exceptions will be rethrown. In that case
// they will only be rethrown if that realm's principal subsumes the
// principal of our (unwrapped) callback.
CallSetup(CallbackObject* aCallback, ErrorResult& aRv,
const char* aExecutionReason,
ExceptionHandling aExceptionHandling,
JSCompartment* aCompartment = nullptr,
JS::Realm* aRealm = nullptr,
bool aIsJSImplementedWebIDL = false);
~CallSetup();
@ -323,9 +322,9 @@ protected:
// Members which can go away whenever
JSContext* mCx;
// Caller's compartment. This will only have a sensible value if
// Caller's realm. This will only have a sensible value if
// mExceptionHandling == eRethrowContentExceptions or eRethrowExceptions.
JSCompartment* mCompartment;
JS::Realm* mRealm;
// And now members whose construction/destruction order we need to control.
Maybe<AutoEntryScript> mAutoEntryScript;

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

@ -7236,9 +7236,9 @@ class CGCallGenerator(CGThing):
getPrincipal = fill(
"""
JSCompartment* compartment = js::GetContextCompartment(cx);
MOZ_ASSERT(compartment);
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
JS::Realm* realm = js::GetContextRealm(cx);
MOZ_ASSERT(realm);
JSPrincipals* principals = JS::GetRealmPrincipals(realm);
nsIPrincipal* principal = nsJSPrincipals::get(principals);
${checkPrincipal}
""",
@ -7563,7 +7563,7 @@ class CGPerSignatureCall(CGThing):
if not idlNode.isStatic():
needsUnwrap = True
needsUnwrappedVar = True
argsPost.append("js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj)")
argsPost.append("(unwrappedObj ? js::GetNonCCWObjectRealm(*unwrappedObj) : js::GetContextRealm(cx))")
elif needScopeObject(returnType, arguments, self.extendedAttributes,
descriptor.wrapperCache, True,
idlNode.getExtendedAttribute("StoreInSlot")):
@ -15009,7 +15009,7 @@ class CGJSImplMember(CGNativeMember):
def getArgs(self, returnType, argList):
args = CGNativeMember.getArgs(self, returnType, argList)
args.append(Argument("JSCompartment*", "aCompartment", "nullptr"))
args.append(Argument("JS::Realm*", "aRealm", "nullptr"))
return args
@ -15058,7 +15058,7 @@ class CGJSImplMethod(CGJSImplMember):
assert args[-1].argType == 'JS::Handle<JSObject*>'
assert args[-1].name == 'aGivenProto'
constructorArgs = [arg.name for arg in args[2:-1]]
constructorArgs.append("js::GetObjectCompartment(scopeObj)")
constructorArgs.append("js::GetNonCCWObjectRealm(scopeObj)")
initCall = fill(
"""
// Wrap the object before calling __Init so that __DOM_IMPL__ is available.
@ -15506,9 +15506,9 @@ class CGCallback(CGClass):
"nullptr"))
# Make copies of the arg list for the two "without rv" overloads. Note
# that those don't need aExceptionHandling or aCompartment arguments
# because those would make not sense anyway: the only sane thing to do
# with exceptions in the "without rv" cases is to report them.
# that those don't need aExceptionHandling or aRealm arguments because
# those would make not sense anyway: the only sane thing to do with
# exceptions in the "without rv" cases is to report them.
argsWithoutRv = list(args)
argsWithoutRv.pop(rvIndex)
argsWithoutThisAndRv = list(argsWithoutRv)
@ -15519,10 +15519,10 @@ class CGCallback(CGClass):
"eReportExceptions"))
# And the argument for communicating when exceptions should really be
# rethrown. In particular, even when aExceptionHandling is
# eRethrowExceptions they won't get rethrown if aCompartment is provided
# eRethrowExceptions they won't get rethrown if aRealm is provided
# and its principal doesn't subsume either the callback or the
# exception.
args.append(Argument("JSCompartment*", "aCompartment", "nullptr"))
args.append(Argument("JS::Realm*", "aRealm", "nullptr"))
# And now insert our template argument.
argsWithoutThis = list(args)
args.insert(0, Argument("const T&", "thisVal"))
@ -15533,8 +15533,8 @@ class CGCallback(CGClass):
# If we just leave things like that, and have no actual arguments in the
# IDL, we will end up trying to call the templated "without rv" overload
# with "rv" as the thisVal. That's no good. So explicitly append the
# aExceptionHandling and aCompartment values we need to end up matching
# the signature of our non-templated "with rv" overload.
# aExceptionHandling and aRealm values we need to end up matching the
# signature of our non-templated "with rv" overload.
argnamesWithoutThisAndRv.extend(["eReportExceptions", "nullptr"])
argnamesWithoutRv = [arg.name for arg in argsWithoutRv]
@ -15550,7 +15550,7 @@ class CGCallback(CGClass):
if (!aExecutionReason) {
aExecutionReason = "${executionReason}";
}
CallSetup s(this, aRv, aExecutionReason, aExceptionHandling, aCompartment);
CallSetup s(this, aRv, aExecutionReason, aExceptionHandling, aRealm);
if (!s.GetContext()) {
MOZ_ASSERT(aRv.Failed());
return${errorReturn};
@ -15961,7 +15961,7 @@ class CallbackMember(CGNativeMember):
"nullptr"))
args.append(Argument("ExceptionHandling", "aExceptionHandling",
"eReportExceptions"))
args.append(Argument("JSCompartment*", "aCompartment", "nullptr"))
args.append(Argument("JS::Realm*", "aRealm", "nullptr"))
return args
# We want to allow the caller to pass in a "this" value, as
# well as a JSContext.
@ -15975,11 +15975,11 @@ class CallbackMember(CGNativeMember):
callSetup = "CallSetup s(this, aRv"
if self.rethrowContentException:
# getArgs doesn't add the aExceptionHandling argument but does add
# aCompartment for us.
callSetup += ', "%s", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ ' % self.getPrettyName()
# aRealm for us.
callSetup += ', "%s", eRethrowContentExceptions, aRealm, /* aIsJSImplementedWebIDL = */ ' % self.getPrettyName()
callSetup += toStringBool(isJSImplementedDescriptor(self.descriptorProvider))
else:
callSetup += ', "%s", aExceptionHandling, aCompartment' % self.getPrettyName()
callSetup += ', "%s", aExceptionHandling, aRealm' % self.getPrettyName()
callSetup += ");\n"
return fill(
"""

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

@ -189,7 +189,7 @@ GetCurrentJSStack(int32_t aMaxDepth)
// is there a current context available?
JSContext* cx = nsContentUtils::GetCurrentJSContext();
if (!cx || !js::GetContextCompartment(cx)) {
if (!cx || !js::GetContextRealm(cx)) {
return nullptr;
}

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

@ -73,6 +73,8 @@ skip-if = debug == false
skip-if = debug == false
[test_jsimplemented_eventhandler.html]
skip-if = debug == false
[test_jsimplemented_cross_realm_this.html]
skip-if = debug == false
[test_iterable.html]
skip-if = debug == false
[test_oom_reporting.html]

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

@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1464374-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1464374</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1464374">Mozilla Bug 1464374</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<iframe></iframe>
<script type="application/javascript">
/** Test for Bug 1464374 **/
SimpleTest.waitForExplicitFinish();
function doTest() {
var frame = frames[0];
var obj = new frame.TestInterfaceJS();
var ex;
try {
TestInterfaceJS.prototype.testThrowTypeError.call(obj);
} catch(e) {
ex = e;
}
ok(ex, "Should have an exception");
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]},
doTest);
</script>
</body>
</html>

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

@ -1537,10 +1537,10 @@ nsHTMLDocument::Open(JSContext* cx,
SetReadyStateInternal(nsIDocument::READYSTATE_LOADING);
// After changing everything around, make sure that the principal on the
// document's compartment exactly matches NodePrincipal().
// document's realm exactly matches NodePrincipal().
DebugOnly<JSObject*> wrapper = GetWrapperPreserveColor();
MOZ_ASSERT_IF(wrapper,
JS_GetCompartmentPrincipals(js::GetObjectCompartment(wrapper)) ==
JS::GetRealmPrincipals(js::GetNonCCWObjectRealm(wrapper)) ==
nsJSPrincipals::get(NodePrincipal()));
return kungFuDeathGrip.forget();

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

@ -618,7 +618,7 @@ AutoJSAPI::PeekException(JS::MutableHandle<JS::Value> aVal)
{
MOZ_ASSERT_IF(mIsMainThread, IsStackTop());
MOZ_ASSERT(HasException());
MOZ_ASSERT(js::GetContextCompartment(cx()));
MOZ_ASSERT(js::GetContextRealm(cx()));
if (!JS_GetPendingException(cx(), aVal)) {
return false;
}

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

@ -890,12 +890,16 @@ nsContentSecurityManager::IsOriginPotentiallyTrustworthy(nsIPrincipal* aPrincipa
// which is technically a substituting protocol handler that is not limited to
// local resource mapping, but in practice is never mapped remotely as this
// would violate assumptions a lot of code makes.
if (scheme.EqualsLiteral("https") ||
scheme.EqualsLiteral("file") ||
scheme.EqualsLiteral("resource") ||
scheme.EqualsLiteral("app") ||
scheme.EqualsLiteral("moz-extension") ||
scheme.EqualsLiteral("wss")) {
// We use nsIProtocolHandler flags to determine which protocols we consider a priori
// authenticated.
bool aPrioriAuthenticated = false;
if (NS_FAILED(NS_URIChainHasFlags(uri,
nsIProtocolHandler::URI_IS_POTENTIALLY_TRUSTWORTHY,
&aPrioriAuthenticated))) {
return NS_ERROR_UNEXPECTED;
}
if (aPrioriAuthenticated) {
*aIsTrustWorthy = true;
return NS_OK;
}

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

@ -597,7 +597,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
* "moz-icon"
* URI_INHERITS_SECURITY_CONTEXT - e.g.
* "javascript"
* URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT - e.g.
* URI_IS_POTENTIALLY_TRUSTWORTHY - e.g.
* "https",
* "moz-safe-about"
*
@ -609,7 +609,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
if (NS_FAILED(NS_URIChainHasFlags(innerContentLocation, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE , &schemeLocal)) ||
NS_FAILED(NS_URIChainHasFlags(innerContentLocation, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &schemeNoReturnData)) ||
NS_FAILED(NS_URIChainHasFlags(innerContentLocation, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, &schemeInherits)) ||
NS_FAILED(NS_URIChainHasFlags(innerContentLocation, nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT, &schemeSecure))) {
NS_FAILED(NS_URIChainHasFlags(innerContentLocation, nsIProtocolHandler::URI_IS_POTENTIALLY_TRUSTWORTHY, &schemeSecure))) {
*aDecision = REJECT_REQUEST;
return NS_ERROR_FAILURE;
}

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

@ -0,0 +1,94 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "gtest/gtest.h"
#include <string.h>
#include <stdlib.h>
#include "nsContentSecurityManager.h"
#include "nsContentUtils.h"
#include "nsIPrincipal.h"
#include "nsScriptSecurityManager.h"
#include "NullPrincipal.h"
static const uint32_t kURIMaxLength = 64;
struct TestExpectations {
char uri[kURIMaxLength ];
bool expectedResult;
};
// ============================= TestDirectives ========================
TEST(SecureContext, IsOriginPotentiallyTrustworthyWithCodeBasePrincipal)
{
//boolean isOriginPotentiallyTrustworthy(in nsIPrincipal aPrincipal);
static const TestExpectations uris[] = {
{ "http://example.com/", false },
{ "https://example.com/", true },
{ "ws://example.com/", false },
{ "wss://example.com/", true },
{ "file:///xyzzy", true },
{ "ftp://example.com", false },
{ "about:config", false },
{ "http://localhost", true },
{ "http://xyzzy.localhost", false },
{ "http://127.0.0.1", true },
{ "resource://xyzzy", true },
{ "moz-extension://xyzzy", true },
{ "data:data:text/plain;charset=utf-8;base64,eHl6enk=", false },
{ "blob://unique-id", false },
{ "mailto:foo@bar.com", false },
{ "moz-icon://example.com", false },
{ "javascript:42", false },
};
uint32_t numExpectations = sizeof(uris) / sizeof(TestExpectations);
nsCOMPtr<nsIContentSecurityManager> csManager = do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
ASSERT_TRUE(!!csManager);
nsresult rv;
for (uint32_t i = 0; i < numExpectations; i++) {
nsCOMPtr<nsIPrincipal> prin;
nsAutoCString uri(uris[i].uri);
rv = nsScriptSecurityManager::GetScriptSecurityManager()->
CreateCodebasePrincipalFromOrigin(uri, getter_AddRefs(prin));
bool isPotentiallyTrustworthy = false;
rv = csManager->IsOriginPotentiallyTrustworthy(prin, &isPotentiallyTrustworthy);
ASSERT_EQ(NS_OK, rv);
ASSERT_EQ(isPotentiallyTrustworthy, uris[i].expectedResult);
}
}
TEST(SecureContext, IsOriginPotentiallyTrustworthyWithSystemPrincipal)
{
RefPtr<nsScriptSecurityManager> ssManager = nsScriptSecurityManager::GetScriptSecurityManager();
ASSERT_TRUE(!!ssManager);
nsCOMPtr<nsIContentSecurityManager> csManager = do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
ASSERT_TRUE(!!csManager);
nsCOMPtr<nsIPrincipal> sysPrin = nsContentUtils::GetSystemPrincipal();
bool isPotentiallyTrustworthy;
nsresult rv = csManager->IsOriginPotentiallyTrustworthy(sysPrin, &isPotentiallyTrustworthy);
ASSERT_EQ(rv, NS_OK);
ASSERT_TRUE(isPotentiallyTrustworthy);
}
TEST(SecureContext, IsOriginPotentiallyTrustworthyWithNullPrincipal)
{
RefPtr<nsScriptSecurityManager> ssManager = nsScriptSecurityManager::GetScriptSecurityManager();
ASSERT_TRUE(!!ssManager);
nsCOMPtr<nsIContentSecurityManager> csManager = do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
ASSERT_TRUE(!!csManager);
RefPtr<NullPrincipal> nullPrin = NullPrincipal::CreateWithoutOriginAttributes();
bool isPotentiallyTrustworthy;
nsresult rv = csManager->IsOriginPotentiallyTrustworthy(nullPrin, &isPotentiallyTrustworthy);
ASSERT_EQ(rv, NS_OK);
ASSERT_TRUE(!isPotentiallyTrustworthy);
}

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

@ -6,6 +6,11 @@
UNIFIED_SOURCES += [
'TestCSPParser.cpp',
'TestSecureContext.cpp',
]
FINAL_LIBRARY = 'xul-gtest'
LOCAL_INCLUDES += [
'/caps',
]

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

@ -46,12 +46,10 @@ tags = fullscreen
[test_bug830858.xul]
[test_bug1224790-1.xul]
tags = openwindow
# synthesizeNativeOSXClick does not work on 10.6
skip-if = os != 'mac' || os_version == '10.6'
skip-if = os != 'mac'
[test_bug1224790-2.xul]
tags = openwindow
# synthesizeNativeOSXClick does not work on 10.6
skip-if = os != 'mac' || os_version == '10.6'
skip-if = os != 'mac'
[test_callback_wrapping.xul]
[test_clonewrapper.xul]
[test_cyclecollector.xul]

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

@ -1206,15 +1206,12 @@ public:
// aRealmStats->extra is a xpc::RealmStatsExtras pointer.
xpc::RealmStatsExtras* extras = new xpc::RealmStatsExtras;
// This is the |jsPathPrefix|. Each worker has exactly two realms:
// one for atoms, and one for everything else.
// This is the |jsPathPrefix|. Each worker has exactly one realm.
JSCompartment* compartment = JS::GetCompartmentForRealm(aRealm);
extras->jsPathPrefix.Assign(mRtPath);
extras->jsPathPrefix += nsPrintfCString("zone(0x%p)/",
(void *)js::GetCompartmentZone(compartment));
extras->jsPathPrefix += js::IsAtomsRealm(aRealm)
? NS_LITERAL_CSTRING("realm(web-worker-atoms)/")
: NS_LITERAL_CSTRING("realm(web-worker)/");
extras->jsPathPrefix += NS_LITERAL_CSTRING("realm(web-worker)/");
// This should never be used when reporting with workers (hence the "?!").
extras->domPathPrefix.AssignLiteral("explicit/workers/?!/");

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

@ -39,9 +39,11 @@ class gfxVarReceiver;
_(UseWebRenderANGLE, bool, false) \
_(UseWebRenderDCompWin, bool, false) \
_(UseWebRenderProgramBinary, bool, false) \
_(UseWebRenderProgramBinaryDisk, bool, false) \
_(WebRenderDebugFlags, int32_t, 0) \
_(ScreenDepth, int32_t, 0) \
_(GREDirectory, nsString, nsString()) \
_(ProfDirectory, nsString, nsString()) \
_(UseOMTP, bool, false) \
_(AllowD3D11KeyedMutex, bool, false) \

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

@ -326,7 +326,6 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
}
bool edgePaddingEnabled = gfxPrefs::TileEdgePaddingEnabled();
for (uint32_t i = 0; i < mRetainedTiles.Length(); ++i) {
TileClient& tile = mRetainedTiles[i];
@ -442,6 +441,8 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
return false;
}
// Get the targets to draw into, and create a dual target
// if we are using component alpha
RefPtr<DrawTarget> dt = backBuffer->BorrowDrawTarget();
RefPtr<DrawTarget> dtOnWhite;
if (backBufferOnWhite) {
@ -460,12 +461,18 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
drawTarget = dt;
}
auto clear = CapturedTiledPaintState::Clear{
dt,
dtOnWhite,
tileDirtyRegion
};
// We need to clear the dirty region of the tile before painting
// if we are painting non-opaque content
Maybe<CapturedTiledPaintState::Clear> clear = Nothing();
if (mode != SurfaceMode::SURFACE_OPAQUE) {
clear = Some(CapturedTiledPaintState::Clear{
dt,
dtOnWhite,
tileDirtyRegion
});
}
// Queue or execute the paint operation
gfx::Tile paintTile;
paintTile.mTileOrigin = gfx::IntPoint(aTileOrigin.x, aTileOrigin.y);
@ -481,7 +488,9 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
asyncPaint->mCapture = captureDT;
asyncPaint->mCopies = std::move(asyncPaintCopies);
asyncPaint->mClears.push_back(clear);
if (clear) {
asyncPaint->mClears.push_back(*clear);
}
asyncPaint->mClients = std::move(asyncPaintClients);
asyncPaint->mClients.push_back(backBuffer);
@ -492,7 +501,9 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
mPaintStates.push_back(asyncPaint);
} else {
paintTile.mDrawTarget = drawTarget;
clear.ClearBuffer();
if (clear) {
clear->ClearBuffer();
}
}
mPaintTiles.push_back(paintTile);

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

@ -197,68 +197,21 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
copyableRegion.And(aNewValidRegion, discardedValidRegion);
copyableRegion.SubOut(aDirtyRegion);
if (!copyableRegion.IsEmpty()) {
OpenMode asyncFlags = asyncPaint ? OpenMode::OPEN_ASYNC
: OpenMode::OPEN_NONE;
if (!mTile.CopyFromBuffer(discardedFrontBuffer,
discardedFrontBufferOnWhite,
discardedValidRegion.GetBounds().TopLeft(),
mTilingOrigin,
copyableRegion,
aFlags,
&paintCopies)) {
gfxWarning() << "[Tiling:Client] Failed to aquire the discarded front buffer's draw target";
} else {
TILING_LOG("TILING %p: Region copied from discarded frontbuffer %s\n", &mPaintedLayer, Stringify(copyableRegion).c_str());
TextureClientAutoLock frontLock(discardedFrontBuffer,
OpenMode::OPEN_READ | asyncFlags);
Maybe<TextureClientAutoLock> frontOnWhiteLock;
if (discardedFrontBufferOnWhite && backBufferOnWhite) {
frontOnWhiteLock.emplace(discardedFrontBufferOnWhite, OpenMode::OPEN_READ | asyncFlags);
}
// Copy to both backBuffer and backBufferOnWhite if required, or copy to neither.
if (frontLock.Succeeded() && (!frontOnWhiteLock || frontOnWhiteLock->Succeeded())) {
RefPtr<gfx::DrawTarget> frontBuffer = discardedFrontBuffer->BorrowDrawTarget();
if (frontBuffer) {
for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
auto copy = CapturedTiledPaintState::Copy{
frontBuffer, dt, rect, dest
};
if (asyncPaint) {
paintCopies.push_back(copy);
} else {
copy.CopyBuffer();
}
}
if (frontOnWhiteLock) {
RefPtr<gfx::DrawTarget> frontBufferOnWhite = discardedFrontBufferOnWhite->BorrowDrawTarget();
if (frontBufferOnWhite) {
for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
auto copy = CapturedTiledPaintState::Copy{
frontBufferOnWhite, dtOnWhite, rect, dest
};
if (asyncPaint) {
paintCopies.push_back(copy);
} else {
copy.CopyBuffer();
}
}
} else {
gfxWarning() << "[Tiling:Client] Failed to aquire the discarded front buffer's draw target";
}
}
} else {
gfxWarning() << "[Tiling:Client] Failed to aquire the discarded front buffer's draw target";
}
TILING_LOG("TILING %p: Region copied from discarded frontbuffer %s\n", &mPaintedLayer, Stringify(copyableRegion).c_str());
// We don't need to repaint valid content that was just copied.
paintRegion.SubOut(copyableRegion);
copyableRegion.MoveBy(-mTilingOrigin);
tileDirtyRegion.SubOut(copyableRegion);
}
// We don't need to repaint valid content that was just copied.
paintRegion.SubOut(copyableRegion);
copyableRegion.MoveBy(-mTilingOrigin);
tileDirtyRegion.SubOut(copyableRegion);
}
}

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

@ -483,45 +483,49 @@ TileClient::ValidateBackBufferFromFront(const nsIntRegion& aDirtyRegion,
std::vector<CapturedTiledPaintState::Copy>* aCopies,
std::vector<RefPtr<TextureClient>>* aClients)
{
if (mBackBuffer && mFrontBuffer) {
gfx::IntSize tileSize = mFrontBuffer->GetSize();
const IntRect tileRect = IntRect(0, 0, tileSize.width, tileSize.height);
if (!mBackBuffer || !mFrontBuffer) {
return;
}
if (aDirtyRegion.Contains(tileRect)) {
// The dirty region means that we no longer need the front buffer, so
// discard it.
DiscardFrontBuffer();
} else {
// Region that needs copying.
nsIntRegion regionToCopy = mInvalidBack;
gfx::IntSize tileSize = mFrontBuffer->GetSize();
const IntRect tileRect = IntRect(0, 0, tileSize.width, tileSize.height);
regionToCopy.Sub(regionToCopy, aDirtyRegion);
regionToCopy.And(regionToCopy, aVisibleRegion);
if (aDirtyRegion.Contains(tileRect)) {
// The dirty region means that we no longer need the front buffer, so
// discard it.
DiscardFrontBuffer();
return;
}
aAddPaintedRegion = regionToCopy;
// Region that needs copying.
nsIntRegion regionToCopy = mInvalidBack;
if (regionToCopy.IsEmpty()) {
// Just redraw it all.
return;
}
regionToCopy.Sub(regionToCopy, aDirtyRegion);
regionToCopy.And(regionToCopy, aVisibleRegion);
// Copy the bounding rect of regionToCopy. As tiles are quite small, it
// is unlikely that we'd save much by copying each individual rect of the
// region, but we can reevaluate this if it becomes an issue.
const IntRect rectToCopy = regionToCopy.GetBounds();
gfx::IntRect gfxRectToCopy(rectToCopy.X(), rectToCopy.Y(), rectToCopy.Width(), rectToCopy.Height());
if (CopyFrontToBack(mFrontBuffer, mBackBuffer, gfxRectToCopy, aFlags, aCopies, aClients)) {
if (mBackBufferOnWhite) {
MOZ_ASSERT(mFrontBufferOnWhite);
if (CopyFrontToBack(mFrontBufferOnWhite, mBackBufferOnWhite, gfxRectToCopy, aFlags, aCopies, aClients)) {
mInvalidBack.Sub(mInvalidBack, aVisibleRegion);
}
} else {
mInvalidBack.Sub(mInvalidBack, aVisibleRegion);
}
}
aAddPaintedRegion = regionToCopy;
if (regionToCopy.IsEmpty()) {
// Just redraw it all.
return;
}
// Copy the bounding rect of regionToCopy. As tiles are quite small, it
// is unlikely that we'd save much by copying each individual rect of the
// region, but we can reevaluate this if it becomes an issue.
const IntRect rectToCopy = regionToCopy.GetBounds();
if (!CopyFrontToBack(mFrontBuffer, mBackBuffer, rectToCopy, aFlags, aCopies, aClients)) {
return;
}
if (mBackBufferOnWhite) {
MOZ_ASSERT(mFrontBufferOnWhite);
if (!CopyFrontToBack(mFrontBufferOnWhite, mBackBufferOnWhite, rectToCopy, aFlags, aCopies, aClients)) {
return;
}
}
mInvalidBack.Sub(mInvalidBack, aVisibleRegion);
}
void
@ -580,6 +584,59 @@ TileClient::DiscardBackBuffer()
}
}
bool
TileClient::CopyFromBuffer(RefPtr<TextureClient> aBuffer,
RefPtr<TextureClient> aBufferOnWhite,
nsIntPoint aBufferOrigin,
nsIntPoint aTileOrigin,
const nsIntRegion& aRegion,
TilePaintFlags aFlags,
std::vector<CapturedTiledPaintState::Copy>* aCopies)
{
if (aRegion.IsEmpty()) {
return true;
}
bool asyncPaint = !!(aFlags & TilePaintFlags::Async);
auto CopyBuffer = [&aRegion, asyncPaint, &aCopies] (auto aSrc, auto aSrcOrigin, auto aDest, auto aDestOrigin) {
MOZ_ASSERT(aDest->IsLocked());
OpenMode asyncFlags = asyncPaint ? OpenMode::OPEN_ASYNC
: OpenMode::OPEN_NONE;
TextureClientAutoLock lock(aSrc, OpenMode::OPEN_READ | asyncFlags);
if (!lock.Succeeded()) {
return false;
}
RefPtr<gfx::DrawTarget> srcTarget = aSrc->BorrowDrawTarget();
RefPtr<gfx::DrawTarget> destTarget = aDest->BorrowDrawTarget();
if (!srcTarget || !destTarget) {
return false;
}
for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
const gfx::IntRect src = iter.Get() - aSrcOrigin;
const gfx::IntPoint dest = iter.Get().TopLeft() - aDestOrigin;
auto copy = CapturedTiledPaintState::Copy{
srcTarget, destTarget, src, dest
};
if (asyncPaint) {
aCopies->push_back(copy);
} else {
copy.CopyBuffer();
}
}
return true;
};
return CopyBuffer(aBuffer, aBufferOrigin, mBackBuffer, aTileOrigin) &&
(!aBufferOnWhite ||
!mBackBufferOnWhite ||
CopyBuffer(aBufferOnWhite, aBufferOrigin, mBackBufferOnWhite, aTileOrigin));
}
static already_AddRefed<TextureClient>
CreateBackBufferTexture(TextureClient* aCurrentTexture,
CompositableClient& aCompositable,

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

@ -140,6 +140,18 @@ struct TileClient
void DiscardBackBuffer();
/*
* Copy aRegion from aBuffer and aBufferOnWhite positioned at aBufferOrigin
* into ourselves assuming we are positioned at aTileOrigin.
*/
bool CopyFromBuffer(RefPtr<TextureClient> aBuffer,
RefPtr<TextureClient> aBufferOnWhite,
nsIntPoint aBufferOrigin,
nsIntPoint aTileOrigin,
const nsIntRegion& aRegion,
TilePaintFlags aFlags,
std::vector<CapturedTiledPaintState::Copy>* aCopies);
/* We wrap the back buffer in a class that disallows assignment
* so that we can track when ever it changes so that we can update
* the expiry tracker for expiring the back buffers */
@ -168,8 +180,10 @@ struct TileClient
nsIntRegion mInvalidBack;
nsExpirationState mExpirationState;
private:
// Copies dirty pixels from the front buffer into the back buffer,
// and records the copied region in aAddPaintedRegion.
/*
* Copies dirty pixels from the front buffer into the back buffer,
* and records the copied region in aAddPaintedRegion.
*/
void ValidateBackBufferFromFront(const nsIntRegion &aDirtyRegion,
const nsIntRegion& aVisibleRegion,
nsIntRegion& aAddPaintedRegion,

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

@ -22,6 +22,7 @@
#include "mozilla/Logging.h"
#include "mozilla/Services.h"
#include "nsAppDirectoryServiceDefs.h"
#include "gfxCrashReporterUtils.h"
#include "gfxPlatform.h"
@ -866,6 +867,18 @@ gfxPlatform::Init()
Preferences::SetBool(FONT_VARIATIONS_PREF, false);
Preferences::Lock(FONT_VARIATIONS_PREF);
}
nsCOMPtr<nsIFile> profDir;
rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP, getter_AddRefs(profDir));
if (NS_FAILED(rv)) {
gfxVars::SetProfDirectory(nsString());
} else {
nsAutoString path;
profDir->GetPath(path);
gfxVars::SetProfDirectory(nsString(path));
}
gfxUtils::RemoveShaderCacheFromDiskIfNecessary();
}
if (obs) {
@ -2626,7 +2639,10 @@ gfxPlatform::InitWebRenderConfig()
#endif
if (Preferences::GetBool("gfx.webrender.program-binary", false)) {
gfx::gfxVars::SetUseWebRenderProgramBinary(gfxConfig::IsEnabled(Feature::WEBRENDER));
gfxVars::SetUseWebRenderProgramBinary(gfxConfig::IsEnabled(Feature::WEBRENDER));
if (Preferences::GetBool("gfx.webrender.program-binary-disk", false)) {
gfxVars::SetUseWebRenderProgramBinaryDisk(gfxConfig::IsEnabled(Feature::WEBRENDER));
}
}
#ifdef MOZ_WIDGET_ANDROID

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

@ -22,11 +22,14 @@
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/Unused.h"
#include "mozilla/Vector.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "nsAppRunner.h"
#include "nsComponentManagerUtils.h"
#include "nsIClipboardHelper.h"
#include "nsIFile.h"
@ -1468,6 +1471,54 @@ gfxUtils::ThreadSafeGetFeatureStatus(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
return gfxInfo->GetFeatureStatus(feature, failureId, status);
}
#define GFX_SHADER_CHECK_BUILD_VERSION_PREF "gfx-shader-check.build-version"
#define GFX_SHADER_CHECK_DEVICE_ID_PREF "gfx-shader-check.device-id"
#define GFX_SHADER_CHECK_DRIVER_VERSION_PREF "gfx-shader-check.driver-version"
/* static */ void
gfxUtils::RemoveShaderCacheFromDiskIfNecessary()
{
if (!gfxVars::UseWebRenderProgramBinaryDisk()) {
return;
}
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
// Get current values
nsCString buildID(mozilla::PlatformBuildID());
nsString deviceID, driverVersion;
gfxInfo->GetAdapterDeviceID(deviceID);
gfxInfo->GetAdapterDriverVersion(driverVersion);
// Get pref stored values
nsAutoCString buildIDChecked;
Preferences::GetCString(GFX_SHADER_CHECK_BUILD_VERSION_PREF, buildIDChecked);
nsAutoString deviceIDChecked, driverVersionChecked;
Preferences::GetString(GFX_SHADER_CHECK_DEVICE_ID_PREF, deviceIDChecked);
Preferences::GetString(GFX_SHADER_CHECK_DRIVER_VERSION_PREF, driverVersionChecked);
if (buildID == buildIDChecked &&
deviceID == deviceIDChecked &&
driverVersion == driverVersionChecked) {
return;
}
nsAutoString path(gfx::gfxVars::ProfDirectory());
if (!wr::remove_program_binary_disk_cache(&path)) {
// Failed to remove program binary disk cache. The disk cache might have
// invalid data. Disable program binary disk cache usage.
gfxVars::SetUseWebRenderProgramBinaryDisk(false);
return;
}
Preferences::SetCString(GFX_SHADER_CHECK_BUILD_VERSION_PREF, buildID);
Preferences::SetString(GFX_SHADER_CHECK_DEVICE_ID_PREF, deviceID);
Preferences::SetString(GFX_SHADER_CHECK_DRIVER_VERSION_PREF, driverVersion);
return;
}
/* static */ bool
gfxUtils::DumpDisplayList() {
return gfxPrefs::LayoutDumpDisplayList() ||

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

@ -295,6 +295,8 @@ public:
nsACString& failureId,
int32_t* status);
static void RemoveShaderCacheFromDiskIfNecessary();
/**
* Copy to the clipboard as a PNG encoded Data URL.
*/

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

@ -11,12 +11,16 @@ euclid = { version = "0.17", features = ["serde"] }
app_units = "0.6"
gleam = "0.5"
log = "0.4"
nsstring = { path = "../../servo/support/gecko/nsstring" }
bincode = "1.0"
uuid = {version = "0.1.18"}
fxhash = "0.2.1"
[dependencies.webrender]
path = "../webrender"
version = "0.57.2"
default-features = false
features = ["capture"]
features = ["capture", "serialize_program"]
[target.'cfg(target_os = "windows")'.dependencies]
dwrote = "0.4.1"

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

@ -70,6 +70,16 @@ RenderThread::Start()
widget::WinCompositorWindowThread::Start();
#endif
layers::SharedSurfacesParent::Initialize();
if (XRE_IsGPUProcess() &&
gfx::gfxVars::UseWebRenderProgramBinary()) {
MOZ_ASSERT(gfx::gfxVars::UseWebRender());
// Initialize program cache if necessary
RefPtr<Runnable> runnable = WrapRunnable(
RefPtr<RenderThread>(sRenderThread.get()),
&RenderThread::ProgramCacheTask);
sRenderThread->Loop()->PostTask(runnable.forget());
}
}
// static
@ -511,13 +521,19 @@ RenderThread::GetRenderTexture(wr::WrExternalImageId aExternalImageId)
return mRenderTextures.GetWeak(aExternalImageId.mHandle);
}
void
RenderThread::ProgramCacheTask()
{
ProgramCache();
}
WebRenderProgramCache*
RenderThread::ProgramCache()
{
MOZ_ASSERT(IsInRenderThread());
if (!mProgramCache) {
mProgramCache = MakeUnique<WebRenderProgramCache>();
mProgramCache = MakeUnique<WebRenderProgramCache>(ThreadPool().Raw());
}
return mProgramCache.get();
}
@ -532,9 +548,16 @@ WebRenderThreadPool::~WebRenderThreadPool()
wr_thread_pool_delete(mThreadPool);
}
WebRenderProgramCache::WebRenderProgramCache()
WebRenderProgramCache::WebRenderProgramCache(wr::WrThreadPool* aThreadPool)
{
mProgramCache = wr_program_cache_new();
MOZ_ASSERT(aThreadPool);
nsAutoString path;
if (gfxVars::UseWebRenderProgramBinaryDisk()) {
path.Append(gfx::gfxVars::ProfDirectory());
}
mProgramCache = wr_program_cache_new(&path, aThreadPool);
wr_try_load_shader_from_disk(mProgramCache);
}
WebRenderProgramCache::~WebRenderProgramCache()

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

@ -42,7 +42,7 @@ protected:
class WebRenderProgramCache {
public:
WebRenderProgramCache();
explicit WebRenderProgramCache(wr::WrThreadPool* aThreadPool);
~WebRenderProgramCache();
@ -170,6 +170,7 @@ private:
void DeferredRenderTextureHostDestroy(RefPtr<RenderTextureHost> aTexture);
void ShutDownTask(layers::SynchronousTask* aTask);
void ProgramCacheTask();
~RenderThread();

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

@ -13,12 +13,14 @@ use webrender::{ExternalImage, ExternalImageHandler, ExternalImageSource};
use webrender::DebugFlags;
use webrender::{ApiRecordingReceiver, BinaryRecorder};
use webrender::{AsyncPropertySampler, PipelineInfo, SceneBuilderHooks};
use webrender::{ProgramCache, UploadMethod, VertexUsageHint};
use webrender::{UploadMethod, VertexUsageHint};
use thread_profiler::register_thread_with_profiler;
use moz2d_renderer::Moz2dImageRenderer;
use program_cache::{WrProgramCache, remove_disk_cache};
use app_units::Au;
use rayon;
use euclid::SideOffsets2D;
use nsstring::nsAString;
#[cfg(target_os = "windows")]
use dwrote::{FontDescriptor, FontWeight, FontStretch, FontStyle};
@ -827,23 +829,40 @@ pub unsafe extern "C" fn wr_thread_pool_delete(thread_pool: *mut WrThreadPool) {
Box::from_raw(thread_pool);
}
pub struct WrProgramCache(Rc<ProgramCache>);
#[no_mangle]
pub unsafe extern "C" fn wr_program_cache_new() -> *mut WrProgramCache {
let program_cache = ProgramCache::new(None);
Box::into_raw(Box::new(WrProgramCache(program_cache)))
pub unsafe extern "C" fn wr_program_cache_new(prof_path: &nsAString, thread_pool: *mut WrThreadPool) -> *mut WrProgramCache {
let workers = &(*thread_pool).0;
let program_cache = WrProgramCache::new(prof_path, workers);
Box::into_raw(Box::new(program_cache))
}
/// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
#[no_mangle]
pub unsafe extern "C" fn wr_program_cache_delete(program_cache: *mut WrProgramCache) {
Rc::from_raw(program_cache);
Box::from_raw(program_cache);
}
#[no_mangle]
pub unsafe extern "C" fn wr_try_load_shader_from_disk(program_cache: *mut WrProgramCache) {
if !program_cache.is_null() {
(*program_cache).try_load_from_disk();
}
}
#[no_mangle]
pub unsafe extern "C" fn remove_program_binary_disk_cache(prof_path: &nsAString) -> bool {
match remove_disk_cache(prof_path) {
Ok(_) => true,
Err(_) => {
error!("Failed to remove program binary disk cache");
false
}
}
}
#[no_mangle]
pub extern "C" fn wr_renderer_update_program_cache(renderer: &mut Renderer, program_cache: &mut WrProgramCache) {
let program_cache = Rc::clone(&program_cache.0);
let program_cache = Rc::clone(&program_cache.rc_get());
renderer.update_program_cache(program_cache);
}

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

@ -8,8 +8,12 @@ extern crate webrender;
extern crate euclid;
extern crate app_units;
extern crate gleam;
extern crate nsstring;
extern crate rayon;
extern crate thread_profiler;
extern crate bincode;
extern crate uuid;
extern crate fxhash;
#[macro_use]
extern crate log;
@ -17,6 +21,7 @@ extern crate log;
#[cfg(target_os = "windows")]
extern crate dwrote;
#[cfg(target_os = "macos")]
extern crate core_foundation;
#[cfg(target_os = "macos")]
@ -24,6 +29,8 @@ extern crate core_graphics;
#[cfg(target_os = "macos")]
extern crate foreign_types;
mod program_cache;
#[allow(non_snake_case)]
pub mod bindings;
pub mod moz2d_renderer;

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

@ -0,0 +1,298 @@
use std::cell::RefCell;
use std::io::{Error, ErrorKind};
use std::fs::{File, create_dir_all, read_dir};
use std::io::{Read, Write};
use std::path::{PathBuf};
use std::rc::Rc;
use std::sync::Arc;
use webrender::{ProgramBinary, ProgramCache, ProgramCacheObserver};
use bincode;
use fxhash;
use nsstring::nsAString;
use rayon::ThreadPool;
use uuid::Uuid;
const MAX_LOAD_TIME_MS: u64 = 400;
const MAX_CACHED_PROGRAM_COUNT: u32 = 15;
fn deserialize_program_binary(path: &PathBuf) -> Result<Arc<ProgramBinary>, Error> {
let mut buf = vec![];
let mut file = File::open(path)?;
file.read_to_end(&mut buf)?;
if buf.len() <= 8 {
return Err(Error::new(ErrorKind::InvalidData, "File size is too small"));
}
let hash = &buf[0 .. 8];
let data = &buf[8 ..];
// Check if hash is correct
let hash:u64 = bincode::deserialize(&hash).unwrap();
let hash_data = fxhash::hash64(&data);
if hash != hash_data {
return Err(Error::new(ErrorKind::InvalidData, "File data is invalid"));
}
// Deserialize ProgramBinary
let binary = match bincode::deserialize(&data) {
Ok(binary) => binary,
Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Failed to deserialize ProgramBinary")),
};
Ok(Arc::new(binary))
}
#[cfg(target_os = "windows")]
fn get_cache_path_from_prof_path(prof_path: &nsAString) -> Option<PathBuf> {
if prof_path.is_empty() {
// Empty means that we do not use disk cache.
return None;
}
use std::ffi::OsString;
use std::os::windows::prelude::*;
let prof_path = OsString::from_wide(prof_path.as_ref());
let mut cache_path = PathBuf::from(&prof_path);
cache_path.push("shader-cache");
Some(cache_path)
}
#[cfg(not(target_os="windows"))]
fn get_cache_path_from_prof_path(_prof_path: &nsAString) -> Option<PathBuf> {
// Not supported yet.
None
}
struct WrProgramBinaryDiskCache {
cache_path: Option<PathBuf>,
program_count: u32,
is_enabled: bool,
workers: Arc<ThreadPool>,
}
impl WrProgramBinaryDiskCache {
#[allow(dead_code)]
fn new(prof_path: &nsAString, workers: &Arc<ThreadPool>) -> Self {
let cache_path = get_cache_path_from_prof_path(prof_path);
let is_enabled = cache_path.is_some();
let workers = Arc::clone(workers);
WrProgramBinaryDiskCache{
cache_path,
program_count: 0,
is_enabled,
workers,
}
}
fn notify_binary_added(&mut self, program_binary: &Arc<ProgramBinary>) {
if !self.is_enabled {
return;
}
if let Some(ref cache_path) = self.cache_path {
if let Err(_) = create_dir_all(&cache_path) {
error!("failed to create dir for shader disk cache");
return;
}
self.program_count += 1;
if self.program_count > MAX_CACHED_PROGRAM_COUNT {
// Disable disk cache to avoid storing more shader programs to disk
self.is_enabled = false;
return;
}
// Use uuid for file name
let uuid1 = Uuid::new_v4();
let file_name = uuid1.to_hyphenated_string();
let program_binary = Arc::clone(program_binary);
let file_path = cache_path.join(&file_name);
let program_count = self.program_count;
// Save to disk on worker thread
self.workers.spawn(move || {
use std::time::{Instant};
let start = Instant::now();
let data: Vec<u8> = match bincode::serialize(&*program_binary) {
Ok(data) => data,
Err(err) => {
error!("Failed to serialize program binary error: {}", err);
return;
}
};
let mut file = match File::create(&file_path) {
Ok(file) => file,
Err(err) => {
error!("Unable to create file for program binary error: {}", err);
return;
}
};
// Write hash
let hash = fxhash::hash64(&data);
let hash = bincode::serialize(&hash).unwrap();
assert!(hash.len() == 8);
match file.write_all(&hash) {
Err(err) => {
error!("Failed to write hash to file error: {}", err);
}
_ => {},
};
// Write serialized data
match file.write_all(&data) {
Err(err) => {
error!("Failed to write program binary to file error: {}", err);
}
_ => {},
};
let elapsed = start.elapsed();
info!("notify_binary_added: {} ms program_count {}",
(elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64, program_count);
});
}
}
pub fn try_load_from_disk(&mut self, program_cache: &Rc<ProgramCache>) {
if !self.is_enabled {
return;
}
if let Some(ref cache_path) = self.cache_path {
use std::time::{Instant};
let start = Instant::now();
// Load program binaries if exist
if cache_path.exists() && cache_path.is_dir() {
for entry in read_dir(cache_path).unwrap() {
let entry = entry.unwrap();
let path = entry.path();
info!("loading shader file");
match deserialize_program_binary(&path) {
Ok(program) => {
program_cache.load_program_binary(program);
}
Err(err) => {
error!("Failed to desriralize program binary error: {}", err);
}
};
self.program_count += 1;
let elapsed = start.elapsed();
let elapsed_ms = (elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
info!("deserialize_program_binary: {} ms program_count {}", elapsed_ms, self.program_count);
if self.program_count > MAX_CACHED_PROGRAM_COUNT || elapsed_ms > MAX_LOAD_TIME_MS {
// Disable disk cache to avoid storing more shader programs to disk
self.is_enabled = false;
break;
}
}
}
}
}
}
pub struct WrProgramCacheObserver {
disk_cache: Rc<RefCell<WrProgramBinaryDiskCache>>,
}
impl WrProgramCacheObserver {
#[allow(dead_code)]
fn new(disk_cache: Rc<RefCell<WrProgramBinaryDiskCache>>) -> Self {
WrProgramCacheObserver{
disk_cache,
}
}
}
impl ProgramCacheObserver for WrProgramCacheObserver {
fn notify_binary_added(&self, program_binary: &Arc<ProgramBinary>) {
self.disk_cache.borrow_mut().notify_binary_added(program_binary);
}
fn notify_program_binary_failed(&self, _program_binary: &Arc<ProgramBinary>) {
error!("Failed program_binary");
}
}
pub struct WrProgramCache {
program_cache: Rc<ProgramCache>,
disk_cache: Option<Rc<RefCell<WrProgramBinaryDiskCache>>>,
}
impl WrProgramCache {
#[cfg(target_os = "windows")]
pub fn new(prof_path: &nsAString, workers: &Arc<ThreadPool>) -> Self {
let disk_cache = Rc::new(RefCell::new(WrProgramBinaryDiskCache::new(prof_path, workers)));
let program_cache_observer = Box::new(WrProgramCacheObserver::new(Rc::clone(&disk_cache)));
let program_cache = ProgramCache::new(Some(program_cache_observer));
WrProgramCache {
program_cache,
disk_cache: Some(disk_cache),
}
}
#[cfg(not(target_os="windows"))]
pub fn new(_prof_path: &nsAString, _: &Arc<ThreadPool>) -> Self {
let program_cache = ProgramCache::new(None);
WrProgramCache {
program_cache,
disk_cache: None,
}
}
pub fn rc_get(&self) -> &Rc<ProgramCache> {
&self.program_cache
}
pub fn try_load_from_disk(&self) {
if let Some(ref disk_cache) = self.disk_cache {
disk_cache.borrow_mut().try_load_from_disk(&self.program_cache);
} else {
error!("Shader disk cache is not supported");
}
}
}
#[cfg(target_os = "windows")]
pub fn remove_disk_cache(prof_path: &nsAString) -> Result<(), Error> {
use std::fs::remove_dir_all;
use std::time::{Instant};
if let Some(cache_path) = get_cache_path_from_prof_path(prof_path) {
if cache_path.exists() {
let start = Instant::now();
remove_dir_all(&cache_path)?;
let elapsed = start.elapsed();
let elapsed_ms = (elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
info!("remove_disk_cache: {} ms", elapsed_ms);
}
}
Ok(())
}
#[cfg(not(target_os="windows"))]
pub fn remove_disk_cache(_prof_path: &nsAString) -> Result<(), Error> {
error!("Shader disk cache is not supported");
return Err(Error::new(ErrorKind::Other, "Not supported"))
}

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

@ -17,6 +17,10 @@
namespace mozilla {
namespace wr {
static const uint32_t MAX_CACHED_PROGRAM_COUNT = 15;
static const uint64_t MAX_LOAD_TIME_MS = 400;
enum class BorderStyle : uint32_t {
None = 0,
Solid = 1,
@ -1000,6 +1004,10 @@ extern bool is_in_main_thread();
extern bool is_in_render_thread();
WR_INLINE
bool remove_program_binary_disk_cache(const nsAString *aProfPath)
WR_FUNC;
WR_INLINE
const VecU8 *wr_add_ref_arc(const ArcVecU8 *aArc)
WR_FUNC;
@ -1411,7 +1419,8 @@ void wr_program_cache_delete(WrProgramCache *aProgramCache)
WR_DESTRUCTOR_SAFE_FUNC;
WR_INLINE
WrProgramCache *wr_program_cache_new()
WrProgramCache *wr_program_cache_new(const nsAString *aProfPath,
WrThreadPool *aThreadPool)
WR_FUNC;
WR_INLINE
@ -1662,6 +1671,10 @@ void wr_transaction_update_epoch(Transaction *aTxn,
WrEpoch aEpoch)
WR_FUNC;
WR_INLINE
void wr_try_load_shader_from_disk(WrProgramCache *aProgramCache)
WR_FUNC;
WR_INLINE
void wr_vec_u8_free(WrVecU8 aV)
WR_FUNC;

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

@ -34,6 +34,8 @@ struct IPCRemoteStream
bool delayedStart;
IPCRemoteStreamType stream;
int64_t length;
};
// Use IPCStream or OptionalIPCStream in your ipdl to represent serialized

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "IPCStreamDestination.h"
#include "mozilla/InputStreamLengthWrapper.h"
#include "mozilla/Mutex.h"
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
@ -264,6 +265,9 @@ NS_INTERFACE_MAP_END
IPCStreamDestination::IPCStreamDestination()
: mOwningThread(NS_GetCurrentThread())
, mDelayedStart(false)
#ifdef MOZ_DEBUG
, mLengthSet(false)
#endif
{
}
@ -302,6 +306,24 @@ IPCStreamDestination::SetDelayedStart(bool aDelayedStart)
mDelayedStart = aDelayedStart;
}
void
IPCStreamDestination::SetLength(int64_t aLength)
{
MOZ_ASSERT(mReader);
MOZ_ASSERT(!mLengthSet);
#ifdef DEBUG
mLengthSet = true;
#endif
if (aLength != -1) {
nsCOMPtr<nsIInputStream> finalStream;
finalStream = new InputStreamLengthWrapper(mReader.forget(), aLength);
mReader = do_QueryInterface(finalStream);
MOZ_ASSERT(mReader);
}
}
already_AddRefed<nsIInputStream>
IPCStreamDestination::TakeReader()
{

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

@ -39,6 +39,9 @@ public:
void
SetDelayedStart(bool aDelayedStart);
void
SetLength(int64_t aLength);
already_AddRefed<nsIInputStream>
TakeReader();
@ -96,6 +99,10 @@ private:
nsCOMPtr<nsIThread> mOwningThread;
bool mDelayedStart;
#ifdef MOZ_DEBUG
bool mLengthSet;
#endif
};
} // namespace ipc

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

@ -9,6 +9,7 @@
#include "nsIIPCSerializableInputStream.h"
#include "mozilla/Assertions.h"
#include "mozilla/InputStreamLengthHelper.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/File.h"
@ -137,6 +138,14 @@ SerializeInputStream(nsIInputStream* aStream, IPCStream& aValue, M* aManager,
MOZ_ASSERT(aStream);
MOZ_ASSERT(aManager);
// Let's try to take the length using InputStreamLengthHelper. If the length
// cannot be taken synchronously, and its length is needed, the stream needs
// to be fully copied in memory on the deserialization side.
int64_t length;
if (!InputStreamLengthHelper::GetSyncLength(aStream, &length)) {
length = -1;
}
// As a fallback, attempt to stream the data across using a IPCStream
// actor. For blocking streams, create a nonblocking pipe instead,
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);
@ -168,6 +177,7 @@ SerializeInputStream(nsIInputStream* aStream, IPCStream& aValue, M* aManager,
IPCRemoteStream remoteStream;
remoteStream.delayedStart() = aDelayedStart;
remoteStream.stream() = IPCStreamSource::Create(asyncStream, aManager);
remoteStream.length() = length;
aValue = remoteStream;
return true;
@ -379,6 +389,7 @@ DeserializeIPCStream(const IPCStream& aValue)
}
destinationStream->SetDelayedStart(remoteStream.delayedStart());
destinationStream->SetLength(remoteStream.length());
return destinationStream->TakeReader();
}

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

@ -61,6 +61,7 @@ union InputStreamParams
MultiplexInputStreamParams;
SlicedInputStreamParams;
IPCBlobInputStreamParams;
InputStreamLengthWrapperParams;
};
union OptionalInputStreamParams
@ -82,5 +83,12 @@ struct MIMEInputStreamParams
bool startedReading;
};
struct InputStreamLengthWrapperParams
{
InputStreamParams stream;
int64_t length;
bool consumed;
};
} // namespace ipc
} // namespace mozilla

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

@ -13,6 +13,7 @@
#include "mozilla/dom/ipc/IPCBlobInputStream.h"
#include "mozilla/dom/ipc/IPCBlobInputStreamStorage.h"
#include "mozilla/SlicedInputStream.h"
#include "mozilla/InputStreamLengthWrapper.h"
#include "nsComponentManagerUtils.h"
#include "nsDebug.h"
#include "nsID.h"
@ -100,6 +101,10 @@ InputStreamHelper::DeserializeInputStream(const InputStreamParams& aParams,
serializable = new mozilla::SlicedInputStream();
break;
case InputStreamParams::TInputStreamLengthWrapperParams:
serializable = new mozilla::InputStreamLengthWrapper();
break;
default:
MOZ_ASSERT(false, "Unknown params!");
return nullptr;

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

@ -97,8 +97,8 @@ typedef void
extern JS_PUBLIC_API(void)
SetRealmNameCallback(JSContext* cx, RealmNameCallback callback);
// Get the global object for the given realm. Returns null only if `realm` is
// the atoms realm.
// Get the global object for the given realm. This only returns nullptr during
// GC, between collecting the global object and destroying the Realm.
extern JS_PUBLIC_API(JSObject*)
GetRealmGlobalOrNull(Handle<Realm*> realm);

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

@ -884,7 +884,7 @@ class RootingContext
return reinterpret_cast<RootingContext*>(cx);
}
friend JSCompartment* js::GetContextCompartment(const JSContext* cx);
friend JS::Realm* js::GetContextRealm(const JSContext* cx);
friend JS::Zone* js::GetContextZone(const JSContext* cx);
};
@ -1054,10 +1054,16 @@ namespace js {
* usable without resorting to jsfriendapi.h, and when JSContext is an
* incomplete type.
*/
inline JS::Realm*
GetContextRealm(const JSContext* cx)
{
return JS::RootingContext::get(cx)->realm_;
}
inline JSCompartment*
GetContextCompartment(const JSContext* cx)
{
return GetCompartmentForRealm(JS::RootingContext::get(cx)->realm_);
return GetCompartmentForRealm(GetContextRealm(cx));
}
inline JS::Zone*

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

@ -378,9 +378,6 @@ UncheckedUnwrapWithoutExpose(JSObject* obj);
void
ReportAccessDenied(JSContext* cx);
JS_FRIEND_API(bool)
IsCrossCompartmentWrapper(JSObject* obj);
JS_FRIEND_API(void)
NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper);

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

@ -174,6 +174,7 @@ const WHITELIST_TYPES: &'static [&'static str] = &[
"JSAutoStructuredCloneBuffer",
"JSClass",
"JSClassOps",
"JSCompartment",
"JSContext",
"JSErrNum",
"JSErrorCallback",

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

@ -1055,7 +1055,7 @@ pub unsafe fn get_object_class(obj: *mut JSObject) -> *const JSClass {
#[inline]
pub unsafe fn get_object_compartment(obj: *mut JSObject) -> *mut JSCompartment {
(*get_object_group(obj)).compartment
(*get_object_group(obj)).realm as *mut JSCompartment
}
#[inline]

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

@ -1999,7 +1999,7 @@ CreateObjectConstructor(JSContext* cx, JSProtoKey key)
static JSObject*
CreateObjectPrototype(JSContext* cx, JSProtoKey key)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
MOZ_ASSERT(cx->global()->isNative());
/*

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

@ -1507,7 +1507,8 @@ BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
// Usage: (check for the return value is omitted for simplicity)
//
// `try { try_block } catch (ex) { catch_block }`
// TryEmitter tryCatch(this, TryEmitter::TryCatch);
// TryEmitter tryCatch(this, TryEmitter::Kind::TryCatch,
// TryEmitter::ControlKind::Syntactic);
// tryCatch.emitTry();
// emit(try_block);
// tryCatch.emitCatch();
@ -1515,7 +1516,8 @@ BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
// tryCatch.emitEnd();
//
// `try { try_block } finally { finally_block }`
// TryEmitter tryCatch(this, TryEmitter::TryFinally);
// TryEmitter tryCatch(this, TryEmitter::Kind::TryFinally,
// TryEmitter::ControlKind::Syntactic);
// tryCatch.emitTry();
// emit(try_block);
// // finally_pos: The "{" character's position in the source code text.
@ -1524,7 +1526,8 @@ BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
// tryCatch.emitEnd();
//
// `try { try_block } catch (ex) {catch_block} finally { finally_block }`
// TryEmitter tryCatch(this, TryEmitter::TryCatchFinally);
// TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
// TryEmitter::ControlKind::Syntactic);
// tryCatch.emitTry();
// emit(try_block);
// tryCatch.emitCatch();
@ -1536,17 +1539,23 @@ BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
class MOZ_STACK_CLASS TryEmitter
{
public:
enum Kind {
enum class Kind {
TryCatch,
TryCatchFinally,
TryFinally
};
// Whether the catch and finally blocks handle the frame's return value.
// If UseRetVal is specified, the bytecode marked with "*" are emitted
// to clear return value with `undefined` before the catch block and the
// finally block, and also to save/restore the return value before/after
// the finally block.
// Syntactic try-catch-finally and internally used non-syntactic
// try-catch-finally behave differently for 2 points.
//
// The first one is whether TryFinallyControl is used or not.
// See the comment for `controlInfo_`.
//
// The second one is whether the catch and finally blocks handle the frame's
// return value. For syntactic try-catch-finally, the bytecode marked with
// "*" are emitted to clear return value with `undefined` before the catch
// block and the finally block, and also to save/restore the return value
// before/after the finally block.
//
// JSOP_TRY
//
@ -1581,27 +1590,17 @@ class MOZ_STACK_CLASS TryEmitter
// end:
// JSOP_JUMPTARGET
//
// For syntactic try-catch-finally, UseRetVal should be used.
// For non-syntactic try-catch-finally, DontUseRetVal should be used.
enum ShouldUseRetVal {
UseRetVal,
DontUseRetVal
};
// Whether this class should use TryFinallyControl.
// See the comment for `controlInfo_`.
//
// For syntactic try-catch-finally, UseControl should be used.
// For non-syntactic try-catch-finally, DontUseControl should be used.
enum ShouldUseControl {
UseControl,
DontUseControl,
// For syntactic try-catch-finally, Syntactic should be used.
// For non-syntactic try-catch-finally, NonSyntactic should be used.
enum class ControlKind {
Syntactic,
NonSyntactic
};
private:
BytecodeEmitter* bce_;
Kind kind_;
ShouldUseRetVal retValKind_;
ControlKind controlKind_;
// Track jumps-over-catches and gosubs-to-finally for later fixup.
//
@ -1609,19 +1608,17 @@ class MOZ_STACK_CLASS TryEmitter
// jumps-over-catches) result in a GOSUB being written into the bytecode
// stream and fixed-up later.
//
// If ShouldUseControl is DontUseControl, all that handling is skipped.
// DontUseControl is used by yield* and the internal try-catch around
// IteratorClose. These internal uses must:
// For non-syntactic try-catch-finally, all that handling is skipped.
// The non-syntactic try-catch-finally must:
// * have only one catch block
// * have JSOP_GOTO at the end of catch-block
// * have no non-local-jump
// * don't use finally block for normal completion of try-block and
// catch-block
//
// Additionally, a finally block may be emitted when ShouldUseControl is
// DontUseControl, even if the kind is not TryCatchFinally or TryFinally,
// because GOSUBs are not emitted. This internal use shares the
// requirements as above.
// Additionally, a finally block may be emitted for non-syntactic
// try-catch-finally, even if the kind is TryCatch, because GOSUBs are not
// emitted.
Maybe<TryFinallyControl> controlInfo_;
// The stack depth before emitting JSOP_TRY.
@ -1642,6 +1639,7 @@ class MOZ_STACK_CLASS TryEmitter
// The offset of JSOP_JUMPTARGET at the beginning of the finally block.
JumpTarget finallyStart_;
#ifdef DEBUG
// The state of this emitter.
//
// +-------+ emitTry +-----+ emitCatch +-------+ emitEnd +-----+
@ -1653,7 +1651,7 @@ class MOZ_STACK_CLASS TryEmitter
// | v emitFinally +---------+ |
// +->+------------>| Finally |--+
// +---------+
enum State {
enum class State {
// The initial state.
Start,
@ -1670,40 +1668,42 @@ class MOZ_STACK_CLASS TryEmitter
End
};
State state_;
#endif
bool hasCatch() const {
return kind_ == TryCatch || kind_ == TryCatchFinally;
return kind_ == Kind::TryCatch || kind_ == Kind::TryCatchFinally;
}
bool hasFinally() const {
return kind_ == TryCatchFinally || kind_ == TryFinally;
return kind_ == Kind::TryCatchFinally || kind_ == Kind::TryFinally;
}
public:
TryEmitter(BytecodeEmitter* bce, Kind kind, ShouldUseRetVal retValKind = UseRetVal,
ShouldUseControl controlKind = UseControl)
TryEmitter(BytecodeEmitter* bce, Kind kind, ControlKind controlKind)
: bce_(bce),
kind_(kind),
retValKind_(retValKind),
controlKind_(controlKind),
depth_(0),
noteIndex_(0),
tryStart_(0),
state_(Start)
tryStart_(0)
#ifdef DEBUG
, state_(State::Start)
#endif
{
if (controlKind == UseControl)
if (controlKind_ == ControlKind::Syntactic)
controlInfo_.emplace(bce_, hasFinally() ? StatementKind::Finally : StatementKind::Try);
finallyStart_.offset = 0;
}
// Emits JSOP_GOTO to the end of try-catch-finally.
// Used in `yield*`.
bool emitJumpOverCatchAndFinally() {
MOZ_MUST_USE bool emitJumpOverCatchAndFinally() {
if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_))
return false;
return true;
}
bool emitTry() {
MOZ_ASSERT(state_ == Start);
MOZ_MUST_USE bool emitTry() {
MOZ_ASSERT(state_ == State::Start);
// Since an exception can be thrown at any place inside the try block,
// we need to restore the stack and the scope chain before we transfer
@ -1721,13 +1721,15 @@ class MOZ_STACK_CLASS TryEmitter
return false;
tryStart_ = bce_->offset();
state_ = Try;
#ifdef DEBUG
state_ = State::Try;
#endif
return true;
}
private:
bool emitTryEnd() {
MOZ_ASSERT(state_ == Try);
MOZ_MUST_USE bool emitTryEnd() {
MOZ_ASSERT(state_ == State::Try);
MOZ_ASSERT(depth_ == bce_->stackDepth);
// GOSUB to finally, if present.
@ -1751,14 +1753,14 @@ class MOZ_STACK_CLASS TryEmitter
}
public:
bool emitCatch() {
MOZ_ASSERT(state_ == Try);
MOZ_MUST_USE bool emitCatch() {
MOZ_ASSERT(state_ == State::Try);
if (!emitTryEnd())
return false;
MOZ_ASSERT(bce_->stackDepth == depth_);
if (retValKind_ == UseRetVal) {
if (controlKind_ == ControlKind::Syntactic) {
// Clear the frame's return value that might have been set by the
// try block:
//
@ -1769,13 +1771,15 @@ class MOZ_STACK_CLASS TryEmitter
return false;
}
state_ = Catch;
#ifdef DEBUG
state_ = State::Catch;
#endif
return true;
}
private:
bool emitCatchEnd() {
MOZ_ASSERT(state_ == Catch);
MOZ_MUST_USE bool emitCatchEnd() {
MOZ_ASSERT(state_ == State::Catch);
if (!controlInfo_)
return true;
@ -1799,24 +1803,26 @@ class MOZ_STACK_CLASS TryEmitter
// "{" character in the source code text, to improve line:column number in
// the error reporting.
// For non-syntactic try-catch-finally, `finallyPos` can be omitted.
bool emitFinally(const Maybe<uint32_t>& finallyPos = Nothing()) {
MOZ_MUST_USE bool emitFinally(const Maybe<uint32_t>& finallyPos = Nothing()) {
// If we are using controlInfo_ (i.e., emitting a syntactic try
// blocks), we must have specified up front if there will be a finally
// close. For internal try blocks, like those emitted for yield* and
// IteratorClose inside for-of loops, we can emitFinally even without
// specifying up front, since the internal try blocks emit no GOSUBs.
// close. For internal non-syntactic try blocks, like those emitted for
// yield* and IteratorClose inside for-of loops, we can emitFinally even
// without specifying up front, since the internal non-syntactic try
// blocks emit no GOSUBs.
if (!controlInfo_) {
if (kind_ == TryCatch)
kind_ = TryCatchFinally;
if (kind_ == Kind::TryCatch)
kind_ = Kind::TryCatchFinally;
} else {
MOZ_ASSERT(hasFinally());
}
if (state_ == Try) {
if (!hasCatch()) {
MOZ_ASSERT(state_ == State::Try);
if (!emitTryEnd())
return false;
} else {
MOZ_ASSERT(state_ == Catch);
MOZ_ASSERT(state_ == State::Catch);
if (!emitCatchEnd())
return false;
}
@ -1841,7 +1847,7 @@ class MOZ_STACK_CLASS TryEmitter
if (!bce_->emit1(JSOP_FINALLY))
return false;
if (retValKind_ == UseRetVal) {
if (controlKind_ == ControlKind::Syntactic) {
if (!bce_->emit1(JSOP_GETRVAL))
return false;
@ -1855,15 +1861,17 @@ class MOZ_STACK_CLASS TryEmitter
return false;
}
state_ = Finally;
#ifdef DEBUG
state_ = State::Finally;
#endif
return true;
}
private:
bool emitFinallyEnd() {
MOZ_ASSERT(state_ == Finally);
MOZ_MUST_USE bool emitFinallyEnd() {
MOZ_ASSERT(state_ == State::Finally);
if (retValKind_ == UseRetVal) {
if (controlKind_ == ControlKind::Syntactic) {
if (!bce_->emit1(JSOP_SETRVAL))
return false;
}
@ -1876,14 +1884,13 @@ class MOZ_STACK_CLASS TryEmitter
}
public:
bool emitEnd() {
if (state_ == Catch) {
MOZ_ASSERT(!hasFinally());
MOZ_MUST_USE bool emitEnd() {
if (!hasFinally()) {
MOZ_ASSERT(state_ == State::Catch);
if (!emitCatchEnd())
return false;
} else {
MOZ_ASSERT(state_ == Finally);
MOZ_ASSERT(hasFinally());
MOZ_ASSERT(state_ == State::Finally);
if (!emitFinallyEnd())
return false;
}
@ -1914,34 +1921,53 @@ class MOZ_STACK_CLASS TryEmitter
return false;
}
state_ = End;
#ifdef DEBUG
state_ = State::End;
#endif
return true;
}
};
// Class for emitting bytecode for blocks like if-then-else.
//
// This class can be used to emit single if-then-else block. Cascading
// elseif's need multiple instances of this class.
// This class can be used to emit single if-then-else block, or cascading
// else-if blocks.
//
// Usage: (check for the return value is omitted for simplicity)
//
// `if (cond) then_block`
// IfThenElseEmitter ifThen(this);
// emit(cond);
// ifThen.emitIf();
// ifThen.emitThen();
// emit(then_block);
// ifThen.emitEnd();
//
// `if (cond) then_block else else_block`
// IfThenElseEmitter ifThenElse(this);
// emit(cond);
// ifThenElse.emitIfElse();
// ifThenElse.emitThenElse();
// emit(then_block);
// ifThenElse.emitElse();
// emit(else_block);
// ifThenElse.emitEnd();
//
// `if (c1) b1 else if (c2) b2 else if (c3) b3 else b4`
// IfThenElseEmitter ifThenElse(this);
// emit(c1);
// ifThenElse.emitThenElse();
// emit(b1);
// ifThenElse.emitElseIf();
// emit(c2);
// ifThenElse.emitThenElse();
// emit(b2);
// ifThenElse.emitElseIf();
// emit(c3);
// ifThenElse.emitThenElse();
// emit(b3);
// ifThenElse.emitElse();
// emit(b4);
// ifThenElse.emitEnd();
//
// `cond ? then_expr : else_expr`
// IfThenElseEmitter condElse(this);
// emit(cond);
@ -1955,7 +1981,10 @@ class MOZ_STACK_CLASS IfThenElseEmitter
{
BytecodeEmitter* bce_;
// Jump around the then clause, to the beginning of the else clause.
JumpList jumpAroundThen_;
// Jump around the else clause, to the end of the entire branch.
JumpList jumpsAroundElse_;
// The stack depth before emitting the then block.
@ -1968,67 +1997,70 @@ class MOZ_STACK_CLASS IfThenElseEmitter
// The number of values pushed in the then and else blocks.
int32_t pushed_;
bool calculatedPushed_;
#endif
// The state of this emitter.
//
// +-------+ emitIf +----+ emitEnd +-----+
// | Start |-+----------->| If |-------------------------+-------->| End |
// +-------+ | +----+ | +-----+
// +-------+ emitCond +------+ emitElse +------+ emitEnd +-----+
// | Start |-+--------->| Cond |--------->| Else |------>+------->| End |
// +-------+ | +------+ +------+ ^ +-----+
// | |
// | emitCond +------+ emitElse +------+ |
// +----------->| Cond |---+--------->| Else |-+
// | +------+ | +------+
// | |
// | emitIfElse +--------+ |
// +----------->| IfElse |-+
// +--------+
enum State {
// v emitThen +------+ |
// +->+--------->| Then |------------------------>+
// ^ | +------+ ^
// | | |
// | | +---+
// | | |
// | | emitThenElse +----------+ emitElse +------+ |
// | +------------->| ThenElse |-+--------->| Else |-+
// | +----------+ | +------+
// | |
// | | emitElseIf +--------+
// | +----------->| ElseIf |-+
// | +--------+ |
// | |
// +------------------------------------------------------+
enum class State {
// The initial state.
Start,
// After calling emitIf.
If,
// After calling emitThen.
Then,
// After calling emitCond.
Cond,
// After calling emitIfElse.
IfElse,
// After calling emitThenElse.
ThenElse,
// After calling Else.
// After calling emitElse.
Else,
// After calling emitElseIf.
ElseIf,
// After calling emitEnd.
End
};
State state_;
#endif
public:
explicit IfThenElseEmitter(BytecodeEmitter* bce)
: bce_(bce),
thenDepth_(0),
thenDepth_(0)
#ifdef DEBUG
pushed_(0),
calculatedPushed_(false),
, pushed_(0)
, calculatedPushed_(false)
, state_(State::Start)
#endif
state_(Start)
{}
~IfThenElseEmitter()
{}
private:
bool emitIf(State nextState) {
MOZ_ASSERT(state_ == Start || state_ == Else);
MOZ_ASSERT(nextState == If || nextState == IfElse || nextState == Cond);
// Clear jumpAroundThen_ offset that points previous JSOP_IFEQ.
if (state_ == Else)
jumpAroundThen_ = JumpList();
MOZ_MUST_USE bool emitIfInternal(SrcNoteType type) {
// Emit an annotated branch-if-false around the then part.
SrcNoteType type = nextState == If ? SRC_IF : nextState == IfElse ? SRC_IF_ELSE : SRC_COND;
if (!bce_->newSrcNote(type))
return false;
if (!bce_->emitJump(JSOP_IFEQ, &jumpAroundThen_))
@ -2039,10 +2071,9 @@ class MOZ_STACK_CLASS IfThenElseEmitter
// If DEBUG, this is also necessary to calculate |pushed_|.
thenDepth_ = bce_->stackDepth;
#else
if (nextState == IfElse || nextState == Cond)
if (type == SRC_COND || type == SRC_IF_ELSE)
thenDepth_ = bce_->stackDepth;
#endif
state_ = nextState;
return true;
}
@ -2058,21 +2089,41 @@ class MOZ_STACK_CLASS IfThenElseEmitter
}
public:
bool emitIf() {
return emitIf(If);
MOZ_MUST_USE bool emitThen() {
MOZ_ASSERT(state_ == State::Start || state_ == State::ElseIf);
if (!emitIfInternal(SRC_IF))
return false;
#ifdef DEBUG
state_ = State::Then;
#endif
return true;
}
bool emitCond() {
return emitIf(Cond);
MOZ_MUST_USE bool emitCond() {
MOZ_ASSERT(state_ == State::Start);
if (!emitIfInternal(SRC_COND))
return false;
#ifdef DEBUG
state_ = State::Cond;
#endif
return true;
}
bool emitIfElse() {
return emitIf(IfElse);
MOZ_MUST_USE bool emitThenElse() {
MOZ_ASSERT(state_ == State::Start || state_ == State::ElseIf);
if (!emitIfInternal(SRC_IF_ELSE))
return false;
#ifdef DEBUG
state_ = State::ThenElse;
#endif
return true;
}
bool emitElse() {
MOZ_ASSERT(state_ == IfElse || state_ == Cond);
private:
MOZ_MUST_USE bool emitElseInternal() {
calculateOrCheckPushed();
// Emit a jump from the end of our then part around the else part. The
@ -2085,19 +2136,54 @@ class MOZ_STACK_CLASS IfThenElseEmitter
if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
return false;
// Clear jumpAroundThen_ offset, to tell emitEnd there was an else part.
jumpAroundThen_ = JumpList();
// Restore stack depth of the then part.
bce_->stackDepth = thenDepth_;
state_ = Else;
#ifdef DEBUG
state_ = State::Else;
#endif
return true;
}
bool emitEnd() {
MOZ_ASSERT(state_ == If || state_ == Else);
public:
MOZ_MUST_USE bool emitElse() {
MOZ_ASSERT(state_ == State::ThenElse || state_ == State::Cond);
if (!emitElseInternal())
return false;
#ifdef DEBUG
state_ = State::Else;
#endif
return true;
}
MOZ_MUST_USE bool emitElseIf() {
MOZ_ASSERT(state_ == State::ThenElse);
if (!emitElseInternal())
return false;
#ifdef DEBUG
state_ = State::ElseIf;
#endif
return true;
}
MOZ_MUST_USE bool emitEnd() {
MOZ_ASSERT(state_ == State::Then || state_ == State::Else);
// If there was an else part for the last branch, jumpAroundThen_ is
// already fixed up when emitting the else part.
MOZ_ASSERT_IF(state_ == State::Then, jumpAroundThen_.offset != -1);
MOZ_ASSERT_IF(state_ == State::Else, jumpAroundThen_.offset == -1);
calculateOrCheckPushed();
if (state_ == If) {
// No else part, fixup the branch-if-false to come here.
if (jumpAroundThen_.offset != -1) {
// No else part for the last branch, fixup the branch-if-false to
// come here.
if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
return false;
}
@ -2106,7 +2192,9 @@ class MOZ_STACK_CLASS IfThenElseEmitter
if (!bce_->emitJumpTargetAndPatch(jumpsAroundElse_))
return false;
state_ = End;
#ifdef DEBUG
state_ = State::End;
#endif
return true;
}
@ -2186,8 +2274,7 @@ class ForOfLoopControl : public LoopControl
}
bool emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce) {
tryCatch_.emplace(bce, TryEmitter::TryCatch, TryEmitter::DontUseRetVal,
TryEmitter::DontUseControl);
tryCatch_.emplace(bce, TryEmitter::Kind::TryCatch, TryEmitter::ControlKind::NonSyntactic);
if (!tryCatch_->emitTry())
return false;
@ -2217,7 +2304,7 @@ class ForOfLoopControl : public LoopControl
return false;
IfThenElseEmitter ifIteratorIsNotClosed(bce);
if (!ifIteratorIsNotClosed.emitIf()) // ITER ... EXCEPTION
if (!ifIteratorIsNotClosed.emitThen()) // ITER ... EXCEPTION
return false;
MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_));
@ -2243,7 +2330,7 @@ class ForOfLoopControl : public LoopControl
IfThenElseEmitter ifGeneratorClosing(bce);
if (!bce->emit1(JSOP_ISGENCLOSING)) // ITER ... FTYPE FVALUE CLOSING
return false;
if (!ifGeneratorClosing.emitIf()) // ITER ... FTYPE FVALUE
if (!ifGeneratorClosing.emitThen()) // ITER ... FTYPE FVALUE
return false;
if (!bce->emitDupAt(slotFromTop + 1)) // ITER ... FTYPE FVALUE ITER
return false;
@ -5423,7 +5510,7 @@ BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope,
if (!emitPushNotUndefinedOrNull()) // ... ITER RET NOT-UNDEF-OR-NULL
return false;
if (!ifReturnMethodIsDefined.emitIfElse()) // ... ITER RET
if (!ifReturnMethodIsDefined.emitThenElse()) // ... ITER RET
return false;
if (completionKind == CompletionKind::Throw) {
@ -5459,8 +5546,7 @@ BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope,
Maybe<TryEmitter> tryCatch;
if (completionKind == CompletionKind::Throw) {
tryCatch.emplace(this, TryEmitter::TryCatch, TryEmitter::DontUseRetVal,
TryEmitter::DontUseControl);
tryCatch.emplace(this, TryEmitter::Kind::TryCatch, TryEmitter::ControlKind::NonSyntactic);
// Mutate stack to balance stack for try-catch.
if (!emit1(JSOP_UNDEFINED)) // ... RET ITER UNDEF
@ -5804,7 +5890,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav
// If spread is not the first element of the pattern,
// iterator can already be completed.
// ... OBJ NEXT ITER *LREF DONE
if (!ifThenElse.emitIfElse()) // ... OBJ NEXT ITER *LREF
if (!ifThenElse.emitThenElse()) // ... OBJ NEXT ITER *LREF
return false;
if (!emitUint32Operand(JSOP_NEWARRAY, 0)) // ... OBJ NEXT ITER *LREF ARRAY
@ -5859,7 +5945,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav
IfThenElseEmitter ifAlreadyDone(this);
if (!isFirst) {
// ... OBJ NEXT ITER *LREF DONE
if (!ifAlreadyDone.emitIfElse()) // ... OBJ NEXT ITER *LREF
if (!ifAlreadyDone.emitThenElse()) // ... OBJ NEXT ITER *LREF
return false;
if (!emit1(JSOP_UNDEFINED)) // ... OBJ NEXT ITER *LREF UNDEF
@ -5894,7 +5980,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav
return false;
IfThenElseEmitter ifDone(this);
if (!ifDone.emitIfElse()) // ... OBJ NEXT ITER DONE *LREF RESULT
if (!ifDone.emitThenElse()) // ... OBJ NEXT ITER DONE *LREF RESULT
return false;
if (!emit1(JSOP_POP)) // ... OBJ NEXT ITER DONE *LREF
@ -5946,7 +6032,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav
// IteratorClose.
// ... OBJ NEXT ITER DONE
IfThenElseEmitter ifDone(this);
if (!ifDone.emitIfElse()) // ... OBJ NEXT ITER
if (!ifDone.emitThenElse()) // ... OBJ NEXT ITER
return false;
if (!emitPopN(2)) // ... OBJ
return false;
@ -6788,14 +6874,14 @@ BytecodeEmitter::emitTry(ParseNode* pn)
TryEmitter::Kind kind;
if (catchScope) {
if (finallyNode)
kind = TryEmitter::TryCatchFinally;
kind = TryEmitter::Kind::TryCatchFinally;
else
kind = TryEmitter::TryCatch;
kind = TryEmitter::Kind::TryCatch;
} else {
MOZ_ASSERT(finallyNode);
kind = TryEmitter::TryFinally;
kind = TryEmitter::Kind::TryFinally;
}
TryEmitter tryCatch(this, kind);
TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
if (!tryCatch.emitTry())
return false;
@ -6852,10 +6938,10 @@ BytecodeEmitter::emitIf(ParseNode* pn)
ParseNode* elseNode = pn->pn_kid3;
if (elseNode) {
if (!ifThenElse.emitIfElse())
if (!ifThenElse.emitThenElse())
return false;
} else {
if (!ifThenElse.emitIf())
if (!ifThenElse.emitThen())
return false;
}
@ -6864,14 +6950,18 @@ BytecodeEmitter::emitIf(ParseNode* pn)
return false;
if (elseNode) {
if (!ifThenElse.emitElse())
return false;
if (elseNode->isKind(ParseNodeKind::If)) {
pn = elseNode;
if (!ifThenElse.emitElseIf())
return false;
goto if_again;
}
if (!ifThenElse.emitElse())
return false;
/* Emit code for the else part. */
if (!emitTreeInBranch(elseNode))
return false;
@ -7074,7 +7164,7 @@ BytecodeEmitter::emitAsyncIterator()
return false;
if (!emit1(JSOP_NOT)) // OBJ ITERFN UNDEF-OR-NULL
return false;
if (!ifAsyncIterIsUndefined.emitIfElse()) // OBJ ITERFN
if (!ifAsyncIterIsUndefined.emitThenElse()) // OBJ ITERFN
return false;
if (!emit1(JSOP_POP)) // OBJ
@ -7389,7 +7479,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
IfThenElseEmitter ifDone(this);
if (!ifDone.emitIf()) // NEXT ITER RESULT
if (!ifDone.emitThen()) // NEXT ITER RESULT
return false;
// Remove RESULT from the stack to release it.
@ -8537,8 +8627,8 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
int32_t startDepth = stackDepth;
MOZ_ASSERT(startDepth >= 3);
TryEmitter tryCatch(this, TryEmitter::TryCatchFinally, TryEmitter::DontUseRetVal,
TryEmitter::DontUseControl);
TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
TryEmitter::ControlKind::NonSyntactic);
if (!tryCatch.emitJumpOverCatchAndFinally()) // NEXT ITER RESULT
return false;
@ -8582,7 +8672,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
IfThenElseEmitter ifThrowMethodIsNotDefined(this);
if (!ifThrowMethodIsNotDefined.emitIf()) // NEXT ITER RESULT EXCEPTION ITER THROW
if (!ifThrowMethodIsNotDefined.emitThen()) // NEXT ITER RESULT EXCEPTION ITER THROW
return false;
savedDepthTemp = stackDepth;
if (!emit1(JSOP_POP)) // NEXT ITER RESULT EXCEPTION ITER
@ -8640,7 +8730,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
IfThenElseEmitter ifGeneratorClosing(this);
if (!emit1(JSOP_ISGENCLOSING)) // NEXT ITER RESULT FTYPE FVALUE CLOSING
return false;
if (!ifGeneratorClosing.emitIf()) // NEXT ITER RESULT FTYPE FVALUE
if (!ifGeneratorClosing.emitThen()) // NEXT ITER RESULT FTYPE FVALUE
return false;
// Step ii.
@ -8664,7 +8754,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
//
// Call "return" with the argument passed to Generator.prototype.return,
// which is currently in rval.value.
if (!ifReturnMethodIsDefined.emitIfElse()) // NEXT ITER OLDRESULT FTYPE FVALUE ITER RET
if (!ifReturnMethodIsDefined.emitThenElse()) // NEXT ITER OLDRESULT FTYPE FVALUE ITER RET
return false;
if (!emit1(JSOP_SWAP)) // NEXT ITER OLDRESULT FTYPE FVALUE RET ITER
return false;
@ -8694,7 +8784,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitAtomOp(cx->names().done, JSOP_GETPROP)) // NEXT ITER OLDRESULT FTYPE FVALUE RESULT DONE
return false;
if (!ifReturnDone.emitIfElse()) // NEXT ITER OLDRESULT FTYPE FVALUE RESULT
if (!ifReturnDone.emitThenElse()) // NEXT ITER OLDRESULT FTYPE FVALUE RESULT
return false;
if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) // NEXT ITER OLDRESULT FTYPE FVALUE VALUE
return false;
@ -9453,7 +9543,7 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUs
if (!emit1(JSOP_NOT))
return false;
if (!ifNotOptimizable.emitIf())
if (!ifNotOptimizable.emitThen())
return false;
if (!emit1(JSOP_POP))
@ -10581,7 +10671,7 @@ BytecodeEmitter::emitClass(ParseNode* pn)
return false;
// [THEN] funProto = heritage, objProto = heritage.prototype
if (!ifThenElse.emitIfElse())
if (!ifThenElse.emitThenElse())
return false;
if (!emit1(JSOP_DUP)) // ... HERITAGE HERITAGE
return false;

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

@ -86,7 +86,7 @@ GCRuntime::tryNewNurseryObject(JSContext* cx, size_t thingSize, size_t nDynamicS
MOZ_ASSERT(cx->isNurseryAllocAllowed());
MOZ_ASSERT(!cx->isNurseryAllocSuppressed());
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
JSObject* obj = cx->nursery().allocateObject(cx, thingSize, nDynamicSlots, clasp);
if (obj)
@ -140,7 +140,7 @@ GCRuntime::tryNewNurseryString(JSContext* cx, size_t thingSize, AllocKind kind)
MOZ_ASSERT(cx->isNurseryAllocAllowed());
MOZ_ASSERT(!cx->helperThread());
MOZ_ASSERT(!cx->isNurseryAllocSuppressed());
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
Cell* cell = cx->nursery().allocateString(cx->zone(), thingSize, kind);
if (cell)
@ -275,13 +275,13 @@ GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind)
}
#if defined(JS_GC_ZEAL) || defined(DEBUG)
MOZ_ASSERT_IF(cx->realm()->isAtomsRealm(),
MOZ_ASSERT_IF(cx->zone()->isAtomsZone(),
kind == AllocKind::ATOM ||
kind == AllocKind::FAT_INLINE_ATOM ||
kind == AllocKind::SYMBOL ||
kind == AllocKind::JITCODE ||
kind == AllocKind::SCOPE);
MOZ_ASSERT_IF(!cx->realm()->isAtomsRealm(),
MOZ_ASSERT_IF(!cx->zone()->isAtomsZone(),
kind != AllocKind::ATOM &&
kind != AllocKind::FAT_INLINE_ATOM);
MOZ_ASSERT(!JS::CurrentThreadIsHeapBusy());

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

@ -83,7 +83,7 @@ AtomMarkingRuntime::computeBitmapFromChunkMarkBits(JSRuntime* runtime, DenseBitm
if (!bitmap.ensureSpace(allocatedWords))
return false;
Zone* atomsZone = runtime->unsafeAtomsRealm()->zone();
Zone* atomsZone = runtime->unsafeAtomsZone();
for (auto thingKind : AllAllocKinds()) {
for (ArenaIter aiter(atomsZone, thingKind); !aiter.done(); aiter.next()) {
Arena* arena = aiter.get();
@ -117,7 +117,7 @@ AddBitmapToChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap)
static_assert(ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD,
"ArenaBitmapWords must evenly divide ArenaBitmapBits");
Zone* atomsZone = runtime->unsafeAtomsRealm()->zone();
Zone* atomsZone = runtime->unsafeAtomsZone();
for (auto thingKind : AllAllocKinds()) {
for (ArenaIter aiter(atomsZone, thingKind); !aiter.done(); aiter.next()) {
Arena* arena = aiter.get();

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

@ -3852,7 +3852,6 @@ Zone::sweepCompartments(FreeOp* fop, bool keepAtleastOne, bool destroyingRuntime
while (read < end) {
JSCompartment* comp = *read++;
Realm* realm = JS::GetRealmForCompartment(comp);
MOZ_ASSERT(!realm->isAtomsRealm());
/*
* Don't delete the last compartment and realm if all the ones before
@ -4126,7 +4125,7 @@ CompartmentCheckTracer::onChild(const JS::GCCellPtr& thing)
{
JSCompartment* comp = DispatchTyped(MaybeCompartmentFunctor(), thing);
if (comp && compartment) {
MOZ_ASSERT(comp == compartment || runtime()->isAtomsCompartment(comp) ||
MOZ_ASSERT(comp == compartment ||
(srcKind == JS::TraceKind::Object &&
InCrossCompartmentMap(static_cast<JSObject*>(src), thing)));
} else {
@ -4223,7 +4222,7 @@ GCRuntime::prepareZonesForCollection(JS::gcreason::Reason reason, bool* isFullOu
/* Assert that zone state is as we expect */
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
MOZ_ASSERT(!zone->isCollecting());
MOZ_ASSERT(!zone->compartments().empty());
MOZ_ASSERT_IF(!zone->isAtomsZone(), !zone->compartments().empty());
for (auto i : AllAllocKinds())
MOZ_ASSERT(!zone->arenas.arenaListsToSweep(i));
}
@ -4251,7 +4250,7 @@ GCRuntime::prepareZonesForCollection(JS::gcreason::Reason reason, bool* isFullOu
// executable code limit.
bool canAllocateMoreCode = jit::CanLikelyAllocateMoreExecutableMemory();
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->scheduledForDestruction = false;
c->maybeAlive = false;
for (RealmsInCompartmentIter r(c); !r.done(); r.next()) {
@ -4478,7 +4477,7 @@ GCRuntime::markCompartments()
Vector<JSCompartment*, 0, js::SystemAllocPolicy> workList;
for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) {
for (CompartmentsIter comp(rt); !comp.done(); comp.next()) {
if (comp->maybeAlive) {
if (!workList.append(comp))
return;
@ -4895,7 +4894,7 @@ DropStringWrappers(JSRuntime* rt)
* us to sweep the wrappers in all compartments every time we sweep a
* compartment group.
*/
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
for (CompartmentsIter c(rt); !c.done(); c.next()) {
for (JSCompartment::StringWrapperEnum e(c); !e.empty(); e.popFront()) {
MOZ_ASSERT(e.front().key().is<JSString*>());
e.removeFront();
@ -5137,7 +5136,7 @@ static void
AssertNoWrappersInGrayList(JSRuntime* rt)
{
#ifdef DEBUG
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
for (CompartmentsIter c(rt); !c.done(); c.next()) {
MOZ_ASSERT(!c->gcIncomingGrayPointers);
for (JSCompartment::NonStringWrapperEnum e(c); !e.empty(); e.popFront())
AssertNotOnGrayList(&e.front().value().unbarrieredGet().toObject());
@ -5412,7 +5411,7 @@ UpdateAtomsBitmap(GCParallelTask* task)
// For convenience sweep these tables non-incrementally as part of bitmap
// sweeping; they are likely to be much smaller than the main atoms table.
runtime->unsafeSymbolRegistry().sweep();
for (RealmsIter realm(runtime, SkipAtoms); !realm.done(); realm.next())
for (RealmsIter realm(runtime); !realm.done(); realm.next())
realm->sweepVarNames();
}
@ -6888,7 +6887,7 @@ GCRuntime::resetIncrementalGC(gc::AbortReason reason, AutoTraceSession& session)
case State::Sweep: {
marker.reset();
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
for (CompartmentsIter c(rt); !c.done(); c.next())
c->scheduledForDestruction = false;
/* Finish sweeping the current sweep group, then abort. */
@ -7552,7 +7551,7 @@ GCRuntime::maybeDoCycleCollection()
size_t realmsTotal = 0;
size_t realmsGray = 0;
for (RealmsIter realm(rt, SkipAtoms); !realm.done(); realm.next()) {
for (RealmsIter realm(rt); !realm.done(); realm.next()) {
++realmsTotal;
GlobalObject* global = realm->unsafeUnbarrieredMaybeGlobal();
if (global && global->isMarkedGray())
@ -7602,7 +7601,7 @@ GCRuntime::shouldRepeatForDeadZone(JS::gcreason::Reason reason)
if (!isIncremental)
return false;
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (c->scheduledForDestruction)
return true;
}
@ -7961,7 +7960,7 @@ js::NewRealm(JSContext* cx, JSPrincipals* principals, const JS::RealmOptions& op
return nullptr;
// Set up the principals.
JS_SetCompartmentPrincipals(JS::GetCompartmentForRealm(realm), principals);
JS::SetRealmPrincipals(realm, principals);
JSCompartment* comp = realm->compartment();
if (!comp->realms().append(realm)) {
@ -8488,7 +8487,7 @@ js::gc::CheckHashTablesAfterMovingGC(JSRuntime* rt)
}
}
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
for (CompartmentsIter c(rt); !c.done(); c.next()) {
c->checkWrapperMapAfterMovingGC();
for (RealmsInCompartmentIter r(c); !r.done(); r.next()) {

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

@ -1029,7 +1029,7 @@ js::Nursery::sweep(JSTracer* trc)
}
cellsWithUid_.clear();
for (CompartmentsIter c(runtime(), SkipAtoms); !c.done(); c.next())
for (CompartmentsIter c(runtime()); !c.done(); c.next())
c->sweepAfterMinorGC(trc);
sweepDictionaryModeObjects();

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

@ -67,7 +67,7 @@ class GCZonesIter
MOZ_ASSERT_IF(rt->gc.atomsZone->isCollectingFromAnyThread(),
!rt->hasHelperThreadZones());
if (!zone->isCollectingFromAnyThread())
if (!done() && !zone->isCollectingFromAnyThread())
next();
}
@ -95,11 +95,22 @@ using GCRealmsIter = CompartmentsOrRealmsIterT<GCZonesIter, RealmsInZoneIter>;
/* Iterates over all zones in the current sweep group. */
class SweepGroupZonesIter {
JS::Zone* current;
ZoneSelector selector;
public:
explicit SweepGroupZonesIter(JSRuntime* rt) {
explicit SweepGroupZonesIter(JSRuntime* rt, ZoneSelector selector = WithAtoms)
: selector(selector)
{
MOZ_ASSERT(CurrentThreadIsPerformingGC());
current = rt->gc.getCurrentSweepGroup();
maybeSkipAtomsZone();
}
void maybeSkipAtomsZone() {
if (selector == SkipAtoms && current && current->isAtomsZone()) {
current = current->nextNodeInGroup();
MOZ_ASSERT_IF(current, !current->isAtomsZone());
}
}
bool done() const { return !current; }
@ -107,6 +118,7 @@ class SweepGroupZonesIter {
void next() {
MOZ_ASSERT(!done());
current = current->nextNodeInGroup();
maybeSkipAtomsZone();
}
JS::Zone* get() const {

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

@ -141,7 +141,7 @@ JS_IterateCompartments(JSContext* cx, void* data,
{
AutoTraceSession session(cx->runtime());
for (CompartmentsIter c(cx->runtime(), WithAtoms); !c.done(); c.next())
for (CompartmentsIter c(cx->runtime()); !c.done(); c.next())
(*compartmentCallback)(cx, data, c);
}
@ -151,7 +151,7 @@ JS::IterateRealms(JSContext* cx, void* data, JS::IterateRealmCallback realmCallb
AutoTraceSession session(cx->runtime());
Rooted<Realm*> realm(cx);
for (RealmsIter r(cx->runtime(), WithAtoms); !r.done(); r.next()) {
for (RealmsIter r(cx->runtime()); !r.done(); r.next()) {
realm = r;
(*realmCallback)(cx, data, realm);
}

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

@ -193,14 +193,7 @@ class CompartmentsOrRealmsIterT
public:
explicit CompartmentsOrRealmsIterT(JSRuntime* rt)
: iterMarker(&rt->gc), zone(rt)
{
if (!zone.done())
inner.emplace(zone);
}
CompartmentsOrRealmsIterT(JSRuntime* rt, ZoneSelector selector)
: iterMarker(&rt->gc), zone(rt, selector)
: iterMarker(&rt->gc), zone(rt, SkipAtoms)
{
if (!zone.done())
inner.emplace(zone);

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

@ -369,7 +369,7 @@ js::gc::GCRuntime::traceRuntimeCommon(JSTracer* trc, TraceOrMarkRuntime traceOrM
// Trace all realm roots, but not the realm itself; it is traced via the
// parent pointer if traceRoots actually traces anything.
for (RealmsIter r(rt, SkipAtoms); !r.done(); r.next())
for (RealmsIter r(rt); !r.done(); r.next())
r->traceRoots(trc, traceOrMark);
// Trace helper thread roots.
@ -427,7 +427,7 @@ js::gc::GCRuntime::finishRoots()
rt->finishSelfHosting();
for (RealmsIter r(rt, SkipAtoms); !r.done(); r.next())
for (RealmsIter r(rt); !r.done(); r.next())
r->finishRoots();
#ifdef DEBUG

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

@ -163,7 +163,7 @@ struct TraceIncomingFunctor {
JS_PUBLIC_API(void)
JS::TraceIncomingCCWs(JSTracer* trc, const JS::CompartmentSet& compartments)
{
for (js::CompartmentsIter comp(trc->runtime(), SkipAtoms); !comp.done(); comp.next()) {
for (js::CompartmentsIter comp(trc->runtime()); !comp.done(); comp.next()) {
if (compartments.has(comp))
continue;

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

@ -0,0 +1,14 @@
var g = newGlobal();
var dbg = Debugger(g);
dbg.onEnterFrame = function(frame) {};
var g2 = newGlobal();
g2[g] = g;
g2.evaluate("grayRoot()")
g2 = undefined;
g = undefined;
dbg = undefined;
gc();
startgc(100000);

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

@ -1043,7 +1043,7 @@ JitRuntime::getBaselineDebugModeOSRHandler(JSContext* cx)
{
if (!baselineDebugModeOSRHandler_) {
AutoLockForExclusiveAccess lock(cx);
AutoAtomsRealm ar(cx, lock);
AutoAtomsZone az(cx, lock);
uint32_t offset;
if (JitCode* code = generateBaselineDebugModeOSRHandler(cx, &offset)) {
baselineDebugModeOSRHandler_ = code;

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

@ -108,6 +108,7 @@ JitContext::JitContext(CompileRuntime* rt, CompileRealm* realm, TempAllocator* t
temp(temp),
runtime(rt),
realm(realm),
zone(realm ? realm->zone() : nullptr),
prev_(CurrentJitContext()),
assemblerCount_(0)
{
@ -119,6 +120,7 @@ JitContext::JitContext(JSContext* cx, TempAllocator* temp)
temp(temp),
runtime(CompileRuntime::get(cx->runtime())),
realm(CompileRealm::get(cx->realm())),
zone(CompileZone::get(cx->zone())),
prev_(CurrentJitContext()),
assemblerCount_(0)
{
@ -211,13 +213,10 @@ JitRuntime::startTrampolineCode(MacroAssembler& masm)
bool
JitRuntime::initialize(JSContext* cx, AutoLockForExclusiveAccess& lock)
{
AutoAtomsRealm ar(cx, lock);
AutoAtomsZone az(cx, lock);
JitContext jctx(cx, nullptr);
if (!cx->realm()->ensureJitRealmExists(cx))
return false;
functionWrappers_ = cx->new_<VMWrapperMap>(cx);
if (!functionWrappers_ || !functionWrappers_->init())
return false;
@ -339,7 +338,7 @@ JitRuntime::debugTrapHandler(JSContext* cx)
// JitRuntime code stubs are shared across compartments and have to
// be allocated in the atoms zone.
AutoLockForExclusiveAccess lock(cx);
AutoAtomsRealm ar(cx, lock);
AutoAtomsZone az(cx, lock);
debugTrapHandler_ = generateDebugTrapHandler(cx);
}
return debugTrapHandler_;
@ -592,7 +591,7 @@ JitRuntime::Trace(JSTracer* trc, AutoLockForExclusiveAccess& lock)
if (trc->runtime()->atomsAreFinished())
return;
Zone* zone = trc->runtime()->atomsRealm(lock)->zone();
Zone* zone = trc->runtime()->atomsZone(lock);
for (auto i = zone->cellIter<JitCode>(); !i.done(); i.next()) {
JitCode* code = i;
TraceRoot(trc, &code, "wrapper");

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

@ -72,6 +72,7 @@ class JitContext
// during compilation.
CompileRuntime* runtime;
CompileRealm* realm;
CompileZone* zone;
int getNextAssemblerId() {
return assemblerCount_++;

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

@ -346,9 +346,7 @@ class RInstructionResults
MOZ_MUST_USE bool init(JSContext* cx, uint32_t numResults);
bool isInitialized() const;
#ifdef DEBUG
size_t length() const;
#endif
JitFrameLayout* frame() const;

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

@ -1494,13 +1494,11 @@ RInstructionResults::isInitialized() const
return initialized_;
}
#ifdef DEBUG
size_t
RInstructionResults::length() const
{
return results_->length();
}
#endif
JitFrameLayout*
RInstructionResults::frame() const
@ -1953,7 +1951,7 @@ SnapshotIterator::initInstructionResults(MaybeReadFallback& fallback)
}
MOZ_ASSERT(results->isInitialized());
MOZ_ASSERT(results->length() == recover_.numInstructions() - 1);
MOZ_RELEASE_ASSERT(results->length() == recover_.numInstructions() - 1);
instructionResults_ = results;
return true;
}

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

@ -157,8 +157,8 @@ struct Imm64
static inline bool
IsCompilingWasm()
{
// wasm compilation pushes a JitContext with a null Realm.
return GetJitContext()->realm == nullptr;
// wasm compilation pushes a JitContext with a null Zone.
return GetJitContext()->zone == nullptr;
}
#endif

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

@ -797,7 +797,7 @@ ReleaseAssertObjectHasNoWrappers(JSContext* cx, HandleObject target)
{
RootedValue origv(cx, ObjectValue(*target));
for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
for (CompartmentsIter c(cx->runtime()); !c.done(); c.next()) {
if (c->lookupWrapper(origv))
MOZ_CRASH("wrapper found for target object");
}
@ -954,7 +954,7 @@ JS_RefreshCrossCompartmentWrappers(JSContext* cx, HandleObject obj)
JS_PUBLIC_API(bool)
JS_InitStandardClasses(JSContext* cx, HandleObject obj)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -1974,7 +1974,7 @@ JS_FireOnNewGlobalObject(JSContext* cx, JS::HandleObject global)
JS_PUBLIC_API(JSObject*)
JS_NewObject(JSContext* cx, const JSClass* jsclasp)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -1991,7 +1991,7 @@ JS_NewObject(JSContext* cx, const JSClass* jsclasp)
JS_PUBLIC_API(JSObject*)
JS_NewObjectWithGivenProto(JSContext* cx, const JSClass* jsclasp, HandleObject proto)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, proto);
@ -2009,7 +2009,7 @@ JS_NewObjectWithGivenProto(JSContext* cx, const JSClass* jsclasp, HandleObject p
JS_PUBLIC_API(JSObject*)
JS_NewPlainObject(JSContext* cx)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -2909,7 +2909,7 @@ JS_PUBLIC_API(bool)
JS_CallFunctionValue(JSContext* cx, HandleObject obj, HandleValue fval, const HandleValueArray& args,
MutableHandleValue rval)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, fval, args);
@ -2926,7 +2926,7 @@ JS_PUBLIC_API(bool)
JS_CallFunction(JSContext* cx, HandleObject obj, HandleFunction fun, const HandleValueArray& args,
MutableHandleValue rval)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, fun, args);
@ -2944,7 +2944,7 @@ JS_PUBLIC_API(bool)
JS_CallFunctionName(JSContext* cx, HandleObject obj, const char* name, const HandleValueArray& args,
MutableHandleValue rval)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, args);
@ -3378,7 +3378,7 @@ JS_SetReservedSlot(JSObject* obj, uint32_t index, const Value& value)
JS_PUBLIC_API(JSObject*)
JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -3389,7 +3389,7 @@ JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents)
JS_PUBLIC_API(JSObject*)
JS_NewArrayObject(JSContext* cx, size_t length)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -3512,7 +3512,7 @@ JS_PUBLIC_API(JSFunction*)
JS_NewFunction(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
const char* name)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -3532,7 +3532,7 @@ JS_NewFunction(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
JS_PUBLIC_API(JSFunction*)
JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id, unsigned nargs)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, id);
@ -3788,7 +3788,7 @@ JS_IsConstructor(JSFunction* fun)
JS_PUBLIC_API(bool)
JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
@ -3800,7 +3800,7 @@ JS_PUBLIC_API(JSFunction*)
JS_DefineFunction(JSContext* cx, HandleObject obj, const char* name, JSNative call,
unsigned nargs, unsigned attrs)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
@ -3816,7 +3816,7 @@ JS_DefineUCFunction(JSContext* cx, HandleObject obj,
const char16_t* name, size_t namelen, JSNative call,
unsigned nargs, unsigned attrs)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
@ -3831,7 +3831,7 @@ extern JS_PUBLIC_API(JSFunction*)
JS_DefineFunctionById(JSContext* cx, HandleObject obj, HandleId id, JSNative call,
unsigned nargs, unsigned attrs)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
@ -4082,7 +4082,7 @@ Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
{
ScopeKind scopeKind = options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global;
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -4223,7 +4223,7 @@ JSScript*
JS::DecodeBinAST(JSContext* cx, const ReadOnlyCompileOptions& options,
const uint8_t* buf, size_t length)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -4547,7 +4547,7 @@ CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
HandleObject enclosingEnv, HandleScope enclosingScope,
MutableHandleFunction fun)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, enclosingEnv);
@ -4716,7 +4716,7 @@ JS::ExposeScriptToDebugger(JSContext* cx, HandleScript script)
JS_PUBLIC_API(JSString*)
JS_DecompileScript(JSContext* cx, HandleScript script)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -4734,7 +4734,7 @@ JS_DecompileScript(JSContext* cx, HandleScript script)
JS_PUBLIC_API(JSString*)
JS_DecompileFunction(JSContext* cx, HandleFunction fun)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, fun);
@ -4744,7 +4744,7 @@ JS_DecompileFunction(JSContext* cx, HandleFunction fun)
MOZ_NEVER_INLINE static bool
ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, Value* rval)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, scope, script);
@ -4838,7 +4838,7 @@ Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
SourceBufferHolder& srcBuf, MutableHandleValue rval)
{
CompileOptions options(cx, optionsArg);
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, env);
@ -4979,7 +4979,7 @@ JS_PUBLIC_API(bool)
JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -5137,7 +5137,7 @@ JS::SetPromiseRejectionTrackerCallback(JSContext* cx, JSPromiseRejectionTrackerC
JS_PUBLIC_API(JSObject*)
JS::NewPromiseObject(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
assertSameCompartment(cx, executor, proto);
@ -5391,7 +5391,7 @@ JS::NewReadableDefaultStreamObject(JSContext* cx,
double highWaterMark /* = 1 */,
JS::HandleObject proto /* = nullptr */)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -5413,7 +5413,7 @@ JS::NewReadableByteStreamObject(JSContext* cx,
double highWaterMark /* = 1 */,
JS::HandleObject proto /* = nullptr */)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -5472,7 +5472,7 @@ JS::NewReadableExternalSourceStreamObject(JSContext* cx, void* underlyingSource,
uint8_t flags /* = 0 */,
HandleObject proto /* = nullptr */)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
AssertHeapIsIdle();
CHECK_REQUEST(cx);
@ -7627,9 +7627,8 @@ GetScriptedCallerGlobal(JSContext* cx)
GlobalObject* global = realm->maybeGlobal();
// No one should be running code in the atoms realm or running code in a
// realm without any live objects, so there should definitely be a live
// global.
// No one should be running code in a realm without any live objects, so
// there should definitely be a live global.
MOZ_ASSERT(global);
return global;

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

@ -162,11 +162,16 @@ JS_GetCompartmentPrincipals(JSCompartment* compartment)
return realm->principals();
}
JS_FRIEND_API(JSPrincipals*)
JS::GetRealmPrincipals(JS::Realm* realm)
{
return realm->principals();
}
JS_FRIEND_API(void)
JS_SetCompartmentPrincipals(JSCompartment* compartment, JSPrincipals* principals)
JS::SetRealmPrincipals(JS::Realm* realm, JSPrincipals* principals)
{
// Short circuit if there's no change.
Realm* realm = JS::GetRealmForCompartment(compartment);
if (principals == realm->principals())
return;
@ -246,7 +251,7 @@ DefineHelpProperty(JSContext* cx, HandleObject obj, const char* prop, const char
JS_FRIEND_API(bool)
JS_DefineFunctionsWithHelp(JSContext* cx, HandleObject obj, const JSFunctionSpecWithHelp* fs)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
@ -351,12 +356,6 @@ js::IsSystemZone(Zone* zone)
return zone->isSystem;
}
JS_FRIEND_API(bool)
js::IsAtomsRealm(JS::Realm* realm)
{
return realm->isAtomsRealm();
}
JS_FRIEND_API(bool)
js::IsAtomsZone(JS::Zone* zone)
{
@ -433,7 +432,7 @@ js::DefineFunctionWithReserved(JSContext* cx, JSObject* objArg, const char* name
unsigned nargs, unsigned attrs)
{
RootedObject obj(cx, objArg);
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAtom* atom = Atomize(cx, name, strlen(name));
@ -447,7 +446,7 @@ JS_FRIEND_API(JSFunction*)
js::NewFunctionWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
const char* name)
{
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
CHECK_REQUEST(cx);
@ -468,7 +467,7 @@ js::NewFunctionByIdWithReserved(JSContext* cx, JSNative native, unsigned nargs,
jsid id)
{
MOZ_ASSERT(JSID_IS_STRING(id));
MOZ_ASSERT(!cx->realm()->isAtomsRealm());
MOZ_ASSERT(!cx->zone()->isAtomsZone());
CHECK_REQUEST(cx);
assertSameCompartment(cx, id);
@ -1275,6 +1274,9 @@ JS::NotifyGCRootsRemoved(JSContext* cx)
JS_FRIEND_API(JS::Realm*)
js::GetAnyRealmInZone(JS::Zone* zone)
{
if (zone->isAtomsZone())
return nullptr;
RealmsInZoneIter realm(zone);
MOZ_ASSERT(!realm.done());
return realm.get();
@ -1543,8 +1545,9 @@ js::EnableAccessValidation(JSContext* cx, bool enabled)
}
JS_FRIEND_API(void)
js::SetCompartmentValidAccessPtr(JSContext* cx, JS::HandleObject global, bool* accessp)
js::SetRealmValidAccessPtr(JSContext* cx, JS::HandleObject global, bool* accessp)
{
MOZ_ASSERT(global->is<GlobalObject>());
global->realm()->setValidAccessPtr(accessp);
}

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

@ -190,9 +190,6 @@ JS_GetIsSecureContext(JSCompartment* compartment);
extern JS_FRIEND_API(JSPrincipals*)
JS_GetCompartmentPrincipals(JSCompartment* compartment);
extern JS_FRIEND_API(void)
JS_SetCompartmentPrincipals(JSCompartment* compartment, JSPrincipals* principals);
extern JS_FRIEND_API(JSPrincipals*)
JS_GetScriptPrincipals(JSScript* script);
@ -325,6 +322,12 @@ ForceLexicalInitialization(JSContext *cx, HandleObject obj);
extern JS_FRIEND_API(int)
IsGCPoisoning();
extern JS_FRIEND_API(JSPrincipals*)
GetRealmPrincipals(JS::Realm* realm);
extern JS_FRIEND_API(void)
SetRealmPrincipals(JS::Realm* realm, JSPrincipals* principals);
} // namespace JS
/**
@ -483,9 +486,6 @@ IsSystemCompartment(JSCompartment* comp);
extern JS_FRIEND_API(bool)
IsSystemZone(JS::Zone* zone);
extern JS_FRIEND_API(bool)
IsAtomsRealm(JS::Realm* realm);
extern JS_FRIEND_API(bool)
IsAtomsZone(JS::Zone* zone);
@ -553,6 +553,7 @@ extern JS_FRIEND_API(size_t)
SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj);
#endif
// Note: this returns nullptr iff |zone| is the atoms zone.
extern JS_FRIEND_API(JS::Realm*)
GetAnyRealmInZone(JS::Zone* zone);
@ -566,8 +567,8 @@ namespace shadow {
struct ObjectGroup {
const Class* clasp;
JSObject* proto;
JSCompartment* compartment;
JSObject* proto;
JS::Realm* realm;
};
struct BaseShape {
@ -670,10 +671,23 @@ InheritanceProtoKeyForStandardClass(JSProtoKey key)
JS_FRIEND_API(bool)
IsFunctionObject(JSObject* obj);
JS_FRIEND_API(bool)
IsCrossCompartmentWrapper(JSObject* obj);
static MOZ_ALWAYS_INLINE JSCompartment*
GetObjectCompartment(JSObject* obj)
{
return reinterpret_cast<shadow::Object*>(obj)->group->compartment;
JS::Realm* realm = reinterpret_cast<shadow::Object*>(obj)->group->realm;
return JS::GetCompartmentForRealm(realm);
}
// CrossCompartmentWrappers are shared by all realms within the compartment, so
// getting a wrapper's realm usually doesn't make sense.
static MOZ_ALWAYS_INLINE JS::Realm*
GetNonCCWObjectRealm(JSObject* obj)
{
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(obj));
return reinterpret_cast<shadow::Object*>(obj)->group->realm;
}
JS_FRIEND_API(JSObject*)
@ -3093,9 +3107,9 @@ class MOZ_STACK_CLASS JS_FRIEND_API(AutoAssertNoContentJS)
};
// Turn on assertions so that we assert that
// !comp->validAccessPtr || *comp->validAccessPtr
// is true for every |comp| that we run JS code in. The compartment's validAccessPtr
// is set via SetCompartmentValidAccessPtr.
// !realm->validAccessPtr || *realm->validAccessPtr
// is true for every |realm| that we run JS code in. The realm's validAccessPtr
// is set via SetRealmValidAccessPtr.
extern JS_FRIEND_API(void)
EnableAccessValidation(JSContext* cx, bool enabled);
@ -3104,7 +3118,7 @@ EnableAccessValidation(JSContext* cx, bool enabled);
// threads that are allowed to run code on |global|, so all changes to *accessp
// should be made from whichever thread owns |global| at a given time.
extern JS_FRIEND_API(void)
SetCompartmentValidAccessPtr(JSContext* cx, JS::HandleObject global, bool* accessp);
SetRealmValidAccessPtr(JSContext* cx, JS::HandleObject global, bool* accessp);
// Returns true if the system zone is available (i.e., if no cooperative contexts
// are using it now).

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

@ -85,6 +85,7 @@ typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
namespace js {
inline JS::Realm* GetContextRealm(const JSContext* cx);
inline JSCompartment* GetContextCompartment(const JSContext* cx);
inline JS::Zone* GetContextZone(const JSContext* cx);

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