Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81152 views
1
/**
2
* Copyright 2013-2014, Facebook, Inc.
3
* All rights reserved.
4
*
5
* This source code is licensed under the BSD-style license found in the
6
* LICENSE file in the root directory of this source tree. An additional grant
7
* of patent rights can be found in the PATENTS file in the same directory.
8
*
9
* @providesModule LegacyImmutableObject
10
* @typechecks
11
*/
12
13
"use strict";
14
15
var assign = require('Object.assign');
16
var invariant = require('invariant');
17
var isNode = require('isNode');
18
var mergeHelpers = require('mergeHelpers');
19
20
var checkMergeObjectArgs = mergeHelpers.checkMergeObjectArgs;
21
var isTerminal = mergeHelpers.isTerminal;
22
23
/**
24
* Wrapper around JavaScript objects that provide a guarantee of immutability at
25
* developer time when strict mode is used. The extra computations required to
26
* enforce immutability is stripped out in production for performance reasons.
27
*/
28
var LegacyImmutableObject;
29
30
function assertLegacyImmutableObject(immutableObject) {
31
invariant(
32
immutableObject instanceof LegacyImmutableObject,
33
'LegacyImmutableObject: Attempted to set fields on an object that is not ' +
34
'an instance of LegacyImmutableObject.'
35
);
36
}
37
38
if (__DEV__) {
39
/**
40
* Constructs an instance of `LegacyImmutableObject`.
41
*
42
* @param {?object} initialProperties The initial set of properties.
43
* @constructor
44
*/
45
LegacyImmutableObject = function LegacyImmutableObject(initialProperties) {
46
assign(this, initialProperties);
47
deepFreeze(this);
48
};
49
50
/**
51
* Checks if an object should be deep frozen. Instances of
52
* `LegacyImmutableObject` are assumed to have already been deep frozen.
53
*
54
* @param {*} object The object to check.
55
* @return {boolean} Whether or not deep freeze is needed.
56
*/
57
var shouldRecurseFreeze = function(object) {
58
return (
59
typeof object === 'object' &&
60
!(object instanceof LegacyImmutableObject) &&
61
object !== null
62
);
63
};
64
65
/**
66
* Freezes the supplied object deeply.
67
*
68
* @param {*} object The object to freeze.
69
*/
70
var deepFreeze = function(object) {
71
if (isNode(object)) {
72
return; // Don't try to freeze DOM nodes.
73
}
74
Object.freeze(object); // First freeze the object.
75
for (var prop in object) {
76
if (object.hasOwnProperty(prop)) {
77
var field = object[prop];
78
if (shouldRecurseFreeze(field)) {
79
deepFreeze(field);
80
}
81
}
82
}
83
};
84
85
/**
86
* Returns a new LegacyImmutableObject that is identical to the supplied
87
* object but with the supplied changes, `put`.
88
*
89
* @param {LegacyImmutableObject} immutableObject Starting object.
90
* @param {?object} put Fields to merge into the object.
91
* @return {LegacyImmutableObject} The result of merging in `put` fields.
92
*/
93
LegacyImmutableObject.set = function(immutableObject, put) {
94
assertLegacyImmutableObject(immutableObject);
95
var totalNewFields = assign({}, immutableObject, put);
96
return new LegacyImmutableObject(totalNewFields);
97
};
98
99
} else {
100
/**
101
* Constructs an instance of `LegacyImmutableObject`.
102
*
103
* @param {?object} initialProperties The initial set of properties.
104
* @constructor
105
*/
106
LegacyImmutableObject = function LegacyImmutableObject(initialProperties) {
107
assign(this, initialProperties);
108
};
109
110
/**
111
* Returns a new LegacyImmutableObject that is identical to the supplied
112
* object but with the supplied changes, `put`.
113
*
114
* @param {LegacyImmutableObject} immutableObject Starting object.
115
* @param {?object} put Fields to merge into the object.
116
* @return {LegacyImmutableObject} The result of merging in `put` fields.
117
*/
118
LegacyImmutableObject.set = function(immutableObject, put) {
119
assertLegacyImmutableObject(immutableObject);
120
var newMap = new LegacyImmutableObject(immutableObject);
121
assign(newMap, put);
122
return newMap;
123
};
124
}
125
126
/**
127
* Sugar for:
128
* `LegacyImmutableObject.set(LegacyImmutableObject, {fieldName: putField})`.
129
*
130
* @param {LegacyImmutableObject} immutableObject Object on which to set field.
131
* @param {string} fieldName Name of the field to set.
132
* @param {*} putField Value of the field to set.
133
* @return {LegacyImmutableObject} [description]
134
*/
135
LegacyImmutableObject.setField = function(immutableObject, fieldName, putField) {
136
var put = {};
137
put[fieldName] = putField;
138
return LegacyImmutableObject.set(immutableObject, put);
139
};
140
141
/**
142
* Returns a new LegacyImmutableObject that is identical to the supplied object
143
* but with the supplied changes recursively applied.
144
*
145
* @param {LegacyImmutableObject} immutableObject Object on which to set fields.
146
* @param {object} put Fields to merge into the object.
147
* @return {LegacyImmutableObject} The result of merging in `put` fields.
148
*/
149
LegacyImmutableObject.setDeep = function(immutableObject, put) {
150
assertLegacyImmutableObject(immutableObject);
151
return _setDeep(immutableObject, put);
152
};
153
154
function _setDeep(object, put) {
155
checkMergeObjectArgs(object, put);
156
var totalNewFields = {};
157
158
// To maintain the order of the keys, copy the base object's entries first.
159
var keys = Object.keys(object);
160
for (var ii = 0; ii < keys.length; ii++) {
161
var key = keys[ii];
162
if (!put.hasOwnProperty(key)) {
163
totalNewFields[key] = object[key];
164
} else if (isTerminal(object[key]) || isTerminal(put[key])) {
165
totalNewFields[key] = put[key];
166
} else {
167
totalNewFields[key] = _setDeep(object[key], put[key]);
168
}
169
}
170
171
// Apply any new keys that the base object didn't have.
172
var newKeys = Object.keys(put);
173
for (ii = 0; ii < newKeys.length; ii++) {
174
var newKey = newKeys[ii];
175
if (object.hasOwnProperty(newKey)) {
176
continue;
177
}
178
totalNewFields[newKey] = put[newKey];
179
}
180
181
return (object instanceof LegacyImmutableObject ||
182
put instanceof LegacyImmutableObject) ?
183
new LegacyImmutableObject(totalNewFields) :
184
totalNewFields;
185
}
186
187
module.exports = LegacyImmutableObject;
188
189