Skip to content

Commit

Permalink
fix(transformer): exponentiation transform: fix temp var names (#6318)
Browse files Browse the repository at this point in the history
Make naming of temp vars follow Babel. It wasn't apparent that our version of this transform was behaving differently from Babel because the Babel plugin has very few tests. The added tests replicate Babel's output.
  • Loading branch information
overlookmotel committed Oct 6, 2024
1 parent c0e2fef commit 3a4bcc7
Show file tree
Hide file tree
Showing 7 changed files with 358 additions and 11 deletions.
4 changes: 4 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ extend-exclude = [
"tasks/coverage/babel",
"tasks/coverage/test262",
"tasks/coverage/typescript",
"tasks/coverage/snapshots",
"tasks/prettier_conformance/prettier",
"tasks/prettier_conformance/snapshots",
"tasks/transform_conformance/tests/**/output.js",
"tasks/transform_conformance/snapshots",
]

[default]
Expand Down
18 changes: 9 additions & 9 deletions crates/oxc_transformer/src/es2016/exponentiation_operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use oxc_ast::{ast::*, NONE};
use oxc_semantic::{ReferenceFlags, SymbolFlags};
use oxc_span::SPAN;
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator};
use oxc_traverse::{Traverse, TraverseCtx};
use oxc_traverse::{ast_operations::get_var_name_from_node, Traverse, TraverseCtx};

use crate::TransformCtx;

Expand Down Expand Up @@ -151,7 +151,8 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
let reference = ctx.ast.expression_from_identifier_reference(
ctx.create_unbound_reference_id(SPAN, ident.name.clone(), ReferenceFlags::Read),
);
self.add_new_reference(reference, &mut nodes, ctx)
let name = ident.name.as_str();
self.add_new_reference(reference, name, &mut nodes, ctx)
};

