23 Keyed Collection

23.1 Map Objects

Map objects are collections of key/value pairs where both the keys and values may be arbitrary ECMAScript language values. A distinct key value may only occur in one key/value pair within the Map's collection. Distinct key values are discriminated using the SameValueZero comparison algorithm.

Map object 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 structures used in this Map objects specification is only intended to describe the required observable semantics of Map objects. It is not intended to be a viable implementation model.

23.1.1 The Map Constructor

The Map constructor is the %Map% intrinsic object and the initial value of the Map property of the global object. When called as a constructor it creates and initializes a new Map object. Map is not intended to be called as a function and will throw an exception when called in that manner.

The Map 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 Map behaviour must include a super call to the Map constructor to create and initialize the subclass instance with the internal state necessary to support the Map.prototype built-in methods.

23.1.1.1 Map ( [ iterable ] )

When the Map function is called with optional argument the following steps are taken:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let map be OrdinaryCreateFromConstructor(NewTarget, "%MapPrototype%", «‍[[MapData]]» ).
  3. ReturnIfAbrupt(map).
  4. Set map’s [[MapData]] internal slot to a new empty List.
  5. If iterable is not present, let iterable be undefined.
  6. If iterable is either undefined or null, let iter be undefined.
  7. Else,
    1. Let adder be Get(map, "set").
    2. ReturnIfAbrupt(adder).
    3. If IsCallable(adder) is false, throw a TypeError exception.
    4. Let iter be GetIterator(iterable).
    5. ReturnIfAbrupt(iter).
  8. If iter is undefined, return map.
  9. Repeat
    1. Let next be IteratorStep(iter).
    2. ReturnIfAbrupt(next).
    3. If next is false, return map.
    4. Let nextItem be IteratorValue(next).
    5. ReturnIfAbrupt(nextItem).
    6. If Type(nextItem) is not Object,
      1. Let error be Completion{[[type]]: throw, [[value]]: a newly created TypeError object, [[target]]:empty}.
      2. Return IteratorClose(iter, error).
    7. Let k be Get(nextItem, "0").
    8. If k is an abrupt completion, return IteratorClose(iter, k).
    9. Let v be Get(nextItem, "1").
    10. If v is an abrupt completion, return IteratorClose(iter, v).
    11. Let status be Call(adder, map, «k.[[value]], v.[[value]]»).
    12. If status is an abrupt completion, return IteratorClose(iter, status).

NOTE If the parameter iterable is present, it is expected to be an object that implements an @@iterator method that returns an iterator object that produces a two element array-like object whose first element is a value that will be used as a Map key and whose second element is the value to associate with that key.

23.1.2 Properties of the Map Constructor

The value of the [[Prototype]] internal slot of the Map constructor is the intrinsic object %FunctionPrototype% (19.2.3).

Besides the length property (whose value is 0), the Map constructor has the following properties:

23.1.2.1 Map.prototype

The initial value of Map.prototype is the intrinsic object %MapPrototype% (23.1.3).

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

23.1.2.2 get Map [ @@species ]

Map[@@species] is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Return the this value.

The value of the name property of this function is "get [Symbol.species]".

NOTE Methods that create derived collection objects should call @@species to determine the constructor to use to create the derived objects. Subclass constructor may over-ride @@species to change the default constructor assignment.

23.1.3 Properties of the Map Prototype Object

The Map prototype object is the intrinsic object %MapPrototype%. The value of the [[Prototype]] internal slot of the Map prototype object is the intrinsic object %ObjectPrototype% (19.1.3). The Map prototype object is an ordinary object. It does not have a [[MapData]] internal slot.

23.1.3.1 Map.prototype.clear ( )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[MapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[MapData]] internal slot.
  5. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. Set p.[[key]] to empty.
    2. Set p.[[value]] to empty.
  6. Return undefined.

NOTE The existing [[MapData]] List is preserved because there may be existing MapIterator objects that are suspended midway through iterating over that List.

23.1.3.2 Map.prototype.constructor

The initial value of Map.prototype.constructor is the intrinsic object %Map%.

