feat(transformer/react): handle babel 8 breaking removed-options (#1489)

1. removed options react jsx
2. Passed 4 test cases.
This commit is contained in:
IWANABETHATGUY 2023-11-22 11:01:40 +08:00 committed by GitHub
parent f06f0f2078
commit b6393f052f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 16 deletions

View file

@ -94,7 +94,7 @@ impl<'a> Transformer<'a> {
es2015_shorthand_properties: ShorthandProperties::new(Rc::clone(&ast), &options), es2015_shorthand_properties: ShorthandProperties::new(Rc::clone(&ast), &options),
es2015_template_literals: TemplateLiterals::new(Rc::clone(&ast), &options), es2015_template_literals: TemplateLiterals::new(Rc::clone(&ast), &options),
es3_property_literal: PropertyLiteral::new(Rc::clone(&ast ), &options), es3_property_literal: PropertyLiteral::new(Rc::clone(&ast ), &options),
react_jsx: options.react_jsx.map(|options| ReactJsx::new(Rc::clone(&ast), ctx.clone(), options)), react_jsx: ReactJsx::new(Rc::clone(&ast), ctx.clone(), options)
} }
} }

View file

@ -24,6 +24,7 @@ pub struct TransformOptions {
pub sticky_regex: bool, pub sticky_regex: bool,
pub template_literals: bool, pub template_literals: bool,
pub property_literals: bool, pub property_literals: bool,
pub babel_8_breaking: Option<bool>,
} }
/// See <https://www.typescriptlang.org/tsconfig#target> /// See <https://www.typescriptlang.org/tsconfig#target>

View file

