refactor(transformer): combine ObjectRestSpread into a single file (#7002)

This commit is contained in:
Boshen 2024-10-29 13:21:46 +00:00
parent e5ecbb9bf1
commit d9edef6ae1
5 changed files with 31 additions and 128 deletions

View file

@ -1,6 +1,6 @@
//! ES2018 object spread transformation.
//!
//! This plugin transforms object spread properties (`{ ...x }`) to a series of `_objectSpread` calls.
//! This plugin transforms rest properties for object destructuring assignment and spread properties for object literals.
//!
//! > This plugin is included in `preset-env`, in ES2018
//!
@ -26,6 +26,8 @@
//! * Babel plugin implementation: <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-object-rest-spread>
//! * Object rest/spread TC39 proposal: <https://github.com/tc39/proposal-object-rest-spread>
use serde::Deserialize;
use oxc_ast::{ast::*, NONE};
use oxc_semantic::{ReferenceFlags, SymbolId};
use oxc_span::SPAN;
@ -33,20 +35,38 @@ use oxc_traverse::{Traverse, TraverseCtx};
use crate::{common::helper_loader::Helper, TransformCtx};
use super::ObjectRestSpreadOptions;
#[derive(Debug, Default, Clone, Copy, Deserialize)]
#[serde(default, rename_all = "camelCase")]
pub struct ObjectRestSpreadOptions {
#[serde(alias = "loose")]
pub(crate) set_spread_properties: bool,
pub struct ObjectSpread<'a, 'ctx> {
options: ObjectRestSpreadOptions,
ctx: &'ctx TransformCtx<'a>,
pub(crate) use_built_ins: bool,
}
impl<'a, 'ctx> ObjectSpread<'a, 'ctx> {
pub struct ObjectRestSpread<'a, 'ctx> {
ctx: &'ctx TransformCtx<'a>,
options: ObjectRestSpreadOptions,
}
impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> {
pub fn new(options: ObjectRestSpreadOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
Self { options, ctx }
Self { ctx, options }
}
}
impl<'a, 'ctx> Traverse<'a> for ObjectSpread<'a, 'ctx> {
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);
}
}
impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> {
fn transform_object_expression(
&mut self,
expr: &mut Expression<'a>,
ctx: &mut TraverseCtx<'a>,
) {
let Expression::ObjectExpression(obj_expr) = expr else {
return;
};
@ -97,9 +117,7 @@ impl<'a, 'ctx> Traverse<'a> for ObjectSpread<'a, 'ctx> {
*expr = ctx.ast.expression_call(SPAN, callee, NONE, arguments, false);
}
}
}
impl<'a, 'ctx> ObjectSpread<'a, 'ctx> {
#[expect(clippy::option_option)]
fn get_object_symbol_id(&self, ctx: &mut TraverseCtx<'a>) -> Option<Option<SymbolId>> {
if self.options.set_spread_properties {
@ -118,7 +136,7 @@ impl<'a, 'ctx> ObjectSpread<'a, 'ctx> {
if let Some(object_id) = object_id {
Self::object_assign(object_id, ctx)
} else {
self.babel_external_helper(ctx)
self.ctx.helper_load(Helper::ObjectSpread2, ctx)
}
}
@ -127,11 +145,6 @@ impl<'a, 'ctx> ObjectSpread<'a, 'ctx> {
ctx.create_reference_id(SPAN, Atom::from("Object"), symbol_id, ReferenceFlags::Read);
let object = ctx.ast.expression_from_identifier_reference(ident);
let property = ctx.ast.identifier_name(SPAN, Atom::from("assign"));
Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false))
}
fn babel_external_helper(&self, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {
self.ctx.helper_load(Helper::ObjectSpread2, ctx)
}
}

View file

@ -1,73 +0,0 @@
//! ES2018 object spread transformation.
//!
//! This plugin transforms rest properties for object destructuring assignment and spread properties for object literals.
//!
//! > This plugin is included in `preset-env`, in ES2018
//!
//! ## Example
//!
//! Input:
//! ```js
//! var x = { a: 1, b: 2 };
//! var y = { ...x, c: 3 };
//! ```
//!
//! Output:
//! ```js
//! var x = { a: 1, b: 2 };
//! var y = _objectSpread({}, x, { c: 3 });
//! ```
//!
//! ## Implementation
//!
//! Implementation based on [@babel/plugin-transform-object-rest-spread](https://babeljs.io/docs/babel-plugin-transform-object-rest-spread).
//!
//! ## References:
//! * Babel plugin implementation: <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-object-rest-spread>
//! * Object rest/spread TC39 proposal: <https://github.com/tc39/proposal-object-rest-spread>
use serde::Deserialize;
use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx};
use crate::TransformCtx;
mod object_rest;
mod object_spread;
use object_rest::ObjectRest;
use object_spread::ObjectSpread;
#[derive(Debug, Default, Clone, Copy, Deserialize)]
#[serde(default, rename_all = "camelCase")]
pub struct ObjectRestSpreadOptions {
#[serde(alias = "loose")]
pub(crate) set_spread_properties: bool,
pub(crate) use_built_ins: bool,
}
pub struct ObjectRestSpread<'a, 'ctx> {
#[allow(dead_code)]
options: ObjectRestSpreadOptions,
// Plugins
object_spread: ObjectSpread<'a, 'ctx>,
#[allow(dead_code)]
object_rest: ObjectRest,
}
impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> {
pub fn new(options: ObjectRestSpreadOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
Self {
object_spread: ObjectSpread::new(options, ctx),
object_rest: ObjectRest::new(options),
options,
}
}
}
impl<'a, 'ctx> Traverse<'a> for ObjectRestSpread<'a, 'ctx> {
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
self.object_spread.enter_expression(expr, ctx);
}
}

