New collections methods

1 Formal informations

2 Set.prototype methods

2.1 Set.prototype.filter( callbackfn [ , thisArg ] )

When the filter method is called, the following steps are taken:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[SetData]]).
  3. If IsCallable(callbackfn) is false, throw a TypeError exception.
  4. Let resultSetData be a new empty List.
  5. Let entries be O.[[SetData]]
  6. Let thisSize be the number of elements in O.[[SetData]].
  7. Let index be 0.
  8. Repeat, while index < thisSize,
    1. Let e be O.[[SetData]][index].
    2. Set index to index + 1.
    3. If e is not empty, then
      1. Let selected be ToBoolean(? Call(callbackfn, thisArg, « kValue, kValue, O »)).
      2. If selected is true, then:
        1. Append e to resultSetData.
  9. Let result be OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »).
  10. Set result.[[SetData]] to resultSetData.
  11. Return result.

2.2 Set.prototype.map( callbackfn [ , thisArg ] )

When the map method is called, the following steps are taken:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[SetData]]).
  3. If IsCallable(callbackfn) is false, throw a TypeError exception.
  4. Let resultSetData be a new empty List.
  5. Let entries be O.[[SetData]]
  6. Let thisSize be the number of elements in O.[[SetData]].
  7. Let index be 0.
  8. Repeat, while index < thisSize,
    1. Let e be O.[[SetData]][index].
    2. Set index to index + 1.
    3. If e is not empty, then
      1. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, kValue, O »).
      2. Append mappedValue to resultSetData.
  9. Let result be OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »).
  10. Set result.[[SetData]] to resultSetData.
  11. Return result.

2.3 Set.prototype.find( predicate [ , thisArg ] )

When the find method is called, the following steps are taken:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[SetData]]).
  3. If IsCallable(predicate) is false, throw a TypeError exception.
  4. Let entries be O.[[SetData]]
  5. Let thisSize be the number of elements in O.[[SetData]].
  6. Let index be 0.
  7. Repeat, while index < thisSize,
    1. Let e be O.[[SetData]][index].
    2. Set index to index + 1.
    3. If e is not empty, then
      1. Let testResult be ToBoolean(? Call(predicate, thisArg, « e, e, O »))
      2. If testResult is true, then return e
  8. Return undefined.

2.4 Set.prototype.some( predicate [ , thisArg ] )

When the some method is called, the following steps are taken:

  1. Let set be the this value.
    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.
  2. If IsCallable(predicate) is false, throw a TypeError exception.
  3. Let entries be O.[[SetData]]
  4. Let thisSize be the number of elements in O.[[SetData]].
  5. Let index be 0.
  6. Repeat, while index < thisSize,
    1. Let e be O.[[SetData]][index].
    2. Set index to index + 1.
    3. If e is not empty, then
      1. Let testResult be ToBoolean(? Call(predicate, thisArg, « e, e, O »))
      2. If testResult is true, then return testResult
  7. Return false.

2.5 Set.prototype.every( predicate [ , thisArg ] )

When the every method is called, the following steps are taken:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[SetData]]).
  3. If IsCallable(predicate) is false, throw a TypeError exception.
  4. Let entries be O.[[SetData]]
  5. Let thisSize be the number of elements in O.[[SetData]].
  6. Let index be 0.
  7. Repeat, while index < thisSize,
    1. Let e be O.[[SetData]][index].
    2. Set index to index + 1.
    3. If e is not empty, then
      1. Let testResult be ToBoolean(? Call(predicate, thisArg, « e, e, set »))
      2. If testResult is false, then return false
  8. Return true.

2.6 Set.prototype.reduce( callbackfn [ , initialValue ] )

When the reduce method is called, the following steps are taken:

  1. Let set be the this value.
    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.
  2. If IsCallable(callbackfn) is false, throw a TypeError exception.
  3. Let entries be the List that is set.[[SetData]].
  4. Let accumulator be undefined
  5. Let first be true.
  6. If initialValue is present, then
    1. Set accumulator to initialValue
  7. For each e that is an element of entries, in original insertion order, do:
    1. If e is not empty, then
      1. If first be true and initialValue is not present:
        1. Set accumulator to e
      2. Else,
        1. Set accumulator to ? Call(callbackfn, undefined, « accumulator, e, e, map »)
      3. Set first to false
  8. If first is true and initialValue is not present, throw TypeError exception.
  9. Return accumulator.

2.7 Set.prototype.join( [ separator ] )

