Handle exprAllowed before ObjectLike is parsed (#12267)
* fix: disallow expression after `}` is consumed in parseObjectLike * refactor: avoid accessing this.prodParam in context update
This commit is contained in:
parent
f04bbf62b5
commit
a8c66f4680
@ -241,15 +241,15 @@ export default class ExpressionParser extends LValParser {
|
|||||||
const startLoc = this.state.startLoc;
|
const startLoc = this.state.startLoc;
|
||||||
if (this.isContextual("yield")) {
|
if (this.isContextual("yield")) {
|
||||||
if (this.prodParam.hasYield) {
|
if (this.prodParam.hasYield) {
|
||||||
|
// If we have [Yield] production, `yield` will start a YieldExpression thus
|
||||||
|
// regex is allowed following. Otherwise `yield` is an identifier and regex
|
||||||
|
// is disallowed in tt.name.updateContext
|
||||||
|
this.state.exprAllowed = true;
|
||||||
let left = this.parseYield();
|
let left = this.parseYield();
|
||||||
if (afterLeftParse) {
|
if (afterLeftParse) {
|
||||||
left = afterLeftParse.call(this, left, startPos, startLoc);
|
left = afterLeftParse.call(this, left, startPos, startLoc);
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
} else {
|
|
||||||
// The tokenizer will assume an expression is allowed after
|
|
||||||
// `yield`, but this isn't that kind of yield
|
|
||||||
this.state.exprAllowed = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1603,14 +1603,13 @@ export default class ExpressionParser extends LValParser {
|
|||||||
node.properties = [];
|
node.properties = [];
|
||||||
this.next();
|
this.next();
|
||||||
|
|
||||||
while (!this.eat(close)) {
|
while (!this.match(close)) {
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
this.expect(tt.comma);
|
this.expect(tt.comma);
|
||||||
if (this.match(close)) {
|
if (this.match(close)) {
|
||||||
this.addExtra(node, "trailingComma", this.state.lastTokStart);
|
this.addExtra(node, "trailingComma", this.state.lastTokStart);
|
||||||
this.next();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1637,6 +1636,13 @@ export default class ExpressionParser extends LValParser {
|
|||||||
node.properties.push(prop);
|
node.properties.push(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The tokenizer uses `braceIsBlock` to detect whether `{` starts a block statement.
|
||||||
|
// If `{` is a block statement, `exprAllowed` will be `true`.
|
||||||
|
// However the tokenizer can not handle edge cases like `0 ? a : { a : 1 } / 2`, here
|
||||||
|
// we update `exprAllowed` when an object-like is parsed.
|
||||||
|
this.state.exprAllowed = false;
|
||||||
|
this.next();
|
||||||
|
|
||||||
this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;
|
this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;
|
||||||
let type = "ObjectExpression";
|
let type = "ObjectExpression";
|
||||||
if (isPattern) {
|
if (isPattern) {
|
||||||
|
|||||||
@ -40,6 +40,14 @@ export const types: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Token-specific context update code
|
// Token-specific context update code
|
||||||
|
// Note that we should avoid accessing `this.prodParam` in context update,
|
||||||
|
// because it is executed immediately when last token is consumed, which may be
|
||||||
|
// before `this.prodParam` is updated. e.g.
|
||||||
|
// ```
|
||||||
|
// function *g() { () => yield / 2 }
|
||||||
|
// ```
|
||||||
|
// When `=>` is eaten, the context update of `yield` is executed, however,
|
||||||
|
// `this.prodParam` still has `[Yield]` production because it is not yet updated
|
||||||
|
|
||||||
tt.parenR.updateContext = tt.braceR.updateContext = function () {
|
tt.parenR.updateContext = tt.braceR.updateContext = function () {
|
||||||
if (this.state.context.length === 1) {
|
if (this.state.context.length === 1) {
|
||||||
@ -59,11 +67,10 @@ tt.name.updateContext = function (prevType) {
|
|||||||
let allowed = false;
|
let allowed = false;
|
||||||
if (prevType !== tt.dot) {
|
if (prevType !== tt.dot) {
|
||||||
if (
|
if (
|
||||||
(this.state.value === "of" &&
|
this.state.value === "of" &&
|
||||||
!this.state.exprAllowed &&
|
!this.state.exprAllowed &&
|
||||||
prevType !== tt._function &&
|
prevType !== tt._function &&
|
||||||
prevType !== tt._class) ||
|
prevType !== tt._class
|
||||||
(this.state.value === "yield" && this.prodParam.hasYield)
|
|
||||||
) {
|
) {
|
||||||
allowed = true;
|
allowed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
1
packages/babel-parser/test/fixtures/core/categorized/labeled-block-statement-regex/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/core/categorized/labeled-block-statement-regex/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
a : { b : 1 }/2/;
|
||||||
64
packages/babel-parser/test/fixtures/core/categorized/labeled-block-statement-regex/output.json
vendored
Normal file
64
packages/babel-parser/test/fixtures/core/categorized/labeled-block-statement-regex/output.json
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":17}},
|
||||||
|
"sourceType": "script",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "LabeledStatement",
|
||||||
|
"start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":13}},
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":4,"end":13,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":13}},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "LabeledStatement",
|
||||||
|
"start":6,"end":11,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":11}},
|
||||||
|
"body": {
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11}},
|
||||||
|
"expression": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"b"},
|
||||||
|
"name": "b"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":0,"end":1,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":1},"identifierName":"a"},
|
||||||
|
"name": "a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start":13,"end":17,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":17}},
|
||||||
|
"expression": {
|
||||||
|
"type": "RegExpLiteral",
|
||||||
|
"start":13,"end":16,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":16}},
|
||||||
|
"extra": {
|
||||||
|
"raw": "/2/"
|
||||||
|
},
|
||||||
|
"pattern": "2",
|
||||||
|
"flags": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
1
packages/babel-parser/test/fixtures/core/categorized/ternary-object-literal-divide/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/core/categorized/ternary-object-literal-divide/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
0 ? a : { b : 1 }/2;
|
||||||
76
packages/babel-parser/test/fixtures/core/categorized/ternary-object-literal-divide/output.json
vendored
Normal file
76
packages/babel-parser/test/fixtures/core/categorized/ternary-object-literal-divide/output.json
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
|
||||||
|
"sourceType": "script",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
|
||||||
|
"expression": {
|
||||||
|
"type": "ConditionalExpression",
|
||||||
|
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||||
|
"test": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":0,"end":1,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":1}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 0,
|
||||||
|
"raw": "0"
|
||||||
|
},
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
"consequent": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":4,"end":5,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":5},"identifierName":"a"},
|
||||||
|
"name": "a"
|
||||||
|
},
|
||||||
|
"alternate": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start":8,"end":19,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":19}},
|
||||||
|
"left": {
|
||||||
|
"type": "ObjectExpression",
|
||||||
|
"start":8,"end":17,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":17}},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"type": "ObjectProperty",
|
||||||
|
"start":10,"end":15,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":15}},
|
||||||
|
"method": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"b"},
|
||||||
|
"name": "b"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"shorthand": false,
|
||||||
|
"value": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 1,
|
||||||
|
"raw": "1"
|
||||||
|
},
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"operator": "/",
|
||||||
|
"right": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":18,"end":19,"loc":{"start":{"line":1,"column":18},"end":{"line":1,"column":19}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"value": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user