From 5d5cd8612f9b43a862973195d40ee77c0540c563 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Tue, 6 Nov 2018 19:37:24 -0800 Subject: [PATCH] Fix several edge cases with context expression state (#8972) * Fix several edge cases with context expression state * Fix review comments * Remove unused field --- .../babel-parser/src/parser/expression.js | 35 +- packages/babel-parser/src/plugins/flow.js | 11 +- .../babel-parser/src/plugins/jsx/index.js | 16 +- .../babel-parser/src/tokenizer/context.js | 56 +- packages/babel-parser/src/tokenizer/index.js | 36 +- packages/babel-parser/src/tokenizer/types.js | 2 +- .../es2015/for-of/brackets-const/input.js | 1 + .../es2015/for-of/brackets-const/output.json | 194 ++++ .../es2015/for-of/brackets-let/input.js | 1 + .../es2015/for-of/brackets-let/output.json | 194 ++++ .../es2015/for-of/brackets-var/input.js | 1 + .../es2015/for-of/brackets-var/output.json | 194 ++++ .../test/fixtures/es2015/yield/asi2/input.js | 3 + .../fixtures/es2015/yield/asi2/output.json | 172 ++++ .../es2015/yield/yield class/input.js | 1 + .../es2015/yield/yield class/output.json | 152 +++ .../fixtures/jsx/errors/html-comment/input.js | 1 + .../jsx/errors/html-comment/options.json | 4 + .../jsx/errors/html-comment/output.json | 70 ++ .../jsx/regression/issue-8891/input.js | 6 + .../jsx/regression/issue-8891/output.json | 873 ++++++++++++++++++ 21 files changed, 1986 insertions(+), 37 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/es2015/for-of/brackets-const/input.js create mode 100644 packages/babel-parser/test/fixtures/es2015/for-of/brackets-const/output.json create mode 100644 packages/babel-parser/test/fixtures/es2015/for-of/brackets-let/input.js create mode 100644 packages/babel-parser/test/fixtures/es2015/for-of/brackets-let/output.json create mode 100644 packages/babel-parser/test/fixtures/es2015/for-of/brackets-var/input.js create mode 100644 packages/babel-parser/test/fixtures/es2015/for-of/brackets-var/output.json create mode 100644 packages/babel-parser/test/fixtures/es2015/yield/asi2/input.js create mode 100644 packages/babel-parser/test/fixtures/es2015/yield/asi2/output.json create mode 100644 packages/babel-parser/test/fixtures/es2015/yield/yield class/input.js create mode 100644 packages/babel-parser/test/fixtures/es2015/yield/yield class/output.json create mode 100644 packages/babel-parser/test/fixtures/jsx/errors/html-comment/input.js create mode 100644 packages/babel-parser/test/fixtures/jsx/errors/html-comment/options.json create mode 100644 packages/babel-parser/test/fixtures/jsx/errors/html-comment/output.json create mode 100644 packages/babel-parser/test/fixtures/jsx/regression/issue-8891/input.js create mode 100644 packages/babel-parser/test/fixtures/jsx/regression/issue-8891/output.json diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index b51cdcef5d79..60bceba8149f 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -23,6 +23,7 @@ import * as N from "../types"; import LValParser from "./lval"; import { reservedWords } from "../util/identifier"; import type { Pos, Position } from "../util/location"; +import * as charCodes from "charcodes"; export default class ExpressionParser extends LValParser { // Forward-declaration: defined in statement.js @@ -718,6 +719,10 @@ export default class ExpressionParser extends LValParser { // or `{}`. parseExprAtom(refShorthandDefaultPos?: ?Pos): N.Expression { + // If a division operator appears in an expression position, the + // tokenizer got confused, and we force it to read a regexp instead. + if (this.state.type === tt.slash) this.readRegexp(); + const canBeArrow = this.state.potentialArrowAt === this.state.start; let node; @@ -964,7 +969,16 @@ export default class ExpressionParser extends LValParser { parseFunctionExpression(): N.FunctionExpression | N.MetaProperty { const node = this.startNode(); - const meta = this.parseIdentifier(true); + + // We do not do parseIdentifier here because when parseFunctionExpression + // is called we already know that the current token is a "name" with the value "function" + // This will improve perf a tiny little bit as we do not do validation but more importantly + // here is that parseIdentifier will remove an item from the expression stack + // if "function" or "class" is parsed as identifier (in objects e.g.), which should not happen here. + let meta = this.startNode(); + this.next(); + meta = this.createIdentifier(meta, "function"); + if (this.state.inGenerator && this.eat(tt.dot)) { return this.parseMetaProperty(node, meta, "sent"); } @@ -1863,8 +1877,14 @@ export default class ExpressionParser extends LValParser { parseIdentifier(liberal?: boolean): N.Identifier { const node = this.startNode(); const name = this.parseIdentifierName(node.start, liberal); + + return this.createIdentifier(node, name); + } + + createIdentifier(node: N.Identifier, name: string): N.Identifier { node.name = name; node.loc.identifierName = name; + return this.finishNode(node, "Identifier"); } @@ -1884,6 +1904,19 @@ export default class ExpressionParser extends LValParser { name = this.state.value; } else if (this.state.type.keyword) { name = this.state.type.keyword; + + // `class` and `function` keywords push new context into this.context. + // But there is no chance to pop the context if the keyword is consumed + // as an identifier such as a property name. + // If the previous token is a dot, this does not apply because the + // context-managing code already ignored the keyword + if ( + (name === "class" || name === "function") && + (this.state.lastTokEnd !== this.state.lastTokStart + 1 || + this.input.charCodeAt(this.state.lastTokStart) !== charCodes.dot) + ) { + this.state.context.pop(); + } } else { throw this.unexpected(); } diff --git a/packages/babel-parser/src/plugins/flow.js b/packages/babel-parser/src/plugins/flow.js index 617a115579bc..bff354249893 100644 --- a/packages/babel-parser/src/plugins/flow.js +++ b/packages/babel-parser/src/plugins/flow.js @@ -6,6 +6,7 @@ import * as N from "../types"; import type { Options } from "../options"; import type { Pos, Position } from "../util/location"; import type State from "../tokenizer/state"; +import { types as tc } from "../tokenizer/context"; import * as charCodes from "charcodes"; import { isIteratorStart } from "../util/identifier"; @@ -2392,7 +2393,10 @@ export default (superClass: Class): Class => refNeedsArrowPos?: ?Pos, ): N.Expression { let jsxError = null; - if (tt.jsxTagStart && this.match(tt.jsxTagStart)) { + if ( + this.hasPlugin("jsx") && + (this.match(tt.jsxTagStart) || this.isRelational("<")) + ) { const state = this.state.clone(); try { return super.parseMaybeAssign( @@ -2408,7 +2412,10 @@ export default (superClass: Class): Class => // Remove `tc.j_expr` and `tc.j_oTag` from context added // by parsing `jsxTagStart` to stop the JSX plugin from // messing with the tokens - this.state.context.length -= 2; + const cLength = this.state.context.length; + if (this.state.context[cLength - 1] === tc.j_oTag) { + this.state.context.length -= 2; + } jsxError = err; } else { diff --git a/packages/babel-parser/src/plugins/jsx/index.js b/packages/babel-parser/src/plugins/jsx/index.js index 0d32ea98d11f..0271aeffed9d 100644 --- a/packages/babel-parser/src/plugins/jsx/index.js +++ b/packages/babel-parser/src/plugins/jsx/index.js @@ -506,6 +506,15 @@ export default (superClass: Class): Class => return this.parseLiteral(this.state.value, "JSXText"); } else if (this.match(tt.jsxTagStart)) { return this.jsxParseElement(); + } else if ( + this.isRelational("<") && + this.state.input.charCodeAt(this.state.pos) !== + charCodes.exclamationMark + ) { + // 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); + return this.jsxParseElement(); } else { return super.parseExprAtom(refShortHandDefaultPos); } @@ -538,7 +547,12 @@ export default (superClass: Class): Class => } } - if (code === charCodes.lessThan && this.state.exprAllowed) { + if ( + code === charCodes.lessThan && + this.state.exprAllowed && + this.state.input.charCodeAt(this.state.pos + 1) !== + charCodes.exclamationMark + ) { ++this.state.pos; return this.finishToken(tt.jsxTagStart); } diff --git a/packages/babel-parser/src/tokenizer/context.js b/packages/babel-parser/src/tokenizer/context.js index bb0f7b8a20d2..6bb2b9491275 100644 --- a/packages/babel-parser/src/tokenizer/context.js +++ b/packages/babel-parser/src/tokenizer/context.js @@ -12,7 +12,7 @@ export class TokContext { token: string, isExpr?: boolean, preserveSpace?: boolean, - override?: Function, // Takes a Tokenizer as a this-parameter, and returns void. + override?: ?Function, // Takes a Tokenizer as a this-parameter, and returns void. ) { this.token = token; this.isExpr = !!isExpr; @@ -31,11 +31,12 @@ export const types: { } = { braceStatement: new TokContext("{", false), braceExpression: new TokContext("{", true), - templateQuasi: new TokContext("${", true), + templateQuasi: new TokContext("${", false), parenStatement: new TokContext("(", false), parenExpression: new TokContext("(", true), template: new TokContext("`", true, true, p => p.readTmplToken()), functionExpression: new TokContext("function", true), + functionStatement: new TokContext("function", false), }; // Token-specific context update code @@ -46,33 +47,26 @@ tt.parenR.updateContext = tt.braceR.updateContext = function() { return; } - const out = this.state.context.pop(); - if ( - out === types.braceStatement && - this.curContext() === types.functionExpression - ) { - this.state.context.pop(); - this.state.exprAllowed = false; - } else if (out === types.templateQuasi) { - this.state.exprAllowed = true; - } else { - this.state.exprAllowed = !out.isExpr; + let out = this.state.context.pop(); + if (out === types.braceStatement && this.curContext().token === "function") { + out = this.state.context.pop(); } + + this.state.exprAllowed = !out.isExpr; }; tt.name.updateContext = function(prevType) { - if (this.state.value === "of" && this.curContext() === types.parenStatement) { - this.state.exprAllowed = !prevType.beforeExpr; - return; - } - - this.state.exprAllowed = false; - - if (prevType === tt._let || prevType === tt._const || prevType === tt._var) { - if (lineBreak.test(this.input.slice(this.state.end))) { - this.state.exprAllowed = true; + let allowed = false; + if (prevType !== tt.dot) { + if ( + (this.state.value === "of" && !this.state.exprAllowed) || + (this.state.value === "yield" && this.state.inGenerator) + ) { + allowed = true; } } + this.state.exprAllowed = allowed; + if (this.state.isIterator) { this.state.isIterator = false; } @@ -107,8 +101,22 @@ tt.incDec.updateContext = function() { }; tt._function.updateContext = tt._class.updateContext = function(prevType) { - if (this.state.exprAllowed && !this.braceIsBlock(prevType)) { + if ( + prevType.beforeExpr && + prevType !== tt.semi && + prevType !== tt._else && + !( + prevType === tt._return && + lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start)) + ) && + !( + (prevType === tt.colon || prevType === tt.braceL) && + this.curContext() === types.b_stat + ) + ) { this.state.context.push(types.functionExpression); + } else { + this.state.context.push(types.functionStatement); } this.state.exprAllowed = false; diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index 150ea892527b..33a272e7dcf0 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -1324,14 +1324,25 @@ export default class Tokenizer extends LocationParser { } braceIsBlock(prevType: TokenType): boolean { - if (prevType === tt.colon) { - const parent = this.curContext(); - if (parent === ct.braceStatement || parent === ct.braceExpression) { - return !parent.isExpr; - } + const parent = this.curContext(); + if (parent === ct.functionExpression || parent === ct.functionStatement) { + return true; + } + if ( + prevType === tt.colon && + (parent === ct.braceStatement || parent === ct.braceExpression) + ) { + return !parent.isExpr; } - if (prevType === tt._return) { + // The check for `tt.name && exprAllowed` detects whether we are + // after a `yield` or `of` construct. See the `updateContext` for + // `tt.name`. + if ( + prevType === tt._return || + prevType === tt._yield || + (prevType === tt.name && this.state.exprAllowed) + ) { return lineBreak.test( this.input.slice(this.state.lastTokEnd, this.state.start), ); @@ -1341,13 +1352,22 @@ export default class Tokenizer extends LocationParser { prevType === tt._else || prevType === tt.semi || prevType === tt.eof || - prevType === tt.parenR + prevType === tt.parenR || + prevType === tt.arrow ) { return true; } if (prevType === tt.braceL) { - return this.curContext() === ct.braceStatement; + return parent === ct.braceStatement; + } + + if ( + prevType === tt._var || + prevType === tt._let || + prevType === tt._const + ) { + return false; } if (prevType === tt.relational) { diff --git a/packages/babel-parser/src/tokenizer/types.js b/packages/babel-parser/src/tokenizer/types.js index 14e94d32ab09..d5e164ecb1ea 100644 --- a/packages/babel-parser/src/tokenizer/types.js +++ b/packages/babel-parser/src/tokenizer/types.js @@ -174,7 +174,7 @@ export const keywords = { new: new KeywordTokenType("new", { beforeExpr, startsExpr }), this: new KeywordTokenType("this", { startsExpr }), super: new KeywordTokenType("super", { startsExpr }), - class: new KeywordTokenType("class"), + class: new KeywordTokenType("class", { startsExpr }), extends: new KeywordTokenType("extends", { beforeExpr }), export: new KeywordTokenType("export"), import: new KeywordTokenType("import", { startsExpr }), diff --git a/packages/babel-parser/test/fixtures/es2015/for-of/brackets-const/input.js b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-const/input.js new file mode 100644 index 000000000000..fc8fecda1a78 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-const/input.js @@ -0,0 +1 @@ +for (const {a} of /b/) {} diff --git a/packages/babel-parser/test/fixtures/es2015/for-of/brackets-const/output.json b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-const/output.json new file mode 100644 index 000000000000..e6724bdbc964 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-const/output.json @@ -0,0 +1,194 @@ +{ + "type": "File", + "start": 0, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 25 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 25 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ForOfStatement", + "start": 0, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 25 + } + }, + "await": false, + "left": { + "type": "VariableDeclaration", + "start": 5, + "end": 14, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 11, + "end": 14, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "id": { + "type": "ObjectPattern", + "start": 11, + "end": 14, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 12, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 12, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 13 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false, + "shorthand": true, + "value": { + "type": "Identifier", + "start": 12, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 13 + }, + "identifierName": "a" + }, + "name": "a" + }, + "extra": { + "shorthand": true + } + } + ] + }, + "init": null + } + ], + "kind": "const" + }, + "right": { + "type": "RegExpLiteral", + "start": 18, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "extra": { + "raw": "/b/" + }, + "pattern": "b", + "flags": "" + }, + "body": { + "type": "BlockStatement", + "start": 23, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 25 + } + }, + "body": [], + "directives": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/for-of/brackets-let/input.js b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-let/input.js new file mode 100644 index 000000000000..0bf988b293f8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-let/input.js @@ -0,0 +1 @@ +for (let {a} of /b/) {} diff --git a/packages/babel-parser/test/fixtures/es2015/for-of/brackets-let/output.json b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-let/output.json new file mode 100644 index 000000000000..6c74fa327abb --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-let/output.json @@ -0,0 +1,194 @@ +{ + "type": "File", + "start": 0, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ForOfStatement", + "start": 0, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "await": false, + "left": { + "type": "VariableDeclaration", + "start": 5, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 9, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "id": { + "type": "ObjectPattern", + "start": 9, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false, + "shorthand": true, + "value": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "a" + }, + "name": "a" + }, + "extra": { + "shorthand": true + } + } + ] + }, + "init": null + } + ], + "kind": "let" + }, + "right": { + "type": "RegExpLiteral", + "start": 16, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "extra": { + "raw": "/b/" + }, + "pattern": "b", + "flags": "" + }, + "body": { + "type": "BlockStatement", + "start": 21, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "body": [], + "directives": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/for-of/brackets-var/input.js b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-var/input.js new file mode 100644 index 000000000000..cef3e0ee5228 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-var/input.js @@ -0,0 +1 @@ +for (var {a} of /b/) {} diff --git a/packages/babel-parser/test/fixtures/es2015/for-of/brackets-var/output.json b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-var/output.json new file mode 100644 index 000000000000..507f3b6495e3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/for-of/brackets-var/output.json @@ -0,0 +1,194 @@ +{ + "type": "File", + "start": 0, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ForOfStatement", + "start": 0, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "await": false, + "left": { + "type": "VariableDeclaration", + "start": 5, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 9, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "id": { + "type": "ObjectPattern", + "start": 9, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "method": false, + "key": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false, + "shorthand": true, + "value": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "a" + }, + "name": "a" + }, + "extra": { + "shorthand": true + } + } + ] + }, + "init": null + } + ], + "kind": "var" + }, + "right": { + "type": "RegExpLiteral", + "start": 16, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "extra": { + "raw": "/b/" + }, + "pattern": "b", + "flags": "" + }, + "body": { + "type": "BlockStatement", + "start": 21, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "body": [], + "directives": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/yield/asi2/input.js b/packages/babel-parser/test/fixtures/es2015/yield/asi2/input.js new file mode 100644 index 000000000000..137d219c49ac --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/yield/asi2/input.js @@ -0,0 +1,3 @@ +function *f() { yield +{}/1/g +} diff --git a/packages/babel-parser/test/fixtures/es2015/yield/asi2/output.json b/packages/babel-parser/test/fixtures/es2015/yield/asi2/output.json new file mode 100644 index 000000000000..2d86b5998e19 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/yield/asi2/output.json @@ -0,0 +1,172 @@ +{ + "type": "File", + "start": 0, + "end": 30, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 30, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "FunctionDeclaration", + "start": 0, + "end": 30, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "f" + }, + "name": "f" + }, + "generator": true, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 14, + "end": 30, + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 16, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "expression": { + "type": "YieldExpression", + "start": 16, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "delegate": false, + "argument": null + } + }, + { + "type": "BlockStatement", + "start": 22, + "end": 24, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "body": [], + "directives": [] + }, + { + "type": "ExpressionStatement", + "start": 24, + "end": 28, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "expression": { + "type": "RegExpLiteral", + "start": 24, + "end": 28, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "extra": { + "raw": "/1/g" + }, + "pattern": "1", + "flags": "g" + } + } + ], + "directives": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/yield/yield class/input.js b/packages/babel-parser/test/fixtures/es2015/yield/yield class/input.js new file mode 100644 index 000000000000..ea7121a71eae --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/yield/yield class/input.js @@ -0,0 +1 @@ +function* bar() { yield class {} } diff --git a/packages/babel-parser/test/fixtures/es2015/yield/yield class/output.json b/packages/babel-parser/test/fixtures/es2015/yield/yield class/output.json new file mode 100644 index 000000000000..e4526ece7675 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/yield/yield class/output.json @@ -0,0 +1,152 @@ +{ + "type": "File", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 34 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 34 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "FunctionDeclaration", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 34 + } + }, + "id": { + "type": "Identifier", + "start": 10, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 13 + }, + "identifierName": "bar" + }, + "name": "bar" + }, + "generator": true, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 16, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 34 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 18, + "end": 32, + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 32 + } + }, + "expression": { + "type": "YieldExpression", + "start": 18, + "end": 32, + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 32 + } + }, + "delegate": false, + "argument": { + "type": "ClassExpression", + "start": 24, + "end": 32, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 32 + } + }, + "id": null, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 30, + "end": 32, + "loc": { + "start": { + "line": 1, + "column": 30 + }, + "end": { + "line": 1, + "column": 32 + } + }, + "body": [] + } + } + } + } + ], + "directives": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/jsx/errors/html-comment/input.js b/packages/babel-parser/test/fixtures/jsx/errors/html-comment/input.js new file mode 100644 index 000000000000..5190fb0e1d65 --- /dev/null +++ b/packages/babel-parser/test/fixtures/jsx/errors/html-comment/input.js @@ -0,0 +1 @@ +