From 623c6cd81d61ff0aabf0ce370a6768cb15c4ca80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Wed, 1 Feb 2023 17:42:47 +0100 Subject: [PATCH] feat: v8::Context::set_promise_hooks accepts None (#1178) Co-authored-by: Bert Belder --- src/binding.cc | 13 ++++---- src/context.rs | 16 +++++----- tests/test_api.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 15 deletions(-) diff --git a/src/binding.cc b/src/binding.cc index 575d95a1..81edebe1 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -1709,13 +1709,14 @@ const v8::Object* v8__Context__GetExtrasBindingObject(v8::Context& self) { return local_to_ptr(ptr_to_local(&self)->GetExtrasBindingObject()); } -void v8__Context__SetPromiseHooks(v8::Context& self, v8::Function& init_hook, - v8::Function& before_hook, - v8::Function& after_hook, - v8::Function& resolve_hook) { +void v8__Context__SetPromiseHooks(v8::Context& self, + const v8::Function* init_hook, + const v8::Function* before_hook, + const v8::Function* after_hook, + const 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)); + ptr_to_local(init_hook), ptr_to_local(before_hook), + ptr_to_local(after_hook), ptr_to_local(resolve_hook)); } const v8::Context* v8__Context__FromSnapshot(v8::Isolate* isolate, diff --git a/src/context.rs b/src/context.rs index 7bf4b716..d03c6715 100644 --- a/src/context.rs +++ b/src/context.rs @@ -110,18 +110,18 @@ impl Context { #[inline(always)] pub fn set_promise_hooks( &self, - init_hook: Local, - before_hook: Local, - after_hook: Local, - resolve_hook: Local, + init_hook: Option>, + before_hook: Option>, + after_hook: Option>, + resolve_hook: Option>, ) { unsafe { v8__Context__SetPromiseHooks( self, - &*init_hook, - &*before_hook, - &*after_hook, - &*resolve_hook, + init_hook.map_or_else(null, |v| &*v), + before_hook.map_or_else(null, |v| &*v), + after_hook.map_or_else(null, |v| &*v), + resolve_hook.map_or_else(null, |v| &*v), ) } } diff --git a/tests/test_api.rs b/tests/test_api.rs index bf727f3a..3fa55ded 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -3269,7 +3269,12 @@ fn context_promise_hooks() { .unwrap(), ) .unwrap(); - context.set_promise_hooks(init_hook, before_hook, after_hook, resolve_hook); + context.set_promise_hooks( + Some(init_hook), + Some(before_hook), + Some(after_hook), + Some(resolve_hook), + ); let source = r#" function expect(expected, actual = promises.size) { @@ -3307,6 +3312,80 @@ fn context_promise_hooks() { } } +#[test] +fn context_promise_hooks_partial() { + let _setup_guard = setup::parallel_test(); + 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::::try_from( + eval( + scope, + r#" + globalThis.promises = new Set(); + function initHook(promise) { + promises.add(promise); + } + initHook; + "#, + ) + .unwrap(), + ) + .unwrap(); + let before_hook = v8::Local::::try_from( + eval( + scope, + r#" + globalThis.promiseStack = []; + function beforeHook(promise) { + promiseStack.push(promise); + } + beforeHook; + "#, + ) + .unwrap(), + ) + .unwrap(); + context.set_promise_hooks(Some(init_hook), Some(before_hook), None, None); + + 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(1); + }); + expect(1); + new Promise(() => {}); + expect(2); + + expect(0, promiseStack.length); + p.then(() => { + expect(1, promiseStack.length); + }); + promises.values().next().value + "#; + let promise = eval(scope, source).unwrap(); + let promise = v8::Local::::try_from(promise).unwrap(); + assert!(promise.has_handler()); + assert_eq!(promise.state(), v8::PromiseState::Fulfilled); + + scope.perform_microtask_checkpoint(); + let _ = eval( + scope, + r#" + expect(1, promiseStack.length); + "#, + ) + .unwrap(); + } +} + #[test] fn allow_atomics_wait() { let _setup_guard = setup::parallel_test();