feat(transformer/object-rest-spread): using helper loader (#6449)

This commit is contained in:
Dunqing 2024-10-14 01:34:53 +00:00
parent c0e9d7eb77
commit 41c8675f0d
5 changed files with 32 additions and 39 deletions

View file

@ -262,7 +262,6 @@ impl<'a> HelperLoaderStore<'a> {
} }
/// Load a helper function and return the callee expression. /// Load a helper function and return the callee expression.
#[allow(dead_code)]
pub fn load(&self, helper_name: Atom<'a>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { pub fn load(&self, helper_name: Atom<'a>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {
match self.mode { match self.mode {
HelperLoaderMode::Runtime => self.transform_for_runtime_helper(&helper_name, ctx), HelperLoaderMode::Runtime => self.transform_for_runtime_helper(&helper_name, ctx),

View file

@ -6,25 +6,28 @@ pub use options::ES2018Options;
use oxc_ast::ast::*; use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx}; use oxc_traverse::{Traverse, TraverseCtx};
pub struct ES2018 { use crate::context::TransformCtx;
pub struct ES2018<'a, 'ctx> {
options: ES2018Options, options: ES2018Options,
// Plugins // Plugins
object_rest_spread: ObjectRestSpread, object_rest_spread: ObjectRestSpread<'a, 'ctx>,
} }
impl ES2018 { impl<'a, 'ctx> ES2018<'a, 'ctx> {
pub fn new(options: ES2018Options) -> Self { pub fn new(options: ES2018Options, ctx: &'ctx TransformCtx<'a>) -> Self {
Self { Self {
object_rest_spread: ObjectRestSpread::new( object_rest_spread: ObjectRestSpread::new(
options.object_rest_spread.unwrap_or_default(), options.object_rest_spread.unwrap_or_default(),
ctx,
), ),
options, options,
} }
} }
} }
impl<'a> Traverse<'a> for ES2018 { impl<'a, 'ctx> Traverse<'a> for ES2018<'a, 'ctx> {
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
if self.options.object_rest_spread.is_some() { if self.options.object_rest_spread.is_some() {
self.object_rest_spread.enter_expression(expr, ctx); self.object_rest_spread.enter_expression(expr, ctx);

View file

@ -32,6 +32,8 @@ use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx}; use oxc_traverse::{Traverse, TraverseCtx};
use serde::Deserialize; use serde::Deserialize;
use crate::context::TransformCtx;
mod object_rest; mod object_rest;
mod object_spread; mod object_spread;
@ -43,27 +45,27 @@ pub struct ObjectRestSpreadOptions {
pub(crate) use_built_ins: bool, pub(crate) use_built_ins: bool,
} }
pub struct ObjectRestSpread { pub struct ObjectRestSpread<'a, 'ctx> {
#[allow(dead_code)] #[allow(dead_code)]
options: ObjectRestSpreadOptions, options: ObjectRestSpreadOptions,
// Plugins // Plugins
object_spread: ObjectSpread, object_spread: ObjectSpread<'a, 'ctx>,
#[allow(dead_code)] #[allow(dead_code)]
object_rest: ObjectRest, object_rest: ObjectRest,
} }
impl ObjectRestSpread { impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> {
pub fn new(options: ObjectRestSpreadOptions) -> Self { pub fn new(options: ObjectRestSpreadOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
Self { Self {
object_spread: ObjectSpread::new(options), object_spread: ObjectSpread::new(options, ctx),
object_rest: ObjectRest::new(options), object_rest: ObjectRest::new(options),
options, options,
} }
} }
} }
impl<'a> Traverse<'a> for ObjectRestSpread { impl<'a, 'ctx> Traverse<'a> for ObjectRestSpread<'a, 'ctx> {
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
self.object_spread.enter_expression(expr, ctx); self.object_spread.enter_expression(expr, ctx);
} }

View file

@ -31,18 +31,21 @@ use oxc_semantic::{ReferenceFlags, SymbolId};
use oxc_span::SPAN; use oxc_span::SPAN;
use oxc_traverse::{Traverse, TraverseCtx}; use oxc_traverse::{Traverse, TraverseCtx};
use crate::context::TransformCtx;
use super::ObjectRestSpreadOptions; use super::ObjectRestSpreadOptions;
pub struct ObjectSpread { pub struct ObjectSpread<'a, 'ctx> {
options: ObjectRestSpreadOptions, options: ObjectRestSpreadOptions,
ctx: &'ctx TransformCtx<'a>,
} }
impl ObjectSpread { impl<'a, 'ctx> ObjectSpread<'a, 'ctx> {
pub fn new(options: ObjectRestSpreadOptions) -> Self { pub fn new(options: ObjectRestSpreadOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
Self { options } Self { options, ctx }
} }
} }
impl<'a> Traverse<'a> for ObjectSpread { impl<'a, 'ctx> Traverse<'a> for ObjectSpread<'a, 'ctx> {
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
let Expression::ObjectExpression(obj_expr) = expr else { let Expression::ObjectExpression(obj_expr) = expr else {
return; return;
@ -77,9 +80,8 @@ impl<'a> Traverse<'a> for ObjectSpread {
arguments.push(Argument::from(ctx.ast.move_expression(&mut spread_prop.argument))); arguments.push(Argument::from(ctx.ast.move_expression(&mut spread_prop.argument)));
let object_id = ctx.scopes().find_binding(ctx.current_scope_id(), "Object"); let object_id = ctx.scopes().find_binding(ctx.current_scope_id(), "Object");
let babel_helpers_id = ctx.scopes().find_binding(ctx.current_scope_id(), "babelHelpers");
let callee = self.get_extend_object_callee(object_id, babel_helpers_id, ctx); let callee = self.get_extend_object_callee(object_id, ctx);
// ({ ...x }) => _objectSpread({}, x) // ({ ...x }) => _objectSpread({}, x)
*expr = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false); *expr = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false);
@ -91,14 +93,14 @@ impl<'a> Traverse<'a> for ObjectSpread {
arguments.push(Argument::from(ctx.ast.move_expression(expr))); arguments.push(Argument::from(ctx.ast.move_expression(expr)));
arguments.push(Argument::from(ctx.ast.expression_object(SPAN, obj_prop_list, None))); arguments.push(Argument::from(ctx.ast.expression_object(SPAN, obj_prop_list, None)));
let callee = self.get_extend_object_callee(object_id, babel_helpers_id, ctx); let callee = self.get_extend_object_callee(object_id, ctx);
*expr = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false); *expr = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false);
} }
} }
} }
impl<'a> ObjectSpread { impl<'a, 'ctx> ObjectSpread<'a, 'ctx> {
fn object_assign(symbol_id: Option<SymbolId>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { fn object_assign(symbol_id: Option<SymbolId>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {
let ident = let ident =
ctx.create_reference_id(SPAN, Atom::from("Object"), symbol_id, ReferenceFlags::Read); ctx.create_reference_id(SPAN, Atom::from("Object"), symbol_id, ReferenceFlags::Read);
@ -108,32 +110,19 @@ impl<'a> ObjectSpread {
Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)) Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false))
} }
fn babel_external_helper( fn babel_external_helper(&self, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {
symbol_id: Option<SymbolId>, self.ctx.helper_loader.load(Atom::from("objectSpread2"), ctx)
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let ident = ctx.create_reference_id(
SPAN,
Atom::from("babelHelpers"),
symbol_id,
ReferenceFlags::Read,
);
let object = ctx.ast.expression_from_identifier_reference(ident);
let property = ctx.ast.identifier_name(SPAN, Atom::from("objectSpread2"));
Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false))
} }
fn get_extend_object_callee( fn get_extend_object_callee(
&mut self, &mut self,
object_id: Option<SymbolId>, object_id: Option<SymbolId>,
babel_helpers_id: Option<SymbolId>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> { ) -> Expression<'a> {
if self.options.set_spread_properties { if self.options.set_spread_properties {
Self::object_assign(object_id, ctx) Self::object_assign(object_id, ctx)
} else { } else {
Self::babel_external_helper(babel_helpers_id, ctx) self.babel_external_helper(ctx)
} }
} }
} }

