Skip to content

Commit

Permalink
refactor(transformer): update object-rest-spread plugin implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed May 6, 2024
1 parent 7074916 commit 401ddc6
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 20 deletions.
4 changes: 4 additions & 0 deletions crates/oxc_transformer/src/es2018/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ impl<'a> ES2018<'a> {
self.object_rest_spread.transform_expression(expr);
}
}

pub fn transform_program_on_exit(&mut self, program: &mut Program<'a>) {
self.object_rest_spread.transform_program_on_exit(program);
}
}
9 changes: 4 additions & 5 deletions crates/oxc_transformer/src/es2018/object_rest_spread.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::rc::Rc;

use oxc_ast::ast::*;
use serde::Deserialize;

Expand Down Expand Up @@ -27,15 +25,12 @@ pub struct ObjectRestSpreadOptions {
/// * <https://babeljs.io/docs/babel-plugin-transform-object-rest-spread>
/// * <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-object-rest-spread>
pub struct ObjectRestSpread<'a> {
ctx: Ctx<'a>,

object_spread: ObjectSpread<'a>,
}

impl<'a> ObjectRestSpread<'a> {
pub fn new(assumptions: CompilerAssumptions, ctx: &Ctx<'a>) -> Self {
Self {
ctx: Rc::clone(ctx),
object_spread: ObjectSpread::new(
ObjectSpreadOptions {
set_spread_properties: assumptions.set_spread_properties,
Expand All @@ -49,4 +44,8 @@ impl<'a> ObjectRestSpread<'a> {
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
self.object_spread.transform_expression(expr);
}

pub fn transform_program_on_exit(&mut self, program: &mut Program<'a>) {
self.object_spread.transform_program_on_exit(program);
}
}
58 changes: 44 additions & 14 deletions crates/oxc_transformer/src/es2018/object_spread.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::rc::Rc;

use oxc_ast::{ast::*, AstBuilder};
use oxc_span::SPAN;
use oxc_span::{CompactStr, SPAN};
use serde::Deserialize;

use crate::context::Ctx;
use crate::{context::Ctx, helpers::module_imports::NamedImport};

#[derive(Debug, Default, Clone, Copy, Deserialize)]
pub struct ObjectSpreadOptions {
Expand Down Expand Up @@ -37,10 +37,24 @@ impl<'a> ObjectSpread<'a> {
self.ast().static_member_expression(SPAN, object, property, false)
}

fn get_extend_object_callee(&self) -> Expression<'a> {
fn get_extend_object_callee(&mut self) -> Expression<'a> {
if self.options.set_spread_properties {
self.get_static_member_expression("Object", "assign")
} else {
if self.ctx.semantic.source_type().is_module() {
self.add_import_statement(
"default",
"_objectSpread",
"@babel/helpers/lib/helpers/objectSpread2.js".into(),
);
} else {
self.add_require_statement(
"_objectSpread",
"@babel/helpers/lib/helpers/objectSpread2.js".into(),
true,
);
}

let ident = IdentifierReference::new(SPAN, self.ast().new_atom("_objectSpread"));
self.ast().identifier_reference_expression(ident)
}
Expand Down Expand Up @@ -69,8 +83,7 @@ impl<'a> ObjectSpread<'a> {
obj_prop_list.push(prop);
}

let ObjectPropertyKind::SpreadProperty(mut spread_prop) =
obj_expr.properties.pop().unwrap()
let Some(ObjectPropertyKind::SpreadProperty(mut spread_prop)) = obj_expr.properties.pop()
else {
unreachable!();
};
Expand All @@ -80,22 +93,39 @@ impl<'a> ObjectSpread<'a> {
args.push(Argument::from(self.ast().move_expression(expr)));
args.push(Argument::from(self.ast().move_expression(&mut spread_prop.argument)));

*expr =
self.ast().call_expression(SPAN, self.get_extend_object_callee(), args, false, None);
let callee = self.get_extend_object_callee();

*expr = self.ast().call_expression(SPAN, callee, args, false, None);

if !obj_prop_list.is_empty() {
obj_prop_list.reverse();
let mut args = self.ast().new_vec();
args.push(Argument::from(self.ast().move_expression(expr)));
args.push(Argument::from(self.ast().object_expression(SPAN, obj_prop_list, None)));

*expr = self.ast().call_expression(
SPAN,
self.get_extend_object_callee(),
args,
false,
None,
);
let callee = self.get_extend_object_callee();

*expr = self.ast().call_expression(SPAN, callee, args, false, None);
}
}

pub fn transform_program_on_exit(&mut self, program: &mut Program<'a>) {
let imports = self.ctx.module_imports.get_import_statements();
let index = program
.body
.iter()
.rposition(|stmt| matches!(stmt, Statement::ImportDeclaration(_)))
.map_or(0, |i| i + 1);
program.body.splice(index..index, imports);
}

fn add_import_statement(&mut self, imported: &str, local: &str, source: CompactStr) {
let import = NamedImport::new(imported.into(), Some(local.into()));
self.ctx.module_imports.add_import(source, import);
}

fn add_require_statement(&mut self, variable_name: &str, source: CompactStr, front: bool) {
let import = NamedImport::new(variable_name.into(), None);
self.ctx.module_imports.add_require(source, import, front);
}
}
1 change: 1 addition & 0 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> {

self.x1_react.transform_program_on_exit(program);
self.x0_typescript.transform_program_on_exit(program);
self.x3_es2018.transform_program_on_exit(program);
}

// ALPHASORT
Expand Down
6 changes: 5 additions & 1 deletion tasks/transform_conformance/src/test_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ fn transform_options(options: &BabelOptions) -> serde_json::Result<TransformOpti
}
}

let assumptions= serde_json::from_value(options.assumptions.clone()).unwrap_or_default();

let react = if let Some(options) = options.get_preset("react") {
get_options::<ReactOptions>(options)?
} else {
Expand Down Expand Up @@ -108,11 +110,13 @@ fn transform_options(options: &BabelOptions) -> serde_json::Result<TransformOpti
.get_plugin("transform-object-rest-spread")
.map(get_options)
.transpose()?,

assumptions,
};

Ok(TransformOptions {
cwd: options.cwd.clone().unwrap(),
assumptions: serde_json::from_value(options.assumptions.clone()).unwrap_or_default(),
assumptions,
typescript: options
.get_plugin("transform-typescript")
.map(get_options::<TypeScriptOptions>)
Expand Down

0 comments on commit 401ddc6

Please sign in to comment.