зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland a=merge on a CLOSED TREE
This commit is contained in:
Коммит
47323ec73b
|
@ -76,17 +76,17 @@
|
||||||
|
|
||||||
<body>
|
<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);
|
||||||
|
});
|
|
@ -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>
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 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(), ¶ms, &tmpBody));
|
MOZ_TRY((asFinalParser()->*parseFunc)(func->nargs(), ¶ms, &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;
|
||||||
|
@ -1037,9 +1069,10 @@ enum class BinVariant {
|
||||||
}
|
}
|
||||||
|
|
||||||
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()));
|
||||||
|
@ -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()));
|
||||||
|
@ -1095,8 +1129,9 @@ enum class BinVariant {
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1112,8 +1147,9 @@ enum class BinVariant {
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -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();
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче