Skip to content

Commit

Permalink
Transform private field expressions WIP 2
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Nov 15, 2024
1 parent da23b14 commit 53007ed
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 18 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_transformer/src/common/helper_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ pub enum Helper {
DefineProperty,
ClassPrivateFieldInitSpec,
ClassPrivateFieldGet,
AssertClassBrand,
}

impl Helper {
Expand All @@ -160,6 +161,7 @@ impl Helper {
Self::DefineProperty => "defineProperty",
Self::ClassPrivateFieldInitSpec => "classPrivateFieldInitSpec",
Self::ClassPrivateFieldGet => "classPrivateFieldGet",
Self::AssertClassBrand => "assertClassBrand",
}
}
}
Expand Down
54 changes: 36 additions & 18 deletions crates/oxc_transformer/src/es2022/class_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,20 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
// Convert to assignment or `_defineProperty` call, depending on `loose` option.
// TODO(improve-on-babel): Even though private static properties may not access class name,
// Babel still creates a temp var for class. That's unnecessary.
let class_binding = self.initialize_class_name_binding(ctx);

if let PropertyKey::PrivateIdentifier(ident) = &mut prop.key {
self.insert_private_static_init_assignment(ident, value, ctx);
} else {
// Convert to assignment or `_defineProperty` call, depending on `loose` option
let assignee = class_binding.create_read_expression(ctx);
let init_expr = self.create_init_assignment(prop, value, assignee, ctx);
self.insert_expr_after_class(init_expr, ctx);
}
}

/// Create a binding for class name, if there isn't one already.
fn initialize_class_name_binding(&mut self, ctx: &mut TraverseCtx<'a>) -> &BoundIdentifier<'a> {
if let ClassName::Name(name) = &self.class_name {
let binding = if self.is_declaration {
// Can only not have a binding if is `export default class {}`
Expand All @@ -606,16 +620,8 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
};
self.class_name = ClassName::Binding(binding);
}
let ClassName::Binding(class_binding) = &self.class_name else { unreachable!() };

if let PropertyKey::PrivateIdentifier(ident) = &mut prop.key {
self.insert_private_static_init_assignment(ident, value, ctx);
} else {
// Convert to assignment or `_defineProperty` call, depending on `loose` option
let assignee = class_binding.create_read_expression(ctx);
let init_expr = self.create_init_assignment(prop, value, assignee, ctx);
self.insert_expr_after_class(init_expr, ctx);
}
let ClassName::Binding(binding) = &self.class_name else { unreachable!() };
binding
}

/// `assignee.foo = value` or `_defineProperty(assignee, "foo", value)`
Expand Down Expand Up @@ -948,23 +954,35 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
}

fn transform_private_field_expression_impl(
&self,
&mut self,
field_expr: ArenaBox<'a, PrivateFieldExpression<'a>>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let field_expr = field_expr.unbox();

let prop = self.lookup_private_property(&field_expr.field);
if prop.is_static && false {
// TODO
todo!();
} else {
let prop_ident = prop.binding.create_read_expression(ctx);

let (helper, arguments) = if prop.is_static {
// `_assertClassBrand(Class, this, _prop)`
// TODO: Temp var for class is created in wrong scope when is a class expression.
// It should already be initialized anyway.
// Need to store `class_name` on stack, because could be from an enclosing class.
let class_binding = self.initialize_class_name_binding(ctx);
let arguments = ctx.ast.vec_from_iter([
Argument::from(prop.binding.create_read_expression(ctx)),
Argument::from(class_binding.create_read_expression(ctx)),
Argument::from(field_expr.object),
Argument::from(prop_ident),
]);
self.ctx.helper_call_expr(Helper::ClassPrivateFieldGet, field_expr.span, arguments, ctx)
}
(Helper::AssertClassBrand, arguments)
} else {
// `_classPrivateFieldGet(_prop, this)`
let arguments = [Argument::from(prop_ident), Argument::from(field_expr.object)];
let arguments = ctx.ast.vec_from_iter(arguments);
(Helper::ClassPrivateFieldGet, arguments)
};

self.ctx.helper_call_expr(helper, field_expr.span, arguments, ctx)
}

fn lookup_private_property(&self, ident: &PrivateIdentifier<'a>) -> &PrivateProp<'a> {
Expand Down

0 comments on commit 53007ed

Please sign in to comment.