-
-
Notifications
You must be signed in to change notification settings - Fork 472
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
fix(transformer/arrow-functions): _this = this
should be inserted after super call expression
#8024
base: main
Are you sure you want to change the base?
Conversation
…er super call expression
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
_this = this
should be inserted after super call expression
CodSpeed Performance ReportMerging #8024 will not alter performanceComparing Summary
|
ctx.ancestors() | ||
.find(|ancestor| { | ||
matches!( | ||
ancestor, | ||
// const A = super(): | ||
Ancestor::VariableDeclarationDeclarations(_) | ||
// super(); | ||
| Ancestor::ExpressionStatementExpression(_) | ||
) | ||
}) | ||
.unwrap() | ||
.address() |
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.
Unwrap failed here, we need to find all possible statements, and this may not be a good implementation
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.
You can use Ancestor::is_via_statement
for this.
Note it doesn't tell you if that ancestor is a statement, but whether its child is a statement.
So if you are visiting a Function
, it could be either an expression or a statement. ctx.parent().is_via_statement()
will tell you.
To find the closest statement, loop through ancestors, and when ancestor.is_via_statement()
returns true
, then the previous ancestor you passed is the statement.
Put another way, you have to walk 1 step further up the tree than the node you're looking for.
The naming is_via_*
is weird, and the fact that you have to look at the ancestor above is confusing as hell. So it's a terrible API! But it does do what you need.
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.
#8031 renames this method to Ancestor::is_parent_of_statement
. I think that's clearer.
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 just found that we have these methods!
@overlookmotel Can you take a look at this PR, I am not sure this is a good direction to fix it. I want to change everything according to esbuild's implementation |
I'm not sure this approach based on
class C extends S {
constructor() {
let f = async () => this;
super();
}
} It can also be used an expression, rather than a statement: class C extends S {
constructor() {
let f = async () => this;
let x = foo(super(), f());
}
} I think the most simple approach involves a double-visit:
This is what the visitor in class properties that I mentioned in #7792 (comment) does, so you could just copy the code. |
Concerning ESBuild's version: Yes it's simpler to implement, but I think less performant at runtime than Babel's version. In Babel's version, there's only 1 call to I don't know for sure, but that sounds more expensive (more garbage collection). I think we could do our own version which is better than both! Maybe something like this: Input: class C extends S {
constructor() {
super();
let f = async () => this;
}
} Output: class C extends S {
constructor() {
var _getThis = () => this;
super();
let f = oxcHelpers.asyncToGenerator(function*() { return this; }, _getThis, "f");
}
} (the last param takes care of naming the function correctly, instead of Babel's extra function wrappers) But... I suggest we follow Babel for now, make our implementation correct, and look at optimizing output later. There's many places we can improve on Babel in lots of transforms. |
PS: I've made a small improvement to the |
That's a trade-off for us considering the different implementations. When I am a developer for the transformer, I prefer a |
To clarify, so in this case, you prefer to double-visited? I have no strong opinion about this. Just think of this way is easier to implement, but cannot solve |
I think double-visit is the best way, yes. I think it'll be able to handle the We could later try and optimize it for common case where But:
|
related: #7792
This PR doesn't contain fixing the async arrow function in
super()
, which is difficult for our architecture. I just found thatesbuild
's implementation is quite simpler! https://esbuild.github.io/try/#dAAwLjI0LjAALS10YXJnZXQ9ZXMyMDE2AGNsYXNzIEMgZXh0ZW5kcyBTIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHN1cGVyKGFzeW5jICgpID0+IHRoaXMpOwogICAgYXN5bmMoKSA9PiB7fQogIH0KfQ