From fa98c470d6e620015e01f323d0e39a56b9857ec2 Mon Sep 17 00:00:00 2001 From: kdy1 Date: Wed, 11 Dec 2019 06:07:21 +0000 Subject: [PATCH] Program instead of Module (#499) This pr adds an option to parse file as script, not module. Related: https://github.com/swc-project/swc/issues/491 --- ecmascript/ast/src/lib.rs | 2 +- ecmascript/ast/src/module.rs | 8 +++++++ ecmascript/codegen/src/lib.rs | 8 +++++++ src/builder.rs | 8 +++---- src/config.rs | 14 +++++++++++-- src/lib.rs | 39 ++++++++++++++++++++++++++--------- tests/projects.rs | 3 +++ 7 files changed, 65 insertions(+), 17 deletions(-) diff --git a/ecmascript/ast/src/lib.rs b/ecmascript/ast/src/lib.rs index a2526a76d35..c6e9fab5abf 100644 --- a/ecmascript/ast/src/lib.rs +++ b/ecmascript/ast/src/lib.rs @@ -27,7 +27,7 @@ pub use self::{ JSXOpeningFragment, JSXSpreadChild, JSXText, }, lit::{Bool, Lit, Null, Number, Regex, RegexFlags, Str}, - module::{Module, ModuleItem, Script}, + module::{Module, ModuleItem, Program, Script}, module_decl::{ DefaultDecl, DefaultExportSpecifier, ExportAll, ExportDecl, ExportDefaultDecl, ExportDefaultExpr, ExportSpecifier, ImportDecl, ImportDefault, ImportSpecific, diff --git a/ecmascript/ast/src/module.rs b/ecmascript/ast/src/module.rs index 6e55e5484b6..7c5742b948e 100644 --- a/ecmascript/ast/src/module.rs +++ b/ecmascript/ast/src/module.rs @@ -2,6 +2,14 @@ use crate::{module_decl::ModuleDecl, stmt::Stmt}; use swc_atoms::JsWord; use swc_common::{ast_node, Span}; +#[ast_node] +pub enum Program { + #[tag("Module")] + Module(Module), + #[tag("Script")] + Script(Script), +} + #[ast_node("Module")] pub struct Module { pub span: Span, diff --git a/ecmascript/codegen/src/lib.rs b/ecmascript/codegen/src/lib.rs index a3cd4b6f45c..5b176941fd8 100644 --- a/ecmascript/codegen/src/lib.rs +++ b/ecmascript/codegen/src/lib.rs @@ -77,6 +77,14 @@ impl<'a> Emitter<'a> { Ok(()) } + #[emitter] + pub fn emit_program(&mut self, node: &Program) -> Result { + match *node { + Program::Module(ref m) => emit!(m), + Program::Script(ref s) => emit!(s), + } + } + #[emitter] pub fn emit_module(&mut self, node: &Module) -> Result { if let Some(ref shebang) = node.shebang { diff --git a/src/builder.rs b/src/builder.rs index 8eccf009f60..79b3d9ed6c3 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -2,7 +2,7 @@ use crate::config::{GlobalPassOption, JscTarget, ModuleConfig}; use atoms::JsWord; use common::{errors::Handler, SourceMap}; use ecmascript::{ - ast::Module, + ast::Program, parser::Syntax, transforms::{ chain_at, compat, const_modules, fixer, helpers, hygiene, modules, @@ -33,8 +33,8 @@ impl<'a, 'b, P: Pass> PassBuilder<'a, 'b, P> { } } - pub fn then(self, next: N) -> PassBuilder<'a, 'b, JoinedPass> { - let pass = chain_at!(Module, self.pass, next); + pub fn then(self, next: N) -> PassBuilder<'a, 'b, JoinedPass> { + let pass = chain_at!(Program, self.pass, next); PassBuilder { cm: self.cm, handler: self.handler, @@ -86,7 +86,7 @@ impl<'a, 'b, P: Pass> PassBuilder<'a, 'b, P> { }; chain_at!( - Module, + Program, self.pass, // compat Optional::new(compat::es2018(), self.target <= JscTarget::Es2018), diff --git a/src/config.rs b/src/config.rs index d128373da26..4a66aaf569c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,7 +4,7 @@ use chashmap::CHashMap; use common::{errors::Handler, FileName, SourceMap}; pub use ecmascript::parser::JscTarget; use ecmascript::{ - ast::{Expr, Module, ModuleItem, Stmt}, + ast::{Expr, ModuleItem, Program, Stmt}, parser::{Parser, Session as ParseSess, SourceFileInput, Syntax}, transforms::{ chain_at, const_modules, modules, @@ -81,6 +81,13 @@ pub struct Options { #[serde(default)] pub source_root: Option, + + #[serde(default = "default_is_module")] + pub is_module: bool, +} + +fn default_is_module() -> bool { + true } #[derive(Clone, Serialize, Deserialize)] @@ -114,6 +121,7 @@ impl Options { &self, cm: &Arc, handler: &Handler, + is_module: bool, config: Option, ) -> BuiltConfig { let mut config = config.unwrap_or_else(Default::default); @@ -163,7 +171,7 @@ impl Options { }; let pass = chain_at!( - Module, + Program, // handle jsx Optional::new(react::react(cm.clone(), transform.react), syntax.jsx()), Optional::new(typescript::strip(), syntax.typescript()), @@ -191,6 +199,7 @@ impl Options { pass, external_helpers, syntax, + is_module, source_maps: self .source_maps .as_ref() @@ -397,6 +406,7 @@ pub struct BuiltConfig { pub minify: bool, pub external_helpers: bool, pub source_maps: bool, + pub is_module: bool, } #[derive(Default, Clone, Serialize, Deserialize)] diff --git a/src/lib.rs b/src/lib.rs index 9ce6f1b369c..d7745db085f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ use common::{ GLOBALS, }; use ecmascript::{ - ast::Module, + ast::Program, codegen::{self, Emitter}, parser::{Parser, Session as ParseSess, Syntax}, transforms::{ @@ -69,25 +69,39 @@ impl Compiler { &self, fm: Arc, syntax: Syntax, + is_module: bool, comments: Option<&Comments>, - ) -> Result { + ) -> Result { self.run(|| { let session = ParseSess { handler: &self.handler, }; let mut parser = Parser::new(session, syntax, SourceFileInput::from(&*fm), comments); - let module = parser.parse_module().map_err(|mut e| { - e.emit(); - Error::FailedToParseModule {} - })?; + let program = if is_module { + parser + .parse_module() + .map_err(|mut e| { + e.emit(); + Error::FailedToParseModule {} + }) + .map(Program::Module)? + } else { + parser + .parse_script() + .map_err(|mut e| { + e.emit(); + Error::FailedToParseModule {} + }) + .map(Program::Script)? + }; - Ok(module) + Ok(program) }) } pub fn print( &self, - module: &Module, + program: &Program, fm: Arc, comments: &Comments, source_map: bool, @@ -127,7 +141,7 @@ impl Compiler { }; emitter - .emit_module(&module) + .emit_program(&program) .map_err(|err| Error::FailedToEmitModule { err })?; } // Invalid utf8 is valid in javascript world. @@ -173,6 +187,7 @@ impl Compiler { root_mode, swcrc, config_file, + is_module, .. } = opts; let root = root @@ -206,7 +221,8 @@ impl Compiler { if let Some(config_file) = config_file { config.merge(&config_file.into_config(Some(path))?) } - let built = opts.build(&self.cm, &self.handler, Some(config)); + let built = + opts.build(&self.cm, &self.handler, *is_module, Some(config)); return Ok(built); } @@ -221,6 +237,7 @@ impl Compiler { let built = opts.build( &self.cm, &self.handler, + *is_module, Some(config_file.into_config(Some(path))?), ); return Ok(built); @@ -232,6 +249,7 @@ impl Compiler { let built = opts.build( &self.cm, &self.handler, + *is_module, match config_file { Some(config_file) => Some(config_file.into_config(None)?), None => None, @@ -267,6 +285,7 @@ impl Compiler { let module = self.parse_js( fm.clone(), config.syntax, + config.is_module, if config.minify { None } else { Some(&comments) }, )?; let mut pass = config.pass; diff --git a/tests/projects.rs b/tests/projects.rs index ff745db3195..c2d0fb900a5 100644 --- a/tests/projects.rs +++ b/tests/projects.rs @@ -12,6 +12,7 @@ fn file(f: &str) -> Result { fm, &Options { swcrc: true, + is_module: true, ..Default::default() }, ); @@ -46,6 +47,8 @@ fn project(dir: &str) { fm, &Options { swcrc: true, + is_module: true, + ..Default::default() }, );