From 8ca8fce4e123954e398716ca8ca3a2557b79229a Mon Sep 17 00:00:00 2001
From: overlookmotel <557937+overlookmotel@users.noreply.github.com>
Date: Sun, 15 Dec 2024 01:53:14 +0000
Subject: [PATCH] perf(transformer/class-properties): reduce work updating
scopes when transforming static prop initializers (#7904)
Static property initializers need to be modified in various ways. One is to change the parent scope of the first level of scopes in the initializer to the new parent scope.
Lots of nodes which have scopes cannot be the first level. e.g. an `IfStatement` cannot because it would have to be inside a function, and that function would be the first-level scope. The `IfStatement` must be a nested scope, so we know we won't need to update its parent.
Skip checking if we need to update parent scope for all these nodes.
---
.../class_properties/static_prop_init.rs | 175 ++++++++++++------
1 file changed, 117 insertions(+), 58 deletions(-)
diff --git a/crates/oxc_transformer/src/es2022/class_properties/static_prop_init.rs b/crates/oxc_transformer/src/es2022/class_properties/static_prop_init.rs
index 101cfd7110bda..4a57516bd0e94 100644
--- a/crates/oxc_transformer/src/es2022/class_properties/static_prop_init.rs
+++ b/crates/oxc_transformer/src/es2022/class_properties/static_prop_init.rs
@@ -95,8 +95,8 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
/// ```
///
/// If this class defines no private properties, class has no name, and no `ScopeFlags` need updating,
-/// then we only need to transform `this`. So can skip traversing into functions and other contexts
-/// which have their own `this`.
+/// then we only need to transform `this`, and re-parent first-level scopes. So can skip traversing
+/// into functions and other contexts which have their own `this`.
///
/// Note: Those functions could contain private fields referring to a *parent* class's private props,
/// but we don't need to transform them here as they remain in same class scope.
@@ -119,8 +119,13 @@ struct StaticInitializerVisitor<'a, 'ctx, 'v> {
/// Incremented when entering a different `this` context, decremented when exiting it.
/// `this` should be transformed when `this_depth == 0`.
this_depth: u32,
- /// Incremented when entering a scope, decremented when exiting it.
+ /// Incremented when entering scope, decremented when exiting it.
/// Parent `ScopeId` should be updated when `scope_depth == 0`.
+ /// Note: `scope_depth` does not aim to track scope depth completely accurately.
+ /// Only requirement is to ensure that `scope_depth == 0` only when we're in first-level scope.
+ /// So we don't bother incrementing + decrementing for scopes which are definitely not first level.
+ /// e.g. `BlockStatement` or `ForStatement` must be in a function, and therefore we're already in a
+ /// nested scope.
scope_depth: u32,
/// Main transform instance.
class_properties: &'v mut ClassProperties<'a, 'ctx>,
@@ -252,31 +257,16 @@ impl<'a, 'ctx, 'v> VisitMut<'a> for StaticInitializerVisitor<'a, 'ctx, 'v> {
self.replace_class_name_with_temp_var(ident);
}
- /// Update parent scope for first level of scopes.
/// Convert scope to sloppy mode if `self.make_sloppy_mode == true`.
+ // `#[inline]` because called from many `walk` functions and is small.
+ #[inline]
fn enter_scope(&mut self, _flags: ScopeFlags, scope_id: &Cell