Skip to content

Complete FinalizationRegistry#2432

Draft
gbrail wants to merge 6 commits into
mozilla:masterfrom
gbrail:greg-finalization-registry
Draft

Complete FinalizationRegistry#2432
gbrail wants to merge 6 commits into
mozilla:masterfrom
gbrail:greg-finalization-registry

Conversation

@gbrail

@gbrail gbrail commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

This builds on the work already done in #2058
and #2431 to complete the implementation
of the FinalizationRegistry.

The all-important reference queue where finalization callbacks are called is
invoked as part of microtask processing by the Context. Applications that have
many Contexts in use at once will see finalizations happening in the one where
the registry was originally created. It uses PhantomReference and a
reference queue to ensure that finalizations happen when the JVM needs them
to happen.

gbrail and others added 4 commits June 13, 2026 23:50
…compliance

Complete rewrite using simplified, Android-compatible approach.

Changes:
- NativeWeakRef: ES2021-compliant WeakRef implementation
- NativeFinalizationRegistry: ES2021-compliant implementation
- ScriptRuntime: Register both constructors in ES6+ block
- Messages.properties: Add validation error messages
- test262.properties: All 76 tests passing

ES2021 Standard Compliance:
- Correctly allows unregistered symbols as weak targets
- Rejects registered symbols created with Symbol.for per spec
- Validates target/heldValue/token same-value constraints
- Proper Symbol.toStringTag on prototypes
- Error messages match spec requirements

Technical Implementation:
- Uses Java WeakReference for WeakRef, simple and direct
- Uses PhantomReference + ReferenceQueue for FinalizationRegistry
- No Cleaner API dependency, not available on Android
- No Context.java modifications needed
- Thread-safe with ConcurrentHashMap
- Cleanup callbacks processed opportunistically during register calls
- Follows modern LambdaConstructor pattern like NativeWeakMap

Benefits:
- Only 2 files instead of 5
- Self-contained, no helper classes or separate queue management
- Android-compatible using Java 8 APIs only
- Addresses reviewer feedback to use simpler, standard Java APIs
Based on the starting point, ensure that finalization callbacks always happen
in the context where they were originally registered as part of microtask
processing.
@aardvark179

Copy link
Copy Markdown
Contributor

I'll review this properly later, I need to make sure I underhand the graph of references and what that implies about lifetimes. Specifically I'm worried that we're keeping FinalisationRegistry objects alive when they should not remain so.

@gbrail

gbrail commented Jun 15, 2026 via email

Copy link
Copy Markdown
Collaborator Author

This prevents one possible form of memory leak, where finalizations are never
run and references pile up.
@gbrail

gbrail commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

I have a bunch more ideas on this still, working...

@gbrail gbrail marked this pull request as draft June 19, 2026 06:45
By default, finalization callbacks will not be called, and nothing will be enqueued
on a ReferenceQueue, although the API will continue to function and appear to
"register" and "unregister" callbacks to match the spec.

If finalization is enabled, embedders of Rhino must somehow ensure that
"processMicrotasks" is periodically called to prevent a too-large ReferenceQueue.
How this is done depends on the framework in question, although microtask processing
happens automatically when Promises are used.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants