mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
refactor(transformer): exponentiation transform: do not wrap in SequenceExpression if not needed (#6343)
`left **= right` is transformed to `left = Math.pow(left, right)`. There is no need to wrap it in a `SequenceExpression`.
This commit is contained in:
parent
0dd9a2ecf3
commit
4aa4e6bec0
4 changed files with 46 additions and 9 deletions
|
|
@ -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::{BoundIdentifier, Traverse, TraverseCtx};
|
||||
use oxc_traverse::{Ancestor, BoundIdentifier, Traverse, TraverseCtx};
|
||||
|
||||
use crate::TransformCtx;
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
|
|||
/// Get left side of `Math.pow(pow_left, ...)` for identifier
|
||||
fn get_pow_left_identifier(
|
||||
&mut self,
|
||||
ident: &IdentifierReference<'a>,
|
||||
ident: &mut IdentifierReference<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> (
|
||||
// Left side of `Math.pow(pow_left, ...)`
|
||||
|
|
@ -153,10 +153,16 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
|
|||
let mut temp_var_inits = ctx.ast.vec();
|
||||
|
||||
// Make sure side-effects of evaluating `left` only happen once
|
||||
let symbol_id = ctx.symbols().get_reference(ident.reference_id().unwrap()).symbol_id();
|
||||
let pow_left = if let Some(symbol_id) = symbol_id {
|
||||
let reference = ctx.scoping.symbols_mut().get_reference_mut(ident.reference_id().unwrap());
|
||||
let pow_left = if let Some(symbol_id) = reference.symbol_id() {
|
||||
// This variable is declared in scope so evaluating it multiple times can't trigger a getter.
|
||||
// No need for a temp var.
|
||||
// `left **= right` is being transformed to `left = Math.pow(left, right)`,
|
||||
// so if `left` is no longer being read from, update its `ReferenceFlags`.
|
||||
if matches!(ctx.ancestry.parent(), Ancestor::ExpressionStatementExpression(_)) {
|
||||
*reference.flags_mut() = ReferenceFlags::Write;
|
||||
}
|
||||
|
||||
ctx.ast.expression_from_identifier_reference(ctx.create_bound_reference_id(
|
||||
SPAN,
|
||||
ident.name.clone(),
|
||||
|
|
@ -447,15 +453,17 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
|
|||
assign_expr.operator = AssignmentOperator::Assign;
|
||||
}
|
||||
|
||||
/// Replace expression `expr` with `(temp1, temp2, expr)` (temp1, temp2 etc from `temp_var_inits`)
|
||||
/// If needs temp var initializers, replace expression `expr` with `(temp1, temp2, expr)`.
|
||||
fn revise_expression(
|
||||
expr: &mut Expression<'a>,
|
||||
mut temp_var_inits: Vec<'a, Expression<'a>>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) {
|
||||
temp_var_inits.reserve_exact(1);
|
||||
temp_var_inits.push(ctx.ast.move_expression(expr));
|
||||
*expr = ctx.ast.expression_sequence(SPAN, temp_var_inits);
|
||||
if !temp_var_inits.is_empty() {
|
||||
temp_var_inits.reserve_exact(1);
|
||||
temp_var_inits.push(ctx.ast.move_expression(expr));
|
||||
*expr = ctx.ast.expression_sequence(SPAN, temp_var_inits);
|
||||
}
|
||||
}
|
||||
|
||||
/// `Math.pow(left, right)`
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
commit: 3bcfee23
|
||||
|
||||
Passed: 59/68
|
||||
Passed: 60/69
|
||||
|
||||
# All Passed:
|
||||
* babel-plugin-transform-nullish-coalescing-operator
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
let bound, boundObj, boundProp;
|
||||
|
||||
x = bound **= 1;
|
||||
x = unbound **= 2;
|
||||
|
||||
x = boundObj.prop **= 3;
|
||||
x = unboundObj.prop **= 4;
|
||||
x = boundObj.foo.bar.qux **= 5;
|
||||
x = unboundObj.foo.bar.qux **= 6;
|
||||
|
||||
x = boundObj[boundProp] **= 7;
|
||||
x = boundObj[unboundProp] **= 8;
|
||||
x = unboundObj[boundProp] **= 9;
|
||||
x = unboundObj[unboundProp] **= 10;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
var _unbound, _unboundObj, _boundObj$foo$bar, _unboundObj$foo$bar, _boundProp, _unboundProp, _unboundObj2, _boundProp2, _unboundObj3, _unboundProp2;
|
||||
let bound, boundObj, boundProp;
|
||||
|
||||
x = bound = Math.pow(bound, 1);
|
||||
x = (_unbound = unbound, unbound = Math.pow(_unbound, 2));
|
||||
|
||||
x = boundObj["prop"] = Math.pow(boundObj["prop"], 3);
|
||||
x = (_unboundObj = unboundObj, _unboundObj["prop"] = Math.pow(_unboundObj["prop"], 4));
|
||||
x = (_boundObj$foo$bar = boundObj.foo.bar, _boundObj$foo$bar["qux"] = Math.pow(_boundObj$foo$bar["qux"], 5));
|
||||
x = (_unboundObj$foo$bar = unboundObj.foo.bar, _unboundObj$foo$bar["qux"] = Math.pow(_unboundObj$foo$bar["qux"], 6));
|
||||
|
||||
x = (_boundProp = boundProp, boundObj[_boundProp] = Math.pow(boundObj[_boundProp], 7));
|
||||
x = (_unboundProp = unboundProp, boundObj[_unboundProp] = Math.pow(boundObj[_unboundProp], 8));
|
||||
x = (_unboundObj2 = unboundObj, _boundProp2 = boundProp, _unboundObj2[_boundProp2] = Math.pow(_unboundObj2[_boundProp2], 9));
|
||||
x = (_unboundObj3 = unboundObj, _unboundProp2 = unboundProp, _unboundObj3[_unboundProp2] = Math.pow(_unboundObj3[_unboundProp2], 10));
|
||||
Loading…
Reference in a new issue