зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland a=merge on a CLOSED TREE
This commit is contained in:
Коммит
47323ec73b
|
@ -76,17 +76,17 @@
|
|||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=506389"
|
||||
title="Some same page links do not fire EVENT_SYSTEM_SCROLLINGSTART">
|
||||
Mozilla Bug 506389
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=437607"
|
||||
title="Clicking the 'Skip to main content' link once works, second time fails to initiate a V cursor jump">
|
||||
Mozilla Bug 437607
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=519303"
|
||||
title="Same page links to targets with content fires scrolling start accessible event on leaf text node">
|
||||
Mozilla Bug 519303
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=410765"
|
||||
title="nsIAccessible actions testing">
|
||||
Mozilla Bug 410765
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=477975"
|
||||
title="nsIAccessible actions testing">
|
||||
Mozilla Bug 477975
|
||||
|
|
|
@ -63,17 +63,17 @@
|
|||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=523789"
|
||||
title="nsHTMLLiAccessible shouldn't be inherited from linkable accessible">
|
||||
Mozilla Bug 523789
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=423409"
|
||||
title="Expose click action if mouseup and mousedown are registered">
|
||||
Mozilla Bug 423409
|
||||
</a>
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=659620"
|
||||
title="hang when trying to edit a page on wikimo with NVDA running">
|
||||
Mozilla Bug 659620
|
||||
|
|
|
@ -92,12 +92,12 @@
|
|||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=410765"
|
||||
title="nsIAccessible actions testing">
|
||||
Mozilla Bug 410765
|
||||
</a>
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=504252"
|
||||
title="Expose STATE_HASPOPUP on XUL elements that have an @popup attribute">
|
||||
Mozilla Bug 504252
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=381599"
|
||||
title="Inverse relations cache">
|
||||
Mozilla Bug 381599
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=672092"
|
||||
title="Reorganize access key and keyboard shortcut handling code">
|
||||
Mozilla Bug 672092
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=423409"
|
||||
title="Expose click action if mouseup and mousedown are registered">
|
||||
Mozilla Bug 423409
|
||||
|
@ -126,7 +126,7 @@
|
|||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<a href="about:mozilla" id="link1" target="_blank">
|
||||
<a href="about:mozilla" id="link1" target="_blank" rel="opener">
|
||||
<img src="../moz.png" id="img1">
|
||||
</a>
|
||||
<a id="link2" onmousedown="">
|
||||
|
|
|
@ -116,7 +116,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
title="Expose HTML5 video and audio elements' embedded controls through accessibility APIs"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=483573">Mozilla Bug 483573</a>
|
||||
<p id="display"></p>
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
|
||||
title="Rework accessible focus handling">
|
||||
Mozilla Bug 673958
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
|
||||
title="Reorganize implementation of XUL tree accessibility">
|
||||
Mozilla Bug 503727
|
||||
|
|
|
@ -165,7 +165,7 @@
|
|||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
<a target="_blank" rel="opener"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
|
||||
title="Reorganize implementation of XUL tree accessibility">
|
||||
Mozilla Bug 503727
|
||||
|
|
|
@ -559,17 +559,13 @@ html|input.urlbar-input:-moz-locale-dir(rtl) {
|
|||
direction: ltr !important;
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
/* Make sure that the location bar's alignment in RTL mode changes according
|
||||
to the input box direction if the user switches the text direction using
|
||||
cmd_switchTextDirection (which applies a dir attribute to the <input>). */
|
||||
html|input.urlbar-input[dir=ltr]:-moz-locale-dir(rtl) {
|
||||
text-align: left !important;
|
||||
}
|
||||
/* Show placeholder text in URL bar using correct direction */
|
||||
html|input.urlbar-input:-moz-locale-dir(rtl):placeholder-shown {
|
||||
direction: rtl !important;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display visual cue that browser is under remote control by Marionette.
|
||||
|
|
|
@ -11,7 +11,7 @@ requestLongerTimeout(2);
|
|||
|
||||
function frame_script() {
|
||||
content.document.body.innerHTML = `
|
||||
<a href="http://example.com/" target="_blank" id="testAnchor">Open a window</a>
|
||||
<a href="http://example.com/" target="_blank" rel="opener" id="testAnchor">Open a window</a>
|
||||
`;
|
||||
|
||||
let element = content.document.getElementById("testAnchor");
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<li>
|
||||
<a id="test-create-new-tab-from-targetblank-click"
|
||||
href="webNav_createdTarget.html#new-tab-from-targetblank-click"
|
||||
target="_blank">
|
||||
target="_blank" rel="opener">
|
||||
Open a target page in a new tab from click to link with target="_blank"
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<li>
|
||||
<a id="test-create-new-tab-from-targetblank-click-subframe"
|
||||
href="webNav_createdTarget.html#new-tab-from-targetblank-click-subframe"
|
||||
target="_blank">
|
||||
target="_blank" rel="opener">
|
||||
Open a target page in a new tab from click to link with target="_blank"
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -113,7 +113,6 @@ included_inclnames_to_ignore = set([
|
|||
# ignore #includes of them when checking #include ordering.
|
||||
oddly_ordered_inclnames = set([
|
||||
'ctypes/typedefs.h', # Included multiple times in the body of ctypes/CTypes.h
|
||||
'frontend/BinSource-auto.h', # Included in the body of frontend/BinSource.h
|
||||
# Included in the body of frontend/TokenStream.h
|
||||
'frontend/ReservedWordsGenerated.h',
|
||||
'gc/StatsPhasesGenerated.h', # Included in the body of gc/Statistics.h
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 103
|
||||
Version 104
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-102...release-103
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-103...release-104
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||
|
|
|
@ -2286,16 +2286,6 @@ menuseparator {
|
|||
background: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.source-footer .commands .coverage {
|
||||
color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.coverage-on .source-footer .commands .coverage {
|
||||
color: var(--theme-highlight-blue);
|
||||
border: 1px solid var(--theme-body-color-inactive);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.source-footer > .commands > .blackboxed > img.blackBox {
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
@ -2872,11 +2862,6 @@ html[dir="rtl"] .editor-mount {
|
|||
background: var(--theme-selection-background-hover);
|
||||
}
|
||||
|
||||
.coverage-on .CodeMirror-code :not(.hit-marker) .CodeMirror-line,
|
||||
.coverage-on .CodeMirror-code :not(.hit-marker) .CodeMirror-gutter-wrapper {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.editor.new-breakpoint svg {
|
||||
fill: var(--theme-selection-background);
|
||||
width: 60px;
|
||||
|
|
|
@ -15,7 +15,10 @@ import {
|
|||
import { mapFrames, fetchExtra } from "./pause";
|
||||
import { updateTab } from "./tabs";
|
||||
|
||||
import { PROMISE } from "./utils/middleware/promise";
|
||||
|
||||
import { setInScopeLines } from "./ast/setInScopeLines";
|
||||
import { updateSymbolLocations } from "./utils/symbols";
|
||||
import {
|
||||
getSymbols,
|
||||
findOutOfScopeLocations,
|
||||
|
@ -24,7 +27,6 @@ import {
|
|||
type AstPosition
|
||||
} from "../workers/parser";
|
||||
|
||||
import { PROMISE } from "./utils/middleware/promise";
|
||||
import { features } from "../utils/prefs";
|
||||
import { isLoaded, isGenerated } from "../utils/source";
|
||||
|
||||
|
@ -56,7 +58,7 @@ export function setSourceMetaData(sourceId: SourceId) {
|
|||
}
|
||||
|
||||
export function setSymbols(sourceId: SourceId) {
|
||||
return async ({ dispatch, getState }: ThunkArgs) => {
|
||||
return async ({ dispatch, getState, sourceMaps }: ThunkArgs) => {
|
||||
const source = getSourceFromId(getState(), sourceId);
|
||||
|
||||
if (source.isWasm || hasSymbols(getState(), source) || !isLoaded(source)) {
|
||||
|
@ -66,7 +68,15 @@ export function setSymbols(sourceId: SourceId) {
|
|||
await dispatch({
|
||||
type: "SET_SYMBOLS",
|
||||
sourceId,
|
||||
[PROMISE]: getSymbols(sourceId)
|
||||
[PROMISE]: (async function() {
|
||||
const symbols = await getSymbols(sourceId);
|
||||
const mappedSymbols = updateSymbolLocations(
|
||||
symbols,
|
||||
source,
|
||||
sourceMaps
|
||||
);
|
||||
return mappedSymbols;
|
||||
})()
|
||||
});
|
||||
|
||||
if (isPaused(getState())) {
|
||||
|
|
|
@ -45,7 +45,7 @@ async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
|
|||
return { breakpoint: newBreakpoint };
|
||||
}
|
||||
|
||||
const { id, hitCount, actualLocation } = await client.setBreakpoint(
|
||||
const { id, actualLocation } = await client.setBreakpoint(
|
||||
generatedLocation,
|
||||
breakpoint.condition,
|
||||
isOriginalId(location.sourceId)
|
||||
|
@ -70,7 +70,6 @@ async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
|
|||
condition: breakpoint.condition,
|
||||
location: newLocation,
|
||||
astLocation,
|
||||
hitCount,
|
||||
generatedLocation: newGeneratedLocation,
|
||||
text,
|
||||
originalText
|
||||
|
|
|
@ -12,7 +12,6 @@ import * as navigation from "./navigation";
|
|||
import * as ui from "./ui";
|
||||
import * as fileSearch from "./file-search";
|
||||
import * as ast from "./ast";
|
||||
import * as coverage from "./coverage";
|
||||
import * as projectTextSearch from "./project-text-search";
|
||||
import * as quickOpen from "./quick-open";
|
||||
import * as sourceTree from "./source-tree";
|
||||
|
@ -33,7 +32,6 @@ export default {
|
|||
...ui,
|
||||
...fileSearch,
|
||||
...ast,
|
||||
...coverage,
|
||||
...projectTextSearch,
|
||||
...quickOpen,
|
||||
...sourceTree,
|
||||
|
|
|
@ -13,7 +13,6 @@ DIRS += [
|
|||
|
||||
DebuggerModules(
|
||||
'ast.js',
|
||||
'coverage.js',
|
||||
'debuggee.js',
|
||||
'event-listeners.js',
|
||||
'expressions.js',
|
||||
|
|
|
@ -83,12 +83,18 @@ function loadSourceMap(sourceId: SourceId) {
|
|||
}
|
||||
|
||||
if (!urls) {
|
||||
// The source might have changed while we looked up the URLs, so we need
|
||||
// to load it again before dispatching. We ran into an issue here because
|
||||
// this was previously using 'source' and was at risk of resetting the
|
||||
// 'loadedState' field to 'loading', putting it in an inconsistent state.
|
||||
const currentSource = getSource(getState(), sourceId);
|
||||
|
||||
// If this source doesn't have a sourcemap, enable it for pretty printing
|
||||
dispatch(
|
||||
({
|
||||
type: "UPDATE_SOURCE",
|
||||
// NOTE: Flow https://github.com/facebook/flow/issues/6342 issue
|
||||
source: (({ ...source, sourceMapURL: "" }: any): Source)
|
||||
source: (({ ...currentSource, sourceMapURL: "" }: any): Source)
|
||||
}: Action)
|
||||
);
|
||||
return;
|
||||
|
|
|
@ -9,4 +9,5 @@ DIRS += [
|
|||
|
||||
DebuggerModules(
|
||||
'create-store.js',
|
||||
'symbols.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* 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/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import {
|
||||
type SymbolDeclaration,
|
||||
type SymbolDeclarations
|
||||
} from "../../workers/parser";
|
||||
|
||||
import type { Source } from "../../types";
|
||||
|
||||
function updateSymbolLocation(
|
||||
site: SymbolDeclaration,
|
||||
source: Source,
|
||||
sourceMaps: any
|
||||
) {
|
||||
return sourceMaps
|
||||
.getGeneratedLocation(
|
||||
{ ...site.location.start, sourceId: source.id },
|
||||
source
|
||||
)
|
||||
.then(loc => {
|
||||
return {
|
||||
...site,
|
||||
generatedLocation: { line: loc.line, column: loc.column }
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateSymbolLocations(
|
||||
symbols: SymbolDeclarations,
|
||||
source: Source,
|
||||
sourceMaps: any
|
||||
): Promise<SymbolDeclarations> {
|
||||
if (!symbols || !symbols.callExpressions) {
|
||||
return Promise.resolve(symbols);
|
||||
}
|
||||
|
||||
const mappedCallExpressions = await Promise.all(
|
||||
symbols.callExpressions.map(site =>
|
||||
updateSymbolLocation(site, source, sourceMaps)
|
||||
)
|
||||
);
|
||||
|
||||
const newSymbols = { ...symbols, callExpressions: mappedCallExpressions };
|
||||
|
||||
return Promise.resolve(newSymbols);
|
||||
}
|
|
@ -242,6 +242,15 @@ class App extends Component<Props, State> {
|
|||
}));
|
||||
}
|
||||
|
||||
// Important so that the tabs chevron updates appropriately when
|
||||
// the user resizes the left or right columns
|
||||
triggerEditorPaneResize() {
|
||||
const editorPane = window.document.querySelector(".editor-pane");
|
||||
if (editorPane) {
|
||||
editorPane.dispatchEvent(new Event("resizeend"));
|
||||
}
|
||||
}
|
||||
|
||||
renderLayout = () => {
|
||||
const { startPanelCollapsed, endPanelCollapsed } = this.props;
|
||||
const horizontal = this.isHorizontal();
|
||||
|
@ -282,6 +291,7 @@ class App extends Component<Props, State> {
|
|||
/>
|
||||
}
|
||||
endPanelCollapsed={endPanelCollapsed}
|
||||
onResizeEnd={this.triggerEditorPaneResize}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { range, keyBy, isEqualWith } from "lodash";
|
||||
import { range, keyBy, isEqualWith, uniqBy, groupBy, flatten } from "lodash";
|
||||
|
||||
import CallSite from "./CallSite";
|
||||
|
||||
|
@ -121,23 +121,43 @@ class CallSites extends Component {
|
|||
filterCallSitesByLineNumber() {
|
||||
const { callSites, breakpoints } = this.props;
|
||||
|
||||
const breakpointLines = new Set(breakpoints.map(bp => bp.location.line));
|
||||
// Get unique lines from breakpoints so we can filter out unwated call sites
|
||||
const uniqueBreakpointLines = new Set(
|
||||
breakpoints.map(bp => bp.location.line)
|
||||
);
|
||||
|
||||
return callSites.filter(({ location }) =>
|
||||
breakpointLines.has(location.start.line)
|
||||
// Get call sites based on activated breakpoint lines
|
||||
const callSitesInRange = callSites.filter(({ location }) =>
|
||||
uniqueBreakpointLines.has(location.start.line)
|
||||
);
|
||||
|
||||
// Group call sites by line
|
||||
const callSitesByLineObj = groupBy(callSitesInRange, "location.start.line");
|
||||
|
||||
// Per group, ensure all call sites are unique
|
||||
return flatten(
|
||||
Object.values(callSitesByLineObj).map(arr => {
|
||||
const uniques = uniqBy(
|
||||
arr,
|
||||
site =>
|
||||
`${site.generatedLocation.line}:${site.generatedLocation.column}`
|
||||
);
|
||||
// Only return call sites for a line when more than 1 is found
|
||||
return uniques.length > 1 ? uniques : [];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { editor, callSites, selectedSource } = this.props;
|
||||
const { editor, callSites, selectedSource, breakpoints } = this.props;
|
||||
|
||||
let sites;
|
||||
if (!callSites || (selectedSource && selectedSource.isPrettyPrinted)) {
|
||||
if (!callSites || breakpoints.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const callSitesFiltered = this.filterCallSitesByLineNumber();
|
||||
|
||||
let sites;
|
||||
editor.codeMirror.operation(() => {
|
||||
const childCallSites = callSitesFiltered.map((callSite, index) => {
|
||||
const props = {
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
getPaneCollapse
|
||||
} from "../../selectors";
|
||||
|
||||
import { features } from "../../utils/prefs";
|
||||
import {
|
||||
isPretty,
|
||||
isLoaded,
|
||||
|
@ -39,7 +38,6 @@ type Props = {
|
|||
togglePrettyPrint: string => void,
|
||||
toggleBlackBox: Object => void,
|
||||
jumpToMappedLocation: (Source: any) => void,
|
||||
recordCoverage: () => void,
|
||||
togglePaneCollapse: () => void
|
||||
};
|
||||
|
||||
|
@ -122,25 +120,6 @@ class SourceFooter extends PureComponent<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
coverageButton() {
|
||||
const { recordCoverage } = this.props;
|
||||
|
||||
if (!features.codeCoverage) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
className="coverage action"
|
||||
title={L10N.getStr("sourceFooter.codeCoverage")}
|
||||
onClick={() => recordCoverage()}
|
||||
aria-label={L10N.getStr("sourceFooter.codeCoverage")}
|
||||
>
|
||||
C
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
renderToggleButton() {
|
||||
if (this.props.horizontal) {
|
||||
return;
|
||||
|
@ -162,7 +141,6 @@ class SourceFooter extends PureComponent<Props> {
|
|||
{this.prettyPrintButton()}
|
||||
{this.blackBoxButton()}
|
||||
{this.blackBoxSummary()}
|
||||
{this.coverageButton()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -231,7 +209,6 @@ export default connect(
|
|||
togglePrettyPrint: actions.togglePrettyPrint,
|
||||
toggleBlackBox: actions.toggleBlackBox,
|
||||
jumpToMappedLocation: actions.jumpToMappedLocation,
|
||||
recordCoverage: actions.recordCoverage,
|
||||
togglePaneCollapse: actions.togglePaneCollapse
|
||||
}
|
||||
)(SourceFooter);
|
||||
|
|
|
@ -76,10 +76,12 @@ class Tabs extends PureComponent<Props, State> {
|
|||
componentDidMount() {
|
||||
window.requestIdleCallback(this.updateHiddenTabs);
|
||||
window.addEventListener("resize", this.onResize);
|
||||
window.document.querySelector(".editor-pane").addEventListener("resizeend", this.onResize);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("resize", this.onResize);
|
||||
window.document.querySelector(".editor-pane").removeEventListener("resizeend", this.onResize);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -18,8 +18,6 @@ import {
|
|||
getActiveSearch,
|
||||
getSelectedLocation,
|
||||
getSelectedSource,
|
||||
getHitCountForSource,
|
||||
getCoverageEnabled,
|
||||
getConditionalPanelLine,
|
||||
getSymbols
|
||||
} from "../../selectors";
|
||||
|
@ -32,7 +30,6 @@ import SearchBar from "./SearchBar";
|
|||
import HighlightLines from "./HighlightLines";
|
||||
import Preview from "./Preview";
|
||||
import Breakpoints from "./Breakpoints";
|
||||
import HitMarker from "./HitMarker";
|
||||
import CallSites from "./CallSites";
|
||||
import DebugLine from "./DebugLine";
|
||||
import HighlightLine from "./HighlightLine";
|
||||
|
@ -76,11 +73,9 @@ const cssVars = {
|
|||
};
|
||||
|
||||
export type Props = {
|
||||
hitCount: Object,
|
||||
selectedLocation: ?Location,
|
||||
selectedSource: ?Source,
|
||||
searchOn: boolean,
|
||||
coverageOn: boolean,
|
||||
horizontal: boolean,
|
||||
startPanelSize: number,
|
||||
endPanelSize: number,
|
||||
|
@ -533,29 +528,6 @@ class Editor extends PureComponent<Props, State> {
|
|||
};
|
||||
}
|
||||
|
||||
renderHitCounts() {
|
||||
const { hitCount, selectedSource } = this.props;
|
||||
|
||||
if (
|
||||
!selectedSource ||
|
||||
!isLoaded(selectedSource) ||
|
||||
!hitCount ||
|
||||
!this.state.editor
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
return hitCount
|
||||
.filter(marker => marker.get("count") > 0)
|
||||
.map(marker => (
|
||||
<HitMarker
|
||||
key={marker.get("line")}
|
||||
hitData={marker.toJS()}
|
||||
editor={this.state.editor.codeMirror}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
renderItems() {
|
||||
const { horizontal, selectedSource } = this.props;
|
||||
const { editor } = this.state;
|
||||
|
@ -577,7 +549,6 @@ class Editor extends PureComponent<Props, State> {
|
|||
<GutterMenu editor={editor} />
|
||||
<ConditionalPanel editor={editor} />
|
||||
{features.columnBreakpoints ? <CallSites editor={editor} /> : null}
|
||||
{this.renderHitCounts()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -593,13 +564,9 @@ class Editor extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { coverageOn } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames("editor-wrapper", {
|
||||
"coverage-on": coverageOn
|
||||
})}
|
||||
className={classnames("editor-wrapper")}
|
||||
ref={c => (this.$editorWrapper = c)}
|
||||
>
|
||||
<div
|
||||
|
@ -619,14 +586,11 @@ Editor.contextTypes = {
|
|||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = getSelectedSource(state);
|
||||
const sourceId = selectedSource ? selectedSource.id : "";
|
||||
|
||||
return {
|
||||
selectedLocation: getSelectedLocation(state),
|
||||
selectedSource,
|
||||
searchOn: getActiveSearch(state) === "file",
|
||||
hitCount: getHitCountForSource(state, sourceId),
|
||||
coverageOn: getCoverageEnabled(state),
|
||||
conditionalPanelLine: getConditionalPanelLine(state),
|
||||
symbols: getSymbols(state, selectedSource)
|
||||
};
|
||||
|
|
|
@ -20,7 +20,6 @@ DebuggerModules(
|
|||
'GutterMenu.js',
|
||||
'HighlightLine.js',
|
||||
'HighlightLines.js',
|
||||
'HitMarker.js',
|
||||
'index.js',
|
||||
'SearchBar.js',
|
||||
'Tab.js',
|
||||
|
|
|
@ -35,6 +35,10 @@ export default class OutlineFilter extends Component<Props, State> {
|
|||
// also bound to the ESC key
|
||||
e.preventDefault();
|
||||
this.props.updateFilter("");
|
||||
} else if (e.key === "Enter") {
|
||||
// We must prevent the form submission from taking any action
|
||||
// https://github.com/devtools-html/debugger.html/pull/7308
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ type Props = {
|
|||
removeBreakpoints: typeof actions.removeBreakpoints,
|
||||
removeAllBreakpoints: typeof actions.removeAllBreakpoints,
|
||||
disableBreakpoint: typeof actions.disableBreakpoint,
|
||||
setBreakpointCondition: typeof actions.setBreakpointCondition,
|
||||
toggleAllBreakpoints: typeof actions.toggleAllBreakpoints,
|
||||
toggleBreakpoints: typeof actions.toggleBreakpoints,
|
||||
openConditionalPanel: typeof actions.openConditionalPanel,
|
||||
|
@ -201,6 +202,7 @@ export default connect(
|
|||
disableBreakpoint: actions.disableBreakpoint,
|
||||
selectSpecificLocation: actions.selectSpecificLocation,
|
||||
selectLocation: actions.selectLocation,
|
||||
setBreakpointCondition: actions.setBreakpointCondition,
|
||||
toggleAllBreakpoints: actions.toggleAllBreakpoints,
|
||||
toggleBreakpoints: actions.toggleBreakpoints,
|
||||
openConditionalPanel: actions.openConditionalPanel
|
||||
|
|
|
@ -18,7 +18,6 @@ import pause from "./pause";
|
|||
import ui from "./ui";
|
||||
import fileSearch from "./file-search";
|
||||
import ast from "./ast";
|
||||
import coverage from "./coverage";
|
||||
import projectTextSearch from "./project-text-search";
|
||||
import quickOpen from "./quick-open";
|
||||
import sourceTree from "./source-tree";
|
||||
|
@ -37,7 +36,6 @@ export default {
|
|||
ui,
|
||||
fileSearch,
|
||||
ast,
|
||||
coverage,
|
||||
projectTextSearch,
|
||||
quickOpen,
|
||||
sourceTree,
|
||||
|
|
|
@ -11,7 +11,6 @@ DebuggerModules(
|
|||
'ast.js',
|
||||
'async-requests.js',
|
||||
'breakpoints.js',
|
||||
'coverage.js',
|
||||
'debuggee.js',
|
||||
'event-listeners.js',
|
||||
'expressions.js',
|
||||
|
|
|
@ -431,13 +431,19 @@ function getSourcesByUrlInSources(
|
|||
return urls[url].map(id => sources[id]);
|
||||
}
|
||||
|
||||
export function getSourcesUrlsInSources(state: OuterState, url: string) {
|
||||
export function getSourcesUrlsInSources(
|
||||
state: OuterState,
|
||||
url: string
|
||||
): string[] {
|
||||
const urls = getUrls(state);
|
||||
if (!url || !urls[url]) {
|
||||
return [];
|
||||
}
|
||||
const plainUrl = url.split("?")[0];
|
||||
|
||||
return [...new Set(Object.keys(urls).filter(Boolean))];
|
||||
return Object.keys(urls)
|
||||
.filter(Boolean)
|
||||
.filter(sourceUrl => sourceUrl.split("?")[0] === plainUrl);
|
||||
}
|
||||
|
||||
export function getHasSiblingOfSameName(state: OuterState, source: ?Source) {
|
||||
|
|
|
@ -14,7 +14,6 @@ export * from "../reducers/pending-breakpoints";
|
|||
export * from "../reducers/ui";
|
||||
export * from "../reducers/file-search";
|
||||
export * from "../reducers/ast";
|
||||
export * from "../reducers/coverage";
|
||||
export * from "../reducers/project-text-search";
|
||||
export * from "../reducers/source-tree";
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@ type AnnotatedFrame =
|
|||
| Frame;
|
||||
|
||||
export function annotateFrames(frames: Frame[]): AnnotatedFrame[] {
|
||||
const annotatedFrames = frames.map(annotateFrame);
|
||||
const annotatedFrames = frames.map(f => annotateFrame(f, frames));
|
||||
return annotateBabelAsyncFrames(annotatedFrames);
|
||||
}
|
||||
|
||||
function annotateFrame(frame: Frame): AnnotatedFrame {
|
||||
const library = getLibraryFromUrl(frame);
|
||||
function annotateFrame(frame: Frame, frames: Frame[]): AnnotatedFrame {
|
||||
const library = getLibraryFromUrl(frame, frames);
|
||||
if (library) {
|
||||
return { ...frame, library };
|
||||
}
|
||||
|
|
|
@ -128,9 +128,15 @@ export function getLibraryFromUrl(frame: Frame, callStack: Array<Frame> = []) {
|
|||
o => o.contextPattern && frameUrl.match(o.contextPattern)
|
||||
);
|
||||
if (match) {
|
||||
const contextMatch = callStack.some(f =>
|
||||
libraryMap.find(o => frameUrl.match(o.pattern))
|
||||
);
|
||||
const contextMatch = callStack.some(f => {
|
||||
const url = getFrameUrl(f);
|
||||
if (!url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return libraryMap.some(o => url.match(o.pattern));
|
||||
});
|
||||
|
||||
if (contextMatch) {
|
||||
return match.label;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ if (isDevelopment()) {
|
|||
pref("devtools.debugger.features.root", true);
|
||||
pref("devtools.debugger.features.map-scopes", true);
|
||||
pref("devtools.debugger.features.remove-command-bar-options", true);
|
||||
pref("devtools.debugger.features.code-coverage", false);
|
||||
pref("devtools.debugger.features.event-listeners", false);
|
||||
pref("devtools.debugger.features.code-folding", false);
|
||||
pref("devtools.debugger.features.outline", true);
|
||||
|
@ -105,7 +104,6 @@ export const features = new PrefsHelper("devtools.debugger.features", {
|
|||
mapScopes: ["Bool", "map-scopes"],
|
||||
removeCommandBarOptions: ["Bool", "remove-command-bar-options"],
|
||||
workers: ["Bool", "workers"],
|
||||
codeCoverage: ["Bool", "code-coverage"],
|
||||
eventListeners: ["Bool", "event-listeners"],
|
||||
outline: ["Bool", "outline"],
|
||||
codeFolding: ["Bool", "code-folding"],
|
||||
|
|
|
@ -81,4 +81,13 @@ add_task(async function() {
|
|||
bp = findBreakpoint(dbg, "simple2", 5);
|
||||
is(bp.condition, "1", "breakpoint is created with the condition");
|
||||
assertEditorBreakpoint(dbg, 5, true);
|
||||
|
||||
const bpCondition = waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
|
||||
//right click breakpoint in breakpoints list
|
||||
rightClickElement(dbg, "breakpointItem", 3)
|
||||
// select "remove condition";
|
||||
selectMenuItem(dbg, 8);
|
||||
await bpCondition;
|
||||
bp = findBreakpoint(dbg, "simple2", 5);
|
||||
is(bp.condition, undefined, "breakpoint condition removed");
|
||||
});
|
||||
|
|
|
@ -52,5 +52,5 @@ add_task(async function() {
|
|||
is(getValue(dbg, 4), 2);
|
||||
|
||||
await toggleExpressionNode(dbg, 1);
|
||||
is(findAllElements(dbg, "expressionNodes").length, 20);
|
||||
is(findAllElements(dbg, "expressionNodes").length, 37);
|
||||
});
|
||||
|
|
|
@ -88,7 +88,7 @@ add_task(async function() {
|
|||
await resume(dbg);
|
||||
await addExpression(dbg, "location");
|
||||
|
||||
is(findAllElements(dbg, "expressionNodes").length, 17);
|
||||
is(findAllElements(dbg, "expressionNodes").length, 34);
|
||||
|
||||
await toggleExpressionNode(dbg, 1);
|
||||
is(findAllElements(dbg, "expressionNodes").length, 1);
|
||||
|
|
|
@ -70,6 +70,10 @@ add_task(async function() {
|
|||
pressKey(dbg, "Escape");
|
||||
is(getItems(dbg).length, 9, "9 items in the list after escape pressed");
|
||||
|
||||
// Ensure no action is taken when Enter key is pressed
|
||||
pressKey(dbg, "Enter");
|
||||
is(getItems(dbg).length, 9, "9 items in the list after enter pressed");
|
||||
|
||||
// check that the term 'todo' includes items with todo
|
||||
type(dbg, "todo");
|
||||
is(getItems(dbg).length, 2, "2 items in the list after 'todo' filter");
|
||||
|
|
|
@ -104,51 +104,6 @@ class FlexboxInspector {
|
|||
this.walker = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current selected node is a flex container, check if it is also a flex item of
|
||||
* a parent flex container and get its parent flex container if any and returns an
|
||||
* object that consists of the parent flex container's items and properties.
|
||||
*
|
||||
* @param {NodeFront} containerNodeFront
|
||||
* The current flex container of the selected node.
|
||||
* @return {Object} consiting of the parent flex container's flex items and properties.
|
||||
*/
|
||||
async getAsFlexItem(containerNodeFront) {
|
||||
// If the current selected node is not a flex container, we know it is a flex item.
|
||||
// No need to look for the parent flex container.
|
||||
if (containerNodeFront !== this.selection.nodeFront) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const flexboxFront = await this.layoutInspector.getCurrentFlexbox(
|
||||
this.selection.nodeFront, true);
|
||||
|
||||
if (!flexboxFront) {
|
||||
return null;
|
||||
}
|
||||
|
||||
containerNodeFront = flexboxFront.containerNodeFront;
|
||||
if (!containerNodeFront) {
|
||||
containerNodeFront = await this.walker.getNodeFromActor(flexboxFront.actorID,
|
||||
["containerEl"]);
|
||||
}
|
||||
|
||||
let flexItemContainer = null;
|
||||
if (flexboxFront) {
|
||||
const flexItems = await this.getFlexItems(flexboxFront);
|
||||
flexItemContainer = {
|
||||
actorID: flexboxFront.actorID,
|
||||
flexItems,
|
||||
flexItemShown: this.selection.nodeFront.actorID,
|
||||
isFlexItemContainer: true,
|
||||
nodeFront: containerNodeFront,
|
||||
properties: flexboxFront.properties,
|
||||
};
|
||||
}
|
||||
|
||||
return flexItemContainer;
|
||||
}
|
||||
|
||||
getComponentProps() {
|
||||
return {
|
||||
onSetFlexboxOverlayColor: this.onSetFlexboxOverlayColor,
|
||||
|
@ -172,6 +127,58 @@ class FlexboxInspector {
|
|||
return this._customHostColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flex container properties for a given node. If the given node is a flex
|
||||
* item, it attempts to fetch the flex container of the parent node of the given node.
|
||||
*
|
||||
* @param {NodeFront} nodeFront
|
||||
* The NodeFront to fetch the flex container properties.
|
||||
* @param {Boolean} onlyLookAtParents
|
||||
* Whether or not to only consider the parent node of the given node.
|
||||
* @return {Object} consisting of the given node's flex container's properties.
|
||||
*/
|
||||
async getFlexContainerProps(nodeFront, onlyLookAtParents = false) {
|
||||
const flexboxFront = await this.layoutInspector.getCurrentFlexbox(nodeFront,
|
||||
onlyLookAtParents);
|
||||
|
||||
if (!flexboxFront) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the FlexboxFront doesn't yet have access to the NodeFront for its container,
|
||||
// then get it from the walker. This happens when the walker hasn't seen this
|
||||
// particular DOM Node in the tree yet or when we are connected to an older server.
|
||||
let containerNodeFront = flexboxFront.containerNodeFront;
|
||||
if (!containerNodeFront) {
|
||||
containerNodeFront = await this.walker.getNodeFromActor(flexboxFront.actorID,
|
||||
["containerEl"]);
|
||||
}
|
||||
|
||||
const flexItems = await this.getFlexItems(flexboxFront);
|
||||
|
||||
// If the current selected node is a flex item, display its flex item sizing
|
||||
// properties.
|
||||
let flexItemShown = null;
|
||||
if (onlyLookAtParents) {
|
||||
flexItemShown = this.selection.nodeFront.actorID;
|
||||
} else {
|
||||
const selectedFlexItem = flexItems.find(item =>
|
||||
item.nodeFront === this.selection.nodeFront);
|
||||
if (selectedFlexItem) {
|
||||
flexItemShown = selectedFlexItem.nodeFront.actorID;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
actorID: flexboxFront.actorID,
|
||||
flexItems,
|
||||
flexItemShown,
|
||||
isFlexItemContainer: onlyLookAtParents,
|
||||
nodeFront: containerNodeFront,
|
||||
properties: flexboxFront.properties,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of flex items object for the given flex container front.
|
||||
*
|
||||
|
@ -303,25 +310,36 @@ class FlexboxInspector {
|
|||
}
|
||||
|
||||
try {
|
||||
const flexboxFront = await this.layoutInspector.getCurrentFlexbox(
|
||||
this.selection.nodeFront);
|
||||
const flexContainer = await this.getFlexContainerProps(this.selection.nodeFront);
|
||||
|
||||
// Clear the flexbox panel if there is no flex container for the current node
|
||||
// selection.
|
||||
if (!flexboxFront) {
|
||||
if (!flexContainer) {
|
||||
this.store.dispatch(clearFlexbox());
|
||||
return;
|
||||
}
|
||||
|
||||
const { flexbox } = this.store.getState();
|
||||
|
||||
// Do nothing because the same flex container is still selected.
|
||||
if (flexbox.actorID == flexboxFront.actorID) {
|
||||
// Compare the new flexbox state of the current selected nodeFront with the old
|
||||
// flexbox state to determine if we need to update.
|
||||
if (hasFlexContainerChanged(flexbox.flexContainer, flexContainer)) {
|
||||
this.update(flexContainer);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the flexbox panel with the new flexbox front contents.
|
||||
this.update(flexboxFront);
|
||||
let flexItemContainer = null;
|
||||
// If the current selected node is also the flex container node, check if it is
|
||||
// a flex item of a parent flex container.
|
||||
if (flexContainer.nodeFront === this.selection.nodeFront) {
|
||||
flexItemContainer = await this.getFlexContainerProps(this.selection.nodeFront,
|
||||
true);
|
||||
}
|
||||
|
||||
// Compare the new and old state of the parent flex container properties.
|
||||
if (hasFlexContainerChanged(flexbox.flexItemContainer, flexItemContainer)) {
|
||||
this.update(flexContainer, flexItemContainer);
|
||||
}
|
||||
} catch (e) {
|
||||
// This call might fail if called asynchrously after the toolbox is finished
|
||||
// closing.
|
||||
|
@ -427,10 +445,14 @@ class FlexboxInspector {
|
|||
* the layout view becomes visible or a new node is selected and needs to be update
|
||||
* with new flexbox data.
|
||||
*
|
||||
* @param {FlexboxFront|null} flexboxFront
|
||||
* The FlexboxFront of the flex container for the current node selection.
|
||||
* @param {Object|null} flexContainer
|
||||
* An object consisting of the current flex container's flex items and
|
||||
* properties.
|
||||
* @param {Object|null} flexItemContainer
|
||||
* An object consisting of the parent flex container's flex items and
|
||||
* properties.
|
||||
*/
|
||||
async update(flexboxFront) {
|
||||
async update(flexContainer, flexItemContainer) {
|
||||
// Stop refreshing if the inspector or store is already destroyed or no node is
|
||||
// selected.
|
||||
if (!this.inspector ||
|
||||
|
@ -442,53 +464,35 @@ class FlexboxInspector {
|
|||
|
||||
try {
|
||||
// Fetch the current flexbox if no flexbox front was passed into this update.
|
||||
if (!flexboxFront) {
|
||||
flexboxFront = await this.layoutInspector.getCurrentFlexbox(
|
||||
this.selection.nodeFront);
|
||||
if (!flexContainer) {
|
||||
flexContainer = await this.getFlexContainerProps(this.selection.nodeFront);
|
||||
}
|
||||
|
||||
// Clear the flexbox panel if there is no flex container for the current node
|
||||
// selection.
|
||||
if (!flexboxFront) {
|
||||
if (!flexContainer) {
|
||||
this.store.dispatch(clearFlexbox());
|
||||
return;
|
||||
}
|
||||
|
||||
// If the FlexboxFront doesn't yet have access to the NodeFront for its container,
|
||||
// then get it from the walker. This happens when the walker hasn't seen this
|
||||
// particular DOM Node in the tree yet or when we are connected to an older server.
|
||||
let containerNodeFront = flexboxFront.containerNodeFront;
|
||||
if (!containerNodeFront) {
|
||||
containerNodeFront = await this.walker.getNodeFromActor(flexboxFront.actorID,
|
||||
["containerEl"]);
|
||||
if (!flexItemContainer && flexContainer.nodeFront === this.selection.nodeFront) {
|
||||
flexItemContainer = await this.getFlexContainerProps(this.selection.nodeFront,
|
||||
true);
|
||||
}
|
||||
|
||||
const flexItemContainer = await this.getAsFlexItem(containerNodeFront);
|
||||
const flexItems = await this.getFlexItems(flexboxFront);
|
||||
// If the current selected node is a flex item, display its flex item sizing
|
||||
// properties.
|
||||
const flexItemShown = flexItems.find(item =>
|
||||
item.nodeFront === this.selection.nodeFront);
|
||||
const highlighted = this._highlighters &&
|
||||
containerNodeFront == this.highlighters.flexboxHighlighterShown;
|
||||
flexContainer.nodeFront === this.highlighters.flexboxHighlighterShown;
|
||||
const color = await this.getOverlayColor();
|
||||
|
||||
this.store.dispatch(updateFlexbox({
|
||||
color,
|
||||
flexContainer: {
|
||||
actorID: flexboxFront.actorID,
|
||||
flexItems,
|
||||
flexItemShown: flexItemShown ? flexItemShown.nodeFront.actorID : null,
|
||||
isFlexItemContainer: false,
|
||||
nodeFront: containerNodeFront,
|
||||
properties: flexboxFront.properties,
|
||||
},
|
||||
flexContainer,
|
||||
flexItemContainer,
|
||||
highlighted,
|
||||
}));
|
||||
|
||||
const isContainerInfoShown = !flexItemShown || !!flexItemContainer;
|
||||
const isItemInfoShown = !!flexItemShown || !!flexItemContainer;
|
||||
const isContainerInfoShown = !flexContainer.flexItemShown || !!flexItemContainer;
|
||||
const isItemInfoShown = !!flexContainer.flexItemShown || !!flexItemContainer;
|
||||
this.sendTelemetryProbes(isContainerInfoShown, isItemInfoShown);
|
||||
} catch (e) {
|
||||
// This call might fail if called asynchrously after the toolbox is finished
|
||||
|
@ -497,4 +501,57 @@ class FlexboxInspector {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given flex container object, returns the flex container properties that can be
|
||||
* used to check if 2 flex container objects are the same.
|
||||
*
|
||||
* @param {Object|null} flexContainer
|
||||
* Object consisting of the flex container's properties.
|
||||
* @return {Object|null} consisting of the comparable flex container's properties.
|
||||
*/
|
||||
function getComparableFlexContainerProperties(flexContainer) {
|
||||
if (!flexContainer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
flexItems: getComparableFlexItemsProperties(flexContainer.flexItems),
|
||||
nodeFront: flexContainer.nodeFront.actorID,
|
||||
properties: flexContainer.properties,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of flex item objects, returns the relevant flex item properties that can
|
||||
* be compared to check if any changes has occurred.
|
||||
*
|
||||
* @param {Array} flexItems
|
||||
* Array of objects containing the flex item properties.
|
||||
* @return {Array} of objects consisting of the comparable flex item's properties.
|
||||
*/
|
||||
function getComparableFlexItemsProperties(flexItems) {
|
||||
return flexItems.map(item => {
|
||||
return {
|
||||
computedStyle: item.computedStyle,
|
||||
flexItemSizing: item.flexItemSizing,
|
||||
nodeFront: item.nodeFront.actorID,
|
||||
properties: item.properties,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the old and new flex container properties
|
||||
*
|
||||
* @param {Object} oldFlexContainer
|
||||
* Object consisting of the old flex container's properties.
|
||||
* @param {Object} newFlexContainer
|
||||
* Object consisting of the new flex container's properties.
|
||||
* @return {Boolean} true if the flex container properties are the same, false otherwise.
|
||||
*/
|
||||
function hasFlexContainerChanged(oldFlexContainer, newFlexContainer) {
|
||||
return JSON.stringify(getComparableFlexContainerProperties(oldFlexContainer)) !==
|
||||
JSON.stringify(getComparableFlexContainerProperties(newFlexContainer));
|
||||
}
|
||||
|
||||
module.exports = FlexboxInspector;
|
||||
|
|
|
@ -20,6 +20,7 @@ support-files =
|
|||
|
||||
[browser_flexbox_accordion_state.js]
|
||||
[browser_flexbox_container_and_item.js]
|
||||
[browser_flexbox_container_and_item_updates_on_change.js]
|
||||
[browser_flexbox_container_element_rep.js]
|
||||
[browser_flexbox_container_properties.js]
|
||||
[browser_flexbox_empty_state.js]
|
||||
|
@ -27,6 +28,7 @@ support-files =
|
|||
[browser_flexbox_highlighter_color_picker_on_RETURN.js]
|
||||
[browser_flexbox_item_list_01.js]
|
||||
[browser_flexbox_item_list_02.js]
|
||||
[browser_flexbox_item_list_updates_on_change.js]
|
||||
[browser_flexbox_item_outline_exists.js]
|
||||
[browser_flexbox_item_outline_has_correct_layout.js]
|
||||
[browser_flexbox_item_outline_hidden_when_useless.js]
|
||||
|
@ -41,6 +43,7 @@ support-files =
|
|||
[browser_flexbox_sizing_info_for_text_nodes.js]
|
||||
[browser_flexbox_sizing_info_has_correct_sections.js]
|
||||
[browser_flexbox_sizing_info_matches_properties_with_!important.js]
|
||||
[browser_flexbox_sizing_info_updates_on_change.js]
|
||||
[browser_flexbox_sizing_wanted_to_grow_but_was_clamped.js]
|
||||
[browser_flexbox_text_nodes_are_listed.js]
|
||||
[browser_flexbox_toggle_flexbox_highlighter_01.js]
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the flex container accordion is rendered when a flex item is updated to
|
||||
// also be a flex container.
|
||||
|
||||
const TEST_URI = `
|
||||
<style>
|
||||
.container {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
<div id="container" class="container">
|
||||
<div id="item">
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
add_task(async function() {
|
||||
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
const { inspector, flexboxInspector, testActor } = await openLayoutView();
|
||||
const { document: doc } = flexboxInspector;
|
||||
|
||||
const onFlexItemSizingRendered = waitForDOM(doc, "ul.flex-item-sizing");
|
||||
await selectNode("#item", inspector);
|
||||
const [flexSizingContainer] = await onFlexItemSizingRendered;
|
||||
|
||||
ok(flexSizingContainer, "The flex sizing info is rendered.");
|
||||
|
||||
info("Changing the flexbox in the page.");
|
||||
const onAccordionsChanged = waitForDOM(doc, ".accordion > div", 4);
|
||||
testActor.eval(`
|
||||
document.getElementById("item").className = "container";
|
||||
`);
|
||||
const [flexItemPane, flexContainerPane] = await onAccordionsChanged;
|
||||
|
||||
ok(flexItemPane, "The flex item accordion pane is rendered.");
|
||||
ok(flexContainerPane, "The flex container accordion pane is rendered.");
|
||||
is(flexItemPane.children[0].textContent, "Flex Item of div#container.container",
|
||||
"Got the correct header for the flex item pane.");
|
||||
is(flexContainerPane.children[0].textContent, "Flex Container",
|
||||
"Got the correct header for the flex container pane.");
|
||||
});
|
|
@ -0,0 +1,44 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the flex item list updates on changes to the number of flex items in the
|
||||
// flex container.
|
||||
|
||||
const TEST_URI = `
|
||||
<style>
|
||||
#container {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
<div id="container">
|
||||
<div></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
add_task(async function() {
|
||||
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
const { inspector, flexboxInspector, testActor } = await openLayoutView();
|
||||
const { document: doc } = flexboxInspector;
|
||||
|
||||
const onFlexItemListRendered = waitForDOM(doc, ".flex-item-list");
|
||||
await selectNode("#container", inspector);
|
||||
const [flexItemList] = await onFlexItemListRendered;
|
||||
|
||||
info("Checking the initial state of the flex item list.");
|
||||
ok(flexItemList, "The flex item list is rendered.");
|
||||
is(flexItemList.querySelectorAll("button").length, 1,
|
||||
"Got the correct number of flex items in the list.");
|
||||
|
||||
info("Changing the flexbox in the page.");
|
||||
const onFlexItemListChanged = waitForDOM(doc, ".flex-item-list > button", 2);
|
||||
testActor.eval(`
|
||||
const div = document.createElement("div");
|
||||
document.getElementById("container").appendChild(div);
|
||||
`);
|
||||
const elements = await onFlexItemListChanged;
|
||||
|
||||
info("Checking the flex item list is correct.");
|
||||
is(elements.length, 2, "Flex item list was changed.");
|
||||
});
|
|
@ -0,0 +1,41 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the flexbox sizing info updates on changes to the flex item properties.
|
||||
|
||||
const TEST_URI = `
|
||||
<style>
|
||||
#container {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
<div id="container">
|
||||
<div id="item"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
add_task(async function() {
|
||||
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
const { inspector, flexboxInspector, testActor } = await openLayoutView();
|
||||
const { document: doc } = flexboxInspector;
|
||||
|
||||
const onFlexItemSizingRendered = waitForDOM(doc, "ul.flex-item-sizing");
|
||||
await selectNode("#item", inspector);
|
||||
const [flexItemSizingContainer] = await onFlexItemSizingRendered;
|
||||
|
||||
info("Checking the initial state of the flex item list.");
|
||||
is(flexItemSizingContainer.querySelectorAll("li").length, 2,
|
||||
"Got the correct number of flex item sizing properties in the list.");
|
||||
|
||||
info("Changing the flexbox in the page.");
|
||||
const onFlexItemSizingChanged = waitForDOM(doc, "ul.flex-item-sizing > li", 3);
|
||||
testActor.eval(`
|
||||
document.getElementById("item").style.minWidth = "100px";
|
||||
`);
|
||||
const elements = await onFlexItemSizingChanged;
|
||||
|
||||
info("Checking the flex item sizing info is correct.");
|
||||
is(elements.length, 3, "Flex item sizing info was changed.");
|
||||
});
|
|
@ -3283,32 +3283,6 @@ function getNodeSetter(item) {
|
|||
return item && item.contents ? item.contents.set : undefined;
|
||||
}
|
||||
|
||||
function makeNodesForAccessors(item) {
|
||||
const accessors = [];
|
||||
|
||||
const getter = getNodeGetter(item);
|
||||
if (getter && getter.type !== "undefined") {
|
||||
accessors.push(createNode({
|
||||
parent: item,
|
||||
name: "<get>",
|
||||
contents: { value: getter },
|
||||
type: NODE_TYPES.GET
|
||||
}));
|
||||
}
|
||||
|
||||
const setter = getNodeSetter(item);
|
||||
if (setter && setter.type !== "undefined") {
|
||||
accessors.push(createNode({
|
||||
parent: item,
|
||||
name: "<set>",
|
||||
contents: { value: setter },
|
||||
type: NODE_TYPES.SET
|
||||
}));
|
||||
}
|
||||
|
||||
return accessors;
|
||||
}
|
||||
|
||||
function sortProperties(properties) {
|
||||
return properties.sort((a, b) => {
|
||||
// Sort numbers in ascending order and sort strings lexicographically
|
||||
|
@ -3442,6 +3416,18 @@ function makeNodesForProperties(objProps, parent) {
|
|||
nodes.push(makeNodesForEntries(parent));
|
||||
}
|
||||
|
||||
// Add accessor nodes if needed
|
||||
for (const name of propertiesNames) {
|
||||
const property = allProperties[name];
|
||||
if (property.get && property.get.type !== "undefined") {
|
||||
nodes.push(createGetterNode({ parent, property, name }));
|
||||
}
|
||||
|
||||
if (property.set && property.set.type !== "undefined") {
|
||||
nodes.push(createSetterNode({ parent, property, name }));
|
||||
}
|
||||
}
|
||||
|
||||
// Add the prototype if it exists and is not null
|
||||
if (prototype && prototype.type !== "null") {
|
||||
nodes.push(makeNodeForPrototype(objProps, parent));
|
||||
|
@ -3511,6 +3497,24 @@ function createNode(options) {
|
|||
};
|
||||
}
|
||||
|
||||
function createGetterNode({ parent, property, name }) {
|
||||
return createNode({
|
||||
parent,
|
||||
name: `<get ${name}()>`,
|
||||
contents: { value: property.get },
|
||||
type: NODE_TYPES.GET
|
||||
});
|
||||
}
|
||||
|
||||
function createSetterNode({ parent, property, name }) {
|
||||
return createNode({
|
||||
parent,
|
||||
name: `<set ${name}()>`,
|
||||
contents: { value: property.set },
|
||||
type: NODE_TYPES.SET
|
||||
});
|
||||
}
|
||||
|
||||
function getSymbolDescriptor(symbol) {
|
||||
return symbol.toString().replace(/^(Symbol\()(.*)(\))$/, "$2");
|
||||
}
|
||||
|
@ -3552,10 +3556,6 @@ function getChildren(options) {
|
|||
return addToCache(item.contents);
|
||||
}
|
||||
|
||||
if (nodeHasAccessors(item)) {
|
||||
return addToCache(makeNodesForAccessors(item));
|
||||
}
|
||||
|
||||
if (nodeIsMapEntry(item)) {
|
||||
return addToCache(makeNodesForMapEntry(item));
|
||||
}
|
||||
|
@ -3647,6 +3647,8 @@ function getClosestNonBucketNode(item) {
|
|||
|
||||
module.exports = {
|
||||
createNode,
|
||||
createGetterNode,
|
||||
createSetterNode,
|
||||
getActor,
|
||||
getChildren,
|
||||
getClosestGripNode,
|
||||
|
@ -6487,7 +6489,7 @@ class ObjectInspector extends Component {
|
|||
const parentElementProps = {
|
||||
className: classnames("node object-node", {
|
||||
focused,
|
||||
lessen: !expanded && (nodeIsDefaultProperties(item) || nodeIsPrototype(item) || dimTopLevelWindow === true && nodeIsWindow(item) && depth === 0),
|
||||
lessen: !expanded && (nodeIsDefaultProperties(item) || nodeIsPrototype(item) || nodeIsGetter(item) || nodeIsSetter(item) || dimTopLevelWindow === true && nodeIsWindow(item) && depth === 0),
|
||||
block: nodeIsBlock(item)
|
||||
}),
|
||||
onClick: e => {
|
||||
|
@ -6557,7 +6559,9 @@ class ObjectInspector extends Component {
|
|||
autoExpandDepth,
|
||||
|
||||
isExpanded: item => expandedPaths && expandedPaths.has(item.path),
|
||||
isExpandable: item => nodeIsPrimitive(item) === false,
|
||||
// TODO: We don't want property with getters to be expandable until we
|
||||
// do have a mechanism to invoke the getter (See #6140).
|
||||
isExpandable: item => !nodeIsPrimitive(item) && !nodeHasAccessors(item),
|
||||
focused: this.focusedItem,
|
||||
|
||||
getRoots: this.getRoots,
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -13282,18 +13282,43 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
|||
nsAutoString referrer;
|
||||
aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
|
||||
nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(referrer);
|
||||
|
||||
bool targetBlank = aTargetSpec.LowerCaseEqualsLiteral("_blank");
|
||||
bool explicitOpenerSet = false;
|
||||
|
||||
// The opener behaviour follows a hierarchy, such that if a higher priority
|
||||
// behaviour is specified, it always takes priority. That priority is
|
||||
// currently: norefrerer > noopener > opener > default
|
||||
|
||||
while (tok.hasMoreTokens()) {
|
||||
const nsAString& token = tok.nextToken();
|
||||
if (token.LowerCaseEqualsLiteral("noreferrer")) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
|
||||
INTERNAL_LOAD_FLAGS_NO_OPENER;
|
||||
// We now have all the flags we could possibly have, so just stop.
|
||||
// noreferrer cannot be overwritten by a 'rel=opener'.
|
||||
explicitOpenerSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (token.LowerCaseEqualsLiteral("noopener")) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
|
||||
explicitOpenerSet = true;
|
||||
}
|
||||
|
||||
if (targetBlank &&
|
||||
StaticPrefs::dom_targetBlankNoOpener_enabled() &&
|
||||
token.LowerCaseEqualsLiteral("opener") &&
|
||||
!explicitOpenerSet) {
|
||||
explicitOpenerSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetBlank &&
|
||||
StaticPrefs::dom_targetBlankNoOpener_enabled() &&
|
||||
!explicitOpenerSet) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
|
||||
}
|
||||
|
||||
if (aNoOpenerImplied) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ function test6() {
|
|||
function test7() {
|
||||
testlink.href = "javascript:opener.activationListener(); window.close();";
|
||||
testlink.target = "_blank";
|
||||
testlink.rel = "opener";
|
||||
activationListener =
|
||||
function() {
|
||||
ok(true, "Click() should activate a link");
|
||||
|
@ -127,6 +128,7 @@ function test7() {
|
|||
function test8() {
|
||||
testlink.href = "javascript:opener.activationListener(); window.close();";
|
||||
testlink.target = "_blank";
|
||||
testlink.rel = "opener";
|
||||
activationListener =
|
||||
function() {
|
||||
ok(false, "Click() should not activate a link");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<body>
|
||||
<a id='link' target='_blank' href="http://example.com">Click me</a>
|
||||
<a id='link' target='_blank' href="http://example.com" rel="opener">Click me</a>
|
||||
|
||||
<script>
|
||||
function clickLink() {
|
||||
|
|
|
@ -37,3 +37,7 @@ skip-if = os == 'mac' # bug 1494843
|
|||
[browser_refresh_wyciwyg_url.js]
|
||||
support-files =
|
||||
file_refresh_wyciwyg_url.html
|
||||
[browser_targetBlankNoOpener.js]
|
||||
support-files =
|
||||
empty.html
|
||||
image_yellow.png
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
const TEST_URL = "http://mochi.test:8888/browser/dom/html/test/empty.html";
|
||||
|
||||
async function checkOpener(browser, elm, name, rel) {
|
||||
let p = BrowserTestUtils.waitForNewTab(gBrowser, null, true, true);
|
||||
|
||||
await ContentTask.spawn(browser, {url: TEST_URL, name, rel, elm }, async obj => {
|
||||
let element;
|
||||
|
||||
if (obj.elm == "anchor") {
|
||||
element = content.document.createElement("a");
|
||||
content.document.body.appendChild(element);
|
||||
element.appendChild(content.document.createTextNode(obj.name));
|
||||
} else {
|
||||
let img = content.document.createElement('img');
|
||||
img.src = "image_yellow.png";
|
||||
content.document.body.appendChild(img);
|
||||
|
||||
element = content.document.createElement("area");
|
||||
img.appendChild(element);
|
||||
|
||||
element.setAttribute("shape", "rect");
|
||||
element.setAttribute("coords", "0,0,100,100");
|
||||
}
|
||||
|
||||
element.setAttribute("target", "_blank");
|
||||
element.setAttribute("href", obj.url);
|
||||
|
||||
if (obj.rel) {
|
||||
element.setAttribute("rel", obj.rel);
|
||||
}
|
||||
|
||||
element.click();
|
||||
});
|
||||
|
||||
let newTab = await p;
|
||||
let newBrowser = gBrowser.getBrowserForTab(newTab);
|
||||
|
||||
let hasOpener = await ContentTask.spawn(newTab.linkedBrowser, null, _ => !!content.window.opener);
|
||||
|
||||
BrowserTestUtils.removeTab(newTab);
|
||||
return hasOpener;
|
||||
}
|
||||
|
||||
async function runTests(browser, elm) {
|
||||
info("Creating an " + elm + " with target=_blank rel=opener");
|
||||
ok(!!(await checkOpener(browser, elm, "rel=opener", "opener")), "We want the opener with rel=opener");
|
||||
|
||||
info("Creating an " + elm + " with target=_blank rel=noopener");
|
||||
ok(!(await checkOpener(browser, elm, "rel=noopener", "noopener")), "We don't want the opener with rel=noopener");
|
||||
|
||||
info("Creating an " + elm + " with target=_blank");
|
||||
ok(!(await checkOpener(browser, elm, "no rel", null)), "We don't want the opener with no rel is passed");
|
||||
|
||||
info("Creating an " + elm + " with target=_blank rel='noopener opener'");
|
||||
ok(!(await checkOpener(browser, elm, "rel=noopener+opener", "noopener opener")), "noopener wins with rel=noopener+opener");
|
||||
|
||||
info("Creating an " + elm + " with target=_blank rel='noreferrer opener'");
|
||||
ok(!(await checkOpener(browser, elm, "noreferrer wins", "noreferrer opener")), "We don't want the opener with rel=noreferrer+opener");
|
||||
|
||||
info("Creating an " + elm + " with target=_blank rel='opener noreferrer'");
|
||||
ok(!(await checkOpener(browser, elm, "noreferrer wins again", "noreferrer opener")), "We don't want the opener with rel=opener+noreferrer");
|
||||
}
|
||||
|
||||
add_task(async _ => {
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.block_multiple_popups", false],
|
||||
["dom.disable_open_during_load", true],
|
||||
["dom.targetBlankNoOpener.enabled", true],
|
||||
]});
|
||||
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, TEST_URL);
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
let browser = gBrowser.getBrowserForTab(tab);
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
|
||||
await runTests(browser, 'anchor');
|
||||
await runTests(browser, 'area');
|
||||
|
||||
info("Removing the tab");
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
<html><body></body></html>
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<body onload="document.querySelector('a').click();">
|
||||
<a href="javascript:opener.document.getElementById('result').textContent = document.cookie;" target="_blank">test</a>
|
||||
<a href="javascript:opener.document.getElementById('result').textContent = document.cookie;" target="_blank" rel="opener">test</a>
|
||||
<div id="result">not tested yet</div>
|
||||
</body>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="UTF-8">
|
||||
<a id="link" href="about:blank" target="_blank"
|
||||
<a id="link" href="about:blank" target="_blank" rel="opener"
|
||||
onclick="document.body.requestFullscreen()">Click here</a>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<body onLoad="doStuff()">
|
||||
I am sandboxed but with "allow-scripts allow-same-origin"
|
||||
|
||||
<a href="file_iframe_sandbox_open_window_fail.html" target="_blank" id="target_blank">open window</a>
|
||||
<a href="file_iframe_sandbox_open_window_fail.html" target="_blank" id="target_blank" rel="opener">open window</a>
|
||||
<a href="file_iframe_sandbox_open_window_fail.html" target="BC341604" id="target_BC341604">open window</a>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<body onLoad="doStuff()">
|
||||
I am sandboxed but with "allow-popups allow-scripts allow-same-origin"
|
||||
|
||||
<a href="file_iframe_sandbox_open_window_pass.html" target="_blank" id="target_blank">open window</a>
|
||||
<a href="file_iframe_sandbox_open_window_pass.html" target="_blank" rel="opener" id="target_blank">open window</a>
|
||||
<a href="file_iframe_sandbox_open_window_pass.html?BC766282" target="BC766282" id="target_BC766282">open window</a>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
This was opened in an iframe with "allow-scripts allow-popups allow-same-origin".
|
||||
However allow-same-origin was removed from the iframe before navigating to me,
|
||||
so I should only have "allow-scripts allow-popups" in force.
|
||||
<a href="file_iframe_sandbox_k_if2.html" target="_blank" id="target_blank_if2">open window</a>
|
||||
<a href="file_iframe_sandbox_k_if2.html" target="_blank" id="target_blank_if2" rel="opener">open window</a>
|
||||
<a href="file_iframe_sandbox_k_if2.html" target="BC766282_if2" id="target_BC766282_if2">open window</a>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
|
||||
<body onLoad="doStuff()">
|
||||
I am sandboxed with "allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation".
|
||||
<a href="file_iframe_sandbox_k_if5.html" target="_blank" id="target_blank_if5">open window</a>
|
||||
<a href="file_iframe_sandbox_k_if5.html" target="_blank" id="target_blank_if5" rel="opener">open window</a>
|
||||
<a href="file_iframe_sandbox_k_if5.html" target="BC766282_if5" id="target_BC766282_if5">open window</a>
|
||||
|
||||
<a href="file_iframe_sandbox_k_if7.html" target="_blank" id="target_blank_if7">open window</a>
|
||||
<a href="file_iframe_sandbox_k_if7.html" target="_blank" id="target_blank_if7" rel="opener">open window</a>
|
||||
<a href="file_iframe_sandbox_k_if7.html" target="BC766282_if7" id="target_BC766282_if7">open window</a>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
After my initial load, "allow-same-origin" is removed and then I open file_iframe_sandbox_k_if9.html
|
||||
in 3 different ways, which attemps to call a function in my parent.
|
||||
This should succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded.
|
||||
<a href="file_iframe_sandbox_k_if9.html" target="_blank" id="target_blank_if9">open window</a>
|
||||
<a href="file_iframe_sandbox_k_if9.html" target="_blank" id="target_blank_if9" rel="opener">open window</a>
|
||||
<a href="file_iframe_sandbox_k_if9.html" target="BC766282_if9" id="target_BC766282_if9">open window</a>
|
||||
|
||||
Now navigate to file_iframe_sandbox_k_if1.html to do tests for a sandbox opening a window
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<html>
|
||||
<body>
|
||||
<a id="link" href="file_window_open_close_inner.html" target="_blank" onclick="setTimeout(function () { window.close() }, 0)">link</a>
|
||||
<a id="link" href="file_window_open_close_inner.html" target="_blank" rel="opener" onclick="setTimeout(function () { window.close() }, 0)">link</a>
|
||||
</html>
|
||||
</body>
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 95 B |
|
@ -119,7 +119,7 @@ class RemoteVideoDecoder : public RemoteDataDecoder {
|
|||
|
||||
if (ok && (size > 0 || presentationTimeUs >= 0)) {
|
||||
RefPtr<layers::Image> img = new SurfaceTextureImage(
|
||||
mDecoder->mImageHandle, inputInfo.mImageSize,
|
||||
mDecoder->mSurfaceHandle, inputInfo.mImageSize,
|
||||
false /* NOT continuous */, gl::OriginPos::BottomLeft);
|
||||
|
||||
RefPtr<VideoData> v = VideoData::CreateFromImage(
|
||||
|
@ -168,7 +168,7 @@ class RemoteVideoDecoder : public RemoteDataDecoder {
|
|||
__func__);
|
||||
}
|
||||
|
||||
mImageHandle = mSurface->GetImageHandle();
|
||||
mSurfaceHandle = mSurface->GetHandle();
|
||||
|
||||
// Register native methods.
|
||||
JavaCallbacksSupport::Init();
|
||||
|
@ -256,7 +256,7 @@ class RemoteVideoDecoder : public RemoteDataDecoder {
|
|||
private:
|
||||
const VideoInfo mConfig;
|
||||
GeckoSurface::GlobalRef mSurface;
|
||||
AndroidSurfaceTextureHandle mImageHandle;
|
||||
AndroidSurfaceTextureHandle mSurfaceHandle;
|
||||
// Only accessed on reader's task queue.
|
||||
bool mIsCodecSupportAdaptivePlayback = false;
|
||||
// Can be accessed on any thread, but only written on during init.
|
||||
|
|
|
@ -9,7 +9,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=841850
|
|||
<title>Tests for Mixed Content Frame Navigation</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?blankTarget" id="blankTarget" target="_blank">Go to http site</a>
|
||||
<a href="http://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?blankTarget" id="blankTarget" target="_blank" rel="opener">Go to http site</a>
|
||||
|
||||
<script>
|
||||
var blankTarget = document.getElementById("blankTarget");
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<p><a id="winOpenNonDefault" href="#" onclick="return openWindow('resizable=no, location=no, personalbar=no, toolbar=no, scrollbars=no, menubar=no, status=no, directories=no, height=100, width=500');">Open a new window via window.open with non-default features.</a></p>
|
||||
<p><a id="winOpenDialog" href="#" onclick="return openWindow('dialog=yes');">Open a new window via window.open with dialog=1.</a></p>
|
||||
<p><a id="winOpenNoURLNonDefault" href="#" onclick="return openBlankWindow('location=no, toolbar=no, height=100, width=100');">Open a blank new window via window.open with non-default features.</a></p>
|
||||
<p><a id="targetBlank" href="dummy.html" target="_blank">Open a new window via target="_blank".</a></p>
|
||||
<p><a id="targetBlank" href="dummy.html" target="_blank" rel="opener">Open a new window via target="_blank".</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a id="test1" href="test_noopener_target.html" target="_blank">1</a>
|
||||
<a id="test1" href="test_noopener_target.html" target="_blank" rel="opener">1</a>
|
||||
<a id="test2" href="test_noopener_target.html" target="_blank" rel="noopener">2</a>
|
||||
<a id="test3" href="test_noopener_target.html" target="_blank" rel="noreferrer">3</a>
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=458091
|
|||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<a id="testlink1" target="_blank" href="javascript:window.opener.finish(sessionStorage['testItem']);window.close();">Javascript Link</a>
|
||||
<a id="testlink2" target="_blank" href="bug458091_child.html">HTTP Link</a>
|
||||
<a id="testlink1" target="_blank" rel="opener" href="javascript:window.opener.finish(sessionStorage['testItem']);window.close();">Javascript Link</a>
|
||||
<a id="testlink2" target="_blank" rel="opener" href="bug458091_child.html">HTTP Link</a>
|
||||
<a id="testlink3" target="alreadyOpened" href="bug458091_child.html">Target Link</a>
|
||||
<script type="application/javascript">
|
||||
|
||||
|
|
|
@ -8,13 +8,6 @@
|
|||
|
||||
#include "AndroidSurfaceTexture.h"
|
||||
|
||||
#include "GeneratedJNINatives.h"
|
||||
|
||||
#include "AndroidNativeWindow.h"
|
||||
#include "GLContextEGL.h"
|
||||
#include "GLBlitHelper.h"
|
||||
#include "GLImages.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -36,184 +29,6 @@ AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::Param surfa
|
|||
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
|
||||
}
|
||||
|
||||
class SharedGL {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedGL);
|
||||
|
||||
SharedGL(AndroidNativeWindow& window)
|
||||
{
|
||||
MutexAutoLock lock(sMutex);
|
||||
|
||||
if (!sContext) {
|
||||
MOZ_ASSERT(sInstanceCount == 0);
|
||||
sContext = CreateContext();
|
||||
if (!sContext) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
InitSurface(window);
|
||||
++sInstanceCount;
|
||||
}
|
||||
|
||||
void Blit(const AndroidSurfaceTextureHandle& sourceTextureHandle,
|
||||
const gfx::IntSize& imageSize)
|
||||
{
|
||||
MutexAutoLock lock(sMutex);
|
||||
MOZ_ASSERT(sContext);
|
||||
|
||||
// Setting overide also makes conext and surface current.
|
||||
sContext->SetEGLSurfaceOverride(mTargetSurface);
|
||||
RefPtr<layers::SurfaceTextureImage> img =
|
||||
new layers::SurfaceTextureImage(sourceTextureHandle,
|
||||
imageSize,
|
||||
false,
|
||||
OriginPos::TopLeft);
|
||||
sContext->BlitHelper()->BlitImage(img, imageSize, OriginPos::BottomLeft);
|
||||
sContext->SwapBuffers();
|
||||
// This method is called through binder IPC and could run on any thread in
|
||||
// the pool. Release the context and surface from this thread after use so
|
||||
// they can be bound to another thread later.
|
||||
UnmakeCurrent(sContext);
|
||||
}
|
||||
|
||||
private:
|
||||
~SharedGL()
|
||||
{
|
||||
MutexAutoLock lock(sMutex);
|
||||
|
||||
if (mTargetSurface != EGL_NO_SURFACE) {
|
||||
GLLibraryEGL::Get()->fDestroySurface(EGL_DISPLAY(), mTargetSurface);
|
||||
}
|
||||
|
||||
// Destroy shared GL context when no one uses it.
|
||||
if (--sInstanceCount == 0) {
|
||||
sContext.reset();
|
||||
}
|
||||
}
|
||||
|
||||
static UniquePtr<GLContextEGL> CreateContext()
|
||||
{
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(!sContext);
|
||||
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
EGLDisplay eglDisplay = egl->fGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
EGLConfig eglConfig;
|
||||
CreateConfig(&eglConfig, /* bpp */ 24, /* depth buffer? */ false);
|
||||
EGLint attributes[] = {
|
||||
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
EGLContext eglContext =
|
||||
egl->fCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attributes);
|
||||
UniquePtr<GLContextEGL> gl = MakeUnique<GLContextEGL>(CreateContextFlags::NONE,
|
||||
SurfaceCaps::Any(),
|
||||
/* offscreen? */ false,
|
||||
eglConfig,
|
||||
EGL_NO_SURFACE,
|
||||
eglContext);
|
||||
if (!gl->Init()) {
|
||||
NS_WARNING("Fail to create GL context for native blitter.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Yield the current state made in constructor.
|
||||
UnmakeCurrent(gl);
|
||||
return gl;
|
||||
}
|
||||
|
||||
void InitSurface(AndroidNativeWindow& window)
|
||||
{
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(sContext);
|
||||
|
||||
mTargetSurface = gl::GLLibraryEGL::Get()->fCreateWindowSurface(sContext->GetEGLDisplay(),
|
||||
sContext->mConfig,
|
||||
window.NativeWindow(),
|
||||
0);
|
||||
}
|
||||
|
||||
static bool UnmakeCurrent(UniquePtr<GLContextEGL>& gl)
|
||||
{
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(gl);
|
||||
|
||||
if (!gl->IsCurrent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return gl::GLLibraryEGL::Get()->fMakeCurrent(EGL_DISPLAY(),
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
static Mutex sMutex;
|
||||
static UniquePtr<GLContextEGL> sContext;
|
||||
static size_t sInstanceCount;
|
||||
|
||||
EGLSurface mTargetSurface;
|
||||
};
|
||||
|
||||
Mutex SharedGL::sMutex("SharedGLContext::sMutex");
|
||||
UniquePtr<GLContextEGL> SharedGL::sContext(nullptr);
|
||||
size_t SharedGL::sInstanceCount = 0;
|
||||
|
||||
class GLBlitterSupport final
|
||||
: public java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<GLBlitterSupport>
|
||||
{
|
||||
public:
|
||||
using Base = java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<GLBlitterSupport>;
|
||||
using Base::AttachNative;
|
||||
using Base::GetNative;
|
||||
using Base::DisposeNative;
|
||||
|
||||
static java::GeckoSurfaceTexture::NativeGLBlitHelper::LocalRef
|
||||
Create(jint sourceTextureHandle,
|
||||
jni::Object::Param targetSurface,
|
||||
jint width,
|
||||
jint height)
|
||||
{
|
||||
AndroidNativeWindow win(java::GeckoSurface::Ref::From(targetSurface));
|
||||
auto helper = java::GeckoSurfaceTexture::NativeGLBlitHelper::New();
|
||||
RefPtr<SharedGL> gl = new SharedGL(win);
|
||||
GLBlitterSupport::AttachNative(
|
||||
helper,
|
||||
MakeUnique<GLBlitterSupport>(std::move(gl),
|
||||
sourceTextureHandle,
|
||||
width,
|
||||
height));
|
||||
return helper;
|
||||
}
|
||||
|
||||
GLBlitterSupport(RefPtr<SharedGL>&& gl,
|
||||
jint sourceTextureHandle,
|
||||
jint width,
|
||||
jint height)
|
||||
: mGl(gl)
|
||||
, mSourceTextureHandle(sourceTextureHandle)
|
||||
, mSize(width, height)
|
||||
{
|
||||
}
|
||||
|
||||
void Blit()
|
||||
{
|
||||
mGl->Blit(mSourceTextureHandle, mSize);
|
||||
}
|
||||
|
||||
private:
|
||||
const RefPtr<SharedGL> mGl;
|
||||
const AndroidSurfaceTextureHandle mSourceTextureHandle;
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
void
|
||||
AndroidSurfaceTexture::Init()
|
||||
{
|
||||
GLBlitterSupport::Init();
|
||||
}
|
||||
|
||||
} // gl
|
||||
} // mozilla
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
|
|
@ -18,7 +18,6 @@ namespace gl {
|
|||
|
||||
class AndroidSurfaceTexture {
|
||||
public:
|
||||
static void Init();
|
||||
static void GetTransformMatrix(java::sdk::SurfaceTexture::Param surfaceTexture,
|
||||
mozilla::gfx::Matrix4x4* outMatrix);
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ bool
|
|||
SharedSurface_SurfaceTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
|
||||
{
|
||||
*out_descriptor =
|
||||
layers::SurfaceTextureDescriptor(mSurface->GetImageHandle(),
|
||||
layers::SurfaceTextureDescriptor(mSurface->GetHandle(),
|
||||
mSize,
|
||||
gfx::SurfaceFormat::R8G8B8A8,
|
||||
false /* NOT continuous */,
|
||||
|
|
|
@ -170,7 +170,7 @@ AndroidNativeWindowTextureData::FillInfo(TextureData::Info& aInfo) const
|
|||
bool
|
||||
AndroidNativeWindowTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
aOutDescriptor = SurfaceTextureDescriptor(mSurface->GetImageHandle(),
|
||||
aOutDescriptor = SurfaceTextureDescriptor(mSurface->GetHandle(),
|
||||
mSize,
|
||||
mFormat,
|
||||
false /* not continuous */,
|
||||
|
|
|
@ -324,6 +324,7 @@ AnimationFrameDiscardingQueue::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf
|
|||
|
||||
AnimationFrameRecyclingQueue::AnimationFrameRecyclingQueue(AnimationFrameRetainedBuffer&& aQueue)
|
||||
: AnimationFrameDiscardingQueue(std::move(aQueue))
|
||||
, mForceUseFirstFrameRefreshArea(false)
|
||||
{
|
||||
// In an ideal world, we would always save the already displayed frames for
|
||||
// recycling but none of the frames were marked as recyclable. We will incur
|
||||
|
@ -361,31 +362,20 @@ AnimationFrameRecyclingQueue::AdvanceInternal()
|
|||
MOZ_ASSERT(!mDisplay.empty());
|
||||
MOZ_ASSERT(mDisplay.front());
|
||||
|
||||
// We have advanced past the first frame. That means the next frame we are
|
||||
// putting in the queue to recycling is the first frame in the animation,
|
||||
// and we no longer need to worry about having looped around.
|
||||
if (mGetIndex == 1) {
|
||||
mForceUseFirstFrameRefreshArea = false;
|
||||
}
|
||||
|
||||
RefPtr<imgFrame>& front = mDisplay.front();
|
||||
|
||||
// The first frame should always have a dirty rect that matches the frame
|
||||
// rect. As such, we should use mFirstFrameRefreshArea instead for recycle
|
||||
// rect calculations.
|
||||
MOZ_ASSERT_IF(mGetIndex == 1,
|
||||
front->GetRect().IsEqualEdges(front->GetDirtyRect()));
|
||||
|
||||
RecycleEntry newEntry(mGetIndex == 1 ? mFirstFrameRefreshArea
|
||||
RecycleEntry newEntry(mForceUseFirstFrameRefreshArea ? mFirstFrameRefreshArea
|
||||
: front->GetDirtyRect());
|
||||
|
||||
// If we are allowed to recycle the frame, then we should save it before the
|
||||
// base class's AdvanceInternal discards it.
|
||||
if (front->ShouldRecycle()) {
|
||||
// Calculate the recycle rect for the recycled frame. This is the cumulative
|
||||
// dirty rect of all of the frames ahead of us to be displayed, and to be
|
||||
// used for recycling. Or in other words, the dirty rect between the
|
||||
// recycled frame and the decoded frame which reuses the buffer.
|
||||
for (const RefPtr<imgFrame>& frame : mDisplay) {
|
||||
newEntry.mRecycleRect = newEntry.mRecycleRect.Union(frame->GetDirtyRect());
|
||||
}
|
||||
for (const RecycleEntry& entry : mRecycle) {
|
||||
newEntry.mRecycleRect = newEntry.mRecycleRect.Union(entry.mDirtyRect);
|
||||
}
|
||||
|
||||
newEntry.mFrame = std::move(front);
|
||||
}
|
||||
|
||||
|
@ -428,20 +418,62 @@ AnimationFrameRecyclingQueue::ResetInternal()
|
|||
RawAccessFrameRef
|
||||
AnimationFrameRecyclingQueue::RecycleFrame(gfx::IntRect& aRecycleRect)
|
||||
{
|
||||
if (mInsertIndex == 0) {
|
||||
// If we are recreating the first frame, then we actually have already
|
||||
// precomputed aggregate of the dirty rects as the first frame refresh
|
||||
// area. We know that all of the frames still in the recycling queue
|
||||
// need to take into account the same dirty rect because they are also
|
||||
// frames which cross the boundary.
|
||||
MOZ_ASSERT(mSizeKnown);
|
||||
MOZ_ASSERT(!mFirstFrameRefreshArea.IsEmpty());
|
||||
for (RecycleEntry& entry : mRecycle) {
|
||||
MOZ_ASSERT(mFirstFrameRefreshArea.Contains(entry.mDirtyRect));
|
||||
entry.mDirtyRect = mFirstFrameRefreshArea;
|
||||
}
|
||||
// Until we advance to the first frame again, any subsequent recycled
|
||||
// frames should also use the first frame refresh area.
|
||||
mForceUseFirstFrameRefreshArea = true;
|
||||
}
|
||||
|
||||
if (mRecycle.empty()) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
RawAccessFrameRef frame;
|
||||
RawAccessFrameRef recycledFrame;
|
||||
if (mRecycle.front().mFrame) {
|
||||
frame = mRecycle.front().mFrame->RawAccessRef();
|
||||
if (frame) {
|
||||
aRecycleRect = mRecycle.front().mRecycleRect;
|
||||
recycledFrame = mRecycle.front().mFrame->RawAccessRef();
|
||||
MOZ_ASSERT(recycledFrame);
|
||||
mRecycle.pop_front();
|
||||
|
||||
if (mForceUseFirstFrameRefreshArea) {
|
||||
// We are still crossing the loop boundary and cannot rely upon the dirty
|
||||
// rects of entries in mDisplay to be representative. E.g. The first frame
|
||||
// is probably has a full frame dirty rect.
|
||||
aRecycleRect = mFirstFrameRefreshArea;
|
||||
} else {
|
||||
// Calculate the recycle rect for the recycled frame. This is the
|
||||
// cumulative dirty rect of all of the frames ahead of us to be displayed,
|
||||
// and to be used for recycling. Or in other words, the dirty rect between
|
||||
// the recycled frame and the decoded frame which reuses the buffer.
|
||||
//
|
||||
// We know at this point that mRecycle contains either frames from the end
|
||||
// of the animation with the first frame refresh area as the dirty rect
|
||||
// (plus the first frame likewise) and frames with their actual dirty rect
|
||||
// from the start. mDisplay should also only contain frames from the start
|
||||
// of the animation onwards.
|
||||
aRecycleRect.SetRect(0, 0, 0, 0);
|
||||
for (const RefPtr<imgFrame>& frame : mDisplay) {
|
||||
aRecycleRect = aRecycleRect.Union(frame->GetDirtyRect());
|
||||
}
|
||||
for (const RecycleEntry& entry : mRecycle) {
|
||||
aRecycleRect = aRecycleRect.Union(entry.mDirtyRect);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mRecycle.pop_front();
|
||||
}
|
||||
|
||||
mRecycle.pop_front();
|
||||
return frame;
|
||||
return recycledFrame;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -449,15 +449,12 @@ public:
|
|||
RecycleEntry(RecycleEntry&& aOther)
|
||||
: mFrame(std::move(aOther.mFrame))
|
||||
, mDirtyRect(aOther.mDirtyRect)
|
||||
, mRecycleRect(aOther.mRecycleRect)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
RecycleEntry& operator=(RecycleEntry&& aOther)
|
||||
{
|
||||
mFrame = std::move(aOther.mFrame);
|
||||
mDirtyRect = aOther.mDirtyRect;
|
||||
mRecycleRect = aOther.mRecycleRect;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -466,8 +463,6 @@ public:
|
|||
|
||||
RefPtr<imgFrame> mFrame; // The frame containing the buffer to recycle.
|
||||
gfx::IntRect mDirtyRect; // The dirty rect of the frame itself.
|
||||
gfx::IntRect mRecycleRect; // The dirty rect between the recycled frame and
|
||||
// the future frame that will be written to it.
|
||||
};
|
||||
|
||||
const std::deque<RecycleEntry>& Recycle() const { return mRecycle; }
|
||||
|
@ -488,6 +483,11 @@ protected:
|
|||
/// The first frame refresh area. This is used instead of the dirty rect for
|
||||
/// the last frame when transitioning back to the first frame.
|
||||
gfx::IntRect mFirstFrameRefreshArea;
|
||||
|
||||
/// Force recycled frames to use the first frame refresh area as their dirty
|
||||
/// rect. This is used when we are recycling frames from the end of an
|
||||
/// animation to produce frames at the beginning of an animation.
|
||||
bool mForceUseFirstFrameRefreshArea;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
|
|
@ -27,6 +27,9 @@ CreateEmptyFrame(const IntSize& aSize = IntSize(1, 1),
|
|||
EXPECT_TRUE(NS_SUCCEEDED(rv));
|
||||
RawAccessFrameRef frameRef = frame->RawAccessRef();
|
||||
frame->SetRawAccessOnly();
|
||||
// Normally the blend animation filter would set the dirty rect, but since
|
||||
// we aren't producing an actual animation here, we need to fake it.
|
||||
frame->SetDirtyRect(aFrameRect);
|
||||
frame->Finish();
|
||||
return frame.forget();
|
||||
}
|
||||
|
@ -105,16 +108,13 @@ VerifyAdvance(AnimationFrameBuffer& aQueue,
|
|||
if (aQueue.IsRecycling()) {
|
||||
const AnimationFrameRecyclingQueue& queue =
|
||||
*static_cast<AnimationFrameRecyclingQueue*>(&aQueue);
|
||||
EXPECT_FALSE(queue.Recycle().back().mDirtyRect.IsEmpty());
|
||||
EXPECT_TRUE(queue.Recycle().back().mDirtyRect.Contains(oldFrame->GetDirtyRect()));
|
||||
EXPECT_EQ(totalRecycled + 1, queue.Recycle().size());
|
||||
if (oldFrame->ShouldRecycle()) {
|
||||
EXPECT_EQ(oldFrame.get(), queue.Recycle().back().mFrame.get());
|
||||
EXPECT_FALSE(queue.Recycle().back().mDirtyRect.IsEmpty());
|
||||
EXPECT_FALSE(queue.Recycle().back().mRecycleRect.IsEmpty());
|
||||
EXPECT_EQ(totalRecycled + 1, queue.Recycle().size());
|
||||
} else {
|
||||
EXPECT_EQ(totalRecycled, queue.Recycle().size());
|
||||
if (!queue.Recycle().empty()) {
|
||||
EXPECT_NE(oldFrame.get(), queue.Recycle().back().mFrame.get());
|
||||
}
|
||||
EXPECT_EQ(nullptr, queue.Recycle().back().mFrame.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -584,7 +584,7 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingLoop)
|
|||
// All the frames we inserted should have been recycleable.
|
||||
ASSERT_FALSE(buffer.Recycle().empty());
|
||||
while (!buffer.Recycle().empty()) {
|
||||
IntRect expectedRect = buffer.Recycle().front().mRecycleRect;
|
||||
IntRect expectedRect(0, 0, 1, 1);
|
||||
RefPtr<imgFrame> expectedFrame = buffer.Recycle().front().mFrame;
|
||||
EXPECT_FALSE(expectedRect.IsEmpty());
|
||||
EXPECT_TRUE(expectedFrame.get() != nullptr);
|
||||
|
@ -646,3 +646,109 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingReset)
|
|||
AnimationFrameRecyclingQueue buffer(std::move(retained));
|
||||
TestDiscardingQueueReset(buffer, firstFrame, kThreshold, kBatch, kStartFrame);
|
||||
}
|
||||
|
||||
TEST_F(ImageAnimationFrameBuffer, RecyclingRect)
|
||||
{
|
||||
const size_t kThreshold = 5;
|
||||
const size_t kBatch = 2;
|
||||
const size_t kStartFrame = 0;
|
||||
const IntSize kImageSize(100, 100);
|
||||
AnimationFrameRetainedBuffer retained(kThreshold, kBatch, kStartFrame);
|
||||
|
||||
// Let's get to the recycling state while marking all of the frames as not
|
||||
// recyclable, just like AnimationFrameBuffer / the decoders would do.
|
||||
RefPtr<imgFrame> frame;
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
AnimationFrameBuffer::InsertStatus status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::CONTINUE, status);
|
||||
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::CONTINUE, status);
|
||||
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::CONTINUE, status);
|
||||
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::YIELD, status);
|
||||
|
||||
VerifyAdvance(retained, 1, false);
|
||||
VerifyAdvance(retained, 2, true);
|
||||
VerifyAdvance(retained, 3, false);
|
||||
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
status = retained.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::DISCARD_CONTINUE, status);
|
||||
|
||||
AnimationFrameRecyclingQueue buffer(std::move(retained));
|
||||
|
||||
// The first frame is now the candidate for recycling. Since it was marked as
|
||||
// not recyclable, we should get nothing.
|
||||
VerifyAdvance(buffer, 4, false);
|
||||
|
||||
IntRect recycleRect;
|
||||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
RawAccessFrameRef frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_FALSE(frameRef);
|
||||
EXPECT_TRUE(recycleRect.IsEmpty());
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
|
||||
// Insert a recyclable partial frame. Its dirty rect shouldn't matter since
|
||||
// the previous frame was not recyclable.
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(0, 0, 25, 25));
|
||||
status = buffer.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::YIELD, status);
|
||||
|
||||
VerifyAdvance(buffer, 5, true);
|
||||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_FALSE(frameRef);
|
||||
EXPECT_TRUE(recycleRect.IsEmpty());
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
|
||||
// Insert a recyclable partial frame. Its dirty rect should match the recycle
|
||||
// rect since it is the only frame in the buffer.
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(25, 0, 50, 50));
|
||||
status = buffer.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::YIELD, status);
|
||||
|
||||
VerifyAdvance(buffer, 6, true);
|
||||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_EQ(IntRect(25, 0, 50, 50), recycleRect);
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
|
||||
// Insert the last frame and mark us as complete. The next recycled frame is
|
||||
// producing the first frame again, so we should use the first frame refresh
|
||||
// area instead of its dirty rect.
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(10, 10, 60, 10));
|
||||
status = buffer.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::YIELD, status);
|
||||
|
||||
bool continueDecoding = buffer.MarkComplete(IntRect(0, 0, 75, 50));
|
||||
EXPECT_FALSE(continueDecoding);
|
||||
|
||||
VerifyAdvance(buffer, 7, true);
|
||||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_EQ(IntRect(0, 0, 75, 50), recycleRect);
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
|
||||
// Now let's reinsert the first frame. The recycle rect should still be the
|
||||
// first frame refresh area instead of the dirty rect of the first frame (e.g.
|
||||
// the full frame).
|
||||
frame = CreateEmptyFrame(kImageSize, IntRect(IntPoint(0, 0), kImageSize), false);
|
||||
status = buffer.Insert(std::move(frame));
|
||||
EXPECT_EQ(AnimationFrameBuffer::InsertStatus::YIELD, status);
|
||||
|
||||
VerifyAdvance(buffer, 0, true);
|
||||
EXPECT_FALSE(buffer.Recycle().empty());
|
||||
frameRef = buffer.RecycleFrame(recycleRect);
|
||||
EXPECT_TRUE(frameRef);
|
||||
EXPECT_EQ(IntRect(0, 0, 75, 50), recycleRect);
|
||||
EXPECT_TRUE(buffer.Recycle().empty());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
// This file was autogenerated by binjs_generate_spidermonkey,
|
||||
// please DO NOT EDIT BY HAND.
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* 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/. */
|
||||
|
||||
// To generate this file, see the documentation in
|
||||
// js/src/frontend/binsource/README.md.
|
||||
|
||||
#ifndef frontend_BinASTEnum_h
|
||||
#define frontend_BinASTEnum_h
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
namespace binast {
|
||||
|
||||
// ----- Declaring string enums (by lexicographical order)
|
||||
|
||||
enum class AssertedDeclaredKind {
|
||||
// "var"
|
||||
Var,
|
||||
// "non-const lexical"
|
||||
NonConstLexical,
|
||||
// "const lexical"
|
||||
ConstLexical,
|
||||
};
|
||||
|
||||
enum class BinaryOperator {
|
||||
// ","
|
||||
Comma,
|
||||
// "||"
|
||||
LogicalOr,
|
||||
// "&&"
|
||||
LogicalAnd,
|
||||
// "|"
|
||||
BitOr,
|
||||
// "^"
|
||||
BitXor,
|
||||
// "&"
|
||||
BitAnd,
|
||||
// "=="
|
||||
Eq,
|
||||
// "!="
|
||||
Neq,
|
||||
// "==="
|
||||
StrictEq,
|
||||
// "!=="
|
||||
StrictNeq,
|
||||
// "<"
|
||||
LessThan,
|
||||
// "<="
|
||||
LeqThan,
|
||||
// ">"
|
||||
GreaterThan,
|
||||
// ">="
|
||||
GeqThan,
|
||||
// "in"
|
||||
In,
|
||||
// "instanceof"
|
||||
Instanceof,
|
||||
// "<<"
|
||||
Lsh,
|
||||
// ">>"
|
||||
Rsh,
|
||||
// ">>>"
|
||||
Ursh,
|
||||
// "+"
|
||||
Plus,
|
||||
// "-"
|
||||
Minus,
|
||||
// "*"
|
||||
Mul,
|
||||
// "/"
|
||||
Div,
|
||||
// "%"
|
||||
Mod,
|
||||
// "**"
|
||||
Pow,
|
||||
};
|
||||
|
||||
enum class CompoundAssignmentOperator {
|
||||
// "+="
|
||||
PlusAssign,
|
||||
// "-="
|
||||
MinusAssign,
|
||||
// "*="
|
||||
MulAssign,
|
||||
// "/="
|
||||
DivAssign,
|
||||
// "%="
|
||||
ModAssign,
|
||||
// "**="
|
||||
PowAssign,
|
||||
// "<<="
|
||||
LshAssign,
|
||||
// ">>="
|
||||
RshAssign,
|
||||
// ">>>="
|
||||
UrshAssign,
|
||||
// "|="
|
||||
BitOrAssign,
|
||||
// "^="
|
||||
BitXorAssign,
|
||||
// "&="
|
||||
BitAndAssign,
|
||||
};
|
||||
|
||||
enum class UnaryOperator {
|
||||
// "+"
|
||||
Plus,
|
||||
// "-"
|
||||
Minus,
|
||||
// "!"
|
||||
Not,
|
||||
// "~"
|
||||
BitNot,
|
||||
// "typeof"
|
||||
Typeof,
|
||||
// "void"
|
||||
Void,
|
||||
// "delete"
|
||||
Delete,
|
||||
};
|
||||
|
||||
enum class UpdateOperator {
|
||||
// "++"
|
||||
Incr,
|
||||
// "--"
|
||||
Decr,
|
||||
};
|
||||
|
||||
enum class VariableDeclarationKind {
|
||||
// "var"
|
||||
Var,
|
||||
// "let"
|
||||
Let,
|
||||
// "const"
|
||||
Const,
|
||||
};
|
||||
|
||||
} // namespace binast
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
#endif // frontend_BinASTEnum_h
|
|
@ -9,6 +9,8 @@
|
|||
// To generate this file, see the documentation in
|
||||
// js/src/frontend/binsource/README.md.
|
||||
|
||||
#include "frontend/BinASTParser.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
@ -17,7 +19,6 @@
|
|||
#include "mozilla/Vector.h"
|
||||
|
||||
#include "frontend/BinSource-macros.h"
|
||||
#include "frontend/BinSource.h"
|
||||
#include "frontend/BinTokenReaderTester.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
|
@ -2954,7 +2955,7 @@ BinASTParser<Tok>::parseInterfaceGetterContents(const size_t start, const BinKin
|
|||
(void) isThisCaptured;
|
||||
MOZ_TRY(parseAssertedVarScope());
|
||||
|
||||
BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
|
||||
BINJS_TRY_DECL(params, this->template new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
|
||||
BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
|
||||
|
||||
*paramsOut = params;
|
||||
|
@ -3494,7 +3495,7 @@ BinASTParser<Tok>::parseInterfaceSetterContents(const size_t start, const BinKin
|
|||
&positionalParams));
|
||||
|
||||
BINJS_MOZ_TRY_DECL(param, parseParameter());
|
||||
BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, param->pn_pos));
|
||||
BINJS_TRY_DECL(params, this->template new_<ListNode>(ParseNodeKind::ParamsBody, param->pn_pos));
|
||||
factory_.addList(params, param);
|
||||
MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
|
||||
MOZ_TRY(parseAssertedVarScope());
|
||||
|
@ -4516,7 +4517,7 @@ BinASTParser<Tok>::parseListOfParameter()
|
|||
|
||||
const auto start = tokenizer_->offset();
|
||||
MOZ_TRY(tokenizer_->enterList(length, guard));
|
||||
BINJS_TRY_DECL(result, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
|
||||
BINJS_TRY_DECL(result, this->template new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
BINJS_MOZ_TRY_DECL(item, parseParameter());
|
|
@ -0,0 +1,353 @@
|
|||
// This file was autogenerated by binjs_generate_spidermonkey,
|
||||
// please DO NOT EDIT BY HAND.
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* 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/. */
|
||||
|
||||
// To generate this file, see the documentation in
|
||||
// js/src/frontend/binsource/README.md.
|
||||
|
||||
#ifndef frontend_BinASTParser_h
|
||||
#define frontend_BinASTParser_h
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "frontend/BCEParserHandle.h"
|
||||
#include "frontend/BinASTParserPerTokenizer.h"
|
||||
#include "frontend/BinToken.h"
|
||||
#include "frontend/BinTokenReaderMultipart.h"
|
||||
#include "frontend/BinTokenReaderTester.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
#include "frontend/ParseContext.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
|
||||
#include "js/CompileOptions.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/GCVector.h"
|
||||
#include "js/Result.h"
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
template<typename Tok>
|
||||
class BinASTParser : public BinASTParserPerTokenizer<Tok>
|
||||
{
|
||||
public:
|
||||
using Base = BinASTParserPerTokenizer<Tok>;
|
||||
|
||||
using Tokenizer = Tok;
|
||||
|
||||
using BinFields = typename Tokenizer::BinFields;
|
||||
using AutoList = typename Tokenizer::AutoList;
|
||||
using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
|
||||
using AutoTuple = typename Tokenizer::AutoTuple;
|
||||
using Chars = typename Tokenizer::Chars;
|
||||
|
||||
public:
|
||||
// Auto-generated types.
|
||||
using AssertedDeclaredKind = binast::AssertedDeclaredKind;
|
||||
using BinaryOperator = binast::BinaryOperator;
|
||||
using CompoundAssignmentOperator = binast::CompoundAssignmentOperator;
|
||||
using UnaryOperator = binast::UnaryOperator;
|
||||
using UpdateOperator = binast::UpdateOperator;
|
||||
using VariableDeclarationKind = binast::VariableDeclarationKind;
|
||||
|
||||
public:
|
||||
// BinASTParserPerTokenizer types.
|
||||
using AssertedScopeKind = typename Base::AssertedScopeKind;
|
||||
|
||||
public:
|
||||
BinASTParser(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames,
|
||||
const JS::ReadOnlyCompileOptions& options,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
Handle<LazyScript*> lazyScript = nullptr)
|
||||
: BinASTParserPerTokenizer<Tok>(cx, alloc, usedNames, options, sourceObject, lazyScript)
|
||||
{}
|
||||
~BinASTParser()
|
||||
{}
|
||||
|
||||
protected:
|
||||
// BinASTParserBase fields.
|
||||
using Base::cx_;
|
||||
|
||||
using Base::alloc_;
|
||||
using Base::usedNames_;
|
||||
|
||||
using Base::sourceObject_;
|
||||
using Base::parseContext_;
|
||||
using Base::factory_;
|
||||
|
||||
protected:
|
||||
// BinASTParserPerTokenizer types.
|
||||
using AutoVariableDeclarationKind = typename Base::AutoVariableDeclarationKind;
|
||||
protected:
|
||||
// BinASTParserPerTokenizer fields.
|
||||
using Base::tokenizer_;
|
||||
using Base::variableDeclarationKind_;
|
||||
|
||||
protected:
|
||||
// BinASTParserPerTokenizer methods.
|
||||
using Base::raiseInvalidClosedVar;
|
||||
using Base::raiseMissingVariableInAssertedScope;
|
||||
using Base::raiseMissingDirectEvalInAssertedScope;
|
||||
using Base::raiseInvalidKind;
|
||||
using Base::raiseInvalidVariant;
|
||||
using Base::raiseMissingField;
|
||||
using Base::raiseEmpty;
|
||||
using Base::raiseOOM;
|
||||
using Base::raiseError;
|
||||
|
||||
using Base::makeEmptyFunctionNode;
|
||||
using Base::buildFunction;
|
||||
using Base::buildFunctionBox;
|
||||
using Base::addScopeName;
|
||||
using Base::captureFunctionName;
|
||||
|
||||
using Base::getDeclaredScope;
|
||||
using Base::getBoundScope;
|
||||
using Base::checkBinding;
|
||||
using Base::checkPositionalParameterIndices;
|
||||
|
||||
using Base::checkFunctionLength;
|
||||
using Base::checkClosedVars;
|
||||
|
||||
using Base::prependDirectivesToBody;
|
||||
|
||||
using Base::forceStrictIfNecessary;
|
||||
|
||||
public:
|
||||
|
||||
// ----- Sums of interfaces (by lexicographical order)
|
||||
// `ParseNode*` may never be nullptr
|
||||
JS::Result<Ok> parseAssertedMaybePositionalParameterName(
|
||||
AssertedScopeKind scopeKind,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<ParseNode*> parseAssignmentTarget();
|
||||
JS::Result<ParseNode*> parseBinding();
|
||||
JS::Result<ParseNode*> parseExpression();
|
||||
JS::Result<ParseNode*> parseExpressionOrSuper();
|
||||
JS::Result<ParseNode*> parseForInOfBindingOrAssignmentTarget();
|
||||
JS::Result<ParseNode*> parseObjectProperty();
|
||||
JS::Result<ParseNode*> parseParameter();
|
||||
JS::Result<ParseNode*> parseProgram();
|
||||
JS::Result<ParseNode*> parsePropertyName();
|
||||
JS::Result<ParseNode*> parseSimpleAssignmentTarget();
|
||||
JS::Result<ParseNode*> parseSpreadElementOrExpression();
|
||||
JS::Result<ParseNode*> parseStatement();
|
||||
JS::Result<Ok> parseSumAssertedMaybePositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
AssertedScopeKind scopeKind,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<ParseNode*> parseSumAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumBinding(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumExpressionOrSuper(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumForInOfBindingOrAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumObjectProperty(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumParameter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumProgram(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumSimpleAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumSpreadElementOrExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumVariableDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
|
||||
// ----- Interfaces (by lexicographical order)
|
||||
// `ParseNode*` may never be nullptr
|
||||
JS::Result<Ok> parseAssertedBlockScope();
|
||||
JS::Result<Ok> parseAssertedBoundName(
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseAssertedBoundNamesScope();
|
||||
JS::Result<Ok> parseAssertedDeclaredName(
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseAssertedParameterScope(
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<Ok> parseAssertedScriptGlobalScope();
|
||||
JS::Result<Ok> parseAssertedVarScope();
|
||||
JS::Result<ParseNode*> parseBindingIdentifier();
|
||||
JS::Result<ParseNode*> parseBlock();
|
||||
JS::Result<LexicalScopeNode*> parseCatchClause();
|
||||
JS::Result<ParseNode*> parseDirective();
|
||||
JS::Result<ListNode*> parseFormalParameters();
|
||||
JS::Result<Ok> parseFunctionExpressionContents(
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<Ok> parseFunctionOrMethodContents(
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<Ok> parseGetterContents(
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<ParseNode*> parseIdentifierExpression();
|
||||
JS::Result<Ok> parseSetterContents(
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<CaseClause*> parseSwitchCase();
|
||||
JS::Result<ParseNode*> parseSwitchDefault();
|
||||
JS::Result<ParseNode*> parseVariableDeclarator();
|
||||
JS::Result<ParseNode*> parseInterfaceArrayAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceArrayBinding(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceArrayExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceAssertedBlockScope(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceAssertedBoundName(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseInterfaceAssertedBoundNamesScope(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceAssertedDeclaredName(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseInterfaceAssertedParameterScope(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<Ok> parseInterfaceAssertedPositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
AssertedScopeKind scopeKind,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<Ok> parseInterfaceAssertedScriptGlobalScope(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceAssertedVarScope(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBinaryExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBindingIdentifier(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBlock(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBreakStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceCallExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<LexicalScopeNode*> parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceClassExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceCompoundAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceComputedMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceComputedMemberExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceComputedPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceConditionalExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceContinueStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceDataProperty(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceDebuggerStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceDirective(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceDoWhileStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerGetter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerMethod(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerSetter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEmptyStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceForInOfBinding(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceForOfStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceForStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ListNode*> parseInterfaceFormalParameters(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceFunctionExpressionContents(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<Ok> parseInterfaceFunctionOrMethodContents(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<Ok> parseInterfaceGetterContents(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<ParseNode*> parseInterfaceIdentifierExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceIfStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyGetter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyMethod(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazySetter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralBooleanExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralInfinityExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralNullExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralNumericExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralRegExpExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralStringExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceModule(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceNewExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceNewTargetExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceObjectAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceObjectBinding(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceObjectExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceReturnStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceScript(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceSetterContents(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<ParseNode*> parseInterfaceShorthandProperty(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceStaticMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceStaticMemberExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSuper(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<CaseClause*> parseInterfaceSwitchCase(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSwitchDefault(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSwitchStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSwitchStatementWithDefault(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceTemplateExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceThisExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceThrowStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceTryCatchStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceTryFinallyStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceUnaryExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceUpdateExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceVariableDeclarator(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceWhileStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceWithStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceYieldExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceYieldStarExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
|
||||
// ----- String enums (by lexicographical order)
|
||||
JS::Result<typename BinASTParser<Tok>::AssertedDeclaredKind> parseAssertedDeclaredKind();
|
||||
JS::Result<typename BinASTParser<Tok>::BinaryOperator> parseBinaryOperator();
|
||||
JS::Result<typename BinASTParser<Tok>::CompoundAssignmentOperator> parseCompoundAssignmentOperator();
|
||||
JS::Result<typename BinASTParser<Tok>::UnaryOperator> parseUnaryOperator();
|
||||
JS::Result<typename BinASTParser<Tok>::UpdateOperator> parseUpdateOperator();
|
||||
JS::Result<typename BinASTParser<Tok>::VariableDeclarationKind> parseVariableDeclarationKind();
|
||||
|
||||
// ----- Lists (by lexicographical order)
|
||||
JS::Result<ParseNode*> parseArguments();
|
||||
JS::Result<ListNode*> parseFunctionBody();
|
||||
JS::Result<Ok> parseListOfAssertedBoundName(
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseListOfAssertedDeclaredName(
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseListOfAssertedMaybePositionalParameterName(
|
||||
AssertedScopeKind scopeKind,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<ListNode*> parseListOfDirective();
|
||||
JS::Result<ListNode*> parseListOfObjectProperty();
|
||||
JS::Result<ListNode*> parseListOfOptionalSpreadElementOrExpression();
|
||||
JS::Result<ListNode*> parseListOfParameter();
|
||||
JS::Result<ListNode*> parseListOfStatement();
|
||||
JS::Result<ListNode*> parseListOfSwitchCase();
|
||||
JS::Result<ListNode*> parseListOfVariableDeclarator();
|
||||
|
||||
// ----- Default values (by lexicographical order)
|
||||
JS::Result<ParseNode*> parseOptionalBinding();
|
||||
JS::Result<ParseNode*> parseOptionalBindingIdentifier();
|
||||
JS::Result<LexicalScopeNode*> parseOptionalCatchClause();
|
||||
JS::Result<ParseNode*> parseOptionalExpression();
|
||||
JS::Result<ParseNode*> parseOptionalSpreadElementOrExpression();
|
||||
JS::Result<ParseNode*> parseOptionalStatement();
|
||||
JS::Result<ParseNode*> parseOptionalVariableDeclarationOrExpression();
|
||||
|
||||
};
|
||||
|
||||
extern template class BinASTParser<BinTokenReaderMultipart>;
|
||||
extern template class BinASTParser<BinTokenReaderTester>;
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
#endif // frontend_BinASTParser_h
|
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "frontend/BinASTParserBase.h"
|
||||
|
||||
#include "vm/JSContext-inl.h"
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
|
||||
|
||||
BinASTParserBase::BinASTParserBase(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
Handle<LazyScript*> lazyScript)
|
||||
: AutoGCRooter(cx, AutoGCRooter::Tag::BinParser)
|
||||
, cx_(cx)
|
||||
, alloc_(alloc)
|
||||
, traceListHead_(nullptr)
|
||||
, usedNames_(usedNames)
|
||||
, nodeAlloc_(cx, alloc)
|
||||
, keepAtoms_(cx)
|
||||
, sourceObject_(cx, sourceObject)
|
||||
, lazyScript_(cx, lazyScript)
|
||||
, parseContext_(nullptr)
|
||||
, factory_(cx, alloc, nullptr, SourceKind::Binary)
|
||||
{
|
||||
MOZ_ASSERT_IF(lazyScript, lazyScript->isBinAST());
|
||||
cx->frontendCollectionPool().addActiveCompilation();
|
||||
tempPoolMark_ = alloc.mark();
|
||||
}
|
||||
|
||||
BinASTParserBase::~BinASTParserBase()
|
||||
{
|
||||
alloc_.release(tempPoolMark_);
|
||||
|
||||
/*
|
||||
* The parser can allocate enormous amounts of memory for large functions.
|
||||
* Eagerly free the memory now (which otherwise won't be freed until the
|
||||
* next GC) to avoid unnecessary OOMs.
|
||||
*/
|
||||
alloc_.freeAllIfHugeAndUnused();
|
||||
|
||||
cx_->frontendCollectionPool().removeActiveCompilation();
|
||||
}
|
||||
|
||||
bool
|
||||
BinASTParserBase::hasUsedName(HandlePropertyName name)
|
||||
{
|
||||
if (UsedNamePtr p = usedNames_.lookup(name)) {
|
||||
return p->value().isUsedInScript(parseContext_->scriptId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
|
@ -0,0 +1,89 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* 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/. */
|
||||
|
||||
#ifndef frontend_BinASTParserBase_h
|
||||
#define frontend_BinASTParserBase_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "frontend/BinTokenReaderMultipart.h"
|
||||
#include "frontend/BinTokenReaderTester.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
#include "frontend/ParseContext.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TracingAPI.h"
|
||||
#include "js/Utility.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSScript.h"
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
class BinASTParserBase : private JS::AutoGCRooter
|
||||
{
|
||||
public:
|
||||
BinASTParserBase(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames,
|
||||
HandleScriptSourceObject sourceObject, Handle<LazyScript*> lazyScript);
|
||||
~BinASTParserBase();
|
||||
|
||||
public:
|
||||
// Names
|
||||
|
||||
bool hasUsedName(HandlePropertyName name);
|
||||
|
||||
// --- GC.
|
||||
|
||||
virtual void doTrace(JSTracer* trc) {}
|
||||
|
||||
void trace(JSTracer* trc) {
|
||||
TraceListNode::TraceList(trc, traceListHead_);
|
||||
doTrace(trc);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
ParseNode* allocParseNode(size_t size) {
|
||||
MOZ_ASSERT(size == sizeof(ParseNode));
|
||||
return static_cast<ParseNode*>(nodeAlloc_.allocNode());
|
||||
}
|
||||
|
||||
JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
|
||||
|
||||
// Needs access to AutoGCRooter.
|
||||
friend void TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser);
|
||||
|
||||
protected:
|
||||
JSContext* cx_;
|
||||
|
||||
// ---- Memory-related stuff
|
||||
protected:
|
||||
LifoAlloc& alloc_;
|
||||
TraceListNode* traceListHead_;
|
||||
UsedNameTracker& usedNames_;
|
||||
private:
|
||||
LifoAlloc::Mark tempPoolMark_;
|
||||
ParseNodeAllocator nodeAlloc_;
|
||||
|
||||
// ---- Parsing-related stuff
|
||||
protected:
|
||||
// Root atoms and objects allocated for the parse tree.
|
||||
AutoKeepAtoms keepAtoms_;
|
||||
|
||||
RootedScriptSourceObject sourceObject_;
|
||||
Rooted<LazyScript*> lazyScript_;
|
||||
ParseContext* parseContext_;
|
||||
FullParseHandler factory_;
|
||||
|
||||
friend class BinParseContext;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
#endif // frontend_BinASTParserBase_h
|
|
@ -4,7 +4,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "frontend/BinSource.h"
|
||||
#include "frontend/BinASTParserPerTokenizer.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Casting.h"
|
||||
|
@ -14,6 +14,7 @@
|
|||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include "frontend/BinASTParser.h"
|
||||
#include "frontend/BinSource-macros.h"
|
||||
#include "frontend/BinTokenReaderTester.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
|
@ -77,50 +78,18 @@ namespace frontend {
|
|||
|
||||
using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
|
||||
|
||||
BinASTParserBase::BinASTParserBase(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames,
|
||||
HandleScriptSourceObject sourceObject, Handle<LazyScript*> lazyScript)
|
||||
: AutoGCRooter(cx, AutoGCRooter::Tag::BinParser)
|
||||
, cx_(cx)
|
||||
, alloc_(alloc)
|
||||
, traceListHead_(nullptr)
|
||||
, usedNames_(usedNames)
|
||||
, nodeAlloc_(cx, alloc)
|
||||
, keepAtoms_(cx)
|
||||
, sourceObject_(cx, sourceObject)
|
||||
, lazyScript_(cx, lazyScript)
|
||||
, parseContext_(nullptr)
|
||||
, factory_(cx, alloc, nullptr, SourceKind::Binary)
|
||||
{
|
||||
MOZ_ASSERT_IF(lazyScript, lazyScript->isBinAST());
|
||||
cx->frontendCollectionPool().addActiveCompilation();
|
||||
tempPoolMark_ = alloc.mark();
|
||||
}
|
||||
|
||||
BinASTParserBase::~BinASTParserBase()
|
||||
{
|
||||
alloc_.release(tempPoolMark_);
|
||||
|
||||
/*
|
||||
* The parser can allocate enormous amounts of memory for large functions.
|
||||
* Eagerly free the memory now (which otherwise won't be freed until the
|
||||
* next GC) to avoid unnecessary OOMs.
|
||||
*/
|
||||
alloc_.freeAllIfHugeAndUnused();
|
||||
|
||||
cx_->frontendCollectionPool().removeActiveCompilation();
|
||||
}
|
||||
|
||||
// ------------- Toplevel constructions
|
||||
|
||||
template<typename Tok> JS::Result<ParseNode*>
|
||||
BinASTParser<Tok>::parse(GlobalSharedContext* globalsc, const Vector<uint8_t>& data,
|
||||
BinASTParserPerTokenizer<Tok>::parse(GlobalSharedContext* globalsc, const Vector<uint8_t>& data,
|
||||
BinASTSourceMetadata** metadataPtr)
|
||||
{
|
||||
return parse(globalsc, data.begin(), data.length(), metadataPtr);
|
||||
}
|
||||
|
||||
template<typename Tok> JS::Result<ParseNode*>
|
||||
BinASTParser<Tok>::parse(GlobalSharedContext* globalsc, const uint8_t* start, const size_t length,
|
||||
BinASTParserPerTokenizer<Tok>::parse(GlobalSharedContext* globalsc, const uint8_t* start,
|
||||
const size_t length,
|
||||
BinASTSourceMetadata** metadataPtr)
|
||||
{
|
||||
auto result = parseAux(globalsc, start, length, metadataPtr);
|
||||
|
@ -130,7 +99,7 @@ BinASTParser<Tok>::parse(GlobalSharedContext* globalsc, const uint8_t* start, co
|
|||
|
||||
|
||||
template<typename Tok> JS::Result<ParseNode*>
|
||||
BinASTParser<Tok>::parseAux(GlobalSharedContext* globalsc,
|
||||
BinASTParserPerTokenizer<Tok>::parseAux(GlobalSharedContext* globalsc,
|
||||
const uint8_t* start, const size_t length,
|
||||
BinASTSourceMetadata** metadataPtr)
|
||||
{
|
||||
|
@ -151,7 +120,7 @@ BinASTParser<Tok>::parseAux(GlobalSharedContext* globalsc,
|
|||
MOZ_TRY(tokenizer_->readHeader());
|
||||
|
||||
ParseNode* result(nullptr);
|
||||
MOZ_TRY_VAR(result, parseProgram());
|
||||
MOZ_TRY_VAR(result, asFinalParser()->parseProgram());
|
||||
|
||||
mozilla::Maybe<GlobalScope::Data*> bindings = NewGlobalScopeData(cx_, varScope, alloc_,
|
||||
parseContext_);
|
||||
|
@ -168,7 +137,8 @@ BinASTParser<Tok>::parseAux(GlobalSharedContext* globalsc,
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<ParseNode*>
|
||||
BinASTParser<Tok>::parseLazyFunction(ScriptSource* scriptSource, const size_t firstOffset)
|
||||
BinASTParserPerTokenizer<Tok>::parseLazyFunction(ScriptSource* scriptSource,
|
||||
const size_t firstOffset)
|
||||
{
|
||||
MOZ_ASSERT(lazyScript_);
|
||||
MOZ_ASSERT(scriptSource->length() > firstOffset);
|
||||
|
@ -203,9 +173,9 @@ BinASTParser<Tok>::parseLazyFunction(ScriptSource* scriptSource, const size_t fi
|
|||
BINJS_TRY(lexicalScope.init(parseContext_));
|
||||
ListNode* params;
|
||||
ListNode* tmpBody;
|
||||
auto parseFunc = isExpr ? &BinASTParser::parseFunctionExpressionContents
|
||||
: &BinASTParser::parseFunctionOrMethodContents;
|
||||
MOZ_TRY((this->*parseFunc)(func->nargs(), ¶ms, &tmpBody));
|
||||
auto parseFunc = isExpr ? &FinalParser::parseFunctionExpressionContents
|
||||
: &FinalParser::parseFunctionOrMethodContents;
|
||||
MOZ_TRY((asFinalParser()->*parseFunc)(func->nargs(), ¶ms, &tmpBody));
|
||||
|
||||
BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
|
||||
BINJS_TRY_DECL(body, factory_.newLexicalScope(*lexicalScopeData, tmpBody));
|
||||
|
@ -215,7 +185,7 @@ BinASTParser<Tok>::parseLazyFunction(ScriptSource* scriptSource, const size_t fi
|
|||
}
|
||||
|
||||
template<typename Tok> void
|
||||
BinASTParser<Tok>::forceStrictIfNecessary(SharedContext* sc, ListNode* directives)
|
||||
BinASTParserPerTokenizer<Tok>::forceStrictIfNecessary(SharedContext* sc, ListNode* directives)
|
||||
{
|
||||
JSAtom* useStrict = cx_->names().useStrict;
|
||||
|
||||
|
@ -228,7 +198,7 @@ BinASTParser<Tok>::forceStrictIfNecessary(SharedContext* sc, ListNode* directive
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<FunctionBox*>
|
||||
BinASTParser<Tok>::buildFunctionBox(GeneratorKind generatorKind,
|
||||
BinASTParserPerTokenizer<Tok>::buildFunctionBox(GeneratorKind generatorKind,
|
||||
FunctionAsyncKind functionAsyncKind,
|
||||
FunctionSyntaxKind syntax,
|
||||
ParseNode* name)
|
||||
|
@ -288,7 +258,8 @@ BinASTParser<Tok>::buildFunctionBox(GeneratorKind generatorKind,
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<CodeNode*>
|
||||
BinASTParser<Tok>::makeEmptyFunctionNode(const size_t start, const BinKind kind, FunctionBox* funbox)
|
||||
BinASTParserPerTokenizer<Tok>::makeEmptyFunctionNode(const size_t start, const BinKind kind,
|
||||
FunctionBox* funbox)
|
||||
{
|
||||
// LazyScript compilation requires basically none of the fields filled out.
|
||||
TokenPos pos = tokenizer_->pos(start);
|
||||
|
@ -305,8 +276,9 @@ BinASTParser<Tok>::makeEmptyFunctionNode(const size_t start, const BinKind kind,
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<ParseNode*>
|
||||
BinASTParser<Tok>::buildFunction(const size_t start, const BinKind kind, ParseNode* name,
|
||||
ListNode* params, ParseNode* body, FunctionBox* funbox)
|
||||
BinASTParserPerTokenizer<Tok>::buildFunction(const size_t start, const BinKind kind,
|
||||
ParseNode* name, ListNode* params, ParseNode* body,
|
||||
FunctionBox* funbox)
|
||||
{
|
||||
// Set the argument count for building argument packets. Function.length is handled
|
||||
// by setting the appropriate funbox field during argument parsing.
|
||||
|
@ -404,7 +376,7 @@ BinASTParser<Tok>::buildFunction(const size_t start, const BinKind kind, ParseNo
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::addScopeName(AssertedScopeKind scopeKind, HandleAtom name,
|
||||
BinASTParserPerTokenizer<Tok>::addScopeName(AssertedScopeKind scopeKind, HandleAtom name,
|
||||
ParseContext::Scope* scope, DeclarationKind declKind,
|
||||
bool isCaptured, bool allowDuplicateName)
|
||||
{
|
||||
|
@ -429,7 +401,7 @@ BinASTParser<Tok>::addScopeName(AssertedScopeKind scopeKind, HandleAtom name,
|
|||
}
|
||||
|
||||
template<typename Tok> void
|
||||
BinASTParser<Tok>::captureFunctionName()
|
||||
BinASTParserPerTokenizer<Tok>::captureFunctionName()
|
||||
{
|
||||
MOZ_ASSERT(parseContext_->isFunctionBox());
|
||||
MOZ_ASSERT(parseContext_->functionBox()->function()->isNamedLambda());
|
||||
|
@ -443,8 +415,10 @@ BinASTParser<Tok>::captureFunctionName()
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::getDeclaredScope(AssertedScopeKind scopeKind, AssertedDeclaredKind kind,
|
||||
ParseContext::Scope*& scope, DeclarationKind& declKind)
|
||||
BinASTParserPerTokenizer<Tok>::getDeclaredScope(AssertedScopeKind scopeKind,
|
||||
AssertedDeclaredKind kind,
|
||||
ParseContext::Scope*& scope,
|
||||
DeclarationKind& declKind)
|
||||
{
|
||||
MOZ_ASSERT(scopeKind == AssertedScopeKind::Block ||
|
||||
scopeKind == AssertedScopeKind::Global ||
|
||||
|
@ -471,8 +445,9 @@ BinASTParser<Tok>::getDeclaredScope(AssertedScopeKind scopeKind, AssertedDeclare
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::getBoundScope(AssertedScopeKind scopeKind,
|
||||
ParseContext::Scope*& scope, DeclarationKind& declKind)
|
||||
BinASTParserPerTokenizer<Tok>::getBoundScope(AssertedScopeKind scopeKind,
|
||||
ParseContext::Scope*& scope,
|
||||
DeclarationKind& declKind)
|
||||
{
|
||||
MOZ_ASSERT(scopeKind == AssertedScopeKind::Catch ||
|
||||
scopeKind == AssertedScopeKind::Parameter);
|
||||
|
@ -495,7 +470,7 @@ BinASTParser<Tok>::getBoundScope(AssertedScopeKind scopeKind,
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::checkBinding(JSAtom* name)
|
||||
BinASTParserPerTokenizer<Tok>::checkBinding(JSAtom* name)
|
||||
{
|
||||
// Check that the variable appears in the corresponding scope.
|
||||
ParseContext::Scope& scope =
|
||||
|
@ -514,7 +489,7 @@ BinASTParser<Tok>::checkBinding(JSAtom* name)
|
|||
// Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda)
|
||||
// 3.1.5 CheckPositionalParameterIndices.
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> positionalParams,
|
||||
BinASTParserPerTokenizer<Tok>::checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> positionalParams,
|
||||
ListNode* params)
|
||||
{
|
||||
// positionalParams should have the corresponding entry up to the last
|
||||
|
@ -601,7 +576,7 @@ BinASTParser<Tok>::checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> pos
|
|||
// Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda)
|
||||
// 3.1.13 CheckFunctionLength.
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::checkFunctionLength(uint32_t expectedLength)
|
||||
BinASTParserPerTokenizer<Tok>::checkFunctionLength(uint32_t expectedLength)
|
||||
{
|
||||
if (parseContext_->functionBox()->length != expectedLength) {
|
||||
return raiseError("Function length does't match");
|
||||
|
@ -610,7 +585,7 @@ BinASTParser<Tok>::checkFunctionLength(uint32_t expectedLength)
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::checkClosedVars(ParseContext::Scope& scope)
|
||||
BinASTParserPerTokenizer<Tok>::checkClosedVars(ParseContext::Scope& scope)
|
||||
{
|
||||
for (ParseContext::Scope::BindingIter bi = scope.bindings(parseContext_); bi; bi++) {
|
||||
if (UsedNamePtr p = usedNames_.lookup(bi.name())) {
|
||||
|
@ -626,7 +601,7 @@ BinASTParser<Tok>::checkClosedVars(ParseContext::Scope& scope)
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::checkFunctionClosedVars()
|
||||
BinASTParserPerTokenizer<Tok>::checkFunctionClosedVars()
|
||||
{
|
||||
MOZ_ASSERT(parseContext_->isFunctionBox());
|
||||
|
||||
|
@ -640,7 +615,7 @@ BinASTParser<Tok>::checkFunctionClosedVars()
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::prependDirectivesToBody(ListNode* body, ListNode* directives)
|
||||
BinASTParserPerTokenizer<Tok>::prependDirectivesToBody(ListNode* body, ListNode* directives)
|
||||
{
|
||||
if (!directives) {
|
||||
return Ok();
|
||||
|
@ -656,7 +631,7 @@ BinASTParser<Tok>::prependDirectivesToBody(ListNode* body, ListNode* directives)
|
|||
}
|
||||
|
||||
template<typename Tok> JS::Result<Ok>
|
||||
BinASTParser<Tok>::prependDirectivesImpl(ListNode* body, ParseNode* directive)
|
||||
BinASTParserPerTokenizer<Tok>::prependDirectivesImpl(ListNode* body, ParseNode* directive)
|
||||
{
|
||||
BINJS_TRY(CheckRecursionLimit(cx_));
|
||||
|
||||
|
@ -673,13 +648,13 @@ BinASTParser<Tok>::prependDirectivesImpl(ListNode* body, ParseNode* directive)
|
|||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseInvalidClosedVar(JSAtom* name)
|
||||
BinASTParserPerTokenizer<Tok>::raiseInvalidClosedVar(JSAtom* name)
|
||||
{
|
||||
return raiseError("Captured variable was not declared as captured");
|
||||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseMissingVariableInAssertedScope(JSAtom* name)
|
||||
BinASTParserPerTokenizer<Tok>::raiseMissingVariableInAssertedScope(JSAtom* name)
|
||||
{
|
||||
// For the moment, we don't trust inputs sufficiently to put the name
|
||||
// in an error message.
|
||||
|
@ -687,13 +662,13 @@ BinASTParser<Tok>::raiseMissingVariableInAssertedScope(JSAtom* name)
|
|||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseMissingDirectEvalInAssertedScope()
|
||||
BinASTParserPerTokenizer<Tok>::raiseMissingDirectEvalInAssertedScope()
|
||||
{
|
||||
return raiseError("Direct call to `eval` was not declared in AssertedScope");
|
||||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseInvalidKind(const char* superKind, const BinKind kind)
|
||||
BinASTParserPerTokenizer<Tok>::raiseInvalidKind(const char* superKind, const BinKind kind)
|
||||
{
|
||||
Sprinter out(cx_);
|
||||
BINJS_TRY(out.init());
|
||||
|
@ -702,7 +677,7 @@ BinASTParser<Tok>::raiseInvalidKind(const char* superKind, const BinKind kind)
|
|||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseInvalidVariant(const char* kind, const BinVariant value)
|
||||
BinASTParserPerTokenizer<Tok>::raiseInvalidVariant(const char* kind, const BinVariant value)
|
||||
{
|
||||
Sprinter out(cx_);
|
||||
BINJS_TRY(out.init());
|
||||
|
@ -712,7 +687,7 @@ BinASTParser<Tok>::raiseInvalidVariant(const char* kind, const BinVariant value)
|
|||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseMissingField(const char* kind, const BinField field)
|
||||
BinASTParserPerTokenizer<Tok>::raiseMissingField(const char* kind, const BinField field)
|
||||
{
|
||||
Sprinter out(cx_);
|
||||
BINJS_TRY(out.init());
|
||||
|
@ -722,7 +697,7 @@ BinASTParser<Tok>::raiseMissingField(const char* kind, const BinField field)
|
|||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseEmpty(const char* description)
|
||||
BinASTParserPerTokenizer<Tok>::raiseEmpty(const char* description)
|
||||
{
|
||||
Sprinter out(cx_);
|
||||
BINJS_TRY(out.init());
|
||||
|
@ -732,13 +707,13 @@ BinASTParser<Tok>::raiseEmpty(const char* description)
|
|||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseOOM()
|
||||
BinASTParserPerTokenizer<Tok>::raiseOOM()
|
||||
{
|
||||
return tokenizer_->raiseOOM();
|
||||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseError(BinKind kind, const char* description)
|
||||
BinASTParserPerTokenizer<Tok>::raiseError(BinKind kind, const char* description)
|
||||
{
|
||||
Sprinter out(cx_);
|
||||
BINJS_TRY(out.init());
|
||||
|
@ -747,19 +722,19 @@ BinASTParser<Tok>::raiseError(BinKind kind, const char* description)
|
|||
}
|
||||
|
||||
template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
|
||||
BinASTParser<Tok>::raiseError(const char* description)
|
||||
BinASTParserPerTokenizer<Tok>::raiseError(const char* description)
|
||||
{
|
||||
return tokenizer_->raiseError(description);
|
||||
}
|
||||
|
||||
template<typename Tok> void
|
||||
BinASTParser<Tok>::poison()
|
||||
BinASTParserPerTokenizer<Tok>::poison()
|
||||
{
|
||||
tokenizer_.reset();
|
||||
}
|
||||
|
||||
template<typename Tok> void
|
||||
BinASTParser<Tok>::reportErrorNoOffsetVA(unsigned errorNumber, va_list args)
|
||||
BinASTParserPerTokenizer<Tok>::reportErrorNoOffsetVA(unsigned errorNumber, va_list args)
|
||||
{
|
||||
ErrorMetadata metadata;
|
||||
metadata.filename = getFilename();
|
||||
|
@ -770,7 +745,7 @@ BinASTParser<Tok>::reportErrorNoOffsetVA(unsigned errorNumber, va_list args)
|
|||
}
|
||||
|
||||
template<typename Tok> void
|
||||
BinASTParser<Tok>::errorAtVA(uint32_t offset, unsigned errorNumber, va_list* args)
|
||||
BinASTParserPerTokenizer<Tok>::errorAtVA(uint32_t offset, unsigned errorNumber, va_list* args)
|
||||
{
|
||||
ErrorMetadata metadata;
|
||||
metadata.filename = getFilename();
|
||||
|
@ -781,7 +756,9 @@ BinASTParser<Tok>::errorAtVA(uint32_t offset, unsigned errorNumber, va_list* arg
|
|||
}
|
||||
|
||||
template<typename Tok> bool
|
||||
BinASTParser<Tok>::reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset, unsigned errorNumber, va_list* args)
|
||||
BinASTParserPerTokenizer<Tok>::reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes,
|
||||
uint32_t offset,
|
||||
unsigned errorNumber, va_list* args)
|
||||
{
|
||||
if (!options().extraWarningsOption) {
|
||||
return true;
|
||||
|
@ -801,16 +778,6 @@ BinASTParser<Tok>::reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes
|
|||
return ReportCompileWarning(cx_, std::move(metadata), std::move(notes), JSREPORT_STRICT | JSREPORT_WARNING, errorNumber, *args);
|
||||
}
|
||||
|
||||
bool
|
||||
BinASTParserBase::hasUsedName(HandlePropertyName name)
|
||||
{
|
||||
if (UsedNamePtr p = usedNames_.lookup(name)) {
|
||||
return p->value().isUsedInScript(parseContext_->scriptId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser)
|
||||
{
|
||||
|
@ -819,18 +786,40 @@ TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser)
|
|||
|
||||
template<typename Tok>
|
||||
void
|
||||
BinASTParser<Tok>::doTrace(JSTracer* trc)
|
||||
BinASTParserPerTokenizer<Tok>::doTrace(JSTracer* trc)
|
||||
{
|
||||
if (tokenizer_) {
|
||||
tokenizer_->traceMetadata(trc);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Tok>
|
||||
inline typename BinASTParserPerTokenizer<Tok>::FinalParser*
|
||||
BinASTParserPerTokenizer<Tok>::asFinalParser()
|
||||
{
|
||||
// Same as GeneralParser::asFinalParser, verify the inheritance to
|
||||
// make sure the static downcast works.
|
||||
static_assert(mozilla::IsBaseOf<BinASTParserPerTokenizer<Tok>, FinalParser>::value,
|
||||
"inheritance relationship required by the static_cast<> below");
|
||||
|
||||
return static_cast<FinalParser*>(this);
|
||||
}
|
||||
|
||||
template<typename Tok>
|
||||
inline const typename BinASTParserPerTokenizer<Tok>::FinalParser*
|
||||
BinASTParserPerTokenizer<Tok>::asFinalParser() const
|
||||
{
|
||||
static_assert(mozilla::IsBaseOf<BinASTParserPerTokenizer<Tok>, FinalParser>::value,
|
||||
"inheritance relationship required by the static_cast<> below");
|
||||
|
||||
return static_cast<const FinalParser*>(this);
|
||||
}
|
||||
|
||||
// Force class instantiation.
|
||||
// This ensures that the symbols are built, without having to export all our
|
||||
// code (and its baggage of #include and macros) in the header.
|
||||
template class BinASTParser<BinTokenReaderMultipart>;
|
||||
template class BinASTParser<BinTokenReaderTester>;
|
||||
template class BinASTParserPerTokenizer<BinTokenReaderMultipart>;
|
||||
template class BinASTParserPerTokenizer<BinTokenReaderTester>;
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
|
@ -4,8 +4,8 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef frontend_BinSource_h
|
||||
#define frontend_BinSource_h
|
||||
#ifndef frontend_BinASTParserPerTokenizer_h
|
||||
#define frontend_BinASTParserPerTokenizer_h
|
||||
|
||||
/**
|
||||
* A Binary AST parser.
|
||||
|
@ -17,6 +17,8 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "frontend/BCEParserHandle.h"
|
||||
#include "frontend/BinASTEnum.h"
|
||||
#include "frontend/BinASTParserBase.h"
|
||||
#include "frontend/BinToken.h"
|
||||
#include "frontend/BinTokenReaderMultipart.h"
|
||||
#include "frontend/BinTokenReaderTester.h"
|
||||
|
@ -33,64 +35,8 @@
|
|||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
class BinASTParserBase: private JS::AutoGCRooter
|
||||
{
|
||||
public:
|
||||
BinASTParserBase(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames,
|
||||
HandleScriptSourceObject sourceObject, Handle<LazyScript*> lazyScript);
|
||||
~BinASTParserBase();
|
||||
|
||||
public:
|
||||
// Names
|
||||
|
||||
|
||||
bool hasUsedName(HandlePropertyName name);
|
||||
|
||||
// --- GC.
|
||||
|
||||
virtual void doTrace(JSTracer* trc) {}
|
||||
|
||||
void trace(JSTracer* trc) {
|
||||
TraceListNode::TraceList(trc, traceListHead_);
|
||||
doTrace(trc);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
ParseNode* allocParseNode(size_t size) {
|
||||
MOZ_ASSERT(size == sizeof(ParseNode));
|
||||
return static_cast<ParseNode*>(nodeAlloc_.allocNode());
|
||||
}
|
||||
|
||||
JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
|
||||
|
||||
// Needs access to AutoGCRooter.
|
||||
friend void TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser);
|
||||
|
||||
protected:
|
||||
JSContext* cx_;
|
||||
|
||||
// ---- Memory-related stuff
|
||||
protected:
|
||||
LifoAlloc& alloc_;
|
||||
TraceListNode* traceListHead_;
|
||||
UsedNameTracker& usedNames_;
|
||||
private:
|
||||
LifoAlloc::Mark tempPoolMark_;
|
||||
ParseNodeAllocator nodeAlloc_;
|
||||
|
||||
// ---- Parsing-related stuff
|
||||
protected:
|
||||
// Root atoms and objects allocated for the parse tree.
|
||||
AutoKeepAtoms keepAtoms_;
|
||||
|
||||
RootedScriptSourceObject sourceObject_;
|
||||
Rooted<LazyScript*> lazyScript_;
|
||||
ParseContext* parseContext_;
|
||||
FullParseHandler factory_;
|
||||
|
||||
friend class BinParseContext;
|
||||
};
|
||||
template<typename Tok>
|
||||
class BinASTParser;
|
||||
|
||||
/**
|
||||
* The parser for a Binary AST.
|
||||
|
@ -99,7 +45,7 @@ class BinASTParserBase: private JS::AutoGCRooter
|
|||
* recoverable.
|
||||
*/
|
||||
template<typename Tok>
|
||||
class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEParserHandle
|
||||
class BinASTParserPerTokenizer : public BinASTParserBase, public ErrorReporter, public BCEParserHandle
|
||||
{
|
||||
public:
|
||||
using Tokenizer = Tok;
|
||||
|
@ -111,14 +57,21 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
|
|||
using Chars = typename Tokenizer::Chars;
|
||||
|
||||
public:
|
||||
BinASTParser(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames, const JS::ReadOnlyCompileOptions& options,
|
||||
HandleScriptSourceObject sourceObject, Handle<LazyScript*> lazyScript = nullptr)
|
||||
// Auto-generated types.
|
||||
using AssertedDeclaredKind = binast::AssertedDeclaredKind;
|
||||
using VariableDeclarationKind = binast::VariableDeclarationKind;
|
||||
|
||||
public:
|
||||
BinASTParserPerTokenizer(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames,
|
||||
const JS::ReadOnlyCompileOptions& options,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
Handle<LazyScript*> lazyScript = nullptr)
|
||||
: BinASTParserBase(cx, alloc, usedNames, sourceObject, lazyScript)
|
||||
, options_(options)
|
||||
, variableDeclarationKind_(VariableDeclarationKind::Var)
|
||||
{
|
||||
}
|
||||
~BinASTParser()
|
||||
~BinASTParserPerTokenizer()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -126,8 +79,9 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
|
|||
* Parse a buffer, returning a node (which may be nullptr) in case of success
|
||||
* or Nothing() in case of error.
|
||||
*
|
||||
* The instance of `ParseNode` MAY NOT survive the `BinASTParser`. Indeed,
|
||||
* destruction of the `BinASTParser` will also destroy the `ParseNode`.
|
||||
* The instance of `ParseNode` MAY NOT survive the
|
||||
* `BinASTParserPerTokenizer`. Indeed, destruction of the
|
||||
* `BinASTParserPerTokenizer` will also destroy the `ParseNode`.
|
||||
*
|
||||
* In case of error, the parser reports the JS error.
|
||||
*/
|
||||
|
@ -139,7 +93,7 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
|
|||
|
||||
JS::Result<ParseNode*> parseLazyFunction(ScriptSource* src, const size_t firstOffset);
|
||||
|
||||
private:
|
||||
protected:
|
||||
MOZ_MUST_USE JS::Result<ParseNode*> parseAux(GlobalSharedContext* globalsc,
|
||||
const uint8_t* start, const size_t length,
|
||||
BinASTSourceMetadata** metadataPtr = nullptr);
|
||||
|
@ -176,9 +130,6 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
|
|||
Var,
|
||||
};
|
||||
|
||||
// Auto-generated methods
|
||||
#include "frontend/BinSource-auto.h"
|
||||
|
||||
// --- Auxiliary parsing functions
|
||||
|
||||
// Build a function object for a function-producing production. Called AFTER creating the scope.
|
||||
|
@ -235,7 +186,7 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
|
|||
// directive.
|
||||
void forceStrictIfNecessary(SharedContext* sc, ListNode* directives);
|
||||
|
||||
private: // Implement ErrorReporter
|
||||
protected: // Implement ErrorReporter
|
||||
const JS::ReadOnlyCompileOptions& options_;
|
||||
|
||||
const JS::ReadOnlyCompileOptions& options() const override {
|
||||
|
@ -319,7 +270,7 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
|
|||
return this->options_.filename();
|
||||
}
|
||||
|
||||
private: // Implement ErrorReporter
|
||||
protected: // Implement ErrorReporter
|
||||
mozilla::Maybe<Tokenizer> tokenizer_;
|
||||
VariableDeclarationKind variableDeclarationKind_;
|
||||
|
||||
|
@ -329,7 +280,7 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
|
|||
// Helper class: Restore field `variableDeclarationKind` upon leaving a scope.
|
||||
class MOZ_RAII AutoVariableDeclarationKind {
|
||||
public:
|
||||
explicit AutoVariableDeclarationKind(BinASTParser<Tok>* parser
|
||||
explicit AutoVariableDeclarationKind(BinASTParserPerTokenizer<Tok>* parser
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: parser_(parser)
|
||||
, kind(parser->variableDeclarationKind_)
|
||||
|
@ -340,17 +291,27 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
|
|||
parser_->variableDeclarationKind_ = kind;
|
||||
}
|
||||
private:
|
||||
BinASTParser<Tok>* parser_;
|
||||
BinASTParser<Tok>::VariableDeclarationKind kind;
|
||||
BinASTParserPerTokenizer<Tok>* parser_;
|
||||
BinASTParserPerTokenizer<Tok>::VariableDeclarationKind kind;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
private:
|
||||
// Some methods in this class require access to auto-generated methods in
|
||||
// BinASTParser which derives this class.
|
||||
// asFinalParser methods provide the access to BinASTParser class methods
|
||||
// of this instance.
|
||||
using FinalParser = BinASTParser<Tok>;
|
||||
|
||||
inline FinalParser* asFinalParser();
|
||||
inline const FinalParser* asFinalParser() const;
|
||||
};
|
||||
|
||||
class BinParseContext : public ParseContext
|
||||
{
|
||||
public:
|
||||
template<typename Tok>
|
||||
BinParseContext(JSContext* cx, BinASTParser<Tok>* parser, SharedContext* sc,
|
||||
BinParseContext(JSContext* cx, BinASTParserPerTokenizer<Tok>* parser, SharedContext* sc,
|
||||
Directives* newDirectives)
|
||||
: ParseContext(cx, parser->parseContext_, sc, *parser,
|
||||
parser->usedNames_, newDirectives, /* isFull = */ true)
|
||||
|
@ -358,10 +319,10 @@ class BinParseContext : public ParseContext
|
|||
};
|
||||
|
||||
|
||||
extern template class BinASTParser<BinTokenReaderMultipart>;
|
||||
extern template class BinASTParser<BinTokenReaderTester>;
|
||||
extern template class BinASTParserPerTokenizer<BinTokenReaderMultipart>;
|
||||
extern template class BinASTParserPerTokenizer<BinTokenReaderTester>;
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
#endif // frontend_BinSource_h
|
||||
#endif // frontend_BinASTParserPerTokenizer_h
|
|
@ -1,319 +0,0 @@
|
|||
// This file was autogenerated by binjs_generate_spidermonkey,
|
||||
// please DO NOT EDIT BY HAND.
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* 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/. */
|
||||
|
||||
// To generate this file, see the documentation in
|
||||
// js/src/frontend/binsource/README.md.
|
||||
|
||||
// This file is meant to be included from the declaration
|
||||
// of class `BinASTParser`. The include may be public or private.
|
||||
|
||||
|
||||
// ----- Declaring string enums (by lexicographical order)
|
||||
enum class AssertedDeclaredKind {
|
||||
Var /* "var" */,
|
||||
NonConstLexical /* "non-const lexical" */,
|
||||
ConstLexical /* "const lexical" */
|
||||
};
|
||||
|
||||
enum class BinaryOperator {
|
||||
Comma /* "," */,
|
||||
LogicalOr /* "||" */,
|
||||
LogicalAnd /* "&&" */,
|
||||
BitOr /* "|" */,
|
||||
BitXor /* "^" */,
|
||||
BitAnd /* "&" */,
|
||||
Eq /* "==" */,
|
||||
Neq /* "!=" */,
|
||||
StrictEq /* "===" */,
|
||||
StrictNeq /* "!==" */,
|
||||
LessThan /* "<" */,
|
||||
LeqThan /* "<=" */,
|
||||
GreaterThan /* ">" */,
|
||||
GeqThan /* ">=" */,
|
||||
In /* "in" */,
|
||||
Instanceof /* "instanceof" */,
|
||||
Lsh /* "<<" */,
|
||||
Rsh /* ">>" */,
|
||||
Ursh /* ">>>" */,
|
||||
Plus /* "+" */,
|
||||
Minus /* "-" */,
|
||||
Mul /* "*" */,
|
||||
Div /* "/" */,
|
||||
Mod /* "%" */,
|
||||
Pow /* "**" */
|
||||
};
|
||||
|
||||
enum class CompoundAssignmentOperator {
|
||||
PlusAssign /* "+=" */,
|
||||
MinusAssign /* "-=" */,
|
||||
MulAssign /* "*=" */,
|
||||
DivAssign /* "/=" */,
|
||||
ModAssign /* "%=" */,
|
||||
PowAssign /* "**=" */,
|
||||
LshAssign /* "<<=" */,
|
||||
RshAssign /* ">>=" */,
|
||||
UrshAssign /* ">>>=" */,
|
||||
BitOrAssign /* "|=" */,
|
||||
BitXorAssign /* "^=" */,
|
||||
BitAndAssign /* "&=" */
|
||||
};
|
||||
|
||||
enum class UnaryOperator {
|
||||
Plus /* "+" */,
|
||||
Minus /* "-" */,
|
||||
Not /* "!" */,
|
||||
BitNot /* "~" */,
|
||||
Typeof /* "typeof" */,
|
||||
Void /* "void" */,
|
||||
Delete /* "delete" */
|
||||
};
|
||||
|
||||
enum class UpdateOperator {
|
||||
Incr /* "++" */,
|
||||
Decr /* "--" */
|
||||
};
|
||||
|
||||
enum class VariableDeclarationKind {
|
||||
Var /* "var" */,
|
||||
Let /* "let" */,
|
||||
Const /* "const" */
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ----- Sums of interfaces (by lexicographical order)
|
||||
// Implementations are autogenerated
|
||||
// `ParseNode*` may never be nullptr
|
||||
JS::Result<Ok> parseAssertedMaybePositionalParameterName(
|
||||
AssertedScopeKind scopeKind,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<ParseNode*> parseAssignmentTarget();
|
||||
JS::Result<ParseNode*> parseBinding();
|
||||
JS::Result<ParseNode*> parseExpression();
|
||||
JS::Result<ParseNode*> parseExpressionOrSuper();
|
||||
JS::Result<ParseNode*> parseForInOfBindingOrAssignmentTarget();
|
||||
JS::Result<ParseNode*> parseObjectProperty();
|
||||
JS::Result<ParseNode*> parseParameter();
|
||||
JS::Result<ParseNode*> parseProgram();
|
||||
JS::Result<ParseNode*> parsePropertyName();
|
||||
JS::Result<ParseNode*> parseSimpleAssignmentTarget();
|
||||
JS::Result<ParseNode*> parseSpreadElementOrExpression();
|
||||
JS::Result<ParseNode*> parseStatement();
|
||||
JS::Result<Ok> parseSumAssertedMaybePositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
AssertedScopeKind scopeKind,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<ParseNode*> parseSumAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumBinding(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumExpressionOrSuper(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumForInOfBindingOrAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumObjectProperty(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumParameter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumProgram(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumSimpleAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumSpreadElementOrExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseSumVariableDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
|
||||
|
||||
// ----- Interfaces (by lexicographical order)
|
||||
// Implementations are autogenerated
|
||||
// `ParseNode*` may never be nullptr
|
||||
JS::Result<Ok> parseAssertedBlockScope();
|
||||
JS::Result<Ok> parseAssertedBoundName(
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseAssertedBoundNamesScope();
|
||||
JS::Result<Ok> parseAssertedDeclaredName(
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseAssertedParameterScope(
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<Ok> parseAssertedScriptGlobalScope();
|
||||
JS::Result<Ok> parseAssertedVarScope();
|
||||
JS::Result<ParseNode*> parseBindingIdentifier();
|
||||
JS::Result<ParseNode*> parseBlock();
|
||||
JS::Result<LexicalScopeNode*> parseCatchClause();
|
||||
JS::Result<ParseNode*> parseDirective();
|
||||
JS::Result<ListNode*> parseFormalParameters();
|
||||
JS::Result<Ok> parseFunctionExpressionContents(
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<Ok> parseFunctionOrMethodContents(
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<Ok> parseGetterContents(
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<ParseNode*> parseIdentifierExpression();
|
||||
JS::Result<Ok> parseSetterContents(
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<CaseClause*> parseSwitchCase();
|
||||
JS::Result<ParseNode*> parseSwitchDefault();
|
||||
JS::Result<ParseNode*> parseVariableDeclarator();
|
||||
JS::Result<ParseNode*> parseInterfaceArrayAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceArrayBinding(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceArrayExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceAssertedBlockScope(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceAssertedBoundName(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseInterfaceAssertedBoundNamesScope(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceAssertedDeclaredName(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseInterfaceAssertedParameterScope(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<Ok> parseInterfaceAssertedPositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
AssertedScopeKind scopeKind,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<Ok> parseInterfaceAssertedScriptGlobalScope(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceAssertedVarScope(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBinaryExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBindingIdentifier(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBlock(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceBreakStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceCallExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<LexicalScopeNode*> parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceClassExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceCompoundAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceComputedMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceComputedMemberExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceComputedPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceConditionalExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceContinueStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceDataProperty(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceDebuggerStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceDirective(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceDoWhileStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerGetter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerMethod(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEagerSetter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceEmptyStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceForInOfBinding(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceForOfStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceForStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ListNode*> parseInterfaceFormalParameters(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceFunctionExpressionContents(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<Ok> parseInterfaceFunctionOrMethodContents(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<Ok> parseInterfaceGetterContents(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<ParseNode*> parseInterfaceIdentifierExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceIfStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyGetter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazyMethod(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLazySetter(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralBooleanExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralInfinityExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralNullExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralNumericExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralPropertyName(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralRegExpExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceLiteralStringExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceModule(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceNewExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceNewTargetExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceObjectAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceObjectBinding(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceObjectExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceReturnStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceScript(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<Ok> parseInterfaceSetterContents(const size_t start, const BinKind kind, const BinFields& fields,
|
||||
uint32_t funLength,
|
||||
ListNode** paramsOut,
|
||||
ListNode** bodyOut);
|
||||
JS::Result<ParseNode*> parseInterfaceShorthandProperty(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceStaticMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceStaticMemberExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSuper(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<CaseClause*> parseInterfaceSwitchCase(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSwitchDefault(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSwitchStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceSwitchStatementWithDefault(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceTemplateExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceThisExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceThrowStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceTryCatchStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceTryFinallyStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceUnaryExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceUpdateExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceVariableDeclarator(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceWhileStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceWithStatement(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceYieldExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
JS::Result<ParseNode*> parseInterfaceYieldStarExpression(const size_t start, const BinKind kind, const BinFields& fields);
|
||||
|
||||
|
||||
// ----- String enums (by lexicographical order)
|
||||
// Implementations are autogenerated
|
||||
JS::Result<typename BinASTParser<Tok>::AssertedDeclaredKind> parseAssertedDeclaredKind();
|
||||
JS::Result<typename BinASTParser<Tok>::BinaryOperator> parseBinaryOperator();
|
||||
JS::Result<typename BinASTParser<Tok>::CompoundAssignmentOperator> parseCompoundAssignmentOperator();
|
||||
JS::Result<typename BinASTParser<Tok>::UnaryOperator> parseUnaryOperator();
|
||||
JS::Result<typename BinASTParser<Tok>::UpdateOperator> parseUpdateOperator();
|
||||
JS::Result<typename BinASTParser<Tok>::VariableDeclarationKind> parseVariableDeclarationKind();
|
||||
|
||||
|
||||
// ----- Lists (by lexicographical order)
|
||||
// Implementations are autogenerated
|
||||
JS::Result<ParseNode*> parseArguments();
|
||||
JS::Result<ListNode*> parseFunctionBody();
|
||||
JS::Result<Ok> parseListOfAssertedBoundName(
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseListOfAssertedDeclaredName(
|
||||
AssertedScopeKind scopeKind);
|
||||
JS::Result<Ok> parseListOfAssertedMaybePositionalParameterName(
|
||||
AssertedScopeKind scopeKind,
|
||||
MutableHandle<GCVector<JSAtom*>> positionalParams);
|
||||
JS::Result<ListNode*> parseListOfDirective();
|
||||
JS::Result<ListNode*> parseListOfObjectProperty();
|
||||
JS::Result<ListNode*> parseListOfOptionalSpreadElementOrExpression();
|
||||
JS::Result<ListNode*> parseListOfParameter();
|
||||
JS::Result<ListNode*> parseListOfStatement();
|
||||
JS::Result<ListNode*> parseListOfSwitchCase();
|
||||
JS::Result<ListNode*> parseListOfVariableDeclarator();
|
||||
|
||||
|
||||
// ----- Default values (by lexicographical order)
|
||||
// Implementations are autogenerated
|
||||
JS::Result<ParseNode*> parseOptionalBinding();
|
||||
JS::Result<ParseNode*> parseOptionalBindingIdentifier();
|
||||
JS::Result<LexicalScopeNode*> parseOptionalCatchClause();
|
||||
JS::Result<ParseNode*> parseOptionalExpression();
|
||||
JS::Result<ParseNode*> parseOptionalSpreadElementOrExpression();
|
||||
JS::Result<ParseNode*> parseOptionalStatement();
|
||||
JS::Result<ParseNode*> parseOptionalVariableDeclarationOrExpression();
|
||||
|
|
@ -15,7 +15,7 @@ parser:
|
|||
append: |
|
||||
result->appendWithoutOrderAssumption(item);
|
||||
|
||||
# Rules for generating BinSource-auto.cpp
|
||||
# Rules for generating BinASTParser.cpp
|
||||
cpp:
|
||||
header: |
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
|
@ -27,6 +27,8 @@ cpp:
|
|||
// To generate this file, see the documentation in
|
||||
// js/src/frontend/binsource/README.md.
|
||||
|
||||
#include "frontend/BinASTParser.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
@ -35,7 +37,6 @@ cpp:
|
|||
#include "mozilla/Vector.h"
|
||||
|
||||
#include "frontend/BinSource-macros.h"
|
||||
#include "frontend/BinSource.h"
|
||||
#include "frontend/BinTokenReaderTester.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
|
@ -70,7 +71,7 @@ cpp:
|
|||
|
||||
|
||||
hpp:
|
||||
# Rules for generating BinSource-class.h
|
||||
# Rules for generating BinASTParser.h
|
||||
class:
|
||||
header: |
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
|
@ -82,8 +83,150 @@ hpp:
|
|||
// To generate this file, see the documentation in
|
||||
// js/src/frontend/binsource/README.md.
|
||||
|
||||
// This file is meant to be included from the declaration
|
||||
// of class `BinASTParser`. The include may be public or private.
|
||||
#ifndef frontend_BinASTParser_h
|
||||
#define frontend_BinASTParser_h
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "frontend/BCEParserHandle.h"
|
||||
#include "frontend/BinASTParserPerTokenizer.h"
|
||||
#include "frontend/BinToken.h"
|
||||
#include "frontend/BinTokenReaderMultipart.h"
|
||||
#include "frontend/BinTokenReaderTester.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
#include "frontend/ParseContext.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
|
||||
#include "js/CompileOptions.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/GCVector.h"
|
||||
#include "js/Result.h"
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
template<typename Tok>
|
||||
class BinASTParser : public BinASTParserPerTokenizer<Tok>
|
||||
{
|
||||
public:
|
||||
using Base = BinASTParserPerTokenizer<Tok>;
|
||||
|
||||
using Tokenizer = Tok;
|
||||
|
||||
using BinFields = typename Tokenizer::BinFields;
|
||||
using AutoList = typename Tokenizer::AutoList;
|
||||
using AutoTaggedTuple = typename Tokenizer::AutoTaggedTuple;
|
||||
using AutoTuple = typename Tokenizer::AutoTuple;
|
||||
using Chars = typename Tokenizer::Chars;
|
||||
|
||||
public:
|
||||
// Auto-generated types.
|
||||
using AssertedDeclaredKind = binast::AssertedDeclaredKind;
|
||||
using BinaryOperator = binast::BinaryOperator;
|
||||
using CompoundAssignmentOperator = binast::CompoundAssignmentOperator;
|
||||
using UnaryOperator = binast::UnaryOperator;
|
||||
using UpdateOperator = binast::UpdateOperator;
|
||||
using VariableDeclarationKind = binast::VariableDeclarationKind;
|
||||
|
||||
public:
|
||||
// BinASTParserPerTokenizer types.
|
||||
using AssertedScopeKind = typename Base::AssertedScopeKind;
|
||||
|
||||
public:
|
||||
BinASTParser(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames,
|
||||
const JS::ReadOnlyCompileOptions& options,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
Handle<LazyScript*> lazyScript = nullptr)
|
||||
: BinASTParserPerTokenizer<Tok>(cx, alloc, usedNames, options, sourceObject, lazyScript)
|
||||
{}
|
||||
~BinASTParser()
|
||||
{}
|
||||
|
||||
protected:
|
||||
// BinASTParserBase fields.
|
||||
using Base::cx_;
|
||||
|
||||
using Base::alloc_;
|
||||
using Base::usedNames_;
|
||||
|
||||
using Base::sourceObject_;
|
||||
using Base::parseContext_;
|
||||
using Base::factory_;
|
||||
|
||||
protected:
|
||||
// BinASTParserPerTokenizer types.
|
||||
using AutoVariableDeclarationKind = typename Base::AutoVariableDeclarationKind;
|
||||
protected:
|
||||
// BinASTParserPerTokenizer fields.
|
||||
using Base::tokenizer_;
|
||||
using Base::variableDeclarationKind_;
|
||||
|
||||
protected:
|
||||
// BinASTParserPerTokenizer methods.
|
||||
using Base::raiseInvalidClosedVar;
|
||||
using Base::raiseMissingVariableInAssertedScope;
|
||||
using Base::raiseMissingDirectEvalInAssertedScope;
|
||||
using Base::raiseInvalidKind;
|
||||
using Base::raiseInvalidVariant;
|
||||
using Base::raiseMissingField;
|
||||
using Base::raiseEmpty;
|
||||
using Base::raiseOOM;
|
||||
using Base::raiseError;
|
||||
|
||||
using Base::makeEmptyFunctionNode;
|
||||
using Base::buildFunction;
|
||||
using Base::buildFunctionBox;
|
||||
using Base::addScopeName;
|
||||
using Base::captureFunctionName;
|
||||
|
||||
using Base::getDeclaredScope;
|
||||
using Base::getBoundScope;
|
||||
using Base::checkBinding;
|
||||
using Base::checkPositionalParameterIndices;
|
||||
|
||||
using Base::checkFunctionLength;
|
||||
using Base::checkClosedVars;
|
||||
|
||||
using Base::prependDirectivesToBody;
|
||||
|
||||
using Base::forceStrictIfNecessary;
|
||||
|
||||
public:
|
||||
footer: |
|
||||
};
|
||||
|
||||
extern template class BinASTParser<BinTokenReaderMultipart>;
|
||||
extern template class BinASTParser<BinTokenReaderTester>;
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
#endif // frontend_BinASTParser_h
|
||||
|
||||
enums:
|
||||
header: |
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* 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/. */
|
||||
|
||||
// To generate this file, see the documentation in
|
||||
// js/src/frontend/binsource/README.md.
|
||||
|
||||
#ifndef frontend_BinASTEnum_h
|
||||
#define frontend_BinASTEnum_h
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
namespace binast {
|
||||
footer: |
|
||||
} // namespace binast
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
#endif // frontend_BinASTEnum_h
|
||||
|
||||
# Rules for generating BinToken.h
|
||||
tokens:
|
||||
|
@ -120,14 +263,14 @@ hpp:
|
|||
*
|
||||
* (sorted by alphabetical order)
|
||||
*/
|
||||
field:
|
||||
variants:
|
||||
doc: |
|
||||
/**
|
||||
* The different variants of Binary AST string enums, as per
|
||||
* the specifications of Binary AST, as a single macro and
|
||||
* `enum class`.
|
||||
*
|
||||
* Separate enum classes are also defined in BinSource-auto.h.
|
||||
* Separate enum classes are also defined in BinASTParser.h.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
|
@ -700,14 +843,14 @@ GetterContents:
|
|||
fields:
|
||||
body:
|
||||
before: |
|
||||
BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
|
||||
BINJS_TRY_DECL(params, this->template new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
|
||||
|
||||
SetterContents:
|
||||
inherits: FunctionExpressionContents
|
||||
fields:
|
||||
param:
|
||||
after: |
|
||||
BINJS_TRY_DECL(params, new_<ListNode>(ParseNodeKind::ParamsBody, param->pn_pos));
|
||||
BINJS_TRY_DECL(params, this->template new_<ListNode>(ParseNodeKind::ParamsBody, param->pn_pos));
|
||||
factory_.addList(params, param);
|
||||
MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
|
||||
|
||||
|
@ -999,7 +1142,7 @@ ListOfParameter:
|
|||
type-ok:
|
||||
ListNode*
|
||||
init: |
|
||||
BINJS_TRY_DECL(result, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
|
||||
BINJS_TRY_DECL(result, this->template new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos(start)));
|
||||
append:
|
||||
factory_.addList(/* list = */ result, /* kid = */ item);
|
||||
|
||||
|
@ -1016,7 +1159,7 @@ ListOfStatement:
|
|||
# type-ok:
|
||||
# ListNode*
|
||||
# init:
|
||||
# BINJS_TRY_DECL(result, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos()));
|
||||
# BINJS_TRY_DECL(result, this->template new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos()));
|
||||
# append:
|
||||
# result->appendWithoutOrderAssumption(item);
|
||||
|
||||
|
|
|
@ -275,17 +275,14 @@ const size_t BINKIND_LIMIT = 200;
|
|||
|
||||
|
||||
/**
|
||||
* The different variants of Binary AST string enums, as per
|
||||
* the specifications of Binary AST, as a single macro and
|
||||
* `enum class`.
|
||||
*
|
||||
* Separate enum classes are also defined in BinSource-auto.h.
|
||||
* The different fields of Binary AST nodes, as per the specifications of
|
||||
* Binary AST.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```c++
|
||||
* #define WITH_VARIANT(CPP_NAME, SPEC_NAME) ...
|
||||
* FOR_EACH_BIN_VARIANT(WITH_VARIANT)
|
||||
* #define WITH_FIELD(CPP_NAME, SPEC_NAME) ...
|
||||
* FOR_EACH_BIN_FIELD(WITH_FIELD)
|
||||
* ```
|
||||
*
|
||||
* (sorted by alphabetical order)
|
||||
|
@ -371,7 +368,22 @@ enum class BinField {
|
|||
const size_t BINFIELD_LIMIT = 69;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The different variants of Binary AST string enums, as per
|
||||
* the specifications of Binary AST, as a single macro and
|
||||
* `enum class`.
|
||||
*
|
||||
* Separate enum classes are also defined in BinASTParser.h.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```c++
|
||||
* #define WITH_VARIANT(CPP_NAME, SPEC_NAME) ...
|
||||
* FOR_EACH_BIN_VARIANT(WITH_VARIANT)
|
||||
* ```
|
||||
*
|
||||
* (sorted by alphabetical order)
|
||||
*/
|
||||
#define FOR_EACH_BIN_VARIANT(F) \
|
||||
F(AssertedDeclaredKindConstLexical, "const lexical") \
|
||||
F(AssertedDeclaredKindNonConstLexical, "non-const lexical") \
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "builtin/ModuleObject.h"
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
# include "frontend/BinSource.h"
|
||||
# include "frontend/BinASTParser.h"
|
||||
#endif // JS_BUILD_BINAST
|
||||
#include "frontend/BytecodeCompilation.h"
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
|
|
|
@ -131,7 +131,8 @@ TraceParser(JSTracer* trc, JS::AutoGCRooter* parser);
|
|||
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
|
||||
/* Trace all GC things reachable from binjs parser. Defined in BinSource.cpp. */
|
||||
/* Trace all GC things reachable from binjs parser. Defined in
|
||||
* BinASTParserPerTokenizer.cpp. */
|
||||
void
|
||||
TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace frontend {
|
|||
enum class SourceKind {
|
||||
// We are parsing from a text source (Parser.h)
|
||||
Text,
|
||||
// We are parsing from a binary source (BinSource.h)
|
||||
// We are parsing from a binary source (BinASTParser.h)
|
||||
Binary,
|
||||
};
|
||||
|
||||
|
@ -108,7 +108,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
#undef DECLARE_AS
|
||||
|
||||
// The FullParseHandler may be used to create nodes for text sources
|
||||
// (from Parser.h) or for binary sources (from BinSource.h). In the latter
|
||||
// (from Parser.h) or for binary sources (from BinASTParser.h). In the latter
|
||||
// case, some common assumptions on offsets are incorrect, e.g. in `a + b`,
|
||||
// `a`, `b` and `+` may be stored in any order. We use `sourceKind()`
|
||||
// to determine whether we need to check these assumptions.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
cargo run -- \
|
||||
../BinSource.webidl_ \
|
||||
../BinSource.yaml \
|
||||
--out-class ../BinSource-auto.h \
|
||||
--out-impl ../BinSource-auto.cpp \
|
||||
--out-class ../BinASTParser.h \
|
||||
--out-impl ../BinASTParser.cpp \
|
||||
--out-enum ../BinASTEnum.h \
|
||||
--out-token ../BinToken.h
|
||||
|
|
|
@ -139,10 +139,22 @@ struct GlobalRules {
|
|||
/// Header to add at the end of the .cpp file.
|
||||
cpp_footer: Option<String>,
|
||||
|
||||
/// Header to add at the start of the .hpp file
|
||||
/// defining the class data/methods.
|
||||
/// Header to add at the start of the .hpp file.
|
||||
/// defining the class.
|
||||
hpp_class_header: Option<String>,
|
||||
|
||||
/// Footer to add at the end of the .hpp file
|
||||
/// defining the class.
|
||||
hpp_class_footer: Option<String>,
|
||||
|
||||
/// Header to add at the start of the .hpp file.
|
||||
/// defining the enums.
|
||||
hpp_enums_header: Option<String>,
|
||||
|
||||
/// Footer to add at the end of the .hpp file
|
||||
/// defining the enums.
|
||||
hpp_enums_footer: Option<String>,
|
||||
|
||||
/// Header to add at the start of the .hpp file.
|
||||
/// defining the tokens.
|
||||
hpp_tokens_header: Option<String>,
|
||||
|
@ -176,6 +188,9 @@ impl GlobalRules {
|
|||
let mut cpp_header = None;
|
||||
let mut cpp_footer = None;
|
||||
let mut hpp_class_header = None;
|
||||
let mut hpp_class_footer = None;
|
||||
let mut hpp_enums_header = None;
|
||||
let mut hpp_enums_footer = None;
|
||||
let mut hpp_tokens_header = None;
|
||||
let mut hpp_tokens_footer = None;
|
||||
let mut hpp_tokens_kind_doc = None;
|
||||
|
@ -211,6 +226,12 @@ impl GlobalRules {
|
|||
"hpp" => {
|
||||
update_rule(&mut hpp_class_header, &node_entries["class"]["header"])
|
||||
.unwrap_or_else(|_| panic!("Rule hpp.class.header must be a string"));
|
||||
update_rule(&mut hpp_class_footer, &node_entries["class"]["footer"])
|
||||
.unwrap_or_else(|_| panic!("Rule hpp.class.footer must be a string"));
|
||||
update_rule(&mut hpp_enums_header, &node_entries["enums"]["header"])
|
||||
.unwrap_or_else(|_| panic!("Rule hpp.enum.header must be a string"));
|
||||
update_rule(&mut hpp_enums_footer, &node_entries["enums"]["footer"])
|
||||
.unwrap_or_else(|_| panic!("Rule hpp.enum.footer must be a string"));
|
||||
update_rule(&mut hpp_tokens_header, &node_entries["tokens"]["header"])
|
||||
.unwrap_or_else(|_| panic!("Rule hpp.tokens.header must be a string"));
|
||||
update_rule(&mut hpp_tokens_footer, &node_entries["tokens"]["footer"])
|
||||
|
@ -398,6 +419,9 @@ impl GlobalRules {
|
|||
cpp_header,
|
||||
cpp_footer,
|
||||
hpp_class_header,
|
||||
hpp_class_footer,
|
||||
hpp_enums_header,
|
||||
hpp_enums_footer,
|
||||
hpp_tokens_header,
|
||||
hpp_tokens_footer,
|
||||
hpp_tokens_kind_doc,
|
||||
|
@ -982,19 +1006,26 @@ enum class BinVariant {
|
|||
}
|
||||
|
||||
/// Declare string enums
|
||||
fn export_declare_string_enums_classes(&self, buffer: &mut String) {
|
||||
buffer.push_str("\n\n// ----- Declaring string enums (by lexicographical order)\n");
|
||||
fn export_declare_string_enums(&self, buffer: &mut String) {
|
||||
buffer.push_str("
|
||||
// ----- Declaring string enums (by lexicographical order)
|
||||
");
|
||||
let string_enums_by_name = self.syntax.string_enums_by_name()
|
||||
.iter()
|
||||
.sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str()));
|
||||
for (name, enum_) in string_enums_by_name {
|
||||
let rendered_cases = enum_.strings()
|
||||
.iter()
|
||||
.map(|str| format!("{case:<20} /* \"{original}\" */",
|
||||
.map(|str| format!(" // \"{original}\"
|
||||
{case},",
|
||||
case = str.to_cpp_enum_case(),
|
||||
original = str))
|
||||
.format(",\n ");
|
||||
let rendered = format!("enum class {name} {{\n {cases}\n}};\n\n",
|
||||
.format("\n");
|
||||
let rendered = format!("
|
||||
enum class {name} {{
|
||||
{cases}
|
||||
}};
|
||||
",
|
||||
cases = rendered_cases,
|
||||
name = name.to_class_cases());
|
||||
buffer.push_str(&rendered);
|
||||
|
@ -1005,9 +1036,10 @@ enum class BinVariant {
|
|||
let sums_of_interfaces = self.syntax.resolved_sums_of_interfaces_by_name()
|
||||
.iter()
|
||||
.sorted_by(|a, b| a.0.cmp(&b.0));
|
||||
buffer.push_str("\n\n// ----- Sums of interfaces (by lexicographical order)\n");
|
||||
buffer.push_str("// Implementations are autogenerated\n");
|
||||
buffer.push_str("// `ParseNode*` may never be nullptr\n");
|
||||
buffer.push_str("
|
||||
// ----- Sums of interfaces (by lexicographical order)
|
||||
// `ParseNode*` may never be nullptr
|
||||
");
|
||||
for &(ref name, _) in &sums_of_interfaces {
|
||||
if !self.refgraph.is_used(name.to_rc_string().clone()) {
|
||||
continue;
|
||||
|
@ -1017,7 +1049,7 @@ enum class BinVariant {
|
|||
let extra_params = rules_for_this_sum.extra_params;
|
||||
let rendered = self.get_method_signature(name, "", "",
|
||||
&extra_params);
|
||||
buffer.push_str(&rendered.reindent("")
|
||||
buffer.push_str(&rendered.reindent(" ")
|
||||
.newline_if_not_empty());
|
||||
}
|
||||
for (name, _) in sums_of_interfaces {
|
||||
|
@ -1031,15 +1063,16 @@ enum class BinVariant {
|
|||
let rendered = self.get_method_signature(name, prefix,
|
||||
INTERFACE_PARAMS,
|
||||
&extra_params);
|
||||
buffer.push_str(&rendered.reindent("")
|
||||
buffer.push_str(&rendered.reindent(" ")
|
||||
.newline_if_not_empty());
|
||||
}
|
||||
}
|
||||
|
||||
fn export_declare_single_interface_methods(&self, buffer: &mut String) {
|
||||
buffer.push_str("\n\n// ----- Interfaces (by lexicographical order)\n");
|
||||
buffer.push_str("// Implementations are autogenerated\n");
|
||||
buffer.push_str("// `ParseNode*` may never be nullptr\n");
|
||||
buffer.push_str("
|
||||
// ----- Interfaces (by lexicographical order)
|
||||
// `ParseNode*` may never be nullptr
|
||||
");
|
||||
let interfaces_by_name = self.syntax.interfaces_by_name()
|
||||
.iter()
|
||||
.sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str()));
|
||||
|
@ -1053,7 +1086,7 @@ enum class BinVariant {
|
|||
|
||||
if self.refgraph.is_used(name.to_rc_string().clone()) {
|
||||
let outer = self.get_method_signature(name, "", "", &extra_params);
|
||||
outer_parsers.push(outer.reindent(""));
|
||||
outer_parsers.push(outer.reindent(" "));
|
||||
}
|
||||
|
||||
let inner_prefix = "Interface";
|
||||
|
@ -1063,7 +1096,7 @@ enum class BinVariant {
|
|||
let inner = self.get_method_signature(name, inner_prefix,
|
||||
INTERFACE_PARAMS,
|
||||
&extra_params);
|
||||
inner_parsers.push(inner.reindent(""));
|
||||
inner_parsers.push(inner.reindent(" "));
|
||||
}
|
||||
|
||||
for parser in outer_parsers.drain(..) {
|
||||
|
@ -1078,8 +1111,9 @@ enum class BinVariant {
|
|||
}
|
||||
|
||||
fn export_declare_string_enums_methods(&self, buffer: &mut String) {
|
||||
buffer.push_str("\n\n// ----- String enums (by lexicographical order)\n");
|
||||
buffer.push_str("// Implementations are autogenerated\n");
|
||||
buffer.push_str("
|
||||
// ----- String enums (by lexicographical order)
|
||||
");
|
||||
let string_enums_by_name = self.syntax.string_enums_by_name()
|
||||
.iter()
|
||||
.sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str()));
|
||||
|
@ -1089,14 +1123,15 @@ enum class BinVariant {
|
|||
}
|
||||
|
||||
let rendered = self.get_method_signature(kind, "", "", &None);
|
||||
buffer.push_str(&rendered.reindent(""));
|
||||
buffer.push_str(&rendered.reindent(" "));
|
||||
buffer.push_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
fn export_declare_list_methods(&self, buffer: &mut String) {
|
||||
buffer.push_str("\n\n// ----- Lists (by lexicographical order)\n");
|
||||
buffer.push_str("// Implementations are autogenerated\n");
|
||||
buffer.push_str("
|
||||
// ----- Lists (by lexicographical order)
|
||||
");
|
||||
for parser in &self.list_parsers_to_generate {
|
||||
if !self.refgraph.is_used(parser.name.to_rc_string().clone()) {
|
||||
continue;
|
||||
|
@ -1106,14 +1141,15 @@ enum class BinVariant {
|
|||
let extra_params = rules_for_this_node.extra_params;
|
||||
let rendered = self.get_method_signature(&parser.name, "", "",
|
||||
&extra_params);
|
||||
buffer.push_str(&rendered.reindent(""));
|
||||
buffer.push_str(&rendered.reindent(" "));
|
||||
buffer.push_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
fn export_declare_option_methods(&self, buffer: &mut String) {
|
||||
buffer.push_str("\n\n// ----- Default values (by lexicographical order)\n");
|
||||
buffer.push_str("// Implementations are autogenerated\n");
|
||||
buffer.push_str("
|
||||
// ----- Default values (by lexicographical order)
|
||||
");
|
||||
for parser in &self.option_parsers_to_generate {
|
||||
if !self.refgraph.is_used(parser.name.to_rc_string().clone()) {
|
||||
continue;
|
||||
|
@ -1123,7 +1159,7 @@ enum class BinVariant {
|
|||
let extra_params = rules_for_this_node.extra_params;
|
||||
let rendered = self.get_method_signature(&parser.name, "", "",
|
||||
&extra_params);
|
||||
buffer.push_str(&rendered.reindent(""));
|
||||
buffer.push_str(&rendered.reindent(" "));
|
||||
buffer.push_str("\n");
|
||||
}
|
||||
}
|
||||
|
@ -1154,13 +1190,30 @@ enum class BinVariant {
|
|||
buffer.push_str(&self.rules.hpp_class_header.reindent(""));
|
||||
buffer.push_str("\n");
|
||||
|
||||
self.export_declare_string_enums_classes(&mut buffer);
|
||||
self.export_declare_sums_of_interface_methods(&mut buffer);
|
||||
self.export_declare_single_interface_methods(&mut buffer);
|
||||
self.export_declare_string_enums_methods(&mut buffer);
|
||||
self.export_declare_list_methods(&mut buffer);
|
||||
self.export_declare_option_methods(&mut buffer);
|
||||
|
||||
buffer.push_str("\n");
|
||||
buffer.push_str(&self.rules.hpp_class_footer.reindent(""));
|
||||
buffer.push_str("\n");
|
||||
buffer
|
||||
}
|
||||
|
||||
fn to_spidermonkey_enum_hpp(&self) -> String {
|
||||
let mut buffer = String::new();
|
||||
|
||||
buffer.push_str(&self.generate_autogenerated_warning());
|
||||
|
||||
buffer.push_str(&self.rules.hpp_enums_header.reindent(""));
|
||||
buffer.push_str("\n");
|
||||
|
||||
self.export_declare_string_enums(&mut buffer);
|
||||
|
||||
buffer.push_str("\n");
|
||||
buffer.push_str(&self.rules.hpp_enums_footer.reindent(""));
|
||||
buffer.push_str("\n");
|
||||
buffer
|
||||
}
|
||||
|
@ -1994,7 +2047,12 @@ fn main() {
|
|||
.long("out-class")
|
||||
.required(true)
|
||||
.takes_value(true)
|
||||
.help("Output header file (.h, designed to be included from within the class file)"),
|
||||
.help("Output header file for class (.h)"),
|
||||
Arg::with_name("OUT_HEADER_ENUM_FILE")
|
||||
.long("out-enum")
|
||||
.required(true)
|
||||
.takes_value(true)
|
||||
.help("Output header file for enum (.h)"),
|
||||
Arg::with_name("OUT_TOKEN_FILE")
|
||||
.long("out-token")
|
||||
.required(true)
|
||||
|
@ -2101,6 +2159,8 @@ fn main() {
|
|||
|
||||
write_to("C++ class header code", "OUT_HEADER_CLASS_FILE",
|
||||
&exporter.to_spidermonkey_class_hpp());
|
||||
write_to("C++ enum header code", "OUT_HEADER_ENUM_FILE",
|
||||
&exporter.to_spidermonkey_enum_hpp());
|
||||
write_to("C++ token header code", "OUT_TOKEN_FILE",
|
||||
&exporter.to_spidermonkey_token_hpp());
|
||||
write_to("C++ token implementation code", "OUT_IMPL_FILE",
|
||||
|
|
|
@ -67,8 +67,9 @@ if CONFIG['JS_BUILD_BINAST']:
|
|||
SOURCES += ['BinTokenReaderTester.cpp']
|
||||
# These parts of BinAST should eventually move to release.
|
||||
SOURCES += [
|
||||
'BinSource-auto.cpp',
|
||||
'BinSource.cpp',
|
||||
'BinASTParser.cpp',
|
||||
'BinASTParserBase.cpp',
|
||||
'BinASTParserPerTokenizer.cpp',
|
||||
'BinSourceRuntimeSupport.cpp',
|
||||
'BinToken.cpp',
|
||||
'BinTokenReaderBase.cpp',
|
||||
|
@ -79,8 +80,9 @@ if CONFIG['JS_BUILD_BINAST']:
|
|||
if CONFIG['FUZZING_INTERFACES'] and CONFIG['LIBFUZZER']:
|
||||
include('/tools/fuzzing/libfuzzer-flags.mozbuild')
|
||||
|
||||
SOURCES['BinSource-auto.cpp'].flags += libfuzzer_flags
|
||||
SOURCES['BinSource.cpp'].flags += libfuzzer_flags
|
||||
SOURCES['BinASTParser.cpp'].flags += libfuzzer_flags
|
||||
SOURCES['BinASTParserBase.cpp'].flags += libfuzzer_flags
|
||||
SOURCES['BinASTParserPerTokenizer.cpp'].flags += libfuzzer_flags
|
||||
SOURCES['BinToken.cpp'].flags += libfuzzer_flags
|
||||
SOURCES['BinTokenReaderBase.cpp'].flags += libfuzzer_flags
|
||||
SOURCES['BinTokenReaderMultipart.cpp'].flags += libfuzzer_flags
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "frontend/BinSource.h"
|
||||
#include "frontend/BinASTParser.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
#include "frontend/ParseContext.h"
|
||||
#include "frontend/Parser.h"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "frontend/BinSource.h"
|
||||
#include "frontend/BinASTParser.h"
|
||||
#include "frontend/FullParseHandler.h"
|
||||
#include "frontend/ParseContext.h"
|
||||
#include "frontend/Parser.h"
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
#include "builtin/RegExp.h"
|
||||
#include "builtin/TestingFunctions.h"
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
# include "frontend/BinSource.h"
|
||||
# include "frontend/BinASTParser.h"
|
||||
#endif // defined(JS_BUILD_BINAST)
|
||||
#include "frontend/ModuleSharedContext.h"
|
||||
#include "frontend/Parser.h"
|
||||
|
|
|
@ -720,6 +720,20 @@ wasm::ExecuteCompileTaskFromHelperThread(CompileTask* task)
|
|||
taskState.notify_one(/* failed or finished */);
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::locallyCompileCurrentTask()
|
||||
{
|
||||
if (!ExecuteCompileTask(currentTask_, error_)) {
|
||||
return false;
|
||||
}
|
||||
if (!finishTask(currentTask_)) {
|
||||
return false;
|
||||
}
|
||||
currentTask_ = nullptr;
|
||||
batchedBytecode_ = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::finishTask(CompileTask* task)
|
||||
{
|
||||
|
@ -756,20 +770,14 @@ ModuleGenerator::launchBatchCompile()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (parallel_) {
|
||||
if (!parallel_) {
|
||||
return locallyCompileCurrentTask();
|
||||
}
|
||||
|
||||
if (!StartOffThreadWasmCompile(currentTask_, mode())) {
|
||||
return false;
|
||||
}
|
||||
outstanding_++;
|
||||
} else {
|
||||
if (!ExecuteCompileTask(currentTask_, error_)) {
|
||||
return false;
|
||||
}
|
||||
if (!finishTask(currentTask_)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
currentTask_ = nullptr;
|
||||
batchedBytecode_ = 0;
|
||||
return true;
|
||||
|
@ -843,7 +851,7 @@ ModuleGenerator::finishFuncDefs()
|
|||
{
|
||||
MOZ_ASSERT(!finishedFuncDefs_);
|
||||
|
||||
if (currentTask_ && !launchBatchCompile()) {
|
||||
if (currentTask_ && !locallyCompileCurrentTask()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -196,6 +196,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||
bool linkCallSites();
|
||||
void noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRange);
|
||||
bool linkCompiledCode(const CompiledCode& code);
|
||||
bool locallyCompileCurrentTask();
|
||||
bool finishTask(CompileTask* task);
|
||||
bool launchBatchCompile();
|
||||
bool finishOutstandingTask();
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче