Skip to content

Commit

Permalink
fix(transformer): exponentiation transform: do not replace object whe…
Browse files Browse the repository at this point in the history
…n private property (#6313)

Fix exponentiation operator transform to bail out early if a private class property.

We can't transform this:

```js
class C {
    #p;
    method() {
        this.#p **= 2;
    }
}
```

But we should at least leave it alone. Previously `get_obj_ref` called `ast.move_expression(expr)` on the member expression's object before bailing out, so example above was transformed to:

```js
class C {
    #p;
    method() {
        null.#p **= 2; // <-- `null`
    }
}
```

This PR makes it spot this case early and bail out *before* calling `ast.move_expression(expr)`.
  • Loading branch information
overlookmotel committed Oct 6, 2024
1 parent fe25b65 commit ccb7bdc
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 15 deletions.
29 changes: 15 additions & 14 deletions crates/oxc_transformer/src/es2016/exponentiation_operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
(ident, obj)
}
match_member_expression!(AssignmentTarget) => {
let obj = self.get_obj_ref(node, nodes, ctx).unwrap();
let obj = self.get_obj_ref(node, nodes, ctx)?;
let member_expr = node.to_member_expression_mut();
let computed = member_expr.is_computed();
let prop = self.get_prop_ref(member_expr, nodes, ctx)?;
let prop = self.get_prop_ref(member_expr, nodes, ctx);
let optional = false;
let obj_clone = Self::clone_expression(&obj, ctx);
let (reference, uid) = match &prop {
Expand Down Expand Up @@ -248,7 +248,11 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
let expr = match node.to_member_expression_mut() {
MemberExpression::ComputedMemberExpression(e) => &mut e.object,
MemberExpression::StaticMemberExpression(e) => &mut e.object,
MemberExpression::PrivateFieldExpression(e) => &mut e.object,
// From Babel: "We can't generate property ref for private name, please install
// `@babel/plugin-transform-class-properties`".
// TODO: Ensure this plugin interacts correctly with class private properties
// transform, so the property is transformed before this transform.
MemberExpression::PrivateFieldExpression(_) => return None,
};
let expr = ctx.ast.move_expression(expr);
// the object reference that we need to save is locally declared
Expand Down Expand Up @@ -277,24 +281,21 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
node: &mut MemberExpression<'a>,
nodes: &mut Vec<'a, Expression<'a>>,
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
let expr = match node {
) -> Expression<'a> {
match node {
MemberExpression::ComputedMemberExpression(expr) => {
let expr = ctx.ast.move_expression(&mut expr.expression);
if expr.is_literal() {
return Some(expr);
return expr;
}
expr
self.add_new_reference(expr, nodes, ctx)
}
MemberExpression::StaticMemberExpression(expr) => {
return Some(ctx.ast.expression_string_literal(SPAN, expr.property.name.clone()));
}
MemberExpression::PrivateFieldExpression(_) => {
// From babel: "We can't generate property ref for private name, please install `@babel/plugin-transform-class-properties`"
return None;
ctx.ast.expression_string_literal(SPAN, expr.property.name.clone())
}
};
Some(self.add_new_reference(expr, nodes, ctx))
// This possibility is ruled out in earlier call to `get_obj_ref`
MemberExpression::PrivateFieldExpression(_) => unreachable!(),
}
}

fn add_new_reference(
Expand Down
2 changes: 1 addition & 1 deletion tasks/transform_conformance/snapshots/oxc.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 3bcfee23

Passed: 56/65
Passed: 57/66

# All Passed:
* babel-plugin-transform-nullish-coalescing-operator
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class C {
#p = 1;

method(obj) {
obj.x **= 2; // Transform
obj['y'] **= 3; // Transform
obj.#p **= 4; // Bail
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class C {
#p = 1;

method(obj) {
obj["x"] = Math.pow(obj["x"], 2);
obj["y"] = Math.pow(obj["y"], 3);
obj.#p **= 4;
}
}

0 comments on commit ccb7bdc

Please sign in to comment.