diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2020-05-20 16:25:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-20 16:25:40 +0200 |
commit | 8799855fdc97960b18fbbb3450ed132e352607c4 (patch) | |
tree | f9539f9c0acbbed88d789d64980f0ebd546229e8 /cli/tsc.rs | |
parent | f366e5e9bb5982376b160bebd35c3edf2c9ff19b (diff) |
refactor: reorganize TS compiler (#5603)
Diffstat (limited to 'cli/tsc.rs')
-rw-r--r-- | cli/tsc.rs | 258 |
1 files changed, 132 insertions, 126 deletions
diff --git a/cli/tsc.rs b/cli/tsc.rs index 41eb7e43c..0bfcf6266 100644 --- a/cli/tsc.rs +++ b/cli/tsc.rs @@ -165,6 +165,33 @@ lazy_static! { Regex::new(r#""checkJs"\s*?:\s*?true"#).unwrap(); } +/// Create a new worker with snapshot of TS compiler and setup compiler's +/// runtime. +fn create_compiler_worker( + global_state: GlobalState, + permissions: Permissions, +) -> CompilerWorker { + // TODO(bartlomieju): these $deno$ specifiers should be unified for all subcommands + // like 'eval', 'repl' + let entry_point = + ModuleSpecifier::resolve_url_or_path("./__$deno$ts_compiler.ts").unwrap(); + let worker_state = + State::new(global_state.clone(), Some(permissions), entry_point, true) + .expect("Unable to create worker state"); + + // TODO(bartlomieju): this metric is never used anywhere + // Count how many times we start the compiler worker. + global_state.compiler_starts.fetch_add(1, Ordering::SeqCst); + + let mut worker = CompilerWorker::new( + "TS".to_string(), + startup_data::compiler_isolate_init(), + worker_state, + ); + worker.execute("bootstrap.tsCompilerRuntime()").unwrap(); + worker +} + #[derive(Clone)] pub enum TargetLib { Main, @@ -312,7 +339,7 @@ struct EmittedSource { #[serde(rename_all = "camelCase")] struct BundleResponse { diagnostics: Diagnostic, - bundle_output: String, + bundle_output: Option<String>, } #[derive(Deserialize)] @@ -356,126 +383,6 @@ impl TsCompiler { }))) } - /// Create a new V8 worker with snapshot of TS compiler and setup compiler's - /// runtime. - fn setup_worker( - global_state: GlobalState, - permissions: Permissions, - ) -> CompilerWorker { - let entry_point = - ModuleSpecifier::resolve_url_or_path("./__$deno$ts_compiler.ts").unwrap(); - let worker_state = - State::new(global_state.clone(), Some(permissions), entry_point, true) - .expect("Unable to create worker state"); - - // Count how many times we start the compiler worker. - global_state.compiler_starts.fetch_add(1, Ordering::SeqCst); - - let mut worker = CompilerWorker::new( - "TS".to_string(), - startup_data::compiler_isolate_init(), - worker_state, - ); - worker.execute("bootstrap.tsCompilerRuntime()").unwrap(); - worker - } - - pub async fn bundle( - &self, - global_state: GlobalState, - module_specifier: ModuleSpecifier, - out_file: Option<PathBuf>, - ) -> Result<(), ErrBox> { - debug!( - "Invoking the compiler to bundle. module_name: {}", - module_specifier.to_string() - ); - eprintln!("Bundling {}", module_specifier.to_string()); - - let import_map: Option<ImportMap> = - match global_state.flags.import_map_path.as_ref() { - None => None, - Some(file_path) => { - if !global_state.flags.unstable { - exit_unstable("--importmap") - } - Some(ImportMap::load(file_path)?) - } - }; - let permissions = Permissions::allow_all(); - let mut module_graph_loader = ModuleGraphLoader::new( - global_state.file_fetcher.clone(), - import_map, - permissions.clone(), - false, - true, - ); - module_graph_loader.add_to_graph(&module_specifier).await?; - let module_graph = module_graph_loader.get_graph(); - let module_graph_json = - serde_json::to_value(module_graph).expect("Failed to serialize data"); - - let root_names = vec![module_specifier.to_string()]; - let bundle = true; - let target = "main"; - let unstable = global_state.flags.unstable; - let compiler_config = self.config.clone(); - let cwd = std::env::current_dir().unwrap(); - let j = match (compiler_config.path, compiler_config.content) { - (Some(config_path), Some(config_data)) => json!({ - "type": msg::CompilerRequestType::Compile as i32, - "target": target, - "rootNames": root_names, - "bundle": bundle, - "unstable": unstable, - "configPath": config_path, - "config": str::from_utf8(&config_data).unwrap(), - "cwd": cwd, - "sourceFileMap": module_graph_json, - }), - _ => json!({ - "type": msg::CompilerRequestType::Compile as i32, - "target": target, - "rootNames": root_names, - "bundle": bundle, - "unstable": unstable, - "cwd": cwd, - "sourceFileMap": module_graph_json, - }), - }; - - let req_msg = j.to_string().into_boxed_str().into_boxed_bytes(); - - let msg = - execute_in_same_thread(global_state.clone(), permissions, req_msg) - .await?; - let json_str = std::str::from_utf8(&msg).unwrap(); - debug!("Message: {}", json_str); - - let bundle_response: BundleResponse = serde_json::from_str(json_str)?; - - if !bundle_response.diagnostics.items.is_empty() { - return Err(ErrBox::from(bundle_response.diagnostics)); - } - - let output_string = fmt::format_text(&bundle_response.bundle_output)?; - - if let Some(out_file_) = out_file.as_ref() { - eprintln!("Emitting bundle to {:?}", out_file_); - - let output_bytes = output_string.as_bytes(); - let output_len = output_bytes.len(); - - deno_fs::write_file(out_file_, output_bytes, 0o666)?; - // TODO(bartlomieju): add "humanFileSize" method - eprintln!("{} bytes emitted.", output_len); - } else { - println!("{}", output_string); - } - - Ok(()) - } - /// Mark given module URL as compiled to avoid multiple compilations of same /// module in single run. fn mark_compiled(&self, url: &Url) { @@ -914,7 +821,7 @@ async fn execute_in_same_thread( permissions: Permissions, req: Buf, ) -> Result<Buf, ErrBox> { - let mut worker = TsCompiler::setup_worker(global_state.clone(), permissions); + let mut worker = create_compiler_worker(global_state.clone(), permissions); let handle = worker.thread_safe_handle(); handle.post_message(req)?; @@ -943,6 +850,100 @@ async fn execute_in_same_thread( } } +pub async fn bundle( + global_state: &GlobalState, + compiler_config: CompilerConfig, + module_specifier: ModuleSpecifier, + maybe_import_map: Option<ImportMap>, + out_file: Option<PathBuf>, + unstable: bool, +) -> Result<(), ErrBox> { + debug!( + "Invoking the compiler to bundle. module_name: {}", + module_specifier.to_string() + ); + eprintln!("Bundling {}", module_specifier.to_string()); + + let permissions = Permissions::allow_all(); + let mut module_graph_loader = ModuleGraphLoader::new( + global_state.file_fetcher.clone(), + maybe_import_map, + permissions.clone(), + false, + true, + ); + module_graph_loader.add_to_graph(&module_specifier).await?; + let module_graph = module_graph_loader.get_graph(); + let module_graph_json = + serde_json::to_value(module_graph).expect("Failed to serialize data"); + + let root_names = vec![module_specifier.to_string()]; + let bundle = true; + let target = "main"; + let cwd = std::env::current_dir().unwrap(); + + // TODO(bartlomieju): this is non-sense; CompilerConfig's `path` and `content` should + // be optional + let j = match (compiler_config.path, compiler_config.content) { + (Some(config_path), Some(config_data)) => json!({ + "type": msg::CompilerRequestType::Compile as i32, + "target": target, + "rootNames": root_names, + "bundle": bundle, + "unstable": unstable, + "configPath": config_path, + "config": str::from_utf8(&config_data).unwrap(), + "cwd": cwd, + "sourceFileMap": module_graph_json, + }), + _ => json!({ + "type": msg::CompilerRequestType::Compile as i32, + "target": target, + "rootNames": root_names, + "bundle": bundle, + "unstable": unstable, + "cwd": cwd, + "sourceFileMap": module_graph_json, + }), + }; + + let req_msg = j.to_string().into_boxed_str().into_boxed_bytes(); + + let msg = + execute_in_same_thread(global_state.clone(), permissions, req_msg).await?; + let json_str = std::str::from_utf8(&msg).unwrap(); + debug!("Message: {}", json_str); + + let bundle_response: BundleResponse = serde_json::from_str(json_str)?; + + if !bundle_response.diagnostics.items.is_empty() { + return Err(ErrBox::from(bundle_response.diagnostics)); + } + + assert!(bundle_response.bundle_output.is_some()); + let output = bundle_response.bundle_output.unwrap(); + + // TODO(bartlomieju): the rest of this function should be handled + // in `main.rs` - it has nothing to do with TypeScript... + let output_string = fmt::format_text(&output)?; + + if let Some(out_file_) = out_file.as_ref() { + eprintln!("Emitting bundle to {:?}", out_file_); + + let output_bytes = output_string.as_bytes(); + let output_len = output_bytes.len(); + + deno_fs::write_file(out_file_, output_bytes, 0o666)?; + // TODO(bartlomieju): do we really need to show this info? (it doesn't respect --quiet flag) + // TODO(bartlomieju): add "humanFileSize" method + eprintln!("{} bytes emitted.", output_len); + } else { + println!("{}", output_string); + } + + Ok(()) +} + /// This function is used by `Deno.compile()` and `Deno.bundle()` APIs. pub async fn runtime_compile<S: BuildHasher>( global_state: GlobalState, @@ -1138,10 +1139,15 @@ mod tests { String::from("$deno$/bundle.js"), ]); - let result = state - .ts_compiler - .bundle(state.clone(), module_name, None) - .await; + let result = bundle( + &state, + CompilerConfig::load(None).unwrap(), + module_name, + None, + None, + false, + ) + .await; assert!(result.is_ok()); } |