mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-21 20:28:58 +00:00
feat: add binding for Context::SetPromiseHooks (#938)
This commit is contained in:
parent
64ce32392a
commit
196145abf1
1
.gn
1
.gn
@ -36,6 +36,7 @@ default_args = {
|
||||
clang_use_chrome_plugins = false
|
||||
v8_monolithic = false
|
||||
v8_enable_snapshot_compression = false
|
||||
v8_enable_javascript_promise_hooks = true
|
||||
v8_use_external_startup_data = false
|
||||
v8_use_snapshot = true
|
||||
is_component_build = false
|
||||
|
@ -1560,6 +1560,18 @@ const v8::Data* v8__Context__GetDataFromSnapshotOnce(v8::Context& self,
|
||||
ptr_to_local(&self)->GetDataFromSnapshotOnce<v8::Data>(index));
|
||||
}
|
||||
|
||||
void v8__Context__SetPromiseHooks(v8::Context& self,
|
||||
v8::Function& init_hook,
|
||||
v8::Function& before_hook,
|
||||
v8::Function& after_hook,
|
||||
v8::Function& resolve_hook) {
|
||||
ptr_to_local(&self)->SetPromiseHooks(
|
||||
ptr_to_local(&init_hook),
|
||||
ptr_to_local(&before_hook),
|
||||
ptr_to_local(&after_hook),
|
||||
ptr_to_local(&resolve_hook));
|
||||
}
|
||||
|
||||
const v8::String* v8__Message__Get(const v8::Message& self) {
|
||||
return local_to_ptr(self.Get());
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::isolate::Isolate;
|
||||
use crate::Context;
|
||||
use crate::Function;
|
||||
use crate::HandleScope;
|
||||
use crate::Local;
|
||||
use crate::Object;
|
||||
@ -15,6 +16,13 @@ extern "C" {
|
||||
global_object: *const Value,
|
||||
) -> *const Context;
|
||||
fn v8__Context__Global(this: *const Context) -> *const Object;
|
||||
fn v8__Context__SetPromiseHooks(
|
||||
this: *const Context,
|
||||
init_hook: *const Function,
|
||||
before_hook: *const Function,
|
||||
after_hook: *const Function,
|
||||
resolve_hook: *const Function,
|
||||
);
|
||||
}
|
||||
|
||||
impl Context {
|
||||
@ -58,4 +66,22 @@ impl Context {
|
||||
) -> Local<'s, Object> {
|
||||
unsafe { scope.cast_local(|_| v8__Context__Global(self)) }.unwrap()
|
||||
}
|
||||
|
||||
pub fn set_promise_hooks(
|
||||
&self,
|
||||
init_hook: Local<Function>,
|
||||
before_hook: Local<Function>,
|
||||
after_hook: Local<Function>,
|
||||
resolve_hook: Local<Function>,
|
||||
) {
|
||||
unsafe {
|
||||
v8__Context__SetPromiseHooks(
|
||||
self,
|
||||
&*init_hook,
|
||||
&*before_hook,
|
||||
&*after_hook,
|
||||
&*resolve_hook,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2483,6 +2483,107 @@ fn promise_hook() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn context_promise_hooks() {
|
||||
let _setup_guard = setup();
|
||||
let isolate = &mut v8::Isolate::new(Default::default());
|
||||
{
|
||||
let scope = &mut v8::HandleScope::new(isolate);
|
||||
let context = v8::Context::new(scope);
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
let init_hook = v8::Local::<v8::Function>::try_from(
|
||||
eval(
|
||||
scope,
|
||||
r#"
|
||||
globalThis.promises = new Set();
|
||||
function initHook(promise) {
|
||||
promises.add(promise);
|
||||
}
|
||||
initHook;
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let before_hook = v8::Local::<v8::Function>::try_from(
|
||||
eval(
|
||||
scope,
|
||||
r#"
|
||||
globalThis.promiseStack = [];
|
||||
function beforeHook(promise) {
|
||||
promiseStack.push(promise);
|
||||
}
|
||||
beforeHook;
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let after_hook = v8::Local::<v8::Function>::try_from(
|
||||
eval(
|
||||
scope,
|
||||
r#"
|
||||
function afterHook(promise) {
|
||||
const it = promiseStack.pop();
|
||||
if (it !== promise) throw new Error("unexpected promise");
|
||||
}
|
||||
afterHook;
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let resolve_hook = v8::Local::<v8::Function>::try_from(
|
||||
eval(
|
||||
scope,
|
||||
r#"
|
||||
function resolveHook(promise) {
|
||||
promises.delete(promise);
|
||||
}
|
||||
resolveHook;
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
context.set_promise_hooks(init_hook, before_hook, after_hook, resolve_hook);
|
||||
|
||||
let source = r#"
|
||||
function expect(expected, actual = promises.size) {
|
||||
if (actual !== expected) throw `expected ${expected}, actual ${actual}`;
|
||||
}
|
||||
expect(0);
|
||||
var p = new Promise(resolve => {
|
||||
expect(1);
|
||||
resolve();
|
||||
expect(0);
|
||||
});
|
||||
expect(0);
|
||||
new Promise(() => {});
|
||||
expect(1);
|
||||
|
||||
expect(0, promiseStack.length);
|
||||
p.then(() => {
|
||||
expect(1, promiseStack.length);
|
||||
});
|
||||
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);
|
||||
|
||||
scope.perform_microtask_checkpoint();
|
||||
let _ = eval(
|
||||
scope,
|
||||
r#"
|
||||
expect(0, promiseStack.length);
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn allow_atomics_wait() {
|
||||
let _setup_guard = setup();
|
||||
|
Loading…
Reference in New Issue
Block a user