summaryrefslogtreecommitdiff
path: root/cli/ast/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/ast/mod.rs')
-rw-r--r--cli/ast/mod.rs187
1 files changed, 112 insertions, 75 deletions
diff --git a/cli/ast/mod.rs b/cli/ast/mod.rs
index f0ad36885..894a42d4e 100644
--- a/cli/ast/mod.rs
+++ b/cli/ast/mod.rs
@@ -24,7 +24,7 @@ use deno_ast::swc::transforms::hygiene;
use deno_ast::swc::transforms::pass::Optional;
use deno_ast::swc::transforms::proposals;
use deno_ast::swc::transforms::react;
-use deno_ast::swc::transforms::resolver::ts_resolver;
+use deno_ast::swc::transforms::resolver_with_mark;
use deno_ast::swc::transforms::typescript;
use deno_ast::swc::visit::FoldWith;
use deno_ast::Diagnostic;
@@ -182,6 +182,8 @@ fn strip_config_from_emit_options(
options: &EmitOptions,
) -> typescript::strip::Config {
typescript::strip::Config {
+ pragma: Some(options.jsx_factory.clone()),
+ pragma_frag: Some(options.jsx_fragment_factory.clone()),
import_not_used_as_values: match options.imports_not_used_as_values {
ImportsNotUsedAsValues::Remove => {
typescript::strip::ImportsNotUsedAsValues::Remove
@@ -219,42 +221,14 @@ pub fn transpile(
let globals = Globals::new();
deno_ast::swc::common::GLOBALS.set(&globals, || {
let top_level_mark = Mark::fresh(Mark::root());
- let jsx_pass = chain!(
- ts_resolver(top_level_mark),
- react::react(
- source_map.clone(),
- Some(&comments),
- react::Options {
- pragma: options.jsx_factory.clone(),
- pragma_frag: options.jsx_fragment_factory.clone(),
- // this will use `Object.assign()` instead of the `_extends` helper
- // when spreading props.
- use_builtins: true,
- ..Default::default()
- },
- top_level_mark,
- ),
- );
- let mut passes = chain!(
- Optional::new(jsx_pass, options.transform_jsx),
- Optional::new(transforms::DownlevelImportsFolder, options.repl_imports),
- Optional::new(transforms::StripExportsFolder, options.repl_imports),
- proposals::decorators::decorators(proposals::decorators::Config {
- legacy: true,
- emit_metadata: options.emit_metadata
- }),
- helpers::inject_helpers(),
- typescript::strip::strip_with_config(strip_config_from_emit_options(
- options
- )),
- fixer(Some(&comments)),
- hygiene(),
+ let module = fold_program(
+ program,
+ options,
+ source_map.clone(),
+ &comments,
+ top_level_mark,
);
- let program = helpers::HELPERS.set(&helpers::Helpers::new(false), || {
- program.fold_with(&mut passes)
- });
-
let mut src_map_buf = vec![];
let mut buf = vec![];
{
@@ -271,7 +245,7 @@ pub fn transpile(
cm: source_map.clone(),
wr: writer,
};
- program.emit_with(&mut emitter)?;
+ module.emit_with(&mut emitter)?;
}
let mut src = String::from_utf8(buf)?;
let mut map: Option<String> = None;
@@ -299,8 +273,7 @@ pub fn transpile_module(
specifier: &ModuleSpecifier,
source: &str,
media_type: MediaType,
- emit_options: &EmitOptions,
- globals: &Globals,
+ options: &EmitOptions,
cm: Rc<SourceMap>,
) -> Result<(Rc<deno_ast::swc::common::SourceFile>, Module), AnyError> {
let source = strip_bom(source);
@@ -314,52 +287,85 @@ pub fn transpile_module(
let module = parser.parse_module().map_err(|err| {
let location = cm.lookup_char_pos(err.span().lo);
Diagnostic {
+ specifier: specifier.to_string(),
+ span: err.span(),
display_position: LineAndColumnDisplay {
line_number: location.line,
column_number: location.col_display + 1,
},
- specifier: specifier.to_string(),
- message: err.into_kind().msg().to_string(),
+ kind: err.into_kind(),
}
})?;
- deno_ast::swc::common::GLOBALS.set(globals, || {
- let top_level_mark = Mark::fresh(Mark::root());
- let jsx_pass = chain!(
- ts_resolver(top_level_mark),
- react::react(
- cm,
- Some(&comments),
- react::Options {
- pragma: emit_options.jsx_factory.clone(),
- pragma_frag: emit_options.jsx_fragment_factory.clone(),
- // this will use `Object.assign()` instead of the `_extends` helper
- // when spreading props.
- use_builtins: true,
- ..Default::default()
- },
- top_level_mark,
- ),
- );
- let mut passes = chain!(
- Optional::new(jsx_pass, emit_options.transform_jsx),
- proposals::decorators::decorators(proposals::decorators::Config {
- legacy: true,
- emit_metadata: emit_options.emit_metadata
- }),
- helpers::inject_helpers(),
+ let top_level_mark = Mark::fresh(Mark::root());
+ let program = fold_program(
+ Program::Module(module),
+ options,
+ cm,
+ &comments,
+ top_level_mark,
+ );
+ let module = match program {
+ Program::Module(module) => module,
+ _ => unreachable!(),
+ };
+
+ Ok((source_file, module))
+}
+
+fn fold_program(
+ program: Program,
+ options: &EmitOptions,
+ source_map: Rc<SourceMap>,
+ comments: &SingleThreadedComments,
+ top_level_mark: Mark,
+) -> Program {
+ let jsx_pass = chain!(
+ resolver_with_mark(top_level_mark),
+ react::react(
+ source_map.clone(),
+ Some(comments),
+ react::Options {
+ pragma: options.jsx_factory.clone(),
+ pragma_frag: options.jsx_fragment_factory.clone(),
+ // this will use `Object.assign()` instead of the `_extends` helper
+ // when spreading props.
+ use_builtins: true,
+ ..Default::default()
+ },
+ top_level_mark,
+ ),
+ );
+ let mut passes = chain!(
+ Optional::new(transforms::DownlevelImportsFolder, options.repl_imports),
+ Optional::new(transforms::StripExportsFolder, options.repl_imports),
+ proposals::decorators::decorators(proposals::decorators::Config {
+ legacy: true,
+ emit_metadata: options.emit_metadata
+ }),
+ helpers::inject_helpers(),
+ Optional::new(
typescript::strip::strip_with_config(strip_config_from_emit_options(
- emit_options
+ options
)),
- fixer(Some(&comments)),
- hygiene(),
- );
-
- let module = helpers::HELPERS.set(&helpers::Helpers::new(false), || {
- module.fold_with(&mut passes)
- });
-
- Ok((source_file, module))
+ !options.transform_jsx
+ ),
+ Optional::new(
+ typescript::strip::strip_with_jsx(
+ source_map,
+ strip_config_from_emit_options(options),
+ comments,
+ top_level_mark
+ ),
+ options.transform_jsx
+ ),
+ Optional::new(jsx_pass, options.transform_jsx),
+ fixer(Some(comments)),
+ hygiene(),
+ );
+
+ helpers::HELPERS.set(&helpers::Helpers::new(false), || {
+ program.fold_with(&mut passes)
})
}
@@ -435,6 +441,37 @@ mod tests {
}
#[test]
+ fn test_transpile_jsx_pragma() {
+ let specifier = resolve_url_or_path("https://deno.land/x/mod.ts")
+ .expect("could not resolve specifier");
+ let source = r#"
+/** @jsx h */
+/** @jsxFrag Fragment */
+import { h, Fragment } from "https://deno.land/x/mod.ts";
+
+function App() {
+ return (
+ <div><></></div>
+ );
+}"#;
+ let module = parse_module(ParseParams {
+ specifier: specifier.as_str().to_string(),
+ source: SourceTextInfo::from_string(source.to_string()),
+ media_type: deno_ast::MediaType::Jsx,
+ capture_tokens: false,
+ maybe_syntax: None,
+ scope_analysis: true,
+ })
+ .unwrap();
+ let (code, _) = transpile(&module, &EmitOptions::default()).unwrap();
+ let expected = r#"/** @jsx h */ /** @jsxFrag Fragment */ import { h, Fragment } from "https://deno.land/x/mod.ts";
+function App() {
+ return(/*#__PURE__*/ h("div", null, /*#__PURE__*/ h(Fragment, null)));
+}"#;
+ assert_eq!(&code[..expected.len()], expected);
+ }
+
+ #[test]
fn test_transpile_decorators() {
let specifier = resolve_url_or_path("https://deno.land/x/mod.ts")
.expect("could not resolve specifier");