diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index cf15b2a92..abe114027 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -170,7 +170,7 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { ctx.create_unbound_reference_id(SPAN, ident.name.clone(), ReferenceFlags::Read), ); let binding = self.create_temp_var(reference, &mut temp_var_inits, ctx); - ctx.ast.expression_from_identifier_reference(binding.create_read_reference(ctx)) + binding.create_read_expression(ctx) }; (pow_left, temp_var_inits) @@ -345,10 +345,8 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { } else { let owned_prop = ctx.ast.move_expression(prop); let binding = self.create_temp_var(owned_prop, &mut temp_var_inits, ctx); - let mut create_ident = - || ctx.ast.expression_from_identifier_reference(binding.create_read_reference(ctx)); - *prop = create_ident(); - create_ident() + *prop = binding.create_read_expression(ctx); + binding.create_read_expression(ctx) }; // Complete 2nd member expression @@ -434,10 +432,8 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { } let binding = self.create_temp_var(ctx.ast.move_expression(obj), temp_var_inits, ctx); - let mut create_id = - || ctx.ast.expression_from_identifier_reference(binding.create_read_reference(ctx)); - *obj = create_id(); - create_id() + *obj = binding.create_read_expression(ctx); + binding.create_read_expression(ctx) } /// `x **= right` -> `x = Math.pow(pow_left, right)` (with provided `pow_left`) @@ -498,12 +494,12 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { self.ctx.var_declarations.insert(&binding, None, ctx); // Add new reference `_name = name` to `temp_var_inits` - let left = - AssignmentTarget::from(ctx.ast.simple_assignment_target_from_identifier_reference( - binding.create_read_write_reference(ctx), - )); - let op = AssignmentOperator::Assign; - temp_var_inits.push(ctx.ast.expression_assignment(SPAN, op, left, expr)); + temp_var_inits.push(ctx.ast.expression_assignment( + SPAN, + AssignmentOperator::Assign, + binding.create_read_write_target(ctx), + expr, + )); binding } diff --git a/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs b/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs index 0c1af22e7..403b2bd55 100644 --- a/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs +++ b/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs @@ -91,17 +91,11 @@ impl<'a, 'ctx> Traverse<'a> for NullishCoalescingOperator<'a, 'ctx> { SymbolFlags::FunctionScopedVariable, ); - let left = - AssignmentTarget::from(ctx.ast.simple_assignment_target_from_identifier_reference( - binding.create_read_write_reference(ctx), - )); - - let reference = - ctx.ast.expression_from_identifier_reference(binding.create_read_reference(ctx)); + let reference = binding.create_read_expression(ctx); let assignment = ctx.ast.expression_assignment( SPAN, AssignmentOperator::Assign, - left, + binding.create_read_write_target(ctx), logical_expr.left, ); let mut new_expr = diff --git a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs index 2274b3778..c1f3d359b 100644 --- a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs +++ b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs @@ -153,10 +153,7 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> { if let Some(ident) = self.maybe_generate_memoised(&static_expr.object, ctx) { // (_o = o).a let right = ctx.ast.move_expression(&mut static_expr.object); - let target = - AssignmentTarget::from(ctx.ast.simple_assignment_target_from_identifier_reference( - ident.create_read_write_reference(ctx), - )); + let target = ident.create_read_write_target(ctx); let object = ctx.ast.expression_assignment(SPAN, AssignmentOperator::Assign, target, right); let left_expr = Expression::from(ctx.ast.member_expression_static( @@ -169,7 +166,7 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> { // (_o.a = 1) let assign_expr = ctx.ast.member_expression_static( SPAN, - ctx.ast.expression_from_identifier_reference(ident.create_read_reference(ctx)), + ident.create_read_expression(ctx), static_expr.property.clone_in(ctx.ast.allocator), false, ); @@ -218,10 +215,7 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> { if let Some(ident) = self.maybe_generate_memoised(&computed_expr.object, ctx) { // (_o = object) let right = ctx.ast.move_expression(&mut computed_expr.object); - let target = - AssignmentTarget::from(ctx.ast.simple_assignment_target_from_identifier_reference( - ident.create_read_write_reference(ctx), - )); + let target = ident.create_read_write_target(ctx); let object = ctx.ast.expression_assignment(SPAN, AssignmentOperator::Assign, target, right); @@ -230,16 +224,11 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> { // _b = expression let property = self.maybe_generate_memoised(&expression, ctx); - if let Some(ref property) = property { - let left = AssignmentTarget::from( - ctx.ast.simple_assignment_target_from_identifier_reference( - property.create_read_write_reference(ctx), - ), - ); + if let Some(property) = &property { expression = ctx.ast.expression_assignment( SPAN, AssignmentOperator::Assign, - left, + property.create_read_write_target(ctx), expression, ); } @@ -247,13 +236,10 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> { // _o[_b] let assign_target = AssignmentTarget::from(ctx.ast.member_expression_computed( SPAN, - ctx.ast.expression_from_identifier_reference(ident.create_read_reference(ctx)), + ident.create_read_expression(ctx), property.map_or_else( || expression.clone_in(ctx.ast.allocator), - |ident| { - ctx.ast - .expression_from_identifier_reference(ident.create_read_reference(ctx)) - }, + |ident| ident.create_read_expression(ctx), ), false, )); @@ -278,15 +264,10 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> { { // _key = ++key if let Some(property_ident) = &property_ident { - let left = AssignmentTarget::from( - ctx.ast.simple_assignment_target_from_identifier_reference( - property_ident.create_read_write_reference(ctx), - ), - ); ctx.ast.expression_assignment( SPAN, AssignmentOperator::Assign, - left, + property_ident.create_read_write_target(ctx), ctx.ast.move_expression(&mut expression), ) } else { @@ -306,9 +287,7 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> { object, { if let Some(property_ident) = property_ident { - ctx.ast.expression_from_identifier_reference( - property_ident.create_read_reference(ctx), - ) + property_ident.create_read_expression(ctx) } else { expression } diff --git a/crates/oxc_transformer/src/react/jsx_source.rs b/crates/oxc_transformer/src/react/jsx_source.rs index 4eefc8336..c0068bca8 100644 --- a/crates/oxc_transformer/src/react/jsx_source.rs +++ b/crates/oxc_transformer/src/react/jsx_source.rs @@ -147,8 +147,7 @@ impl<'a, 'ctx> ReactJsxSource<'a, 'ctx> { let filename = { let key = ctx.ast.property_key_identifier_name(SPAN, "fileName"); - let ident = self.get_filename_var(ctx).create_read_reference(ctx); - let value = ctx.ast.expression_from_identifier_reference(ident); + let value = self.get_filename_var(ctx).create_read_expression(ctx); ctx.ast.object_property_kind_object_property( SPAN, kind, key, value, None, false, false, false, ) diff --git a/crates/oxc_transformer/src/react/refresh.rs b/crates/oxc_transformer/src/react/refresh.rs index 18d6e3f0a..8d10e5665 100644 --- a/crates/oxc_transformer/src/react/refresh.rs +++ b/crates/oxc_transformer/src/react/refresh.rs @@ -469,9 +469,7 @@ impl<'a, 'ctx> ReactRefresh<'a, 'ctx> { ) -> AssignmentTarget<'a> { let binding = ctx.generate_uid_in_root_scope("c", SymbolFlags::FunctionScopedVariable); self.registrations.push((binding.symbol_id, persistent_id)); - let ident = binding.create_reference(reference_flags, ctx); - let ident = ctx.ast.simple_assignment_target_from_identifier_reference(ident); - ctx.ast.assignment_target_simple(ident) + binding.create_target(reference_flags, ctx) } /// Similar to the `findInnerComponents` function in `react-refresh/babel`. diff --git a/crates/oxc_traverse/src/context/bound_identifier.rs b/crates/oxc_traverse/src/context/bound_identifier.rs index 61dea4c26..4765c0404 100644 --- a/crates/oxc_traverse/src/context/bound_identifier.rs +++ b/crates/oxc_traverse/src/context/bound_identifier.rs @@ -1,5 +1,5 @@ use oxc_ast::{ - ast::{BindingIdentifier, BindingPattern, IdentifierReference}, + ast::{AssignmentTarget, BindingIdentifier, BindingPattern, Expression, IdentifierReference}, NONE, }; use oxc_span::{Atom, Span, SPAN}; @@ -58,11 +58,18 @@ impl<'a> BoundIdentifier<'a> { ctx.ast.binding_pattern(binding_pattern_kind, NONE, false) } + // --- Read only --- + /// Create `IdentifierReference` referencing this binding, which is read from, with dummy `Span` pub fn create_read_reference(&self, ctx: &mut TraverseCtx<'a>) -> IdentifierReference<'a> { self.create_spanned_read_reference(SPAN, ctx) } + /// Create `Expression::Identifier` referencing this binding, which is read from, with dummy `Span` + pub fn create_read_expression(&self, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { + self.create_spanned_read_expression(SPAN, ctx) + } + /// Create `IdentifierReference` referencing this binding, which is read from, with specified `Span` pub fn create_spanned_read_reference( &self, @@ -72,12 +79,32 @@ impl<'a> BoundIdentifier<'a> { self.create_spanned_reference(span, ReferenceFlags::Read, ctx) } + /// Create `Expression::Identifier` referencing this binding, which is read from, with specified `Span` + pub fn create_spanned_read_expression( + &self, + span: Span, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + self.create_spanned_expression(span, ReferenceFlags::Read, ctx) + } + + // --- Write only --- + /// Create `IdentifierReference` referencing this binding, which is written to, with dummy `Span` - #[allow(unused)] pub fn create_write_reference(&self, ctx: &mut TraverseCtx<'a>) -> IdentifierReference<'a> { self.create_spanned_write_reference(SPAN, ctx) } + /// Create `Expression::Identifier` referencing this binding, which is written to, with dummy `Span` + pub fn create_write_expression(&self, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { + self.create_spanned_write_expression(SPAN, ctx) + } + + /// Create `AssignmentTarget` referencing this binding, which is written to, with dummy `Span` + pub fn create_write_target(&self, ctx: &mut TraverseCtx<'a>) -> AssignmentTarget<'a> { + self.create_spanned_write_target(SPAN, ctx) + } + /// Create `IdentifierReference` referencing this binding, which is written to, with specified `Span` pub fn create_spanned_write_reference( &self, @@ -87,9 +114,28 @@ impl<'a> BoundIdentifier<'a> { self.create_spanned_reference(span, ReferenceFlags::Write, ctx) } + /// Create `Expression::Identifier` referencing this binding, which is written to, with specified `Span` + pub fn create_spanned_write_expression( + &self, + span: Span, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + self.create_spanned_expression(span, ReferenceFlags::Write, ctx) + } + + /// Create `AssignmentTarget` referencing this binding, which is written to, with specified `Span` + pub fn create_spanned_write_target( + &self, + span: Span, + ctx: &mut TraverseCtx<'a>, + ) -> AssignmentTarget<'a> { + self.create_spanned_target(span, ReferenceFlags::Write, ctx) + } + + // --- Read and write --- + /// Create `IdentifierReference` referencing this binding, which is read from + written to, /// with dummy `Span` - #[allow(unused)] pub fn create_read_write_reference( &self, ctx: &mut TraverseCtx<'a>, @@ -97,6 +143,18 @@ impl<'a> BoundIdentifier<'a> { self.create_spanned_read_write_reference(SPAN, ctx) } + /// Create `Expression::Identifier` referencing this binding, which is read from + written to, + /// with dummy `Span` + pub fn create_read_write_expression(&self, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { + self.create_spanned_read_write_expression(SPAN, ctx) + } + + /// Create `AssignmentTarget` referencing this binding, which is read from + written to, + /// with dummy `Span` + pub fn create_read_write_target(&self, ctx: &mut TraverseCtx<'a>) -> AssignmentTarget<'a> { + self.create_spanned_read_write_target(SPAN, ctx) + } + /// Create `IdentifierReference` referencing this binding, which is read from + written to, /// with specified `Span` pub fn create_spanned_read_write_reference( @@ -107,6 +165,28 @@ impl<'a> BoundIdentifier<'a> { self.create_spanned_reference(span, ReferenceFlags::Read | ReferenceFlags::Write, ctx) } + /// Create `Expression::Identifier` referencing this binding, which is read from + written to, + /// with specified `Span` + pub fn create_spanned_read_write_expression( + &self, + span: Span, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + self.create_spanned_expression(span, ReferenceFlags::Read | ReferenceFlags::Write, ctx) + } + + /// Create `AssignmentTarget` referencing this binding, which is read from + written to, + /// with specified `Span` + pub fn create_spanned_read_write_target( + &self, + span: Span, + ctx: &mut TraverseCtx<'a>, + ) -> AssignmentTarget<'a> { + self.create_spanned_target(span, ReferenceFlags::Read | ReferenceFlags::Write, ctx) + } + + // --- Specified ReferenceFlags --- + /// Create `IdentifierReference` referencing this binding, with specified `ReferenceFlags` pub fn create_reference( &self, @@ -116,6 +196,24 @@ impl<'a> BoundIdentifier<'a> { self.create_spanned_reference(SPAN, flags, ctx) } + /// Create `Expression::Identifier` referencing this binding, with specified `ReferenceFlags` + pub fn create_expression( + &self, + flags: ReferenceFlags, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + self.create_spanned_expression(SPAN, flags, ctx) + } + + /// Create `AssignmentTarget` referencing this binding, with specified `ReferenceFlags` + pub fn create_target( + &self, + flags: ReferenceFlags, + ctx: &mut TraverseCtx<'a>, + ) -> AssignmentTarget<'a> { + self.create_spanned_target(SPAN, flags, ctx) + } + /// Create `IdentifierReference` referencing this binding, with specified `Span` and `ReferenceFlags` pub fn create_spanned_reference( &self, @@ -125,4 +223,26 @@ impl<'a> BoundIdentifier<'a> { ) -> IdentifierReference<'a> { ctx.create_bound_reference_id(span, self.name.clone(), self.symbol_id, flags) } + + /// Create `Expression::Identifier` referencing this binding, with specified `Span` and `ReferenceFlags` + pub fn create_spanned_expression( + &self, + span: Span, + flags: ReferenceFlags, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + let ident = self.create_spanned_reference(span, flags, ctx); + ctx.ast.expression_from_identifier_reference(ident) + } + + /// Create `Expression::Identifier` referencing this binding, with specified `Span` and `ReferenceFlags` + pub fn create_spanned_target( + &self, + span: Span, + flags: ReferenceFlags, + ctx: &mut TraverseCtx<'a>, + ) -> AssignmentTarget<'a> { + let ident = self.create_spanned_reference(span, flags, ctx); + AssignmentTarget::from(ctx.ast.simple_assignment_target_from_identifier_reference(ident)) + } }