diff options
author | Nayeem Rahman <nayeemrmn99@gmail.com> | 2021-03-04 12:19:47 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-04 13:19:47 +0100 |
commit | 0f2121355f65baa27b530ef286c8b4ca0009fabf (patch) | |
tree | 646725573df762eb09035dd7533e9d4d40280461 /core/runtime.rs | |
parent | af7e02124fbec3cd3b2d17f6fa88682b826e455e (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.rs | 38 |
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(); } |