Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Nov 14, 2024
1 parent b31ef44 commit cfa877e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 9 deletions.
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
8 changes: 4 additions & 4 deletions crates/oxc_transformer/src/es2018/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ pub(crate) mod async_generator_functions;
mod object_rest_spread;
mod options;

use oxc_ast::ast::{
ArrowFunctionExpression, CatchClause, Expression, ForInStatement, ForOfStatement, ForStatement,
Function, Statement, VariableDeclaration,
};
use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx};

use crate::context::TransformCtx;
Expand Down Expand Up @@ -58,6 +55,9 @@ impl<'a, 'ctx> Traverse<'a> for ES2018<'a, 'ctx> {
if self.options.async_generator_functions {
self.async_generator_functions.enter_statement(stmt, ctx);
}
if self.options.object_rest_spread.is_some() {
self.object_rest_spread.enter_statement(stmt, ctx);
}
}

fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
Expand Down
45 changes: 42 additions & 3 deletions crates/oxc_transformer/src/es2018/object_rest_spread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ use serde::Deserialize;
use oxc_allocator::{CloneIn, Vec as ArenaVec};
use oxc_ast::{ast::*, NONE};
use oxc_diagnostics::OxcDiagnostic;
use oxc_ecmascript::ToJsString;
use oxc_ecmascript::{BoundNames, ToJsString};
use oxc_semantic::{IsGlobalReference, ScopeId, SymbolFlags};
use oxc_span::{GetSpan, SPAN};
use oxc_traverse::{MaybeBoundIdentifier, Traverse, TraverseCtx};
use oxc_traverse::{BoundIdentifier, MaybeBoundIdentifier, Traverse, TraverseCtx};

use crate::{common::helper_loader::Helper, TransformCtx};

Expand Down Expand Up @@ -147,6 +147,43 @@ impl<'a, 'ctx> Traverse<'a> for ObjectRestSpread<'a, 'ctx> {
_ => {}
}
}

fn enter_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
self.transform_named_export(stmt, ctx);
}
}

impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> {
// Transform `export var { ...x } = y` ->
// ```
// var x = _extends({}, (_objectDestructuringEmpty(y), y));
// export { x };
//
// ```
fn transform_named_export(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
let Statement::ExportNamedDeclaration(export_named_declaration) = stmt else { return };
let Some(decl) = &mut export_named_declaration.declaration else { return };
let Declaration::VariableDeclaration(var_decl) = decl else { return };
let changed = self.transform_variable_declaration(var_decl, ctx);
if changed {
let mut specifiers = vec![];
decl.bound_names(&mut |ident| {
specifiers.push(ident.clone());
});
export_named_declaration.specifiers.extend(specifiers.into_iter().map(|ident| {
let local = ModuleExportName::IdentifierReference(
BoundIdentifier::from_binding_ident(&ident).create_read_reference(ctx),
);
let exported =
ctx.ast.module_export_name_identifier_name(ident.span, ident.name.clone());
ctx.ast.export_specifier(ident.span, local, exported, ImportOrExportKind::Value)
}));
if let Some(declaration) = export_named_declaration.declaration.take() {
let new_stmt = Statement::from(declaration);
self.ctx.statement_injector.insert_before(stmt, new_stmt);
}
}
}
}

// Transform `({ x, ..y })`.
Expand Down Expand Up @@ -301,7 +338,7 @@ impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> {
&mut self,
decl: &mut VariableDeclaration<'a>,
ctx: &mut TraverseCtx<'a>,
) {
) -> bool {
let mut new_decls = vec![];
for (i, variable_declarator) in decl.declarations.iter_mut().enumerate() {
if Self::has_nested_object_rest(&variable_declarator.id) {
Expand All @@ -310,10 +347,12 @@ impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> {
}
}
}
let changed = !new_decls.is_empty();
// TODO: performance can be improved by not shuffling the vec multiple times.
for (i, decls) in new_decls {
decl.declarations.splice(i..=i, decls);
}
changed
}

/// Recursively check for object rest.
Expand Down
4 changes: 3 additions & 1 deletion tasks/transform_conformance/snapshots/babel.snap.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,9 @@ after transform: SymbolId(0): [ReferenceId(1), ReferenceId(2), ReferenceId(4)]
rebuilt : SymbolId(0): [ReferenceId(3), ReferenceId(4)]

* object-rest/export/input.mjs
x Output mismatch
Unresolved reference IDs mismatch for "asdf2":
after transform: [ReferenceId(0), ReferenceId(3), ReferenceId(4)]
rebuilt : [ReferenceId(0), ReferenceId(2)]

* object-rest/for-x/input.js
x Output mismatch
Expand Down

0 comments on commit cfa877e

Please sign in to comment.