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

This commit is contained in:
Coroiu Cristina 2018-11-28 23:56:03 +02:00
Родитель f1dd32d581 d4aafa8e1c
Коммит 47323ec73b
145 изменённых файлов: 12169 добавлений и 2524 удалений

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

@ -76,17 +76,17 @@
<body> <body>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=506389" href="https://bugzilla.mozilla.org/show_bug.cgi?id=506389"
title="Some same page links do not fire EVENT_SYSTEM_SCROLLINGSTART"> title="Some same page links do not fire EVENT_SYSTEM_SCROLLINGSTART">
Mozilla Bug 506389 Mozilla Bug 506389
</a><br> </a><br>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=437607" 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"> title="Clicking the 'Skip to main content' link once works, second time fails to initiate a V cursor jump">
Mozilla Bug 437607 Mozilla Bug 437607
</a><br> </a><br>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=519303" 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"> title="Same page links to targets with content fires scrolling start accessible event on leaf text node">
Mozilla Bug 519303 Mozilla Bug 519303

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

@ -135,7 +135,7 @@
<body> <body>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=410765" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410765"
title="nsIAccessible actions testing"> title="nsIAccessible actions testing">
Mozilla Bug 410765 Mozilla Bug 410765

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

@ -77,7 +77,7 @@
<body> <body>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=477975" href="https://bugzilla.mozilla.org/show_bug.cgi?id=477975"
title="nsIAccessible actions testing"> title="nsIAccessible actions testing">
Mozilla Bug 477975 Mozilla Bug 477975

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

@ -63,17 +63,17 @@
<body> <body>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=523789" href="https://bugzilla.mozilla.org/show_bug.cgi?id=523789"
title="nsHTMLLiAccessible shouldn't be inherited from linkable accessible"> title="nsHTMLLiAccessible shouldn't be inherited from linkable accessible">
Mozilla Bug 523789 Mozilla Bug 523789
</a><br> </a><br>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=423409" href="https://bugzilla.mozilla.org/show_bug.cgi?id=423409"
title="Expose click action if mouseup and mousedown are registered"> title="Expose click action if mouseup and mousedown are registered">
Mozilla Bug 423409 Mozilla Bug 423409
</a> </a>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=659620" href="https://bugzilla.mozilla.org/show_bug.cgi?id=659620"
title="hang when trying to edit a page on wikimo with NVDA running"> title="hang when trying to edit a page on wikimo with NVDA running">
Mozilla Bug 659620 Mozilla Bug 659620

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

@ -92,12 +92,12 @@
<hbox flex="1" style="overflow: auto;"> <hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml"> <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" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410765"
title="nsIAccessible actions testing"> title="nsIAccessible actions testing">
Mozilla Bug 410765 Mozilla Bug 410765
</a> </a>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=504252" href="https://bugzilla.mozilla.org/show_bug.cgi?id=504252"
title="Expose STATE_HASPOPUP on XUL elements that have an @popup attribute"> title="Expose STATE_HASPOPUP on XUL elements that have an @popup attribute">
Mozilla Bug 504252 Mozilla Bug 504252

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

@ -38,7 +38,7 @@
<body> <body>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=381599" href="https://bugzilla.mozilla.org/show_bug.cgi?id=381599"
title="Inverse relations cache"> title="Inverse relations cache">
Mozilla Bug 381599 Mozilla Bug 381599

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

@ -66,7 +66,7 @@
<hbox flex="1" style="overflow: auto;"> <hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml"> <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" href="https://bugzilla.mozilla.org/show_bug.cgi?id=672092"
title="Reorganize access key and keyboard shortcut handling code"> title="Reorganize access key and keyboard shortcut handling code">
Mozilla Bug 672092 Mozilla Bug 672092

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

@ -116,7 +116,7 @@
<body> <body>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=423409" href="https://bugzilla.mozilla.org/show_bug.cgi?id=423409"
title="Expose click action if mouseup and mousedown are registered"> title="Expose click action if mouseup and mousedown are registered">
Mozilla Bug 423409 Mozilla Bug 423409
@ -126,7 +126,7 @@
<pre id="test"> <pre id="test">
</pre> </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"> <img src="../moz.png" id="img1">
</a> </a>
<a id="link2" onmousedown=""> <a id="link2" onmousedown="">

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

@ -116,7 +116,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
</head> </head>
<body> <body>
<a target="_blank" <a target="_blank" rel="opener"
title="Expose HTML5 video and audio elements' embedded controls through accessibility APIs" 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> href="https://bugzilla.mozilla.org/show_bug.cgi?id=483573">Mozilla Bug 483573</a>
<p id="display"></p> <p id="display"></p>

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

@ -81,7 +81,7 @@
<body> <body>
<a target="_blank" <a target="_blank" rel="opener"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958" href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
title="Rework accessible focus handling"> title="Rework accessible focus handling">
Mozilla Bug 673958 Mozilla Bug 673958

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

@ -100,7 +100,7 @@
<hbox flex="1" style="overflow: auto;"> <hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml"> <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" href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility"> title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727 Mozilla Bug 503727

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

@ -165,7 +165,7 @@
<hbox flex="1" style="overflow: auto;"> <hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml"> <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" href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility"> title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727 Mozilla Bug 503727

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

