0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-10 06:07:03 -04:00

refactor(core): Move pending_promise_rejections to ContextState (#17447)

This is a requirement before supporting modules in realms.
This commit is contained in:
Andreu Botella 2023-01-16 08:36:42 -08:00 committed by Bartek Iwańczuk
parent 566e30c29d
commit 3b03fb822d
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
3 changed files with 65 additions and 39 deletions

View file

@ -455,10 +455,12 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) {
let scope = &mut unsafe { v8::CallbackScope::new(&message) }; let scope = &mut unsafe { v8::CallbackScope::new(&message) };
let context_state_rc = JsRealm::state_from_scope(scope); 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 tc_scope = &mut v8::TryCatch::new(scope);
let undefined: v8::Local<v8::Value> = v8::undefined(tc_scope).into(); let undefined: v8::Local<v8::Value> = v8::undefined(tc_scope).into();
let type_ = v8::Integer::new(tc_scope, message.get_event() as i32); 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 { } else {
let state_rc = JsRuntime::state(scope);
let mut state = state_rc.borrow_mut();
let promise = message.get_promise(); let promise = message.get_promise();
let promise_global = v8::Global::new(scope, promise); let promise_global = v8::Global::new(scope, promise);
match message.get_event() { match message.get_event() {
PromiseRejectWithNoHandler => { PromiseRejectWithNoHandler => {
let error = message.get_value().unwrap(); let error = message.get_value().unwrap();
let error_global = v8::Global::new(scope, error); let error_global = v8::Global::new(scope, error);
state context_state
.pending_promise_rejections .pending_promise_rejections
.insert(promise_global, error_global); .insert(promise_global, error_global);
} }
PromiseHandlerAddedAfterReject => { PromiseHandlerAddedAfterReject => {
state.pending_promise_rejections.remove(&promise_global); context_state
.pending_promise_rejections
.remove(&promise_global);
} }
PromiseRejectAfterResolved => {} PromiseRejectAfterResolved => {}
PromiseResolveAfterResolved => { PromiseResolveAfterResolved => {

View file

@ -864,13 +864,13 @@ fn op_store_pending_promise_rejection<'a>(
promise: serde_v8::Value<'a>, promise: serde_v8::Value<'a>,
reason: serde_v8::Value<'a>, reason: serde_v8::Value<'a>,
) { ) {
let state_rc = JsRuntime::state(scope); let context_state_rc = JsRealm::state_from_scope(scope);
let mut state = state_rc.borrow_mut(); let mut context_state = context_state_rc.borrow_mut();
let promise_value = let promise_value =
v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap(); v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap();
let promise_global = v8::Global::new(scope, promise_value); let promise_global = v8::Global::new(scope, promise_value);
let error_global = v8::Global::new(scope, reason.v8_value); let error_global = v8::Global::new(scope, reason.v8_value);
state context_state
.pending_promise_rejections .pending_promise_rejections
.insert(promise_global, error_global); .insert(promise_global, error_global);
} }
@ -880,12 +880,14 @@ fn op_remove_pending_promise_rejection<'a>(
scope: &mut v8::HandleScope<'a>, scope: &mut v8::HandleScope<'a>,
promise: serde_v8::Value<'a>, promise: serde_v8::Value<'a>,
) { ) {
let state_rc = JsRuntime::state(scope); let context_state_rc = JsRealm::state_from_scope(scope);
let mut state = state_rc.borrow_mut(); let mut context_state = context_state_rc.borrow_mut();
let promise_value = let promise_value =
v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap(); v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap();
let promise_global = v8::Global::new(scope, promise_value); 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)] #[op(v8)]
@ -893,12 +895,12 @@ fn op_has_pending_promise_rejection<'a>(
scope: &mut v8::HandleScope<'a>, scope: &mut v8::HandleScope<'a>,
promise: serde_v8::Value<'a>, promise: serde_v8::Value<'a>,
) -> bool { ) -> bool {
let state_rc = JsRuntime::state(scope); let context_state_rc = JsRealm::state_from_scope(scope);
let state = state_rc.borrow(); let context_state = context_state_rc.borrow();
let promise_value = let promise_value =
v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap(); v8::Local::<v8::Promise>::try_from(promise.v8_value).unwrap();
let promise_global = v8::Global::new(scope, promise_value); let promise_global = v8::Global::new(scope, promise_value);
state context_state
.pending_promise_rejections .pending_promise_rejections
.contains_key(&promise_global) .contains_key(&promise_global)
} }

View file

@ -155,6 +155,8 @@ pub(crate) struct ContextState {
pub(crate) js_promise_reject_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_format_exception_cb: Option<v8::Global<v8::Function>>,
pub(crate) js_wasm_streaming_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>, pub(crate) unrefed_ops: HashSet<i32>,
// We don't explicitly re-read this prop but need the slice to live alongside // We don't explicitly re-read this prop but need the slice to live alongside
// the context // the context
@ -169,8 +171,6 @@ pub struct JsRuntimeState {
pub(crate) js_macrotask_cbs: Vec<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_nexttick_cbs: Vec<v8::Global<v8::Function>>,
pub(crate) has_tick_scheduled: bool, 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_dyn_mod_evaluate: Vec<DynImportModEvaluate>,
pub(crate) pending_mod_evaluate: Option<ModEvaluate>, pub(crate) pending_mod_evaluate: Option<ModEvaluate>,
/// A counter used to delay our dynamic import deadlock detection by one spin /// 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 _ }; unsafe { std::alloc::alloc(layout) as *mut _ };
let state_rc = Rc::new(RefCell::new(JsRuntimeState { let state_rc = Rc::new(RefCell::new(JsRuntimeState {
pending_promise_rejections: HashMap::new(),
pending_dyn_mod_evaluate: vec![], pending_dyn_mod_evaluate: vec![],
pending_mod_evaluate: None, pending_mod_evaluate: None,
dyn_module_evaluate_idle_counter: 0, dyn_module_evaluate_idle_counter: 0,
@ -1605,6 +1604,7 @@ impl JsRuntime {
&mut self, &mut self,
id: ModuleId, id: ModuleId,
) -> oneshot::Receiver<Result<(), Error>> { ) -> oneshot::Receiver<Result<(), Error>> {
let global_realm = self.global_realm();
let state_rc = self.state.clone(); let state_rc = self.state.clone();
let module_map_rc = Self::module_map(self.v8_isolate()); let module_map_rc = Self::module_map(self.v8_isolate());
let scope = &mut self.handle_scope(); let scope = &mut self.handle_scope();
@ -1688,7 +1688,11 @@ impl JsRuntime {
.handled_promise_rejections .handled_promise_rejections
.contains(&promise_global); .contains(&promise_global);
if !pending_rejection_was_already_handled { 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); let promise_global = v8::Global::new(tc_scope, promise);
@ -2127,26 +2131,14 @@ impl JsRuntime {
} }
fn check_promise_rejections(&mut self) -> Result<(), Error> { fn check_promise_rejections(&mut self) -> Result<(), Error> {
let mut state = self.state.borrow_mut(); let known_realms = self.state.borrow().known_realms.clone();
let isolate = self.v8_isolate();
if state.pending_promise_rejections.is_empty() { for weak_context in known_realms {
return Ok(()); if let Some(context) = weak_context.to_global(isolate) {
JsRealm(context).check_promise_rejections(isolate)?;
}
} }
Ok(())
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)
} }
// Send finished responses to JS // Send finished responses to JS
@ -2497,6 +2489,36 @@ impl JsRealm {
} }
// TODO(andreubotella): `mod_evaluate`, `load_main_module`, `load_side_module` // 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] #[inline]