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 Immutable
10
*/
11
12
var assign = require('Object.assign');
13
var invariant = require('invariant');
14
var isNode = require('isNode');
15
var keyOf = require('keyOf');
16
17
var SECRET_KEY = keyOf({_DONT_EVER_TYPE_THIS_SECRET_KEY: null});
18
19
/**
20
* `Immutable` provides a guarantee of immutability at developer time when
21
* strict mode is used. The extra computations required to enforce immutability
22
* are stripped out in production for performance reasons. `Immutable`
23
* guarantees to enforce immutability for enumerable, own properties. This
24
* allows easy wrapping of `Immutable` with the ability to store non-enumerable
25
* properties on the instance that only your static methods reason about. In
26
* order to achieve IE8 compatibility (which doesn't have the ability to define
27
* non-enumerable properties), modules that want to build their own reasoning
28
* of `Immutable`s and store computations can define their non-enumerable
29
* properties under the name `toString`, and in IE8 only define a standard
30
* property called `toString` which will mistakenly be considered not
31
* enumerable due to its name (but only in IE8). The only limitation is that no
32
* one can store their own `toString` property.
33
* https://developer.mozilla.org/en-US/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
34
*/
35
class Immutable {
36
/**
37
* An instance of `Immutable` appears to be a plain JavaScript object, except
38
* `instanceof Immutable` evaluates to `true`, and it is deeply frozen in
39
* development mode.
40
*
41
* @param {number} secret Ensures this isn't accidentally constructed outside
42
* of convenience constructors. If created outside of a convenience
43
* constructor, may not be frozen. Forbidding that use case for now until we
44
* have a better API.
45
*/
46
constructor(secret) {
47
invariant(
48
secret === Immutable[SECRET_KEY],
49
'Only certain classes should create instances of `Immutable`.' +
50
'You probably want something like ImmutableObject.create.'
51
);
52
}
53
54
/**
55
* Helper method for classes that make use of `Immutable`.
56
* @param {Immutable} immutable Object to merge properties into.
57
* @param {array<object>} propertyObjects List of objects to merge into
58
* `destination`.
59
*/
60
static mergeAllPropertiesInto(destination, propertyObjects) {
61
var argLength = propertyObjects.length;
62
for (var i = 0; i < argLength; i++) {
63
assign(destination, propertyObjects[i]);
64
}
65
}
66
67
68
/**
69
* Freezes the supplied object deeply. Other classes may implement their own
70
* version based on this.
71
*
72
* @param {*} object The object to freeze.
73
*/
74
static deepFreezeRootNode(object) {
75
if (isNode(object)) {
76
return; // Don't try to freeze DOM nodes.
77
}
78
Object.freeze(object); // First freeze the object.
79
for (var prop in object) {
80
if (object.hasOwnProperty(prop)) {
81
Immutable.recurseDeepFreeze(object[prop]);
82
}
83
}
84
Object.seal(object);
85
}
86
87
/**
88
* Differs from `deepFreezeRootNode`, in that we first check if this is a
89
* necessary recursion. If the object is already an `Immutable`, then the
90
* recursion is unnecessary as it is already frozen. That check obviously
91
* wouldn't work for the root node version `deepFreezeRootNode`!
92
*/
93
static recurseDeepFreeze(object) {
94
if (isNode(object) || !Immutable.shouldRecurseFreeze(object)) {
95
return; // Don't try to freeze DOM nodes.
96
}
97
Object.freeze(object); // First freeze the object.
98
for (var prop in object) {
99
if (object.hasOwnProperty(prop)) {
100
Immutable.recurseDeepFreeze(object[prop]);
101
}
102
}
103
Object.seal(object);
104
}
105
106
/**
107
* Checks if an object should be deep frozen. Instances of `Immutable` are
108
* assumed to have already been deep frozen, so we can have large `__DEV__`
109
* time savings by skipping freezing of them.
110
*
111
* @param {*} object The object to check.
112
* @return {boolean} Whether or not deep freeze is needed.
113
*/
114
static shouldRecurseFreeze(object) {
115
return (
116
typeof object === 'object' &&
117
!(object instanceof Immutable) &&
118
object !== null
119
);
120
}
121
}
122
123
Immutable._DONT_EVER_TYPE_THIS_SECRET_KEY = Math.random();
124
125
module.exports = Immutable;
126
127