react 0.6.3 → 0.9.0-rc1
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 +10 -222
- package/addons.js +1 -0
- package/lib/AutoFocusMixin.js +30 -0
- package/lib/CSSCore.js +115 -0
- package/lib/CSSProperty.js +121 -0
- package/lib/CSSPropertyOperations.js +97 -0
- package/lib/ChangeEventPlugin.js +387 -0
- package/lib/ClientReactRootIndex.js +30 -0
- package/lib/CompositionEventPlugin.js +260 -0
- package/lib/DOMChildrenOperations.js +165 -0
- package/lib/DOMProperty.js +268 -0
- package/lib/DOMPropertyOperations.js +181 -0
- package/lib/Danger.js +187 -0
- package/lib/DefaultDOMPropertyConfig.js +197 -0
- package/lib/DefaultEventPluginOrder.js +44 -0
- package/lib/EnterLeaveEventPlugin.js +145 -0
- package/lib/EventConstants.js +76 -0
- package/lib/EventListener.js +69 -0
- package/lib/EventPluginHub.js +291 -0
- package/lib/EventPluginRegistry.js +260 -0
- package/lib/EventPluginUtils.js +214 -0
- package/lib/EventPropagators.js +143 -0
- package/lib/ExecutionEnvironment.js +44 -0
- package/lib/LinkedStateMixin.js +46 -0
- package/lib/LinkedValueUtils.js +161 -0
- package/lib/MobileSafariClickEventPlugin.js +63 -0
- package/lib/PooledClass.js +119 -0
- package/lib/React.js +95 -0
- package/lib/ReactCSSTransitionGroup.js +65 -0
- package/lib/ReactCSSTransitionGroupChild.js +138 -0
- package/lib/ReactChildren.js +132 -0
- package/lib/ReactComponent.js +550 -0
- package/lib/ReactComponentBrowserEnvironment.js +158 -0
- package/lib/ReactComponentEnvironment.js +26 -0
- package/lib/ReactCompositeComponent.js +1455 -0
- package/lib/ReactContext.js +67 -0
- package/lib/ReactCurrentOwner.js +39 -0
- package/lib/ReactDOM.js +207 -0
- package/lib/ReactDOMButton.js +68 -0
- package/lib/ReactDOMComponent.js +399 -0
- package/lib/ReactDOMForm.js +59 -0
- package/lib/ReactDOMIDOperations.js +218 -0
- package/lib/ReactDOMImg.js +58 -0
- package/lib/ReactDOMInput.js +181 -0
- package/lib/ReactDOMOption.js +51 -0
- package/lib/ReactDOMSelect.js +179 -0
- package/lib/ReactDOMSelection.js +189 -0
- package/lib/ReactDOMTextarea.js +140 -0
- package/lib/ReactDefaultBatchingStrategy.js +75 -0
- package/lib/ReactDefaultInjection.js +115 -0
- package/lib/ReactDefaultPerf.js +244 -0
- package/lib/ReactDefaultPerfAnalysis.js +199 -0
- package/lib/ReactErrorUtils.js +37 -0
- package/lib/ReactEventEmitter.js +337 -0
- package/lib/ReactEventEmitterMixin.js +57 -0
- package/lib/ReactEventTopLevelCallback.js +109 -0
- package/lib/ReactInjection.js +39 -0
- package/lib/ReactInputSelection.js +140 -0
- package/lib/ReactInstanceHandles.js +338 -0
- package/lib/ReactLink.js +54 -0
- package/lib/ReactMarkupChecksum.js +53 -0
- package/lib/ReactMount.js +641 -0
- package/lib/ReactMountReady.js +95 -0
- package/lib/ReactMultiChild.js +425 -0
- package/lib/ReactMultiChildUpdateTypes.js +38 -0
- package/lib/ReactOwner.js +154 -0
- package/lib/ReactPerf.js +85 -0
- package/lib/ReactPropTransferer.js +147 -0
- package/lib/ReactPropTypeLocationNames.js +31 -0
- package/lib/ReactPropTypeLocations.js +29 -0
- package/lib/ReactPropTypes.js +359 -0
- package/lib/ReactPutListenerQueue.js +61 -0
- package/lib/ReactReconcileTransaction.js +181 -0
- package/lib/ReactRootIndex.js +36 -0
- package/lib/ReactServerRendering.js +59 -0
- package/lib/ReactStateSetters.js +111 -0
- package/lib/ReactTextComponent.js +99 -0
- package/lib/ReactTransitionChildMapping.js +106 -0
- package/lib/ReactTransitionEvents.js +97 -0
- package/lib/ReactTransitionGroup.js +187 -0
- package/lib/ReactUpdates.js +148 -0
- package/lib/ReactWithAddons.js +46 -0
- package/lib/SelectEventPlugin.js +200 -0
- package/lib/ServerReactRootIndex.js +36 -0
- package/lib/SimpleEventPlugin.js +413 -0
- package/lib/SyntheticClipboardEvent.js +51 -0
- package/lib/SyntheticCompositionEvent.js +51 -0
- package/lib/SyntheticDragEvent.js +44 -0
- package/lib/SyntheticEvent.js +164 -0
- package/lib/SyntheticFocusEvent.js +44 -0
- package/lib/SyntheticKeyboardEvent.js +58 -0
- package/lib/SyntheticMouseEvent.js +85 -0
- package/lib/SyntheticTouchEvent.js +50 -0
- package/lib/SyntheticUIEvent.js +45 -0
- package/lib/SyntheticWheelEvent.js +66 -0
- package/lib/Transaction.js +276 -0
- package/lib/ViewportMetrics.js +37 -0
- package/lib/accumulate.js +54 -0
- package/lib/adler32.js +39 -0
- package/lib/cloneWithProps.js +59 -0
- package/lib/containsNode.js +49 -0
- package/lib/copyProperties.js +54 -0
- package/lib/createArrayFrom.js +91 -0
- package/lib/createFullPageComponent.js +63 -0
- package/lib/createNodesFromMarkup.js +93 -0
- package/lib/createObjectFrom.js +61 -0
- package/lib/cx.js +44 -0
- package/lib/dangerousStyleValue.js +57 -0
- package/lib/emptyFunction.js +43 -0
- package/lib/escapeTextForBrowser.js +47 -0
- package/lib/flattenChildren.js +57 -0
- package/lib/forEachAccumulated.js +36 -0
- package/lib/getActiveElement.js +34 -0
- package/lib/getEventKey.js +85 -0
- package/lib/getEventTarget.js +36 -0
- package/lib/getMarkupWrap.js +118 -0
- package/lib/getNodeForCharacterOffset.js +80 -0
- package/lib/getReactRootElementInContainer.js +40 -0
- package/lib/getTextContentAccessor.js +42 -0
- package/lib/getUnboundedScrollPosition.js +45 -0
- package/lib/hyphenate.js +35 -0
- package/lib/invariant.js +62 -0
- package/lib/isEventSupported.js +70 -0
- package/lib/isNode.js +33 -0
- package/lib/isTextInputElement.js +49 -0
- package/lib/isTextNode.js +30 -0
- package/lib/joinClasses.js +44 -0
- package/lib/keyMirror.js +58 -0
- package/lib/keyOf.js +41 -0
- package/lib/memoizeStringOnly.js +39 -0
- package/lib/merge.js +37 -0
- package/lib/mergeHelpers.js +136 -0
- package/lib/mergeInto.js +45 -0
- package/lib/mixInto.js +34 -0
- package/lib/objMap.js +47 -0
- package/lib/objMapKeyVal.js +47 -0
- package/lib/onlyChild.js +43 -0
- package/lib/performanceNow.js +42 -0
- package/lib/shallowEqual.js +49 -0
- package/lib/shouldUpdateReactComponent.js +58 -0
- package/lib/toArray.js +75 -0
- package/lib/traverseAllChildren.js +189 -0
- package/lib/warning.js +40 -0
- package/package.json +32 -21
- package/react.js +1 -0
- package/.npmignore +0 -7
- package/.travis.yml +0 -5
- package/Jakefile.js +0 -39
- package/LICENSE +0 -19
- package/browser-test/dist.html +0 -90
- package/browser-test/index.html +0 -86
- package/browser-test/min.html +0 -90
- package/dist/react.js +0 -3107
- package/dist/react.min.js +0 -22
- package/doc/advanced.md +0 -174
- package/doc/color-def.graffle +0 -938
- package/doc/color-def.png +0 -0
- package/doc/simple.dot +0 -25
- package/doc/simple.png +0 -0
- package/examples/longer-example.js +0 -41
- package/examples/simple.js +0 -45
- package/examples/using-ast-directly.js +0 -30
- package/examples/using-events1.js +0 -79
- package/examples/using-log-events.js +0 -43
- package/lib/base-task.js +0 -123
- package/lib/cb-task.js +0 -84
- package/lib/core.js +0 -138
- package/lib/dsl.js +0 -138
- package/lib/error.js +0 -55
- package/lib/event-collector.js +0 -81
- package/lib/event-manager.js +0 -89
- package/lib/eventemitter.js +0 -20
- package/lib/finalcb-first-task.js +0 -68
- package/lib/finalcb-task.js +0 -65
- package/lib/id.js +0 -22
- package/lib/input-parser.js +0 -56
- package/lib/log-events.js +0 -101
- package/lib/parse.js +0 -41
- package/lib/promise-resolve.js +0 -50
- package/lib/promise-task.js +0 -93
- package/lib/react.js +0 -59
- package/lib/ret-task.js +0 -71
- package/lib/sprintf.js +0 -18
- package/lib/status.js +0 -14
- package/lib/task.js +0 -251
- package/lib/track-tasks.js +0 -74
- package/lib/validate.js +0 -159
- package/lib/vcon.js +0 -90
- package/lib/when-task.js +0 -85
- package/src/dist.build.requirejs +0 -20
- package/test/ast.mocha.js +0 -136
- package/test/cb-task.mocha.js +0 -220
- package/test/core-deferred.mocha.js +0 -143
- package/test/core-when.mocha.js +0 -96
- package/test/core.mocha.js +0 -589
- package/test/dsl.mocha.js +0 -350
- package/test/event-manager.mocha.js +0 -119
- package/test/exec-options.mocha.js +0 -48
- package/test/finalcb-task.mocha.js +0 -58
- package/test/input-parser.mocha.js +0 -86
- package/test/log-events.mocha.js +0 -88
- package/test/mocha.opts +0 -2
- package/test/module-use.mocha.js +0 -147
- package/test/promise-auto-resolve.mocha.js +0 -68
- package/test/ret-task.mocha.js +0 -220
- package/test/task.mocha.js +0 -42
- package/test/validate-cb-task.mocha.js +0 -100
- package/test/validate-ret-task.mocha.js +0 -110
- package/test/validate.mocha.js +0 -324
- package/test/vcon.mocha.js +0 -193
- package/vendor/chai/chai.js +0 -2038
- package/vendor/jquery/jquery-1.7.1.js +0 -9266
- package/vendor/jquery/jquery-1.7.1.min.js +0 -4
- package/vendor/mocha/mocha.css +0 -135
- package/vendor/mocha/mocha.js +0 -3589
- package/vendor/node/util.js +0 -531
- package/vendor/requirejs/require.js +0 -2053
- package/vendor/requirejs/require.min.js +0 -33
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013 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 ReactComponentBrowserEnvironment
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/*jslint evil: true */
|
|
20
|
+
|
|
21
|
+
"use strict";
|
|
22
|
+
|
|
23
|
+
var ReactDOMIDOperations = require("./ReactDOMIDOperations");
|
|
24
|
+
var ReactMarkupChecksum = require("./ReactMarkupChecksum");
|
|
25
|
+
var ReactMount = require("./ReactMount");
|
|
26
|
+
var ReactPerf = require("./ReactPerf");
|
|
27
|
+
var ReactReconcileTransaction = require("./ReactReconcileTransaction");
|
|
28
|
+
|
|
29
|
+
var getReactRootElementInContainer = require("./getReactRootElementInContainer");
|
|
30
|
+
var invariant = require("./invariant");
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
var ELEMENT_NODE_TYPE = 1;
|
|
34
|
+
var DOC_NODE_TYPE = 9;
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Abstracts away all functionality of `ReactComponent` requires knowledge of
|
|
39
|
+
* the browser context.
|
|
40
|
+
*/
|
|
41
|
+
var ReactComponentBrowserEnvironment = {
|
|
42
|
+
/**
|
|
43
|
+
* Mixed into every component instance.
|
|
44
|
+
*/
|
|
45
|
+
Mixin: {
|
|
46
|
+
/**
|
|
47
|
+
* Returns the DOM node rendered by this component.
|
|
48
|
+
*
|
|
49
|
+
* @return {DOMElement} The root node of this component.
|
|
50
|
+
* @final
|
|
51
|
+
* @protected
|
|
52
|
+
*/
|
|
53
|
+
getDOMNode: function() {
|
|
54
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
55
|
+
this.isMounted(),
|
|
56
|
+
'getDOMNode(): A component must be mounted to have a DOM node.'
|
|
57
|
+
) : invariant(this.isMounted()));
|
|
58
|
+
return ReactMount.getNode(this._rootNodeID);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
ReactReconcileTransaction: ReactReconcileTransaction,
|
|
63
|
+
|
|
64
|
+
BackendIDOperations: ReactDOMIDOperations,
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* If a particular environment requires that some resources be cleaned up,
|
|
68
|
+
* specify this in the injected Mixin. In the DOM, we would likely want to
|
|
69
|
+
* purge any cached node ID lookups.
|
|
70
|
+
*
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
unmountIDFromEnvironment: function(rootNodeID) {
|
|
74
|
+
ReactMount.purgeID(rootNodeID);
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {string} markup Markup string to place into the DOM Element.
|
|
79
|
+
* @param {DOMElement} container DOM Element to insert markup into.
|
|
80
|
+
* @param {boolean} shouldReuseMarkup Should reuse the existing markup in the
|
|
81
|
+
* container if possible.
|
|
82
|
+
*/
|
|
83
|
+
mountImageIntoNode: ReactPerf.measure(
|
|
84
|
+
'ReactComponentBrowserEnvironment',
|
|
85
|
+
'mountImageIntoNode',
|
|
86
|
+
function(markup, container, shouldReuseMarkup) {
|
|
87
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
88
|
+
container && (
|
|
89
|
+
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
90
|
+
container.nodeType === DOC_NODE_TYPE
|
|
91
|
+
),
|
|
92
|
+
'mountComponentIntoNode(...): Target container is not valid.'
|
|
93
|
+
) : invariant(container && (
|
|
94
|
+
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
95
|
+
container.nodeType === DOC_NODE_TYPE
|
|
96
|
+
)));
|
|
97
|
+
|
|
98
|
+
if (shouldReuseMarkup) {
|
|
99
|
+
if (ReactMarkupChecksum.canReuseMarkup(
|
|
100
|
+
markup,
|
|
101
|
+
getReactRootElementInContainer(container))) {
|
|
102
|
+
return;
|
|
103
|
+
} else {
|
|
104
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
105
|
+
container.nodeType !== DOC_NODE_TYPE,
|
|
106
|
+
'You\'re trying to render a component to the document using ' +
|
|
107
|
+
'server rendering but the checksum was invalid. This usually ' +
|
|
108
|
+
'means you rendered a different component type or props on ' +
|
|
109
|
+
'the client from the one on the server, or your render() ' +
|
|
110
|
+
'methods are impure. React cannot handle this case due to ' +
|
|
111
|
+
'cross-browser quirks by rendering at the document root. You ' +
|
|
112
|
+
'should look for environment dependent code in your components ' +
|
|
113
|
+
'and ensure the props are the same client and server side.'
|
|
114
|
+
) : invariant(container.nodeType !== DOC_NODE_TYPE));
|
|
115
|
+
|
|
116
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
117
|
+
console.warn(
|
|
118
|
+
'React attempted to use reuse markup in a container but the ' +
|
|
119
|
+
'checksum was invalid. This generally means that you are ' +
|
|
120
|
+
'using server rendering and the markup generated on the ' +
|
|
121
|
+
'server was not what the client was expecting. React injected' +
|
|
122
|
+
'new markup to compensate which works but you have lost many ' +
|
|
123
|
+
'of the benefits of server rendering. Instead, figure out ' +
|
|
124
|
+
'why the markup being generated is different on the client ' +
|
|
125
|
+
'or server.'
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
132
|
+
container.nodeType !== DOC_NODE_TYPE,
|
|
133
|
+
'You\'re trying to render a component to the document but ' +
|
|
134
|
+
'you didn\'t use server rendering. We can\'t do this ' +
|
|
135
|
+
'without using server rendering due to cross-browser quirks. ' +
|
|
136
|
+
'See renderComponentToString() for server rendering.'
|
|
137
|
+
) : invariant(container.nodeType !== DOC_NODE_TYPE));
|
|
138
|
+
|
|
139
|
+
// Asynchronously inject markup by ensuring that the container is not in
|
|
140
|
+
// the document when settings its `innerHTML`.
|
|
141
|
+
var parent = container.parentNode;
|
|
142
|
+
if (parent) {
|
|
143
|
+
var next = container.nextSibling;
|
|
144
|
+
parent.removeChild(container);
|
|
145
|
+
container.innerHTML = markup;
|
|
146
|
+
if (next) {
|
|
147
|
+
parent.insertBefore(container, next);
|
|
148
|
+
} else {
|
|
149
|
+
parent.appendChild(container);
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
container.innerHTML = markup;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
module.exports = ReactComponentBrowserEnvironment;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013 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 ReactComponentEnvironment
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var ReactComponentBrowserEnvironment =
|
|
22
|
+
require("./ReactComponentBrowserEnvironment");
|
|
23
|
+
|
|
24
|
+
var ReactComponentEnvironment = ReactComponentBrowserEnvironment;
|
|
25
|
+
|
|
26
|
+
module.exports = ReactComponentEnvironment;
|
|
@@ -0,0 +1,1455 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013 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 ReactCompositeComponent
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var ReactComponent = require("./ReactComponent");
|
|
22
|
+
var ReactContext = require("./ReactContext");
|
|
23
|
+
var ReactCurrentOwner = require("./ReactCurrentOwner");
|
|
24
|
+
var ReactErrorUtils = require("./ReactErrorUtils");
|
|
25
|
+
var ReactOwner = require("./ReactOwner");
|
|
26
|
+
var ReactPerf = require("./ReactPerf");
|
|
27
|
+
var ReactPropTransferer = require("./ReactPropTransferer");
|
|
28
|
+
var ReactPropTypeLocations = require("./ReactPropTypeLocations");
|
|
29
|
+
var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
|
|
30
|
+
var ReactUpdates = require("./ReactUpdates");
|
|
31
|
+
|
|
32
|
+
var invariant = require("./invariant");
|
|
33
|
+
var keyMirror = require("./keyMirror");
|
|
34
|
+
var merge = require("./merge");
|
|
35
|
+
var mixInto = require("./mixInto");
|
|
36
|
+
var objMap = require("./objMap");
|
|
37
|
+
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Policies that describe methods in `ReactCompositeComponentInterface`.
|
|
41
|
+
*/
|
|
42
|
+
var SpecPolicy = keyMirror({
|
|
43
|
+
/**
|
|
44
|
+
* These methods may be defined only once by the class specification or mixin.
|
|
45
|
+
*/
|
|
46
|
+
DEFINE_ONCE: null,
|
|
47
|
+
/**
|
|
48
|
+
* These methods may be defined by both the class specification and mixins.
|
|
49
|
+
* Subsequent definitions will be chained. These methods must return void.
|
|
50
|
+
*/
|
|
51
|
+
DEFINE_MANY: null,
|
|
52
|
+
/**
|
|
53
|
+
* These methods are overriding the base ReactCompositeComponent class.
|
|
54
|
+
*/
|
|
55
|
+
OVERRIDE_BASE: null,
|
|
56
|
+
/**
|
|
57
|
+
* These methods are similar to DEFINE_MANY, except we assume they return
|
|
58
|
+
* objects. We try to merge the keys of the return values of all the mixed in
|
|
59
|
+
* functions. If there is a key conflict we throw.
|
|
60
|
+
*/
|
|
61
|
+
DEFINE_MANY_MERGED: null
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Composite components are higher-level components that compose other composite
|
|
66
|
+
* or native components.
|
|
67
|
+
*
|
|
68
|
+
* To create a new type of `ReactCompositeComponent`, pass a specification of
|
|
69
|
+
* your new class to `React.createClass`. The only requirement of your class
|
|
70
|
+
* specification is that you implement a `render` method.
|
|
71
|
+
*
|
|
72
|
+
* var MyComponent = React.createClass({
|
|
73
|
+
* render: function() {
|
|
74
|
+
* return <div>Hello World</div>;
|
|
75
|
+
* }
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* The class specification supports a specific protocol of methods that have
|
|
79
|
+
* special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for
|
|
80
|
+
* more the comprehensive protocol. Any other properties and methods in the
|
|
81
|
+
* class specification will available on the prototype.
|
|
82
|
+
*
|
|
83
|
+
* @interface ReactCompositeComponentInterface
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
var ReactCompositeComponentInterface = {
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* An array of Mixin objects to include when defining your component.
|
|
90
|
+
*
|
|
91
|
+
* @type {array}
|
|
92
|
+
* @optional
|
|
93
|
+
*/
|
|
94
|
+
mixins: SpecPolicy.DEFINE_MANY,
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* An object containing properties and methods that should be defined on
|
|
98
|
+
* the component's constructor instead of its prototype (static methods).
|
|
99
|
+
*
|
|
100
|
+
* @type {object}
|
|
101
|
+
* @optional
|
|
102
|
+
*/
|
|
103
|
+
statics: SpecPolicy.DEFINE_MANY,
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Definition of prop types for this component.
|
|
107
|
+
*
|
|
108
|
+
* @type {object}
|
|
109
|
+
* @optional
|
|
110
|
+
*/
|
|
111
|
+
propTypes: SpecPolicy.DEFINE_MANY,
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Definition of context types for this component.
|
|
115
|
+
*
|
|
116
|
+
* @type {object}
|
|
117
|
+
* @optional
|
|
118
|
+
*/
|
|
119
|
+
contextTypes: SpecPolicy.DEFINE_MANY,
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Definition of context types this component sets for its children.
|
|
123
|
+
*
|
|
124
|
+
* @type {object}
|
|
125
|
+
* @optional
|
|
126
|
+
*/
|
|
127
|
+
childContextTypes: SpecPolicy.DEFINE_MANY,
|
|
128
|
+
|
|
129
|
+
// ==== Definition methods ====
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Invoked when the component is mounted. Values in the mapping will be set on
|
|
133
|
+
* `this.props` if that prop is not specified (i.e. using an `in` check).
|
|
134
|
+
*
|
|
135
|
+
* This method is invoked before `getInitialState` and therefore cannot rely
|
|
136
|
+
* on `this.state` or use `this.setState`.
|
|
137
|
+
*
|
|
138
|
+
* @return {object}
|
|
139
|
+
* @optional
|
|
140
|
+
*/
|
|
141
|
+
getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Invoked once before the component is mounted. The return value will be used
|
|
145
|
+
* as the initial value of `this.state`.
|
|
146
|
+
*
|
|
147
|
+
* getInitialState: function() {
|
|
148
|
+
* return {
|
|
149
|
+
* isOn: false,
|
|
150
|
+
* fooBaz: new BazFoo()
|
|
151
|
+
* }
|
|
152
|
+
* }
|
|
153
|
+
*
|
|
154
|
+
* @return {object}
|
|
155
|
+
* @optional
|
|
156
|
+
*/
|
|
157
|
+
getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @return {object}
|
|
161
|
+
* @optional
|
|
162
|
+
*/
|
|
163
|
+
getChildContext: SpecPolicy.DEFINE_MANY_MERGED,
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Uses props from `this.props` and state from `this.state` to render the
|
|
167
|
+
* structure of the component.
|
|
168
|
+
*
|
|
169
|
+
* No guarantees are made about when or how often this method is invoked, so
|
|
170
|
+
* it must not have side effects.
|
|
171
|
+
*
|
|
172
|
+
* render: function() {
|
|
173
|
+
* var name = this.props.name;
|
|
174
|
+
* return <div>Hello, {name}!</div>;
|
|
175
|
+
* }
|
|
176
|
+
*
|
|
177
|
+
* @return {ReactComponent}
|
|
178
|
+
* @nosideeffects
|
|
179
|
+
* @required
|
|
180
|
+
*/
|
|
181
|
+
render: SpecPolicy.DEFINE_ONCE,
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
// ==== Delegate methods ====
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Invoked when the component is initially created and about to be mounted.
|
|
189
|
+
* This may have side effects, but any external subscriptions or data created
|
|
190
|
+
* by this method must be cleaned up in `componentWillUnmount`.
|
|
191
|
+
*
|
|
192
|
+
* @optional
|
|
193
|
+
*/
|
|
194
|
+
componentWillMount: SpecPolicy.DEFINE_MANY,
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Invoked when the component has been mounted and has a DOM representation.
|
|
198
|
+
* However, there is no guarantee that the DOM node is in the document.
|
|
199
|
+
*
|
|
200
|
+
* Use this as an opportunity to operate on the DOM when the component has
|
|
201
|
+
* been mounted (initialized and rendered) for the first time.
|
|
202
|
+
*
|
|
203
|
+
* @param {DOMElement} rootNode DOM element representing the component.
|
|
204
|
+
* @optional
|
|
205
|
+
*/
|
|
206
|
+
componentDidMount: SpecPolicy.DEFINE_MANY,
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Invoked before the component receives new props.
|
|
210
|
+
*
|
|
211
|
+
* Use this as an opportunity to react to a prop transition by updating the
|
|
212
|
+
* state using `this.setState`. Current props are accessed via `this.props`.
|
|
213
|
+
*
|
|
214
|
+
* componentWillReceiveProps: function(nextProps, nextContext) {
|
|
215
|
+
* this.setState({
|
|
216
|
+
* likesIncreasing: nextProps.likeCount > this.props.likeCount
|
|
217
|
+
* });
|
|
218
|
+
* }
|
|
219
|
+
*
|
|
220
|
+
* NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
|
|
221
|
+
* transition may cause a state change, but the opposite is not true. If you
|
|
222
|
+
* need it, you are probably looking for `componentWillUpdate`.
|
|
223
|
+
*
|
|
224
|
+
* @param {object} nextProps
|
|
225
|
+
* @optional
|
|
226
|
+
*/
|
|
227
|
+
componentWillReceiveProps: SpecPolicy.DEFINE_MANY,
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Invoked while deciding if the component should be updated as a result of
|
|
231
|
+
* receiving new props, state and/or context.
|
|
232
|
+
*
|
|
233
|
+
* Use this as an opportunity to `return false` when you're certain that the
|
|
234
|
+
* transition to the new props/state/context will not require a component
|
|
235
|
+
* update.
|
|
236
|
+
*
|
|
237
|
+
* shouldComponentUpdate: function(nextProps, nextState, nextContext) {
|
|
238
|
+
* return !equal(nextProps, this.props) ||
|
|
239
|
+
* !equal(nextState, this.state) ||
|
|
240
|
+
* !equal(nextContext, this.context);
|
|
241
|
+
* }
|
|
242
|
+
*
|
|
243
|
+
* @param {object} nextProps
|
|
244
|
+
* @param {?object} nextState
|
|
245
|
+
* @param {?object} nextContext
|
|
246
|
+
* @return {boolean} True if the component should update.
|
|
247
|
+
* @optional
|
|
248
|
+
*/
|
|
249
|
+
shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Invoked when the component is about to update due to a transition from
|
|
253
|
+
* `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
|
|
254
|
+
* and `nextContext`.
|
|
255
|
+
*
|
|
256
|
+
* Use this as an opportunity to perform preparation before an update occurs.
|
|
257
|
+
*
|
|
258
|
+
* NOTE: You **cannot** use `this.setState()` in this method.
|
|
259
|
+
*
|
|
260
|
+
* @param {object} nextProps
|
|
261
|
+
* @param {?object} nextState
|
|
262
|
+
* @param {?object} nextContext
|
|
263
|
+
* @param {ReactReconcileTransaction} transaction
|
|
264
|
+
* @optional
|
|
265
|
+
*/
|
|
266
|
+
componentWillUpdate: SpecPolicy.DEFINE_MANY,
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Invoked when the component's DOM representation has been updated.
|
|
270
|
+
*
|
|
271
|
+
* Use this as an opportunity to operate on the DOM when the component has
|
|
272
|
+
* been updated.
|
|
273
|
+
*
|
|
274
|
+
* @param {object} prevProps
|
|
275
|
+
* @param {?object} prevState
|
|
276
|
+
* @param {?object} prevContext
|
|
277
|
+
* @param {DOMElement} rootNode DOM element representing the component.
|
|
278
|
+
* @optional
|
|
279
|
+
*/
|
|
280
|
+
componentDidUpdate: SpecPolicy.DEFINE_MANY,
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Invoked when the component is about to be removed from its parent and have
|
|
284
|
+
* its DOM representation destroyed.
|
|
285
|
+
*
|
|
286
|
+
* Use this as an opportunity to deallocate any external resources.
|
|
287
|
+
*
|
|
288
|
+
* NOTE: There is no `componentDidUnmount` since your component will have been
|
|
289
|
+
* destroyed by that point.
|
|
290
|
+
*
|
|
291
|
+
* @optional
|
|
292
|
+
*/
|
|
293
|
+
componentWillUnmount: SpecPolicy.DEFINE_MANY,
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
// ==== Advanced methods ====
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Updates the component's currently mounted DOM representation.
|
|
301
|
+
*
|
|
302
|
+
* By default, this implements React's rendering and reconciliation algorithm.
|
|
303
|
+
* Sophisticated clients may wish to override this.
|
|
304
|
+
*
|
|
305
|
+
* @param {ReactReconcileTransaction} transaction
|
|
306
|
+
* @internal
|
|
307
|
+
* @overridable
|
|
308
|
+
*/
|
|
309
|
+
updateComponent: SpecPolicy.OVERRIDE_BASE
|
|
310
|
+
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Mapping from class specification keys to special processing functions.
|
|
315
|
+
*
|
|
316
|
+
* Although these are declared like instance properties in the specification
|
|
317
|
+
* when defining classes using `React.createClass`, they are actually static
|
|
318
|
+
* and are accessible on the constructor instead of the prototype. Despite
|
|
319
|
+
* being static, they must be defined outside of the "statics" key under
|
|
320
|
+
* which all other static methods are defined.
|
|
321
|
+
*/
|
|
322
|
+
var RESERVED_SPEC_KEYS = {
|
|
323
|
+
displayName: function(ConvenienceConstructor, displayName) {
|
|
324
|
+
ConvenienceConstructor.componentConstructor.displayName = displayName;
|
|
325
|
+
},
|
|
326
|
+
mixins: function(ConvenienceConstructor, mixins) {
|
|
327
|
+
if (mixins) {
|
|
328
|
+
for (var i = 0; i < mixins.length; i++) {
|
|
329
|
+
mixSpecIntoComponent(ConvenienceConstructor, mixins[i]);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
childContextTypes: function(ConvenienceConstructor, childContextTypes) {
|
|
334
|
+
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
335
|
+
validateTypeDef(
|
|
336
|
+
Constructor,
|
|
337
|
+
childContextTypes,
|
|
338
|
+
ReactPropTypeLocations.childContext
|
|
339
|
+
);
|
|
340
|
+
Constructor.childContextTypes = merge(
|
|
341
|
+
Constructor.childContextTypes,
|
|
342
|
+
childContextTypes
|
|
343
|
+
);
|
|
344
|
+
},
|
|
345
|
+
contextTypes: function(ConvenienceConstructor, contextTypes) {
|
|
346
|
+
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
347
|
+
validateTypeDef(
|
|
348
|
+
Constructor,
|
|
349
|
+
contextTypes,
|
|
350
|
+
ReactPropTypeLocations.context
|
|
351
|
+
);
|
|
352
|
+
Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
|
|
353
|
+
},
|
|
354
|
+
propTypes: function(ConvenienceConstructor, propTypes) {
|
|
355
|
+
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
356
|
+
validateTypeDef(
|
|
357
|
+
Constructor,
|
|
358
|
+
propTypes,
|
|
359
|
+
ReactPropTypeLocations.prop
|
|
360
|
+
);
|
|
361
|
+
Constructor.propTypes = merge(Constructor.propTypes, propTypes);
|
|
362
|
+
},
|
|
363
|
+
statics: function(ConvenienceConstructor, statics) {
|
|
364
|
+
mixStaticSpecIntoComponent(ConvenienceConstructor, statics);
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
function validateTypeDef(Constructor, typeDef, location) {
|
|
369
|
+
for (var propName in typeDef) {
|
|
370
|
+
if (typeDef.hasOwnProperty(propName)) {
|
|
371
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
372
|
+
typeof typeDef[propName] == 'function',
|
|
373
|
+
'%s: %s type `%s` is invalid; it must be a function, usually from ' +
|
|
374
|
+
'React.PropTypes.',
|
|
375
|
+
Constructor.displayName || 'ReactCompositeComponent',
|
|
376
|
+
ReactPropTypeLocationNames[location],
|
|
377
|
+
propName
|
|
378
|
+
) : invariant(typeof typeDef[propName] == 'function'));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function validateMethodOverride(proto, name) {
|
|
384
|
+
var specPolicy = ReactCompositeComponentInterface[name];
|
|
385
|
+
|
|
386
|
+
// Disallow overriding of base class methods unless explicitly allowed.
|
|
387
|
+
if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
|
|
388
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
389
|
+
specPolicy === SpecPolicy.OVERRIDE_BASE,
|
|
390
|
+
'ReactCompositeComponentInterface: You are attempting to override ' +
|
|
391
|
+
'`%s` from your class specification. Ensure that your method names ' +
|
|
392
|
+
'do not overlap with React methods.',
|
|
393
|
+
name
|
|
394
|
+
) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE));
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Disallow defining methods more than once unless explicitly allowed.
|
|
398
|
+
if (proto.hasOwnProperty(name)) {
|
|
399
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
400
|
+
specPolicy === SpecPolicy.DEFINE_MANY ||
|
|
401
|
+
specPolicy === SpecPolicy.DEFINE_MANY_MERGED,
|
|
402
|
+
'ReactCompositeComponentInterface: You are attempting to define ' +
|
|
403
|
+
'`%s` on your component more than once. This conflict may be due ' +
|
|
404
|
+
'to a mixin.',
|
|
405
|
+
name
|
|
406
|
+
) : invariant(specPolicy === SpecPolicy.DEFINE_MANY ||
|
|
407
|
+
specPolicy === SpecPolicy.DEFINE_MANY_MERGED));
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function validateLifeCycleOnReplaceState(instance) {
|
|
412
|
+
var compositeLifeCycleState = instance._compositeLifeCycleState;
|
|
413
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
414
|
+
instance.isMounted() ||
|
|
415
|
+
compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
|
|
416
|
+
'replaceState(...): Can only update a mounted or mounting component.'
|
|
417
|
+
) : invariant(instance.isMounted() ||
|
|
418
|
+
compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
|
|
419
|
+
("production" !== process.env.NODE_ENV ? invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE,
|
|
420
|
+
'replaceState(...): Cannot update during an existing state transition ' +
|
|
421
|
+
'(such as within `render`). This could potentially cause an infinite ' +
|
|
422
|
+
'loop so it is forbidden.'
|
|
423
|
+
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE));
|
|
424
|
+
("production" !== process.env.NODE_ENV ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
|
|
425
|
+
'replaceState(...): Cannot update while unmounting component. This ' +
|
|
426
|
+
'usually means you called setState() on an unmounted component.'
|
|
427
|
+
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Custom version of `mixInto` which handles policy validation and reserved
|
|
432
|
+
* specification keys when building `ReactCompositeComponent` classses.
|
|
433
|
+
*/
|
|
434
|
+
function mixSpecIntoComponent(ConvenienceConstructor, spec) {
|
|
435
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
436
|
+
!isValidClass(spec),
|
|
437
|
+
'ReactCompositeComponent: You\'re attempting to ' +
|
|
438
|
+
'use a component class as a mixin. Instead, just use a regular object.'
|
|
439
|
+
) : invariant(!isValidClass(spec)));
|
|
440
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
441
|
+
!ReactComponent.isValidComponent(spec),
|
|
442
|
+
'ReactCompositeComponent: You\'re attempting to ' +
|
|
443
|
+
'use a component as a mixin. Instead, just use a regular object.'
|
|
444
|
+
) : invariant(!ReactComponent.isValidComponent(spec)));
|
|
445
|
+
|
|
446
|
+
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
447
|
+
var proto = Constructor.prototype;
|
|
448
|
+
for (var name in spec) {
|
|
449
|
+
var property = spec[name];
|
|
450
|
+
if (!spec.hasOwnProperty(name)) {
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
validateMethodOverride(proto, name);
|
|
455
|
+
|
|
456
|
+
if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
|
|
457
|
+
RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property);
|
|
458
|
+
} else {
|
|
459
|
+
// Setup methods on prototype:
|
|
460
|
+
// The following member methods should not be automatically bound:
|
|
461
|
+
// 1. Expected ReactCompositeComponent methods (in the "interface").
|
|
462
|
+
// 2. Overridden methods (that were mixed in).
|
|
463
|
+
var isCompositeComponentMethod = name in ReactCompositeComponentInterface;
|
|
464
|
+
var isInherited = name in proto;
|
|
465
|
+
var markedDontBind = property && property.__reactDontBind;
|
|
466
|
+
var isFunction = typeof property === 'function';
|
|
467
|
+
var shouldAutoBind =
|
|
468
|
+
isFunction &&
|
|
469
|
+
!isCompositeComponentMethod &&
|
|
470
|
+
!isInherited &&
|
|
471
|
+
!markedDontBind;
|
|
472
|
+
|
|
473
|
+
if (shouldAutoBind) {
|
|
474
|
+
if (!proto.__reactAutoBindMap) {
|
|
475
|
+
proto.__reactAutoBindMap = {};
|
|
476
|
+
}
|
|
477
|
+
proto.__reactAutoBindMap[name] = property;
|
|
478
|
+
proto[name] = property;
|
|
479
|
+
} else {
|
|
480
|
+
if (isInherited) {
|
|
481
|
+
// For methods which are defined more than once, call the existing
|
|
482
|
+
// methods before calling the new property.
|
|
483
|
+
if (ReactCompositeComponentInterface[name] ===
|
|
484
|
+
SpecPolicy.DEFINE_MANY_MERGED) {
|
|
485
|
+
proto[name] = createMergedResultFunction(proto[name], property);
|
|
486
|
+
} else {
|
|
487
|
+
proto[name] = createChainedFunction(proto[name], property);
|
|
488
|
+
}
|
|
489
|
+
} else {
|
|
490
|
+
proto[name] = property;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
|
|
498
|
+
if (!statics) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
for (var name in statics) {
|
|
502
|
+
var property = statics[name];
|
|
503
|
+
if (!statics.hasOwnProperty(name) || !property) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
var isInherited = name in ConvenienceConstructor;
|
|
508
|
+
var result = property;
|
|
509
|
+
if (isInherited) {
|
|
510
|
+
var existingProperty = ConvenienceConstructor[name];
|
|
511
|
+
var existingType = typeof existingProperty;
|
|
512
|
+
var propertyType = typeof property;
|
|
513
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
514
|
+
existingType === 'function' && propertyType === 'function',
|
|
515
|
+
'ReactCompositeComponent: You are attempting to define ' +
|
|
516
|
+
'`%s` on your component more than once, but that is only supported ' +
|
|
517
|
+
'for functions, which are chained together. This conflict may be ' +
|
|
518
|
+
'due to a mixin.',
|
|
519
|
+
name
|
|
520
|
+
) : invariant(existingType === 'function' && propertyType === 'function'));
|
|
521
|
+
result = createChainedFunction(existingProperty, property);
|
|
522
|
+
}
|
|
523
|
+
ConvenienceConstructor[name] = result;
|
|
524
|
+
ConvenienceConstructor.componentConstructor[name] = result;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Merge two objects, but throw if both contain the same key.
|
|
530
|
+
*
|
|
531
|
+
* @param {object} one The first object, which is mutated.
|
|
532
|
+
* @param {object} two The second object
|
|
533
|
+
* @return {object} one after it has been mutated to contain everything in two.
|
|
534
|
+
*/
|
|
535
|
+
function mergeObjectsWithNoDuplicateKeys(one, two) {
|
|
536
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
537
|
+
one && two && typeof one === 'object' && typeof two === 'object',
|
|
538
|
+
'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
|
|
539
|
+
) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
|
|
540
|
+
|
|
541
|
+
objMap(two, function(value, key) {
|
|
542
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
543
|
+
one[key] === undefined,
|
|
544
|
+
'mergeObjectsWithNoDuplicateKeys(): ' +
|
|
545
|
+
'Tried to merge two objects with the same key: %s',
|
|
546
|
+
key
|
|
547
|
+
) : invariant(one[key] === undefined));
|
|
548
|
+
one[key] = value;
|
|
549
|
+
});
|
|
550
|
+
return one;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Creates a function that invokes two functions and merges their return values.
|
|
555
|
+
*
|
|
556
|
+
* @param {function} one Function to invoke first.
|
|
557
|
+
* @param {function} two Function to invoke second.
|
|
558
|
+
* @return {function} Function that invokes the two argument functions.
|
|
559
|
+
* @private
|
|
560
|
+
*/
|
|
561
|
+
function createMergedResultFunction(one, two) {
|
|
562
|
+
return function mergedResult() {
|
|
563
|
+
var a = one.apply(this, arguments);
|
|
564
|
+
var b = two.apply(this, arguments);
|
|
565
|
+
if (a == null) {
|
|
566
|
+
return b;
|
|
567
|
+
} else if (b == null) {
|
|
568
|
+
return a;
|
|
569
|
+
}
|
|
570
|
+
return mergeObjectsWithNoDuplicateKeys(a, b);
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Creates a function that invokes two functions and ignores their return vales.
|
|
576
|
+
*
|
|
577
|
+
* @param {function} one Function to invoke first.
|
|
578
|
+
* @param {function} two Function to invoke second.
|
|
579
|
+
* @return {function} Function that invokes the two argument functions.
|
|
580
|
+
* @private
|
|
581
|
+
*/
|
|
582
|
+
function createChainedFunction(one, two) {
|
|
583
|
+
return function chainedFunction() {
|
|
584
|
+
one.apply(this, arguments);
|
|
585
|
+
two.apply(this, arguments);
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
590
|
+
|
|
591
|
+
var unmountedPropertyWhitelist = {
|
|
592
|
+
constructor: true,
|
|
593
|
+
construct: true,
|
|
594
|
+
isOwnedBy: true, // should be deprecated but can have code mod (internal)
|
|
595
|
+
mountComponent: true,
|
|
596
|
+
mountComponentIntoNode: true,
|
|
597
|
+
props: true,
|
|
598
|
+
type: true,
|
|
599
|
+
_checkPropTypes: true,
|
|
600
|
+
_mountComponentIntoNode: true,
|
|
601
|
+
_processContext: true
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
var hasWarnedOnComponentType = {};
|
|
605
|
+
|
|
606
|
+
var warnIfUnmounted = function(instance, key) {
|
|
607
|
+
if (instance.__hasBeenMounted) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
var name = instance.constructor.displayName || 'Unknown';
|
|
611
|
+
var owner = ReactCurrentOwner.current;
|
|
612
|
+
var ownerName = (owner && owner.constructor.displayName) || 'Unknown';
|
|
613
|
+
var warningKey = key + '|' + name + '|' + ownerName;
|
|
614
|
+
if (hasWarnedOnComponentType.hasOwnProperty(warningKey)) {
|
|
615
|
+
// We have already warned for this combination. Skip it this time.
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
hasWarnedOnComponentType[warningKey] = true;
|
|
619
|
+
|
|
620
|
+
var context = owner ? ' in ' + ownerName + '.' : ' at the top level.';
|
|
621
|
+
var staticMethodExample = '<' + name + ' />.type.' + key + '(...)';
|
|
622
|
+
|
|
623
|
+
console.warn(
|
|
624
|
+
'Invalid access to component property "' + key + '" on ' + name +
|
|
625
|
+
context + ' See http://fb.me/react-warning-descriptors .' +
|
|
626
|
+
' Use a static method instead: ' + staticMethodExample
|
|
627
|
+
);
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
var defineMembraneProperty = function(membrane, prototype, key) {
|
|
631
|
+
Object.defineProperty(membrane, key, {
|
|
632
|
+
|
|
633
|
+
configurable: false,
|
|
634
|
+
enumerable: true,
|
|
635
|
+
|
|
636
|
+
get: function() {
|
|
637
|
+
if (this !== membrane) {
|
|
638
|
+
// When this is accessed through a prototype chain we need to check if
|
|
639
|
+
// this component was mounted.
|
|
640
|
+
warnIfUnmounted(this, key);
|
|
641
|
+
}
|
|
642
|
+
return prototype[key];
|
|
643
|
+
},
|
|
644
|
+
|
|
645
|
+
set: function(value) {
|
|
646
|
+
if (this !== membrane) {
|
|
647
|
+
// When this is accessed through a prototype chain, we first check if
|
|
648
|
+
// this component was mounted. Then we define a value on "this"
|
|
649
|
+
// instance, effectively disabling the membrane on that prototype
|
|
650
|
+
// chain.
|
|
651
|
+
warnIfUnmounted(this, key);
|
|
652
|
+
Object.defineProperty(this, key, {
|
|
653
|
+
enumerable: true,
|
|
654
|
+
configurable: true,
|
|
655
|
+
writable: true,
|
|
656
|
+
value: value
|
|
657
|
+
});
|
|
658
|
+
} else {
|
|
659
|
+
// Otherwise, this should modify the prototype
|
|
660
|
+
prototype[key] = value;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
});
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Creates a membrane prototype which wraps the original prototype. If any
|
|
669
|
+
* property is accessed in an unmounted state, a warning is issued.
|
|
670
|
+
*
|
|
671
|
+
* @param {object} prototype Original prototype.
|
|
672
|
+
* @return {object} The membrane prototype.
|
|
673
|
+
* @private
|
|
674
|
+
*/
|
|
675
|
+
var createMountWarningMembrane = function(prototype) {
|
|
676
|
+
try {
|
|
677
|
+
var membrane = Object.create(prototype);
|
|
678
|
+
for (var key in prototype) {
|
|
679
|
+
if (unmountedPropertyWhitelist.hasOwnProperty(key)) {
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
defineMembraneProperty(membrane, prototype, key);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
membrane.mountComponent = function() {
|
|
686
|
+
this.__hasBeenMounted = true;
|
|
687
|
+
return prototype.mountComponent.apply(this, arguments);
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
return membrane;
|
|
691
|
+
} catch(x) {
|
|
692
|
+
// In IE8 define property will fail on non-DOM objects. If anything in
|
|
693
|
+
// the membrane creation fails, we'll bail out and just use the prototype
|
|
694
|
+
// without warnings.
|
|
695
|
+
return prototype;
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* `ReactCompositeComponent` maintains an auxiliary life cycle state in
|
|
703
|
+
* `this._compositeLifeCycleState` (which can be null).
|
|
704
|
+
*
|
|
705
|
+
* This is different from the life cycle state maintained by `ReactComponent` in
|
|
706
|
+
* `this._lifeCycleState`. The following diagram shows how the states overlap in
|
|
707
|
+
* time. There are times when the CompositeLifeCycle is null - at those times it
|
|
708
|
+
* is only meaningful to look at ComponentLifeCycle alone.
|
|
709
|
+
*
|
|
710
|
+
* Top Row: ReactComponent.ComponentLifeCycle
|
|
711
|
+
* Low Row: ReactComponent.CompositeLifeCycle
|
|
712
|
+
*
|
|
713
|
+
* +-------+------------------------------------------------------+--------+
|
|
714
|
+
* | UN | MOUNTED | UN |
|
|
715
|
+
* |MOUNTED| | MOUNTED|
|
|
716
|
+
* +-------+------------------------------------------------------+--------+
|
|
717
|
+
* | ^--------+ +------+ +------+ +------+ +--------^ |
|
|
718
|
+
* | | | | | | | | | | | |
|
|
719
|
+
* | 0--|MOUNTING|-0-|RECEIV|-0-|RECEIV|-0-|RECEIV|-0-| UN |--->0 |
|
|
720
|
+
* | | | |PROPS | | PROPS| | STATE| |MOUNTING| |
|
|
721
|
+
* | | | | | | | | | | | |
|
|
722
|
+
* | | | | | | | | | | | |
|
|
723
|
+
* | +--------+ +------+ +------+ +------+ +--------+ |
|
|
724
|
+
* | | | |
|
|
725
|
+
* +-------+------------------------------------------------------+--------+
|
|
726
|
+
*/
|
|
727
|
+
var CompositeLifeCycle = keyMirror({
|
|
728
|
+
/**
|
|
729
|
+
* Components in the process of being mounted respond to state changes
|
|
730
|
+
* differently.
|
|
731
|
+
*/
|
|
732
|
+
MOUNTING: null,
|
|
733
|
+
/**
|
|
734
|
+
* Components in the process of being unmounted are guarded against state
|
|
735
|
+
* changes.
|
|
736
|
+
*/
|
|
737
|
+
UNMOUNTING: null,
|
|
738
|
+
/**
|
|
739
|
+
* Components that are mounted and receiving new props respond to state
|
|
740
|
+
* changes differently.
|
|
741
|
+
*/
|
|
742
|
+
RECEIVING_PROPS: null,
|
|
743
|
+
/**
|
|
744
|
+
* Components that are mounted and receiving new state are guarded against
|
|
745
|
+
* additional state changes.
|
|
746
|
+
*/
|
|
747
|
+
RECEIVING_STATE: null
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* @lends {ReactCompositeComponent.prototype}
|
|
752
|
+
*/
|
|
753
|
+
var ReactCompositeComponentMixin = {
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Base constructor for all composite component.
|
|
757
|
+
*
|
|
758
|
+
* @param {?object} initialProps
|
|
759
|
+
* @param {*} children
|
|
760
|
+
* @final
|
|
761
|
+
* @internal
|
|
762
|
+
*/
|
|
763
|
+
construct: function(initialProps, children) {
|
|
764
|
+
// Children can be either an array or more than one argument
|
|
765
|
+
ReactComponent.Mixin.construct.apply(this, arguments);
|
|
766
|
+
|
|
767
|
+
this.state = null;
|
|
768
|
+
this._pendingState = null;
|
|
769
|
+
|
|
770
|
+
this.context = this._processContext(ReactContext.current);
|
|
771
|
+
this._currentContext = ReactContext.current;
|
|
772
|
+
this._pendingContext = null;
|
|
773
|
+
|
|
774
|
+
this._compositeLifeCycleState = null;
|
|
775
|
+
},
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Checks whether or not this composite component is mounted.
|
|
779
|
+
* @return {boolean} True if mounted, false otherwise.
|
|
780
|
+
* @protected
|
|
781
|
+
* @final
|
|
782
|
+
*/
|
|
783
|
+
isMounted: function() {
|
|
784
|
+
return ReactComponent.Mixin.isMounted.call(this) &&
|
|
785
|
+
this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
|
|
786
|
+
},
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* Initializes the component, renders markup, and registers event listeners.
|
|
790
|
+
*
|
|
791
|
+
* @param {string} rootID DOM ID of the root node.
|
|
792
|
+
* @param {ReactReconcileTransaction} transaction
|
|
793
|
+
* @param {number} mountDepth number of components in the owner hierarchy
|
|
794
|
+
* @return {?string} Rendered markup to be inserted into the DOM.
|
|
795
|
+
* @final
|
|
796
|
+
* @internal
|
|
797
|
+
*/
|
|
798
|
+
mountComponent: ReactPerf.measure(
|
|
799
|
+
'ReactCompositeComponent',
|
|
800
|
+
'mountComponent',
|
|
801
|
+
function(rootID, transaction, mountDepth) {
|
|
802
|
+
ReactComponent.Mixin.mountComponent.call(
|
|
803
|
+
this,
|
|
804
|
+
rootID,
|
|
805
|
+
transaction,
|
|
806
|
+
mountDepth
|
|
807
|
+
);
|
|
808
|
+
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
|
|
809
|
+
|
|
810
|
+
this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
|
|
811
|
+
this.props = this._processProps(this.props);
|
|
812
|
+
|
|
813
|
+
if (this.__reactAutoBindMap) {
|
|
814
|
+
this._bindAutoBindMethods();
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
this.state = this.getInitialState ? this.getInitialState() : null;
|
|
818
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
819
|
+
typeof this.state === 'object' && !Array.isArray(this.state),
|
|
820
|
+
'%s.getInitialState(): must return an object or null',
|
|
821
|
+
this.constructor.displayName || 'ReactCompositeComponent'
|
|
822
|
+
) : invariant(typeof this.state === 'object' && !Array.isArray(this.state)));
|
|
823
|
+
|
|
824
|
+
this._pendingState = null;
|
|
825
|
+
this._pendingForceUpdate = false;
|
|
826
|
+
|
|
827
|
+
if (this.componentWillMount) {
|
|
828
|
+
this.componentWillMount();
|
|
829
|
+
// When mounting, calls to `setState` by `componentWillMount` will set
|
|
830
|
+
// `this._pendingState` without triggering a re-render.
|
|
831
|
+
if (this._pendingState) {
|
|
832
|
+
this.state = this._pendingState;
|
|
833
|
+
this._pendingState = null;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
this._renderedComponent = this._renderValidatedComponent();
|
|
838
|
+
|
|
839
|
+
// Done with mounting, `setState` will now trigger UI changes.
|
|
840
|
+
this._compositeLifeCycleState = null;
|
|
841
|
+
var markup = this._renderedComponent.mountComponent(
|
|
842
|
+
rootID,
|
|
843
|
+
transaction,
|
|
844
|
+
mountDepth + 1
|
|
845
|
+
);
|
|
846
|
+
if (this.componentDidMount) {
|
|
847
|
+
transaction.getReactMountReady().enqueue(this, this.componentDidMount);
|
|
848
|
+
}
|
|
849
|
+
return markup;
|
|
850
|
+
}
|
|
851
|
+
),
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* Releases any resources allocated by `mountComponent`.
|
|
855
|
+
*
|
|
856
|
+
* @final
|
|
857
|
+
* @internal
|
|
858
|
+
*/
|
|
859
|
+
unmountComponent: function() {
|
|
860
|
+
this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING;
|
|
861
|
+
if (this.componentWillUnmount) {
|
|
862
|
+
this.componentWillUnmount();
|
|
863
|
+
}
|
|
864
|
+
this._compositeLifeCycleState = null;
|
|
865
|
+
|
|
866
|
+
this._defaultProps = null;
|
|
867
|
+
|
|
868
|
+
this._renderedComponent.unmountComponent();
|
|
869
|
+
this._renderedComponent = null;
|
|
870
|
+
|
|
871
|
+
ReactComponent.Mixin.unmountComponent.call(this);
|
|
872
|
+
|
|
873
|
+
if (this.refs) {
|
|
874
|
+
this.refs = null;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// Some existing components rely on this.props even after they've been
|
|
878
|
+
// destroyed (in event handlers).
|
|
879
|
+
// TODO: this.props = null;
|
|
880
|
+
// TODO: this.state = null;
|
|
881
|
+
},
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Sets a subset of the state. Always use this or `replaceState` to mutate
|
|
885
|
+
* state. You should treat `this.state` as immutable.
|
|
886
|
+
*
|
|
887
|
+
* There is no guarantee that `this.state` will be immediately updated, so
|
|
888
|
+
* accessing `this.state` after calling this method may return the old value.
|
|
889
|
+
*
|
|
890
|
+
* There is no guarantee that calls to `setState` will run synchronously,
|
|
891
|
+
* as they may eventually be batched together. You can provide an optional
|
|
892
|
+
* callback that will be executed when the call to setState is actually
|
|
893
|
+
* completed.
|
|
894
|
+
*
|
|
895
|
+
* @param {object} partialState Next partial state to be merged with state.
|
|
896
|
+
* @param {?function} callback Called after state is updated.
|
|
897
|
+
* @final
|
|
898
|
+
* @protected
|
|
899
|
+
*/
|
|
900
|
+
setState: function(partialState, callback) {
|
|
901
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
902
|
+
typeof partialState === 'object' || partialState == null,
|
|
903
|
+
'setState(...): takes an object of state variables to update.'
|
|
904
|
+
) : invariant(typeof partialState === 'object' || partialState == null));
|
|
905
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
906
|
+
if (partialState == null) {
|
|
907
|
+
console.warn(
|
|
908
|
+
'setState(...): You passed an undefined or null state object; ' +
|
|
909
|
+
'instead, use forceUpdate().'
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
// Merge with `_pendingState` if it exists, otherwise with existing state.
|
|
914
|
+
this.replaceState(
|
|
915
|
+
merge(this._pendingState || this.state, partialState),
|
|
916
|
+
callback
|
|
917
|
+
);
|
|
918
|
+
},
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* Replaces all of the state. Always use this or `setState` to mutate state.
|
|
922
|
+
* You should treat `this.state` as immutable.
|
|
923
|
+
*
|
|
924
|
+
* There is no guarantee that `this.state` will be immediately updated, so
|
|
925
|
+
* accessing `this.state` after calling this method may return the old value.
|
|
926
|
+
*
|
|
927
|
+
* @param {object} completeState Next state.
|
|
928
|
+
* @param {?function} callback Called after state is updated.
|
|
929
|
+
* @final
|
|
930
|
+
* @protected
|
|
931
|
+
*/
|
|
932
|
+
replaceState: function(completeState, callback) {
|
|
933
|
+
validateLifeCycleOnReplaceState(this);
|
|
934
|
+
this._pendingState = completeState;
|
|
935
|
+
ReactUpdates.enqueueUpdate(this, callback);
|
|
936
|
+
},
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* Filters the context object to only contain keys specified in
|
|
940
|
+
* `contextTypes`, and asserts that they are valid.
|
|
941
|
+
*
|
|
942
|
+
* @param {object} context
|
|
943
|
+
* @return {?object}
|
|
944
|
+
* @private
|
|
945
|
+
*/
|
|
946
|
+
_processContext: function(context) {
|
|
947
|
+
var maskedContext = null;
|
|
948
|
+
var contextTypes = this.constructor.contextTypes;
|
|
949
|
+
if (contextTypes) {
|
|
950
|
+
maskedContext = {};
|
|
951
|
+
for (var contextName in contextTypes) {
|
|
952
|
+
maskedContext[contextName] = context[contextName];
|
|
953
|
+
}
|
|
954
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
955
|
+
this._checkPropTypes(
|
|
956
|
+
contextTypes,
|
|
957
|
+
maskedContext,
|
|
958
|
+
ReactPropTypeLocations.context
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
return maskedContext;
|
|
963
|
+
},
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* @param {object} currentContext
|
|
967
|
+
* @return {object}
|
|
968
|
+
* @private
|
|
969
|
+
*/
|
|
970
|
+
_processChildContext: function(currentContext) {
|
|
971
|
+
var childContext = this.getChildContext && this.getChildContext();
|
|
972
|
+
var displayName = this.constructor.displayName || 'ReactCompositeComponent';
|
|
973
|
+
if (childContext) {
|
|
974
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
975
|
+
typeof this.constructor.childContextTypes === 'object',
|
|
976
|
+
'%s.getChildContext(): childContextTypes must be defined in order to ' +
|
|
977
|
+
'use getChildContext().',
|
|
978
|
+
displayName
|
|
979
|
+
) : invariant(typeof this.constructor.childContextTypes === 'object'));
|
|
980
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
981
|
+
this._checkPropTypes(
|
|
982
|
+
this.constructor.childContextTypes,
|
|
983
|
+
childContext,
|
|
984
|
+
ReactPropTypeLocations.childContext
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
for (var name in childContext) {
|
|
988
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
989
|
+
name in this.constructor.childContextTypes,
|
|
990
|
+
'%s.getChildContext(): key "%s" is not defined in childContextTypes.',
|
|
991
|
+
displayName,
|
|
992
|
+
name
|
|
993
|
+
) : invariant(name in this.constructor.childContextTypes));
|
|
994
|
+
}
|
|
995
|
+
return merge(currentContext, childContext);
|
|
996
|
+
}
|
|
997
|
+
return currentContext;
|
|
998
|
+
},
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* Processes props by setting default values for unspecified props and
|
|
1002
|
+
* asserting that the props are valid. Does not mutate its argument; returns
|
|
1003
|
+
* a new props object with defaults merged in.
|
|
1004
|
+
*
|
|
1005
|
+
* @param {object} newProps
|
|
1006
|
+
* @return {object}
|
|
1007
|
+
* @private
|
|
1008
|
+
*/
|
|
1009
|
+
_processProps: function(newProps) {
|
|
1010
|
+
var props = merge(newProps);
|
|
1011
|
+
var defaultProps = this._defaultProps;
|
|
1012
|
+
for (var propName in defaultProps) {
|
|
1013
|
+
if (typeof props[propName] === 'undefined') {
|
|
1014
|
+
props[propName] = defaultProps[propName];
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1018
|
+
var propTypes = this.constructor.propTypes;
|
|
1019
|
+
if (propTypes) {
|
|
1020
|
+
this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
return props;
|
|
1024
|
+
},
|
|
1025
|
+
|
|
1026
|
+
/**
|
|
1027
|
+
* Assert that the props are valid
|
|
1028
|
+
*
|
|
1029
|
+
* @param {object} propTypes Map of prop name to a ReactPropType
|
|
1030
|
+
* @param {object} props
|
|
1031
|
+
* @param {string} location e.g. "prop", "context", "child context"
|
|
1032
|
+
* @private
|
|
1033
|
+
*/
|
|
1034
|
+
_checkPropTypes: function(propTypes, props, location) {
|
|
1035
|
+
var componentName = this.constructor.displayName;
|
|
1036
|
+
for (var propName in propTypes) {
|
|
1037
|
+
if (propTypes.hasOwnProperty(propName)) {
|
|
1038
|
+
propTypes[propName](props, propName, componentName, location);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
},
|
|
1042
|
+
|
|
1043
|
+
performUpdateIfNecessary: function() {
|
|
1044
|
+
var compositeLifeCycleState = this._compositeLifeCycleState;
|
|
1045
|
+
// Do not trigger a state transition if we are in the middle of mounting or
|
|
1046
|
+
// receiving props because both of those will already be doing this.
|
|
1047
|
+
if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING ||
|
|
1048
|
+
compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
ReactComponent.Mixin.performUpdateIfNecessary.call(this);
|
|
1052
|
+
},
|
|
1053
|
+
|
|
1054
|
+
/**
|
|
1055
|
+
* If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is
|
|
1056
|
+
* set, update the component.
|
|
1057
|
+
*
|
|
1058
|
+
* @param {ReactReconcileTransaction} transaction
|
|
1059
|
+
* @internal
|
|
1060
|
+
*/
|
|
1061
|
+
_performUpdateIfNecessary: function(transaction) {
|
|
1062
|
+
if (this._pendingProps == null &&
|
|
1063
|
+
this._pendingState == null &&
|
|
1064
|
+
this._pendingContext == null &&
|
|
1065
|
+
!this._pendingForceUpdate) {
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
var nextFullContext = this._pendingContext || this._currentContext;
|
|
1070
|
+
var nextContext = this._processContext(nextFullContext);
|
|
1071
|
+
this._pendingContext = null;
|
|
1072
|
+
|
|
1073
|
+
var nextProps = this.props;
|
|
1074
|
+
if (this._pendingProps != null) {
|
|
1075
|
+
nextProps = this._processProps(this._pendingProps);
|
|
1076
|
+
this._pendingProps = null;
|
|
1077
|
+
|
|
1078
|
+
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
|
|
1079
|
+
if (this.componentWillReceiveProps) {
|
|
1080
|
+
this.componentWillReceiveProps(nextProps, nextContext);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
|
|
1085
|
+
|
|
1086
|
+
// Unlike props, state, and context, we specifically don't want to set
|
|
1087
|
+
// _pendingOwner to null here because it's possible for a component to have
|
|
1088
|
+
// a null owner, so we instead make `this._owner === this._pendingOwner`
|
|
1089
|
+
// mean that there's no owner change pending.
|
|
1090
|
+
var nextOwner = this._pendingOwner;
|
|
1091
|
+
|
|
1092
|
+
var nextState = this._pendingState || this.state;
|
|
1093
|
+
this._pendingState = null;
|
|
1094
|
+
|
|
1095
|
+
try {
|
|
1096
|
+
if (this._pendingForceUpdate ||
|
|
1097
|
+
!this.shouldComponentUpdate ||
|
|
1098
|
+
this.shouldComponentUpdate(nextProps, nextState, nextContext)) {
|
|
1099
|
+
this._pendingForceUpdate = false;
|
|
1100
|
+
// Will set `this.props`, `this.state` and `this.context`.
|
|
1101
|
+
this._performComponentUpdate(
|
|
1102
|
+
nextProps,
|
|
1103
|
+
nextOwner,
|
|
1104
|
+
nextState,
|
|
1105
|
+
nextFullContext,
|
|
1106
|
+
nextContext,
|
|
1107
|
+
transaction
|
|
1108
|
+
);
|
|
1109
|
+
} else {
|
|
1110
|
+
// If it's determined that a component should not update, we still want
|
|
1111
|
+
// to set props and state.
|
|
1112
|
+
this.props = nextProps;
|
|
1113
|
+
this._owner = nextOwner;
|
|
1114
|
+
this.state = nextState;
|
|
1115
|
+
this._currentContext = nextFullContext;
|
|
1116
|
+
this.context = nextContext;
|
|
1117
|
+
}
|
|
1118
|
+
} finally {
|
|
1119
|
+
this._compositeLifeCycleState = null;
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Merges new props and state, notifies delegate methods of update and
|
|
1125
|
+
* performs update.
|
|
1126
|
+
*
|
|
1127
|
+
* @param {object} nextProps Next object to set as properties.
|
|
1128
|
+
* @param {?ReactComponent} nextOwner Next component to set as owner
|
|
1129
|
+
* @param {?object} nextState Next object to set as state.
|
|
1130
|
+
* @param {?object} nextFullContext Next object to set as _currentContext.
|
|
1131
|
+
* @param {?object} nextContext Next object to set as context.
|
|
1132
|
+
* @param {ReactReconcileTransaction} transaction
|
|
1133
|
+
* @private
|
|
1134
|
+
*/
|
|
1135
|
+
_performComponentUpdate: function(
|
|
1136
|
+
nextProps,
|
|
1137
|
+
nextOwner,
|
|
1138
|
+
nextState,
|
|
1139
|
+
nextFullContext,
|
|
1140
|
+
nextContext,
|
|
1141
|
+
transaction
|
|
1142
|
+
) {
|
|
1143
|
+
var prevProps = this.props;
|
|
1144
|
+
var prevOwner = this._owner;
|
|
1145
|
+
var prevState = this.state;
|
|
1146
|
+
var prevContext = this.context;
|
|
1147
|
+
|
|
1148
|
+
if (this.componentWillUpdate) {
|
|
1149
|
+
this.componentWillUpdate(nextProps, nextState, nextContext);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
this.props = nextProps;
|
|
1153
|
+
this._owner = nextOwner;
|
|
1154
|
+
this.state = nextState;
|
|
1155
|
+
this._currentContext = nextFullContext;
|
|
1156
|
+
this.context = nextContext;
|
|
1157
|
+
|
|
1158
|
+
this.updateComponent(
|
|
1159
|
+
transaction,
|
|
1160
|
+
prevProps,
|
|
1161
|
+
prevOwner,
|
|
1162
|
+
prevState,
|
|
1163
|
+
prevContext
|
|
1164
|
+
);
|
|
1165
|
+
|
|
1166
|
+
if (this.componentDidUpdate) {
|
|
1167
|
+
transaction.getReactMountReady().enqueue(
|
|
1168
|
+
this,
|
|
1169
|
+
this.componentDidUpdate.bind(this, prevProps, prevState, prevContext)
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1172
|
+
},
|
|
1173
|
+
|
|
1174
|
+
receiveComponent: function(nextComponent, transaction) {
|
|
1175
|
+
if (nextComponent === this) {
|
|
1176
|
+
// Since props and context are immutable after the component is
|
|
1177
|
+
// mounted, we can do a cheap identity compare here to determine
|
|
1178
|
+
// if this is a superfluous reconcile.
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
this._pendingContext = nextComponent._currentContext;
|
|
1183
|
+
ReactComponent.Mixin.receiveComponent.call(
|
|
1184
|
+
this,
|
|
1185
|
+
nextComponent,
|
|
1186
|
+
transaction
|
|
1187
|
+
);
|
|
1188
|
+
},
|
|
1189
|
+
|
|
1190
|
+
/**
|
|
1191
|
+
* Updates the component's currently mounted DOM representation.
|
|
1192
|
+
*
|
|
1193
|
+
* By default, this implements React's rendering and reconciliation algorithm.
|
|
1194
|
+
* Sophisticated clients may wish to override this.
|
|
1195
|
+
*
|
|
1196
|
+
* @param {ReactReconcileTransaction} transaction
|
|
1197
|
+
* @param {object} prevProps
|
|
1198
|
+
* @param {?ReactComponent} prevOwner
|
|
1199
|
+
* @param {?object} prevState
|
|
1200
|
+
* @param {?object} prevContext
|
|
1201
|
+
* @internal
|
|
1202
|
+
* @overridable
|
|
1203
|
+
*/
|
|
1204
|
+
updateComponent: ReactPerf.measure(
|
|
1205
|
+
'ReactCompositeComponent',
|
|
1206
|
+
'updateComponent',
|
|
1207
|
+
function(transaction, prevProps, prevOwner, prevState, prevContext) {
|
|
1208
|
+
ReactComponent.Mixin.updateComponent.call(
|
|
1209
|
+
this,
|
|
1210
|
+
transaction,
|
|
1211
|
+
prevProps,
|
|
1212
|
+
prevOwner
|
|
1213
|
+
);
|
|
1214
|
+
var prevComponent = this._renderedComponent;
|
|
1215
|
+
var nextComponent = this._renderValidatedComponent();
|
|
1216
|
+
if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
|
|
1217
|
+
prevComponent.receiveComponent(nextComponent, transaction);
|
|
1218
|
+
} else {
|
|
1219
|
+
// These two IDs are actually the same! But nothing should rely on that.
|
|
1220
|
+
var thisID = this._rootNodeID;
|
|
1221
|
+
var prevComponentID = prevComponent._rootNodeID;
|
|
1222
|
+
prevComponent.unmountComponent();
|
|
1223
|
+
this._renderedComponent = nextComponent;
|
|
1224
|
+
var nextMarkup = nextComponent.mountComponent(
|
|
1225
|
+
thisID,
|
|
1226
|
+
transaction,
|
|
1227
|
+
this._mountDepth + 1
|
|
1228
|
+
);
|
|
1229
|
+
ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
|
|
1230
|
+
prevComponentID,
|
|
1231
|
+
nextMarkup
|
|
1232
|
+
);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Forces an update. This should only be invoked when it is known with
|
|
1239
|
+
* certainty that we are **not** in a DOM transaction.
|
|
1240
|
+
*
|
|
1241
|
+
* You may want to call this when you know that some deeper aspect of the
|
|
1242
|
+
* component's state has changed but `setState` was not called.
|
|
1243
|
+
*
|
|
1244
|
+
* This will not invoke `shouldUpdateComponent`, but it will invoke
|
|
1245
|
+
* `componentWillUpdate` and `componentDidUpdate`.
|
|
1246
|
+
*
|
|
1247
|
+
* @param {?function} callback Called after update is complete.
|
|
1248
|
+
* @final
|
|
1249
|
+
* @protected
|
|
1250
|
+
*/
|
|
1251
|
+
forceUpdate: function(callback) {
|
|
1252
|
+
var compositeLifeCycleState = this._compositeLifeCycleState;
|
|
1253
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
1254
|
+
this.isMounted() ||
|
|
1255
|
+
compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
|
|
1256
|
+
'forceUpdate(...): Can only force an update on mounted or mounting ' +
|
|
1257
|
+
'components.'
|
|
1258
|
+
) : invariant(this.isMounted() ||
|
|
1259
|
+
compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
|
|
1260
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
1261
|
+
compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
|
|
1262
|
+
compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
|
|
1263
|
+
'forceUpdate(...): Cannot force an update while unmounting component ' +
|
|
1264
|
+
'or during an existing state transition (such as within `render`).'
|
|
1265
|
+
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
|
|
1266
|
+
compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
|
|
1267
|
+
this._pendingForceUpdate = true;
|
|
1268
|
+
ReactUpdates.enqueueUpdate(this, callback);
|
|
1269
|
+
},
|
|
1270
|
+
|
|
1271
|
+
/**
|
|
1272
|
+
* @private
|
|
1273
|
+
*/
|
|
1274
|
+
_renderValidatedComponent: ReactPerf.measure(
|
|
1275
|
+
'ReactCompositeComponent',
|
|
1276
|
+
'_renderValidatedComponent',
|
|
1277
|
+
function() {
|
|
1278
|
+
var renderedComponent;
|
|
1279
|
+
var previousContext = ReactContext.current;
|
|
1280
|
+
ReactContext.current = this._processChildContext(this._currentContext);
|
|
1281
|
+
ReactCurrentOwner.current = this;
|
|
1282
|
+
try {
|
|
1283
|
+
renderedComponent = this.render();
|
|
1284
|
+
} finally {
|
|
1285
|
+
ReactContext.current = previousContext;
|
|
1286
|
+
ReactCurrentOwner.current = null;
|
|
1287
|
+
}
|
|
1288
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
1289
|
+
ReactComponent.isValidComponent(renderedComponent),
|
|
1290
|
+
'%s.render(): A valid ReactComponent must be returned. You may have ' +
|
|
1291
|
+
'returned null, undefined, an array, or some other invalid object.',
|
|
1292
|
+
this.constructor.displayName || 'ReactCompositeComponent'
|
|
1293
|
+
) : invariant(ReactComponent.isValidComponent(renderedComponent)));
|
|
1294
|
+
return renderedComponent;
|
|
1295
|
+
}
|
|
1296
|
+
),
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* @private
|
|
1300
|
+
*/
|
|
1301
|
+
_bindAutoBindMethods: function() {
|
|
1302
|
+
for (var autoBindKey in this.__reactAutoBindMap) {
|
|
1303
|
+
if (!this.__reactAutoBindMap.hasOwnProperty(autoBindKey)) {
|
|
1304
|
+
continue;
|
|
1305
|
+
}
|
|
1306
|
+
var method = this.__reactAutoBindMap[autoBindKey];
|
|
1307
|
+
this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard(
|
|
1308
|
+
method,
|
|
1309
|
+
this.constructor.displayName + '.' + autoBindKey
|
|
1310
|
+
));
|
|
1311
|
+
}
|
|
1312
|
+
},
|
|
1313
|
+
|
|
1314
|
+
/**
|
|
1315
|
+
* Binds a method to the component.
|
|
1316
|
+
*
|
|
1317
|
+
* @param {function} method Method to be bound.
|
|
1318
|
+
* @private
|
|
1319
|
+
*/
|
|
1320
|
+
_bindAutoBindMethod: function(method) {
|
|
1321
|
+
var component = this;
|
|
1322
|
+
var boundMethod = function() {
|
|
1323
|
+
return method.apply(component, arguments);
|
|
1324
|
+
};
|
|
1325
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1326
|
+
boundMethod.__reactBoundContext = component;
|
|
1327
|
+
boundMethod.__reactBoundMethod = method;
|
|
1328
|
+
boundMethod.__reactBoundArguments = null;
|
|
1329
|
+
var componentName = component.constructor.displayName;
|
|
1330
|
+
var _bind = boundMethod.bind;
|
|
1331
|
+
boundMethod.bind = function(newThis ) {var args=Array.prototype.slice.call(arguments,1);
|
|
1332
|
+
// User is trying to bind() an autobound method; we effectively will
|
|
1333
|
+
// ignore the value of "this" that the user is trying to use, so
|
|
1334
|
+
// let's warn.
|
|
1335
|
+
if (newThis !== component && newThis !== null) {
|
|
1336
|
+
console.warn(
|
|
1337
|
+
'bind(): React component methods may only be bound to the ' +
|
|
1338
|
+
'component instance. See ' + componentName
|
|
1339
|
+
);
|
|
1340
|
+
} else if (!args.length) {
|
|
1341
|
+
console.warn(
|
|
1342
|
+
'bind(): You are binding a component method to the component. ' +
|
|
1343
|
+
'React does this for you automatically in a high-performance ' +
|
|
1344
|
+
'way, so you can safely remove this call. See ' + componentName
|
|
1345
|
+
);
|
|
1346
|
+
return boundMethod;
|
|
1347
|
+
}
|
|
1348
|
+
var reboundMethod = _bind.apply(boundMethod, arguments);
|
|
1349
|
+
reboundMethod.__reactBoundContext = component;
|
|
1350
|
+
reboundMethod.__reactBoundMethod = method;
|
|
1351
|
+
reboundMethod.__reactBoundArguments = args;
|
|
1352
|
+
return reboundMethod;
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
return boundMethod;
|
|
1356
|
+
}
|
|
1357
|
+
};
|
|
1358
|
+
|
|
1359
|
+
var ReactCompositeComponentBase = function() {};
|
|
1360
|
+
mixInto(ReactCompositeComponentBase, ReactComponent.Mixin);
|
|
1361
|
+
mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
|
|
1362
|
+
mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
|
|
1363
|
+
mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
|
|
1364
|
+
|
|
1365
|
+
/**
|
|
1366
|
+
* Checks if a value is a valid component constructor.
|
|
1367
|
+
*
|
|
1368
|
+
* @param {*}
|
|
1369
|
+
* @return {boolean}
|
|
1370
|
+
* @public
|
|
1371
|
+
*/
|
|
1372
|
+
function isValidClass(componentClass) {
|
|
1373
|
+
return componentClass instanceof Function &&
|
|
1374
|
+
'componentConstructor' in componentClass &&
|
|
1375
|
+
componentClass.componentConstructor instanceof Function;
|
|
1376
|
+
}
|
|
1377
|
+
/**
|
|
1378
|
+
* Module for creating composite components.
|
|
1379
|
+
*
|
|
1380
|
+
* @class ReactCompositeComponent
|
|
1381
|
+
* @extends ReactComponent
|
|
1382
|
+
* @extends ReactOwner
|
|
1383
|
+
* @extends ReactPropTransferer
|
|
1384
|
+
*/
|
|
1385
|
+
var ReactCompositeComponent = {
|
|
1386
|
+
|
|
1387
|
+
LifeCycle: CompositeLifeCycle,
|
|
1388
|
+
|
|
1389
|
+
Base: ReactCompositeComponentBase,
|
|
1390
|
+
|
|
1391
|
+
/**
|
|
1392
|
+
* Creates a composite component class given a class specification.
|
|
1393
|
+
*
|
|
1394
|
+
* @param {object} spec Class specification (which must define `render`).
|
|
1395
|
+
* @return {function} Component constructor function.
|
|
1396
|
+
* @public
|
|
1397
|
+
*/
|
|
1398
|
+
createClass: function(spec) {
|
|
1399
|
+
var Constructor = function() {};
|
|
1400
|
+
Constructor.prototype = new ReactCompositeComponentBase();
|
|
1401
|
+
Constructor.prototype.constructor = Constructor;
|
|
1402
|
+
|
|
1403
|
+
var ConvenienceConstructor = function(props, children) {
|
|
1404
|
+
var instance = new Constructor();
|
|
1405
|
+
instance.construct.apply(instance, arguments);
|
|
1406
|
+
return instance;
|
|
1407
|
+
};
|
|
1408
|
+
ConvenienceConstructor.componentConstructor = Constructor;
|
|
1409
|
+
Constructor.ConvenienceConstructor = ConvenienceConstructor;
|
|
1410
|
+
ConvenienceConstructor.originalSpec = spec;
|
|
1411
|
+
|
|
1412
|
+
mixSpecIntoComponent(ConvenienceConstructor, spec);
|
|
1413
|
+
|
|
1414
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
1415
|
+
Constructor.prototype.render,
|
|
1416
|
+
'createClass(...): Class specification must implement a `render` method.'
|
|
1417
|
+
) : invariant(Constructor.prototype.render));
|
|
1418
|
+
|
|
1419
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1420
|
+
if (Constructor.prototype.componentShouldUpdate) {
|
|
1421
|
+
console.warn(
|
|
1422
|
+
(spec.displayName || 'A component') + ' has a method called ' +
|
|
1423
|
+
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
|
|
1424
|
+
'The name is phrased as a question because the function is ' +
|
|
1425
|
+
'expected to return a value.'
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
// Expose the convience constructor on the prototype so that it can be
|
|
1431
|
+
// easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for
|
|
1432
|
+
// static methods like <Foo />.type.staticMethod();
|
|
1433
|
+
// This should not be named constructor since this may not be the function
|
|
1434
|
+
// that created the descriptor, and it may not even be a constructor.
|
|
1435
|
+
ConvenienceConstructor.type = Constructor;
|
|
1436
|
+
Constructor.prototype.type = Constructor;
|
|
1437
|
+
|
|
1438
|
+
// Reduce time spent doing lookups by setting these on the prototype.
|
|
1439
|
+
for (var methodName in ReactCompositeComponentInterface) {
|
|
1440
|
+
if (!Constructor.prototype[methodName]) {
|
|
1441
|
+
Constructor.prototype[methodName] = null;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1446
|
+
Constructor.prototype = createMountWarningMembrane(Constructor.prototype);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
return ConvenienceConstructor;
|
|
1450
|
+
},
|
|
1451
|
+
|
|
1452
|
+
isValidClass: isValidClass
|
|
1453
|
+
};
|
|
1454
|
+
|
|
1455
|
+
module.exports = ReactCompositeComponent;
|