When the join method is called, the following steps are taken:

  1. Let set be the this value.
    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.
  2. If separator is undefined, let sep be the single-element String ",".
  3. Else, let sep be ? ToString(separator).
  4. Let R be the empty String.
  5. Let k be false.
  6. Let entries be O.[[SetData]]
  7. Let thisSize be the number of elements in O.[[SetData]].
  8. Let index be 0.
  9. Repeat, while index < thisSize,
    1. Let e be O.[[SetData]][index].
    2. Set index to index + 1.
    3. If e is not empty, then
      1. If k is true, let R be the string-concatenation of R and sep.
      2. Set k to true.
      3. Let next be ? ToString(e).
      4. Set R to the string-concatenation of R and next.
  10. Return R.

2.8 Set.prototype.addAll(...items)

When the addAll method is called, the following steps are taken:

  1. Let len be the actual number of arguments passed to this function.
  2. Let items be the List of arguments passed to this function.
  3. Let set be the this value.
    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.
  4. Let elements be CreateArrayFromList(items).
  5. Let adder be ? Get(set, "add")
  6. Return ? AddEntriesFromIterable(set, elements, adder).

The length property of the addAll method is 0.

2.9 Set.prototype.deleteAll(...items)

When the deleteAll method is called, the following steps are taken:

  1. Let len be the actual number of arguments passed to this function.
  2. Let items be the List of arguments passed to this function.
  3. Let set be the this value.
    1. If Type(set) is not Object, throw a TypeError exception.
  4. Let k be 0.
  5. Let remover be ? Get(set, "delete")
  6. If IsCallable(remover) is false, throw a TypeError exception.
  7. Let allDeleted be true.
  8. Repeat while k < len
    1. Let value be items[k].
    2. Let wasDeleted be Call(remover, set, value)
    3. Set allDeleted to be allDeleted && wasDeleted
    4. Increase k by 1.
  9. Return ToBoolean(allDeleted);

3 Map.prototype methods

3.1 Map.prototype.mapValues( callbackfn, [ thisArg ] )

Editor's Note
This code serves as placeholder until formal spec is written for this method.
function mapValues(callbackFn, thisArg) {
    assert(isObject(this), 'this is not an object');
    assert(isCallable(callbackFn), 'callback is not a function');
    const Ctor = SpeciesConstructor(this, Map);
    const retObj = new Ctor();
    const _set = retObj.set;
    for(const [key, value] of this) {
        const newValue = Reflect.apply(callbackFn, thisArg, [value, key, this])
        Reflect.apply(_set, retObj, [key, newValue]);
    }
    return retObj;
}

3.2 Map.prototype.mapKeys( callbackfn, [ thisArg ] )

Editor's Note
This code serves as placeholder until formal spec is written for this method.
function mapKeys(callbackFn, thisArg) {
    assert(isObject(this), 'this is not an object');
    assert(isCallable(callbackFn), 'callback is not a function');
    const Ctor = SpeciesConstructor(this, Map);
    const retObj = new Ctor();
    const _set = retObj.set;
    for(const [key, value] of this) {
        const newKey = Reflect.apply(callbackFn, thisArg, [value, key, this])
        Reflect.apply(_set, retObj, [newKey, value]);
    }
    return retObj;
}

3.3 Map.prototype.filter( callbackfn, [ thisArg ] )

Editor's Note
This code serves as placeholder until formal spec is written for this method.
  1. Let map be the this value.
    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.
  2. If IsCallable(callbackfn) is false, throw a TypeError exception.
  3. If thisArg was supplied, let T be thisArg; else let T be undefined.
  4. Let Ctr be ? SpeciesConstructor(map, %Map%)
  5. Let newMap be ? Construct(Ctr)
  6. Let adder be ? Get(newSet, "set")
    1. If IsCallable(adder) is false, throw a TypeError.
  7. Let entries be the List that is map.[[MapData]]
  8. Let newMapData be new empty List.
  9. For each Record { [[Key]], [[Value]] } p that is an element of entries, do
    1. If p.[[Key]] is not empty, then
      1. Let key be p.[[Key]]
      2. Let value be p.[[Value]]
      3. Let selected be ToBoolean(? Call(callbackfn, T, « value, key, map »))
      4. If selected is true, then
        1. Let pair be CreateArrayFromList(« value, key »)
        2. Append pair as last element to newMapData.
  10. Return ? AddEntriesFromIterable(map, CreateArrayFromList(newMapData), adder).

3.4 Map.prototype.find( callbackfn [ , thisArg ] )

