react 0.8.0 → 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 +0 -8
- package/addons.js +0 -3
- package/lib/AutoFocusMixin.js +30 -0
- package/lib/CSSCore.js +22 -21
- package/lib/CSSProperty.js +31 -0
- package/lib/ChangeEventPlugin.js +26 -4
- package/lib/ClientReactRootIndex.js +30 -0
- package/lib/CompositionEventPlugin.js +57 -9
- package/lib/DOMChildrenOperations.js +32 -2
- package/lib/DOMProperty.js +2 -0
- package/lib/DOMPropertyOperations.js +14 -1
- package/lib/Danger.js +8 -7
- package/lib/DefaultDOMPropertyConfig.js +12 -2
- package/lib/EnterLeaveEventPlugin.js +37 -4
- package/lib/EventConstants.js +3 -0
- package/lib/EventListener.js +42 -34
- package/lib/EventPluginHub.js +113 -12
- package/lib/EventPluginRegistry.js +39 -16
- package/lib/EventPluginUtils.js +32 -3
- package/lib/EventPropagators.js +6 -42
- package/lib/ExecutionEnvironment.js +3 -0
- package/lib/LinkedValueUtils.js +161 -0
- package/lib/PooledClass.js +6 -0
- package/lib/React.js +27 -3
- package/lib/ReactCSSTransitionGroup.js +65 -0
- package/lib/{ReactTransitionableChild.js → ReactCSSTransitionGroupChild.js} +21 -35
- package/lib/ReactComponent.js +87 -52
- package/lib/ReactComponentBrowserEnvironment.js +67 -49
- package/lib/ReactComponentEnvironment.js +2 -0
- package/lib/ReactCompositeComponent.js +547 -112
- package/lib/ReactContext.js +67 -0
- package/lib/ReactDOM.js +13 -0
- package/lib/ReactDOMButton.js +4 -0
- package/lib/ReactDOMComponent.js +46 -21
- package/lib/ReactDOMForm.js +9 -2
- package/lib/ReactDOMIDOperations.js +105 -60
- package/lib/ReactDOMImg.js +58 -0
- package/lib/ReactDOMInput.js +26 -14
- package/lib/ReactDOMOption.js +1 -0
- package/lib/ReactDOMSelect.js +36 -17
- package/lib/ReactDOMTextarea.js +12 -8
- package/lib/ReactDefaultInjection.js +50 -26
- package/lib/ReactDefaultPerf.js +207 -370
- package/lib/ReactDefaultPerfAnalysis.js +199 -0
- package/lib/ReactErrorUtils.js +5 -14
- package/lib/ReactEventEmitter.js +141 -145
- package/lib/ReactEventEmitterMixin.js +0 -32
- package/lib/ReactEventTopLevelCallback.js +32 -12
- package/lib/ReactInjection.js +39 -0
- package/lib/ReactInstanceHandles.js +35 -19
- package/lib/ReactLink.js +1 -1
- package/lib/ReactMount.js +127 -103
- package/lib/ReactMountReady.js +1 -1
- package/lib/ReactMultiChild.js +30 -46
- package/lib/ReactMultiChildUpdateTypes.js +2 -0
- package/lib/ReactOwner.js +10 -2
- package/lib/ReactPerf.js +5 -8
- package/lib/ReactPropTransferer.js +40 -21
- package/lib/ReactPropTypeLocationNames.js +31 -0
- package/lib/ReactPropTypeLocations.js +29 -0
- package/lib/ReactPropTypes.js +248 -47
- package/lib/ReactPutListenerQueue.js +61 -0
- package/lib/ReactReconcileTransaction.js +20 -0
- package/lib/ReactRootIndex.js +36 -0
- package/lib/ReactServerRendering.js +8 -11
- package/lib/ReactTextComponent.js +8 -3
- package/lib/{ReactTransitionKeySet.js → ReactTransitionChildMapping.js} +42 -47
- package/lib/ReactTransitionGroup.js +132 -57
- package/lib/ReactUpdates.js +14 -11
- package/lib/ReactWithAddons.js +7 -2
- package/lib/SelectEventPlugin.js +22 -39
- package/lib/ServerReactRootIndex.js +36 -0
- package/lib/SimpleEventPlugin.js +54 -6
- package/lib/SyntheticClipboardEvent.js +7 -1
- package/lib/SyntheticDragEvent.js +44 -0
- package/lib/SyntheticEvent.js +2 -1
- package/lib/SyntheticKeyboardEvent.js +4 -2
- package/lib/SyntheticWheelEvent.js +10 -7
- package/lib/Transaction.js +61 -36
- package/lib/cloneWithProps.js +59 -0
- package/lib/createArrayFrom.js +10 -13
- package/lib/createFullPageComponent.js +63 -0
- package/lib/cx.js +2 -2
- package/lib/flattenChildren.js +5 -2
- package/lib/getActiveElement.js +4 -3
- package/lib/getEventKey.js +85 -0
- package/lib/getMarkupWrap.js +10 -0
- package/lib/getTextContentAccessor.js +5 -3
- package/lib/getUnboundedScrollPosition.js +2 -2
- package/lib/invariant.js +12 -4
- package/lib/isEventSupported.js +7 -11
- package/lib/mergeHelpers.js +5 -6
- package/lib/onlyChild.js +43 -0
- package/lib/shouldUpdateReactComponent.js +58 -0
- package/lib/toArray.js +75 -0
- package/lib/traverseAllChildren.js +69 -7
- package/lib/warning.js +40 -0
- package/package.json +2 -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
|
@@ -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;
|
|
@@ -61,7 +61,7 @@ var ReactComponentBrowserEnvironment = {
|
|
|
61
61
|
|
|
62
62
|
ReactReconcileTransaction: ReactReconcileTransaction,
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
BackendIDOperations: ReactDOMIDOperations,
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* If a particular environment requires that some resources be cleaned up,
|
|
@@ -80,61 +80,79 @@ var ReactComponentBrowserEnvironment = {
|
|
|
80
80
|
* @param {boolean} shouldReuseMarkup Should reuse the existing markup in the
|
|
81
81
|
* container if possible.
|
|
82
82
|
*/
|
|
83
|
-
mountImageIntoNode:
|
|
84
|
-
|
|
85
|
-
|
|
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 && (
|
|
86
94
|
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
|
-
|
|
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
|
+
}
|
|
110
128
|
}
|
|
111
129
|
}
|
|
112
|
-
}
|
|
113
130
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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));
|
|
121
138
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
+
}
|
|
131
151
|
} else {
|
|
132
|
-
|
|
152
|
+
container.innerHTML = markup;
|
|
133
153
|
}
|
|
134
|
-
} else {
|
|
135
|
-
container.innerHTML = markup;
|
|
136
154
|
}
|
|
137
|
-
|
|
155
|
+
)
|
|
138
156
|
};
|
|
139
157
|
|
|
140
158
|
module.exports = ReactComponentBrowserEnvironment;
|
|
@@ -19,11 +19,14 @@
|
|
|
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
|
|
|
29
32
|
var invariant = require("./invariant");
|
|
@@ -31,6 +34,7 @@ var keyMirror = require("./keyMirror");
|
|
|
31
34
|
var merge = require("./merge");
|
|
32
35
|
var mixInto = require("./mixInto");
|
|
33
36
|
var objMap = require("./objMap");
|
|
37
|
+
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
40
|
* Policies that describe methods in `ReactCompositeComponentInterface`.
|
|
@@ -89,15 +93,38 @@ var ReactCompositeComponentInterface = {
|
|
|
89
93
|
*/
|
|
90
94
|
mixins: SpecPolicy.DEFINE_MANY,
|
|
91
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
|
+
|
|
92
105
|
/**
|
|
93
106
|
* Definition of prop types for this component.
|
|
94
107
|
*
|
|
95
108
|
* @type {object}
|
|
96
109
|
* @optional
|
|
97
110
|
*/
|
|
98
|
-
propTypes: SpecPolicy.
|
|
111
|
+
propTypes: SpecPolicy.DEFINE_MANY,
|
|
99
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Definition of context types for this component.
|
|
115
|
+
*
|
|
116
|
+
* @type {object}
|
|
117
|
+
* @optional
|
|
118
|
+
*/
|
|
119
|
+
contextTypes: SpecPolicy.DEFINE_MANY,
|
|
100
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,
|
|
101
128
|
|
|
102
129
|
// ==== Definition methods ====
|
|
103
130
|
|
|
@@ -129,6 +156,12 @@ var ReactCompositeComponentInterface = {
|
|
|
129
156
|
*/
|
|
130
157
|
getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
|
|
131
158
|
|
|
159
|
+
/**
|
|
160
|
+
* @return {object}
|
|
161
|
+
* @optional
|
|
162
|
+
*/
|
|
163
|
+
getChildContext: SpecPolicy.DEFINE_MANY_MERGED,
|
|
164
|
+
|
|
132
165
|
/**
|
|
133
166
|
* Uses props from `this.props` and state from `this.state` to render the
|
|
134
167
|
* structure of the component.
|
|
@@ -178,7 +211,7 @@ var ReactCompositeComponentInterface = {
|
|
|
178
211
|
* Use this as an opportunity to react to a prop transition by updating the
|
|
179
212
|
* state using `this.setState`. Current props are accessed via `this.props`.
|
|
180
213
|
*
|
|
181
|
-
* componentWillReceiveProps: function(nextProps) {
|
|
214
|
+
* componentWillReceiveProps: function(nextProps, nextContext) {
|
|
182
215
|
* this.setState({
|
|
183
216
|
* likesIncreasing: nextProps.likeCount > this.props.likeCount
|
|
184
217
|
* });
|
|
@@ -195,17 +228,21 @@ var ReactCompositeComponentInterface = {
|
|
|
195
228
|
|
|
196
229
|
/**
|
|
197
230
|
* Invoked while deciding if the component should be updated as a result of
|
|
198
|
-
* receiving new props and
|
|
231
|
+
* receiving new props, state and/or context.
|
|
199
232
|
*
|
|
200
233
|
* Use this as an opportunity to `return false` when you're certain that the
|
|
201
|
-
* transition to the new props
|
|
234
|
+
* transition to the new props/state/context will not require a component
|
|
235
|
+
* update.
|
|
202
236
|
*
|
|
203
|
-
* shouldComponentUpdate: function(nextProps, nextState) {
|
|
204
|
-
* return !equal(nextProps, this.props) ||
|
|
237
|
+
* shouldComponentUpdate: function(nextProps, nextState, nextContext) {
|
|
238
|
+
* return !equal(nextProps, this.props) ||
|
|
239
|
+
* !equal(nextState, this.state) ||
|
|
240
|
+
* !equal(nextContext, this.context);
|
|
205
241
|
* }
|
|
206
242
|
*
|
|
207
243
|
* @param {object} nextProps
|
|
208
244
|
* @param {?object} nextState
|
|
245
|
+
* @param {?object} nextContext
|
|
209
246
|
* @return {boolean} True if the component should update.
|
|
210
247
|
* @optional
|
|
211
248
|
*/
|
|
@@ -213,7 +250,8 @@ var ReactCompositeComponentInterface = {
|
|
|
213
250
|
|
|
214
251
|
/**
|
|
215
252
|
* Invoked when the component is about to update due to a transition from
|
|
216
|
-
* `this.props` and `this.
|
|
253
|
+
* `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
|
|
254
|
+
* and `nextContext`.
|
|
217
255
|
*
|
|
218
256
|
* Use this as an opportunity to perform preparation before an update occurs.
|
|
219
257
|
*
|
|
@@ -221,6 +259,7 @@ var ReactCompositeComponentInterface = {
|
|
|
221
259
|
*
|
|
222
260
|
* @param {object} nextProps
|
|
223
261
|
* @param {?object} nextState
|
|
262
|
+
* @param {?object} nextContext
|
|
224
263
|
* @param {ReactReconcileTransaction} transaction
|
|
225
264
|
* @optional
|
|
226
265
|
*/
|
|
@@ -234,6 +273,7 @@ var ReactCompositeComponentInterface = {
|
|
|
234
273
|
*
|
|
235
274
|
* @param {object} prevProps
|
|
236
275
|
* @param {?object} prevState
|
|
276
|
+
* @param {?object} prevContext
|
|
237
277
|
* @param {DOMElement} rootNode DOM element representing the component.
|
|
238
278
|
* @optional
|
|
239
279
|
*/
|
|
@@ -273,25 +313,73 @@ var ReactCompositeComponentInterface = {
|
|
|
273
313
|
/**
|
|
274
314
|
* Mapping from class specification keys to special processing functions.
|
|
275
315
|
*
|
|
276
|
-
* Although these are declared in the specification
|
|
277
|
-
* using `React.createClass`, they
|
|
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.
|
|
278
321
|
*/
|
|
279
322
|
var RESERVED_SPEC_KEYS = {
|
|
280
|
-
displayName: function(
|
|
281
|
-
|
|
323
|
+
displayName: function(ConvenienceConstructor, displayName) {
|
|
324
|
+
ConvenienceConstructor.componentConstructor.displayName = displayName;
|
|
282
325
|
},
|
|
283
|
-
mixins: function(
|
|
326
|
+
mixins: function(ConvenienceConstructor, mixins) {
|
|
284
327
|
if (mixins) {
|
|
285
328
|
for (var i = 0; i < mixins.length; i++) {
|
|
286
|
-
mixSpecIntoComponent(
|
|
329
|
+
mixSpecIntoComponent(ConvenienceConstructor, mixins[i]);
|
|
287
330
|
}
|
|
288
331
|
}
|
|
289
332
|
},
|
|
290
|
-
|
|
291
|
-
Constructor
|
|
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);
|
|
292
365
|
}
|
|
293
366
|
};
|
|
294
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
|
+
|
|
295
383
|
function validateMethodOverride(proto, name) {
|
|
296
384
|
var specPolicy = ReactCompositeComponentInterface[name];
|
|
297
385
|
|
|
@@ -320,7 +408,6 @@ function validateMethodOverride(proto, name) {
|
|
|
320
408
|
}
|
|
321
409
|
}
|
|
322
410
|
|
|
323
|
-
|
|
324
411
|
function validateLifeCycleOnReplaceState(instance) {
|
|
325
412
|
var compositeLifeCycleState = instance._compositeLifeCycleState;
|
|
326
413
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
@@ -344,17 +431,30 @@ function validateLifeCycleOnReplaceState(instance) {
|
|
|
344
431
|
* Custom version of `mixInto` which handles policy validation and reserved
|
|
345
432
|
* specification keys when building `ReactCompositeComponent` classses.
|
|
346
433
|
*/
|
|
347
|
-
function mixSpecIntoComponent(
|
|
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;
|
|
348
447
|
var proto = Constructor.prototype;
|
|
349
448
|
for (var name in spec) {
|
|
350
449
|
var property = spec[name];
|
|
351
|
-
if (!spec.hasOwnProperty(name)
|
|
450
|
+
if (!spec.hasOwnProperty(name)) {
|
|
352
451
|
continue;
|
|
353
452
|
}
|
|
453
|
+
|
|
354
454
|
validateMethodOverride(proto, name);
|
|
355
455
|
|
|
356
456
|
if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
|
|
357
|
-
RESERVED_SPEC_KEYS[name](
|
|
457
|
+
RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property);
|
|
358
458
|
} else {
|
|
359
459
|
// Setup methods on prototype:
|
|
360
460
|
// The following member methods should not be automatically bound:
|
|
@@ -362,7 +462,7 @@ function mixSpecIntoComponent(Constructor, spec) {
|
|
|
362
462
|
// 2. Overridden methods (that were mixed in).
|
|
363
463
|
var isCompositeComponentMethod = name in ReactCompositeComponentInterface;
|
|
364
464
|
var isInherited = name in proto;
|
|
365
|
-
var markedDontBind = property.__reactDontBind;
|
|
465
|
+
var markedDontBind = property && property.__reactDontBind;
|
|
366
466
|
var isFunction = typeof property === 'function';
|
|
367
467
|
var shouldAutoBind =
|
|
368
468
|
isFunction &&
|
|
@@ -394,6 +494,37 @@ function mixSpecIntoComponent(Constructor, spec) {
|
|
|
394
494
|
}
|
|
395
495
|
}
|
|
396
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
|
+
|
|
397
528
|
/**
|
|
398
529
|
* Merge two objects, but throw if both contain the same key.
|
|
399
530
|
*
|
|
@@ -429,10 +560,14 @@ function mergeObjectsWithNoDuplicateKeys(one, two) {
|
|
|
429
560
|
*/
|
|
430
561
|
function createMergedResultFunction(one, two) {
|
|
431
562
|
return function mergedResult() {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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);
|
|
436
571
|
};
|
|
437
572
|
}
|
|
438
573
|
|
|
@@ -451,6 +586,118 @@ function createChainedFunction(one, two) {
|
|
|
451
586
|
};
|
|
452
587
|
}
|
|
453
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
|
+
|
|
454
701
|
/**
|
|
455
702
|
* `ReactCompositeComponent` maintains an auxiliary life cycle state in
|
|
456
703
|
* `this._compositeLifeCycleState` (which can be null).
|
|
@@ -516,8 +763,14 @@ var ReactCompositeComponentMixin = {
|
|
|
516
763
|
construct: function(initialProps, children) {
|
|
517
764
|
// Children can be either an array or more than one argument
|
|
518
765
|
ReactComponent.Mixin.construct.apply(this, arguments);
|
|
766
|
+
|
|
519
767
|
this.state = null;
|
|
520
768
|
this._pendingState = null;
|
|
769
|
+
|
|
770
|
+
this.context = this._processContext(ReactContext.current);
|
|
771
|
+
this._currentContext = ReactContext.current;
|
|
772
|
+
this._pendingContext = null;
|
|
773
|
+
|
|
521
774
|
this._compositeLifeCycleState = null;
|
|
522
775
|
},
|
|
523
776
|
|
|
@@ -555,13 +808,19 @@ var ReactCompositeComponentMixin = {
|
|
|
555
808
|
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
|
|
556
809
|
|
|
557
810
|
this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
|
|
558
|
-
this._processProps(this.props);
|
|
811
|
+
this.props = this._processProps(this.props);
|
|
559
812
|
|
|
560
813
|
if (this.__reactAutoBindMap) {
|
|
561
814
|
this._bindAutoBindMethods();
|
|
562
815
|
}
|
|
563
816
|
|
|
564
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
|
+
|
|
565
824
|
this._pendingState = null;
|
|
566
825
|
this._pendingForceUpdate = false;
|
|
567
826
|
|
|
@@ -606,10 +865,11 @@ var ReactCompositeComponentMixin = {
|
|
|
606
865
|
|
|
607
866
|
this._defaultProps = null;
|
|
608
867
|
|
|
609
|
-
ReactComponent.Mixin.unmountComponent.call(this);
|
|
610
868
|
this._renderedComponent.unmountComponent();
|
|
611
869
|
this._renderedComponent = null;
|
|
612
870
|
|
|
871
|
+
ReactComponent.Mixin.unmountComponent.call(this);
|
|
872
|
+
|
|
613
873
|
if (this.refs) {
|
|
614
874
|
this.refs = null;
|
|
615
875
|
}
|
|
@@ -638,6 +898,18 @@ var ReactCompositeComponentMixin = {
|
|
|
638
898
|
* @protected
|
|
639
899
|
*/
|
|
640
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
|
+
}
|
|
641
913
|
// Merge with `_pendingState` if it exists, otherwise with existing state.
|
|
642
914
|
this.replaceState(
|
|
643
915
|
merge(this._pendingState || this.state, partialState),
|
|
@@ -663,29 +935,107 @@ var ReactCompositeComponentMixin = {
|
|
|
663
935
|
ReactUpdates.enqueueUpdate(this, callback);
|
|
664
936
|
},
|
|
665
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
|
+
|
|
666
1000
|
/**
|
|
667
1001
|
* Processes props by setting default values for unspecified props and
|
|
668
|
-
* asserting that the props are valid.
|
|
1002
|
+
* asserting that the props are valid. Does not mutate its argument; returns
|
|
1003
|
+
* a new props object with defaults merged in.
|
|
669
1004
|
*
|
|
670
|
-
* @param {object}
|
|
1005
|
+
* @param {object} newProps
|
|
1006
|
+
* @return {object}
|
|
671
1007
|
* @private
|
|
672
1008
|
*/
|
|
673
|
-
_processProps: function(
|
|
674
|
-
var
|
|
1009
|
+
_processProps: function(newProps) {
|
|
1010
|
+
var props = merge(newProps);
|
|
675
1011
|
var defaultProps = this._defaultProps;
|
|
676
|
-
for (propName in defaultProps) {
|
|
677
|
-
if (
|
|
1012
|
+
for (var propName in defaultProps) {
|
|
1013
|
+
if (typeof props[propName] === 'undefined') {
|
|
678
1014
|
props[propName] = defaultProps[propName];
|
|
679
1015
|
}
|
|
680
1016
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
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);
|
|
689
1039
|
}
|
|
690
1040
|
}
|
|
691
1041
|
},
|
|
@@ -711,41 +1061,63 @@ var ReactCompositeComponentMixin = {
|
|
|
711
1061
|
_performUpdateIfNecessary: function(transaction) {
|
|
712
1062
|
if (this._pendingProps == null &&
|
|
713
1063
|
this._pendingState == null &&
|
|
1064
|
+
this._pendingContext == null &&
|
|
714
1065
|
!this._pendingForceUpdate) {
|
|
715
1066
|
return;
|
|
716
1067
|
}
|
|
717
1068
|
|
|
1069
|
+
var nextFullContext = this._pendingContext || this._currentContext;
|
|
1070
|
+
var nextContext = this._processContext(nextFullContext);
|
|
1071
|
+
this._pendingContext = null;
|
|
1072
|
+
|
|
718
1073
|
var nextProps = this.props;
|
|
719
1074
|
if (this._pendingProps != null) {
|
|
720
|
-
nextProps = this._pendingProps;
|
|
721
|
-
this._processProps(nextProps);
|
|
1075
|
+
nextProps = this._processProps(this._pendingProps);
|
|
722
1076
|
this._pendingProps = null;
|
|
723
1077
|
|
|
724
1078
|
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
|
|
725
1079
|
if (this.componentWillReceiveProps) {
|
|
726
|
-
this.componentWillReceiveProps(nextProps,
|
|
1080
|
+
this.componentWillReceiveProps(nextProps, nextContext);
|
|
727
1081
|
}
|
|
728
1082
|
}
|
|
729
1083
|
|
|
730
1084
|
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
|
|
731
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
|
+
|
|
732
1092
|
var nextState = this._pendingState || this.state;
|
|
733
1093
|
this._pendingState = null;
|
|
734
1094
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
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;
|
|
746
1120
|
}
|
|
747
|
-
|
|
748
|
-
this._compositeLifeCycleState = null;
|
|
749
1121
|
},
|
|
750
1122
|
|
|
751
1123
|
/**
|
|
@@ -753,31 +1125,68 @@ var ReactCompositeComponentMixin = {
|
|
|
753
1125
|
* performs update.
|
|
754
1126
|
*
|
|
755
1127
|
* @param {object} nextProps Next object to set as properties.
|
|
1128
|
+
* @param {?ReactComponent} nextOwner Next component to set as owner
|
|
756
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.
|
|
757
1132
|
* @param {ReactReconcileTransaction} transaction
|
|
758
1133
|
* @private
|
|
759
1134
|
*/
|
|
760
|
-
_performComponentUpdate: function(
|
|
1135
|
+
_performComponentUpdate: function(
|
|
1136
|
+
nextProps,
|
|
1137
|
+
nextOwner,
|
|
1138
|
+
nextState,
|
|
1139
|
+
nextFullContext,
|
|
1140
|
+
nextContext,
|
|
1141
|
+
transaction
|
|
1142
|
+
) {
|
|
761
1143
|
var prevProps = this.props;
|
|
1144
|
+
var prevOwner = this._owner;
|
|
762
1145
|
var prevState = this.state;
|
|
1146
|
+
var prevContext = this.context;
|
|
763
1147
|
|
|
764
1148
|
if (this.componentWillUpdate) {
|
|
765
|
-
this.componentWillUpdate(nextProps, nextState,
|
|
1149
|
+
this.componentWillUpdate(nextProps, nextState, nextContext);
|
|
766
1150
|
}
|
|
767
1151
|
|
|
768
1152
|
this.props = nextProps;
|
|
1153
|
+
this._owner = nextOwner;
|
|
769
1154
|
this.state = nextState;
|
|
770
|
-
|
|
771
|
-
this.
|
|
1155
|
+
this._currentContext = nextFullContext;
|
|
1156
|
+
this.context = nextContext;
|
|
1157
|
+
|
|
1158
|
+
this.updateComponent(
|
|
1159
|
+
transaction,
|
|
1160
|
+
prevProps,
|
|
1161
|
+
prevOwner,
|
|
1162
|
+
prevState,
|
|
1163
|
+
prevContext
|
|
1164
|
+
);
|
|
772
1165
|
|
|
773
1166
|
if (this.componentDidUpdate) {
|
|
774
1167
|
transaction.getReactMountReady().enqueue(
|
|
775
1168
|
this,
|
|
776
|
-
this.componentDidUpdate.bind(this, prevProps, prevState)
|
|
1169
|
+
this.componentDidUpdate.bind(this, prevProps, prevState, prevContext)
|
|
777
1170
|
);
|
|
778
1171
|
}
|
|
779
1172
|
},
|
|
780
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
|
+
|
|
781
1190
|
/**
|
|
782
1191
|
* Updates the component's currently mounted DOM representation.
|
|
783
1192
|
*
|
|
@@ -786,32 +1195,39 @@ var ReactCompositeComponentMixin = {
|
|
|
786
1195
|
*
|
|
787
1196
|
* @param {ReactReconcileTransaction} transaction
|
|
788
1197
|
* @param {object} prevProps
|
|
1198
|
+
* @param {?ReactComponent} prevOwner
|
|
789
1199
|
* @param {?object} prevState
|
|
1200
|
+
* @param {?object} prevContext
|
|
790
1201
|
* @internal
|
|
791
1202
|
* @overridable
|
|
792
1203
|
*/
|
|
793
1204
|
updateComponent: ReactPerf.measure(
|
|
794
1205
|
'ReactCompositeComponent',
|
|
795
1206
|
'updateComponent',
|
|
796
|
-
function(transaction, prevProps, prevState) {
|
|
797
|
-
ReactComponent.Mixin.updateComponent.call(
|
|
798
|
-
|
|
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;
|
|
799
1215
|
var nextComponent = this._renderValidatedComponent();
|
|
800
|
-
if (
|
|
801
|
-
|
|
1216
|
+
if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
|
|
1217
|
+
prevComponent.receiveComponent(nextComponent, transaction);
|
|
802
1218
|
} else {
|
|
803
1219
|
// These two IDs are actually the same! But nothing should rely on that.
|
|
804
1220
|
var thisID = this._rootNodeID;
|
|
805
|
-
var
|
|
806
|
-
|
|
1221
|
+
var prevComponentID = prevComponent._rootNodeID;
|
|
1222
|
+
prevComponent.unmountComponent();
|
|
807
1223
|
this._renderedComponent = nextComponent;
|
|
808
1224
|
var nextMarkup = nextComponent.mountComponent(
|
|
809
1225
|
thisID,
|
|
810
1226
|
transaction,
|
|
811
1227
|
this._mountDepth + 1
|
|
812
1228
|
);
|
|
813
|
-
ReactComponent.
|
|
814
|
-
|
|
1229
|
+
ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
|
|
1230
|
+
prevComponentID,
|
|
815
1231
|
nextMarkup
|
|
816
1232
|
);
|
|
817
1233
|
}
|
|
@@ -855,25 +1271,29 @@ var ReactCompositeComponentMixin = {
|
|
|
855
1271
|
/**
|
|
856
1272
|
* @private
|
|
857
1273
|
*/
|
|
858
|
-
_renderValidatedComponent:
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
renderedComponent
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
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;
|
|
868
1295
|
}
|
|
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
|
-
},
|
|
1296
|
+
),
|
|
877
1297
|
|
|
878
1298
|
/**
|
|
879
1299
|
* @private
|
|
@@ -908,7 +1328,7 @@ var ReactCompositeComponentMixin = {
|
|
|
908
1328
|
boundMethod.__reactBoundArguments = null;
|
|
909
1329
|
var componentName = component.constructor.displayName;
|
|
910
1330
|
var _bind = boundMethod.bind;
|
|
911
|
-
boundMethod.bind = function(newThis) {
|
|
1331
|
+
boundMethod.bind = function(newThis ) {var args=Array.prototype.slice.call(arguments,1);
|
|
912
1332
|
// User is trying to bind() an autobound method; we effectively will
|
|
913
1333
|
// ignore the value of "this" that the user is trying to use, so
|
|
914
1334
|
// let's warn.
|
|
@@ -917,7 +1337,7 @@ var ReactCompositeComponentMixin = {
|
|
|
917
1337
|
'bind(): React component methods may only be bound to the ' +
|
|
918
1338
|
'component instance. See ' + componentName
|
|
919
1339
|
);
|
|
920
|
-
} else if (
|
|
1340
|
+
} else if (!args.length) {
|
|
921
1341
|
console.warn(
|
|
922
1342
|
'bind(): You are binding a component method to the component. ' +
|
|
923
1343
|
'React does this for you automatically in a high-performance ' +
|
|
@@ -928,8 +1348,7 @@ var ReactCompositeComponentMixin = {
|
|
|
928
1348
|
var reboundMethod = _bind.apply(boundMethod, arguments);
|
|
929
1349
|
reboundMethod.__reactBoundContext = component;
|
|
930
1350
|
reboundMethod.__reactBoundMethod = method;
|
|
931
|
-
reboundMethod.__reactBoundArguments =
|
|
932
|
-
Array.prototype.slice.call(arguments, 1);
|
|
1351
|
+
reboundMethod.__reactBoundArguments = args;
|
|
933
1352
|
return reboundMethod;
|
|
934
1353
|
};
|
|
935
1354
|
}
|
|
@@ -943,6 +1362,18 @@ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
|
|
|
943
1362
|
mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
|
|
944
1363
|
mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
|
|
945
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
|
+
}
|
|
946
1377
|
/**
|
|
947
1378
|
* Module for creating composite components.
|
|
948
1379
|
*
|
|
@@ -968,7 +1399,17 @@ var ReactCompositeComponent = {
|
|
|
968
1399
|
var Constructor = function() {};
|
|
969
1400
|
Constructor.prototype = new ReactCompositeComponentBase();
|
|
970
1401
|
Constructor.prototype.constructor = Constructor;
|
|
971
|
-
|
|
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);
|
|
972
1413
|
|
|
973
1414
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
974
1415
|
Constructor.prototype.render,
|
|
@@ -986,6 +1427,14 @@ var ReactCompositeComponent = {
|
|
|
986
1427
|
}
|
|
987
1428
|
}
|
|
988
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
|
+
|
|
989
1438
|
// Reduce time spent doing lookups by setting these on the prototype.
|
|
990
1439
|
for (var methodName in ReactCompositeComponentInterface) {
|
|
991
1440
|
if (!Constructor.prototype[methodName]) {
|
|
@@ -993,28 +1442,14 @@ var ReactCompositeComponent = {
|
|
|
993
1442
|
}
|
|
994
1443
|
}
|
|
995
1444
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
};
|
|
1001
|
-
ConvenienceConstructor.componentConstructor = Constructor;
|
|
1002
|
-
ConvenienceConstructor.originalSpec = spec;
|
|
1445
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1446
|
+
Constructor.prototype = createMountWarningMembrane(Constructor.prototype);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1003
1449
|
return ConvenienceConstructor;
|
|
1004
1450
|
},
|
|
1005
1451
|
|
|
1006
|
-
|
|
1007
|
-
* Checks if a value is a valid component constructor.
|
|
1008
|
-
*
|
|
1009
|
-
* @param {*}
|
|
1010
|
-
* @return {boolean}
|
|
1011
|
-
* @public
|
|
1012
|
-
*/
|
|
1013
|
-
isValidClass: function(componentClass) {
|
|
1014
|
-
return componentClass instanceof Function &&
|
|
1015
|
-
'componentConstructor' in componentClass &&
|
|
1016
|
-
componentClass.componentConstructor instanceof Function;
|
|
1017
|
-
}
|
|
1452
|
+
isValidClass: isValidClass
|
|
1018
1453
|
};
|
|
1019
1454
|
|
|
1020
1455
|
module.exports = ReactCompositeComponent;
|