mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-01-12 00:54:15 -05:00
Add Isolate::set_promise_hook() (#496)
This commit is contained in:
parent
ea0c7c9383
commit
57390ec4ee
4 changed files with 90 additions and 0 deletions
|
@ -188,6 +188,10 @@ void v8__Isolate__RequestInterrupt(v8::Isolate* isolate,
|
||||||
isolate->RequestInterrupt(callback, data);
|
isolate->RequestInterrupt(callback, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void v8__Isolate__SetPromiseHook(v8::Isolate* isolate, v8::PromiseHook hook) {
|
||||||
|
isolate->SetPromiseHook(hook);
|
||||||
|
}
|
||||||
|
|
||||||
void v8__Isolate__SetPromiseRejectCallback(v8::Isolate* isolate,
|
void v8__Isolate__SetPromiseRejectCallback(v8::Isolate* isolate,
|
||||||
v8::PromiseRejectCallback callback) {
|
v8::PromiseRejectCallback callback) {
|
||||||
isolate->SetPromiseRejectCallback(callback);
|
isolate->SetPromiseRejectCallback(callback);
|
||||||
|
|
|
@ -42,8 +42,34 @@ pub enum MicrotasksPolicy {
|
||||||
Auto = 2,
|
Auto = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PromiseHook with type Init is called when a new promise is
|
||||||
|
/// created. When a new promise is created as part of the chain in the
|
||||||
|
/// case of Promise.then or in the intermediate promises created by
|
||||||
|
/// Promise.{race, all}/AsyncFunctionAwait, we pass the parent promise
|
||||||
|
/// otherwise we pass undefined.
|
||||||
|
///
|
||||||
|
/// PromiseHook with type Resolve is called at the beginning of
|
||||||
|
/// resolve or reject function defined by CreateResolvingFunctions.
|
||||||
|
///
|
||||||
|
/// PromiseHook with type Before is called at the beginning of the
|
||||||
|
/// PromiseReactionJob.
|
||||||
|
///
|
||||||
|
/// PromiseHook with type After is called right at the end of the
|
||||||
|
/// PromiseReactionJob.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum PromiseHookType {
|
||||||
|
Init,
|
||||||
|
Resolve,
|
||||||
|
Before,
|
||||||
|
After,
|
||||||
|
}
|
||||||
|
|
||||||
pub type MessageCallback = extern "C" fn(Local<Message>, Local<Value>);
|
pub type MessageCallback = extern "C" fn(Local<Message>, Local<Value>);
|
||||||
|
|
||||||
|
pub type PromiseHook =
|
||||||
|
extern "C" fn(PromiseHookType, Local<Promise>, Local<Value>);
|
||||||
|
|
||||||
pub type PromiseRejectCallback = extern "C" fn(PromiseRejectMessage);
|
pub type PromiseRejectCallback = extern "C" fn(PromiseRejectMessage);
|
||||||
|
|
||||||
/// HostInitializeImportMetaObjectCallback is called the first time import.meta
|
/// HostInitializeImportMetaObjectCallback is called the first time import.meta
|
||||||
|
@ -127,6 +153,7 @@ extern "C" {
|
||||||
callback: NearHeapLimitCallback,
|
callback: NearHeapLimitCallback,
|
||||||
heap_limit: usize,
|
heap_limit: usize,
|
||||||
);
|
);
|
||||||
|
fn v8__Isolate__SetPromiseHook(isolate: *mut Isolate, hook: PromiseHook);
|
||||||
fn v8__Isolate__SetPromiseRejectCallback(
|
fn v8__Isolate__SetPromiseRejectCallback(
|
||||||
isolate: *mut Isolate,
|
isolate: *mut Isolate,
|
||||||
callback: PromiseRejectCallback,
|
callback: PromiseRejectCallback,
|
||||||
|
@ -398,6 +425,12 @@ impl Isolate {
|
||||||
unsafe { v8__Isolate__AddMessageListener(self, callback) }
|
unsafe { v8__Isolate__AddMessageListener(self, callback) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the PromiseHook callback for various promise lifecycle
|
||||||
|
/// events.
|
||||||
|
pub fn set_promise_hook(&mut self, hook: PromiseHook) {
|
||||||
|
unsafe { v8__Isolate__SetPromiseHook(self, hook) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Set callback to notify about promise reject with no handler, or
|
/// Set callback to notify about promise reject with no handler, or
|
||||||
/// revocation of such a previous notification once the handler is added.
|
/// revocation of such a previous notification once the handler is added.
|
||||||
pub fn set_promise_reject_callback(
|
pub fn set_promise_reject_callback(
|
||||||
|
|
|
@ -98,6 +98,8 @@ pub use isolate::MessageCallback;
|
||||||
pub use isolate::MicrotasksPolicy;
|
pub use isolate::MicrotasksPolicy;
|
||||||
pub use isolate::NearHeapLimitCallback;
|
pub use isolate::NearHeapLimitCallback;
|
||||||
pub use isolate::OwnedIsolate;
|
pub use isolate::OwnedIsolate;
|
||||||
|
pub use isolate::PromiseHook;
|
||||||
|
pub use isolate::PromiseHookType;
|
||||||
pub use isolate::PromiseRejectCallback;
|
pub use isolate::PromiseRejectCallback;
|
||||||
pub use isolate_create_params::CreateParams;
|
pub use isolate_create_params::CreateParams;
|
||||||
pub use module::*;
|
pub use module::*;
|
||||||
|
|
|
@ -1726,6 +1726,57 @@ fn promise_reject_callback_no_value() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn promise_hook() {
|
||||||
|
extern "C" fn hook(
|
||||||
|
type_: v8::PromiseHookType,
|
||||||
|
promise: v8::Local<v8::Promise>,
|
||||||
|
_parent: v8::Local<v8::Value>,
|
||||||
|
) {
|
||||||
|
let scope = &mut unsafe { v8::CallbackScope::new(promise) };
|
||||||
|
let context = promise.creation_context(scope);
|
||||||
|
let scope = &mut v8::ContextScope::new(scope, context);
|
||||||
|
let global = context.global(scope);
|
||||||
|
let name = v8::String::new(scope, "hook").unwrap();
|
||||||
|
let func = global.get(scope, name.into()).unwrap();
|
||||||
|
let func = v8::Local::<v8::Function>::try_from(func).unwrap();
|
||||||
|
let args = &[v8::Integer::new(scope, type_ as i32).into(), promise.into()];
|
||||||
|
func.call(scope, global.into(), args).unwrap();
|
||||||
|
}
|
||||||
|
let _setup_guard = setup();
|
||||||
|
let isolate = &mut v8::Isolate::new(Default::default());
|
||||||
|
isolate.set_promise_hook(hook);
|
||||||
|
{
|
||||||
|
let scope = &mut v8::HandleScope::new(isolate);
|
||||||
|
let context = v8::Context::new(scope);
|
||||||
|
let scope = &mut v8::ContextScope::new(scope, context);
|
||||||
|
let source = r#"
|
||||||
|
var promises = new Set();
|
||||||
|
function hook(type, promise) {
|
||||||
|
if (type === /* Init */ 0) promises.add(promise);
|
||||||
|
if (type === /* Resolve */ 1) promises.delete(promise);
|
||||||
|
}
|
||||||
|
function expect(expected, actual = promises.size) {
|
||||||
|
if (actual !== expected) throw `expected ${expected}, actual ${actual}`;
|
||||||
|
}
|
||||||
|
expect(0);
|
||||||
|
new Promise(resolve => {
|
||||||
|
expect(1);
|
||||||
|
resolve();
|
||||||
|
expect(0);
|
||||||
|
});
|
||||||
|
expect(0);
|
||||||
|
new Promise(() => {});
|
||||||
|
expect(1);
|
||||||
|
promises.values().next().value
|
||||||
|
"#;
|
||||||
|
let promise = eval(scope, source).unwrap();
|
||||||
|
let promise = v8::Local::<v8::Promise>::try_from(promise).unwrap();
|
||||||
|
assert!(!promise.has_handler());
|
||||||
|
assert_eq!(promise.state(), v8::PromiseState::Pending);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn mock_script_origin<'s>(
|
fn mock_script_origin<'s>(
|
||||||
scope: &mut v8::HandleScope<'s>,
|
scope: &mut v8::HandleScope<'s>,
|
||||||
resource_name_: &str,
|
resource_name_: &str,
|
||||||
|
|
Loading…
Reference in a new issue