When the find method is called, the following steps are taken:

  1. Let map be the this value.
    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.
  2. If IsCallable(callbackfn) is false, throw a TypeError exception.
  3. If thisArg was supplied, let T be thisArg; else let T be undefined.
  4. Let entries be the List that is map.[[MapData]].
  5. For each Record { [[Key]], [[Value]] } e that is an element of entries, in original key insertion order, do:
    1. If e.[[Key]] is not empty, then
      1. Let testResult be ToBoolean(? Call(callbackfn, T, « e.[[Value]], e.[[Key]], map »)).
      2. If testResult is true, then return e.[[Value]].
  6. Return undefined.

3.5 Map.prototype.findKey( callbackfn [ , thisArg ] )

When the findKey method is called, the following steps are taken:

  1. Let map be the this value.
    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.
  2. If IsCallable(callbackfn) is false, throw a TypeError exception.
  3. If thisArg was supplied, let T be thisArg; else let T be undefined.
  4. Let entries be the List that is map.[[MapData]].
  5. For each Record { [[Key]], [[Value]] } e that is an element of entries, in original key insertion order, do:
    1. If e.[[Key]] is not empty, then
      1. Let testResult be ToBoolean(? Call(callbackfn, T, « e.[[Value]], e.[[Key]], map »)).
      2. If testResult is true, then return e.[[Key]].
  6. Return undefined.

3.6 Map.prototype.keyOf( searchElement )

When the keyOf method is called, the following steps are taken:

  1. Let map be the this value.
    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.
  2. Let entries be the List that is map.[[MapData]].
  3. For each Record { [[Key]], [[Value]] } e that is an element of entries, in original key insertion order, do:
    1. If e.[[Key]] is not empty, then
      1. Let same be the result of performing Strict Equality Comparison searchElement === e.[[Value]].
      2. If same is true, then return e.[[Key]].
  4. Return undefined.

3.7 Map.prototype.some( callbackfn [ , thisArg ] )

When the some method is called, the following steps are taken:

  1. Let map be the this value.
    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.
  2. If IsCallable(callbackfn) is false, throw a TypeError exception.
  3. If thisArg was supplied, let T be thisArg; else let T be undefined.
  4. Let entries be the List that is map.[[MapData]].
  5. For each Record { [[Key]], [[Value]] } e that is an element of entries, in original key insertion order, do:
    1. If e.[[Key]] is not empty, then
      1. Let testResult be ToBoolean(? Call(callbackfn, T, « e.[[Value]], e.[[Key]], map »))
      2. If testResult is true, then return true
  6. Return false.

3.8 Map.prototype.every( predicate [ , thisArg ] )

When the every method is called, the following steps are taken:

  1. Let M be the this value.
  2. Perform ? RequireInternalSlot(M, [[MapData]]).
  3. If IsCallable(predicate) is **false*, throw a *TypeError exception.
  4. Let entries be the List that is map.[[MapData]].
  5. For each Record { [[Key]], [[Value]] } e of M.[[MapData]], do
    1. If e.[[Key]] is not empty, then
      1. Let testResult be ToBoolean(? Call(predicate, T, « e.[[Value]], e.[[Key]], map »))
      2. If testResult is false, then return false
  6. Return true.

3.9 Map.prototype.includes( searchElement )

When the includes method is called, the following steps are taken:

  1. Let map be the this value.
    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.
  2. Let entries be the List that is map.[[MapData]].
  3. For each Record { [[Key]], [[Value]] } e that is an element of entries, in original key insertion order, do:
    1. If e.[[Key]] is not empty, then
      1. If SameValueZero(searchElement, e.[[Value]]) is true, return true.
  4. Return false.

3.10 Map.prototype.reduce( callbackfn [ , initialValue ] )

When the reduce method is called, the following steps are taken:

  1. Let map be the this value.
    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.
  2. If IsCallable(callbackfn) is false, throw a TypeError exception.
  3. Let entries be the List that is map.[[MapData]].
  4. Let accumulator be undefined
  5. Let first be true.
  6. If initialValue is present, then
    1. Set accumulator to initialValue
  7. For each Record { [[Key]], [[Value]] } e that is an element of entries, in original key insertion order, do:
    1. If e.[[Key]] is not empty, then
      1. If first be true and initialValue is not present:
        1. Set accumulator to e.[[Value]]
      2. Else,
        1. Set accumulator to ? Call(callbackfn, undefined, « accumulator, e.[[Value]], e.[[Key]], map »)
      3. Set first to false
  8. If first is true and initialValue is not present, throw TypeError exception.
  9. Return accumulator.

3.11 Map.prototype.merge(... iterables )

