Introduce scope tracking in the parser#9493
Introduce scope tracking in the parser#9493danez merged 27 commits intobabel:masterfrom danez:scope-tracking
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.
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.
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.
nicolo-ribaudo
left a comment
There was a problem hiding this comment.
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.
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.
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.
…s lexical declarations
|
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. |
nicolo-ribaudo
left a comment
There was a problem hiding this comment.
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
varin 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:
superis 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.