1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-03 04:48:52 -05: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 GitHub
parent 6da958d7ec
commit f0c79a676c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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 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 => {

View file

@ -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)
}

View file

@ -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]