WeakMap Objects
- WeakMaps are collections of key/value pairs where the keys are objects and values may be arbitrary ECMAScript language values. A WeakMap may be queried to see if it contains a key/value pair with a specific key, but no mechanism is provided for enumerating the objects it holds as keys. In certain conditions, objects which are not live are removed as WeakMap keys, as described in .
+ WeakMaps are collections of key/value pairs where the keys are objects and/or symbols and values may be arbitrary ECMAScript language values. A WeakMap may be queried to see if it contains a key/value pair with a specific key, but no mechanism is provided for enumerating the values it holds as keys. In certain conditions, values which are not live are removed as WeakMap keys, as described in .
An implementation may impose an arbitrarily determined latency between the time a key/value pair of a WeakMap becomes inaccessible and the time when the key/value pair is removed from the WeakMap. If this latency was observable to ECMAScript program, it would be a source of indeterminacy that could impact program execution. For that reason, an ECMAScript implementation must not provide any means to observe a key of a WeakMap that does not require the observer to present the observed key.
WeakMaps must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of key/value pairs in the collection. The data structure used in this specification is only intended to describe the required observable semantics of WeakMaps. It is not intended to be a viable implementation model.
- WeakMap and WeakSets are intended to provide mechanisms for dynamically associating state with an object in a manner that does not “leak” memory resources if, in the absence of the WeakMap or WeakSet, the object otherwise became inaccessible and subject to resource reclamation by the implementation's garbage collection mechanisms. This characteristic can be achieved by using an inverted per-object mapping of weak map instances to keys. Alternatively each weak map may internally store its key to value mappings but this approach requires coordination between the WeakMap or WeakSet implementation and the garbage collector. The following references describe mechanism that may be useful to implementations of WeakMap and WeakSets:
+ WeakMap and WeakSet are intended to provide mechanisms for dynamically associating state with an object or symbol in a manner that does not “leak” memory resources if, in the absence of the WeakMap or WeakSet instance, the object or symbol otherwise became inaccessible and subject to resource reclamation by the implementation's garbage collection mechanisms. This characteristic can be achieved by using an inverted per-object/symbol mapping of WeakMap or WeakSet instances to keys. Alternatively, each WeakMap or WeakSet instance may internally store its key and value data, but this approach requires coordination between the WeakMap or WeakSet implementation and the garbage collector. The following references describe mechanism that may be useful to implementations of WeakMap and WeakSet:
Barry Hayes. 1997. Ephemerons: a new finalization mechanism. In Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA '97), A. Michael Berman (Ed.). ACM, New York, NY, USA, 176-183, http://doi.acm.org/10.1145/263698.263733.
Alexandra Barros, Roberto Ierusalimschy, Eliminating Cycles in Weak Tables. Journal of Universal Computer Science - J.UCS, vol. 14, no. 21, pp. 3481-3497, 2008, http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
@@ -40984,7 +41023,7 @@ WeakMap.prototype.delete ( _key_ )
1. Let _M_ be the *this* value.
1. Perform ? RequireInternalSlot(_M_, [[WeakMapData]]).
- 1. If _key_ is not an Object, return *false*.
+ 1. If CanBeHeldWeakly(_key_) is *false*, return *false*.
1. For each Record { [[Key]], [[Value]] } _p_ of _M_.[[WeakMapData]], do
1. If _p_.[[Key]] is not ~empty~ and SameValue(_p_.[[Key]], _key_) is *true*, then
1. Set _p_.[[Key]] to ~empty~.
@@ -41003,7 +41042,7 @@ WeakMap.prototype.get ( _key_ )
1. Let _M_ be the *this* value.
1. Perform ? RequireInternalSlot(_M_, [[WeakMapData]]).
- 1. If _key_ is not an Object, return *undefined*.
+ 1. If CanBeHeldWeakly(_key_) is *false*, return *undefined*.
1. For each Record { [[Key]], [[Value]] } _p_ of _M_.[[WeakMapData]], do
1. If _p_.[[Key]] is not ~empty~ and SameValue(_p_.[[Key]], _key_) is *true*, return _p_.[[Value]].
1. Return *undefined*.
@@ -41016,7 +41055,7 @@ WeakMap.prototype.has ( _key_ )
1. Let _M_ be the *this* value.
1. Perform ? RequireInternalSlot(_M_, [[WeakMapData]]).
- 1. If _key_ is not an Object, return *false*.
+ 1. If CanBeHeldWeakly(_key_) is *false*, return *false*.
1. For each Record { [[Key]], [[Value]] } _p_ of _M_.[[WeakMapData]], do
1. If _p_.[[Key]] is not ~empty~ and SameValue(_p_.[[Key]], _key_) is *true*, return *true*.
1. Return *false*.
@@ -41029,7 +41068,7 @@ WeakMap.prototype.set ( _key_, _value_ )
1. Let _M_ be the *this* value.
1. Perform ? RequireInternalSlot(_M_, [[WeakMapData]]).
- 1. If _key_ is not an Object, throw a *TypeError* exception.
+ 1. If CanBeHeldWeakly(_key_) is *false*, throw a *TypeError* exception.
1. For each Record { [[Key]], [[Value]] } _p_ of _M_.[[WeakMapData]], do
1. If _p_.[[Key]] is not ~empty~ and SameValue(_p_.[[Key]], _key_) is *true*, then
1. Set _p_.[[Value]] to _value_.
@@ -41055,8 +41094,8 @@ Properties of WeakMap Instances
WeakSet Objects
- WeakSets are collections of objects. A distinct object may only occur once as an element of a WeakSet's collection. A WeakSet may be queried to see if it contains a specific object, but no mechanism is provided for enumerating the objects it holds. In certain conditions, objects which are not live are removed as WeakSet elements, as described in .
- An implementation may impose an arbitrarily determined latency between the time an object contained in a WeakSet becomes inaccessible and the time when the object is removed from the WeakSet. If this latency was observable to ECMAScript program, it would be a source of indeterminacy that could impact program execution. For that reason, an ECMAScript implementation must not provide any means to determine if a WeakSet contains a particular object that does not require the observer to present the observed object.
+ WeakSets are collections of objects and/or symbols. A distinct object or symbol may only occur once as an element of a WeakSet's collection. A WeakSet may be queried to see if it contains a specific value, but no mechanism is provided for enumerating the values it holds. In certain conditions, values which are not live are removed as WeakSet elements, as described in .
+ An implementation may impose an arbitrarily determined latency between the time a value contained in a WeakSet becomes inaccessible and the time when the value is removed from the WeakSet. If this latency was observable to ECMAScript program, it would be a source of indeterminacy that could impact program execution. For that reason, an ECMAScript implementation must not provide any means to determine if a WeakSet contains a particular value that does not require the observer to present the observed value.
WeakSets must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements in the collection. The data structure used in this specification is only intended to describe the required observable semantics of WeakSets. It is not intended to be a viable implementation model.
See the NOTE in .
@@ -41125,7 +41164,7 @@ WeakSet.prototype.add ( _value_ )
1. Let _S_ be the *this* value.
1. Perform ? RequireInternalSlot(_S_, [[WeakSetData]]).
- 1. If _value_ is not an Object, throw a *TypeError* exception.
+ 1. If CanBeHeldWeakly(_value_) is *false*, throw a *TypeError* exception.
1. For each element _e_ of _S_.[[WeakSetData]], do
1. If _e_ is not ~empty~ and SameValue(_e_, _value_) is *true*, then
1. Return _S_.
@@ -41145,7 +41184,7 @@ WeakSet.prototype.delete ( _value_ )
1. Let _S_ be the *this* value.
1. Perform ? RequireInternalSlot(_S_, [[WeakSetData]]).
- 1. If _value_ is not an Object, return *false*.
+ 1. If CanBeHeldWeakly(_value_) is *false*, return *false*.
1. For each element _e_ of _S_.[[WeakSetData]], do
1. If _e_ is not ~empty~ and SameValue(_e_, _value_) is *true*, then
1. Replace the element of _S_.[[WeakSetData]] whose value is _e_ with an element whose value is ~empty~.
@@ -41163,7 +41202,7 @@ WeakSet.prototype.has ( _value_ )
1. Let _S_ be the *this* value.
1. Perform ? RequireInternalSlot(_S_, [[WeakSetData]]).
- 1. If _value_ is not an Object, return *false*.
+ 1. If CanBeHeldWeakly(_value_) is *false*, return *false*.
1. For each element _e_ of _S_.[[WeakSetData]], do
1. If _e_ is not ~empty~ and SameValue(_e_, _value_) is *true*, return *true*.
1. Return *false*.
@@ -43243,7 +43282,7 @@ Managing Memory
WeakRef Objects
- A WeakRef is an object that is used to refer to a target object without preserving it from garbage collection. WeakRefs can be dereferenced to allow access to the target object, if the target object hasn't been reclaimed by garbage collection.
+ A WeakRef is an object that is used to refer to a target object or symbol without preserving it from garbage collection. WeakRefs can be dereferenced to allow access to the target value, if the target hasn't been reclaimed by garbage collection.
The WeakRef Constructor
@@ -43269,7 +43308,7 @@ WeakRef ( _target_ )
This function performs the following steps when called:
1. If NewTarget is *undefined*, throw a *TypeError* exception.
- 1. If _target_ is not an Object, throw a *TypeError* exception.
+ 1. If CanBeHeldWeakly(_target_) is *false*, throw a *TypeError* exception.
1. Let _weakRef_ be ? OrdinaryCreateFromConstructor(NewTarget, *"%WeakRef.prototype%"*, « [[WeakRefTarget]] »).
1. Perform AddToKeptObjects(_target_).
1. Set _weakRef_.[[WeakRefTarget]] to _target_.
@@ -43325,7 +43364,7 @@ WeakRef.prototype.deref ( )
- If the WeakRef returns a _target_ Object that is not *undefined*, then this _target_ object should not be garbage collected until the current execution of ECMAScript code has completed. The AddToKeptObjects operation makes sure read consistency is maintained.
+ If the WeakRef returns a _target_ value that is not *undefined*, then this _target_ value should not be garbage collected until the current execution of ECMAScript code has completed. The AddToKeptObjects operation makes sure read consistency is maintained.
let target = { foo() {} };
@@ -43381,7 +43420,7 @@ Properties of WeakRef Instances
FinalizationRegistry Objects
- A FinalizationRegistry is an object that manages registration and unregistration of cleanup operations that are performed when target objects are garbage collected.
+ A FinalizationRegistry is an object that manages registration and unregistration of cleanup operations that are performed when target objects and symbols are garbage collected.
The FinalizationRegistry Constructor
@@ -43460,9 +43499,9 @@ FinalizationRegistry.prototype.register ( _target_, _heldValue_ [ , _unregis
1. Let _finalizationRegistry_ be the *this* value.
1. Perform ? RequireInternalSlot(_finalizationRegistry_, [[Cells]]).
- 1. If _target_ is not an Object, throw a *TypeError* exception.
+ 1. If CanBeHeldWeakly(_target_) is *false*, throw a *TypeError* exception.
1. If SameValue(_target_, _heldValue_) is *true*, throw a *TypeError* exception.
- 1. If _unregisterToken_ is not an Object, then
+ 1. If CanBeHeldWeakly(_unregisterToken_) is *false*, then
1. If _unregisterToken_ is not *undefined*, throw a *TypeError* exception.
1. Set _unregisterToken_ to ~empty~.
1. Let _cell_ be the Record { [[WeakRefTarget]]: _target_, [[HeldValue]]: _heldValue_, [[UnregisterToken]]: _unregisterToken_ }.
@@ -43481,7 +43520,7 @@ FinalizationRegistry.prototype.unregister ( _unregisterToken_ )
1. Let _finalizationRegistry_ be the *this* value.
1. Perform ? RequireInternalSlot(_finalizationRegistry_, [[Cells]]).
- 1. If _unregisterToken_ is not an Object, throw a *TypeError* exception.
+ 1. If CanBeHeldWeakly(_unregisterToken_) is *false*, throw a *TypeError* exception.
1. Let _removed_ be *false*.
1. For each Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } _cell_ of _finalizationRegistry_.[[Cells]], do
1. If _cell_.[[UnregisterToken]] is not ~empty~ and SameValue(_cell_.[[UnregisterToken]], _unregisterToken_) is *true*, then