Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Latest commit

 

History

History
284 lines (206 loc) · 11.1 KB

spec.md

File metadata and controls

284 lines (206 loc) · 11.1 KB

[TOC]

Specification [Work In Progress]

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.

WeakFactory Objects

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 WeakFactory Constructor

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:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakFactoryPrototype%", « [[WeakFactory]] »).
  3. If cleanup is undefined, then
    1. Set O.[[Cleanup]] to undefined.
  4. Else
    1. Set O.[[Cleanup]] to cleanup.
  5. Set O.[[ActiveCells]] to a new empty List.
  6. Set O.[[HasDirty]] to false.
  7. Perform ! RegisterWeakFactory(O).
  8. Return O

The WeakFactory.prototype Object

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:

WeakFactory.prototype.makeRef(target, holdings = undefined)

The operation WeakFactory.prototype.makeRef with arguments target and holdings is used to create WeakRef objects.

It performs the following steps:

  1. Let O be the this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have all of the internal slots of a WeakFactory Instance, throw a TypeError exception.
  4. If Type(target) is not Object, throw a TypeError exception
  5. If SameValue(target, holdings), throw a TypeError exception
  6. If SameRealm(target, this), then
    1. Let weakRef be ObjectCreate(%WeakRefPrototype%, ([[Factory]], [[WeakRefTarget]], [[Holdings]])).
    2. Set weakRef.[[Factory]] to O.
    3. Set weakRef.[[WeakRefTarget]] to target.
    4. Set weakRef.[[Holdings]] to holdings.
    5. Set all weakRef's garbage collection internal operations.
    6. Perform ! KeepDuringJob(target).
  7. Else
    1. Let weakRef be ObjectCreate(%WeakRefPrototype%, ([[Factory]], [[WeakRefTarget]], [[Holdings]], [[Strong]])).
    2. Set weakRef.[[Factory]] to O.
    3. Set weakRef.[[WeakRefTarget]] to target.
    4. Set weakRef.[[Holdings]] to holdings.
    5. Set weakRef.[[Strong]] to target.
  8. Add weakref to O.[[ActiveCells]].
  9. Return weakRef.

WeakFactory.prototype.shutdown()

Disable all cleanup for WeakCells created by this WeakFactory. This is used to enable a subsystem using this WeakFactory to shutdown completely without triggering unnecessary finalization.

  1. Let O be the this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have all of the internal slots of a WeakFactory Instance, throw a TypeError exception.
  4. Set O.[[Cleanup]] to undefined.
  5. Set O.[[ActiveCells]] to undefined.
  6. Set O.[[HasDirty]] to false.
  7. Return undefined.

WeakFactory.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the string value "WeakFactory".

Properties of WeakFactory Instances

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.

WeakCell Objects

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.

The WeakCell.prototype Object

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()

WeakCell.prototype.clear() performs the following steps:

  1. Let O be the this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have all of the internal slots of a WeakCell Instance, throw a TypeError exception.
  4. Let _factory be O.[[Factory]].
  5. If factory is not undefined.
    1. Remove O from factory.[[ActiveCells]].
    2. Set O.[[WeakRefTarget]] to undefined.
    3. Set O.[[Factory]] to undefined.
    4. Set O.[[Holdings]] to undefined.
  6. Return undefined.

get WeakCell.prototype.holdings

WeakCell.prototype.holdings is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let O be the this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have all of the internal slots of a WeakCell Instance, throw a TypeError exception.
  4. Return O.[[Holdings]].

WeakCell.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the string value "WeakCell".

Properties of WeakCell Instances

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

WeakRef Objects

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.

The WeakRef.prototype Object

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()

WeakRef.prototype.deref() performs the following steps:

  1. Let O be the this value.
  2. If Type(O) is not Object, throw a TypeError exception.
  3. If O does not have all of the internal slots of a WeakRef Instance, throw a TypeError exception.
  4. Let a be the value of the [[WeakRefTarget]] internal slot of O.
  5. If a is not undefined, perform ! KeepDuringJob(a).
  6. Return a.

WeakRef.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the string value "WeakRef".

Properties of WeakRef Instances

All properties on WeakRef instances are inherited from the WeakCell.prototype "superclass".

Job and Agent Extensions

This section describes extensions to existing standard elements.

Agent Additions

Each Agent contains a new property [[WeakFactories]] which points weakly (via records TBD) to the WeakFactory instances created in that agent.

WeakCellJobs Queue

Add a separate "WeakCellJobs" JobQueue for all cleanup operations in the agent. (Section 8.4)

Abstract Operations

This section decribes additional abstract operations to support WeakCells and cleanup.

SameRealm Abstract Operation

When the abstract operation SameRealm is called with two references, a and b, it returns true if they were created in the same Realm.

KeepDuringJob Abstract Operation

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.

WeakTargetReclaimed

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:

  1. Assert: Type(weakcell) is Object.
  2. Assert: weakcell has all of the internal slots of a WeakCell Instance.
  3. Let factory be weakcell.[[Factory]].
  4. If factory is not undefined, then Set factory.[[HasDirty]] to true.
  5. Return undefined.

RegisterWeakFactory

Add a WeakFactory to the [[WeakFactories]] list of the current agent.

DoAgentFinalization

When the abstract operation DoAgentFinalization is called with an argument agent, it performs the following steps:

  1. Assert: Type(agent) is Object.
  2. Assert: agent has all of the internal slots of an Agent Instance.
  3. For each factory in agent.[[WeakFactories]]
    1. If factory.[[HasDirty]], then
      1. Perform EnqueueJob("WeakCellJobs", WeakFactoryCleanupJob, « factory »).

WeakFactoryCleanupJob(factory)

The job WeakFactoryCleanupJob with parameter factory, and then performs the following steps:

  1. Assert: Type(factory) is Object.
  2. Assert: factory has all of the internal slots of a WeakFactory Instance.
  3. Let iterator be ObjectCreate(%ReclaimedIteratorPrototype%, « [[Factory]] »).
  4. Set iterator.[[WeakFactory]] = factory.
  5. Let next be a new built-in function defined in WeakFactoryCleanupIterator next.
  6. Perform CreateMethodProperty(iterator, next, next).
  7. Call factory.[[Cleanup]](iterator).
  8. Return undefined

WeakFactoryCleanupIterator.next()

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?