@babel/parser error recovery (#10363)

* Add error recovery support to @babel/parser

* Update @babel/parser tests to always recover from errors

* Update this.raise usage in @babel/parser:

- expression.js
- lval.js
- statement.js
- estree.js
- flow.js
- jsx/index.js
- tokenizer/index.js

* Update @babel/parser fixtures with recovered errors

* Fix tests out of @babel/parser

* Do not use try/catch for control flow

* Update invalid fixtures

* Do not report invalid lhs in toAssignable

* Do not validate function id multiple times

* Dedupe reserved await errors

* Remove duplicate errors about strict reserved bindings

* Remove duplicated error about yield/await inside params

* Don't error twice for methods in object patterns

* Don't report invalid super() twice

* Remove dup error about reserved param for expr arrows

* Remove double escapes in migrated tests

* Dedupe errors about invalid escapes in identifiers

* Remove duplicated error about decorated constructor

* Remove duplicated error about spread in flow class

* Don't throw for invalid super usage

* Don't fail for object decorators with stage 2

* Fix flow inexact type errors

* Fix flow

* Fix errors about escapes in keywords (ref: #10455)

* Update after rebase

* Fix todo

* Remove duplicated error when using += for defaults

* Remove unnecessary throw

* Nit: use ??
This commit is contained in:
Nicolò Ribaudo 2019-11-05 10:15:00 +01:00 committed by GitHub
parent d25262ec4b
commit 87feda7c2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2224 changed files with 155996 additions and 3353 deletions

View File

@ -2,6 +2,7 @@
"type": "File", "type": "File",
"start": 0, "start": 0,
"end": 91, "end": 91,
"errors": [],
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,

View File

@ -21,6 +21,7 @@ export type Options = {
ranges: boolean, ranges: boolean,
tokens: boolean, tokens: boolean,
createParenthesizedExpressions: boolean, createParenthesizedExpressions: boolean,
errorRecovery: boolean,
}; };
export const defaultOptions: Options = { export const defaultOptions: Options = {
@ -62,6 +63,9 @@ export const defaultOptions: Options = {
// Whether to create ParenthesizedExpression AST nodes (if false // Whether to create ParenthesizedExpression AST nodes (if false
// the parser sets extra.parenthesized on the expression nodes instead). // the parser sets extra.parenthesized on the expression nodes instead).
createParenthesizedExpressions: false, createParenthesizedExpressions: false,
// When enabled, errors are attached to the AST instead of being directly thrown.
// Some errors will still throw, because @babel/parser can't always recover.
errorRecovery: false,
}; };
// Interpret and default an options object // Interpret and default an options object

View File

@ -108,6 +108,7 @@ export default class ExpressionParser extends LValParser {
this.unexpected(); this.unexpected();
} }
expr.comments = this.state.comments; expr.comments = this.state.comments;
expr.errors = this.state.errors;
return expr; return expr;
} }
@ -786,11 +787,11 @@ export default class ExpressionParser extends LValParser {
if (node.callee.type === "Import") { if (node.callee.type === "Import") {
if (node.arguments.length !== 1) { if (node.arguments.length !== 1) {
this.raise(node.start, "import() requires exactly one argument"); this.raise(node.start, "import() requires exactly one argument");
} } else {
const importArg = node.arguments[0];
const importArg = node.arguments[0]; if (importArg && importArg.type === "SpreadElement") {
if (importArg && importArg.type === "SpreadElement") { this.raise(importArg.start, "... is not allowed in import()");
this.raise(importArg.start, "... is not allowed in import()"); }
} }
} }
return this.finishNode( return this.finishNode(
@ -903,13 +904,6 @@ export default class ExpressionParser extends LValParser {
switch (this.state.type) { switch (this.state.type) {
case tt._super: case tt._super:
if (!this.scope.allowSuper && !this.options.allowSuperOutsideMethod) {
this.raise(
this.state.start,
"super is only allowed in object methods and classes",
);
}
node = this.startNode(); node = this.startNode();
this.next(); this.next();
if ( if (
@ -922,6 +916,14 @@ export default class ExpressionParser extends LValParser {
"super() is only valid inside a class constructor of a subclass. " + "super() is only valid inside a class constructor of a subclass. " +
"Maybe a typo in the method name ('constructor') or not extending another class?", "Maybe a typo in the method name ('constructor') or not extending another class?",
); );
} else if (
!this.scope.allowSuper &&
!this.options.allowSuperOutsideMethod
) {
this.raise(
node.start,
"super is only allowed in object methods and classes",
);
} }
if ( if (
@ -929,7 +931,11 @@ export default class ExpressionParser extends LValParser {
!this.match(tt.bracketL) && !this.match(tt.bracketL) &&
!this.match(tt.dot) !this.match(tt.dot)
) { ) {
this.unexpected(); this.raise(
node.start,
"super can only be used with function calls (i.e. super()) or " +
"in property accesses (i.e. super.prop or super[prop])",
);
} }
return this.finishNode(node, "Super"); return this.finishNode(node, "Super");
@ -1106,15 +1112,16 @@ export default class ExpressionParser extends LValParser {
} }
this.next(); this.next();
if (this.primaryTopicReferenceIsAllowedInCurrentTopicContext()) {
this.registerTopicReference(); if (!this.primaryTopicReferenceIsAllowedInCurrentTopicContext()) {
return this.finishNode(node, "PipelinePrimaryTopicReference"); this.raise(
} else {
throw this.raise(
node.start, node.start,
`Topic reference was used in a lexical context without topic binding`, `Topic reference was used in a lexical context without topic binding`,
); );
} }
this.registerTopicReference();
return this.finishNode(node, "PipelinePrimaryTopicReference");
} }
} }
@ -1199,6 +1206,15 @@ export default class ExpressionParser extends LValParser {
if (this.isContextual("meta")) { if (this.isContextual("meta")) {
this.expectPlugin("importMeta"); this.expectPlugin("importMeta");
if (!this.inModule) {
this.raise(
id.start,
`import.meta may appear only with 'sourceType: "module"'`,
{ code: "BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED" },
);
}
this.sawUnambiguousESM = true;
} else if (!this.hasPlugin("importMeta")) { } else if (!this.hasPlugin("importMeta")) {
this.raise( this.raise(
id.start, id.start,
@ -1206,15 +1222,6 @@ export default class ExpressionParser extends LValParser {
); );
} }
if (!this.inModule) {
this.raise(
id.start,
`import.meta may appear only with 'sourceType: "module"'`,
{ code: "BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED" },
);
}
this.sawUnambiguousESM = true;
return this.parseMetaProperty(node, id, "meta"); return this.parseMetaProperty(node, id, "meta");
} }
@ -1386,7 +1393,10 @@ export default class ExpressionParser extends LValParser {
parseNew(): N.NewExpression | N.MetaProperty { parseNew(): N.NewExpression | N.MetaProperty {
const node = this.startNode(); const node = this.startNode();
const meta = this.parseIdentifier(true);
let meta = this.startNode();
this.next();
meta = this.createIdentifier(meta, "new");
if (this.eat(tt.dot)) { if (this.eat(tt.dot)) {
const metaProp = this.parseMetaProperty(node, meta, "target"); const metaProp = this.parseMetaProperty(node, meta, "target");
@ -1553,12 +1563,12 @@ export default class ExpressionParser extends LValParser {
this.state.start, this.state.start,
"Stage 2 decorators disallow object literal property decorators", "Stage 2 decorators disallow object literal property decorators",
); );
} else { }
// we needn't check if decorators (stage 0) plugin is enabled since it's checked by
// the call to this.parseDecorator // we needn't check if decorators (stage 0) plugin is enabled since it's checked by
while (this.match(tt.at)) { // the call to this.parseDecorator
decorators.push(this.parseDecorator()); while (this.match(tt.at)) {
} decorators.push(this.parseDecorator());
} }
} }
@ -1933,7 +1943,7 @@ export default class ExpressionParser extends LValParser {
if (isExpression) { if (isExpression) {
node.body = this.parseMaybeAssign(); node.body = this.parseMaybeAssign();
this.checkParams(node, false, allowExpression); this.checkParams(node, false, allowExpression, false);
} else { } else {
const nonSimple = !this.isSimpleParamList(node.params); const nonSimple = !this.isSimpleParamList(node.params);
if (!oldStrict || nonSimple) { if (!oldStrict || nonSimple) {
@ -1967,6 +1977,7 @@ export default class ExpressionParser extends LValParser {
node, node,
!oldStrict && !useStrict && !allowExpression && !isMethod && !nonSimple, !oldStrict && !useStrict && !allowExpression && !isMethod && !nonSimple,
allowExpression, allowExpression,
!oldStrict && useStrict,
); );
node.body = this.parseBlock(true, false); node.body = this.parseBlock(true, false);
this.state.labels = oldLabels; this.state.labels = oldLabels;
@ -1975,7 +1986,14 @@ export default class ExpressionParser extends LValParser {
this.state.inParameters = oldInParameters; this.state.inParameters = oldInParameters;
// Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
if (this.state.strict && node.id) { if (this.state.strict && node.id) {
this.checkLVal(node.id, BIND_OUTSIDE, undefined, "function name"); this.checkLVal(
node.id,
BIND_OUTSIDE,
undefined,
"function name",
undefined,
!oldStrict && useStrict,
);
} }
this.state.strict = oldStrict; this.state.strict = oldStrict;
} }
@ -1994,6 +2012,7 @@ export default class ExpressionParser extends LValParser {
allowDuplicates: boolean, allowDuplicates: boolean,
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
isArrowFunction: ?boolean, isArrowFunction: ?boolean,
strictModeChanged?: boolean = true,
): void { ): void {
// $FlowIssue // $FlowIssue
const nameHash: {} = Object.create(null); const nameHash: {} = Object.create(null);
@ -2003,6 +2022,8 @@ export default class ExpressionParser extends LValParser {
BIND_VAR, BIND_VAR,
allowDuplicates ? null : nameHash, allowDuplicates ? null : nameHash,
"function parameter list", "function parameter list",
undefined,
strictModeChanged,
); );
} }
} }
@ -2084,6 +2105,8 @@ export default class ExpressionParser extends LValParser {
// Parse the next token as an identifier. If `liberal` is true (used // Parse the next token as an identifier. If `liberal` is true (used
// when parsing properties), it will also convert keywords into // when parsing properties), it will also convert keywords into
// identifiers. // identifiers.
// This shouldn't be used to parse the keywords of meta properties, since they
// are not identifiers and cannot contain escape sequences.
parseIdentifier(liberal?: boolean): N.Identifier { parseIdentifier(liberal?: boolean): N.Identifier {
const node = this.startNode(); const node = this.startNode();
@ -2104,11 +2127,6 @@ export default class ExpressionParser extends LValParser {
if (this.match(tt.name)) { if (this.match(tt.name)) {
name = this.state.value; name = this.state.value;
// An escaped identifier whose value is the same as a keyword
if (!liberal && this.state.containsEsc && isKeyword(name)) {
this.raise(this.state.pos, `Escape sequence in keyword ${name}`);
}
} else if (this.state.type.keyword) { } else if (this.state.type.keyword) {
name = this.state.type.keyword; name = this.state.type.keyword;
@ -2128,7 +2146,11 @@ export default class ExpressionParser extends LValParser {
throw this.unexpected(); throw this.unexpected();
} }
if (!liberal) { if (liberal) {
// If the current token is not used as a keyword, set its type to "tt.name".
// This will prevent this.next() from throwing about unexpected escapes.
this.state.type = tt.name;
} else {
this.checkReservedWord( this.checkReservedWord(
name, name,
this.state.start, this.state.start,
@ -2153,6 +2175,7 @@ export default class ExpressionParser extends LValParser {
startLoc, startLoc,
"Can not use 'yield' as identifier inside a generator", "Can not use 'yield' as identifier inside a generator",
); );
return;
} }
if (word === "await") { if (word === "await") {
@ -2161,7 +2184,9 @@ export default class ExpressionParser extends LValParser {
startLoc, startLoc,
"Can not use 'await' as identifier inside an async function", "Can not use 'await' as identifier inside an async function",
); );
} else if ( return;
}
if (
this.state.awaitPos === -1 && this.state.awaitPos === -1 &&
(this.state.maybeInArrowParameters || this.isAwaitAllowed()) (this.state.maybeInArrowParameters || this.isAwaitAllowed())
) { ) {
@ -2174,9 +2199,11 @@ export default class ExpressionParser extends LValParser {
startLoc, startLoc,
"'arguments' is not allowed in class field initializer", "'arguments' is not allowed in class field initializer",
); );
return;
} }
if (checkKeywords && isKeyword(word)) { if (checkKeywords && isKeyword(word)) {
this.raise(startLoc, `Unexpected keyword '${word}'`); this.raise(startLoc, `Unexpected keyword '${word}'`);
return;
} }
const reservedTest = !this.state.strict const reservedTest = !this.state.strict
@ -2191,8 +2218,9 @@ export default class ExpressionParser extends LValParser {
startLoc, startLoc,
"Can not use keyword 'await' outside an async function", "Can not use keyword 'await' outside an async function",
); );
} else {
this.raise(startLoc, `Unexpected reserved word '${word}'`);
} }
this.raise(startLoc, `Unexpected reserved word '${word}'`);
} }
} }
@ -2206,9 +2234,6 @@ export default class ExpressionParser extends LValParser {
// Parses await expression inside async function. // Parses await expression inside async function.
parseAwait(): N.AwaitExpression { parseAwait(): N.AwaitExpression {
if (this.state.awaitPos === -1) {
this.state.awaitPos = this.state.start;
}
const node = this.startNode(); const node = this.startNode();
this.next(); this.next();
@ -2218,8 +2243,10 @@ export default class ExpressionParser extends LValParser {
node.start, node.start,
"await is not allowed in async function parameters", "await is not allowed in async function parameters",
); );
} else if (this.state.awaitPos === -1) {
this.state.awaitPos = node.start;
} }
if (this.match(tt.star)) { if (this.eat(tt.star)) {
this.raise( this.raise(
node.start, node.start,
"await* has been removed from the async functions proposal. Use Promise.all() instead.", "await* has been removed from the async functions proposal. Use Promise.all() instead.",
@ -2259,13 +2286,12 @@ export default class ExpressionParser extends LValParser {
// Parses yield expression inside generator. // Parses yield expression inside generator.
parseYield(noIn?: ?boolean): N.YieldExpression { parseYield(noIn?: ?boolean): N.YieldExpression {
if (this.state.yieldPos === -1) {
this.state.yieldPos = this.state.start;
}
const node = this.startNode(); const node = this.startNode();
if (this.state.inParameters) { if (this.state.inParameters) {
this.raise(node.start, "yield is not allowed in generator parameters"); this.raise(node.start, "yield is not allowed in generator parameters");
} else if (this.state.yieldPos === -1) {
this.state.yieldPos = node.start;
} }
this.next(); this.next();
@ -2291,7 +2317,7 @@ export default class ExpressionParser extends LValParser {
if (left.type === "SequenceExpression") { if (left.type === "SequenceExpression") {
// Ensure that the pipeline head is not a comma-delimited // Ensure that the pipeline head is not a comma-delimited
// sequence expression. // sequence expression.
throw this.raise( this.raise(
leftStartPos, leftStartPos,
`Pipeline head should not be a comma-separated sequence expression`, `Pipeline head should not be a comma-separated sequence expression`,
); );
@ -2336,7 +2362,7 @@ export default class ExpressionParser extends LValParser {
pipelineStyle === "PipelineTopicExpression" && pipelineStyle === "PipelineTopicExpression" &&
childExpression.type === "SequenceExpression" childExpression.type === "SequenceExpression"
) { ) {
throw this.raise( this.raise(
startPos, startPos,
`Pipeline body may not be a comma-separated sequence expression`, `Pipeline body may not be a comma-separated sequence expression`,
); );
@ -2362,7 +2388,7 @@ export default class ExpressionParser extends LValParser {
break; break;
case "PipelineTopicExpression": case "PipelineTopicExpression":
if (!this.topicReferenceWasUsedInCurrentTopicContext()) { if (!this.topicReferenceWasUsedInCurrentTopicContext()) {
throw this.raise( this.raise(
startPos, startPos,
`Pipeline is in topic style but does not use topic reference`, `Pipeline is in topic style but does not use topic reference`,
); );
@ -2370,7 +2396,9 @@ export default class ExpressionParser extends LValParser {
bodyNode.expression = childExpression; bodyNode.expression = childExpression;
break; break;
default: default:
throw this.raise(startPos, `Unknown pipeline style ${pipelineStyle}`); throw new Error(
`Internal @babel/parser error: Unknown pipeline style (${pipelineStyle})`,
);
} }
return this.finishNode(bodyNode, pipelineStyle); return this.finishNode(bodyNode, pipelineStyle);
} }

View File

@ -39,7 +39,10 @@ export default class Parser extends StatementParser {
const file = this.startNode(); const file = this.startNode();
const program = this.startNode(); const program = this.startNode();
this.nextToken(); this.nextToken();
return this.parseTopLevel(file, program); file.errors = null;
this.parseTopLevel(file, program);
file.errors = this.state.errors;
return file;
} }
} }

View File

@ -10,6 +10,8 @@ import CommentsParser from "./comments";
// message. // message.
export default class LocationParser extends CommentsParser { export default class LocationParser extends CommentsParser {
+isLookahead: boolean;
getLocationForPosition(pos: number): Position { getLocationForPosition(pos: number): Position {
let loc; let loc;
if (pos === this.state.start) loc = this.state.startLoc; if (pos === this.state.start) loc = this.state.startLoc;
@ -31,7 +33,7 @@ export default class LocationParser extends CommentsParser {
missingPluginNames?: Array<string>, missingPluginNames?: Array<string>,
code?: string, code?: string,
} = {}, } = {},
): empty { ): Error | empty {
const loc = this.getLocationForPosition(pos); const loc = this.getLocationForPosition(pos);
message += ` (${loc.line}:${loc.column})`; message += ` (${loc.line}:${loc.column})`;
@ -47,6 +49,12 @@ export default class LocationParser extends CommentsParser {
if (code !== undefined) { if (code !== undefined) {
err.code = code; err.code = code;
} }
throw err;
if (this.options.errorRecovery) {
if (!this.isLookahead) this.state.errors.push(err);
return err;
} else {
throw err;
}
} }
} }

View File

@ -15,7 +15,10 @@ import type {
SpreadElement, SpreadElement,
} from "../types"; } from "../types";
import type { Pos, Position } from "../util/location"; import type { Pos, Position } from "../util/location";
import { isStrictBindReservedWord } from "../util/identifier"; import {
isStrictBindOnlyReservedWord,
isStrictBindReservedWord,
} from "../util/identifier";
import { NodeUtils } from "./node"; import { NodeUtils } from "./node";
import { type BindingTypes, BIND_NONE } from "../util/scopeflags"; import { type BindingTypes, BIND_NONE } from "../util/scopeflags";
@ -37,6 +40,8 @@ export default class LValParser extends NodeUtils {
// Convert existing expression atom to assignable pattern // Convert existing expression atom to assignable pattern
// if possible. // if possible.
// NOTE: There is a corresponding "isAssignable" method in flow.js.
// When this one is updated, please check if also that one needs to be updated.
toAssignable( toAssignable(
node: Node, node: Node,
@ -96,15 +101,16 @@ export default class LValParser extends NodeUtils {
break; break;
case "AssignmentExpression": case "AssignmentExpression":
if (node.operator === "=") { if (node.operator !== "=") {
node.type = "AssignmentPattern";
delete node.operator;
} else {
this.raise( this.raise(
node.left.end, node.left.end,
"Only '=' operator can be used for specifying default value.", "Only '=' operator can be used for specifying default value.",
); );
} }
node.type = "AssignmentPattern";
delete node.operator;
this.toAssignable(node.left, isBinding, contextDescription);
break; break;
case "ParenthesizedExpression": case "ParenthesizedExpression":
@ -118,14 +124,9 @@ export default class LValParser extends NodeUtils {
case "MemberExpression": case "MemberExpression":
if (!isBinding) break; if (!isBinding) break;
default: { default:
const message = // We don't know how to deal with this node. It will
"Invalid left-hand side" + // be reported by a later call to checkLVal
(contextDescription
? " in " + contextDescription
: /* istanbul ignore next */ "expression");
this.raise(node.start, message);
}
} }
} }
return node; return node;
@ -349,12 +350,18 @@ export default class LValParser extends NodeUtils {
checkClashes: ?{ [key: string]: boolean }, checkClashes: ?{ [key: string]: boolean },
contextDescription: string, contextDescription: string,
disallowLetBinding?: boolean, disallowLetBinding?: boolean,
strictModeChanged?: boolean = false,
): void { ): void {
switch (expr.type) { switch (expr.type) {
case "Identifier": case "Identifier":
if ( if (
this.state.strict && this.state.strict &&
isStrictBindReservedWord(expr.name, this.inModule) // "Global" reserved words have already been checked by parseIdentifier,
// unless they have been found in the id or parameters of a strict-mode
// function in a sloppy context.
(strictModeChanged
? isStrictBindReservedWord(expr.name, this.inModule)
: isStrictBindOnlyReservedWord(expr.name))
) { ) {
this.raise( this.raise(
expr.start, expr.start,
@ -404,6 +411,11 @@ export default class LValParser extends NodeUtils {
case "ObjectPattern": case "ObjectPattern":
for (let prop of expr.properties) { for (let prop of expr.properties) {
if (prop.type === "ObjectProperty") prop = prop.value; if (prop.type === "ObjectProperty") prop = prop.value;
// If we find here an ObjectMethod, it's because this was originally
// an ObjectExpression which has then been converted.
// toAssignable already reported this error with a nicer message.
else if (prop.type === "ObjectMethod") continue;
this.checkLVal( this.checkLVal(
prop, prop,
bindingType, bindingType,
@ -489,7 +501,7 @@ export default class LValParser extends NodeUtils {
} }
raiseRestNotLast(pos: number) { raiseRestNotLast(pos: number) {
this.raise(pos, `Rest element must be last element`); throw this.raise(pos, `Rest element must be last element`);
} }
raiseTrailingCommaAfterRest(pos: number) { raiseTrailingCommaAfterRest(pos: number) {

View File

@ -203,7 +203,7 @@ export default class StatementParser extends ExpressionParser {
case tt._var: case tt._var:
kind = kind || this.state.value; kind = kind || this.state.value;
if (context && kind !== "var") { if (context && kind !== "var") {
this.unexpected( this.raise(
this.state.start, this.state.start,
"Lexical declaration cannot appear in a single-statement context", "Lexical declaration cannot appear in a single-statement context",
); );
@ -269,8 +269,8 @@ export default class StatementParser extends ExpressionParser {
default: { default: {
if (this.isAsyncFunction()) { if (this.isAsyncFunction()) {
if (context) { if (context) {
this.unexpected( this.raise(
null, this.state.start,
"Async functions can only be declared at the top level or inside a block", "Async functions can only be declared at the top level or inside a block",
); );
} }
@ -351,7 +351,7 @@ export default class StatementParser extends ExpressionParser {
); );
} }
} else if (!this.canHaveLeadingDecorator()) { } else if (!this.canHaveLeadingDecorator()) {
this.raise( throw this.raise(
this.state.start, this.state.start,
"Leading decorators must be attached to a class declaration", "Leading decorators must be attached to a class declaration",
); );
@ -1036,7 +1036,7 @@ export default class StatementParser extends ExpressionParser {
this.initFunction(node, isAsync); this.initFunction(node, isAsync);
if (this.match(tt.star) && isHangingStatement) { if (this.match(tt.star) && isHangingStatement) {
this.unexpected( this.raise(
this.state.start, this.state.start,
"Generators can only be declared at the top level or inside a block", "Generators can only be declared at the top level or inside a block",
); );
@ -1077,10 +1077,10 @@ export default class StatementParser extends ExpressionParser {
this.scope.exit(); this.scope.exit();
if (isStatement && !isHangingStatement) { if (isStatement && !isHangingStatement) {
// We need to validate this _after_ parsing the function body // We need to register this _after_ parsing the function body
// because of TypeScript body-less function declarations, // because of TypeScript body-less function declarations,
// which shouldn't be added to the scope. // which shouldn't be added to the scope.
this.checkFunctionStatementId(node); this.registerFunctionStatementId(node);
} }
this.state.maybeInArrowParameters = oldMaybeInArrowParameters; this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
@ -1111,22 +1111,21 @@ export default class StatementParser extends ExpressionParser {
this.checkYieldAwaitInDefaultParams(); this.checkYieldAwaitInDefaultParams();
} }
checkFunctionStatementId(node: N.Function): void { registerFunctionStatementId(node: N.Function): void {
if (!node.id) return; if (!node.id) return;
// If it is a regular function declaration in sloppy mode, then it is // If it is a regular function declaration in sloppy mode, then it is
// subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
// mode depends on properties of the current scope (see // mode depends on properties of the current scope (see
// treatFunctionsAsVar). // treatFunctionsAsVar).
this.checkLVal( this.scope.declareName(
node.id, node.id.name,
this.state.strict || node.generator || node.async this.state.strict || node.generator || node.async
? this.scope.treatFunctionsAsVar ? this.scope.treatFunctionsAsVar
? BIND_VAR ? BIND_VAR
: BIND_LEXICAL : BIND_LEXICAL
: BIND_FUNCTION, : BIND_FUNCTION,
null, node.id.start,
"function name",
); );
} }
@ -1191,7 +1190,7 @@ export default class StatementParser extends ExpressionParser {
while (!this.eat(tt.braceR)) { while (!this.eat(tt.braceR)) {
if (this.eat(tt.semi)) { if (this.eat(tt.semi)) {
if (decorators.length > 0) { if (decorators.length > 0) {
this.raise( throw this.raise(
this.state.lastTokEnd, this.state.lastTokEnd,
"Decorators must not be followed by a semicolon", "Decorators must not be followed by a semicolon",
); );
@ -1229,7 +1228,7 @@ export default class StatementParser extends ExpressionParser {
}); });
if (decorators.length) { if (decorators.length) {
this.raise( throw this.raise(
this.state.start, this.state.start,
"You have trailing decorators with no method", "You have trailing decorators with no method",
); );
@ -1362,13 +1361,6 @@ export default class StatementParser extends ExpressionParser {
if (isConstructor) { if (isConstructor) {
publicMethod.kind = "constructor"; publicMethod.kind = "constructor";
if (publicMethod.decorators) {
this.raise(
publicMethod.start,
"You can't attach decorators to a class constructor",
);
}
// TypeScript allows multiple overloaded constructor declarations. // TypeScript allows multiple overloaded constructor declarations.
if (state.hadConstructor && !this.hasPlugin("typescript")) { if (state.hadConstructor && !this.hasPlugin("typescript")) {
this.raise(key.start, "Duplicate constructor in the same class"); this.raise(key.start, "Duplicate constructor in the same class");
@ -1797,7 +1789,7 @@ export default class StatementParser extends ExpressionParser {
this.hasPlugin("decorators") && this.hasPlugin("decorators") &&
this.getPluginOption("decorators", "decoratorsBeforeExport") this.getPluginOption("decorators", "decoratorsBeforeExport")
) { ) {
this.unexpected( this.raise(
this.state.start, this.state.start,
"Decorators must be placed *before* the 'export' keyword." + "Decorators must be placed *before* the 'export' keyword." +
" You can set the 'decoratorsBeforeExport' option to false to use" + " You can set the 'decoratorsBeforeExport' option to false to use" +
@ -1807,7 +1799,7 @@ export default class StatementParser extends ExpressionParser {
this.parseDecorators(false); this.parseDecorators(false);
return this.parseClass(expr, true, true); return this.parseClass(expr, true, true);
} else if (this.match(tt._const) || this.match(tt._var) || this.isLet()) { } else if (this.match(tt._const) || this.match(tt._var) || this.isLet()) {
return this.raise( throw this.raise(
this.state.start, this.state.start,
"Only expressions, functions or classes are allowed as the `default` export.", "Only expressions, functions or classes are allowed as the `default` export.",
); );
@ -1977,7 +1969,7 @@ export default class StatementParser extends ExpressionParser {
name: string, name: string,
): void { ): void {
if (this.state.exportedIdentifiers.indexOf(name) > -1) { if (this.state.exportedIdentifiers.indexOf(name) > -1) {
throw this.raise( this.raise(
node.start, node.start,
name === "default" name === "default"
? "Only one default export allowed per module." ? "Only one default export allowed per module."
@ -2098,8 +2090,8 @@ export default class StatementParser extends ExpressionParser {
} else { } else {
// Detect an attempt to deep destructure // Detect an attempt to deep destructure
if (this.eat(tt.colon)) { if (this.eat(tt.colon)) {
this.unexpected( throw this.raise(
null, this.state.start,
"ES2015 named imports do not destructure. " + "ES2015 named imports do not destructure. " +
"Use another statement for destructuring after the import.", "Use another statement for destructuring after the import.",
); );

View File

@ -2,6 +2,7 @@
import { types as tt, type TokenType } from "../tokenizer/types"; import { types as tt, type TokenType } from "../tokenizer/types";
import Tokenizer from "../tokenizer"; import Tokenizer from "../tokenizer";
import State from "../tokenizer/state";
import type { Node } from "../types"; import type { Node } from "../types";
import { lineBreak, skipWhiteSpace } from "../util/whitespace"; import { lineBreak, skipWhiteSpace } from "../util/whitespace";
import { isIdentifierChar } from "../util/identifier"; import { isIdentifierChar } from "../util/identifier";
@ -9,6 +10,14 @@ import * as charCodes from "charcodes";
const literal = /^('|")((?:\\?.)*?)\1/; const literal = /^('|")((?:\\?.)*?)\1/;
type TryParse<Node, Error, Thrown, Aborted, FailState> = {
node: Node,
error: Error,
thrown: Thrown,
aborted: Aborted,
failState: FailState,
};
// ## Parser utilities // ## Parser utilities
export default class UtilParser extends Tokenizer { export default class UtilParser extends Tokenizer {
@ -215,4 +224,58 @@ export default class UtilParser extends Tokenizer {
return false; return false;
} }
// tryParse will clone parser state.
// It is expensive and should be used with cautions
tryParse<T: Node | $ReadOnlyArray<Node>>(
fn: (abort: (node?: T) => empty) => T,
oldState: State = this.state.clone(),
):
| TryParse<T, null, false, false, null>
| TryParse<T | null, SyntaxError, boolean, false, State>
| TryParse<T | null, null, false, true, State> {
const abortSignal: { node: T | null } = { node: null };
try {
const node = fn((node = null) => {
abortSignal.node = node;
throw abortSignal;
});
if (this.state.errors.length > oldState.errors.length) {
const failState = this.state;
this.state = oldState;
return {
node,
error: (failState.errors[oldState.errors.length]: SyntaxError),
thrown: false,
aborted: false,
failState,
};
}
return {
node,
error: null,
thrown: false,
aborted: false,
failState: null,
};
} catch (error) {
const failState = this.state;
this.state = oldState;
if (error instanceof SyntaxError) {
return { node: null, error, thrown: true, aborted: false, failState };
}
if (error === abortSignal) {
return {
node: abortSignal.node,
error: null,
thrown: false,
aborted: true,
failState,
};
}
throw error;
}
}
} }

View File

@ -93,9 +93,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} else { } else {
this.raise(start, "setter must have exactly one formal parameter"); this.raise(start, "setter must have exactly one formal parameter");
} }
} } else if (
prop.kind === "set" &&
if (prop.kind === "set" && prop.value.params[0].type === "RestElement") { prop.value.params[0].type === "RestElement"
) {
this.raise( this.raise(
start, start,
"setter function argument must not be a rest parameter", "setter function argument must not be a rest parameter",
@ -382,12 +383,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isLast: boolean, isLast: boolean,
) { ) {
if (prop.kind === "get" || prop.kind === "set") { if (prop.kind === "get" || prop.kind === "set") {
this.raise( throw this.raise(
prop.key.start, prop.key.start,
"Object pattern can't contain getter or setter", "Object pattern can't contain getter or setter",
); );
} else if (prop.method) { } else if (prop.method) {
this.raise(prop.key.start, "Object pattern can't contain methods"); throw this.raise(
prop.key.start,
"Object pattern can't contain methods",
);
} else { } else {
super.toAssignableObjectExpressionProp(prop, isBinding, isLast); super.toAssignableObjectExpressionProp(prop, isBinding, isLast);
} }

View File

@ -1,5 +1,7 @@
// @flow // @flow
/*:: declare var invariant; */
import type Parser from "../parser"; import type Parser from "../parser";
import { types as tt, type TokenType } from "../tokenizer/types"; import { types as tt, type TokenType } from "../tokenizer/types";
import * as N from "../types"; import * as N from "../types";
@ -263,7 +265,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.flowParseDeclareModuleExports(node); return this.flowParseDeclareModuleExports(node);
} else { } else {
if (insideModule) { if (insideModule) {
this.unexpected( this.raise(
this.state.lastTokStart, this.state.lastTokStart,
"`declare module` cannot be used inside another `declare module`", "`declare module` cannot be used inside another `declare module`",
); );
@ -313,7 +315,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (this.match(tt._import)) { if (this.match(tt._import)) {
this.next(); this.next();
if (!this.isContextual("type") && !this.match(tt._typeof)) { if (!this.isContextual("type") && !this.match(tt._typeof)) {
this.unexpected( this.raise(
this.state.lastTokStart, this.state.lastTokStart,
"Imports within a `declare module` body must always be `import type` or `import typeof`", "Imports within a `declare module` body must always be `import type` or `import typeof`",
); );
@ -345,17 +347,17 @@ export default (superClass: Class<Parser>): Class<Parser> =>
body.forEach(bodyElement => { body.forEach(bodyElement => {
if (isEsModuleType(bodyElement)) { if (isEsModuleType(bodyElement)) {
if (kind === "CommonJS") { if (kind === "CommonJS") {
this.unexpected(bodyElement.start, errorMessage); this.raise(bodyElement.start, errorMessage);
} }
kind = "ES"; kind = "ES";
} else if (bodyElement.type === "DeclareModuleExports") { } else if (bodyElement.type === "DeclareModuleExports") {
if (hasModuleExport) { if (hasModuleExport) {
this.unexpected( this.raise(
bodyElement.start, bodyElement.start,
"Duplicate `declare module.exports` statement", "Duplicate `declare module.exports` statement",
); );
} }
if (kind === "ES") this.unexpected(bodyElement.start, errorMessage); if (kind === "ES") this.raise(bodyElement.start, errorMessage);
kind = "CommonJS"; kind = "CommonJS";
hasModuleExport = true; hasModuleExport = true;
} }
@ -548,8 +550,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
checkNotUnderscore(word: string) { checkNotUnderscore(word: string) {
if (word === "_") { if (word === "_") {
throw this.unexpected( this.raise(
null, this.state.start,
"`_` is only allowed as a type argument to call or new", "`_` is only allowed as a type argument to call or new",
); );
} }
@ -632,7 +634,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.default = this.flowParseType(); node.default = this.flowParseType();
} else { } else {
if (requireDefault) { if (requireDefault) {
this.unexpected( this.raise(
nodeStart, nodeStart,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
"Type parameter declaration needs a default, since a preceding type parameter declaration has a default.", "Type parameter declaration needs a default, since a preceding type parameter declaration has a default.",
@ -878,6 +880,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
while (!this.match(endDelim)) { while (!this.match(endDelim)) {
let isStatic = false; let isStatic = false;
let protoStart: ?number = null; let protoStart: ?number = null;
let inexactStart: ?number = null;
const node = this.startNode(); const node = this.startNode();
if (allowProto && this.isContextual("proto")) { if (allowProto && this.isContextual("proto")) {
@ -950,17 +953,29 @@ export default (superClass: Class<Parser>): Class<Parser> =>
variance, variance,
kind, kind,
allowSpread, allowSpread,
allowInexact, allowInexact ?? !exact,
); );
if (propOrInexact === null) { if (propOrInexact === null) {
inexact = true; inexact = true;
inexactStart = this.state.lastTokStart;
} else { } else {
nodeStart.properties.push(propOrInexact); nodeStart.properties.push(propOrInexact);
} }
} }
this.flowObjectTypeSemicolon(); this.flowObjectTypeSemicolon();
if (
inexactStart &&
!this.match(tt.braceR) &&
!this.match(tt.braceBarR)
) {
this.raise(
inexactStart,
"Explicit inexact syntax must appear at the end of an inexact object",
);
}
} }
this.expect(endDelim); this.expect(endDelim);
@ -990,10 +1005,38 @@ export default (superClass: Class<Parser>): Class<Parser> =>
allowSpread: boolean, allowSpread: boolean,
allowInexact: boolean, allowInexact: boolean,
): (N.FlowObjectTypeProperty | N.FlowObjectTypeSpreadProperty) | null { ): (N.FlowObjectTypeProperty | N.FlowObjectTypeSpreadProperty) | null {
if (this.match(tt.ellipsis)) { if (this.eat(tt.ellipsis)) {
const isInexactToken =
this.match(tt.comma) ||
this.match(tt.semi) ||
this.match(tt.braceR) ||
this.match(tt.braceBarR);
if (isInexactToken) {
if (!allowSpread) {
this.raise(
this.state.lastTokStart,
"Explicit inexact syntax cannot appear in class or interface definitions",
);
} else if (!allowInexact) {
this.raise(
this.state.lastTokStart,
"Explicit inexact syntax cannot appear inside an explicit exact object type",
);
}
if (variance) {
this.raise(
variance.start,
"Explicit inexact syntax cannot have variance",
);
}
return null;
}
if (!allowSpread) { if (!allowSpread) {
this.unexpected( this.raise(
null, this.state.lastTokStart,
"Spread operator cannot appear in class or interface definitions", "Spread operator cannot appear in class or interface definitions",
); );
} }
@ -1001,35 +1044,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.unexpected(protoStart); this.unexpected(protoStart);
} }
if (variance) { if (variance) {
this.unexpected( this.raise(variance.start, "Spread properties cannot have variance");
variance.start,
"Spread properties cannot have variance",
);
}
this.expect(tt.ellipsis);
const isInexactToken = this.eat(tt.comma) || this.eat(tt.semi);
if (this.match(tt.braceR)) {
if (allowInexact) return null;
this.unexpected(
null,
"Explicit inexact syntax is only allowed inside inexact objects",
);
} }
if (this.match(tt.braceBarR)) {
this.unexpected(
null,
"Explicit inexact syntax cannot appear inside an explicit exact object type",
);
}
if (isInexactToken) {
this.unexpected(
null,
"Explicit inexact syntax must appear at the end of an inexact object",
);
}
node.argument = this.flowParseType(); node.argument = this.flowParseType();
return this.finishNode(node, "ObjectTypeSpreadProperty"); return this.finishNode(node, "ObjectTypeSpreadProperty");
} else { } else {
@ -1400,8 +1417,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
); );
} }
this.unexpected( throw this.raise(
null, this.state.start,
`Unexpected token, expected "number" or "bigint"`, `Unexpected token, expected "number" or "bigint"`,
); );
} }
@ -1720,23 +1737,23 @@ export default (superClass: Class<Parser>): Class<Parser> =>
): N.Expression { ): N.Expression {
if (!this.match(tt.question)) return expr; if (!this.match(tt.question)) return expr;
// only do the expensive clone if there is a question mark // only use the expensive "tryParse" method if there is a question mark
// and if we come from inside parens // and if we come from inside parens
if (refNeedsArrowPos) { if (refNeedsArrowPos) {
const state = this.state.clone(); const result = this.tryParse(() =>
try { super.parseConditional(expr, noIn, startPos, startLoc),
return super.parseConditional(expr, noIn, startPos, startLoc); );
} catch (err) {
if (err instanceof SyntaxError) { if (!result.node) {
this.state = state; // $FlowIgnore
refNeedsArrowPos.start = err.pos || this.state.start; refNeedsArrowPos.start = result.error.pos || this.state.start;
return expr; return expr;
} else {
// istanbul ignore next: no such error is expected
throw err;
}
} }
if (result.error) this.state = result.failState;
return result.node;
} }
this.expect(tt.question); this.expect(tt.question);
const state = this.state.clone(); const state = this.state.clone();
const originalNoArrowAt = this.state.noArrowAt; const originalNoArrowAt = this.state.noArrowAt;
@ -1776,10 +1793,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.state.noArrowAt = noArrowAt.concat(valid[0].start); this.state.noArrowAt = noArrowAt.concat(valid[0].start);
({ consequent, failed } = this.tryParseConditionalConsequent()); ({ consequent, failed } = this.tryParseConditionalConsequent());
} }
this.getArrowLikeExpressions(consequent, true);
} }
this.getArrowLikeExpressions(consequent, true);
this.state.noArrowAt = originalNoArrowAt; this.state.noArrowAt = originalNoArrowAt;
this.expect(tt.colon); this.expect(tt.colon);
@ -1825,19 +1842,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (node.type === "ArrowFunctionExpression") { if (node.type === "ArrowFunctionExpression") {
if (node.typeParameters || !node.returnType) { if (node.typeParameters || !node.returnType) {
// This is an arrow expression without ambiguity, so check its parameters // This is an arrow expression without ambiguity, so check its parameters
this.toAssignableList( this.finishArrowValidation(node);
// node.params is Expression[] instead of $ReadOnlyArray<Pattern> because it
// has not been converted yet.
((node.params: any): N.Expression[]),
true,
"arrow function parameters",
node.extra?.trailingComma,
);
// Enter scope, as checkParams defines bindings
this.scope.enter(functionFlags(false, false) | SCOPE_ARROW);
// Use super's method to force the parameters to be checked
super.checkParams(node, false, true);
this.scope.exit();
} else { } else {
arrows.push(node); arrows.push(node);
} }
@ -1849,30 +1854,29 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} }
if (disallowInvalid) { if (disallowInvalid) {
for (let i = 0; i < arrows.length; i++) { arrows.forEach(node => this.finishArrowValidation(node));
this.toAssignableList(
((node.params: any): N.Expression[]),
true,
"arrow function parameters",
node.extra?.trailingComma,
);
}
return [arrows, []]; return [arrows, []];
} }
return partition(arrows, node => { return partition(arrows, node =>
try { node.params.every(param => this.isAssignable(param, true)),
this.toAssignableList( );
((node.params: any): N.Expression[]), }
true,
"arrow function parameters", finishArrowValidation(node: N.ArrowFunctionExpression) {
node.extra?.trailingComma, this.toAssignableList(
); // node.params is Expression[] instead of $ReadOnlyArray<Pattern> because it
return true; // has not been converted yet.
} catch (err) { ((node.params: any): N.Expression[]),
return false; true,
} "arrow function parameters",
}); node.extra?.trailingComma,
);
// Enter scope, as checkParams defines bindings
this.scope.enter(functionFlags(false, false) | SCOPE_ARROW);
// Use super's method to force the parameters to be checked
super.checkParams(node, false, true);
this.scope.exit();
} }
forwardNoArrowParamsConversionAt<T>(node: N.Node, parse: () => T): T { forwardNoArrowParamsConversionAt<T>(node: N.Node, parse: () => T): T {
@ -2025,6 +2029,49 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} }
} }
isAssignable(node: N.Node, isBinding?: boolean): boolean {
switch (node.type) {
case "Identifier":
case "ObjectPattern":
case "ArrayPattern":
case "AssignmentPattern":
return true;
case "ObjectExpression": {
const last = node.properties.length - 1;
return node.properties.every((prop, i) => {
return (
prop.type !== "ObjectMethod" &&
(i === last || prop.type === "SpreadElement") &&
this.isAssignable(prop)
);
});
}
case "ObjectProperty":
return this.isAssignable(node.value);
case "SpreadElement":
return this.isAssignable(node.argument);
case "ArrayExpression":
return node.elements.every(element => this.isAssignable(element));
case "AssignmentExpression":
return node.operator === "=";
case "ParenthesizedExpression":
return this.isAssignable(node.expression);
case "MemberExpression":
case "OptionalMemberExpression":
return !isBinding;
default:
return false;
}
}
toAssignable( toAssignable(
node: N.Node, node: N.Node,
isBinding: ?boolean, isBinding: ?boolean,
@ -2253,13 +2300,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
parseAssignableListItemTypes(param: N.Pattern): N.Pattern { parseAssignableListItemTypes(param: N.Pattern): N.Pattern {
if (this.eat(tt.question)) { if (this.eat(tt.question)) {
if (param.type !== "Identifier") { if (param.type !== "Identifier") {
throw this.raise( this.raise(
param.start, param.start,
"A binding pattern parameter cannot be optional in an implementation signature.", "A binding pattern parameter cannot be optional in an implementation signature.",
); );
} }
param.optional = true; ((param: any): N.Identifier).optional = true;
} }
if (this.match(tt.colon)) { if (this.match(tt.colon)) {
param.typeAnnotation = this.flowParseTypeAnnotation(); param.typeAnnotation = this.flowParseTypeAnnotation();
@ -2490,45 +2537,50 @@ export default (superClass: Class<Parser>): Class<Parser> =>
afterLeftParse?: Function, afterLeftParse?: Function,
refNeedsArrowPos?: ?Pos, refNeedsArrowPos?: ?Pos,
): N.Expression { ): N.Expression {
let jsxError = null; let state = null;
let jsx;
if ( if (
this.hasPlugin("jsx") && this.hasPlugin("jsx") &&
(this.match(tt.jsxTagStart) || this.isRelational("<")) (this.match(tt.jsxTagStart) || this.isRelational("<"))
) { ) {
const state = this.state.clone(); state = this.state.clone();
try {
return super.parseMaybeAssign(
noIn,
refShorthandDefaultPos,
afterLeftParse,
refNeedsArrowPos,
);
} catch (err) {
if (err instanceof SyntaxError) {
this.state = state;
// Remove `tc.j_expr` and `tc.j_oTag` from context added jsx = this.tryParse(
// by parsing `jsxTagStart` to stop the JSX plugin from () =>
// messing with the tokens super.parseMaybeAssign(
const cLength = this.state.context.length; noIn,
if (this.state.context[cLength - 1] === tc.j_oTag) { refShorthandDefaultPos,
this.state.context.length -= 2; afterLeftParse,
} refNeedsArrowPos,
),
state,
);
/*:: invariant(!jsx.aborted) */
jsxError = err; if (!jsx.error) return jsx.node;
} else {
// istanbul ignore next: no such error is expected // Remove `tc.j_expr` and `tc.j_oTag` from context added
throw err; // by parsing `jsxTagStart` to stop the JSX plugin from
} // messing with the tokens
const { context } = this.state;
if (context[context.length - 1] === tc.j_oTag) {
context.length -= 2;
} else if (context[context.length - 1] === tc.j_expr) {
context.length -= 1;
} }
} }
if (jsxError != null || this.isRelational("<")) { if ((jsx && jsx.error) || this.isRelational("<")) {
let arrowExpression; state = state || this.state.clone();
let typeParameters; let typeParameters;
try {
const arrow = this.tryParse(() => {
typeParameters = this.flowParseTypeParameterDeclaration(); typeParameters = this.flowParseTypeParameterDeclaration();
arrowExpression = this.forwardNoArrowParamsConversionAt(
const arrowExpression = this.forwardNoArrowParamsConversionAt(
typeParameters, typeParameters,
() => () =>
super.parseMaybeAssign( super.parseMaybeAssign(
@ -2540,20 +2592,43 @@ export default (superClass: Class<Parser>): Class<Parser> =>
); );
arrowExpression.typeParameters = typeParameters; arrowExpression.typeParameters = typeParameters;
this.resetStartLocationFromNode(arrowExpression, typeParameters); this.resetStartLocationFromNode(arrowExpression, typeParameters);
} catch (err) {
throw jsxError || err; return arrowExpression;
}, state);
const arrowExpression: ?N.ArrowFunctionExpression =
arrow.node && arrow.node.type === "ArrowFunctionExpression"
? arrow.node
: null;
if (!arrow.error && arrowExpression) return arrowExpression;
// If we are here, both JSX and Flow parsing attemps failed.
// Give the precedence to the JSX error, except if JSX had an
// unrecoverable error while Flow didn't.
// If the error is recoverable, we can only re-report it if there is
// a node we can return.
if (jsx && jsx.node) {
/*:: invariant(jsx.failState) */
this.state = jsx.failState;
return jsx.node;
} }
if (arrowExpression.type === "ArrowFunctionExpression") { if (arrowExpression) {
/*:: invariant(arrow.failState) */
this.state = arrow.failState;
return arrowExpression; return arrowExpression;
} else if (jsxError != null) {
throw jsxError;
} else {
this.raise(
typeParameters.start,
"Expected an arrow function after this type parameter declaration",
);
} }
if (jsx && jsx.thrown) throw jsx.error;
if (arrow.thrown) throw arrow.error;
/*:: invariant(typeParameters) */
throw this.raise(
typeParameters.start,
"Expected an arrow function after this type parameter declaration",
);
} }
return super.parseMaybeAssign( return super.parseMaybeAssign(
@ -2567,8 +2642,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// handle return types for arrow functions // handle return types for arrow functions
parseArrow(node: N.ArrowFunctionExpression): ?N.ArrowFunctionExpression { parseArrow(node: N.ArrowFunctionExpression): ?N.ArrowFunctionExpression {
if (this.match(tt.colon)) { if (this.match(tt.colon)) {
const state = this.state.clone(); const result = this.tryParse(() => {
try {
const oldNoAnonFunctionType = this.state.noAnonFunctionType; const oldNoAnonFunctionType = this.state.noAnonFunctionType;
this.state.noAnonFunctionType = true; this.state.noAnonFunctionType = true;
@ -2586,18 +2660,18 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (this.canInsertSemicolon()) this.unexpected(); if (this.canInsertSemicolon()) this.unexpected();
if (!this.match(tt.arrow)) this.unexpected(); if (!this.match(tt.arrow)) this.unexpected();
// assign after it is clear it is an arrow return typeNode;
node.returnType = typeNode.typeAnnotation });
? this.finishNode(typeNode, "TypeAnnotation")
: null; if (result.thrown) return null;
} catch (err) { /*:: invariant(result.node) */
if (err instanceof SyntaxError) {
this.state = state; if (result.error) this.state = result.failState;
} else {
// istanbul ignore next: no such error is expected // assign after it is clear it is an arrow
throw err; node.returnType = result.node.typeAnnotation
} ? this.finishNode(result.node, "TypeAnnotation")
} : null;
} }
return super.parseArrow(node); return super.parseArrow(node);
@ -2630,7 +2704,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return; return;
} }
return super.checkParams(node, allowDuplicates, isArrowFunction); return super.checkParams(...arguments);
} }
parseParenAndDistinguishExpression(canBeArrow: boolean): N.Expression { parseParenAndDistinguishExpression(canBeArrow: boolean): N.Expression {
@ -2662,23 +2736,33 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.isRelational("<") this.isRelational("<")
) { ) {
const state = this.state.clone(); const state = this.state.clone();
let error; const arrow = this.tryParse(
try { abort =>
const node = this.parseAsyncArrowWithTypeParameters( this.parseAsyncArrowWithTypeParameters(startPos, startLoc) ||
startPos, abort(),
startLoc, state,
); );
if (node) return node;
} catch (e) { if (!arrow.error && !arrow.aborted) return arrow.node;
error = e;
const result = this.tryParse(
() => super.parseSubscripts(base, startPos, startLoc, noCalls),
state,
);
if (result.node && !result.error) return result.node;
if (arrow.node) {
this.state = arrow.failState;
return arrow.node;
} }
this.state = state; if (result.node) {
try { this.state = result.failState;
return super.parseSubscripts(base, startPos, startLoc, noCalls); return result.node;
} catch (e) {
throw error || e;
} }
throw arrow.error || result.error;
} }
return super.parseSubscripts(base, startPos, startLoc, noCalls); return super.parseSubscripts(base, startPos, startLoc, noCalls);
@ -2717,8 +2801,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
) { ) {
const node = this.startNodeAt(startPos, startLoc); const node = this.startNodeAt(startPos, startLoc);
node.callee = base; node.callee = base;
const state = this.state.clone();
try { const result = this.tryParse(() => {
node.typeArguments = this.flowParseTypeParameterInstantiationCallOrNew(); node.typeArguments = this.flowParseTypeParameterInstantiationCallOrNew();
this.expect(tt.parenL); this.expect(tt.parenL);
node.arguments = this.parseCallExpressionArguments(tt.parenR, false); node.arguments = this.parseCallExpressionArguments(tt.parenR, false);
@ -2727,12 +2811,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node, node,
subscriptState.optionalChainMember, subscriptState.optionalChainMember,
); );
} catch (e) { });
if (e instanceof SyntaxError) {
this.state = state; if (result.node) {
} else { if (result.error) this.state = result.failState;
throw e; return result.node;
}
} }
} }
@ -2748,16 +2831,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
parseNewArguments(node: N.NewExpression): void { parseNewArguments(node: N.NewExpression): void {
let targs = null; let targs = null;
if (this.shouldParseTypes() && this.isRelational("<")) { if (this.shouldParseTypes() && this.isRelational("<")) {
const state = this.state.clone(); targs = this.tryParse(() =>
try { this.flowParseTypeParameterInstantiationCallOrNew(),
targs = this.flowParseTypeParameterInstantiationCallOrNew(); ).node;
} catch (e) {
if (e instanceof SyntaxError) {
this.state = state;
} else {
throw e;
}
}
} }
node.typeArguments = targs; node.typeArguments = targs;
@ -2811,7 +2887,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
parseTopLevel(file: N.File, program: N.Program): N.File { parseTopLevel(file: N.File, program: N.Program): N.File {
const fileNode = super.parseTopLevel(file, program); const fileNode = super.parseTopLevel(file, program);
if (this.state.hasFlowComment) { if (this.state.hasFlowComment) {
this.unexpected(null, "Unterminated flow-comment"); this.raise(this.state.pos, "Unterminated flow-comment");
} }
return fileNode; return fileNode;
} }
@ -2832,7 +2908,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (this.state.hasFlowComment) { if (this.state.hasFlowComment) {
const end = this.input.indexOf("*-/", (this.state.pos += 2)); const end = this.input.indexOf("*-/", (this.state.pos += 2));
if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment"); if (end === -1) {
throw this.raise(this.state.pos - 2, "Unterminated comment");
}
this.state.pos = end + 3; this.state.pos = end + 3;
return; return;
} }
@ -2874,7 +2952,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
hasFlowCommentCompletion(): void { hasFlowCommentCompletion(): void {
const end = this.input.indexOf("*/", this.state.pos); const end = this.input.indexOf("*/", this.state.pos);
if (end === -1) { if (end === -1) {
this.raise(this.state.pos, "Unterminated comment"); throw this.raise(this.state.pos, "Unterminated comment");
} }
} }
@ -2931,7 +3009,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
enumName, enumName,
suppliedType, suppliedType,
}: { enumName: string, suppliedType: null | string }, }: { enumName: string, suppliedType: null | string },
): void { ) {
const suggestion = const suggestion =
`Use one of \`boolean\`, \`number\`, \`string\`, or \`symbol\` in ` + `Use one of \`boolean\`, \`number\`, \`string\`, or \`symbol\` in ` +
`enum \`${enumName}\`.`; `enum \`${enumName}\`.`;
@ -2939,13 +3017,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
suppliedType === null suppliedType === null
? `Supplied enum type is not valid. ${suggestion}` ? `Supplied enum type is not valid. ${suggestion}`
: `Enum type \`${suppliedType}\` is not valid. ${suggestion}`; : `Enum type \`${suppliedType}\` is not valid. ${suggestion}`;
this.raise(pos, message); return this.raise(pos, message);
} }
flowEnumErrorInvalidMemberInitializer( flowEnumErrorInvalidMemberInitializer(
pos: number, pos: number,
{ enumName, explicitType, memberName }: EnumContext, { enumName, explicitType, memberName }: EnumContext,
): void { ) {
let message = null; let message = null;
switch (explicitType) { switch (explicitType) {
case "boolean": case "boolean":
@ -2966,7 +3044,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
`The enum member initializer for \`${memberName}\` needs to be a literal (either ` + `The enum member initializer for \`${memberName}\` needs to be a literal (either ` +
`a boolean, number, or string) in enum \`${enumName}\`.`; `a boolean, number, or string) in enum \`${enumName}\`.`;
} }
this.raise(pos, message); return this.raise(pos, message);
} }
flowEnumErrorNumberMemberNotInitialized( flowEnumErrorNumberMemberNotInitialized(
@ -3119,8 +3197,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
break; break;
} }
case "invalid": { case "invalid": {
this.flowEnumErrorInvalidMemberInitializer(init.pos, context); throw this.flowEnumErrorInvalidMemberInitializer(init.pos, context);
break;
} }
case "none": { case "none": {
switch (explicitType) { switch (explicitType) {
@ -3184,28 +3261,29 @@ export default (superClass: Class<Parser>): Class<Parser> =>
enumName: string, enumName: string,
}): EnumExplicitType { }): EnumExplicitType {
if (this.eatContextual("of")) { if (this.eatContextual("of")) {
if (this.match(tt.name)) { if (!this.match(tt.name)) {
switch (this.state.value) { throw this.flowEnumErrorInvalidExplicitType(this.state.start, {
case "boolean":
case "number":
case "string":
case "symbol": {
const explicitType = this.state.value;
this.next();
return explicitType;
}
default:
this.flowEnumErrorInvalidExplicitType(this.state.start, {
enumName,
suppliedType: this.state.value,
});
}
} else {
this.flowEnumErrorInvalidExplicitType(this.state.start, {
enumName, enumName,
suppliedType: null, suppliedType: null,
}); });
} }
const { value } = this.state;
this.next();
if (
value !== "boolean" &&
value !== "number" &&
value !== "string" &&
value !== "symbol"
) {
this.flowEnumErrorInvalidExplicitType(this.state.start, {
enumName,
suppliedType: value,
});
}
return value;
} }
return null; return null;
} }

View File

@ -82,7 +82,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let chunkStart = this.state.pos; let chunkStart = this.state.pos;
for (;;) { for (;;) {
if (this.state.pos >= this.length) { if (this.state.pos >= this.length) {
this.raise(this.state.start, "Unterminated JSX contents"); throw this.raise(this.state.start, "Unterminated JSX contents");
} }
const ch = this.input.charCodeAt(this.state.pos); const ch = this.input.charCodeAt(this.state.pos);
@ -142,7 +142,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let chunkStart = ++this.state.pos; let chunkStart = ++this.state.pos;
for (;;) { for (;;) {
if (this.state.pos >= this.length) { if (this.state.pos >= this.length) {
this.raise(this.state.start, "Unterminated string constant"); throw this.raise(this.state.start, "Unterminated string constant");
} }
const ch = this.input.charCodeAt(this.state.pos); const ch = this.input.charCodeAt(this.state.pos);
@ -279,13 +279,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.next(); this.next();
node = this.jsxParseExpressionContainer(node); node = this.jsxParseExpressionContainer(node);
if (node.expression.type === "JSXEmptyExpression") { if (node.expression.type === "JSXEmptyExpression") {
throw this.raise( this.raise(
node.start, node.start,
"JSX attributes must only be assigned a non-empty expression", "JSX attributes must only be assigned a non-empty expression",
); );
} else {
return node;
} }
return node;
case tt.jsxTagStart: case tt.jsxTagStart:
case tt.string: case tt.string:
@ -485,12 +484,18 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.closingElement = closingElement; node.closingElement = closingElement;
} }
node.children = children; node.children = children;
if (this.match(tt.relational) && this.state.value === "<") { while (this.isRelational("<")) {
// In case we encounter an lt token here it will always be the start of
// jsx as the lt sign is not allowed in places that expect an expression
this.finishToken(tt.jsxTagStart);
this.raise( this.raise(
this.state.start, this.state.start,
"Adjacent JSX elements must be wrapped in an enclosing tag. " + "Adjacent JSX elements must be wrapped in an enclosing tag. " +
"Did you want a JSX fragment <>...</>?", "Did you want a JSX fragment <>...</>?",
); );
this.jsxParseElement();
} }
return isFragment(openingElement) return isFragment(openingElement)

View File

@ -1,6 +1,9 @@
// @flow // @flow
/*:: declare var invariant; */
import type { TokenType } from "../../tokenizer/types"; import type { TokenType } from "../../tokenizer/types";
import type State from "../../tokenizer/state";
import { types as tt } from "../../tokenizer/types"; import { types as tt } from "../../tokenizer/types";
import { types as ct } from "../../tokenizer/context"; import { types as ct } from "../../tokenizer/context";
import * as N from "../../types"; import * as N from "../../types";
@ -234,8 +237,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.expect(tt._import); this.expect(tt._import);
this.expect(tt.parenL); this.expect(tt.parenL);
if (!this.match(tt.string)) { if (!this.match(tt.string)) {
throw this.unexpected( this.raise(
null, this.state.start,
"Argument in a type import must be a string literal", "Argument in a type import must be a string literal",
); );
} }
@ -371,13 +374,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
pattern.type !== "ObjectPattern" && pattern.type !== "ObjectPattern" &&
pattern.type !== "ArrayPattern" pattern.type !== "ArrayPattern"
) { ) {
throw this.unexpected( this.raise(
pattern.start, pattern.start,
"Name in a signature must be an Identifier, ObjectPattern or ArrayPattern," + "Name in a signature must be an Identifier, ObjectPattern or ArrayPattern," +
`instead got ${pattern.type}`, `instead got ${pattern.type}`,
); );
} }
return pattern; return (pattern: any);
}, },
); );
} }
@ -642,7 +645,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
const node: N.TsLiteralType = this.startNode(); const node: N.TsLiteralType = this.startNode();
const templateNode = this.parseTemplate(false); const templateNode = this.parseTemplate(false);
if (templateNode.expressions.length > 0) { if (templateNode.expressions.length > 0) {
throw this.raise( this.raise(
templateNode.expressions[0].start, templateNode.expressions[0].start,
"Template literal types cannot have any substitution", "Template literal types cannot have any substitution",
); );
@ -1276,17 +1279,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return res; return res;
} }
tsTryParseAndCatch<T>(f: () => T): ?T { tsTryParseAndCatch<T: ?N.NodeBase>(f: () => T): ?T {
const state = this.state.clone(); const result = this.tryParse(abort => f() || abort());
try {
return f(); if (result.aborted || !result.node) return undefined;
} catch (e) { if (result.error) this.state = result.failState;
if (e instanceof SyntaxError) { return result.node;
this.state = state;
return undefined;
}
throw e;
}
} }
tsTryParse<T>(f: () => ?T): ?T { tsTryParse<T>(f: () => ?T): ?T {
@ -1558,12 +1556,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (accessibility) pp.accessibility = accessibility; if (accessibility) pp.accessibility = accessibility;
if (readonly) pp.readonly = readonly; if (readonly) pp.readonly = readonly;
if (elt.type !== "Identifier" && elt.type !== "AssignmentPattern") { if (elt.type !== "Identifier" && elt.type !== "AssignmentPattern") {
throw this.raise( this.raise(
pp.start, pp.start,
"A parameter property may not be declared using a binding pattern.", "A parameter property may not be declared using a binding pattern.",
); );
} }
pp.parameter = elt; pp.parameter = ((elt: any): N.Identifier | N.AssignmentPattern);
return this.finishNode(pp, "TSParameterProperty"); return this.finishNode(pp, "TSParameterProperty");
} }
@ -1597,11 +1595,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
super.parseFunctionBodyAndFinish(node, type, isMethod); super.parseFunctionBodyAndFinish(node, type, isMethod);
} }
checkFunctionStatementId(node: N.Function): void { registerFunctionStatementId(node: N.Function): void {
if (!node.body && node.id) { if (!node.body && node.id) {
// Function ids are validated after parsing their body.
// For bodyless function, we need to do it here.
this.checkLVal(node.id, BIND_TS_AMBIENT, null, "function name"); this.checkLVal(node.id, BIND_TS_AMBIENT, null, "function name");
} else { } else {
super.checkFunctionStatementId(...arguments); super.registerFunctionStatementId(...arguments);
} }
} }
@ -1946,19 +1946,17 @@ export default (superClass: Class<Parser>): Class<Parser> =>
); );
} }
const state = this.state.clone(); const result = this.tryParse(() =>
try { super.parseConditional(expr, noIn, startPos, startLoc),
return super.parseConditional(expr, noIn, startPos, startLoc); );
} catch (err) {
if (!(err instanceof SyntaxError)) {
// istanbul ignore next: no such error is expected
throw err;
}
this.state = state; if (!result.node) {
refNeedsArrowPos.start = err.pos || this.state.start; // $FlowIgnore
refNeedsArrowPos.start = result.error.pos || this.state.start;
return expr; return expr;
} }
if (result.error) this.state = result.failState;
return result.node;
} }
// Note: These "type casts" are *not* valid TS expressions. // Note: These "type casts" are *not* valid TS expressions.
@ -2161,80 +2159,97 @@ export default (superClass: Class<Parser>): Class<Parser> =>
parseMaybeAssign(...args): N.Expression { parseMaybeAssign(...args): N.Expression {
// Note: When the JSX plugin is on, type assertions (`<T> x`) aren't valid syntax. // Note: When the JSX plugin is on, type assertions (`<T> x`) aren't valid syntax.
let jsxError: ?SyntaxError; let state: ?State;
let jsx;
let typeCast;
if (this.match(tt.jsxTagStart)) { if (this.match(tt.jsxTagStart)) {
const context = this.curContext();
assert(context === ct.j_oTag);
// Only time j_oTag is pushed is right after j_expr.
assert(this.state.context[this.state.context.length - 2] === ct.j_expr);
// Prefer to parse JSX if possible. But may be an arrow fn. // Prefer to parse JSX if possible. But may be an arrow fn.
const state = this.state.clone(); state = this.state.clone();
try {
return super.parseMaybeAssign(...args);
} catch (err) {
if (!(err instanceof SyntaxError)) {
// istanbul ignore next: no such error is expected
throw err;
}
this.state = state; jsx = this.tryParse(() => super.parseMaybeAssign(...args), state);
// Pop the context added by the jsxTagStart. /*:: invariant(!jsx.aborted) */
assert(this.curContext() === ct.j_oTag);
this.state.context.pop(); if (!jsx.error) return jsx.node;
assert(this.curContext() === ct.j_expr);
this.state.context.pop(); // Remove `tc.j_expr` and `tc.j_oTag` from context added
jsxError = err; // by parsing `jsxTagStart` to stop the JSX plugin from
// messing with the tokens
const { context } = this.state;
if (context[context.length - 1] === ct.j_oTag) {
context.length -= 2;
} else if (context[context.length - 1] === ct.j_expr) {
context.length -= 1;
} }
} }
if (jsxError === undefined && !this.isRelational("<")) { if (!(jsx && jsx.error) && !this.isRelational("<")) {
return super.parseMaybeAssign(...args); return super.parseMaybeAssign(...args);
} }
// Either way, we're looking at a '<': tt.jsxTagStart or relational. // Either way, we're looking at a '<': tt.jsxTagStart or relational.
let arrowExpression;
let typeParameters: N.TsTypeParameterDeclaration; let typeParameters: N.TsTypeParameterDeclaration;
const state = this.state.clone(); state = state || this.state.clone();
try {
const arrow = this.tryParse(abort => {
// This is similar to TypeScript's `tryParseParenthesizedArrowFunctionExpression`. // This is similar to TypeScript's `tryParseParenthesizedArrowFunctionExpression`.
typeParameters = this.tsParseTypeParameters(); typeParameters = this.tsParseTypeParameters();
arrowExpression = super.parseMaybeAssign(...args); const expr = super.parseMaybeAssign(...args);
if ( if (
arrowExpression.type !== "ArrowFunctionExpression" || expr.type !== "ArrowFunctionExpression" ||
(arrowExpression.extra && arrowExpression.extra.parenthesized) (expr.extra && expr.extra.parenthesized)
) { ) {
this.unexpected(); // Go to the catch block (needs a SyntaxError). abort();
}
} catch (err) {
if (!(err instanceof SyntaxError)) {
// istanbul ignore next: no such error is expected
throw err;
} }
if (jsxError) { // Correct TypeScript code should have at least 1 type parameter, but don't crash on bad code.
throw jsxError; if (typeParameters && typeParameters.params.length !== 0) {
this.resetStartLocationFromNode(expr, typeParameters);
} }
expr.typeParameters = typeParameters;
return expr;
}, state);
if (!arrow.error && !arrow.aborted) return arrow.node;
if (!jsx) {
// Try parsing a type cast instead of an arrow function. // Try parsing a type cast instead of an arrow function.
// This will never happen outside of JSX. // This will never happen outside of JSX.
// (Because in JSX the '<' should be a jsxTagStart and not a relational. // (Because in JSX the '<' should be a jsxTagStart and not a relational.
assert(!this.hasPlugin("jsx")); assert(!this.hasPlugin("jsx"));
// Parsing an arrow function failed, so try a type cast.
this.state = state;
// This will start with a type assertion (via parseMaybeUnary). // This will start with a type assertion (via parseMaybeUnary).
// But don't directly call `this.tsParseTypeAssertion` because we want to handle any binary after it. // But don't directly call `this.tsParseTypeAssertion` because we want to handle any binary after it.
return super.parseMaybeAssign(...args); typeCast = this.tryParse(() => super.parseMaybeAssign(...args), state);
/*:: invariant(!typeCast.aborted) */
if (!typeCast.error) return typeCast.node;
} }
// Correct TypeScript code should have at least 1 type parameter, but don't crash on bad code. if (jsx && jsx.node) {
if (typeParameters && typeParameters.params.length !== 0) { /*:: invariant(jsx.failState) */
this.resetStartLocationFromNode(arrowExpression, typeParameters); this.state = jsx.failState;
return jsx.node;
} }
arrowExpression.typeParameters = typeParameters;
return arrowExpression; if (arrow.node) {
/*:: invariant(arrow.failState) */
this.state = arrow.failState;
return arrow.node;
}
if (typeCast && typeCast.node) {
/*:: invariant(typeCast.failState) */
this.state = typeCast.failState;
return typeCast.node;
}
if (jsx && jsx.thrown) throw jsx.error;
if (arrow.thrown) throw arrow.error;
if (typeCast && typeCast.thrown) throw typeCast.error;
throw (jsx && jsx.error) || arrow.error || (typeCast && typeCast.error);
} }
// Handle type assertions // Handle type assertions
@ -2250,23 +2265,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (this.match(tt.colon)) { if (this.match(tt.colon)) {
// This is different from how the TS parser does it. // This is different from how the TS parser does it.
// TS uses lookahead. The Babel Parser parses it as a parenthesized expression and converts. // TS uses lookahead. The Babel Parser parses it as a parenthesized expression and converts.
const state = this.state.clone();
try { const result = this.tryParse(abort => {
const returnType = this.tsParseTypeOrTypePredicateAnnotation( const returnType = this.tsParseTypeOrTypePredicateAnnotation(
tt.colon, tt.colon,
); );
if (this.canInsertSemicolon() || !this.match(tt.arrow)) { if (this.canInsertSemicolon() || !this.match(tt.arrow)) abort();
this.state = state; return returnType;
return undefined; });
}
node.returnType = returnType; if (result.aborted) return;
} catch (err) {
if (err instanceof SyntaxError) { if (!result.thrown) {
this.state = state; if (result.error) this.state = result.failState;
} else { node.returnType = result.node;
// istanbul ignore next: no such error is expected
throw err;
}
} }
} }
@ -2277,13 +2289,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
parseAssignableListItemTypes(param: N.Pattern) { parseAssignableListItemTypes(param: N.Pattern) {
if (this.eat(tt.question)) { if (this.eat(tt.question)) {
if (param.type !== "Identifier") { if (param.type !== "Identifier") {
throw this.raise( this.raise(
param.start, param.start,
"A binding pattern parameter cannot be optional in an implementation signature.", "A binding pattern parameter cannot be optional in an implementation signature.",
); );
} }
param.optional = true; ((param: any): N.Identifier).optional = true;
} }
const type = this.tsTryParseTypeAnnotation(); const type = this.tsTryParseTypeAnnotation();
if (type) param.typeAnnotation = type; if (type) param.typeAnnotation = type;

View File

@ -126,8 +126,11 @@ export default class Tokenizer extends LocationParser {
// Move to the next token // Move to the next token
next(): void { next(): void {
if (this.options.tokens && !this.isLookahead) { if (!this.isLookahead) {
this.state.tokens.push(new Token(this.state)); this.checkKeywordEscapes();
if (this.options.tokens) {
this.state.tokens.push(new Token(this.state));
}
} }
this.state.lastTokEnd = this.state.end; this.state.lastTokEnd = this.state.end;
@ -248,7 +251,7 @@ export default class Tokenizer extends LocationParser {
const startLoc = this.state.curPosition(); const startLoc = this.state.curPosition();
const start = this.state.pos; const start = this.state.pos;
const end = this.input.indexOf("*/", this.state.pos + 2); const end = this.input.indexOf("*/", this.state.pos + 2);
if (end === -1) this.raise(start, "Unterminated comment"); if (end === -1) throw this.raise(start, "Unterminated comment");
this.state.pos = end + 2; this.state.pos = end + 2;
lineBreakG.lastIndex = start; lineBreakG.lastIndex = start;
@ -384,7 +387,7 @@ export default class Tokenizer extends LocationParser {
const nextPos = this.state.pos + 1; const nextPos = this.state.pos + 1;
const next = this.input.charCodeAt(nextPos); const next = this.input.charCodeAt(nextPos);
if (next >= charCodes.digit0 && next <= charCodes.digit9) { if (next >= charCodes.digit0 && next <= charCodes.digit9) {
this.raise(this.state.pos, "Unexpected digit after hash token"); throw this.raise(this.state.pos, "Unexpected digit after hash token");
} }
if ( if (
@ -400,7 +403,7 @@ export default class Tokenizer extends LocationParser {
) { ) {
this.finishOp(tt.hash, 1); this.finishOp(tt.hash, 1);
} else { } else {
this.raise(this.state.pos, "Unexpected character '#'"); throw this.raise(this.state.pos, "Unexpected character '#'");
} }
} }
@ -808,7 +811,7 @@ export default class Tokenizer extends LocationParser {
} }
} }
this.raise( throw this.raise(
this.state.pos, this.state.pos,
`Unexpected character '${String.fromCodePoint(code)}'`, `Unexpected character '${String.fromCodePoint(code)}'`,
); );
@ -825,11 +828,11 @@ export default class Tokenizer extends LocationParser {
let escaped, inClass; let escaped, inClass;
for (;;) { for (;;) {
if (this.state.pos >= this.length) { if (this.state.pos >= this.length) {
this.raise(start, "Unterminated regular expression"); throw this.raise(start, "Unterminated regular expression");
} }
const ch = this.input.charAt(this.state.pos); const ch = this.input.charAt(this.state.pos);
if (lineBreak.test(ch)) { if (lineBreak.test(ch)) {
this.raise(start, "Unterminated regular expression"); throw this.raise(start, "Unterminated regular expression");
} }
if (escaped) { if (escaped) {
escaped = false; escaped = false;
@ -858,9 +861,6 @@ export default class Tokenizer extends LocationParser {
if (mods.indexOf(char) > -1) { if (mods.indexOf(char) > -1) {
this.raise(this.state.pos + 1, "Duplicate regular expression flag"); this.raise(this.state.pos + 1, "Duplicate regular expression flag");
} }
++this.state.pos;
mods += char;
} else if ( } else if (
isIdentifierChar(charCode) || isIdentifierChar(charCode) ||
charCode === charCodes.backslash charCode === charCodes.backslash
@ -869,6 +869,9 @@ export default class Tokenizer extends LocationParser {
} else { } else {
break; break;
} }
++this.state.pos;
mods += char;
} }
this.finishToken(tt.regexp, { this.finishToken(tt.regexp, {
@ -880,10 +883,16 @@ export default class Tokenizer extends LocationParser {
// Read an integer in the given radix. Return null if zero digits // Read an integer in the given radix. Return null if zero digits
// were read, the integer value otherwise. When `len` is given, this // were read, the integer value otherwise. When `len` is given, this
// will return `null` unless the integer has exactly `len` digits. // will return `null` unless the integer has exactly `len` digits.
// When `forceLen` is `true`, it means that we already know that in case
// of a malformed number we have to skip `len` characters anyway, instead
// of bailing out early. For example, in "\u{123Z}" we want to read up to }
// anyway, while in "\u00Z" we will stop at Z instead of consuming four
// characters (and thus the closing quote).
readInt( readInt(
radix: number, radix: number,
len?: number, len?: number,
forceLen?: boolean,
allowNumSeparator: boolean = true, allowNumSeparator: boolean = true,
): number | null { ): number | null {
const start = this.state.pos; const start = this.state.pos;
@ -900,6 +909,7 @@ export default class Tokenizer extends LocationParser {
? allowedNumericSeparatorSiblings.oct ? allowedNumericSeparatorSiblings.oct
: allowedNumericSeparatorSiblings.bin; : allowedNumericSeparatorSiblings.bin;
let invalid = false;
let total = 0; let total = 0;
for (let i = 0, e = len == null ? Infinity : len; i < e; ++i) { for (let i = 0, e = len == null ? Infinity : len; i < e; ++i) {
@ -911,15 +921,19 @@ export default class Tokenizer extends LocationParser {
const prev = this.input.charCodeAt(this.state.pos - 1); const prev = this.input.charCodeAt(this.state.pos - 1);
const next = this.input.charCodeAt(this.state.pos + 1); const next = this.input.charCodeAt(this.state.pos + 1);
if (allowedSiblings.indexOf(next) === -1) { if (allowedSiblings.indexOf(next) === -1) {
this.raise(this.state.pos, "Invalid or unexpected token"); this.raise(
} this.state.pos,
"A numeric separator is only allowed between two digits",
if ( );
} else if (
forbiddenSiblings.indexOf(prev) > -1 || forbiddenSiblings.indexOf(prev) > -1 ||
forbiddenSiblings.indexOf(next) > -1 || forbiddenSiblings.indexOf(next) > -1 ||
Number.isNaN(next) Number.isNaN(next)
) { ) {
this.raise(this.state.pos, "Invalid or unexpected token"); this.raise(
this.state.pos,
"A numeric separator is only allowed between two digits",
);
} }
if (!allowNumSeparator) { if (!allowNumSeparator) {
@ -944,13 +958,30 @@ export default class Tokenizer extends LocationParser {
} else { } else {
val = Infinity; val = Infinity;
} }
if (val >= radix) break; if (val >= radix) {
// If we are in "errorRecovery" mode and we found a digit which is too big,
// don't break the loop.
if (this.options.errorRecovery && val <= 9) {
val = 0;
this.raise(
this.state.start + i + 2,
"Expected number in radix " + radix,
);
} else if (forceLen) {
val = 0;
invalid = true;
} else {
break;
}
}
++this.state.pos; ++this.state.pos;
total = total * radix + val; total = total * radix + val;
} }
if ( if (
this.state.pos === start || this.state.pos === start ||
(len != null && this.state.pos - start !== len) (len != null && this.state.pos - start !== len) ||
invalid
) { ) {
return null; return null;
} }
@ -976,7 +1007,7 @@ export default class Tokenizer extends LocationParser {
} }
if (isIdentifierStart(this.input.codePointAt(this.state.pos))) { if (isIdentifierStart(this.input.codePointAt(this.state.pos))) {
this.raise(this.state.pos, "Identifier directly after number"); throw this.raise(this.state.pos, "Identifier directly after number");
} }
if (isBigInt) { if (isBigInt) {
@ -1062,7 +1093,7 @@ export default class Tokenizer extends LocationParser {
} }
if (isIdentifierStart(this.input.codePointAt(this.state.pos))) { if (isIdentifierStart(this.input.codePointAt(this.state.pos))) {
this.raise(this.state.pos, "Identifier directly after number"); throw this.raise(this.state.pos, "Identifier directly after number");
} }
// remove "_" for numeric literal separator, and "n" for BigInts // remove "_" for numeric literal separator, and "n" for BigInts
@ -1087,6 +1118,7 @@ export default class Tokenizer extends LocationParser {
const codePos = ++this.state.pos; const codePos = ++this.state.pos;
code = this.readHexChar( code = this.readHexChar(
this.input.indexOf("}", this.state.pos) - this.state.pos, this.input.indexOf("}", this.state.pos) - this.state.pos,
true,
throwOnInvalid, throwOnInvalid,
); );
++this.state.pos; ++this.state.pos;
@ -1102,7 +1134,7 @@ export default class Tokenizer extends LocationParser {
} }
} }
} else { } else {
code = this.readHexChar(4, throwOnInvalid); code = this.readHexChar(4, false, throwOnInvalid);
} }
return code; return code;
} }
@ -1112,7 +1144,7 @@ export default class Tokenizer extends LocationParser {
chunkStart = ++this.state.pos; chunkStart = ++this.state.pos;
for (;;) { for (;;) {
if (this.state.pos >= this.length) { if (this.state.pos >= this.length) {
this.raise(this.state.start, "Unterminated string constant"); throw this.raise(this.state.start, "Unterminated string constant");
} }
const ch = this.input.charCodeAt(this.state.pos); const ch = this.input.charCodeAt(this.state.pos);
if (ch === quote) break; if (ch === quote) break;
@ -1128,7 +1160,7 @@ export default class Tokenizer extends LocationParser {
++this.state.pos; ++this.state.pos;
++this.state.curLine; ++this.state.curLine;
} else if (isNewLine(ch)) { } else if (isNewLine(ch)) {
this.raise(this.state.start, "Unterminated string constant"); throw this.raise(this.state.start, "Unterminated string constant");
} else { } else {
++this.state.pos; ++this.state.pos;
} }
@ -1145,7 +1177,7 @@ export default class Tokenizer extends LocationParser {
containsInvalid = false; containsInvalid = false;
for (;;) { for (;;) {
if (this.state.pos >= this.length) { if (this.state.pos >= this.length) {
this.raise(this.state.start, "Unterminated template"); throw this.raise(this.state.start, "Unterminated template");
} }
const ch = this.input.charCodeAt(this.state.pos); const ch = this.input.charCodeAt(this.state.pos);
if ( if (
@ -1214,7 +1246,7 @@ export default class Tokenizer extends LocationParser {
case charCodes.lowercaseR: case charCodes.lowercaseR:
return "\r"; return "\r";
case charCodes.lowercaseX: { case charCodes.lowercaseX: {
const code = this.readHexChar(2, throwOnInvalid); const code = this.readHexChar(2, false, throwOnInvalid);
return code === null ? null : String.fromCharCode(code); return code === null ? null : String.fromCharCode(code);
} }
case charCodes.lowercaseU: { case charCodes.lowercaseU: {
@ -1288,9 +1320,13 @@ export default class Tokenizer extends LocationParser {
// Used to read character escape sequences ('\x', '\u'). // Used to read character escape sequences ('\x', '\u').
readHexChar(len: number, throwOnInvalid: boolean): number | null { readHexChar(
len: number,
forceLen: boolean,
throwOnInvalid: boolean,
): number | null {
const codePos = this.state.pos; const codePos = this.state.pos;
const n = this.readInt(16, len, false); const n = this.readInt(16, len, forceLen, false);
if (n === null) { if (n === null) {
if (throwOnInvalid) { if (throwOnInvalid) {
this.raise(codePos, "Bad character escape sequence"); this.raise(codePos, "Bad character escape sequence");
@ -1333,20 +1369,18 @@ export default class Tokenizer extends LocationParser {
this.state.pos, this.state.pos,
"Expecting Unicode escape sequence \\uXXXX", "Expecting Unicode escape sequence \\uXXXX",
); );
continue;
} }
++this.state.pos; ++this.state.pos;
const esc = this.readCodePoint(true); const esc = this.readCodePoint(true);
if (esc !== null) {
if (!identifierCheck(esc)) {
this.raise(escStart, "Invalid Unicode escape");
}
if ( word += String.fromCodePoint(esc);
// $FlowFixMe (thinks esc may be null, but throwOnInvalid is true)
!identifierCheck(esc, true)
) {
this.raise(escStart, "Invalid Unicode escape");
} }
// $FlowFixMe
word += String.fromCodePoint(esc);
chunkStart = this.state.pos; chunkStart = this.state.pos;
} else { } else {
break; break;
@ -1364,7 +1398,7 @@ export default class Tokenizer extends LocationParser {
readWord(): void { readWord(): void {
const word = this.readWord1(); const word = this.readWord1();
const type = (!this.state.containsEsc && keywordTypes.get(word)) || tt.name; const type = keywordTypes.get(word) || tt.name;
// Allow @@iterator and @@asyncIterator as a identifier only inside type // Allow @@iterator and @@asyncIterator as a identifier only inside type
if ( if (
@ -1377,6 +1411,13 @@ export default class Tokenizer extends LocationParser {
this.finishToken(type, word); this.finishToken(type, word);
} }
checkKeywordEscapes(): void {
const kw = this.state.type.keyword;
if (kw && this.state.containsEsc) {
this.raise(this.state.start, `Escape sequence in keyword ${kw}`);
}
}
braceIsBlock(prevType: TokenType): boolean { braceIsBlock(prevType: TokenType): boolean {
const parent = this.curContext(); const parent = this.curContext();
if (parent === ct.functionExpression || parent === ct.functionStatement) { if (parent === ct.functionExpression || parent === ct.functionStatement) {

View File

@ -38,6 +38,8 @@ export default class State {
this.startLoc = this.endLoc = this.curPosition(); this.startLoc = this.endLoc = this.curPosition();
} }
errors: SyntaxError[] = [];
// Used to signify the start of a potential arrow function // Used to signify the start of a potential arrow function
potentialArrowAt: number = -1; potentialArrowAt: number = -1;

View File

@ -21,9 +21,7 @@ const reservedWords = {
}; };
const reservedWordsStrictSet = new Set(reservedWords.strict); const reservedWordsStrictSet = new Set(reservedWords.strict);
const reservedWordsStrictBindSet = new Set( const reservedWordsStrictBindSet = new Set(reservedWords.strictBind);
reservedWords.strict.concat(reservedWords.strictBind),
);
/** /**
* Checks if word is a reserved word in non-strict mode * Checks if word is a reserved word in non-strict mode
@ -41,6 +39,14 @@ export function isStrictReservedWord(word: string, inModule: boolean): boolean {
return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word); return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);
} }
/**
* Checks if word is a reserved word in binding strict mode, but it is allowed as
* a normal identifier.
*/
export function isStrictBindOnlyReservedWord(word: string): boolean {
return reservedWordsStrictBindSet.has(word);
}
/** /**
* Checks if word is a reserved word in binding strict mode * Checks if word is a reserved word in binding strict mode
* *
@ -50,7 +56,9 @@ export function isStrictBindReservedWord(
word: string, word: string,
inModule: boolean, inModule: boolean,
): boolean { ): boolean {
return isReservedWord(word, inModule) || reservedWordsStrictBindSet.has(word); return (
isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word)
);
} }
export function isKeyword(word: string): boolean { export function isKeyword(word: string): boolean {

View File

@ -1,3 +0,0 @@
{
"throws": "Illegal 'use strict' directive in function with non-simple parameter list (1:0)"
}

View File

@ -0,0 +1,128 @@
{
"type": "FunctionExpression",
"start": 0,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 40
}
},
"id": null,
"generator": false,
"async": false,
"params": [
{
"type": "AssignmentPattern",
"start": 10,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 23
}
},
"left": {
"type": "Identifier",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "a"
},
"name": "a"
},
"right": {
"type": "StringLiteral",
"start": 14,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 23
}
},
"extra": {
"rawValue": "default",
"raw": "\"default\""
},
"value": "default"
}
}
],
"body": {
"type": "BlockStatement",
"start": 25,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 25
},
"end": {
"line": 1,
"column": 40
}
},
"body": [],
"directives": [
{
"type": "Directive",
"start": 26,
"end": 39,
"loc": {
"start": {
"line": 1,
"column": 26
},
"end": {
"line": 1,
"column": 39
}
},
"value": {
"type": "DirectiveLiteral",
"start": 26,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 26
},
"end": {
"line": 1,
"column": 38
}
},
"value": "use strict",
"extra": {
"raw": "\"use strict\"",
"rawValue": "use strict"
}
}
}
]
},
"errors": [
"SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list (1:0)"
]
}

View File

@ -1,4 +1,3 @@
{ {
"strictMode": true, "strictMode": true
"throws": "Unexpected reserved word 'public' (2:0)" }
}

View File

@ -0,0 +1,20 @@
{
"type": "Identifier",
"start": 1,
"end": 7,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 6
},
"identifierName": "public"
},
"name": "public",
"errors": [
"SyntaxError: Unexpected reserved word 'public' (2:0)"
]
}

View File

@ -1,3 +0,0 @@
{
"throws": "In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement (1:10)"
}

View File

@ -0,0 +1,125 @@
{
"type": "File",
"start": 0,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 26
}
},
"errors": [
"SyntaxError: In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement (1:10)"
],
"program": {
"type": "Program",
"start": 0,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 26
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "WhileStatement",
"start": 0,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 26
}
},
"test": {
"type": "NumericLiteral",
"start": 7,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 8
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"body": {
"type": "FunctionDeclaration",
"start": 10,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 26
}
},
"id": {
"type": "Identifier",
"start": 19,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 22
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 24,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 24
},
"end": {
"line": 1,
"column": 26
}
},
"body": [],
"directives": []
}
}
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement (1:20)"
}

View File

@ -0,0 +1,189 @@
{
"type": "File",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"errors": [
"SyntaxError: In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement (1:20)"
],
"program": {
"type": "Program",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "WhileStatement",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"test": {
"type": "NumericLiteral",
"start": 7,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 8
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
},
"body": {
"type": "LabeledStatement",
"start": 10,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 36
}
},
"body": {
"type": "LabeledStatement",
"start": 15,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 36
}
},
"body": {
"type": "FunctionDeclaration",
"start": 20,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 36
}
},
"id": {
"type": "Identifier",
"start": 29,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 29
},
"end": {
"line": 1,
"column": 32
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 34,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 34
},
"end": {
"line": 1,
"column": 36
}
},
"body": [],
"directives": []
}
},
"label": {
"type": "Identifier",
"start": 15,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 18
},
"identifierName": "bar"
},
"name": "bar"
}
},
"label": {
"type": "Identifier",
"start": 10,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 13
},
"identifierName": "foo"
},
"name": "foo"
}
}
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Unexpected keyword 'break' (2:2)"
}

View File

@ -0,0 +1,160 @@
{
"type": "File",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 2
}
},
"errors": [
"SyntaxError: Unexpected keyword 'break' (2:2)"
],
"program": {
"type": "Program",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 2
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 2
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 3,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
},
"identifierName": "a"
},
"name": "a"
},
"init": {
"type": "ObjectExpression",
"start": 8,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 3,
"column": 1
}
},
"properties": [
{
"type": "ObjectProperty",
"start": 12,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 12
}
},
"method": false,
"key": {
"type": "Identifier",
"start": 12,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 12
},
"identifierName": "break"
},
"name": "break"
},
"computed": false,
"shorthand": true,
"value": {
"type": "Identifier",
"start": 12,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 12
},
"identifierName": "break"
},
"name": "break"
},
"extra": {
"shorthand": true
}
}
]
}
}
],
"kind": "var"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Invalid escape sequence in template (1:2)"
}

View File

@ -0,0 +1,91 @@
{
"type": "File",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"errors": [
"SyntaxError: Invalid escape sequence in template (1:2)"
],
"program": {
"type": "Program",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"expression": {
"type": "TemplateLiteral",
"start": 0,
"end": 4,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 4
}
},
"expressions": [],
"quasis": [
{
"type": "TemplateElement",
"start": 1,
"end": 3,
"loc": {
"start": {
"line": 1,
"column": 1
},
"end": {
"line": 1,
"column": 3
}
},
"value": {
"raw": "\\8",
"cooked": null
},
"tail": true
}
]
}
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Invalid escape sequence in template (1:2)"
}

View File

@ -0,0 +1,91 @@
{
"type": "File",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"errors": [
"SyntaxError: Invalid escape sequence in template (1:2)"
],
"program": {
"type": "Program",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 5
}
},
"expression": {
"type": "TemplateLiteral",
"start": 0,
"end": 4,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 4
}
},
"expressions": [],
"quasis": [
{
"type": "TemplateElement",
"start": 1,
"end": 3,
"loc": {
"start": {
"line": 1,
"column": 1
},
"end": {
"line": 1,
"column": 3
}
},
"value": {
"raw": "\\9",
"cooked": null
},
"tail": true
}
]
}
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Legacy octal literals are not allowed in strict mode (1:0)" }
}

View File

@ -0,0 +1,73 @@
{
"type": "File",
"start": 0,
"end": 4,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 4
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:0)"
],
"program": {
"type": "Program",
"start": 0,
"end": 4,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 4
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 4,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 4
}
},
"expression": {
"type": "NumericLiteral",
"start": 0,
"end": 4,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 4
}
},
"extra": {
"rawValue": 9.5,
"raw": "09.5"
},
"value": 9.5
}
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (4:6)"
}

View File

@ -0,0 +1,247 @@
{
"type": "File",
"start": 0,
"end": 44,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (4:6)"
],
"program": {
"type": "Program",
"start": 0,
"end": 44,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 44,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 1
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 4,
"end": 12,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 10
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 8,
"end": 11,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 9
}
},
"id": {
"type": "Identifier",
"start": 8,
"end": 11,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 9
},
"identifierName": "bar"
},
"name": "bar"
},
"init": null
}
],
"kind": "let"
},
{
"type": "VariableDeclaration",
"start": 15,
"end": 27,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 14
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 19,
"end": 26,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 13
}
},
"id": {
"type": "Identifier",
"start": 19,
"end": 22,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 25,
"end": 26,
"loc": {
"start": {
"line": 3,
"column": 12
},
"end": {
"line": 3,
"column": 13
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "var"
},
{
"type": "VariableDeclaration",
"start": 30,
"end": 42,
"loc": {
"start": {
"line": 4,
"column": 2
},
"end": {
"line": 4,
"column": 14
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 34,
"end": 41,
"loc": {
"start": {
"line": 4,
"column": 6
},
"end": {
"line": 4,
"column": 13
}
},
"id": {
"type": "Identifier",
"start": 34,
"end": 37,
"loc": {
"start": {
"line": 4,
"column": 6
},
"end": {
"line": 4,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 40,
"end": 41,
"loc": {
"start": {
"line": 4,
"column": 12
},
"end": {
"line": 4,
"column": 13
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "let"
}
],
"directives": []
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (3:4)"
}

View File

@ -0,0 +1,229 @@
{
"type": "File",
"start": 0,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (3:4)"
],
"program": {
"type": "Program",
"start": 0,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 8
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 7
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 7
},
"identifierName": "bar"
},
"name": "bar"
},
"init": null
}
],
"kind": "let"
},
{
"type": "VariableDeclaration",
"start": 9,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 12
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 13,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 11
}
},
"id": {
"type": "Identifier",
"start": 13,
"end": 16,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 7
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 11
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "var"
},
{
"type": "VariableDeclaration",
"start": 22,
"end": 34,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 26,
"end": 33,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 3,
"column": 11
}
},
"id": {
"type": "Identifier",
"start": 26,
"end": 29,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 3,
"column": 7
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 32,
"end": 33,
"loc": {
"start": {
"line": 3,
"column": 10
},
"end": {
"line": 3,
"column": 11
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "let"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (4:6)"
}

View File

@ -0,0 +1,247 @@
{
"type": "File",
"start": 0,
"end": 44,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (4:6)"
],
"program": {
"type": "Program",
"start": 0,
"end": 44,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 44,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 1
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 4,
"end": 12,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 10
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 8,
"end": 11,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 9
}
},
"id": {
"type": "Identifier",
"start": 8,
"end": 11,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 9
},
"identifierName": "bar"
},
"name": "bar"
},
"init": null
}
],
"kind": "let"
},
{
"type": "VariableDeclaration",
"start": 15,
"end": 27,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 14
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 19,
"end": 26,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 13
}
},
"id": {
"type": "Identifier",
"start": 19,
"end": 22,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 25,
"end": 26,
"loc": {
"start": {
"line": 3,
"column": 12
},
"end": {
"line": 3,
"column": 13
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "let"
},
{
"type": "VariableDeclaration",
"start": 30,
"end": 42,
"loc": {
"start": {
"line": 4,
"column": 2
},
"end": {
"line": 4,
"column": 14
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 34,
"end": 41,
"loc": {
"start": {
"line": 4,
"column": 6
},
"end": {
"line": 4,
"column": 13
}
},
"id": {
"type": "Identifier",
"start": 34,
"end": 37,
"loc": {
"start": {
"line": 4,
"column": 6
},
"end": {
"line": 4,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 40,
"end": 41,
"loc": {
"start": {
"line": 4,
"column": 12
},
"end": {
"line": 4,
"column": 13
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "var"
}
],
"directives": []
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (3:4)"
}

View File

@ -0,0 +1,229 @@
{
"type": "File",
"start": 0,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (3:4)"
],
"program": {
"type": "Program",
"start": 0,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 8
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 7
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 7
},
"identifierName": "bar"
},
"name": "bar"
},
"init": null
}
],
"kind": "let"
},
{
"type": "VariableDeclaration",
"start": 9,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 12
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 13,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 11
}
},
"id": {
"type": "Identifier",
"start": 13,
"end": 16,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 7
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 11
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "let"
},
{
"type": "VariableDeclaration",
"start": 22,
"end": 34,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 26,
"end": 33,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 3,
"column": 11
}
},
"id": {
"type": "Identifier",
"start": 26,
"end": 29,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 3,
"column": 7
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 32,
"end": 33,
"loc": {
"start": {
"line": 3,
"column": 10
},
"end": {
"line": 3,
"column": 11
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "var"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (2:15)"
}

View File

@ -0,0 +1,154 @@
{
"type": "File",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (2:15)"
],
"program": {
"type": "Program",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "TryStatement",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"block": {
"type": "BlockStatement",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 2,
"column": 1
}
},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start": 8,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 3,
"column": 1
}
},
"param": {
"type": "ArrayPattern",
"start": 15,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 19
}
},
"elements": [
{
"type": "Identifier",
"start": 16,
"end": 19,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 13
},
"identifierName": "foo"
},
"name": "foo"
},
{
"type": "Identifier",
"start": 21,
"end": 24,
"loc": {
"start": {
"line": 2,
"column": 15
},
"end": {
"line": 2,
"column": 18
},
"identifierName": "foo"
},
"name": "foo"
}
]
},
"body": {
"type": "BlockStatement",
"start": 27,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 21
},
"end": {
"line": 3,
"column": 1
}
},
"body": [],
"directives": []
}
},
"finalizer": null
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (1:35)"
}

View File

@ -0,0 +1,222 @@
{
"type": "File",
"start": 0,
"end": 39,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 39
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (1:35)"
],
"program": {
"type": "Program",
"start": 0,
"end": 39,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 39
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 8
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 7
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 7
},
"identifierName": "foo"
},
"name": "foo"
},
"init": null
}
],
"kind": "let"
},
{
"type": "TryStatement",
"start": 9,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 30
}
},
"block": {
"type": "BlockStatement",
"start": 13,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 15
}
},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start": 16,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 16
},
"end": {
"line": 1,
"column": 30
}
},
"param": {
"type": "Identifier",
"start": 23,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 23
},
"end": {
"line": 1,
"column": 26
},
"identifierName": "foo"
},
"name": "foo"
},
"body": {
"type": "BlockStatement",
"start": 28,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 28
},
"end": {
"line": 1,
"column": 30
}
},
"body": [],
"directives": []
}
},
"finalizer": null
},
{
"type": "VariableDeclaration",
"start": 31,
"end": 39,
"loc": {
"start": {
"line": 1,
"column": 31
},
"end": {
"line": 1,
"column": 39
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 35,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 35
},
"end": {
"line": 1,
"column": 38
}
},
"id": {
"type": "Identifier",
"start": 35,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 35
},
"end": {
"line": 1,
"column": 38
},
"identifierName": "foo"
},
"name": "foo"
},
"init": null
}
],
"kind": "let"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (3:11)"
}

View File

@ -0,0 +1,173 @@
{
"type": "File",
"start": 0,
"end": 43,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (3:11)"
],
"program": {
"type": "Program",
"start": 0,
"end": 43,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "TryStatement",
"start": 0,
"end": 43,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"block": {
"type": "BlockStatement",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 2,
"column": 1
}
},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start": 8,
"end": 43,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 4,
"column": 1
}
},
"param": {
"type": "Identifier",
"start": 15,
"end": 18,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
},
"body": {
"type": "BlockStatement",
"start": 20,
"end": 43,
"loc": {
"start": {
"line": 2,
"column": 14
},
"end": {
"line": 4,
"column": 1
}
},
"body": [
{
"type": "FunctionDeclaration",
"start": 24,
"end": 41,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 19
}
},
"id": {
"type": "Identifier",
"start": 33,
"end": 36,
"loc": {
"start": {
"line": 3,
"column": 11
},
"end": {
"line": 3,
"column": 14
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 39,
"end": 41,
"loc": {
"start": {
"line": 3,
"column": 17
},
"end": {
"line": 3,
"column": 19
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
},
"finalizer": null
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (3:6)"
}

View File

@ -0,0 +1,172 @@
{
"type": "File",
"start": 0,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (3:6)"
],
"program": {
"type": "Program",
"start": 0,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "TryStatement",
"start": 0,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"block": {
"type": "BlockStatement",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 2,
"column": 1
}
},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start": 8,
"end": 34,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 4,
"column": 1
}
},
"param": {
"type": "Identifier",
"start": 15,
"end": 18,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
},
"body": {
"type": "BlockStatement",
"start": 20,
"end": 34,
"loc": {
"start": {
"line": 2,
"column": 14
},
"end": {
"line": 4,
"column": 1
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 24,
"end": 32,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 10
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 28,
"end": 31,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
}
},
"id": {
"type": "Identifier",
"start": 28,
"end": 31,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": null
}
],
"kind": "let"
}
],
"directives": []
}
},
"finalizer": null
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (2:28)"
}

View File

@ -0,0 +1,293 @@
{
"type": "File",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (2:28)"
],
"program": {
"type": "Program",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "TryStatement",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"block": {
"type": "BlockStatement",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 2,
"column": 1
}
},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start": 8,
"end": 47,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 3,
"column": 1
}
},
"param": {
"type": "ObjectPattern",
"start": 15,
"end": 42,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 36
}
},
"properties": [
{
"type": "ObjectProperty",
"start": 17,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 17
}
},
"method": false,
"key": {
"type": "Identifier",
"start": 17,
"end": 18,
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 12
},
"identifierName": "a"
},
"name": "a"
},
"computed": false,
"shorthand": false,
"value": {
"type": "Identifier",
"start": 20,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 14
},
"end": {
"line": 2,
"column": 17
},
"identifierName": "foo"
},
"name": "foo"
}
},
{
"type": "ObjectProperty",
"start": 25,
"end": 40,
"loc": {
"start": {
"line": 2,
"column": 19
},
"end": {
"line": 2,
"column": 34
}
},
"method": false,
"key": {
"type": "Identifier",
"start": 25,
"end": 26,
"loc": {
"start": {
"line": 2,
"column": 19
},
"end": {
"line": 2,
"column": 20
},
"identifierName": "b"
},
"name": "b"
},
"computed": false,
"shorthand": false,
"value": {
"type": "ObjectPattern",
"start": 28,
"end": 40,
"loc": {
"start": {
"line": 2,
"column": 22
},
"end": {
"line": 2,
"column": 34
}
},
"properties": [
{
"type": "ObjectProperty",
"start": 30,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 24
},
"end": {
"line": 2,
"column": 32
}
},
"method": false,
"key": {
"type": "Identifier",
"start": 30,
"end": 31,
"loc": {
"start": {
"line": 2,
"column": 24
},
"end": {
"line": 2,
"column": 25
},
"identifierName": "c"
},
"name": "c"
},
"computed": false,
"shorthand": false,
"value": {
"type": "ArrayPattern",
"start": 33,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 27
},
"end": {
"line": 2,
"column": 32
}
},
"elements": [
{
"type": "Identifier",
"start": 34,
"end": 37,
"loc": {
"start": {
"line": 2,
"column": 28
},
"end": {
"line": 2,
"column": 31
},
"identifierName": "foo"
},
"name": "foo"
}
]
}
}
]
}
}
]
},
"body": {
"type": "BlockStatement",
"start": 44,
"end": 47,
"loc": {
"start": {
"line": 2,
"column": 38
},
"end": {
"line": 3,
"column": 1
}
},
"body": [],
"directives": []
}
},
"finalizer": null
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (3:6)"
}

View File

@ -0,0 +1,189 @@
{
"type": "File",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (3:6)"
],
"program": {
"type": "Program",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "TryStatement",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"block": {
"type": "BlockStatement",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 2,
"column": 1
}
},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start": 8,
"end": 36,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 4,
"column": 1
}
},
"param": {
"type": "ArrayPattern",
"start": 15,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 14
}
},
"elements": [
{
"type": "Identifier",
"start": 16,
"end": 19,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 13
},
"identifierName": "foo"
},
"name": "foo"
}
]
},
"body": {
"type": "BlockStatement",
"start": 22,
"end": 36,
"loc": {
"start": {
"line": 2,
"column": 16
},
"end": {
"line": 4,
"column": 1
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 26,
"end": 34,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 10
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 30,
"end": 33,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
}
},
"id": {
"type": "Identifier",
"start": 30,
"end": 33,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": null
}
],
"kind": "var"
}
],
"directives": []
}
},
"finalizer": null
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (3:6)"
}

View File

@ -0,0 +1,227 @@
{
"type": "File",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (3:6)"
],
"program": {
"type": "Program",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "TryStatement",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"block": {
"type": "BlockStatement",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 2,
"column": 1
}
},
"body": [],
"directives": []
},
"handler": {
"type": "CatchClause",
"start": 8,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 4,
"column": 1
}
},
"param": {
"type": "ObjectPattern",
"start": 15,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 16
}
},
"properties": [
{
"type": "ObjectProperty",
"start": 17,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 14
}
},
"method": false,
"key": {
"type": "Identifier",
"start": 17,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 14
},
"identifierName": "foo"
},
"name": "foo"
},
"computed": false,
"shorthand": true,
"value": {
"type": "Identifier",
"start": 17,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 14
},
"identifierName": "foo"
},
"name": "foo"
},
"extra": {
"shorthand": true
}
}
]
},
"body": {
"type": "BlockStatement",
"start": 24,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 18
},
"end": {
"line": 4,
"column": 1
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 28,
"end": 36,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 10
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 32,
"end": 35,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
}
},
"id": {
"type": "Identifier",
"start": 32,
"end": 35,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": null
}
],
"kind": "var"
}
],
"directives": []
}
},
"finalizer": null
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (2:6)"
}

View File

@ -0,0 +1,166 @@
{
"type": "File",
"start": 0,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 13
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (2:6)"
],
"program": {
"type": "Program",
"start": 0,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 13
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 10,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 12
}
},
"body": []
}
},
{
"type": "EmptyStatement",
"start": 12,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 13
}
}
},
{
"type": "ClassDeclaration",
"start": 14,
"end": 26,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 20,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 24,
"end": 26,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 12
}
},
"body": []
}
},
{
"type": "EmptyStatement",
"start": 26,
"end": 27,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 13
}
}
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (2:6)"
}

View File

@ -0,0 +1,172 @@
{
"type": "File",
"start": 0,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (2:6)"
],
"program": {
"type": "Program",
"start": 0,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 10,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 12
}
},
"body": []
}
},
{
"type": "EmptyStatement",
"start": 12,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 13
}
}
},
{
"type": "VariableDeclaration",
"start": 14,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 20,
"end": 27,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 13
}
},
"id": {
"type": "Identifier",
"start": 20,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 26,
"end": 27,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 13
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "const"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (2:9)"
}

View File

@ -0,0 +1,169 @@
{
"type": "File",
"start": 0,
"end": 33,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 19
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (2:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 33,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 19
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 10,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 12
}
},
"body": []
}
},
{
"type": "EmptyStatement",
"start": 12,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 13
}
}
},
{
"type": "FunctionDeclaration",
"start": 14,
"end": 32,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 18
}
},
"id": {
"type": "Identifier",
"start": 23,
"end": 26,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 30,
"end": 32,
"loc": {
"start": {
"line": 2,
"column": 16
},
"end": {
"line": 2,
"column": 18
}
},
"body": [],
"directives": []
}
},
{
"type": "EmptyStatement",
"start": 32,
"end": 33,
"loc": {
"start": {
"line": 2,
"column": 18
},
"end": {
"line": 2,
"column": 19
}
}
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (2:4)"
}

View File

@ -0,0 +1,172 @@
{
"type": "File",
"start": 0,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 12
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (2:4)"
],
"program": {
"type": "Program",
"start": 0,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 12
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 10,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 12
}
},
"body": []
}
},
{
"type": "EmptyStatement",
"start": 12,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 13
}
}
},
{
"type": "VariableDeclaration",
"start": 14,
"end": 26,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 12
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 18,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 11
}
},
"id": {
"type": "Identifier",
"start": 18,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 7
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 24,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 11
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "let"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (2:4)"
}

View File

@ -0,0 +1,153 @@
{
"type": "File",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 8
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (2:4)"
],
"program": {
"type": "Program",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 8
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 10,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 12
}
},
"body": []
}
},
{
"type": "EmptyStatement",
"start": 12,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 13
}
}
},
{
"type": "VariableDeclaration",
"start": 14,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 8
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 18,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 7
}
},
"id": {
"type": "Identifier",
"start": 18,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 7
},
"identifierName": "foo"
},
"name": "foo"
},
"init": null
}
],
"kind": "var"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (1:13)"
}

View File

@ -0,0 +1,160 @@
{
"type": "File",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (1:13)"
],
"program": {
"type": "Program",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 11
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 9,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
},
{
"type": "VariableDeclarator",
"start": 13,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 18
}
},
"id": {
"type": "Identifier",
"start": 13,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 16
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 17,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 18
}
},
"extra": {
"rawValue": 2,
"raw": "2"
},
"value": 2
}
}
],
"kind": "const"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'f' has already been declared (1:28)"
}

View File

@ -0,0 +1,160 @@
{
"type": "File",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"errors": [
"SyntaxError: Identifier 'f' has already been declared (1:28)"
],
"program": {
"type": "Program",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"body": [
{
"type": "FunctionDeclaration",
"start": 2,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 17
}
},
"id": {
"type": "Identifier",
"start": 11,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 12
},
"identifierName": "f"
},
"name": "f"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 15,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 17
}
},
"body": [],
"directives": []
}
},
{
"type": "FunctionDeclaration",
"start": 18,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 18
},
"end": {
"line": 1,
"column": 34
}
},
"id": {
"type": "Identifier",
"start": 28,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 28
},
"end": {
"line": 1,
"column": 29
},
"identifierName": "f"
},
"name": "f"
},
"generator": true,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 32,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 32
},
"end": {
"line": 1,
"column": 34
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Identifier 'foo' has already been declared (1:29)" }
}

View File

@ -0,0 +1,160 @@
{
"type": "File",
"start": 0,
"end": 39,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 39
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (1:29)"
],
"program": {
"type": "Program",
"start": 0,
"end": 39,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 39
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 39,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 39
}
},
"body": [
{
"type": "FunctionDeclaration",
"start": 2,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 19
}
},
"id": {
"type": "Identifier",
"start": 11,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 14
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 17,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 19
}
},
"body": [],
"directives": []
}
},
{
"type": "FunctionDeclaration",
"start": 20,
"end": 37,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 37
}
},
"id": {
"type": "Identifier",
"start": 29,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 29
},
"end": {
"line": 1,
"column": 32
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 35,
"end": 37,
"loc": {
"start": {
"line": 1,
"column": 35
},
"end": {
"line": 1,
"column": 37
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Identifier 'foo' has already been declared (2:9)" }
}

View File

@ -0,0 +1,142 @@
{
"type": "File",
"start": 0,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 17
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (2:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 17
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "FunctionDeclaration",
"start": 0,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 17
}
},
"id": {
"type": "Identifier",
"start": 9,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 15,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 17
}
},
"body": [],
"directives": []
}
},
{
"type": "FunctionDeclaration",
"start": 18,
"end": 35,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 17
}
},
"id": {
"type": "Identifier",
"start": 27,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 33,
"end": 35,
"loc": {
"start": {
"line": 2,
"column": 15
},
"end": {
"line": 2,
"column": 17
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (3:6)"
}

View File

@ -0,0 +1,178 @@
{
"type": "File",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (3:6)"
],
"program": {
"type": "Program",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 38,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"body": [
{
"type": "FunctionDeclaration",
"start": 4,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 19
}
},
"id": {
"type": "Identifier",
"start": 13,
"end": 16,
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 14
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 19,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 17
},
"end": {
"line": 2,
"column": 19
}
},
"body": [],
"directives": []
}
},
{
"type": "VariableDeclaration",
"start": 24,
"end": 36,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 14
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 28,
"end": 35,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 13
}
},
"id": {
"type": "Identifier",
"start": 28,
"end": 31,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "foo"
},
"name": "foo"
},
"init": {
"type": "NumericLiteral",
"start": 34,
"end": 35,
"loc": {
"start": {
"line": 3,
"column": 12
},
"end": {
"line": 3,
"column": 13
}
},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
],
"kind": "var"
}
],
"directives": []
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'f' has already been declared (1:28)"
}

View File

@ -0,0 +1,160 @@
{
"type": "File",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"errors": [
"SyntaxError: Identifier 'f' has already been declared (1:28)"
],
"program": {
"type": "Program",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 36
}
},
"body": [
{
"type": "FunctionDeclaration",
"start": 2,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 18
}
},
"id": {
"type": "Identifier",
"start": 12,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 13
},
"identifierName": "f"
},
"name": "f"
},
"generator": true,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 16,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 16
},
"end": {
"line": 1,
"column": 18
}
},
"body": [],
"directives": []
}
},
{
"type": "FunctionDeclaration",
"start": 19,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 34
}
},
"id": {
"type": "Identifier",
"start": 28,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 28
},
"end": {
"line": 1,
"column": 29
},
"identifierName": "f"
},
"name": "f"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 32,
"end": 34,
"loc": {
"start": {
"line": 1,
"column": 32
},
"end": {
"line": 1,
"column": 34
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'foo' has already been declared (1:9)"
}

View File

@ -0,0 +1,122 @@
{
"type": "File",
"start": 0,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 13
}
},
"errors": [
"SyntaxError: Identifier 'foo' has already been declared (1:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 13
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 13
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 7
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 7
},
"identifierName": "foo"
},
"name": "foo"
},
"init": null
},
{
"type": "VariableDeclarator",
"start": 9,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 9,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
},
"init": null
}
],
"kind": "let"
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'a' has already been declared (3:8)"
}

View File

@ -0,0 +1,176 @@
{
"type": "File",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'a' has already been declared (3:8)"
],
"program": {
"type": "Program",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 4,
"end": 10,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 8
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 8,
"end": 9,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 7
}
},
"id": {
"type": "Identifier",
"start": 8,
"end": 9,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 7
},
"identifierName": "a"
},
"name": "a"
},
"init": null
}
],
"kind": "let"
},
{
"type": "BlockStatement",
"start": 13,
"end": 23,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 12
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 15,
"end": 21,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 3,
"column": 10
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 3,
"column": 8
},
"end": {
"line": 3,
"column": 9
}
},
"id": {
"type": "Identifier",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 3,
"column": 8
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "a"
},
"name": "a"
},
"init": null
}
],
"kind": "var"
}
],
"directives": []
}
],
"directives": []
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Identifier 'i' has already been declared (2:8)"
}

View File

@ -0,0 +1,194 @@
{
"type": "File",
"start": 0,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"errors": [
"SyntaxError: Identifier 'i' has already been declared (2:8)"
],
"program": {
"type": "Program",
"start": 0,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ForStatement",
"start": 0,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"init": {
"type": "VariableDeclaration",
"start": 5,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 14
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 9,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "i"
},
"name": "i"
},
"init": {
"type": "NumericLiteral",
"start": 13,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 14
}
},
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
}
],
"kind": "let"
},
"test": null,
"update": null,
"body": {
"type": "BlockStatement",
"start": 18,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 18
},
"end": {
"line": 3,
"column": 1
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 24,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 10
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 28,
"end": 29,
"loc": {
"start": {
"line": 2,
"column": 8
},
"end": {
"line": 2,
"column": 9
}
},
"id": {
"type": "Identifier",
"start": 28,
"end": 29,
"loc": {
"start": {
"line": 2,
"column": 8
},
"end": {
"line": 2,
"column": 9
},
"identifierName": "i"
},
"name": "i"
},
"init": null
}
],
"kind": "var"
}
],
"directives": []
}
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Export 'encrypt' is not defined (1:9)" }
}

View File

@ -0,0 +1,106 @@
{
"type": "File",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 30
}
},
"errors": [
"SyntaxError: Export 'encrypt' is not defined (1:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 30
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 30
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 27
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 16
},
"identifierName": "encrypt"
},
"name": "encrypt"
},
"exported": {
"type": "Identifier",
"start": 20,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 27
},
"identifierName": "default"
},
"name": "default"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Export 'encrypt' is not defined (1:9)" }
}

View File

@ -0,0 +1,158 @@
{
"type": "File",
"start": 0,
"end": 52,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 21
}
},
"errors": [
"SyntaxError: Export 'encrypt' is not defined (1:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 52,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 21
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 30
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 27
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 16
},
"identifierName": "encrypt"
},
"name": "encrypt"
},
"exported": {
"type": "Identifier",
"start": 20,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 27
},
"identifierName": "decrypt"
},
"name": "decrypt"
}
}
],
"source": null,
"declaration": null
},
{
"type": "FunctionDeclaration",
"start": 31,
"end": 52,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 21
}
},
"id": {
"type": "Identifier",
"start": 40,
"end": 47,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 16
},
"identifierName": "decrypt"
},
"name": "decrypt"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 50,
"end": 52,
"loc": {
"start": {
"line": 2,
"column": 19
},
"end": {
"line": 2,
"column": 21
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Export 'encrypt' is not defined (4:9)" }
}

View File

@ -0,0 +1,176 @@
{
"type": "File",
"start": 0,
"end": 46,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 18
}
},
"errors": [
"SyntaxError: Export 'encrypt' is not defined (4:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 46,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 18
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 1
}
},
"body": [
{
"type": "FunctionDeclaration",
"start": 4,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 23
}
},
"id": {
"type": "Identifier",
"start": 13,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 18
},
"identifierName": "encrypt"
},
"name": "encrypt"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 23,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 21
},
"end": {
"line": 2,
"column": 23
}
},
"body": [],
"directives": []
}
}
],
"directives": []
},
{
"type": "ExportNamedDeclaration",
"start": 28,
"end": 46,
"loc": {
"start": {
"line": 4,
"column": 0
},
"end": {
"line": 4,
"column": 18
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 37,
"end": 44,
"loc": {
"start": {
"line": 4,
"column": 9
},
"end": {
"line": 4,
"column": 16
}
},
"local": {
"type": "Identifier",
"start": 37,
"end": 44,
"loc": {
"start": {
"line": 4,
"column": 9
},
"end": {
"line": 4,
"column": 16
},
"identifierName": "encrypt"
},
"name": "encrypt"
},
"exported": {
"type": "Identifier",
"start": 37,
"end": 44,
"loc": {
"start": {
"line": 4,
"column": 9
},
"end": {
"line": 4,
"column": 16
},
"identifierName": "encrypt"
},
"name": "encrypt"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Export 'Object' is not defined (1:9)" }
}

View File

@ -0,0 +1,106 @@
{
"type": "File",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"errors": [
"SyntaxError: Export 'Object' is not defined (1:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 25
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 22
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 15
},
"identifierName": "Object"
},
"name": "Object"
},
"exported": {
"type": "Identifier",
"start": 19,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 22
},
"identifierName": "Obj"
},
"name": "Obj"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Export 'Object' is not defined (1:9)" }
}

View File

@ -0,0 +1,106 @@
{
"type": "File",
"start": 0,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 18
}
},
"errors": [
"SyntaxError: Export 'Object' is not defined (1:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 18
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 18
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 15
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 15
},
"identifierName": "Object"
},
"name": "Object"
},
"exported": {
"type": "Identifier",
"start": 9,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 15
},
"identifierName": "Object"
},
"name": "Object"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "In strict mode code, functions can only be declared at top level or inside a block (2:10)" }
}

View File

@ -0,0 +1,191 @@
{
"type": "File",
"start": 0,
"end": 51,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 31
}
},
"errors": [
"SyntaxError: In strict mode code, functions can only be declared at top level or inside a block (2:10)",
"SyntaxError: Export 'encrypt' is not defined (1:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 51,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 31
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 16
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 16
},
"identifierName": "encrypt"
},
"name": "encrypt"
},
"exported": {
"type": "Identifier",
"start": 9,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 16
},
"identifierName": "encrypt"
},
"name": "encrypt"
}
}
],
"source": null,
"declaration": null
},
{
"type": "IfStatement",
"start": 20,
"end": 51,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 31
}
},
"test": {
"type": "BooleanLiteral",
"start": 24,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 8
}
},
"value": true
},
"consequent": {
"type": "FunctionDeclaration",
"start": 30,
"end": 51,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 31
}
},
"id": {
"type": "Identifier",
"start": 39,
"end": 46,
"loc": {
"start": {
"line": 2,
"column": 19
},
"end": {
"line": 2,
"column": 26
},
"identifierName": "encrypt"
},
"name": "encrypt"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 49,
"end": 51,
"loc": {
"start": {
"line": 2,
"column": 29
},
"end": {
"line": 2,
"column": 31
}
},
"body": [],
"directives": []
}
},
"alternate": null
}
],
"directives": []
}
}

View File

@ -1,4 +1,3 @@
{ {
"sourceType": "module", "sourceType": "module"
"throws": "Export 'encrypt' is not defined (1:9)" }
}

View File

@ -0,0 +1,106 @@
{
"type": "File",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"errors": [
"SyntaxError: Export 'encrypt' is not defined (1:9)"
],
"program": {
"type": "Program",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 16
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 16
},
"identifierName": "encrypt"
},
"name": "encrypt"
},
"exported": {
"type": "Identifier",
"start": 9,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 16
},
"identifierName": "encrypt"
},
"name": "encrypt"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -1,3 +0,0 @@
{
"throws": "Invalid regular expression flag (1:17)"
}

View File

@ -0,0 +1,112 @@
{
"type": "File",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
"errors": [
"SyntaxError: Invalid regular expression flag (1:17)",
"SyntaxError: Invalid regular expression flag (1:19)",
"SyntaxError: Invalid regular expression flag (1:20)",
"SyntaxError: Invalid regular expression flag (1:21)",
"SyntaxError: Invalid regular expression flag (1:22)"
],
"program": {
"type": "Program",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 22
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
},
"identifierName": "x"
},
"name": "x"
},
"init": {
"type": "RegExpLiteral",
"start": 8,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 1,
"column": 22
}
},
"extra": {
"raw": "/[P QR]/\\u0067"
},
"pattern": "[P QR]",
"flags": "\\u0067"
}
}
],
"kind": "var"
}
],
"directives": []
}
}

View File

@ -1,3 +1,3 @@
{ {
"throws": "Invalid number (1:0)" "throws": "Identifier directly after number (1:2)"
} }

View File

@ -1,3 +0,0 @@
{
"throws": "Invalid number (1:0)"
}

View File

@ -0,0 +1,73 @@
{
"type": "File",
"start": 0,
"end": 2,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 2
}
},
"errors": [
"SyntaxError: Invalid number (1:0)"
],
"program": {
"type": "Program",
"start": 0,
"end": 2,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 2
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 2,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 2
}
},
"expression": {
"type": "NumericLiteral",
"start": 0,
"end": 2,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 2
}
},
"extra": {
"rawValue": 3,
"raw": "3e"
},
"value": 3
}
}
],
"directives": []
}
}

Some files were not shown because too many files have changed in this diff Show More