-
-
Notifications
You must be signed in to change notification settings - Fork 339
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
feat(traverse): add scope flags to TraverseCtx
#3229
feat(traverse): add scope flags to TraverseCtx
#3229
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. Join @overlookmotel and the rest of your teammates on Graphite |
CodSpeed Performance ReportMerging #3229 will not alter performanceComparing Summary
|
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 may have missed this, where is the logic for checking "use strict" inside a function?
Edit: oh it's in another PR.
Merge activity
|
Add scope flags to `TraverseCtx`. Closes #3189. `walk_*` functions build a stack of `ScopeFlags` as AST is traversed, and they can be queried from within visitors with `ctx.scope()`, `ctx.ancestor_scope()` and `ctx.find_scope()`. The codegen which generates `walk_*` functions gets the info about which AST types have scopes, and how to check for strict mode from the `#[visited_node]` attrs on AST type definitions in `oxc_ast`. A few notes: Each scope inherits the strict mode flag from the level before it in the stack, so if you need to know "am I in strict mode context here?", `ctx.scope().is_strict_mode()` will tell you - no need to travel back up the stack to find out. Scopes do *not* inherit any other flags from level before it. So `ctx.scope()` in a block nested in a function will return `ScopeFlags::empty()` not `ScopeFlags::Function`. I had to add an extra flag `ScopeFlags::Method`. The reason for this is to deal with when a `Function` is actually a `MethodDefinition`, and to avoid creating 2 scopes in this case. The principle I'm trying to follow is to encode as little logic in the codegen as possible, as it's rather hidden away. Instead the codegen follows a standard logic for every node, guided by attributes which are visible next to the types in `oxc_ast`. This hopefully makes how `Traverse`'s visitors are generated less mysterious, and easier to change. The case of `Function` within `MethodDefinition` is a weird one and would not be possible to implement without encoding a magic "special case" within the codegen without this extra `ScopeFlags::Method` variant. Its existence does not alter the operation of any other code in Oxc which uses `ScopeFlags`. In my view `ScopeFlags` might benefit from a little bit of an overhaul anyway. I believe we could pack more information into the bits and make it more useful.
122b361
to
4208733
Compare
365a12f
to
46c02ae
Compare
@Boshen FYI The logic for checking for oxc/crates/oxc_ast/src/ast/js.rs Lines 2134 to 2143 in ec41dba
The additional |
Fixes a bug in #3229. The logic to prevent a duplicate scope being created for a `Function` which is a `MethodDefinition` would also stop a scope being created for inner function in: ```rs class X { foo() { function bar() {} } } ``` or ```rs class X { foo( bar = function() {} ) {} } ``` This PR fixes that. This change also allows removing `ScopeFlags::Method` which #3229 added.
Add scope flags to
TraverseCtx
.Closes #3189.
walk_*
functions build a stack ofScopeFlags
as AST is traversed, and they can be queried from within visitors withctx.scope()
,ctx.ancestor_scope()
andctx.find_scope()
.The codegen which generates
walk_*
functions gets the info about which AST types have scopes, and how to check for strict mode from the#[visited_node]
attrs on AST type definitions inoxc_ast
.A few notes:
Each scope inherits the strict mode flag from the level before it in the stack, so if you need to know "am I in strict mode context here?",
ctx.scope().is_strict_mode()
will tell you - no need to travel back up the stack to find out.Scopes do not inherit any other flags from level before it. So
ctx.scope()
in a block nested in a function will returnScopeFlags::empty()
notScopeFlags::Function
.I had to add an extra flag
ScopeFlags::Method
. The reason for this is to deal with when aFunction
is actually aMethodDefinition
, and to avoid creating 2 scopes in this case. The principle I'm trying to follow is to encode as little logic in the codegen as possible, as it's rather hidden away. Instead the codegen follows a standard logic for every node, guided by attributes which are visible next to the types inoxc_ast
. This hopefully makes howTraverse
's visitors are generated less mysterious, and easier to change.The case of
Function
withinMethodDefinition
is a weird one and would not be possible to implement without encoding a magic "special case" within the codegen without this extraScopeFlags::Method
variant. Its existence does not alter the operation of any other code in Oxc which usesScopeFlags
.In my view
ScopeFlags
might benefit from a little bit of an overhaul anyway. I believe we could pack more information into the bits and make it more useful.