summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreu Botella <andreu@andreubotella.com>2023-01-16 08:36:42 -0800
committerGitHub <noreply@github.com>2023-01-16 22:06:42 +0530
commitf0c79a676cc36a5e8f6f5af86d93186d41974518 (patch)
tree61831add9e02b32fbc399b613fe11408c4f79d18
parent6da958d7ec31f2ffd21bb2beb8cc193a62afc55c (diff)
refactor(core): Move `pending_promise_rejections` to `ContextState` (#17447)
This is a requirement before supporting modules in realms.
-rw-r--r--core/bindings.rs16
-rw-r--r--core/ops_builtin_v8.rs20
-rw-r--r--core/runtime.rs68
3 files changed, 65 insertions, 39 deletions
diff --git a/core/bindings.rs b/core/bindings.rs
index 96225e4cd..bf0da18e4 100644
--- a/core/bindings.rs
+++ b/core/bindings.rs
@@ -455,10 +455,12 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) {
let scope = &mut unsafe { v8::CallbackScope::new(&message) };
let context_state_rc = JsRealm::state_from_scope(scope);
+ let mut context_state = context_state_rc.borrow_mut();
+
+ if let Some(js_promise_reject_cb) = context_state.js_promise_reject_cb.clone()
+ {
+ drop(context_state);
- let promise_reject_cb =
- context_state_rc.borrow().js_promise_reject_cb.clone();
- if let Some(js_promise_reject_cb) = promise_reject_cb {
let tc_scope = &mut v8::TryCatch::new(scope);
let undefined: v8::Local<v8::Value> = v8::undefined(tc_scope).into();
let type_ = v8::Integer::new(tc_scope, message.get_event() as i32);
@@ -496,20 +498,20 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) {
}
}
} else {
- let state_rc = JsRuntime::state(scope);
- let mut state = state_rc.borrow_mut();
let promise = message.get_promise();
let promise_global = v8::Global::new(scope, promise);
match message.get_event() {
PromiseRejectWithNoHandler => {
let error = message.get_value().unwrap();
let error_global = v8::Global::new(scope, error);
- state
+ context_state
.pending_promise_rejections
.insert(promise_global, error_global);
}
PromiseHandlerAddedAfterReject => {
- state.pending_promise_rejections.remove(&promise_global);
+ context_state
+ .pending_promise_rejections
+ .remove(&promise_global);
}
PromiseRejectAfterResolved => {}
PromiseResolveAfterResolved => {
diff --git a/core/ops_builtin_v8.rs b/core/ops_builtin_v8.rs
index 5128a056b..225a81901 100644
--- a/core/ops_builtin_v8.rs
+++ b/core/ops_builtin_v8.rs
@@ -864,13 +864,13 @@ fn op_store_pending_promise_rejection<'a>(
promise: serde_v8::Value<'a>,
reason: serde_v8::Value<'a>,
) {
- let state_rc = JsRuntime::state(scope);
- let mut state = state_rc.borrow_mut();
+ let context_state_rc = JsRealm::state_from_scope(scope);
+ let mut context_state = context_state_rc.borrow_mut();
let promise_value =
v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap();
let promise_global = v8::Global::new(scope, promise_value);
let error_global = v8::Global::new(scope, reason.v8_value);
- state
+ context_state
.pending_promise_rejections
.insert(promise_global, error_global);
}
@@ -880,12 +880,14 @@ fn op_remove_pending_promise_rejection<'a>(
scope: &mut v8::HandleScope<'a>,
promise: serde_v8::Value<'a>,
) {
- let state_rc = JsRuntime::state(scope);
- let mut state = state_rc.borrow_mut();
+ let context_state_rc = JsRealm::state_from_scope(scope);
+ let mut context_state = context_state_rc.borrow_mut();
let promise_value =
v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap();
let promise_global = v8::Global::new(scope, promise_value);
- state.pending_promise_rejections.remove(&promise_global);
+ context_state
+ .pending_promise_rejections
+ .remove(&promise_global);
}
#[op(v8)]
@@ -893,12 +895,12 @@ fn op_has_pending_promise_rejection<'a>(
scope: &mut v8::HandleScope<'a>,
promise: serde_v8::Value<'a>,
) -> bool {
- let state_rc = JsRuntime::state(scope);
- let state = state_rc.borrow();
+ let context_state_rc = JsRealm::state_from_scope(scope);
+ let context_state = context_state_rc.borrow();
let promise_value =
v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap();
let promise_global = v8::Global::new(scope, promise_value);
- state
+ context_state
.pending_promise_rejections
.contains_key(&promise_global)
}
diff --git a/core/runtime.rs b/core/runtime.rs
index 9f1dbf12d..bd85e1a88 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -155,6 +155,8 @@ pub(crate) struct ContextState {
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) pending_promise_rejections:
+ HashMap<v8::Global<v8::Promise>, v8::Global<v8::Value>>,
pub(crate) unrefed_ops: HashSet<i32>,
// We don't explicitly re-read this prop but need the slice to live alongside
// the context
@@ -169,8 +171,6 @@ pub struct JsRuntimeState {
pub(crate) js_macrotask_cbs: Vec<v8::Global<v8::Function>>,
pub(crate) js_nexttick_cbs: Vec<v8::Global<v8::Function>>,
pub(crate) has_tick_scheduled: bool,
- pub(crate) pending_promise_rejections:
- HashMap<v8::Global<v8::Promise>, v8::Global<v8::Value>>,
pub(crate) pending_dyn_mod_evaluate: Vec<DynImportModEvaluate>,
pub(crate) pending_mod_evaluate: Option<ModEvaluate>,
/// A counter used to delay our dynamic import deadlock detection by one spin
@@ -384,7 +384,6 @@ impl JsRuntime {
unsafe { std::alloc::alloc(layout) as *mut _ };
let state_rc = Rc::new(RefCell::new(JsRuntimeState {
- pending_promise_rejections: HashMap::new(),
pending_dyn_mod_evaluate: vec![],
pending_mod_evaluate: None,
dyn_module_evaluate_idle_counter: 0,
@@ -1605,6 +1604,7 @@ impl JsRuntime {
&mut self,
id: ModuleId,
) -> oneshot::Receiver<Result<(), Error>> {
+ let global_realm = self.global_realm();
let state_rc = self.state.clone();
let module_map_rc = Self::module_map(self.v8_isolate());
let scope = &mut self.handle_scope();
@@ -1688,7 +1688,11 @@ impl JsRuntime {
.handled_promise_rejections
.contains(&promise_global);
if !pending_rejection_was_already_handled {
- state.pending_promise_rejections.remove(&promise_global);
+ global_realm
+ .state(tc_scope)
+ .borrow_mut()
+ .pending_promise_rejections
+ .remove(&promise_global);
}
}
let promise_global = v8::Global::new(tc_scope, promise);
@@ -2127,26 +2131,14 @@ impl JsRuntime {
}
fn check_promise_rejections(&mut self) -> Result<(), Error> {
- let mut state = self.state.borrow_mut();
-
- if state.pending_promise_rejections.is_empty() {
- return Ok(());
+ let known_realms = self.state.borrow().known_realms.clone();
+ let isolate = self.v8_isolate();
+ for weak_context in known_realms {
+ if let Some(context) = weak_context.to_global(isolate) {
+ JsRealm(context).check_promise_rejections(isolate)?;
+ }
}
-
- let key = {
- state
- .pending_promise_rejections
- .keys()
- .next()
- .unwrap()
- .clone()
- };
- let handle = state.pending_promise_rejections.remove(&key).unwrap();
- drop(state);
-
- let scope = &mut self.handle_scope();
- let exception = v8::Local::new(scope, handle);
- exception_to_err_result(scope, exception, true)
+ Ok(())
}
// Send finished responses to JS
@@ -2497,6 +2489,36 @@ impl JsRealm {
}
// TODO(andreubotella): `mod_evaluate`, `load_main_module`, `load_side_module`
+
+ fn check_promise_rejections(
+ &self,
+ isolate: &mut v8::Isolate,
+ ) -> Result<(), Error> {
+ let context_state_rc = self.state(isolate);
+ let mut context_state = context_state_rc.borrow_mut();
+
+ if context_state.pending_promise_rejections.is_empty() {
+ return Ok(());
+ }
+
+ let key = {
+ context_state
+ .pending_promise_rejections
+ .keys()
+ .next()
+ .unwrap()
+ .clone()
+ };
+ let handle = context_state
+ .pending_promise_rejections
+ .remove(&key)
+ .unwrap();
+ drop(context_state);
+
+ let scope = &mut self.handle_scope(isolate);
+ let exception = v8::Local::new(scope, handle);
+ exception_to_err_result(scope, exception, true)
+ }
}
#[inline]