diff --git a/crates/oxc_transformer/src/es2022/class_properties/class.rs b/crates/oxc_transformer/src/es2022/class_properties/class.rs index 0a02376a7bc25..aa81f38ec2261 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/class.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/class.rs @@ -78,7 +78,6 @@ impl<'a> ClassProperties<'a, '_> { let mut has_static_private_method_or_static_block = false; // TODO: Store `FxIndexMap`s in a pool and re-use them let mut private_props = FxIndexMap::default(); - let mut constructor = None; for element in &mut body.body { match element { ClassElement::PropertyDefinition(prop) => { @@ -107,11 +106,7 @@ impl<'a> ClassProperties<'a, '_> { } } ClassElement::MethodDefinition(method) => { - if method.kind == MethodDefinitionKind::Constructor { - if method.value.body.is_some() { - constructor = Some(method); - } - } else if let PropertyKey::PrivateIdentifier(ident) = &method.key { + if let PropertyKey::PrivateIdentifier(ident) = &method.key { if method.r#static { has_static_private_method_or_static_block = true; } else { @@ -239,51 +234,6 @@ impl<'a> ClassProperties<'a, '_> { return; } - // Scope that instance property initializers will be inserted into. - // This is usually class constructor, but can also be a `_super` function which is created. - let instance_inits_scope_id; - // Scope of class constructor, if instance property initializers will be inserted into constructor. - // Used for checking for variable name clashes. - // e.g. `class C { prop = x(); constructor(x) {} }` - // - `x` in constructor needs to be renamed when `x()` is moved into constructor body. - // `None` if class has no existing constructor, as then there can't be any clashes. - let mut instance_inits_constructor_scope_id = None; - - // Determine where to insert instance property initializers in constructor - let instance_inits_insert_location = if let Some(constructor) = constructor { - // Existing constructor - let constructor = constructor.value.as_mut(); - if has_super_class { - let (insert_scopes, insert_location) = - Self::replace_super_in_constructor(constructor, ctx); - instance_inits_scope_id = insert_scopes.insert_in_scope_id; - instance_inits_constructor_scope_id = insert_scopes.constructor_scope_id; - insert_location - } else { - let constructor_scope_id = constructor.scope_id(); - instance_inits_scope_id = constructor_scope_id; - // Only record `constructor_scope_id` if constructor's scope has some bindings. - // If it doesn't, no need to check for shadowed symbols in instance prop initializers, - // because no bindings to clash with. - instance_inits_constructor_scope_id = - if ctx.scoping().get_bindings(constructor_scope_id).is_empty() { - None - } else { - Some(constructor_scope_id) - }; - InstanceInitsInsertLocation::ExistingConstructor(0) - } - } else { - // No existing constructor - create scope for one - let constructor_scope_id = ctx.scoping_mut().add_scope( - Some(class_scope_id), - NodeId::DUMMY, - ScopeFlags::Function | ScopeFlags::Constructor | ScopeFlags::StrictMode, - ); - instance_inits_scope_id = constructor_scope_id; - InstanceInitsInsertLocation::NewConstructor - }; - // Extract instance properties initializers. // // We leave the properties themselves in place, but take the initializers. @@ -326,6 +276,49 @@ impl<'a> ClassProperties<'a, '_> { } } + // Scope that instance property initializers will be inserted into. + // This is usually class constructor, but can also be a `_super` function which is created. + let instance_inits_scope_id; + // Scope of class constructor, if instance property initializers will be inserted into constructor. + // Used for checking for variable name clashes. + // e.g. `class C { prop = x(); constructor(x) {} }` + // - `x` in constructor needs to be renamed when `x()` is moved into constructor body. + // `None` if class has no existing constructor, as then there can't be any clashes. + let mut instance_inits_constructor_scope_id = None; + + // Determine where to insert instance property initializers in constructor + let instance_inits_insert_location = if let Some(constructor) = constructor.as_deref_mut() { + if has_super_class { + let (insert_scopes, insert_location) = + Self::replace_super_in_constructor(constructor, ctx); + instance_inits_scope_id = insert_scopes.insert_in_scope_id; + instance_inits_constructor_scope_id = insert_scopes.constructor_scope_id; + insert_location + } else { + let constructor_scope_id = constructor.scope_id(); + instance_inits_scope_id = constructor_scope_id; + // Only record `constructor_scope_id` if constructor's scope has some bindings. + // If it doesn't, no need to check for shadowed symbols in instance prop initializers, + // because no bindings to clash with. + instance_inits_constructor_scope_id = + if ctx.scoping().get_bindings(constructor_scope_id).is_empty() { + None + } else { + Some(constructor_scope_id) + }; + InstanceInitsInsertLocation::ExistingConstructor(0) + } + } else { + // No existing constructor - create scope for one + let constructor_scope_id = ctx.scoping_mut().add_scope( + Some(class_scope_id), + NodeId::DUMMY, + ScopeFlags::Function | ScopeFlags::Constructor | ScopeFlags::StrictMode, + ); + instance_inits_scope_id = constructor_scope_id; + InstanceInitsInsertLocation::NewConstructor + }; + // Reparent property initializers scope to `instance_inits_scope_id`. self.reparent_initializers_scope( instance_inits.as_slice(),