Drain deferred V8 N-API finalizers after dispatch - #217
Open
matthargett wants to merge 2 commits into
Open
Conversation
V8 weak callbacks enqueue N-API finalizers for a safe second pass, but AppRuntime did not drain that queue. Run the queue after each host dispatch and cover the behavior with a deterministic V8-only unit test.
matthargett
commented
Jul 30, 2026
| napi_env env_ptr{env}; | ||
|
|
||
| // Finalizers can mutate this queue, so continue until it is empty. | ||
| while (!env_ptr->pending_finalizers.empty()) |
Author
There was a problem hiding this comment.
hypothetically, this could go on forever in some pathological case with a semi-malicious native module. lmk if you want a safeguard counter check in there.
Run deferred V8 finalizers once after each dispatcher batch and cap each batch at eight milliseconds. This prevents large GC queues from monopolizing the runtime thread while preserving eventual finalization on later turns. Add a deterministic slow-finalizer regression test that proves the queue yields and then drains completely.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Drain deferred V8 N-API finalizers at a safe host boundary, with an 8 ms budget per dispatcher turn.
V8 weak callbacks enqueue non-experimental N-API finalizers for a safe second pass. JsRuntimeHost did not run that pass, so collected wrappers retained native resources until runtime teardown. This is independent of Dawn, WebGPU, and application rendering code.
Reproduction
The profiling workload uses four packaged VRM files (from https://github.com/PolygonalMind/100Avatars ), loaded through the browser-shaped Blob path, with four thin instances per avatar. It replaces the batch ten times after 180 rendered frames:
The measured files were four distinct 6-10 MB VRMs from PolygonalMind/100Avatars.
Validation