diff options
Diffstat (limited to 'cli/compilers/ts.rs')
-rw-r--r-- | cli/compilers/ts.rs | 195 |
1 files changed, 77 insertions, 118 deletions
diff --git a/cli/compilers/ts.rs b/cli/compilers/ts.rs index c7896ec61..c882f7d66 100644 --- a/cli/compilers/ts.rs +++ b/cli/compilers/ts.rs @@ -2,7 +2,6 @@ use super::compiler_worker::CompilerWorker; use crate::compilers::CompilationResultFuture; use crate::compilers::CompiledModule; -use crate::compilers::CompiledModuleFuture; use crate::diagnostics::Diagnostic; use crate::disk_cache::DiskCache; use crate::file_fetcher::SourceFile; @@ -18,7 +17,6 @@ use deno_core::Buf; use deno_core::ErrBox; use deno_core::ModuleSpecifier; use futures::future::FutureExt; -use futures::Future; use regex::Regex; use serde_json::json; use std::collections::HashMap; @@ -26,10 +24,12 @@ use std::collections::HashSet; use std::fs; use std::hash::BuildHasher; use std::io; +use std::ops::Deref; use std::path::PathBuf; use std::pin::Pin; use std::str; use std::sync::atomic::Ordering; +use std::sync::Arc; use std::sync::Mutex; use url::Url; @@ -202,7 +202,7 @@ pub fn source_code_version_hash( crate::checksum::gen(vec![source_code, version.as_bytes(), config_hash]) } -pub struct TsCompiler { +pub struct TsCompilerInner { pub file_fetcher: SourceFileFetcher, pub config: CompilerConfig, pub disk_cache: DiskCache, @@ -216,6 +216,16 @@ pub struct TsCompiler { pub compile_js: bool, } +#[derive(Clone)] +pub struct TsCompiler(Arc<TsCompilerInner>); + +impl Deref for TsCompiler { + type Target = TsCompilerInner; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl TsCompiler { pub fn new( file_fetcher: SourceFileFetcher, @@ -224,17 +234,14 @@ impl TsCompiler { config_path: Option<String>, ) -> Result<Self, ErrBox> { let config = CompilerConfig::load(config_path)?; - - let compiler = Self { + Ok(TsCompiler(Arc::new(TsCompilerInner { file_fetcher, disk_cache, compile_js: config.compile_js, config, compiled: Mutex::new(HashSet::new()), use_disk_cache, - }; - - Ok(compiler) + }))) } /// Create a new V8 worker with snapshot of TS compiler and setup compiler's @@ -261,12 +268,12 @@ impl TsCompiler { worker } - pub fn bundle_async( + pub async fn bundle_async( &self, global_state: ThreadSafeGlobalState, module_name: String, out_file: Option<String>, - ) -> impl Future<Output = Result<(), ErrBox>> { + ) -> Result<(), ErrBox> { debug!( "Invoking the compiler to bundle. module_name: {}", module_name @@ -282,41 +289,15 @@ impl TsCompiler { true, ); - // TODO(ry) The code below looks very similar to spawn_ts_compiler_worker. - // Can we combine them? - let (load_sender, load_receiver) = - tokio::sync::oneshot::channel::<Result<(), ErrBox>>(); - std::thread::spawn(move || { - let mut worker = TsCompiler::setup_worker(global_state); - let handle = worker.thread_safe_handle(); - - let fut = async move { - if let Err(err) = handle.post_message(req_msg).await { - load_sender.send(Err(err)).unwrap(); - return; - } - debug!("Sent message to worker"); - if let Err(err) = (&mut *worker).await { - load_sender.send(Err(err)).unwrap(); - return; - } - let maybe_msg = handle.get_message().await; - debug!("Received message from worker"); - if let Some(ref msg) = maybe_msg { - let json_str = std::str::from_utf8(msg).unwrap(); - debug!("Message: {}", json_str); - if let Some(diagnostics) = Diagnostic::from_emit_result(json_str) { - let err = ErrBox::from(diagnostics); - load_sender.send(Err(err)).unwrap(); - return; - } - } - load_sender.send(Ok(())).unwrap(); + let maybe_msg = execute_in_thread(global_state.clone(), req_msg).await?; + if let Some(ref msg) = maybe_msg { + let json_str = std::str::from_utf8(msg).unwrap(); + debug!("Message: {}", json_str); + if let Some(diagnostics) = Diagnostic::from_emit_result(json_str) { + return Err(ErrBox::from(diagnostics)); } - .boxed_local(); - crate::tokio_util::run_basic(fut); - }); - async { load_receiver.await.unwrap() }.boxed_local() + } + Ok(()) } /// Mark given module URL as compiled to avoid multiple compilations of same @@ -342,17 +323,14 @@ impl TsCompiler { /// /// If compilation is required then new V8 worker is spawned with fresh TS /// compiler. - pub fn compile_async( + pub async fn compile_async( &self, global_state: ThreadSafeGlobalState, source_file: &SourceFile, target: TargetLib, - ) -> Pin<Box<CompiledModuleFuture>> { + ) -> Result<CompiledModule, ErrBox> { if self.has_compiled(&source_file.url) { - return match self.get_compiled_module(&source_file.url) { - Ok(compiled) => futures::future::ok(compiled).boxed(), - Err(err) => futures::future::err(err).boxed(), - }; + return self.get_compiled_module(&source_file.url); } if self.use_disk_cache { @@ -373,7 +351,7 @@ impl TsCompiler { self.get_compiled_module(&source_file.url) { self.mark_compiled(&source_file.url); - return futures::future::ok(compiled_module).boxed(); + return Ok(compiled_module); } } } @@ -394,51 +372,22 @@ impl TsCompiler { false, ); - // TODO(ry) The code below looks very similar to spawn_ts_compiler_worker. - // Can we combine them? - let (load_sender, load_receiver) = - tokio::sync::oneshot::channel::<Result<CompiledModule, ErrBox>>(); - std::thread::spawn(move || { - debug!(">>>>> compile_async START"); + let ts_compiler = self.clone(); - let mut worker = TsCompiler::setup_worker(global_state.clone()); - let handle = worker.thread_safe_handle(); + let compiling_job = global_state + .progress + .add("Compile", &module_url.to_string()); + let maybe_msg = execute_in_thread(global_state.clone(), req_msg).await?; - let compiling_job = global_state - .progress - .add("Compile", &module_url.to_string()); - - let fut = async move { - if let Err(err) = handle.post_message(req_msg).await { - load_sender.send(Err(err)).unwrap(); - return; - } - if let Err(err) = (&mut *worker).await { - load_sender.send(Err(err)).unwrap(); - return; - } - let maybe_msg = handle.get_message().await; - if let Some(ref msg) = maybe_msg { - let json_str = std::str::from_utf8(msg).unwrap(); - if let Some(diagnostics) = Diagnostic::from_emit_result(json_str) { - let err = ErrBox::from(diagnostics); - load_sender.send(Err(err)).unwrap(); - return; - } - } - let compiled_module = global_state - .ts_compiler - .get_compiled_module(&source_file_.url) - .expect("Expected to find compiled file"); - drop(compiling_job); - debug!(">>>>> compile_sync END"); - load_sender.send(Ok(compiled_module)).unwrap(); + if let Some(ref msg) = maybe_msg { + let json_str = std::str::from_utf8(msg).unwrap(); + if let Some(diagnostics) = Diagnostic::from_emit_result(json_str) { + return Err(ErrBox::from(diagnostics)); } - .boxed_local(); - crate::tokio_util::run_basic(fut); - }); - - async { load_receiver.await.unwrap() }.boxed_local() + } + let compiled_module = ts_compiler.get_compiled_module(&source_file_.url)?; + drop(compiling_job); + Ok(compiled_module) } /// Get associated `CompiledFileMetadata` for given module if it exists. @@ -654,37 +603,47 @@ impl TsCompiler { } } -// TODO(ry) this is pretty general purpose and should be lifted and generalized. -fn spawn_ts_compiler_worker( - req_msg: Buf, +async fn execute_in_thread( global_state: ThreadSafeGlobalState, -) -> Pin<Box<CompilationResultFuture>> { + req: Buf, +) -> Result<Option<Buf>, ErrBox> { let (load_sender, load_receiver) = - tokio::sync::oneshot::channel::<JsonResult>(); - + tokio::sync::oneshot::channel::<Result<Option<Buf>, ErrBox>>(); std::thread::spawn(move || { - let mut worker = TsCompiler::setup_worker(global_state); + debug!(">>>>> compile_async START"); + + let mut worker = TsCompiler::setup_worker(global_state.clone()); let handle = worker.thread_safe_handle(); - let fut = async move { - debug!("Sent message to worker"); - if let Err(err) = handle.post_message(req_msg).await { - load_sender.send(Err(err)).unwrap(); - return; - } - if let Err(err) = (&mut *worker).await { - load_sender.send(Err(err)).unwrap(); - return; + crate::tokio_util::run_basic( + async move { + if let Err(err) = handle.post_message(req).await { + load_sender.send(Err(err)).unwrap(); + return; + } + if let Err(err) = (&mut *worker).await { + load_sender.send(Err(err)).unwrap(); + return; + } + let maybe_msg = handle.get_message().await; + load_sender.send(Ok(maybe_msg)).unwrap(); + debug!(">>>>> compile_sync END"); } - let msg = handle.get_message().await.unwrap(); - let json_str = std::str::from_utf8(&msg).unwrap(); - load_sender.send(Ok(json!(json_str))).unwrap(); - }; - crate::tokio_util::run_basic(fut); + .boxed_local(), + ); }); - let fut = async { load_receiver.await.unwrap() }; - fut.boxed_local() + load_receiver.await.unwrap() +} + +async fn execute_in_thread_json( + req_msg: Buf, + global_state: ThreadSafeGlobalState, +) -> JsonResult { + let maybe_msg = execute_in_thread(global_state, req_msg).await?; + let msg = maybe_msg.unwrap(); + let json_str = std::str::from_utf8(&msg).unwrap(); + Ok(json!(json_str)) } pub fn runtime_compile_async<S: BuildHasher>( @@ -706,7 +665,7 @@ pub fn runtime_compile_async<S: BuildHasher>( .into_boxed_str() .into_boxed_bytes(); - spawn_ts_compiler_worker(req_msg, global_state) + execute_in_thread_json(req_msg, global_state).boxed_local() } pub fn runtime_transpile_async<S: BuildHasher>( @@ -723,7 +682,7 @@ pub fn runtime_transpile_async<S: BuildHasher>( .into_boxed_str() .into_boxed_bytes(); - spawn_ts_compiler_worker(req_msg, global_state) + execute_in_thread_json(req_msg, global_state).boxed_local() } #[cfg(test)] |