fix(transformer/class-properties): transform delete chain expression in static prop initializers (#7656)

Follow-on after #7575. Annoyingly, we have to transform private fields in static prop initializers separately, to make sure the stack of private properties is in sync while visiting them.
This commit is contained in:
overlookmotel 2024-12-05 01:07:18 +00:00
parent 44fe854231
commit ad76d1d72d
3 changed files with 22 additions and 9 deletions

View file

@ -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(_) => {

View file

@ -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)

View file

@ -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 <chain expression>`, so can avoid checking that again.
self.class_properties.transform_unary_expression_impl(expr, self.ctx);
}
_ => {}
}
}
}
// `object.#prop`