diff options
author | Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> | 2024-08-28 13:42:42 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-28 13:42:42 -0700 |
commit | 37501aa32357e75b9ddc92198da94d92fcdd0798 (patch) | |
tree | f87a09bbe351ebe29b0c1b4fff4dca5b4f066ced | |
parent | 6ccaebcdeae95a82b270ac5bde78b65b37fadb45 (diff) |
fix(napi): Don't run microtasks in napi_resolve_deferred (#25246)
Fixes an incredibly obscure bug that causes parcel's file watcher to not
get any file update notifications on macOS.
The issue was that the native addon was calling `napi_resolve_deferred`,
but when we resolved the promise, v8 was running microtasks
automatically. That executed JS, which called back into the native addon
and broke the addon's assumption that the call wouldn't be reentrant.
-rw-r--r-- | cli/napi/js_native_api.rs | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/cli/napi/js_native_api.rs b/cli/napi/js_native_api.rs index 5269d8d1d..e922d8c3f 100644 --- a/cli/napi/js_native_api.rs +++ b/cli/napi/js_native_api.rs @@ -3307,19 +3307,30 @@ fn napi_resolve_deferred( check_arg!(env, result); check_arg!(env, deferred); + // Make sure microtasks don't run and call back into JS + env + .scope() + .set_microtasks_policy(v8::MicrotasksPolicy::Explicit); + let deferred_ptr = unsafe { NonNull::new_unchecked(deferred as *mut v8::PromiseResolver) }; let global = unsafe { v8::Global::from_raw(env.isolate(), deferred_ptr) }; let resolver = v8::Local::new(&mut env.scope(), global); - if !resolver + let success = resolver .resolve(&mut env.scope(), result.unwrap()) - .unwrap_or(false) - { - return napi_generic_failure; - } + .unwrap_or(false); - napi_ok + // Restore policy + env + .scope() + .set_microtasks_policy(v8::MicrotasksPolicy::Auto); + + if success { + napi_ok + } else { + napi_generic_failure + } } #[napi_sym] |