From 5bdaacc4f6fe68232a1e4ccc699b45f22cc42931 Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 11 Feb 2026 11:34:17 +0000 Subject: [PATCH] fix(transformer): propagate source spans for sourcemap correctness (#19258) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Propagate original source node spans to their outermost transformed replacements across all transformer plugins - Codegen skips sourcemap entries for nodes with empty spans (`SPAN`), so transformed nodes previously produced no sourcemap mappings - Updated 20 files across typescript, jsx, es2016-es2026, class properties, and shared utility functions - Added `span: Span` parameters to shared helpers (`create_assignment`, `create_member_callee`, `create_prototype_member`) and threaded spans through call chains - Kept `SPAN` for truly synthetic nodes (generated temps, helper function internals, protocol boilerplate) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- .../src/common/arrow_function_converter.rs | 4 +-- .../src/common/computed_key.rs | 3 +- .../src/decorator/legacy/mod.rs | 9 +++-- .../src/es2016/exponentiation_operator.rs | 27 ++++++++------ .../src/es2017/async_to_generator.rs | 8 +++-- .../async_generator_functions/for_await.rs | 24 +++++++++---- .../src/es2018/object_rest_spread.rs | 5 ++- .../src/es2020/optional_chaining.rs | 8 +++-- .../es2021/logical_assignment_operators.rs | 3 +- .../src/es2022/class_properties/class.rs | 10 +++--- .../es2022/class_properties/constructor.rs | 2 +- .../es2022/class_properties/private_field.rs | 12 +++---- .../src/es2022/class_properties/prop_decl.rs | 36 ++++++++++--------- .../class_properties/super_converter.rs | 6 ++-- .../es2026/explicit_resource_management.rs | 14 +++++--- crates/oxc_transformer/src/jsx/jsx_impl.rs | 6 ++-- crates/oxc_transformer/src/jsx/refresh.rs | 7 ++-- crates/oxc_transformer/src/typescript/enum.rs | 36 ++++++++++++------- .../src/typescript/namespace.rs | 17 ++++----- .../oxc_transformer/src/utils/ast_builder.rs | 13 ++++--- 20 files changed, 154 insertions(+), 96 deletions(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index 29efd781d5159..32486af5a395f 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -786,7 +786,7 @@ impl<'a> ArrowFunctionConverter<'a> { if let Some(assign_value) = assign_value { arguments.push(Argument::from(assign_value.take_in(ctx.ast))); } - let call = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false); + let call = ctx.ast.expression_call(expr.span(), callee, NONE, arguments, false); Some(call) } @@ -826,7 +826,7 @@ impl<'a> ArrowFunctionConverter<'a> { let property = ctx.ast.identifier_name(SPAN, "call"); let callee = ctx.ast.member_expression_static(SPAN, object, property, false); let callee = Expression::from(callee); - Some(ctx.ast.expression_call(SPAN, callee, NONE, arguments, false)) + Some(ctx.ast.expression_call(call.span, callee, NONE, arguments, false)) } /// Transform an `AssignmentExpression` whose assignment target is a `super` member expression. diff --git a/crates/oxc_transformer/src/common/computed_key.rs b/crates/oxc_transformer/src/common/computed_key.rs index c2077187c2f98..7e6954517fa2f 100644 --- a/crates/oxc_transformer/src/common/computed_key.rs +++ b/crates/oxc_transformer/src/common/computed_key.rs @@ -2,6 +2,7 @@ use oxc_ast::ast::Expression; use oxc_semantic::SymbolFlags; +use oxc_span::SPAN; use crate::{context::TraverseCtx, utils::ast_builder::create_assignment}; @@ -67,7 +68,7 @@ pub fn create_computed_key_temp_var<'a>( ctx.state.var_declarations.insert_let(&binding, None, ctx.ast); - let assignment = create_assignment(&binding, key, ctx); + let assignment = create_assignment(&binding, key, SPAN, ctx); let ident = binding.create_read_expression(ctx); (assignment, ident) diff --git a/crates/oxc_transformer/src/decorator/legacy/mod.rs b/crates/oxc_transformer/src/decorator/legacy/mod.rs index 23d66de281c7f..c334fd83e78c2 100644 --- a/crates/oxc_transformer/src/decorator/legacy/mod.rs +++ b/crates/oxc_transformer/src/decorator/legacy/mod.rs @@ -662,7 +662,12 @@ impl<'a> LegacyDecorator<'a> { // `_Class = this`; let class_alias_with_this_assignment = ctx.ast.statement_expression( SPAN, - create_assignment(class_alias_binding, ctx.ast.expression_this(SPAN), ctx), + create_assignment( + class_alias_binding, + ctx.ast.expression_this(SPAN), + SPAN, + ctx, + ), ); let body = ctx.ast.vec1(class_alias_with_this_assignment); let scope_id = ctx.create_child_scope_of_current(ScopeFlags::ClassStaticBlock); @@ -1051,7 +1056,7 @@ impl<'a> LegacyDecorator<'a> { ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { let ident = class_binding.create_read_expression(ctx); - if is_static { ident } else { create_prototype_member(ident, ctx) } + if is_static { ident } else { create_prototype_member(ident, SPAN, ctx) } } /// Get the name of the property key. diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index 7fb872e242ece..a963932be3775 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -35,7 +35,7 @@ use oxc_allocator::{CloneIn, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_semantic::ReferenceFlags; -use oxc_span::SPAN; +use oxc_span::{SPAN, Span}; use oxc_syntax::operator::{AssignmentOperator, BinaryOperator}; use oxc_traverse::{BoundIdentifier, Traverse}; @@ -112,7 +112,7 @@ impl<'a> ExponentiationOperator<'a> { Expression::BinaryExpression(binary_expr) => binary_expr.unbox(), _ => unreachable!(), }; - *expr = Self::math_pow(binary_expr.left, binary_expr.right, ctx); + *expr = Self::math_pow(binary_expr.span, binary_expr.left, binary_expr.right, ctx); } /// Convert `AssignmentExpression` where assignee is an identifier. @@ -129,13 +129,14 @@ impl<'a> ExponentiationOperator<'a> { #[inline] fn convert_identifier_assignment(&self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { let Expression::AssignmentExpression(assign_expr) = expr else { unreachable!() }; + let span = assign_expr.span; let AssignmentTarget::AssignmentTargetIdentifier(ident) = &mut assign_expr.left else { unreachable!() }; let (pow_left, temp_var_inits) = self.get_pow_left_identifier(ident, ctx); Self::convert_assignment(assign_expr, pow_left, ctx); - Self::revise_expression(expr, temp_var_inits, ctx); + Self::revise_expression(expr, temp_var_inits, span, ctx); } /// Get left side of `Math.pow(pow_left, ...)` for identifier @@ -199,6 +200,7 @@ impl<'a> ExponentiationOperator<'a> { ctx: &mut TraverseCtx<'a>, ) { let Expression::AssignmentExpression(assign_expr) = expr else { unreachable!() }; + let span = assign_expr.span; let AssignmentTarget::StaticMemberExpression(member_expr) = &mut assign_expr.left else { unreachable!() }; @@ -207,7 +209,7 @@ impl<'a> ExponentiationOperator<'a> { self.get_pow_left_static_member(member_expr, ctx); assign_expr.left = replacement_left; Self::convert_assignment(assign_expr, pow_left, ctx); - Self::revise_expression(expr, temp_var_inits, ctx); + Self::revise_expression(expr, temp_var_inits, span, ctx); } /// Get left side of `Math.pow(pow_left, ...)` for static member expression @@ -298,13 +300,14 @@ impl<'a> ExponentiationOperator<'a> { ctx: &mut TraverseCtx<'a>, ) { let Expression::AssignmentExpression(assign_expr) = expr else { unreachable!() }; + let span = assign_expr.span; let AssignmentTarget::ComputedMemberExpression(member_expr) = &mut assign_expr.left else { unreachable!() }; let (pow_left, temp_var_inits) = self.get_pow_left_computed_member(member_expr, ctx); Self::convert_assignment(assign_expr, pow_left, ctx); - Self::revise_expression(expr, temp_var_inits, ctx); + Self::revise_expression(expr, temp_var_inits, span, ctx); } /// Get left side of `Math.pow(pow_left, ...)` for computed member expression @@ -379,13 +382,14 @@ impl<'a> ExponentiationOperator<'a> { ctx: &mut TraverseCtx<'a>, ) { let Expression::AssignmentExpression(assign_expr) = expr else { unreachable!() }; + let span = assign_expr.span; let AssignmentTarget::PrivateFieldExpression(member_expr) = &mut assign_expr.left else { unreachable!() }; let (pow_left, temp_var_inits) = self.get_pow_left_private_field(member_expr, ctx); Self::convert_assignment(assign_expr, pow_left, ctx); - Self::revise_expression(expr, temp_var_inits, ctx); + Self::revise_expression(expr, temp_var_inits, span, ctx); } /// Get left side of `Math.pow(pow_left, ...)` for static member expression @@ -511,8 +515,9 @@ impl<'a> ExponentiationOperator<'a> { pow_left: Expression<'a>, ctx: &mut TraverseCtx<'a>, ) { + let span = assign_expr.span; let pow_right = assign_expr.right.take_in(ctx.ast); - assign_expr.right = Self::math_pow(pow_left, pow_right, ctx); + assign_expr.right = Self::math_pow(span, pow_left, pow_right, ctx); assign_expr.operator = AssignmentOperator::Assign; } @@ -520,17 +525,19 @@ impl<'a> ExponentiationOperator<'a> { fn revise_expression( expr: &mut Expression<'a>, mut temp_var_inits: ArenaVec<'a, Expression<'a>>, + span: Span, ctx: &TraverseCtx<'a>, ) { if !temp_var_inits.is_empty() { temp_var_inits.reserve_exact(1); temp_var_inits.push(expr.take_in(ctx.ast)); - *expr = ctx.ast.expression_sequence(SPAN, temp_var_inits); + *expr = ctx.ast.expression_sequence(span, temp_var_inits); } } /// `Math.pow(left, right)` fn math_pow( + span: Span, left: Expression<'a>, right: Expression<'a>, ctx: &mut TraverseCtx<'a>, @@ -540,9 +547,9 @@ impl<'a> ExponentiationOperator<'a> { let object = ctx.create_ident_expr(SPAN, math, math_symbol_id, ReferenceFlags::Read); let property = ctx.ast.identifier_name(SPAN, "pow"); let callee = - Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)); + Expression::from(ctx.ast.member_expression_static(span, object, property, false)); let arguments = ctx.ast.vec_from_array([Argument::from(left), Argument::from(right)]); - ctx.ast.expression_call(SPAN, callee, NONE, arguments, false) + ctx.ast.expression_call(span, callee, NONE, arguments, false) } /// Create a temporary variable. diff --git a/crates/oxc_transformer/src/es2017/async_to_generator.rs b/crates/oxc_transformer/src/es2017/async_to_generator.rs index f01e7101bb05a..72a3ba5d7f73c 100644 --- a/crates/oxc_transformer/src/es2017/async_to_generator.rs +++ b/crates/oxc_transformer/src/es2017/async_to_generator.rs @@ -178,7 +178,7 @@ impl<'a> AsyncToGenerator<'a> { ) -> Option> { // We don't need to handle top-level await. if Self::is_inside_async_function(ctx) { - Some(ctx.ast.expression_yield(SPAN, false, Some(expr.argument.take_in(ctx.ast)))) + Some(ctx.ast.expression_yield(expr.span, false, Some(expr.argument.take_in(ctx.ast)))) } else { None } @@ -302,6 +302,7 @@ impl<'a> AsyncGeneratorExecutor<'a> { wrapper_function: &mut Function<'a>, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { + let span = wrapper_function.span; let body = wrapper_function.body.take().unwrap(); let params = wrapper_function.params.take_in_box(ctx.ast); let id = wrapper_function.id.take(); @@ -391,7 +392,7 @@ impl<'a> AsyncGeneratorExecutor<'a> { // Construct the IIFE let callee = Expression::FunctionExpression(wrapper_function.take_in_box(ctx.ast)); - ctx.ast.expression_call_with_pure(SPAN, callee, NONE, ctx.ast.vec(), false, true) + ctx.ast.expression_call_with_pure(span, callee, NONE, ctx.ast.vec(), false, true) } /// Transforms async function declarations into generator functions wrapped in the asyncToGenerator helper. @@ -465,6 +466,7 @@ impl<'a> AsyncGeneratorExecutor<'a> { arrow: &mut ArrowFunctionExpression<'a>, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { + let arrow_span = arrow.span; let mut body = arrow.body.take_in_box(ctx.ast); // If the arrow's expression is true, we need to wrap the only one expression with return statement. @@ -528,7 +530,7 @@ impl<'a> AsyncGeneratorExecutor<'a> { let wrapper_function = Self::create_function(None, params, body, wrapper_scope_id, ctx); // Construct the IIFE let callee = Expression::FunctionExpression(wrapper_function); - ctx.ast.expression_call(SPAN, callee, NONE, ctx.ast.vec(), false) + ctx.ast.expression_call(arrow_span, callee, NONE, ctx.ast.vec(), false) } } diff --git a/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs b/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs index 0989291225446..ac5173052c077 100644 --- a/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs +++ b/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs @@ -3,7 +3,7 @@ use oxc_allocator::{TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_semantic::{ScopeFlags, ScopeId, SymbolFlags}; -use oxc_span::SPAN; +use oxc_span::{SPAN, Span}; use oxc_traverse::{Ancestor, BoundIdentifier}; use crate::{ @@ -45,6 +45,7 @@ impl<'a> AsyncGeneratorFunctions<'a> { return; } + let for_of_span = for_of.span; let allow_multiple_statements = Self::is_multiple_statements_allowed(ctx); let parent_scope_id = if allow_multiple_statements { ctx.current_scope_id() @@ -59,7 +60,8 @@ impl<'a> AsyncGeneratorFunctions<'a> { // 1. Use the last statement as the new statement. // 2. insert the rest of the statements before the current statement. // TODO: Once we have a method to replace the current statement, we can simplify this logic. - let mut statements = self.transform_for_of_statement(for_of, parent_scope_id, ctx); + let mut statements = + self.transform_for_of_statement(for_of, parent_scope_id, for_of_span, ctx); let mut new_stmt = statements.pop().unwrap(); // If it's a labeled statement, we need to wrap the ForStatement with a labeled statement. @@ -72,7 +74,7 @@ impl<'a> AsyncGeneratorFunctions<'a> { let try_statement_block_body = &mut try_statement.block.body; let for_statement = try_statement_block_body.pop().unwrap(); try_statement_block_body.push(ctx.ast.statement_labeled( - SPAN, + for_of_span, label.clone(), for_statement, )); @@ -97,6 +99,7 @@ impl<'a> AsyncGeneratorFunctions<'a> { &self, stmt: &mut ForOfStatement<'a>, parent_scope_id: ScopeId, + span: Span, ctx: &mut TraverseCtx<'a>, ) -> ArenaVec<'a, Statement<'a>> { let step_key = @@ -153,7 +156,15 @@ impl<'a> AsyncGeneratorFunctions<'a> { ctx.ast.vec1(Argument::from(iterator)), ctx, ); - Self::build_for_await(iterator, &step_key, body, stmt.scope_id(), parent_scope_id, ctx) + Self::build_for_await( + iterator, + &step_key, + body, + stmt.scope_id(), + parent_scope_id, + span, + ctx, + ) } /// Build a `for` statement used to replace the `for await` statement. @@ -195,6 +206,7 @@ impl<'a> AsyncGeneratorFunctions<'a> { body: ArenaVec<'a, Statement<'a>>, for_of_scope_id: ScopeId, parent_scope_id: ScopeId, + span: Span, ctx: &mut TraverseCtx<'a>, ) -> ArenaVec<'a, Statement<'a>> { let var_scope_id = ctx.current_scope_id(); @@ -258,7 +270,7 @@ impl<'a> AsyncGeneratorFunctions<'a> { ctx.create_child_scope(block_scope_id, ScopeFlags::empty()); let for_statement = ctx.ast.statement_for_with_scope_id( - SPAN, + span, Some(ctx.ast.for_statement_init_variable_declaration( SPAN, VariableDeclarationKind::Var, @@ -477,7 +489,7 @@ impl<'a> AsyncGeneratorFunctions<'a> { Some(block_statement) }; - let try_statement = ctx.ast.statement_try(SPAN, block, catch_clause, finally); + let try_statement = ctx.ast.statement_try(span, block, catch_clause, finally); items.push(try_statement); items diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread.rs b/crates/oxc_transformer/src/es2018/object_rest_spread.rs index d1806f97f6671..10697bdd0ac55 100644 --- a/crates/oxc_transformer/src/es2018/object_rest_spread.rs +++ b/crates/oxc_transformer/src/es2018/object_rest_spread.rs @@ -491,6 +491,7 @@ impl<'a> ObjectRestSpread<'a> { return; } + let span = obj_expr.span; let mut call_expr: Option>> = None; let mut props = ctx.ast.vec_with_capacity(obj_expr.properties.len()); @@ -508,7 +509,9 @@ impl<'a> ObjectRestSpread<'a> { Self::make_object_spread(&mut call_expr, &mut props, ctx); } - *expr = Expression::CallExpression(call_expr.unwrap()); + let mut final_call = call_expr.unwrap(); + final_call.span = span; + *expr = Expression::CallExpression(final_call); } fn make_object_spread( diff --git a/crates/oxc_transformer/src/es2020/optional_chaining.rs b/crates/oxc_transformer/src/es2020/optional_chaining.rs index 24da961ed616d..42ea3640e5751 100644 --- a/crates/oxc_transformer/src/es2020/optional_chaining.rs +++ b/crates/oxc_transformer/src/es2020/optional_chaining.rs @@ -51,7 +51,7 @@ use std::mem; use oxc_allocator::{CloneIn, TakeIn}; use oxc_ast::{NONE, ast::*}; -use oxc_span::SPAN; +use oxc_span::{GetSpan, SPAN, Span}; use oxc_traverse::{Ancestor, BoundIdentifier, MaybeBoundIdentifier, Traverse}; use crate::{ @@ -234,6 +234,7 @@ impl<'a> OptionalChaining<'a> { is_delete: bool, test: Expression<'a>, alternate: Expression<'a>, + span: Span, ctx: &TraverseCtx<'a>, ) -> Expression<'a> { let consequent = if is_delete { @@ -241,7 +242,7 @@ impl<'a> OptionalChaining<'a> { } else { ctx.ast.void_0(SPAN) }; - ctx.ast.expression_conditional(SPAN, test, consequent, alternate) + ctx.ast.expression_conditional(span, test, consequent, alternate) } /// Convert chain expression to expression @@ -317,6 +318,7 @@ impl<'a> OptionalChaining<'a> { chain_expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { + let span = chain_expr.span(); let mut chain_expr = Self::convert_chain_expression_to_expression(chain_expr, ctx); // ^^^^^^^^^^ After the recursive transformation, the chain_expr will be transformed into // a pure non-optional expression and it's the last part of the chain expression. @@ -349,7 +351,7 @@ impl<'a> OptionalChaining<'a> { self.temp_binding = None; self.call_context = CallContext::None; - Self::create_conditional_expression(is_delete, left, chain_expr, ctx) + Self::create_conditional_expression(is_delete, left, chain_expr, span, ctx) } /// Transform an expression to bind a proper context diff --git a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs index 1b92f331f8baf..84695b9737fc7 100644 --- a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs +++ b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs @@ -123,11 +123,12 @@ impl<'a> LogicalAssignmentOperators { _ => return, }; + let span = assignment_expr.span; let assign_op = AssignmentOperator::Assign; let right = assignment_expr.right.take_in(ctx.ast); let right = ctx.ast.expression_assignment(SPAN, assign_op, assign_target, right); - let logical_expr = ctx.ast.expression_logical(SPAN, left_expr, operator, right); + let logical_expr = ctx.ast.expression_logical(span, left_expr, operator, right); *expr = logical_expr; } diff --git a/crates/oxc_transformer/src/es2022/class_properties/class.rs b/crates/oxc_transformer/src/es2022/class_properties/class.rs index 0392478222c9b..7c1b986b3eed1 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/class.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/class.rs @@ -461,7 +461,7 @@ impl<'a> ClassProperties<'a> { // rather than separate `var _Class` declaration. let class_name = BoundIdentifier::from_binding_ident(ident).create_read_expression(ctx); - let expr = create_assignment(temp_binding, class_name, ctx); + let expr = create_assignment(temp_binding, class_name, SPAN, ctx); let stmt = ctx.ast.statement_expression(SPAN, expr); self.insert_after_stmts.insert(0, stmt); } else { @@ -654,7 +654,7 @@ impl<'a> ClassProperties<'a> { // `_prop = _classPrivateFieldLooseKey("prop")` let value = Self::create_private_prop_key_loose(name, ctx); - Some(create_assignment(&prop.binding, value, ctx)) + Some(create_assignment(&prop.binding, value, SPAN, ctx)) })); } else { let mut weakmap_symbol_id = None; @@ -673,7 +673,7 @@ impl<'a> ClassProperties<'a> { let binding = class_details.bindings.brand(); ctx.state.var_declarations.insert_var(binding, ctx.ast); let value = create_new_weakset(ctx); - return Some(create_assignment(binding, value, ctx)); + return Some(create_assignment(binding, value, SPAN, ctx)); } // Insert `var _prop;` declaration @@ -685,7 +685,7 @@ impl<'a> ClassProperties<'a> { // `_prop = new WeakMap()` let value = create_new_weakmap(&mut weakmap_symbol_id, ctx); - Some(create_assignment(&prop.binding, value, ctx)) + Some(create_assignment(&prop.binding, value, SPAN, ctx)) })); } } @@ -718,7 +718,7 @@ impl<'a> ClassProperties<'a> { // `_Class = class {}` let class_expr = expr.take_in(ctx.ast); - let assignment = create_assignment(binding, class_expr, ctx); + let assignment = create_assignment(binding, class_expr, SPAN, ctx); if exprs.is_empty() && self.insert_after_exprs.is_empty() { // No need to wrap in sequence if no static property diff --git a/crates/oxc_transformer/src/es2022/class_properties/constructor.rs b/crates/oxc_transformer/src/es2022/class_properties/constructor.rs index 7ede151ea6e35..57af623bde453 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/constructor.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/constructor.rs @@ -405,7 +405,7 @@ impl<'a> ClassProperties<'a> { let init = if self.current_class().is_declaration { Some(super_func) } else { - let assignment = create_assignment(super_binding, super_func, ctx); + let assignment = create_assignment(super_binding, super_func, SPAN, ctx); // TODO: Why does this end up before class, not after? // TODO: This isn't right. Should not be adding to `insert_after_exprs` in entry phase. self.insert_after_exprs.push(assignment); diff --git a/crates/oxc_transformer/src/es2022/class_properties/private_field.rs b/crates/oxc_transformer/src/es2022/class_properties/private_field.rs index 92282c501d29a..253a70cf433b2 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/private_field.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/private_field.rs @@ -1015,7 +1015,7 @@ impl<'a> ClassProperties<'a> { // `_object$prop = _assertClassBrand(Class, object, _prop)._` let temp_binding = VarDeclarationsStore::create_uid_var(&temp_var_name_base, ctx); - let assignment = create_assignment(&temp_binding, get_expr, ctx); + let assignment = create_assignment(&temp_binding, get_expr, SPAN, ctx); // `++_object$prop` / `_object$prop++` (reusing existing `UpdateExpression`) let UpdateExpression { span, prefix, .. } = **update_expr; @@ -1048,7 +1048,7 @@ impl<'a> ClassProperties<'a> { // `_object$prop2 = _object$prop++` let temp_binding2 = VarDeclarationsStore::create_uid_var(&temp_var_name_base, ctx); - let assignment2 = create_assignment(&temp_binding2, update_expr, ctx); + let assignment2 = create_assignment(&temp_binding2, update_expr, SPAN, ctx); // `(_object$prop = _assertClassBrand(Class, object, _prop)._, _object$prop2 = _object$prop++, _object$prop)` let mut value = ctx.ast.expression_sequence( @@ -1111,7 +1111,7 @@ impl<'a> ClassProperties<'a> { // `_object$prop = _classPrivateFieldGet(_prop, object)` let temp_binding = VarDeclarationsStore::create_uid_var(&temp_var_name_base, ctx); - let assignment = create_assignment(&temp_binding, get_call, ctx); + let assignment = create_assignment(&temp_binding, get_call, SPAN, ctx); // `++_object$prop` / `_object$prop++` (reusing existing `UpdateExpression`) let UpdateExpression { span, prefix, .. } = **update_expr; @@ -1139,7 +1139,7 @@ impl<'a> ClassProperties<'a> { // Source = `object.#prop++` (postfix `++`) // `_object$prop2 = _object$prop++` let temp_binding2 = VarDeclarationsStore::create_uid_var(&temp_var_name_base, ctx); - let assignment2 = create_assignment(&temp_binding2, update_expr, ctx); + let assignment2 = create_assignment(&temp_binding2, update_expr, SPAN, ctx); // `(_object$prop = _classPrivateFieldGet(_prop, object), _object$prop2 = _object$prop++, _object$prop)` let value = ctx.ast.expression_sequence( @@ -1873,7 +1873,7 @@ impl<'a> ClassProperties<'a> { } else { prop_binding.create_read_expression(ctx) }; - let callee = create_member_callee(callee, "has", ctx); + let callee = create_member_callee(callee, "has", span, ctx); let argument = self.create_check_in_rhs(right, SPAN, ctx); ctx.ast.expression_call(span, callee, NONE, ctx.ast.vec1(Argument::from(argument)), false) } @@ -2154,7 +2154,7 @@ impl<'a> ClassProperties<'a> { let class_ident = class_binding.create_read_expression(ctx); let object = self.create_assert_class_brand_without_value(class_ident, object, ctx); let arguments = ctx.ast.vec_from_array([Argument::from(object), Argument::from(value)]); - let callee = create_member_callee(prop_ident, "call", ctx); + let callee = create_member_callee(prop_ident, "call", span, ctx); // `_prop.call(_assertClassBrand(Class, object), value)` ctx.ast.expression_call(span, callee, NONE, arguments, false) } else { diff --git a/crates/oxc_transformer/src/es2022/class_properties/prop_decl.rs b/crates/oxc_transformer/src/es2022/class_properties/prop_decl.rs index 1fc34afa82ede..bd385b15e58e9 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/prop_decl.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/prop_decl.rs @@ -2,7 +2,7 @@ //! Transform of class property declarations (instance or static properties). use oxc_ast::{NONE, ast::*}; -use oxc_span::SPAN; +use oxc_span::{SPAN, Span}; use oxc_syntax::reference::ReferenceFlags; use crate::{ @@ -29,9 +29,10 @@ impl<'a> ClassProperties<'a> { // Get value let value = prop.value.take(); + let span = prop.span; let init_expr = if let PropertyKey::PrivateIdentifier(ident) = &mut prop.key { let value = value.unwrap_or_else(|| ctx.ast.void_0(SPAN)); - self.create_private_instance_init_assignment(ident, value, ctx) + self.create_private_instance_init_assignment(ident, value, span, ctx) } else { let value = match value { Some(value) => value, @@ -62,13 +63,14 @@ impl<'a> ClassProperties<'a> { &self, ident: &PrivateIdentifier<'a>, value: Expression<'a>, + span: Span, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { if self.private_fields_as_properties { let this = ctx.ast.expression_this(SPAN); - self.create_private_init_assignment_loose(ident, value, this, ctx) + self.create_private_init_assignment_loose(ident, value, this, span, ctx) } else { - self.create_private_instance_init_assignment_not_loose(ident, value, ctx) + self.create_private_instance_init_assignment_not_loose(ident, value, span, ctx) } } @@ -77,6 +79,7 @@ impl<'a> ClassProperties<'a> { &self, ident: &PrivateIdentifier<'a>, value: Expression<'a>, + span: Span, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { let private_props = self.current_class().private_props.as_ref().unwrap(); @@ -86,8 +89,7 @@ impl<'a> ClassProperties<'a> { Argument::from(prop.binding.create_read_expression(ctx)), Argument::from(value), ]); - // TODO: Should this have span of original `PropertyDefinition`? - helper_call_expr(Helper::ClassPrivateFieldInitSpec, SPAN, arguments, ctx) + helper_call_expr(Helper::ClassPrivateFieldInitSpec, span, arguments, ctx) } } @@ -108,9 +110,10 @@ impl<'a> ClassProperties<'a> { value }); + let span = prop.span; if let PropertyKey::PrivateIdentifier(ident) = &mut prop.key { let value = value.unwrap_or_else(|| ctx.ast.void_0(SPAN)); - self.insert_private_static_init_assignment(ident, value, ctx); + self.insert_private_static_init_assignment(ident, value, span, ctx); } else { let value = match value { Some(value) => value, @@ -155,10 +158,11 @@ impl<'a> ClassProperties<'a> { &mut self, ident: &PrivateIdentifier<'a>, value: Expression<'a>, + span: Span, ctx: &mut TraverseCtx<'a>, ) { if self.private_fields_as_properties { - self.insert_private_static_init_assignment_loose(ident, value, ctx); + self.insert_private_static_init_assignment_loose(ident, value, span, ctx); } else { self.insert_private_static_init_assignment_not_loose(ident, value, ctx); } @@ -170,6 +174,7 @@ impl<'a> ClassProperties<'a> { &mut self, ident: &PrivateIdentifier<'a>, value: Expression<'a>, + span: Span, ctx: &mut TraverseCtx<'a>, ) { // TODO: This logic appears elsewhere. De-duplicate it. @@ -184,7 +189,8 @@ impl<'a> ClassProperties<'a> { }; let assignee = class_binding.create_read_expression(ctx); - let assignment = self.create_private_init_assignment_loose(ident, value, assignee, ctx); + let assignment = + self.create_private_init_assignment_loose(ident, value, assignee, span, ctx); self.insert_expr_after_class(assignment, ctx); } @@ -221,7 +227,7 @@ impl<'a> ClassProperties<'a> { self.insert_after_stmts.push(var_decl); } else { // `_prop = {_: value}` - let assignment = create_assignment(prop_binding, obj, ctx); + let assignment = create_assignment(prop_binding, obj, SPAN, ctx); self.insert_after_exprs.push(assignment); } } @@ -289,9 +295,8 @@ impl<'a> ClassProperties<'a> { } }; - // TODO: Should this have span of the original `PropertyDefinition`? ctx.ast.expression_assignment( - SPAN, + prop.span, AssignmentOperator::Assign, AssignmentTarget::from(left), value, @@ -330,8 +335,7 @@ impl<'a> ClassProperties<'a> { Argument::from(key), Argument::from(value), ]); - // TODO: Should this have span of the original `PropertyDefinition`? - helper_call_expr(Helper::DefineProperty, SPAN, arguments, ctx) + helper_call_expr(Helper::DefineProperty, prop.span, arguments, ctx) } /// `Object.defineProperty(, _prop, {writable: true, value: value})` @@ -340,6 +344,7 @@ impl<'a> ClassProperties<'a> { ident: &PrivateIdentifier<'a>, value: Expression<'a>, assignee: Expression<'a>, + span: Span, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { // `Object.defineProperty` @@ -383,7 +388,6 @@ impl<'a> ClassProperties<'a> { Argument::from(prop_binding.create_read_expression(ctx)), Argument::from(prop_def), ]); - // TODO: Should this have span of original `PropertyDefinition`? - ctx.ast.expression_call(SPAN, callee, NONE, arguments, false) + ctx.ast.expression_call(span, callee, NONE, arguments, false) } } diff --git a/crates/oxc_transformer/src/es2022/class_properties/super_converter.rs b/crates/oxc_transformer/src/es2022/class_properties/super_converter.rs index b8995409263cc..802597cdd705c 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/super_converter.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/super_converter.rs @@ -501,7 +501,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_> { // `_super$prop = _superPropGet(_Class, prop, _Class)` let temp_binding = VarDeclarationsStore::create_uid_var(temp_var_name_base, ctx); - let assignment = create_assignment(&temp_binding, get_call, ctx); + let assignment = create_assignment(&temp_binding, get_call, SPAN, ctx); // `++_super$prop` / `_super$prop++` (reusing existing `UpdateExpression`) let span = update_expr.span; @@ -522,7 +522,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_> { // Source = `super.prop++` (postfix `++`) // `_super$prop2 = _super$prop++` let temp_binding2 = VarDeclarationsStore::create_uid_var(temp_var_name_base, ctx); - let assignment2 = create_assignment(&temp_binding2, update_expr, ctx); + let assignment2 = create_assignment(&temp_binding2, update_expr, SPAN, ctx); // `(_super$prop = _superPropGet(_Class, prop, _Class), _super$prop2 = _super$prop++, _super$prop)` let value = ctx.ast.expression_sequence( @@ -617,7 +617,7 @@ impl<'a> ClassPropertiesSuperConverter<'a, '_> { // TODO(improve-on-babel): `superPropGet` and `superPropSet` helper function has a flag // to use `class.prototype` rather than `class`. We should consider using that flag here. // - class = create_prototype_member(class, ctx); + class = create_prototype_member(class, SPAN, ctx); ctx.ast.expression_this(SPAN) } ClassPropertiesSuperConverterMode::StaticPrivateMethod => ctx.ast.expression_this(SPAN), diff --git a/crates/oxc_transformer/src/es2026/explicit_resource_management.rs b/crates/oxc_transformer/src/es2026/explicit_resource_management.rs index 2086224dfe810..9b51aba37fee3 100644 --- a/crates/oxc_transformer/src/es2026/explicit_resource_management.rs +++ b/crates/oxc_transformer/src/es2026/explicit_resource_management.rs @@ -41,7 +41,7 @@ use oxc_allocator::{Address, Box as ArenaBox, GetAddress, TakeIn, Vec as ArenaVe use oxc_ast::{NONE, ast::*}; use oxc_ecmascript::BoundNames; use oxc_semantic::{ScopeFlags, ScopeId, SymbolFlags}; -use oxc_span::SPAN; +use oxc_span::{SPAN, Span}; use oxc_traverse::{BoundIdentifier, Traverse}; use crate::{ @@ -179,6 +179,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for ExplicitResourceManagement<'a> { &using_ctx, static_block_new_scope_id, needs_await, + SPAN, ctx, )); } @@ -220,6 +221,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for ExplicitResourceManagement<'a> { &using_ctx, current_scope_id, needs_await, + SPAN, ctx, )); } @@ -279,6 +281,7 @@ impl<'a> Traverse<'a, TransformState<'a>> for ExplicitResourceManagement<'a> { &using_ctx, block_stmt_scope_id, needs_await, + SPAN, ctx, )); @@ -538,6 +541,7 @@ impl<'a> ExplicitResourceManagement<'a> { /// ``` fn transform_block_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) { let Statement::BlockStatement(block_stmt) = stmt else { unreachable!() }; + let span = block_stmt.span; if let Some((new_stmts, needs_await, using_ctx)) = self.transform_statements(&mut block_stmt.body, ctx.current_hoist_scope_id(), ctx) @@ -549,6 +553,7 @@ impl<'a> ExplicitResourceManagement<'a> { &using_ctx, current_scope_id, needs_await, + span, ctx, ); } @@ -590,7 +595,7 @@ impl<'a> ExplicitResourceManagement<'a> { let current_scope_id = ctx.current_scope_id(); let Statement::SwitchStatement(switch_stmt) = stmt else { unreachable!() }; - + let span = switch_stmt.span; let switch_stmt_scope_id = switch_stmt.scope_id(); for case in &mut switch_stmt.cases { @@ -674,7 +679,7 @@ impl<'a> ExplicitResourceManagement<'a> { let catch = Self::create_catch_clause(&using_ctx, current_scope_id, ctx); let finally = Self::create_finally_block(&using_ctx, current_scope_id, needs_await, ctx); - *stmt = ctx.ast.statement_try(SPAN, block, Some(catch), Some(finally)); + *stmt = ctx.ast.statement_try(span, block, Some(catch), Some(finally)); } /// Transforms: @@ -788,11 +793,12 @@ impl<'a> ExplicitResourceManagement<'a> { using_ctx: &BoundIdentifier<'a>, parent_scope_id: ScopeId, needs_await: bool, + span: Span, ctx: &mut TraverseCtx<'a>, ) -> Statement<'a> { let catch = Self::create_catch_clause(using_ctx, parent_scope_id, ctx); let finally = Self::create_finally_block(using_ctx, parent_scope_id, needs_await, ctx); - ctx.ast.statement_try(SPAN, body, Some(catch), Some(finally)) + ctx.ast.statement_try(span, body, Some(catch), Some(finally)) } /// `catch (_) { _usingCtx.e = _; }` diff --git a/crates/oxc_transformer/src/jsx/jsx_impl.rs b/crates/oxc_transformer/src/jsx/jsx_impl.rs index 09434c554da84..1d3068fa789b2 100644 --- a/crates/oxc_transformer/src/jsx/jsx_impl.rs +++ b/crates/oxc_transformer/src/jsx/jsx_impl.rs @@ -657,7 +657,7 @@ impl<'a> JsxImpl<'a> { need_jsxs = true; let elements = children.into_iter().map(ArrayExpressionElement::from); let elements = ctx.ast.vec_from_iter(elements); - ctx.ast.expression_array(SPAN, elements) + ctx.ast.expression_array(span, elements) }; let children = ctx.ast.property_key_static_identifier(SPAN, "children"); let kind = PropertyKind::Init; @@ -668,7 +668,7 @@ impl<'a> JsxImpl<'a> { } // If runtime is automatic that means we always to add `{ .. }` as the second argument even if it's empty - let mut object_expression = ctx.ast.expression_object(SPAN, properties); + let mut object_expression = ctx.ast.expression_object(span, properties); if let Some(options) = self.object_rest_spread_options { ObjectRestSpread::transform_object_expression(options, &mut object_expression, ctx); } @@ -719,7 +719,7 @@ impl<'a> JsxImpl<'a> { } if !properties.is_empty() { - let mut object_expression = ctx.ast.expression_object(SPAN, properties); + let mut object_expression = ctx.ast.expression_object(span, properties); if let Some(options) = self.object_rest_spread_options { ObjectRestSpread::transform_object_expression( options, diff --git a/crates/oxc_transformer/src/jsx/refresh.rs b/crates/oxc_transformer/src/jsx/refresh.rs index d5285e7b42d42..732dbbf1d95f0 100644 --- a/crates/oxc_transformer/src/jsx/refresh.rs +++ b/crates/oxc_transformer/src/jsx/refresh.rs @@ -256,9 +256,10 @@ impl<'a> Traverse<'a, TransformState<'a>> for ReactRefresh<'a> { Some((binding_identifier.clone(), arguments.clone_in(ctx.ast.allocator))); } + let span = expr.span(); arguments.insert(0, Argument::from(expr.take_in(ctx.ast))); *expr = ctx.ast.expression_call( - SPAN, + span, binding.create_read_expression(ctx), NONE, arguments, @@ -288,8 +289,8 @@ impl<'a> Traverse<'a, TransformState<'a>> for ReactRefresh<'a> { let binding = BoundIdentifier::from_binding_ident(&binding_identifier); let callee = binding.create_read_expression(ctx); - let expr = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false); - let statement = ctx.ast.statement_expression(SPAN, expr); + let expr = ctx.ast.expression_call(func.span, callee, NONE, arguments, false); + let statement = ctx.ast.statement_expression(func.span, expr); // Get the address of the statement containing this `FunctionDeclaration` let address = match ctx.parent() { diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index 036809e8f90d6..84b0993bdbaad 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -115,9 +115,10 @@ impl<'a> TypeScriptEnum<'a> { ¶m_binding, ctx, ); - let body = ast.alloc_function_body(decl.span, ast.vec(), statements); + let span = decl.span; + let body = ast.alloc_function_body(span, ast.vec(), statements); let callee = ctx.ast.expression_function_with_scope_id_and_pure_and_pife( - SPAN, + span, FunctionType::FunctionExpression, None, false, @@ -154,12 +155,12 @@ impl<'a> TypeScriptEnum<'a> { ReferenceFlags::Read, ); let right = ast.expression_object(SPAN, ast.vec()); - let expression = ast.expression_logical(SPAN, left, op, right); + let expression = ast.expression_logical(span, left, op, right); ast.vec1(Argument::from(expression)) }; let call_expression = ast.expression_call_with_pure( - SPAN, + span, callee, NONE, arguments, @@ -176,8 +177,8 @@ impl<'a> TypeScriptEnum<'a> { ReferenceFlags::Write, ); let left = AssignmentTarget::AssignmentTargetIdentifier(ctx.alloc(left)); - let expr = ast.expression_assignment(SPAN, op, left, call_expression); - return Some(ast.statement_expression(decl.span, expr)); + let expr = ast.expression_assignment(span, op, left, call_expression); + return Some(ast.statement_expression(span, expr)); } let kind = if is_export || is_not_top_scope { @@ -189,10 +190,10 @@ impl<'a> TypeScriptEnum<'a> { let binding_identifier = decl.id.clone(); let binding = BindingPattern::BindingIdentifier(ctx.alloc(binding_identifier)); let decl = - ast.variable_declarator(SPAN, kind, binding, NONE, Some(call_expression), false); + ast.variable_declarator(span, kind, binding, NONE, Some(call_expression), false); ast.vec1(decl) }; - let variable_declaration = ast.declaration_variable(decl.span, kind, decls, false); + let variable_declaration = ast.declaration_variable(span, kind, decls, false); let stmt = if let Some(export_span) = export_span { let declaration = ctx @@ -225,6 +226,7 @@ impl<'a> TypeScriptEnum<'a> { let mut prev_member_name = None; for member in members.take_in(ctx.ast) { + let member_span = member.span; let member_name = member.id.static_name(); let init = if let Some(mut initializer) = member.initializer { @@ -290,8 +292,12 @@ impl<'a> TypeScriptEnum<'a> { ast.member_expression_computed(SPAN, obj, expr, false) }; let left = SimpleAssignmentTarget::from(member_expr); - let mut expr = - ast.expression_assignment(SPAN, AssignmentOperator::Assign, left.into(), init); + let mut expr = ast.expression_assignment( + member_span, + AssignmentOperator::Assign, + left.into(), + init, + ); // Foo[Foo["x"] = init] = "x" if !is_str { @@ -301,12 +307,16 @@ impl<'a> TypeScriptEnum<'a> { }; let left = SimpleAssignmentTarget::from(member_expr); let right = ast.expression_string_literal(SPAN, member_name, None); - expr = - ast.expression_assignment(SPAN, AssignmentOperator::Assign, left.into(), right); + expr = ast.expression_assignment( + member_span, + AssignmentOperator::Assign, + left.into(), + right, + ); } prev_member_name = Some(member_name); - statements.push(ast.statement_expression(member.span, expr)); + statements.push(ast.statement_expression(member_span, expr)); } self.enums.insert(param_binding.name, previous_enum_members); diff --git a/crates/oxc_transformer/src/typescript/namespace.rs b/crates/oxc_transformer/src/typescript/namespace.rs index 776d531ef5229..c570f8b89e67e 100644 --- a/crates/oxc_transformer/src/typescript/namespace.rs +++ b/crates/oxc_transformer/src/typescript/namespace.rs @@ -1,7 +1,7 @@ use oxc_allocator::{Box as ArenaBox, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_ecmascript::BoundNames; -use oxc_span::SPAN; +use oxc_span::{SPAN, Span}; use oxc_syntax::{ operator::{AssignmentOperator, LogicalOperator}, scope::{ScopeFlags, ScopeId}, @@ -280,10 +280,10 @@ impl<'a> TypeScriptNamespace { } if !Self::is_redeclaration_namespace(&ident, ctx) { - let declaration = Self::create_variable_declaration(&binding, ctx); + let declaration = Self::create_variable_declaration(&binding, span, ctx); if is_export { let export_named_decl = - ctx.ast.plain_export_named_declaration_declaration(SPAN, declaration); + ctx.ast.plain_export_named_declaration_declaration(span, declaration); let stmt = Statement::ExportNamedDeclaration(export_named_decl); parent_stmts.push(stmt); } else { @@ -307,15 +307,16 @@ impl<'a> TypeScriptNamespace { // ^^^^^^^ fn create_variable_declaration( binding: &BoundIdentifier<'a>, + span: Span, ctx: &TraverseCtx<'a>, ) -> Declaration<'a> { let kind = VariableDeclarationKind::Let; let declarations = { let pattern = binding.create_binding_pattern(ctx); - let decl = ctx.ast.variable_declarator(SPAN, kind, pattern, NONE, None, false); + let decl = ctx.ast.variable_declarator(span, kind, pattern, NONE, None, false); ctx.ast.vec1(decl) }; - ctx.ast.declaration_variable(SPAN, kind, declarations, false) + ctx.ast.declaration_variable(span, kind, declarations, false) } // `namespace Foo { }` -> `let Foo; (function (_Foo) { })(Foo || (Foo = {}));` @@ -339,7 +340,7 @@ impl<'a> TypeScriptNamespace { let function_expr = Expression::FunctionExpression(ctx.ast.alloc_plain_function_with_scope_id( FunctionType::FunctionExpression, - SPAN, + span, None, params, func_body, @@ -347,7 +348,7 @@ impl<'a> TypeScriptNamespace { )); *ctx.scoping_mut().scope_flags_mut(scope_id) = ScopeFlags::Function | ScopeFlags::StrictMode; - ctx.ast.expression_parenthesized(SPAN, function_expr) + ctx.ast.expression_parenthesized(span, function_expr) }; // (function (_N) { var M; (function (_M) { var x; })(M || (M = _N.M || (_N.M = {})));})(N || (N = {})); @@ -403,7 +404,7 @@ impl<'a> TypeScriptNamespace { ctx.ast.vec1(Argument::from(expr)) }; - let expr = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false); + let expr = ctx.ast.expression_call(span, callee, NONE, arguments, false); ctx.ast.statement_expression(span, expr) } diff --git a/crates/oxc_transformer/src/utils/ast_builder.rs b/crates/oxc_transformer/src/utils/ast_builder.rs index cb31b43245635..dac2c7541196f 100644 --- a/crates/oxc_transformer/src/utils/ast_builder.rs +++ b/crates/oxc_transformer/src/utils/ast_builder.rs @@ -12,10 +12,11 @@ use crate::context::TraverseCtx; pub fn create_member_callee<'a>( object: Expression<'a>, property: &'static str, + span: Span, ctx: &TraverseCtx<'a>, ) -> Expression<'a> { let property = ctx.ast.identifier_name(SPAN, Atom::from(property)); - Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)) + Expression::from(ctx.ast.member_expression_static(span, object, property, false)) } /// `object` -> `object.bind(this)`. @@ -25,7 +26,7 @@ pub fn create_bind_call<'a>( span: Span, ctx: &TraverseCtx<'a>, ) -> Expression<'a> { - let callee = create_member_callee(callee, "bind", ctx); + let callee = create_member_callee(callee, "bind", span, ctx); let arguments = ctx.ast.vec1(Argument::from(this)); ctx.ast.expression_call(span, callee, NONE, arguments, false) } @@ -37,7 +38,7 @@ pub fn create_call_call<'a>( span: Span, ctx: &TraverseCtx<'a>, ) -> Expression<'a> { - let callee = create_member_callee(callee, "call", ctx); + let callee = create_member_callee(callee, "call", span, ctx); let arguments = ctx.ast.vec1(Argument::from(this)); ctx.ast.expression_call(span, callee, NONE, arguments, false) } @@ -78,10 +79,11 @@ pub fn wrap_statements_in_arrow_function_iife<'a>( /// `object` -> `object.prototype`. pub fn create_prototype_member<'a>( object: Expression<'a>, + span: Span, ctx: &TraverseCtx<'a>, ) -> Expression<'a> { let property = ctx.ast.identifier_name(SPAN, Atom::from("prototype")); - let static_member = ctx.ast.member_expression_static(SPAN, object, property, false); + let static_member = ctx.ast.member_expression_static(span, object, property, false); Expression::from(static_member) } @@ -122,10 +124,11 @@ pub fn create_this_property_assignment<'a>( pub fn create_assignment<'a>( binding: &BoundIdentifier<'a>, value: Expression<'a>, + span: Span, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { ctx.ast.expression_assignment( - SPAN, + span, AssignmentOperator::Assign, binding.create_target(ReferenceFlags::Write, ctx), value,