react 0.8.0 → 0.10.0
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 +0 -8
- package/addons.js +0 -3
- package/lib/AutoFocusMixin.js +32 -0
- package/lib/CSSCore.js +23 -22
- package/lib/CSSProperty.js +32 -1
- package/lib/CSSPropertyOperations.js +1 -1
- package/lib/ChangeEventPlugin.js +27 -5
- package/lib/ClientReactRootIndex.js +30 -0
- package/lib/CompositionEventPlugin.js +58 -10
- package/lib/DOMChildrenOperations.js +39 -3
- package/lib/DOMProperty.js +9 -5
- package/lib/DOMPropertyOperations.js +21 -8
- package/lib/Danger.js +9 -8
- package/lib/DefaultDOMPropertyConfig.js +23 -14
- package/lib/DefaultEventPluginOrder.js +1 -1
- package/lib/EnterLeaveEventPlugin.js +38 -5
- package/lib/EventConstants.js +4 -1
- package/lib/EventListener.js +42 -34
- package/lib/EventPluginHub.js +118 -13
- package/lib/EventPluginRegistry.js +62 -18
- package/lib/EventPluginUtils.js +33 -4
- package/lib/EventPropagators.js +7 -43
- package/lib/ExecutionEnvironment.js +4 -1
- package/lib/LinkedStateMixin.js +1 -1
- package/lib/LinkedValueUtils.js +160 -0
- package/lib/MobileSafariClickEventPlugin.js +1 -1
- package/lib/PooledClass.js +7 -1
- package/lib/React.js +30 -4
- package/lib/ReactBrowserComponentMixin.js +42 -0
- package/lib/ReactCSSTransitionGroup.js +65 -0
- package/lib/{ReactTransitionableChild.js → ReactCSSTransitionGroupChild.js} +22 -36
- package/lib/ReactChildren.js +4 -4
- package/lib/ReactComponent.js +163 -83
- package/lib/ReactComponentBrowserEnvironment.js +55 -71
- package/lib/ReactCompositeComponent.js +686 -119
- package/lib/ReactContext.js +67 -0
- package/lib/ReactCurrentOwner.js +1 -1
- package/lib/ReactDOM.js +19 -6
- package/lib/ReactDOMButton.js +6 -1
- package/lib/ReactDOMComponent.js +66 -24
- package/lib/ReactDOMForm.js +13 -3
- package/lib/ReactDOMIDOperations.js +106 -61
- package/lib/ReactDOMImg.js +61 -0
- package/lib/ReactDOMInput.js +28 -15
- package/lib/ReactDOMOption.js +13 -8
- package/lib/ReactDOMSelect.js +38 -18
- package/lib/ReactDOMSelection.js +1 -1
- package/lib/ReactDOMTextarea.js +19 -11
- package/lib/ReactDefaultBatchingStrategy.js +1 -1
- package/lib/ReactDefaultInjection.js +60 -26
- package/lib/ReactDefaultPerf.js +208 -371
- package/lib/ReactDefaultPerfAnalysis.js +199 -0
- package/lib/ReactErrorUtils.js +6 -15
- package/lib/ReactEventEmitter.js +144 -146
- package/lib/ReactEventEmitterMixin.js +1 -33
- package/lib/ReactEventTopLevelCallback.js +75 -15
- package/lib/ReactInjection.js +43 -0
- package/lib/ReactInputSelection.js +3 -2
- package/lib/ReactInstanceHandles.js +36 -20
- package/lib/ReactLink.js +2 -2
- package/lib/ReactMarkupChecksum.js +1 -1
- package/lib/ReactMount.js +136 -104
- package/lib/ReactMountReady.js +2 -2
- package/lib/ReactMultiChild.js +40 -49
- package/lib/ReactMultiChildUpdateTypes.js +3 -1
- package/lib/ReactOwner.js +17 -4
- package/lib/ReactPerf.js +6 -9
- package/lib/ReactPropTransferer.js +41 -22
- package/lib/ReactPropTypeLocationNames.js +31 -0
- package/lib/{ReactComponentEnvironment.js → ReactPropTypeLocations.js} +11 -6
- package/lib/ReactPropTypes.js +249 -48
- package/lib/ReactPutListenerQueue.js +61 -0
- package/lib/ReactReconcileTransaction.js +28 -7
- package/lib/ReactRootIndex.js +36 -0
- package/lib/ReactServerRendering.js +46 -19
- package/lib/ReactServerRenderingTransaction.js +116 -0
- package/lib/ReactStateSetters.js +1 -1
- package/lib/ReactTestUtils.js +394 -0
- package/lib/ReactTextComponent.js +33 -6
- package/lib/{ReactTransitionKeySet.js → ReactTransitionChildMapping.js} +43 -48
- package/lib/ReactTransitionEvents.js +1 -1
- package/lib/ReactTransitionGroup.js +133 -58
- package/lib/ReactUpdates.js +15 -12
- package/lib/ReactWithAddons.js +15 -3
- package/lib/SelectEventPlugin.js +23 -40
- package/lib/ServerReactRootIndex.js +36 -0
- package/lib/SimpleEventPlugin.js +55 -7
- package/lib/SyntheticClipboardEvent.js +8 -2
- package/lib/SyntheticCompositionEvent.js +1 -1
- package/lib/SyntheticDragEvent.js +44 -0
- package/lib/SyntheticEvent.js +3 -2
- package/lib/SyntheticFocusEvent.js +1 -1
- package/lib/SyntheticKeyboardEvent.js +5 -3
- package/lib/SyntheticMouseEvent.js +1 -1
- package/lib/SyntheticTouchEvent.js +1 -1
- package/lib/SyntheticUIEvent.js +1 -1
- package/lib/SyntheticWheelEvent.js +11 -8
- package/lib/Transaction.js +62 -37
- package/lib/ViewportMetrics.js +1 -1
- package/lib/accumulate.js +1 -1
- package/lib/adler32.js +1 -1
- package/lib/cloneWithProps.js +59 -0
- package/lib/containsNode.js +1 -1
- package/lib/copyProperties.js +1 -1
- package/lib/createArrayFrom.js +11 -14
- package/lib/createFullPageComponent.js +63 -0
- package/lib/createNodesFromMarkup.js +1 -1
- package/lib/createObjectFrom.js +1 -1
- package/lib/cx.js +3 -3
- package/lib/dangerousStyleValue.js +1 -1
- package/lib/emptyFunction.js +1 -1
- package/lib/emptyObject.js +27 -0
- package/lib/escapeTextForBrowser.js +1 -1
- package/lib/flattenChildren.js +6 -3
- package/lib/focusNode.js +33 -0
- package/lib/forEachAccumulated.js +1 -1
- package/lib/getActiveElement.js +5 -4
- package/lib/getEventKey.js +85 -0
- package/lib/getEventTarget.js +1 -1
- package/lib/getMarkupWrap.js +11 -1
- package/lib/getNodeForCharacterOffset.js +1 -1
- package/lib/getReactRootElementInContainer.js +1 -1
- package/lib/getTextContentAccessor.js +6 -4
- package/lib/getUnboundedScrollPosition.js +3 -3
- package/lib/hyphenate.js +1 -1
- package/lib/instantiateReactComponent.js +70 -0
- package/lib/invariant.js +20 -12
- package/lib/isEventSupported.js +8 -12
- package/lib/isNode.js +2 -2
- package/lib/isTextInputElement.js +1 -1
- package/lib/isTextNode.js +1 -1
- package/lib/joinClasses.js +1 -1
- package/lib/keyMirror.js +1 -1
- package/lib/keyOf.js +1 -1
- package/lib/memoizeStringOnly.js +1 -1
- package/lib/merge.js +1 -1
- package/lib/mergeHelpers.js +6 -7
- package/lib/mergeInto.js +1 -1
- package/lib/mixInto.js +1 -1
- package/lib/monitorCodeUse.js +37 -0
- package/lib/objMap.js +1 -1
- package/lib/objMapKeyVal.js +1 -1
- package/lib/onlyChild.js +43 -0
- package/lib/performanceNow.js +1 -1
- package/lib/shallowEqual.js +1 -1
- package/lib/shouldUpdateReactComponent.js +61 -0
- package/lib/toArray.js +75 -0
- package/lib/traverseAllChildren.js +72 -9
- package/lib/update.js +159 -0
- package/lib/warning.js +48 -0
- package/package.json +3 -3
- package/react.js +0 -3
- package/ReactJSErrors.js +0 -40
- package/lib/$.js +0 -46
- package/lib/CallbackRegistry.js +0 -91
- package/lib/LinkedValueMixin.js +0 -68
- package/lib/ex.js +0 -49
- package/lib/filterAttributes.js +0 -45
- package/lib/ge.js +0 -76
- package/lib/mutateHTMLNodeWithMarkup.js +0 -100
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013 Facebook, Inc.
|
|
2
|
+
* Copyright 2013-2014 Facebook, Inc.
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
var ReactDOMIDOperations = require("./ReactDOMIDOperations");
|
|
24
24
|
var ReactMarkupChecksum = require("./ReactMarkupChecksum");
|
|
25
25
|
var ReactMount = require("./ReactMount");
|
|
26
|
+
var ReactPerf = require("./ReactPerf");
|
|
26
27
|
var ReactReconcileTransaction = require("./ReactReconcileTransaction");
|
|
27
28
|
|
|
28
29
|
var getReactRootElementInContainer = require("./getReactRootElementInContainer");
|
|
29
30
|
var invariant = require("./invariant");
|
|
30
|
-
var mutateHTMLNodeWithMarkup = require("./mutateHTMLNodeWithMarkup");
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
var ELEMENT_NODE_TYPE = 1;
|
|
@@ -39,29 +39,9 @@ var DOC_NODE_TYPE = 9;
|
|
|
39
39
|
* the browser context.
|
|
40
40
|
*/
|
|
41
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
42
|
ReactReconcileTransaction: ReactReconcileTransaction,
|
|
63
43
|
|
|
64
|
-
|
|
44
|
+
BackendIDOperations: ReactDOMIDOperations,
|
|
65
45
|
|
|
66
46
|
/**
|
|
67
47
|
* If a particular environment requires that some resources be cleaned up,
|
|
@@ -80,61 +60,65 @@ var ReactComponentBrowserEnvironment = {
|
|
|
80
60
|
* @param {boolean} shouldReuseMarkup Should reuse the existing markup in the
|
|
81
61
|
* container if possible.
|
|
82
62
|
*/
|
|
83
|
-
mountImageIntoNode:
|
|
84
|
-
|
|
85
|
-
|
|
63
|
+
mountImageIntoNode: ReactPerf.measure(
|
|
64
|
+
'ReactComponentBrowserEnvironment',
|
|
65
|
+
'mountImageIntoNode',
|
|
66
|
+
function(markup, container, shouldReuseMarkup) {
|
|
67
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
68
|
+
container && (
|
|
69
|
+
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
70
|
+
container.nodeType === DOC_NODE_TYPE
|
|
71
|
+
),
|
|
72
|
+
'mountComponentIntoNode(...): Target container is not valid.'
|
|
73
|
+
) : invariant(container && (
|
|
86
74
|
container.nodeType === ELEMENT_NODE_TYPE ||
|
|
87
|
-
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
'
|
|
103
|
-
'
|
|
104
|
-
'
|
|
105
|
-
'
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
75
|
+
container.nodeType === DOC_NODE_TYPE
|
|
76
|
+
)));
|
|
77
|
+
|
|
78
|
+
if (shouldReuseMarkup) {
|
|
79
|
+
if (ReactMarkupChecksum.canReuseMarkup(
|
|
80
|
+
markup,
|
|
81
|
+
getReactRootElementInContainer(container))) {
|
|
82
|
+
return;
|
|
83
|
+
} else {
|
|
84
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
85
|
+
container.nodeType !== DOC_NODE_TYPE,
|
|
86
|
+
'You\'re trying to render a component to the document using ' +
|
|
87
|
+
'server rendering but the checksum was invalid. This usually ' +
|
|
88
|
+
'means you rendered a different component type or props on ' +
|
|
89
|
+
'the client from the one on the server, or your render() ' +
|
|
90
|
+
'methods are impure. React cannot handle this case due to ' +
|
|
91
|
+
'cross-browser quirks by rendering at the document root. You ' +
|
|
92
|
+
'should look for environment dependent code in your components ' +
|
|
93
|
+
'and ensure the props are the same client and server side.'
|
|
94
|
+
) : invariant(container.nodeType !== DOC_NODE_TYPE));
|
|
95
|
+
|
|
96
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
97
|
+
console.warn(
|
|
98
|
+
'React attempted to use reuse markup in a container but the ' +
|
|
99
|
+
'checksum was invalid. This generally means that you are ' +
|
|
100
|
+
'using server rendering and the markup generated on the ' +
|
|
101
|
+
'server was not what the client was expecting. React injected' +
|
|
102
|
+
'new markup to compensate which works but you have lost many ' +
|
|
103
|
+
'of the benefits of server rendering. Instead, figure out ' +
|
|
104
|
+
'why the markup being generated is different on the client ' +
|
|
105
|
+
'or server.'
|
|
106
|
+
);
|
|
107
|
+
}
|
|
110
108
|
}
|
|
111
109
|
}
|
|
112
|
-
}
|
|
113
110
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
111
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
112
|
+
container.nodeType !== DOC_NODE_TYPE,
|
|
113
|
+
'You\'re trying to render a component to the document but ' +
|
|
114
|
+
'you didn\'t use server rendering. We can\'t do this ' +
|
|
115
|
+
'without using server rendering due to cross-browser quirks. ' +
|
|
116
|
+
'See renderComponentToString() for server rendering.'
|
|
117
|
+
) : invariant(container.nodeType !== DOC_NODE_TYPE));
|
|
121
118
|
|
|
122
|
-
// Asynchronously inject markup by ensuring that the container is not in
|
|
123
|
-
// the document when settings its `innerHTML`.
|
|
124
|
-
var parent = container.parentNode;
|
|
125
|
-
if (parent) {
|
|
126
|
-
var next = container.nextSibling;
|
|
127
|
-
parent.removeChild(container);
|
|
128
|
-
container.innerHTML = markup;
|
|
129
|
-
if (next) {
|
|
130
|
-
parent.insertBefore(container, next);
|
|
131
|
-
} else {
|
|
132
|
-
parent.appendChild(container);
|
|
133
|
-
}
|
|
134
|
-
} else {
|
|
135
119
|
container.innerHTML = markup;
|
|
136
120
|
}
|
|
137
|
-
|
|
121
|
+
)
|
|
138
122
|
};
|
|
139
123
|
|
|
140
124
|
module.exports = ReactComponentBrowserEnvironment;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2013 Facebook, Inc.
|
|
2
|
+
* Copyright 2013-2014 Facebook, Inc.
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -19,18 +19,25 @@
|
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
21
|
var ReactComponent = require("./ReactComponent");
|
|
22
|
+
var ReactContext = require("./ReactContext");
|
|
22
23
|
var ReactCurrentOwner = require("./ReactCurrentOwner");
|
|
23
24
|
var ReactErrorUtils = require("./ReactErrorUtils");
|
|
24
25
|
var ReactOwner = require("./ReactOwner");
|
|
25
26
|
var ReactPerf = require("./ReactPerf");
|
|
26
27
|
var ReactPropTransferer = require("./ReactPropTransferer");
|
|
28
|
+
var ReactPropTypeLocations = require("./ReactPropTypeLocations");
|
|
29
|
+
var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
|
|
27
30
|
var ReactUpdates = require("./ReactUpdates");
|
|
28
31
|
|
|
32
|
+
var instantiateReactComponent = require("./instantiateReactComponent");
|
|
29
33
|
var invariant = require("./invariant");
|
|
30
34
|
var keyMirror = require("./keyMirror");
|
|
31
35
|
var merge = require("./merge");
|
|
32
36
|
var mixInto = require("./mixInto");
|
|
37
|
+
var monitorCodeUse = require("./monitorCodeUse");
|
|
33
38
|
var objMap = require("./objMap");
|
|
39
|
+
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
|
|
40
|
+
var warning = require("./warning");
|
|
34
41
|
|
|
35
42
|
/**
|
|
36
43
|
* Policies that describe methods in `ReactCompositeComponentInterface`.
|
|
@@ -57,6 +64,9 @@ var SpecPolicy = keyMirror({
|
|
|
57
64
|
DEFINE_MANY_MERGED: null
|
|
58
65
|
});
|
|
59
66
|
|
|
67
|
+
|
|
68
|
+
var injectedMixins = [];
|
|
69
|
+
|
|
60
70
|
/**
|
|
61
71
|
* Composite components are higher-level components that compose other composite
|
|
62
72
|
* or native components.
|
|
@@ -89,15 +99,38 @@ var ReactCompositeComponentInterface = {
|
|
|
89
99
|
*/
|
|
90
100
|
mixins: SpecPolicy.DEFINE_MANY,
|
|
91
101
|
|
|
102
|
+
/**
|
|
103
|
+
* An object containing properties and methods that should be defined on
|
|
104
|
+
* the component's constructor instead of its prototype (static methods).
|
|
105
|
+
*
|
|
106
|
+
* @type {object}
|
|
107
|
+
* @optional
|
|
108
|
+
*/
|
|
109
|
+
statics: SpecPolicy.DEFINE_MANY,
|
|
110
|
+
|
|
92
111
|
/**
|
|
93
112
|
* Definition of prop types for this component.
|
|
94
113
|
*
|
|
95
114
|
* @type {object}
|
|
96
115
|
* @optional
|
|
97
116
|
*/
|
|
98
|
-
propTypes: SpecPolicy.
|
|
117
|
+
propTypes: SpecPolicy.DEFINE_MANY,
|
|
99
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Definition of context types for this component.
|
|
121
|
+
*
|
|
122
|
+
* @type {object}
|
|
123
|
+
* @optional
|
|
124
|
+
*/
|
|
125
|
+
contextTypes: SpecPolicy.DEFINE_MANY,
|
|
100
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Definition of context types this component sets for its children.
|
|
129
|
+
*
|
|
130
|
+
* @type {object}
|
|
131
|
+
* @optional
|
|
132
|
+
*/
|
|
133
|
+
childContextTypes: SpecPolicy.DEFINE_MANY,
|
|
101
134
|
|
|
102
135
|
// ==== Definition methods ====
|
|
103
136
|
|
|
@@ -129,6 +162,12 @@ var ReactCompositeComponentInterface = {
|
|
|
129
162
|
*/
|
|
130
163
|
getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
|
|
131
164
|
|
|
165
|
+
/**
|
|
166
|
+
* @return {object}
|
|
167
|
+
* @optional
|
|
168
|
+
*/
|
|
169
|
+
getChildContext: SpecPolicy.DEFINE_MANY_MERGED,
|
|
170
|
+
|
|
132
171
|
/**
|
|
133
172
|
* Uses props from `this.props` and state from `this.state` to render the
|
|
134
173
|
* structure of the component.
|
|
@@ -178,7 +217,7 @@ var ReactCompositeComponentInterface = {
|
|
|
178
217
|
* Use this as an opportunity to react to a prop transition by updating the
|
|
179
218
|
* state using `this.setState`. Current props are accessed via `this.props`.
|
|
180
219
|
*
|
|
181
|
-
* componentWillReceiveProps: function(nextProps) {
|
|
220
|
+
* componentWillReceiveProps: function(nextProps, nextContext) {
|
|
182
221
|
* this.setState({
|
|
183
222
|
* likesIncreasing: nextProps.likeCount > this.props.likeCount
|
|
184
223
|
* });
|
|
@@ -195,17 +234,21 @@ var ReactCompositeComponentInterface = {
|
|
|
195
234
|
|
|
196
235
|
/**
|
|
197
236
|
* Invoked while deciding if the component should be updated as a result of
|
|
198
|
-
* receiving new props and
|
|
237
|
+
* receiving new props, state and/or context.
|
|
199
238
|
*
|
|
200
239
|
* Use this as an opportunity to `return false` when you're certain that the
|
|
201
|
-
* transition to the new props
|
|
240
|
+
* transition to the new props/state/context will not require a component
|
|
241
|
+
* update.
|
|
202
242
|
*
|
|
203
|
-
* shouldComponentUpdate: function(nextProps, nextState) {
|
|
204
|
-
* return !equal(nextProps, this.props) ||
|
|
243
|
+
* shouldComponentUpdate: function(nextProps, nextState, nextContext) {
|
|
244
|
+
* return !equal(nextProps, this.props) ||
|
|
245
|
+
* !equal(nextState, this.state) ||
|
|
246
|
+
* !equal(nextContext, this.context);
|
|
205
247
|
* }
|
|
206
248
|
*
|
|
207
249
|
* @param {object} nextProps
|
|
208
250
|
* @param {?object} nextState
|
|
251
|
+
* @param {?object} nextContext
|
|
209
252
|
* @return {boolean} True if the component should update.
|
|
210
253
|
* @optional
|
|
211
254
|
*/
|
|
@@ -213,7 +256,8 @@ var ReactCompositeComponentInterface = {
|
|
|
213
256
|
|
|
214
257
|
/**
|
|
215
258
|
* Invoked when the component is about to update due to a transition from
|
|
216
|
-
* `this.props` and `this.
|
|
259
|
+
* `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
|
|
260
|
+
* and `nextContext`.
|
|
217
261
|
*
|
|
218
262
|
* Use this as an opportunity to perform preparation before an update occurs.
|
|
219
263
|
*
|
|
@@ -221,6 +265,7 @@ var ReactCompositeComponentInterface = {
|
|
|
221
265
|
*
|
|
222
266
|
* @param {object} nextProps
|
|
223
267
|
* @param {?object} nextState
|
|
268
|
+
* @param {?object} nextContext
|
|
224
269
|
* @param {ReactReconcileTransaction} transaction
|
|
225
270
|
* @optional
|
|
226
271
|
*/
|
|
@@ -234,6 +279,7 @@ var ReactCompositeComponentInterface = {
|
|
|
234
279
|
*
|
|
235
280
|
* @param {object} prevProps
|
|
236
281
|
* @param {?object} prevState
|
|
282
|
+
* @param {?object} prevContext
|
|
237
283
|
* @param {DOMElement} rootNode DOM element representing the component.
|
|
238
284
|
* @optional
|
|
239
285
|
*/
|
|
@@ -273,25 +319,73 @@ var ReactCompositeComponentInterface = {
|
|
|
273
319
|
/**
|
|
274
320
|
* Mapping from class specification keys to special processing functions.
|
|
275
321
|
*
|
|
276
|
-
* Although these are declared in the specification
|
|
277
|
-
* using `React.createClass`, they
|
|
322
|
+
* Although these are declared like instance properties in the specification
|
|
323
|
+
* when defining classes using `React.createClass`, they are actually static
|
|
324
|
+
* and are accessible on the constructor instead of the prototype. Despite
|
|
325
|
+
* being static, they must be defined outside of the "statics" key under
|
|
326
|
+
* which all other static methods are defined.
|
|
278
327
|
*/
|
|
279
328
|
var RESERVED_SPEC_KEYS = {
|
|
280
|
-
displayName: function(
|
|
281
|
-
|
|
329
|
+
displayName: function(ConvenienceConstructor, displayName) {
|
|
330
|
+
ConvenienceConstructor.componentConstructor.displayName = displayName;
|
|
282
331
|
},
|
|
283
|
-
mixins: function(
|
|
332
|
+
mixins: function(ConvenienceConstructor, mixins) {
|
|
284
333
|
if (mixins) {
|
|
285
334
|
for (var i = 0; i < mixins.length; i++) {
|
|
286
|
-
mixSpecIntoComponent(
|
|
335
|
+
mixSpecIntoComponent(ConvenienceConstructor, mixins[i]);
|
|
287
336
|
}
|
|
288
337
|
}
|
|
289
338
|
},
|
|
290
|
-
|
|
291
|
-
Constructor
|
|
339
|
+
childContextTypes: function(ConvenienceConstructor, childContextTypes) {
|
|
340
|
+
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
341
|
+
validateTypeDef(
|
|
342
|
+
Constructor,
|
|
343
|
+
childContextTypes,
|
|
344
|
+
ReactPropTypeLocations.childContext
|
|
345
|
+
);
|
|
346
|
+
Constructor.childContextTypes = merge(
|
|
347
|
+
Constructor.childContextTypes,
|
|
348
|
+
childContextTypes
|
|
349
|
+
);
|
|
350
|
+
},
|
|
351
|
+
contextTypes: function(ConvenienceConstructor, contextTypes) {
|
|
352
|
+
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
353
|
+
validateTypeDef(
|
|
354
|
+
Constructor,
|
|
355
|
+
contextTypes,
|
|
356
|
+
ReactPropTypeLocations.context
|
|
357
|
+
);
|
|
358
|
+
Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
|
|
359
|
+
},
|
|
360
|
+
propTypes: function(ConvenienceConstructor, propTypes) {
|
|
361
|
+
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
362
|
+
validateTypeDef(
|
|
363
|
+
Constructor,
|
|
364
|
+
propTypes,
|
|
365
|
+
ReactPropTypeLocations.prop
|
|
366
|
+
);
|
|
367
|
+
Constructor.propTypes = merge(Constructor.propTypes, propTypes);
|
|
368
|
+
},
|
|
369
|
+
statics: function(ConvenienceConstructor, statics) {
|
|
370
|
+
mixStaticSpecIntoComponent(ConvenienceConstructor, statics);
|
|
292
371
|
}
|
|
293
372
|
};
|
|
294
373
|
|
|
374
|
+
function validateTypeDef(Constructor, typeDef, location) {
|
|
375
|
+
for (var propName in typeDef) {
|
|
376
|
+
if (typeDef.hasOwnProperty(propName)) {
|
|
377
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
378
|
+
typeof typeDef[propName] == 'function',
|
|
379
|
+
'%s: %s type `%s` is invalid; it must be a function, usually from ' +
|
|
380
|
+
'React.PropTypes.',
|
|
381
|
+
Constructor.displayName || 'ReactCompositeComponent',
|
|
382
|
+
ReactPropTypeLocationNames[location],
|
|
383
|
+
propName
|
|
384
|
+
) : invariant(typeof typeDef[propName] == 'function'));
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
295
389
|
function validateMethodOverride(proto, name) {
|
|
296
390
|
var specPolicy = ReactCompositeComponentInterface[name];
|
|
297
391
|
|
|
@@ -320,7 +414,6 @@ function validateMethodOverride(proto, name) {
|
|
|
320
414
|
}
|
|
321
415
|
}
|
|
322
416
|
|
|
323
|
-
|
|
324
417
|
function validateLifeCycleOnReplaceState(instance) {
|
|
325
418
|
var compositeLifeCycleState = instance._compositeLifeCycleState;
|
|
326
419
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
@@ -344,17 +437,30 @@ function validateLifeCycleOnReplaceState(instance) {
|
|
|
344
437
|
* Custom version of `mixInto` which handles policy validation and reserved
|
|
345
438
|
* specification keys when building `ReactCompositeComponent` classses.
|
|
346
439
|
*/
|
|
347
|
-
function mixSpecIntoComponent(
|
|
440
|
+
function mixSpecIntoComponent(ConvenienceConstructor, spec) {
|
|
441
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
442
|
+
!isValidClass(spec),
|
|
443
|
+
'ReactCompositeComponent: You\'re attempting to ' +
|
|
444
|
+
'use a component class as a mixin. Instead, just use a regular object.'
|
|
445
|
+
) : invariant(!isValidClass(spec)));
|
|
446
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
447
|
+
!ReactComponent.isValidComponent(spec),
|
|
448
|
+
'ReactCompositeComponent: You\'re attempting to ' +
|
|
449
|
+
'use a component as a mixin. Instead, just use a regular object.'
|
|
450
|
+
) : invariant(!ReactComponent.isValidComponent(spec)));
|
|
451
|
+
|
|
452
|
+
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
348
453
|
var proto = Constructor.prototype;
|
|
349
454
|
for (var name in spec) {
|
|
350
455
|
var property = spec[name];
|
|
351
|
-
if (!spec.hasOwnProperty(name)
|
|
456
|
+
if (!spec.hasOwnProperty(name)) {
|
|
352
457
|
continue;
|
|
353
458
|
}
|
|
459
|
+
|
|
354
460
|
validateMethodOverride(proto, name);
|
|
355
461
|
|
|
356
462
|
if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
|
|
357
|
-
RESERVED_SPEC_KEYS[name](
|
|
463
|
+
RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property);
|
|
358
464
|
} else {
|
|
359
465
|
// Setup methods on prototype:
|
|
360
466
|
// The following member methods should not be automatically bound:
|
|
@@ -362,7 +468,7 @@ function mixSpecIntoComponent(Constructor, spec) {
|
|
|
362
468
|
// 2. Overridden methods (that were mixed in).
|
|
363
469
|
var isCompositeComponentMethod = name in ReactCompositeComponentInterface;
|
|
364
470
|
var isInherited = name in proto;
|
|
365
|
-
var markedDontBind = property.__reactDontBind;
|
|
471
|
+
var markedDontBind = property && property.__reactDontBind;
|
|
366
472
|
var isFunction = typeof property === 'function';
|
|
367
473
|
var shouldAutoBind =
|
|
368
474
|
isFunction &&
|
|
@@ -394,6 +500,37 @@ function mixSpecIntoComponent(Constructor, spec) {
|
|
|
394
500
|
}
|
|
395
501
|
}
|
|
396
502
|
|
|
503
|
+
function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
|
|
504
|
+
if (!statics) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
for (var name in statics) {
|
|
508
|
+
var property = statics[name];
|
|
509
|
+
if (!statics.hasOwnProperty(name)) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
var isInherited = name in ConvenienceConstructor;
|
|
514
|
+
var result = property;
|
|
515
|
+
if (isInherited) {
|
|
516
|
+
var existingProperty = ConvenienceConstructor[name];
|
|
517
|
+
var existingType = typeof existingProperty;
|
|
518
|
+
var propertyType = typeof property;
|
|
519
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
520
|
+
existingType === 'function' && propertyType === 'function',
|
|
521
|
+
'ReactCompositeComponent: You are attempting to define ' +
|
|
522
|
+
'`%s` on your component more than once, but that is only supported ' +
|
|
523
|
+
'for functions, which are chained together. This conflict may be ' +
|
|
524
|
+
'due to a mixin.',
|
|
525
|
+
name
|
|
526
|
+
) : invariant(existingType === 'function' && propertyType === 'function'));
|
|
527
|
+
result = createChainedFunction(existingProperty, property);
|
|
528
|
+
}
|
|
529
|
+
ConvenienceConstructor[name] = result;
|
|
530
|
+
ConvenienceConstructor.componentConstructor[name] = result;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
397
534
|
/**
|
|
398
535
|
* Merge two objects, but throw if both contain the same key.
|
|
399
536
|
*
|
|
@@ -429,10 +566,14 @@ function mergeObjectsWithNoDuplicateKeys(one, two) {
|
|
|
429
566
|
*/
|
|
430
567
|
function createMergedResultFunction(one, two) {
|
|
431
568
|
return function mergedResult() {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
569
|
+
var a = one.apply(this, arguments);
|
|
570
|
+
var b = two.apply(this, arguments);
|
|
571
|
+
if (a == null) {
|
|
572
|
+
return b;
|
|
573
|
+
} else if (b == null) {
|
|
574
|
+
return a;
|
|
575
|
+
}
|
|
576
|
+
return mergeObjectsWithNoDuplicateKeys(a, b);
|
|
436
577
|
};
|
|
437
578
|
}
|
|
438
579
|
|
|
@@ -451,6 +592,203 @@ function createChainedFunction(one, two) {
|
|
|
451
592
|
};
|
|
452
593
|
}
|
|
453
594
|
|
|
595
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
596
|
+
|
|
597
|
+
var unmountedPropertyWhitelist = {
|
|
598
|
+
constructor: true,
|
|
599
|
+
construct: true,
|
|
600
|
+
isOwnedBy: true, // should be deprecated but can have code mod (internal)
|
|
601
|
+
type: true,
|
|
602
|
+
props: true,
|
|
603
|
+
// currently private but belong on the descriptor and are valid for use
|
|
604
|
+
// inside the framework:
|
|
605
|
+
__keyValidated__: true,
|
|
606
|
+
_owner: true,
|
|
607
|
+
_currentContext: true
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
var componentInstanceProperties = {
|
|
611
|
+
__keyValidated__: true,
|
|
612
|
+
__keySetters: true,
|
|
613
|
+
_compositeLifeCycleState: true,
|
|
614
|
+
_currentContext: true,
|
|
615
|
+
_defaultProps: true,
|
|
616
|
+
_instance: true,
|
|
617
|
+
_lifeCycleState: true,
|
|
618
|
+
_mountDepth: true,
|
|
619
|
+
_owner: true,
|
|
620
|
+
_pendingCallbacks: true,
|
|
621
|
+
_pendingContext: true,
|
|
622
|
+
_pendingForceUpdate: true,
|
|
623
|
+
_pendingOwner: true,
|
|
624
|
+
_pendingProps: true,
|
|
625
|
+
_pendingState: true,
|
|
626
|
+
_renderedComponent: true,
|
|
627
|
+
_rootNodeID: true,
|
|
628
|
+
context: true,
|
|
629
|
+
props: true,
|
|
630
|
+
refs: true,
|
|
631
|
+
state: true,
|
|
632
|
+
|
|
633
|
+
// These are known instance properties coming from other sources
|
|
634
|
+
_pendingQueries: true,
|
|
635
|
+
_queryPropListeners: true,
|
|
636
|
+
queryParams: true
|
|
637
|
+
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
var hasWarnedOnComponentType = {};
|
|
641
|
+
|
|
642
|
+
var warningStackCounter = 0;
|
|
643
|
+
|
|
644
|
+
var issueMembraneWarning = function(instance, key) {
|
|
645
|
+
var isWhitelisted = unmountedPropertyWhitelist.hasOwnProperty(key);
|
|
646
|
+
if (warningStackCounter > 0 || isWhitelisted) {
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
var name = instance.constructor.displayName || 'Unknown';
|
|
650
|
+
var owner = ReactCurrentOwner.current;
|
|
651
|
+
var ownerName = (owner && owner.constructor.displayName) || 'Unknown';
|
|
652
|
+
var warningKey = key + '|' + name + '|' + ownerName;
|
|
653
|
+
if (hasWarnedOnComponentType.hasOwnProperty(warningKey)) {
|
|
654
|
+
// We have already warned for this combination. Skip it this time.
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
hasWarnedOnComponentType[warningKey] = true;
|
|
658
|
+
|
|
659
|
+
var context = owner ? ' in ' + ownerName + '.' : ' at the top level.';
|
|
660
|
+
var staticMethodExample = '<' + name + ' />.type.' + key + '(...)';
|
|
661
|
+
|
|
662
|
+
monitorCodeUse('react_descriptor_property_access', { component: name });
|
|
663
|
+
console.warn(
|
|
664
|
+
'Invalid access to component property "' + key + '" on ' + name +
|
|
665
|
+
context + ' See http://fb.me/react-warning-descriptors .' +
|
|
666
|
+
' Use a static method instead: ' + staticMethodExample
|
|
667
|
+
);
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
var wrapInMembraneFunction = function(fn, thisBinding) {
|
|
671
|
+
if (fn.__reactMembraneFunction && fn.__reactMembraneSelf === thisBinding) {
|
|
672
|
+
return fn.__reactMembraneFunction;
|
|
673
|
+
}
|
|
674
|
+
return fn.__reactMembraneFunction = function() {
|
|
675
|
+
/**
|
|
676
|
+
* By getting this function, you've already received a warning. The
|
|
677
|
+
* internals of this function will likely cause more warnings. To avoid
|
|
678
|
+
* Spamming too much we disable any warning triggered inside of this
|
|
679
|
+
* stack.
|
|
680
|
+
*/
|
|
681
|
+
warningStackCounter++;
|
|
682
|
+
try {
|
|
683
|
+
// If the this binding is unchanged, we defer to the real component.
|
|
684
|
+
// This is important to keep some referential integrity in the
|
|
685
|
+
// internals. E.g. owner equality check.
|
|
686
|
+
var self = this === thisBinding ? this.__realComponentInstance : this;
|
|
687
|
+
return fn.apply(self, arguments);
|
|
688
|
+
} finally {
|
|
689
|
+
warningStackCounter--;
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
};
|
|
693
|
+
|
|
694
|
+
var defineMembraneProperty = function(membrane, prototype, key) {
|
|
695
|
+
Object.defineProperty(membrane, key, {
|
|
696
|
+
|
|
697
|
+
configurable: false,
|
|
698
|
+
enumerable: true,
|
|
699
|
+
|
|
700
|
+
get: function() {
|
|
701
|
+
if (this === membrane) {
|
|
702
|
+
// We're allowed to access the prototype directly.
|
|
703
|
+
return prototype[key];
|
|
704
|
+
}
|
|
705
|
+
issueMembraneWarning(this, key);
|
|
706
|
+
|
|
707
|
+
var realValue = this.__realComponentInstance[key];
|
|
708
|
+
// If the real value is a function, we need to provide a wrapper that
|
|
709
|
+
// disables nested warnings. The properties type and constructors are
|
|
710
|
+
// expected to the be constructors and therefore is often use with an
|
|
711
|
+
// equality check and we shouldn't try to rebind those.
|
|
712
|
+
if (typeof realValue === 'function' &&
|
|
713
|
+
key !== 'type' &&
|
|
714
|
+
key !== 'constructor') {
|
|
715
|
+
return wrapInMembraneFunction(realValue, this);
|
|
716
|
+
}
|
|
717
|
+
return realValue;
|
|
718
|
+
},
|
|
719
|
+
|
|
720
|
+
set: function(value) {
|
|
721
|
+
if (this === membrane) {
|
|
722
|
+
// We're allowed to set a value on the prototype directly.
|
|
723
|
+
prototype[key] = value;
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
issueMembraneWarning(this, key);
|
|
727
|
+
this.__realComponentInstance[key] = value;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
});
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Creates a membrane prototype which wraps the original prototype. If any
|
|
735
|
+
* property is accessed in an unmounted state, a warning is issued.
|
|
736
|
+
*
|
|
737
|
+
* @param {object} prototype Original prototype.
|
|
738
|
+
* @return {object} The membrane prototype.
|
|
739
|
+
* @private
|
|
740
|
+
*/
|
|
741
|
+
var createMountWarningMembrane = function(prototype) {
|
|
742
|
+
var membrane = {};
|
|
743
|
+
var key;
|
|
744
|
+
for (key in prototype) {
|
|
745
|
+
defineMembraneProperty(membrane, prototype, key);
|
|
746
|
+
}
|
|
747
|
+
// These are properties that goes into the instance but not the prototype.
|
|
748
|
+
// We can create the membrane on the prototype even though this will
|
|
749
|
+
// result in a faulty hasOwnProperty check it's better perf.
|
|
750
|
+
for (key in componentInstanceProperties) {
|
|
751
|
+
if (componentInstanceProperties.hasOwnProperty(key) &&
|
|
752
|
+
!(key in prototype)) {
|
|
753
|
+
defineMembraneProperty(membrane, prototype, key);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return membrane;
|
|
757
|
+
};
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Creates a membrane constructor which wraps the component that gets mounted.
|
|
761
|
+
*
|
|
762
|
+
* @param {function} constructor Original constructor.
|
|
763
|
+
* @return {function} The membrane constructor.
|
|
764
|
+
* @private
|
|
765
|
+
*/
|
|
766
|
+
var createDescriptorProxy = function(constructor) {
|
|
767
|
+
try {
|
|
768
|
+
var ProxyConstructor = function() {
|
|
769
|
+
this.__realComponentInstance = new constructor();
|
|
770
|
+
|
|
771
|
+
// We can only safely pass through known instance variables. Unknown
|
|
772
|
+
// expandos are not safe. Use the real mounted instance to avoid this
|
|
773
|
+
// problem if it blows something up.
|
|
774
|
+
Object.freeze(this);
|
|
775
|
+
};
|
|
776
|
+
|
|
777
|
+
ProxyConstructor.prototype = createMountWarningMembrane(
|
|
778
|
+
constructor.prototype
|
|
779
|
+
);
|
|
780
|
+
|
|
781
|
+
return ProxyConstructor;
|
|
782
|
+
} catch(x) {
|
|
783
|
+
// In IE8 define property will fail on non-DOM objects. If anything in
|
|
784
|
+
// the membrane creation fails, we'll bail out and just use the plain
|
|
785
|
+
// constructor without warnings.
|
|
786
|
+
return constructor;
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
}
|
|
791
|
+
|
|
454
792
|
/**
|
|
455
793
|
* `ReactCompositeComponent` maintains an auxiliary life cycle state in
|
|
456
794
|
* `this._compositeLifeCycleState` (which can be null).
|
|
@@ -516,11 +854,34 @@ var ReactCompositeComponentMixin = {
|
|
|
516
854
|
construct: function(initialProps, children) {
|
|
517
855
|
// Children can be either an array or more than one argument
|
|
518
856
|
ReactComponent.Mixin.construct.apply(this, arguments);
|
|
857
|
+
ReactOwner.Mixin.construct.apply(this, arguments);
|
|
858
|
+
|
|
519
859
|
this.state = null;
|
|
520
860
|
this._pendingState = null;
|
|
861
|
+
|
|
862
|
+
this.context = null;
|
|
863
|
+
this._currentContext = ReactContext.current;
|
|
864
|
+
this._pendingContext = null;
|
|
865
|
+
|
|
866
|
+
// The descriptor that was used to instantiate this component. Will be
|
|
867
|
+
// set by the instantiator instead of the constructor since this
|
|
868
|
+
// constructor is currently used by both instances and descriptors.
|
|
869
|
+
this._descriptor = null;
|
|
870
|
+
|
|
521
871
|
this._compositeLifeCycleState = null;
|
|
522
872
|
},
|
|
523
873
|
|
|
874
|
+
/**
|
|
875
|
+
* Components in the intermediate state now has cyclic references. To avoid
|
|
876
|
+
* breaking JSON serialization we expose a custom JSON format.
|
|
877
|
+
* @return {object} JSON compatible representation.
|
|
878
|
+
* @internal
|
|
879
|
+
* @final
|
|
880
|
+
*/
|
|
881
|
+
toJSON: function() {
|
|
882
|
+
return { type: this.type, props: this.props };
|
|
883
|
+
},
|
|
884
|
+
|
|
524
885
|
/**
|
|
525
886
|
* Checks whether or not this composite component is mounted.
|
|
526
887
|
* @return {boolean} True if mounted, false otherwise.
|
|
@@ -536,7 +897,7 @@ var ReactCompositeComponentMixin = {
|
|
|
536
897
|
* Initializes the component, renders markup, and registers event listeners.
|
|
537
898
|
*
|
|
538
899
|
* @param {string} rootID DOM ID of the root node.
|
|
539
|
-
* @param {ReactReconcileTransaction} transaction
|
|
900
|
+
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
540
901
|
* @param {number} mountDepth number of components in the owner hierarchy
|
|
541
902
|
* @return {?string} Rendered markup to be inserted into the DOM.
|
|
542
903
|
* @final
|
|
@@ -554,14 +915,21 @@ var ReactCompositeComponentMixin = {
|
|
|
554
915
|
);
|
|
555
916
|
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
|
|
556
917
|
|
|
918
|
+
this.context = this._processContext(this._currentContext);
|
|
557
919
|
this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
|
|
558
|
-
this._processProps(this.props);
|
|
920
|
+
this.props = this._processProps(this.props);
|
|
559
921
|
|
|
560
922
|
if (this.__reactAutoBindMap) {
|
|
561
923
|
this._bindAutoBindMethods();
|
|
562
924
|
}
|
|
563
925
|
|
|
564
926
|
this.state = this.getInitialState ? this.getInitialState() : null;
|
|
927
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
928
|
+
typeof this.state === 'object' && !Array.isArray(this.state),
|
|
929
|
+
'%s.getInitialState(): must return an object or null',
|
|
930
|
+
this.constructor.displayName || 'ReactCompositeComponent'
|
|
931
|
+
) : invariant(typeof this.state === 'object' && !Array.isArray(this.state)));
|
|
932
|
+
|
|
565
933
|
this._pendingState = null;
|
|
566
934
|
this._pendingForceUpdate = false;
|
|
567
935
|
|
|
@@ -575,7 +943,9 @@ var ReactCompositeComponentMixin = {
|
|
|
575
943
|
}
|
|
576
944
|
}
|
|
577
945
|
|
|
578
|
-
this._renderedComponent =
|
|
946
|
+
this._renderedComponent = instantiateReactComponent(
|
|
947
|
+
this._renderValidatedComponent()
|
|
948
|
+
);
|
|
579
949
|
|
|
580
950
|
// Done with mounting, `setState` will now trigger UI changes.
|
|
581
951
|
this._compositeLifeCycleState = null;
|
|
@@ -606,13 +976,10 @@ var ReactCompositeComponentMixin = {
|
|
|
606
976
|
|
|
607
977
|
this._defaultProps = null;
|
|
608
978
|
|
|
609
|
-
ReactComponent.Mixin.unmountComponent.call(this);
|
|
610
979
|
this._renderedComponent.unmountComponent();
|
|
611
980
|
this._renderedComponent = null;
|
|
612
981
|
|
|
613
|
-
|
|
614
|
-
this.refs = null;
|
|
615
|
-
}
|
|
982
|
+
ReactComponent.Mixin.unmountComponent.call(this);
|
|
616
983
|
|
|
617
984
|
// Some existing components rely on this.props even after they've been
|
|
618
985
|
// destroyed (in event handlers).
|
|
@@ -638,6 +1005,17 @@ var ReactCompositeComponentMixin = {
|
|
|
638
1005
|
* @protected
|
|
639
1006
|
*/
|
|
640
1007
|
setState: function(partialState, callback) {
|
|
1008
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
1009
|
+
typeof partialState === 'object' || partialState == null,
|
|
1010
|
+
'setState(...): takes an object of state variables to update.'
|
|
1011
|
+
) : invariant(typeof partialState === 'object' || partialState == null));
|
|
1012
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1013
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
1014
|
+
partialState != null,
|
|
1015
|
+
'setState(...): You passed an undefined or null state object; ' +
|
|
1016
|
+
'instead, use forceUpdate().'
|
|
1017
|
+
) : null);
|
|
1018
|
+
}
|
|
641
1019
|
// Merge with `_pendingState` if it exists, otherwise with existing state.
|
|
642
1020
|
this.replaceState(
|
|
643
1021
|
merge(this._pendingState || this.state, partialState),
|
|
@@ -663,29 +1041,107 @@ var ReactCompositeComponentMixin = {
|
|
|
663
1041
|
ReactUpdates.enqueueUpdate(this, callback);
|
|
664
1042
|
},
|
|
665
1043
|
|
|
1044
|
+
/**
|
|
1045
|
+
* Filters the context object to only contain keys specified in
|
|
1046
|
+
* `contextTypes`, and asserts that they are valid.
|
|
1047
|
+
*
|
|
1048
|
+
* @param {object} context
|
|
1049
|
+
* @return {?object}
|
|
1050
|
+
* @private
|
|
1051
|
+
*/
|
|
1052
|
+
_processContext: function(context) {
|
|
1053
|
+
var maskedContext = null;
|
|
1054
|
+
var contextTypes = this.constructor.contextTypes;
|
|
1055
|
+
if (contextTypes) {
|
|
1056
|
+
maskedContext = {};
|
|
1057
|
+
for (var contextName in contextTypes) {
|
|
1058
|
+
maskedContext[contextName] = context[contextName];
|
|
1059
|
+
}
|
|
1060
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1061
|
+
this._checkPropTypes(
|
|
1062
|
+
contextTypes,
|
|
1063
|
+
maskedContext,
|
|
1064
|
+
ReactPropTypeLocations.context
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
return maskedContext;
|
|
1069
|
+
},
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* @param {object} currentContext
|
|
1073
|
+
* @return {object}
|
|
1074
|
+
* @private
|
|
1075
|
+
*/
|
|
1076
|
+
_processChildContext: function(currentContext) {
|
|
1077
|
+
var childContext = this.getChildContext && this.getChildContext();
|
|
1078
|
+
var displayName = this.constructor.displayName || 'ReactCompositeComponent';
|
|
1079
|
+
if (childContext) {
|
|
1080
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
1081
|
+
typeof this.constructor.childContextTypes === 'object',
|
|
1082
|
+
'%s.getChildContext(): childContextTypes must be defined in order to ' +
|
|
1083
|
+
'use getChildContext().',
|
|
1084
|
+
displayName
|
|
1085
|
+
) : invariant(typeof this.constructor.childContextTypes === 'object'));
|
|
1086
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1087
|
+
this._checkPropTypes(
|
|
1088
|
+
this.constructor.childContextTypes,
|
|
1089
|
+
childContext,
|
|
1090
|
+
ReactPropTypeLocations.childContext
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
for (var name in childContext) {
|
|
1094
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
1095
|
+
name in this.constructor.childContextTypes,
|
|
1096
|
+
'%s.getChildContext(): key "%s" is not defined in childContextTypes.',
|
|
1097
|
+
displayName,
|
|
1098
|
+
name
|
|
1099
|
+
) : invariant(name in this.constructor.childContextTypes));
|
|
1100
|
+
}
|
|
1101
|
+
return merge(currentContext, childContext);
|
|
1102
|
+
}
|
|
1103
|
+
return currentContext;
|
|
1104
|
+
},
|
|
1105
|
+
|
|
666
1106
|
/**
|
|
667
1107
|
* Processes props by setting default values for unspecified props and
|
|
668
|
-
* asserting that the props are valid.
|
|
1108
|
+
* asserting that the props are valid. Does not mutate its argument; returns
|
|
1109
|
+
* a new props object with defaults merged in.
|
|
669
1110
|
*
|
|
670
|
-
* @param {object}
|
|
1111
|
+
* @param {object} newProps
|
|
1112
|
+
* @return {object}
|
|
671
1113
|
* @private
|
|
672
1114
|
*/
|
|
673
|
-
_processProps: function(
|
|
674
|
-
var
|
|
1115
|
+
_processProps: function(newProps) {
|
|
1116
|
+
var props = merge(newProps);
|
|
675
1117
|
var defaultProps = this._defaultProps;
|
|
676
|
-
for (propName in defaultProps) {
|
|
677
|
-
if (
|
|
1118
|
+
for (var propName in defaultProps) {
|
|
1119
|
+
if (typeof props[propName] === 'undefined') {
|
|
678
1120
|
props[propName] = defaultProps[propName];
|
|
679
1121
|
}
|
|
680
1122
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
1123
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1124
|
+
var propTypes = this.constructor.propTypes;
|
|
1125
|
+
if (propTypes) {
|
|
1126
|
+
this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
return props;
|
|
1130
|
+
},
|
|
1131
|
+
|
|
1132
|
+
/**
|
|
1133
|
+
* Assert that the props are valid
|
|
1134
|
+
*
|
|
1135
|
+
* @param {object} propTypes Map of prop name to a ReactPropType
|
|
1136
|
+
* @param {object} props
|
|
1137
|
+
* @param {string} location e.g. "prop", "context", "child context"
|
|
1138
|
+
* @private
|
|
1139
|
+
*/
|
|
1140
|
+
_checkPropTypes: function(propTypes, props, location) {
|
|
1141
|
+
var componentName = this.constructor.displayName;
|
|
1142
|
+
for (var propName in propTypes) {
|
|
1143
|
+
if (propTypes.hasOwnProperty(propName)) {
|
|
1144
|
+
propTypes[propName](props, propName, componentName, location);
|
|
689
1145
|
}
|
|
690
1146
|
}
|
|
691
1147
|
},
|
|
@@ -711,41 +1167,63 @@ var ReactCompositeComponentMixin = {
|
|
|
711
1167
|
_performUpdateIfNecessary: function(transaction) {
|
|
712
1168
|
if (this._pendingProps == null &&
|
|
713
1169
|
this._pendingState == null &&
|
|
1170
|
+
this._pendingContext == null &&
|
|
714
1171
|
!this._pendingForceUpdate) {
|
|
715
1172
|
return;
|
|
716
1173
|
}
|
|
717
1174
|
|
|
1175
|
+
var nextFullContext = this._pendingContext || this._currentContext;
|
|
1176
|
+
var nextContext = this._processContext(nextFullContext);
|
|
1177
|
+
this._pendingContext = null;
|
|
1178
|
+
|
|
718
1179
|
var nextProps = this.props;
|
|
719
1180
|
if (this._pendingProps != null) {
|
|
720
|
-
nextProps = this._pendingProps;
|
|
721
|
-
this._processProps(nextProps);
|
|
1181
|
+
nextProps = this._processProps(this._pendingProps);
|
|
722
1182
|
this._pendingProps = null;
|
|
723
1183
|
|
|
724
1184
|
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
|
|
725
1185
|
if (this.componentWillReceiveProps) {
|
|
726
|
-
this.componentWillReceiveProps(nextProps,
|
|
1186
|
+
this.componentWillReceiveProps(nextProps, nextContext);
|
|
727
1187
|
}
|
|
728
1188
|
}
|
|
729
1189
|
|
|
730
1190
|
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
|
|
731
1191
|
|
|
1192
|
+
// Unlike props, state, and context, we specifically don't want to set
|
|
1193
|
+
// _pendingOwner to null here because it's possible for a component to have
|
|
1194
|
+
// a null owner, so we instead make `this._owner === this._pendingOwner`
|
|
1195
|
+
// mean that there's no owner change pending.
|
|
1196
|
+
var nextOwner = this._pendingOwner;
|
|
1197
|
+
|
|
732
1198
|
var nextState = this._pendingState || this.state;
|
|
733
1199
|
this._pendingState = null;
|
|
734
1200
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1201
|
+
try {
|
|
1202
|
+
if (this._pendingForceUpdate ||
|
|
1203
|
+
!this.shouldComponentUpdate ||
|
|
1204
|
+
this.shouldComponentUpdate(nextProps, nextState, nextContext)) {
|
|
1205
|
+
this._pendingForceUpdate = false;
|
|
1206
|
+
// Will set `this.props`, `this.state` and `this.context`.
|
|
1207
|
+
this._performComponentUpdate(
|
|
1208
|
+
nextProps,
|
|
1209
|
+
nextOwner,
|
|
1210
|
+
nextState,
|
|
1211
|
+
nextFullContext,
|
|
1212
|
+
nextContext,
|
|
1213
|
+
transaction
|
|
1214
|
+
);
|
|
1215
|
+
} else {
|
|
1216
|
+
// If it's determined that a component should not update, we still want
|
|
1217
|
+
// to set props and state.
|
|
1218
|
+
this.props = nextProps;
|
|
1219
|
+
this._owner = nextOwner;
|
|
1220
|
+
this.state = nextState;
|
|
1221
|
+
this._currentContext = nextFullContext;
|
|
1222
|
+
this.context = nextContext;
|
|
1223
|
+
}
|
|
1224
|
+
} finally {
|
|
1225
|
+
this._compositeLifeCycleState = null;
|
|
746
1226
|
}
|
|
747
|
-
|
|
748
|
-
this._compositeLifeCycleState = null;
|
|
749
1227
|
},
|
|
750
1228
|
|
|
751
1229
|
/**
|
|
@@ -753,31 +1231,71 @@ var ReactCompositeComponentMixin = {
|
|
|
753
1231
|
* performs update.
|
|
754
1232
|
*
|
|
755
1233
|
* @param {object} nextProps Next object to set as properties.
|
|
1234
|
+
* @param {?ReactComponent} nextOwner Next component to set as owner
|
|
756
1235
|
* @param {?object} nextState Next object to set as state.
|
|
1236
|
+
* @param {?object} nextFullContext Next object to set as _currentContext.
|
|
1237
|
+
* @param {?object} nextContext Next object to set as context.
|
|
757
1238
|
* @param {ReactReconcileTransaction} transaction
|
|
758
1239
|
* @private
|
|
759
1240
|
*/
|
|
760
|
-
_performComponentUpdate: function(
|
|
1241
|
+
_performComponentUpdate: function(
|
|
1242
|
+
nextProps,
|
|
1243
|
+
nextOwner,
|
|
1244
|
+
nextState,
|
|
1245
|
+
nextFullContext,
|
|
1246
|
+
nextContext,
|
|
1247
|
+
transaction
|
|
1248
|
+
) {
|
|
761
1249
|
var prevProps = this.props;
|
|
1250
|
+
var prevOwner = this._owner;
|
|
762
1251
|
var prevState = this.state;
|
|
1252
|
+
var prevContext = this.context;
|
|
763
1253
|
|
|
764
1254
|
if (this.componentWillUpdate) {
|
|
765
|
-
this.componentWillUpdate(nextProps, nextState,
|
|
1255
|
+
this.componentWillUpdate(nextProps, nextState, nextContext);
|
|
766
1256
|
}
|
|
767
1257
|
|
|
768
1258
|
this.props = nextProps;
|
|
1259
|
+
this._owner = nextOwner;
|
|
769
1260
|
this.state = nextState;
|
|
770
|
-
|
|
771
|
-
this.
|
|
1261
|
+
this._currentContext = nextFullContext;
|
|
1262
|
+
this.context = nextContext;
|
|
1263
|
+
|
|
1264
|
+
this.updateComponent(
|
|
1265
|
+
transaction,
|
|
1266
|
+
prevProps,
|
|
1267
|
+
prevOwner,
|
|
1268
|
+
prevState,
|
|
1269
|
+
prevContext
|
|
1270
|
+
);
|
|
772
1271
|
|
|
773
1272
|
if (this.componentDidUpdate) {
|
|
774
1273
|
transaction.getReactMountReady().enqueue(
|
|
775
1274
|
this,
|
|
776
|
-
this.componentDidUpdate.bind(this, prevProps, prevState)
|
|
1275
|
+
this.componentDidUpdate.bind(this, prevProps, prevState, prevContext)
|
|
777
1276
|
);
|
|
778
1277
|
}
|
|
779
1278
|
},
|
|
780
1279
|
|
|
1280
|
+
receiveComponent: function(nextComponent, transaction) {
|
|
1281
|
+
if (nextComponent === this._descriptor) {
|
|
1282
|
+
// Since props and context are immutable after the component is
|
|
1283
|
+
// mounted, we can do a cheap identity compare here to determine
|
|
1284
|
+
// if this is a superfluous reconcile.
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
// Update the descriptor that was last used by this component instance
|
|
1289
|
+
this._descriptor = nextComponent;
|
|
1290
|
+
|
|
1291
|
+
this._pendingContext = nextComponent._currentContext;
|
|
1292
|
+
ReactComponent.Mixin.receiveComponent.call(
|
|
1293
|
+
this,
|
|
1294
|
+
nextComponent,
|
|
1295
|
+
transaction
|
|
1296
|
+
);
|
|
1297
|
+
},
|
|
1298
|
+
|
|
781
1299
|
/**
|
|
782
1300
|
* Updates the component's currently mounted DOM representation.
|
|
783
1301
|
*
|
|
@@ -786,32 +1304,41 @@ var ReactCompositeComponentMixin = {
|
|
|
786
1304
|
*
|
|
787
1305
|
* @param {ReactReconcileTransaction} transaction
|
|
788
1306
|
* @param {object} prevProps
|
|
1307
|
+
* @param {?ReactComponent} prevOwner
|
|
789
1308
|
* @param {?object} prevState
|
|
1309
|
+
* @param {?object} prevContext
|
|
790
1310
|
* @internal
|
|
791
1311
|
* @overridable
|
|
792
1312
|
*/
|
|
793
1313
|
updateComponent: ReactPerf.measure(
|
|
794
1314
|
'ReactCompositeComponent',
|
|
795
1315
|
'updateComponent',
|
|
796
|
-
function(transaction, prevProps, prevState) {
|
|
797
|
-
ReactComponent.Mixin.updateComponent.call(
|
|
798
|
-
|
|
1316
|
+
function(transaction, prevProps, prevOwner, prevState, prevContext) {
|
|
1317
|
+
ReactComponent.Mixin.updateComponent.call(
|
|
1318
|
+
this,
|
|
1319
|
+
transaction,
|
|
1320
|
+
prevProps,
|
|
1321
|
+
prevOwner
|
|
1322
|
+
);
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
var prevComponentInstance = this._renderedComponent;
|
|
799
1326
|
var nextComponent = this._renderValidatedComponent();
|
|
800
|
-
if (
|
|
801
|
-
|
|
1327
|
+
if (shouldUpdateReactComponent(prevComponentInstance, nextComponent)) {
|
|
1328
|
+
prevComponentInstance.receiveComponent(nextComponent, transaction);
|
|
802
1329
|
} else {
|
|
803
1330
|
// These two IDs are actually the same! But nothing should rely on that.
|
|
804
1331
|
var thisID = this._rootNodeID;
|
|
805
|
-
var
|
|
806
|
-
|
|
807
|
-
this._renderedComponent = nextComponent;
|
|
808
|
-
var nextMarkup =
|
|
1332
|
+
var prevComponentID = prevComponentInstance._rootNodeID;
|
|
1333
|
+
prevComponentInstance.unmountComponent();
|
|
1334
|
+
this._renderedComponent = instantiateReactComponent(nextComponent);
|
|
1335
|
+
var nextMarkup = this._renderedComponent.mountComponent(
|
|
809
1336
|
thisID,
|
|
810
1337
|
transaction,
|
|
811
1338
|
this._mountDepth + 1
|
|
812
1339
|
);
|
|
813
|
-
ReactComponent.
|
|
814
|
-
|
|
1340
|
+
ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
|
|
1341
|
+
prevComponentID,
|
|
815
1342
|
nextMarkup
|
|
816
1343
|
);
|
|
817
1344
|
}
|
|
@@ -855,25 +1382,29 @@ var ReactCompositeComponentMixin = {
|
|
|
855
1382
|
/**
|
|
856
1383
|
* @private
|
|
857
1384
|
*/
|
|
858
|
-
_renderValidatedComponent:
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
renderedComponent
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
1385
|
+
_renderValidatedComponent: ReactPerf.measure(
|
|
1386
|
+
'ReactCompositeComponent',
|
|
1387
|
+
'_renderValidatedComponent',
|
|
1388
|
+
function() {
|
|
1389
|
+
var renderedComponent;
|
|
1390
|
+
var previousContext = ReactContext.current;
|
|
1391
|
+
ReactContext.current = this._processChildContext(this._currentContext);
|
|
1392
|
+
ReactCurrentOwner.current = this;
|
|
1393
|
+
try {
|
|
1394
|
+
renderedComponent = this.render();
|
|
1395
|
+
} finally {
|
|
1396
|
+
ReactContext.current = previousContext;
|
|
1397
|
+
ReactCurrentOwner.current = null;
|
|
1398
|
+
}
|
|
1399
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
1400
|
+
ReactComponent.isValidComponent(renderedComponent),
|
|
1401
|
+
'%s.render(): A valid ReactComponent must be returned. You may have ' +
|
|
1402
|
+
'returned null, undefined, an array, or some other invalid object.',
|
|
1403
|
+
this.constructor.displayName || 'ReactCompositeComponent'
|
|
1404
|
+
) : invariant(ReactComponent.isValidComponent(renderedComponent)));
|
|
1405
|
+
return renderedComponent;
|
|
868
1406
|
}
|
|
869
|
-
|
|
870
|
-
ReactComponent.isValidComponent(renderedComponent),
|
|
871
|
-
'%s.render(): A valid ReactComponent must be returned. You may have ' +
|
|
872
|
-
'returned null, undefined, an array, or some other invalid object.',
|
|
873
|
-
this.constructor.displayName || 'ReactCompositeComponent'
|
|
874
|
-
) : invariant(ReactComponent.isValidComponent(renderedComponent)));
|
|
875
|
-
return renderedComponent;
|
|
876
|
-
},
|
|
1407
|
+
),
|
|
877
1408
|
|
|
878
1409
|
/**
|
|
879
1410
|
* @private
|
|
@@ -908,16 +1439,18 @@ var ReactCompositeComponentMixin = {
|
|
|
908
1439
|
boundMethod.__reactBoundArguments = null;
|
|
909
1440
|
var componentName = component.constructor.displayName;
|
|
910
1441
|
var _bind = boundMethod.bind;
|
|
911
|
-
boundMethod.bind = function(newThis) {
|
|
1442
|
+
boundMethod.bind = function(newThis ) {var args=Array.prototype.slice.call(arguments,1);
|
|
912
1443
|
// User is trying to bind() an autobound method; we effectively will
|
|
913
1444
|
// ignore the value of "this" that the user is trying to use, so
|
|
914
1445
|
// let's warn.
|
|
915
1446
|
if (newThis !== component && newThis !== null) {
|
|
1447
|
+
monitorCodeUse('react_bind_warning', { component: componentName });
|
|
916
1448
|
console.warn(
|
|
917
1449
|
'bind(): React component methods may only be bound to the ' +
|
|
918
1450
|
'component instance. See ' + componentName
|
|
919
1451
|
);
|
|
920
|
-
} else if (
|
|
1452
|
+
} else if (!args.length) {
|
|
1453
|
+
monitorCodeUse('react_bind_warning', { component: componentName });
|
|
921
1454
|
console.warn(
|
|
922
1455
|
'bind(): You are binding a component method to the component. ' +
|
|
923
1456
|
'React does this for you automatically in a high-performance ' +
|
|
@@ -928,8 +1461,7 @@ var ReactCompositeComponentMixin = {
|
|
|
928
1461
|
var reboundMethod = _bind.apply(boundMethod, arguments);
|
|
929
1462
|
reboundMethod.__reactBoundContext = component;
|
|
930
1463
|
reboundMethod.__reactBoundMethod = method;
|
|
931
|
-
reboundMethod.__reactBoundArguments =
|
|
932
|
-
Array.prototype.slice.call(arguments, 1);
|
|
1464
|
+
reboundMethod.__reactBoundArguments = args;
|
|
933
1465
|
return reboundMethod;
|
|
934
1466
|
};
|
|
935
1467
|
}
|
|
@@ -943,6 +1475,18 @@ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
|
|
|
943
1475
|
mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
|
|
944
1476
|
mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
|
|
945
1477
|
|
|
1478
|
+
/**
|
|
1479
|
+
* Checks if a value is a valid component constructor.
|
|
1480
|
+
*
|
|
1481
|
+
* @param {*}
|
|
1482
|
+
* @return {boolean}
|
|
1483
|
+
* @public
|
|
1484
|
+
*/
|
|
1485
|
+
function isValidClass(componentClass) {
|
|
1486
|
+
return componentClass instanceof Function &&
|
|
1487
|
+
'componentConstructor' in componentClass &&
|
|
1488
|
+
componentClass.componentConstructor instanceof Function;
|
|
1489
|
+
}
|
|
946
1490
|
/**
|
|
947
1491
|
* Module for creating composite components.
|
|
948
1492
|
*
|
|
@@ -968,7 +1512,23 @@ var ReactCompositeComponent = {
|
|
|
968
1512
|
var Constructor = function() {};
|
|
969
1513
|
Constructor.prototype = new ReactCompositeComponentBase();
|
|
970
1514
|
Constructor.prototype.constructor = Constructor;
|
|
971
|
-
|
|
1515
|
+
|
|
1516
|
+
var DescriptorConstructor = Constructor;
|
|
1517
|
+
|
|
1518
|
+
var ConvenienceConstructor = function(props, children) {
|
|
1519
|
+
var descriptor = new DescriptorConstructor();
|
|
1520
|
+
descriptor.construct.apply(descriptor, arguments);
|
|
1521
|
+
return descriptor;
|
|
1522
|
+
};
|
|
1523
|
+
ConvenienceConstructor.componentConstructor = Constructor;
|
|
1524
|
+
Constructor.ConvenienceConstructor = ConvenienceConstructor;
|
|
1525
|
+
ConvenienceConstructor.originalSpec = spec;
|
|
1526
|
+
|
|
1527
|
+
injectedMixins.forEach(
|
|
1528
|
+
mixSpecIntoComponent.bind(null, ConvenienceConstructor)
|
|
1529
|
+
);
|
|
1530
|
+
|
|
1531
|
+
mixSpecIntoComponent(ConvenienceConstructor, spec);
|
|
972
1532
|
|
|
973
1533
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
974
1534
|
Constructor.prototype.render,
|
|
@@ -977,6 +1537,10 @@ var ReactCompositeComponent = {
|
|
|
977
1537
|
|
|
978
1538
|
if ("production" !== process.env.NODE_ENV) {
|
|
979
1539
|
if (Constructor.prototype.componentShouldUpdate) {
|
|
1540
|
+
monitorCodeUse(
|
|
1541
|
+
'react_component_should_update_warning',
|
|
1542
|
+
{ component: spec.displayName }
|
|
1543
|
+
);
|
|
980
1544
|
console.warn(
|
|
981
1545
|
(spec.displayName || 'A component') + ' has a method called ' +
|
|
982
1546
|
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
|
|
@@ -986,6 +1550,14 @@ var ReactCompositeComponent = {
|
|
|
986
1550
|
}
|
|
987
1551
|
}
|
|
988
1552
|
|
|
1553
|
+
// Expose the convience constructor on the prototype so that it can be
|
|
1554
|
+
// easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for
|
|
1555
|
+
// static methods like <Foo />.type.staticMethod();
|
|
1556
|
+
// This should not be named constructor since this may not be the function
|
|
1557
|
+
// that created the descriptor, and it may not even be a constructor.
|
|
1558
|
+
ConvenienceConstructor.type = Constructor;
|
|
1559
|
+
Constructor.prototype.type = Constructor;
|
|
1560
|
+
|
|
989
1561
|
// Reduce time spent doing lookups by setting these on the prototype.
|
|
990
1562
|
for (var methodName in ReactCompositeComponentInterface) {
|
|
991
1563
|
if (!Constructor.prototype[methodName]) {
|
|
@@ -993,27 +1565,22 @@ var ReactCompositeComponent = {
|
|
|
993
1565
|
}
|
|
994
1566
|
}
|
|
995
1567
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
instance
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1568
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1569
|
+
// In DEV the convenience constructor generates a proxy to another
|
|
1570
|
+
// instance around it to warn about access to properties on the
|
|
1571
|
+
// descriptor.
|
|
1572
|
+
DescriptorConstructor = createDescriptorProxy(Constructor);
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1003
1575
|
return ConvenienceConstructor;
|
|
1004
1576
|
},
|
|
1005
1577
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
*/
|
|
1013
|
-
isValidClass: function(componentClass) {
|
|
1014
|
-
return componentClass instanceof Function &&
|
|
1015
|
-
'componentConstructor' in componentClass &&
|
|
1016
|
-
componentClass.componentConstructor instanceof Function;
|
|
1578
|
+
isValidClass: isValidClass,
|
|
1579
|
+
|
|
1580
|
+
injection: {
|
|
1581
|
+
injectMixin: function(mixin) {
|
|
1582
|
+
injectedMixins.push(mixin);
|
|
1583
|
+
}
|
|
1017
1584
|
}
|
|
1018
1585
|
};
|
|
1019
1586
|
|