23.1.3.3 Map.prototype.delete ( key )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[MapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[MapData]] internal slot.
  5. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, then
      1. Set p.[[key]] to empty.
      2. Set p.[[value]] to empty.
      3. Return true.
  6. Return false.

NOTE The value empty is used as a specification device to indicate that an entry has been deleted. Actual implementations may take other actions such as physically removing the entry from internal data structures.

23.1.3.4 Map.prototype.entries ( )

The following steps are taken:

  1. Let M be the this value.
  2. Return CreateMapIterator(M, "key+value").

23.1.3.5 Map.prototype.forEach ( callbackfn [ , thisArg ] )

When the forEach method is called with one or two arguments, the following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[MapData]] internal slot, throw a TypeError exception.
  4. If IsCallable(callbackfn) is false, throw a TypeError exception.
  5. If thisArg was supplied, let T be thisArg; else let T be undefined.
  6. Let entries be the List that is the value of M's [[MapData]] internal slot.
  7. Repeat for each Record {[[key]], [[value]]} e that is an element of entries, in original key insertion order
    1. If e.[[key]] is not empty, then
      1. Let funcResult be Call(callbackfn, T, «e.[[value]], e.[[key]], M»).
      2. ReturnIfAbrupt(funcResult).
  8. Return undefined.

The length property of the forEach method is 1.

NOTE callbackfn should be a function that accepts three arguments. forEach calls callbackfn once for each key/value pair present in the map object, in key insertion order. callbackfn is called only for keys of the map which actually exist; it is not called for keys that have been deleted from the map.

If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackfn. If it is not provided, undefined is used instead.

callbackfn is called with three arguments: the value of the item, the key of the item, and the Map object being traversed.

forEach does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn. Each entry of a map's [[MapData]] is only visited once. New keys added after the call to forEach begins are visited. A key will be revisited if it is deleted after it has been visited and then re-added before the forEach call completes. Keys that are deleted after the call to forEach begins and before being visited are not visited unless the key is added again before the forEach call completes.

23.1.3.6 Map.prototype.get ( key )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[MapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[MapData]] internal slot.
  5. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, return p.[[value]].
  6. Return undefined.

23.1.3.7 Map.prototype.has ( key )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[MapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[MapData]] internal slot.
  5. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, return true.
  6. Return false.

23.1.3.8 Map.prototype.keys ( )

The following steps are taken:

  1. Let M be the this value.
  2. Return CreateMapIterator(M, "key").

23.1.3.9 Map.prototype.set ( key , value )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[MapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[MapData]] internal slot.
  5. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValueZero(p.[[key]], key) is true, then
      1. Set p.[[value]] to value.
      2. Return M.
  6. If key is −0, let key be +0.
  7. Let p be the Record {[[key]]: key, [[value]]: value}.
  8. Append p as the last element of entries.
  9. Return M.

23.1.3.10 get Map.prototype.size

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

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[MapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[MapData]] internal slot.
  5. Let count be 0.
  6. For each Record {[[key]], [[value]]} p that is an element of entries
    1. If p.[[key]] is not empty, set count to count+1.
  7. Return count.

23.1.3.11 Map.prototype.values ( )

The following steps are taken:

  1. Let M be the this value.
  2. Return CreateMapIterator(M, "value").

23.1.3.12 Map.prototype [ @@iterator ]( )

The initial value of the @@iterator property is the same function object as the initial value of the entries property.

23.1.3.13 Map.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Map".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

23.1.4 Properties of Map Instances

Map instances are ordinary objects that inherit properties from the Map prototype. Map instances also have a [[MapData]] internal slot.

23.1.5 Map Iterator Objects

A Map Iterator is an object, that represents a specific iteration over some specific Map instance object. There is not a named constructor for Map Iterator objects. Instead, map iterator objects are created by calling certain methods of Map instance objects.

23.1.5.1 CreateMapIterator Abstract Operation