View file

@ -1,37 +0,0 @@
//! ES2018 object spread transformation.
//!
//! PLACEHOLDER ONLY. NOT IMPLEMENTED YET. TODO.
//!
//! > This plugin is included in `preset-env`, in ES2018
//!
//! ## Example
//!
//! Input:
//! ```js
//! var { a, ...b } = x;
//! ```
//!
//! Output:
//! ```js
//! // TBD
//! ```
//!
//! ## Implementation
//!
//! Implementation based on [@babel/plugin-transform-object-rest-spread](https://babeljs.io/docs/babel-plugin-transform-object-rest-spread).
//!
//! ## References:
//! * Babel plugin implementation: <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-object-rest-spread>
//! * Object rest/spread TC39 proposal: <https://github.com/tc39/proposal-object-rest-spread>
use super::ObjectRestSpreadOptions;
pub struct ObjectRest {
_options: ObjectRestSpreadOptions,
}
impl ObjectRest {
pub fn new(options: ObjectRestSpreadOptions) -> Self {
Self { _options: options }
}
}

View file

@ -94,11 +94,11 @@ impl TransformOptions {
arrow_function: None,
},
es2016: ES2016Options { exponentiation_operator: true },
es2018: ES2018Options { object_rest_spread: Some(ObjectRestSpreadOptions::default()) },
es2017: ES2017Options {
// Turned off because it is not ready.
async_to_generator: false,
},
es2018: ES2018Options { object_rest_spread: Some(ObjectRestSpreadOptions::default()) },
es2019: ES2019Options { optional_catch_binding: true },
es2020: ES2020Options { nullish_coalescing_operator: true },
es2021: ES2021Options { logical_assignment_operators: true },

View file

@ -34,7 +34,7 @@ use crate::TraverseCtx;
/// * `BoundIdentifier` is `Clone` (unlike `BindingIdentifier`).
/// * `BoundIdentifier` re-uses the same `Atom` for all `BindingIdentifier` / `IdentifierReference`s
/// created from it.
#[derive(Clone)]
#[derive(Debug, Clone)]
pub struct BoundIdentifier<'a> {
pub name: Atom<'a>,
pub symbol_id: SymbolId,