Skip to content

Commit

Permalink
feat(transformer/class-properties): transform callee that is referred…
Browse files Browse the repository at this point in the history
… to a private method
  • Loading branch information
Dunqing committed Dec 26, 2024
1 parent 00a33aa commit 558357d
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 76 deletions.
17 changes: 14 additions & 3 deletions crates/oxc_transformer/src/es2022/class_properties/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,15 +447,16 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
} else {
// TODO: Only call `insert_many_before` if some private *instance* props
let mut weakmap_symbol_id = None;
let has_method = false;
let mut has_method = false;
self.ctx.statement_injector.insert_many_before(
&stmt_address,
private_props.values().filter_map(|prop| {
if prop.is_static || has_method || prop.is_accessor {
if prop.is_static || (prop.is_method && has_method) || prop.is_accessor {
return None;
}
if prop.is_method {
// `var _C_brand = new WeakSet();`
has_method = true;
let binding = class_details.bindings.brand();
let value = create_new_weakset(ctx);
Some(create_variable_declaration(binding, value, ctx))
Expand Down Expand Up @@ -587,11 +588,21 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
}));
} else {
let mut weakmap_symbol_id = None;
let mut has_method = false;
exprs.extend(private_props.values().filter_map(|prop| {
if prop.is_method || prop.is_accessor {
if (prop.is_method && has_method) || prop.is_accessor {
return None;
}

if prop.is_method {
has_method = true;
// `_C_brand = new WeakSet()`
let binding = class_details.bindings.brand();
self.ctx.var_declarations.insert_var(binding, ctx);
let value = create_new_weakset(ctx);
return Some(create_assignment(binding, value, ctx));
}

// Insert `var _prop;` declaration
self.ctx.var_declarations.insert_var(&prop.binding, ctx);

Expand Down
39 changes: 26 additions & 13 deletions crates/oxc_transformer/src/es2022/class_properties/private_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,7 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
return;
}

let Some((callee, object)) = self.transform_private_field_callee(field_expr, ctx) else {
return;
};
let (callee, object) = self.transform_private_field_callee(field_expr, ctx);
Self::substitute_callee_and_insert_context(call_expr, callee, object, ctx);
}

Expand Down Expand Up @@ -260,7 +258,7 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
&mut self,
field_expr: &mut PrivateFieldExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Option<(Expression<'a>, Expression<'a>)> {
) -> (Expression<'a>, Expression<'a>) {
let ResolvedPrivateProp {
prop_binding,
class_bindings,
Expand All @@ -270,12 +268,15 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
is_declaration,
} = self.classes_stack.find_private_prop(&field_expr.field);

let prop_ident = prop_binding.create_read_expression(ctx);

if is_method || is_accessor {
return None;
return (
self.create_assert_class_brand_for_private_method(prop_ident, ctx),
ctx.ast.expression_this(SPAN),
);
};

let prop_ident = prop_binding.create_read_expression(ctx);

// `(object.#method)()`
// ^^^^^^^^^^^^^^^^ is a parenthesized expression
let object = ctx.ast.move_expression(field_expr.object.get_inner_expression_mut());
Expand Down Expand Up @@ -330,7 +331,7 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
(get_call, object2)
};

Some(replacement)
replacement
}

/// Transform assignment to private field.
Expand Down Expand Up @@ -1152,7 +1153,7 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
if matches!(ctx.ancestor(1), Ancestor::CallExpressionCallee(_)) {
// `(Foo?.#m)();` -> `(Foo === null || Foo === void 0 ? void 0 : _m._.bind(Foo))();`
// ^^^^^^^^^^^^ is a call expression, we need to bind the proper context
*expr = self.transform_bindable_private_field(field_expr, ctx).unwrap();
*expr = self.transform_bindable_private_field(field_expr, ctx);
} else {
self.transform_private_field_expression(expr, ctx);
}
Expand Down Expand Up @@ -1573,16 +1574,16 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
);
Some(Expression::from(replacement))
} else {
self.transform_bindable_private_field(field_expr, ctx)
Some(self.transform_bindable_private_field(field_expr, ctx))
}
}

fn transform_bindable_private_field(
&mut self,
field_expr: &mut PrivateFieldExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
let (callee, context) = self.transform_private_field_callee(field_expr, ctx)?;
) -> Expression<'a> {
let (callee, context) = self.transform_private_field_callee(field_expr, ctx);

// Return `<callee>.bind(object)`, to be substituted as tag of tagged template expression
let callee = Expression::from(ctx.ast.member_expression_static(
Expand All @@ -1592,7 +1593,7 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
false,
));
let arguments = ctx.ast.vec1(Argument::from(context));
Some(ctx.ast.expression_call(field_expr.span, callee, NONE, arguments, false))
ctx.ast.expression_call(field_expr.span, callee, NONE, arguments, false)
}

/// Transform private field in assignment pattern.
Expand Down Expand Up @@ -1785,6 +1786,18 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
)
}

/// `_assertClassBrand(_Class_brand, object, _prop)`
#[inline]
fn create_assert_class_brand_for_private_method(
&self,
value_or_prop_ident: Expression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let class_ident = self.current_class().bindings.brand().create_read_expression(ctx);
let object = ctx.ast.expression_this(SPAN);
self.create_assert_class_brand(class_ident, object, value_or_prop_ident, ctx)
}

/// `_assertClassBrand(Class, object, _prop)._`
fn create_assert_class_brand_underscore(
&self,
Expand Down
19 changes: 2 additions & 17 deletions tasks/transform_conformance/snapshots/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 54a8389f

Passed: 623/1095
Passed: 628/1095

# All Passed:
* babel-plugin-transform-logical-assignment-operators
Expand Down Expand Up @@ -462,7 +462,7 @@ x Output mismatch
x Output mismatch


# babel-plugin-transform-private-methods (8/148)
# babel-plugin-transform-private-methods (13/148)
* accessors/arguments/input.js
x Output mismatch

Expand Down Expand Up @@ -565,15 +565,6 @@ x Output mismatch
* misc/multiple/input.js
x Output mismatch

* private-method/assignment/input.js
x Output mismatch

* private-method/async/input.js
x Output mismatch

* private-method/before-fields/input.js
x Output mismatch

* private-method/class-binding/input.js
x Output mismatch

Expand All @@ -589,9 +580,6 @@ x Output mismatch
* private-method/exfiltrated/input.js
x Output mismatch

* private-method/generator/input.js
x Output mismatch

* private-method/read-only/input.js
x Output mismatch

Expand All @@ -601,9 +589,6 @@ x Output mismatch
* private-method/super/input.js
x Output mismatch

* private-method/tagged-template/input.js
x Output mismatch

* private-method-loose/assignment/input.js
x Output mismatch

Expand Down
Loading

0 comments on commit 558357d

Please sign in to comment.