react 0.10.0 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/JSXTransformer.js +20344 -0
- package/dist/react-with-addons.js +20276 -0
- package/dist/react-with-addons.min.js +22 -0
- package/dist/react.js +18484 -0
- package/dist/react.min.js +21 -0
- package/lib/BeforeInputEventPlugin.js +222 -0
- package/lib/CSSPropertyOperations.js +3 -3
- package/lib/{ReactMountReady.js → CallbackQueue.js} +32 -24
- package/lib/ChangeEventPlugin.js +1 -1
- package/lib/CompositionEventPlugin.js +5 -1
- package/lib/DOMChildrenOperations.js +21 -14
- package/lib/DOMProperty.js +45 -17
- package/lib/DOMPropertyOperations.js +22 -10
- package/lib/DefaultEventPluginOrder.js +1 -0
- package/lib/EventConstants.js +1 -0
- package/lib/EventListener.js +5 -2
- package/lib/EventPluginHub.js +0 -5
- package/lib/EventPluginRegistry.js +6 -4
- package/lib/EventPluginUtils.js +11 -1
- package/lib/ExecutionEnvironment.js +8 -2
- package/lib/{DefaultDOMPropertyConfig.js → HTMLDOMPropertyConfig.js} +42 -49
- package/lib/LinkedValueUtils.js +21 -22
- package/lib/LocalEventTrapMixin.js +52 -0
- package/lib/React.js +57 -3
- package/lib/ReactBrowserComponentMixin.js +4 -0
- package/lib/{ReactEventEmitter.js → ReactBrowserEventEmitter.js} +115 -94
- package/lib/ReactCSSTransitionGroup.js +2 -0
- package/lib/ReactCSSTransitionGroupChild.js +2 -5
- package/lib/ReactChildren.js +31 -10
- package/lib/ReactComponent.js +88 -237
- package/lib/ReactComponentBrowserEnvironment.js +3 -2
- package/lib/ReactComponentWithPureRenderMixin.js +54 -0
- package/lib/ReactCompositeComponent.js +222 -384
- package/lib/ReactDOM.js +22 -18
- package/lib/ReactDOMComponent.js +26 -24
- package/lib/ReactDOMForm.js +5 -13
- package/lib/ReactDOMIDOperations.js +2 -31
- package/lib/ReactDOMImg.js +5 -14
- package/lib/ReactDOMSelect.js +16 -15
- package/lib/ReactDOMSelection.js +35 -10
- package/lib/ReactDOMTextarea.js +2 -4
- package/lib/ReactDefaultBatchingStrategy.js +3 -3
- package/lib/ReactDefaultInjection.js +18 -15
- package/lib/ReactDefaultPerf.js +28 -11
- package/lib/ReactDefaultPerfAnalysis.js +4 -0
- package/lib/ReactDescriptor.js +251 -0
- package/lib/ReactDescriptorValidator.js +283 -0
- package/lib/ReactEmptyComponent.js +78 -0
- package/lib/ReactEventEmitterMixin.js +1 -3
- package/lib/ReactEventListener.js +189 -0
- package/lib/ReactInjection.js +4 -2
- package/lib/ReactLink.js +24 -0
- package/lib/ReactMount.js +51 -19
- package/lib/ReactMultiChild.js +9 -11
- package/lib/ReactPropTransferer.js +44 -29
- package/lib/ReactPropTypes.js +226 -242
- package/lib/ReactPutListenerQueue.js +2 -2
- package/lib/ReactReconcileTransaction.js +14 -14
- package/lib/ReactServerRendering.js +5 -5
- package/lib/ReactServerRenderingTransaction.js +4 -5
- package/lib/ReactTestUtils.js +39 -21
- package/lib/ReactTextComponent.js +8 -22
- package/lib/ReactTransitionChildMapping.js +2 -2
- package/lib/ReactTransitionEvents.js +19 -0
- package/lib/ReactTransitionGroup.js +9 -6
- package/lib/ReactUpdates.js +139 -22
- package/lib/ReactWithAddons.js +5 -2
- package/lib/SVGDOMPropertyConfig.js +97 -0
- package/lib/SimpleEventPlugin.js +7 -1
- package/lib/SyntheticInputEvent.js +52 -0
- package/lib/SyntheticKeyboardEvent.js +33 -4
- package/lib/SyntheticMouseEvent.js +3 -0
- package/lib/SyntheticTouchEvent.js +4 -1
- package/lib/SyntheticUIEvent.js +24 -2
- package/lib/Transaction.js +0 -32
- package/lib/cloneWithProps.js +3 -1
- package/lib/createFullPageComponent.js +1 -1
- package/lib/dangerousStyleValue.js +11 -5
- package/lib/escapeTextForBrowser.js +2 -3
- package/lib/flattenChildren.js +9 -7
- package/lib/getEventKey.js +35 -5
- package/lib/getEventModifierState.js +52 -0
- package/lib/getMarkupWrap.js +2 -0
- package/lib/getTextContentAccessor.js +1 -1
- package/lib/hyphenate.js +3 -0
- package/lib/hyphenateStyleName.js +46 -0
- package/lib/instantiateReactComponent.js +13 -21
- package/lib/invariant.js +17 -19
- package/lib/{objMap.js → mapObject.js} +8 -3
- package/lib/mergeHelpers.js +11 -0
- package/lib/mergeInto.js +3 -2
- package/lib/onlyChild.js +3 -3
- package/lib/performance.js +33 -0
- package/lib/performanceNow.js +5 -14
- package/lib/setInnerHTML.js +85 -0
- package/lib/shouldUpdateReactComponent.js +12 -29
- package/lib/toArray.js +1 -1
- package/lib/traverseAllChildren.js +7 -4
- package/lib/update.js +57 -45
- package/package.json +4 -3
- package/lib/ReactEventTopLevelCallback.js +0 -149
- package/lib/createObjectFrom.js +0 -61
- package/lib/objMapKeyVal.js +0 -47
package/lib/ReactDOMTextarea.js
CHANGED
|
@@ -88,8 +88,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
|
88
88
|
// `textContent` (unnecessary since we update value).
|
|
89
89
|
// The initial value can be a boolean or object so that's why it's
|
|
90
90
|
// forced to be a string.
|
|
91
|
-
initialValue: '' + (value != null ? value : defaultValue)
|
|
92
|
-
value: defaultValue
|
|
91
|
+
initialValue: '' + (value != null ? value : defaultValue)
|
|
93
92
|
};
|
|
94
93
|
},
|
|
95
94
|
|
|
@@ -101,7 +100,6 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
|
101
100
|
render: function() {
|
|
102
101
|
// Clone `this.props` so we don't mutate the input.
|
|
103
102
|
var props = merge(this.props);
|
|
104
|
-
var value = LinkedValueUtils.getValue(this);
|
|
105
103
|
|
|
106
104
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
107
105
|
props.dangerouslySetInnerHTML == null,
|
|
@@ -109,7 +107,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
|
|
109
107
|
) : invariant(props.dangerouslySetInnerHTML == null));
|
|
110
108
|
|
|
111
109
|
props.defaultValue = null;
|
|
112
|
-
props.value =
|
|
110
|
+
props.value = null;
|
|
113
111
|
props.onChange = this._handleChange;
|
|
114
112
|
|
|
115
113
|
// Always set children to the same thing. In IE9, the selection range will
|
|
@@ -58,16 +58,16 @@ var ReactDefaultBatchingStrategy = {
|
|
|
58
58
|
* Call the provided function in a context within which calls to `setState`
|
|
59
59
|
* and friends are batched such that components aren't updated unnecessarily.
|
|
60
60
|
*/
|
|
61
|
-
batchedUpdates: function(callback,
|
|
61
|
+
batchedUpdates: function(callback, a, b) {
|
|
62
62
|
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
|
|
63
63
|
|
|
64
64
|
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
|
|
65
65
|
|
|
66
66
|
// The code is written this way to avoid extra allocations
|
|
67
67
|
if (alreadyBatchingUpdates) {
|
|
68
|
-
callback(
|
|
68
|
+
callback(a, b);
|
|
69
69
|
} else {
|
|
70
|
-
transaction.perform(callback, null,
|
|
70
|
+
transaction.perform(callback, null, a, b);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
};
|
|
@@ -18,22 +18,19 @@
|
|
|
18
18
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
var ExecutionEnvironment = require("./ExecutionEnvironment");
|
|
24
|
-
|
|
25
|
-
var DefaultDOMPropertyConfig = require("./DefaultDOMPropertyConfig");
|
|
26
|
-
|
|
21
|
+
var BeforeInputEventPlugin = require("./BeforeInputEventPlugin");
|
|
27
22
|
var ChangeEventPlugin = require("./ChangeEventPlugin");
|
|
28
23
|
var ClientReactRootIndex = require("./ClientReactRootIndex");
|
|
29
24
|
var CompositionEventPlugin = require("./CompositionEventPlugin");
|
|
30
25
|
var DefaultEventPluginOrder = require("./DefaultEventPluginOrder");
|
|
31
26
|
var EnterLeaveEventPlugin = require("./EnterLeaveEventPlugin");
|
|
27
|
+
var ExecutionEnvironment = require("./ExecutionEnvironment");
|
|
28
|
+
var HTMLDOMPropertyConfig = require("./HTMLDOMPropertyConfig");
|
|
32
29
|
var MobileSafariClickEventPlugin = require("./MobileSafariClickEventPlugin");
|
|
33
30
|
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
34
31
|
var ReactComponentBrowserEnvironment =
|
|
35
32
|
require("./ReactComponentBrowserEnvironment");
|
|
36
|
-
var
|
|
33
|
+
var ReactDefaultBatchingStrategy = require("./ReactDefaultBatchingStrategy");
|
|
37
34
|
var ReactDOM = require("./ReactDOM");
|
|
38
35
|
var ReactDOMButton = require("./ReactDOMButton");
|
|
39
36
|
var ReactDOMForm = require("./ReactDOMForm");
|
|
@@ -42,19 +39,20 @@ var ReactDOMInput = require("./ReactDOMInput");
|
|
|
42
39
|
var ReactDOMOption = require("./ReactDOMOption");
|
|
43
40
|
var ReactDOMSelect = require("./ReactDOMSelect");
|
|
44
41
|
var ReactDOMTextarea = require("./ReactDOMTextarea");
|
|
42
|
+
var ReactEventListener = require("./ReactEventListener");
|
|
43
|
+
var ReactInjection = require("./ReactInjection");
|
|
45
44
|
var ReactInstanceHandles = require("./ReactInstanceHandles");
|
|
46
45
|
var ReactMount = require("./ReactMount");
|
|
47
46
|
var SelectEventPlugin = require("./SelectEventPlugin");
|
|
48
47
|
var ServerReactRootIndex = require("./ServerReactRootIndex");
|
|
49
48
|
var SimpleEventPlugin = require("./SimpleEventPlugin");
|
|
50
|
-
|
|
51
|
-
var ReactDefaultBatchingStrategy = require("./ReactDefaultBatchingStrategy");
|
|
49
|
+
var SVGDOMPropertyConfig = require("./SVGDOMPropertyConfig");
|
|
52
50
|
|
|
53
51
|
var createFullPageComponent = require("./createFullPageComponent");
|
|
54
52
|
|
|
55
53
|
function inject() {
|
|
56
|
-
ReactInjection.EventEmitter.
|
|
57
|
-
|
|
54
|
+
ReactInjection.EventEmitter.injectReactEventListener(
|
|
55
|
+
ReactEventListener
|
|
58
56
|
);
|
|
59
57
|
|
|
60
58
|
/**
|
|
@@ -74,7 +72,8 @@ function inject() {
|
|
|
74
72
|
ChangeEventPlugin: ChangeEventPlugin,
|
|
75
73
|
CompositionEventPlugin: CompositionEventPlugin,
|
|
76
74
|
MobileSafariClickEventPlugin: MobileSafariClickEventPlugin,
|
|
77
|
-
SelectEventPlugin: SelectEventPlugin
|
|
75
|
+
SelectEventPlugin: SelectEventPlugin,
|
|
76
|
+
BeforeInputEventPlugin: BeforeInputEventPlugin
|
|
78
77
|
});
|
|
79
78
|
|
|
80
79
|
ReactInjection.DOM.injectComponentClasses({
|
|
@@ -88,17 +87,21 @@ function inject() {
|
|
|
88
87
|
|
|
89
88
|
html: createFullPageComponent(ReactDOM.html),
|
|
90
89
|
head: createFullPageComponent(ReactDOM.head),
|
|
91
|
-
title: createFullPageComponent(ReactDOM.title),
|
|
92
90
|
body: createFullPageComponent(ReactDOM.body)
|
|
93
91
|
});
|
|
94
92
|
|
|
95
|
-
|
|
96
93
|
// This needs to happen after createFullPageComponent() otherwise the mixin
|
|
97
94
|
// gets double injected.
|
|
98
95
|
ReactInjection.CompositeComponent.injectMixin(ReactBrowserComponentMixin);
|
|
99
96
|
|
|
100
|
-
ReactInjection.DOMProperty.injectDOMPropertyConfig(
|
|
97
|
+
ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);
|
|
98
|
+
ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);
|
|
99
|
+
|
|
100
|
+
ReactInjection.EmptyComponent.injectEmptyComponent(ReactDOM.noscript);
|
|
101
101
|
|
|
102
|
+
ReactInjection.Updates.injectReconcileTransaction(
|
|
103
|
+
ReactComponentBrowserEnvironment.ReactReconcileTransaction
|
|
104
|
+
);
|
|
102
105
|
ReactInjection.Updates.injectBatchingStrategy(
|
|
103
106
|
ReactDefaultBatchingStrategy
|
|
104
107
|
);
|
package/lib/ReactDefaultPerf.js
CHANGED
|
@@ -30,8 +30,13 @@ function roundFloat(val) {
|
|
|
30
30
|
return Math.floor(val * 100) / 100;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
function addValue(obj, key, val) {
|
|
34
|
+
obj[key] = (obj[key] || 0) + val;
|
|
35
|
+
}
|
|
36
|
+
|
|
33
37
|
var ReactDefaultPerf = {
|
|
34
38
|
_allMeasurements: [], // last item in the list is the current one
|
|
39
|
+
_mountStack: [0],
|
|
35
40
|
_injected: false,
|
|
36
41
|
|
|
37
42
|
start: function() {
|
|
@@ -58,15 +63,15 @@ var ReactDefaultPerf = {
|
|
|
58
63
|
return {
|
|
59
64
|
'Component class name': item.componentName,
|
|
60
65
|
'Total inclusive time (ms)': roundFloat(item.inclusive),
|
|
61
|
-
'
|
|
62
|
-
'Exclusive time
|
|
66
|
+
'Exclusive mount time (ms)': roundFloat(item.exclusive),
|
|
67
|
+
'Exclusive render time (ms)': roundFloat(item.render),
|
|
68
|
+
'Mount time per instance (ms)': roundFloat(item.exclusive / item.count),
|
|
69
|
+
'Render time per instance (ms)': roundFloat(item.render / item.count),
|
|
63
70
|
'Instances': item.count
|
|
64
71
|
};
|
|
65
72
|
}));
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
|
|
69
|
-
);
|
|
73
|
+
// TODO: ReactDefaultPerfAnalysis.getTotalTime() does not return the correct
|
|
74
|
+
// number.
|
|
70
75
|
},
|
|
71
76
|
|
|
72
77
|
printInclusive: function(measurements) {
|
|
@@ -149,6 +154,7 @@ var ReactDefaultPerf = {
|
|
|
149
154
|
ReactDefaultPerf._allMeasurements.push({
|
|
150
155
|
exclusive: {},
|
|
151
156
|
inclusive: {},
|
|
157
|
+
render: {},
|
|
152
158
|
counts: {},
|
|
153
159
|
writes: {},
|
|
154
160
|
displayNames: {},
|
|
@@ -211,22 +217,33 @@ var ReactDefaultPerf = {
|
|
|
211
217
|
args[0] :
|
|
212
218
|
this._rootNodeID;
|
|
213
219
|
var isRender = fnName === '_renderValidatedComponent';
|
|
220
|
+
var isMount = fnName === 'mountComponent';
|
|
221
|
+
|
|
222
|
+
var mountStack = ReactDefaultPerf._mountStack;
|
|
214
223
|
var entry = ReactDefaultPerf._allMeasurements[
|
|
215
224
|
ReactDefaultPerf._allMeasurements.length - 1
|
|
216
225
|
];
|
|
217
226
|
|
|
218
227
|
if (isRender) {
|
|
219
|
-
entry.counts
|
|
220
|
-
|
|
228
|
+
addValue(entry.counts, rootNodeID, 1);
|
|
229
|
+
} else if (isMount) {
|
|
230
|
+
mountStack.push(0);
|
|
221
231
|
}
|
|
222
232
|
|
|
223
233
|
start = performanceNow();
|
|
224
234
|
rv = func.apply(this, args);
|
|
225
235
|
totalTime = performanceNow() - start;
|
|
226
236
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
237
|
+
if (isRender) {
|
|
238
|
+
addValue(entry.render, rootNodeID, totalTime);
|
|
239
|
+
} else if (isMount) {
|
|
240
|
+
var subMountTime = mountStack.pop();
|
|
241
|
+
mountStack[mountStack.length - 1] += totalTime;
|
|
242
|
+
addValue(entry.exclusive, rootNodeID, totalTime - subMountTime);
|
|
243
|
+
addValue(entry.inclusive, rootNodeID, totalTime);
|
|
244
|
+
} else {
|
|
245
|
+
addValue(entry.inclusive, rootNodeID, totalTime);
|
|
246
|
+
}
|
|
230
247
|
|
|
231
248
|
entry.displayNames[rootNodeID] = {
|
|
232
249
|
current: this.constructor.displayName,
|
|
@@ -80,8 +80,12 @@ function getExclusiveSummary(measurements) {
|
|
|
80
80
|
componentName: displayName,
|
|
81
81
|
inclusive: 0,
|
|
82
82
|
exclusive: 0,
|
|
83
|
+
render: 0,
|
|
83
84
|
count: 0
|
|
84
85
|
};
|
|
86
|
+
if (measurement.render[id]) {
|
|
87
|
+
candidates[displayName].render += measurement.render[id];
|
|
88
|
+
}
|
|
85
89
|
if (measurement.exclusive[id]) {
|
|
86
90
|
candidates[displayName].exclusive += measurement.exclusive[id];
|
|
87
91
|
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2014 Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @providesModule ReactDescriptor
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var ReactContext = require("./ReactContext");
|
|
22
|
+
var ReactCurrentOwner = require("./ReactCurrentOwner");
|
|
23
|
+
|
|
24
|
+
var merge = require("./merge");
|
|
25
|
+
var warning = require("./warning");
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Warn for mutations.
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
* @param {object} object
|
|
32
|
+
* @param {string} key
|
|
33
|
+
*/
|
|
34
|
+
function defineWarningProperty(object, key) {
|
|
35
|
+
Object.defineProperty(object, key, {
|
|
36
|
+
|
|
37
|
+
configurable: false,
|
|
38
|
+
enumerable: true,
|
|
39
|
+
|
|
40
|
+
get: function() {
|
|
41
|
+
if (!this._store) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return this._store[key];
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
set: function(value) {
|
|
48
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
49
|
+
false,
|
|
50
|
+
'Don\'t set the ' + key + ' property of the component. ' +
|
|
51
|
+
'Mutate the existing props object instead.'
|
|
52
|
+
) : null);
|
|
53
|
+
this._store[key] = value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* This is updated to true if the membrane is successfully created.
|
|
61
|
+
*/
|
|
62
|
+
var useMutationMembrane = false;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Warn for mutations.
|
|
66
|
+
*
|
|
67
|
+
* @internal
|
|
68
|
+
* @param {object} descriptor
|
|
69
|
+
*/
|
|
70
|
+
function defineMutationMembrane(prototype) {
|
|
71
|
+
try {
|
|
72
|
+
var pseudoFrozenProperties = {
|
|
73
|
+
props: true
|
|
74
|
+
};
|
|
75
|
+
for (var key in pseudoFrozenProperties) {
|
|
76
|
+
defineWarningProperty(prototype, key);
|
|
77
|
+
}
|
|
78
|
+
useMutationMembrane = true;
|
|
79
|
+
} catch (x) {
|
|
80
|
+
// IE will fail on defineProperty
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Transfer static properties from the source to the target. Functions are
|
|
86
|
+
* rebound to have this reflect the original source.
|
|
87
|
+
*/
|
|
88
|
+
function proxyStaticMethods(target, source) {
|
|
89
|
+
if (typeof source !== 'function') {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
for (var key in source) {
|
|
93
|
+
if (source.hasOwnProperty(key)) {
|
|
94
|
+
var value = source[key];
|
|
95
|
+
if (typeof value === 'function') {
|
|
96
|
+
var bound = value.bind(source);
|
|
97
|
+
// Copy any properties defined on the function, such as `isRequired` on
|
|
98
|
+
// a PropTypes validator. (mergeInto refuses to work on functions.)
|
|
99
|
+
for (var k in value) {
|
|
100
|
+
if (value.hasOwnProperty(k)) {
|
|
101
|
+
bound[k] = value[k];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
target[key] = bound;
|
|
105
|
+
} else {
|
|
106
|
+
target[key] = value;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Base constructor for all React descriptors. This is only used to make this
|
|
114
|
+
* work with a dynamic instanceof check. Nothing should live on this prototype.
|
|
115
|
+
*
|
|
116
|
+
* @param {*} type
|
|
117
|
+
* @internal
|
|
118
|
+
*/
|
|
119
|
+
var ReactDescriptor = function() {};
|
|
120
|
+
|
|
121
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
122
|
+
defineMutationMembrane(ReactDescriptor.prototype);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
ReactDescriptor.createFactory = function(type) {
|
|
126
|
+
|
|
127
|
+
var descriptorPrototype = Object.create(ReactDescriptor.prototype);
|
|
128
|
+
|
|
129
|
+
var factory = function(props, children) {
|
|
130
|
+
// For consistency we currently allocate a new object for every descriptor.
|
|
131
|
+
// This protects the descriptor from being mutated by the original props
|
|
132
|
+
// object being mutated. It also protects the original props object from
|
|
133
|
+
// being mutated by children arguments and default props. This behavior
|
|
134
|
+
// comes with a performance cost and could be deprecated in the future.
|
|
135
|
+
// It could also be optimized with a smarter JSX transform.
|
|
136
|
+
if (props == null) {
|
|
137
|
+
props = {};
|
|
138
|
+
} else if (typeof props === 'object') {
|
|
139
|
+
props = merge(props);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Children can be more than one argument, and those are transferred onto
|
|
143
|
+
// the newly allocated props object.
|
|
144
|
+
var childrenLength = arguments.length - 1;
|
|
145
|
+
if (childrenLength === 1) {
|
|
146
|
+
props.children = children;
|
|
147
|
+
} else if (childrenLength > 1) {
|
|
148
|
+
var childArray = Array(childrenLength);
|
|
149
|
+
for (var i = 0; i < childrenLength; i++) {
|
|
150
|
+
childArray[i] = arguments[i + 1];
|
|
151
|
+
}
|
|
152
|
+
props.children = childArray;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Initialize the descriptor object
|
|
156
|
+
var descriptor = Object.create(descriptorPrototype);
|
|
157
|
+
|
|
158
|
+
// Record the component responsible for creating this descriptor.
|
|
159
|
+
descriptor._owner = ReactCurrentOwner.current;
|
|
160
|
+
|
|
161
|
+
// TODO: Deprecate withContext, and then the context becomes accessible
|
|
162
|
+
// through the owner.
|
|
163
|
+
descriptor._context = ReactContext.current;
|
|
164
|
+
|
|
165
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
166
|
+
// The validation flag and props are currently mutative. We put them on
|
|
167
|
+
// an external backing store so that we can freeze the whole object.
|
|
168
|
+
// This can be replaced with a WeakMap once they are implemented in
|
|
169
|
+
// commonly used development environments.
|
|
170
|
+
descriptor._store = { validated: false, props: props };
|
|
171
|
+
|
|
172
|
+
// We're not allowed to set props directly on the object so we early
|
|
173
|
+
// return and rely on the prototype membrane to forward to the backing
|
|
174
|
+
// store.
|
|
175
|
+
if (useMutationMembrane) {
|
|
176
|
+
Object.freeze(descriptor);
|
|
177
|
+
return descriptor;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
descriptor.props = props;
|
|
182
|
+
return descriptor;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// Currently we expose the prototype of the descriptor so that
|
|
186
|
+
// <Foo /> instanceof Foo works. This is controversial pattern.
|
|
187
|
+
factory.prototype = descriptorPrototype;
|
|
188
|
+
|
|
189
|
+
// Expose the type on the factory and the prototype so that it can be
|
|
190
|
+
// easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for
|
|
191
|
+
// static methods like <Foo />.type.staticMethod();
|
|
192
|
+
// This should not be named constructor since this may not be the function
|
|
193
|
+
// that created the descriptor, and it may not even be a constructor.
|
|
194
|
+
factory.type = type;
|
|
195
|
+
descriptorPrototype.type = type;
|
|
196
|
+
|
|
197
|
+
proxyStaticMethods(factory, type);
|
|
198
|
+
|
|
199
|
+
// Expose a unique constructor on the prototype is that this works with type
|
|
200
|
+
// systems that compare constructor properties: <Foo />.constructor === Foo
|
|
201
|
+
// This may be controversial since it requires a known factory function.
|
|
202
|
+
descriptorPrototype.constructor = factory;
|
|
203
|
+
|
|
204
|
+
return factory;
|
|
205
|
+
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
ReactDescriptor.cloneAndReplaceProps = function(oldDescriptor, newProps) {
|
|
209
|
+
var newDescriptor = Object.create(oldDescriptor.constructor.prototype);
|
|
210
|
+
// It's important that this property order matches the hidden class of the
|
|
211
|
+
// original descriptor to maintain perf.
|
|
212
|
+
newDescriptor._owner = oldDescriptor._owner;
|
|
213
|
+
newDescriptor._context = oldDescriptor._context;
|
|
214
|
+
|
|
215
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
216
|
+
newDescriptor._store = {
|
|
217
|
+
validated: oldDescriptor._store.validated,
|
|
218
|
+
props: newProps
|
|
219
|
+
};
|
|
220
|
+
if (useMutationMembrane) {
|
|
221
|
+
Object.freeze(newDescriptor);
|
|
222
|
+
return newDescriptor;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
newDescriptor.props = newProps;
|
|
227
|
+
return newDescriptor;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Checks if a value is a valid descriptor constructor.
|
|
232
|
+
*
|
|
233
|
+
* @param {*}
|
|
234
|
+
* @return {boolean}
|
|
235
|
+
* @public
|
|
236
|
+
*/
|
|
237
|
+
ReactDescriptor.isValidFactory = function(factory) {
|
|
238
|
+
return typeof factory === 'function' &&
|
|
239
|
+
factory.prototype instanceof ReactDescriptor;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @param {?object} object
|
|
244
|
+
* @return {boolean} True if `object` is a valid component.
|
|
245
|
+
* @final
|
|
246
|
+
*/
|
|
247
|
+
ReactDescriptor.isValidDescriptor = function(object) {
|
|
248
|
+
return object instanceof ReactDescriptor;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
module.exports = ReactDescriptor;
|