Skip to content

Commit

Permalink
refactor(transformer): nullish coalescing transform: no cloning ident…
Browse files Browse the repository at this point in the history
…ifier references (#6295)

`clone_identifier_reference` involves a lookup of `SymbolId`. Use `BoundIdentifier` instead which caches the ID.
  • Loading branch information
overlookmotel committed Oct 5, 2024
1 parent 409dffc commit 527f7c8
Showing 1 changed file with 12 additions and 26 deletions.
38 changes: 12 additions & 26 deletions crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
use oxc_allocator::CloneIn;
use oxc_ast::{ast::*, NONE};
use oxc_semantic::{ReferenceFlags, ScopeFlags, ScopeId, SymbolFlags};
use oxc_semantic::{ReferenceFlags, ScopeFlags, SymbolFlags};
use oxc_span::SPAN;
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, LogicalOperator};
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
Expand Down Expand Up @@ -84,28 +84,33 @@ impl<'a, 'ctx> Traverse<'a> for NullishCoalescingOperator<'a, 'ctx> {
ctx.current_scope_id()
};

let (id, ident) =
Self::create_new_var_with_expression(&logical_expr.left, current_scope_id, ctx);
// Add `var _name` to scope
let binding = ctx.generate_uid_based_on_node(
&logical_expr.left,
current_scope_id,
SymbolFlags::FunctionScopedVariable,
);

let left =
AssignmentTarget::from(ctx.ast.simple_assignment_target_from_identifier_reference(
ctx.clone_identifier_reference(&ident, ReferenceFlags::read_write()),
binding.create_read_write_reference(ctx),
));

let reference = ctx.ast.expression_from_identifier_reference(ident);
let reference =
ctx.ast.expression_from_identifier_reference(binding.create_read_reference(ctx));
let assignment = ctx.ast.expression_assignment(
SPAN,
AssignmentOperator::Assign,
left,
logical_expr.left,
);

let mut new_expr =
Self::create_conditional_expression(reference, assignment, logical_expr.right, ctx);

if is_parent_formal_parameter {
// Replace `function (a, x = a.b ?? c) {}` to `function (a, x = (() => a.b ?? c)() ){}`
// so the temporary variable can be injected in correct scope
let id = binding.create_binding_pattern(ctx);
let param = ctx.ast.formal_parameter(SPAN, ctx.ast.vec(), id, None, false, false);
let params = ctx.ast.formal_parameters(
SPAN,
Expand All @@ -125,7 +130,7 @@ impl<'a, 'ctx> Traverse<'a> for NullishCoalescingOperator<'a, 'ctx> {
// `(x) => x;` -> `((x) => x)();`
new_expr = ctx.ast.expression_call(SPAN, arrow_function, NONE, ctx.ast.vec(), false);
} else {
self.ctx.var_declarations.insert_binding_pattern(id, None, ctx);
self.ctx.var_declarations.insert(&binding, None, ctx);
}

*expr = new_expr;
Expand All @@ -142,25 +147,6 @@ impl<'a, 'ctx> NullishCoalescingOperator<'a, 'ctx> {
}
}

fn create_new_var_with_expression(
expr: &Expression<'a>,
current_scope_id: ScopeId,
ctx: &mut TraverseCtx<'a>,
) -> (BindingPattern<'a>, IdentifierReference<'a>) {
// Add `var name` to scope
let binding = ctx.generate_uid_based_on_node(
expr,
current_scope_id,
SymbolFlags::FunctionScopedVariable,
);

// var _name;
let id = binding.create_binding_pattern(ctx);

let reference = binding.create_read_reference(ctx);
(id, reference)
}

/// Create a conditional expression
///
/// ```js
Expand Down

0 comments on commit 527f7c8

Please sign in to comment.