Skip to content

Commit

Permalink
add should_create_temp_variable_for_identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Dunqing committed Nov 19, 2024
1 parent 1ad360c commit 638a0db
Showing 1 changed file with 24 additions and 14 deletions.
38 changes: 24 additions & 14 deletions crates/oxc_transformer/src/es2020/optional_chaining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ impl<'a, 'ctx> OptionalChaining<'a, 'ctx> {
}
}

/// Check if we should create a temp variable for the identifier
///
/// Except the `eval`, we should create a temp variable for all global references
fn should_create_temp_variable_for_identifier(
ident: &IdentifierReference<'a>,
ctx: &TraverseCtx<'a>,
) -> bool {
ident.is_global_reference(ctx.symbols()) && ident.name != "eval"
}

/// Skip transparent expression wrapper nodes
fn skip_transparent_expr_wrapper_nodes<'b>(
ctx: &'b TraverseCtx<'a>,
Expand Down Expand Up @@ -422,6 +432,7 @@ impl<'a, 'ctx> OptionalChaining<'a, 'ctx> {
let expr = expr.get_inner_expression_mut();
// (nest member expressions have transformed, current optional expr that need to transform)
match expr {
// nested chain expression like `(foo?.bar)?.baz`
Expression::ChainExpression(_) => {
*expr = Self::convert_chain_expression_to_expression(expr, ctx);
let left = self.transform_chain_expression_recursion(expr, ctx).unwrap();
Expand Down Expand Up @@ -511,7 +522,7 @@ impl<'a, 'ctx> OptionalChaining<'a, 'ctx> {
// If the expression is an identifier and it's not a global reference, we just to wrap it with checks
// `foo` -> `foo !== null && foo !== void 0`
if let Expression::Identifier(ident) = expr {
if !ident.is_global_reference(ctx.symbols()) || ident.name == "eval" {
if !Self::should_create_temp_variable_for_identifier(ident, ctx) {
let binding = MaybeBoundIdentifier::from_identifier_reference(ident, ctx);
let left1 = binding.create_read_expression(ctx);
let left2 = binding.create_read_expression(ctx);
Expand All @@ -527,19 +538,18 @@ impl<'a, 'ctx> OptionalChaining<'a, 'ctx> {
// If the [`MemberExpression::object`] is a global reference, we need to assign it to a temp binding.
// i.e `foo` -> `(_foo = foo)
if let Expression::Identifier(ident) = object {
let binding =
if ident.is_global_reference(ctx.symbols()) && ident.name != "eval" {
let binding = self.generate_binding(object, ctx);
// `(_foo = foo)`
*object = Self::create_assignment_expression(
binding.create_read_write_target(ctx),
ctx.ast.move_expression(object),
ctx,
);
binding.to_maybe_bound_identifier()
} else {
MaybeBoundIdentifier::from_identifier_reference(ident, ctx)
};
let binding = if Self::should_create_temp_variable_for_identifier(ident, ctx) {
let binding = self.generate_binding(object, ctx);
// `(_foo = foo)`
*object = Self::create_assignment_expression(
binding.create_read_write_target(ctx),
ctx.ast.move_expression(object),
ctx,
);
binding.to_maybe_bound_identifier()
} else {
MaybeBoundIdentifier::from_identifier_reference(ident, ctx)
};
self.set_binding_context(binding);
} else if matches!(object, Expression::Super(_)) {
self.set_this_context();
Expand Down

0 comments on commit 638a0db

Please sign in to comment.