View file

@ -93,7 +93,7 @@ impl<'a> Transformer<'a> {
x2_es2021: ES2021::new(self.options.es2021, &self.ctx), x2_es2021: ES2021::new(self.options.es2021, &self.ctx),
x2_es2020: ES2020::new(self.options.es2020, &self.ctx), x2_es2020: ES2020::new(self.options.es2020, &self.ctx),
x2_es2019: ES2019::new(self.options.es2019), x2_es2019: ES2019::new(self.options.es2019),
x2_es2018: ES2018::new(self.options.es2018), x2_es2018: ES2018::new(self.options.es2018, &self.ctx),
x2_es2016: ES2016::new(self.options.es2016, &self.ctx), x2_es2016: ES2016::new(self.options.es2016, &self.ctx),
x3_es2015: ES2015::new(self.options.es2015), x3_es2015: ES2015::new(self.options.es2015),
x4_regexp: RegExp::new(self.options.regexp, &self.ctx), x4_regexp: RegExp::new(self.options.regexp, &self.ctx),
@ -112,7 +112,7 @@ struct TransformerImpl<'a, 'ctx> {
x2_es2021: ES2021<'a, 'ctx>, x2_es2021: ES2021<'a, 'ctx>,
x2_es2020: ES2020<'a, 'ctx>, x2_es2020: ES2020<'a, 'ctx>,
x2_es2019: ES2019, x2_es2019: ES2019,
x2_es2018: ES2018, x2_es2018: ES2018<'a, 'ctx>,
x2_es2016: ES2016<'a, 'ctx>, x2_es2016: ES2016<'a, 'ctx>,
x3_es2015: ES2015<'a>, x3_es2015: ES2015<'a>,
x4_regexp: RegExp<'a, 'ctx>, x4_regexp: RegExp<'a, 'ctx>,