Several methods of Map objects return Iterator objects. The abstract operation CreateMapIterator with arguments map and kind is used to create such iterator objects. It performs the following steps:

  1. If Type(map) is not Object, throw a TypeError exception.
  2. If map does not have a [[MapData]] internal slot, throw a TypeError exception.
  3. Let iterator be ObjectCreate(%MapIteratorPrototype%, «‍[[Map]], [[MapNextIndex]], [[MapIterationKind]]»).
  4. Set iterator’s [[Map]] internal slot to map.
  5. Set iterator’s [[MapNextIndex]] internal slot to 0.
  6. Set iterator’s [[MapIterationKind]] internal slot to kind.
  7. Return iterator.

23.1.5.2 The %MapIteratorPrototype% Object

All Map Iterator Objects inherit properties from the %MapIteratorPrototype% intrinsic object. The %MapIteratorPrototype% intrinsic object is an ordinary object and its [[Prototype]] internal slot is the %IteratorPrototype% intrinsic object (25.1.2). In addition, %MapIteratorPrototype% has the following properties:

23.1.5.2.1 %MapIteratorPrototype%.next ( )

  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 Map Iterator Instance (23.1.5.3), throw a TypeError exception.
  4. Let m be the value of the [[Map]] internal slot of O.
  5. Let index be the value of the [[MapNextIndex]] internal slot of O.
  6. Let itemKind be the value of the [[MapIterationKind]] internal slot of O.
  7. If m is undefined, return CreateIterResultObject(undefined, true).
  8. Assert: m has a [[MapData]] internal slot.
  9. Let entries be the List that is the value of the [[MapData]] internal slot of m.
  10. Repeat while index is less than the total number of elements of entries. The number of elements must be redetermined each time this method is evaluated.
    1. Let e be the Record {[[key]], [[value]]} that is the value of entries[index].
    2. Set index to index+1.
    3. Set the [[MapNextIndex]] internal slot of O to index.
    4. If e.[[key]] is not empty, then
      1. If itemKind is "key", let result be e.[[key]].
      2. Else if itemKind is "value", let result be e.[[value]].
      3. Else,
        1. Assert: itemKind is "key+value".
        2. Let result be CreateArrayFromListe.[[key]], e.[[value]]»).
      4. Return CreateIterResultObject(result, false).
  11. Set the [[Map]] internal slot of O to undefined.
  12. Return CreateIterResultObject(undefined, true).

