summaryrefslogtreecommitdiff
path: root/core/runtime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/runtime.rs')
-rw-r--r--core/runtime.rs122
1 files changed, 81 insertions, 41 deletions
diff --git a/core/runtime.rs b/core/runtime.rs
index 4aad2bd76..2c16ddeb8 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -2145,14 +2145,54 @@ impl JsRealm {
#[inline]
pub fn queue_async_op(
- scope: &v8::Isolate,
+ state: Rc<RefCell<OpState>>,
+ scope: &mut v8::HandleScope,
+ deferred: bool,
op: impl Future<Output = (v8::Global<v8::Context>, PromiseId, OpId, OpResult)>
+ 'static,
) {
- let state_rc = JsRuntime::state(scope);
- let mut state = state_rc.borrow_mut();
- state.pending_ops.push(OpCall::eager(op));
- state.have_unpolled_ops = true;
+ match OpCall::eager(op) {
+ // This calls promise.resolve() before the control goes back to userland JS. It works something
+ // along the lines of:
+ //
+ // function opresolve(promiseId, ...) {
+ // getPromise(promiseId).resolve(...);
+ // }
+ // const p = setPromise();
+ // op.op_async(promiseId, ...); // Calls `opresolve`
+ // return p;
+ EagerPollResult::Ready((context, promise_id, op_id, mut resp))
+ if !deferred =>
+ {
+ let args = &[
+ v8::Integer::new(scope, promise_id).into(),
+ resp.to_v8(scope).unwrap(),
+ ];
+
+ let realm = JsRealm::new(context);
+ let js_recv_cb_handle =
+ realm.state(scope).borrow().js_recv_cb.clone().unwrap();
+ state.borrow().tracker.track_async_completed(op_id);
+
+ let tc_scope = &mut v8::TryCatch::new(scope);
+ let js_recv_cb = js_recv_cb_handle.open(tc_scope);
+ let this = v8::undefined(tc_scope).into();
+ js_recv_cb.call(tc_scope, this, args);
+ }
+ EagerPollResult::Ready(op) => {
+ let ready = OpCall::ready(op);
+ let state_rc = JsRuntime::state(scope);
+ let mut state = state_rc.borrow_mut();
+ state.pending_ops.push(ready);
+ state.have_unpolled_ops = true;
+ }
+ EagerPollResult::Pending(op) => {
+ let state_rc = JsRuntime::state(scope);
+ let mut state = state_rc.borrow_mut();
+ state.pending_ops.push(op);
+ state.have_unpolled_ops = true;
+ }
+ }
}
#[cfg(test)]
@@ -2194,7 +2234,7 @@ pub mod tests {
dispatch_count: Arc<AtomicUsize>,
}
- #[op]
+ #[op(deferred)]
async fn op_test(
rc_op_state: Rc<RefCell<OpState>>,
control: u8,
@@ -2256,41 +2296,6 @@ pub mod tests {
}
#[test]
- fn test_dispatch() {
- let (mut runtime, dispatch_count) = setup(Mode::Async);
- runtime
- .execute_script(
- "filename.js",
- r#"
- let control = 42;
- Deno.core.opAsync("op_test", control);
- async function main() {
- Deno.core.opAsync("op_test", control);
- }
- main();
- "#,
- )
- .unwrap();
- assert_eq!(dispatch_count.load(Ordering::Relaxed), 2);
- }
-
- #[test]
- fn test_op_async_promise_id() {
- let (mut runtime, _dispatch_count) = setup(Mode::Async);
- runtime
- .execute_script(
- "filename.js",
- r#"
- const p = Deno.core.opAsync("op_test", 42);
- if (p[Symbol.for("Deno.core.internalPromiseId")] == undefined) {
- throw new Error("missing id on returned promise");
- }
- "#,
- )
- .unwrap();
- }
-
- #[test]
fn test_ref_unref_ops() {
let (mut runtime, _dispatch_count) = setup(Mode::Async);
runtime
@@ -2345,6 +2350,41 @@ pub mod tests {
}
#[test]
+ fn test_dispatch() {
+ let (mut runtime, dispatch_count) = setup(Mode::Async);
+ runtime
+ .execute_script(
+ "filename.js",
+ r#"
+ let control = 42;
+ Deno.core.opAsync("op_test", control);
+ async function main() {
+ Deno.core.opAsync("op_test", control);
+ }
+ main();
+ "#,
+ )
+ .unwrap();
+ assert_eq!(dispatch_count.load(Ordering::Relaxed), 2);
+ }
+
+ #[test]
+ fn test_op_async_promise_id() {
+ let (mut runtime, _dispatch_count) = setup(Mode::Async);
+ runtime
+ .execute_script(
+ "filename.js",
+ r#"
+ const p = Deno.core.opAsync("op_test", 42);
+ if (p[Symbol.for("Deno.core.internalPromiseId")] == undefined) {
+ throw new Error("missing id on returned promise");
+ }
+ "#,
+ )
+ .unwrap();
+ }
+
+ #[test]
fn test_dispatch_no_zero_copy_buf() {
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(false));
runtime