From 05a2815e6ceb6d12e122be4e4ef84281d398f8c2 Mon Sep 17 00:00:00 2001 From: Fy <1114550440@qq.com> Date: Mon, 27 Mar 2023 14:39:37 +0800 Subject: [PATCH] feat(es/react): Support script within automatic runtime (#7126) **Description:** Inject `const { jsx: _jsx} = require("react/jsx-runtime")` when sourceType is `script` **Related issue:** - Closes https://github.com/swc-project/swc/issues/7119. --- crates/swc/src/config/mod.rs | 8 +- crates/swc_bundler/tests/common/mod.rs | 1 + .../swc_ecma_transforms_react/src/jsx/mod.rs | 244 +++++++++++------- .../src/jsx/tests.rs | 99 ++++++- crates/swc_ecma_transforms_react/src/lib.rs | 9 +- .../src/pure_annotations/tests.rs | 1 + .../integration/jsx-dev-transform/input.js | 8 + .../jsx-dev-transform/options.json | 1 + .../integration/jsx-dev-transform/output.js | 23 ++ .../script/integration/jsx-transform/input.js | 8 + .../integration/jsx-transform/options.json | 1 + .../integration/jsx-transform/output.js | 11 + .../jsxdev-args-with-fragment/input.js | 6 + .../jsxdev-args-with-fragment/options.json | 1 + .../jsxdev-args-with-fragment/output.js | 19 ++ .../integration/jsxdev-fragment/input.js | 6 + .../integration/jsxdev-fragment/options.json | 1 + .../integration/jsxdev-fragment/output.js | 19 ++ .../script/integration/with-pragma/input.js | 9 + .../integration/with-pragma/options.json | 1 + .../script/integration/with-pragma/output.js | 23 ++ .../after-polyfills-script/input.js | 7 + .../after-polyfills-script/options.json | 1 + .../after-polyfills-script/output.js | 8 + .../input.js | 10 + .../options.json | 1 + .../output.js | 17 ++ .../complicated-scope-script/input.js | 15 ++ .../complicated-scope-script/options.json | 1 + .../complicated-scope-script/output.js | 16 ++ .../jsx/fixture/autoImport/options.json | 1 + 31 files changed, 476 insertions(+), 100 deletions(-) create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/input.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/options.json create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/output.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/input.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/options.json create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/output.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/input.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/options.json create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/output.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/input.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/options.json create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/output.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/input.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/options.json create mode 100644 crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/output.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/input.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/options.json create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/output.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/input.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/options.json create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/output.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/input.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/options.json create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/output.js create mode 100644 crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/options.json diff --git a/crates/swc/src/config/mod.rs b/crates/swc/src/config/mod.rs index ecc4106d6159..6dcc839795fa 100644 --- a/crates/swc/src/config/mod.rs +++ b/crates/swc/src/config/mod.rs @@ -749,7 +749,13 @@ impl Options { custom_before_pass(&program), // handle jsx Optional::new( - react::react(cm.clone(), comments, transform.react, top_level_mark), + react::react( + cm.clone(), + comments, + transform.react, + top_level_mark, + unresolved_mark + ), syntax.jsx() ), pass, diff --git a/crates/swc_bundler/tests/common/mod.rs b/crates/swc_bundler/tests/common/mod.rs index 55df4ff2fffa..2bad2443867f 100644 --- a/crates/swc_bundler/tests/common/mod.rs +++ b/crates/swc_bundler/tests/common/mod.rs @@ -146,6 +146,7 @@ impl Load for Loader { None, Default::default(), top_level_mark, + unresolved_mark, )) .fold_with(&mut inject_helpers(unresolved_mark)) }); diff --git a/crates/swc_ecma_transforms_react/src/jsx/mod.rs b/crates/swc_ecma_transforms_react/src/jsx/mod.rs index d227d2060841..ef77a525496a 100644 --- a/crates/swc_ecma_transforms_react/src/jsx/mod.rs +++ b/crates/swc_ecma_transforms_react/src/jsx/mod.rs @@ -18,7 +18,9 @@ use swc_common::{ use swc_config::merge::Merge; use swc_ecma_ast::*; use swc_ecma_parser::{parse_file_as_expr, Syntax}; -use swc_ecma_utils::{drop_span, prepend_stmt, private_ident, quote_ident, undefined, ExprFactory}; +use swc_ecma_utils::{ + drop_span, prepend_stmt, private_ident, quote_ident, undefined, ExprFactory, StmtLike, +}; use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith}; use self::static_check::should_use_create_element; @@ -187,6 +189,7 @@ pub fn jsx( comments: Option, options: Options, top_level_mark: Mark, + unresolved_mark: Mark, ) -> impl Fold + VisitMut where C: Comments, @@ -194,6 +197,7 @@ where as_folder(Jsx { cm: cm.clone(), top_level_mark, + unresolved_mark, runtime: options.runtime.unwrap_or_default(), import_source: options .import_source @@ -232,6 +236,7 @@ where cm: Lrc, top_level_mark: Mark, + unresolved_mark: Mark, runtime: Runtime, /// For automatic runtime. @@ -376,6 +381,62 @@ impl Jsx where C: Comments, { + fn inject_runtime(&mut self, body: &mut Vec, inject: F) + where + T: StmtLike, + // Fn(Vec<(local, imported)>, src, body) + F: Fn(Vec<(Ident, Ident)>, &str, &mut Vec), + { + if self.runtime == Runtime::Automatic { + if let Some(local) = self.import_create_element.take() { + inject( + vec![(local, quote_ident!("createElement"))], + &self.import_source, + body, + ); + } + + let imports = self.import_jsx.take(); + let imports = if self.development { + imports + .map(|local| (local, quote_ident!("jsxDEV"))) + .into_iter() + .chain( + self.import_fragment + .take() + .map(|local| (local, quote_ident!("Fragment"))), + ) + .collect::>() + } else { + imports + .map(|local| (local, quote_ident!("jsx"))) + .into_iter() + .chain( + self.import_jsxs + .take() + .map(|local| (local, quote_ident!("jsxs"))), + ) + .chain( + self.import_fragment + .take() + .map(|local| (local, quote_ident!("Fragment"))), + ) + .collect::>() + }; + + if !imports.is_empty() { + let jsx_runtime = if self.development { + "jsx-dev-runtime" + } else { + "jsx-runtime" + }; + + let value = format!("{}/{}", self.import_source, jsx_runtime); + inject(imports, &value, body) + } + } + } + fn jsx_frag_to_expr(&mut self, el: JSXFragment) -> Expr { let span = el.span(); @@ -477,7 +538,7 @@ where /// # Automatic /// - /// + ///
=> jsx('div', null); /// /// # Classic /// @@ -975,113 +1036,116 @@ where module.visit_mut_children_with(self); if self.runtime == Runtime::Automatic { - if let Some(local) = self.import_create_element.take() { - let specifier = ImportSpecifier::Named(ImportNamedSpecifier { - span: DUMMY_SP, - local, - imported: Some(ModuleExportName::Ident(Ident::new( - "createElement".into(), - DUMMY_SP, - ))), - is_type_only: false, - }); - prepend_stmt( - &mut module.body, - ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { - span: DUMMY_SP, - specifiers: vec![specifier], - src: Str { - span: DUMMY_SP, - raw: None, - value: self.import_source.clone(), - } - .into(), - type_only: Default::default(), - asserts: Default::default(), - })), - ); - } - - let imports = self.import_jsx.take(); - let imports = if self.development { - imports - .map(|local| ImportNamedSpecifier { - span: DUMMY_SP, - local, - imported: Some(ModuleExportName::Ident(quote_ident!("jsxDEV"))), - is_type_only: false, - }) + self.inject_runtime(&mut module.body, |imports, src, stmts| { + let specifiers = imports .into_iter() - .chain( - self.import_fragment - .take() - .map(|local| ImportNamedSpecifier { - span: DUMMY_SP, - local, - imported: Some(ModuleExportName::Ident(quote_ident!("Fragment"))), - is_type_only: false, - }), - ) - .map(ImportSpecifier::Named) - .collect::>() - } else { - imports - .map(|local| ImportNamedSpecifier { - span: DUMMY_SP, - local, - imported: Some(ModuleExportName::Ident(quote_ident!("jsx"))), - is_type_only: false, + .map(|(local, imported)| { + ImportSpecifier::Named(ImportNamedSpecifier { + span: DUMMY_SP, + local, + imported: Some(ModuleExportName::Ident(imported)), + is_type_only: false, + }) }) - .into_iter() - .chain(self.import_jsxs.take().map(|local| ImportNamedSpecifier { - span: DUMMY_SP, - local, - imported: Some(ModuleExportName::Ident(quote_ident!("jsxs"))), - is_type_only: false, - })) - .chain( - self.import_fragment - .take() - .map(|local| ImportNamedSpecifier { - span: DUMMY_SP, - local, - imported: Some(ModuleExportName::Ident(quote_ident!("Fragment"))), - is_type_only: false, - }), - ) - .map(ImportSpecifier::Named) - .collect::>() - }; - - if !imports.is_empty() { - let jsx_runtime = if self.development { - "jsx-dev-runtime" - } else { - "jsx-runtime" - }; - - let value = format!("{}/{}", self.import_source, jsx_runtime); + .collect(); prepend_stmt( - &mut module.body, + stmts, ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { span: DUMMY_SP, - specifiers: imports, + specifiers, src: Str { span: DUMMY_SP, raw: None, - value: value.into(), + value: src.into(), } .into(), type_only: Default::default(), asserts: Default::default(), })), - ); + ) + }); + } + } + + fn visit_mut_script(&mut self, script: &mut Script) { + self.parse_directives(script.span); + + for item in &script.body { + let span = item.span(); + if self.parse_directives(span) { + break; } } + + script.visit_mut_children_with(self); + + if self.runtime == Runtime::Automatic { + let mark = self.unresolved_mark; + self.inject_runtime(&mut script.body, |imports, src, stmts| { + prepend_stmt(stmts, add_require(imports, src, mark)) + }); + } } } +// const { createElement } = require('react') +// const { jsx: jsx } = require('react/jsx-runtime') +fn add_require(imports: Vec<(Ident, Ident)>, src: &str, unresolved_mark: Mark) -> Stmt { + Stmt::Decl(Decl::Var(Box::new(VarDecl { + span: DUMMY_SP, + kind: VarDeclKind::Const, + declare: false, + decls: vec![VarDeclarator { + span: DUMMY_SP, + name: Pat::Object(ObjectPat { + span: DUMMY_SP, + props: imports + .into_iter() + .map(|(local, imported)| { + if imported.sym != local.sym { + ObjectPatProp::KeyValue(KeyValuePatProp { + key: PropName::Ident(imported), + value: Box::new(Pat::Ident(BindingIdent { + id: local, + type_ann: None, + })), + }) + } else { + ObjectPatProp::Assign(AssignPatProp { + span: DUMMY_SP, + key: local, + value: None, + }) + } + }) + .collect(), + optional: false, + type_ann: None, + }), + // require('react') + init: Some(Box::new(Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Ident(Ident { + span: DUMMY_SP.apply_mark(unresolved_mark), + sym: js_word!("require"), + optional: false, + }))), + args: vec![ExprOrSpread { + spread: None, + expr: Box::new(Expr::Lit(Lit::Str(Str { + span: DUMMY_SP, + value: src.into(), + raw: None, + }))), + }], + type_args: None, + }))), + definite: false, + }], + }))) +} + impl Jsx where C: Comments, diff --git a/crates/swc_ecma_transforms_react/src/jsx/tests.rs b/crates/swc_ecma_transforms_react/src/jsx/tests.rs index a0d12a73a74a..56cf2899a411 100644 --- a/crates/swc_ecma_transforms_react/src/jsx/tests.rs +++ b/crates/swc_ecma_transforms_react/src/jsx/tests.rs @@ -1,16 +1,22 @@ #![allow(dead_code)] -use std::path::PathBuf; +use std::{ + fs, + path::{Path, PathBuf}, +}; use swc_common::{chain, Mark}; -use swc_ecma_parser::EsConfig; -use swc_ecma_transforms_base::resolver; +use swc_ecma_codegen::{Config, Emitter}; +use swc_ecma_parser::{EsConfig, Parser, StringInput}; +use swc_ecma_transforms_base::{fixer::fixer, hygiene, resolver}; use swc_ecma_transforms_compat::{ es2015::{arrow, classes}, es3::property_literals, }; use swc_ecma_transforms_module::common_js::common_js; use swc_ecma_transforms_testing::{parse_options, test, test_fixture, FixtureTestConfig, Tester}; +use swc_ecma_visit::FoldWith; +use testing::NormalizedOutput; use super::*; use crate::{display_name, pure_annotations, react}; @@ -24,7 +30,8 @@ fn tr(t: &mut Tester, options: Options, top_level_mark: Mark) -> impl Fold { t.cm.clone(), Some(t.comments.clone()), options, - top_level_mark + top_level_mark, + unresolved_mark ), display_name(), classes(Some(t.comments.clone()), Default::default()), @@ -71,7 +78,8 @@ fn fixture_tr(t: &mut Tester, mut options: FixtureOptions) -> impl Fold { t.cm.clone(), Some(t.comments.clone()), options.options, - top_level_mark + top_level_mark, + unresolved_mark, ), display_name(), pure_annotations(Some(t.comments.clone())) @@ -94,7 +102,8 @@ fn integration_tr(t: &mut Tester, mut options: FixtureOptions) -> impl Fold { t.cm.clone(), Some(t.comments.clone()), options.options, - top_level_mark + top_level_mark, + unresolved_mark ), display_name(), ) @@ -1338,6 +1347,7 @@ test!( }), |t| { let top_level_mark = Mark::fresh(Mark::root()); + let unresolved_mark = Mark::fresh(Mark::root()); chain!( classes(Some(t.comments.clone()), Default::default()), @@ -1345,7 +1355,8 @@ test!( t.cm.clone(), Some(t.comments.clone()), Default::default(), - top_level_mark + top_level_mark, + unresolved_mark ) ) }, @@ -1419,7 +1430,8 @@ test!( t.cm.clone(), Some(t.comments.clone()), Default::default(), - top_level_mark + top_level_mark, + unresolved_mark ) ) }, @@ -1483,3 +1495,74 @@ fn integration(input: PathBuf) { }, ); } + +#[testing::fixture("tests/script/**/input.js")] +fn script(input: PathBuf) { + let output = input.with_file_name("output.js"); + + let options = parse_options(input.parent().unwrap()); + + let input = fs::read_to_string(&input).unwrap(); + + test_script(&input, &output, options); +} + +fn test_script(src: &str, output: &Path, options: Options) { + Tester::run(|tester| { + let fm = tester + .cm + .new_source_file(FileName::Real("input.js".into()), src.into()); + + let syntax = Syntax::Es(EsConfig { + jsx: true, + ..Default::default() + }); + + let mut parser = Parser::new(syntax, StringInput::from(&*fm), Some(&tester.comments)); + + let script = parser.parse_script().unwrap(); + + let top_level_mark = Mark::new(); + let unresolved_mark = Mark::new(); + + let script = script.fold_with(&mut chain!( + resolver(Mark::new(), top_level_mark, false), + react( + tester.cm.clone(), + Some(&tester.comments), + options, + top_level_mark, + unresolved_mark, + ), + hygiene::hygiene(), + fixer(Some(&tester.comments)) + )); + + let mut buf = vec![]; + + let mut emitter = Emitter { + cfg: Config { + target: Default::default(), + ascii_only: true, + minify: false, + omit_last_semi: true, + }, + cm: tester.cm.clone(), + wr: Box::new(swc_ecma_codegen::text_writer::JsWriter::new( + tester.cm.clone(), + "\n", + &mut buf, + None, + )), + comments: Some(&tester.comments), + }; + + // println!("Emitting: {:?}", module); + emitter.emit_script(&script).unwrap(); + + let s = String::from_utf8_lossy(&buf).to_string(); + assert!(NormalizedOutput::new_raw(s).compare_to_file(output).is_ok()); + + Ok(()) + }) +} diff --git a/crates/swc_ecma_transforms_react/src/lib.rs b/crates/swc_ecma_transforms_react/src/lib.rs index 6d4b7afddcb9..44950ad1383b 100644 --- a/crates/swc_ecma_transforms_react/src/lib.rs +++ b/crates/swc_ecma_transforms_react/src/lib.rs @@ -37,6 +37,7 @@ pub fn react( comments: Option, mut options: Options, top_level_mark: Mark, + unresolved_mark: Mark, ) -> impl Fold + VisitMut where C: Comments + Clone, @@ -56,7 +57,13 @@ where comments.clone(), top_level_mark ), - jsx(cm, comments.clone(), options, top_level_mark), + jsx( + cm, + comments.clone(), + options, + top_level_mark, + unresolved_mark + ), display_name(), pure_annotations(comments), ) diff --git a/crates/swc_ecma_transforms_react/src/pure_annotations/tests.rs b/crates/swc_ecma_transforms_react/src/pure_annotations/tests.rs index 5030af3285db..267a2ae844e7 100644 --- a/crates/swc_ecma_transforms_react/src/pure_annotations/tests.rs +++ b/crates/swc_ecma_transforms_react/src/pure_annotations/tests.rs @@ -74,6 +74,7 @@ fn run_test(input: &str, expected: &str) { Some(&actual_comments), Default::default(), top_level_mark, + unresolved_mark, )); let actual_src = emit(actual_sm, actual_comments, &actual); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/input.js b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/input.js new file mode 100644 index 000000000000..5374eb97cbcb --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/input.js @@ -0,0 +1,8 @@ +const App = ( +
+
+ <> +
hoge
+ +
+); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/options.json b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/options.json new file mode 100644 index 000000000000..e7394a9a83f4 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/options.json @@ -0,0 +1 @@ +{ "runtime": "automatic", "development": true } diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/output.js b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/output.js new file mode 100644 index 000000000000..7283c010ea9c --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-dev-transform/output.js @@ -0,0 +1,23 @@ +const { jsxDEV: _jsxDEV , Fragment: _Fragment } = require("react/jsx-dev-runtime"); +const App = /*#__PURE__*/ _jsxDEV("div", { + children: [ + /*#__PURE__*/ _jsxDEV("div", {}, void 0, false, { + fileName: "input.js", + lineNumber: 3, + columnNumber: 9 + }, this), + /*#__PURE__*/ _jsxDEV(_Fragment, { + children: /*#__PURE__*/ _jsxDEV("div", { + children: "hoge" + }, 1, false, { + fileName: "input.js", + lineNumber: 5, + columnNumber: 13 + }, this) + }, void 0, false) + ] +}, void 0, true, { + fileName: "input.js", + lineNumber: 2, + columnNumber: 5 +}, this); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/input.js b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/input.js new file mode 100644 index 000000000000..5374eb97cbcb --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/input.js @@ -0,0 +1,8 @@ +const App = ( +
+
+ <> +
hoge
+ +
+); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/options.json b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/options.json new file mode 100644 index 000000000000..8c29c48c6f58 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/options.json @@ -0,0 +1 @@ +{ "runtime": "automatic" } diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/output.js b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/output.js new file mode 100644 index 000000000000..215cdb6d95f9 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsx-transform/output.js @@ -0,0 +1,11 @@ +const { jsx: _jsx , jsxs: _jsxs , Fragment: _Fragment } = require("react/jsx-runtime"); +const App = /*#__PURE__*/ _jsxs("div", { + children: [ + /*#__PURE__*/ _jsx("div", {}), + /*#__PURE__*/ _jsx(_Fragment, { + children: /*#__PURE__*/ _jsx("div", { + children: "hoge" + }, 1) + }) + ] +}); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/input.js b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/input.js new file mode 100644 index 000000000000..1cbfdc88d670 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/input.js @@ -0,0 +1,6 @@ +var x = ( + <> +
hoge
+
fuga
+ +); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/options.json b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/options.json new file mode 100644 index 000000000000..e7394a9a83f4 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/options.json @@ -0,0 +1 @@ +{ "runtime": "automatic", "development": true } diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/output.js b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/output.js new file mode 100644 index 000000000000..9e1dccb4d770 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-args-with-fragment/output.js @@ -0,0 +1,19 @@ +const { jsxDEV: _jsxDEV , Fragment: _Fragment } = require("react/jsx-dev-runtime"); +var x = /*#__PURE__*/ _jsxDEV(_Fragment, { + children: [ + /*#__PURE__*/ _jsxDEV("div", { + children: "hoge" + }, void 0, false, { + fileName: "input.js", + lineNumber: 3, + columnNumber: 9 + }, this), + /*#__PURE__*/ _jsxDEV("div", { + children: "fuga" + }, void 0, false, { + fileName: "input.js", + lineNumber: 4, + columnNumber: 9 + }, this) + ] +}, void 0, true); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/input.js b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/input.js new file mode 100644 index 000000000000..8998b645e119 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/input.js @@ -0,0 +1,6 @@ +const App = ( + <> +
hoge
+
fuga
+ +); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/options.json b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/options.json new file mode 100644 index 000000000000..e7394a9a83f4 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/options.json @@ -0,0 +1 @@ +{ "runtime": "automatic", "development": true } diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/output.js b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/output.js new file mode 100644 index 000000000000..5f8a6527ce21 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/jsxdev-fragment/output.js @@ -0,0 +1,19 @@ +const { jsxDEV: _jsxDEV , Fragment: _Fragment } = require("react/jsx-dev-runtime"); +const App = /*#__PURE__*/ _jsxDEV(_Fragment, { + children: [ + /*#__PURE__*/ _jsxDEV("div", { + children: "hoge" + }, void 0, false, { + fileName: "input.js", + lineNumber: 3, + columnNumber: 9 + }, this), + /*#__PURE__*/ _jsxDEV("div", { + children: "fuga" + }, void 0, false, { + fileName: "input.js", + lineNumber: 4, + columnNumber: 9 + }, this) + ] +}, void 0, true); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/input.js b/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/input.js new file mode 100644 index 000000000000..92dc99d3ebf2 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/input.js @@ -0,0 +1,9 @@ +/**@jsxRuntime automatic */ +const App = ( +
+
+ <> +
hoge
+ +
+); diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/options.json b/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/options.json new file mode 100644 index 000000000000..b9c76dfe86e8 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/options.json @@ -0,0 +1 @@ +{ "development": true } diff --git a/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/output.js b/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/output.js new file mode 100644 index 000000000000..a98766dc4d54 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/integration/with-pragma/output.js @@ -0,0 +1,23 @@ +/**@jsxRuntime automatic */ const { jsxDEV: _jsxDEV , Fragment: _Fragment } = require("react/jsx-dev-runtime"); +const App = /*#__PURE__*/ _jsxDEV("div", { + children: [ + /*#__PURE__*/ _jsxDEV("div", {}, void 0, false, { + fileName: "input.js", + lineNumber: 4, + columnNumber: 9 + }, this), + /*#__PURE__*/ _jsxDEV(_Fragment, { + children: /*#__PURE__*/ _jsxDEV("div", { + children: "hoge" + }, void 0, false, { + fileName: "input.js", + lineNumber: 6, + columnNumber: 13 + }, this) + }, void 0, false) + ] +}, void 0, true, { + fileName: "input.js", + lineNumber: 3, + columnNumber: 5 +}, this); diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/input.js b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/input.js new file mode 100644 index 000000000000..4c14f688b6d4 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/input.js @@ -0,0 +1,7 @@ +// https://github.com/babel/babel/issues/12522 + +require("react-app-polyfill/ie11"); +require("react-app-polyfill/stable"); +const ReactDOM = require("react-dom"); + +ReactDOM.render(

