UNPKG

immutable-js

Version:
149 lines (130 loc) 4.35 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. */ import { KeyedIterable } from './Iterable'; import { KeyedCollection } from './Collection'; import { NativeObject } from './Native'; import { Map, emptyMap, makeMap } from './Map'; import { invariant, typedef as defineTypeOf } from './util/toolset'; import { nullOrUndefined } from './util/is'; export var RECORD_TYPEDEF = '[KeyedCollection Record]'; export 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 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. } } defineTypeOf({ Record: RECORD_TYPEDEF });