diff --git a/crates/oxc_transformer/src/es2022/class_properties/mod.rs b/crates/oxc_transformer/src/es2022/class_properties/mod.rs index 3e3385e12f3fc..0a64061361c6b 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/mod.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/mod.rs @@ -252,7 +252,8 @@ impl<'a, 'ctx> Traverse<'a> for ClassProperties<'a, 'ctx> { // `#[inline]` because this is a hot path #[inline] fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { - // Note: `delete this.#prop` is an early syntax error, so no need to handle transforming it + // IMPORTANT: If add any other visitors here to handle private fields, + // also need to add them to visitor in `static_prop.rs`. match expr { // `class {}` Expression::ClassExpression(_) => { diff --git a/crates/oxc_transformer/src/es2022/class_properties/private.rs b/crates/oxc_transformer/src/es2022/class_properties/private.rs index 6cc87e24f0a0a..b646fac317b8b 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/private.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/private.rs @@ -1375,12 +1375,15 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> { } } - fn transform_unary_expression_impl( + // Note: This is also called by visitor in `static_prop.rs` + pub(super) fn transform_unary_expression_impl( &mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>, ) { let Expression::UnaryExpression(unary_expr) = expr else { unreachable!() }; + debug_assert!(unary_expr.operator == UnaryOperator::Delete); + debug_assert!(matches!(unary_expr.argument, Expression::ChainExpression(_))); if let Some((result, chain_expr)) = self.transform_chain_expression_impl(&mut unary_expr.argument, ctx) diff --git a/crates/oxc_transformer/src/es2022/class_properties/static_prop.rs b/crates/oxc_transformer/src/es2022/class_properties/static_prop.rs index ab55ab4d4fde9..fa8b0f7578a3e 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/static_prop.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/static_prop.rs @@ -163,14 +163,23 @@ impl<'a, 'ctx, 'v> VisitMut<'a> for StaticInitializerVisitor<'a, 'ctx, 'v> { self.replace_this_with_temp_var(expr, span); return; } - // `delete this` + // `delete this` / `delete object?.#prop.xyz` Expression::UnaryExpression(unary_expr) => { - if unary_expr.operator == UnaryOperator::Delete - && matches!(&unary_expr.argument, Expression::ThisExpression(_)) - { - let span = unary_expr.span; - self.replace_delete_this_with_true(expr, span); - return; + if unary_expr.operator == UnaryOperator::Delete { + match &unary_expr.argument { + Expression::ThisExpression(_) => { + let span = unary_expr.span; + self.replace_delete_this_with_true(expr, span); + return; + } + Expression::ChainExpression(_) => { + // Call directly into `transform_unary_expression_impl` rather than + // main entry point `transform_unary_expression`. We already checked that + // `expr` is `delete `, so can avoid checking that again. + self.class_properties.transform_unary_expression_impl(expr, self.ctx); + } + _ => {} + } } } // `object.#prop`