From 41ddf60ab02c31ce90d27bedf9cf9e448ba71280 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Sun, 29 Dec 2024 12:27:32 +0000 Subject: [PATCH] feat(minfier): add `CompressOptions::target` (#8179) --- Cargo.lock | 1 + crates/oxc_minifier/src/options.rs | 13 +++- crates/oxc_syntax/Cargo.toml | 1 + crates/oxc_syntax/src/es_target.rs | 68 ++++++++++++++++++ crates/oxc_syntax/src/lib.rs | 1 + crates/oxc_transformer/src/options/env.rs | 1 + .../oxc_transformer/src/options/es_target.rs | 69 ++----------------- crates/oxc_transformer/src/options/mod.rs | 1 + crates/oxc_wasm/src/lib.rs | 1 + 9 files changed, 90 insertions(+), 66 deletions(-) create mode 100644 crates/oxc_syntax/src/es_target.rs diff --git a/Cargo.lock b/Cargo.lock index 9461a3e989753..77b21a8d4c01d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1987,6 +1987,7 @@ version = "0.44.0" dependencies = [ "assert-unchecked", "bitflags 2.6.0", + "cow-utils", "nonmax", "oxc_allocator", "oxc_ast_macros", diff --git a/crates/oxc_minifier/src/options.rs b/crates/oxc_minifier/src/options.rs index 0cb3aa16e3724..0b5d45aa89f6e 100644 --- a/crates/oxc_minifier/src/options.rs +++ b/crates/oxc_minifier/src/options.rs @@ -1,5 +1,14 @@ +use oxc_syntax::es_target::ESTarget; + #[derive(Debug, Clone, Copy)] pub struct CompressOptions { + /// Enable features that are targeted above. + /// + /// e.g. + /// + /// * catch optional binding when >= es2019 + pub target: ESTarget, + /// Remove `debugger;` statements. /// /// Default `true` @@ -20,10 +29,10 @@ impl Default for CompressOptions { impl CompressOptions { pub fn all_true() -> Self { - Self { drop_debugger: true, drop_console: true } + Self { target: ESTarget::ESNext, drop_debugger: true, drop_console: true } } pub fn all_false() -> Self { - Self { drop_debugger: false, drop_console: false } + Self { target: ESTarget::ESNext, drop_debugger: false, drop_console: false } } } diff --git a/crates/oxc_syntax/Cargo.toml b/crates/oxc_syntax/Cargo.toml index f0fc82c6eba1d..fbd8355e0096f 100644 --- a/crates/oxc_syntax/Cargo.toml +++ b/crates/oxc_syntax/Cargo.toml @@ -28,6 +28,7 @@ oxc_span = { workspace = true } assert-unchecked = { workspace = true } bitflags = { workspace = true } +cow-utils = { workspace = true } nonmax = { workspace = true } phf = { workspace = true, features = ["macros"] } rustc-hash = { workspace = true } diff --git a/crates/oxc_syntax/src/es_target.rs b/crates/oxc_syntax/src/es_target.rs new file mode 100644 index 0000000000000..4e6f86d5e1fa6 --- /dev/null +++ b/crates/oxc_syntax/src/es_target.rs @@ -0,0 +1,68 @@ +//! ECMAScript Target +use std::{fmt, str::FromStr}; + +use cow_utils::CowUtils; + +/// ECMAScript Target +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] +#[allow(missing_docs)] +pub enum ESTarget { + ES5, + ES2015, + ES2016, + ES2017, + ES2018, + ES2019, + ES2020, + ES2021, + ES2022, + ES2023, + ES2024, + ES2025, + #[default] + ESNext, +} + +impl FromStr for ESTarget { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.cow_to_lowercase().as_ref() { + "es5" => Ok(Self::ES5), + "es6" | "es2015" => Ok(Self::ES2015), + "es2016" => Ok(Self::ES2016), + "es2017" => Ok(Self::ES2017), + "es2018" => Ok(Self::ES2018), + "es2019" => Ok(Self::ES2019), + "es2020" => Ok(Self::ES2020), + "es2021" => Ok(Self::ES2021), + "es2022" => Ok(Self::ES2022), + "es2023" => Ok(Self::ES2023), + "es2024" => Ok(Self::ES2024), + "es2025" => Ok(Self::ES2025), + "esnext" => Ok(Self::ESNext), + _ => Err(format!("Invalid target \"{s}\".")), + } + } +} + +impl fmt::Display for ESTarget { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::ES5 => "es5", + Self::ES2015 => "es2015", + Self::ES2016 => "es2016", + Self::ES2017 => "es2017", + Self::ES2018 => "es2018", + Self::ES2019 => "es2019", + Self::ES2020 => "es2020", + Self::ES2021 => "es2021", + Self::ES2022 => "es2022", + Self::ES2023 => "es2023", + Self::ES2024 => "es2024", + Self::ES2025 => "es2025", + Self::ESNext => "esnext", + }; + write!(f, "{s}",) + } +} diff --git a/crates/oxc_syntax/src/lib.rs b/crates/oxc_syntax/src/lib.rs index 94b728ff74dd8..4e564d2d7c2fb 100644 --- a/crates/oxc_syntax/src/lib.rs +++ b/crates/oxc_syntax/src/lib.rs @@ -1,6 +1,7 @@ //! Common code for JavaScript Syntax #![warn(missing_docs)] pub mod class; +pub mod es_target; pub mod identifier; pub mod keyword; pub mod module_record; diff --git a/crates/oxc_transformer/src/options/env.rs b/crates/oxc_transformer/src/options/env.rs index eee0aa4586115..893668269764f 100644 --- a/crates/oxc_transformer/src/options/env.rs +++ b/crates/oxc_transformer/src/options/env.rs @@ -119,6 +119,7 @@ impl EnvOptions { /// /// * When the query failed to parse. pub fn from_target_list>(list: &[S]) -> Result { + use crate::options::es_target::ESVersion; let mut es_target = None; let mut engine_targets = EngineTargets::default(); diff --git a/crates/oxc_transformer/src/options/es_target.rs b/crates/oxc_transformer/src/options/es_target.rs index e067ddf7f8478..2ac1982d52973 100644 --- a/crates/oxc_transformer/src/options/es_target.rs +++ b/crates/oxc_transformer/src/options/es_target.rs @@ -1,72 +1,13 @@ -use std::{fmt, str::FromStr}; - use browserslist::Version; -use cow_utils::CowUtils; - -#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] -pub enum ESTarget { - ES5, - ES2015, - ES2016, - ES2017, - ES2018, - ES2019, - ES2020, - ES2021, - ES2022, - ES2023, - ES2024, - ES2025, - #[default] - ESNext, -} - -impl FromStr for ESTarget { - type Err = String; - fn from_str(s: &str) -> Result { - match s.cow_to_lowercase().as_ref() { - "es5" => Ok(Self::ES5), - "es6" | "es2015" => Ok(Self::ES2015), - "es2016" => Ok(Self::ES2016), - "es2017" => Ok(Self::ES2017), - "es2018" => Ok(Self::ES2018), - "es2019" => Ok(Self::ES2019), - "es2020" => Ok(Self::ES2020), - "es2021" => Ok(Self::ES2021), - "es2022" => Ok(Self::ES2022), - "es2023" => Ok(Self::ES2023), - "es2024" => Ok(Self::ES2024), - "es2025" => Ok(Self::ES2025), - "esnext" => Ok(Self::ESNext), - _ => Err(format!("Invalid target \"{s}\".")), - } - } -} +pub use oxc_syntax::es_target::ESTarget; -impl fmt::Display for ESTarget { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match self { - Self::ES5 => "es5", - Self::ES2015 => "es2015", - Self::ES2016 => "es2016", - Self::ES2017 => "es2017", - Self::ES2018 => "es2018", - Self::ES2019 => "es2019", - Self::ES2020 => "es2020", - Self::ES2021 => "es2021", - Self::ES2022 => "es2022", - Self::ES2023 => "es2023", - Self::ES2024 => "es2024", - Self::ES2025 => "es2025", - Self::ESNext => "esnext", - }; - write!(f, "{s}",) - } +pub trait ESVersion { + fn version(&self) -> Version; } -impl ESTarget { - pub fn version(&self) -> Version { +impl ESVersion for ESTarget { + fn version(&self) -> Version { match self { Self::ES5 => Version(5, 0, 0), Self::ES2015 => Version(2015, 0, 0), diff --git a/crates/oxc_transformer/src/options/mod.rs b/crates/oxc_transformer/src/options/mod.rs index 82a40e53e9153..647125b057db6 100644 --- a/crates/oxc_transformer/src/options/mod.rs +++ b/crates/oxc_transformer/src/options/mod.rs @@ -121,6 +121,7 @@ impl TransformOptions { impl From for TransformOptions { fn from(target: ESTarget) -> Self { + use crate::options::es_target::ESVersion; let mut engine_targets = EngineTargets::default(); engine_targets.insert(Engine::Es, target.version()); let mut env = EnvOptions::from(engine_targets); diff --git a/crates/oxc_wasm/src/lib.rs b/crates/oxc_wasm/src/lib.rs index a43d0a7495c32..23c77bba88ebc 100644 --- a/crates/oxc_wasm/src/lib.rs +++ b/crates/oxc_wasm/src/lib.rs @@ -275,6 +275,7 @@ impl Oxc { CompressOptions { drop_console: compress_options.drop_console, drop_debugger: compress_options.drop_debugger, + ..CompressOptions::all_false() } } else { CompressOptions::all_false()