Skip to content

Commit

Permalink
feat(transformer): transform object rest spread
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Nov 19, 2024
1 parent 4c367b6 commit 79c15c8
Show file tree
Hide file tree
Showing 32 changed files with 2,634 additions and 654 deletions.
10 changes: 10 additions & 0 deletions crates/oxc_ast/src/ast_impl/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,16 @@ impl<'a> BindingPatternKind<'a> {
matches!(self, Self::BindingIdentifier(_))
}

#[allow(missing_docs)]
pub fn is_object_pattern(&self) -> bool {
matches!(self, Self::ObjectPattern(_))
}

#[allow(missing_docs)]
pub fn is_array_pattern(&self) -> bool {
matches!(self, Self::ArrayPattern(_))
}

#[allow(missing_docs)]
pub fn is_assignment_pattern(&self) -> bool {
matches!(self, Self::AssignmentPattern(_))
Expand Down
6 changes: 4 additions & 2 deletions crates/oxc_transformer/examples/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use oxc_codegen::CodeGenerator;
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use oxc_transformer::{EnvOptions, TransformOptions, Transformer};
use oxc_transformer::{EnvOptions, HelperLoaderMode, TransformOptions, Transformer};
use pico_args::Arguments;

// Instruction:
Expand Down Expand Up @@ -55,7 +55,7 @@ fn main() {

let (symbols, scopes) = ret.semantic.into_symbol_table_and_scope_tree();

let transform_options = if let Some(query) = &targets {
let mut transform_options = if let Some(query) = &targets {
TransformOptions {
env: EnvOptions::from_browserslist_query(query).unwrap(),
..TransformOptions::default()
Expand All @@ -66,6 +66,8 @@ fn main() {
TransformOptions::enable_all()
};

transform_options.helper_loader.mode = HelperLoaderMode::External;

let ret = Transformer::new(&allocator, path, &transform_options).build_with_symbols_and_scopes(
symbols,
scopes,
Expand Down
8 changes: 8 additions & 0 deletions crates/oxc_transformer/src/common/helper_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ pub enum Helper {
AsyncToGenerator,
ObjectSpread2,
WrapAsyncGenerator,
Extends,
ObjectDestructuringEmpty,
ObjectWithoutProperties,
ToPropertyKey,
}

impl Helper {
Expand All @@ -154,6 +158,10 @@ impl Helper {
Self::AsyncToGenerator => "asyncToGenerator",
Self::ObjectSpread2 => "objectSpread2",
Self::WrapAsyncGenerator => "wrapAsyncGenerator",
Self::Extends => "extends",
Self::ObjectDestructuringEmpty => "objectDestructuringEmpty",
Self::ObjectWithoutProperties => "objectWithoutProperties",
Self::ToPropertyKey => "toPropertyKey",
}
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/oxc_transformer/src/common/statement_injector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ impl<'a> StatementInjectorStore<'a> {
// The non-trivial inner functions are not marked `#[inline]` - compiler can decide whether to inline or not.
impl<'a> StatementInjectorStore<'a> {
/// Add a statement to be inserted immediately before the target statement.
#[expect(dead_code)]
#[inline]
pub fn insert_before<A: GetAddress>(&self, target: &A, stmt: Statement<'a>) {
self.insert_before_address(target.address(), stmt);
Expand Down
2 changes: 0 additions & 2 deletions crates/oxc_transformer/src/compiler_assumptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ pub struct CompilerAssumptions {
pub enumerable_module_meta: bool,

#[serde(default)]
#[deprecated = "Not Implemented"]
pub ignore_function_length: bool,

#[serde(default)]
Expand Down Expand Up @@ -61,7 +60,6 @@ pub struct CompilerAssumptions {
pub no_uninitialized_private_field_access: bool,

#[serde(default)]
#[deprecated = "Not Implemented"]
pub object_rest_no_symbols: bool,

#[serde(default)]
Expand Down
5 changes: 4 additions & 1 deletion crates/oxc_transformer/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
statement_injector::StatementInjectorStore, top_level_statements::TopLevelStatementsStore,
var_declarations::VarDeclarationsStore,
},
Module, TransformOptions,
CompilerAssumptions, Module, TransformOptions,
};

pub struct TransformCtx<'a> {
Expand All @@ -31,6 +31,8 @@ pub struct TransformCtx<'a> {

pub module: Module,

pub assumptions: CompilerAssumptions,

// Helpers
/// Manage helper loading
pub helper_loader: HelperLoaderStore<'a>,
Expand Down Expand Up @@ -61,6 +63,7 @@ impl<'a> TransformCtx<'a> {
source_type: SourceType::default(),
source_text: "",
module: options.env.module,
assumptions: options.assumptions,
helper_loader: HelperLoaderStore::new(&options.helper_loader),
module_imports: ModuleImportsStore::new(),
var_declarations: VarDeclarationsStore::new(),
Expand Down
54 changes: 51 additions & 3 deletions crates/oxc_transformer/src/es2018/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ pub(crate) mod async_generator_functions;
mod object_rest_spread;
mod options;

use oxc_ast::ast::{Expression, ForOfStatement, Function, Statement};
use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx};

use crate::context::TransformCtx;

use async_generator_functions::AsyncGeneratorFunctions;
pub use object_rest_spread::{ObjectRestSpread, ObjectRestSpreadOptions};
pub use options::ES2018Options;
Expand All @@ -32,6 +33,12 @@ impl<'a, 'ctx> ES2018<'a, 'ctx> {
}

impl<'a, 'ctx> Traverse<'a> for ES2018<'a, 'ctx> {
fn exit_program(&mut self, program: &mut oxc_ast::ast::Program<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.object_rest_spread.is_some() {
self.object_rest_spread.exit_program(program, ctx);
}
}

fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.object_rest_spread.is_some() {
self.object_rest_spread.enter_expression(expr, ctx);
Expand All @@ -56,9 +63,34 @@ impl<'a, 'ctx> Traverse<'a> for ES2018<'a, 'ctx> {
}
}

fn enter_for_of_statement(&mut self, node: &mut ForOfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
fn enter_for_in_statement(&mut self, stmt: &mut ForInStatement<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.object_rest_spread.is_some() {
self.object_rest_spread.enter_for_in_statement(stmt, ctx);
}
}

fn enter_for_of_statement(&mut self, stmt: &mut ForOfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.async_generator_functions {
self.async_generator_functions.enter_for_of_statement(node, ctx);
self.async_generator_functions.enter_for_of_statement(stmt, ctx);
}
if self.options.object_rest_spread.is_some() {
self.object_rest_spread.enter_for_of_statement(stmt, ctx);
}
}

fn enter_arrow_function_expression(
&mut self,
arrow: &mut ArrowFunctionExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if self.options.object_rest_spread.is_some() {
self.object_rest_spread.enter_arrow_function_expression(arrow, ctx);
}
}

fn enter_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.object_rest_spread.is_some() {
self.object_rest_spread.enter_function(func, ctx);
}
}

Expand All @@ -67,4 +99,20 @@ impl<'a, 'ctx> Traverse<'a> for ES2018<'a, 'ctx> {
self.async_generator_functions.exit_function(node, 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);
}
}

fn enter_catch_clause(&mut self, clause: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.object_rest_spread.is_some() {
self.object_rest_spread.enter_catch_clause(clause, ctx);
}
}
}
Loading

0 comments on commit 79c15c8

Please sign in to comment.