mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
commit
f5b2c7c8e6
@ -79,7 +79,7 @@ clean clobber repackage::
|
||||
MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_APP_VERSION) --buildid=$(DEPTH)/buildid.h)
|
||||
|
||||
.PHONY: repackage
|
||||
tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME) features
|
||||
tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME)
|
||||
rm -rf $(dist_dest)
|
||||
$(MKDIR) -p '$(dist_dest)/Contents/MacOS'
|
||||
$(MKDIR) -p '$(dist_dest)/$(LPROJ)'
|
||||
@ -100,7 +100,3 @@ ifdef MOZ_UPDATER
|
||||
endif
|
||||
printf APPLMOZB > '$(dist_dest)/Contents/PkgInfo'
|
||||
endif
|
||||
|
||||
.PHONY: features
|
||||
tools features::
|
||||
$(call py_action,generate_builtin_addons,--features=browser/features browser/chrome/browser/content/browser/built_in_addons.json)
|
||||
|
@ -96,23 +96,3 @@ $(addprefix install-,$(INSTALL_MANIFESTS)): install-%: $(addprefix $(TOPOBJDIR)/
|
||||
# that are not supported by data in moz.build.
|
||||
|
||||
$(TOPOBJDIR)/build/application.ini: $(TOPOBJDIR)/buildid.h $(TOPOBJDIR)/source-repo.h
|
||||
|
||||
# The manifest of allowed system add-ons should be re-built when using
|
||||
# "build faster".
|
||||
#
|
||||
# Note the dependency on install-dist/bin. The form of this
|
||||
# dependency is critical: it's triggering the stem rule (install-%)
|
||||
# above to force the dist/bin manifest to be processed. The more
|
||||
# obvious `$(TOPOBJDIR)/install-dist_bin` doesn't work because
|
||||
# dist/bin isn't in $(INSTALL_MANIFESTS) in the
|
||||
# FasterMake+RecursiveMake (artifact build) situation.
|
||||
ifeq ($(MOZ_BUILD_APP),browser)
|
||||
$(TOPOBJDIR)/browser/app/features: install-dist/bin
|
||||
|
||||
default: $(TOPOBJDIR)/browser/app/features
|
||||
endif
|
||||
ifeq ($(MOZ_BUILD_APP),mobile/android)
|
||||
$(TOPOBJDIR)/mobile/android/base/features: install-dist/bin
|
||||
|
||||
default: $(TOPOBJDIR)/mobile/android/base/features
|
||||
endif
|
||||
|
@ -101,12 +101,14 @@ function setOutOfScopeLocations() {
|
||||
}
|
||||
|
||||
function compressPausePoints(pausePoints) {
|
||||
const compressed = {}
|
||||
const compressed = {};
|
||||
|
||||
for (const line in pausePoints) {
|
||||
compressed[line] = {}
|
||||
compressed[line] = {};
|
||||
|
||||
for (const col in pausePoints[line]) {
|
||||
const point = pausePoints[line][col]
|
||||
compressed[line][col] = (point.break && 1) | (point.step && 2)
|
||||
const point = pausePoints[line][col];
|
||||
compressed[line][col] = (point.break && 1) | (point.step && 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,6 @@ var _preview = require("../utils/preview");
|
||||
|
||||
var _ast = require("../utils/ast");
|
||||
|
||||
var _editor = require("../utils/editor/index");
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _promise = require("./utils/middleware/promise");
|
||||
@ -25,74 +23,37 @@ var _expressions = require("./expressions");
|
||||
|
||||
var _pause = require("./pause/index");
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
/* 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/>. */
|
||||
function isInvalidTarget(target) {
|
||||
if (!target || !target.innerText) {
|
||||
return true;
|
||||
function findExpressionMatch(state, codeMirror, tokenPos) {
|
||||
const source = (0, _selectors.getSelectedSource)(state);
|
||||
const symbols = (0, _selectors.getSymbols)(state, source);
|
||||
let match;
|
||||
|
||||
if (!symbols || symbols.loading) {
|
||||
match = (0, _getExpression.getExpressionFromCoords)(codeMirror, tokenPos);
|
||||
} else {
|
||||
match = (0, _ast.findBestMatchExpression)(symbols, tokenPos);
|
||||
}
|
||||
|
||||
const tokenText = target.innerText.trim();
|
||||
const cursorPos = target.getBoundingClientRect(); // exclude literal tokens where it does not make sense to show a preview
|
||||
|
||||
const invalidType = ["cm-atom", ""].includes(target.className); // exclude syntax where the expression would be a syntax error
|
||||
|
||||
const invalidToken = tokenText === "" || tokenText.match(/^[(){}\|&%,.;=<>\+-/\*\s](?=)/);
|
||||
const isPresentation = target.attributes.role && target.attributes.getNamedItem("role").value == "presentation"; // exclude codemirror elements that are not tokens
|
||||
|
||||
const invalidTarget = target.parentElement && !target.parentElement.closest(".CodeMirror-line") || cursorPos.top == 0;
|
||||
return invalidTarget || invalidToken || invalidType || isPresentation;
|
||||
return match;
|
||||
}
|
||||
|
||||
function updatePreview(target, editor) {
|
||||
function updatePreview(target, tokenPos, codeMirror) {
|
||||
return ({
|
||||
dispatch,
|
||||
getState,
|
||||
client,
|
||||
sourceMaps
|
||||
}) => {
|
||||
const tokenPos = (0, _editor.getTokenLocation)(editor.codeMirror, target);
|
||||
const cursorPos = target.getBoundingClientRect();
|
||||
const preview = (0, _selectors.getPreview)(getState());
|
||||
|
||||
if ((0, _selectors.getCanRewind)(getState())) {
|
||||
if ((0, _selectors.getCanRewind)(getState()) || !(0, _selectors.isSelectedFrameVisible)(getState()) || !(0, _selectors.isLineInScope)(getState(), tokenPos.line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preview) {
|
||||
// Return early if we are currently showing another preview or
|
||||
// if we are mousing over the same token as before
|
||||
if (preview.updating || (0, _lodash.isEqual)(preview.tokenPos, tokenPos)) {
|
||||
return;
|
||||
} // We are mousing over a new token that is not in the preview
|
||||
|
||||
|
||||
if (!target.classList.contains("debug-expression")) {
|
||||
dispatch(clearPreview());
|
||||
}
|
||||
}
|
||||
|
||||
if (isInvalidTarget(target)) {
|
||||
dispatch(clearPreview());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(0, _selectors.isSelectedFrameVisible)(getState()) || !(0, _selectors.isLineInScope)(getState(), tokenPos.line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const source = (0, _selectors.getSelectedSource)(getState());
|
||||
const symbols = (0, _selectors.getSymbols)(getState(), source);
|
||||
let match;
|
||||
|
||||
if (!symbols || symbols.loading) {
|
||||
match = (0, _getExpression.getExpressionFromCoords)(editor.codeMirror, tokenPos);
|
||||
} else {
|
||||
match = (0, _ast.findBestMatchExpression)(symbols, tokenPos);
|
||||
}
|
||||
const match = findExpressionMatch(getState(), codeMirror, tokenPos);
|
||||
|
||||
if (!match) {
|
||||
return;
|
||||
|
@ -29,8 +29,6 @@ var _PreviewFunction = require("../../shared/PreviewFunction");
|
||||
|
||||
var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction);
|
||||
|
||||
var _editor = require("../../../utils/editor/index");
|
||||
|
||||
var _preview = require("../../../utils/preview");
|
||||
|
||||
var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"];
|
||||
@ -63,6 +61,18 @@ const {
|
||||
loadItemProperties
|
||||
} = ObjectInspectorUtils.loadProperties;
|
||||
|
||||
function inPreview(event) {
|
||||
const relatedTarget = event.relatedTarget;
|
||||
|
||||
if (!relatedTarget || relatedTarget.classList.contains("preview-expression")) {
|
||||
return true;
|
||||
} // $FlowIgnore
|
||||
|
||||
|
||||
const inPreviewSelection = document.elementsFromPoint(event.clientX, event.clientY).some(el => el.classList.contains("preview-selection"));
|
||||
return inPreviewSelection;
|
||||
}
|
||||
|
||||
class Popup extends _react.Component {
|
||||
constructor(...args) {
|
||||
var _temp;
|
||||
@ -70,11 +80,13 @@ class Popup extends _react.Component {
|
||||
return _temp = super(...args), this.onMouseLeave = e => {
|
||||
const relatedTarget = e.relatedTarget;
|
||||
|
||||
if (relatedTarget && relatedTarget.classList && (relatedTarget.classList.contains("popover") || relatedTarget.classList.contains("debug-expression") || relatedTarget.classList.contains("editor-mount"))) {
|
||||
return;
|
||||
if (!relatedTarget) {
|
||||
return this.props.onClose();
|
||||
}
|
||||
|
||||
this.props.onClose();
|
||||
if (!inPreview(e)) {
|
||||
this.props.onClose();
|
||||
}
|
||||
}, _temp;
|
||||
}
|
||||
|
||||
@ -96,26 +108,6 @@ class Popup extends _react.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
value,
|
||||
editor,
|
||||
range
|
||||
} = this.props;
|
||||
|
||||
if (!value || !value.type == "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.marker = (0, _editor.markText)(editor, "preview-selection", range);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.marker) {
|
||||
this.marker.clear();
|
||||
}
|
||||
}
|
||||
|
||||
getRoot() {
|
||||
const {
|
||||
expression,
|
||||
|
@ -27,15 +27,40 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
||||
/* 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/>. */
|
||||
function inPopup(e) {
|
||||
const {
|
||||
relatedTarget
|
||||
} = e;
|
||||
|
||||
if (!relatedTarget) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const pop = relatedTarget.closest(".popover") || relatedTarget.classList.contains("debug-expression");
|
||||
return pop;
|
||||
}
|
||||
|
||||
function getElementFromPos(pos) {
|
||||
// $FlowIgnore
|
||||
return document.elementFromPoint(pos.x + pos.width / 2, pos.y + pos.height / 2);
|
||||
}
|
||||
|
||||
class Preview extends _react.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.target = null;
|
||||
|
||||
this.onMouseOver = e => {
|
||||
const {
|
||||
target
|
||||
} = e;
|
||||
this.props.updatePreview(target, this.props.editor);
|
||||
this.onTokenEnter = ({
|
||||
target,
|
||||
tokenPos
|
||||
}) => {
|
||||
this.props.updatePreview(target, tokenPos, this.props.editor.codeMirror);
|
||||
};
|
||||
|
||||
this.onTokenLeave = e => {
|
||||
if (!inPopup(e)) {
|
||||
this.props.clearPreview();
|
||||
}
|
||||
};
|
||||
|
||||
this.onMouseUp = () => {
|
||||
@ -52,17 +77,11 @@ class Preview extends _react.PureComponent {
|
||||
return true;
|
||||
};
|
||||
|
||||
this.onMouseLeave = e => {
|
||||
const target = e.target;
|
||||
|
||||
if (target.classList.contains("CodeMirror")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onScroll = () => {
|
||||
this.props.clearPreview();
|
||||
};
|
||||
|
||||
this.onClose = () => {
|
||||
this.onClose = e => {
|
||||
this.props.clearPreview();
|
||||
};
|
||||
|
||||
@ -72,30 +91,54 @@ class Preview extends _react.PureComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateListeners();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
this.updateListeners(prevProps);
|
||||
this.updateHighlight(prevProps);
|
||||
}
|
||||
|
||||
updateListeners(prevProps) {
|
||||
const {
|
||||
isPaused
|
||||
} = this.props;
|
||||
const {
|
||||
codeMirror
|
||||
} = this.props.editor;
|
||||
const codeMirrorWrapper = codeMirror.getWrapperElement();
|
||||
codeMirrorWrapper.addEventListener("mouseover", this.onMouseOver);
|
||||
codeMirrorWrapper.addEventListener("mouseup", this.onMouseUp);
|
||||
codeMirrorWrapper.addEventListener("mousedown", this.onMouseDown);
|
||||
codeMirrorWrapper.addEventListener("mouseleave", this.onMouseLeave);
|
||||
const wasNotPaused = !prevProps || !prevProps.isPaused;
|
||||
const wasPaused = prevProps && prevProps.isPaused;
|
||||
|
||||
if (document.body) {
|
||||
document.body.addEventListener("mouseleave", this.onMouseLeave);
|
||||
if (isPaused && wasNotPaused) {
|
||||
codeMirror.on("scroll", this.onScroll);
|
||||
codeMirror.on("tokenenter", this.onTokenEnter);
|
||||
codeMirror.on("tokenleave", this.onTokenLeave);
|
||||
codeMirrorWrapper.addEventListener("mouseup", this.onMouseUp);
|
||||
codeMirrorWrapper.addEventListener("mousedown", this.onMouseDown);
|
||||
}
|
||||
|
||||
if (!isPaused && wasPaused) {
|
||||
codeMirror.off("tokenenter", this.onTokenEnter);
|
||||
codeMirror.off("tokenleave", this.onTokenLeave);
|
||||
codeMirrorWrapper.removeEventListener("mouseup", this.onMouseUp);
|
||||
codeMirrorWrapper.removeEventListener("mousedown", this.onMouseDown);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const codeMirror = this.props.editor.codeMirror;
|
||||
const codeMirrorWrapper = codeMirror.getWrapperElement();
|
||||
codeMirrorWrapper.removeEventListener("mouseover", this.onMouseOver);
|
||||
codeMirrorWrapper.removeEventListener("mouseup", this.onMouseUp);
|
||||
codeMirrorWrapper.removeEventListener("mousedown", this.onMouseDown);
|
||||
codeMirrorWrapper.removeEventListener("mouseleave", this.onMouseLeave);
|
||||
updateHighlight(prevProps) {
|
||||
const {
|
||||
preview
|
||||
} = this.props;
|
||||
|
||||
if (document.body) {
|
||||
document.body.removeEventListener("mouseleave", this.onMouseLeave);
|
||||
if (preview && !preview.updating) {
|
||||
const target = getElementFromPos(preview.cursorPos);
|
||||
target && target.classList.add("preview-selection");
|
||||
}
|
||||
|
||||
if (prevProps.preview && !prevProps.preview.updating) {
|
||||
const target = getElementFromPos(prevProps.preview.cursorPos);
|
||||
target && target.classList.remove("preview-selection");
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,6 +186,7 @@ class Preview extends _react.PureComponent {
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
preview: (0, _selectors.getPreview)(state),
|
||||
isPaused: (0, _selectors.getIsPaused)(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state)
|
||||
});
|
||||
|
||||
|
@ -261,6 +261,7 @@ class Editor extends _react.PureComponent {
|
||||
codeMirrorWrapper.tabIndex = 0;
|
||||
codeMirrorWrapper.addEventListener("keydown", e => this.onKeyDown(e));
|
||||
codeMirrorWrapper.addEventListener("click", e => this.onClick(e));
|
||||
codeMirrorWrapper.addEventListener("mouseover", (0, _editor.onMouseOver)(codeMirror));
|
||||
|
||||
const toggleFoldMarkerVisibility = e => {
|
||||
if (node instanceof HTMLElement) {
|
||||
|
@ -152,6 +152,8 @@ class Breakpoint extends _react.PureComponent {
|
||||
__html: node.innerHTML
|
||||
};
|
||||
}
|
||||
/* eslint-disable react/no-danger */
|
||||
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
@ -57,18 +57,6 @@ class Popover extends _react.Component {
|
||||
return this.calculateTopForRightOrientation(target, editor, popover);
|
||||
};
|
||||
|
||||
this.onMouseLeave = e => {
|
||||
const {
|
||||
onMouseLeave
|
||||
} = this.props;
|
||||
|
||||
if (/^(bracket-arrow|gap)$/.test(e.currentTarget.className)) {
|
||||
return;
|
||||
}
|
||||
|
||||
onMouseLeave(e);
|
||||
};
|
||||
|
||||
this.state = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
@ -260,7 +248,7 @@ class Popover extends _react.Component {
|
||||
className: (0, _classnames2.default)("popover", `orientation-${orientation}`, {
|
||||
up: orientation === "up"
|
||||
}),
|
||||
onMouseLeave: this.onMouseLeave,
|
||||
onMouseLeave: this.props.onMouseLeave,
|
||||
style: {
|
||||
top,
|
||||
left
|
||||
|
@ -103,11 +103,16 @@ function update(state = initialASTState(), action) {
|
||||
|
||||
if (!action.value) {
|
||||
return state.set("preview", null);
|
||||
} // NOTE: if the preview does not exist, it has been cleared
|
||||
|
||||
|
||||
if (state.get("preview")) {
|
||||
return state.set("preview", _objectSpread({}, action.value, {
|
||||
updating: false
|
||||
}));
|
||||
}
|
||||
|
||||
return state.set("preview", _objectSpread({}, action.value, {
|
||||
updating: false
|
||||
}));
|
||||
return state;
|
||||
}
|
||||
|
||||
case "RESUME":
|
||||
|
@ -8,6 +8,7 @@ exports.getPauseReason = getPauseReason;
|
||||
exports.getPauseCommand = getPauseCommand;
|
||||
exports.isStepping = isStepping;
|
||||
exports.isPaused = isPaused;
|
||||
exports.getIsPaused = getIsPaused;
|
||||
exports.getPreviousPauseFrameLocation = getPreviousPauseFrameLocation;
|
||||
exports.isEvaluatingExpression = isEvaluatingExpression;
|
||||
exports.getPopupObjectProperties = getPopupObjectProperties;
|
||||
@ -304,6 +305,10 @@ function isPaused(state) {
|
||||
return !!getFrames(state);
|
||||
}
|
||||
|
||||
function getIsPaused(state) {
|
||||
return !!getFrames(state);
|
||||
}
|
||||
|
||||
function getPreviousPauseFrameLocation(state) {
|
||||
return state.pause.previousLocation;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.onMouseOver = undefined;
|
||||
|
||||
var _sourceDocuments = require("./source-documents");
|
||||
|
||||
@ -51,6 +52,15 @@ Object.keys(_ui).forEach(function (key) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var _tokenEvents = require("./token-events");
|
||||
|
||||
Object.defineProperty(exports, "onMouseOver", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _tokenEvents.onMouseOver;
|
||||
}
|
||||
});
|
||||
exports.getEditor = getEditor;
|
||||
exports.removeEditor = removeEditor;
|
||||
exports.shouldShowPrettyPrint = shouldShowPrettyPrint;
|
||||
|
@ -15,4 +15,5 @@ DevToolsModules(
|
||||
'source-documents.js',
|
||||
'source-editor.js',
|
||||
'source-search.js',
|
||||
'token-events.js',
|
||||
)
|
||||
|
@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.onMouseOver = onMouseOver;
|
||||
|
||||
var _ = require("./index");
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
/* 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/>. */
|
||||
function isInvalidTarget(target) {
|
||||
if (!target || !target.innerText) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const tokenText = target.innerText.trim();
|
||||
const cursorPos = target.getBoundingClientRect(); // exclude literal tokens where it does not make sense to show a preview
|
||||
|
||||
const invalidType = ["cm-atom", ""].includes(target.className); // exclude syntax where the expression would be a syntax error
|
||||
|
||||
const invalidToken = tokenText === "" || tokenText.match(/^[(){}\|&%,.;=<>\+-/\*\s](?=)/); // exclude codemirror elements that are not tokens
|
||||
|
||||
const invalidTarget = target.parentElement && !target.parentElement.closest(".CodeMirror-line") || cursorPos.top == 0;
|
||||
const invalidClasses = ["editor-mount"];
|
||||
|
||||
if (invalidClasses.some(className => target.classList.contains(className))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target.closest(".popover")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return invalidTarget || invalidToken || invalidType;
|
||||
}
|
||||
|
||||
function dispatch(codeMirror, eventName, data) {
|
||||
codeMirror.constructor.signal(codeMirror, eventName, data);
|
||||
}
|
||||
|
||||
function invalidLeaveTarget(target) {
|
||||
if (!target || target.closest(".popover")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function onMouseOver(codeMirror) {
|
||||
let prevTokenPos = null;
|
||||
|
||||
function onMouseLeave(event) {
|
||||
if (invalidLeaveTarget(event.relatedTarget)) {
|
||||
return addMouseLeave(event.target);
|
||||
}
|
||||
|
||||
prevTokenPos = null;
|
||||
dispatch(codeMirror, "tokenleave", event);
|
||||
}
|
||||
|
||||
function addMouseLeave(target) {
|
||||
target.addEventListener("mouseleave", onMouseLeave, {
|
||||
capture: true,
|
||||
once: true
|
||||
});
|
||||
}
|
||||
|
||||
return enterEvent => {
|
||||
const {
|
||||
target
|
||||
} = enterEvent;
|
||||
|
||||
if (isInvalidTarget(target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tokenPos = (0, _.getTokenLocation)(codeMirror, target);
|
||||
|
||||
if (!(0, _lodash.isEqual)(prevTokenPos, tokenPos)) {
|
||||
addMouseLeave(target);
|
||||
dispatch(codeMirror, "tokenenter", {
|
||||
event: enterEvent,
|
||||
target,
|
||||
tokenPos
|
||||
});
|
||||
prevTokenPos = tokenPos;
|
||||
}
|
||||
};
|
||||
}
|
@ -158,7 +158,7 @@ skip-if = (os == "win" && ccov) # Bug 1453549
|
||||
skip-if = ccov || (verify && debug && (os == 'linux')) # Bug 1441545
|
||||
[browser_dbg-sourcemapped-stepping.js]
|
||||
[browser_dbg-sourcemapped-preview.js]
|
||||
skip-if = (os == "win" && ccov) || (os == "win" && !debug) # Bug 1448523, Bug 1448450
|
||||
skip-if = os == "win" # Bug 1448523, Bug 1448450
|
||||
[browser_dbg-breaking.js]
|
||||
[browser_dbg-breaking-from-console.js]
|
||||
[browser_dbg-breakpoints.js]
|
||||
|
@ -32,6 +32,7 @@ async function testCase(dbg, { name, count, steps }) {
|
||||
add_task(async function test() {
|
||||
const dbg = await initDebugger("doc-pause-points.html");
|
||||
|
||||
await selectSource(dbg, "pause-points.js")
|
||||
await testCase(dbg, {
|
||||
name: "statements",
|
||||
count: 7,
|
||||
|
@ -5,10 +5,7 @@
|
||||
// and doesn't have functions.
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html");
|
||||
const {
|
||||
selectors: { getSelectedSource },
|
||||
getState
|
||||
} = dbg;
|
||||
const { selectors: { getSelectedSource }, getState } = dbg;
|
||||
|
||||
navigate(dbg, "doc-on-load.html");
|
||||
|
||||
|
@ -1213,18 +1213,31 @@ function getCoordsFromPosition(cm, { line, ch }) {
|
||||
return cm.charCoords({ line: ~~line, ch: ~~ch });
|
||||
}
|
||||
|
||||
function hoverAtPos(dbg, { line, ch }) {
|
||||
async function waitForScrolling(codeMirror) {
|
||||
return new Promise(resolve => {
|
||||
codeMirror.on("scroll", resolve);
|
||||
setTimeout(resolve, 500);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
async function hoverAtPos(dbg, { line, ch }) {
|
||||
info(`Hovering at ${line}, ${ch}`);
|
||||
const cm = getCM(dbg);
|
||||
|
||||
// Ensure the line is visible with margin because the bar at the bottom of
|
||||
// the editor overlaps into what the editor things is its own space, blocking
|
||||
// the click event below.
|
||||
cm.scrollIntoView({ line: line - 1, ch }, 100);
|
||||
cm.scrollIntoView({ line: line - 1, ch }, 0);
|
||||
await waitForScrolling(cm);
|
||||
|
||||
const coords = getCoordsFromPosition(cm, { line: line - 1, ch });
|
||||
const tokenEl = dbg.win.document.elementFromPoint(coords.left, coords.top);
|
||||
|
||||
if (!tokenEl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tokenEl.dispatchEvent(
|
||||
new MouseEvent("mouseover", {
|
||||
bubbles: true,
|
||||
@ -1234,6 +1247,9 @@ function hoverAtPos(dbg, { line, ch }) {
|
||||
);
|
||||
}
|
||||
|
||||
// tryHovering will hover at a position every second until we
|
||||
// see a preview element (popup, tooltip) appear. Once it appears,
|
||||
// it considers it a success.
|
||||
function tryHovering(dbg, line, column, elementName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const element = waitForElement(dbg, elementName);
|
||||
@ -1251,7 +1267,7 @@ function tryHovering(dbg, line, column, elementName) {
|
||||
}
|
||||
|
||||
hoverAtPos(dbg, { line, ch: column - 1 });
|
||||
}, 200);
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -536,6 +536,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
||||
// When pause points are specified for the source,
|
||||
// we should pause when we are at a stepOver pause point
|
||||
const pausePoint = findPausePointForLocation(pausePoints, newLocation);
|
||||
|
||||
if (pausePoint) {
|
||||
if (pausePoint.step) {
|
||||
return pauseAndRespond(this);
|
||||
|
@ -1313,18 +1313,6 @@ ReparentWrappersInSubtree(nsIContent* aRoot)
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
nsIGlobalObject* docGlobal = aRoot->OwnerDoc()->GetScopeObject();
|
||||
if (NS_WARN_IF(!docGlobal)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> rootedGlobal(cx, docGlobal->GetGlobalJSObject());
|
||||
if (NS_WARN_IF(!rootedGlobal)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rootedGlobal = xpc::GetXBLScope(cx, rootedGlobal);
|
||||
|
||||
ErrorResult rv;
|
||||
JS::Rooted<JSObject*> reflector(cx);
|
||||
for (nsIContent* cur = aRoot; cur; cur = cur->GetNextNode(aRoot)) {
|
||||
|
@ -475,6 +475,8 @@ ClaimOnMainThread(const ClientInfo& aClientInfo,
|
||||
}, [promise] (nsresult aRv) {
|
||||
promise->Reject(aRv, __func__);
|
||||
});
|
||||
|
||||
scopeExit.release();
|
||||
});
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget()));
|
||||
|
@ -124,6 +124,28 @@ ClientSource::GetDocShell() const
|
||||
return mOwner.as<nsCOMPtr<nsIDocShell>>();
|
||||
}
|
||||
|
||||
nsIGlobalObject*
|
||||
ClientSource::GetGlobal() const
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
nsPIDOMWindowInner* win = GetInnerWindow();
|
||||
if (win) {
|
||||
return win->AsGlobal();
|
||||
}
|
||||
|
||||
WorkerPrivate* wp = GetWorkerPrivate();
|
||||
if (wp) {
|
||||
return wp->GlobalScope();
|
||||
}
|
||||
|
||||
// Note, ClientSource objects attached to docshell for conceptual
|
||||
// initial about:blank will get nullptr here. The caller should
|
||||
// use MaybeCreateIntitialDocument() to create the window before
|
||||
// GetGlobal() if it wants this before.
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ClientSource::MaybeCreateInitialDocument()
|
||||
{
|
||||
@ -431,10 +453,47 @@ ClientSource::Control(const ClientControlledArgs& aArgs)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
|
||||
// Determine if the client is allowed to be controlled. Currently we
|
||||
// prevent service workers from controlling clients that cannot access
|
||||
// storage. We exempt this restriction for local URL clients, like about:blank
|
||||
// and blob:, since access to service workers is dictated by their parent.
|
||||
//
|
||||
// Note, we default to allowing the client to be controlled in the case
|
||||
// where we are not execution ready yet. This can only happen if the
|
||||
// the non-subresource load is intercepted by a service worker. Since
|
||||
// ServiceWorkerInterceptController() uses StorageAllowedForChannel()
|
||||
// it should be fine to accept these control messages.
|
||||
//
|
||||
// Its also fine to default to allowing ClientSource attached to a docshell
|
||||
// to be controlled. These clients represent inital about:blank windows
|
||||
// that do not have an inner window created yet. We explicitly allow initial
|
||||
// about:blank.
|
||||
bool controlAllowed = true;
|
||||
if (GetInnerWindow()) {
|
||||
|
||||
// Local URL windows and windows with access to storage can be controlled.
|
||||
controlAllowed = Info().URL().LowerCaseEqualsLiteral("about:blank") ||
|
||||
StringBeginsWith(Info().URL(), NS_LITERAL_CSTRING("blob:")) ||
|
||||
nsContentUtils::StorageAllowedForWindow(GetInnerWindow()) ==
|
||||
nsContentUtils::StorageAccess::eAllow;
|
||||
} else if (GetWorkerPrivate()) {
|
||||
// Local URL workers and workers with access to storage cna be controlled.
|
||||
controlAllowed = GetWorkerPrivate()->IsStorageAllowed() ||
|
||||
StringBeginsWith(GetWorkerPrivate()->ScriptURL(),
|
||||
NS_LITERAL_STRING("blob:"));
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
if (NS_WARN_IF(!controlAllowed)) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
__func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
SetController(ServiceWorkerDescriptor(aArgs.serviceWorker()));
|
||||
|
||||
RefPtr<ClientOpPromise> ref =
|
||||
ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
ref = ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
@ -670,35 +729,55 @@ ClientSource::PostMessage(const ClientPostMessageArgs& aArgs)
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientSource::Claim(const ClientClaimArgs& aArgs)
|
||||
{
|
||||
// The ClientSource::Claim method is only needed in the legacy
|
||||
// mode where the ServiceWorkerManager is run in each child-process.
|
||||
// In parent-process mode this method should not be called.
|
||||
MOZ_DIAGNOSTIC_ASSERT(!ServiceWorkerParentInterceptEnabled());
|
||||
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
nsIGlobalObject* global = GetGlobal();
|
||||
if (NS_WARN_IF(!global)) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
__func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
// Note, we cannot just mark the ClientSource controlled. We must go through
|
||||
// the SWM so that it can keep track of which clients are controlled by each
|
||||
// registration. We must tell the child-process SWM in legacy child-process
|
||||
// mode. In parent-process service worker mode the SWM is notified in the
|
||||
// parent-process in ClientManagerService::Claim().
|
||||
|
||||
RefPtr<GenericPromise::Private> innerPromise =
|
||||
new GenericPromise::Private(__func__);
|
||||
ServiceWorkerDescriptor swd(aArgs.serviceWorker());
|
||||
|
||||
// Today the ServiceWorkerManager maintains its own list of
|
||||
// nsIDocument objects controlled by each service worker. We
|
||||
// need to try to update that data structure for now. If we
|
||||
// can't, however, then simply mark the Client as controlled.
|
||||
// In the future this will be enough for the SWM as well since
|
||||
// it will eventually hold ClientHandle objects instead of
|
||||
// nsIDocuments.
|
||||
nsPIDOMWindowInner* innerWindow = GetInnerWindow();
|
||||
nsIDocument* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
|
||||
RefPtr<ServiceWorkerManager> swm = doc ? ServiceWorkerManager::GetInstance()
|
||||
: nullptr;
|
||||
if (!swm || !doc) {
|
||||
SetController(swd);
|
||||
ref = ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
return ref.forget();
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
"ClientSource::Claim",
|
||||
[innerPromise, clientInfo = mClientInfo, swd] () mutable {
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (NS_WARN_IF(!swm)) {
|
||||
innerPromise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise> p = swm->MaybeClaimClient(clientInfo, swd);
|
||||
p->ChainTo(innerPromise.forget(), __func__);
|
||||
});
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
r->Run();
|
||||
} else {
|
||||
MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget()));
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise::Private> outerPromise =
|
||||
new ClientOpPromise::Private(__func__);
|
||||
|
||||
auto holder =
|
||||
MakeRefPtr<DOMMozPromiseRequestHolder<GenericPromise>>(innerWindow->AsGlobal());
|
||||
auto holder = MakeRefPtr<DOMMozPromiseRequestHolder<GenericPromise>>(global);
|
||||
|
||||
RefPtr<GenericPromise> p = swm->MaybeClaimClient(mClientInfo, swd);
|
||||
p->Then(mEventTarget, __func__,
|
||||
innerPromise->Then(mEventTarget, __func__,
|
||||
[outerPromise, holder] (bool aResult) {
|
||||
holder->Complete();
|
||||
outerPromise->Resolve(NS_OK, __func__);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#endif
|
||||
|
||||
class nsIDocShell;
|
||||
class nsIGlobalObject;
|
||||
class nsISerialEventTarget;
|
||||
class nsPIDOMWindowInner;
|
||||
|
||||
@ -78,6 +79,9 @@ class ClientSource final : public ClientThing<ClientSourceChild>
|
||||
nsIDocShell*
|
||||
GetDocShell() const;
|
||||
|
||||
nsIGlobalObject*
|
||||
GetGlobal() const;
|
||||
|
||||
void
|
||||
MaybeCreateInitialDocument();
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "ClientSourceOpParent.h"
|
||||
|
||||
#include "ClientSourceParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -25,10 +27,22 @@ ClientSourceOpParent::Recv__delete__(const ClientOpResult& aResult)
|
||||
{
|
||||
if (aResult.type() == ClientOpResult::Tnsresult &&
|
||||
NS_FAILED(aResult.get_nsresult())) {
|
||||
|
||||
// If a control message fails then clear the controller from
|
||||
// the ClientSourceParent. We eagerly marked it controlled at
|
||||
// the start of the operation.
|
||||
if (mArgs.type() == ClientOpConstructorArgs::TClientControlledArgs) {
|
||||
auto source = static_cast<ClientSourceParent*>(Manager());
|
||||
if (source) {
|
||||
source->ClearController();
|
||||
}
|
||||
}
|
||||
|
||||
mPromise->Reject(aResult.get_nsresult(), __func__);
|
||||
mPromise = nullptr;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mPromise->Resolve(aResult, __func__);
|
||||
mPromise = nullptr;
|
||||
return IPC_OK();
|
||||
@ -36,7 +50,8 @@ ClientSourceOpParent::Recv__delete__(const ClientOpResult& aResult)
|
||||
|
||||
ClientSourceOpParent::ClientSourceOpParent(const ClientOpConstructorArgs& aArgs,
|
||||
ClientOpPromise::Private* aPromise)
|
||||
: mPromise(aPromise)
|
||||
: mArgs(aArgs)
|
||||
, mPromise(aPromise)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mPromise);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace dom {
|
||||
|
||||
class ClientSourceOpParent final : public PClientSourceOpParent
|
||||
{
|
||||
const ClientOpConstructorArgs mArgs;
|
||||
RefPtr<ClientOpPromise::Private> mPromise;
|
||||
|
||||
// PClientSourceOpParent interface
|
||||
|
@ -274,6 +274,12 @@ ClientSourceParent::GetController() const
|
||||
return mController;
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceParent::ClearController()
|
||||
{
|
||||
mController.reset();
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceParent::AttachHandle(ClientHandleParent* aClientHandle)
|
||||
{
|
||||
@ -298,7 +304,11 @@ ClientSourceParent::StartOp(const ClientOpConstructorArgs& aArgs)
|
||||
new ClientOpPromise::Private(__func__);
|
||||
|
||||
// If we are being controlled, remember that data before propagating
|
||||
// on to the ClientSource.
|
||||
// on to the ClientSource. This must be set prior to triggering
|
||||
// the controllerchange event from the ClientSource since some tests
|
||||
// expect matchAll() to find the controlled client immediately after.
|
||||
// If the control operation fails, then we reset the controller value
|
||||
// to reflect the final state.
|
||||
if (aArgs.type() == ClientOpConstructorArgs::TClientControlledArgs) {
|
||||
mController.reset();
|
||||
mController.emplace(aArgs.get_ClientControlledArgs().serviceWorker());
|
||||
|
@ -79,6 +79,9 @@ public:
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
GetController() const;
|
||||
|
||||
void
|
||||
ClearController();
|
||||
|
||||
void
|
||||
AttachHandle(ClientHandleParent* aClientSource);
|
||||
|
||||
|
@ -317,6 +317,7 @@ ServiceWorkerManager::StartControllingClient(const ClientInfo& aClientInfo,
|
||||
MOZ_DIAGNOSTIC_ASSERT(aRegistrationInfo->GetActive());
|
||||
|
||||
RefPtr<GenericPromise> ref;
|
||||
RefPtr<ServiceWorkerManager> self(this);
|
||||
|
||||
const ServiceWorkerDescriptor& active =
|
||||
aRegistrationInfo->GetActive()->Descriptor();
|
||||
@ -326,7 +327,12 @@ ServiceWorkerManager::StartControllingClient(const ClientInfo& aClientInfo,
|
||||
RefPtr<ServiceWorkerRegistrationInfo> old =
|
||||
entry.Data()->mRegistrationInfo.forget();
|
||||
|
||||
ref = entry.Data()->mClientHandle->Control(active);
|
||||
if (aControlClientHandle) {
|
||||
ref = entry.Data()->mClientHandle->Control(active);
|
||||
} else {
|
||||
ref = GenericPromise::CreateAndResolve(false, __func__);
|
||||
}
|
||||
|
||||
entry.Data()->mRegistrationInfo = aRegistrationInfo;
|
||||
|
||||
if (old != aRegistrationInfo) {
|
||||
@ -336,6 +342,17 @@ ServiceWorkerManager::StartControllingClient(const ClientInfo& aClientInfo,
|
||||
|
||||
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_CONTROLLED_DOCUMENTS, 1);
|
||||
|
||||
// Always check to see if we failed to actually control the client. In
|
||||
// that case removed the client from our list of controlled clients.
|
||||
ref->Then(
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
|
||||
[] (bool) {
|
||||
// do nothing on success
|
||||
}, [self, aClientInfo] (nsresult aRv) {
|
||||
// failed to control, forget about this client
|
||||
self->StopControllingClient(aClientInfo);
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
@ -355,15 +372,25 @@ ServiceWorkerManager::StartControllingClient(const ClientInfo& aClientInfo,
|
||||
return new ControlledClientData(clientHandle, aRegistrationInfo);
|
||||
});
|
||||
|
||||
RefPtr<ServiceWorkerManager> self(this);
|
||||
clientHandle->OnDetach()->Then(
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
|
||||
[self = std::move(self), aClientInfo] {
|
||||
[self, aClientInfo] {
|
||||
self->StopControllingClient(aClientInfo);
|
||||
});
|
||||
|
||||
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_CONTROLLED_DOCUMENTS, 1);
|
||||
|
||||
// Always check to see if we failed to actually control the client. In
|
||||
// that case removed the client from our list of controlled clients.
|
||||
ref->Then(
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
|
||||
[] (bool) {
|
||||
// do nothing on success
|
||||
}, [self, aClientInfo] (nsresult aRv) {
|
||||
// failed to control, forget about this client
|
||||
self->StopControllingClient(aClientInfo);
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
@ -2695,7 +2722,20 @@ ServiceWorkerManager::UpdateClientControllers(ServiceWorkerRegistrationInfo* aRe
|
||||
// Fire event after iterating mControlledClients is done to prevent
|
||||
// modification by reentering from the event handlers during iteration.
|
||||
for (auto& handle : handleList) {
|
||||
handle->Control(activeWorker->Descriptor());
|
||||
RefPtr<GenericPromise> p = handle->Control(activeWorker->Descriptor());
|
||||
|
||||
RefPtr<ServiceWorkerManager> self = this;
|
||||
|
||||
// If we fail to control the client, then automatically remove it
|
||||
// from our list of controlled clients.
|
||||
p->Then(
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
|
||||
[] (bool) {
|
||||
// do nothing on success
|
||||
}, [self, clientInfo = handle->Info()] (nsresult aRv) {
|
||||
// failed to control, forget about this client
|
||||
self->StopControllingClient(clientInfo);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -820,6 +820,11 @@ WebSocketImpl::ScheduleConnectionCloseEvents(nsISupports* aContext,
|
||||
aStatusCode = NS_OK;
|
||||
}
|
||||
|
||||
if (aStatusCode == NS_ERROR_NET_INADEQUATE_SECURITY) {
|
||||
// TLS negotiation failed so we need to set status code to 1015.
|
||||
mCloseEventCode = 1015;
|
||||
}
|
||||
|
||||
if (NS_FAILED(aStatusCode)) {
|
||||
ConsoleError();
|
||||
mFailed = true;
|
||||
|
@ -240,16 +240,15 @@ WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
|
||||
void
|
||||
WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters)
|
||||
const nsTArray<wr::WrFilterOp>& aFilters,
|
||||
WebRenderBackgroundData* aBackground)
|
||||
{
|
||||
MOZ_ASSERT(aDisplayList && aDisplayListBuilder);
|
||||
|
||||
AUTO_PROFILER_TRACING("Paint", "RenderLayers");
|
||||
|
||||
#if DUMP_LISTS
|
||||
// Useful for debugging, it dumps the display list *before* we try to build
|
||||
// WR commands from it
|
||||
if (XRE_IsContentProcess()) nsFrame::PrintDisplayList(aDisplayListBuilder, *aDisplayList);
|
||||
if (XRE_IsContentProcess() && aDisplayList) nsFrame::PrintDisplayList(aDisplayListBuilder, *aDisplayList);
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
@ -266,7 +265,9 @@ WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
|
||||
wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize, mLastDisplayListSize);
|
||||
wr::IpcResourceUpdateQueue resourceUpdates(WrBridge());
|
||||
|
||||
{ // Record the time spent "layerizing". WR doesn't actually layerize but
|
||||
if (aDisplayList) {
|
||||
MOZ_ASSERT(aDisplayListBuilder && !aBackground);
|
||||
// Record the time spent "layerizing". WR doesn't actually layerize but
|
||||
// generating the WR display list is the closest equivalent
|
||||
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
|
||||
|
||||
@ -277,6 +278,10 @@ WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
|
||||
mScrollData,
|
||||
contentSize,
|
||||
aFilters);
|
||||
} else {
|
||||
// ViewToPaint does not have frame yet, then render only background clolor.
|
||||
MOZ_ASSERT(!aDisplayListBuilder && aBackground);
|
||||
aBackground->AddWebRenderCommands(builder);
|
||||
}
|
||||
|
||||
DiscardCompositorAnimations();
|
||||
|
@ -71,7 +71,8 @@ public:
|
||||
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) override;
|
||||
void EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>());
|
||||
const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
|
||||
WebRenderBackgroundData* aBackground = nullptr);
|
||||
virtual void EndTransaction(DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags = END_DEFAULT) override;
|
||||
|
@ -20,6 +20,15 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
void
|
||||
WebRenderBackgroundData::AddWebRenderCommands(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
aBuilder.PushRect(mBounds,
|
||||
mBounds,
|
||||
true,
|
||||
mColor);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
WebRenderUserData::SupportsAsyncUpdate(nsIFrame* aFrame)
|
||||
{
|
||||
|
@ -37,6 +37,19 @@ class WebRenderFallbackData;
|
||||
class WebRenderLayerManager;
|
||||
class WebRenderGroupData;
|
||||
|
||||
class WebRenderBackgroundData
|
||||
{
|
||||
public:
|
||||
WebRenderBackgroundData(wr::LayoutRect aBounds, wr::ColorF aColor)
|
||||
: mBounds(aBounds)
|
||||
, mColor(aColor)
|
||||
{ }
|
||||
void AddWebRenderCommands(wr::DisplayListBuilder& aBuilder);
|
||||
protected:
|
||||
wr::LayoutRect mBounds;
|
||||
wr::ColorF mColor;
|
||||
};
|
||||
|
||||
class WebRenderUserData
|
||||
{
|
||||
public:
|
||||
|
@ -55,6 +55,10 @@ ID3D11Device*
|
||||
RenderCompositorANGLE::GetDeviceOfEGLDisplay()
|
||||
{
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
MOZ_ASSERT(egl);
|
||||
if (!egl || !egl->IsExtensionSupported(gl::GLLibraryEGL::EXT_device_query)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Fetch the D3D11 device.
|
||||
EGLDeviceEXT eglDevice = nullptr;
|
||||
|
@ -5,6 +5,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* [SMDOC] JS::CallArgs API
|
||||
*
|
||||
* Helper classes encapsulating access to the callee, |this| value, arguments,
|
||||
* and argument count for a call/construct operation.
|
||||
*
|
||||
@ -46,10 +48,7 @@
|
||||
*
|
||||
* It's possible (albeit deprecated) to manually index into |vp| to access the
|
||||
* callee, |this|, and arguments of a function, and to set its return value.
|
||||
* It's also possible to use the supported API of JS_CALLEE, JS_THIS, JS_ARGV,
|
||||
* JS_RVAL, and JS_SET_RVAL to the same ends.
|
||||
*
|
||||
* But neither API has the error-handling or moving-GC correctness of CallArgs.
|
||||
* This does not have the error-handling or moving-GC correctness of CallArgs.
|
||||
* New code should use CallArgs instead whenever possible.
|
||||
*
|
||||
* The eventual plan is to change JSNative to take |const CallArgs&| directly,
|
||||
|
@ -27,6 +27,8 @@ class Debugger;
|
||||
namespace JS {
|
||||
namespace dbg {
|
||||
|
||||
// [SMDOC] Debugger builder API
|
||||
//
|
||||
// Helping embedding code build objects for Debugger
|
||||
// -------------------------------------------------
|
||||
//
|
||||
|
@ -37,6 +37,8 @@ class RegExpShared;
|
||||
class JS_FRIEND_API(Wrapper);
|
||||
|
||||
/*
|
||||
* [SMDOC] Proxy Objects
|
||||
*
|
||||
* A proxy is a JSObject with highly customizable behavior. ES6 specifies a
|
||||
* single kind of proxy, but the customization mechanisms we use to implement
|
||||
* ES6 Proxy objects are also useful wherever an object with weird behavior is
|
||||
|
@ -5,6 +5,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* [SMDOC] JS::Result
|
||||
*
|
||||
* `Result` is used as the return type of many SpiderMonkey functions that
|
||||
* can either succeed or fail. See "/mfbt/Result.h".
|
||||
*
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "js/Utility.h"
|
||||
|
||||
/*
|
||||
* [SMDOC] Stack Rooting
|
||||
*
|
||||
* Moving GC Stack Rooting
|
||||
*
|
||||
* A moving GC may change the physical location of GC allocated things, even
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "js/Value.h"
|
||||
#include "js/Vector.h"
|
||||
|
||||
// JS::ubi::Node
|
||||
// [SMDOC] ubi::Node (Heap Analysis framework)
|
||||
//
|
||||
// JS::ubi::Node is a pointer-like type designed for internal use by heap
|
||||
// analysis tools. A ubi::Node can refer to:
|
||||
|
@ -268,6 +268,8 @@ CanonicalizeNaN(double d)
|
||||
}
|
||||
|
||||
/**
|
||||
* [SMDOC] JS::Value type
|
||||
*
|
||||
* JS::Value is the interface for a single JavaScript Engine value. A few
|
||||
* general notes on JS::Value:
|
||||
*
|
||||
|
@ -939,16 +939,6 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
|
||||
return result.succeed();
|
||||
}
|
||||
|
||||
bool
|
||||
js::WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index)
|
||||
{
|
||||
if (!obj->is<ArrayObject>())
|
||||
return false;
|
||||
|
||||
ArrayObject* arr = &obj->as<ArrayObject>();
|
||||
return !arr->lengthIsWritable() && index >= arr->length();
|
||||
}
|
||||
|
||||
static bool
|
||||
array_addProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
|
||||
{
|
||||
|
@ -113,14 +113,6 @@ extern ArrayObject*
|
||||
NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
|
||||
HandleObject proto = nullptr);
|
||||
|
||||
/*
|
||||
* Determines whether a write to the given element on |obj| should fail because
|
||||
* |obj| is an Array with a non-writable length, and writing that element would
|
||||
* increase the length of the array.
|
||||
*/
|
||||
extern bool
|
||||
WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index);
|
||||
|
||||
extern bool
|
||||
GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp);
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
/*
|
||||
* -------------
|
||||
* Typed Objects
|
||||
* [SMDOC] Typed Objects
|
||||
* -------------
|
||||
*
|
||||
* Typed objects are a special kind of JS object where the data is
|
||||
|
@ -10,6 +10,8 @@
|
||||
#define frontend_Parser_h
|
||||
|
||||
/*
|
||||
* [SMDOC] JS Parser
|
||||
*
|
||||
* JS parsers capable of generating ASTs from source text.
|
||||
*
|
||||
* A parser embeds token stream information, then gets and matches tokens to
|
||||
|
@ -16,6 +16,8 @@
|
||||
#define frontend_TokenStream_h
|
||||
|
||||
/*
|
||||
* [SMDOC] Parser Token Stream
|
||||
*
|
||||
* A token stream exposes the raw tokens -- operators, names, numbers,
|
||||
* keywords, and so on -- of JavaScript source code.
|
||||
*
|
||||
|
@ -15,7 +15,7 @@
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
// Atom Marking Overview
|
||||
// [SMDOC] GC Atom Marking
|
||||
//
|
||||
// Things in the atoms zone (which includes atomized strings and other things,
|
||||
// all of which we will refer to as 'atoms' here) may be pointed to freely by
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "js/Value.h"
|
||||
|
||||
/*
|
||||
* [SMDOC] GC Barriers
|
||||
*
|
||||
* A write barrier is a mechanism used by incremental or generation GCs to
|
||||
* ensure that every value that needs to be marked is marked. In general, the
|
||||
* write barrier should be invoked whenever a write can cause the set of things
|
||||
|
@ -5,6 +5,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* [SMDOC] Garbage Collector
|
||||
*
|
||||
* This code implements an incremental mark-and-sweep garbage collector, with
|
||||
* most sweeping carried out in the background on a parallel thread.
|
||||
*
|
||||
|
@ -54,6 +54,8 @@ using mozilla::IsBaseOf;
|
||||
using mozilla::IsSame;
|
||||
using mozilla::PodCopy;
|
||||
|
||||
// [SMDOC] GC Tracing
|
||||
//
|
||||
// Tracing Overview
|
||||
// ================
|
||||
//
|
||||
|
@ -5,6 +5,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* [SMDOC] GC Scheduling
|
||||
*
|
||||
* GC Scheduling Overview
|
||||
* ======================
|
||||
*
|
||||
|
@ -99,6 +99,8 @@ class MOZ_NON_TEMPORARY_CLASS FunctionToStringCache
|
||||
|
||||
namespace JS {
|
||||
|
||||
// [SMDOC] GC Zones
|
||||
//
|
||||
// A zone is a collection of compartments. Every compartment belongs to exactly
|
||||
// one zone. In Firefox, there is roughly one zone per tab along with a system
|
||||
// zone for everything else. Zones mainly serve as boundaries for garbage
|
||||
|
@ -1326,6 +1326,7 @@ Analysis::VisitAssertion(AssertionNode* that)
|
||||
EnsureAnalyzed(that->on_success());
|
||||
}
|
||||
|
||||
// [SMDOC] Irregexp internals
|
||||
// -------------------------------------------------------------------
|
||||
// Implementation of the Irregexp regular expression engine.
|
||||
//
|
||||
|
@ -45,3 +45,16 @@ function testException1() {
|
||||
}
|
||||
}
|
||||
testException1();
|
||||
|
||||
function testDOMCalls() {
|
||||
var g = newGlobal({sameCompartmentAs: this});
|
||||
var obj = g.evaluate("new FakeDOMObject()");
|
||||
for (var i = 0; i < 2000; i++) {
|
||||
assertCorrectRealm();
|
||||
assertEq(obj.doFoo(1), 1);
|
||||
assertEq(typeof obj.x, "number");
|
||||
assertEq(obj.global, g);
|
||||
obj.global = g; // Throws if not setter's global.
|
||||
}
|
||||
}
|
||||
testDOMCalls();
|
||||
|
@ -1,11 +1,11 @@
|
||||
function linearModule(min, max, ops) {
|
||||
function linearModule(min, max, ops, current_memory, grow_memory) {
|
||||
var opsText = ops.map(function (op) {
|
||||
if (op[0] == "CM") {
|
||||
res = `(if i32 (i32.ne (current_memory) (i32.const ${op[1]}))
|
||||
res = `(if i32 (i32.ne (${current_memory}) (i32.const ${op[1]}))
|
||||
(i32.load offset=10 (i32.const 4294967295))
|
||||
(i32.const 0))`
|
||||
} else if (op[0] == "GM") {
|
||||
res = `(if i32 (i32.ne (grow_memory (i32.const ${op[1]})) (i32.const ${op[2]}))
|
||||
res = `(if i32 (i32.ne (${grow_memory} (i32.const ${op[1]})) (i32.const ${op[2]}))
|
||||
(i32.load offset=10 (i32.const 4294967295))
|
||||
(i32.const 0))`
|
||||
} else if (op[0] == "L") {
|
||||
@ -35,11 +35,12 @@ function linearModule(min, max, ops) {
|
||||
`
|
||||
(func (result i32)
|
||||
(drop ` + opsText + `)
|
||||
(current_memory)
|
||||
(${current_memory})
|
||||
) (export "run" 0))`;
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
// Just grow some memory
|
||||
wasmFullPass(linearModule(3,5, [["CM", 3]]), 3);
|
||||
wasmFullPass(linearModule(3,5, [["CM", 3]], "current_memory", "grow_memory"), 3); // Old opcode names
|
||||
wasmFullPass(linearModule(3,5, [["CM", 3]], "memory.size", "memory.grow"), 3); // New opcode names
|
||||
|
@ -116,6 +116,8 @@ IonSpewAliasInfo(const char* pre, MInstruction* ins, const char* post)
|
||||
#endif
|
||||
}
|
||||
|
||||
// [SMDOC] IonMonkey Alias Analysis
|
||||
//
|
||||
// This pass annotates every load instruction with the last store instruction
|
||||
// on which it depends. The algorithm is optimistic in that it ignores explicit
|
||||
// dependencies and only considers loads and stores.
|
||||
|
@ -15,6 +15,8 @@ namespace js {
|
||||
namespace jit {
|
||||
|
||||
/*
|
||||
* [SMDOC] Atomic Operations
|
||||
*
|
||||
* The atomic operations layer defines types and functions for
|
||||
* JIT-compatible atomic operation.
|
||||
*
|
||||
|
@ -16,8 +16,10 @@
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// A "bailout" is a condition in which we need to recover an interpreter frame
|
||||
// from an IonFrame. Bailouts can happen for the following reasons:
|
||||
// [SMDOC] IonMonkey Bailouts
|
||||
//
|
||||
// A "bailout" is a condition in which we need to recover a baseline frame from
|
||||
// an IonFrame. Bailouts can happen for the following reasons:
|
||||
// (1) A deoptimization guard, for example, an add overflows or a type check
|
||||
// fails.
|
||||
// (2) A check or assumption held by the JIT is invalidated by the VM, and
|
||||
@ -36,7 +38,7 @@ namespace jit {
|
||||
// jmp _bailout
|
||||
//
|
||||
// The bailout target needs to somehow translate the Ion frame (whose state
|
||||
// will differ at each program point) to an interpreter frame. This state is
|
||||
// will differ at each program point) to a baseline frame. This state is
|
||||
// captured into the IonScript's snapshot buffer, and for each bailout we know
|
||||
// which snapshot corresponds to its state.
|
||||
//
|
||||
@ -49,7 +51,7 @@ namespace jit {
|
||||
// to find the structure of the frame, and then use the stack and spilled
|
||||
// registers to perform frame conversion.
|
||||
// (5) Bailout() returns, and the JIT must immediately return to the
|
||||
// interpreter (all frames are converted at once).
|
||||
// baseline JIT code (all frames are converted at once).
|
||||
//
|
||||
// (2) and (3) are implemented by a trampoline held in the compartment.
|
||||
// Naively, we could implement (1) like:
|
||||
|
@ -625,7 +625,7 @@ GeneratePrototypeGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
|
||||
// [[GetOwnProperty]] has no definition of the target property.
|
||||
//
|
||||
//
|
||||
// Shape Teleporting Optimization
|
||||
// [SMDOC] Shape Teleporting Optimization
|
||||
// ------------------------------
|
||||
//
|
||||
// Starting with the assumption (and guideline to developers) that mutating
|
||||
|
@ -22,6 +22,8 @@ namespace jit {
|
||||
|
||||
enum class BaselineCacheIRStubKind;
|
||||
|
||||
// [SMDOC] CacheIR
|
||||
//
|
||||
// CacheIR is an (extremely simple) linear IR language for inline caches.
|
||||
// From this IR, we can generate machine code for Baseline or Ion IC stubs.
|
||||
//
|
||||
|
@ -4418,6 +4418,12 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative* call)
|
||||
masm.Push(argObj);
|
||||
masm.moveStackPtrTo(argObj);
|
||||
|
||||
if (call->mir()->maybeCrossRealm()) {
|
||||
// We use argJSContext as scratch register here.
|
||||
masm.movePtr(ImmGCPtr(target->rawJSFunction()), argJSContext);
|
||||
masm.switchToObjectRealm(argJSContext, argJSContext);
|
||||
}
|
||||
|
||||
// Construct native exit frame.
|
||||
uint32_t safepointOffset = masm.buildFakeExitFrame(argJSContext);
|
||||
masm.loadJSContext(argJSContext);
|
||||
@ -4447,6 +4453,14 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative* call)
|
||||
JSReturnOperand);
|
||||
}
|
||||
|
||||
// Switch back to the current realm if needed. Note: if the DOM method threw
|
||||
// an exception, the exception handler will do this.
|
||||
if (call->mir()->maybeCrossRealm()) {
|
||||
static_assert(!JSReturnOperand.aliases(ReturnReg),
|
||||
"Clobbering ReturnReg should not affect the return value");
|
||||
masm.switchToRealm(gen->realm->realmPtr(), ReturnReg);
|
||||
}
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (JitOptions.spectreJitToCxxCalls && call->mir()->hasLiveDefUses())
|
||||
@ -12255,6 +12269,12 @@ CodeGenerator::visitGetDOMProperty(LGetDOMProperty* ins)
|
||||
// Rooting will happen at GC time.
|
||||
masm.moveStackPtrTo(ObjectReg);
|
||||
|
||||
Realm* getterRealm = ins->mir()->getterRealm();
|
||||
if (gen->realm->realmPtr() != getterRealm) {
|
||||
// We use JSContextReg as scratch register here.
|
||||
masm.switchToRealm(getterRealm, JSContextReg);
|
||||
}
|
||||
|
||||
uint32_t safepointOffset = masm.buildFakeExitFrame(JSContextReg);
|
||||
masm.loadJSContext(JSContextReg);
|
||||
masm.enterFakeExitFrame(JSContextReg, JSContextReg, ExitFrameType::IonDOMGetter);
|
||||
@ -12280,6 +12300,14 @@ CodeGenerator::visitGetDOMProperty(LGetDOMProperty* ins)
|
||||
JSReturnOperand);
|
||||
}
|
||||
|
||||
// Switch back to the current realm if needed. Note: if the getter threw an
|
||||
// exception, the exception handler will do this.
|
||||
if (gen->realm->realmPtr() != getterRealm) {
|
||||
static_assert(!JSReturnOperand.aliases(ReturnReg),
|
||||
"Clobbering ReturnReg should not affect the return value");
|
||||
masm.switchToRealm(gen->realm->realmPtr(), ReturnReg);
|
||||
}
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (JitOptions.spectreJitToCxxCalls && ins->mir()->hasLiveDefUses())
|
||||
@ -12360,6 +12388,12 @@ CodeGenerator::visitSetDOMProperty(LSetDOMProperty* ins)
|
||||
// Rooting will happen at GC time.
|
||||
masm.moveStackPtrTo(ObjectReg);
|
||||
|
||||
Realm* setterRealm = ins->mir()->setterRealm();
|
||||
if (gen->realm->realmPtr() != setterRealm) {
|
||||
// We use JSContextReg as scratch register here.
|
||||
masm.switchToRealm(setterRealm, JSContextReg);
|
||||
}
|
||||
|
||||
uint32_t safepointOffset = masm.buildFakeExitFrame(JSContextReg);
|
||||
masm.loadJSContext(JSContextReg);
|
||||
masm.enterFakeExitFrame(JSContextReg, JSContextReg, ExitFrameType::IonDOMSetter);
|
||||
@ -12377,6 +12411,11 @@ CodeGenerator::visitSetDOMProperty(LSetDOMProperty* ins)
|
||||
|
||||
masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
|
||||
|
||||
// Switch back to the current realm if needed. Note: if the setter threw an
|
||||
// exception, the exception handler will do this.
|
||||
if (gen->realm->realmPtr() != setterRealm)
|
||||
masm.switchToRealm(gen->realm->realmPtr(), ReturnReg);
|
||||
|
||||
masm.adjustStack(IonDOMExitFrameLayout::Size());
|
||||
|
||||
MOZ_ASSERT(masm.framePushed() == initialStack);
|
||||
|
@ -11004,7 +11004,8 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
|
||||
// needed.
|
||||
get = MGetDOMMember::New(alloc(), jitinfo, obj, guard, globalGuard);
|
||||
} else {
|
||||
get = MGetDOMProperty::New(alloc(), jitinfo, objKind, obj, guard, globalGuard);
|
||||
get = MGetDOMProperty::New(alloc(), jitinfo, objKind, commonGetter->realm(), obj,
|
||||
guard, globalGuard);
|
||||
}
|
||||
if (!get)
|
||||
return abort(AbortReason::Alloc);
|
||||
@ -11693,7 +11694,7 @@ IonBuilder::setPropTryCommonDOMSetter(bool* emitted, MDefinition* obj,
|
||||
// Emit SetDOMProperty.
|
||||
MOZ_ASSERT(setter->jitInfo()->type() == JSJitInfo::Setter);
|
||||
MSetDOMProperty* set = MSetDOMProperty::New(alloc(), setter->jitInfo()->setter, objKind,
|
||||
obj, value);
|
||||
setter->realm(), obj, value);
|
||||
|
||||
current->add(set);
|
||||
current->push(value);
|
||||
|
@ -12385,12 +12385,14 @@ class MSetDOMProperty
|
||||
public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >::Data
|
||||
{
|
||||
const JSJitSetterOp func_;
|
||||
Realm* setterRealm_;
|
||||
DOMObjectKind objectKind_;
|
||||
|
||||
MSetDOMProperty(const JSJitSetterOp func, DOMObjectKind objectKind, MDefinition* obj,
|
||||
MDefinition* val)
|
||||
MSetDOMProperty(const JSJitSetterOp func, DOMObjectKind objectKind, Realm* setterRealm,
|
||||
MDefinition* obj, MDefinition* val)
|
||||
: MBinaryInstruction(classOpcode, obj, val),
|
||||
func_(func),
|
||||
setterRealm_(setterRealm),
|
||||
objectKind_(objectKind)
|
||||
{ }
|
||||
|
||||
@ -12402,6 +12404,9 @@ class MSetDOMProperty
|
||||
JSJitSetterOp fun() const {
|
||||
return func_;
|
||||
}
|
||||
Realm* setterRealm() const {
|
||||
return setterRealm_;
|
||||
}
|
||||
DOMObjectKind objectKind() const {
|
||||
return objectKind_;
|
||||
}
|
||||
@ -12517,11 +12522,14 @@ class MGetDOMPropertyBase
|
||||
class MGetDOMProperty
|
||||
: public MGetDOMPropertyBase
|
||||
{
|
||||
Realm* getterRealm_;
|
||||
DOMObjectKind objectKind_;
|
||||
|
||||
protected:
|
||||
MGetDOMProperty(const JSJitInfo* jitinfo, DOMObjectKind objectKind)
|
||||
MGetDOMProperty(const JSJitInfo* jitinfo, DOMObjectKind objectKind,
|
||||
Realm* getterRealm)
|
||||
: MGetDOMPropertyBase(classOpcode, jitinfo),
|
||||
getterRealm_(getterRealm),
|
||||
objectKind_(objectKind)
|
||||
{}
|
||||
|
||||
@ -12529,14 +12537,18 @@ class MGetDOMProperty
|
||||
INSTRUCTION_HEADER(GetDOMProperty)
|
||||
|
||||
static MGetDOMProperty* New(TempAllocator& alloc, const JSJitInfo* info, DOMObjectKind objectKind,
|
||||
MDefinition* obj, MDefinition* guard, MDefinition* globalGuard)
|
||||
Realm* getterRealm, MDefinition* obj, MDefinition* guard,
|
||||
MDefinition* globalGuard)
|
||||
{
|
||||
auto* res = new(alloc) MGetDOMProperty(info, objectKind);
|
||||
auto* res = new(alloc) MGetDOMProperty(info, objectKind, getterRealm);
|
||||
if (!res || !res->init(alloc, obj, guard, globalGuard))
|
||||
return nullptr;
|
||||
return res;
|
||||
}
|
||||
|
||||
Realm* getterRealm() const {
|
||||
return getterRealm_;
|
||||
}
|
||||
DOMObjectKind objectKind() const {
|
||||
return objectKind_;
|
||||
}
|
||||
@ -12545,6 +12557,9 @@ class MGetDOMProperty
|
||||
if (!ins->isGetDOMProperty())
|
||||
return false;
|
||||
|
||||
if (ins->toGetDOMProperty()->getterRealm() != getterRealm())
|
||||
return false;
|
||||
|
||||
return baseCongruentTo(ins->toGetDOMProperty());
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "vm/TypedArrayObject.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
|
||||
// [SMDOC] MacroAssembler multi-platform overview
|
||||
//
|
||||
// * How to read/write MacroAssembler method declarations:
|
||||
//
|
||||
// The following macros are made to avoid #ifdef around each method declarations
|
||||
|
@ -37,6 +37,8 @@ using mozilla::Swap;
|
||||
using JS::GenericNaN;
|
||||
using JS::ToInt32;
|
||||
|
||||
// [SMDOC] IonMonkey Range Analysis
|
||||
//
|
||||
// This algorithm is based on the paper "Eliminating Range Checks Using
|
||||
// Static Single Assignment Form" by Gough and Klaren.
|
||||
//
|
||||
|
@ -17,6 +17,8 @@
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// [SMDOC] IonMonkey Recover Instructions
|
||||
//
|
||||
// This file contains all recover instructions.
|
||||
//
|
||||
// A recover instruction is an equivalent of a MIR instruction which is executed
|
||||
|
@ -466,6 +466,8 @@ class RegisterSet {
|
||||
}
|
||||
};
|
||||
|
||||
// [SMDOC] JIT Register-Set overview
|
||||
//
|
||||
// There are 2 use cases for register sets:
|
||||
//
|
||||
// 1. To serve as a pool of allocatable register. This is useful for working
|
||||
@ -504,6 +506,8 @@ class AllocatableSet;
|
||||
template <typename RegisterSet>
|
||||
class LiveSet;
|
||||
|
||||
// [SMDOC] JIT Register-Set (Allocatable)
|
||||
//
|
||||
// Base accessors classes have the minimal set of raw methods to manipulate the register set
|
||||
// given as parameter in a consistent manner. These methods are:
|
||||
//
|
||||
@ -620,6 +624,8 @@ class AllocatableSetAccessors<RegisterSet>
|
||||
};
|
||||
|
||||
|
||||
// [SMDOC] JIT Register-Set (Live)
|
||||
//
|
||||
// The LiveSet accessors are used to collect a list of allocated
|
||||
// registers. Taking or adding a register should *not* consider the aliases, as
|
||||
// we care about interpreting the registers with the correct type. For example,
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// [SMDOC] JIT Inline Caches (ICs)
|
||||
//
|
||||
// Baseline Inline Caches are polymorphic caches that aggressively
|
||||
// share their stub code.
|
||||
|
@ -19,6 +19,8 @@
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
// [SMDOC] IonMonkey Snapshot encoding
|
||||
//
|
||||
// Encodings:
|
||||
// [ptr] A fixed-size pointer.
|
||||
// [vwu] A variable-width unsigned integer.
|
||||
|
@ -15,6 +15,8 @@ using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
/*
|
||||
* [SMDOC] IonMonkey Value Numbering
|
||||
*
|
||||
* Some notes on the main algorithm here:
|
||||
* - The SSA identifier id() is the value number. We do replaceAllUsesWith as
|
||||
* we go, so there's always at most one visible value with a given number.
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "jit/JitSpewer.h"
|
||||
#include "jit/shared/IonAssemblerBuffer.h"
|
||||
|
||||
// [SMDOC] JIT AssemblerBuffer constant pooling (ARM/ARM64/MIPS)
|
||||
//
|
||||
// This code extends the AssemblerBuffer to support the pooling of values loaded
|
||||
// using program-counter relative addressing modes. This is necessary with the
|
||||
// ARM instruction set because it has a fixed instruction size that can not
|
||||
|
@ -6137,36 +6137,21 @@ JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t lengt
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
/*
|
||||
* FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
|
||||
* would allow to distinguish between insufficient buffer and encoding
|
||||
* error.
|
||||
*/
|
||||
size_t writtenLength = length;
|
||||
JSLinearString* linear = str->ensureLinear(cx);
|
||||
if (!linear)
|
||||
return size_t(-1);
|
||||
|
||||
bool res;
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
size_t writeLength = Min(linear->length(), length);
|
||||
if (linear->hasLatin1Chars()) {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
res = DeflateStringToBuffer(nullptr, linear->latin1Chars(nogc), linear->length(), buffer,
|
||||
&writtenLength);
|
||||
mozilla::PodCopy(reinterpret_cast<Latin1Char*>(buffer), linear->latin1Chars(nogc),
|
||||
writeLength);
|
||||
} else {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
res = DeflateStringToBuffer(nullptr, linear->twoByteChars(nogc), linear->length(), buffer,
|
||||
&writtenLength);
|
||||
const char16_t* src = linear->twoByteChars(nogc);
|
||||
for (size_t i = 0; i < writeLength; i++)
|
||||
buffer[i] = char(src[i]);
|
||||
}
|
||||
if (res) {
|
||||
MOZ_ASSERT(writtenLength <= length);
|
||||
return writtenLength;
|
||||
}
|
||||
MOZ_ASSERT(writtenLength <= length);
|
||||
size_t necessaryLength = str->length();
|
||||
if (necessaryLength == size_t(-1))
|
||||
return size_t(-1);
|
||||
MOZ_ASSERT(writtenLength == length); // C strings are NOT encoded.
|
||||
return necessaryLength;
|
||||
return linear->length();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::Symbol*)
|
||||
|
@ -7839,11 +7839,43 @@ dom_set_x(JSContext* cx, HandleObject obj, void* self, JSJitSetterCallArgs args)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
dom_get_global(JSContext* cx, HandleObject obj, void* self, JSJitGetterCallArgs args)
|
||||
{
|
||||
MOZ_ASSERT(JS_GetClass(obj) == GetDomClass());
|
||||
MOZ_ASSERT(self == (void*)0x1234);
|
||||
|
||||
// Return the current global (instead of obj->global()) to test cx->realm
|
||||
// switching in the JIT.
|
||||
args.rval().setObject(*ToWindowProxyIfWindow(cx->global()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
dom_set_global(JSContext* cx, HandleObject obj, void* self, JSJitSetterCallArgs args)
|
||||
{
|
||||
MOZ_ASSERT(JS_GetClass(obj) == GetDomClass());
|
||||
MOZ_ASSERT(self == (void*)0x1234);
|
||||
|
||||
// Throw an exception if our argument is not the current global. This lets
|
||||
// us test cx->realm switching.
|
||||
if (!args[0].isObject() ||
|
||||
ToWindowIfWindowProxy(&args[0].toObject()) != cx->global())
|
||||
{
|
||||
JS_ReportErrorASCII(cx, "Setter not called with matching global argument");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
dom_doFoo(JSContext* cx, HandleObject obj, void* self, const JSJitMethodCallArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(JS_GetClass(obj) == GetDomClass());
|
||||
MOZ_ASSERT(self == (void*)0x1234);
|
||||
MOZ_ASSERT(cx->realm() == args.callee().as<JSFunction>().realm());
|
||||
|
||||
/* Just return args.length(). */
|
||||
args.rval().setInt32(args.length());
|
||||
@ -7854,8 +7886,8 @@ static const JSJitInfo dom_x_getterinfo = {
|
||||
{ (JSJitGetterOp)dom_get_x },
|
||||
{ 0 }, /* protoID */
|
||||
{ 0 }, /* depth */
|
||||
JSJitInfo::AliasNone, /* aliasSet */
|
||||
JSJitInfo::Getter,
|
||||
JSJitInfo::AliasNone, /* aliasSet */
|
||||
JSVAL_TYPE_UNKNOWN, /* returnType */
|
||||
true, /* isInfallible. False in setters. */
|
||||
true, /* isMovable */
|
||||
@ -7882,6 +7914,41 @@ static const JSJitInfo dom_x_setterinfo = {
|
||||
0 /* slotIndex */
|
||||
};
|
||||
|
||||
// Note: this getter uses AliasEverything and is marked as fallible and
|
||||
// non-movable (1) to prevent Ion from getting too clever optimizing it and
|
||||
// (2) it's nice to have a few different kinds of getters in the shell.
|
||||
static const JSJitInfo dom_global_getterinfo = {
|
||||
{ (JSJitGetterOp)dom_get_global },
|
||||
{ 0 }, /* protoID */
|
||||
{ 0 }, /* depth */
|
||||
JSJitInfo::Getter,
|
||||
JSJitInfo::AliasEverything, /* aliasSet */
|
||||
JSVAL_TYPE_OBJECT, /* returnType */
|
||||
false, /* isInfallible. False in setters. */
|
||||
false, /* isMovable */
|
||||
false, /* isEliminatable */
|
||||
false, /* isAlwaysInSlot */
|
||||
false, /* isLazilyCachedInSlot */
|
||||
false, /* isTypedMethod */
|
||||
0 /* slotIndex */
|
||||
};
|
||||
|
||||
static const JSJitInfo dom_global_setterinfo = {
|
||||
{ (JSJitGetterOp)dom_set_global },
|
||||
{ 0 }, /* protoID */
|
||||
{ 0 }, /* depth */
|
||||
JSJitInfo::Setter,
|
||||
JSJitInfo::AliasEverything, /* aliasSet */
|
||||
JSVAL_TYPE_UNKNOWN, /* returnType */
|
||||
false, /* isInfallible. False in setters. */
|
||||
false, /* isMovable. */
|
||||
false, /* isEliminatable. */
|
||||
false, /* isAlwaysInSlot */
|
||||
false, /* isLazilyCachedInSlot */
|
||||
false, /* isTypedMethod */
|
||||
0 /* slotIndex */
|
||||
};
|
||||
|
||||
static const JSJitInfo doFoo_methodinfo = {
|
||||
{ (JSJitGetterOp)dom_doFoo },
|
||||
{ 0 }, /* protoID */
|
||||
@ -7906,6 +7973,13 @@ static const JSPropertySpec dom_props[] = {
|
||||
{ { dom_genericSetter, &dom_x_setterinfo } }
|
||||
} },
|
||||
},
|
||||
{"global",
|
||||
JSPROP_ENUMERATE,
|
||||
{ {
|
||||
{ { dom_genericGetter, &dom_global_getterinfo } },
|
||||
{ { dom_genericSetter, &dom_global_setterinfo } }
|
||||
} },
|
||||
},
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
namespace js {
|
||||
|
||||
/**
|
||||
* [SMDOC] ExclusiveData API
|
||||
*
|
||||
* A mutual exclusion lock class.
|
||||
*
|
||||
* `ExclusiveData` provides an RAII guard to automatically lock and unlock when
|
||||
|
@ -119,36 +119,6 @@ js::InflateString(JSContext* cx, const char* bytes, size_t length)
|
||||
return chars;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
bool
|
||||
js::DeflateStringToBuffer(JSContext* maybecx, const CharT* src, size_t srclen,
|
||||
char* dst, size_t* dstlenp)
|
||||
{
|
||||
size_t dstlen = *dstlenp;
|
||||
if (srclen > dstlen) {
|
||||
for (size_t i = 0; i < dstlen; i++)
|
||||
dst[i] = char(src[i]);
|
||||
if (maybecx) {
|
||||
AutoSuppressGC suppress(maybecx);
|
||||
JS_ReportErrorNumberASCII(maybecx, GetErrorMessage, nullptr,
|
||||
JSMSG_BUFFER_TOO_SMALL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < srclen; i++)
|
||||
dst[i] = char(src[i]);
|
||||
*dstlenp = srclen;
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool
|
||||
js::DeflateStringToBuffer(JSContext* maybecx, const Latin1Char* src, size_t srclen,
|
||||
char* dst, size_t* dstlenp);
|
||||
|
||||
template bool
|
||||
js::DeflateStringToBuffer(JSContext* maybecx, const char16_t* src, size_t srclen,
|
||||
char* dst, size_t* dstlenp);
|
||||
|
||||
/*
|
||||
* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
|
||||
* least 4 bytes long. Return the number of UTF-8 bytes of data written.
|
||||
|
@ -152,17 +152,6 @@ CopyAndInflateChars(char16_t* dst, const JS::Latin1Char* src, size_t srclen)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
|
||||
* 'length chars. The buffer is NOT null-terminated. The destination length
|
||||
* must to be initialized with the buffer size and will contain on return the
|
||||
* number of copied bytes.
|
||||
*/
|
||||
template <typename CharT>
|
||||
extern bool
|
||||
DeflateStringToBuffer(JSContext* maybecx, const CharT* chars,
|
||||
size_t charsLength, char* bytes, size_t* length);
|
||||
|
||||
/*
|
||||
* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
|
||||
* least 4 bytes long. Return the number of UTF-8 bytes of data written.
|
||||
|
@ -98,6 +98,8 @@ struct ArgumentsData
|
||||
static const unsigned ARGS_LENGTH_MAX = 500 * 1000;
|
||||
|
||||
/*
|
||||
* [SMDOC] ArgumentsObject
|
||||
*
|
||||
* ArgumentsObject instances represent |arguments| objects created to store
|
||||
* function arguments when a function is called. It's expensive to create such
|
||||
* objects if they're never used, so they're only created when they are
|
||||
|
@ -592,6 +592,8 @@ ArrayBufferObject::changeContents(JSContext* cx, BufferContents newContents,
|
||||
}
|
||||
|
||||
/*
|
||||
* [SMDOC] WASM Linear Memory structure
|
||||
*
|
||||
* Wasm Raw Buf Linear Memory Structure
|
||||
*
|
||||
* The linear heap in Wasm is an mmaped array buffer. Several
|
||||
|
@ -35,7 +35,7 @@ FOR_EACH_OPCODE(ENUMERATE_OPCODE)
|
||||
} JSOp;
|
||||
|
||||
/*
|
||||
* JS bytecode formats.
|
||||
* [SMDOC] Bytecode Format flags (JOF_*)
|
||||
*/
|
||||
enum {
|
||||
JOF_BYTE = 0, /* single bytecode, no immediates */
|
||||
|
@ -45,6 +45,8 @@ EnvironmentCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
|
||||
/*** Environment objects *****************************************************/
|
||||
|
||||
/*
|
||||
* [SMDOC] Environment Objects
|
||||
*
|
||||
* About environments
|
||||
* ------------------
|
||||
*
|
||||
|
@ -49,6 +49,8 @@ bool SetImmutablePrototype(JSContext* cx, JS::HandleObject obj, bool* succeeded)
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* [SMDOC] JSObject layout
|
||||
*
|
||||
* A JavaScript object.
|
||||
*
|
||||
* This is the base class for all objects exposed to JS script (as well as some
|
||||
|
@ -2332,6 +2332,8 @@ ScriptSource::setSourceMapURL(JSContext* cx, const char16_t* sourceMapURL)
|
||||
}
|
||||
|
||||
/*
|
||||
* [SMDOC] JSScript data layout (shared)
|
||||
*
|
||||
* Shared script data management.
|
||||
*
|
||||
* SharedScriptData::data contains data that can be shared within a
|
||||
@ -2505,6 +2507,8 @@ js::FreeScriptData(JSRuntime* rt)
|
||||
}
|
||||
|
||||
/*
|
||||
* [SMDOC] JSScript data layout (unshared)
|
||||
*
|
||||
* JSScript::data and SharedScriptData::data have complex,
|
||||
* manually-controlled, memory layouts.
|
||||
*
|
||||
|
@ -1194,6 +1194,17 @@ CallAddPropertyHookDense(JSContext* cx, HandleNativeObject obj, uint32_t index,
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a write to the given element on |arr| should fail
|
||||
* because |arr| has a non-writable length, and writing that element would
|
||||
* increase the length of the array.
|
||||
*/
|
||||
static bool
|
||||
WouldDefinePastNonwritableLength(ArrayObject* arr, uint32_t index)
|
||||
{
|
||||
return !arr->lengthIsWritable() && index >= arr->length();
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
UpdateShapeTypeAndValue(JSContext* cx, NativeObject* obj, Shape* shape, jsid id,
|
||||
const Value& value)
|
||||
@ -1621,7 +1632,7 @@ js::NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
// 9.4.2.1 step 3. Don't extend a fixed-length array.
|
||||
uint32_t index;
|
||||
if (IdIsIndex(id, &index)) {
|
||||
if (WouldDefinePastNonwritableLength(obj, index))
|
||||
if (WouldDefinePastNonwritableLength(arr, index))
|
||||
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
|
||||
}
|
||||
} else if (obj->is<TypedArrayObject>()) {
|
||||
@ -1923,7 +1934,7 @@ DefineNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
// 9.4.2.1 step 3. Don't extend a fixed-length array.
|
||||
uint32_t index;
|
||||
if (IdIsIndex(id, &index)) {
|
||||
if (WouldDefinePastNonwritableLength(obj, index))
|
||||
if (WouldDefinePastNonwritableLength(&obj->as<ArrayObject>(), index))
|
||||
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
|
||||
}
|
||||
} else if (obj->is<TypedArrayObject>()) {
|
||||
@ -2647,11 +2658,14 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
|
||||
return result.succeed();
|
||||
}
|
||||
|
||||
return result.failSoft(JSMSG_BAD_INDEX);
|
||||
// A previously existing typed array element can only be out-of-bounds
|
||||
// if the above ToNumber call detached the typed array's buffer.
|
||||
MOZ_ASSERT(obj->as<TypedArrayObject>().hasDetachedBuffer());
|
||||
|
||||
return result.failSoft(JSMSG_TYPED_ARRAY_DETACHED);
|
||||
}
|
||||
|
||||
if (WouldDefinePastNonwritableLength(obj, index))
|
||||
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
|
||||
MOZ_ASSERT(obj->containsDenseElement(index));
|
||||
|
||||
if (!obj->maybeCopyElementsForWrite(cx))
|
||||
return false;
|
||||
@ -2669,9 +2683,8 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
|
||||
* dense or typed array element (i.e. not actually a pointer to a Shape).
|
||||
*/
|
||||
static bool
|
||||
SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue v,
|
||||
HandleValue receiver, HandleNativeObject pobj, Handle<PropertyResult> prop,
|
||||
ObjectOpResult& result)
|
||||
SetExistingProperty(JSContext* cx, HandleId id, HandleValue v, HandleValue receiver,
|
||||
HandleNativeObject pobj, Handle<PropertyResult> prop, ObjectOpResult& result)
|
||||
{
|
||||
// Step 5 for dense elements.
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
@ -2744,7 +2757,7 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle
|
||||
|
||||
if (prop) {
|
||||
// Steps 5-6.
|
||||
return SetExistingProperty(cx, obj, id, v, receiver, pobj, prop, result);
|
||||
return SetExistingProperty(cx, id, v, receiver, pobj, prop, result);
|
||||
}
|
||||
|
||||
// Steps 4.a-b. The check for 'done' on this next line is tricky.
|
||||
|
@ -92,6 +92,8 @@ ArraySetLength(JSContext* cx, Handle<ArrayObject*> obj, HandleId id,
|
||||
unsigned attrs, HandleValue value, ObjectOpResult& result);
|
||||
|
||||
/*
|
||||
* [SMDOC] NativeObject Elements layout
|
||||
*
|
||||
* Elements header used for native objects. The elements component of such objects
|
||||
* offers an efficient representation for all or some of the indexed properties
|
||||
* of the object, using a flat array of Values rather than a shape hierarchy
|
||||
@ -159,6 +161,9 @@ ArraySetLength(JSContext* cx, Handle<ArrayObject*> obj, HandleId id,
|
||||
* of an object does not necessarily visit indexes in the order they were
|
||||
* created.
|
||||
*
|
||||
*
|
||||
* [SMDOC] NativeObject shifted elements optimization
|
||||
*
|
||||
* Shifted elements
|
||||
* ----------------
|
||||
* It's pretty common to use an array as a queue, like this:
|
||||
@ -432,6 +437,8 @@ enum class ShouldUpdateTypes {
|
||||
};
|
||||
|
||||
/*
|
||||
* [SMDOC] NativeObject layout
|
||||
*
|
||||
* NativeObject specifies the internal implementation of a native object.
|
||||
*
|
||||
* Native objects use ShapedObject::shape to record property information. Two
|
||||
|
@ -65,7 +65,7 @@ enum NewObjectKind {
|
||||
};
|
||||
|
||||
/*
|
||||
* Lazy object groups overview.
|
||||
* [SMDOC] Type-Inference lazy ObjectGroup
|
||||
*
|
||||
* Object groups which represent at most one JS object are constructed lazily.
|
||||
* These include groups for native functions, standard classes, scripted
|
||||
@ -109,6 +109,8 @@ class ObjectGroup : public gc::TenuredCell
|
||||
void* addendum_ = nullptr;
|
||||
|
||||
/*
|
||||
* [SMDOC] Type-Inference object properties
|
||||
*
|
||||
* Properties of this object.
|
||||
*
|
||||
* The type sets in the properties of a group describe the possible values
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* [SMDOC] Bytecode Definitions
|
||||
*
|
||||
* JavaScript operation bytecodes. Add a new bytecode by claiming one of the
|
||||
* JSOP_UNUSED* here or by extracting the first unused opcode from
|
||||
* FOR_EACH_TRAILING_UNUSED_OPCODE and updating js::detail::LastDefinedOpcode
|
||||
|
@ -223,9 +223,8 @@ Sprinter::putString(JSString* s)
|
||||
InvariantChecker ic(this);
|
||||
|
||||
size_t length = s->length();
|
||||
size_t size = length;
|
||||
|
||||
char* buffer = reserve(size);
|
||||
char* buffer = reserve(length);
|
||||
if (!buffer)
|
||||
return false;
|
||||
|
||||
@ -234,12 +233,15 @@ Sprinter::putString(JSString* s)
|
||||
return false;
|
||||
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (linear->hasLatin1Chars())
|
||||
if (linear->hasLatin1Chars()) {
|
||||
PodCopy(reinterpret_cast<Latin1Char*>(buffer), linear->latin1Chars(nogc), length);
|
||||
else
|
||||
DeflateStringToBuffer(nullptr, linear->twoByteChars(nogc), length, buffer, &size);
|
||||
} else {
|
||||
const char16_t* src = linear->twoByteChars(nogc);
|
||||
for (size_t i = 0; i < length; i++)
|
||||
buffer[i] = char(src[i]);
|
||||
}
|
||||
|
||||
buffer[size] = 0;
|
||||
buffer[length] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -119,6 +119,8 @@ class NewProxyCache
|
||||
}
|
||||
};
|
||||
|
||||
// [SMDOC] Object MetadataBuilder API
|
||||
//
|
||||
// We must ensure that all newly allocated JSObjects get their metadata
|
||||
// set. However, metadata builders may require the new object be in a sane
|
||||
// state (eg, have its reserved slots initialized so they can get the
|
||||
|
@ -107,7 +107,7 @@ class Simulator;
|
||||
#endif
|
||||
} // namespace jit
|
||||
|
||||
// JS Engine Threading
|
||||
// [SMDOC] JS Engine Threading
|
||||
//
|
||||
// Threads interacting with a runtime are divided into two categories:
|
||||
//
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "vm/SymbolType.h"
|
||||
|
||||
/*
|
||||
* [SMDOC] Shapes
|
||||
*
|
||||
* In isolation, a Shape represents a property that exists in one or more
|
||||
* objects; it has an id, flags, etc. (But it doesn't represent the property's
|
||||
* value.) However, Shapes are always stored in linked linear sequence of
|
||||
|
@ -69,7 +69,7 @@ class DebugFrame;
|
||||
class Instance;
|
||||
}
|
||||
|
||||
// VM stack layout
|
||||
// [SMDOC] VM stack layout
|
||||
//
|
||||
// A JSRuntime's stack consists of a linked list of activations. Every activation
|
||||
// contains a number of scripted frames that are either running in the interpreter
|
||||
|
@ -44,7 +44,7 @@ static const size_t UINT32_CHAR_BUFFER_LENGTH = sizeof("4294967295") - 1;
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* JavaScript strings
|
||||
* [SMDOC] JavaScript Strings
|
||||
*
|
||||
* Conceptually, a JS string is just an array of chars and a length. This array
|
||||
* of chars may or may not be null-terminated and, if it is, the null character
|
||||
|
@ -122,6 +122,8 @@ struct HashSymbolsByDescription
|
||||
};
|
||||
|
||||
/*
|
||||
* [SMDOC] Symbol.for() registry (ES6 GlobalSymbolRegistry)
|
||||
*
|
||||
* The runtime-wide symbol registry, used to implement Symbol.for().
|
||||
*
|
||||
* ES6 draft rev 25 (2014 May 22) calls this the GlobalSymbolRegistry List. In
|
||||
|
@ -213,6 +213,8 @@ class HeapTypeSet;
|
||||
class TemporaryTypeSet;
|
||||
|
||||
/*
|
||||
* [SMDOC] Type-Inference TypeSet
|
||||
*
|
||||
* Information about the set of types associated with an lvalue. There are
|
||||
* three kinds of type sets:
|
||||
*
|
||||
|
@ -16,7 +16,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* WebAssembly baseline compiler ("RabaldrMonkey")
|
||||
/*
|
||||
* [SMDOC] WebAssembly baseline compiler (RabaldrMonkey)
|
||||
*
|
||||
* General assumptions for 32-bit vs 64-bit code:
|
||||
*
|
||||
|
@ -1656,15 +1656,19 @@ WasmTokenStream::next()
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
if (consume(u"memory.")) {
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
if (consume(u"copy"))
|
||||
return WasmToken(WasmToken::MemCopy, begin, cur_);
|
||||
if (consume(u"fill"))
|
||||
return WasmToken(WasmToken::MemFill, begin, cur_);
|
||||
#endif
|
||||
if (consume(u"grow"))
|
||||
return WasmToken(WasmToken::GrowMemory, begin, cur_);
|
||||
if (consume(u"size"))
|
||||
return WasmToken(WasmToken::CurrentMemory, begin, cur_);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (consume(u"module"))
|
||||
return WasmToken(WasmToken::Module, begin, cur_);
|
||||
if (consume(u"memory"))
|
||||
|
@ -176,6 +176,8 @@
|
||||
#include "nsLayoutStylesheetCache.h"
|
||||
#include "mozilla/layers/InputAPZContext.h"
|
||||
#include "mozilla/layers/FocusTarget.h"
|
||||
#include "mozilla/layers/WebRenderLayerManager.h"
|
||||
#include "mozilla/layers/WebRenderUserData.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
#include "mozilla/ServoStyleSet.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
@ -6319,7 +6321,15 @@ PresShell::Paint(nsView* aViewToPaint,
|
||||
}
|
||||
|
||||
if (layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
|
||||
// TODO: bug 1405465 - create a WR display list which simulates the color layer below.
|
||||
nsPresContext* pc = GetPresContext();
|
||||
LayoutDeviceRect bounds =
|
||||
LayoutDeviceRect::FromAppUnits(pc->GetVisibleArea(), pc->AppUnitsPerDevPixel());
|
||||
bgcolor = NS_ComposeColors(bgcolor, mCanvasBackgroundColor);
|
||||
WebRenderBackgroundData data(wr::ToLayoutRect(bounds), wr::ToColorF(ToDeviceColor(bgcolor)));
|
||||
nsTArray<wr::WrFilterOp> wrFilters;
|
||||
|
||||
MaybeSetupTransactionIdAllocator(layerManager, presContext);
|
||||
layerManager->AsWebRenderLayerManager()->EndTransactionWithoutLayer(nullptr, nullptr, wrFilters, &data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1916,6 +1916,11 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat
|
||||
CreateGeneratedContent(aState, aParentContent, pseudoComputedStyle,
|
||||
contentIndex);
|
||||
if (content) {
|
||||
// We don't strictly have to set NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE
|
||||
// here; it would get set under AppendChildTo. But AppendChildTo might
|
||||
// think that we're going from not being anonymous to being anonymous and
|
||||
// do some extra work; setting the flag here avoids that.
|
||||
content->SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
|
||||
container->AppendChildTo(content, false);
|
||||
if (content->IsElement()) {
|
||||
// If we created any children elements, Servo needs to traverse them, but
|
||||
|
@ -58,7 +58,7 @@ fuzzy-if(cocoaWidget,1,4) fuzzy-if(d2d,59,342) fuzzy-if(d3d11&&advancedLayers&&!
|
||||
== intersecting-clipping-1-image.html intersecting-clipping-1-refi.html
|
||||
== intersecting-clipping-1-overflow-hidden.html intersecting-clipping-1-ref.html
|
||||
fuzzy-if(Android,5,105) fuzzy-if(d2d,1,20) fuzzy-if(skiaContent,1,300) == intersecting-clipping-1-refi.html intersecting-clipping-1-ref.html
|
||||
fuzzy-if(true,1,33) fuzzy-if(d2d,59,350) fuzzy-if(cocoaWidget,1,332) fuzzy-if(Android,124,440) fuzzy-if(skiaContent,1,135) fuzzy-if(d3d11&&advancedLayers,81,353) == intersecting-clipping-1-refc.html intersecting-clipping-1-ref.html # bug 732535
|
||||
fuzzy-if(true,1,33) fuzzy-if(d2d,59,350) fuzzy-if(cocoaWidget,1,332) fuzzy-if(Android,124,440) fuzzy-if(skiaContent,1,135) fuzzy-if(d3d11&&advancedLayers,81,353) skip-if(winWidget) == intersecting-clipping-1-refc.html intersecting-clipping-1-ref.html # bug 732535 # Disable on Windows bug 1451808
|
||||
|
||||
# Inheritance
|
||||
== inherit-1.html inherit-1-ref.html # border-radius shouldn't inherit
|
||||
|
@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
|
||||
|
||||
The cubeb-pulse-rs git repository is: https://github.com/djg/cubeb-pulse-rs.git
|
||||
|
||||
The git commit ID used was f90aecf00ed6e5c67f593b3ecf412a8f3ffc0b1f (2018-04-18 08:06:35 +1000)
|
||||
The git commit ID used was d0bdf51ebd0a653cc4276d2346db852a3060ade0 (2018-06-29 10:09:52 +1000)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user