feat(transformer): add compiler assumptions (#2872)

closes #2869
This commit is contained in:
Boshen 2024-03-31 10:04:21 +08:00 committed by GitHub
parent 7034bcc47d
commit 7710d8caf1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 149 additions and 22 deletions

View file

@ -1,15 +0,0 @@
#[cfg(feature = "serialize")]
use serde::Deserialize;
/// Compiler assumptions
///
/// See <https://babeljs.io/docs/assumptions>
#[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 <https://babeljs.io/docs/assumptions#nodocumentall>.
#[cfg_attr(feature = "serialize", serde(default))]
pub no_document_all: bool,
}

View file

@ -1,6 +1,5 @@
//! Common code for JavaScript Syntax
pub mod assumptions;
pub mod class;
pub mod identifier;
pub mod keyword;

View file

@ -0,0 +1,34 @@
use serde::Deserialize;
/// Compiler assumptions
///
/// For producing smaller output.
///
/// See <https://babeljs.io/docs/assumptions>
#[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,
}

View file

@ -5,6 +5,8 @@
//! * <https://babel.dev/docs/presets>
//! * <https://github.com/microsoft/TypeScript/blob/main/src/compiler/transformer.ts>
// Core
mod compiler_assumptions;
// Plugins: <https://babeljs.io/docs/plugins-list>
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,

View file

@ -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:
///
/// * <https://babeljs.io/docs/babel-plugin-transform-react-jsx>
/// * <https://github.com/babel/babel/tree/main/packages/babel-helper-builder-react-jsx>
#[derive(Debug, Default)]
pub struct ReactJsx {
#[allow(unused)]

View file

@ -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,
}

View file

@ -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 {

View file

@ -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::<DecoratorsOptions>)