react 0.9.0 → 0.11.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 +3 -0
- package/dist/JSXTransformer.js +13448 -0
- package/dist/react-with-addons.js +20235 -0
- package/dist/react-with-addons.min.js +22 -0
- package/dist/react.js +18443 -0
- package/dist/react.min.js +21 -0
- package/lib/AutoFocusMixin.js +3 -1
- package/lib/BeforeInputEventPlugin.js +222 -0
- package/lib/CSSPropertyOperations.js +3 -3
- package/lib/{ReactMountReady.js → CallbackQueue.js} +32 -24
- package/lib/ChangeEventPlugin.js +1 -1
- package/lib/CompositionEventPlugin.js +5 -1
- package/lib/DOMChildrenOperations.js +33 -20
- package/lib/DOMProperty.js +51 -21
- package/lib/DOMPropertyOperations.js +28 -16
- package/lib/DefaultEventPluginOrder.js +1 -0
- package/lib/EventConstants.js +1 -0
- package/lib/EventListener.js +5 -2
- package/lib/EventPluginHub.js +2 -5
- package/lib/EventPluginRegistry.js +6 -4
- package/lib/EventPluginUtils.js +11 -1
- package/lib/ExecutionEnvironment.js +8 -2
- package/lib/{DefaultDOMPropertyConfig.js → HTMLDOMPropertyConfig.js} +41 -58
- package/lib/LinkedValueUtils.js +26 -28
- package/lib/LocalEventTrapMixin.js +52 -0
- package/lib/React.js +39 -3
- package/lib/ReactBrowserComponentMixin.js +46 -0
- package/lib/{ReactEventEmitter.js → ReactBrowserEventEmitter.js} +115 -94
- package/lib/ReactCSSTransitionGroup.js +12 -10
- package/lib/ReactCSSTransitionGroupChild.js +2 -5
- package/lib/ReactChildren.js +31 -10
- package/lib/ReactComponent.js +119 -223
- package/lib/ReactComponentBrowserEnvironment.js +3 -36
- package/lib/ReactComponentWithPureRenderMixin.js +54 -0
- package/lib/ReactCompositeComponent.js +249 -287
- package/lib/ReactDOM.js +25 -23
- package/lib/ReactDOMButton.js +2 -1
- package/lib/ReactDOMComponent.js +42 -23
- package/lib/ReactDOMForm.js +7 -12
- package/lib/ReactDOMIDOperations.js +2 -31
- package/lib/ReactDOMImg.js +7 -13
- package/lib/ReactDOMInput.js +2 -1
- package/lib/ReactDOMOption.js +11 -7
- package/lib/ReactDOMSelect.js +18 -16
- package/lib/ReactDOMSelection.js +35 -10
- package/lib/ReactDOMTextarea.js +9 -7
- package/lib/ReactDefaultBatchingStrategy.js +3 -3
- package/lib/ReactDefaultInjection.js +27 -14
- package/lib/ReactDefaultPerf.js +28 -11
- package/lib/ReactDefaultPerfAnalysis.js +4 -0
- package/lib/ReactDescriptor.js +251 -0
- package/lib/ReactDescriptorValidator.js +283 -0
- package/lib/ReactEmptyComponent.js +78 -0
- package/lib/ReactEventEmitterMixin.js +1 -3
- package/lib/ReactEventListener.js +189 -0
- package/lib/ReactInjection.js +8 -2
- package/lib/ReactInputSelection.js +2 -1
- package/lib/ReactLink.js +24 -0
- package/lib/ReactMount.js +61 -21
- package/lib/ReactMultiChild.js +18 -13
- package/lib/ReactOwner.js +6 -1
- package/lib/ReactPropTransferer.js +44 -29
- package/lib/ReactPropTypes.js +226 -242
- package/lib/ReactPutListenerQueue.js +2 -2
- package/lib/ReactReconcileTransaction.js +21 -20
- package/lib/ReactServerRendering.js +41 -11
- package/lib/ReactServerRenderingTransaction.js +115 -0
- package/lib/ReactTestUtils.js +39 -21
- package/lib/ReactTextComponent.js +21 -13
- package/lib/ReactTransitionChildMapping.js +2 -2
- package/lib/ReactTransitionEvents.js +19 -0
- package/lib/ReactTransitionGroup.js +9 -6
- package/lib/ReactUpdates.js +139 -22
- package/lib/ReactWithAddons.js +8 -3
- package/lib/SVGDOMPropertyConfig.js +97 -0
- package/lib/SimpleEventPlugin.js +7 -1
- package/lib/SyntheticInputEvent.js +52 -0
- package/lib/SyntheticKeyboardEvent.js +33 -4
- package/lib/SyntheticMouseEvent.js +3 -0
- package/lib/SyntheticTouchEvent.js +4 -1
- package/lib/SyntheticUIEvent.js +24 -2
- package/lib/Transaction.js +0 -32
- package/lib/cloneWithProps.js +10 -8
- package/lib/createFullPageComponent.js +1 -1
- package/lib/dangerousStyleValue.js +11 -5
- package/lib/{ReactComponentEnvironment.js → emptyObject.js} +6 -5
- package/lib/escapeTextForBrowser.js +2 -3
- package/lib/flattenChildren.js +9 -7
- package/lib/focusNode.js +33 -0
- package/lib/getEventKey.js +35 -5
- package/lib/getEventModifierState.js +52 -0
- package/lib/getMarkupWrap.js +2 -0
- package/lib/getTextContentAccessor.js +1 -1
- package/lib/hyphenate.js +3 -0
- package/lib/hyphenateStyleName.js +46 -0
- package/lib/instantiateReactComponent.js +62 -0
- package/lib/invariant.js +17 -19
- package/lib/isNode.js +1 -1
- package/lib/{objMap.js → mapObject.js} +8 -3
- package/lib/mergeHelpers.js +11 -0
- package/lib/mergeInto.js +3 -2
- package/lib/monitorCodeUse.js +37 -0
- package/lib/onlyChild.js +3 -3
- package/lib/performance.js +33 -0
- package/lib/performanceNow.js +5 -14
- package/lib/setInnerHTML.js +77 -0
- package/lib/shouldUpdateReactComponent.js +14 -28
- package/lib/toArray.js +1 -1
- package/lib/traverseAllChildren.js +9 -5
- package/lib/update.js +171 -0
- package/package.json +4 -3
- package/lib/ReactEventTopLevelCallback.js +0 -149
- package/lib/createObjectFrom.js +0 -61
- package/lib/objMapKeyVal.js +0 -47
|
@@ -28,6 +28,7 @@ var ReactReconcileTransaction = require("./ReactReconcileTransaction");
|
|
|
28
28
|
|
|
29
29
|
var getReactRootElementInContainer = require("./getReactRootElementInContainer");
|
|
30
30
|
var invariant = require("./invariant");
|
|
31
|
+
var setInnerHTML = require("./setInnerHTML");
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
var ELEMENT_NODE_TYPE = 1;
|
|
@@ -39,26 +40,6 @@ var DOC_NODE_TYPE = 9;
|
|
|
39
40
|
* the browser context.
|
|
40
41
|
*/
|
|
41
42
|
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
43
|
ReactReconcileTransaction: ReactReconcileTransaction,
|
|
63
44
|
|
|
64
45
|
BackendIDOperations: ReactDOMIDOperations,
|
|
@@ -118,7 +99,7 @@ var ReactComponentBrowserEnvironment = {
|
|
|
118
99
|
'React attempted to use reuse markup in a container but the ' +
|
|
119
100
|
'checksum was invalid. This generally means that you are ' +
|
|
120
101
|
'using server rendering and the markup generated on the ' +
|
|
121
|
-
'server was not what the client was expecting. React injected' +
|
|
102
|
+
'server was not what the client was expecting. React injected ' +
|
|
122
103
|
'new markup to compensate which works but you have lost many ' +
|
|
123
104
|
'of the benefits of server rendering. Instead, figure out ' +
|
|
124
105
|
'why the markup being generated is different on the client ' +
|
|
@@ -136,21 +117,7 @@ var ReactComponentBrowserEnvironment = {
|
|
|
136
117
|
'See renderComponentToString() for server rendering.'
|
|
137
118
|
) : invariant(container.nodeType !== DOC_NODE_TYPE));
|
|
138
119
|
|
|
139
|
-
|
|
140
|
-
// the document when settings its `innerHTML`.
|
|
141
|
-
var parent = container.parentNode;
|
|
142
|
-
if (parent) {
|
|
143
|
-
var next = container.nextSibling;
|
|
144
|
-
parent.removeChild(container);
|
|
145
|
-
container.innerHTML = markup;
|
|
146
|
-
if (next) {
|
|
147
|
-
parent.insertBefore(container, next);
|
|
148
|
-
} else {
|
|
149
|
-
parent.appendChild(container);
|
|
150
|
-
}
|
|
151
|
-
} else {
|
|
152
|
-
container.innerHTML = markup;
|
|
153
|
-
}
|
|
120
|
+
setInnerHTML(container, markup);
|
|
154
121
|
}
|
|
155
122
|
)
|
|
156
123
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2014 Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @providesModule ReactComponentWithPureRenderMixin
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var shallowEqual = require("./shallowEqual");
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* If your React component's render function is "pure", e.g. it will render the
|
|
25
|
+
* same result given the same props and state, provide this Mixin for a
|
|
26
|
+
* considerable performance boost.
|
|
27
|
+
*
|
|
28
|
+
* Most React components have pure render functions.
|
|
29
|
+
*
|
|
30
|
+
* Example:
|
|
31
|
+
*
|
|
32
|
+
* var ReactComponentWithPureRenderMixin =
|
|
33
|
+
* require('ReactComponentWithPureRenderMixin');
|
|
34
|
+
* React.createClass({
|
|
35
|
+
* mixins: [ReactComponentWithPureRenderMixin],
|
|
36
|
+
*
|
|
37
|
+
* render: function() {
|
|
38
|
+
* return <div className={this.props.className}>foo</div>;
|
|
39
|
+
* }
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* Note: This only checks shallow equality for props and state. If these contain
|
|
43
|
+
* complex data structures this mixin may have false-negatives for deeper
|
|
44
|
+
* differences. Only mixin to components which have simple props and state, or
|
|
45
|
+
* use `forceUpdate()` when you know deep data structures have changed.
|
|
46
|
+
*/
|
|
47
|
+
var ReactComponentWithPureRenderMixin = {
|
|
48
|
+
shouldComponentUpdate: function(nextProps, nextState) {
|
|
49
|
+
return !shallowEqual(this.props, nextProps) ||
|
|
50
|
+
!shallowEqual(this.state, nextState);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
module.exports = ReactComponentWithPureRenderMixin;
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
var ReactComponent = require("./ReactComponent");
|
|
22
22
|
var ReactContext = require("./ReactContext");
|
|
23
23
|
var ReactCurrentOwner = require("./ReactCurrentOwner");
|
|
24
|
+
var ReactDescriptor = require("./ReactDescriptor");
|
|
25
|
+
var ReactDescriptorValidator = require("./ReactDescriptorValidator");
|
|
26
|
+
var ReactEmptyComponent = require("./ReactEmptyComponent");
|
|
24
27
|
var ReactErrorUtils = require("./ReactErrorUtils");
|
|
25
28
|
var ReactOwner = require("./ReactOwner");
|
|
26
29
|
var ReactPerf = require("./ReactPerf");
|
|
@@ -29,12 +32,15 @@ var ReactPropTypeLocations = require("./ReactPropTypeLocations");
|
|
|
29
32
|
var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
|
|
30
33
|
var ReactUpdates = require("./ReactUpdates");
|
|
31
34
|
|
|
35
|
+
var instantiateReactComponent = require("./instantiateReactComponent");
|
|
32
36
|
var invariant = require("./invariant");
|
|
33
37
|
var keyMirror = require("./keyMirror");
|
|
34
38
|
var merge = require("./merge");
|
|
35
39
|
var mixInto = require("./mixInto");
|
|
36
|
-
var
|
|
40
|
+
var monitorCodeUse = require("./monitorCodeUse");
|
|
41
|
+
var mapObject = require("./mapObject");
|
|
37
42
|
var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
|
|
43
|
+
var warning = require("./warning");
|
|
38
44
|
|
|
39
45
|
/**
|
|
40
46
|
* Policies that describe methods in `ReactCompositeComponentInterface`.
|
|
@@ -61,6 +67,9 @@ var SpecPolicy = keyMirror({
|
|
|
61
67
|
DEFINE_MANY_MERGED: null
|
|
62
68
|
});
|
|
63
69
|
|
|
70
|
+
|
|
71
|
+
var injectedMixins = [];
|
|
72
|
+
|
|
64
73
|
/**
|
|
65
74
|
* Composite components are higher-level components that compose other composite
|
|
66
75
|
* or native components.
|
|
@@ -320,18 +329,17 @@ var ReactCompositeComponentInterface = {
|
|
|
320
329
|
* which all other static methods are defined.
|
|
321
330
|
*/
|
|
322
331
|
var RESERVED_SPEC_KEYS = {
|
|
323
|
-
displayName: function(
|
|
324
|
-
|
|
332
|
+
displayName: function(Constructor, displayName) {
|
|
333
|
+
Constructor.displayName = displayName;
|
|
325
334
|
},
|
|
326
|
-
mixins: function(
|
|
335
|
+
mixins: function(Constructor, mixins) {
|
|
327
336
|
if (mixins) {
|
|
328
337
|
for (var i = 0; i < mixins.length; i++) {
|
|
329
|
-
mixSpecIntoComponent(
|
|
338
|
+
mixSpecIntoComponent(Constructor, mixins[i]);
|
|
330
339
|
}
|
|
331
340
|
}
|
|
332
341
|
},
|
|
333
|
-
childContextTypes: function(
|
|
334
|
-
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
342
|
+
childContextTypes: function(Constructor, childContextTypes) {
|
|
335
343
|
validateTypeDef(
|
|
336
344
|
Constructor,
|
|
337
345
|
childContextTypes,
|
|
@@ -342,8 +350,7 @@ var RESERVED_SPEC_KEYS = {
|
|
|
342
350
|
childContextTypes
|
|
343
351
|
);
|
|
344
352
|
},
|
|
345
|
-
contextTypes: function(
|
|
346
|
-
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
353
|
+
contextTypes: function(Constructor, contextTypes) {
|
|
347
354
|
validateTypeDef(
|
|
348
355
|
Constructor,
|
|
349
356
|
contextTypes,
|
|
@@ -351,8 +358,21 @@ var RESERVED_SPEC_KEYS = {
|
|
|
351
358
|
);
|
|
352
359
|
Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
|
|
353
360
|
},
|
|
354
|
-
|
|
355
|
-
|
|
361
|
+
/**
|
|
362
|
+
* Special case getDefaultProps which should move into statics but requires
|
|
363
|
+
* automatic merging.
|
|
364
|
+
*/
|
|
365
|
+
getDefaultProps: function(Constructor, getDefaultProps) {
|
|
366
|
+
if (Constructor.getDefaultProps) {
|
|
367
|
+
Constructor.getDefaultProps = createMergedResultFunction(
|
|
368
|
+
Constructor.getDefaultProps,
|
|
369
|
+
getDefaultProps
|
|
370
|
+
);
|
|
371
|
+
} else {
|
|
372
|
+
Constructor.getDefaultProps = getDefaultProps;
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
propTypes: function(Constructor, propTypes) {
|
|
356
376
|
validateTypeDef(
|
|
357
377
|
Constructor,
|
|
358
378
|
propTypes,
|
|
@@ -360,11 +380,20 @@ var RESERVED_SPEC_KEYS = {
|
|
|
360
380
|
);
|
|
361
381
|
Constructor.propTypes = merge(Constructor.propTypes, propTypes);
|
|
362
382
|
},
|
|
363
|
-
statics: function(
|
|
364
|
-
mixStaticSpecIntoComponent(
|
|
383
|
+
statics: function(Constructor, statics) {
|
|
384
|
+
mixStaticSpecIntoComponent(Constructor, statics);
|
|
365
385
|
}
|
|
366
386
|
};
|
|
367
387
|
|
|
388
|
+
function getDeclarationErrorAddendum(component) {
|
|
389
|
+
var owner = component._owner || null;
|
|
390
|
+
if (owner && owner.constructor && owner.constructor.displayName) {
|
|
391
|
+
return ' Check the render method of `' + owner.constructor.displayName +
|
|
392
|
+
'`.';
|
|
393
|
+
}
|
|
394
|
+
return '';
|
|
395
|
+
}
|
|
396
|
+
|
|
368
397
|
function validateTypeDef(Constructor, typeDef, location) {
|
|
369
398
|
for (var propName in typeDef) {
|
|
370
399
|
if (typeDef.hasOwnProperty(propName)) {
|
|
@@ -381,7 +410,9 @@ function validateTypeDef(Constructor, typeDef, location) {
|
|
|
381
410
|
}
|
|
382
411
|
|
|
383
412
|
function validateMethodOverride(proto, name) {
|
|
384
|
-
var specPolicy = ReactCompositeComponentInterface
|
|
413
|
+
var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
|
|
414
|
+
ReactCompositeComponentInterface[name] :
|
|
415
|
+
null;
|
|
385
416
|
|
|
386
417
|
// Disallow overriding of base class methods unless explicitly allowed.
|
|
387
418
|
if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
|
|
@@ -431,19 +462,18 @@ function validateLifeCycleOnReplaceState(instance) {
|
|
|
431
462
|
* Custom version of `mixInto` which handles policy validation and reserved
|
|
432
463
|
* specification keys when building `ReactCompositeComponent` classses.
|
|
433
464
|
*/
|
|
434
|
-
function mixSpecIntoComponent(
|
|
465
|
+
function mixSpecIntoComponent(Constructor, spec) {
|
|
435
466
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
436
|
-
!
|
|
467
|
+
!ReactDescriptor.isValidFactory(spec),
|
|
437
468
|
'ReactCompositeComponent: You\'re attempting to ' +
|
|
438
469
|
'use a component class as a mixin. Instead, just use a regular object.'
|
|
439
|
-
) : invariant(!
|
|
470
|
+
) : invariant(!ReactDescriptor.isValidFactory(spec)));
|
|
440
471
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
441
|
-
!
|
|
472
|
+
!ReactDescriptor.isValidDescriptor(spec),
|
|
442
473
|
'ReactCompositeComponent: You\'re attempting to ' +
|
|
443
474
|
'use a component as a mixin. Instead, just use a regular object.'
|
|
444
|
-
) : invariant(!
|
|
475
|
+
) : invariant(!ReactDescriptor.isValidDescriptor(spec)));
|
|
445
476
|
|
|
446
|
-
var Constructor = ConvenienceConstructor.componentConstructor;
|
|
447
477
|
var proto = Constructor.prototype;
|
|
448
478
|
for (var name in spec) {
|
|
449
479
|
var property = spec[name];
|
|
@@ -454,20 +484,21 @@ function mixSpecIntoComponent(ConvenienceConstructor, spec) {
|
|
|
454
484
|
validateMethodOverride(proto, name);
|
|
455
485
|
|
|
456
486
|
if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
|
|
457
|
-
RESERVED_SPEC_KEYS[name](
|
|
487
|
+
RESERVED_SPEC_KEYS[name](Constructor, property);
|
|
458
488
|
} else {
|
|
459
489
|
// Setup methods on prototype:
|
|
460
490
|
// The following member methods should not be automatically bound:
|
|
461
491
|
// 1. Expected ReactCompositeComponent methods (in the "interface").
|
|
462
492
|
// 2. Overridden methods (that were mixed in).
|
|
463
|
-
var isCompositeComponentMethod =
|
|
464
|
-
|
|
493
|
+
var isCompositeComponentMethod =
|
|
494
|
+
ReactCompositeComponentInterface.hasOwnProperty(name);
|
|
495
|
+
var isAlreadyDefined = proto.hasOwnProperty(name);
|
|
465
496
|
var markedDontBind = property && property.__reactDontBind;
|
|
466
497
|
var isFunction = typeof property === 'function';
|
|
467
498
|
var shouldAutoBind =
|
|
468
499
|
isFunction &&
|
|
469
500
|
!isCompositeComponentMethod &&
|
|
470
|
-
!
|
|
501
|
+
!isAlreadyDefined &&
|
|
471
502
|
!markedDontBind;
|
|
472
503
|
|
|
473
504
|
if (shouldAutoBind) {
|
|
@@ -477,37 +508,60 @@ function mixSpecIntoComponent(ConvenienceConstructor, spec) {
|
|
|
477
508
|
proto.__reactAutoBindMap[name] = property;
|
|
478
509
|
proto[name] = property;
|
|
479
510
|
} else {
|
|
480
|
-
if (
|
|
511
|
+
if (isAlreadyDefined) {
|
|
512
|
+
var specPolicy = ReactCompositeComponentInterface[name];
|
|
513
|
+
|
|
514
|
+
// These cases should already be caught by validateMethodOverride
|
|
515
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
516
|
+
isCompositeComponentMethod && (
|
|
517
|
+
specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
|
|
518
|
+
specPolicy === SpecPolicy.DEFINE_MANY
|
|
519
|
+
),
|
|
520
|
+
'ReactCompositeComponent: Unexpected spec policy %s for key %s ' +
|
|
521
|
+
'when mixing in component specs.',
|
|
522
|
+
specPolicy,
|
|
523
|
+
name
|
|
524
|
+
) : invariant(isCompositeComponentMethod && (
|
|
525
|
+
specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
|
|
526
|
+
specPolicy === SpecPolicy.DEFINE_MANY
|
|
527
|
+
)));
|
|
528
|
+
|
|
481
529
|
// For methods which are defined more than once, call the existing
|
|
482
|
-
// methods before calling the new property.
|
|
483
|
-
if (
|
|
484
|
-
SpecPolicy.DEFINE_MANY_MERGED) {
|
|
530
|
+
// methods before calling the new property, merging if appropriate.
|
|
531
|
+
if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
|
|
485
532
|
proto[name] = createMergedResultFunction(proto[name], property);
|
|
486
|
-
} else {
|
|
533
|
+
} else if (specPolicy === SpecPolicy.DEFINE_MANY) {
|
|
487
534
|
proto[name] = createChainedFunction(proto[name], property);
|
|
488
535
|
}
|
|
489
536
|
} else {
|
|
490
537
|
proto[name] = property;
|
|
538
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
539
|
+
// Add verbose displayName to the function, which helps when looking
|
|
540
|
+
// at profiling tools.
|
|
541
|
+
if (typeof property === 'function' && spec.displayName) {
|
|
542
|
+
proto[name].displayName = spec.displayName + '_' + name;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
491
545
|
}
|
|
492
546
|
}
|
|
493
547
|
}
|
|
494
548
|
}
|
|
495
549
|
}
|
|
496
550
|
|
|
497
|
-
function mixStaticSpecIntoComponent(
|
|
551
|
+
function mixStaticSpecIntoComponent(Constructor, statics) {
|
|
498
552
|
if (!statics) {
|
|
499
553
|
return;
|
|
500
554
|
}
|
|
501
555
|
for (var name in statics) {
|
|
502
556
|
var property = statics[name];
|
|
503
|
-
if (!statics.hasOwnProperty(name)
|
|
504
|
-
|
|
557
|
+
if (!statics.hasOwnProperty(name)) {
|
|
558
|
+
continue;
|
|
505
559
|
}
|
|
506
560
|
|
|
507
|
-
var isInherited = name in
|
|
561
|
+
var isInherited = name in Constructor;
|
|
508
562
|
var result = property;
|
|
509
563
|
if (isInherited) {
|
|
510
|
-
var existingProperty =
|
|
564
|
+
var existingProperty = Constructor[name];
|
|
511
565
|
var existingType = typeof existingProperty;
|
|
512
566
|
var propertyType = typeof property;
|
|
513
567
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
@@ -520,8 +574,7 @@ function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
|
|
|
520
574
|
) : invariant(existingType === 'function' && propertyType === 'function'));
|
|
521
575
|
result = createChainedFunction(existingProperty, property);
|
|
522
576
|
}
|
|
523
|
-
|
|
524
|
-
ConvenienceConstructor.componentConstructor[name] = result;
|
|
577
|
+
Constructor[name] = result;
|
|
525
578
|
}
|
|
526
579
|
}
|
|
527
580
|
|
|
@@ -538,7 +591,7 @@ function mergeObjectsWithNoDuplicateKeys(one, two) {
|
|
|
538
591
|
'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
|
|
539
592
|
) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
|
|
540
593
|
|
|
541
|
-
|
|
594
|
+
mapObject(two, function(value, key) {
|
|
542
595
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
543
596
|
one[key] === undefined,
|
|
544
597
|
'mergeObjectsWithNoDuplicateKeys(): ' +
|
|
@@ -586,118 +639,6 @@ function createChainedFunction(one, two) {
|
|
|
586
639
|
};
|
|
587
640
|
}
|
|
588
641
|
|
|
589
|
-
if ("production" !== process.env.NODE_ENV) {
|
|
590
|
-
|
|
591
|
-
var unmountedPropertyWhitelist = {
|
|
592
|
-
constructor: true,
|
|
593
|
-
construct: true,
|
|
594
|
-
isOwnedBy: true, // should be deprecated but can have code mod (internal)
|
|
595
|
-
mountComponent: true,
|
|
596
|
-
mountComponentIntoNode: true,
|
|
597
|
-
props: true,
|
|
598
|
-
type: true,
|
|
599
|
-
_checkPropTypes: true,
|
|
600
|
-
_mountComponentIntoNode: true,
|
|
601
|
-
_processContext: true
|
|
602
|
-
};
|
|
603
|
-
|
|
604
|
-
var hasWarnedOnComponentType = {};
|
|
605
|
-
|
|
606
|
-
var warnIfUnmounted = function(instance, key) {
|
|
607
|
-
if (instance.__hasBeenMounted) {
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
|
-
var name = instance.constructor.displayName || 'Unknown';
|
|
611
|
-
var owner = ReactCurrentOwner.current;
|
|
612
|
-
var ownerName = (owner && owner.constructor.displayName) || 'Unknown';
|
|
613
|
-
var warningKey = key + '|' + name + '|' + ownerName;
|
|
614
|
-
if (hasWarnedOnComponentType.hasOwnProperty(warningKey)) {
|
|
615
|
-
// We have already warned for this combination. Skip it this time.
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
hasWarnedOnComponentType[warningKey] = true;
|
|
619
|
-
|
|
620
|
-
var context = owner ? ' in ' + ownerName + '.' : ' at the top level.';
|
|
621
|
-
var staticMethodExample = '<' + name + ' />.type.' + key + '(...)';
|
|
622
|
-
|
|
623
|
-
console.warn(
|
|
624
|
-
'Invalid access to component property "' + key + '" on ' + name +
|
|
625
|
-
context + ' See http://fb.me/react-warning-descriptors .' +
|
|
626
|
-
' Use a static method instead: ' + staticMethodExample
|
|
627
|
-
);
|
|
628
|
-
};
|
|
629
|
-
|
|
630
|
-
var defineMembraneProperty = function(membrane, prototype, key) {
|
|
631
|
-
Object.defineProperty(membrane, key, {
|
|
632
|
-
|
|
633
|
-
configurable: false,
|
|
634
|
-
enumerable: true,
|
|
635
|
-
|
|
636
|
-
get: function() {
|
|
637
|
-
if (this !== membrane) {
|
|
638
|
-
// When this is accessed through a prototype chain we need to check if
|
|
639
|
-
// this component was mounted.
|
|
640
|
-
warnIfUnmounted(this, key);
|
|
641
|
-
}
|
|
642
|
-
return prototype[key];
|
|
643
|
-
},
|
|
644
|
-
|
|
645
|
-
set: function(value) {
|
|
646
|
-
if (this !== membrane) {
|
|
647
|
-
// When this is accessed through a prototype chain, we first check if
|
|
648
|
-
// this component was mounted. Then we define a value on "this"
|
|
649
|
-
// instance, effectively disabling the membrane on that prototype
|
|
650
|
-
// chain.
|
|
651
|
-
warnIfUnmounted(this, key);
|
|
652
|
-
Object.defineProperty(this, key, {
|
|
653
|
-
enumerable: true,
|
|
654
|
-
configurable: true,
|
|
655
|
-
writable: true,
|
|
656
|
-
value: value
|
|
657
|
-
});
|
|
658
|
-
} else {
|
|
659
|
-
// Otherwise, this should modify the prototype
|
|
660
|
-
prototype[key] = value;
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
});
|
|
665
|
-
};
|
|
666
|
-
|
|
667
|
-
/**
|
|
668
|
-
* Creates a membrane prototype which wraps the original prototype. If any
|
|
669
|
-
* property is accessed in an unmounted state, a warning is issued.
|
|
670
|
-
*
|
|
671
|
-
* @param {object} prototype Original prototype.
|
|
672
|
-
* @return {object} The membrane prototype.
|
|
673
|
-
* @private
|
|
674
|
-
*/
|
|
675
|
-
var createMountWarningMembrane = function(prototype) {
|
|
676
|
-
try {
|
|
677
|
-
var membrane = Object.create(prototype);
|
|
678
|
-
for (var key in prototype) {
|
|
679
|
-
if (unmountedPropertyWhitelist.hasOwnProperty(key)) {
|
|
680
|
-
continue;
|
|
681
|
-
}
|
|
682
|
-
defineMembraneProperty(membrane, prototype, key);
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
membrane.mountComponent = function() {
|
|
686
|
-
this.__hasBeenMounted = true;
|
|
687
|
-
return prototype.mountComponent.apply(this, arguments);
|
|
688
|
-
};
|
|
689
|
-
|
|
690
|
-
return membrane;
|
|
691
|
-
} catch(x) {
|
|
692
|
-
// In IE8 define property will fail on non-DOM objects. If anything in
|
|
693
|
-
// the membrane creation fails, we'll bail out and just use the prototype
|
|
694
|
-
// without warnings.
|
|
695
|
-
return prototype;
|
|
696
|
-
}
|
|
697
|
-
};
|
|
698
|
-
|
|
699
|
-
}
|
|
700
|
-
|
|
701
642
|
/**
|
|
702
643
|
* `ReactCompositeComponent` maintains an auxiliary life cycle state in
|
|
703
644
|
* `this._compositeLifeCycleState` (which can be null).
|
|
@@ -755,21 +696,21 @@ var ReactCompositeComponentMixin = {
|
|
|
755
696
|
/**
|
|
756
697
|
* Base constructor for all composite component.
|
|
757
698
|
*
|
|
758
|
-
* @param {
|
|
759
|
-
* @param {*} children
|
|
699
|
+
* @param {ReactDescriptor} descriptor
|
|
760
700
|
* @final
|
|
761
701
|
* @internal
|
|
762
702
|
*/
|
|
763
|
-
construct: function(
|
|
703
|
+
construct: function(descriptor) {
|
|
764
704
|
// Children can be either an array or more than one argument
|
|
765
705
|
ReactComponent.Mixin.construct.apply(this, arguments);
|
|
706
|
+
ReactOwner.Mixin.construct.apply(this, arguments);
|
|
766
707
|
|
|
767
708
|
this.state = null;
|
|
768
709
|
this._pendingState = null;
|
|
769
710
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
this.
|
|
711
|
+
// This is the public post-processed context. The real context and pending
|
|
712
|
+
// context lives on the descriptor.
|
|
713
|
+
this.context = null;
|
|
773
714
|
|
|
774
715
|
this._compositeLifeCycleState = null;
|
|
775
716
|
},
|
|
@@ -789,7 +730,7 @@ var ReactCompositeComponentMixin = {
|
|
|
789
730
|
* Initializes the component, renders markup, and registers event listeners.
|
|
790
731
|
*
|
|
791
732
|
* @param {string} rootID DOM ID of the root node.
|
|
792
|
-
* @param {ReactReconcileTransaction} transaction
|
|
733
|
+
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
793
734
|
* @param {number} mountDepth number of components in the owner hierarchy
|
|
794
735
|
* @return {?string} Rendered markup to be inserted into the DOM.
|
|
795
736
|
* @final
|
|
@@ -807,13 +748,13 @@ var ReactCompositeComponentMixin = {
|
|
|
807
748
|
);
|
|
808
749
|
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
|
|
809
750
|
|
|
810
|
-
this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
|
|
811
|
-
this.props = this._processProps(this.props);
|
|
812
|
-
|
|
813
751
|
if (this.__reactAutoBindMap) {
|
|
814
752
|
this._bindAutoBindMethods();
|
|
815
753
|
}
|
|
816
754
|
|
|
755
|
+
this.context = this._processContext(this._descriptor._context);
|
|
756
|
+
this.props = this._processProps(this.props);
|
|
757
|
+
|
|
817
758
|
this.state = this.getInitialState ? this.getInitialState() : null;
|
|
818
759
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
819
760
|
typeof this.state === 'object' && !Array.isArray(this.state),
|
|
@@ -834,7 +775,9 @@ var ReactCompositeComponentMixin = {
|
|
|
834
775
|
}
|
|
835
776
|
}
|
|
836
777
|
|
|
837
|
-
this._renderedComponent =
|
|
778
|
+
this._renderedComponent = instantiateReactComponent(
|
|
779
|
+
this._renderValidatedComponent()
|
|
780
|
+
);
|
|
838
781
|
|
|
839
782
|
// Done with mounting, `setState` will now trigger UI changes.
|
|
840
783
|
this._compositeLifeCycleState = null;
|
|
@@ -844,7 +787,7 @@ var ReactCompositeComponentMixin = {
|
|
|
844
787
|
mountDepth + 1
|
|
845
788
|
);
|
|
846
789
|
if (this.componentDidMount) {
|
|
847
|
-
transaction.getReactMountReady().enqueue(this, this
|
|
790
|
+
transaction.getReactMountReady().enqueue(this.componentDidMount, this);
|
|
848
791
|
}
|
|
849
792
|
return markup;
|
|
850
793
|
}
|
|
@@ -863,17 +806,11 @@ var ReactCompositeComponentMixin = {
|
|
|
863
806
|
}
|
|
864
807
|
this._compositeLifeCycleState = null;
|
|
865
808
|
|
|
866
|
-
this._defaultProps = null;
|
|
867
|
-
|
|
868
809
|
this._renderedComponent.unmountComponent();
|
|
869
810
|
this._renderedComponent = null;
|
|
870
811
|
|
|
871
812
|
ReactComponent.Mixin.unmountComponent.call(this);
|
|
872
813
|
|
|
873
|
-
if (this.refs) {
|
|
874
|
-
this.refs = null;
|
|
875
|
-
}
|
|
876
|
-
|
|
877
814
|
// Some existing components rely on this.props even after they've been
|
|
878
815
|
// destroyed (in event handlers).
|
|
879
816
|
// TODO: this.props = null;
|
|
@@ -902,13 +839,12 @@ var ReactCompositeComponentMixin = {
|
|
|
902
839
|
typeof partialState === 'object' || partialState == null,
|
|
903
840
|
'setState(...): takes an object of state variables to update.'
|
|
904
841
|
) : invariant(typeof partialState === 'object' || partialState == null));
|
|
905
|
-
if ("production" !== process.env.NODE_ENV)
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
}
|
|
842
|
+
if ("production" !== process.env.NODE_ENV){
|
|
843
|
+
("production" !== process.env.NODE_ENV ? warning(
|
|
844
|
+
partialState != null,
|
|
845
|
+
'setState(...): You passed an undefined or null state object; ' +
|
|
846
|
+
'instead, use forceUpdate().'
|
|
847
|
+
) : null);
|
|
912
848
|
}
|
|
913
849
|
// Merge with `_pendingState` if it exists, otherwise with existing state.
|
|
914
850
|
this.replaceState(
|
|
@@ -1007,12 +943,17 @@ var ReactCompositeComponentMixin = {
|
|
|
1007
943
|
* @private
|
|
1008
944
|
*/
|
|
1009
945
|
_processProps: function(newProps) {
|
|
1010
|
-
var
|
|
1011
|
-
var
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
946
|
+
var defaultProps = this.constructor.defaultProps;
|
|
947
|
+
var props;
|
|
948
|
+
if (defaultProps) {
|
|
949
|
+
props = merge(newProps);
|
|
950
|
+
for (var propName in defaultProps) {
|
|
951
|
+
if (typeof props[propName] === 'undefined') {
|
|
952
|
+
props[propName] = defaultProps[propName];
|
|
953
|
+
}
|
|
1015
954
|
}
|
|
955
|
+
} else {
|
|
956
|
+
props = newProps;
|
|
1016
957
|
}
|
|
1017
958
|
if ("production" !== process.env.NODE_ENV) {
|
|
1018
959
|
var propTypes = this.constructor.propTypes;
|
|
@@ -1032,15 +973,32 @@ var ReactCompositeComponentMixin = {
|
|
|
1032
973
|
* @private
|
|
1033
974
|
*/
|
|
1034
975
|
_checkPropTypes: function(propTypes, props, location) {
|
|
976
|
+
// TODO: Stop validating prop types here and only use the descriptor
|
|
977
|
+
// validation.
|
|
1035
978
|
var componentName = this.constructor.displayName;
|
|
1036
979
|
for (var propName in propTypes) {
|
|
1037
980
|
if (propTypes.hasOwnProperty(propName)) {
|
|
1038
|
-
|
|
981
|
+
var error =
|
|
982
|
+
propTypes[propName](props, propName, componentName, location);
|
|
983
|
+
if (error instanceof Error) {
|
|
984
|
+
// We may want to extend this logic for similar errors in
|
|
985
|
+
// renderComponent calls, so I'm abstracting it away into
|
|
986
|
+
// a function to minimize refactoring in the future
|
|
987
|
+
var addendum = getDeclarationErrorAddendum(this);
|
|
988
|
+
("production" !== process.env.NODE_ENV ? warning(false, error.message + addendum) : null);
|
|
989
|
+
}
|
|
1039
990
|
}
|
|
1040
991
|
}
|
|
1041
992
|
},
|
|
1042
993
|
|
|
1043
|
-
|
|
994
|
+
/**
|
|
995
|
+
* If any of `_pendingDescriptor`, `_pendingState`, or `_pendingForceUpdate`
|
|
996
|
+
* is set, update the component.
|
|
997
|
+
*
|
|
998
|
+
* @param {ReactReconcileTransaction} transaction
|
|
999
|
+
* @internal
|
|
1000
|
+
*/
|
|
1001
|
+
performUpdateIfNecessary: function(transaction) {
|
|
1044
1002
|
var compositeLifeCycleState = this._compositeLifeCycleState;
|
|
1045
1003
|
// Do not trigger a state transition if we are in the middle of mounting or
|
|
1046
1004
|
// receiving props because both of those will already be doing this.
|
|
@@ -1048,32 +1006,21 @@ var ReactCompositeComponentMixin = {
|
|
|
1048
1006
|
compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
|
|
1049
1007
|
return;
|
|
1050
1008
|
}
|
|
1051
|
-
ReactComponent.Mixin.performUpdateIfNecessary.call(this);
|
|
1052
|
-
},
|
|
1053
1009
|
|
|
1054
|
-
|
|
1055
|
-
* If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is
|
|
1056
|
-
* set, update the component.
|
|
1057
|
-
*
|
|
1058
|
-
* @param {ReactReconcileTransaction} transaction
|
|
1059
|
-
* @internal
|
|
1060
|
-
*/
|
|
1061
|
-
_performUpdateIfNecessary: function(transaction) {
|
|
1062
|
-
if (this._pendingProps == null &&
|
|
1010
|
+
if (this._pendingDescriptor == null &&
|
|
1063
1011
|
this._pendingState == null &&
|
|
1064
|
-
this._pendingContext == null &&
|
|
1065
1012
|
!this._pendingForceUpdate) {
|
|
1066
1013
|
return;
|
|
1067
1014
|
}
|
|
1068
1015
|
|
|
1069
|
-
var
|
|
1070
|
-
var nextContext = this._processContext(nextFullContext);
|
|
1071
|
-
this._pendingContext = null;
|
|
1072
|
-
|
|
1016
|
+
var nextContext = this.context;
|
|
1073
1017
|
var nextProps = this.props;
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1018
|
+
var nextDescriptor = this._descriptor;
|
|
1019
|
+
if (this._pendingDescriptor != null) {
|
|
1020
|
+
nextDescriptor = this._pendingDescriptor;
|
|
1021
|
+
nextContext = this._processContext(nextDescriptor._context);
|
|
1022
|
+
nextProps = this._processProps(nextDescriptor.props);
|
|
1023
|
+
this._pendingDescriptor = null;
|
|
1077
1024
|
|
|
1078
1025
|
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
|
|
1079
1026
|
if (this.componentWillReceiveProps) {
|
|
@@ -1083,37 +1030,46 @@ var ReactCompositeComponentMixin = {
|
|
|
1083
1030
|
|
|
1084
1031
|
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
|
|
1085
1032
|
|
|
1086
|
-
// Unlike props, state, and context, we specifically don't want to set
|
|
1087
|
-
// _pendingOwner to null here because it's possible for a component to have
|
|
1088
|
-
// a null owner, so we instead make `this._owner === this._pendingOwner`
|
|
1089
|
-
// mean that there's no owner change pending.
|
|
1090
|
-
var nextOwner = this._pendingOwner;
|
|
1091
|
-
|
|
1092
1033
|
var nextState = this._pendingState || this.state;
|
|
1093
1034
|
this._pendingState = null;
|
|
1094
1035
|
|
|
1095
1036
|
try {
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1037
|
+
var shouldUpdate =
|
|
1038
|
+
this._pendingForceUpdate ||
|
|
1039
|
+
!this.shouldComponentUpdate ||
|
|
1040
|
+
this.shouldComponentUpdate(nextProps, nextState, nextContext);
|
|
1041
|
+
|
|
1042
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
1043
|
+
if (typeof shouldUpdate === "undefined") {
|
|
1044
|
+
console.warn(
|
|
1045
|
+
(this.constructor.displayName || 'ReactCompositeComponent') +
|
|
1046
|
+
'.shouldComponentUpdate(): Returned undefined instead of a ' +
|
|
1047
|
+
'boolean value. Make sure to return true or false.'
|
|
1048
|
+
);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
if (shouldUpdate) {
|
|
1099
1053
|
this._pendingForceUpdate = false;
|
|
1100
1054
|
// Will set `this.props`, `this.state` and `this.context`.
|
|
1101
1055
|
this._performComponentUpdate(
|
|
1056
|
+
nextDescriptor,
|
|
1102
1057
|
nextProps,
|
|
1103
|
-
nextOwner,
|
|
1104
1058
|
nextState,
|
|
1105
|
-
nextFullContext,
|
|
1106
1059
|
nextContext,
|
|
1107
1060
|
transaction
|
|
1108
1061
|
);
|
|
1109
1062
|
} else {
|
|
1110
1063
|
// If it's determined that a component should not update, we still want
|
|
1111
1064
|
// to set props and state.
|
|
1065
|
+
this._descriptor = nextDescriptor;
|
|
1112
1066
|
this.props = nextProps;
|
|
1113
|
-
this._owner = nextOwner;
|
|
1114
1067
|
this.state = nextState;
|
|
1115
|
-
this._currentContext = nextFullContext;
|
|
1116
1068
|
this.context = nextContext;
|
|
1069
|
+
|
|
1070
|
+
// Owner cannot change because shouldUpdateReactComponent doesn't allow
|
|
1071
|
+
// it. TODO: Remove this._owner completely.
|
|
1072
|
+
this._owner = nextDescriptor._owner;
|
|
1117
1073
|
}
|
|
1118
1074
|
} finally {
|
|
1119
1075
|
this._compositeLifeCycleState = null;
|
|
@@ -1124,24 +1080,22 @@ var ReactCompositeComponentMixin = {
|
|
|
1124
1080
|
* Merges new props and state, notifies delegate methods of update and
|
|
1125
1081
|
* performs update.
|
|
1126
1082
|
*
|
|
1127
|
-
* @param {
|
|
1128
|
-
* @param {
|
|
1083
|
+
* @param {ReactDescriptor} nextDescriptor Next descriptor
|
|
1084
|
+
* @param {object} nextProps Next public object to set as properties.
|
|
1129
1085
|
* @param {?object} nextState Next object to set as state.
|
|
1130
|
-
* @param {?object}
|
|
1131
|
-
* @param {?object} nextContext Next object to set as context.
|
|
1086
|
+
* @param {?object} nextContext Next public object to set as context.
|
|
1132
1087
|
* @param {ReactReconcileTransaction} transaction
|
|
1133
1088
|
* @private
|
|
1134
1089
|
*/
|
|
1135
1090
|
_performComponentUpdate: function(
|
|
1091
|
+
nextDescriptor,
|
|
1136
1092
|
nextProps,
|
|
1137
|
-
nextOwner,
|
|
1138
1093
|
nextState,
|
|
1139
|
-
nextFullContext,
|
|
1140
1094
|
nextContext,
|
|
1141
1095
|
transaction
|
|
1142
1096
|
) {
|
|
1097
|
+
var prevDescriptor = this._descriptor;
|
|
1143
1098
|
var prevProps = this.props;
|
|
1144
|
-
var prevOwner = this._owner;
|
|
1145
1099
|
var prevState = this.state;
|
|
1146
1100
|
var prevContext = this.context;
|
|
1147
1101
|
|
|
@@ -1149,40 +1103,44 @@ var ReactCompositeComponentMixin = {
|
|
|
1149
1103
|
this.componentWillUpdate(nextProps, nextState, nextContext);
|
|
1150
1104
|
}
|
|
1151
1105
|
|
|
1106
|
+
this._descriptor = nextDescriptor;
|
|
1152
1107
|
this.props = nextProps;
|
|
1153
|
-
this._owner = nextOwner;
|
|
1154
1108
|
this.state = nextState;
|
|
1155
|
-
this._currentContext = nextFullContext;
|
|
1156
1109
|
this.context = nextContext;
|
|
1157
1110
|
|
|
1111
|
+
// Owner cannot change because shouldUpdateReactComponent doesn't allow
|
|
1112
|
+
// it. TODO: Remove this._owner completely.
|
|
1113
|
+
this._owner = nextDescriptor._owner;
|
|
1114
|
+
|
|
1158
1115
|
this.updateComponent(
|
|
1159
1116
|
transaction,
|
|
1160
|
-
|
|
1161
|
-
prevOwner,
|
|
1162
|
-
prevState,
|
|
1163
|
-
prevContext
|
|
1117
|
+
prevDescriptor
|
|
1164
1118
|
);
|
|
1165
1119
|
|
|
1166
1120
|
if (this.componentDidUpdate) {
|
|
1167
1121
|
transaction.getReactMountReady().enqueue(
|
|
1168
|
-
this,
|
|
1169
|
-
this
|
|
1122
|
+
this.componentDidUpdate.bind(this, prevProps, prevState, prevContext),
|
|
1123
|
+
this
|
|
1170
1124
|
);
|
|
1171
1125
|
}
|
|
1172
1126
|
},
|
|
1173
1127
|
|
|
1174
|
-
receiveComponent: function(
|
|
1175
|
-
if (
|
|
1176
|
-
|
|
1177
|
-
//
|
|
1178
|
-
// if this is a
|
|
1128
|
+
receiveComponent: function(nextDescriptor, transaction) {
|
|
1129
|
+
if (nextDescriptor === this._descriptor &&
|
|
1130
|
+
nextDescriptor._owner != null) {
|
|
1131
|
+
// Since descriptors are immutable after the owner is rendered,
|
|
1132
|
+
// we can do a cheap identity compare here to determine if this is a
|
|
1133
|
+
// superfluous reconcile. It's possible for state to be mutable but such
|
|
1134
|
+
// change should trigger an update of the owner which would recreate
|
|
1135
|
+
// the descriptor. We explicitly check for the existence of an owner since
|
|
1136
|
+
// it's possible for a descriptor created outside a composite to be
|
|
1137
|
+
// deeply mutated and reused.
|
|
1179
1138
|
return;
|
|
1180
1139
|
}
|
|
1181
1140
|
|
|
1182
|
-
this._pendingContext = nextComponent._currentContext;
|
|
1183
1141
|
ReactComponent.Mixin.receiveComponent.call(
|
|
1184
1142
|
this,
|
|
1185
|
-
|
|
1143
|
+
nextDescriptor,
|
|
1186
1144
|
transaction
|
|
1187
1145
|
);
|
|
1188
1146
|
},
|
|
@@ -1194,34 +1152,32 @@ var ReactCompositeComponentMixin = {
|
|
|
1194
1152
|
* Sophisticated clients may wish to override this.
|
|
1195
1153
|
*
|
|
1196
1154
|
* @param {ReactReconcileTransaction} transaction
|
|
1197
|
-
* @param {
|
|
1198
|
-
* @param {?ReactComponent} prevOwner
|
|
1199
|
-
* @param {?object} prevState
|
|
1200
|
-
* @param {?object} prevContext
|
|
1155
|
+
* @param {ReactDescriptor} prevDescriptor
|
|
1201
1156
|
* @internal
|
|
1202
1157
|
* @overridable
|
|
1203
1158
|
*/
|
|
1204
1159
|
updateComponent: ReactPerf.measure(
|
|
1205
1160
|
'ReactCompositeComponent',
|
|
1206
1161
|
'updateComponent',
|
|
1207
|
-
function(transaction,
|
|
1162
|
+
function(transaction, prevParentDescriptor) {
|
|
1208
1163
|
ReactComponent.Mixin.updateComponent.call(
|
|
1209
1164
|
this,
|
|
1210
1165
|
transaction,
|
|
1211
|
-
|
|
1212
|
-
prevOwner
|
|
1166
|
+
prevParentDescriptor
|
|
1213
1167
|
);
|
|
1214
|
-
|
|
1215
|
-
var
|
|
1216
|
-
|
|
1217
|
-
|
|
1168
|
+
|
|
1169
|
+
var prevComponentInstance = this._renderedComponent;
|
|
1170
|
+
var prevDescriptor = prevComponentInstance._descriptor;
|
|
1171
|
+
var nextDescriptor = this._renderValidatedComponent();
|
|
1172
|
+
if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
|
|
1173
|
+
prevComponentInstance.receiveComponent(nextDescriptor, transaction);
|
|
1218
1174
|
} else {
|
|
1219
1175
|
// These two IDs are actually the same! But nothing should rely on that.
|
|
1220
1176
|
var thisID = this._rootNodeID;
|
|
1221
|
-
var prevComponentID =
|
|
1222
|
-
|
|
1223
|
-
this._renderedComponent =
|
|
1224
|
-
var nextMarkup =
|
|
1177
|
+
var prevComponentID = prevComponentInstance._rootNodeID;
|
|
1178
|
+
prevComponentInstance.unmountComponent();
|
|
1179
|
+
this._renderedComponent = instantiateReactComponent(nextDescriptor);
|
|
1180
|
+
var nextMarkup = this._renderedComponent.mountComponent(
|
|
1225
1181
|
thisID,
|
|
1226
1182
|
transaction,
|
|
1227
1183
|
this._mountDepth + 1
|
|
@@ -1277,20 +1233,28 @@ var ReactCompositeComponentMixin = {
|
|
|
1277
1233
|
function() {
|
|
1278
1234
|
var renderedComponent;
|
|
1279
1235
|
var previousContext = ReactContext.current;
|
|
1280
|
-
ReactContext.current = this._processChildContext(
|
|
1236
|
+
ReactContext.current = this._processChildContext(
|
|
1237
|
+
this._descriptor._context
|
|
1238
|
+
);
|
|
1281
1239
|
ReactCurrentOwner.current = this;
|
|
1282
1240
|
try {
|
|
1283
1241
|
renderedComponent = this.render();
|
|
1242
|
+
if (renderedComponent === null || renderedComponent === false) {
|
|
1243
|
+
renderedComponent = ReactEmptyComponent.getEmptyComponent();
|
|
1244
|
+
ReactEmptyComponent.registerNullComponentID(this._rootNodeID);
|
|
1245
|
+
} else {
|
|
1246
|
+
ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID);
|
|
1247
|
+
}
|
|
1284
1248
|
} finally {
|
|
1285
1249
|
ReactContext.current = previousContext;
|
|
1286
1250
|
ReactCurrentOwner.current = null;
|
|
1287
1251
|
}
|
|
1288
1252
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
1289
|
-
|
|
1253
|
+
ReactDescriptor.isValidDescriptor(renderedComponent),
|
|
1290
1254
|
'%s.render(): A valid ReactComponent must be returned. You may have ' +
|
|
1291
|
-
'returned
|
|
1255
|
+
'returned undefined, an array or some other invalid object.',
|
|
1292
1256
|
this.constructor.displayName || 'ReactCompositeComponent'
|
|
1293
|
-
) : invariant(
|
|
1257
|
+
) : invariant(ReactDescriptor.isValidDescriptor(renderedComponent)));
|
|
1294
1258
|
return renderedComponent;
|
|
1295
1259
|
}
|
|
1296
1260
|
),
|
|
@@ -1333,11 +1297,13 @@ var ReactCompositeComponentMixin = {
|
|
|
1333
1297
|
// ignore the value of "this" that the user is trying to use, so
|
|
1334
1298
|
// let's warn.
|
|
1335
1299
|
if (newThis !== component && newThis !== null) {
|
|
1300
|
+
monitorCodeUse('react_bind_warning', { component: componentName });
|
|
1336
1301
|
console.warn(
|
|
1337
1302
|
'bind(): React component methods may only be bound to the ' +
|
|
1338
1303
|
'component instance. See ' + componentName
|
|
1339
1304
|
);
|
|
1340
1305
|
} else if (!args.length) {
|
|
1306
|
+
monitorCodeUse('react_bind_warning', { component: componentName });
|
|
1341
1307
|
console.warn(
|
|
1342
1308
|
'bind(): You are binding a component method to the component. ' +
|
|
1343
1309
|
'React does this for you automatically in a high-performance ' +
|
|
@@ -1362,18 +1328,6 @@ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
|
|
|
1362
1328
|
mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
|
|
1363
1329
|
mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
|
|
1364
1330
|
|
|
1365
|
-
/**
|
|
1366
|
-
* Checks if a value is a valid component constructor.
|
|
1367
|
-
*
|
|
1368
|
-
* @param {*}
|
|
1369
|
-
* @return {boolean}
|
|
1370
|
-
* @public
|
|
1371
|
-
*/
|
|
1372
|
-
function isValidClass(componentClass) {
|
|
1373
|
-
return componentClass instanceof Function &&
|
|
1374
|
-
'componentConstructor' in componentClass &&
|
|
1375
|
-
componentClass.componentConstructor instanceof Function;
|
|
1376
|
-
}
|
|
1377
1331
|
/**
|
|
1378
1332
|
* Module for creating composite components.
|
|
1379
1333
|
*
|
|
@@ -1396,20 +1350,22 @@ var ReactCompositeComponent = {
|
|
|
1396
1350
|
* @public
|
|
1397
1351
|
*/
|
|
1398
1352
|
createClass: function(spec) {
|
|
1399
|
-
var Constructor = function() {
|
|
1353
|
+
var Constructor = function(props, owner) {
|
|
1354
|
+
this.construct(props, owner);
|
|
1355
|
+
};
|
|
1400
1356
|
Constructor.prototype = new ReactCompositeComponentBase();
|
|
1401
1357
|
Constructor.prototype.constructor = Constructor;
|
|
1402
1358
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
ConvenienceConstructor.componentConstructor = Constructor;
|
|
1409
|
-
Constructor.ConvenienceConstructor = ConvenienceConstructor;
|
|
1410
|
-
ConvenienceConstructor.originalSpec = spec;
|
|
1359
|
+
injectedMixins.forEach(
|
|
1360
|
+
mixSpecIntoComponent.bind(null, Constructor)
|
|
1361
|
+
);
|
|
1362
|
+
|
|
1363
|
+
mixSpecIntoComponent(Constructor, spec);
|
|
1411
1364
|
|
|
1412
|
-
|
|
1365
|
+
// Initialize the defaultProps property after all mixins have been merged
|
|
1366
|
+
if (Constructor.getDefaultProps) {
|
|
1367
|
+
Constructor.defaultProps = Constructor.getDefaultProps();
|
|
1368
|
+
}
|
|
1413
1369
|
|
|
1414
1370
|
("production" !== process.env.NODE_ENV ? invariant(
|
|
1415
1371
|
Constructor.prototype.render,
|
|
@@ -1418,6 +1374,10 @@ var ReactCompositeComponent = {
|
|
|
1418
1374
|
|
|
1419
1375
|
if ("production" !== process.env.NODE_ENV) {
|
|
1420
1376
|
if (Constructor.prototype.componentShouldUpdate) {
|
|
1377
|
+
monitorCodeUse(
|
|
1378
|
+
'react_component_should_update_warning',
|
|
1379
|
+
{ component: spec.displayName }
|
|
1380
|
+
);
|
|
1421
1381
|
console.warn(
|
|
1422
1382
|
(spec.displayName || 'A component') + ' has a method called ' +
|
|
1423
1383
|
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
|
|
@@ -1427,14 +1387,6 @@ var ReactCompositeComponent = {
|
|
|
1427
1387
|
}
|
|
1428
1388
|
}
|
|
1429
1389
|
|
|
1430
|
-
// Expose the convience constructor on the prototype so that it can be
|
|
1431
|
-
// easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for
|
|
1432
|
-
// static methods like <Foo />.type.staticMethod();
|
|
1433
|
-
// This should not be named constructor since this may not be the function
|
|
1434
|
-
// that created the descriptor, and it may not even be a constructor.
|
|
1435
|
-
ConvenienceConstructor.type = Constructor;
|
|
1436
|
-
Constructor.prototype.type = Constructor;
|
|
1437
|
-
|
|
1438
1390
|
// Reduce time spent doing lookups by setting these on the prototype.
|
|
1439
1391
|
for (var methodName in ReactCompositeComponentInterface) {
|
|
1440
1392
|
if (!Constructor.prototype[methodName]) {
|
|
@@ -1442,14 +1394,24 @@ var ReactCompositeComponent = {
|
|
|
1442
1394
|
}
|
|
1443
1395
|
}
|
|
1444
1396
|
|
|
1397
|
+
var descriptorFactory = ReactDescriptor.createFactory(Constructor);
|
|
1398
|
+
|
|
1445
1399
|
if ("production" !== process.env.NODE_ENV) {
|
|
1446
|
-
|
|
1400
|
+
return ReactDescriptorValidator.createFactory(
|
|
1401
|
+
descriptorFactory,
|
|
1402
|
+
Constructor.propTypes,
|
|
1403
|
+
Constructor.contextTypes
|
|
1404
|
+
);
|
|
1447
1405
|
}
|
|
1448
1406
|
|
|
1449
|
-
return
|
|
1407
|
+
return descriptorFactory;
|
|
1450
1408
|
},
|
|
1451
1409
|
|
|
1452
|
-
|
|
1410
|
+
injection: {
|
|
1411
|
+
injectMixin: function(mixin) {
|
|
1412
|
+
injectedMixins.push(mixin);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1453
1415
|
};
|
|
1454
1416
|
|
|
1455
1417
|
module.exports = ReactCompositeComponent;
|