let reference = ctx.ast.move_assignment_target(assign_target);
Expand Down Expand Up @@ -228,6 +229,7 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
let mut obj = ctx.ast.move_expression(obj);
// If the object reference that we need to save is locally declared, evaluating it multiple times
// will not trigger getters or setters. `super` cannot be directly assigned, so use it directly too.
// TODO(improve-on-babel): We could also skip creating a temp var for `this.x **= 2`.
let needs_temp_var = match &obj {
Expression::Super(_) => false,
Expression::Identifier(ident) => {
Expand All @@ -236,7 +238,8 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
_ => true,
};
if needs_temp_var {
obj = self.add_new_reference(obj, nodes, ctx);
let name = get_var_name_from_node(&obj);
obj = self.add_new_reference(obj, &name, nodes, ctx);
}

let computed = member_expr.is_computed();
Expand Down Expand Up @@ -311,7 +314,8 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
if expr.is_literal() {
return expr;
}
self.add_new_reference(expr, nodes, ctx)
let name = get_var_name_from_node(&expr);
self.add_new_reference(expr, &name, nodes, ctx)
}
MemberExpression::StaticMemberExpression(expr) => {
ctx.ast.expression_string_literal(SPAN, expr.property.name.clone())
Expand All @@ -324,14 +328,10 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
fn add_new_reference(
&mut self,
expr: Expression<'a>,
name: &str,
nodes: &mut Vec<'a, Expression<'a>>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let name = match expr {
Expression::Identifier(ref ident) => ident.name.clone().as_str(),
_ => "ref",
};

let binding = ctx.generate_uid_in_current_scope(name, SymbolFlags::FunctionScopedVariable);

// var _name;
Expand Down
141 changes: 139 additions & 2 deletions tasks/transform_conformance/snapshots/oxc.snap.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,154 @@
commit: 3bcfee23

Passed: 57/66
Passed: 57/68

# All Passed:
* babel-plugin-transform-nullish-coalescing-operator
* babel-plugin-transform-optional-catch-binding
* babel-plugin-transform-exponentiation-operator
* babel-plugin-transform-arrow-functions
* babel-preset-typescript
* babel-plugin-transform-react-jsx-source
* regexp


# babel-plugin-transform-exponentiation-operator (2/4)
* assign-to-identifier/input.js
Reference flags mismatch for "x":
after transform: ReferenceId(6): ReferenceFlags(Write)
rebuilt : ReferenceId(2): ReferenceFlags(Read)
Reference flags mismatch for "_y":
after transform: ReferenceId(9): ReferenceFlags(Write)
rebuilt : ReferenceId(3): ReferenceFlags(Read | Write)
Reference flags mismatch for "_z":
after transform: ReferenceId(13): ReferenceFlags(Write)
rebuilt : ReferenceId(8): ReferenceFlags(Read | Write)
Reference flags mismatch for "_q":
after transform: ReferenceId(17): ReferenceFlags(Write)
rebuilt : ReferenceId(14): ReferenceFlags(Read | Write)

* assign-to-member-expression/input.js
Reference flags mismatch for "_obj$foo$bar":
after transform: ReferenceId(42): ReferenceFlags(Write)
rebuilt : ReferenceId(6): ReferenceFlags(Read | Write)
Reference flags mismatch for "_boundPropName":
after transform: ReferenceId(46): ReferenceFlags(Write)
rebuilt : ReferenceId(11): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundPropName":
after transform: ReferenceId(51): ReferenceFlags(Write)
rebuilt : ReferenceId(18): ReferenceFlags(Read | Write)
Reference flags mismatch for "_obj$foo2$bar":
after transform: ReferenceId(56): ReferenceFlags(Write)
rebuilt : ReferenceId(25): ReferenceFlags(Read | Write)
Reference flags mismatch for "_boundPropName2":
after transform: ReferenceId(58): ReferenceFlags(Write)
rebuilt : ReferenceId(27): ReferenceFlags(Read | Write)
Reference flags mismatch for "_obj$foo3$bar":
after transform: ReferenceId(63): ReferenceFlags(Write)
rebuilt : ReferenceId(34): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundPropName2":
after transform: ReferenceId(65): ReferenceFlags(Write)
rebuilt : ReferenceId(36): ReferenceFlags(Read | Write)
Reference flags mismatch for "_boundPropObj$foo$bar":
after transform: ReferenceId(70): ReferenceFlags(Write)
rebuilt : ReferenceId(43): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundPropObj$foo$b":
after transform: ReferenceId(75): ReferenceFlags(Write)
rebuilt : ReferenceId(50): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj":
after transform: ReferenceId(80): ReferenceFlags(Write)
rebuilt : ReferenceId(57): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj2":
after transform: ReferenceId(84): ReferenceFlags(Write)
rebuilt : ReferenceId(62): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj$foo$bar":
after transform: ReferenceId(88): ReferenceFlags(Write)
rebuilt : ReferenceId(67): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj3":
after transform: ReferenceId(92): ReferenceFlags(Write)
rebuilt : ReferenceId(72): ReferenceFlags(Read | Write)
Reference flags mismatch for "_boundPropName3":
after transform: ReferenceId(94): ReferenceFlags(Write)
rebuilt : ReferenceId(74): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj4":
after transform: ReferenceId(99): ReferenceFlags(Write)
rebuilt : ReferenceId(81): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundPropName3":
after transform: ReferenceId(101): ReferenceFlags(Write)
rebuilt : ReferenceId(83): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj$foo2$bar":
after transform: ReferenceId(106): ReferenceFlags(Write)
rebuilt : ReferenceId(90): ReferenceFlags(Read | Write)
Reference flags mismatch for "_boundPropName4":
after transform: ReferenceId(108): ReferenceFlags(Write)
rebuilt : ReferenceId(92): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj$foo3$bar":
after transform: ReferenceId(113): ReferenceFlags(Write)
rebuilt : ReferenceId(99): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundPropName4":
after transform: ReferenceId(115): ReferenceFlags(Write)
rebuilt : ReferenceId(101): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj5":
after transform: ReferenceId(120): ReferenceFlags(Write)
rebuilt : ReferenceId(108): ReferenceFlags(Read | Write)
Reference flags mismatch for "_boundPropObj2$foo$ba":
after transform: ReferenceId(122): ReferenceFlags(Write)
rebuilt : ReferenceId(110): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundObj6":
after transform: ReferenceId(127): ReferenceFlags(Write)
rebuilt : ReferenceId(117): ReferenceFlags(Read | Write)
Reference flags mismatch for "_unboundPropObj2$foo$":
after transform: ReferenceId(129): ReferenceFlags(Write)
rebuilt : ReferenceId(119): ReferenceFlags(Read | Write)
Reference flags mismatch for "_fn":
after transform: ReferenceId(134): ReferenceFlags(Write)
rebuilt : ReferenceId(126): ReferenceFlags(Read | Write)
Reference flags mismatch for "_fn$foo$bar":
after transform: ReferenceId(138): ReferenceFlags(Write)
rebuilt : ReferenceId(131): ReferenceFlags(Read | Write)
Reference flags mismatch for "_fn$prop":
after transform: ReferenceId(142): ReferenceFlags(Write)
rebuilt : ReferenceId(136): ReferenceFlags(Read | Write)
Reference flags mismatch for "_fn2":
after transform: ReferenceId(144): ReferenceFlags(Write)
rebuilt : ReferenceId(138): ReferenceFlags(Read | Write)
Reference flags mismatch for "_fn$prop2":
after transform: ReferenceId(149): ReferenceFlags(Write)
rebuilt : ReferenceId(145): ReferenceFlags(Read | Write)
Reference flags mismatch for "_ref":
after transform: ReferenceId(151): ReferenceFlags(Write)
rebuilt : ReferenceId(147): ReferenceFlags(Read | Write)
Reference flags mismatch for "_this":
after transform: ReferenceId(156): ReferenceFlags(Write)
rebuilt : ReferenceId(154): ReferenceFlags(Read | Write)
Reference flags mismatch for "_this$foo$bar":
after transform: ReferenceId(160): ReferenceFlags(Write)
rebuilt : ReferenceId(158): ReferenceFlags(Read | Write)
Reference flags mismatch for "_this2":
after transform: ReferenceId(164): ReferenceFlags(Write)
rebuilt : ReferenceId(162): ReferenceFlags(Read | Write)
Reference flags mismatch for "_this3":
after transform: ReferenceId(168): ReferenceFlags(Write)
rebuilt : ReferenceId(166): ReferenceFlags(Read | Write)
Reference flags mismatch for "_fn4$foo$bar$qux":
after transform: ReferenceId(170): ReferenceFlags(Write)
rebuilt : ReferenceId(167): ReferenceFlags(Read | Write)
Reference flags mismatch for "_this4":
after transform: ReferenceId(175): ReferenceFlags(Write)
rebuilt : ReferenceId(174): ReferenceFlags(Read | Write)
Reference flags mismatch for "_this$foo$bar2":
after transform: ReferenceId(179): ReferenceFlags(Write)
rebuilt : ReferenceId(178): ReferenceFlags(Read | Write)
Reference flags mismatch for "_this5":
after transform: ReferenceId(183): ReferenceFlags(Write)
rebuilt : ReferenceId(182): ReferenceFlags(Read | Write)
Reference flags mismatch for "_this6":
after transform: ReferenceId(187): ReferenceFlags(Write)
rebuilt : ReferenceId(186): ReferenceFlags(Read | Write)
Reference flags mismatch for "_fn4$foo$bar$qux2":
after transform: ReferenceId(189): ReferenceFlags(Write)
rebuilt : ReferenceId(187): ReferenceFlags(Read | Write)


# babel-plugin-transform-typescript (1/8)
* class-property-definition/input.ts
Unresolved references mismatch:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let x, fn;
x **= 2;
y **= 3;
z **= fn();
q **= unboundFn();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var _y, _z, _q;
let x, fn;
x = Math.pow(x, 2);
_y = y, y = Math.pow(_y, 3);
_z = z, z = Math.pow(_z, fn());
_q = q, q = Math.pow(_q, unboundFn());
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Bound root of member expression
let obj;
obj.prop **= 2;
obj['prop blah'] **= 3;
obj.foo.bar.qux **= 4;

let boundPropName;
obj[boundPropName] **= 5;
obj[unboundPropName] **= 6;

let boundPropName2;
obj.foo2.bar2[boundPropName2] **= 7;
obj.foo3.bar3[unboundPropName2] **= 8;

let boundPropObj;
obj[boundPropObj.foo.bar.qux] **= 9;
obj[unboundPropObj.foo.bar.qux] **= 10;

// Unbound root of member expression
unboundObj.prop **= 11;
unboundObj['prop blah'] **= 12;
unboundObj.foo.bar.qux **= 13;

let boundPropName3;
unboundObj[boundPropName3] **= 14;
unboundObj[unboundPropName3] **= 15;

let boundPropName4;
unboundObj.foo2.bar2[boundPropName4] **= 16;
unboundObj.foo3.bar3[unboundPropName4] **= 17;

let boundPropObj2;
unboundObj[boundPropObj2.foo.bar.qux] **= 18;
unboundObj[unboundPropObj2.foo.bar.qux] **= 19;

// Other expressions
let fn, fn2;
fn().prop **= 20;
fn().foo().bar().qux **= 21;
fn().prop[fn2()] **= 22;
fn().prop[fn3().foo().bar().qux() + ' junk'] **= 23;

// `this`
this.prop **= 24;
this.foo.bar.qux **= 25;
this['prop blah'] **= 26;
this[fn4().foo.bar.qux()] **= 27;

function outer() {
this.prop **= 28;
this.foo.bar.qux **= 29;
this['prop blah'] **= 30;
this[fn4().foo.bar.qux()] **= 31;
}
Loading

0 comments on commit 3a4bcc7

Please sign in to comment.