-
-
Notifications
You must be signed in to change notification settings - Fork 616
Description
Feature Description
Summary
Implement CanBeHeldWeakly Symbol support for FinalizationRegistry unregister token handling.
Currently, FinalizationRegistry has TODO markers for Symbol support in its weak checks (core/engine/src/builtins/finalization_registry/mod.rs around lines 225, 249, 307). This issue proposes implementing Symbol handling for register and unregister token validation so behavior matches ECMAScript rules for non-registered Symbols.
Specification Intent
The ECMAScript abstract operation CanBeHeldWeakly(v) returns true when:
vis an Object.vis a Symbol andSymbol.keyFor(v)isundefined(a non-registered Symbol).- Otherwise,
false.
For this issue, this logic must be applied to the unregisterToken validation in both FinalizationRegistry.prototype.register and FinalizationRegistry.prototype.unregister.
Motivation
- Improves ECMAScript conformance for
FinalizationRegistry. - Closes a clear runtime correctness gap in weak-reference related APIs.
- Demonstrates robust handling of Symbol lifecycles in GC-observable features.
Proposed Scope
- Add Symbol branch to
unregisterTokenvalidation inregister. - Add Symbol branch to
unregisterTokenvalidation inunregister. - Reject registered Symbols from
Symbol.for(...)forunregisterToken. - Accept non-registered Symbols from
Symbol(...). - Keep existing Object behavior unchanged.
Acceptance Criteria
-
registeraccepts Object, non-registered Symbol, orundefinedasunregisterToken. -
registerthrowsTypeErrorfor registered SymbolunregisterToken. -
unregisteraccepts Object or non-registered Symbol. -
unregisterthrowsTypeErrorfor registered Symbol. - Existing
FinalizationRegistrybehavior and tests remain passing.
Test Plan
Add and pass tests in tests.rs:
register/unregisterwithSymbol(local)removes registration successfully.registerwithSymbol.for(global)as token throwsTypeError.unregisterwithSymbol.for(global)throwsTypeError.- Existing object-token tests continue to pass.
Example code
This JavaScript code should execute according to the updated CanBeHeldWeakly semantics:
const registry = new FinalizationRegistry(heldValue => {});
let localSymbol = Symbol("local");
let globalSymbol = Symbol.for("global");
// 1. Should succeed most importntly (non-registered symbol)
registry.register({}, "val", localSymbol);
registry.unregister(localSymbol);
// 2. Should throw TypeError (registered symbol cannot be held weakly) focus on it
try {
registry.register({}, "val", globalSymbol);
} catch (e) {
console.log(e.name); // Expected: TypeError
}
// 3. Should throw TypeError check it
try {
registry.unregister(globalSymbol);
} catch (e) {
console.log(e.name); // Expected: TypeError
}