Editor's Note
This code serves as placeholder until formal spec is written for this method.
function merge(...iterables) {
    assert(isObject(this), 'this is not an object');
    assert(this instanceof Map, 'this is not a Map instance');
    for(const iterable of iterables) {
        for(const [key, value] of iterable) {
            this.set(key, value);
        }
    }

    return this;
}

3.12 Map.prototype.deleteAll(...items)

When the deleteAll method is called, the following steps are taken:

The length property of the deleteAll method is 0.

  1. Let len be the actual number of arguments passed to this function.
  2. Let items be the List of arguments passed to this function.
  3. Let map be the this value.
    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.
  4. Let k be 0.
  5. Let remover be ? Get(map, "delete")
  6. If IsCallable(remover) is false, throw a TypeError exception.
  7. Repeat while k < len
    1. Let value be items[k].
    2. Call(remover, map, value)
    3. Increase k by 1.
  8. Return map.

3.13 Map.prototype.update(key, callback [, thunk])

Editor's Note
This code serves as placeholder until formal spec is written for this method.
function update(key, cb, thunk) {
    assert(isObject(this), 'this is not an object');
    assert(isCallable(callbackFn), 'callback is not a function');
    asset(isMap(this), 'this is not a Map instance');
    const isPresentInMap = this.has(key);
    if (isPresentInMap === false && arguments.length < 3) {
        throw new Error('Invalid!');
    }
    const value = isPresentInMap ? this.get(key) : thunk(key, this);
    const newValue = cb(value, key, this);
    this.set(key, newValue);
    return this;
}

4 Map static methods

4.1 Map.keyBy( iterable, callbackfn)

When the keyBy method is called, the following steps are taken:

  1. Let C be the this value.
  2. If IsConstructor(C) is true
    1. Let map be ? Construct(C)
  3. Else,
    1. Throw a TypeError.
  4. If map does not have a [[MapData]] internal slot, throw a TypeError exception.
  5. If IsCallable(callbackfn) is false, throw a TypeError exception.
  6. Let set be ? Get(map, "set")
  7. Let iteratorRecord be ? GetIterator(iterable).
  8. Repeat,
    1. Let next be ? IteratorStep(iteratorRecord).
    2. If next is false, return map.
    3. Let item be ? IteratorValue(next).
    4. Let key be Call(callbackfn, null, « item »)
    5. Let status be Call(set, map, « key.[[Value]], value.[[Value]] »).
    6. If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).

5 WeakSet.prototype.addAll(...items)

When the addAll method is called, the following steps are taken:

  1. Let len be the actual number of arguments passed to this function.
  2. Let items be the List of arguments passed to this function.
  3. Let weakset be the this value.
    1. If Type(weakset) is not Object, throw a TypeError exception.
  4. Let k be 0.
  5. Let adder be ? Get(weakset, "add")
  6. If IsCallable(adder) is false, throw a TypeError exception.
  7. Repeat while k < len
    1. Let kValue be items[k].
    2. Call(adder, weakset, kValue)
    3. Increase k by 1.
  8. Return weakset.

The length property of the addAll method is 0.

6 WeakSet.prototype.deleteAll(...items)

When the deleteAll method is called, the following steps are taken:

  1. Let len be the actual number of arguments passed to this function.
  2. Let items be the List of arguments passed to this function.
  3. Let weakset be the this value.
    1. If Type(weakset) is not Object, throw a TypeError exception.
  4. Let k be 0.
  5. Let remover be ? Get(weakset, "delete")
  6. If IsCallable(remover) is false, throw a TypeError exception.
  7. Repeat while k < len
    1. Let value be items[k].
    2. Call(remover, weakset, value)
    3. Increase k by 1.
  8. Return weakset.

The length property of the deleteAll method is 0.

7 WeakMap.prototype.deleteAll(...items)

When the deleteAll method is called, the following steps are taken:

  1. Let len be the actual number of arguments passed to this function.
  2. Let items be the List of arguments passed to this function.
  3. Let weakmap be the this value.
    1. If Type(weakmap) is not Object, throw a TypeError exception.
  4. Let k be 0.
  5. Let remover be ? Get(weakmap, "delete")
  6. If IsCallable(remover) is false, throw a TypeError exception.
  7. Repeat while k < len
    1. Let value be items[k].
    2. Call(remover, weakmap, value)
    3. Increase k by 1.
  8. Return weakmap.

The length property of the deleteAll method is 0.

A Copyright & Software License

Copyright Notice

© 2024 Michał Wadas, Ecma International

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.