summaryrefslogtreecommitdiff
path: root/core/runtime.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-10-21 08:24:22 +0530
committerGitHub <noreply@github.com>2022-10-21 08:24:22 +0530
commitc007657cfda4e07ee3070919c0b629f874ba9106 (patch)
treed9cb64b8b2f22f9d5ea1133b40830b0abe32c10b /core/runtime.rs
parent4b6168d5e3a990e7982bcb1a8fb525f1141d8839 (diff)
Revert realms from deno_core (#16366)
This revert has been discussed at length out-of-band (including with @andreubotella). The realms work in impeding ongoing event loop and performance work. We very much want to land realms but it needs to wait until these lower-level refactors are complete. We hope to bring realms back in a couple weeks.
Diffstat (limited to 'core/runtime.rs')
-rw-r--r--core/runtime.rs479
1 files changed, 71 insertions, 408 deletions
diff --git a/core/runtime.rs b/core/runtime.rs
index 60e187af5..c1ef6d1a4 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -47,8 +47,7 @@ use std::task::Context;
use std::task::Poll;
use v8::OwnedIsolate;
-type PendingOpFuture =
- OpCall<(v8::Global<v8::Context>, PromiseId, OpId, OpResult)>;
+type PendingOpFuture = OpCall<(PromiseId, OpId, OpResult)>;
pub enum Snapshot {
Static(&'static [u8]),
@@ -143,24 +142,18 @@ pub type SharedArrayBufferStore =
pub type CompiledWasmModuleStore = CrossIsolateStore<v8::CompiledWasmModule>;
-#[derive(Default)]
-pub(crate) struct ContextState {
- js_recv_cb: Option<v8::Global<v8::Function>>,
- pub(crate) js_build_custom_error_cb: Option<v8::Global<v8::Function>>,
- pub(crate) js_promise_reject_cb: Option<v8::Global<v8::Function>>,
- pub(crate) js_format_exception_cb: Option<v8::Global<v8::Function>>,
- pub(crate) js_wasm_streaming_cb: Option<v8::Global<v8::Function>>,
- pub(crate) unrefed_ops: HashSet<i32>,
-}
-
/// Internal state for JsRuntime which is stored in one of v8::Isolate's
/// embedder slots.
pub(crate) struct JsRuntimeState {
global_realm: Option<JsRealm>,
- known_realms: Vec<v8::Weak<v8::Context>>,
+ pub(crate) js_recv_cb: Option<v8::Global<v8::Function>>,
pub(crate) js_macrotask_cbs: Vec<v8::Global<v8::Function>>,
pub(crate) js_nexttick_cbs: Vec<v8::Global<v8::Function>>,
+ pub(crate) js_promise_reject_cb: Option<v8::Global<v8::Function>>,
+ pub(crate) js_format_exception_cb: Option<v8::Global<v8::Function>>,
+ pub(crate) js_build_custom_error_cb: Option<v8::Global<v8::Function>>,
pub(crate) has_tick_scheduled: bool,
+ pub(crate) js_wasm_streaming_cb: Option<v8::Global<v8::Function>>,
pub(crate) pending_promise_exceptions:
HashMap<v8::Global<v8::Promise>, v8::Global<v8::Value>>,
pub(crate) pending_dyn_mod_evaluate: Vec<DynImportModEvaluate>,
@@ -171,6 +164,7 @@ pub(crate) struct JsRuntimeState {
pub(crate) source_map_getter: Option<Box<dyn SourceMapGetter>>,
pub(crate) source_map_cache: SourceMapCache,
pub(crate) pending_ops: FuturesUnordered<PendingOpFuture>,
+ pub(crate) unrefed_ops: HashSet<i32>,
pub(crate) have_unpolled_ops: bool,
pub(crate) op_state: Rc<RefCell<OpState>>,
#[allow(dead_code)]
@@ -408,20 +402,24 @@ impl JsRuntime {
.module_loader
.unwrap_or_else(|| Rc::new(NoopModuleLoader));
- let known_realms = vec![v8::Weak::new(&mut isolate, &global_context)];
let state_rc = Rc::new(RefCell::new(JsRuntimeState {
- global_realm: Some(JsRealm(global_context.clone())),
- known_realms,
+ global_realm: Some(JsRealm(global_context)),
pending_promise_exceptions: HashMap::new(),
pending_dyn_mod_evaluate: vec![],
pending_mod_evaluate: None,
dyn_module_evaluate_idle_counter: 0,
+ js_recv_cb: None,
js_macrotask_cbs: vec![],
js_nexttick_cbs: vec![],
+ js_promise_reject_cb: None,
+ js_format_exception_cb: None,
+ js_build_custom_error_cb: None,
has_tick_scheduled: false,
+ js_wasm_streaming_cb: None,
source_map_getter: options.source_map_getter,
source_map_cache: Default::default(),
pending_ops: FuturesUnordered::new(),
+ unrefed_ops: HashSet::new(),
shared_array_buffer_store: options.shared_array_buffer_store,
compiled_wasm_module_store: options.compiled_wasm_module_store,
op_state: op_state.clone(),
@@ -436,10 +434,6 @@ impl JsRuntime {
Rc::into_raw(state_rc) as *mut c_void,
);
- global_context
- .open(&mut isolate)
- .set_slot(&mut isolate, Rc::<RefCell<ContextState>>::default());
-
let module_map_rc = Rc::new(RefCell::new(ModuleMap::new(loader, op_state)));
isolate.set_data(
Self::MODULE_MAP_DATA_OFFSET,
@@ -464,8 +458,7 @@ impl JsRuntime {
js_runtime.init_extension_js(&realm).unwrap();
}
// Init callbacks (opresolve)
- let global_realm = js_runtime.global_realm();
- js_runtime.init_cbs(&global_realm);
+ js_runtime.init_cbs();
js_runtime
}
@@ -528,22 +521,12 @@ impl JsRuntime {
&Self::state(self.v8_isolate()).borrow().op_ctxs,
self.built_from_snapshot,
);
- context.set_slot(scope, Rc::<RefCell<ContextState>>::default());
-
- Self::state(scope)
- .borrow_mut()
- .known_realms
- .push(v8::Weak::new(scope, &context));
-
JsRealm::new(v8::Global::new(scope, context))
};
if !self.built_from_snapshot {
self.init_extension_js(&realm)?;
}
-
- self.init_cbs(&realm);
-
Ok(realm)
}
@@ -712,24 +695,20 @@ impl JsRuntime {
}
/// Grabs a reference to core.js' opresolve & syncOpsCache()
- fn init_cbs(&mut self, realm: &JsRealm) {
- let (recv_cb, build_custom_error_cb) = {
- let scope = &mut realm.handle_scope(self.v8_isolate());
- let recv_cb =
- Self::grab_global::<v8::Function>(scope, "Deno.core.opresolve")
- .expect("Deno.core.opresolve is undefined in the realm");
- let recv_cb = v8::Global::new(scope, recv_cb);
- let build_custom_error_cb =
- Self::grab_global::<v8::Function>(scope, "Deno.core.buildCustomError")
- .expect("Deno.core.buildCustomError is undefined in the realm");
- let build_custom_error_cb = v8::Global::new(scope, build_custom_error_cb);
- (recv_cb, build_custom_error_cb)
- };
- // Put global handle in callback state
- let state = realm.state(self.v8_isolate());
- state.borrow_mut().js_recv_cb.replace(recv_cb);
+ fn init_cbs(&mut self) {
+ let scope = &mut self.handle_scope();
+ let recv_cb =
+ Self::grab_global::<v8::Function>(scope, "Deno.core.opresolve").unwrap();
+ let recv_cb = v8::Global::new(scope, recv_cb);
+ let build_custom_error_cb =
+ Self::grab_global::<v8::Function>(scope, "Deno.core.buildCustomError")
+ .expect("Deno.core.buildCustomError is undefined in the realm");
+ let build_custom_error_cb = v8::Global::new(scope, build_custom_error_cb);
+ // Put global handles in state
+ let state_rc = JsRuntime::state(scope);
+ let mut state = state_rc.borrow_mut();
+ state.js_recv_cb.replace(recv_cb);
state
- .borrow_mut()
.js_build_custom_error_cb
.replace(build_custom_error_cb);
}
@@ -794,25 +773,14 @@ impl JsRuntime {
let v8_isolate = self.v8_isolate();
Self::drop_state_and_module_map(v8_isolate);
}
-
// Drop other v8::Global handles before snapshotting
{
- for weak_context in &state.borrow().known_realms {
- if let Some(context) = weak_context.to_global(self.v8_isolate()) {
- let realm = JsRealm::new(context.clone());
- let realm_state = realm.state(self.v8_isolate());
- std::mem::take(&mut realm_state.borrow_mut().js_recv_cb);
- std::mem::take(
- &mut realm_state.borrow_mut().js_build_custom_error_cb,
- );
- context
- .open(self.v8_isolate())
- .clear_all_slots(self.v8_isolate());
- }
- }
let mut state = state.borrow_mut();
- state.known_realms.clear();
- // Free up additional global handles before creating the snapshot
+ std::mem::take(&mut state.js_recv_cb);
+ std::mem::take(&mut state.js_promise_reject_cb);
+ std::mem::take(&mut state.js_format_exception_cb);
+ std::mem::take(&mut state.js_wasm_streaming_cb);
+ std::mem::take(&mut state.js_build_custom_error_cb);
state.js_macrotask_cbs.clear();
state.js_nexttick_cbs.clear();
}
@@ -1125,16 +1093,8 @@ Pending dynamic modules:\n".to_string();
let state = state_rc.borrow_mut();
let module_map = module_map_rc.borrow();
- let mut num_unrefed_ops = 0;
- for weak_context in &state.known_realms {
- if let Some(context) = weak_context.to_global(isolate) {
- let realm = JsRealm::new(context);
- num_unrefed_ops += realm.state(isolate).borrow().unrefed_ops.len();
- }
- }
-
EventLoopPendingState {
- has_pending_refed_ops: state.pending_ops.len() > num_unrefed_ops,
+ has_pending_refed_ops: state.pending_ops.len() > state.unrefed_ops.len(),
has_pending_dyn_imports: module_map.has_pending_dynamic_imports(),
has_pending_dyn_module_evaluation: !state
.pending_dyn_mod_evaluate
@@ -1903,30 +1863,17 @@ impl JsRuntime {
fn resolve_async_ops(&mut self, cx: &mut Context) -> Result<(), Error> {
let state_rc = Self::state(self.v8_isolate());
- // We keep a list of promise IDs and OpResults per realm. Since v8::Context
- // isn't hashable, `results_per_realm` is a vector of (context, list) tuples
- type ResultList = Vec<(i32, OpResult)>;
- let mut results_per_realm: Vec<(v8::Global<v8::Context>, ResultList)> = {
- let known_realms = &mut state_rc.borrow_mut().known_realms;
- let mut results = Vec::with_capacity(known_realms.len());
-
- // Avoid calling the method multiple times
- let isolate = self.v8_isolate();
-
- // Remove GC'd realms from `known_realms` at the same time as we populate
- // `results` with those that are still alive.
- known_realms.retain(|weak| {
- if !weak.is_empty() {
- let context = weak.to_global(isolate).unwrap();
- results.push((context, vec![]));
- true
- } else {
- false
- }
- });
+ let js_recv_cb_handle = state_rc.borrow().js_recv_cb.clone().unwrap();
+ let scope = &mut self.handle_scope();
- results
- };
+ // We return async responses to JS in unbounded batches (may change),
+ // each batch is a flat vector of tuples:
+ // `[promise_id1, op_result1, promise_id2, op_result2, ...]`
+ // promise_id is a simple integer, op_result is an ops::OpResult
+ // which contains a value OR an error, encoded as a tuple.
+ // This batch is received in JS via the special `arguments` variable
+ // and then each tuple is used to resolve or reject promises
+ let mut args: Vec<v8::Local<v8::Value>> = vec![];
// Now handle actual ops.
{
@@ -1935,47 +1882,10 @@ impl JsRuntime {
while let Poll::Ready(Some(item)) = state.pending_ops.poll_next_unpin(cx)
{
- let (context, promise_id, op_id, resp) = item;
+ let (promise_id, op_id, mut resp) = item;
+ state.unrefed_ops.remove(&promise_id);
state.op_state.borrow().tracker.track_async_completed(op_id);
- for (context2, results) in results_per_realm.iter_mut() {
- if context == *context2 {
- results.push((promise_id, resp));
- break;
- }
- }
- JsRealm::new(context)
- .state(self.v8_isolate())
- .borrow_mut()
- .unrefed_ops
- .remove(&promise_id);
- }
- }
-
- for (context, results) in results_per_realm {
- if results.is_empty() {
- continue;
- }
-
- let realm = JsRealm::new(context);
- let js_recv_cb_handle = realm
- .state(self.v8_isolate())
- .borrow()
- .js_recv_cb
- .clone()
- .unwrap();
- let scope = &mut realm.handle_scope(self.v8_isolate());
-
- // We return async responses to JS in unbounded batches (may change),
- // each batch is a flat vector of tuples:
- // `[promise_id1, op_result1, promise_id2, op_result2, ...]`
- // promise_id is a simple integer, op_result is an ops::OpResult
- // which contains a value OR an error, encoded as a tuple.
- // This batch is received in JS via the special `arguments` variable
- // and then each tuple is used to resolve or reject promises
- let mut args = vec![];
-
- for (promise_id, mut resp) in results.into_iter() {
- args.push(v8::Integer::new(scope, promise_id).into());
+ args.push(v8::Integer::new(scope, promise_id as i32).into());
args.push(match resp.to_v8(scope) {
Ok(v) => v,
Err(e) => OpResult::Err(OpError::new(&|_| "TypeError", e.into()))
@@ -1983,18 +1893,21 @@ impl JsRuntime {
.unwrap(),
});
}
+ }
- 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.as_slice());
-
- if let Some(exception) = tc_scope.exception() {
- return exception_to_err_result(tc_scope, exception, false);
- }
+ if args.is_empty() {
+ return Ok(());
}
- Ok(())
+ 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.as_slice());
+
+ match tc_scope.exception() {
+ None => Ok(()),
+ Some(exception) => exception_to_err_result(tc_scope, exception, false),
+ }
}
fn drain_macrotasks(&mut self) -> Result<(), Error> {
@@ -2108,28 +2021,6 @@ impl JsRealm {
&self.0
}
- pub(crate) fn state(
- &self,
- isolate: &mut v8::Isolate,
- ) -> Rc<RefCell<ContextState>> {
- self
- .context()
- .open(isolate)
- .get_slot::<Rc<RefCell<ContextState>>>(isolate)
- .unwrap()
- .clone()
- }
-
- pub(crate) fn state_from_scope(
- scope: &mut v8::HandleScope,
- ) -> Rc<RefCell<ContextState>> {
- let context = scope.get_current_context();
- context
- .get_slot::<Rc<RefCell<ContextState>>>(scope)
- .unwrap()
- .clone()
- }
-
pub fn handle_scope<'s>(
&self,
isolate: &'s mut v8::Isolate,
@@ -2200,8 +2091,7 @@ pub fn queue_async_op(
state: Rc<RefCell<OpState>>,
scope: &mut v8::HandleScope,
deferred: bool,
- op: impl Future<Output = (v8::Global<v8::Context>, PromiseId, OpId, OpResult)>
- + 'static,
+ op: impl Future<Output = (PromiseId, OpId, OpResult)> + 'static,
) {
match OpCall::eager(op) {
// This calls promise.resolve() before the control goes back to userland JS. It works something
@@ -2213,17 +2103,14 @@ pub fn queue_async_op(
// const p = setPromise();
// op.op_async(promiseId, ...); // Calls `opresolve`
// return p;
- EagerPollResult::Ready((context, promise_id, op_id, mut resp))
- if !deferred =>
- {
+ EagerPollResult::Ready((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();
+ JsRuntime::state(scope).borrow().js_recv_cb.clone().unwrap();
state.borrow().tracker.track_async_completed(op_id);
let tc_scope = &mut v8::TryCatch::new(scope);
@@ -2361,11 +2248,11 @@ pub mod tests {
)
.unwrap();
{
- let realm = runtime.global_realm();
let isolate = runtime.v8_isolate();
let state_rc = JsRuntime::state(isolate);
- assert_eq!(state_rc.borrow().pending_ops.len(), 2);
- assert_eq!(realm.state(isolate).borrow().unrefed_ops.len(), 0);
+ let state = state_rc.borrow();
+ assert_eq!(state.pending_ops.len(), 2);
+ assert_eq!(state.unrefed_ops.len(), 0);
}
runtime
.execute_script(
@@ -2377,11 +2264,11 @@ pub mod tests {
)
.unwrap();
{
- let realm = runtime.global_realm();
let isolate = runtime.v8_isolate();
let state_rc = JsRuntime::state(isolate);
- assert_eq!(state_rc.borrow().pending_ops.len(), 2);
- assert_eq!(realm.state(isolate).borrow().unrefed_ops.len(), 2);
+ let state = state_rc.borrow();
+ assert_eq!(state.pending_ops.len(), 2);
+ assert_eq!(state.unrefed_ops.len(), 2);
}
runtime
.execute_script(
@@ -2393,11 +2280,11 @@ pub mod tests {
)
.unwrap();
{
- let realm = runtime.global_realm();
let isolate = runtime.v8_isolate();
let state_rc = JsRuntime::state(isolate);
- assert_eq!(state_rc.borrow().pending_ops.len(), 2);
- assert_eq!(realm.state(isolate).borrow().unrefed_ops.len(), 0);
+ let state = state_rc.borrow();
+ assert_eq!(state.pending_ops.len(), 2);
+ assert_eq!(state.unrefed_ops.len(), 0);
}
}
@@ -3624,54 +3511,6 @@ Deno.core.opAsync('op_async_serialize_object_with_numbers_as_keys', {
}
#[tokio::test]
- async fn test_set_promise_reject_callback_realms() {
- let mut runtime = JsRuntime::new(RuntimeOptions::default());
- let global_realm = runtime.global_realm();
- let realm1 = runtime.create_realm().unwrap();
- let realm2 = runtime.create_realm().unwrap();
-
- let realm_expectations = &[
- (&global_realm, "global_realm", 42),
- (&realm1, "realm1", 140),
- (&realm2, "realm2", 720),
- ];
-
- // Set up promise reject callbacks.
- for (realm, realm_name, number) in realm_expectations {
- realm
- .execute_script(
- runtime.v8_isolate(),
- "",
- &format!(
- r#"
- globalThis.rejectValue = undefined;
- Deno.core.setPromiseRejectCallback((_type, _promise, reason) => {{
- globalThis.rejectValue = `{realm_name}/${{reason}}`;
- }});
- Deno.core.opAsync("op_void_async").then(() => Promise.reject({number}));
- "#,
- realm_name=realm_name,
- number=number
- ),
- )
- .unwrap();
- }
-
- runtime.run_event_loop(false).await.unwrap();
-
- for (realm, realm_name, number) in realm_expectations {
- let reject_value = realm
- .execute_script(runtime.v8_isolate(), "", "globalThis.rejectValue")
- .unwrap();
- let scope = &mut realm.handle_scope(runtime.v8_isolate());
- let reject_value = v8::Local::new(scope, reject_value);
- assert!(reject_value.is_string());
- let reject_value_string = reject_value.to_rust_string_lossy(scope);
- assert_eq!(reject_value_string, format!("{}/{}", realm_name, number));
- }
- }
-
- #[tokio::test]
async fn test_set_promise_reject_callback_top_level_await() {
static PROMISE_REJECT: AtomicUsize = AtomicUsize::new(0);
@@ -3990,180 +3829,4 @@ Deno.core.opAsync('op_async_serialize_object_with_numbers_as_keys', {
let scope = &mut realm.handle_scope(runtime.v8_isolate());
assert_eq!(ret, serde_v8::to_v8(scope, "Test").unwrap());
}
-
- #[test]
- fn js_realm_sync_ops() {
- // Test that returning a ZeroCopyBuf and throwing an exception from a sync
- // op result in objects with prototypes from the right realm. Note that we
- // don't test the result of returning structs, because they will be
- // serialized to objects with null prototype.
-
- #[op]
- fn op_test(fail: bool) -> Result<ZeroCopyBuf, Error> {
- if !fail {
- Ok(ZeroCopyBuf::empty())
- } else {
- Err(crate::error::type_error("Test"))
- }
- }
-
- let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![Extension::builder().ops(vec![op_test::decl()]).build()],
- get_error_class_fn: Some(&|error| {
- crate::error::get_custom_error_class(error).unwrap()
- }),
- ..Default::default()
- });
- let new_realm = runtime.create_realm().unwrap();
-
- // Test in both realms
- for realm in [runtime.global_realm(), new_realm].into_iter() {
- let ret = realm
- .execute_script(
- runtime.v8_isolate(),
- "",
- r#"
- const buf = Deno.core.ops.op_test(false);
- let err;
- try {
- Deno.core.ops.op_test(true);
- } catch(e) {
- err = e;
- }
- buf instanceof Uint8Array && buf.byteLength === 0 &&
- err instanceof TypeError && err.message === "Test"
- "#,
- )
- .unwrap();
- assert!(ret.open(runtime.v8_isolate()).is_true());
- }
- }
-
- #[tokio::test]
- async fn js_realm_async_ops() {
- // Test that returning a ZeroCopyBuf and throwing an exception from a async
- // op result in objects with prototypes from the right realm. Note that we
- // don't test the result of returning structs, because they will be
- // serialized to objects with null prototype.
-
- #[op]
- async fn op_test(fail: bool) -> Result<ZeroCopyBuf, Error> {
- if !fail {
- Ok(ZeroCopyBuf::empty())
- } else {
- Err(crate::error::type_error("Test"))
- }
- }
-
- let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![Extension::builder().ops(vec![op_test::decl()]).build()],
- get_error_class_fn: Some(&|error| {
- crate::error::get_custom_error_class(error).unwrap()
- }),
- ..Default::default()
- });
-
- let global_realm = runtime.global_realm();
- let new_realm = runtime.create_realm().unwrap();
-
- let mut rets = vec![];
-
- // Test in both realms
- for realm in [global_realm, new_realm].into_iter() {
- let ret = realm
- .execute_script(
- runtime.v8_isolate(),
- "",
- r#"
- (async function () {
- const buf = await Deno.core.opAsync("op_test", false);
- let err;
- try {
- await Deno.core.opAsync("op_test", true);
- } catch(e) {
- err = e;
- }
- return buf instanceof Uint8Array && buf.byteLength === 0 &&
- err instanceof TypeError && err.message === "Test" ;
- })();
- "#,
- )
- .unwrap();
- rets.push((realm, ret));
- }
-
- runtime.run_event_loop(false).await.unwrap();
-
- for ret in rets {
- let scope = &mut ret.0.handle_scope(runtime.v8_isolate());
- let value = v8::Local::new(scope, ret.1);
- let promise = v8::Local::<v8::Promise>::try_from(value).unwrap();
- let result = promise.result(scope);
-
- assert!(result.is_boolean() && result.is_true());
- }
- }
-
- #[tokio::test]
- async fn js_realm_ref_unref_ops() {
- run_in_task(|cx| {
- // Never resolves.
- #[op]
- async fn op_pending() {
- futures::future::pending().await
- }
-
- let mut runtime = JsRuntime::new(RuntimeOptions {
- extensions: vec![Extension::builder()
- .ops(vec![op_pending::decl()])
- .build()],
- ..Default::default()
- });
- let main_realm = runtime.global_realm();
- let other_realm = runtime.create_realm().unwrap();
-
- main_realm
- .execute_script(
- runtime.v8_isolate(),
- "",
- "var promise = Deno.core.opAsync('op_pending');",
- )
- .unwrap();
- other_realm
- .execute_script(
- runtime.v8_isolate(),
- "",
- "var promise = Deno.core.opAsync('op_pending');",
- )
- .unwrap();
- assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
-
- main_realm
- .execute_script(
- runtime.v8_isolate(),
- "",
- r#"
- let promiseIdSymbol = Symbol.for("Deno.core.internalPromiseId");
- Deno.core.ops.op_unref_op(promise[promiseIdSymbol]);
- "#,
- )
- .unwrap();
- assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
-
- other_realm
- .execute_script(
- runtime.v8_isolate(),
- "",
- r#"
- let promiseIdSymbol = Symbol.for("Deno.core.internalPromiseId");
- Deno.core.ops.op_unref_op(promise[promiseIdSymbol]);
- "#,
- )
- .unwrap();
- assert!(matches!(
- runtime.poll_event_loop(cx, false),
- Poll::Ready(Ok(()))
- ));
- });
- }
}