Merge inbound to mozilla-central. a=merge

This commit is contained in:
Margareta Eliza Balazs 2018-06-29 12:41:54 +03:00
Родитель 9786adccaf 8ac43f77d0
Коммит ee85ffa45d
120 изменённых файлов: 1056 добавлений и 499 удалений

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

@ -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)

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