Conversation
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/46718/ |
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit f2434cb:
|
nicolo-ribaudo
left a comment
There was a problem hiding this comment.
I love how this simplifies the code.
|
|
||
| eq: new TokenType("=", { beforeExpr, isAssign }), | ||
| assign: new TokenType("_=", { beforeExpr, isAssign }), | ||
| slashAssign: new TokenType("_=", { beforeExpr, isAssign }), |
There was a problem hiding this comment.
nit
| slashAssign: new TokenType("_=", { beforeExpr, isAssign }), | |
| slashAssign: new TokenType("/=", { beforeExpr, isAssign }), |
There was a problem hiding this comment.
The token type label is visible when tokens: true is enabled so it may breaks if people are depending on token.label since /= was parsed as tt.assign whose label is /=. We can modify the label in Babel 8.
There was a problem hiding this comment.
why wrap it in a new class and use the 'new' keyword. Did you run a benchmark test on that?
There was a problem hiding this comment.
The token is initiated once and reused elsewhere. I am aware that using a binary packed number is more optimal because it eliminates the memory loading instructions compiled from tt.slashAssign. Also note that the NewExpression here is a one time cost, we reuse the token object defined here in finishToken.
However this PR is refactoring, it only tries to not degrade the performance so reviewers can be focused on the code architecture changes. We will land performance improvement in a separate PR.
f5898d2 to
b5ce3e1
Compare
| case tt.bracketR: | ||
| case tt.braceBarR: | ||
| case tt.colon: | ||
| case tt.comma: |
There was a problem hiding this comment.
The original approach checks tt.semi and then excludes tokens with type.startsExpr. I think the new approach easier to reason about since it is an allowlist. This approach is taken from V8:
However, V8 has tt._in here, which I think it is redundant because it seems to me that in never follow an AssignmentExpression. The spec has
[+In] RelationalExpression[?In, ?Yield, ?Await] in ShiftExpression
for ( LeftHandSideExpression in Expression ) Statement
for ( var ForBinding in Expression ) Statement
for ( ForDeclaration in Expression ) Statement
None of the productions before in can parsed down to an argument-less YieldExpression.
There was a problem hiding this comment.
Maybe it's because of this?
function* fn() {
a ? yield : 2
}There was a problem hiding this comment.
Oh I meant for tt._in. 🤦
b5ce3e1 to
a787a7d
Compare
403623a to
930a7aa
Compare
| this.state.exprAllowed = false; | ||
| }; | ||
|
|
||
| tt.jsxTagEnd.updateContext = function (prevType) { |
There was a problem hiding this comment.
It is merged with updateContext because it manipulates this.state.exprAllowed based on different contexts.
| @@ -0,0 +1,2 @@ | |||
| function *f1() { yield / 1 /g } | |||
| function *f2() { yield /=2 /i } | |||
There was a problem hiding this comment.
If we don't already have it, can you add this test? (with normal functions)
function f1() { yield / 1 /g }
function f2() { yield /=2 /i }| // regular expression). | ||
| // The `beforeExpr` property is used to disambiguate between 1) binary | ||
| // expression (<) and JSX Tag start (<name>); 2) object literal and JSX | ||
| // texts. It is set on the `updateContext` function in the JSX plugin. |
There was a problem hiding this comment.
We can probably further simplify the exprAllowed logic in updateContext of JSX plugin, based on the usage here. However I would like to land it separately before this PR is too big for review.
| node.argument = this.parseMaybeAssign(); | ||
| let delegating = false; | ||
| let argument = null; | ||
| if (!this.hasPrecedingLineBreak()) { |
There was a problem hiding this comment.
I'm curious about why
function* fn() {
yield
* []
}is disallowed, it doesn't seem to be ambiguous 🤔
There was a problem hiding this comment.
Good question. I have no idea why it is disallowed, maybe @bakkot can shred some light here?
There was a problem hiding this comment.
That decision was before my time, so I can only speculate. I agree it would still be unambiguous without the NLTH restriction. My best guess is that it's future-proofing, to reserve the possibility of introducing * as a prefix operator.
| } else if (type === tt.jsxTagEnd) { | ||
| const out = context.pop(); | ||
| if ((out === tc.j_oTag && prevType === tt.slash) || out === tc.j_cTag) { | ||
| context.pop(); |
There was a problem hiding this comment.
What are we popping out here? j_expr?
There was a problem hiding this comment.
If out is j_oTag (<name></name>), context.pop is j_expr
If out is j_cTag (<name />), context.pop is the context before j_cTag, which is also the one before j_expr since we reinterpret j_expr, j_oTag as j_cTag when we see slash following jsxTagStart.
The logic here is was tt.jsxTagEnd.updateContext, I move it here so we can simplify the updateContext interface.
|
How much memory does it consume to parse this? If I try to parse this on an Intel 386 sx / dx 16 mhz cpu, I will have no problems? |
This PR reduces the tokenizer state
exprAllowedusage. It is now used only in the JSX plugin and we could consider moveexprAllowedupdates to the plugin.The
exprAllowedwas used for 1) checking regex start, 2) allowing*=>in the Flow plugin and 3) checking JSX expression start. It turns out we can come up with an alternative approach for the 1) and 2) use case, which greatly simplifies the tokenizer context update logic which involves many checks.In this PR, the tokenizer context now only takes care of whether
}matches to${or{. TheexprAllowedare now only maintained in the JSX plugin, and used for disambiguate 1) relational expression<and JSX Tag start<jsx>; 2) object literal ({name}) and JSX text.I will mark this PR ready for review when refactoringexprAllowedfor the third usage is done.