From cfd11e4efded10b62ed361ac9af9e875de04e499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Tue, 7 Apr 2020 21:05:59 -0400 Subject: [PATCH] fix: do not push new token context when function is following dot/questionDot --- .../babel-parser/src/parser/expression.js | 13 +- .../babel-parser/src/tokenizer/context.js | 5 +- .../jsx/regression/issue-11387/input.js | 1 + .../jsx/regression/issue-11387/options.json | 3 + .../jsx/regression/issue-11387/output.json | 525 ++++++++++++++++++ 5 files changed, 537 insertions(+), 10 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/jsx/regression/issue-11387/input.js create mode 100644 packages/babel-parser/test/fixtures/jsx/regression/issue-11387/options.json create mode 100644 packages/babel-parser/test/fixtures/jsx/regression/issue-11387/output.json diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index d97a429ee0b6..46e90e825507 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -2125,17 +2125,12 @@ export default class ExpressionParser extends LValParser { } else if (this.state.type.keyword) { name = this.state.type.keyword; - // `class` and `function` keywords push new context into this.context. + // `class` and `function` keywords push function-type token 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(); + const context = this.state.context; + if (context[context.length - 1].token === "function") { + context.pop(); } } else { throw this.unexpected(); diff --git a/packages/babel-parser/src/tokenizer/context.js b/packages/babel-parser/src/tokenizer/context.js index 3f3907872c06..83e21443a955 100644 --- a/packages/babel-parser/src/tokenizer/context.js +++ b/packages/babel-parser/src/tokenizer/context.js @@ -101,7 +101,10 @@ tt.incDec.updateContext = function() { }; tt._function.updateContext = tt._class.updateContext = function(prevType) { - if ( + if (prevType === tt.dot || prevType === tt.questionDot) { + // when function/class follows dot/questionDot, it is part of + // (optional)MemberExpression, then we don't need to push new token context + } else if ( prevType.beforeExpr && prevType !== tt.semi && prevType !== tt._else && diff --git a/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/input.js b/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/input.js new file mode 100644 index 000000000000..34425fe24a91 --- /dev/null +++ b/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/input.js @@ -0,0 +1 @@ +
{(this?.class, this.class, this?.function, this.function)}
diff --git a/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/options.json b/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/options.json new file mode 100644 index 000000000000..698e7668500f --- /dev/null +++ b/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["jsx", "flow"] +} diff --git a/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/output.json b/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/output.json new file mode 100644 index 000000000000..df60608629b5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/jsx/regression/issue-11387/output.json @@ -0,0 +1,525 @@ +{ + "type": "File", + "start":0,"end":69,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":69}}, + "program": { + "type": "Program", + "start":0,"end":69,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":69}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":69,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":69}}, + "expression": { + "type": "JSXElement", + "start":0,"end":69,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":69}}, + "openingElement": { + "type": "JSXOpeningElement", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5}}, + "name": { + "type": "JSXIdentifier", + "start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4}}, + "name": "div" + }, + "attributes": [], + "selfClosing": false + }, + "closingElement": { + "type": "JSXClosingElement", + "start":63,"end":69,"loc":{"start":{"line":1,"column":63},"end":{"line":1,"column":69}}, + "name": { + "type": "JSXIdentifier", + "start":65,"end":68,"loc":{"start":{"line":1,"column":65},"end":{"line":1,"column":68}}, + "name": "div" + } + }, + "children": [ + { + "type": "JSXExpressionContainer", + "start":5,"end":63,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":63}}, + "expression": { + "type": "SequenceExpression", + "start":7,"end":61,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":61}}, + "expressions": [ + { + "type": "OptionalMemberExpression", + "start":7,"end":18,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":18}}, + "object": { + "type": "ThisExpression", + "start":7,"end":11,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":11}} + }, + "property": { + "type": "Identifier", + "start":13,"end":18,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":18},"identifierName":"class"}, + "name": "class" + }, + "computed": false, + "optional": true + }, + { + "type": "MemberExpression", + "start":20,"end":30,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":30}}, + "object": { + "type": "ThisExpression", + "start":20,"end":24,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":24}} + }, + "property": { + "type": "Identifier", + "start":25,"end":30,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":30},"identifierName":"class"}, + "name": "class" + }, + "computed": false + }, + { + "type": "OptionalMemberExpression", + "start":32,"end":46,"loc":{"start":{"line":1,"column":32},"end":{"line":1,"column":46}}, + "object": { + "type": "ThisExpression", + "start":32,"end":36,"loc":{"start":{"line":1,"column":32},"end":{"line":1,"column":36}} + }, + "property": { + "type": "Identifier", + "start":38,"end":46,"loc":{"start":{"line":1,"column":38},"end":{"line":1,"column":46},"identifierName":"function"}, + "name": "function" + }, + "computed": false, + "optional": true + }, + { + "type": "MemberExpression", + "start":48,"end":61,"loc":{"start":{"line":1,"column":48},"end":{"line":1,"column":61}}, + "object": { + "type": "ThisExpression", + "start":48,"end":52,"loc":{"start":{"line":1,"column":48},"end":{"line":1,"column":52}} + }, + "property": { + "type": "Identifier", + "start":53,"end":61,"loc":{"start":{"line":1,"column":53},"end":{"line":1,"column":61},"identifierName":"function"}, + "name": "function" + }, + "computed": false + } + ], + "extra": { + "parenthesized": true, + "parenStart": 6 + } + } + } + ] + } + } + ], + "directives": [] + }, + "tokens": [ + { + "type": { + "label": "jsxTagStart", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "start":0,"end":1,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":1}} + }, + { + "type": { + "label": "jsxName", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "value": "div", + "start":1,"end":4,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":4}} + }, + { + "type": { + "label": "jsxTagEnd", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "start":4,"end":5,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":5}} + }, + { + "type": { + "label": "{", + "beforeExpr": true, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6}} + }, + { + "type": { + "label": "(", + "beforeExpr": true, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7}} + }, + { + "type": { + "label": "this", + "keyword": "this", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "value": "this", + "start":7,"end":11,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":11}} + }, + { + "type": { + "label": "?.", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "start":11,"end":13,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":13}} + }, + { + "type": { + "label": "name", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "value": "class", + "start":13,"end":18,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":18}} + }, + { + "type": { + "label": ",", + "beforeExpr": true, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "start":18,"end":19,"loc":{"start":{"line":1,"column":18},"end":{"line":1,"column":19}} + }, + { + "type": { + "label": "this", + "keyword": "this", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "value": "this", + "start":20,"end":24,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":24}} + }, + { + "type": { + "label": ".", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "start":24,"end":25,"loc":{"start":{"line":1,"column":24},"end":{"line":1,"column":25}} + }, + { + "type": { + "label": "name", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "value": "class", + "start":25,"end":30,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":30}} + }, + { + "type": { + "label": ",", + "beforeExpr": true, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "start":30,"end":31,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":31}} + }, + { + "type": { + "label": "this", + "keyword": "this", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "value": "this", + "start":32,"end":36,"loc":{"start":{"line":1,"column":32},"end":{"line":1,"column":36}} + }, + { + "type": { + "label": "?.", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "start":36,"end":38,"loc":{"start":{"line":1,"column":36},"end":{"line":1,"column":38}} + }, + { + "type": { + "label": "name", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "value": "function", + "start":38,"end":46,"loc":{"start":{"line":1,"column":38},"end":{"line":1,"column":46}} + }, + { + "type": { + "label": ",", + "beforeExpr": true, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "start":46,"end":47,"loc":{"start":{"line":1,"column":46},"end":{"line":1,"column":47}} + }, + { + "type": { + "label": "this", + "keyword": "this", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "value": "this", + "start":48,"end":52,"loc":{"start":{"line":1,"column":48},"end":{"line":1,"column":52}} + }, + { + "type": { + "label": ".", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "start":52,"end":53,"loc":{"start":{"line":1,"column":52},"end":{"line":1,"column":53}} + }, + { + "type": { + "label": "name", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "value": "function", + "start":53,"end":61,"loc":{"start":{"line":1,"column":53},"end":{"line":1,"column":61}} + }, + { + "type": { + "label": ")", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "start":61,"end":62,"loc":{"start":{"line":1,"column":61},"end":{"line":1,"column":62}} + }, + { + "type": { + "label": "}", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "start":62,"end":63,"loc":{"start":{"line":1,"column":62},"end":{"line":1,"column":63}} + }, + { + "type": { + "label": "jsxTagStart", + "beforeExpr": false, + "startsExpr": true, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "start":63,"end":64,"loc":{"start":{"line":1,"column":63},"end":{"line":1,"column":64}} + }, + { + "type": { + "label": "/", + "beforeExpr": true, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": 10, + "updateContext": null + }, + "value": "/", + "start":64,"end":65,"loc":{"start":{"line":1,"column":64},"end":{"line":1,"column":65}} + }, + { + "type": { + "label": "jsxName", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "value": "div", + "start":65,"end":68,"loc":{"start":{"line":1,"column":65},"end":{"line":1,"column":68}} + }, + { + "type": { + "label": "jsxTagEnd", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null + }, + "start":68,"end":69,"loc":{"start":{"line":1,"column":68},"end":{"line":1,"column":69}} + }, + { + "type": { + "label": "eof", + "beforeExpr": false, + "startsExpr": false, + "rightAssociative": false, + "isLoop": false, + "isAssign": false, + "prefix": false, + "postfix": false, + "binop": null, + "updateContext": null + }, + "start":69,"end":69,"loc":{"start":{"line":1,"column":69},"end":{"line":1,"column":69}} + } + ] +} \ No newline at end of file