summaryrefslogtreecommitdiff
path: root/cli/ops.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/ops.rs')
-rw-r--r--cli/ops.rs65
1 files changed, 41 insertions, 24 deletions
diff --git a/cli/ops.rs b/cli/ops.rs
index eeb6a10c7..1f208bbe2 100644
--- a/cli/ops.rs
+++ b/cli/ops.rs
@@ -163,6 +163,14 @@ pub fn dispatch_all_legacy(
);
if base.sync() {
+ // TODO(ry) This is not correct! If the sync op is not actually synchronous
+ // (like in the case of op_fetch_module_meta_data) this wait() will block
+ // a thread in the Tokio runtime. Depending on the size of the runtime's
+ // thread pool, this may result in a dead lock!
+ //
+ // The solution is that ops should return an Op directly. Op::Sync contains
+ // the result value, so if its returned directly from the OpCreator, we
+ // know it has actually be evaluated synchronously.
Op::Sync(fut.wait().unwrap())
} else {
Op::Async(fut)
@@ -455,30 +463,39 @@ fn op_fetch_module_meta_data(
let use_cache = !state.flags.reload;
let no_fetch = state.flags.no_fetch;
- Box::new(futures::future::result(|| -> OpResult {
- let builder = &mut FlatBufferBuilder::new();
- // TODO(ry) Use fetch_module_meta_data_async.
- let out = state
- .dir
- .fetch_module_meta_data(specifier, referrer, use_cache, no_fetch)?;
- let data_off = builder.create_vector(out.source_code.as_slice());
- let msg_args = msg::FetchModuleMetaDataResArgs {
- module_name: Some(builder.create_string(&out.module_name)),
- filename: Some(builder.create_string(&out.filename)),
- media_type: out.media_type,
- data: Some(data_off),
- };
- let inner = msg::FetchModuleMetaDataRes::create(builder, &msg_args);
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::FetchModuleMetaDataRes,
- ..Default::default()
- },
- ))
- }()))
+ let fut = state
+ .dir
+ .fetch_module_meta_data_async(specifier, referrer, use_cache, no_fetch)
+ .and_then(move |out| {
+ let builder = &mut FlatBufferBuilder::new();
+ let data_off = builder.create_vector(out.source_code.as_slice());
+ let msg_args = msg::FetchModuleMetaDataResArgs {
+ module_name: Some(builder.create_string(&out.module_name)),
+ filename: Some(builder.create_string(&out.filename)),
+ media_type: out.media_type,
+ data: Some(data_off),
+ };
+ let inner = msg::FetchModuleMetaDataRes::create(builder, &msg_args);
+ Ok(serialize_response(
+ cmd_id,
+ builder,
+ msg::BaseArgs {
+ inner: Some(inner.as_union_value()),
+ inner_type: msg::Any::FetchModuleMetaDataRes,
+ ..Default::default()
+ },
+ ))
+ });
+
+ // Unfortunately TypeScript's CompilerHost interface does not leave room for
+ // asynchronous source code fetching. This complicates things greatly and
+ // requires us to use tokio_util::block_on() below.
+ assert!(base.sync());
+
+ // WARNING: Here we use tokio_util::block_on() which starts a new Tokio
+ // runtime for executing the future. This is so we don't inadvernently run
+ // out of threads in the main runtime.
+ Box::new(futures::future::result(tokio_util::block_on(fut)))
}
/// Retrieve any relevant compiler configuration.