UNPKG

immutable-js

Version:
1,479 lines (1,285 loc) 42.2 kB
/** * Copyright (c) 2015, Jan Biasi. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.Immutable = factory() }(this, function () { 'use strict'; /** * IE Array.isArray Polyfill * developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray * */ if(!Array.isArray) { Array.isArray = function (vArg) { return Object.prototype.toString.call(vArg) === "[object Array]"; }; } /** * ES5 Object.assign Polyfill by MDN * developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign * * This polyfill doesn't support symbol properties, since ES5 * doesn't have symbols anyway. */ if (!Object.assign) { Object.defineProperty(Object, 'assign', { enumerable: false, configurable: true, writable: true, value: function(target) { 'use strict'; if (target === undefined || target === null) { throw new TypeError('Cannot convert first argument to object'); } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) { continue; } nextSource = Object(nextSource); var keysArray = Object.keys(Object(nextSource)); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { to[nextKey] = nextSource[nextKey]; } } } return to; } }); } var IS_ITERABLE_FLAG = '@@__IMMUTABLE_ITERABLE__@@'; var IS_KEYED_FLAG = '@@__IMMUTABLE_KEYED__@@'; var IS_INDEXED_FLAG = '@@__IMMUTABLE_INDEXED__@@'; var IS_ORDERED_FLAG = '@@__IMMUTABLE_ORDERED__@@'; var IS_SEQUENCE_FLAG = '@@__IMMUTABLE_SEQUENCE__@@'; var IS_STACK_FLAG = '@@__IMMUTABLE_STACK__@@'; var IS_MAP_FLAG = '@@__IMMUTABLE_MAP__@@'; var IS_LIST_FLAG = '@@__IMMUTABLE_LIST__@@'; var CACHE_FLAG = '@@__CACHE__@@'; function isIterable(maybeIterable) { return !!(maybeIterable && maybeIterable[IS_ITERABLE_FLAG]); } function isKeyed(maybeKeyed) { return !!(maybeKeyed && maybeKeyed[IS_KEYED_FLAG]); } function isIndexed(maybeIndexed) { return !!(maybeIndexed && maybeIndexed[IS_INDEXED_FLAG]); } function isAssociative(maybeAssociative) { return isKeyed(maybeAssociative) || isIndexed(maybeAssociative); } function isOrdered(maybeOrdered) { return !!(maybeOrdered && maybeOrdered[IS_ORDERED_FLAG]); } function Flags__isSequence(maybeSequence) { return !!(maybeSequence && maybeSequence[IS_SEQUENCE_FLAG]); } function isStack(maybeStack) { return !!(maybeStack && maybeStack[IS_STACK_FLAG]); } function isMap(maybeMap) { return !!(maybeMap && maybeMap[IS_MAP_FLAG]); } function isList(maybeList) { return !!(maybeList && maybeList[IS_LIST_FLAG]); } function hasCache(maybeHasCache) { return !!(maybeHasCache && maybeHasCache[CACHE_FLAG] && maybeHasCache._cache) } function is__arrayLike(value) { return !!(value && typeof value.length === 'number'); } function nullOrUndefined(value) { return !!(value === null || value === undefined); } /** * 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. * */ function equal(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; } } if (typeof valueA.equals === 'function' && typeof valueB.equals === 'function' && valueA.equals(valueB)) { return true; } return false; } var TYPEDEF_FIELD = '__type__'; function toolset__typedef(blueprint, prefered) { if(typeof blueprint === 'object') { if(!blueprint.prototype) { return; } for(var scheme in blueprint) { if(scheme && blueprint.hasOwnProperty(scheme)) { toolset__typedef(blueprint[scheme], scheme); } } } else if(blueprint && typeof prefered === 'string') { blueprint.prototype[TYPEDEF_FIELD] = prefered; } } function invariant(condition, error) { if (!condition) throw new Error(error); } /** * Contributes additional methods to a constructor */ function mixin(ctor, funcs) { var copier = key => { ctor.prototype[key] = funcs[key]; }; Object.keys(funcs).forEach(copier); Object.getOwnPropertySymbols && Object.getOwnPropertySymbols(funcs).forEach(copier); return ctor; } function createClass(ctor, superClass) { if (superClass) { ctor.prototype = Object.create(superClass.prototype); } ctor.prototype.constructor = ctor; } var ITERABLE_TYPEDEF = '[object Iterable]'; class Iterable { constructor(value) { return isIterable(value) ? value : Sequence(value); } __toString(head, data, tail) { if(!data) { return head + tail; } return head + ' ' + data + ' ' + tail; } isSequence() { return (this[TYPEDEF_FIELD] === SEQUENCE_TYPEDEF); } toSequence() { return isIndexed(this) ? this.toIndexedSequence() : this.toKeyedSequence(); } updateSize(newSize) { if(nullOrUndefined(newSize)) { if(this.getNative()) { if(typeof this.getNative() === 'object') { this.size = Object.keys(this.getNative()).length; } else if(Array.isArray(this.getNative())) { this.size = this.getNative().length; } } else { this.size = 0; } } else if(typeof newSize === 'number') { this.size = Math.round(newSize); } else { throw new TypeError( 'Need a number to set size and not ' + typeof newSize ); } } getNative() { return this.__internal; } map(handle) { return this.__iterate(handle); } wasAltered() { return this.__altered; } asMutable() { return this.__ownerID ? this : this.__ensureOwner(new OwnerID()); } asImmutable() { if(!this.__ensureOwner) { // if implementation missing throw Error('Can\'t ensure owner to make immutable of ' + this); } if(this.__ownerID) { this.__ownerID = undefined; this.__altered = false; this.size = this.__internal.length; return this; } } isKeyedSequence() { return (this[TYPEDEF_FIELD] === KEYED_SEQUENCE_TYPEDEF); } toKeyedSequence() { return new KeyedSequence(this.getNative()); } isIndexedSequence() { return (this[TYPEDEF_FIELD] === INDEXED_SEQUENCE_TYPEDEF); } toIndexedSequence() { return new IndexedSequence(this.getNative()); } isSetSequence() { return (this[TYPEDEF_FIELD] === SET_SEQUENCE_TYPEDEF); } toSetSequence() { return new SetSequence(this.getNative()); } } var KEYED_ITERABLE_TYPEDEF = '[Iterable KeyedIterable]'; class KeyedIterable extends Iterable { constructor(value) { super(value); } } var INDEXED_ITERABLE_TYPEDEF = '[Iterable IndexedIterable]'; class IndexedIterable extends Iterable { constructor(value) { super(value); } } var SET_ITERABLE_TYPEDEF = '[Iterable SetIterable]'; class SetIterable extends Iterable { constructor(value) { super(value); } } var IterablePrototype = Iterable.prototype; IterablePrototype[IS_ITERABLE_FLAG] = true; var KeyedIterablePrototype = KeyedIterable.prototype; KeyedIterablePrototype[IS_KEYED_FLAG] = true; var IndexedIterablePrototype = IndexedIterable.prototype; IndexedIterablePrototype[IS_INDEXED_FLAG] = true; function quoteString(value) { return typeof value === 'string' ? JSON.stringify(value) : value; } toolset__typedef({ Iterable: ITERABLE_TYPEDEF, KeyedIterable: KEYED_ITERABLE_TYPEDEF, IndexedIterable: INDEXED_ITERABLE_TYPEDEF }); Iterable.isIterable = isIterable; Iterable.isKeyed = isKeyed; Iterable.isIndexed = isIndexed; Iterable.isAssociative = isAssociative; Iterable.isOrdered = isOrdered; Iterable.Keyed = KeyedIterable; Iterable.Indexed = IndexedIterable; Iterable.Set = SetIterable; var COLLECTION_TYPEDEF = '[Iterable Collection]'; class Collection extends Iterable { constructor() { throw TypeError('Abstract'); } } var KEYED_COLLECTION_TYPEDEF = '[KeyedIterable KeyedCollection]'; class KeyedCollection extends KeyedIterable {} var INDEXED_COLLECTION_TYPEDEF = '[IndexedIterable IndexedCollection]'; class IndexedCollection extends IndexedIterable {} var SET_COLLECTION_TYPEDEF = '[SetIterable SetCollection]'; class SetCollection extends SetIterable {} toolset__typedef({ Collection: COLLECTION_TYPEDEF, KeyedCollection: KEYED_COLLECTION_TYPEDEF, IndexedCollection: INDEXED_COLLECTION_TYPEDEF, SetCollection: SET_COLLECTION_TYPEDEF }); Collection.Keyed = KeyedCollection; Collection.Indexed = IndexedCollection; Collection.Set = SetCollection; function clone(item) { if (!item) { // null, undefined values check return item; } var types = [Number, String, Boolean], result; // normalizing primitives if someone did new String('aaa'), or new Number('444'); types.forEach(function(type) { if (item instanceof type) { result = type(item); } }); if (typeof result === 'undefined') { if (Object.prototype.toString.call(item) === '[object Array]') { result = []; item.forEach(function(child, index, array) { result[index] = clone(child); }); } else if (typeof item === 'object') { // testing that this is DOM if (item.nodeType && typeof item.cloneNode === 'function') { result = item.cloneNode(true); } else if (!item.prototype) { // check that this is a literal if (item instanceof Date) { result = new Date(item); } else { // it is an object literal result = {}; for (var i in item) { if(item.hasOwnProperty(i)) { result[i] = clone(item[i]); } } } } else { // depending what you would like here, // just keep the reference, or create new object if (false && item.constructor) { result = Object.create(item.prototype); } else { result = item; } } } else { result = item; } } return result; } var IS_NATIVE_FLAG = '@@__IS_NATIVE__@@'; function isNative(maybeNative) { return !!(maybeNative && maybeNative[IS_NATIVE_FLAG]); } var NATIVE_COLLECTION_TYPEDEF = '[native Collection]' class NativeCollection { constructor() { var args = Array.prototype.slice.call(arguments); if(args.length > 1) { let array = new NativeArray(); array.__initialSize = args.length; args.forEach(v => array.push(v)); return array; } else if(args.length === 1) { var single = args[0]; if(Array.isArray(single)) { let array = new NativeArray(); single.forEach(v => array.push(v)); array.__initialSize = single.length || 0; return array; } else if(typeof single === 'object') { let object = new NativeObject(); object.__initialSize = Object.keys(single).length; return object.extend(single); } } else { return new NativeObject(); } } toString() { return NATIVE_COLLECTION_TYPEDEF; } } var NATIVE_ARRAY_TYPEDEF = '[native Array]'; class NativeArray extends Array { constructor() { super(0); } toString() { return NATIVE_ARRAY_TYPEDEF; } toNative() { return this; } isNativeArray(maybeNativeArray) { return maybeNativeArray && maybeNativeArray.toString && maybeNativeArray.toString() === NATIVE_ARRAY_TYPEDEF; } __clone() { return this.slice(); } } var NATIVE_OBJECT_TYPEDEF = '[native Object]'; class NativeObject extends Object { constructor() { super(null); } __clone() { return clone(this); } extend(source) { var object = Object.assign(new NativeObject(), source); return object; } toString() { return NATIVE_OBJECT_TYPEDEF; } isNativeObject(maybeNativeObject) { return maybeNativeObject && maybeNativeObject.toString && maybeNativeObject.toString() === NATIVE_OBJECT_TYPEDEF; } } NativeCollection.prototype[IS_NATIVE_FLAG] = true; NativeObject.prototype[IS_NATIVE_FLAG] = true; NativeArray.prototype[IS_NATIVE_FLAG] = true; /** * RFC4122 version 4 compliant solution that solves that issue by offsetting * the first 13 hex numbers by a hex portion of the timestamp. */ function guid() { var d = new Date().getTime(); var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = (d + Math.random()*16)%16 | 0; d = Math.floor(d/16); return (c === 'x' ? r : (r&0x3|0x8)).toString(16); }); return uuid; } var OWNER_TYPEDEF = '[OwnerID]'; class OwnerID { constructor() { this.__key__ = guid(); } toString() { return '[OwnerID ' + this.__toString() + ']'; } __toString() { return this.__key__; } } toolset__typedef(OwnerID, OWNER_TYPEDEF); var STACK_TYPEDEF = '[IndexedCollection Stack]'; class Stack extends IndexedCollection { constructor() { var args = Array.prototype.slice.call(arguments); if(nullOrUndefined(args)) { return emptyStack(); } else if(args.length === 1) { let singleArg = args[0]; if(Array.isArray(singleArg)) { return makeStack(singleArg); } else if(typeof singleArg === 'object') { return makeStack(objectToArray(singleArg)); } } else if(args.length > 1) { return makeStack(args); } } static of(...values) { return new Stack(values); } push(...values) { if(this.__ownerID) { values.forEach(v => this.__internal.push(v)); this.size = this.__internal.length; this.__altered = true; return this; } return new Stack( this.__internal.__clone().concat( Array.prototype.slice.call(arguments) ) ); } shift() { if(this.__ownerID) { this.__internal.pop(); this.size = this.__internal.length; this.__altered = true; return this; } var cloned = this.__internal.__clone(); var newSize = cloned.pop(); return new Stack(cloned); } clear() { if(this.size === 0) { return this; } if(this.__ownerID) { this.size = 0; this.__altered = true; return this.toStack(); } return emptyStack(); } toString() { return this.__toString('Stack [', this.__internal.join(',') ,']'); } toStack() { return this; } __ensureOwner(ownerID) { if(ownerID === this.__ownerID) { return this; } if(!ownerID || nullOrUndefined(ownerID)) { this.__ownerID = ownerID; this.__altered = false; return this; } return makeStack(this.__internal, ownerID); } __iterate(handle, reverse) { var maxLength = this.size; for(var n = 0; n <= maxLength; n++) { let entry = this.__internal[reverse ? maxLength - n : n]; if(handle(entry, n, this) === false) { return n + 1; } } return n; } } toolset__typedef(Stack, STACK_TYPEDEF); Stack.prototype[IS_STACK_FLAG] = true; var EMPTY_STACK; function emptyStack() { return EMPTY_STACK || (EMPTY_STACK = makeStack()); } function makeStack(array, ownerID) { var stack = Object.create(Stack.prototype); stack.__ownerID = ownerID; stack.__altered = false; if(isNative(array)) { stack.__internal = array.toNative(); } else { stack.__internal = new NativeArray(); if(Array.isArray(array)) { array.forEach(v => stack.__internal.push(v)); stack.size = array.length; } } return stack; } function objectToArray(object) { var stack = new NativeArray(); if(object && typeof object === 'object') { for(var key in object) { if(object[key] && object.hasOwnProperty(key)) { if(typeof object[key] === 'object') { stack.push(objectToArray(object[key])); } else if(!nullOrUndefined(object[key])) { stack.push(object[key]); } } } } else { throw TypeError( 'Object to array conversion needs object ' + 'and not ' + typeof object ); } return stack; } var LIST_TYPEDEF = '[IndexedCollection List]'; class List extends IndexedCollection { constructor(value) { return arguments.length > 1 ? makeList( Array.prototype.slice.call(arguments) ) : makeList(value); } static of (...values) { return this(values); } toString() { return this.__toString('List [', this.__internal.join(',') ,']'); } push(...values) { if(this.__ownerID) { values.forEach(v => this.__internal.push(v)); this.size = this.__internal.length; this.__altered = true; return this; } return makeList(this.__internal.__clone().concat(values)); } shift() { if(this.__ownerID) { this.__internal.pop(); this.size = this.__internal.length; this.__altered = true; return this; } var cloned = this.__internal.__clone(); var newSize = cloned.pop(); return new List(cloned); } clean() { if(this.size === 0) { return this; } if(this.__ownerID) { this.__altered = true; this.__internal = new NativeArray(); this.size = this.__internal.length; return this; } return emptyList(); } __iterator(handle, reverse) { } __ensureOwner(ownerID) { if(ownerID === this.__ownerID) { return this; } if(!ownerID || nullOrUndefined(ownerID)) { this.__ownerID = ownerID; this.__altered = false; return this; } return makeList(this.__internal, ownerID); } } var EMPTY_LIST; function emptyList() { return EMPTY_LIST || (EMPTY_LIST = makeList(null)); } function makeList(values, ownerID) { var list = Object.create(List.prototype); list.__ownerID = ownerID; list.__altered = false; list.__internal = new NativeArray(); list.size = 0; if(nullOrUndefined(values)) { return list; } else if(isNative(values)) { list.__internal = values; } else if (Array.isArray(values)) { list.__internal = new NativeArray(); values.forEach((value, index) => { list.__internal.push(value); }); list.size = list.__internal.length; } else { throw TypeError( 'Expected an array or values as input and not ' + typeof values ); } return list; } toolset__typedef({ List: LIST_TYPEDEF }); List.prototype[IS_LIST_FLAG] = true; List.isList = isList; var MAP_TYPEDEF = '[KeyedCollection Map]'; class src_Map__Map extends KeyedCollection { constructor(value) { return value ? makeMap(value) : emptyMap(); } has(key) { if(key && !nullOrUndefined(this.__internal[key])) { if(this.__internal.hasOwnProperty(key)) { return true; } } return false; } get(key, notSetValue) { if(key && this.has(key)) { return this.__internal[key]; } return notSetValue; } set(key, value) { if(this.__ownerID) { this.__internal[key] = value; this.__altered = true; return this; } var updated = this.__internal.__clone(); updated[key] = value; return makeMap(updated, null); } remove(key) { if(!key || !this.has(key)) { return this; } if(this.__ownerID) { delete this.__internal[key]; this.size = this.size--; this.__altered = true; return this; } var copied = this.__internal.__clone(); delete copied[key]; return makeMap(copied); } clear() { if(this.size === 0) { return this; } if(this.__ownerID) { this.size = 0; this.__altered = true; this.__internal = new NativeObject(); return this; } return makeMap(new NativeObject(null)); } __iterate(handle, reverse) { var object = this.__internal; var keys = this.__keys || Object.keys(object); var maxIndex = keys.length - 1; for(var n = 0; n <= maxIndex; n++) { let key = keys[reverse ? maxIndex - n: n]; if(handle(object[key], key, this) === false) { return n + 1; } } return n; } wasAltered() { return this.__altered; } toString() { return this.__toString('Map {', Object.keys(this.__internal).map((v, index) => { return typeof this.__internal[v] === 'string' ? JSON.stringify(this.__internal[v]) : this.__internal[v]; }),'}'); } toMap() { return this; } } var EMPTY_MAP; function emptyMap() { return EMPTY_MAP || (EMPTY_MAP = makeMap()); } function makeMap(init, ownerID) { var map = Object.create(src_Map__Map.prototype); map.__internal = new NativeObject(); map.__ownerID = ownerID; map.__altered = false; if(init && (isNative(init) || (typeof init === 'object'))) { map.__internal = map.__internal.extend(init); } map.size = Object.keys(map.__internal).length; return map; } toolset__typedef({ Map: MAP_TYPEDEF }); src_Map__Map.prototype[IS_MAP_FLAG] = true; src_Map__Map.isMap = isMap; var SEQUENCE_TYPEDEF = '[Iterable ImmutableSequence]'; class Sequence extends Iterable { constructor(value) { if(value === null || value === undefined) { return emptySequence(); } else if(isIterable(value)) { return value.toSequence(); } else { return sequenceFromValue(value); } throw new Error( 'Couldn\'t create an immutable-sequence of: ' + value ); } static of(...value) { return Sequence(value); } toSequence() { return this; } cacheResult() { if (!this._cache) { this._cache = 'this.entrySeq().toArray()'; //this.size = this._cache.length; } return this; } toString() { return this.__toString('Sequence [', null, ']'); } } var INDEXED_SEQUENCE_TYPEDEF = '[Sequence IndexedSequence]'; class IndexedSequence extends Sequence { constructor(value) { if(nullOrUndefined(value)) { return emptySequence(); } else if(!isIterable(value)) { return indexedSequenceFromData(value); } else if(isKeyed(value)) { return value.entrySequence(); } else { return value.toIndexedSequence(); } throw new Error( 'Couldn\'t create an indexed-sequence of: ' + value ); } static of(sequence) { return IndexedSequence(sequence); } toIndexedSequence() { return this; } toString() { return this.__toString(INDEXED_SEQUENCE_TYPEDEF) } __iterate() { console.log('Iterate on IterableSequence'); } } var ARRAY_SEQUENCE_TYPEDEF = '[IndexedSequence ArraySequence]'; class ArraySequence extends IndexedSequence { constructor(array) { this.__internal = array; this.size = array.length; } __iterate(handle, reverse) { var array = this.__internal; var maxIndex = array.length - 1; for(var n = 0; n <= maxIndex; n++) { let findex = reverse ? maxIndex - n : n; if(handle(array[findex], n, this) === false) { return n + 1; } } return n; } static of(array) { return new ArraySequence(array); } toArraySequence() { return this; } } var KEYED_SEQUENCE_TYPEDEF = '[Sequence KeyedSequence]'; class KeyedSequence extends Sequence { constructor(obj) { } toKeyedSequence() { return this; } } var OBJECT_SEQUENCE_TYPEDEF = '[KeyedSequence ObjectSequence]'; class ObjectSequence extends KeyedSequence { constructor(object) { var keys = Object.keys(object); this.__object = object; this.__keys = keys; this.size = keys.length; } __iterate(handle, reverse) { var object = this.__object; var keys = this.__keys; var maxIndex = keys.length - 1; for(var n = 0; n <= maxIndex; n++) { let key = keys[reverse ? maxIndex - n: n]; if(handle(object[key], key, this) === false) { return n + 1; } } return n; } static of(object) { return new ObjectSequence(object); } toObjectSequence() { return this; } has(key) { return this._object.hasOwnProperty(key); } keys() { return this.__keys; } values() { var results = []; this.keys().map(val => results.push(val)); return results; } } var SET_SEQUENCE_TYPEDEF = '[ArraySequence SetSequence]'; class SetSequence extends ArraySequence { constructor(value) { if(nullOrUndefined(value)) { /* If no value is given, return an empty sequence */ return emptySequence().toSetSequence(); } else if(!isIterable(value)) { /* If not is iterable, return a index sequence */ return indexedSequenceFromData(value).toSetSequence(); } else if(isKeyed(value)) { /* If has keys, get the raw sequence */ return value.entrySequence().toSetSequence(); } else { return emptySequence(value); } throw new Error( 'Couldn\'t create a set-sequence of: ' + value ); } toSetSequence() { return this; } } ObjectSequence.prototype[IS_ORDERED_FLAG] = true; var EMPTY_SEQUENCE; function emptySequence() { return EMPTY_SEQUENCE || (EMPTY_SEQUENCE = new ArraySequence([])); } function maybeIndexedSequenceFromData(value) { return( is__arrayLike(value) ? new ArraySequence(value) : isIterable(value) ? new IndexedSequence(value) : undefined ); } function keyedSequenceFromData(value) { var seq = Array.isArray(value) ? new ArraySequence(value) : typeof value === 'object' ? new ObjectSequence(value) : undefined; if(!seq) { throw new TypeError( 'Expected Array or iterable obejct of [k, v] entries, ' + 'or keyed object: ' + value ); } return seq; } function indexedSequenceFromData(value) { var seq = maybeIndexedSequenceFromData(value); if(!seq) { throw new TypeError( 'Expected Array-like or iterable object of values: ' + value ); } return seq; } function sequenceFromValue(value) { var seq = (typeof value === 'object' && new ObjectSequence(value)) || maybeIndexedSequenceFromData(value); if(!seq) { throw new TypeError( 'Expected Array or iterable object of values, ' + 'or keyed objects: ' + value ); } return seq; } toolset__typedef({ Sequence: SEQUENCE_TYPEDEF, ArraySequence: ARRAY_SEQUENCE_TYPEDEF, IndexedSequence: INDEXED_SEQUENCE_TYPEDEF, KeyedSequence: KEYED_SEQUENCE_TYPEDEF, ObjectSequence: OBJECT_SEQUENCE_TYPEDEF, SetSequence: SET_SEQUENCE_TYPEDEF }); Sequence.Object = ObjectSequence; Sequence.Indexed = IndexedSequence; Sequence.Keyed = KeyedSequence; Sequence.Array = ArraySequence; Sequence.Set = SetSequence; Sequence.isSequence = Flags__isSequence; Sequence.prototype[IS_SEQUENCE_FLAG] = true; function fromJS(native, converter) { return converter ? fromJSWith(converter, native, '', {'': native}) : fromJSDefault(native); } function fromJSWith(converter, native, key, parent) { if(Array.isArray(native)) { return converter.call(parent, key, IndexedSequence(native).map((v, k) => { fromJSWith(converter, v, k, native); })); } else if(maybePlainObject(native)) { return converter.call(parent, key, KeyedSequence(native).map((v, k) => { fromJSWith(converter, v, k, native); })); } } function fromJSDefault(json) { if(Array.isArray(json)) { return IndexedSequence(json); } if(maybePlainObject(json)) { return KeyedSequence(json); } } function maybePlainObject(value) { return value && (value.constructor === Object || value.constructor === undefined); } var SET_TYPEDEF = '[SetCollection Set]'; class src_Set__Set extends SetCollection { constructor(object) { return makeSet(object); } toSet() { return this; } toString() { return this.__toString('Set {', this.__keys.join(','), '}'); } set(key) { var copy = this.__internal.__clone(); copy[key] = true; console.log(copy); return new src_Set__Set( ); } unset(key) { var reduc = delete this.__internal.clone()[key]; return new src_Set__Set(reduc); } __iterate(handle, reverse) { var object = this.__internal; var keys = this.__keys; var maxIndex = keys.length - 1; for(var n = 0; n <= maxIndex; n++) { let key = keys[reverse ? maxIndex - n: n]; if(handle(object[key], key, this) === false) { return n + 1; } } return n; } } var EMPTY_SET; function emptySet() { return EMPTY_SET || (EMPTY_SET = makeSet()); } function makeSet(map, ownerID) { var set = Object.create(src_Set__Set.prototype); set.__internal = new NativeObject(); set.__ownerID = ownerID; if(map && isNative(map)) { set.__internal = map; } else if(map && typeof map === 'object') { set.__internal = set.__internal.extend(map); } set.__keys = Object.keys(set.__internal); set.size = set.__keys.length; return set; } var RECORD_TYPEDEF = '[KeyedCollection Record]'; class Record extends KeyedCollection { constructor(defaultValues, name) { var init; var RecordType = function Record(values) { if(values instanceof RecordType) { return values; } if(!(this instanceof RecordType)) { return new RecordType(values); } if(!init) { init = true; var keys = Object.keys(defaultValues); setProps(RecordTypePrototype, keys); RecordTypePrototype.size = keys.length || 0; RecordTypePrototype.name = name; RecordTypePrototype.__keys = keys; RecordTypePrototype.__defaultValues = defaultValues; } RecordTypePrototype.__internal = new src_Map__Map(); return RecordTypePrototype; } var RecordTypePrototype = RecordType.prototype = Object.create(Record.prototype); RecordTypePrototype.constructor = RecordType; return RecordType; } toString() { return this.__toString(recordName(this) + '{', this.__keys.join(','), '}'); } toMap() { return makeMap(this.__internal, this.__ownerID); } has(key) { return this.__defaultValues.hasOwnProperty(key); } get(key, notSetValue) { if(!this.has(key)) { return notSetValue; } var defval = this.__defaultValues[key]; return this.__internal ? this.__internal.get(key, defval) : defval; } set(key, value) { if(!this.has(key)) { throw new Error('Can\'t set unknown key "' + key + '" on ' + recordName(this)); } var newMap = this.__internal && this.__internal.set(key, value); if(this.__ownerID || newMap === this.__internal) { return this; } return makeRecord(this, newMap); } remove(key) { if (!this.has(key)) { return this; } var newMap = this._map && this.__internal.remove(key); if (this.__ownerID || newMap === this.__internal) { return this; } return makeRecord(this, newMap); } clear() { if(this.__ownerID) { this.__internal && this.__internal.clear(); return this; } var RecordType = this.constructor; return RecordType.__empty || (RecordType.__empty = makeRecord(this, emptyMap())) } wasAltered() { return this.__internal.wasAltered(); } __ensureOwner(ownerID) { if(ownerID === this.__ownerID) { return this; } if(!ownerID || nullOrUndefined(ownerID)) { this.__ownerID = ownerID; this.__altered = false; return this; } return makeRecord(this, this.__internal, ownerID); } } function makeRecord(recordType, map, ownerID) { var record = Object.create(Object.getPrototypeOf(recordType)); record.__internal = map; record.__ownerID = ownerID; return record; } function recordName(record) { return record._name || record.constructor.name || 'Record'; } function setProp(prototype, name) { Object.defineProperty(prototype, name, { get: function() { return this.get(name); }, set: function(value) { invariant(this.__ownerID, 'Can\'t call set on an immutable record.'); this.set(name, value); } }); } function setProps(prototype, names) { try { names.forEach(setProp.bind(undefined, prototype)); } catch (error) { // Maybe IE8. } } toolset__typedef({ Record: RECORD_TYPEDEF }); class Range extends IndexedSequence { constructor(start, end, step) { if(!(this instanceof Range)) { return new Range(start, end, step); } invariant(step !== 0, 'Can\'t create a range with steps by 0'); start = start || 0; if(end === undefined) { end = Infinity; } step = step === undefined ? 1 : Math.abs(step); // Absolute value of number if(end < start) { step = -step; } this.__start = start; this.__end = end; this.__step = step; this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1); if(this.size === 0) { if(EMPTY_RANGE) { return EMPTY_RANGE; } EMPTY_RANGE = this; } } } var EMPTY_RANGE; class Repeat extends Sequence { constructor(value, repeater) { if(!(this instanceof Repeat)) { return new Repeat(value, repeater); } this.__value = value; this.size = repeater === undefined ? Infinity : Math.max(0, repeater); if(this.size === 0) { if(EMPTY_REPEAT) { return EMPTY_REPEAT; } EMPTY_REPEAT = this; } } toString() { return this.__toString('Repeat [', this.__value + ' ' + this.size + ' times', ']'); } includes(search) { return equal(this.__value, search); } indexOf(search) { if(this.includes(search)) { return 0; } return -1; } __iterate(handle) { for(var ii = 0; ii < this.size; ii++) { if(handle(this.__value, ii, this) === false) { return ii + 1; } } return ii; } __ensureOwner(ownerID) { if(ownerID === this.__ownerID) { return this; } if(!ownerID || nullOrUndefined(ownerID)) { this.__ownerID = ownerID; this.__altered = false; return this; } return new Repeat(this.__value, this.size, ownerID); } } var EMPTY_REPEAT; // Polyfills for ES5 and older Browsers var Immutable = { Sequence: Sequence, Iterable: Iterable, Collection: Collection, List: List, Map: src_Map__Map, Native: NativeCollection, Set: src_Set__Set, Stack: Stack, Range: Range, Record: Record, Repeat: Repeat, fromJS: fromJS } return Immutable; }));