Refactor await/yield production parameter tracking (#10956)
* test: add test fixtures * refactor: track AWAIT and YIELD in separate handler * fix flow errors * add flow type annotation to production-parameter * address review comments * refactor: track [Return] parameter
This commit is contained in:
parent
8ab27c8ffe
commit
38529699d6
@ -5,6 +5,7 @@ import type State from "../tokenizer/state";
|
|||||||
import type { PluginsMap } from "./index";
|
import type { PluginsMap } from "./index";
|
||||||
import type ScopeHandler from "../util/scope";
|
import type ScopeHandler from "../util/scope";
|
||||||
import type ClassScopeHandler from "../util/class-scope";
|
import type ClassScopeHandler from "../util/class-scope";
|
||||||
|
import type ProductionParameterHandler from "../util/production-parameter";
|
||||||
|
|
||||||
export default class BaseParser {
|
export default class BaseParser {
|
||||||
// Properties set by constructor in index.js
|
// Properties set by constructor in index.js
|
||||||
@ -12,6 +13,7 @@ export default class BaseParser {
|
|||||||
inModule: boolean;
|
inModule: boolean;
|
||||||
scope: ScopeHandler<*>;
|
scope: ScopeHandler<*>;
|
||||||
classScope: ClassScopeHandler;
|
classScope: ClassScopeHandler;
|
||||||
|
prodParam: ProductionParameterHandler;
|
||||||
plugins: PluginsMap;
|
plugins: PluginsMap;
|
||||||
filename: ?string;
|
filename: ?string;
|
||||||
sawUnambiguousESM: boolean = false;
|
sawUnambiguousESM: boolean = false;
|
||||||
|
|||||||
@ -33,15 +33,20 @@ import * as charCodes from "charcodes";
|
|||||||
import {
|
import {
|
||||||
BIND_OUTSIDE,
|
BIND_OUTSIDE,
|
||||||
BIND_VAR,
|
BIND_VAR,
|
||||||
functionFlags,
|
|
||||||
SCOPE_ARROW,
|
SCOPE_ARROW,
|
||||||
SCOPE_CLASS,
|
SCOPE_CLASS,
|
||||||
SCOPE_DIRECT_SUPER,
|
SCOPE_DIRECT_SUPER,
|
||||||
|
SCOPE_FUNCTION,
|
||||||
SCOPE_SUPER,
|
SCOPE_SUPER,
|
||||||
SCOPE_PROGRAM,
|
SCOPE_PROGRAM,
|
||||||
SCOPE_ASYNC,
|
|
||||||
} from "../util/scopeflags";
|
} from "../util/scopeflags";
|
||||||
import { ExpressionErrors } from "./util";
|
import { ExpressionErrors } from "./util";
|
||||||
|
import {
|
||||||
|
PARAM_AWAIT,
|
||||||
|
PARAM_RETURN,
|
||||||
|
PARAM,
|
||||||
|
functionFlags,
|
||||||
|
} from "../util/production-parameter";
|
||||||
|
|
||||||
export default class ExpressionParser extends LValParser {
|
export default class ExpressionParser extends LValParser {
|
||||||
// Forward-declaration: defined in statement.js
|
// Forward-declaration: defined in statement.js
|
||||||
@ -108,11 +113,12 @@ export default class ExpressionParser extends LValParser {
|
|||||||
|
|
||||||
// Convenience method to parse an Expression only
|
// Convenience method to parse an Expression only
|
||||||
getExpression(): N.Expression {
|
getExpression(): N.Expression {
|
||||||
let scopeFlags = SCOPE_PROGRAM;
|
let paramFlags = PARAM;
|
||||||
if (this.hasPlugin("topLevelAwait") && this.inModule) {
|
if (this.hasPlugin("topLevelAwait") && this.inModule) {
|
||||||
scopeFlags |= SCOPE_ASYNC;
|
paramFlags |= PARAM_AWAIT;
|
||||||
}
|
}
|
||||||
this.scope.enter(scopeFlags);
|
this.scope.enter(SCOPE_PROGRAM);
|
||||||
|
this.prodParam.enter(paramFlags);
|
||||||
this.nextToken();
|
this.nextToken();
|
||||||
const expr = this.parseExpression();
|
const expr = this.parseExpression();
|
||||||
if (!this.match(tt.eof)) {
|
if (!this.match(tt.eof)) {
|
||||||
@ -131,12 +137,18 @@ export default class ExpressionParser extends LValParser {
|
|||||||
// and, *if* the syntactic construct they handle is present, wrap
|
// and, *if* the syntactic construct they handle is present, wrap
|
||||||
// the AST node that the inner parser gave them in another node.
|
// the AST node that the inner parser gave them in another node.
|
||||||
|
|
||||||
// Parse a full expression. The optional arguments are used to
|
// Parse a full expression.
|
||||||
// forbid the `in` operator (in for loops initialization expressions)
|
// - `noIn`
|
||||||
// and provide reference for storing '=' operator inside shorthand
|
// is used to forbid the `in` operator (in for loops initialization expressions)
|
||||||
// property assignment in contexts where both object expression
|
// When `noIn` is true, the production parameter [In] is not present.
|
||||||
// and object pattern might appear (so it's possible to raise
|
// Whenever [?In] appears in the right-hand sides of a production, we pass
|
||||||
// delayed syntax error at correct position).
|
// `noIn` to the subroutine calls.
|
||||||
|
|
||||||
|
// - `refExpressionErrors `
|
||||||
|
// provides reference for storing '=' operator inside shorthand
|
||||||
|
// property assignment in contexts where both object expression
|
||||||
|
// and object pattern might appear (so it's possible to raise
|
||||||
|
// delayed syntax error at correct position).
|
||||||
|
|
||||||
parseExpression(
|
parseExpression(
|
||||||
noIn?: boolean,
|
noIn?: boolean,
|
||||||
@ -169,7 +181,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
const startPos = this.state.start;
|
const startPos = this.state.start;
|
||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
if (this.isContextual("yield")) {
|
if (this.isContextual("yield")) {
|
||||||
if (this.scope.inGenerator) {
|
if (this.prodParam.hasYield) {
|
||||||
let left = this.parseYield(noIn);
|
let left = this.parseYield(noIn);
|
||||||
if (afterLeftParse) {
|
if (afterLeftParse) {
|
||||||
left = afterLeftParse.call(this, left, startPos, startLoc);
|
left = afterLeftParse.call(this, left, startPos, startLoc);
|
||||||
@ -367,7 +379,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
if (
|
if (
|
||||||
this.match(tt.name) &&
|
this.match(tt.name) &&
|
||||||
this.state.value === "await" &&
|
this.state.value === "await" &&
|
||||||
this.scope.inAsync
|
this.prodParam.hasAwait
|
||||||
) {
|
) {
|
||||||
throw this.raise(
|
throw this.raise(
|
||||||
this.state.start,
|
this.state.start,
|
||||||
@ -1161,7 +1173,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
this.next();
|
this.next();
|
||||||
meta = this.createIdentifier(meta, "function");
|
meta = this.createIdentifier(meta, "function");
|
||||||
|
|
||||||
if (this.scope.inGenerator && this.eat(tt.dot)) {
|
if (this.prodParam.hasYield && this.eat(tt.dot)) {
|
||||||
return this.parseMetaProperty(node, meta, "sent");
|
return this.parseMetaProperty(node, meta, "sent");
|
||||||
}
|
}
|
||||||
return this.parseFunction(node);
|
return this.parseFunction(node);
|
||||||
@ -1833,13 +1845,15 @@ export default class ExpressionParser extends LValParser {
|
|||||||
node.generator = !!isGenerator;
|
node.generator = !!isGenerator;
|
||||||
const allowModifiers = isConstructor; // For TypeScript parameter properties
|
const allowModifiers = isConstructor; // For TypeScript parameter properties
|
||||||
this.scope.enter(
|
this.scope.enter(
|
||||||
functionFlags(isAsync, node.generator) |
|
SCOPE_FUNCTION |
|
||||||
SCOPE_SUPER |
|
SCOPE_SUPER |
|
||||||
(inClassScope ? SCOPE_CLASS : 0) |
|
(inClassScope ? SCOPE_CLASS : 0) |
|
||||||
(allowDirectSuper ? SCOPE_DIRECT_SUPER : 0),
|
(allowDirectSuper ? SCOPE_DIRECT_SUPER : 0),
|
||||||
);
|
);
|
||||||
|
this.prodParam.enter(functionFlags(isAsync, node.generator));
|
||||||
this.parseFunctionParams((node: any), allowModifiers);
|
this.parseFunctionParams((node: any), allowModifiers);
|
||||||
this.parseFunctionBodyAndFinish(node, type, true);
|
this.parseFunctionBodyAndFinish(node, type, true);
|
||||||
|
this.prodParam.exit();
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
|
|
||||||
this.state.yieldPos = oldYieldPos;
|
this.state.yieldPos = oldYieldPos;
|
||||||
@ -1857,7 +1871,8 @@ export default class ExpressionParser extends LValParser {
|
|||||||
isAsync: boolean,
|
isAsync: boolean,
|
||||||
trailingCommaPos: ?number,
|
trailingCommaPos: ?number,
|
||||||
): N.ArrowFunctionExpression {
|
): N.ArrowFunctionExpression {
|
||||||
this.scope.enter(functionFlags(isAsync, false) | SCOPE_ARROW);
|
this.scope.enter(SCOPE_FUNCTION | SCOPE_ARROW);
|
||||||
|
this.prodParam.enter(functionFlags(isAsync, false));
|
||||||
this.initFunction(node, isAsync);
|
this.initFunction(node, isAsync);
|
||||||
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
||||||
const oldYieldPos = this.state.yieldPos;
|
const oldYieldPos = this.state.yieldPos;
|
||||||
@ -1872,6 +1887,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
this.state.awaitPos = -1;
|
this.state.awaitPos = -1;
|
||||||
this.parseFunctionBody(node, true);
|
this.parseFunctionBody(node, true);
|
||||||
|
|
||||||
|
this.prodParam.exit();
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
|
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
|
||||||
this.state.yieldPos = oldYieldPos;
|
this.state.yieldPos = oldYieldPos;
|
||||||
@ -1949,7 +1965,11 @@ export default class ExpressionParser extends LValParser {
|
|||||||
allowExpression,
|
allowExpression,
|
||||||
!oldStrict && useStrict,
|
!oldStrict && useStrict,
|
||||||
);
|
);
|
||||||
|
// FunctionBody[Yield, Await]:
|
||||||
|
// StatementList[?Yield, ?Await, +Return] opt
|
||||||
|
this.prodParam.enter(this.prodParam.currentFlags() | PARAM_RETURN);
|
||||||
node.body = this.parseBlock(true, false);
|
node.body = this.parseBlock(true, false);
|
||||||
|
this.prodParam.exit();
|
||||||
this.state.labels = oldLabels;
|
this.state.labels = oldLabels;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2140,7 +2160,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
checkKeywords: boolean,
|
checkKeywords: boolean,
|
||||||
isBinding: boolean,
|
isBinding: boolean,
|
||||||
): void {
|
): void {
|
||||||
if (this.scope.inGenerator && word === "yield") {
|
if (this.prodParam.hasYield && word === "yield") {
|
||||||
this.raise(
|
this.raise(
|
||||||
startLoc,
|
startLoc,
|
||||||
"Can not use 'yield' as identifier inside a generator",
|
"Can not use 'yield' as identifier inside a generator",
|
||||||
@ -2149,7 +2169,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (word === "await") {
|
if (word === "await") {
|
||||||
if (this.scope.inAsync) {
|
if (this.prodParam.hasAwait) {
|
||||||
this.raise(
|
this.raise(
|
||||||
startLoc,
|
startLoc,
|
||||||
"Can not use 'await' as identifier inside an async function",
|
"Can not use 'await' as identifier inside an async function",
|
||||||
@ -2187,7 +2207,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
: isStrictReservedWord;
|
: isStrictReservedWord;
|
||||||
|
|
||||||
if (reservedTest(word, this.inModule)) {
|
if (reservedTest(word, this.inModule)) {
|
||||||
if (!this.scope.inAsync && word === "await") {
|
if (!this.prodParam.hasAwait && word === "await") {
|
||||||
this.raise(
|
this.raise(
|
||||||
startLoc,
|
startLoc,
|
||||||
"Can not use keyword 'await' outside an async function",
|
"Can not use keyword 'await' outside an async function",
|
||||||
@ -2199,10 +2219,10 @@ export default class ExpressionParser extends LValParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAwaitAllowed(): boolean {
|
isAwaitAllowed(): boolean {
|
||||||
if (this.scope.inFunction) return this.scope.inAsync;
|
if (this.scope.inFunction) return this.prodParam.hasAwait;
|
||||||
if (this.options.allowAwaitOutsideFunction) return true;
|
if (this.options.allowAwaitOutsideFunction) return true;
|
||||||
if (this.hasPlugin("topLevelAwait")) {
|
if (this.hasPlugin("topLevelAwait")) {
|
||||||
return this.inModule && this.scope.inAsync;
|
return this.inModule && this.prodParam.hasAwait;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,13 @@ import type { File /*::, JSXOpeningElement */ } from "../types";
|
|||||||
import type { PluginList } from "../plugin-utils";
|
import type { PluginList } from "../plugin-utils";
|
||||||
import { getOptions } from "../options";
|
import { getOptions } from "../options";
|
||||||
import StatementParser from "./statement";
|
import StatementParser from "./statement";
|
||||||
import { SCOPE_ASYNC, SCOPE_PROGRAM } from "../util/scopeflags";
|
import { SCOPE_PROGRAM } from "../util/scopeflags";
|
||||||
import ScopeHandler from "../util/scope";
|
import ScopeHandler from "../util/scope";
|
||||||
import ClassScopeHandler from "../util/class-scope";
|
import ClassScopeHandler from "../util/class-scope";
|
||||||
|
import ProductionParameterHandler, {
|
||||||
|
PARAM_AWAIT,
|
||||||
|
PARAM,
|
||||||
|
} from "../util/production-parameter";
|
||||||
|
|
||||||
export type PluginsMap = Map<string, { [string]: any }>;
|
export type PluginsMap = Map<string, { [string]: any }>;
|
||||||
|
|
||||||
@ -28,6 +32,7 @@ export default class Parser extends StatementParser {
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
this.inModule = this.options.sourceType === "module";
|
this.inModule = this.options.sourceType === "module";
|
||||||
this.scope = new ScopeHandler(this.raise.bind(this), this.inModule);
|
this.scope = new ScopeHandler(this.raise.bind(this), this.inModule);
|
||||||
|
this.prodParam = new ProductionParameterHandler();
|
||||||
this.classScope = new ClassScopeHandler(this.raise.bind(this));
|
this.classScope = new ClassScopeHandler(this.raise.bind(this));
|
||||||
this.plugins = pluginsMap(this.options.plugins);
|
this.plugins = pluginsMap(this.options.plugins);
|
||||||
this.filename = options.sourceFilename;
|
this.filename = options.sourceFilename;
|
||||||
@ -39,11 +44,12 @@ export default class Parser extends StatementParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parse(): File {
|
parse(): File {
|
||||||
let scopeFlags = SCOPE_PROGRAM;
|
let paramFlags = PARAM;
|
||||||
if (this.hasPlugin("topLevelAwait") && this.inModule) {
|
if (this.hasPlugin("topLevelAwait") && this.inModule) {
|
||||||
scopeFlags |= SCOPE_ASYNC;
|
paramFlags |= PARAM_AWAIT;
|
||||||
}
|
}
|
||||||
this.scope.enter(scopeFlags);
|
this.scope.enter(SCOPE_PROGRAM);
|
||||||
|
this.prodParam.enter(paramFlags);
|
||||||
const file = this.startNode();
|
const file = this.startNode();
|
||||||
const program = this.startNode();
|
const program = this.startNode();
|
||||||
this.nextToken();
|
this.nextToken();
|
||||||
|
|||||||
@ -15,8 +15,8 @@ import {
|
|||||||
BIND_LEXICAL,
|
BIND_LEXICAL,
|
||||||
BIND_VAR,
|
BIND_VAR,
|
||||||
BIND_FUNCTION,
|
BIND_FUNCTION,
|
||||||
functionFlags,
|
|
||||||
SCOPE_CLASS,
|
SCOPE_CLASS,
|
||||||
|
SCOPE_FUNCTION,
|
||||||
SCOPE_OTHER,
|
SCOPE_OTHER,
|
||||||
SCOPE_SIMPLE_CATCH,
|
SCOPE_SIMPLE_CATCH,
|
||||||
SCOPE_SUPER,
|
SCOPE_SUPER,
|
||||||
@ -28,6 +28,7 @@ import {
|
|||||||
type BindingTypes,
|
type BindingTypes,
|
||||||
} from "../util/scopeflags";
|
} from "../util/scopeflags";
|
||||||
import { ExpressionErrors } from "./util";
|
import { ExpressionErrors } from "./util";
|
||||||
|
import { PARAM, functionFlags } from "../util/production-parameter";
|
||||||
|
|
||||||
const loopLabel = { kind: "loop" },
|
const loopLabel = { kind: "loop" },
|
||||||
switchLabel = { kind: "switch" };
|
switchLabel = { kind: "switch" };
|
||||||
@ -574,7 +575,7 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parseReturnStatement(node: N.ReturnStatement): N.ReturnStatement {
|
parseReturnStatement(node: N.ReturnStatement): N.ReturnStatement {
|
||||||
if (!this.scope.inFunction && !this.options.allowReturnOutsideFunction) {
|
if (!this.prodParam.hasReturn && !this.options.allowReturnOutsideFunction) {
|
||||||
this.raise(this.state.start, "'return' outside of function");
|
this.raise(this.state.start, "'return' outside of function");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1059,7 +1060,8 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
this.state.maybeInArrowParameters = false;
|
this.state.maybeInArrowParameters = false;
|
||||||
this.state.yieldPos = -1;
|
this.state.yieldPos = -1;
|
||||||
this.state.awaitPos = -1;
|
this.state.awaitPos = -1;
|
||||||
this.scope.enter(functionFlags(node.async, node.generator));
|
this.scope.enter(SCOPE_FUNCTION);
|
||||||
|
this.prodParam.enter(functionFlags(isAsync, node.generator));
|
||||||
|
|
||||||
if (!isStatement) {
|
if (!isStatement) {
|
||||||
node.id = this.parseFunctionId();
|
node.id = this.parseFunctionId();
|
||||||
@ -1078,6 +1080,7 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.prodParam.exit();
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
|
|
||||||
if (isStatement && !isHangingStatement) {
|
if (isStatement && !isHangingStatement) {
|
||||||
@ -1599,9 +1602,12 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
node: N.ClassPrivateProperty,
|
node: N.ClassPrivateProperty,
|
||||||
): N.ClassPrivateProperty {
|
): N.ClassPrivateProperty {
|
||||||
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
||||||
|
// [In] production parameter is tracked in parseMaybeAssign
|
||||||
|
this.prodParam.enter(PARAM);
|
||||||
|
|
||||||
node.value = this.eat(tt.eq) ? this.parseMaybeAssign() : null;
|
node.value = this.eat(tt.eq) ? this.parseMaybeAssign() : null;
|
||||||
this.semicolon();
|
this.semicolon();
|
||||||
|
this.prodParam.exit();
|
||||||
|
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
|
|
||||||
@ -1614,6 +1620,8 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
||||||
|
// [In] production parameter is tracked in parseMaybeAssign
|
||||||
|
this.prodParam.enter(PARAM);
|
||||||
|
|
||||||
if (this.match(tt.eq)) {
|
if (this.match(tt.eq)) {
|
||||||
this.expectPlugin("classProperties");
|
this.expectPlugin("classProperties");
|
||||||
@ -1624,6 +1632,7 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
}
|
}
|
||||||
this.semicolon();
|
this.semicolon();
|
||||||
|
|
||||||
|
this.prodParam.exit();
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
|
|
||||||
return this.finishNode(node, "ClassProperty");
|
return this.finishNode(node, "ClassProperty");
|
||||||
|
|||||||
@ -12,13 +12,13 @@ import { types as tc } from "../tokenizer/context";
|
|||||||
import * as charCodes from "charcodes";
|
import * as charCodes from "charcodes";
|
||||||
import { isIteratorStart } from "../util/identifier";
|
import { isIteratorStart } from "../util/identifier";
|
||||||
import {
|
import {
|
||||||
functionFlags,
|
|
||||||
type BindingTypes,
|
type BindingTypes,
|
||||||
BIND_NONE,
|
BIND_NONE,
|
||||||
BIND_LEXICAL,
|
BIND_LEXICAL,
|
||||||
BIND_VAR,
|
BIND_VAR,
|
||||||
BIND_FUNCTION,
|
BIND_FUNCTION,
|
||||||
SCOPE_ARROW,
|
SCOPE_ARROW,
|
||||||
|
SCOPE_FUNCTION,
|
||||||
SCOPE_OTHER,
|
SCOPE_OTHER,
|
||||||
} from "../util/scopeflags";
|
} from "../util/scopeflags";
|
||||||
import type { ExpressionErrors } from "../parser/util";
|
import type { ExpressionErrors } from "../parser/util";
|
||||||
@ -1889,7 +1889,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
node.extra?.trailingComma,
|
node.extra?.trailingComma,
|
||||||
);
|
);
|
||||||
// Enter scope, as checkParams defines bindings
|
// Enter scope, as checkParams defines bindings
|
||||||
this.scope.enter(functionFlags(false, false) | SCOPE_ARROW);
|
this.scope.enter(SCOPE_FUNCTION | SCOPE_ARROW);
|
||||||
// Use super's method to force the parameters to be checked
|
// Use super's method to force the parameters to be checked
|
||||||
super.checkParams(node, false, true);
|
super.checkParams(node, false, true);
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import {
|
|||||||
import TypeScriptScopeHandler from "./scope";
|
import TypeScriptScopeHandler from "./scope";
|
||||||
import * as charCodes from "charcodes";
|
import * as charCodes from "charcodes";
|
||||||
import type { ExpressionErrors } from "../../parser/util";
|
import type { ExpressionErrors } from "../../parser/util";
|
||||||
|
import { PARAM } from "../../util/production-parameter";
|
||||||
|
|
||||||
type TsModifier =
|
type TsModifier =
|
||||||
| "readonly"
|
| "readonly"
|
||||||
@ -1265,7 +1266,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
node.body = inner;
|
node.body = inner;
|
||||||
} else {
|
} else {
|
||||||
this.scope.enter(SCOPE_TS_MODULE);
|
this.scope.enter(SCOPE_TS_MODULE);
|
||||||
|
this.prodParam.enter(PARAM);
|
||||||
node.body = this.tsParseModuleBlock();
|
node.body = this.tsParseModuleBlock();
|
||||||
|
this.prodParam.exit();
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
}
|
}
|
||||||
return this.finishNode(node, "TSModuleDeclaration");
|
return this.finishNode(node, "TSModuleDeclaration");
|
||||||
@ -1284,7 +1287,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
}
|
}
|
||||||
if (this.match(tt.braceL)) {
|
if (this.match(tt.braceL)) {
|
||||||
this.scope.enter(SCOPE_TS_MODULE);
|
this.scope.enter(SCOPE_TS_MODULE);
|
||||||
|
this.prodParam.enter(PARAM);
|
||||||
node.body = this.tsParseModuleBlock();
|
node.body = this.tsParseModuleBlock();
|
||||||
|
this.prodParam.exit();
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
} else {
|
} else {
|
||||||
this.semicolon();
|
this.semicolon();
|
||||||
@ -1439,11 +1444,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
// Would like to use tsParseAmbientExternalModuleDeclaration here, but already ran past "global".
|
// Would like to use tsParseAmbientExternalModuleDeclaration here, but already ran past "global".
|
||||||
if (this.match(tt.braceL)) {
|
if (this.match(tt.braceL)) {
|
||||||
this.scope.enter(SCOPE_TS_MODULE);
|
this.scope.enter(SCOPE_TS_MODULE);
|
||||||
|
this.prodParam.enter(PARAM);
|
||||||
const mod: N.TsModuleDeclaration = node;
|
const mod: N.TsModuleDeclaration = node;
|
||||||
mod.global = true;
|
mod.global = true;
|
||||||
mod.id = expr;
|
mod.id = expr;
|
||||||
mod.body = this.tsParseModuleBlock();
|
mod.body = this.tsParseModuleBlock();
|
||||||
this.scope.exit();
|
this.scope.exit();
|
||||||
|
this.prodParam.exit();
|
||||||
return this.finishNode(mod, "TSModuleDeclaration");
|
return this.finishNode(mod, "TSModuleDeclaration");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -60,7 +60,7 @@ tt.name.updateContext = function(prevType) {
|
|||||||
if (prevType !== tt.dot) {
|
if (prevType !== tt.dot) {
|
||||||
if (
|
if (
|
||||||
(this.state.value === "of" && !this.state.exprAllowed) ||
|
(this.state.value === "of" && !this.state.exprAllowed) ||
|
||||||
(this.state.value === "yield" && this.scope.inGenerator)
|
(this.state.value === "yield" && this.prodParam.hasYield)
|
||||||
) {
|
) {
|
||||||
allowed = true;
|
allowed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
63
packages/babel-parser/src/util/production-parameter.js
Normal file
63
packages/babel-parser/src/util/production-parameter.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// @flow
|
||||||
|
export const PARAM = 0b000, // Initial Parameter flags
|
||||||
|
PARAM_YIELD = 0b001, // track [Yield] production parameter
|
||||||
|
PARAM_AWAIT = 0b010, // track [Await] production parameter
|
||||||
|
PARAM_RETURN = 0b100; // track [Return] production parameter
|
||||||
|
|
||||||
|
// ProductionParameterHandler is a stack fashioned production parameter tracker
|
||||||
|
// https://tc39.es/ecma262/#sec-grammar-notation
|
||||||
|
// The tracked parameters are defined above. Note that the [In] parameter is
|
||||||
|
// tracked in `noIn` argument of `parseExpression`.
|
||||||
|
//
|
||||||
|
// Whenever [+Await]/[+Yield] appears in the right-hand sides of a production,
|
||||||
|
// we must enter a new tracking stack. For example when parsing
|
||||||
|
//
|
||||||
|
// AsyncFunctionDeclaration [Yield, Await]:
|
||||||
|
// async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await]
|
||||||
|
// ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody }
|
||||||
|
//
|
||||||
|
// we must follow such process:
|
||||||
|
//
|
||||||
|
// 1. parse async keyword
|
||||||
|
// 2. parse function keyword
|
||||||
|
// 3. parse bindingIdentifier <= inherit current parameters: [?Await]
|
||||||
|
// 4. enter new stack with (PARAM_AWAIT)
|
||||||
|
// 5. parse formal parameters <= must have [Await] parameter [+Await]
|
||||||
|
// 6. parse function body
|
||||||
|
// 7. exit current stack
|
||||||
|
|
||||||
|
export type ParamKind = typeof PARAM | typeof PARAM_AWAIT | typeof PARAM_YIELD;
|
||||||
|
|
||||||
|
export default class ProductionParameterHandler {
|
||||||
|
stacks: Array<ParamKind> = [];
|
||||||
|
enter(flags: ParamKind) {
|
||||||
|
this.stacks.push(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit() {
|
||||||
|
this.stacks.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFlags(): ParamKind {
|
||||||
|
return this.stacks[this.stacks.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasAwait(): boolean {
|
||||||
|
return (this.currentFlags() & PARAM_AWAIT) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasYield(): boolean {
|
||||||
|
return (this.currentFlags() & PARAM_YIELD) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasReturn(): boolean {
|
||||||
|
return (this.currentFlags() & PARAM_RETURN) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function functionFlags(
|
||||||
|
isAsync: boolean,
|
||||||
|
isGenerator: boolean,
|
||||||
|
): ParamKind {
|
||||||
|
return (isAsync ? PARAM_AWAIT : 0) | (isGenerator ? PARAM_YIELD : 0);
|
||||||
|
}
|
||||||
@ -1,10 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
SCOPE_ARROW,
|
SCOPE_ARROW,
|
||||||
SCOPE_ASYNC,
|
|
||||||
SCOPE_DIRECT_SUPER,
|
SCOPE_DIRECT_SUPER,
|
||||||
SCOPE_FUNCTION,
|
SCOPE_FUNCTION,
|
||||||
SCOPE_GENERATOR,
|
|
||||||
SCOPE_SIMPLE_CATCH,
|
SCOPE_SIMPLE_CATCH,
|
||||||
SCOPE_SUPER,
|
SCOPE_SUPER,
|
||||||
SCOPE_PROGRAM,
|
SCOPE_PROGRAM,
|
||||||
@ -53,25 +51,6 @@ export default class ScopeHandler<IScope: Scope = Scope> {
|
|||||||
get inFunction() {
|
get inFunction() {
|
||||||
return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0;
|
return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0;
|
||||||
}
|
}
|
||||||
get inGenerator() {
|
|
||||||
return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0;
|
|
||||||
}
|
|
||||||
// the following loop always exit because SCOPE_PROGRAM is SCOPE_VAR
|
|
||||||
// $FlowIgnore
|
|
||||||
get inAsync() {
|
|
||||||
for (let i = this.scopeStack.length - 1; ; i--) {
|
|
||||||
const scope = this.scopeStack[i];
|
|
||||||
const isVarScope = scope.flags & SCOPE_VAR;
|
|
||||||
const isClassScope = scope.flags & SCOPE_CLASS;
|
|
||||||
if (isClassScope && !isVarScope) {
|
|
||||||
// If it meets a class scope before a var scope, it means it is a class property initializer
|
|
||||||
// which does not have an [Await] parameter in its grammar
|
|
||||||
return false;
|
|
||||||
} else if (isVarScope) {
|
|
||||||
return (scope.flags & SCOPE_ASYNC) > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
get allowSuper() {
|
get allowSuper() {
|
||||||
return (this.currentThisScope().flags & SCOPE_SUPER) > 0;
|
return (this.currentThisScope().flags & SCOPE_SUPER) > 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,17 +2,15 @@
|
|||||||
|
|
||||||
// Each scope gets a bitset that may contain these flags
|
// Each scope gets a bitset that may contain these flags
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
export const SCOPE_OTHER = 0b0000000000,
|
export const SCOPE_OTHER = 0b00000000,
|
||||||
SCOPE_PROGRAM = 0b0000000001,
|
SCOPE_PROGRAM = 0b00000001,
|
||||||
SCOPE_FUNCTION = 0b0000000010,
|
SCOPE_FUNCTION = 0b00000010,
|
||||||
SCOPE_ASYNC = 0b0000000100,
|
SCOPE_ARROW = 0b00000100,
|
||||||
SCOPE_GENERATOR = 0b0000001000,
|
SCOPE_SIMPLE_CATCH = 0b00001000,
|
||||||
SCOPE_ARROW = 0b0000010000,
|
SCOPE_SUPER = 0b00010000,
|
||||||
SCOPE_SIMPLE_CATCH = 0b0000100000,
|
SCOPE_DIRECT_SUPER = 0b00100000,
|
||||||
SCOPE_SUPER = 0b0001000000,
|
SCOPE_CLASS = 0b01000000,
|
||||||
SCOPE_DIRECT_SUPER = 0b0010000000,
|
SCOPE_TS_MODULE = 0b10000000,
|
||||||
SCOPE_CLASS = 0b0100000000,
|
|
||||||
SCOPE_TS_MODULE = 0b1000000000,
|
|
||||||
SCOPE_VAR = SCOPE_PROGRAM | SCOPE_FUNCTION | SCOPE_TS_MODULE;
|
SCOPE_VAR = SCOPE_PROGRAM | SCOPE_FUNCTION | SCOPE_TS_MODULE;
|
||||||
|
|
||||||
export type ScopeFlags =
|
export type ScopeFlags =
|
||||||
@ -20,22 +18,12 @@ export type ScopeFlags =
|
|||||||
| typeof SCOPE_PROGRAM
|
| typeof SCOPE_PROGRAM
|
||||||
| typeof SCOPE_FUNCTION
|
| typeof SCOPE_FUNCTION
|
||||||
| typeof SCOPE_VAR
|
| typeof SCOPE_VAR
|
||||||
| typeof SCOPE_ASYNC
|
|
||||||
| typeof SCOPE_GENERATOR
|
|
||||||
| typeof SCOPE_ARROW
|
| typeof SCOPE_ARROW
|
||||||
| typeof SCOPE_SIMPLE_CATCH
|
| typeof SCOPE_SIMPLE_CATCH
|
||||||
| typeof SCOPE_SUPER
|
| typeof SCOPE_SUPER
|
||||||
| typeof SCOPE_DIRECT_SUPER
|
| typeof SCOPE_DIRECT_SUPER
|
||||||
| typeof SCOPE_CLASS;
|
| typeof SCOPE_CLASS;
|
||||||
|
|
||||||
export function functionFlags(isAsync: boolean, isGenerator: boolean) {
|
|
||||||
return (
|
|
||||||
SCOPE_FUNCTION |
|
|
||||||
(isAsync ? SCOPE_ASYNC : 0) |
|
|
||||||
(isGenerator ? SCOPE_GENERATOR : 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// These flags are meant to be _only_ used inside the Scope class (or subclasses).
|
// These flags are meant to be _only_ used inside the Scope class (or subclasses).
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
export const BIND_KIND_VALUE = 0b00000_0000_01,
|
export const BIND_KIND_VALUE = 0b00000_0000_01,
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
function* foo() {
|
||||||
|
class C {
|
||||||
|
// here yield is an identifier reference
|
||||||
|
p = yield + 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["classProperties"]
|
||||||
|
}
|
||||||
@ -0,0 +1,264 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start": 0,
|
||||||
|
"end": 100,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 6,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errors": [
|
||||||
|
"SyntaxError: Unexpected reserved word 'yield' (4:8)"
|
||||||
|
],
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 0,
|
||||||
|
"end": 100,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 6,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceType": "script",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "FunctionDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 100,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 6,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 10,
|
||||||
|
"end": 13,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 10
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"identifierName": "foo"
|
||||||
|
},
|
||||||
|
"name": "foo"
|
||||||
|
},
|
||||||
|
"generator": true,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start": 16,
|
||||||
|
"end": 100,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 16
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 6,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start": 20,
|
||||||
|
"end": 98,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 2
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 5,
|
||||||
|
"column": 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 26,
|
||||||
|
"end": 27,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 9
|
||||||
|
},
|
||||||
|
"identifierName": "C"
|
||||||
|
},
|
||||||
|
"name": "C"
|
||||||
|
},
|
||||||
|
"superClass": null,
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start": 28,
|
||||||
|
"end": 98,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 10
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 5,
|
||||||
|
"column": 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start": 79,
|
||||||
|
"end": 94,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 4
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 19
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 79,
|
||||||
|
"end": 80,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 4
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 5
|
||||||
|
},
|
||||||
|
"identifierName": "p"
|
||||||
|
},
|
||||||
|
"name": "p"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"value": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 83,
|
||||||
|
"end": 93,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 18
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 83,
|
||||||
|
"end": 88,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"identifierName": "yield"
|
||||||
|
},
|
||||||
|
"name": "yield"
|
||||||
|
},
|
||||||
|
"operator": "+",
|
||||||
|
"right": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start": 91,
|
||||||
|
"end": 93,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 16
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 18
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 42,
|
||||||
|
"raw": "42"
|
||||||
|
},
|
||||||
|
"value": 42
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"leadingComments": [
|
||||||
|
{
|
||||||
|
"type": "CommentLine",
|
||||||
|
"value": " here yield is an identifier reference",
|
||||||
|
"start": 34,
|
||||||
|
"end": 74,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 4
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 44
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
},
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"type": "CommentLine",
|
||||||
|
"value": " here yield is an identifier reference",
|
||||||
|
"start": 34,
|
||||||
|
"end": 74,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 4
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 44
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class C {
|
||||||
|
p = function* () { yield + 42 };
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["classProperties"]
|
||||||
|
}
|
||||||
@ -0,0 +1,224 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start": 0,
|
||||||
|
"end": 46,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 0,
|
||||||
|
"end": 46,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceType": "script",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 46,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 6
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 7
|
||||||
|
},
|
||||||
|
"identifierName": "C"
|
||||||
|
},
|
||||||
|
"name": "C"
|
||||||
|
},
|
||||||
|
"superClass": null,
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start": 8,
|
||||||
|
"end": 46,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start": 12,
|
||||||
|
"end": 44,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 2
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 34
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 12,
|
||||||
|
"end": 13,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 2
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 3
|
||||||
|
},
|
||||||
|
"identifierName": "p"
|
||||||
|
},
|
||||||
|
"name": "p"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"value": {
|
||||||
|
"type": "FunctionExpression",
|
||||||
|
"start": 16,
|
||||||
|
"end": 43,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 6
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 33
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": null,
|
||||||
|
"generator": true,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start": 29,
|
||||||
|
"end": 43,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 19
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 33
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start": 31,
|
||||||
|
"end": 41,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 21
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 31
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"expression": {
|
||||||
|
"type": "YieldExpression",
|
||||||
|
"start": 31,
|
||||||
|
"end": 41,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 21
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 31
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delegate": false,
|
||||||
|
"argument": {
|
||||||
|
"type": "UnaryExpression",
|
||||||
|
"start": 37,
|
||||||
|
"end": 41,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 27
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 31
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"operator": "+",
|
||||||
|
"prefix": true,
|
||||||
|
"argument": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start": 39,
|
||||||
|
"end": 41,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 29
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 31
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 42,
|
||||||
|
"raw": "42"
|
||||||
|
},
|
||||||
|
"value": 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user