@ -15,7 +15,7 @@ use oxc_syntax::{
}; };
pub use self::options::{ReactJsxOptions, ReactJsxRuntime}; pub use self::options::{ReactJsxOptions, ReactJsxRuntime};
use crate::context::TransformerCtx; use crate::{context::TransformerCtx, TransformOptions};
#[derive(Debug, Error, Diagnostic)] #[derive(Debug, Error, Diagnostic)]
#[error("pragma and pragmaFrag cannot be set when runtime is automatic.")] #[error("pragma and pragmaFrag cannot be set when runtime is automatic.")]
@ -59,6 +59,7 @@ pub struct ReactJsx<'a> {
import_create_element: bool, import_create_element: bool,
require_jsx_runtime: bool, require_jsx_runtime: bool,
jsx_runtime_importer: Atom, jsx_runtime_importer: Atom,
pub babel_8_breaking: Option<bool>,
} }
enum JSXElementOrFragment<'a, 'b> { enum JSXElementOrFragment<'a, 'b> {
@ -100,21 +101,35 @@ impl<'a, 'b> JSXElementOrFragment<'a, 'b> {
} }
impl<'a> ReactJsx<'a> { impl<'a> ReactJsx<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>, ctx: TransformerCtx<'a>, options: ReactJsxOptions) -> Self { pub fn new(
ast: Rc<AstBuilder<'a>>,
mut ctx: TransformerCtx<'a>,
options: TransformOptions,
) -> Option<Self> {
let imports = ast.new_vec(); let imports = ast.new_vec();
let options = options.with_comments(&ctx.semantic()); let jsx_options = options.react_jsx?.with_comments(&ctx.semantic());
if options.babel_8_breaking == Some(true) {
if jsx_options.use_built_ins.is_some() {
ctx.error(miette::Error::msg("@babel/plugin-transform-react-jsx: Since \"useBuiltIns\" is removed in Babel 8, you can remove it from the config."));
return None;
}
if jsx_options.use_spread.is_some() {
ctx.error(miette::Error::msg("@babel/plugin-transform-react-jsx: Since Babel 8, an inline object with spread elements is always used, and the \"useSpread\" option is no longer available. Please remove it from your config."));
return None;
}
}
let jsx_runtime_importer = let jsx_runtime_importer =
if options.import_source == "react" || options.runtime.is_classic() { if jsx_options.import_source == "react" || jsx_options.runtime.is_classic() {
Atom::new_inline("react/jsx-runtime") Atom::new_inline("react/jsx-runtime")
} else { } else {
Atom::from(format!("{}/jsx-runtime", options.import_source)) Atom::from(format!("{}/jsx-runtime", jsx_options.import_source))
}; };
Some(Self {
Self {
ast, ast,
ctx, ctx,
options, options: jsx_options,
imports, imports,
jsx_runtime_importer, jsx_runtime_importer,
require_jsx_runtime: false, require_jsx_runtime: false,
@ -122,7 +137,8 @@ impl<'a> ReactJsx<'a> {
import_jsxs: false, import_jsxs: false,
import_fragment: false, import_fragment: false,
import_create_element: false, import_create_element: false,
} babel_8_breaking: options.babel_8_breaking,
})
} }
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) { pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {

View file

@ -7,6 +7,7 @@ use serde::Deserialize;
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ReactJsxOptions { pub struct ReactJsxOptions {
/// Decides which runtime to use. /// Decides which runtime to use.
#[serde(default)]
pub runtime: ReactJsxRuntime, pub runtime: ReactJsxRuntime,
/// Toggles whether or not to throw an error if an XML namespaced tag name is used. e.g. `<f:image />` /// Toggles whether or not to throw an error if an XML namespaced tag name is used. e.g. `<f:image />`
/// Though the JSX spec allows this, it is disabled by default since React's JSX does not currently have support for it. /// Though the JSX spec allows this, it is disabled by default since React's JSX does not currently have support for it.
@ -25,6 +26,15 @@ pub struct ReactJsxOptions {
/// Replace the component used when compiling JSX fragments. It should be a valid JSX tag name. default to `React.Fragment` /// Replace the component used when compiling JSX fragments. It should be a valid JSX tag name. default to `React.Fragment`
#[serde(default = "default_pragma_frag")] #[serde(default = "default_pragma_frag")]
pub pragma_frag: Cow<'static, str>, pub pragma_frag: Cow<'static, str>,
/// When spreading props, use Object.assign directly instead of Babel's extend helper.
/// Use `Some<T>` instead of `bool` because we want to know if user set this field explicitly,
/// which used for creating warning, https://github.com/oxc-project/oxc/blob/c3e2098c04d8916cb812bdd16d2026bb430ac25f/crates/oxc_transformer/src/react_jsx/mod.rs#L111-L114
pub use_built_ins: Option<bool>,
/// When spreading props, use inline object with spread elements directly instead of Babel's extend helper or Object.assign.
/// Use `Some<T>` instead of `bool` because we want to know if user set this field explicitly,
/// which used for creating warning, https://github.com/oxc-project/oxc/blob/c3e2098c04d8916cb812bdd16d2026bb430ac25f/crates/oxc_transformer/src/react_jsx/mod.rs#L111-L114
pub use_spread: Option<bool>,
} }
fn default_throw_if_namespace() -> bool { fn default_throw_if_namespace() -> bool {
@ -51,6 +61,8 @@ impl Default for ReactJsxOptions {
import_source: default_import_source(), import_source: default_import_source(),
pragma: default_pragma(), pragma: default_pragma(),
pragma_frag: default_pragma_frag(), pragma_frag: default_pragma_frag(),
use_built_ins: None,
use_spread: None,
} }
} }
} }

View file

@ -1,4 +1,4 @@
Passed: 265/1081 Passed: 269/1081
# All Passed: # All Passed:
* babel-plugin-transform-numeric-separator * babel-plugin-transform-numeric-separator
@ -844,7 +844,7 @@ Passed: 265/1081
* regression/11061/input.mjs * regression/11061/input.mjs
* variable-declaration/non-null-in-optional-chain/input.ts * variable-declaration/non-null-in-optional-chain/input.ts
# babel-plugin-transform-react-jsx (139/156) # babel-plugin-transform-react-jsx (143/156)
* autoImport/after-polyfills-compiled-to-cjs/input.mjs * autoImport/after-polyfills-compiled-to-cjs/input.mjs
* autoImport/complicated-scope-module/input.js * autoImport/complicated-scope-module/input.js
* react/arrow-functions/input.js * react/arrow-functions/input.js
@ -855,10 +855,6 @@ Passed: 265/1081
* react-automatic/should-throw-when-filter-is-specified/input.js * react-automatic/should-throw-when-filter-is-specified/input.js
* regression/issue-12478-automatic/input.js * regression/issue-12478-automatic/input.js
* regression/issue-12478-classic/input.js * regression/issue-12478-classic/input.js
* removed-options/invalid-use-builtins-false/input.js
* removed-options/invalid-use-builtins-true/input.js
* removed-options/invalid-use-spread-false/input.js
* removed-options/invalid-use-spread-true/input.js
* runtime/invalid-runtime/input.js * runtime/invalid-runtime/input.js
* spread-transform/transform-to-babel-extend/input.js * spread-transform/transform-to-babel-extend/input.js
* spread-transform/transform-to-object-assign/input.js * spread-transform/transform-to-object-assign/input.js

View file

@ -88,6 +88,7 @@ pub trait TestCase {
let options = self.options(); let options = self.options();
TransformOptions { TransformOptions {
target: TransformTarget::ESNext, target: TransformTarget::ESNext,
babel_8_breaking: options.babel_8_breaking,
react_jsx: options react_jsx: options
.get_plugin("transform-react-jsx") .get_plugin("transform-react-jsx")
.map(get_options::<ReactJsxOptions>), .map(get_options::<ReactJsxOptions>),