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
Bug/missing references after crawl #11011
Bug/missing references after crawl #11011
Conversation
Merged to avoid subtle assumption that `Declaration` is called before `ClassDeclaration`
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!
Added to v7.8.4 milestone because it is blocking downstream tools.
if (!id) return; | ||
|
||
const name = id.name; | ||
path.scope.bindings[name] = path.scope.getBinding(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.
Isn't the following change all that's necessary?
- path.scope.bindings[name] = path.scope.getBinding(name);
+ path.scope.bindings[name] = path.scope.parent.getBinding(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.
I agree. parent
is the nearest function scope, but classes are block-scoped:
let A;
function fn() {
{
class A {}
}
A; // This references the let declaration, not the path.
}
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 change
- path.scope.bindings[name] = path.scope.getBinding(name);
+ path.scope.bindings[name] = path.scope.parent.getBinding(name);
implicitly depends on the fact that the Declaration
visitor runs before ClassDeclaration
visitor, so that path.scope.parent.getBinding
always points to the new binding which may be initialized in Declaration
visitor or BlockScoped
visitor.
See #10896 (comment)
Besides that, I agree we should do path.scope.parent
instead of parent
.
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.
implicitly depends on the fact that the
Declaration
visitor runs beforeClassDeclaration
visitor, so thatpath.scope.parent.getBinding
always points to the new binding which may be initialized inDeclaration
visitor orBlockScoped
visitor.
If the class binding may be(always is?) initialized in BlockScoped
won't this stop the identifier from being visible inside the class scope if the visitors are merged?
babel/packages/babel-traverse/src/scope/index.js
Lines 62 to 64 in 63a12f2
Declaration(path) { | |
// delegate block scope handling to the `BlockScoped` method | |
if (path.isBlockScoped()) return; |
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.
@regiontog Ah you are right! The ClassDeclaration
binding is registered in BlockScoped
and BlockScoped
runs before ClassDeclaration
. I am curious why the test can even get passed.
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.
Thanks!
When traversing during a
crawl()
babel currently sets the class identifier inside the class to the old binding. This has caused a number of issues in parcel(parcel-bundler/parcel#3932, parcel-bundler/parcel#2513, parcel-bundler/parcel#2981, parcel-bundler/parcel#3664). This PR sets the binding to the binding in the parent. See #10896 for in depth explanation.In addition the assumption that a
Declaration
visitor is visited beforeClassDeclaration
incrawl()
was removed by merging the visitors.