Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81158 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 ImmutableObject
10
*/
11
12
"use strict";
13
14
var Immutable = require('Immutable');
15
16
var invariant = require('invariant');
17
var keyOf = require('keyOf');
18
var mergeHelpers = require('mergeHelpers');
19
20
var checkMergeObjectArgs = mergeHelpers.checkMergeObjectArgs;
21
var isTerminal = mergeHelpers.isTerminal;
22
23
var SECRET_KEY = keyOf({_DONT_EVER_TYPE_THIS_SECRET_KEY: null});
24
25
/**
26
* Static methods creating and operating on instances of `Immutable`.
27
*/
28
function assertImmutable(immutable) {
29
invariant(
30
immutable instanceof Immutable,
31
'ImmutableObject: Attempted to set fields on an object that is not an ' +
32
'instance of Immutable.'
33
);
34
}
35
36
/**
37
* Static methods for reasoning about instances of `ImmutableObject`. Execute
38
* the freeze commands in `__DEV__` mode to alert the programmer that something
39
* is attempting to mutate. Since freezing is very expensive, we avoid doing it
40
* at all in production.
41
*/
42
class ImmutableObject extends Immutable {
43
/**
44
* @arguments {array<object>} The arguments is an array of objects that, when
45
* merged together, will form the immutable objects.
46
*/
47
constructor() {
48
super(Immutable[SECRET_KEY]);
49
Immutable.mergeAllPropertiesInto(this, arguments);
50
if (__DEV__) {
51
Immutable.deepFreezeRootNode(this);
52
}
53
}
54
55
/**
56
* DEPRECATED - prefer to instantiate with new ImmutableObject().
57
*
58
* @arguments {array<object>} The arguments is an array of objects that, when
59
* merged together, will form the immutable objects.
60
*/
61
static create() {
62
var obj = Object.create(ImmutableObject.prototype);
63
ImmutableObject.apply(obj, arguments);
64
return obj;
65
}
66
67
/**
68
* Returns a new `Immutable` that is identical to the supplied `Immutable`
69
* but with the specified changes, `put`. Any keys that are in the
70
* intersection of `immutable` and `put` retain the ordering of `immutable.
71
* New keys are placed after keys that exist in `immutable`.
72
*
73
* @param {Immutable} immutable Starting object.
74
* @param {?object} put Fields to merge into the object.
75
* @return {Immutable} The result of merging in `put` fields.
76
*/
77
static set(immutable, put) {
78
assertImmutable(immutable);
79
invariant(
80
typeof put === 'object' && put !== undefined && !Array.isArray(put),
81
'Invalid ImmutableMap.set argument `put`'
82
);
83
return new ImmutableObject(immutable, put);
84
}
85
86
/**
87
* Sugar for `ImmutableObject.set(ImmutableObject, {fieldName: putField})`.
88
* Look out for key crushing: Use `keyOf()` to guard against it.
89
*
90
* @param {Immutable} immutable Object on which to set properties.
91
* @param {string} fieldName Name of the field to set.
92
* @param {*} putField Value of the field to set.
93
* @return {Immutable} new Immutable as described in `set`.
94
*/
95
static setProperty(immutableObject, fieldName, putField) {
96
var put = {};
97
put[fieldName] = putField;
98
return ImmutableObject.set(immutableObject, put);
99
}
100
101
/**
102
* Returns a new `Immutable` that is identical to the supplied object but
103
* with the supplied changes recursively applied.
104
*
105
* Experimental. Likely does not handle `Arrays` correctly.
106
*
107
* @param {Immutable} immutable Object on which to set fields.
108
* @param {object} put Fields to merge into the object.
109
* @return {Immutable} The result of merging in `put` fields.
110
*/
111
static setDeep(immutable, put) {
112
assertImmutable(immutable);
113
return _setDeep(immutable, put);
114
}
115
}
116
117
function _setDeep(obj, put) {
118
checkMergeObjectArgs(obj, put);
119
var totalNewFields = {};
120
121
// To maintain the order of the keys, copy the base object's entries first.
122
var keys = Object.keys(obj);
123
for (var ii = 0; ii < keys.length; ii++) {
124
var key = keys[ii];
125
if (!put.hasOwnProperty(key)) {
126
totalNewFields[key] = obj[key];
127
} else if (isTerminal(obj[key]) || isTerminal(put[key])) {
128
totalNewFields[key] = put[key];
129
} else {
130
totalNewFields[key] = _setDeep(obj[key], put[key]);
131
}
132
}
133
134
// Apply any new keys that the base obj didn't have.
135
var newKeys = Object.keys(put);
136
for (ii = 0; ii < newKeys.length; ii++) {
137
var newKey = newKeys[ii];
138
if (obj.hasOwnProperty(newKey)) {
139
continue;
140
}
141
totalNewFields[newKey] = put[newKey];
142
}
143
144
return (
145
obj instanceof Immutable ? new ImmutableObject(totalNewFields) :
146
put instanceof Immutable ? new ImmutableObject(totalNewFields) :
147
totalNewFields
148
);
149
}
150
151
module.exports = ImmutableObject;
152
153