fix: do not push new token context when function is following dot/questionDot (#11388)

* fix: do not push new token context when function is following dot/questionDot

* more cautiously poping context
This commit is contained in:
Huáng Jùnliàng 2020-04-08 10:10:36 -04:00 committed by GitHub
parent fbcb251d61
commit 8b976b0670
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 127 additions and 7 deletions

View File

@ -2125,17 +2125,15 @@ export default class ExpressionParser extends LValParser {
} else if (this.state.type.keyword) { } else if (this.state.type.keyword) {
name = 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 // But there is no chance to pop the context if the keyword is consumed
// as an identifier such as a property name. // as an identifier such as a property name.
// If the previous token is a dot, this does not apply because the const context = this.state.context;
// context-managing code already ignored the keyword
if ( if (
(name === "class" || name === "function") && (name === "class" || name === "function") &&
(this.state.lastTokEnd !== this.state.lastTokStart + 1 || context[context.length - 1].token === "function"
this.input.charCodeAt(this.state.lastTokStart) !== charCodes.dot)
) { ) {
this.state.context.pop(); context.pop();
} }
} else { } else {
throw this.unexpected(); throw this.unexpected();

View File

@ -101,7 +101,10 @@ tt.incDec.updateContext = function() {
}; };
tt._function.updateContext = tt._class.updateContext = function(prevType) { 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.beforeExpr &&
prevType !== tt.semi && prevType !== tt.semi &&
prevType !== tt._else && prevType !== tt._else &&

View File

@ -0,0 +1 @@
<div>{(this?.class, this.class, this?.function, this.function)}</div>

View File

@ -0,0 +1,3 @@
{
"plugins": ["jsx", "flow"]
}

View File

@ -0,0 +1,115 @@
{
"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": []
}
}