Skip to content

Commit

Permalink
feat(transformer/logical-assignment-operators): no temp vars for lite…
Browse files Browse the repository at this point in the history
…rals (#7759)

`TransformCtx::duplicate_expression` (introduced in #7754) don't create temp vars for literals. This produces more compact output for the logical assignment operators transform.

This diverges from Babel (it's better!) so add an override for one of Babel's fixtures. Also add further tests for all literal types.
  • Loading branch information
overlookmotel committed Dec 10, 2024
1 parent 8f8b4c3 commit e010b6a
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 8 deletions.
25 changes: 20 additions & 5 deletions crates/oxc_transformer/src/common/duplicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{
ptr,
};

use oxc_allocator::CloneIn;
use oxc_ast::ast::{AssignmentOperator, Expression};
use oxc_span::SPAN;
use oxc_syntax::reference::ReferenceFlags;
Expand Down Expand Up @@ -109,13 +110,27 @@ impl<'a> TransformCtx<'a> {

self.var_declarations.create_uid_var(&ident.name, ctx)
}
// Reading `this` or `super` cannot have side effects, so no need for temp var
Expression::ThisExpression(this) => {
let references = create_array(|| ctx.ast.expression_this(this.span));
// Reading any of these cannot have side effects, so no need for temp var
Expression::ThisExpression(_)
| Expression::Super(_)
| Expression::BooleanLiteral(_)
| Expression::NullLiteral(_)
| Expression::NumericLiteral(_)
| Expression::BigIntLiteral(_)
| Expression::RegExpLiteral(_)
| Expression::StringLiteral(_) => {
let references = create_array(|| expr.clone_in(ctx.ast.allocator));
return (expr, references);
}
Expression::Super(super_expr) => {
let references = create_array(|| ctx.ast.expression_super(super_expr.span));
// Template literal can have no side effects if it has no expressions
Expression::TemplateLiteral(lit) if lit.expressions.is_empty() => {
let references = create_array(|| {
ctx.ast.expression_template_literal(
lit.span,
lit.quasis.clone_in(ctx.ast.allocator),
ctx.ast.vec(),
)
});
return (expr, references);
}
// Anything else requires temp var
Expand Down
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/semantic_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -42409,8 +42409,8 @@ rebuilt : ["a", "b", "c", "d", "e", "f", "g", "h", "i"]

tasks/coverage/typescript/tests/cases/conformance/es2021/logicalAssignment/logicalAssignment2.ts
semantic error: Bindings mismatch:
after transform: ScopeId(0): ["A", "_a$foo", "_a$foo$bar", "_b$foo", "_b$foo$bar", "_baz", "_baz2", "_baz3", "_c$baz", "_c$foo", "_c$foo$_baz", "_c$foo$bar", "_c$foo$bar$baz", "a", "b", "c", "result"]
rebuilt : ScopeId(0): ["_a$foo", "_a$foo$bar", "_b$foo", "_b$foo$bar", "_baz", "_baz2", "_baz3", "_c$baz", "_c$foo", "_c$foo$_baz", "_c$foo$bar", "_c$foo$bar$baz"]
after transform: ScopeId(0): ["A", "_a$foo", "_a$foo$bar", "_b$foo", "_b$foo$bar", "_c$baz", "_c$foo", "_c$foo$bar", "_c$foo$bar$baz", "_c$foo$baz", "a", "b", "c", "result"]
rebuilt : ScopeId(0): ["_a$foo", "_a$foo$bar", "_b$foo", "_b$foo$bar", "_c$baz", "_c$foo", "_c$foo$bar", "_c$foo$bar$baz", "_c$foo$baz"]
Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1)]
rebuilt : ScopeId(0): []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var _o, _o2;
let o;
o ?? (o = {});
(_o = o).a ?? (_o.a = 1);
(_o2 = o)["b"] ?? (_o2["b"] = 2);
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: 54a8389f

Passed: 99/111
Passed: 102/114

# All Passed:
* babel-plugin-transform-class-static-block
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
let boundObj;

boundObj[true] &&= 1;
boundObj[null] &&= 2;
boundObj[123] &&= 3;
boundObj[123n] &&= 4;
boundObj[/abc/g] &&= 5;
boundObj["abc"] &&= 6;

unboundObj[true] &&= 7;
unboundObj[null] &&= 8;
unboundObj[123] &&= 9;
unboundObj[123n] &&= 10;
unboundObj[/abc/g] &&= 11;
unboundObj["abc"] &&= 12;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var _unboundObj,
_unboundObj2,
_unboundObj3,
_unboundObj4,
_unboundObj5,
_unboundObj6;

let boundObj;

boundObj[true] && (boundObj[true] = 1);
boundObj[null] && (boundObj[null] = 2);
boundObj[123] && (boundObj[123] = 3);
boundObj[123n] && (boundObj[123n] = 4);
boundObj[/abc/g] && (boundObj[/abc/g] = 5);
boundObj["abc"] && (boundObj["abc"] = 6);

(_unboundObj = unboundObj)[true] && (_unboundObj[true] = 7);
(_unboundObj2 = unboundObj)[null] && (_unboundObj2[null] = 8);
(_unboundObj3 = unboundObj)[123] && (_unboundObj3[123] = 9);
(_unboundObj4 = unboundObj)[123n] && (_unboundObj4[123n] = 10);
(_unboundObj5 = unboundObj)[/abc/g] && (_unboundObj5[/abc/g] = 11);
(_unboundObj6 = unboundObj)["abc"] && (_unboundObj6["abc"] = 12);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let boundObj;

boundObj[`abc`] &&= 1;
unboundObj[`abc`] &&= 2;

boundObj[`abc${foo}def`] &&= 3;
unboundObj[`abc${foo}def`] &&= 4;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var _unboundObj,
_ref,
_unboundObj2,
_ref2;

let boundObj;

boundObj[`abc`] && (boundObj[`abc`] = 1);
(_unboundObj = unboundObj)[`abc`] && (_unboundObj[`abc`] = 2);

boundObj[_ref = `abc${foo}def`] && (boundObj[_ref] = 3);
(_unboundObj2 = unboundObj)[_ref2 = `abc${foo}def`] && (_unboundObj2[_ref2] = 4);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let boundProp;

"abc".length &&= 1;
"abc"[boundProp] &&= 2;
"abc"[unboundProp] &&= 3;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var _unboundProp;

let boundProp;

"abc".length && ("abc".length = 1);
"abc"[boundProp] && ("abc"[boundProp] = 2);
"abc"[_unboundProp = unboundProp] && ("abc"[_unboundProp] = 3);

0 comments on commit e010b6a

Please sign in to comment.