summaryrefslogtreecommitdiff
path: root/cli/tsc.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2020-09-26 16:33:25 +0200
committerGitHub <noreply@github.com>2020-09-26 16:33:25 +0200
commitff785bc35aa650152643ffc65a2195e2b27f845b (patch)
tree1a06106a4cb30049e5fb9928c51ab0fea4c21e3b /cli/tsc.rs
parente0d4696a7201301dfa23e108b6e73d016e3f5e63 (diff)
refactor: use JsRuntime to implement TSC (#7691)
This commits removes "CompilerWorker" in favor of using "JsRuntime". "cli/ops/compiler.rs" has been removed in favor of inline registration of ops in "cli/tsc.rs"
Diffstat (limited to 'cli/tsc.rs')
-rw-r--r--cli/tsc.rs194
1 files changed, 68 insertions, 126 deletions
diff --git a/cli/tsc.rs b/cli/tsc.rs
index b9a8c9c4c..61d877e2d 100644
--- a/cli/tsc.rs
+++ b/cli/tsc.rs
@@ -8,29 +8,26 @@ use crate::disk_cache::DiskCache;
use crate::file_fetcher::SourceFile;
use crate::file_fetcher::SourceFileFetcher;
use crate::flags::Flags;
-use crate::fmt_errors::JsError;
use crate::global_state::GlobalState;
use crate::js;
use crate::media_type::MediaType;
use crate::module_graph::ModuleGraph;
use crate::module_graph::ModuleGraphLoader;
-use crate::ops;
use crate::permissions::Permissions;
use crate::source_maps::SourceMapGetter;
-use crate::state::CliModuleLoader;
use crate::tsc_config;
use crate::version;
-use crate::worker::Worker;
-use core::task::Context;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
-use deno_core::futures::future::Future;
-use deno_core::futures::future::FutureExt;
+use deno_core::error::JsError;
+use deno_core::json_op_sync;
use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::url::Url;
+use deno_core::JsRuntime;
use deno_core::ModuleSpecifier;
+use deno_core::RuntimeOptions;
use log::debug;
use log::info;
use log::Level;
@@ -44,15 +41,12 @@ use std::collections::HashSet;
use std::fs;
use std::io;
use std::ops::Deref;
-use std::ops::DerefMut;
use std::path::Path;
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 std::task::Poll;
use swc_common::comments::Comment;
use swc_common::comments::CommentKind;
use swc_ecmascript::dep_graph;
@@ -125,71 +119,6 @@ pub struct CompiledModule {
pub name: String,
}
-pub struct CompilerWorker {
- worker: Worker,
- response: Arc<Mutex<Option<String>>>,
-}
-
-impl CompilerWorker {
- pub fn new(
- name: String,
- permissions: Permissions,
- global_state: Arc<GlobalState>,
- ) -> Self {
- let main_module =
- ModuleSpecifier::resolve_url_or_path("./$deno$compiler.ts").unwrap();
- // TODO(bartlomieju): compiler worker shouldn't require any loader/state
- let loader = CliModuleLoader::new(None);
- let mut worker = Worker::new(
- name,
- Some(js::compiler_isolate_init()),
- permissions,
- main_module,
- global_state,
- loader,
- false,
- true,
- );
- let response = Arc::new(Mutex::new(None));
- ops::runtime::init(&mut worker);
- ops::errors::init(&mut worker);
- ops::timers::init(&mut worker);
- ops::compiler::init(&mut worker, response.clone());
- Self { worker, response }
- }
-
- pub fn get_response(&mut self) -> String {
- let mut maybe_response = self.response.lock().unwrap();
- assert!(
- maybe_response.is_some(),
- "Unexpected missing response from TS compiler"
- );
- maybe_response.take().unwrap()
- }
-}
-
-impl Deref for CompilerWorker {
- type Target = Worker;
- fn deref(&self) -> &Self::Target {
- &self.worker
- }
-}
-
-impl DerefMut for CompilerWorker {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.worker
- }
-}
-
-impl Future for CompilerWorker {
- type Output = Result<(), AnyError>;
-
- fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
- let inner = self.get_mut();
- inner.worker.poll_unpin(cx)
- }
-}
-
lazy_static! {
/// Matches the `@deno-types` pragma.
static ref DENO_TYPES_RE: Regex =
@@ -224,24 +153,6 @@ fn warn_ignored_options(
}
}
-/// Create a new worker with snapshot of TS compiler and setup compiler's
-/// runtime.
-fn create_compiler_worker(
- global_state: &Arc<GlobalState>,
- permissions: Permissions,
-) -> CompilerWorker {
- // 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(), permissions, global_state.clone());
- worker
- .execute("globalThis.bootstrapCompilerRuntime()")
- .unwrap();
- worker
-}
-
#[derive(Clone)]
pub enum TargetLib {
Main,
@@ -548,7 +459,6 @@ impl TsCompiler {
global_state: &Arc<GlobalState>,
source_file: &SourceFile,
target: TargetLib,
- permissions: Permissions,
module_graph: &ModuleGraph,
allow_js: bool,
) -> Result<(), AnyError> {
@@ -634,8 +544,7 @@ impl TsCompiler {
let req_msg = j.to_string();
- let json_str =
- execute_in_same_thread(global_state, permissions, req_msg).await?;
+ let json_str = execute_in_tsc(global_state.clone(), req_msg)?;
let compile_response: CompileResponse = serde_json::from_str(&json_str)?;
@@ -754,8 +663,7 @@ impl TsCompiler {
let req_msg = j.to_string();
- let json_str =
- execute_in_same_thread(global_state, permissions, req_msg).await?;
+ let json_str = execute_in_tsc(global_state.clone(), req_msg)?;
let bundle_response: BundleResponse = serde_json::from_str(&json_str)?;
@@ -1047,16 +955,62 @@ impl TsCompiler {
}
}
-async fn execute_in_same_thread(
- global_state: &Arc<GlobalState>,
- permissions: Permissions,
+fn execute_in_tsc(
+ global_state: Arc<GlobalState>,
req: String,
) -> Result<String, AnyError> {
- let mut worker = create_compiler_worker(&global_state, permissions);
+ // TODO(bartlomieju): this is only used in testing, I'm not sure it's
+ // worth keeping around
+ // Count how many times we start the compiler worker.
+ global_state.compiler_starts.fetch_add(1, Ordering::SeqCst);
+
+ let mut js_runtime = JsRuntime::new(RuntimeOptions {
+ startup_snapshot: Some(js::compiler_isolate_init()),
+ ..Default::default()
+ });
+
+ let debug_flag = global_state
+ .flags
+ .log_level
+ .map_or(false, |l| l == log::Level::Debug);
+ let response = Arc::new(Mutex::new(None));
+
+ {
+ js_runtime.register_op(
+ "op_fetch_asset",
+ crate::op_fetch_asset::op_fetch_asset(HashMap::default()),
+ );
+ let res = response.clone();
+ js_runtime.register_op(
+ "op_compiler_respond",
+ json_op_sync(move |_state, args, _bufs| {
+ let mut response_slot = res.lock().unwrap();
+ let replaced_value = response_slot.replace(args.to_string());
+ assert!(
+ replaced_value.is_none(),
+ "op_compiler_respond found unexpected existing compiler output",
+ );
+ Ok(json!({}))
+ }),
+ );
+ }
+
+ let bootstrap_script = format!(
+ "globalThis.bootstrapCompilerRuntime({{ debugFlag: {} }})",
+ debug_flag
+ );
+ js_runtime.execute("<compiler>", &bootstrap_script)?;
+
let script = format!("globalThis.tsCompilerOnMessage({{ data: {} }});", req);
- worker.execute2("<compiler>", &script)?;
- (&mut *worker).await?;
- Ok(worker.get_response())
+ js_runtime.execute("<compiler>", &script)?;
+
+ let maybe_response = response.lock().unwrap().take();
+ assert!(
+ maybe_response.is_some(),
+ "Unexpected missing response from TS compiler"
+ );
+
+ Ok(maybe_response.unwrap())
}
async fn create_runtime_module_graph(
@@ -1099,7 +1053,7 @@ async fn create_runtime_module_graph(
Ok((root_names, module_graph_loader.get_graph()))
}
-fn js_error_to_errbox(error: AnyError) -> AnyError {
+fn extract_js_error(error: AnyError) -> AnyError {
match error.downcast::<JsError>() {
Ok(js_error) => {
let msg = format!("Error in TS compiler:\n{}", js_error);
@@ -1195,10 +1149,8 @@ pub async fn runtime_compile(
let compiler = global_state.ts_compiler.clone();
- let json_str = execute_in_same_thread(global_state, permissions, req_msg)
- .await
- .map_err(js_error_to_errbox)?;
-
+ let json_str =
+ execute_in_tsc(global_state.clone(), req_msg).map_err(extract_js_error)?;
let response: RuntimeCompileResponse = serde_json::from_str(&json_str)?;
if response.diagnostics.0.is_empty() && sources.is_none() {
@@ -1304,9 +1256,8 @@ pub async fn runtime_bundle(
})
.to_string();
- let json_str = execute_in_same_thread(global_state, permissions, req_msg)
- .await
- .map_err(js_error_to_errbox)?;
+ let json_str =
+ execute_in_tsc(global_state.clone(), req_msg).map_err(extract_js_error)?;
let _response: RuntimeBundleResponse = serde_json::from_str(&json_str)?;
// We're returning `Ok()` instead of `Err()` because it's not runtime
// error if there were diagnostics produced; we want to let user handle
@@ -1316,8 +1267,7 @@ pub async fn runtime_bundle(
/// This function is used by `Deno.transpileOnly()` API.
pub async fn runtime_transpile(
- global_state: &Arc<GlobalState>,
- permissions: Permissions,
+ global_state: Arc<GlobalState>,
sources: &HashMap<String, String>,
maybe_options: &Option<String>,
) -> Result<Value, AnyError> {
@@ -1343,9 +1293,8 @@ pub async fn runtime_transpile(
})
.to_string();
- let json_str = execute_in_same_thread(global_state, permissions, req_msg)
- .await
- .map_err(js_error_to_errbox)?;
+ let json_str =
+ execute_in_tsc(global_state, req_msg).map_err(extract_js_error)?;
let v = serde_json::from_str::<Value>(&json_str)
.expect("Error decoding JSON string.");
Ok(v)
@@ -1628,14 +1577,7 @@ mod tests {
.unwrap();
let result = ts_compiler
- .compile(
- &mock_state,
- &out,
- TargetLib::Main,
- Permissions::allow_all(),
- &module_graph,
- false,
- )
+ .compile(&mock_state, &out, TargetLib::Main, &module_graph, false)
.await;
assert!(result.is_ok());
let compiled_file = ts_compiler.get_compiled_module(&out.url).unwrap();