summaryrefslogtreecommitdiff
path: root/core/runtime.rs
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2021-03-04 12:19:47 +0000
committerGitHub <noreply@github.com>2021-03-04 13:19:47 +0100
commit0f2121355f65baa27b530ef286c8b4ca0009fabf (patch)
tree646725573df762eb09035dd7533e9d4d40280461 /core/runtime.rs
parentaf7e02124fbec3cd3b2d17f6fa88682b826e455e (diff)
fix(runtime/web_worker): Don't block self.onmessage with TLA (#9619)
This commit rewrites implementation of "JsRuntime::mod_evaluate". Event loop is no longer polled automatically and users must manually drive event loop forward after calling "mod_evaluate". Co-authored-by: Nayeem Rahman <nayeemrmn99@gmail.com> Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com>
Diffstat (limited to 'core/runtime.rs')
-rw-r--r--core/runtime.rs38
1 files changed, 14 insertions, 24 deletions
diff --git a/core/runtime.rs b/core/runtime.rs
index 595a7733b..66d51eb73 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -853,14 +853,19 @@ impl JsRuntime {
Ok(())
}
+ // TODO(bartlomieju): make it return `ModuleEvaluationFuture`?
/// Evaluates an already instantiated ES module.
///
+ /// Returns a receiver handle that resolves when module promise resolves.
+ /// Implementors must manually call `run_event_loop()` to drive module
+ /// evaluation future.
+ ///
/// `AnyError` can be downcast to a type that exposes additional information
/// about the V8 exception. By default this type is `JsError`, however it may
/// be a different type if `RuntimeOptions::js_error_create_fn` has been set.
///
/// This function panics if module has not been instantiated.
- fn mod_evaluate_inner(
+ pub fn mod_evaluate(
&mut self,
id: ModuleId,
) -> mpsc::Receiver<Result<(), AnyError>> {
@@ -929,24 +934,6 @@ impl JsRuntime {
receiver
}
- pub async fn mod_evaluate(&mut self, id: ModuleId) -> Result<(), AnyError> {
- let mut receiver = self.mod_evaluate_inner(id);
-
- poll_fn(|cx| {
- if let Poll::Ready(maybe_result) = receiver.poll_next_unpin(cx) {
- debug!("received module evaluate {:#?}", maybe_result);
- // If `None` is returned it means that runtime was destroyed before
- // evaluation was complete. This can happen in Web Worker when `self.close()`
- // is called at top level.
- let result = maybe_result.unwrap_or(Ok(()));
- return Poll::Ready(result);
- }
- let _r = self.poll_event_loop(cx)?;
- Poll::Pending
- })
- .await
- }
-
fn dyn_import_error(&mut self, id: ModuleLoadId, err: AnyError) {
let state_rc = Self::state(self.v8_isolate());
let context = self.global_context();
@@ -1140,7 +1127,8 @@ impl JsRuntime {
v8::PromiseState::Fulfilled => {
state.pending_mod_evaluate.take();
scope.perform_microtask_checkpoint();
- sender.try_send(Ok(())).unwrap();
+ // Receiver end might have been already dropped, ignore the result
+ let _ = sender.try_send(Ok(()));
}
v8::PromiseState::Rejected => {
let exception = promise.result(scope);
@@ -1150,7 +1138,8 @@ impl JsRuntime {
let err1 = exception_to_err_result::<()>(scope, exception, false)
.map_err(|err| attach_handle_to_error(scope, err, exception))
.unwrap_err();
- sender.try_send(Err(err1)).unwrap();
+ // Receiver end might have been already dropped, ignore the result
+ let _ = sender.try_send(Err(err1));
}
}
}
@@ -1937,7 +1926,7 @@ pub mod tests {
throw Error("assert");
}
}
-
+
let asyncRecv = 0;
Deno.core.setAsyncHandler(1, (buf) => {
assert(buf.byteLength === 100 * 1024 * 1024);
@@ -2351,7 +2340,7 @@ pub mod tests {
runtime.mod_instantiate(mod_a).unwrap();
assert_eq!(dispatch_count.load(Ordering::Relaxed), 0);
- runtime.mod_evaluate_inner(mod_a);
+ runtime.mod_evaluate(mod_a);
assert_eq!(dispatch_count.load(Ordering::Relaxed), 1);
}
@@ -2594,7 +2583,8 @@ pub mod tests {
)
.unwrap();
- futures::executor::block_on(runtime.mod_evaluate(module_id)).unwrap();
+ runtime.mod_evaluate(module_id);
+ futures::executor::block_on(runtime.run_event_loop()).unwrap();
let _snapshot = runtime.snapshot();
}