-
Notifications
You must be signed in to change notification settings - Fork 38
Document expectations of WeakRef behavior in practice #192
Description
TL;DR: Other than with certain caveats (see below), can developers rely on receiving finalizer calls or not? (For instance, to clean up other things related to reclaimed objects, like cache entries, WeakRefs, wasm objects...) I'm confused because some aspects of the explainer seem to suggest they can, but others (and the proposed spec text) suggest they can't. Does this need firming up and/or clarification?
Details:
I get that finalizer calls have these caveats at a minimum:
- The specification doesn't require implementations to do garbage collection at all (some embedded implementations, for instance). No GC means no finalizer calls.
- The explainer gives two other times finalizers reasonably wouldn't be called:
- When the entire process is going away.
- When the
FinalizationRegistrythe objects were in is, itself, unreachable.
Other than that, though, can developers reasonably rely on getting finalizer calls for cleanup purposes?
Evidence suggesting "yes, they can:"
-
The explainer says (my emphasis):
Whenever you have a JavaScript object that is backed by something in WebAssembly, you might want to run custom cleanup code (in WebAssembly or JavaScript) when the object goes away. A previous proposal exposed a collection of weak references, with the idea that finalization actions could be taken by periodically checking if they are still alive. This proposal includes a first-class concept of finalizers in order to give developers a way to avoid that repeated scanning.
(Granted, "a way" doesn't necessarily mean they can always avoid it. You could read that as "a way to avoid that repeated scanning if you've ever seen a finalizer call, but you still have to have the code for repeated scanning in case you never see a finalizer call.")
-
The "Fixed version that doesn't leak memory" of the explainer's
makeWeakCachedexample relies on finalizers to avoid leaking memory.
Evidence suggesting "no, they can't:"
- The explainer says finalizers can be omitted by an implementation "for any reason or no reason."
- The spec explicitly makes calling HostCleanupFinalizationRegistry optional.
- Step 7 of the
nextmethod of the finalization cleanup interator says an implementation "may" return a result object containing the held value of a cell with an empty [[WeakRefTarget]], not that it will. - The Execution section of the spec says an implementation "may" mark [[WeakRefTarget]]s empty, not that it will. This means even if userland code proactively calls
cleanupSome, it won't do anything if the implementation has never set [[WeakRegTarget]]s empty.
If the intention is that finalizers should be called "at some point in the future" by implementations that do perform garbage collection except in some limited situations, should the requirement be firmer/clearer? Or is it something developers can't reasonably rely on?
Thanks!
I'm curious about the intention re specified behavior/requirements. I do see that the signals are good that implementers of major engines will call finalizers; V8 and SpiderMonkey both do (behind flags at present). (I can't find any public signals for finalizers from Apple — for instance, here or here — but I haven't trawled the notes, and if V8 and SpiderMonkey both support them, it's hard to see JavaScriptCore not.)