From 638a0dbb1acd239ad9d5f3fd8c95f017cc5ad5f1 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Wed, 20 Nov 2024 00:23:22 +0800 Subject: [PATCH] add should_create_temp_variable_for_identifier --- .../src/es2020/optional_chaining.rs | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/crates/oxc_transformer/src/es2020/optional_chaining.rs b/crates/oxc_transformer/src/es2020/optional_chaining.rs index 6e2880de0aa19..38d6c065988f3 100644 --- a/crates/oxc_transformer/src/es2020/optional_chaining.rs +++ b/crates/oxc_transformer/src/es2020/optional_chaining.rs @@ -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>, @@ -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(); @@ -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); @@ -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();