diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread/object_spread.rs b/crates/oxc_transformer/src/es2018/object_rest_spread.rs similarity index 82% rename from crates/oxc_transformer/src/es2018/object_rest_spread/object_spread.rs rename to crates/oxc_transformer/src/es2018/object_rest_spread.rs index c9d9a20f117d7..ba174c8450556 100644 --- a/crates/oxc_transformer/src/es2018/object_rest_spread/object_spread.rs +++ b/crates/oxc_transformer/src/es2018/object_rest_spread.rs @@ -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: //! * Object rest/spread TC39 proposal: +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, + pub(crate) use_built_ins: bool, +} + +pub struct ObjectRestSpread<'a, 'ctx> { ctx: &'ctx TransformCtx<'a>, + options: ObjectRestSpreadOptions, } -impl<'a, 'ctx> ObjectSpread<'a, 'ctx> { +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> { 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) - } } diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread/mod.rs b/crates/oxc_transformer/src/es2018/object_rest_spread/mod.rs deleted file mode 100644 index ed7741daefb33..0000000000000 --- a/crates/oxc_transformer/src/es2018/object_rest_spread/mod.rs +++ /dev/null @@ -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: -//! * Object rest/spread TC39 proposal: - -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); - } -} diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread/object_rest.rs b/crates/oxc_transformer/src/es2018/object_rest_spread/object_rest.rs deleted file mode 100644 index 19a8455ff2ccf..0000000000000 --- a/crates/oxc_transformer/src/es2018/object_rest_spread/object_rest.rs +++ /dev/null @@ -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: -//! * Object rest/spread TC39 proposal: - -use super::ObjectRestSpreadOptions; - -pub struct ObjectRest { - _options: ObjectRestSpreadOptions, -} - -impl ObjectRest { - pub fn new(options: ObjectRestSpreadOptions) -> Self { - Self { _options: options } - } -} diff --git a/crates/oxc_transformer/src/options/transformer.rs b/crates/oxc_transformer/src/options/transformer.rs index 01d7cb02a097a..24972e25a52b8 100644 --- a/crates/oxc_transformer/src/options/transformer.rs +++ b/crates/oxc_transformer/src/options/transformer.rs @@ -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 }, diff --git a/crates/oxc_traverse/src/context/bound_identifier.rs b/crates/oxc_traverse/src/context/bound_identifier.rs index 2863a2acb088f..2e4a071d768c8 100644 --- a/crates/oxc_traverse/src/context/bound_identifier.rs +++ b/crates/oxc_traverse/src/context/bound_identifier.rs @@ -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,