-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce scope tracking in the parser #9493
Conversation
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/10229/ |
We have some tests that test the duplicate declaration checks of babel-traverse, but as the parser now throws first we are not getting to the point of testing duplicate declarations in traverse. I see 3 options:
1 and 2 are not really good options for me. So I guess I will go for 3 which is the most work but the best I feel? Any other ideas on this? |
👍 for 3. We could ask help to the community to rewrite the |
Turns out it was only 4 tests. Probably took longer to write the message above, than it will take to fix them :D |
Whoops, wrong PR. I meant to approve #9522
}, | ||
}, | ||
]); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if i should leave that or not. If this check would be in traverse I would leave it, but in the transform, the only valid usecase now would be someone creating in a plugin invalid code and then running the transform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that we need it: currently all the other early errors (except for the duplicated bindings errors) are only in @babel/parser
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should also add binding types for Flow and TS types, and check if they are duplicated.
In flow types and vars share the same namespace (type A = string; var A
is an error), while in TypeScript they are in different namespaces. type A = string; type A = number;
is an error in both languages.
|
||
// The functions in this module keep track of declared variables in the | ||
// current scope in order to detect duplicate variable names. | ||
export default class ScopeParser extends UtilParser { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since ScopeParser
is pretty much its own thing, maybe we could use it like this.scope.*
instead of adding it to the prototype chain, like we do for State
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to be a separate class, which works and might be nice to have like this if we would want to reuse this parts in traverse for example.
But when looking into flow I noticed another problem: extending the scope tracking is not as easy possible with the external class. So for typescript we probably would want to add another binding group for types. Flow has some custom rules too when it comes to declare class|var|function
. I'm not sure if we actually want to support extending the scope tracking but it might be nice.
Okay so I added fixes for flow:
I also added tests for TS to ensure types do not count as duplicate declarations of other lexical declarations. Any further additions for flow and typescript need changes to the logic in how duplicate declarations are checked. But the problem is that there is no easy way to extend the scope handler, as any addition (for example a new scope group for typescript type declarations) will need adjustments to all other parts of the scope tracking logic, so that lexical and function declarations are checked correctly against for example flow For now this PR does not introduce any duplicate checks for flow an ts, besides the ones mentions above, and we can follow up in a separate PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR looks good, I left some last minor comments.
- Could you add a test that the first code throws while the second doesn't, in script scope? (I couldn't find it, but maybe it already exists? I searched for
var
in the diff){ function f() {} var f; }
function f() {} var f;
This started causing problems when babel released this change yesterday babel/babel#9493 resolves #15
Pending resolution of pull-stream/stream-to-pull-stream#16. The extra `destroy` function causes babel to throw after babel/babel#9493 was merged and released. License: MIT Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
Pending resolution of pull-stream/stream-to-pull-stream#16. The extra `destroy` function causes babel to throw after babel/babel#9493 was merged and released. License: MIT Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
This introduces scope tracking in the parser. The scope tracking replaces some of the Flags we currently have (inGenerator, inFunction, ...).
Spec changes:
super
is used even though there is no superClassThe idea here is to enter and exit scopes, during parsing so we always can check the current scope. A scope consists of flags (which adds information we need in several places like SCOPE_FUNCTION, SCOPE_ASYNC, ...) and 3 collections of declared bindings in this scope (var, lexical(let, const, classes) and functions).
TODO:
Big thanks to acorn, as most of this here is ported from acorn. :) Same goes for copyright on most of it.