mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(transformer): support importSource option in react_jsx (#1115)
This commit is contained in:
parent
b16c298b35
commit
f0e452a599
6 changed files with 41 additions and 14 deletions
|
|
@ -79,7 +79,6 @@ impl<'a> Transformer<'a> {
|
|||
Self {
|
||||
// TODO: pass verbatim_module_syntax from user config
|
||||
typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast), ctx.clone(), false)),
|
||||
react_jsx: options.react_jsx.map(|options| ReactJsx::new(Rc::clone(&ast), &ctx, options)),
|
||||
regexp_flags: RegexpFlags::new(Rc::clone(&ast), &options),
|
||||
es2022_class_static_block: es2022::ClassStaticBlock::new(Rc::clone(&ast), &options),
|
||||
es2021_logical_assignment_operators: LogicalAssignmentOperators::new(Rc::clone(&ast), ctx.clone(), &options),
|
||||
|
|
@ -88,6 +87,7 @@ impl<'a> Transformer<'a> {
|
|||
es2016_exponentiation_operator: ExponentiationOperator::new(Rc::clone(&ast), ctx.clone(), &options),
|
||||
es2015_shorthand_properties: ShorthandProperties::new(Rc::clone(&ast), &options),
|
||||
es2015_template_literals: TemplateLiterals::new(Rc::clone(&ast), &options),
|
||||
react_jsx: options.react_jsx.map(|options| ReactJsx::new(Rc::clone(&ast), &ctx, options)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use oxc_syntax::assumptions::CompilerAssumptions;
|
|||
|
||||
use crate::{es2020::NullishCoalescingOperatorOptions, react_jsx::ReactJsxOptions};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct TransformOptions {
|
||||
pub target: TransformTarget,
|
||||
pub assumptions: CompilerAssumptions,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ pub struct ReactJsx<'a> {
|
|||
import_jsxs: bool,
|
||||
import_fragment: bool,
|
||||
import_create_element: bool,
|
||||
// Will be store jsx runtime importer, like `react/jsx-runtime`
|
||||
jsx_runtime_importer: Atom,
|
||||
}
|
||||
|
||||
enum JSXElementOrFragment<'a, 'b> {
|
||||
|
|
@ -75,10 +77,19 @@ impl<'a> ReactJsx<'a> {
|
|||
) -> Self {
|
||||
let imports = ast.new_vec();
|
||||
let options = options.with_comments(&ctx.semantic());
|
||||
|
||||
let jsx_runtime_importer =
|
||||
if options.import_source == "react" || options.runtime.is_classic() {
|
||||
Atom::new_inline("react/jsx-runtime")
|
||||
} else {
|
||||
Atom::from(format!("{}/jsx-runtime", options.import_source))
|
||||
};
|
||||
|
||||
Self {
|
||||
ast,
|
||||
options,
|
||||
imports,
|
||||
jsx_runtime_importer,
|
||||
import_jsx: false,
|
||||
import_jsxs: false,
|
||||
import_fragment: false,
|
||||
|
|
@ -111,6 +122,10 @@ impl<'a> ReactJsx<'a> {
|
|||
program.body.splice(index..index, imports);
|
||||
}
|
||||
|
||||
fn new_string_literal(name: &str) -> StringLiteral {
|
||||
StringLiteral::new(SPAN, name.into())
|
||||
}
|
||||
|
||||
fn add_import<'b>(
|
||||
&mut self,
|
||||
e: &JSXElementOrFragment<'a, 'b>,
|
||||
|
|
@ -133,21 +148,24 @@ impl<'a> ReactJsx<'a> {
|
|||
fn add_import_jsx(&mut self) {
|
||||
if !self.import_jsx {
|
||||
self.import_jsx = true;
|
||||
self.add_import_statement("jsx", "_jsx", "react/jsx-runtime");
|
||||
let source = Self::new_string_literal(self.jsx_runtime_importer.as_str());
|
||||
self.add_import_statement("jsx", "_jsx", source);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_import_jsxs(&mut self) {
|
||||
if !self.import_jsxs {
|
||||
self.import_jsxs = true;
|
||||
self.add_import_statement("jsxs", "_jsxs", "react/jsx-runtime");
|
||||
let source = Self::new_string_literal(self.jsx_runtime_importer.as_str());
|
||||
self.add_import_statement("jsxs", "_jsxs", source);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_import_fragment(&mut self) {
|
||||
if !self.import_fragment {
|
||||
self.import_fragment = true;
|
||||
self.add_import_statement("Fragment", "_Fragment", "react/jsx-runtime");
|
||||
let source = Self::new_string_literal(self.jsx_runtime_importer.as_str());
|
||||
self.add_import_statement("Fragment", "_Fragment", source);
|
||||
self.add_import_jsx();
|
||||
}
|
||||
}
|
||||
|
|
@ -155,11 +173,12 @@ impl<'a> ReactJsx<'a> {
|
|||
fn add_import_create_element(&mut self) {
|
||||
if !self.import_create_element {
|
||||
self.import_create_element = true;
|
||||
self.add_import_statement("createElement", "_createElement", "react");
|
||||
let source = Self::new_string_literal(self.options.import_source.as_ref());
|
||||
self.add_import_statement("createElement", "_createElement", source);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_import_statement(&mut self, imported: &str, local: &str, source: &str) {
|
||||
fn add_import_statement(&mut self, imported: &str, local: &str, source: StringLiteral) {
|
||||
let mut specifiers = self.ast.new_vec_with_capacity(1);
|
||||
specifiers.push(ImportDeclarationSpecifier::ImportSpecifier(ImportSpecifier {
|
||||
span: SPAN,
|
||||
|
|
@ -167,7 +186,6 @@ impl<'a> ReactJsx<'a> {
|
|||
local: BindingIdentifier::new(SPAN, local.into()),
|
||||
import_kind: ImportOrExportKind::Value,
|
||||
}));
|
||||
let source = StringLiteral::new(SPAN, source.into());
|
||||
let import_statement = self.ast.import_declaration(
|
||||
SPAN,
|
||||
Some(specifiers),
|
||||
|
|
|
|||
|
|
@ -1,14 +1,23 @@
|
|||
use serde::Deserialize;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use oxc_semantic::Semantic;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize)]
|
||||
#[derive(Debug, Default, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ReactJsxOptions {
|
||||
/// Decides which runtime to use.
|
||||
pub runtime: ReactJsxRuntime,
|
||||
/// 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.
|
||||
pub throw_if_namespace: Option<bool>,
|
||||
/// Replaces the import source when importing functions. default to `react`
|
||||
#[serde(default = "default_import_source")]
|
||||
pub import_source: Cow<'static, str>,
|
||||
}
|
||||
|
||||
fn default_import_source() -> Cow<'static, str> {
|
||||
Cow::Borrowed("react")
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize)]
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ impl Tester {
|
|||
let program = Parser::new(&self.allocator, source_text, self.source_type).parse().program;
|
||||
let semantic = SemanticBuilder::new(source_text, self.source_type).build(&program).semantic;
|
||||
let program = self.allocator.alloc(program);
|
||||
Transformer::new(&self.allocator, self.source_type, semantic, self.options).build(program);
|
||||
Transformer::new(&self.allocator, self.source_type, semantic, self.options.clone())
|
||||
.build(program);
|
||||
Codegen::<false>::new(source_text.len(), CodegenOptions).build(program)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Passed: 255/1113
|
||||
Passed: 256/1113
|
||||
|
||||
# All Passed:
|
||||
* babel-plugin-transform-numeric-separator
|
||||
|
|
@ -825,14 +825,13 @@ Passed: 255/1113
|
|||
* regression/11061/input.mjs
|
||||
* variable-declaration/non-null-in-optional-chain/input.ts
|
||||
|
||||
# babel-plugin-transform-react-jsx (93/170)
|
||||
# babel-plugin-transform-react-jsx (94/170)
|
||||
* autoImport/after-polyfills-compiled-to-cjs/input.mjs
|
||||
* autoImport/after-polyfills-script-not-supported/input.js
|
||||
* autoImport/auto-import-react-source-type-module/input.js
|
||||
* autoImport/auto-import-react-source-type-script/input.js
|
||||
* autoImport/complicated-scope-module/input.js
|
||||
* autoImport/complicated-scope-script/input.js
|
||||
* autoImport/import-source/input.js
|
||||
* autoImport/import-source-pragma/input.js
|
||||
* pure/false-default-pragma-automatic-runtime/input.js
|
||||
* pure/false-pragma-comment-automatic-runtime/input.js
|
||||
|
|
|
|||
Loading…
Reference in a new issue