immutable
Version:
Immutable Data Collections
1,459 lines (1,287 loc) • 199 kB
JavaScript
/**
* @license
* MIT License
*
* Copyright (c) 2014-present, Lee Byron and other contributors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Immutable = {}));
})(this, (function (exports) { 'use strict';
// Used for setting prototype methods that IE8 chokes on.
var DELETE = 'delete';
// Constants describing the size of trie nodes.
var SHIFT = 5; // Resulted in best performance after ______?
var SIZE = 1 << SHIFT;
var MASK = SIZE - 1;
// A consistent shared value representing "not set" which equals nothing other
// than itself, and nothing that could be provided externally.
var NOT_SET = {};
// Boolean references, Rough equivalent of `bool &`.
function MakeRef() {
return { value: false };
}
function SetRef(ref) {
if (ref) {
ref.value = true;
}
}
// A function which returns a value representing an "owner" for transient writes
// to tries. The return value will only ever equal itself, and will not equal
// the return of any subsequent call of this function.
function OwnerID() { }
function ensureSize(iter) {
// @ts-expect-error size should exists on Collection
if (iter.size === undefined) {
// @ts-expect-error size should exists on Collection, __iterate does exist on Collection
iter.size = iter.__iterate(returnTrue);
}
// @ts-expect-error size should exists on Collection
return iter.size;
}
function wrapIndex(iter, index) {
// This implements "is array index" which the ECMAString spec defines as:
//
// A String property name P is an array index if and only if
// ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
// to 2^32−1.
//
// http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects
if (typeof index !== 'number') {
var uint32Index = index >>> 0; // N >>> 0 is shorthand for ToUint32
if ('' + uint32Index !== index || uint32Index === 4294967295) {
return NaN;
}
index = uint32Index;
}
return index < 0 ? ensureSize(iter) + index : index;
}
function returnTrue() {
return true;
}
function wholeSlice(begin, end, size) {
return (((begin === 0 && !isNeg(begin)) ||
(size !== undefined && begin <= -size)) &&
(end === undefined || (size !== undefined && end >= size)));
}
function resolveBegin(begin, size) {
return resolveIndex(begin, size, 0);
}
function resolveEnd(end, size) {
return resolveIndex(end, size, size);
}
function resolveIndex(index, size, defaultIndex) {
// Sanitize indices using this shorthand for ToInt32(argument)
// http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
return index === undefined
? defaultIndex
: isNeg(index)
? size === Infinity
? size
: Math.max(0, size + index) | 0
: size === undefined || size === index
? index
: Math.min(size, index) | 0;
}
function isNeg(value) {
// Account for -0 which is negative, but not less than 0.
return value < 0 || (value === 0 && 1 / value === -Infinity);
}
// Note: value is unchanged to not break immutable-devtools.
var IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@';
/**
* True if `maybeCollection` is a Collection, or any of its subclasses.
*
* ```js
* import { isCollection, Map, List, Stack } from 'immutable';
*
* isCollection([]); // false
* isCollection({}); // false
* isCollection(Map()); // true
* isCollection(List()); // true
* isCollection(Stack()); // true
* ```
*/
function isCollection(maybeCollection) {
return Boolean(maybeCollection &&
// @ts-expect-error: maybeCollection is typed as `{}`, need to change in 6.0 to `maybeCollection && typeof maybeCollection === 'object' && IS_COLLECTION_SYMBOL in maybeCollection`
maybeCollection[IS_COLLECTION_SYMBOL]);
}
var IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@';
/**
* True if `maybeKeyed` is a Collection.Keyed, or any of its subclasses.
*
* ```js
* import { isKeyed, Map, List, Stack } from 'immutable';
*
* isKeyed([]); // false
* isKeyed({}); // false
* isKeyed(Map()); // true
* isKeyed(List()); // false
* isKeyed(Stack()); // false
* ```
*/
function isKeyed(maybeKeyed) {
return Boolean(maybeKeyed &&
// @ts-expect-error: maybeKeyed is typed as `{}`, need to change in 6.0 to `maybeKeyed && typeof maybeKeyed === 'object' && IS_KEYED_SYMBOL in maybeKeyed`
maybeKeyed[IS_KEYED_SYMBOL]);
}
var IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@';
/**
* True if `maybeIndexed` is a Collection.Indexed, or any of its subclasses.
*
* ```js
* import { isIndexed, Map, List, Stack, Set } from 'immutable';
*
* isIndexed([]); // false
* isIndexed({}); // false
* isIndexed(Map()); // false
* isIndexed(List()); // true
* isIndexed(Stack()); // true
* isIndexed(Set()); // false
* ```
*/
function isIndexed(maybeIndexed) {
return Boolean(maybeIndexed &&
// @ts-expect-error: maybeIndexed is typed as `{}`, need to change in 6.0 to `maybeIndexed && typeof maybeIndexed === 'object' && IS_INDEXED_SYMBOL in maybeIndexed`
maybeIndexed[IS_INDEXED_SYMBOL]);
}
/**
* True if `maybeAssociative` is either a Keyed or Indexed Collection.
*
* ```js
* import { isAssociative, Map, List, Stack, Set } from 'immutable';
*
* isAssociative([]); // false
* isAssociative({}); // false
* isAssociative(Map()); // true
* isAssociative(List()); // true
* isAssociative(Stack()); // true
* isAssociative(Set()); // false
* ```
*/
function isAssociative(maybeAssociative) {
return isKeyed(maybeAssociative) || isIndexed(maybeAssociative);
}
var Collection = function Collection(value) {
// eslint-disable-next-line no-constructor-return
return isCollection(value) ? value : Seq(value);
};
var KeyedCollection = /*@__PURE__*/(function (Collection) {
function KeyedCollection(value) {
// eslint-disable-next-line no-constructor-return
return isKeyed(value) ? value : KeyedSeq(value);
}
if ( Collection ) KeyedCollection.__proto__ = Collection;
KeyedCollection.prototype = Object.create( Collection && Collection.prototype );
KeyedCollection.prototype.constructor = KeyedCollection;
return KeyedCollection;
}(Collection));
var IndexedCollection = /*@__PURE__*/(function (Collection) {
function IndexedCollection(value) {
// eslint-disable-next-line no-constructor-return
return isIndexed(value) ? value : IndexedSeq(value);
}
if ( Collection ) IndexedCollection.__proto__ = Collection;
IndexedCollection.prototype = Object.create( Collection && Collection.prototype );
IndexedCollection.prototype.constructor = IndexedCollection;
return IndexedCollection;
}(Collection));
var SetCollection = /*@__PURE__*/(function (Collection) {
function SetCollection(value) {
// eslint-disable-next-line no-constructor-return
return isCollection(value) && !isAssociative(value) ? value : SetSeq(value);
}
if ( Collection ) SetCollection.__proto__ = Collection;
SetCollection.prototype = Object.create( Collection && Collection.prototype );
SetCollection.prototype.constructor = SetCollection;
return SetCollection;
}(Collection));
Collection.Keyed = KeyedCollection;
Collection.Indexed = IndexedCollection;
Collection.Set = SetCollection;
var IS_SEQ_SYMBOL = '@@__IMMUTABLE_SEQ__@@';
/**
* True if `maybeSeq` is a Seq.
*/
function isSeq(maybeSeq) {
return Boolean(maybeSeq &&
// @ts-expect-error: maybeSeq is typed as `{}`, need to change in 6.0 to `maybeSeq && typeof maybeSeq === 'object' && MAYBE_SEQ_SYMBOL in maybeSeq`
maybeSeq[IS_SEQ_SYMBOL]);
}
var IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@';
/**
* True if `maybeRecord` is a Record.
*/
function isRecord(maybeRecord) {
return Boolean(maybeRecord &&
// @ts-expect-error: maybeRecord is typed as `{}`, need to change in 6.0 to `maybeRecord && typeof maybeRecord === 'object' && IS_RECORD_SYMBOL in maybeRecord`
maybeRecord[IS_RECORD_SYMBOL]);
}
/**
* True if `maybeImmutable` is an Immutable Collection or Record.
*
* Note: Still returns true even if the collections is within a `withMutations()`.
*
* ```js
* import { isImmutable, Map, List, Stack } from 'immutable';
* isImmutable([]); // false
* isImmutable({}); // false
* isImmutable(Map()); // true
* isImmutable(List()); // true
* isImmutable(Stack()); // true
* isImmutable(Map().asMutable()); // true
* ```
*/
function isImmutable(maybeImmutable) {
return isCollection(maybeImmutable) || isRecord(maybeImmutable);
}
var IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@';
function isOrdered(maybeOrdered) {
return Boolean(maybeOrdered &&
// @ts-expect-error: maybeOrdered is typed as `{}`, need to change in 6.0 to `maybeOrdered && typeof maybeOrdered === 'object' && IS_ORDERED_SYMBOL in maybeOrdered`
maybeOrdered[IS_ORDERED_SYMBOL]);
}
var ITERATE_KEYS = 0;
var ITERATE_VALUES = 1;
var ITERATE_ENTRIES = 2;
var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
var FAUX_ITERATOR_SYMBOL = '@@iterator';
var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL;
var Iterator = function Iterator(next) {
this.next = next;
};
Iterator.prototype.toString = function toString () {
return '[Iterator]';
};
Iterator.KEYS = ITERATE_KEYS;
Iterator.VALUES = ITERATE_VALUES;
Iterator.ENTRIES = ITERATE_ENTRIES;
Iterator.prototype.inspect = Iterator.prototype.toSource = function () {
return this.toString();
};
Iterator.prototype[ITERATOR_SYMBOL] = function () {
return this;
};
function iteratorValue(type, k, v, iteratorResult) {
var value =
type === ITERATE_KEYS ? k : type === ITERATE_VALUES ? v : [k, v];
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
iteratorResult
? (iteratorResult.value = value)
: (iteratorResult = {
value: value,
done: false,
});
return iteratorResult;
}
function iteratorDone() {
return { value: undefined, done: true };
}
function hasIterator(maybeIterable) {
if (Array.isArray(maybeIterable)) {
// IE11 trick as it does not support `Symbol.iterator`
return true;
}
return !!getIteratorFn(maybeIterable);
}
function isIterator(maybeIterator) {
return maybeIterator && typeof maybeIterator.next === 'function';
}
function getIterator(iterable) {
var iteratorFn = getIteratorFn(iterable);
return iteratorFn && iteratorFn.call(iterable);
}
function getIteratorFn(iterable) {
var iteratorFn =
iterable &&
((REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) ||
iterable[FAUX_ITERATOR_SYMBOL]);
if (typeof iteratorFn === 'function') {
return iteratorFn;
}
}
function isEntriesIterable(maybeIterable) {
var iteratorFn = getIteratorFn(maybeIterable);
return iteratorFn && iteratorFn === maybeIterable.entries;
}
function isKeysIterable(maybeIterable) {
var iteratorFn = getIteratorFn(maybeIterable);
return iteratorFn && iteratorFn === maybeIterable.keys;
}
var hasOwnProperty = Object.prototype.hasOwnProperty;
function isArrayLike(value) {
if (Array.isArray(value) || typeof value === 'string') {
return true;
}
// @ts-expect-error "Type 'unknown' is not assignable to type 'boolean'" : convert to Boolean
return (value &&
typeof value === 'object' &&
// @ts-expect-error check that `'length' in value &&`
Number.isInteger(value.length) &&
// @ts-expect-error check that `'length' in value &&`
value.length >= 0 &&
// @ts-expect-error check that `'length' in value &&`
(value.length === 0
? // Only {length: 0} is considered Array-like.
Object.keys(value).length === 1
: // An object is only Array-like if it has a property where the last value
// in the array-like may be found (which could be undefined).
// @ts-expect-error check that `'length' in value &&`
value.hasOwnProperty(value.length - 1)));
}
var Seq = /*@__PURE__*/(function (Collection) {
function Seq(value) {
// eslint-disable-next-line no-constructor-return
return value === undefined || value === null
? emptySequence()
: isImmutable(value)
? value.toSeq()
: seqFromValue(value);
}
if ( Collection ) Seq.__proto__ = Collection;
Seq.prototype = Object.create( Collection && Collection.prototype );
Seq.prototype.constructor = Seq;
Seq.prototype.toSeq = function toSeq () {
return this;
};
Seq.prototype.toString = function toString () {
return this.__toString('Seq {', '}');
};
Seq.prototype.cacheResult = function cacheResult () {
if (!this._cache && this.__iterateUncached) {
this._cache = this.entrySeq().toArray();
this.size = this._cache.length;
}
return this;
};
// abstract __iterateUncached(fn, reverse)
Seq.prototype.__iterate = function __iterate (fn, reverse) {
var cache = this._cache;
if (cache) {
var size = cache.length;
var i = 0;
while (i !== size) {
var entry = cache[reverse ? size - ++i : i++];
if (fn(entry[1], entry[0], this) === false) {
break;
}
}
return i;
}
return this.__iterateUncached(fn, reverse);
};
// abstract __iteratorUncached(type, reverse)
Seq.prototype.__iterator = function __iterator (type, reverse) {
var cache = this._cache;
if (cache) {
var size = cache.length;
var i = 0;
return new Iterator(function () {
if (i === size) {
return iteratorDone();
}
var entry = cache[reverse ? size - ++i : i++];
return iteratorValue(type, entry[0], entry[1]);
});
}
return this.__iteratorUncached(type, reverse);
};
return Seq;
}(Collection));
var KeyedSeq = /*@__PURE__*/(function (Seq) {
function KeyedSeq(value) {
// eslint-disable-next-line no-constructor-return
return value === undefined || value === null
? emptySequence().toKeyedSeq()
: isCollection(value)
? isKeyed(value)
? value.toSeq()
: value.fromEntrySeq()
: isRecord(value)
? value.toSeq()
: keyedSeqFromValue(value);
}
if ( Seq ) KeyedSeq.__proto__ = Seq;
KeyedSeq.prototype = Object.create( Seq && Seq.prototype );
KeyedSeq.prototype.constructor = KeyedSeq;
KeyedSeq.prototype.toKeyedSeq = function toKeyedSeq () {
return this;
};
return KeyedSeq;
}(Seq));
var IndexedSeq = /*@__PURE__*/(function (Seq) {
function IndexedSeq(value) {
// eslint-disable-next-line no-constructor-return
return value === undefined || value === null
? emptySequence()
: isCollection(value)
? isKeyed(value)
? value.entrySeq()
: value.toIndexedSeq()
: isRecord(value)
? value.toSeq().entrySeq()
: indexedSeqFromValue(value);
}
if ( Seq ) IndexedSeq.__proto__ = Seq;
IndexedSeq.prototype = Object.create( Seq && Seq.prototype );
IndexedSeq.prototype.constructor = IndexedSeq;
IndexedSeq.of = function of (/*...values*/) {
return IndexedSeq(arguments);
};
IndexedSeq.prototype.toIndexedSeq = function toIndexedSeq () {
return this;
};
IndexedSeq.prototype.toString = function toString () {
return this.__toString('Seq [', ']');
};
return IndexedSeq;
}(Seq));
var SetSeq = /*@__PURE__*/(function (Seq) {
function SetSeq(value) {
// eslint-disable-next-line no-constructor-return
return (
isCollection(value) && !isAssociative(value) ? value : IndexedSeq(value)
).toSetSeq();
}
if ( Seq ) SetSeq.__proto__ = Seq;
SetSeq.prototype = Object.create( Seq && Seq.prototype );
SetSeq.prototype.constructor = SetSeq;
SetSeq.of = function of (/*...values*/) {
return SetSeq(arguments);
};
SetSeq.prototype.toSetSeq = function toSetSeq () {
return this;
};
return SetSeq;
}(Seq));
Seq.isSeq = isSeq;
Seq.Keyed = KeyedSeq;
Seq.Set = SetSeq;
Seq.Indexed = IndexedSeq;
Seq.prototype[IS_SEQ_SYMBOL] = true;
// #pragma Root Sequences
var ArraySeq = /*@__PURE__*/(function (IndexedSeq) {
function ArraySeq(array) {
this._array = array;
this.size = array.length;
}
if ( IndexedSeq ) ArraySeq.__proto__ = IndexedSeq;
ArraySeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
ArraySeq.prototype.constructor = ArraySeq;
ArraySeq.prototype.get = function get (index, notSetValue) {
return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue;
};
ArraySeq.prototype.__iterate = function __iterate (fn, reverse) {
var array = this._array;
var size = array.length;
var i = 0;
while (i !== size) {
var ii = reverse ? size - ++i : i++;
if (fn(array[ii], ii, this) === false) {
break;
}
}
return i;
};
ArraySeq.prototype.__iterator = function __iterator (type, reverse) {
var array = this._array;
var size = array.length;
var i = 0;
return new Iterator(function () {
if (i === size) {
return iteratorDone();
}
var ii = reverse ? size - ++i : i++;
return iteratorValue(type, ii, array[ii]);
});
};
return ArraySeq;
}(IndexedSeq));
var ObjectSeq = /*@__PURE__*/(function (KeyedSeq) {
function ObjectSeq(object) {
var keys = Object.keys(object).concat(
Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : []
);
this._object = object;
this._keys = keys;
this.size = keys.length;
}
if ( KeyedSeq ) ObjectSeq.__proto__ = KeyedSeq;
ObjectSeq.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
ObjectSeq.prototype.constructor = ObjectSeq;
ObjectSeq.prototype.get = function get (key, notSetValue) {
if (notSetValue !== undefined && !this.has(key)) {
return notSetValue;
}
return this._object[key];
};
ObjectSeq.prototype.has = function has (key) {
return hasOwnProperty.call(this._object, key);
};
ObjectSeq.prototype.__iterate = function __iterate (fn, reverse) {
var object = this._object;
var keys = this._keys;
var size = keys.length;
var i = 0;
while (i !== size) {
var key = keys[reverse ? size - ++i : i++];
if (fn(object[key], key, this) === false) {
break;
}
}
return i;
};
ObjectSeq.prototype.__iterator = function __iterator (type, reverse) {
var object = this._object;
var keys = this._keys;
var size = keys.length;
var i = 0;
return new Iterator(function () {
if (i === size) {
return iteratorDone();
}
var key = keys[reverse ? size - ++i : i++];
return iteratorValue(type, key, object[key]);
});
};
return ObjectSeq;
}(KeyedSeq));
ObjectSeq.prototype[IS_ORDERED_SYMBOL] = true;
var CollectionSeq = /*@__PURE__*/(function (IndexedSeq) {
function CollectionSeq(collection) {
this._collection = collection;
this.size = collection.length || collection.size;
}
if ( IndexedSeq ) CollectionSeq.__proto__ = IndexedSeq;
CollectionSeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
CollectionSeq.prototype.constructor = CollectionSeq;
CollectionSeq.prototype.__iterateUncached = function __iterateUncached (fn, reverse) {
if (reverse) {
return this.cacheResult().__iterate(fn, reverse);
}
var collection = this._collection;
var iterator = getIterator(collection);
var iterations = 0;
if (isIterator(iterator)) {
var step;
while (!(step = iterator.next()).done) {
if (fn(step.value, iterations++, this) === false) {
break;
}
}
}
return iterations;
};
CollectionSeq.prototype.__iteratorUncached = function __iteratorUncached (type, reverse) {
if (reverse) {
return this.cacheResult().__iterator(type, reverse);
}
var collection = this._collection;
var iterator = getIterator(collection);
if (!isIterator(iterator)) {
return new Iterator(iteratorDone);
}
var iterations = 0;
return new Iterator(function () {
var step = iterator.next();
return step.done ? step : iteratorValue(type, iterations++, step.value);
});
};
return CollectionSeq;
}(IndexedSeq));
// # pragma Helper functions
var EMPTY_SEQ;
function emptySequence() {
return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([]));
}
function keyedSeqFromValue(value) {
var seq = maybeIndexedSeqFromValue(value);
if (seq) {
return seq.fromEntrySeq();
}
if (typeof value === 'object') {
return new ObjectSeq(value);
}
throw new TypeError(
'Expected Array or collection object of [k, v] entries, or keyed object: ' +
value
);
}
function indexedSeqFromValue(value) {
var seq = maybeIndexedSeqFromValue(value);
if (seq) {
return seq;
}
throw new TypeError(
'Expected Array or collection object of values: ' + value
);
}
function seqFromValue(value) {
var seq = maybeIndexedSeqFromValue(value);
if (seq) {
return isEntriesIterable(value)
? seq.fromEntrySeq()
: isKeysIterable(value)
? seq.toSetSeq()
: seq;
}
if (typeof value === 'object') {
return new ObjectSeq(value);
}
throw new TypeError(
'Expected Array or collection object of values, or keyed object: ' + value
);
}
function maybeIndexedSeqFromValue(value) {
return isArrayLike(value)
? new ArraySeq(value)
: hasIterator(value)
? new CollectionSeq(value)
: undefined;
}
var IS_MAP_SYMBOL = '@@__IMMUTABLE_MAP__@@';
/**
* True if `maybeMap` is a Map.
*
* Also true for OrderedMaps.
*/
function isMap(maybeMap) {
return Boolean(maybeMap &&
// @ts-expect-error: maybeMap is typed as `{}`, need to change in 6.0 to `maybeMap && typeof maybeMap === 'object' && IS_MAP_SYMBOL in maybeMap`
maybeMap[IS_MAP_SYMBOL]);
}
/**
* True if `maybeOrderedMap` is an OrderedMap.
*/
function isOrderedMap(maybeOrderedMap) {
return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap);
}
/**
* True if `maybeValue` is a JavaScript Object which has *both* `equals()`
* and `hashCode()` methods.
*
* Any two instances of *value objects* can be compared for value equality with
* `Immutable.is()` and can be used as keys in a `Map` or members in a `Set`.
*/
function isValueObject(maybeValue) {
return Boolean(maybeValue &&
// @ts-expect-error: maybeValue is typed as `{}`
typeof maybeValue.equals === 'function' &&
// @ts-expect-error: maybeValue is typed as `{}`
typeof maybeValue.hashCode === 'function');
}
/**
* An extension of the "same-value" algorithm as [described for use by ES6 Map
* and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality)
*
* NaN is considered the same as NaN, however -0 and 0 are considered the same
* value, which is different from the algorithm described by
* [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
*
* This is extended further to allow Objects to describe the values they
* represent, by way of `valueOf` or `equals` (and `hashCode`).
*
* Note: because of this extension, the key equality of Immutable.Map and the
* value equality of Immutable.Set will differ from ES6 Map and Set.
*
* ### Defining custom values
*
* The easiest way to describe the value an object represents is by implementing
* `valueOf`. For example, `Date` represents a value by returning a unix
* timestamp for `valueOf`:
*
* var date1 = new Date(1234567890000); // Fri Feb 13 2009 ...
* var date2 = new Date(1234567890000);
* date1.valueOf(); // 1234567890000
* assert( date1 !== date2 );
* assert( Immutable.is( date1, date2 ) );
*
* Note: overriding `valueOf` may have other implications if you use this object
* where JavaScript expects a primitive, such as implicit string coercion.
*
* For more complex types, especially collections, implementing `valueOf` may
* not be performant. An alternative is to implement `equals` and `hashCode`.
*
* `equals` takes another object, presumably of similar type, and returns true
* if it is equal. Equality is symmetrical, so the same result should be
* returned if this and the argument are flipped.
*
* assert( a.equals(b) === b.equals(a) );
*
* `hashCode` returns a 32bit integer number representing the object which will
* be used to determine how to store the value object in a Map or Set. You must
* provide both or neither methods, one must not exist without the other.
*
* Also, an important relationship between these methods must be upheld: if two
* values are equal, they *must* return the same hashCode. If the values are not
* equal, they might have the same hashCode; this is called a hash collision,
* and while undesirable for performance reasons, it is acceptable.
*
* if (a.equals(b)) {
* assert( a.hashCode() === b.hashCode() );
* }
*
* All Immutable collections are Value Objects: they implement `equals()`
* and `hashCode()`.
*/
function is(valueA, valueB) {
if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
return true;
}
if (!valueA || !valueB) {
return false;
}
if (typeof valueA.valueOf === 'function' &&
typeof valueB.valueOf === 'function') {
valueA = valueA.valueOf();
valueB = valueB.valueOf();
if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
return true;
}
if (!valueA || !valueB) {
return false;
}
}
return !!(isValueObject(valueA) &&
isValueObject(valueB) &&
valueA.equals(valueB));
}
var imul =
typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2
? Math.imul
: function imul(a, b) {
a |= 0; // int
b |= 0; // int
var c = a & 0xffff;
var d = b & 0xffff;
// Shift by 0 fixes the sign on the high part.
return (c * d + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0)) | 0; // int
};
// v8 has an optimization for storing 31-bit signed numbers.
// Values which have either 00 or 11 as the high order bits qualify.
// This function drops the highest order bit in a signed number, maintaining
// the sign bit.
function smi(i32) {
return ((i32 >>> 1) & 0x40000000) | (i32 & 0xbfffffff);
}
var defaultValueOf = Object.prototype.valueOf;
function hash(o) {
// eslint-disable-next-line eqeqeq
if (o == null) {
return hashNullish(o);
}
if (typeof o.hashCode === 'function') {
// Drop any high bits from accidentally long hash codes.
return smi(o.hashCode(o));
}
var v = valueOf(o);
// eslint-disable-next-line eqeqeq
if (v == null) {
return hashNullish(v);
}
switch (typeof v) {
case 'boolean':
// The hash values for built-in constants are a 1 value for each 5-byte
// shift region expect for the first, which encodes the value. This
// reduces the odds of a hash collision for these common values.
return v ? 0x42108421 : 0x42108420;
case 'number':
return hashNumber(v);
case 'string':
return v.length > STRING_HASH_CACHE_MIN_STRLEN
? cachedHashString(v)
: hashString(v);
case 'object':
case 'function':
return hashJSObj(v);
case 'symbol':
return hashSymbol(v);
default:
if (typeof v.toString === 'function') {
return hashString(v.toString());
}
throw new Error('Value type ' + typeof v + ' cannot be hashed.');
}
}
function hashNullish(nullish) {
return nullish === null ? 0x42108422 : /* undefined */ 0x42108423;
}
// Compress arbitrarily large numbers into smi hashes.
function hashNumber(n) {
if (n !== n || n === Infinity) {
return 0;
}
var hash = n | 0;
if (hash !== n) {
hash ^= n * 0xffffffff;
}
while (n > 0xffffffff) {
n /= 0xffffffff;
hash ^= n;
}
return smi(hash);
}
function cachedHashString(string) {
var hashed = stringHashCache[string];
if (hashed === undefined) {
hashed = hashString(string);
if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) {
STRING_HASH_CACHE_SIZE = 0;
stringHashCache = {};
}
STRING_HASH_CACHE_SIZE++;
stringHashCache[string] = hashed;
}
return hashed;
}
// http://jsperf.com/hashing-strings
function hashString(string) {
// This is the hash from JVM
// The hash code for a string is computed as
// s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
// where s[i] is the ith character of the string and n is the length of
// the string. We "mod" the result to make it between 0 (inclusive) and 2^31
// (exclusive) by dropping high bits.
var hashed = 0;
for (var ii = 0; ii < string.length; ii++) {
hashed = (31 * hashed + string.charCodeAt(ii)) | 0;
}
return smi(hashed);
}
function hashSymbol(sym) {
var hashed = symbolMap[sym];
if (hashed !== undefined) {
return hashed;
}
hashed = nextHash();
symbolMap[sym] = hashed;
return hashed;
}
function hashJSObj(obj) {
var hashed;
if (usingWeakMap) {
hashed = weakMap.get(obj);
if (hashed !== undefined) {
return hashed;
}
}
hashed = obj[UID_HASH_KEY];
if (hashed !== undefined) {
return hashed;
}
if (!canDefineProperty) {
hashed = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY];
if (hashed !== undefined) {
return hashed;
}
hashed = getIENodeHash(obj);
if (hashed !== undefined) {
return hashed;
}
}
hashed = nextHash();
if (usingWeakMap) {
weakMap.set(obj, hashed);
} else if (isExtensible !== undefined && isExtensible(obj) === false) {
throw new Error('Non-extensible objects are not allowed as keys.');
} else if (canDefineProperty) {
Object.defineProperty(obj, UID_HASH_KEY, {
enumerable: false,
configurable: false,
writable: false,
value: hashed,
});
} else if (
obj.propertyIsEnumerable !== undefined &&
obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable
) {
// Since we can't define a non-enumerable property on the object
// we'll hijack one of the less-used non-enumerable properties to
// save our hash on it. Since this is a function it will not show up in
// `JSON.stringify` which is what we want.
obj.propertyIsEnumerable = function () {
return this.constructor.prototype.propertyIsEnumerable.apply(
this,
arguments
);
};
obj.propertyIsEnumerable[UID_HASH_KEY] = hashed;
} else if (obj.nodeType !== undefined) {
// At this point we couldn't get the IE `uniqueID` to use as a hash
// and we couldn't use a non-enumerable property to exploit the
// dontEnum bug so we simply add the `UID_HASH_KEY` on the node
// itself.
obj[UID_HASH_KEY] = hashed;
} else {
throw new Error('Unable to set a non-enumerable property on object.');
}
return hashed;
}
// Get references to ES5 object methods.
var isExtensible = Object.isExtensible;
// True if Object.defineProperty works as expected. IE8 fails this test.
var canDefineProperty = (function () {
try {
Object.defineProperty({}, '@', {});
return true;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return false;
}
})();
// IE has a `uniqueID` property on DOM nodes. We can construct the hash from it
// and avoid memory leaks from the IE cloneNode bug.
function getIENodeHash(node) {
if (node && node.nodeType > 0) {
switch (node.nodeType) {
case 1: // Element
return node.uniqueID;
case 9: // Document
return node.documentElement && node.documentElement.uniqueID;
}
}
}
function valueOf(obj) {
return obj.valueOf !== defaultValueOf && typeof obj.valueOf === 'function'
? obj.valueOf(obj)
: obj;
}
function nextHash() {
var nextHash = ++_objHashUID;
if (_objHashUID & 0x40000000) {
_objHashUID = 0;
}
return nextHash;
}
// If possible, use a WeakMap.
var usingWeakMap = typeof WeakMap === 'function';
var weakMap;
if (usingWeakMap) {
weakMap = new WeakMap();
}
var symbolMap = Object.create(null);
var _objHashUID = 0;
var UID_HASH_KEY = '__immutablehash__';
if (typeof Symbol === 'function') {
UID_HASH_KEY = Symbol(UID_HASH_KEY);
}
var STRING_HASH_CACHE_MIN_STRLEN = 16;
var STRING_HASH_CACHE_MAX_SIZE = 255;
var STRING_HASH_CACHE_SIZE = 0;
var stringHashCache = {};
var ToKeyedSequence = /*@__PURE__*/(function (KeyedSeq) {
function ToKeyedSequence(indexed, useKeys) {
this._iter = indexed;
this._useKeys = useKeys;
this.size = indexed.size;
}
if ( KeyedSeq ) ToKeyedSequence.__proto__ = KeyedSeq;
ToKeyedSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
ToKeyedSequence.prototype.constructor = ToKeyedSequence;
ToKeyedSequence.prototype.get = function get (key, notSetValue) {
return this._iter.get(key, notSetValue);
};
ToKeyedSequence.prototype.has = function has (key) {
return this._iter.has(key);
};
ToKeyedSequence.prototype.valueSeq = function valueSeq () {
return this._iter.valueSeq();
};
ToKeyedSequence.prototype.reverse = function reverse () {
var this$1$1 = this;
var reversedSequence = reverseFactory(this, true);
if (!this._useKeys) {
reversedSequence.valueSeq = function () { return this$1$1._iter.toSeq().reverse(); };
}
return reversedSequence;
};
ToKeyedSequence.prototype.map = function map (mapper, context) {
var this$1$1 = this;
var mappedSequence = mapFactory(this, mapper, context);
if (!this._useKeys) {
mappedSequence.valueSeq = function () { return this$1$1._iter.toSeq().map(mapper, context); };
}
return mappedSequence;
};
ToKeyedSequence.prototype.__iterate = function __iterate (fn, reverse) {
var this$1$1 = this;
return this._iter.__iterate(function (v, k) { return fn(v, k, this$1$1); }, reverse);
};
ToKeyedSequence.prototype.__iterator = function __iterator (type, reverse) {
return this._iter.__iterator(type, reverse);
};
return ToKeyedSequence;
}(KeyedSeq));
ToKeyedSequence.prototype[IS_ORDERED_SYMBOL] = true;
var ToIndexedSequence = /*@__PURE__*/(function (IndexedSeq) {
function ToIndexedSequence(iter) {
this._iter = iter;
this.size = iter.size;
}
if ( IndexedSeq ) ToIndexedSequence.__proto__ = IndexedSeq;
ToIndexedSequence.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
ToIndexedSequence.prototype.constructor = ToIndexedSequence;
ToIndexedSequence.prototype.includes = function includes (value) {
return this._iter.includes(value);
};
ToIndexedSequence.prototype.__iterate = function __iterate (fn, reverse) {
var this$1$1 = this;
var i = 0;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
reverse && ensureSize(this);
return this._iter.__iterate(
function (v) { return fn(v, reverse ? this$1$1.size - ++i : i++, this$1$1); },
reverse
);
};
ToIndexedSequence.prototype.__iterator = function __iterator (type, reverse) {
var this$1$1 = this;
var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
var i = 0;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
reverse && ensureSize(this);
return new Iterator(function () {
var step = iterator.next();
return step.done
? step
: iteratorValue(
type,
reverse ? this$1$1.size - ++i : i++,
step.value,
step
);
});
};
return ToIndexedSequence;
}(IndexedSeq));
var ToSetSequence = /*@__PURE__*/(function (SetSeq) {
function ToSetSequence(iter) {
this._iter = iter;
this.size = iter.size;
}
if ( SetSeq ) ToSetSequence.__proto__ = SetSeq;
ToSetSequence.prototype = Object.create( SetSeq && SetSeq.prototype );
ToSetSequence.prototype.constructor = ToSetSequence;
ToSetSequence.prototype.has = function has (key) {
return this._iter.includes(key);
};
ToSetSequence.prototype.__iterate = function __iterate (fn, reverse) {
var this$1$1 = this;
return this._iter.__iterate(function (v) { return fn(v, v, this$1$1); }, reverse);
};
ToSetSequence.prototype.__iterator = function __iterator (type, reverse) {
var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
return new Iterator(function () {
var step = iterator.next();
return step.done
? step
: iteratorValue(type, step.value, step.value, step);
});
};
return ToSetSequence;
}(SetSeq));
var FromEntriesSequence = /*@__PURE__*/(function (KeyedSeq) {
function FromEntriesSequence(entries) {
this._iter = entries;
this.size = entries.size;
}
if ( KeyedSeq ) FromEntriesSequence.__proto__ = KeyedSeq;
FromEntriesSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
FromEntriesSequence.prototype.constructor = FromEntriesSequence;
FromEntriesSequence.prototype.entrySeq = function entrySeq () {
return this._iter.toSeq();
};
FromEntriesSequence.prototype.__iterate = function __iterate (fn, reverse) {
var this$1$1 = this;
return this._iter.__iterate(function (entry) {
// Check if entry exists first so array access doesn't throw for holes
// in the parent iteration.
if (entry) {
validateEntry(entry);
var indexedCollection = isCollection(entry);
return fn(
indexedCollection ? entry.get(1) : entry[1],
indexedCollection ? entry.get(0) : entry[0],
this$1$1
);
}
}, reverse);
};
FromEntriesSequence.prototype.__iterator = function __iterator (type, reverse) {
var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
return new Iterator(function () {
while (true) {
var step = iterator.next();
if (step.done) {
return step;
}
var entry = step.value;
// Check if entry exists first so array access doesn't throw for holes
// in the parent iteration.
if (entry) {
validateEntry(entry);
var indexedCollection = isCollection(entry);
return iteratorValue(
type,
indexedCollection ? entry.get(0) : entry[0],
indexedCollection ? entry.get(1) : entry[1],
step
);
}
}
});
};
return FromEntriesSequence;
}(KeyedSeq));
ToIndexedSequence.prototype.cacheResult =
ToKeyedSequence.prototype.cacheResult =
ToSetSequence.prototype.cacheResult =
FromEntriesSequence.prototype.cacheResult =
cacheResultThrough;
function flipFactory(collection) {
var flipSequence = makeSequence(collection);
flipSequence._iter = collection;
flipSequence.size = collection.size;
flipSequence.flip = function () { return collection; };
flipSequence.reverse = function () {
var reversedSequence = collection.reverse.apply(this); // super.reverse()
reversedSequence.flip = function () { return collection.reverse(); };
return reversedSequence;
};
flipSequence.has = function (key) { return collection.includes(key); };
flipSequence.includes = function (key) { return collection.has(key); };
flipSequence.cacheResult = cacheResultThrough;
flipSequence.__iterateUncached = function (fn, reverse) {
var this$1$1 = this;
return collection.__iterate(function (v, k) { return fn(k, v, this$1$1) !== false; }, reverse);
};
flipSequence.__iteratorUncached = function (type, reverse) {
if (type === ITERATE_ENTRIES) {
var iterator = collection.__iterator(type, reverse);
return new Iterator(function () {
var step = iterator.next();
if (!step.done) {
var k = step.value[0];
step.value[0] = step.value[1];
step.value[1] = k;
}
return step;
});
}
return collection.__iterator(
type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES,
reverse
);
};
return flipSequence;
}
function mapFactory(collection, mapper, context) {
var mappedSequence = makeSequence(collection);
mappedSequence.size = collection.size;
mappedSequence.has = function (key) { return collection.has(key); };
mappedSequence.get = function (key, notSetValue) {
var v = collection.get(key, NOT_SET);
return v === NOT_SET
? notSetValue
: mapper.call(context, v, key, collection);
};
mappedSequence.__iterateUncached = function (fn, reverse) {
var this$1$1 = this;
return collection.__iterate(
function (v, k, c) { return fn(mapper.call(context, v, k, c), k, this$1$1) !== false; },
reverse
);
};
mappedSequence.__iteratorUncached = function (type, reverse) {
var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
return new Iterator(function () {
var step = iterator.next();
if (step.done) {
return step;
}
var entry = step.value;
var key = entry[0];
return iteratorValue(
type,
key,
mapper.call(context, entry[1], key, collection),
step
);
});
};
return mappedSequence;
}
function reverseFactory(collection, useKeys) {
var this$1$1 = this;
var reversedSequence = makeSequence(collection);
reversedSequence._iter = collection;
reversedSequence.size = collection.size;
reversedSequence.reverse = function () { return collection; };
if (collection.flip) {
reversedSequence.flip = function () {
var flipSequence = flipFactory(collection);
flipSequence.reverse = function () { return collection.flip(); };
return flipSequence;
};
}
reversedSequence.get = function (key, notSetValue) { return collection.get(useKeys ? key : -1 - key, notSetValue); };
reversedSequence.has = function (key) { return collection.has(useKeys ? key : -1 - key); };
reversedSequence.includes = function (value) { return collection.includes(value); };
reversedSequence.cacheResult = cacheResultThrough;
reversedSequence.__iterate = function (fn, reverse) {
var this$1$1 = this;
var i = 0;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
reverse && ensureSize(collection);
return collection.__iterate(
function (v, k) { return fn(v, useKeys ? k : reverse ? this$1$1.size - ++i : i++, this$1$1); },
!reverse
);
};
reversedSequence.__iterator = function (type, reverse) {
var i = 0;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
reverse && ensureSize(collection);
var iterator = collection.__iterator(ITERATE_ENTRIES, !reverse);
return new Iterator(function () {
var step = iterator.next();
if (step.done) {
return step;
}
var entry = step.value;
return iteratorValue(
type,
useKeys ? entry[0] : reverse ? this$1$1.size - ++i : i++,
entry[1],
step
);
});
};
return reversedSequence;
}
function filterFactory(collection, predicate, context, useKeys) {
var filterSequence = makeSequence(collection);
if (useKeys) {
filterSequence.has = function (key) {
var v = collection.get(key, NOT_SET);
return v !== NOT_SET && !!predicate.call(context, v, key, collecti