@ -559,17 +559,13 @@ html|input.urlbar-input:-moz-locale-dir(rtl) {
direction: ltr !important; direction: ltr !important;
text-align: right !important; text-align: right !important;
} }
/* Make sure that the location bar's alignment in RTL mode changes according /* 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 to the input box direction if the user switches the text direction using
cmd_switchTextDirection (which applies a dir attribute to the <input>). */ cmd_switchTextDirection (which applies a dir attribute to the <input>). */
html|input.urlbar-input[dir=ltr]:-moz-locale-dir(rtl) { html|input.urlbar-input[dir=ltr]:-moz-locale-dir(rtl) {
text-align: left !important; 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. * Display visual cue that browser is under remote control by Marionette.

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

@ -11,7 +11,7 @@ requestLongerTimeout(2);
function frame_script() { function frame_script() {
content.document.body.innerHTML = ` 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"); let element = content.document.getElementById("testAnchor");

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

@ -33,7 +33,7 @@
<li> <li>
<a id="test-create-new-tab-from-targetblank-click" <a id="test-create-new-tab-from-targetblank-click"
href="webNav_createdTarget.html#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" Open a target page in a new tab from click to link with target="_blank"
</a> </a>
</li> </li>

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

@ -33,7 +33,7 @@
<li> <li>
<a id="test-create-new-tab-from-targetblank-click-subframe" <a id="test-create-new-tab-from-targetblank-click-subframe"
href="webNav_createdTarget.html#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" Open a target page in a new tab from click to link with target="_blank"
</a> </a>
</li> </li>

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

@ -113,7 +113,6 @@ included_inclnames_to_ignore = set([
# ignore #includes of them when checking #include ordering. # ignore #includes of them when checking #include ordering.
oddly_ordered_inclnames = set([ oddly_ordered_inclnames = set([
'ctypes/typedefs.h', # Included multiple times in the body of ctypes/CTypes.h '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 # Included in the body of frontend/TokenStream.h
'frontend/ReservedWordsGenerated.h', 'frontend/ReservedWordsGenerated.h',
'gc/StatsPhasesGenerated.h', # Included in the body of gc/Statistics.h 'gc/StatsPhasesGenerated.h', # Included in the body of gc/Statistics.h

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

@ -1,9 +1,9 @@
This is the debugger.html project output. This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html 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: Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.2 - babel-plugin-transform-es2015-modules-commonjs @6.26.2

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

@ -2286,16 +2286,6 @@ menuseparator {
background: var(--theme-body-color); 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 { .source-footer > .commands > .blackboxed > img.blackBox {
background: var(--theme-highlight-blue); background: var(--theme-highlight-blue);
} }
@ -2872,11 +2862,6 @@ html[dir="rtl"] .editor-mount {
background: var(--theme-selection-background-hover); 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 { .editor.new-breakpoint svg {
fill: var(--theme-selection-background); fill: var(--theme-selection-background);
width: 60px; width: 60px;

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

@ -15,7 +15,10 @@ import {
import { mapFrames, fetchExtra } from "./pause"; import { mapFrames, fetchExtra } from "./pause";
import { updateTab } from "./tabs"; import { updateTab } from "./tabs";
import { PROMISE } from "./utils/middleware/promise";
import { setInScopeLines } from "./ast/setInScopeLines"; import { setInScopeLines } from "./ast/setInScopeLines";
import { updateSymbolLocations } from "./utils/symbols";
import { import {
getSymbols, getSymbols,
findOutOfScopeLocations, findOutOfScopeLocations,
@ -24,7 +27,6 @@ import {
type AstPosition type AstPosition
} from "../workers/parser"; } from "../workers/parser";
import { PROMISE } from "./utils/middleware/promise";
import { features } from "../utils/prefs"; import { features } from "../utils/prefs";
import { isLoaded, isGenerated } from "../utils/source"; import { isLoaded, isGenerated } from "../utils/source";
@ -56,7 +58,7 @@ export function setSourceMetaData(sourceId: SourceId) {
} }
export function setSymbols(sourceId: SourceId) { export function setSymbols(sourceId: SourceId) {
return async ({ dispatch, getState }: ThunkArgs) => { return async ({ dispatch, getState, sourceMaps }: ThunkArgs) => {
const source = getSourceFromId(getState(), sourceId); const source = getSourceFromId(getState(), sourceId);
if (source.isWasm || hasSymbols(getState(), source) || !isLoaded(source)) { if (source.isWasm || hasSymbols(getState(), source) || !isLoaded(source)) {
@ -66,7 +68,15 @@ export function setSymbols(sourceId: SourceId) {
await dispatch({ await dispatch({
type: "SET_SYMBOLS", type: "SET_SYMBOLS",
sourceId, sourceId,
[PROMISE]: getSymbols(sourceId) [PROMISE]: (async function() {
const symbols = await getSymbols(sourceId);
const mappedSymbols = updateSymbolLocations(
symbols,
source,
sourceMaps
);
return mappedSymbols;
})()
}); });
if (isPaused(getState())) { if (isPaused(getState())) {

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

@ -45,7 +45,7 @@ async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
return { breakpoint: newBreakpoint }; return { breakpoint: newBreakpoint };
} }
const { id, hitCount, actualLocation } = await client.setBreakpoint( const { id, actualLocation } = await client.setBreakpoint(
generatedLocation, generatedLocation,
breakpoint.condition, breakpoint.condition,
isOriginalId(location.sourceId) isOriginalId(location.sourceId)
@ -70,7 +70,6 @@ async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
condition: breakpoint.condition, condition: breakpoint.condition,
location: newLocation, location: newLocation,
astLocation, astLocation,
hitCount,
generatedLocation: newGeneratedLocation, generatedLocation: newGeneratedLocation,
text, text,
originalText originalText

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

@ -12,7 +12,6 @@ import * as navigation from "./navigation";
import * as ui from "./ui"; import * as ui from "./ui";
import * as fileSearch from "./file-search"; import * as fileSearch from "./file-search";
import * as ast from "./ast"; import * as ast from "./ast";
import * as coverage from "./coverage";
import * as projectTextSearch from "./project-text-search"; import * as projectTextSearch from "./project-text-search";
import * as quickOpen from "./quick-open"; import * as quickOpen from "./quick-open";
import * as sourceTree from "./source-tree"; import * as sourceTree from "./source-tree";
@ -33,7 +32,6 @@ export default {
...ui, ...ui,
...fileSearch, ...fileSearch,
...ast, ...ast,
...coverage,
...projectTextSearch, ...projectTextSearch,
...quickOpen, ...quickOpen,
...sourceTree, ...sourceTree,

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

@ -13,7 +13,6 @@ DIRS += [
DebuggerModules( DebuggerModules(
'ast.js', 'ast.js',
'coverage.js',
'debuggee.js', 'debuggee.js',
'event-listeners.js', 'event-listeners.js',
'expressions.js', 'expressions.js',

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

@ -83,12 +83,18 @@ function loadSourceMap(sourceId: SourceId) {
} }
if (!urls) { 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 // If this source doesn't have a sourcemap, enable it for pretty printing
dispatch( dispatch(
({ ({
type: "UPDATE_SOURCE", type: "UPDATE_SOURCE",
// NOTE: Flow https://github.com/facebook/flow/issues/6342 issue // NOTE: Flow https://github.com/facebook/flow/issues/6342 issue
source: (({ ...source, sourceMapURL: "" }: any): Source) source: (({ ...currentSource, sourceMapURL: "" }: any): Source)
}: Action) }: Action)
); );
return; return;

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

@ -9,4 +9,5 @@ DIRS += [
DebuggerModules( DebuggerModules(
'create-store.js', '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 = () => { renderLayout = () => {
const { startPanelCollapsed, endPanelCollapsed } = this.props; const { startPanelCollapsed, endPanelCollapsed } = this.props;
const horizontal = this.isHorizontal(); const horizontal = this.isHorizontal();
@ -282,6 +291,7 @@ class App extends Component<Props, State> {
/> />
} }
endPanelCollapsed={endPanelCollapsed} endPanelCollapsed={endPanelCollapsed}
onResizeEnd={this.triggerEditorPaneResize}
/> />
); );
}; };

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

@ -5,7 +5,7 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { range, keyBy, isEqualWith } from "lodash"; import { range, keyBy, isEqualWith, uniqBy, groupBy, flatten } from "lodash";
import CallSite from "./CallSite"; import CallSite from "./CallSite";
@ -121,23 +121,43 @@ class CallSites extends Component {
filterCallSitesByLineNumber() { filterCallSitesByLineNumber() {
const { callSites, breakpoints } = this.props; 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 }) => // Get call sites based on activated breakpoint lines
breakpointLines.has(location.start.line) 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() { render() {
const { editor, callSites, selectedSource } = this.props; const { editor, callSites, selectedSource, breakpoints } = this.props;
let sites; if (!callSites || breakpoints.length === 0) {
if (!callSites || (selectedSource && selectedSource.isPrettyPrinted)) {
return null; return null;
} }
const callSitesFiltered = this.filterCallSitesByLineNumber(); const callSitesFiltered = this.filterCallSitesByLineNumber();
let sites;
editor.codeMirror.operation(() => { editor.codeMirror.operation(() => {
const childCallSites = callSitesFiltered.map((callSite, index) => { const childCallSites = callSitesFiltered.map((callSite, index) => {
const props = { const props = {

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

@ -14,7 +14,6 @@ import {
getPaneCollapse getPaneCollapse
} from "../../selectors"; } from "../../selectors";
import { features } from "../../utils/prefs";
import { import {
isPretty, isPretty,
isLoaded, isLoaded,
@ -39,7 +38,6 @@ type Props = {
togglePrettyPrint: string => void, togglePrettyPrint: string => void,
toggleBlackBox: Object => void, toggleBlackBox: Object => void,
jumpToMappedLocation: (Source: any) => void, jumpToMappedLocation: (Source: any) => void,
recordCoverage: () => void,
togglePaneCollapse: () => 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() { renderToggleButton() {
if (this.props.horizontal) { if (this.props.horizontal) {
return; return;
@ -162,7 +141,6 @@ class SourceFooter extends PureComponent<Props> {
{this.prettyPrintButton()} {this.prettyPrintButton()}
{this.blackBoxButton()} {this.blackBoxButton()}
{this.blackBoxSummary()} {this.blackBoxSummary()}
{this.coverageButton()}
</div> </div>
); );
} }
@ -231,7 +209,6 @@ export default connect(
togglePrettyPrint: actions.togglePrettyPrint, togglePrettyPrint: actions.togglePrettyPrint,
toggleBlackBox: actions.toggleBlackBox, toggleBlackBox: actions.toggleBlackBox,
jumpToMappedLocation: actions.jumpToMappedLocation, jumpToMappedLocation: actions.jumpToMappedLocation,
recordCoverage: actions.recordCoverage,
togglePaneCollapse: actions.togglePaneCollapse togglePaneCollapse: actions.togglePaneCollapse
} }
)(SourceFooter); )(SourceFooter);

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

@ -76,10 +76,12 @@ class Tabs extends PureComponent<Props, State> {
componentDidMount() { componentDidMount() {
window.requestIdleCallback(this.updateHiddenTabs); window.requestIdleCallback(this.updateHiddenTabs);
window.addEventListener("resize", this.onResize); window.addEventListener("resize", this.onResize);
window.document.querySelector(".editor-pane").addEventListener("resizeend", this.onResize);
} }
componentWillUnmount() { componentWillUnmount() {
window.removeEventListener("resize", this.onResize); window.removeEventListener("resize", this.onResize);
window.document.querySelector(".editor-pane").removeEventListener("resizeend", this.onResize);
} }
/* /*

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

@ -18,8 +18,6 @@ import {
getActiveSearch, getActiveSearch,
getSelectedLocation, getSelectedLocation,
getSelectedSource, getSelectedSource,
getHitCountForSource,
getCoverageEnabled,
getConditionalPanelLine, getConditionalPanelLine,
getSymbols getSymbols
} from "../../selectors"; } from "../../selectors";
@ -32,7 +30,6 @@ import SearchBar from "./SearchBar";
import HighlightLines from "./HighlightLines"; import HighlightLines from "./HighlightLines";
import Preview from "./Preview"; import Preview from "./Preview";
import Breakpoints from "./Breakpoints"; import Breakpoints from "./Breakpoints";
import HitMarker from "./HitMarker";
import CallSites from "./CallSites"; import CallSites from "./CallSites";
import DebugLine from "./DebugLine"; import DebugLine from "./DebugLine";
import HighlightLine from "./HighlightLine"; import HighlightLine from "./HighlightLine";
@ -76,11 +73,9 @@ const cssVars = {
}; };
export type Props = { export type Props = {
hitCount: Object,
selectedLocation: ?Location, selectedLocation: ?Location,
selectedSource: ?Source, selectedSource: ?Source,
searchOn: boolean, searchOn: boolean,
coverageOn: boolean,
horizontal: boolean, horizontal: boolean,
startPanelSize: number, startPanelSize: number,
endPanelSize: 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() { renderItems() {
const { horizontal, selectedSource } = this.props; const { horizontal, selectedSource } = this.props;
const { editor } = this.state; const { editor } = this.state;
@ -577,7 +549,6 @@ class Editor extends PureComponent<Props, State> {
<GutterMenu editor={editor} /> <GutterMenu editor={editor} />
<ConditionalPanel editor={editor} /> <ConditionalPanel editor={editor} />
{features.columnBreakpoints ? <CallSites editor={editor} /> : null} {features.columnBreakpoints ? <CallSites editor={editor} /> : null}
{this.renderHitCounts()}
</div> </div>
); );
} }
@ -593,13 +564,9 @@ class Editor extends PureComponent<Props, State> {
} }
render() { render() {
const { coverageOn } = this.props;
return ( return (
<div <div
className={classnames("editor-wrapper", { className={classnames("editor-wrapper")}
"coverage-on": coverageOn
})}
ref={c => (this.$editorWrapper = c)} ref={c => (this.$editorWrapper = c)}
> >
<div <div
@ -619,14 +586,11 @@ Editor.contextTypes = {
const mapStateToProps = state => { const mapStateToProps = state => {
const selectedSource = getSelectedSource(state); const selectedSource = getSelectedSource(state);
const sourceId = selectedSource ? selectedSource.id : "";
return { return {
selectedLocation: getSelectedLocation(state), selectedLocation: getSelectedLocation(state),
selectedSource, selectedSource,
searchOn: getActiveSearch(state) === "file", searchOn: getActiveSearch(state) === "file",
hitCount: getHitCountForSource(state, sourceId),
coverageOn: getCoverageEnabled(state),
conditionalPanelLine: getConditionalPanelLine(state), conditionalPanelLine: getConditionalPanelLine(state),
symbols: getSymbols(state, selectedSource) symbols: getSymbols(state, selectedSource)
}; };

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

@ -20,7 +20,6 @@ DebuggerModules(
'GutterMenu.js', 'GutterMenu.js',
'HighlightLine.js', 'HighlightLine.js',
'HighlightLines.js', 'HighlightLines.js',
'HitMarker.js',
'index.js', 'index.js',
'SearchBar.js', 'SearchBar.js',
'Tab.js', 'Tab.js',

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

@ -35,6 +35,10 @@ export default class OutlineFilter extends Component<Props, State> {
// also bound to the ESC key // also bound to the ESC key
e.preventDefault(); e.preventDefault();
this.props.updateFilter(""); 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, removeBreakpoints: typeof actions.removeBreakpoints,
removeAllBreakpoints: typeof actions.removeAllBreakpoints, removeAllBreakpoints: typeof actions.removeAllBreakpoints,
disableBreakpoint: typeof actions.disableBreakpoint, disableBreakpoint: typeof actions.disableBreakpoint,
setBreakpointCondition: typeof actions.setBreakpointCondition,
toggleAllBreakpoints: typeof actions.toggleAllBreakpoints, toggleAllBreakpoints: typeof actions.toggleAllBreakpoints,
toggleBreakpoints: typeof actions.toggleBreakpoints, toggleBreakpoints: typeof actions.toggleBreakpoints,
openConditionalPanel: typeof actions.openConditionalPanel, openConditionalPanel: typeof actions.openConditionalPanel,
@ -201,6 +202,7 @@ export default connect(
disableBreakpoint: actions.disableBreakpoint, disableBreakpoint: actions.disableBreakpoint,
selectSpecificLocation: actions.selectSpecificLocation, selectSpecificLocation: actions.selectSpecificLocation,
selectLocation: actions.selectLocation, selectLocation: actions.selectLocation,
setBreakpointCondition: actions.setBreakpointCondition,
toggleAllBreakpoints: actions.toggleAllBreakpoints, toggleAllBreakpoints: actions.toggleAllBreakpoints,
toggleBreakpoints: actions.toggleBreakpoints, toggleBreakpoints: actions.toggleBreakpoints,
openConditionalPanel: actions.openConditionalPanel openConditionalPanel: actions.openConditionalPanel

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

@ -18,7 +18,6 @@ import pause from "./pause";
import ui from "./ui"; import ui from "./ui";
import fileSearch from "./file-search"; import fileSearch from "./file-search";
import ast from "./ast"; import ast from "./ast";
import coverage from "./coverage";
import projectTextSearch from "./project-text-search"; import projectTextSearch from "./project-text-search";
import quickOpen from "./quick-open"; import quickOpen from "./quick-open";
import sourceTree from "./source-tree"; import sourceTree from "./source-tree";
@ -37,7 +36,6 @@ export default {
ui, ui,
fileSearch, fileSearch,
ast, ast,
coverage,
projectTextSearch, projectTextSearch,
quickOpen, quickOpen,
sourceTree, sourceTree,

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

@ -11,7 +11,6 @@ DebuggerModules(
'ast.js', 'ast.js',
'async-requests.js', 'async-requests.js',
'breakpoints.js', 'breakpoints.js',
'coverage.js',
'debuggee.js', 'debuggee.js',
'event-listeners.js', 'event-listeners.js',
'expressions.js', 'expressions.js',

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

@ -431,13 +431,19 @@ function getSourcesByUrlInSources(
return urls[url].map(id => sources[id]); 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); const urls = getUrls(state);
if (!url || !urls[url]) { if (!url || !urls[url]) {
return []; 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) { export function getHasSiblingOfSameName(state: OuterState, source: ?Source) {

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

@ -14,7 +14,6 @@ export * from "../reducers/pending-breakpoints";
export * from "../reducers/ui"; export * from "../reducers/ui";
export * from "../reducers/file-search"; export * from "../reducers/file-search";
export * from "../reducers/ast"; export * from "../reducers/ast";
export * from "../reducers/coverage";
export * from "../reducers/project-text-search"; export * from "../reducers/project-text-search";
export * from "../reducers/source-tree"; export * from "../reducers/source-tree";

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

@ -18,12 +18,12 @@ type AnnotatedFrame =
| Frame; | Frame;
export function annotateFrames(frames: Frame[]): AnnotatedFrame[] { export function annotateFrames(frames: Frame[]): AnnotatedFrame[] {
const annotatedFrames = frames.map(annotateFrame); const annotatedFrames = frames.map(f => annotateFrame(f, frames));
return annotateBabelAsyncFrames(annotatedFrames); return annotateBabelAsyncFrames(annotatedFrames);
} }
function annotateFrame(frame: Frame): AnnotatedFrame { function annotateFrame(frame: Frame, frames: Frame[]): AnnotatedFrame {
const library = getLibraryFromUrl(frame); const library = getLibraryFromUrl(frame, frames);
if (library) { if (library) {
return { ...frame, library }; return { ...frame, library };
} }

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

@ -128,9 +128,15 @@ export function getLibraryFromUrl(frame: Frame, callStack: Array<Frame> = []) {
o => o.contextPattern && frameUrl.match(o.contextPattern) o => o.contextPattern && frameUrl.match(o.contextPattern)
); );
if (match) { if (match) {
const contextMatch = callStack.some(f => const contextMatch = callStack.some(f => {
libraryMap.find(o => frameUrl.match(o.pattern)) const url = getFrameUrl(f);
); if (!url) {
return false;
}
return libraryMap.some(o => url.match(o.pattern));
});
if (contextMatch) { if (contextMatch) {
return match.label; return match.label;
} }

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

@ -50,7 +50,6 @@ if (isDevelopment()) {
pref("devtools.debugger.features.root", true); pref("devtools.debugger.features.root", true);
pref("devtools.debugger.features.map-scopes", true); pref("devtools.debugger.features.map-scopes", true);
pref("devtools.debugger.features.remove-command-bar-options", 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.event-listeners", false);
pref("devtools.debugger.features.code-folding", false); pref("devtools.debugger.features.code-folding", false);
pref("devtools.debugger.features.outline", true); pref("devtools.debugger.features.outline", true);
@ -105,7 +104,6 @@ export const features = new PrefsHelper("devtools.debugger.features", {
mapScopes: ["Bool", "map-scopes"], mapScopes: ["Bool", "map-scopes"],
removeCommandBarOptions: ["Bool", "remove-command-bar-options"], removeCommandBarOptions: ["Bool", "remove-command-bar-options"],
workers: ["Bool", "workers"], workers: ["Bool", "workers"],
codeCoverage: ["Bool", "code-coverage"],
eventListeners: ["Bool", "event-listeners"], eventListeners: ["Bool", "event-listeners"],
outline: ["Bool", "outline"], outline: ["Bool", "outline"],
codeFolding: ["Bool", "code-folding"], codeFolding: ["Bool", "code-folding"],

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

@ -81,4 +81,13 @@ add_task(async function() {
bp = findBreakpoint(dbg, "simple2", 5); bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "1", "breakpoint is created with the condition"); is(bp.condition, "1", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true); 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); is(getValue(dbg, 4), 2);
await toggleExpressionNode(dbg, 1); 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 resume(dbg);
await addExpression(dbg, "location"); await addExpression(dbg, "location");
is(findAllElements(dbg, "expressionNodes").length, 17); is(findAllElements(dbg, "expressionNodes").length, 34);
await toggleExpressionNode(dbg, 1); await toggleExpressionNode(dbg, 1);
is(findAllElements(dbg, "expressionNodes").length, 1); is(findAllElements(dbg, "expressionNodes").length, 1);

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

@ -70,6 +70,10 @@ add_task(async function() {
pressKey(dbg, "Escape"); pressKey(dbg, "Escape");
is(getItems(dbg).length, 9, "9 items in the list after escape pressed"); 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 // check that the term 'todo' includes items with todo
type(dbg, "todo"); type(dbg, "todo");
is(getItems(dbg).length, 2, "2 items in the list after 'todo' filter"); is(getItems(dbg).length, 2, "2 items in the list after 'todo' filter");

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

@ -104,51 +104,6 @@ class FlexboxInspector {
this.walker = null; 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() { getComponentProps() {
return { return {
onSetFlexboxOverlayColor: this.onSetFlexboxOverlayColor, onSetFlexboxOverlayColor: this.onSetFlexboxOverlayColor,
@ -172,6 +127,58 @@ class FlexboxInspector {
return this._customHostColors; 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. * Returns an array of flex items object for the given flex container front.
* *
@ -303,25 +310,36 @@ class FlexboxInspector {
} }
try { try {
const flexboxFront = await this.layoutInspector.getCurrentFlexbox( const flexContainer = await this.getFlexContainerProps(this.selection.nodeFront);
this.selection.nodeFront);
// Clear the flexbox panel if there is no flex container for the current node // Clear the flexbox panel if there is no flex container for the current node
// selection. // selection.
if (!flexboxFront) { if (!flexContainer) {
this.store.dispatch(clearFlexbox()); this.store.dispatch(clearFlexbox());
return; return;
} }
const { flexbox } = this.store.getState(); const { flexbox } = this.store.getState();
// Do nothing because the same flex container is still selected. // Compare the new flexbox state of the current selected nodeFront with the old
if (flexbox.actorID == flexboxFront.actorID) { // flexbox state to determine if we need to update.
if (hasFlexContainerChanged(flexbox.flexContainer, flexContainer)) {
this.update(flexContainer);
return; return;
} }
// Update the flexbox panel with the new flexbox front contents. let flexItemContainer = null;
this.update(flexboxFront); // 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) { } catch (e) {
// This call might fail if called asynchrously after the toolbox is finished // This call might fail if called asynchrously after the toolbox is finished
// closing. // closing.
@ -427,10 +445,14 @@ class FlexboxInspector {
* the layout view becomes visible or a new node is selected and needs to be update * the layout view becomes visible or a new node is selected and needs to be update
* with new flexbox data. * with new flexbox data.
* *
* @param {FlexboxFront|null} flexboxFront * @param {Object|null} flexContainer
* The FlexboxFront of the flex container for the current node selection. * 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 // Stop refreshing if the inspector or store is already destroyed or no node is
// selected. // selected.
if (!this.inspector || if (!this.inspector ||
@ -442,53 +464,35 @@ class FlexboxInspector {
try { try {
// Fetch the current flexbox if no flexbox front was passed into this update. // Fetch the current flexbox if no flexbox front was passed into this update.
if (!flexboxFront) { if (!flexContainer) {
flexboxFront = await this.layoutInspector.getCurrentFlexbox( flexContainer = await this.getFlexContainerProps(this.selection.nodeFront);
this.selection.nodeFront);
} }
// Clear the flexbox panel if there is no flex container for the current node // Clear the flexbox panel if there is no flex container for the current node
// selection. // selection.
if (!flexboxFront) { if (!flexContainer) {
this.store.dispatch(clearFlexbox()); this.store.dispatch(clearFlexbox());
return; return;
} }
// If the FlexboxFront doesn't yet have access to the NodeFront for its container, if (!flexItemContainer && flexContainer.nodeFront === this.selection.nodeFront) {
// then get it from the walker. This happens when the walker hasn't seen this flexItemContainer = await this.getFlexContainerProps(this.selection.nodeFront,
// particular DOM Node in the tree yet or when we are connected to an older server. true);
let containerNodeFront = flexboxFront.containerNodeFront;
if (!containerNodeFront) {
containerNodeFront = await this.walker.getNodeFromActor(flexboxFront.actorID,
["containerEl"]);
} }
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 && const highlighted = this._highlighters &&
containerNodeFront == this.highlighters.flexboxHighlighterShown; flexContainer.nodeFront === this.highlighters.flexboxHighlighterShown;
const color = await this.getOverlayColor(); const color = await this.getOverlayColor();
this.store.dispatch(updateFlexbox({ this.store.dispatch(updateFlexbox({
color, color,
flexContainer: { flexContainer,
actorID: flexboxFront.actorID,
flexItems,
flexItemShown: flexItemShown ? flexItemShown.nodeFront.actorID : null,
isFlexItemContainer: false,
nodeFront: containerNodeFront,
properties: flexboxFront.properties,
},
flexItemContainer, flexItemContainer,
highlighted, highlighted,
})); }));
const isContainerInfoShown = !flexItemShown || !!flexItemContainer; const isContainerInfoShown = !flexContainer.flexItemShown || !!flexItemContainer;
const isItemInfoShown = !!flexItemShown || !!flexItemContainer; const isItemInfoShown = !!flexContainer.flexItemShown || !!flexItemContainer;
this.sendTelemetryProbes(isContainerInfoShown, isItemInfoShown); this.sendTelemetryProbes(isContainerInfoShown, isItemInfoShown);
} catch (e) { } catch (e) {
// This call might fail if called asynchrously after the toolbox is finished // 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; module.exports = FlexboxInspector;

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

@ -20,6 +20,7 @@ support-files =
[browser_flexbox_accordion_state.js] [browser_flexbox_accordion_state.js]
[browser_flexbox_container_and_item.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_element_rep.js]
[browser_flexbox_container_properties.js] [browser_flexbox_container_properties.js]
[browser_flexbox_empty_state.js] [browser_flexbox_empty_state.js]
@ -27,6 +28,7 @@ support-files =
[browser_flexbox_highlighter_color_picker_on_RETURN.js] [browser_flexbox_highlighter_color_picker_on_RETURN.js]
[browser_flexbox_item_list_01.js] [browser_flexbox_item_list_01.js]
[browser_flexbox_item_list_02.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_exists.js]
[browser_flexbox_item_outline_has_correct_layout.js] [browser_flexbox_item_outline_has_correct_layout.js]
[browser_flexbox_item_outline_hidden_when_useless.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_for_text_nodes.js]
[browser_flexbox_sizing_info_has_correct_sections.js] [browser_flexbox_sizing_info_has_correct_sections.js]
[browser_flexbox_sizing_info_matches_properties_with_!important.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_sizing_wanted_to_grow_but_was_clamped.js]
[browser_flexbox_text_nodes_are_listed.js] [browser_flexbox_text_nodes_are_listed.js]
[browser_flexbox_toggle_flexbox_highlighter_01.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; 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) { function sortProperties(properties) {
return properties.sort((a, b) => { return properties.sort((a, b) => {
// Sort numbers in ascending order and sort strings lexicographically // Sort numbers in ascending order and sort strings lexicographically
@ -3442,6 +3416,18 @@ function makeNodesForProperties(objProps, parent) {
nodes.push(makeNodesForEntries(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 // Add the prototype if it exists and is not null
if (prototype && prototype.type !== "null") { if (prototype && prototype.type !== "null") {
nodes.push(makeNodeForPrototype(objProps, parent)); 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) { function getSymbolDescriptor(symbol) {
return symbol.toString().replace(/^(Symbol\()(.*)(\))$/, "$2"); return symbol.toString().replace(/^(Symbol\()(.*)(\))$/, "$2");
} }
@ -3552,10 +3556,6 @@ function getChildren(options) {
return addToCache(item.contents); return addToCache(item.contents);
} }
if (nodeHasAccessors(item)) {
return addToCache(makeNodesForAccessors(item));
}
if (nodeIsMapEntry(item)) { if (nodeIsMapEntry(item)) {
return addToCache(makeNodesForMapEntry(item)); return addToCache(makeNodesForMapEntry(item));
} }
@ -3647,6 +3647,8 @@ function getClosestNonBucketNode(item) {
module.exports = { module.exports = {
createNode, createNode,
createGetterNode,
createSetterNode,
getActor, getActor,
getChildren, getChildren,
getClosestGripNode, getClosestGripNode,
@ -6487,7 +6489,7 @@ class ObjectInspector extends Component {
const parentElementProps = { const parentElementProps = {
className: classnames("node object-node", { className: classnames("node object-node", {
focused, 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) block: nodeIsBlock(item)
}), }),
onClick: e => { onClick: e => {
@ -6557,7 +6559,9 @@ class ObjectInspector extends Component {
autoExpandDepth, autoExpandDepth,
isExpanded: item => expandedPaths && expandedPaths.has(item.path), 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, focused: this.focusedItem,
getRoots: this.getRoots, getRoots: this.getRoots,

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -13282,18 +13282,43 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
nsAutoString referrer; nsAutoString referrer;
aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer); aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(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()) { while (tok.hasMoreTokens()) {
const nsAString& token = tok.nextToken(); const nsAString& token = tok.nextToken();
if (token.LowerCaseEqualsLiteral("noreferrer")) { if (token.LowerCaseEqualsLiteral("noreferrer")) {
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER | flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
INTERNAL_LOAD_FLAGS_NO_OPENER; 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; break;
} }
if (token.LowerCaseEqualsLiteral("noopener")) { if (token.LowerCaseEqualsLiteral("noopener")) {
flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; 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) { if (aNoOpenerImplied) {
flags |= INTERNAL_LOAD_FLAGS_NO_OPENER; flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
} }

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

@ -116,6 +116,7 @@ function test6() {
function test7() { function test7() {
testlink.href = "javascript:opener.activationListener(); window.close();"; testlink.href = "javascript:opener.activationListener(); window.close();";
testlink.target = "_blank"; testlink.target = "_blank";
testlink.rel = "opener";
activationListener = activationListener =
function() { function() {
ok(true, "Click() should activate a link"); ok(true, "Click() should activate a link");
@ -127,6 +128,7 @@ function test7() {
function test8() { function test8() {
testlink.href = "javascript:opener.activationListener(); window.close();"; testlink.href = "javascript:opener.activationListener(); window.close();";
testlink.target = "_blank"; testlink.target = "_blank";
testlink.rel = "opener";
activationListener = activationListener =
function() { function() {
ok(false, "Click() should not activate a link"); ok(false, "Click() should not activate a link");

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

@ -1,6 +1,6 @@
<html> <html>
<body> <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> <script>
function clickLink() { function clickLink() {

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

@ -37,3 +37,7 @@ skip-if = os == 'mac' # bug 1494843
[browser_refresh_wyciwyg_url.js] [browser_refresh_wyciwyg_url.js]
support-files = support-files =
file_refresh_wyciwyg_url.html 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);
});

1
dom/html/test/empty.html Normal file
Просмотреть файл

@ -0,0 +1 @@
<html><body></body></html>

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

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<body onload="document.querySelector('a').click();"> <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> <div id="result">not tested yet</div>
</body> </body>

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

@ -1,4 +1,4 @@
<!DOCTYPE html> <!DOCTYPE html>
<meta charset="UTF-8"> <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> onclick="document.body.requestFullscreen()">Click here</a>

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

@ -30,7 +30,7 @@
<body onLoad="doStuff()"> <body onLoad="doStuff()">
I am sandboxed but with "allow-scripts allow-same-origin" 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> <a href="file_iframe_sandbox_open_window_fail.html" target="BC341604" id="target_BC341604">open window</a>
</body> </body>
</html> </html>

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

@ -28,7 +28,7 @@
<body onLoad="doStuff()"> <body onLoad="doStuff()">
I am sandboxed but with "allow-popups allow-scripts allow-same-origin" 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> <a href="file_iframe_sandbox_open_window_pass.html?BC766282" target="BC766282" id="target_BC766282">open window</a>
</body> </body>
</html> </html>

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

@ -41,7 +41,7 @@
This was opened in an iframe with "allow-scripts allow-popups allow-same-origin". 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, However allow-same-origin was removed from the iframe before navigating to me,
so I should only have "allow-scripts allow-popups" in force. 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> <a href="file_iframe_sandbox_k_if2.html" target="BC766282_if2" id="target_BC766282_if2">open window</a>
</body> </body>
</html> </html>

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

@ -25,10 +25,10 @@
<body onLoad="doStuff()"> <body onLoad="doStuff()">
I am sandboxed with "allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation". 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_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> <a href="file_iframe_sandbox_k_if7.html" target="BC766282_if7" id="target_BC766282_if7">open window</a>
</body> </body>
</html> </html>

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

@ -26,7 +26,7 @@
After my initial load, "allow-same-origin" is removed and then I open file_iframe_sandbox_k_if9.html 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. 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. 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> <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 Now navigate to file_iframe_sandbox_k_if1.html to do tests for a sandbox opening a window

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

@ -1,5 +1,5 @@
<html> <html>
<body> <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> </html>
</body> </body>

Двоичные данные
dom/html/test/image_yellow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 95 B

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

@ -119,7 +119,7 @@ class RemoteVideoDecoder : public RemoteDataDecoder {
if (ok && (size > 0 || presentationTimeUs >= 0)) { if (ok && (size > 0 || presentationTimeUs >= 0)) {
RefPtr<layers::Image> img = new SurfaceTextureImage( RefPtr<layers::Image> img = new SurfaceTextureImage(
mDecoder->mImageHandle, inputInfo.mImageSize, mDecoder->mSurfaceHandle, inputInfo.mImageSize,
false /* NOT continuous */, gl::OriginPos::BottomLeft); false /* NOT continuous */, gl::OriginPos::BottomLeft);
RefPtr<VideoData> v = VideoData::CreateFromImage( RefPtr<VideoData> v = VideoData::CreateFromImage(
@ -168,7 +168,7 @@ class RemoteVideoDecoder : public RemoteDataDecoder {
__func__); __func__);
} }
mImageHandle = mSurface->GetImageHandle(); mSurfaceHandle = mSurface->GetHandle();
// Register native methods. // Register native methods.
JavaCallbacksSupport::Init(); JavaCallbacksSupport::Init();
@ -256,7 +256,7 @@ class RemoteVideoDecoder : public RemoteDataDecoder {
private: private:
const VideoInfo mConfig; const VideoInfo mConfig;
GeckoSurface::GlobalRef mSurface; GeckoSurface::GlobalRef mSurface;
AndroidSurfaceTextureHandle mImageHandle; AndroidSurfaceTextureHandle mSurfaceHandle;
// Only accessed on reader's task queue. // Only accessed on reader's task queue.
bool mIsCodecSupportAdaptivePlayback = false; bool mIsCodecSupportAdaptivePlayback = false;
// Can be accessed on any thread, but only written on during init. // 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> <title>Tests for Mixed Content Frame Navigation</title>
</head> </head>
<body> <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> <script>
var blankTarget = document.getElementById("blankTarget"); 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="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="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="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> </body>
</html> </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="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> <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> </div>
<pre id="test"> <pre id="test">
<a id="testlink1" target="_blank" href="javascript:window.opener.finish(sessionStorage['testItem']);window.close();">Javascript 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" href="bug458091_child.html">HTTP 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> <a id="testlink3" target="alreadyOpened" href="bug458091_child.html">Target Link</a>
<script type="application/javascript"> <script type="application/javascript">

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

@ -8,13 +8,6 @@
#include "AndroidSurfaceTexture.h" #include "AndroidSurfaceTexture.h"
#include "GeneratedJNINatives.h"
#include "AndroidNativeWindow.h"
#include "GLContextEGL.h"
#include "GLBlitHelper.h"
#include "GLImages.h"
using namespace mozilla; using namespace mozilla;
namespace mozilla { namespace mozilla {
@ -36,184 +29,6 @@ AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::Param surfa
env->ReleaseFloatArrayElements(jarray.Get(), array, 0); 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 } // gl
} // mozilla } // mozilla
#endif // MOZ_WIDGET_ANDROID #endif // MOZ_WIDGET_ANDROID

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

@ -18,7 +18,6 @@ namespace gl {
class AndroidSurfaceTexture { class AndroidSurfaceTexture {
public: public:
static void Init();
static void GetTransformMatrix(java::sdk::SurfaceTexture::Param surfaceTexture, static void GetTransformMatrix(java::sdk::SurfaceTexture::Param surfaceTexture,
mozilla::gfx::Matrix4x4* outMatrix); mozilla::gfx::Matrix4x4* outMatrix);

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

@ -280,7 +280,7 @@ bool
SharedSurface_SurfaceTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) SharedSurface_SurfaceTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{ {
*out_descriptor = *out_descriptor =
layers::SurfaceTextureDescriptor(mSurface->GetImageHandle(), layers::SurfaceTextureDescriptor(mSurface->GetHandle(),
mSize, mSize,
gfx::SurfaceFormat::R8G8B8A8, gfx::SurfaceFormat::R8G8B8A8,
false /* NOT continuous */, false /* NOT continuous */,

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

@ -170,7 +170,7 @@ AndroidNativeWindowTextureData::FillInfo(TextureData::Info& aInfo) const
bool bool
AndroidNativeWindowTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) AndroidNativeWindowTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{ {
aOutDescriptor = SurfaceTextureDescriptor(mSurface->GetImageHandle(), aOutDescriptor = SurfaceTextureDescriptor(mSurface->GetHandle(),
mSize, mSize,
mFormat, mFormat,
false /* not continuous */, false /* not continuous */,

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

@ -324,6 +324,7 @@ AnimationFrameDiscardingQueue::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf
AnimationFrameRecyclingQueue::AnimationFrameRecyclingQueue(AnimationFrameRetainedBuffer&& aQueue) AnimationFrameRecyclingQueue::AnimationFrameRecyclingQueue(AnimationFrameRetainedBuffer&& aQueue)
: AnimationFrameDiscardingQueue(std::move(aQueue)) : AnimationFrameDiscardingQueue(std::move(aQueue))
, mForceUseFirstFrameRefreshArea(false)
{ {
// In an ideal world, we would always save the already displayed frames for // 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 // 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.empty());
MOZ_ASSERT(mDisplay.front()); 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(); RefPtr<imgFrame>& front = mDisplay.front();
RecycleEntry newEntry(mForceUseFirstFrameRefreshArea ? mFirstFrameRefreshArea
// 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
: front->GetDirtyRect()); : front->GetDirtyRect());
// If we are allowed to recycle the frame, then we should save it before the // If we are allowed to recycle the frame, then we should save it before the
// base class's AdvanceInternal discards it. // base class's AdvanceInternal discards it.
if (front->ShouldRecycle()) { 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); newEntry.mFrame = std::move(front);
} }
@ -428,20 +418,62 @@ AnimationFrameRecyclingQueue::ResetInternal()
RawAccessFrameRef RawAccessFrameRef
AnimationFrameRecyclingQueue::RecycleFrame(gfx::IntRect& aRecycleRect) 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()) { if (mRecycle.empty()) {
return RawAccessFrameRef(); return RawAccessFrameRef();
} }
RawAccessFrameRef frame; RawAccessFrameRef recycledFrame;
if (mRecycle.front().mFrame) { if (mRecycle.front().mFrame) {
frame = mRecycle.front().mFrame->RawAccessRef(); recycledFrame = mRecycle.front().mFrame->RawAccessRef();
if (frame) { MOZ_ASSERT(recycledFrame);
aRecycleRect = mRecycle.front().mRecycleRect; 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 recycledFrame;
return frame;
} }
bool bool

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

@ -449,15 +449,12 @@ public:
RecycleEntry(RecycleEntry&& aOther) RecycleEntry(RecycleEntry&& aOther)
: mFrame(std::move(aOther.mFrame)) : mFrame(std::move(aOther.mFrame))
, mDirtyRect(aOther.mDirtyRect) , mDirtyRect(aOther.mDirtyRect)
, mRecycleRect(aOther.mRecycleRect) { }
{
}
RecycleEntry& operator=(RecycleEntry&& aOther) RecycleEntry& operator=(RecycleEntry&& aOther)
{ {
mFrame = std::move(aOther.mFrame); mFrame = std::move(aOther.mFrame);
mDirtyRect = aOther.mDirtyRect; mDirtyRect = aOther.mDirtyRect;
mRecycleRect = aOther.mRecycleRect;
return *this; return *this;
} }
@ -466,8 +463,6 @@ public:
RefPtr<imgFrame> mFrame; // The frame containing the buffer to recycle. RefPtr<imgFrame> mFrame; // The frame containing the buffer to recycle.
gfx::IntRect mDirtyRect; // The dirty rect of the frame itself. 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; } 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 first frame refresh area. This is used instead of the dirty rect for
/// the last frame when transitioning back to the first frame. /// the last frame when transitioning back to the first frame.
gfx::IntRect mFirstFrameRefreshArea; 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 } // namespace image

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

@ -27,6 +27,9 @@ CreateEmptyFrame(const IntSize& aSize = IntSize(1, 1),
EXPECT_TRUE(NS_SUCCEEDED(rv)); EXPECT_TRUE(NS_SUCCEEDED(rv));
RawAccessFrameRef frameRef = frame->RawAccessRef(); RawAccessFrameRef frameRef = frame->RawAccessRef();
frame->SetRawAccessOnly(); 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(); frame->Finish();
return frame.forget(); return frame.forget();
} }
@ -105,16 +108,13 @@ VerifyAdvance(AnimationFrameBuffer& aQueue,
if (aQueue.IsRecycling()) { if (aQueue.IsRecycling()) {
const AnimationFrameRecyclingQueue& queue = const AnimationFrameRecyclingQueue& queue =
*static_cast<AnimationFrameRecyclingQueue*>(&aQueue); *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()) { if (oldFrame->ShouldRecycle()) {
EXPECT_EQ(oldFrame.get(), queue.Recycle().back().mFrame.get()); 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 { } else {
EXPECT_EQ(totalRecycled, queue.Recycle().size()); EXPECT_EQ(nullptr, queue.Recycle().back().mFrame.get());
if (!queue.Recycle().empty()) {
EXPECT_NE(oldFrame.get(), queue.Recycle().back().mFrame.get());
}
} }
} }
} }
@ -584,7 +584,7 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingLoop)
// All the frames we inserted should have been recycleable. // All the frames we inserted should have been recycleable.
ASSERT_FALSE(buffer.Recycle().empty()); ASSERT_FALSE(buffer.Recycle().empty());
while (!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; RefPtr<imgFrame> expectedFrame = buffer.Recycle().front().mFrame;
EXPECT_FALSE(expectedRect.IsEmpty()); EXPECT_FALSE(expectedRect.IsEmpty());
EXPECT_TRUE(expectedFrame.get() != nullptr); EXPECT_TRUE(expectedFrame.get() != nullptr);
@ -646,3 +646,109 @@ TEST_F(ImageAnimationFrameBuffer, RecyclingReset)
AnimationFrameRecyclingQueue buffer(std::move(retained)); AnimationFrameRecyclingQueue buffer(std::move(retained));
TestDiscardingQueueReset(buffer, firstFrame, kThreshold, kBatch, kStartFrame); 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 // To generate this file, see the documentation in
// js/src/frontend/binsource/README.md. // js/src/frontend/binsource/README.md.
#include "frontend/BinASTParser.h"
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/Casting.h" #include "mozilla/Casting.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
@ -17,7 +19,6 @@
#include "mozilla/Vector.h" #include "mozilla/Vector.h"
#include "frontend/BinSource-macros.h" #include "frontend/BinSource-macros.h"
#include "frontend/BinSource.h"
#include "frontend/BinTokenReaderTester.h" #include "frontend/BinTokenReaderTester.h"
#include "frontend/FullParseHandler.h" #include "frontend/FullParseHandler.h"
#include "frontend/ParseNode.h" #include "frontend/ParseNode.h"
@ -2954,7 +2955,7 @@ BinASTParser<Tok>::parseInterfaceGetterContents(const size_t start, const BinKin
(void) isThisCaptured; (void) isThisCaptured;
MOZ_TRY(parseAssertedVarScope()); 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()); BINJS_MOZ_TRY_DECL(body, parseFunctionBody());
*paramsOut = params; *paramsOut = params;
@ -3494,7 +3495,7 @@ BinASTParser<Tok>::parseInterfaceSetterContents(const size_t start, const BinKin
&positionalParams)); &positionalParams));
BINJS_MOZ_TRY_DECL(param, parseParameter()); 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); factory_.addList(params, param);
MOZ_TRY(checkPositionalParameterIndices(positionalParams, params)); MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
MOZ_TRY(parseAssertedVarScope()); MOZ_TRY(parseAssertedVarScope());
@ -4516,7 +4517,7 @@ BinASTParser<Tok>::parseListOfParameter()
const auto start = tokenizer_->offset(); const auto start = tokenizer_->offset();
MOZ_TRY(tokenizer_->enterList(length, guard)); 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) { for (uint32_t i = 0; i < length; ++i) {
BINJS_MOZ_TRY_DECL(item, parseParameter()); 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 * 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/. */ * 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/ArrayUtils.h"
#include "mozilla/Casting.h" #include "mozilla/Casting.h"
@ -14,6 +14,7 @@
#include "mozilla/ScopeExit.h" #include "mozilla/ScopeExit.h"
#include "mozilla/Vector.h" #include "mozilla/Vector.h"
#include "frontend/BinASTParser.h"
#include "frontend/BinSource-macros.h" #include "frontend/BinSource-macros.h"
#include "frontend/BinTokenReaderTester.h" #include "frontend/BinTokenReaderTester.h"
#include "frontend/FullParseHandler.h" #include "frontend/FullParseHandler.h"
@ -77,50 +78,18 @@ namespace frontend {
using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr; 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 // ------------- Toplevel constructions
template<typename Tok> JS::Result<ParseNode*> 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) BinASTSourceMetadata** metadataPtr)
{ {
return parse(globalsc, data.begin(), data.length(), metadataPtr); return parse(globalsc, data.begin(), data.length(), metadataPtr);
} }
template<typename Tok> JS::Result<ParseNode*> 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) BinASTSourceMetadata** metadataPtr)
{ {
auto result = parseAux(globalsc, start, length, 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*> template<typename Tok> JS::Result<ParseNode*>
BinASTParser<Tok>::parseAux(GlobalSharedContext* globalsc, BinASTParserPerTokenizer<Tok>::parseAux(GlobalSharedContext* globalsc,
const uint8_t* start, const size_t length, const uint8_t* start, const size_t length,
BinASTSourceMetadata** metadataPtr) BinASTSourceMetadata** metadataPtr)
{ {
@ -151,7 +120,7 @@ BinASTParser<Tok>::parseAux(GlobalSharedContext* globalsc,
MOZ_TRY(tokenizer_->readHeader()); MOZ_TRY(tokenizer_->readHeader());
ParseNode* result(nullptr); ParseNode* result(nullptr);
MOZ_TRY_VAR(result, parseProgram()); MOZ_TRY_VAR(result, asFinalParser()->parseProgram());
mozilla::Maybe<GlobalScope::Data*> bindings = NewGlobalScopeData(cx_, varScope, alloc_, mozilla::Maybe<GlobalScope::Data*> bindings = NewGlobalScopeData(cx_, varScope, alloc_,
parseContext_); parseContext_);
@ -168,7 +137,8 @@ BinASTParser<Tok>::parseAux(GlobalSharedContext* globalsc,
} }
template<typename Tok> JS::Result<ParseNode*> 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(lazyScript_);
MOZ_ASSERT(scriptSource->length() > firstOffset); MOZ_ASSERT(scriptSource->length() > firstOffset);
@ -203,9 +173,9 @@ BinASTParser<Tok>::parseLazyFunction(ScriptSource* scriptSource, const size_t fi
BINJS_TRY(lexicalScope.init(parseContext_)); BINJS_TRY(lexicalScope.init(parseContext_));
ListNode* params; ListNode* params;
ListNode* tmpBody; ListNode* tmpBody;
auto parseFunc = isExpr ? &BinASTParser::parseFunctionExpressionContents auto parseFunc = isExpr ? &FinalParser::parseFunctionExpressionContents
: &BinASTParser::parseFunctionOrMethodContents; : &FinalParser::parseFunctionOrMethodContents;
MOZ_TRY((this->*parseFunc)(func->nargs(), &params, &tmpBody)); MOZ_TRY((asFinalParser()->*parseFunc)(func->nargs(), &params, &tmpBody));
BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_)); BINJS_TRY_DECL(lexicalScopeData, NewLexicalScopeData(cx_, lexicalScope, alloc_, parseContext_));
BINJS_TRY_DECL(body, factory_.newLexicalScope(*lexicalScopeData, tmpBody)); 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 template<typename Tok> void
BinASTParser<Tok>::forceStrictIfNecessary(SharedContext* sc, ListNode* directives) BinASTParserPerTokenizer<Tok>::forceStrictIfNecessary(SharedContext* sc, ListNode* directives)
{ {
JSAtom* useStrict = cx_->names().useStrict; JSAtom* useStrict = cx_->names().useStrict;
@ -228,7 +198,7 @@ BinASTParser<Tok>::forceStrictIfNecessary(SharedContext* sc, ListNode* directive
} }
template<typename Tok> JS::Result<FunctionBox*> template<typename Tok> JS::Result<FunctionBox*>
BinASTParser<Tok>::buildFunctionBox(GeneratorKind generatorKind, BinASTParserPerTokenizer<Tok>::buildFunctionBox(GeneratorKind generatorKind,
FunctionAsyncKind functionAsyncKind, FunctionAsyncKind functionAsyncKind,
FunctionSyntaxKind syntax, FunctionSyntaxKind syntax,
ParseNode* name) ParseNode* name)
@ -288,7 +258,8 @@ BinASTParser<Tok>::buildFunctionBox(GeneratorKind generatorKind,
} }
template<typename Tok> JS::Result<CodeNode*> 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. // LazyScript compilation requires basically none of the fields filled out.
TokenPos pos = tokenizer_->pos(start); 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*> template<typename Tok> JS::Result<ParseNode*>
BinASTParser<Tok>::buildFunction(const size_t start, const BinKind kind, ParseNode* name, BinASTParserPerTokenizer<Tok>::buildFunction(const size_t start, const BinKind kind,
ListNode* params, ParseNode* body, FunctionBox* funbox) ParseNode* name, ListNode* params, ParseNode* body,
FunctionBox* funbox)
{ {
// Set the argument count for building argument packets. Function.length is handled // Set the argument count for building argument packets. Function.length is handled
// by setting the appropriate funbox field during argument parsing. // 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> 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, ParseContext::Scope* scope, DeclarationKind declKind,
bool isCaptured, bool allowDuplicateName) bool isCaptured, bool allowDuplicateName)
{ {
@ -429,7 +401,7 @@ BinASTParser<Tok>::addScopeName(AssertedScopeKind scopeKind, HandleAtom name,
} }
template<typename Tok> void template<typename Tok> void
BinASTParser<Tok>::captureFunctionName() BinASTParserPerTokenizer<Tok>::captureFunctionName()
{ {
MOZ_ASSERT(parseContext_->isFunctionBox()); MOZ_ASSERT(parseContext_->isFunctionBox());
MOZ_ASSERT(parseContext_->functionBox()->function()->isNamedLambda()); MOZ_ASSERT(parseContext_->functionBox()->function()->isNamedLambda());
@ -443,8 +415,10 @@ BinASTParser<Tok>::captureFunctionName()
} }
template<typename Tok> JS::Result<Ok> template<typename Tok> JS::Result<Ok>
BinASTParser<Tok>::getDeclaredScope(AssertedScopeKind scopeKind, AssertedDeclaredKind kind, BinASTParserPerTokenizer<Tok>::getDeclaredScope(AssertedScopeKind scopeKind,
ParseContext::Scope*& scope, DeclarationKind& declKind) AssertedDeclaredKind kind,
ParseContext::Scope*& scope,
DeclarationKind& declKind)
{ {
MOZ_ASSERT(scopeKind == AssertedScopeKind::Block || MOZ_ASSERT(scopeKind == AssertedScopeKind::Block ||
scopeKind == AssertedScopeKind::Global || scopeKind == AssertedScopeKind::Global ||
@ -471,8 +445,9 @@ BinASTParser<Tok>::getDeclaredScope(AssertedScopeKind scopeKind, AssertedDeclare
} }
template<typename Tok> JS::Result<Ok> template<typename Tok> JS::Result<Ok>
BinASTParser<Tok>::getBoundScope(AssertedScopeKind scopeKind, BinASTParserPerTokenizer<Tok>::getBoundScope(AssertedScopeKind scopeKind,
ParseContext::Scope*& scope, DeclarationKind& declKind) ParseContext::Scope*& scope,
DeclarationKind& declKind)
{ {
MOZ_ASSERT(scopeKind == AssertedScopeKind::Catch || MOZ_ASSERT(scopeKind == AssertedScopeKind::Catch ||
scopeKind == AssertedScopeKind::Parameter); scopeKind == AssertedScopeKind::Parameter);
@ -495,7 +470,7 @@ BinASTParser<Tok>::getBoundScope(AssertedScopeKind scopeKind,
} }
template<typename Tok> JS::Result<Ok> 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. // Check that the variable appears in the corresponding scope.
ParseContext::Scope& scope = ParseContext::Scope& scope =
@ -514,7 +489,7 @@ BinASTParser<Tok>::checkBinding(JSAtom* name)
// Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda) // Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda)
// 3.1.5 CheckPositionalParameterIndices. // 3.1.5 CheckPositionalParameterIndices.
template<typename Tok> JS::Result<Ok> template<typename Tok> JS::Result<Ok>
BinASTParser<Tok>::checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> positionalParams, BinASTParserPerTokenizer<Tok>::checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> positionalParams,
ListNode* params) ListNode* params)
{ {
// positionalParams should have the corresponding entry up to the last // 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) // Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda)
// 3.1.13 CheckFunctionLength. // 3.1.13 CheckFunctionLength.
template<typename Tok> JS::Result<Ok> template<typename Tok> JS::Result<Ok>
BinASTParser<Tok>::checkFunctionLength(uint32_t expectedLength) BinASTParserPerTokenizer<Tok>::checkFunctionLength(uint32_t expectedLength)
{ {
if (parseContext_->functionBox()->length != expectedLength) { if (parseContext_->functionBox()->length != expectedLength) {
return raiseError("Function length does't match"); return raiseError("Function length does't match");
@ -610,7 +585,7 @@ BinASTParser<Tok>::checkFunctionLength(uint32_t expectedLength)
} }
template<typename Tok> JS::Result<Ok> 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++) { for (ParseContext::Scope::BindingIter bi = scope.bindings(parseContext_); bi; bi++) {
if (UsedNamePtr p = usedNames_.lookup(bi.name())) { if (UsedNamePtr p = usedNames_.lookup(bi.name())) {
@ -626,7 +601,7 @@ BinASTParser<Tok>::checkClosedVars(ParseContext::Scope& scope)
} }
template<typename Tok> JS::Result<Ok> template<typename Tok> JS::Result<Ok>
BinASTParser<Tok>::checkFunctionClosedVars() BinASTParserPerTokenizer<Tok>::checkFunctionClosedVars()
{ {
MOZ_ASSERT(parseContext_->isFunctionBox()); MOZ_ASSERT(parseContext_->isFunctionBox());
@ -640,7 +615,7 @@ BinASTParser<Tok>::checkFunctionClosedVars()
} }
template<typename Tok> JS::Result<Ok> template<typename Tok> JS::Result<Ok>
BinASTParser<Tok>::prependDirectivesToBody(ListNode* body, ListNode* directives) BinASTParserPerTokenizer<Tok>::prependDirectivesToBody(ListNode* body, ListNode* directives)
{ {
if (!directives) { if (!directives) {
return Ok(); return Ok();
@ -656,7 +631,7 @@ BinASTParser<Tok>::prependDirectivesToBody(ListNode* body, ListNode* directives)
} }
template<typename Tok> JS::Result<Ok> template<typename Tok> JS::Result<Ok>
BinASTParser<Tok>::prependDirectivesImpl(ListNode* body, ParseNode* directive) BinASTParserPerTokenizer<Tok>::prependDirectivesImpl(ListNode* body, ParseNode* directive)
{ {
BINJS_TRY(CheckRecursionLimit(cx_)); BINJS_TRY(CheckRecursionLimit(cx_));
@ -673,13 +648,13 @@ BinASTParser<Tok>::prependDirectivesImpl(ListNode* body, ParseNode* directive)
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> 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"); return raiseError("Captured variable was not declared as captured");
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> 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 // For the moment, we don't trust inputs sufficiently to put the name
// in an error message. // in an error message.
@ -687,13 +662,13 @@ BinASTParser<Tok>::raiseMissingVariableInAssertedScope(JSAtom* name)
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
BinASTParser<Tok>::raiseMissingDirectEvalInAssertedScope() BinASTParserPerTokenizer<Tok>::raiseMissingDirectEvalInAssertedScope()
{ {
return raiseError("Direct call to `eval` was not declared in AssertedScope"); return raiseError("Direct call to `eval` was not declared in AssertedScope");
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> 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_); Sprinter out(cx_);
BINJS_TRY(out.init()); BINJS_TRY(out.init());
@ -702,7 +677,7 @@ BinASTParser<Tok>::raiseInvalidKind(const char* superKind, const BinKind kind)
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> 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_); Sprinter out(cx_);
BINJS_TRY(out.init()); BINJS_TRY(out.init());
@ -712,7 +687,7 @@ BinASTParser<Tok>::raiseInvalidVariant(const char* kind, const BinVariant value)
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> 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_); Sprinter out(cx_);
BINJS_TRY(out.init()); BINJS_TRY(out.init());
@ -722,7 +697,7 @@ BinASTParser<Tok>::raiseMissingField(const char* kind, const BinField field)
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
BinASTParser<Tok>::raiseEmpty(const char* description) BinASTParserPerTokenizer<Tok>::raiseEmpty(const char* description)
{ {
Sprinter out(cx_); Sprinter out(cx_);
BINJS_TRY(out.init()); BINJS_TRY(out.init());
@ -732,13 +707,13 @@ BinASTParser<Tok>::raiseEmpty(const char* description)
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
BinASTParser<Tok>::raiseOOM() BinASTParserPerTokenizer<Tok>::raiseOOM()
{ {
return tokenizer_->raiseOOM(); return tokenizer_->raiseOOM();
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> 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_); Sprinter out(cx_);
BINJS_TRY(out.init()); BINJS_TRY(out.init());
@ -747,19 +722,19 @@ BinASTParser<Tok>::raiseError(BinKind kind, const char* description)
} }
template<typename Tok> mozilla::GenericErrorResult<JS::Error&> template<typename Tok> mozilla::GenericErrorResult<JS::Error&>
BinASTParser<Tok>::raiseError(const char* description) BinASTParserPerTokenizer<Tok>::raiseError(const char* description)
{ {
return tokenizer_->raiseError(description); return tokenizer_->raiseError(description);
} }
template<typename Tok> void template<typename Tok> void
BinASTParser<Tok>::poison() BinASTParserPerTokenizer<Tok>::poison()
{ {
tokenizer_.reset(); tokenizer_.reset();
} }
template<typename Tok> void template<typename Tok> void
BinASTParser<Tok>::reportErrorNoOffsetVA(unsigned errorNumber, va_list args) BinASTParserPerTokenizer<Tok>::reportErrorNoOffsetVA(unsigned errorNumber, va_list args)
{ {
ErrorMetadata metadata; ErrorMetadata metadata;
metadata.filename = getFilename(); metadata.filename = getFilename();
@ -770,7 +745,7 @@ BinASTParser<Tok>::reportErrorNoOffsetVA(unsigned errorNumber, va_list args)
} }
template<typename Tok> void 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; ErrorMetadata metadata;
metadata.filename = getFilename(); metadata.filename = getFilename();
@ -781,7 +756,9 @@ BinASTParser<Tok>::errorAtVA(uint32_t offset, unsigned errorNumber, va_list* arg
} }
template<typename Tok> bool 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) { if (!options().extraWarningsOption) {
return true; 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); 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 void
TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser) TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser)
{ {
@ -819,18 +786,40 @@ TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser)
template<typename Tok> template<typename Tok>
void void
BinASTParser<Tok>::doTrace(JSTracer* trc) BinASTParserPerTokenizer<Tok>::doTrace(JSTracer* trc)
{ {
if (tokenizer_) { if (tokenizer_) {
tokenizer_->traceMetadata(trc); 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. // Force class instantiation.
// This ensures that the symbols are built, without having to export all our // This ensures that the symbols are built, without having to export all our
// code (and its baggage of #include and macros) in the header. // code (and its baggage of #include and macros) in the header.
template class BinASTParser<BinTokenReaderMultipart>; template class BinASTParserPerTokenizer<BinTokenReaderMultipart>;
template class BinASTParser<BinTokenReaderTester>; template class BinASTParserPerTokenizer<BinTokenReaderTester>;
} // namespace frontend } // namespace frontend
} // namespace js } // namespace js

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

@ -4,8 +4,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef frontend_BinSource_h #ifndef frontend_BinASTParserPerTokenizer_h
#define frontend_BinSource_h #define frontend_BinASTParserPerTokenizer_h
/** /**
* A Binary AST parser. * A Binary AST parser.
@ -17,6 +17,8 @@
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "frontend/BCEParserHandle.h" #include "frontend/BCEParserHandle.h"
#include "frontend/BinASTEnum.h"
#include "frontend/BinASTParserBase.h"
#include "frontend/BinToken.h" #include "frontend/BinToken.h"
#include "frontend/BinTokenReaderMultipart.h" #include "frontend/BinTokenReaderMultipart.h"
#include "frontend/BinTokenReaderTester.h" #include "frontend/BinTokenReaderTester.h"
@ -33,64 +35,8 @@
namespace js { namespace js {
namespace frontend { namespace frontend {
class BinASTParserBase: private JS::AutoGCRooter template<typename Tok>
{ class BinASTParser;
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;
};
/** /**
* The parser for a Binary AST. * The parser for a Binary AST.
@ -99,7 +45,7 @@ class BinASTParserBase: private JS::AutoGCRooter
* recoverable. * recoverable.
*/ */
template<typename Tok> template<typename Tok>
class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEParserHandle class BinASTParserPerTokenizer : public BinASTParserBase, public ErrorReporter, public BCEParserHandle
{ {
public: public:
using Tokenizer = Tok; using Tokenizer = Tok;
@ -111,14 +57,21 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
using Chars = typename Tokenizer::Chars; using Chars = typename Tokenizer::Chars;
public: public:
BinASTParser(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames, const JS::ReadOnlyCompileOptions& options, // Auto-generated types.
HandleScriptSourceObject sourceObject, Handle<LazyScript*> lazyScript = nullptr) 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) : BinASTParserBase(cx, alloc, usedNames, sourceObject, lazyScript)
, options_(options) , options_(options)
, variableDeclarationKind_(VariableDeclarationKind::Var) , 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 * Parse a buffer, returning a node (which may be nullptr) in case of success
* or Nothing() in case of error. * or Nothing() in case of error.
* *
* The instance of `ParseNode` MAY NOT survive the `BinASTParser`. Indeed, * The instance of `ParseNode` MAY NOT survive the
* destruction of the `BinASTParser` will also destroy the `ParseNode`. * `BinASTParserPerTokenizer`. Indeed, destruction of the
* `BinASTParserPerTokenizer` will also destroy the `ParseNode`.
* *
* In case of error, the parser reports the JS error. * 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); JS::Result<ParseNode*> parseLazyFunction(ScriptSource* src, const size_t firstOffset);
private: protected:
MOZ_MUST_USE JS::Result<ParseNode*> parseAux(GlobalSharedContext* globalsc, MOZ_MUST_USE JS::Result<ParseNode*> parseAux(GlobalSharedContext* globalsc,
const uint8_t* start, const size_t length, const uint8_t* start, const size_t length,
BinASTSourceMetadata** metadataPtr = nullptr); BinASTSourceMetadata** metadataPtr = nullptr);
@ -176,9 +130,6 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
Var, Var,
}; };
// Auto-generated methods
#include "frontend/BinSource-auto.h"
// --- Auxiliary parsing functions // --- Auxiliary parsing functions
// Build a function object for a function-producing production. Called AFTER creating the scope. // 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. // directive.
void forceStrictIfNecessary(SharedContext* sc, ListNode* directives); void forceStrictIfNecessary(SharedContext* sc, ListNode* directives);
private: // Implement ErrorReporter protected: // Implement ErrorReporter
const JS::ReadOnlyCompileOptions& options_; const JS::ReadOnlyCompileOptions& options_;
const JS::ReadOnlyCompileOptions& options() const override { const JS::ReadOnlyCompileOptions& options() const override {
@ -319,7 +270,7 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
return this->options_.filename(); return this->options_.filename();
} }
private: // Implement ErrorReporter protected: // Implement ErrorReporter
mozilla::Maybe<Tokenizer> tokenizer_; mozilla::Maybe<Tokenizer> tokenizer_;
VariableDeclarationKind variableDeclarationKind_; VariableDeclarationKind variableDeclarationKind_;
@ -329,7 +280,7 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
// Helper class: Restore field `variableDeclarationKind` upon leaving a scope. // Helper class: Restore field `variableDeclarationKind` upon leaving a scope.
class MOZ_RAII AutoVariableDeclarationKind { class MOZ_RAII AutoVariableDeclarationKind {
public: public:
explicit AutoVariableDeclarationKind(BinASTParser<Tok>* parser explicit AutoVariableDeclarationKind(BinASTParserPerTokenizer<Tok>* parser
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: parser_(parser) : parser_(parser)
, kind(parser->variableDeclarationKind_) , kind(parser->variableDeclarationKind_)
@ -340,17 +291,27 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa
parser_->variableDeclarationKind_ = kind; parser_->variableDeclarationKind_ = kind;
} }
private: private:
BinASTParser<Tok>* parser_; BinASTParserPerTokenizer<Tok>* parser_;
BinASTParser<Tok>::VariableDeclarationKind kind; BinASTParserPerTokenizer<Tok>::VariableDeclarationKind kind;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 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 class BinParseContext : public ParseContext
{ {
public: public:
template<typename Tok> template<typename Tok>
BinParseContext(JSContext* cx, BinASTParser<Tok>* parser, SharedContext* sc, BinParseContext(JSContext* cx, BinASTParserPerTokenizer<Tok>* parser, SharedContext* sc,
Directives* newDirectives) Directives* newDirectives)
: ParseContext(cx, parser->parseContext_, sc, *parser, : ParseContext(cx, parser->parseContext_, sc, *parser,
parser->usedNames_, newDirectives, /* isFull = */ true) parser->usedNames_, newDirectives, /* isFull = */ true)
@ -358,10 +319,10 @@ class BinParseContext : public ParseContext
}; };
extern template class BinASTParser<BinTokenReaderMultipart>; extern template class BinASTParserPerTokenizer<BinTokenReaderMultipart>;
extern template class BinASTParser<BinTokenReaderTester>; extern template class BinASTParserPerTokenizer<BinTokenReaderTester>;
} // namespace frontend } // namespace frontend
} // namespace js } // 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: | append: |
result->appendWithoutOrderAssumption(item); result->appendWithoutOrderAssumption(item);
# Rules for generating BinSource-auto.cpp # Rules for generating BinASTParser.cpp
cpp: cpp:
header: | header: |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- 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 // To generate this file, see the documentation in
// js/src/frontend/binsource/README.md. // js/src/frontend/binsource/README.md.
#include "frontend/BinASTParser.h"
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/Casting.h" #include "mozilla/Casting.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
@ -35,7 +37,6 @@ cpp:
#include "mozilla/Vector.h" #include "mozilla/Vector.h"
#include "frontend/BinSource-macros.h" #include "frontend/BinSource-macros.h"
#include "frontend/BinSource.h"
#include "frontend/BinTokenReaderTester.h" #include "frontend/BinTokenReaderTester.h"
#include "frontend/FullParseHandler.h" #include "frontend/FullParseHandler.h"
#include "frontend/ParseNode.h" #include "frontend/ParseNode.h"
@ -70,7 +71,7 @@ cpp:
hpp: hpp:
# Rules for generating BinSource-class.h # Rules for generating BinASTParser.h
class: class:
header: | header: |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- 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 // To generate this file, see the documentation in
// js/src/frontend/binsource/README.md. // js/src/frontend/binsource/README.md.
// This file is meant to be included from the declaration #ifndef frontend_BinASTParser_h
// of class `BinASTParser`. The include may be public or private. #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 # Rules for generating BinToken.h
tokens: tokens:
@ -120,14 +263,14 @@ hpp:
* *
* (sorted by alphabetical order) * (sorted by alphabetical order)
*/ */
field: variants:
doc: | doc: |
/** /**
* The different variants of Binary AST string enums, as per * The different variants of Binary AST string enums, as per
* the specifications of Binary AST, as a single macro and * the specifications of Binary AST, as a single macro and
* `enum class`. * `enum class`.
* *
* Separate enum classes are also defined in BinSource-auto.h. * Separate enum classes are also defined in BinASTParser.h.
* *
* Usage: * Usage:
* *
@ -700,14 +843,14 @@ GetterContents:
fields: fields:
body: body:
before: | 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: SetterContents:
inherits: FunctionExpressionContents inherits: FunctionExpressionContents
fields: fields:
param: param:
after: | 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); factory_.addList(params, param);
MOZ_TRY(checkPositionalParameterIndices(positionalParams, params)); MOZ_TRY(checkPositionalParameterIndices(positionalParams, params));
@ -999,7 +1142,7 @@ ListOfParameter:
type-ok: type-ok:
ListNode* ListNode*
init: | 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: append:
factory_.addList(/* list = */ result, /* kid = */ item); factory_.addList(/* list = */ result, /* kid = */ item);
@ -1016,7 +1159,7 @@ ListOfStatement:
# type-ok: # type-ok:
# ListNode* # ListNode*
# init: # init:
# BINJS_TRY_DECL(result, new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos())); # BINJS_TRY_DECL(result, this->template new_<ListNode>(ParseNodeKind::ParamsBody, tokenizer_->pos()));
# append: # append:
# result->appendWithoutOrderAssumption(item); # result->appendWithoutOrderAssumption(item);

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

@ -275,17 +275,14 @@ const size_t BINKIND_LIMIT = 200;
/** /**
* The different variants of Binary AST string enums, as per * The different fields of Binary AST nodes, as per the specifications of
* the specifications of Binary AST, as a single macro and * Binary AST.
* `enum class`.
*
* Separate enum classes are also defined in BinSource-auto.h.
* *
* Usage: * Usage:
* *
* ```c++ * ```c++
* #define WITH_VARIANT(CPP_NAME, SPEC_NAME) ... * #define WITH_FIELD(CPP_NAME, SPEC_NAME) ...
* FOR_EACH_BIN_VARIANT(WITH_VARIANT) * FOR_EACH_BIN_FIELD(WITH_FIELD)
* ``` * ```
* *
* (sorted by alphabetical order) * (sorted by alphabetical order)
@ -371,7 +368,22 @@ enum class BinField {
const size_t BINFIELD_LIMIT = 69; 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) \ #define FOR_EACH_BIN_VARIANT(F) \
F(AssertedDeclaredKindConstLexical, "const lexical") \ F(AssertedDeclaredKindConstLexical, "const lexical") \
F(AssertedDeclaredKindNonConstLexical, "non-const lexical") \ F(AssertedDeclaredKindNonConstLexical, "non-const lexical") \

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

@ -13,7 +13,7 @@
#include "builtin/ModuleObject.h" #include "builtin/ModuleObject.h"
#if defined(JS_BUILD_BINAST) #if defined(JS_BUILD_BINAST)
# include "frontend/BinSource.h" # include "frontend/BinASTParser.h"
#endif // JS_BUILD_BINAST #endif // JS_BUILD_BINAST
#include "frontend/BytecodeCompilation.h" #include "frontend/BytecodeCompilation.h"
#include "frontend/BytecodeEmitter.h" #include "frontend/BytecodeEmitter.h"

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

@ -131,7 +131,8 @@ TraceParser(JSTracer* trc, JS::AutoGCRooter* parser);
#if defined(JS_BUILD_BINAST) #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 void
TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser); TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser);

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

@ -26,7 +26,7 @@ namespace frontend {
enum class SourceKind { enum class SourceKind {
// We are parsing from a text source (Parser.h) // We are parsing from a text source (Parser.h)
Text, Text,
// We are parsing from a binary source (BinSource.h) // We are parsing from a binary source (BinASTParser.h)
Binary, Binary,
}; };
@ -108,7 +108,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
#undef DECLARE_AS #undef DECLARE_AS
// The FullParseHandler may be used to create nodes for text sources // 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`, // 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()` // `a`, `b` and `+` may be stored in any order. We use `sourceKind()`
// to determine whether we need to check these assumptions. // to determine whether we need to check these assumptions.

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

@ -3,6 +3,7 @@
cargo run -- \ cargo run -- \
../BinSource.webidl_ \ ../BinSource.webidl_ \
../BinSource.yaml \ ../BinSource.yaml \
--out-class ../BinSource-auto.h \ --out-class ../BinASTParser.h \
--out-impl ../BinSource-auto.cpp \ --out-impl ../BinASTParser.cpp \
--out-enum ../BinASTEnum.h \
--out-token ../BinToken.h --out-token ../BinToken.h

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

@ -139,10 +139,22 @@ struct GlobalRules {
/// Header to add at the end of the .cpp file. /// Header to add at the end of the .cpp file.
cpp_footer: Option<String>, cpp_footer: Option<String>,
/// Header to add at the start of the .hpp file /// Header to add at the start of the .hpp file.
/// defining the class data/methods. /// defining the class.
hpp_class_header: Option<String>, 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. /// Header to add at the start of the .hpp file.
/// defining the tokens. /// defining the tokens.
hpp_tokens_header: Option<String>, hpp_tokens_header: Option<String>,
@ -176,6 +188,9 @@ impl GlobalRules {
let mut cpp_header = None; let mut cpp_header = None;
let mut cpp_footer = None; let mut cpp_footer = None;
let mut hpp_class_header = 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_header = None;
let mut hpp_tokens_footer = None; let mut hpp_tokens_footer = None;
let mut hpp_tokens_kind_doc = None; let mut hpp_tokens_kind_doc = None;
@ -211,6 +226,12 @@ impl GlobalRules {
"hpp" => { "hpp" => {
update_rule(&mut hpp_class_header, &node_entries["class"]["header"]) update_rule(&mut hpp_class_header, &node_entries["class"]["header"])
.unwrap_or_else(|_| panic!("Rule hpp.class.header must be a string")); .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"]) update_rule(&mut hpp_tokens_header, &node_entries["tokens"]["header"])
.unwrap_or_else(|_| panic!("Rule hpp.tokens.header must be a string")); .unwrap_or_else(|_| panic!("Rule hpp.tokens.header must be a string"));
update_rule(&mut hpp_tokens_footer, &node_entries["tokens"]["footer"]) update_rule(&mut hpp_tokens_footer, &node_entries["tokens"]["footer"])
@ -398,6 +419,9 @@ impl GlobalRules {
cpp_header, cpp_header,
cpp_footer, cpp_footer,
hpp_class_header, hpp_class_header,
hpp_class_footer,
hpp_enums_header,
hpp_enums_footer,
hpp_tokens_header, hpp_tokens_header,
hpp_tokens_footer, hpp_tokens_footer,
hpp_tokens_kind_doc, hpp_tokens_kind_doc,
@ -982,19 +1006,26 @@ enum class BinVariant {
} }
/// Declare string enums /// Declare string enums
fn export_declare_string_enums_classes(&self, buffer: &mut String) { fn export_declare_string_enums(&self, buffer: &mut String) {
buffer.push_str("\n\n// ----- Declaring string enums (by lexicographical order)\n"); buffer.push_str("
// ----- Declaring string enums (by lexicographical order)
");
let string_enums_by_name = self.syntax.string_enums_by_name() let string_enums_by_name = self.syntax.string_enums_by_name()
.iter() .iter()
.sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str())); .sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str()));
for (name, enum_) in string_enums_by_name { for (name, enum_) in string_enums_by_name {
let rendered_cases = enum_.strings() let rendered_cases = enum_.strings()
.iter() .iter()
.map(|str| format!("{case:<20} /* \"{original}\" */", .map(|str| format!(" // \"{original}\"
{case},",
case = str.to_cpp_enum_case(), case = str.to_cpp_enum_case(),
original = str)) original = str))
.format(",\n "); .format("\n");
let rendered = format!("enum class {name} {{\n {cases}\n}};\n\n", let rendered = format!("
enum class {name} {{
{cases}
}};
",
cases = rendered_cases, cases = rendered_cases,
name = name.to_class_cases()); name = name.to_class_cases());
buffer.push_str(&rendered); buffer.push_str(&rendered);
@ -1005,9 +1036,10 @@ enum class BinVariant {
let sums_of_interfaces = self.syntax.resolved_sums_of_interfaces_by_name() let sums_of_interfaces = self.syntax.resolved_sums_of_interfaces_by_name()
.iter() .iter()
.sorted_by(|a, b| a.0.cmp(&b.0)); .sorted_by(|a, b| a.0.cmp(&b.0));
buffer.push_str("\n\n// ----- Sums of interfaces (by lexicographical order)\n"); buffer.push_str("
buffer.push_str("// Implementations are autogenerated\n"); // ----- Sums of interfaces (by lexicographical order)
buffer.push_str("// `ParseNode*` may never be nullptr\n"); // `ParseNode*` may never be nullptr
");
for &(ref name, _) in &sums_of_interfaces { for &(ref name, _) in &sums_of_interfaces {
if !self.refgraph.is_used(name.to_rc_string().clone()) { if !self.refgraph.is_used(name.to_rc_string().clone()) {
continue; continue;
@ -1017,7 +1049,7 @@ enum class BinVariant {
let extra_params = rules_for_this_sum.extra_params; let extra_params = rules_for_this_sum.extra_params;
let rendered = self.get_method_signature(name, "", "", let rendered = self.get_method_signature(name, "", "",
&extra_params); &extra_params);
buffer.push_str(&rendered.reindent("") buffer.push_str(&rendered.reindent(" ")
.newline_if_not_empty()); .newline_if_not_empty());
} }
for (name, _) in sums_of_interfaces { for (name, _) in sums_of_interfaces {
@ -1031,15 +1063,16 @@ enum class BinVariant {
let rendered = self.get_method_signature(name, prefix, let rendered = self.get_method_signature(name, prefix,
INTERFACE_PARAMS, INTERFACE_PARAMS,
&extra_params); &extra_params);
buffer.push_str(&rendered.reindent("") buffer.push_str(&rendered.reindent(" ")
.newline_if_not_empty()); .newline_if_not_empty());
} }
} }
fn export_declare_single_interface_methods(&self, buffer: &mut String) { fn export_declare_single_interface_methods(&self, buffer: &mut String) {
buffer.push_str("\n\n// ----- Interfaces (by lexicographical order)\n"); buffer.push_str("
buffer.push_str("// Implementations are autogenerated\n"); // ----- Interfaces (by lexicographical order)
buffer.push_str("// `ParseNode*` may never be nullptr\n"); // `ParseNode*` may never be nullptr
");
let interfaces_by_name = self.syntax.interfaces_by_name() let interfaces_by_name = self.syntax.interfaces_by_name()
.iter() .iter()
.sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str())); .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()) { if self.refgraph.is_used(name.to_rc_string().clone()) {
let outer = self.get_method_signature(name, "", "", &extra_params); let outer = self.get_method_signature(name, "", "", &extra_params);
outer_parsers.push(outer.reindent("")); outer_parsers.push(outer.reindent(" "));
} }
let inner_prefix = "Interface"; let inner_prefix = "Interface";
@ -1063,7 +1096,7 @@ enum class BinVariant {
let inner = self.get_method_signature(name, inner_prefix, let inner = self.get_method_signature(name, inner_prefix,
INTERFACE_PARAMS, INTERFACE_PARAMS,
&extra_params); &extra_params);
inner_parsers.push(inner.reindent("")); inner_parsers.push(inner.reindent(" "));
} }
for parser in outer_parsers.drain(..) { for parser in outer_parsers.drain(..) {
@ -1078,8 +1111,9 @@ enum class BinVariant {
} }
fn export_declare_string_enums_methods(&self, buffer: &mut String) { fn export_declare_string_enums_methods(&self, buffer: &mut String) {
buffer.push_str("\n\n// ----- String enums (by lexicographical order)\n"); buffer.push_str("
buffer.push_str("// Implementations are autogenerated\n"); // ----- String enums (by lexicographical order)
");
let string_enums_by_name = self.syntax.string_enums_by_name() let string_enums_by_name = self.syntax.string_enums_by_name()
.iter() .iter()
.sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str())); .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); let rendered = self.get_method_signature(kind, "", "", &None);
buffer.push_str(&rendered.reindent("")); buffer.push_str(&rendered.reindent(" "));
buffer.push_str("\n"); buffer.push_str("\n");
} }
} }
fn export_declare_list_methods(&self, buffer: &mut String) { fn export_declare_list_methods(&self, buffer: &mut String) {
buffer.push_str("\n\n// ----- Lists (by lexicographical order)\n"); buffer.push_str("
buffer.push_str("// Implementations are autogenerated\n"); // ----- Lists (by lexicographical order)
");
for parser in &self.list_parsers_to_generate { for parser in &self.list_parsers_to_generate {
if !self.refgraph.is_used(parser.name.to_rc_string().clone()) { if !self.refgraph.is_used(parser.name.to_rc_string().clone()) {
continue; continue;
@ -1106,14 +1141,15 @@ enum class BinVariant {
let extra_params = rules_for_this_node.extra_params; let extra_params = rules_for_this_node.extra_params;
let rendered = self.get_method_signature(&parser.name, "", "", let rendered = self.get_method_signature(&parser.name, "", "",
&extra_params); &extra_params);
buffer.push_str(&rendered.reindent("")); buffer.push_str(&rendered.reindent(" "));
buffer.push_str("\n"); buffer.push_str("\n");
} }
} }
fn export_declare_option_methods(&self, buffer: &mut String) { fn export_declare_option_methods(&self, buffer: &mut String) {
buffer.push_str("\n\n// ----- Default values (by lexicographical order)\n"); buffer.push_str("
buffer.push_str("// Implementations are autogenerated\n"); // ----- Default values (by lexicographical order)
");
for parser in &self.option_parsers_to_generate { for parser in &self.option_parsers_to_generate {
if !self.refgraph.is_used(parser.name.to_rc_string().clone()) { if !self.refgraph.is_used(parser.name.to_rc_string().clone()) {
continue; continue;
@ -1123,7 +1159,7 @@ enum class BinVariant {
let extra_params = rules_for_this_node.extra_params; let extra_params = rules_for_this_node.extra_params;
let rendered = self.get_method_signature(&parser.name, "", "", let rendered = self.get_method_signature(&parser.name, "", "",
&extra_params); &extra_params);
buffer.push_str(&rendered.reindent("")); buffer.push_str(&rendered.reindent(" "));
buffer.push_str("\n"); buffer.push_str("\n");
} }
} }
@ -1154,13 +1190,30 @@ enum class BinVariant {
buffer.push_str(&self.rules.hpp_class_header.reindent("")); buffer.push_str(&self.rules.hpp_class_header.reindent(""));
buffer.push_str("\n"); buffer.push_str("\n");
self.export_declare_string_enums_classes(&mut buffer);
self.export_declare_sums_of_interface_methods(&mut buffer); self.export_declare_sums_of_interface_methods(&mut buffer);
self.export_declare_single_interface_methods(&mut buffer); self.export_declare_single_interface_methods(&mut buffer);
self.export_declare_string_enums_methods(&mut buffer); self.export_declare_string_enums_methods(&mut buffer);
self.export_declare_list_methods(&mut buffer); self.export_declare_list_methods(&mut buffer);
self.export_declare_option_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.push_str("\n");
buffer buffer
} }
@ -1994,7 +2047,12 @@ fn main() {
.long("out-class") .long("out-class")
.required(true) .required(true)
.takes_value(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") Arg::with_name("OUT_TOKEN_FILE")
.long("out-token") .long("out-token")
.required(true) .required(true)
@ -2101,6 +2159,8 @@ fn main() {
write_to("C++ class header code", "OUT_HEADER_CLASS_FILE", write_to("C++ class header code", "OUT_HEADER_CLASS_FILE",
&exporter.to_spidermonkey_class_hpp()); &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", write_to("C++ token header code", "OUT_TOKEN_FILE",
&exporter.to_spidermonkey_token_hpp()); &exporter.to_spidermonkey_token_hpp());
write_to("C++ token implementation code", "OUT_IMPL_FILE", write_to("C++ token implementation code", "OUT_IMPL_FILE",

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

@ -67,8 +67,9 @@ if CONFIG['JS_BUILD_BINAST']:
SOURCES += ['BinTokenReaderTester.cpp'] SOURCES += ['BinTokenReaderTester.cpp']
# These parts of BinAST should eventually move to release. # These parts of BinAST should eventually move to release.
SOURCES += [ SOURCES += [
'BinSource-auto.cpp', 'BinASTParser.cpp',
'BinSource.cpp', 'BinASTParserBase.cpp',
'BinASTParserPerTokenizer.cpp',
'BinSourceRuntimeSupport.cpp', 'BinSourceRuntimeSupport.cpp',
'BinToken.cpp', 'BinToken.cpp',
'BinTokenReaderBase.cpp', 'BinTokenReaderBase.cpp',
@ -79,8 +80,9 @@ if CONFIG['JS_BUILD_BINAST']:
if CONFIG['FUZZING_INTERFACES'] and CONFIG['LIBFUZZER']: if CONFIG['FUZZING_INTERFACES'] and CONFIG['LIBFUZZER']:
include('/tools/fuzzing/libfuzzer-flags.mozbuild') include('/tools/fuzzing/libfuzzer-flags.mozbuild')
SOURCES['BinSource-auto.cpp'].flags += libfuzzer_flags SOURCES['BinASTParser.cpp'].flags += libfuzzer_flags
SOURCES['BinSource.cpp'].flags += libfuzzer_flags SOURCES['BinASTParserBase.cpp'].flags += libfuzzer_flags
SOURCES['BinASTParserPerTokenizer.cpp'].flags += libfuzzer_flags
SOURCES['BinToken.cpp'].flags += libfuzzer_flags SOURCES['BinToken.cpp'].flags += libfuzzer_flags
SOURCES['BinTokenReaderBase.cpp'].flags += libfuzzer_flags SOURCES['BinTokenReaderBase.cpp'].flags += libfuzzer_flags
SOURCES['BinTokenReaderMultipart.cpp'].flags += libfuzzer_flags SOURCES['BinTokenReaderMultipart.cpp'].flags += libfuzzer_flags

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

@ -10,7 +10,7 @@
#include "jsapi.h" #include "jsapi.h"
#include "frontend/BinSource.h" #include "frontend/BinASTParser.h"
#include "frontend/FullParseHandler.h" #include "frontend/FullParseHandler.h"
#include "frontend/ParseContext.h" #include "frontend/ParseContext.h"
#include "frontend/Parser.h" #include "frontend/Parser.h"

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

@ -23,7 +23,7 @@
#include "jsapi.h" #include "jsapi.h"
#include "frontend/BinSource.h" #include "frontend/BinASTParser.h"
#include "frontend/FullParseHandler.h" #include "frontend/FullParseHandler.h"
#include "frontend/ParseContext.h" #include "frontend/ParseContext.h"
#include "frontend/Parser.h" #include "frontend/Parser.h"

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

@ -68,7 +68,7 @@
#include "builtin/RegExp.h" #include "builtin/RegExp.h"
#include "builtin/TestingFunctions.h" #include "builtin/TestingFunctions.h"
#if defined(JS_BUILD_BINAST) #if defined(JS_BUILD_BINAST)
# include "frontend/BinSource.h" # include "frontend/BinASTParser.h"
#endif // defined(JS_BUILD_BINAST) #endif // defined(JS_BUILD_BINAST)
#include "frontend/ModuleSharedContext.h" #include "frontend/ModuleSharedContext.h"
#include "frontend/Parser.h" #include "frontend/Parser.h"

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

@ -720,6 +720,20 @@ wasm::ExecuteCompileTaskFromHelperThread(CompileTask* task)
taskState.notify_one(/* failed or finished */); 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 bool
ModuleGenerator::finishTask(CompileTask* task) ModuleGenerator::finishTask(CompileTask* task)
{ {
@ -756,20 +770,14 @@ ModuleGenerator::launchBatchCompile()
return false; return false;
} }
if (parallel_) { if (!parallel_) {
return locallyCompileCurrentTask();
}
if (!StartOffThreadWasmCompile(currentTask_, mode())) { if (!StartOffThreadWasmCompile(currentTask_, mode())) {
return false; return false;
} }
outstanding_++; outstanding_++;
} else {
if (!ExecuteCompileTask(currentTask_, error_)) {
return false;
}
if (!finishTask(currentTask_)) {
return false;
}
}
currentTask_ = nullptr; currentTask_ = nullptr;
batchedBytecode_ = 0; batchedBytecode_ = 0;
return true; return true;
@ -843,7 +851,7 @@ ModuleGenerator::finishFuncDefs()
{ {
MOZ_ASSERT(!finishedFuncDefs_); MOZ_ASSERT(!finishedFuncDefs_);
if (currentTask_ && !launchBatchCompile()) { if (currentTask_ && !locallyCompileCurrentTask()) {
return false; return false;
} }

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

@ -196,6 +196,7 @@ class MOZ_STACK_CLASS ModuleGenerator
bool linkCallSites(); bool linkCallSites();
void noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRange); void noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRange);
bool linkCompiledCode(const CompiledCode& code); bool linkCompiledCode(const CompiledCode& code);
bool locallyCompileCurrentTask();
bool finishTask(CompileTask* task); bool finishTask(CompileTask* task);
bool launchBatchCompile(); bool launchBatchCompile();
bool finishOutstandingTask(); bool finishOutstandingTask();

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