react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / src / utils / LegacyImmutableObject.js
81152 views/**1* Copyright 2013-2014, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under the BSD-style license found in the5* LICENSE file in the root directory of this source tree. An additional grant6* of patent rights can be found in the PATENTS file in the same directory.7*8* @providesModule LegacyImmutableObject9* @typechecks10*/1112"use strict";1314var assign = require('Object.assign');15var invariant = require('invariant');16var isNode = require('isNode');17var mergeHelpers = require('mergeHelpers');1819var checkMergeObjectArgs = mergeHelpers.checkMergeObjectArgs;20var isTerminal = mergeHelpers.isTerminal;2122/**23* Wrapper around JavaScript objects that provide a guarantee of immutability at24* developer time when strict mode is used. The extra computations required to25* enforce immutability is stripped out in production for performance reasons.26*/27var LegacyImmutableObject;2829function assertLegacyImmutableObject(immutableObject) {30invariant(31immutableObject instanceof LegacyImmutableObject,32'LegacyImmutableObject: Attempted to set fields on an object that is not ' +33'an instance of LegacyImmutableObject.'34);35}3637if (__DEV__) {38/**39* Constructs an instance of `LegacyImmutableObject`.40*41* @param {?object} initialProperties The initial set of properties.42* @constructor43*/44LegacyImmutableObject = function LegacyImmutableObject(initialProperties) {45assign(this, initialProperties);46deepFreeze(this);47};4849/**50* Checks if an object should be deep frozen. Instances of51* `LegacyImmutableObject` are assumed to have already been deep frozen.52*53* @param {*} object The object to check.54* @return {boolean} Whether or not deep freeze is needed.55*/56var shouldRecurseFreeze = function(object) {57return (58typeof object === 'object' &&59!(object instanceof LegacyImmutableObject) &&60object !== null61);62};6364/**65* Freezes the supplied object deeply.66*67* @param {*} object The object to freeze.68*/69var deepFreeze = function(object) {70if (isNode(object)) {71return; // Don't try to freeze DOM nodes.72}73Object.freeze(object); // First freeze the object.74for (var prop in object) {75if (object.hasOwnProperty(prop)) {76var field = object[prop];77if (shouldRecurseFreeze(field)) {78deepFreeze(field);79}80}81}82};8384/**85* Returns a new LegacyImmutableObject that is identical to the supplied86* object but with the supplied changes, `put`.87*88* @param {LegacyImmutableObject} immutableObject Starting object.89* @param {?object} put Fields to merge into the object.90* @return {LegacyImmutableObject} The result of merging in `put` fields.91*/92LegacyImmutableObject.set = function(immutableObject, put) {93assertLegacyImmutableObject(immutableObject);94var totalNewFields = assign({}, immutableObject, put);95return new LegacyImmutableObject(totalNewFields);96};9798} else {99/**100* Constructs an instance of `LegacyImmutableObject`.101*102* @param {?object} initialProperties The initial set of properties.103* @constructor104*/105LegacyImmutableObject = function LegacyImmutableObject(initialProperties) {106assign(this, initialProperties);107};108109/**110* Returns a new LegacyImmutableObject that is identical to the supplied111* object but with the supplied changes, `put`.112*113* @param {LegacyImmutableObject} immutableObject Starting object.114* @param {?object} put Fields to merge into the object.115* @return {LegacyImmutableObject} The result of merging in `put` fields.116*/117LegacyImmutableObject.set = function(immutableObject, put) {118assertLegacyImmutableObject(immutableObject);119var newMap = new LegacyImmutableObject(immutableObject);120assign(newMap, put);121return newMap;122};123}124125/**126* Sugar for:127* `LegacyImmutableObject.set(LegacyImmutableObject, {fieldName: putField})`.128*129* @param {LegacyImmutableObject} immutableObject Object on which to set field.130* @param {string} fieldName Name of the field to set.131* @param {*} putField Value of the field to set.132* @return {LegacyImmutableObject} [description]133*/134LegacyImmutableObject.setField = function(immutableObject, fieldName, putField) {135var put = {};136put[fieldName] = putField;137return LegacyImmutableObject.set(immutableObject, put);138};139140/**141* Returns a new LegacyImmutableObject that is identical to the supplied object142* but with the supplied changes recursively applied.143*144* @param {LegacyImmutableObject} immutableObject Object on which to set fields.145* @param {object} put Fields to merge into the object.146* @return {LegacyImmutableObject} The result of merging in `put` fields.147*/148LegacyImmutableObject.setDeep = function(immutableObject, put) {149assertLegacyImmutableObject(immutableObject);150return _setDeep(immutableObject, put);151};152153function _setDeep(object, put) {154checkMergeObjectArgs(object, put);155var totalNewFields = {};156157// To maintain the order of the keys, copy the base object's entries first.158var keys = Object.keys(object);159for (var ii = 0; ii < keys.length; ii++) {160var key = keys[ii];161if (!put.hasOwnProperty(key)) {162totalNewFields[key] = object[key];163} else if (isTerminal(object[key]) || isTerminal(put[key])) {164totalNewFields[key] = put[key];165} else {166totalNewFields[key] = _setDeep(object[key], put[key]);167}168}169170// Apply any new keys that the base object didn't have.171var newKeys = Object.keys(put);172for (ii = 0; ii < newKeys.length; ii++) {173var newKey = newKeys[ii];174if (object.hasOwnProperty(newKey)) {175continue;176}177totalNewFields[newKey] = put[newKey];178}179180return (object instanceof LegacyImmutableObject ||181put instanceof LegacyImmutableObject) ?182new LegacyImmutableObject(totalNewFields) :183totalNewFields;184}185186module.exports = LegacyImmutableObject;187188189