diff --git a/crates/oxc_transformer/src/es2018/mod.rs b/crates/oxc_transformer/src/es2018/mod.rs index a459d22a3fcd20..66d1d6c25a928e 100644 --- a/crates/oxc_transformer/src/es2018/mod.rs +++ b/crates/oxc_transformer/src/es2018/mod.rs @@ -34,4 +34,14 @@ impl<'a, 'ctx> Traverse<'a> for ES2018<'a, 'ctx> { self.object_rest_spread.enter_expression(expr, ctx); } } + + fn enter_variable_declaration( + &mut self, + decl: &mut VariableDeclaration<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + if self.options.object_rest_spread.is_some() { + self.object_rest_spread.enter_variable_declaration(decl, ctx); + } + } } diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread.rs b/crates/oxc_transformer/src/es2018/object_rest_spread.rs index ba174c84505560..1cebe7b0e1a6cb 100644 --- a/crates/oxc_transformer/src/es2018/object_rest_spread.rs +++ b/crates/oxc_transformer/src/es2018/object_rest_spread.rs @@ -29,7 +29,7 @@ use serde::Deserialize; use oxc_ast::{ast::*, NONE}; -use oxc_semantic::{ReferenceFlags, SymbolId}; +use oxc_semantic::{ReferenceFlags, SymbolFlags, SymbolId}; use oxc_span::SPAN; use oxc_traverse::{Traverse, TraverseCtx}; @@ -46,6 +46,7 @@ pub struct ObjectRestSpreadOptions { pub struct ObjectRestSpread<'a, 'ctx> { ctx: &'ctx TransformCtx<'a>, + options: ObjectRestSpreadOptions, } @@ -59,6 +60,14 @@ impl<'a, 'ctx> Traverse<'a> for ObjectRestSpread<'a, 'ctx> { fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { self.transform_object_expression(expr, ctx); } + + fn enter_variable_declaration( + &mut self, + decl: &mut VariableDeclaration<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.transform_variable_declaration(decl, ctx); + } } impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> { @@ -148,3 +157,52 @@ impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> { Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)) } } + +impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> { + fn transform_variable_declaration( + &mut self, + decl: &mut VariableDeclaration<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + for variable_declarator in decl.declarations.iter_mut() { + self.transform_variable_declarator(variable_declarator, ctx); + } + } + + fn transform_variable_declarator( + &mut self, + decl: &mut VariableDeclarator<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + // Get the object pattern. + let BindingPatternKind::ObjectPattern(pat) = &decl.id.kind else { return }; + // Does not have a object rest. + let Some(rest) = &pat.rest else { + return; + }; + // Rest binding is not an identifier (syntax error). + if !rest.argument.kind.is_binding_identifier() { + return; + } + // Does not have an init (syntax error). + let Some(init) = &decl.init else { return }; + + let binding = ctx + .generate_uid_in_current_scope_based_on_node(init, SymbolFlags::FunctionScopedVariable); + + decl.id.kind = ctx + .ast + .binding_pattern_kind_from_binding_identifier(binding.create_binding_identifier(ctx)); + + // let mut new_declarators = ctx.ast.vec(); + + let BindingPatternKind::ObjectPattern(pat) = &mut decl.id.kind else { unreachable!() }; + let BindingPatternKind::BindingIdentifier(rest_ident) = pat.rest.unwrap().argument.kind + else { + unreachable!() + }; + + // rest + dbg!(binding); + } +} diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index a75fbd545e380d..8dbbd429a76985 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -159,6 +159,14 @@ impl<'a, 'ctx> Traverse<'a> for TransformerImpl<'a, 'ctx> { } } + fn enter_variable_declaration( + &mut self, + decl: &mut VariableDeclaration<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.x2_es2018.enter_variable_declaration(decl, ctx); + } + fn enter_variable_declarator( &mut self, decl: &mut VariableDeclarator<'a>,