Hello, World!

, document.getElementById("root")); diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/options.json b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/options.json new file mode 100644 index 000000000000..8c29c48c6f58 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/options.json @@ -0,0 +1 @@ +{ "runtime": "automatic" } diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/output.js b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/output.js new file mode 100644 index 000000000000..3ecd3ac38c08 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/after-polyfills-script/output.js @@ -0,0 +1,8 @@ +// https://github.com/babel/babel/issues/12522 +const { jsx: _jsx } = require("react/jsx-runtime"); +require("react-app-polyfill/ie11"); +require("react-app-polyfill/stable"); +const ReactDOM = require("react-dom"); +ReactDOM.render(/*#__PURE__*/ _jsx("p", { + children: "Hello, World!" +}), document.getElementById("root")); diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/input.js b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/input.js new file mode 100644 index 000000000000..189da391f70b --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/input.js @@ -0,0 +1,10 @@ +var x = ( + <> +
+
+
+
+
+
+ +); diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/options.json b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/options.json new file mode 100644 index 000000000000..8c29c48c6f58 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/options.json @@ -0,0 +1 @@ +{ "runtime": "automatic" } diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/output.js b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/output.js new file mode 100644 index 000000000000..35ea082fb384 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/auto-import-runtime-source-type-script/output.js @@ -0,0 +1,17 @@ +const { jsx: _jsx , jsxs: _jsxs , Fragment: _Fragment } = require("react/jsx-runtime"); +const { createElement: _createElement } = require("react"); +var x = /*#__PURE__*/ _jsx(_Fragment, { + children: /*#__PURE__*/ _jsxs("div", { + children: [ + /*#__PURE__*/ _jsx("div", {}, "1"), + /*#__PURE__*/ _jsx("div", { + meow: "wolf" + }, "2"), + /*#__PURE__*/ _jsx("div", {}, "3"), + /*#__PURE__*/ _createElement("div", { + ...props, + key: "4" + }) + ] + }) +}); diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/input.js b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/input.js new file mode 100644 index 000000000000..dc274bc8d9a2 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/input.js @@ -0,0 +1,15 @@ +const Bar = () => { + const Foo = () => { + const Component = ({ thing, ..._react }) => { + if (!thing) { + var _react2 = "something useless"; + var b = _react3(); + var c = _react5(); + var jsx = 1; + var _jsx = 2; + return
; + } + return ; + }; + }; +}; diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/options.json b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/options.json new file mode 100644 index 000000000000..8c29c48c6f58 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/options.json @@ -0,0 +1 @@ +{ "runtime": "automatic" } diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/output.js b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/output.js new file mode 100644 index 000000000000..6f52798bdbc7 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/complicated-scope-script/output.js @@ -0,0 +1,16 @@ +const { jsx: _jsx } = require("react/jsx-runtime"); +const Bar = ()=>{ + const Foo = ()=>{ + const Component = ({ thing , ..._react })=>{ + if (!thing) { + var _react2 = "something useless"; + var b = _react3(); + var c = _react5(); + var jsx = 1; + var _jsx1 = 2; + return /*#__PURE__*/ _jsx("div", {}); + } + return /*#__PURE__*/ _jsx("span", {}); + }; + }; +}; diff --git a/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/options.json b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/options.json new file mode 100644 index 000000000000..8c29c48c6f58 --- /dev/null +++ b/crates/swc_ecma_transforms_react/tests/script/jsx/fixture/autoImport/options.json @@ -0,0 +1 @@ +{ "runtime": "automatic" }