Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81152 views
1
/**
2
* Copyright 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 ReactElement
10
*/
11
12
"use strict";
13
14
var ReactContext = require('ReactContext');
15
var ReactCurrentOwner = require('ReactCurrentOwner');
16
17
var warning = require('warning');
18
19
var RESERVED_PROPS = {
20
key: true,
21
ref: true
22
};
23
24
/**
25
* Warn for mutations.
26
*
27
* @internal
28
* @param {object} object
29
* @param {string} key
30
*/
31
function defineWarningProperty(object, key) {
32
Object.defineProperty(object, key, {
33
34
configurable: false,
35
enumerable: true,
36
37
get: function() {
38
if (!this._store) {
39
return null;
40
}
41
return this._store[key];
42
},
43
44
set: function(value) {
45
warning(
46
false,
47
'Don\'t set the ' + key + ' property of the component. ' +
48
'Mutate the existing props object instead.'
49
);
50
this._store[key] = value;
51
}
52
53
});
54
}
55
56
/**
57
* This is updated to true if the membrane is successfully created.
58
*/
59
var useMutationMembrane = false;
60
61
/**
62
* Warn for mutations.
63
*
64
* @internal
65
* @param {object} element
66
*/
67
function defineMutationMembrane(prototype) {
68
try {
69
var pseudoFrozenProperties = {
70
props: true
71
};
72
for (var key in pseudoFrozenProperties) {
73
defineWarningProperty(prototype, key);
74
}
75
useMutationMembrane = true;
76
} catch (x) {
77
// IE will fail on defineProperty
78
}
79
}
80
81
/**
82
* Base constructor for all React elements. This is only used to make this
83
* work with a dynamic instanceof check. Nothing should live on this prototype.
84
*
85
* @param {*} type
86
* @param {string|object} ref
87
* @param {*} key
88
* @param {*} props
89
* @internal
90
*/
91
var ReactElement = function(type, key, ref, owner, context, props) {
92
// Built-in properties that belong on the element
93
this.type = type;
94
this.key = key;
95
this.ref = ref;
96
97
// Record the component responsible for creating this element.
98
this._owner = owner;
99
100
// TODO: Deprecate withContext, and then the context becomes accessible
101
// through the owner.
102
this._context = context;
103
104
if (__DEV__) {
105
// The validation flag and props are currently mutative. We put them on
106
// an external backing store so that we can freeze the whole object.
107
// This can be replaced with a WeakMap once they are implemented in
108
// commonly used development environments.
109
this._store = { validated: false, props: props };
110
111
// We're not allowed to set props directly on the object so we early
112
// return and rely on the prototype membrane to forward to the backing
113
// store.
114
if (useMutationMembrane) {
115
Object.freeze(this);
116
return;
117
}
118
}
119
120
this.props = props;
121
};
122
123
// We intentionally don't expose the function on the constructor property.
124
// ReactElement should be indistinguishable from a plain object.
125
ReactElement.prototype = {
126
_isReactElement: true
127
};
128
129
if (__DEV__) {
130
defineMutationMembrane(ReactElement.prototype);
131
}
132
133
ReactElement.createElement = function(type, config, children) {
134
var propName;
135
136
// Reserved names are extracted
137
var props = {};
138
139
var key = null;
140
var ref = null;
141
142
if (config != null) {
143
ref = config.ref === undefined ? null : config.ref;
144
if (__DEV__) {
145
warning(
146
config.key !== null,
147
'createElement(...): Encountered component with a `key` of null. In ' +
148
'a future version, this will be treated as equivalent to the string ' +
149
'\'null\'; instead, provide an explicit key or use undefined.'
150
);
151
}
152
// TODO: Change this back to `config.key === undefined`
153
key = config.key == null ? null : '' + config.key;
154
// Remaining properties are added to a new props object
155
for (propName in config) {
156
if (config.hasOwnProperty(propName) &&
157
!RESERVED_PROPS.hasOwnProperty(propName)) {
158
props[propName] = config[propName];
159
}
160
}
161
}
162
163
// Children can be more than one argument, and those are transferred onto
164
// the newly allocated props object.
165
var childrenLength = arguments.length - 2;
166
if (childrenLength === 1) {
167
props.children = children;
168
} else if (childrenLength > 1) {
169
var childArray = Array(childrenLength);
170
for (var i = 0; i < childrenLength; i++) {
171
childArray[i] = arguments[i + 2];
172
}
173
props.children = childArray;
174
}
175
176
// Resolve default props
177
if (type && type.defaultProps) {
178
var defaultProps = type.defaultProps;
179
for (propName in defaultProps) {
180
if (typeof props[propName] === 'undefined') {
181
props[propName] = defaultProps[propName];
182
}
183
}
184
}
185
186
return new ReactElement(
187
type,
188
key,
189
ref,
190
ReactCurrentOwner.current,
191
ReactContext.current,
192
props
193
);
194
};
195
196
ReactElement.createFactory = function(type) {
197
var factory = ReactElement.createElement.bind(null, type);
198
// Expose the type on the factory and the prototype so that it can be
199
// easily accessed on elements. E.g. <Foo />.type === Foo.type.
200
// This should not be named `constructor` since this may not be the function
201
// that created the element, and it may not even be a constructor.
202
factory.type = type;
203
return factory;
204
};
205
206
ReactElement.cloneAndReplaceProps = function(oldElement, newProps) {
207
var newElement = new ReactElement(
208
oldElement.type,
209
oldElement.key,
210
oldElement.ref,
211
oldElement._owner,
212
oldElement._context,
213
newProps
214
);
215
216
if (__DEV__) {
217
// If the key on the original is valid, then the clone is valid
218
newElement._store.validated = oldElement._store.validated;
219
}
220
return newElement;
221
};
222
223
/**
224
* @param {?object} object
225
* @return {boolean} True if `object` is a valid component.
226
* @final
227
*/
228
ReactElement.isValidElement = function(object) {
229
// ReactTestUtils is often used outside of beforeEach where as React is
230
// within it. This leads to two different instances of React on the same
231
// page. To identify a element from a different React instance we use
232
// a flag instead of an instanceof check.
233
var isElement = !!(object && object._isReactElement);
234
// if (isElement && !(object instanceof ReactElement)) {
235
// This is an indicator that you're using multiple versions of React at the
236
// same time. This will screw with ownership and stuff. Fix it, please.
237
// TODO: We could possibly warn here.
238
// }
239
return isElement;
240
};
241
242
module.exports = ReactElement;
243
244