23.1.5.2.2 %MapIteratorPrototype% [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Map Iterator".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

23.1.5.3 Properties of Map Iterator Instances

Map Iterator instances are ordinary objects that inherit properties from the %MapIteratorPrototype% intrinsic object. Map Iterator instances are initially created with the internal slots described in Table 50.

Table 50 — Internal Slots of Map Iterator Instances
Internal Slot Description
[[Map]] The Map object that is being iterated.
[[MapNextIndex]] The integer index of the next Map data element to be examined by this iterator.
[[MapIterationKind]] A String value that identifies what is to be returned for each element of the iteration. The possible values are: "key", "value", "key+value".

23.2 Set Objects

Set objects are collections of ECMAScript language values. A distinct value may only occur once as an element of a Set's collection. Distinct values are discriminated using the SameValueZero comparison algorithm.

Set objects 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 structures used in this Set objects specification is only intended to describe the required observable semantics of Set objects. It is not intended to be a viable implementation model.

23.2.1 The Set Constructor

The Set constructor is the %Set% intrinsic object and the initial value of the Set property of the global object. When called as a constructor it creates and initializes a new Set object. Set is not intended to be called as a function and will throw an exception when called in that manner.

The Set 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 Set behaviour must include a super call to the Set constructor to create and initialize the subclass instance with the internal state necessary to support the Set.prototype built-in methods.

23.2.1.1 Set ( [ iterable ] )

When the Set function is called with optional argument iterable the following steps are taken:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let set be OrdinaryCreateFromConstructor(NewTarget, "%SetPrototype%", «‍[[SetData]]» ).
  3. ReturnIfAbrupt(set).
  4. Set set’s [[SetData]] internal slot to a new empty List.
  5. If iterable is not present, let iterable be undefined.
  6. If iterable is either undefined or null, let iter be undefined.
  7. Else,
    1. Let adder be Get(set, "add").
    2. ReturnIfAbrupt(adder).
    3. If IsCallable(adder) is false, throw a TypeError exception.
    4. Let iter be GetIterator(iterable).
    5. ReturnIfAbrupt(iter).
  8. If iter is undefined, return set.
  9. Repeat
    1. Let next be IteratorStep(iter).
    2. ReturnIfAbrupt(next).
    3. If next is false, return set.
    4. Let nextValue be IteratorValue(next).
    5. ReturnIfAbrupt(nextValue).
    6. Let status be Call(adder, set, «nextValue.[[value]]»).
    7. If status is an abrupt completion, return IteratorClose(iter, status).

23.2.2 Properties of the Set Constructor

The value of the [[Prototype]] internal slot of the Set constructor is the intrinsic object %FunctionPrototype% (19.2.3).

Besides the length property (whose value is 0), the Set constructor has the following properties:

23.2.2.1 Set.prototype

The initial value of Set.prototype is the intrinsic %SetPrototype% object (23.2.3).

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

23.2.2.2 get Set [ @@species ]

Set[@@species] is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Return the this value.

The value of the name property of this function is "get [Symbol.species]".

NOTE Methods that create derived collection objects should call @@species to determine the constructor to use to create the derived objects. Subclass constructor may over-ride @@species to change the default constructor assignment.

23.2.3 Properties of the Set Prototype Object

The Set prototype object is the intrinsic object %SetPrototype%. The value of the [[Prototype]] internal slot of the Set prototype object is the intrinsic object %ObjectPrototype% (19.1.3). The Set prototype object is an ordinary object. It does not have a [[SetData]] internal slot.

23.2.3.1 Set.prototype.add ( value )

The following steps are taken:

  1. Let S be the this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[SetData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of S's [[SetData]] internal slot.
  5. Repeat for each e that is an element of entries,
    1. If e is not empty and SameValueZero(e, value) is true, then
      1. Return S.
  6. If value is −0, let value be +0.
  7. Append value as the last element of entries.
  8. Return S.

23.2.3.2 Set.prototype.clear ( )

The following steps are taken:

  1. Let S be this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[SetData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of S's [[SetData]] internal slot.
  5. Repeat for each e that is an element of entries,
    1. Replace the element of entries whose value is e with an element whose value is empty.
  6. Return undefined.

23.2.3.3 Set.prototype.constructor

The initial value of Set.prototype.constructor is the intrinsic object %Set%.

23.2.3.4 Set.prototype.delete ( value )

The following steps are taken:

  1. Let S be the this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[SetData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of S's [[SetData]] internal slot.
  5. Repeat for each e that is an element of entries,
    1. If e is not empty and SameValueZero(e, value) is true, then
      1. Replace the element of entries whose value is e with an element whose value is empty.
      2. Return true.
  6. Return false.

NOTE The value empty is used as a specification device to indicate that an entry has been deleted. Actual implementations may take other actions such as physically removing the entry from internal data structures.

23.2.3.5 Set.prototype.entries ( )

The following steps are taken:

  1. Let S be the this value.
  2. Return CreateSetIterator(S, "key+value").

NOTE For iteration purposes, a Set appears similar to a Map where each entry has the same value for its key and value.

23.2.3.6 Set.prototype.forEach ( callbackfn [ , thisArg ] )

When the forEach method is called with one or two arguments, the following steps are taken:

  1. Let S be the this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[SetData]] internal slot, throw a TypeError exception.
  4. If IsCallable(callbackfn) is false, throw a TypeError exception.
  5. If thisArg was supplied, let T be thisArg; else let T be undefined.
  6. Let entries be the List that is the value of S's [[SetData]] internal slot.
  7. Repeat for each e that is an element of entries, in original insertion order
    1. If e is not empty, then
      1. Let funcResult be Call(callbackfn, T, «e, e, S»).
      2. ReturnIfAbrupt(funcResult).
  8. Return undefined.

The length property of the forEach method is 1.

NOTE callbackfn should be a function that accepts three arguments. forEach calls callbackfn once for each value present in the set object, in value insertion order. callbackfn is called only for values of the Set which actually exist; it is not called for keys that have been deleted from the set.

If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackfn. If it is not provided, undefined is used instead.

callbackfn is called with three arguments: the first two arguments are a value contained in the Set. The same value is passed for both arguments. The Set object being traversed is passed as the third argument.

The callbackfn is called with three arguments to be consistent with the call back functions used by forEach methods for Map and Array. For Sets, each item value is considered to be both the key and the value.

forEach does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.

Each value is normally visited only once. However, a value will be revisited if it is deleted after it has been visited and then re-added before the forEach call completes. Values that are deleted after the call to forEach begins and before being visited are not visited unless the value is added again before the forEach call completes. New values added after the call to forEach begins are visited.

23.2.3.7 Set.prototype.has ( value )

The following steps are taken:

  1. Let S be the this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[SetData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of S's [[SetData]] internal slot.
  5. Repeat for each e that is an element of entries,
    1. If e is not empty and SameValueZero(e, value) is true, return true.
  6. Return false.

23.2.3.8 Set.prototype.keys ( )

The initial value of the keys property is the same function object as the initial value of the values property.

NOTE For iteration purposes, a Set appears similar to a Map where each entry has the same value for its key and value.

23.2.3.9 get Set.prototype.size

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

  1. Let S be the this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[SetData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of S's [[SetData]] internal slot.
  5. Let count be 0.
  6. For each e that is an element of entries
    1. If e is not empty, set count to count+1.
  7. Return count.

23.2.3.10 Set.prototype.values ( )

The following steps are taken:

  1. Let S be the this value.
  2. Return CreateSetIterator(S, "value").

23.2.3.11 Set.prototype [ @@iterator ] ( )

The initial value of the @@iterator property is the same function object as the initial value of the values property.

23.2.3.12 Set.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Set".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

23.2.4 Properties of Set Instances

Set instances are ordinary objects that inherit properties from the Set prototype. Set instances also have a [[SetData]] internal slot.

23.2.5 Set Iterator Objects

A Set Iterator is an ordinary object, with the structure defined below, that represents a specific iteration over some specific Set instance object. There is not a named constructor for Set Iterator objects. Instead, set iterator objects are created by calling certain methods of Set instance objects.

23.2.5.1 CreateSetIterator Abstract Operation

Several methods of Set objects return Iterator objects. The abstract operation CreateSetIterator with arguments set and kind is used to create such iterator objects. It performs the following steps:

  1. If Type(set) is not Object, throw a TypeError exception.
  2. If set does not have a [[SetData]] internal slot, throw a TypeError exception.
  3. Let iterator be ObjectCreate(%SetIteratorPrototype%, «‍[[IteratedSet]], [[SetNextIndex]], [[SetIterationKind]]»).
  4. Set iterator’s [[IteratedSet]] internal slot to set.
  5. Set iterator’s [[SetNextIndex]] internal slot to 0.
  6. Set iterator’s [[SetIterationKind]] internal slot to kind.
  7. Return iterator.

23.2.5.2 The %SetIteratorPrototype% Object

All Set Iterator Objects inherit properties from the %SetIteratorPrototype% intrinsic object. The %SetIteratorPrototype% intrinsic object is an ordinary object and its [[Prototype]] internal slot is the %IteratorPrototype% intrinsic object (25.1.2). In addition, %SetIteratorPrototype% has the following properties:

23.2.5.2.1 %SetIteratorPrototype%.next ( )

  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 Set Iterator Instance (23.2.5.3), throw a TypeError exception.
  4. Let s be the value of the [[IteratedSet]] internal slot of O.
  5. Let index be the value of the [[SetNextIndex]] internal slot of O.
  6. Let itemKind be the value of the [[SetIterationKind]] internal slot of O.
  7. If s is undefined, return CreateIterResultObject(undefined, true).
  8. Assert: s has a [[SetData]] internal slot.
  9. Let entries be the List that is the value of the [[SetData]] internal slot of s.
  10. Repeat while index is less than the total number of elements of entries. The number of elements must be redetermined each time this method is evaluated.
    1. Let e be entries[index].
    2. Set index to index+1;
    3. Set the [[SetNextIndex]] internal slot of O to index.
    4. If e is not empty, then
      1. If itemKind is "key+value", then
        1. Return CreateIterResultObject(CreateArrayFromListe, e»), false).
      2. Return CreateIterResultObject(e, false).
  11. Set the [[IteratedSet]] internal slot of O to undefined.
  12. Return CreateIterResultObject(undefined, true).

23.2.5.2.2 %SetIteratorPrototype% [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Set Iterator".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

23.2.5.3 Properties of Set Iterator Instances

Set Iterator instances are ordinary objects that inherit properties from the %SetIteratorPrototype% intrinsic object. Set Iterator instances are initially created with the internal slots specified in Table 51.

Table 51 — Internal Slots of Set Iterator Instances
Internal Slot Description
[[IteratedSet]] The Set object that is being iterated.
[[SetNextIndex]] The integer index of the next Set data element to be examined by this iterator
[[SetIterationKind]] A Sring value that identifies what is to be returned for each element of the iteration. The possible values are: "key", "value", "key+value". "key" and "value" have the same meaning.

23.3 WeakMap Objects

WeakMap objects 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. If an object that is being used as the key of a WeakMap key/value pair is only reachable by following a chain of references that start within that WeakMap, then that key/value pair is inaccessible and is automatically removed from the WeakMap. WeakMap implementations must detect and remove such key/value pairs and any associated resources.

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.

WeakMap objects 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 WeakMap objects specification are only intended to describe the required observable semantics of WeakMap objects. It is not intended to be a viable implementation model.

NOTE 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. Achieving 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:

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

23.3.1 The WeakMap Constructor

The WeakMap constructor is the %WeakMap% intrinsic object and the initial value of the WeakMap property of the global object. When called as a constructor it creates and initializes a new WeakMap object. WeakMap is not intended to be called as a function and will throw an exception when called in that manner.

The WeakMap 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 WeakMap behaviour must include a super call to the WeakMap constructor to create and initialize the subclass instance with the internal state necessary to support the WeakMap.prototype built-in methods.

23.3.1.1 WeakMap ( [ iterable ] )

When the WeakMap function is called with optional argument iterable the following steps are taken:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let map be OrdinaryCreateFromConstructor(NewTarget, "%WeakMapPrototype%", «‍[[WeakMapData]]» ).
  3. ReturnIfAbrupt(map).
  4. Set map’s [[WeakMapData]] internal slot to a new empty List.
  5. If iterable is not present, let iterable be undefined.
  6. If iterable is either undefined or null, let iter be undefined.
  7. Else,
    1. Let adder be Get(map, "set").
    2. ReturnIfAbrupt(adder).
    3. If IsCallable(adder) is false, throw a TypeError exception.
    4. Let iter be GetIterator(iterable).
    5. ReturnIfAbrupt(iter).
  8. If iter is undefined, return map.
  9. Repeat
    1. Let next be IteratorStep(iter).
    2. ReturnIfAbrupt(next).
    3. If next is false, return map.
    4. Let nextItem be IteratorValue(next).
    5. ReturnIfAbrupt(nextItem).
    6. If Type(nextItem) is not Object,
      1. Let error be Completion{[[type]]: throw, [[value]]: a newly created TypeError object, [[target]]:empty}.
      2. Return IteratorClose(iter, error).
    7. Let k be Get(nextItem, "0").
    8. If k is an abrupt completion, return IteratorClose(iter, k).
    9. Let v be Get(nextItem, "1").
    10. If v is an abrupt completion, return IteratorClose(iter, v).
    11. Let status be Call(adder, map, «k.[[value]], v.[[value]]»).
    12. If status is an abrupt completion, return IteratorClose(iter, status).

NOTE If the parameter iterable is present, it is expected to be an object that implements an @@iterator method that returns an iterator object that produces a two element array-like object whose first element is a value that will be used as a WeakMap key and whose second element is the value to associate with that key.

23.3.2 Properties of the WeakMap Constructor

The value of the [[Prototype]] internal slot of the WeakMap constructor is the intrinsic object %FunctionPrototype% (19.2.3).

Besides the length property (whose value is 0), the WeakMap constructor has the following properties:

23.3.2.1 WeakMap.prototype

The initial value of WeakMap.prototype is the intrinsic object %WeakMapPrototype% (23.3.3).

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

23.3.3 Properties of the WeakMap Prototype Object

The WeakMap prototype object is the intrinsic object %WeakMapPrototype%. The value of the [[Prototype]] internal slot of the WeakMap prototype object is the intrinsic object %ObjectPrototype% (19.1.3). The WeakMap prototype object is an ordinary object. It does not have a [[WeakMapData]] internal slot.

23.3.3.1 WeakMap.prototype.constructor

The initial value of WeakMap.prototype.constructor is the intrinsic object %WeakMap%.

23.3.3.2 WeakMap.prototype.delete ( key )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[WeakMapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[WeakMapData]] internal slot.
  5. If Type(key) is not Object, return false.
  6. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValue(p.[[key]], key) is true, then
      1. Set p.[[key]] to empty.
      2. Set p.[[value]] to empty.
      3. Return true.
  7. Return false.

NOTE The value empty is used as a specification device to indicate that an entry has been deleted. Actual implementations may take other actions such as physically removing the entry from internal data structures.

23.3.3.3 WeakMap.prototype.get ( key )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[WeakMapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[WeakMapData]] internal slot.
  5. If Type(key) is not Object, return undefined.
  6. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValue(p.[[key]], key) is true, return p.[[value]].
  7. Return undefined.

23.3.3.4 WeakMap.prototype.has ( key )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[WeakMapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[WeakMapData]] internal slot.
  5. If Type(key) is not Object, return false.
  6. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValue(p.[[key]], key) is true, return true.
  7. Return false.

23.3.3.5 WeakMap.prototype.set ( key , value )

The following steps are taken:

  1. Let M be the this value.
  2. If Type(M) is not Object, throw a TypeError exception.
  3. If M does not have a [[WeakMapData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of M's [[WeakMapData]] internal slot.
  5. If Type(key) is not Object, throw a TypeError exception.
  6. Repeat for each Record {[[key]], [[value]]} p that is an element of entries,
    1. If p.[[key]] is not empty and SameValue(p.[[key]], key) is true, then
      1. Set p.[[value]] to value.
      2. Return M.
  7. Let p be the Record {[[key]]: key, [[value]]: value}.
  8. Append p as the last element of entries.
  9. Return M.

23.3.3.6 WeakMap.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "WeakMap".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

23.3.4 Properties of WeakMap Instances

WeakMap instances are ordinary objects that inherit properties from the WeakMap prototype. WeakMap instances also have a [[WeakMapData]] internal slot.

23.4 WeakSet Objects

WeakSet objects 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. If an object that is contained by a WeakSet is only reachable by following a chain of references that start within that WeakSet, then that object is inaccessible and is automatically removed from the WeakSet. WeakSet implementations must detect and remove such objects and any associated resources.

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.

WeakSet objects 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 WeakSet objects specification is only intended to describe the required observable semantics of WeakSet objects. It is not intended to be a viable implementation model.

NOTE See the NOTE in 23.3.

23.4.1 The WeakSet Constructor

The WeakSet constructor is the %WeakSet% intrinsic object and the initial value of the WeakSet property of the global object. When called as a constructor it creates and initializes a new WeakSet object. WeakSet is not intended to be called as a function and will throw an exception when called in that manner.

The WeakSet 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 WeakSet behaviour must include a super call to the WeakSet constructor to create and initialize the subclass instance with the internal state necessary to support the WeakSet.prototype built-in methods.

23.4.1.1 WeakSet ( [ iterable ] )

When the WeakSet function is called with optional argument iterable the following steps are taken:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let set be OrdinaryCreateFromConstructor(NewTarget, "%WeakSetPrototype%", «‍[[WeakSetData]]» ).
  3. ReturnIfAbrupt(set).
  4. Set set’s [[WeakSetData]] internal slot to a new empty List.
  5. If iterable is not present, let iterable be undefined.
  6. If iterable is either undefined or null, let iter be undefined.
  7. Else,
    1. Let adder be Get(set, "add").
    2. ReturnIfAbrupt(adder).
    3. If IsCallable(adder) is false, throw a TypeError exception.
    4. Let iter be GetIterator(iterable).
    5. ReturnIfAbrupt(iter).
  8. If iter is undefined, return set.
  9. Repeat
    1. Let next be IteratorStep(iter).
    2. ReturnIfAbrupt(next).
    3. If next is false, return set.
    4. Let nextValue be IteratorValue(next).
    5. ReturnIfAbrupt(nextValue).
    6. Let status be Call(adder, set, «nextValue »).
    7. If status is an abrupt completion, return IteratorClose(iter, status).

23.4.2 Properties of the WeakSet Constructor

The value of the [[Prototype]] internal slot of the WeakSet constructor is the intrinsic object %FunctionPrototype% (19.2.3).

Besides the length property (whose value is 0), the WeakSet constructor has the following properties:

23.4.2.1 WeakSet.prototype

The initial value of WeakSet.prototype is the intrinsic %WeakSetPrototype% object (23.4.3).

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

23.4.3 Properties of the WeakSet Prototype Object

The WeakSet prototype object is the intrinsic object %WeakSetPrototype%. The value of the [[Prototype]] internal slot of the WeakSet prototype object is the intrinsic object %ObjectPrototype% (19.1.3). The WeakSet prototype object is an ordinary object. It does not have a [[WeakSetData]] internal slot.

23.4.3.1 WeakSet.prototype.add ( value )

The following steps are taken:

  1. Let S be the this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[WeakSetData]] internal slot, throw a TypeError exception.
  4. If Type(value) is not Object, throw a TypeError exception.
  5. Let entries be the List that is the value of S's [[WeakSetData]] internal slot.
  6. Repeat for each e that is an element of entries,
    1. If e is not empty and SameValue(e, value) is true, then
      1. Return S.
  7. Append value as the last element of entries.
  8. Return S.

23.4.3.2 WeakSet.prototype.constructor

The initial value of WeakSet.prototype.constructor is the %WeakSet% intrinsic object.

23.4.3.3 WeakSet.prototype.delete ( value )

The following steps are taken:

  1. Let S be the this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[WeakSetData]] internal slot, throw a TypeError exception.
  4. If Type(value) is not Object, return false.
  5. Let entries be the List that is the value of S's [[WeakSetData]] internal slot.
  6. Repeat for each e that is an element of entries,
    1. If e is not empty and SameValue(e, value) is true, then
      1. Replace the element of entries whose value is e with an element whose value is empty.
      2. Return true.
  7. Return false.

NOTE The value empty is used as a specification device to indicate that an entry has been deleted. Actual implementations may take other actions such as physically removing the entry from internal data structures.

23.4.3.4 WeakSet.prototype.has ( value )

The following steps are taken:

  1. Let S be the this value.
  2. If Type(S) is not Object, throw a TypeError exception.
  3. If S does not have a [[WeakSetData]] internal slot, throw a TypeError exception.
  4. Let entries be the List that is the value of S's [[WeakSetData]] internal slot.
  5. If Type(value) is not Object, return false.
  6. Repeat for each e that is an element of entries,
    1. If e is not empty and SameValue(e, value) is true, return true.
  7. Return false.

23.4.3.5 WeakSet.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "WeakSet".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

23.4.4 Properties of WeakSet Instances

WeakSet instances are ordinary objects that inherit properties from the WeakSet prototype. WeakSet instances also have a [[WeakSetData]] internal slot.