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
Update scope info after destructuring transform #14494
Conversation
59/66 introduced tests failing
Via crawling the scope after the transfomrations are made. 10/66 tests passing instead of earlier 7/66.
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/51754/ |
Would appreciate any comments which could help bring up the number of passing tests. This d40dce6 already makes 3 more tests pass which weren't before. E.g. one of the failing tests is https://github.com/babel/babel/blob/main/packages/babel-plugin-transform-destructuring/test/fixtures/destructuring/spread/input.js . I'm not sure where that is handled in this transform plugin so that its scope bindings may be taken care of. |
Also test assumptions / preconditions
1. Update tests: some were spurious failures 2. Address failing tests: introduce scope crawling in for statement cases
This is now fixed. If someone can help me with the failing CI test (I don't understand the failure) then that'd be great! |
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.
Nice work. Left some nit comments on code and testing approach.
@@ -637,6 +637,7 @@ export function convertVariableDeclaration( | |||
} else { | |||
path.replaceWithMultiple(nodesOut); | |||
} | |||
path.scope.crawl(); |
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.
Q: Is Line 625 - 633 still required now that we crawl the scope?
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 understand the plugin source very well but removing them doesn't cause any tests to fail. I'll remove them, let me know if you think we should keep them.
- nit: improve variable naming style - remove some manual scope updation code which isn't necessary now that we're crawling
The test is passing because in the second round
You don't have to put in in all options.json. Options.json in these folders will be applied to their sub tests:
|
traverse.cache.clear(); | ||
traverse(transformed.ast, { | ||
VariableDeclarator(path) { | ||
const b = path.scope.getBinding(path.get("id").node.name); |
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.
Further improvement idea: To make it a universal check, we should loop through Object.keys(path.getBindingIdentifiers())
. The current check is ok for transform-destructuring
since path.get("id")
is always an identifier after transformed.
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.
Sure, but if the bindings don't exist, would that be returned in path.getBindingIdentifiers()
?
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.
At the AST level, instead of LHS of the variable declarator we can also go for all identifiers that are present. But I couldn't think of a way to exclude globals or member expressions (e.g. slice
in arr.slice
or Array
global) which definitely won't have scope bindings.
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.
path.getBindingIdentifiers()
extracts ids from the AST, it does not access the scope info.
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.
At the AST level, instead of LHS of the variable declarator we can also go for all identifiers that are present.
hasBinding
will respect globals. path.isReferencedIdentifier()
can exclude referenced identifiers. I think we can start from VariableDeclarator / Function params only.
The most strict check will be to compare the scope info after transform against a new scope created from scratch (without traverse cache), but I guess it will fail many, if not most current tests.
I'm trying what you suggested, but I get |
My bad, it should be: module.exports = (babel) => {
return {
visitor: {
Program: {
exit(programPath) {
// so that this plugin is always called after the transform-destructuring plugin
programPath.traverse(checkScopeVisitor)
}
}
}
}
} |
See suggestions in JLHwung's review
You're right. It works (tested that they're failing without the fix), and it works better! Any thoughts on where the |
packages/babel-plugin-transform-destructuring/test/fixtures/allowArrayLike/options.json
Outdated
Show resolved
Hide resolved
To generalize the check
All checks pass. Thanks for all the comments. Should we merge? |
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.
Thanks
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 dislike path.scope.crawl()
because it's a very expensive operation. Would just using path.scope.registerDeclaration
on the new nodes work to fix this bug?
@nicolo-ribaudo Thanks. I had tried your suggestion, but this transform in particular is written in a way that all the nodes are prepared at once and then attached to AST at once Based on my try, I think
Do we have any perf tests so we can measure the exact impact on performance? |
We have some, but @JLHwung is probably the best person to tell you about them. Let's merge this PR now since it improves correctness, we can iterate on performance later. |
Introduces a test suite to demonstrate #14438 and provides a fix that makes all tests pass.