mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 20:28:58 +00:00
perf(transformer/arrow-functions): bail out of visiting early when inserting _this = this after super() (#8482)
In arrow functions transform (including async-to-generator), we need to insert a `_this = this` assignment in parent function, if the arrow function uses `this`. If the arrow function is in constructor of a class which `extend`s another class, this assignment needs to be inserted after `super()`, because `this` is invalid before a `super()` call has occurred.
Optimize the visitor which searches class constructor for `super()` for the common case where `super()` call occurs as a top-level statement early in the constructor. e.g.
```js
class C extends S {
constructor() {
super();
// ... lots more code here ...
}
}
```
In this case, we can insert `_this = this;` statement after `super();` and then exit the visitor. There's no need search the rest of the constructor for further `super()` calls, because `_this` is definitely now initialized prior to any of that code.
This commit is contained in:
parent
3e05055783
commit
53ef263077
1 changed files with 11 additions and 11 deletions
|
|
@ -1310,24 +1310,24 @@ impl<'a> VisitMut<'a> for ConstructorBodyThisAfterSuperInserter<'a, '_> {
|
|||
// `super()` can't appear in a nested function
|
||||
}
|
||||
|
||||
/// `super()` -> `super(); _this = this;`
|
||||
/// `super();` -> `super(); _this = this;`
|
||||
fn visit_statements(&mut self, statements: &mut ArenaVec<'a, Statement<'a>>) {
|
||||
let mut new_stmts = vec![];
|
||||
|
||||
for (index, stmt) in statements.iter_mut().enumerate() {
|
||||
if matches!(stmt, Statement::ExpressionStatement(expr_stmt) if expr_stmt.expression.is_super_call_expression())
|
||||
{
|
||||
let assignment = self.create_assignment_to_this_temp_var();
|
||||
let new_stmt = self.ctx.ast.statement_expression(SPAN, assignment);
|
||||
new_stmts.push((index, new_stmt));
|
||||
} else {
|
||||
self.visit_statement(stmt);
|
||||
let assignment = self.ctx.ast.statement_expression(SPAN, assignment);
|
||||
statements.insert(index + 1, assignment);
|
||||
// `super();` found as top-level statement in this block of statements.
|
||||
// No need to continue visiting later statements, because `_this` is definitely assigned
|
||||
// to at this point - no need to assign to it again.
|
||||
// This means we don't visit the whole constructor in the common case where `super();`
|
||||
// appears as a top-level statement early in class constructor
|
||||
// `constructor() { super(); blah; blah; blah; }`.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (index, new_stmt) in new_stmts.into_iter().rev() {
|
||||
// insert the new statement after the super call
|
||||
statements.insert(index + 1, new_stmt);
|
||||
self.visit_statement(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue