Restore traversal context after enter / traverse#13813
Restore traversal context after enter / traverse#13813nicolo-ribaudo merged 7 commits intobabel:mainfrom
Conversation
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/49081/ |
|
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 f11e12d:
|
| // a requeued node (e.g. by .replaceWith()) that is then marked | ||
| // with .skip(). | ||
| if (this.shouldSkip || this.call("enter") || this.shouldSkip) { | ||
| if (this.shouldSkip || this.call("enter")) { |
There was a problem hiding this comment.
If this.enter("enter") is false, either fns is empty (no visitors), or all the visitors does not change the traverse flags. If fns is empty, then this.shouldSkip would not be changed at all. If all the visitors do not change traversal flags, then this.shouldSkip should equals to this.shouldSkip before enter hook is called. Therefore the second this.shouldSkip check is redundant.
|
Does this also fix #12631? |
Thanks for the reminder. I check out the reproduction repo: The traversal context does change after |
| @@ -0,0 +1,11 @@ | |||
| async function main() { | |||
| async () => { | |||
There was a problem hiding this comment.
Is it intentional that this function is no longer invoked?
There was a problem hiding this comment.
Kind of. Personally I prefer the minimal AST structure that can reproduce the bug. In this case we are not testing the runtime semantics so the simpler the input code is, the easier to reason about what is going on. You can verify that the original code example also works on the PR REPL.
|
Could we also benchmark, for example, compiling https://github.com/babel/babel/blob/main/packages/babel-parser/src/parser/expression.js with |
|
I added a real-world benchmark, the current PR is 3% (not statistically significant) slower than main branch. The minimal sample size for benchmark is 100. |
In this PR we restores the context after
call("enter")andtraverse.node. The current AST operations we provided did not guarantee that the traversal context is perserved, let alone users may even change the associated context. The traversal context is crucial to sub-traverse in order to isolate visitors / traverse states from the root traverse.See also #13801 (comment) for how the leaked traversal context causes confusing errors.
I add a benchmark case to access the performance impact of this PR. The benchmark is a worst case scenario because context is changed in every node visitor. Compared to 7.15.4, Babel traverse in this PR is 10% slower. In the real world most context change happen in sub traverse, preserving context will ensure global visitors are not invoked in sub traverse so the real world performance should be better than this.
Benchmark Results