From 7710d8caf16b0e671570cb4af44b78fdb8b8e85b Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 31 Mar 2024 10:04:21 +0800 Subject: [PATCH] feat(transformer): add compiler assumptions (#2872) closes #2869 --- crates/oxc_syntax/src/assumptions.rs | 15 --- crates/oxc_syntax/src/lib.rs | 1 - .../src/compiler_assumptions.rs | 34 +++++++ crates/oxc_transformer/src/lib.rs | 9 ++ crates/oxc_transformer/src/react_jsx/mod.rs | 11 ++- .../oxc_transformer/src/react_jsx/options.rs | 97 +++++++++++++++++++ tasks/common/src/babel.rs | 3 +- tasks/transform_conformance/src/test_case.rs | 1 + 8 files changed, 149 insertions(+), 22 deletions(-) delete mode 100644 crates/oxc_syntax/src/assumptions.rs create mode 100644 crates/oxc_transformer/src/compiler_assumptions.rs create mode 100644 crates/oxc_transformer/src/react_jsx/options.rs diff --git a/crates/oxc_syntax/src/assumptions.rs b/crates/oxc_syntax/src/assumptions.rs deleted file mode 100644 index 72e152acc..000000000 --- a/crates/oxc_syntax/src/assumptions.rs +++ /dev/null @@ -1,15 +0,0 @@ -#[cfg(feature = "serialize")] -use serde::Deserialize; - -/// Compiler assumptions -/// -/// See -#[derive(Debug, Default, Clone, Copy)] -#[cfg_attr(feature = "serialize", derive(Deserialize))] -#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))] -pub struct CompilerAssumptions { - /// When using operators that check for null or undefined, assume that they are never used with the special value document.all. - /// See . - #[cfg_attr(feature = "serialize", serde(default))] - pub no_document_all: bool, -} diff --git a/crates/oxc_syntax/src/lib.rs b/crates/oxc_syntax/src/lib.rs index c911699cd..7ff536f60 100644 --- a/crates/oxc_syntax/src/lib.rs +++ b/crates/oxc_syntax/src/lib.rs @@ -1,6 +1,5 @@ //! Common code for JavaScript Syntax -pub mod assumptions; pub mod class; pub mod identifier; pub mod keyword; diff --git a/crates/oxc_transformer/src/compiler_assumptions.rs b/crates/oxc_transformer/src/compiler_assumptions.rs new file mode 100644 index 000000000..d909092fc --- /dev/null +++ b/crates/oxc_transformer/src/compiler_assumptions.rs @@ -0,0 +1,34 @@ +use serde::Deserialize; + +/// Compiler assumptions +/// +/// For producing smaller output. +/// +/// See +#[derive(Debug, Default, Clone, Copy, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CompilerAssumptions { + pub array_like_is_iterable: bool, + pub constant_reexports: bool, + pub constant_super: bool, + pub enumerable_module_meta: bool, + pub ignore_function_length: bool, + pub ignore_to_primitive_hint: bool, + pub iterable_is_array: bool, + pub mutable_template_object: bool, + pub no_class_calls: bool, + pub no_document_all: bool, + pub no_incomplete_ns_import_detection: bool, + pub no_new_arrows: bool, + pub no_uninitialized_private_field_access: bool, + pub object_rest_no_symbols: bool, + pub private_fields_as_symbols: bool, + pub private_fields_as_properties: bool, + pub pure_getters: bool, + pub set_class_methods: bool, + pub set_computed_properties: bool, + pub set_public_class_fields: bool, + pub set_spread_properties: bool, + pub skip_for_of_iterator_closing: bool, + pub super_is_callable_constructor: bool, +} diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index e9735ae5c..0ab383732 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -5,6 +5,8 @@ //! * //! * +// Core +mod compiler_assumptions; // Plugins: mod decorators; mod react_display_name; @@ -20,6 +22,7 @@ use oxc_semantic::Semantic; use oxc_span::SourceType; pub use crate::{ + compiler_assumptions::CompilerAssumptions, decorators::{Decorators, DecoratorsOptions}, react_display_name::{ReactDisplayName, ReactDisplayNameOptions}, react_jsx::{ReactJsx, ReactJsxOptions}, @@ -31,6 +34,12 @@ pub use crate::{ #[allow(unused)] #[derive(Debug, Default, Clone)] pub struct TransformOptions { + // Core + /// Set assumptions in order to produce smaller output. + /// For more information, check the [assumptions](https://babel.dev/docs/assumptions) documentation page. + pub assumptions: CompilerAssumptions, + + // Plugins pub decorators: DecoratorsOptions, pub typescript: TypeScriptOptions, pub react_jsx: ReactJsxOptions, diff --git a/crates/oxc_transformer/src/react_jsx/mod.rs b/crates/oxc_transformer/src/react_jsx/mod.rs index 6da4ebe32..0c65599a7 100644 --- a/crates/oxc_transformer/src/react_jsx/mod.rs +++ b/crates/oxc_transformer/src/react_jsx/mod.rs @@ -1,8 +1,6 @@ -use serde::Deserialize; +mod options; -#[derive(Debug, Default, Clone, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ReactJsxOptions; +pub use self::options::ReactJsxOptions; /// [plugin-transform-react-jsx](https://babeljs.io/docs/babel-plugin-transform-react-jsx) /// @@ -12,6 +10,11 @@ pub struct ReactJsxOptions; /// please use @babel/plugin-transform-react-jsx-development for a better debugging experience. /// /// This plugin is included in `preset-react`. +/// +/// References: +/// +/// * +/// * #[derive(Debug, Default)] pub struct ReactJsx { #[allow(unused)] diff --git a/crates/oxc_transformer/src/react_jsx/options.rs b/crates/oxc_transformer/src/react_jsx/options.rs new file mode 100644 index 000000000..b7b2c700f --- /dev/null +++ b/crates/oxc_transformer/src/react_jsx/options.rs @@ -0,0 +1,97 @@ +use std::borrow::Cow; + +use serde::Deserialize; + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ReactJsxOptions { + // Both Runtimes + // + /// Decides which runtime to use. + pub runtime: ReactJsxRuntime, + + /// This toggles behavior specific to development, such as adding __source and __self. + /// + /// Defaults to `true`. + #[serde(default = "default_as_true")] + pub development: bool, + + /// Enables `@babel/plugin-transform-react-pure-annotations`. + /// + /// It will mark top-level React method calls as pure for tree shaking. + /// + /// Defaults to `true`. + #[serde(default = "default_as_true")] + pub pure: bool, + // + // React Automatic Runtime + // + /// Replaces the import source when importing functions. + /// + /// Defaults to `react`. + #[serde(default = "default_for_import_source")] + pub import_source: Cow<'static, str>, + // + // React Classic Runtime + // + /// Replace the function used when compiling JSX expressions. + /// + /// It should be a qualified name (e.g. React.createElement) or an identifier (e.g. createElement). + /// + /// Note that the @jsx React.DOM pragma has been deprecated as of React v0.12 + /// + /// Defaults to `React.createElement`. + #[serde(default = "default_for_pragma")] + pub pragma: Cow<'static, str>, + + /// Replace the component used when compiling JSX fragments. It should be a valid JSX tag name. + /// + /// Defaults to `React.Fragment`. + #[serde(default = "default_for_pragma_frag")] + pub pragma_frag: Cow<'static, str>, + // + // `useBuiltIns` and `useSpread` are deprecated in babel 8. +} + +impl Default for ReactJsxOptions { + fn default() -> Self { + Self { + runtime: ReactJsxRuntime::default(), + development: default_as_true(), + pure: default_as_true(), + import_source: default_for_import_source(), + pragma: default_for_pragma(), + pragma_frag: default_for_pragma_frag(), + } + } +} + +#[inline] +fn default_as_true() -> bool { + true +} + +#[inline] +fn default_for_import_source() -> Cow<'static, str> { + Cow::Borrowed("react") +} + +fn default_for_pragma() -> Cow<'static, str> { + Cow::Borrowed("React.createElement") +} + +fn default_for_pragma_frag() -> Cow<'static, str> { + Cow::Borrowed("React.Fragment") +} + +/// Decides which runtime to use. +/// +/// Auto imports the functions that JSX transpiles to. +/// classic does not automatic import anything. +#[derive(Debug, Default, Clone, Deserialize)] +pub enum ReactJsxRuntime { + Classic, + /// The default runtime is switched to automatic in Babel 8. + #[default] + Automatic, +} diff --git a/tasks/common/src/babel.rs b/tasks/common/src/babel.rs index 67a8c85be..65ddcab5d 100644 --- a/tasks/common/src/babel.rs +++ b/tasks/common/src/babel.rs @@ -1,6 +1,5 @@ use std::path::Path; -use oxc_syntax::assumptions::CompilerAssumptions; use serde::Deserialize; use serde_json::Value; @@ -21,7 +20,7 @@ pub struct BabelOptions { #[serde(default)] pub allow_undeclared_exports: bool, #[serde(default)] - pub assumptions: CompilerAssumptions, + pub assumptions: Value, } impl BabelOptions { diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index 89b99217b..e835c1c9d 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -87,6 +87,7 @@ pub trait TestCase { } let options = self.options(); TransformOptions { + assumptions: serde_json::from_value(options.assumptions.clone()).unwrap_or_default(), decorators: options .get_plugin("proposal-decorators") .map(get_options::)