refactor(transformer/class-properties): move supers to super_converter (#8103)

Move to a separate struct, and then we can use it in other places. See #8106
This commit is contained in:
Dunqing 2024-12-31 12:30:53 +00:00
parent 58ed83242a
commit d82fb52fa5
3 changed files with 62 additions and 23 deletions

View file

@ -183,8 +183,8 @@
//! * `static_block_and_prop_init.rs`: Transform of static property initializers and static blocks.
//! * `computed_key.rs`: Transform of property/method computed keys.
//! * `private_field.rs`: Transform of private fields (`this.#prop`).
//! * `private_method.rs`: Transform of private methods (`this.#method()`).
//! * `super.rs`: Transform `super` expressions.
//! * `private_method.rs`: Transform of private methods (`this.#method()`).
//! * `super_converter.rs`: Transform `super` expressions.
//! * `class_details.rs`: Structures containing details of classes and private properties.
//! * `class_bindings.rs`: Structure containing bindings for class name and temp var.
//! * `utils.rs`: Utility functions.
@ -218,7 +218,7 @@ mod private_field;
mod private_method;
mod prop_decl;
mod static_block_and_prop_init;
mod supers;
mod super_converter;
mod utils;
use class_bindings::ClassBindings;
use class_details::{ClassDetails, ClassesStack, PrivateProp, ResolvedPrivateProp};

View file

@ -11,7 +11,10 @@ use oxc_syntax::scope::{ScopeFlags, ScopeId};
use oxc_traverse::TraverseCtx;
use super::super::ClassStaticBlock;
use super::ClassProperties;
use super::{
super_converter::{ClassPropertiesSuperConverter, ClassPropertiesSuperConverterMode},
ClassProperties,
};
impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
/// Transform static property initializer.
@ -179,8 +182,8 @@ struct StaticVisitor<'a, 'ctx, 'v> {
/// the `ScopeId` of the old static block, so we don't need to reparent scopes anyway,
/// so `scope_depth` is ignored.
scope_depth: u32,
/// Main transform instance.
class_properties: &'v mut ClassProperties<'a, 'ctx>,
/// Converter for `super` expressions.
super_converter: ClassPropertiesSuperConverter<'a, 'ctx, 'v>,
/// `TraverseCtx` object.
ctx: &'v mut TraverseCtx<'a>,
}
@ -200,7 +203,17 @@ impl<'a, 'ctx, 'v> StaticVisitor<'a, 'ctx, 'v> {
#[expect(clippy::bool_to_int_with_if)]
let scope_depth = if reparent_scopes { 0 } else { 1 };
Self { walk_deep, make_sloppy_mode, this_depth: 0, scope_depth, class_properties, ctx }
Self {
walk_deep,
make_sloppy_mode,
this_depth: 0,
scope_depth,
super_converter: ClassPropertiesSuperConverter::new(
ClassPropertiesSuperConverterMode::Static,
class_properties,
),
ctx,
}
}
}
@ -476,7 +489,7 @@ impl<'a, 'ctx, 'v> StaticVisitor<'a, 'ctx, 'v> {
/// Replace `this` with reference to temp var for class.
fn replace_this_with_temp_var(&mut self, expr: &mut Expression<'a>, span: Span) {
if self.this_depth == 0 {
let class_details = self.class_properties.current_class_mut();
let class_details = self.super_converter.class_properties.current_class_mut();
let temp_binding = class_details.bindings.get_or_init_static_binding(self.ctx);
*expr = temp_binding.create_spanned_read_expression(span, self.ctx);
}
@ -485,7 +498,7 @@ impl<'a, 'ctx, 'v> StaticVisitor<'a, 'ctx, 'v> {
/// Replace reference to class name with reference to temp var for class.
fn replace_class_name_with_temp_var(&mut self, ident: &mut IdentifierReference<'a>) {
// Check identifier is reference to class name
let class_details = self.class_properties.current_class_mut();
let class_details = self.super_converter.class_properties.current_class_mut();
let class_name_symbol_id = class_details.bindings.name_symbol_id();
let Some(class_name_symbol_id) = class_name_symbol_id else { return };
@ -527,7 +540,7 @@ impl<'a, 'ctx, 'v> StaticVisitor<'a, 'ctx, 'v> {
#[inline]
fn transform_static_member_expression_if_super(&mut self, expr: &mut Expression<'a>) {
if self.this_depth == 0 {
self.class_properties.transform_static_member_expression(expr, self.ctx);
self.super_converter.transform_static_member_expression(expr, self.ctx);
}
}
@ -535,7 +548,7 @@ impl<'a, 'ctx, 'v> StaticVisitor<'a, 'ctx, 'v> {
#[inline]
fn transform_computed_member_expression_if_super(&mut self, expr: &mut Expression<'a>) {
if self.this_depth == 0 {
self.class_properties.transform_computed_member_expression(expr, self.ctx);
self.super_converter.transform_computed_member_expression(expr, self.ctx);
}
}
@ -546,7 +559,7 @@ impl<'a, 'ctx, 'v> StaticVisitor<'a, 'ctx, 'v> {
call_expr: &mut CallExpression<'a>,
) {
if self.this_depth == 0 {
self.class_properties
self.super_converter
.transform_call_expression_for_super_member_expr(call_expr, self.ctx);
}
}
@ -559,7 +572,7 @@ impl<'a, 'ctx, 'v> StaticVisitor<'a, 'ctx, 'v> {
expr: &mut Expression<'a>,
) {
if self.this_depth == 0 {
self.class_properties
self.super_converter
.transform_assignment_expression_for_super_assignment_target(expr, self.ctx);
}
}
@ -572,7 +585,7 @@ impl<'a, 'ctx, 'v> StaticVisitor<'a, 'ctx, 'v> {
expr: &mut Expression<'a>,
) {
if self.this_depth == 0 {
self.class_properties
self.super_converter
.transform_update_expression_for_super_assignment_target(expr, self.ctx);
}
}

View file

@ -10,7 +10,29 @@ use crate::Helper;
use super::{utils::create_assignment, ClassProperties};
impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
#[derive(Debug)]
pub(super) enum ClassPropertiesSuperConverterMode {
// `static prop` or `static {}`
Static,
}
/// Convert `super` expressions.
pub(super) struct ClassPropertiesSuperConverter<'a, 'ctx, 'v> {
#[expect(unused)]
mode: ClassPropertiesSuperConverterMode,
pub(super) class_properties: &'v mut ClassProperties<'a, 'ctx>,
}
impl<'a, 'ctx, 'v> ClassPropertiesSuperConverter<'a, 'ctx, 'v> {
pub(super) fn new(
mode: ClassPropertiesSuperConverterMode,
class_properties: &'v mut ClassProperties<'a, 'ctx>,
) -> Self {
Self { mode, class_properties }
}
}
impl<'a, 'ctx, 'v> ClassPropertiesSuperConverter<'a, 'ctx, 'v> {
/// Transform static member expression where object is `super`.
///
/// `super.prop` -> `_superPropGet(_Class, "prop", _Class)`
@ -238,7 +260,7 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
self.create_super_prop_set(span, property, value, ctx)
} else {
// Make 2 copies of `object`
let (property1, property2) = self.duplicate_object(property, ctx);
let (property1, property2) = self.class_properties.duplicate_object(property, ctx);
if let Some(operator) = operator.to_binary_operator() {
// `super[prop] += value`
@ -471,13 +493,14 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
// Make 2 copies of `property`
let (property1, property2) = self.duplicate_object(property, ctx);
let (property1, property2) = self.class_properties.duplicate_object(property, ctx);
// `_superPropGet(_Class, prop, _Class)`
let get_call = self.create_super_prop_get(SPAN, property2, false, ctx);
// `_super$prop = _superPropGet(_Class, prop, _Class)`
let temp_binding = self.ctx.var_declarations.create_uid_var(temp_var_name_base, ctx);
let temp_binding =
self.class_properties.ctx.var_declarations.create_uid_var(temp_var_name_base, ctx);
let assignment = create_assignment(&temp_binding, get_call, ctx);
// `++_super$prop` / `_super$prop++` (reusing existing `UpdateExpression`)
@ -498,7 +521,8 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
} else {
// Source = `super.prop++` (postfix `++`)
// `_super$prop2 = _super$prop++`
let temp_binding2 = self.ctx.var_declarations.create_uid_var(temp_var_name_base, ctx);
let temp_binding2 =
self.class_properties.ctx.var_declarations.create_uid_var(temp_var_name_base, ctx);
let assignment2 = create_assignment(&temp_binding2, update_expr, ctx);
// `(_super$prop = _superPropGet(_Class, prop, _Class), _super$prop2 = _super$prop++, _super$prop)`
@ -533,7 +557,8 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
is_callee: bool,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let temp_binding = self.current_class_mut().bindings.get_or_init_static_binding(ctx);
let temp_binding =
self.class_properties.current_class_mut().bindings.get_or_init_static_binding(ctx);
let ident1 = Argument::from(temp_binding.create_read_expression(ctx));
let ident2 = Argument::from(temp_binding.create_read_expression(ctx));
@ -549,7 +574,7 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
};
// `_superPropGet(_Class, prop, _Class)` or `_superPropGet(_Class, prop, _Class, 2)`
self.ctx.helper_call_expr(Helper::SuperPropGet, span, arguments, ctx)
self.class_properties.ctx.helper_call_expr(Helper::SuperPropGet, span, arguments, ctx)
}
/// `_superPropSet(_Class, prop, value, _Class, 1)`
@ -560,7 +585,8 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
value: Expression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let temp_binding = self.current_class_mut().bindings.get_or_init_static_binding(ctx);
let temp_binding =
self.class_properties.current_class_mut().bindings.get_or_init_static_binding(ctx);
let arguments = ctx.ast.vec_from_array([
Argument::from(temp_binding.create_read_expression(ctx)),
Argument::from(property),
@ -573,6 +599,6 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
NumberBase::Decimal,
)),
]);
self.ctx.helper_call_expr(Helper::SuperPropSet, span, arguments, ctx)
self.class_properties.ctx.helper_call_expr(Helper::SuperPropSet, span, arguments, ctx)
}
}