From 56493bd02b49a48a115f57176b426b835be5cda0 Mon Sep 17 00:00:00 2001 From: Ali Rezvani <3788964+rzvxa@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:57:32 +0330 Subject: [PATCH] feat(transformer): add transform literal for numeric literals. (#2797) [es2015 transform literals](https://babeljs.io/docs/babel-plugin-transform-literals) --------- Co-authored-by: Dunqing --- crates/oxc_transformer/src/es2015/literals.rs | 45 +++++++++++++++++++ crates/oxc_transformer/src/es2015/mod.rs | 2 + crates/oxc_transformer/src/lib.rs | 9 +++- crates/oxc_transformer/src/options.rs | 1 + tasks/transform_conformance/src/test_case.rs | 1 + 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 crates/oxc_transformer/src/es2015/literals.rs diff --git a/crates/oxc_transformer/src/es2015/literals.rs b/crates/oxc_transformer/src/es2015/literals.rs new file mode 100644 index 0000000000000..56d160f4253d9 --- /dev/null +++ b/crates/oxc_transformer/src/es2015/literals.rs @@ -0,0 +1,45 @@ +use std::rc::Rc; + +use oxc_ast::{ast::*, AstBuilder}; + +use crate::{ + context::TransformerCtx, + options::{TransformOptions, TransformTarget}, +}; + +/// ES2015: Shorthand Properties +/// +/// References: +/// * +/// * +pub struct Literals<'a> { + _ast: Rc>, +} + +impl<'a> Literals<'a> { + #![allow(clippy::unused_self)] + + pub fn new(ctx: TransformerCtx<'a>, options: &TransformOptions) -> Option { + (options.target < TransformTarget::ES2015 || options.literals) + .then_some(Self { _ast: ctx.ast }) + } + + pub fn transform_number_literal(&mut self, lit: &mut NumericLiteral<'a>) { + // early return if number's raw value is empty or shorter than 2 characters, + // both `0bxxx` and `0oxxx` need at least 3 characters be defined. + if lit.raw.len() <= 2 { + return; + } + + if let [b'0', b'b' | b'B' | b'o' | b'O'] = lit.raw[0..2].as_bytes() { + // Set binary and octal raw values to empty, It would force the codegen, + // to generate them from their value. + lit.raw = ""; + } + } + + pub fn transform_string_literal(&mut self, _: &mut StringLiteral<'a>) { + // TODO: As of today oxc_lexer takes care of this, We have to rework it + // so it can be controlled via the transformer. + } +} diff --git a/crates/oxc_transformer/src/es2015/mod.rs b/crates/oxc_transformer/src/es2015/mod.rs index ce30b75b279be..94618af441cb5 100644 --- a/crates/oxc_transformer/src/es2015/mod.rs +++ b/crates/oxc_transformer/src/es2015/mod.rs @@ -2,6 +2,7 @@ mod arrow_functions; mod duplicate_keys; mod function_name; mod instanceof; +mod literals; mod new_target; mod shorthand_properties; mod template_literals; @@ -10,6 +11,7 @@ pub use arrow_functions::{ArrowFunctions, ArrowFunctionsOptions}; pub use duplicate_keys::DuplicateKeys; pub use function_name::FunctionName; pub use instanceof::Instanceof; +pub use literals::Literals; pub use new_target::NewTarget; pub use shorthand_properties::ShorthandProperties; pub use template_literals::TemplateLiterals; diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 0d614844d5219..f601c75247b20 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -92,6 +92,7 @@ pub struct Transformer<'a> { es2015_template_literals: Option>, es2015_duplicate_keys: Option>, es2015_instanceof: Option>, + es2015_literals: Option>, es2015_new_target: Option>, es3_property_literal: Option>, } @@ -133,6 +134,7 @@ impl<'a> Transformer<'a> { es2015_template_literals: TemplateLiterals::new(Rc::clone(&ast), &options), es2015_duplicate_keys: DuplicateKeys::new(Rc::clone(&ast), &options), es2015_instanceof: Instanceof::new(Rc::clone(&ast), ctx.clone(), &options), + es2015_literals: Literals::new(ctx.clone(), &options), es2015_new_target: NewTarget::new(Rc::clone(&ast),ctx.clone(), &options), // other es3_property_literal: PropertyLiteral::new(Rc::clone(&ast), &options), @@ -252,10 +254,15 @@ impl<'a> VisitMut<'a> for Transformer<'a> { // walk_directive_mut(self, directive); } - fn visit_string_literal(&mut self, lit: &mut StringLiteral) { + fn visit_number_literal(&mut self, lit: &mut NumericLiteral<'a>) { + self.es2015_literals.as_mut().map(|t| t.transform_number_literal(lit)); + } + + fn visit_string_literal(&mut self, lit: &mut StringLiteral<'a>) { self.es2019_json_strings .as_mut() .map(|t: &mut JsonStrings| t.transform_string_literal(lit)); + self.es2015_literals.as_mut().map(|t| t.transform_string_literal(lit)); } fn visit_method_definition(&mut self, def: &mut MethodDefinition<'a>) { diff --git a/crates/oxc_transformer/src/options.rs b/crates/oxc_transformer/src/options.rs index e658cefe3a74f..4127cb553bd39 100644 --- a/crates/oxc_transformer/src/options.rs +++ b/crates/oxc_transformer/src/options.rs @@ -30,6 +30,7 @@ pub struct TransformOptions { pub function_name: bool, pub arrow_functions: Option, pub shorthand_properties: bool, + pub literals: bool, pub sticky_regex: bool, pub template_literals: bool, pub property_literals: bool, diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index 1dc1a7b6fe1e4..f67b44a998e89 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -101,6 +101,7 @@ pub trait TestCase { assumptions: options.assumptions, class_static_block: options.get_plugin("transform-class-static-block").is_some(), instanceof: options.get_plugin("transform-instanceof").is_some(), + literals: options.get_plugin("transform-literals").is_some(), function_name: options.get_plugin("transform-function-name").is_some(), arrow_functions: options .get_plugin("transform-arrow-functions")