[TOC]
The specification for weak references and finalization will include
the WeakCell
type, the WeakRef
type, the WeakFactory
type, some
abstract functions, and some characteristics of the runtime garbage
collector.
A WeakFactory
is an object that creates WeakCells
and WeakRefs
for a
related group of target objects, and implements and manages the cleanup after
each of those targets have been reclaimed.
The Ream constructor is the %WeakFactory% intrinsic object and the initial value of the WeakFactory property of the global object. When called as a constructor it creates and initializes a new WeakFactory object. WeakFactory is not intended to be called as a function and will throw an exception when called in that manner.
The WeakFactory constructor is designed to be subclassable. It may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified WeakFactory behaviour must include a super call to the WeakFactory constructor to create and initialize the subclass instance with the internal state necessary to support the WeakFactory.prototype built-in methods.
When WeakFactory is called with argument cleanup, it performs the following steps:
- If NewTarget is undefined, throw a TypeError exception.
- Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakFactoryPrototype%", « [[WeakFactory]] »).
- If cleanup is undefined, then
- Set O.[[Cleanup]] to undefined.
- Else
- Set O.[[Cleanup]] to cleanup.
- Set O.[[ActiveCells]] to a new empty List.
- Set O.[[HasDirty]] to false.
- Perform ! RegisterWeakFactory(O).
- Return O
The initial value of WeakMap.prototype is the intrinsic object
%WeakFactoryPrototype%
. The %WeakFactoryPrototype%
object is an
ordinary object and its [[Prototype]]
internal slot is the
%ObjectPrototype%
intrinsic object. In addition,
WeakFactory.prototype
has the following properties:
The operation WeakFactory.prototype.makeRef
with arguments target
and holdings
is used to create WeakRef
objects.
It performs the following steps:
- Let O be the this value.
- If Type(O) is not Object, throw a TypeError exception.
- If O does not have all of the internal slots of a WeakFactory Instance, throw a TypeError exception.
- If Type(target) is not Object, throw a TypeError exception
- If SameValue(target, holdings), throw a TypeError exception
- If SameRealm(target, this), then
- Let weakRef be ObjectCreate(%WeakRefPrototype%, ([[Factory]], [[WeakRefTarget]], [[Holdings]])).
- Set weakRef.[[Factory]] to O.
- Set weakRef.[[WeakRefTarget]] to target.
- Set weakRef.[[Holdings]] to holdings.
- Set all weakRef's garbage collection internal operations.
- Perform ! KeepDuringJob(target).
- Else
- Let weakRef be ObjectCreate(%WeakRefPrototype%, ([[Factory]], [[WeakRefTarget]], [[Holdings]], [[Strong]])).
- Set weakRef.[[Factory]] to O.
- Set weakRef.[[WeakRefTarget]] to target.
- Set weakRef.[[Holdings]] to holdings.
- Set weakRef.[[Strong]] to target.
- Add weakref to O.[[ActiveCells]].
- Return weakRef.
Disable all cleanup for WeakCell
s created by this WeakFactory
. This is used to
enable a subsystem using this WeakFactory
to shutdown completely without
triggering unnecessary finalization.
- Let O be the this value.
- If Type(O) is not Object, throw a TypeError exception.
- If O does not have all of the internal slots of a WeakFactory Instance, throw a TypeError exception.
- Set O.[[Cleanup]] to undefined.
- Set O.[[ActiveCells]] to undefined.
- Set O.[[HasDirty]] to false.
- Return undefined.
The initial value of the @@toStringTag property is the string value "WeakFactory".
WeakFactory instances are ordinary objects that inherit properties from the WeakFactory.prototype intrinsic object. WeakFactory instances are initially created with the internal slots listed in Table K.
Table K — Internal Slots of WeakFactory Instances
Internal Slot | Description |
---|---|
[[Cleanup]] | An optional reference to a function |
[[ActiveCells]] | WeakRefs that are Active or Dirty. |
[[HasDirty]] | True if some of ActiveCells has become Dirty. |
A WeakCell
is an object that is used to refer to a target object
without preserving it from garbage collection, and to enable code to
be run to clean up after the target is garbage collected. Correct
instances can only be created via a WeakFactory
object because the
instances must contain a pointer to such a factory.
All WeakCell
objects inherit properties from the
%WeakCellPrototype%
intrinsic object. The WeakCell.prototype
object is an ordinary object and its [[Prototype]]
internal slot is
the %ObjectPrototype%
intrinsic object. In addition,
WeakCell.prototype
has the following properties:
WeakCell.prototype.clear() performs the following steps:
- Let O be the this value.
- If Type(O) is not Object, throw a TypeError exception.
- If O does not have all of the internal slots of a WeakCell Instance, throw a TypeError exception.
- Let _factory be O.[[Factory]].
- If factory is not undefined.
- Remove O from factory.[[ActiveCells]].
- Set O.[[WeakRefTarget]] to undefined.
- Set O.[[Factory]] to undefined.
- Set O.[[Holdings]] to undefined.
- Return undefined.
WeakCell.prototype.holdings is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
- Let O be the this value.
- If Type(O) is not Object, throw a TypeError exception.
- If O does not have all of the internal slots of a WeakCell Instance, throw a TypeError exception.
- Return O.[[Holdings]].
The initial value of the @@toStringTag property is the string value "WeakCell".
WeakCell instances are ordinary objects that inherit properties from the WeakCell.prototype intrinsic object. WeakCell instances are initially created with the internal slots listed in Table L.
Table L — Internal Slots of WeakCell Instances
Internal Slot | Description |
---|---|
[[WeakRefTarget]] | The reference to the target object |
[[Factory]] | AThe factory that created the object |
[[Holdings]] | Any value, passed as a parameter to the cleanup function in the factory |
A WeakRef
is a kind of WeakCell that can also be dereferenced. Correct
instances can only be created via a WeakFactory object because the instances
must contain a pointer to such a factory.
All WeakRef
objects inherit properties from the
%WeakRefPrototype%
intrinsic object. The %WeakRefPrototype%
object is an ordinary object and its [[Prototype]]
internal slot is
the %WeakCellPrototype%
intrinsic object. In addition,
WeakRef.prototype
has the following properties:
WeakRef.prototype.deref() performs the following steps:
- Let O be the this value.
- If Type(O) is not Object, throw a TypeError exception.
- If O does not have all of the internal slots of a WeakRef Instance, throw a TypeError exception.
- Let a be the value of the [[WeakRefTarget]] internal slot of O.
- If a is not undefined, perform ! KeepDuringJob(a).
- Return a.
The initial value of the @@toStringTag property is the string value "WeakRef".
All properties on WeakRef instances are inherited from the WeakCell.prototype "superclass".
This section describes extensions to existing standard elements.
Each Agent contains a new property [[WeakFactories]] which points weakly (via records TBD) to the WeakFactory instances created in that agent.
Add a separate "WeakCellJobs" JobQueue for all cleanup operations in the agent. (Section 8.4)
This section decribes additional abstract operations to support WeakCells and cleanup.
When the abstract operation SameRealm
is called with two references, a and
b, it returns true if they were created in the same Realm.
When the abstract operation KeepDuringJob
is called with a target
object reference, it adds the target to an identity Set that will
point strongly at the target until the end of the current Job. This
may be abstractly implemented as a Set in the current Job that becomes
unreachable when the Job ends because the Job becomes unreachable, or
as a Set in the current Agent that gets cleared at the end of each
Job.
The garbage collector calls this abstract operation when it has made a target object unreachable and set all weakRef [[WeakRefTarget]] fields that point to it to undefined.
When the abstract operation WeakTargetReclaimed
is called with a
weakcell argument (by the garbage collector), it performs the following
steps:
- Assert: Type(weakcell) is Object.
- Assert: weakcell has all of the internal slots of a WeakCell Instance.
- Let factory be weakcell.[[Factory]].
- If factory is not undefined, then Set factory.[[HasDirty]] to true.
- Return undefined.
Add a WeakFactory
to the [[WeakFactories]] list of the current agent.
When the abstract operation DoAgentFinalization
is called with an argument
agent, it performs the following steps:
- Assert: Type(agent) is Object.
- Assert: agent has all of the internal slots of an Agent Instance.
- For each factory in agent.[[WeakFactories]]
- If factory.[[HasDirty]], then
- Perform EnqueueJob("WeakCellJobs", WeakFactoryCleanupJob, « factory »).
- If factory.[[HasDirty]], then
The job WeakFactoryCleanupJob
with parameter factory, and then performs
the following steps:
- Assert: Type(factory) is Object.
- Assert: factory has all of the internal slots of a WeakFactory Instance.
- Let iterator be ObjectCreate(%ReclaimedIteratorPrototype%, « [[Factory]] »).
- Set iterator.[[WeakFactory]] = factory.
- Let next be a new built-in function defined in
WeakFactoryCleanupIterator
next. - Perform CreateMethodProperty(iterator, next, next).
- Call factory.[[Cleanup]](iterator).
- Return undefined
The WeakFactoryCleanupIterator.next method is a standard built-in function object that performs the following steps:
TBD: search the factory.[[ActiveCells]] for a dirty WeakCell TDB: how is done set correctly?