react 15.0.3-alpha.1 → 15.2.0-rc.1

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.
Files changed (122) hide show
  1. package/dist/react-with-addons.js +3311 -2007
  2. package/dist/react-with-addons.min.js +7 -6
  3. package/dist/react.js +2734 -2014
  4. package/dist/react.min.js +6 -6
  5. package/lib/CSSPropertyOperations.js +5 -5
  6. package/lib/CallbackQueue.js +3 -2
  7. package/lib/DOMChildrenOperations.js +42 -7
  8. package/lib/DOMLazyTree.js +18 -5
  9. package/lib/DOMProperty.js +6 -4
  10. package/lib/DOMPropertyOperations.js +35 -12
  11. package/lib/Danger.js +10 -8
  12. package/lib/DisabledInputUtils.js +5 -5
  13. package/lib/EventPluginHub.js +8 -2
  14. package/lib/EventPluginRegistry.js +13 -7
  15. package/lib/EventPluginUtils.js +3 -1
  16. package/lib/HTMLDOMPropertyConfig.js +1 -2
  17. package/lib/LinkedStateMixin.js +1 -0
  18. package/lib/LinkedValueUtils.js +5 -3
  19. package/lib/NativeMethodsMixin.js +6 -4
  20. package/lib/PooledClass.js +3 -1
  21. package/lib/React.js +1 -1
  22. package/lib/ReactCSSTransitionGroup.js +5 -0
  23. package/lib/ReactCSSTransitionGroupChild.js +15 -8
  24. package/lib/ReactChildReconciler.js +15 -6
  25. package/lib/ReactChildren.js +9 -1
  26. package/lib/ReactClass.js +15 -13
  27. package/lib/ReactComponent.js +3 -6
  28. package/lib/ReactComponentBrowserEnvironment.js +0 -5
  29. package/lib/ReactComponentEnvironment.js +3 -1
  30. package/lib/ReactComponentTreeDevtool.js +223 -0
  31. package/lib/ReactComponentTreeTestUtils.js +87 -0
  32. package/lib/ReactComponentWithPureRenderMixin.js +2 -0
  33. package/lib/ReactCompositeComponent.js +208 -119
  34. package/lib/ReactDOM.js +3 -6
  35. package/lib/ReactDOMButton.js +2 -2
  36. package/lib/ReactDOMComponent.js +165 -71
  37. package/lib/ReactDOMComponentTree.js +23 -21
  38. package/lib/ReactDOMDebugTool.js +7 -1
  39. package/lib/ReactDOMEmptyComponent.js +9 -9
  40. package/lib/ReactDOMFactories.js +1 -1
  41. package/lib/ReactDOMIDOperations.js +0 -5
  42. package/lib/ReactDOMInput.js +57 -19
  43. package/lib/ReactDOMOption.js +40 -26
  44. package/lib/ReactDOMSelect.js +3 -3
  45. package/lib/ReactDOMTextComponent.js +28 -26
  46. package/lib/ReactDOMTextarea.js +59 -32
  47. package/lib/ReactDOMTreeTraversal.js +18 -16
  48. package/lib/ReactDOMUnknownPropertyDevtool.js +41 -15
  49. package/lib/ReactDebugTool.js +250 -11
  50. package/lib/ReactDefaultInjection.js +2 -11
  51. package/lib/ReactElement.js +90 -25
  52. package/lib/ReactElementValidator.js +26 -81
  53. package/lib/ReactEventListener.js +2 -2
  54. package/lib/ReactFragment.js +8 -3
  55. package/lib/{ReactNativeComponent.js → ReactHostComponent.js} +10 -29
  56. package/lib/ReactHostOperationHistoryDevtool.js +37 -0
  57. package/lib/ReactInjection.js +2 -4
  58. package/lib/ReactInstanceHandles.js +8 -6
  59. package/lib/ReactLink.js +3 -0
  60. package/lib/ReactMount.js +43 -20
  61. package/lib/ReactMultiChild.js +51 -8
  62. package/lib/ReactNativeAttributePayload.js +5 -2
  63. package/lib/ReactNativeBaseComponent.js +7 -7
  64. package/lib/ReactNativeBridgeEventPlugin.js +1 -1
  65. package/lib/ReactNativeComponentTree.js +8 -6
  66. package/lib/ReactNativeDOMIDOperations.js +4 -8
  67. package/lib/ReactNativeDefaultInjection.js +9 -7
  68. package/lib/ReactNativeGlobalResponderHandler.js +1 -1
  69. package/lib/ReactNativeMount.js +25 -8
  70. package/lib/ReactNativeTagHandles.js +3 -1
  71. package/lib/ReactNativeTextComponent.js +18 -9
  72. package/lib/ReactNativeTreeTraversal.js +11 -11
  73. package/lib/ReactNodeTypes.js +5 -3
  74. package/lib/ReactNoop.js +76 -0
  75. package/lib/ReactOwner.js +4 -2
  76. package/lib/ReactPerf.js +473 -75
  77. package/lib/ReactPropTypes.js +23 -0
  78. package/lib/ReactReconcileTransaction.js +1 -1
  79. package/lib/ReactReconciler.js +57 -11
  80. package/lib/ReactServerRendering.js +24 -3
  81. package/lib/ReactServerRenderingTransaction.js +5 -1
  82. package/lib/ReactSimpleEmptyComponent.js +4 -4
  83. package/lib/ReactTestMount.js +126 -0
  84. package/lib/ReactTestReconcileTransaction.js +100 -0
  85. package/lib/ReactTestRenderer.js +133 -0
  86. package/lib/ReactTestUtils.js +25 -10
  87. package/lib/ReactTransitionChildMapping.js +7 -1
  88. package/lib/ReactTransitionGroup.js +44 -5
  89. package/lib/ReactUpdateQueue.js +9 -1
  90. package/lib/ReactUpdates.js +30 -11
  91. package/lib/ReactVersion.js +1 -1
  92. package/lib/ReactWithAddons.js +1 -1
  93. package/lib/ResponderEventPlugin.js +8 -6
  94. package/lib/ResponderTouchHistoryStore.js +6 -4
  95. package/lib/SimpleEventPlugin.js +3 -1
  96. package/lib/SyntheticEvent.js +2 -3
  97. package/lib/SyntheticUIEvent.js +1 -1
  98. package/lib/Transaction.js +4 -2
  99. package/lib/accumulate.js +3 -1
  100. package/lib/accumulateInto.js +3 -1
  101. package/lib/checkReactTypeSpec.js +71 -0
  102. package/lib/createReactNativeComponentClass.js +2 -2
  103. package/lib/dangerousStyleValue.js +3 -1
  104. package/lib/escapeTextContentForBrowser.js +96 -12
  105. package/lib/findDOMNode.js +8 -4
  106. package/lib/findNodeHandle.js +5 -3
  107. package/lib/flattenChildren.js +13 -4
  108. package/lib/{getNativeComponentFromComposite.js → getHostComponentFromComposite.js} +4 -4
  109. package/lib/instantiateReactComponent.js +44 -10
  110. package/lib/onlyChild.js +10 -5
  111. package/lib/reactComponentExpect.js +3 -3
  112. package/lib/reactProdInvariant.js +38 -0
  113. package/lib/setInnerHTML.js +17 -1
  114. package/lib/setTextContent.js +8 -0
  115. package/lib/shallowCompare.js +1 -0
  116. package/lib/traverseAllChildren.js +3 -1
  117. package/lib/update.js +16 -11
  118. package/package.json +2 -2
  119. package/lib/MetaMatchers.js +0 -118
  120. package/lib/ReactDebugInstanceMap.js +0 -102
  121. package/lib/ReactDefaultPerf.js +0 -316
  122. package/lib/ReactDefaultPerfAnalysis.js +0 -210
@@ -11,8 +11,9 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ var _prodInvariant = require('./reactProdInvariant');
15
+
14
16
  var ReactNoopUpdateQueue = require('./ReactNoopUpdateQueue');
15
- var ReactInstrumentation = require('./ReactInstrumentation');
16
17
 
17
18
  var canDefineProperty = require('./canDefineProperty');
18
19
  var emptyObject = require('fbjs/lib/emptyObject');
@@ -59,11 +60,7 @@ ReactComponent.prototype.isReactComponent = {};
59
60
  * @protected
60
61
  */
61
62
  ReactComponent.prototype.setState = function (partialState, callback) {
62
- !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.') : invariant(false) : void 0;
63
- if (process.env.NODE_ENV !== 'production') {
64
- ReactInstrumentation.debugTool.onSetState();
65
- process.env.NODE_ENV !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0;
66
- }
63
+ !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;
67
64
  this.updater.enqueueSetState(this, partialState);
68
65
  if (callback) {
69
66
  this.updater.enqueueCallback(this, callback, 'setState');
@@ -13,7 +13,6 @@
13
13
 
14
14
  var DOMChildrenOperations = require('./DOMChildrenOperations');
15
15
  var ReactDOMIDOperations = require('./ReactDOMIDOperations');
16
- var ReactPerf = require('./ReactPerf');
17
16
 
18
17
  /**
19
18
  * Abstracts away all functionality of the reconciler that requires knowledge of
@@ -37,8 +36,4 @@ var ReactComponentBrowserEnvironment = {
37
36
 
38
37
  };
39
38
 
40
- ReactPerf.measureMethods(ReactComponentBrowserEnvironment, 'ReactComponentBrowserEnvironment', {
41
- replaceNodeWithMarkup: 'replaceNodeWithMarkup'
42
- });
43
-
44
39
  module.exports = ReactComponentBrowserEnvironment;
@@ -11,6 +11,8 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ var _prodInvariant = require('./reactProdInvariant');
15
+
14
16
  var invariant = require('fbjs/lib/invariant');
15
17
 
16
18
  var injected = false;
@@ -38,7 +40,7 @@ var ReactComponentEnvironment = {
38
40
 
39
41
  injection: {
40
42
  injectEnvironment: function (environment) {
41
- !!injected ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : invariant(false) : void 0;
43
+ !!injected ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : _prodInvariant('104') : void 0;
42
44
  ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment;
43
45
  ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup;
44
46
  ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates;
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Copyright 2016-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactComponentTreeDevtool
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ var _prodInvariant = require('./reactProdInvariant');
15
+
16
+ var ReactCurrentOwner = require('./ReactCurrentOwner');
17
+
18
+ var invariant = require('fbjs/lib/invariant');
19
+ var warning = require('fbjs/lib/warning');
20
+
21
+ var tree = {};
22
+ var unmountedIDs = {};
23
+ var rootIDs = {};
24
+
25
+ function updateTree(id, update) {
26
+ if (!tree[id]) {
27
+ tree[id] = {
28
+ element: null,
29
+ parentID: null,
30
+ ownerID: null,
31
+ text: null,
32
+ childIDs: [],
33
+ displayName: 'Unknown',
34
+ isMounted: false,
35
+ updateCount: 0
36
+ };
37
+ // TODO: We need to do this awkward dance because TopLevelWrapper "never
38
+ // gets mounted" but its display name gets set in instantiateReactComponent
39
+ // before its debug ID is set to 0.
40
+ unmountedIDs[id] = true;
41
+ }
42
+ update(tree[id]);
43
+ }
44
+
45
+ function purgeDeep(id) {
46
+ var item = tree[id];
47
+ if (item) {
48
+ var childIDs = item.childIDs;
49
+
50
+ delete tree[id];
51
+ childIDs.forEach(purgeDeep);
52
+ }
53
+ }
54
+
55
+ function describeComponentFrame(name, source, ownerName) {
56
+ return '\n in ' + name + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
57
+ }
58
+
59
+ function describeID(id) {
60
+ var name = ReactComponentTreeDevtool.getDisplayName(id);
61
+ var element = ReactComponentTreeDevtool.getElement(id);
62
+ var ownerID = ReactComponentTreeDevtool.getOwnerID(id);
63
+ var ownerName;
64
+ if (ownerID) {
65
+ ownerName = ReactComponentTreeDevtool.getDisplayName(ownerID);
66
+ }
67
+ process.env.NODE_ENV !== 'production' ? warning(element, 'ReactComponentTreeDevtool: Missing React element for debugID %s when ' + 'building stack', id) : void 0;
68
+ return describeComponentFrame(name, element && element._source, ownerName);
69
+ }
70
+
71
+ var ReactComponentTreeDevtool = {
72
+ onSetDisplayName: function (id, displayName) {
73
+ updateTree(id, function (item) {
74
+ return item.displayName = displayName;
75
+ });
76
+ },
77
+ onSetChildren: function (id, nextChildIDs) {
78
+ updateTree(id, function (item) {
79
+ item.childIDs = nextChildIDs;
80
+
81
+ nextChildIDs.forEach(function (nextChildID) {
82
+ var nextChild = tree[nextChildID];
83
+ !nextChild ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected devtool events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('68') : void 0;
84
+ !(nextChild.displayName != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onSetDisplayName() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('69') : void 0;
85
+ !(nextChild.childIDs != null || nextChild.text != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onSetChildren() or onSetText() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('70') : void 0;
86
+ !nextChild.isMounted ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0;
87
+ if (nextChild.parentID == null) {
88
+ nextChild.parentID = id;
89
+ // TODO: This shouldn't be necessary but mounting a new root during in
90
+ // componentWillMount currently causes not-yet-mounted components to
91
+ // be purged from our tree data so their parent ID is missing.
92
+ }
93
+ !(nextChild.parentID === id) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onSetParent() and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('72', nextChildID, nextChild.parentID, id) : void 0;
94
+ });
95
+ });
96
+ },
97
+ onSetOwner: function (id, ownerID) {
98
+ updateTree(id, function (item) {
99
+ return item.ownerID = ownerID;
100
+ });
101
+ },
102
+ onSetParent: function (id, parentID) {
103
+ updateTree(id, function (item) {
104
+ return item.parentID = parentID;
105
+ });
106
+ },
107
+ onSetText: function (id, text) {
108
+ updateTree(id, function (item) {
109
+ return item.text = text;
110
+ });
111
+ },
112
+ onBeforeMountComponent: function (id, element) {
113
+ updateTree(id, function (item) {
114
+ return item.element = element;
115
+ });
116
+ },
117
+ onBeforeUpdateComponent: function (id, element) {
118
+ updateTree(id, function (item) {
119
+ return item.element = element;
120
+ });
121
+ },
122
+ onMountComponent: function (id) {
123
+ updateTree(id, function (item) {
124
+ return item.isMounted = true;
125
+ });
126
+ delete unmountedIDs[id];
127
+ },
128
+ onMountRootComponent: function (id) {
129
+ rootIDs[id] = true;
130
+ },
131
+ onUpdateComponent: function (id) {
132
+ updateTree(id, function (item) {
133
+ return item.updateCount++;
134
+ });
135
+ },
136
+ onUnmountComponent: function (id) {
137
+ updateTree(id, function (item) {
138
+ return item.isMounted = false;
139
+ });
140
+ unmountedIDs[id] = true;
141
+ delete rootIDs[id];
142
+ },
143
+ purgeUnmountedComponents: function () {
144
+ if (ReactComponentTreeDevtool._preventPurging) {
145
+ // Should only be used for testing.
146
+ return;
147
+ }
148
+
149
+ for (var id in unmountedIDs) {
150
+ purgeDeep(id);
151
+ }
152
+ unmountedIDs = {};
153
+ },
154
+ isMounted: function (id) {
155
+ var item = tree[id];
156
+ return item ? item.isMounted : false;
157
+ },
158
+ getCurrentStackAddendum: function (topElement) {
159
+ var info = '';
160
+ if (topElement) {
161
+ var type = topElement.type;
162
+ var name = typeof type === 'function' ? type.displayName || type.name : type;
163
+ var owner = topElement._owner;
164
+ info += describeComponentFrame(name || 'Unknown', topElement._source, owner && owner.getName());
165
+ }
166
+
167
+ var currentOwner = ReactCurrentOwner.current;
168
+ var id = currentOwner && currentOwner._debugID;
169
+
170
+ info += ReactComponentTreeDevtool.getStackAddendumByID(id);
171
+ return info;
172
+ },
173
+ getStackAddendumByID: function (id) {
174
+ var info = '';
175
+ while (id) {
176
+ info += describeID(id);
177
+ id = ReactComponentTreeDevtool.getParentID(id);
178
+ }
179
+ return info;
180
+ },
181
+ getChildIDs: function (id) {
182
+ var item = tree[id];
183
+ return item ? item.childIDs : [];
184
+ },
185
+ getDisplayName: function (id) {
186
+ var item = tree[id];
187
+ return item ? item.displayName : 'Unknown';
188
+ },
189
+ getElement: function (id) {
190
+ var item = tree[id];
191
+ return item ? item.element : null;
192
+ },
193
+ getOwnerID: function (id) {
194
+ var item = tree[id];
195
+ return item ? item.ownerID : null;
196
+ },
197
+ getParentID: function (id) {
198
+ var item = tree[id];
199
+ return item ? item.parentID : null;
200
+ },
201
+ getSource: function (id) {
202
+ var item = tree[id];
203
+ var element = item ? item.element : null;
204
+ var source = element != null ? element._source : null;
205
+ return source;
206
+ },
207
+ getText: function (id) {
208
+ var item = tree[id];
209
+ return item ? item.text : null;
210
+ },
211
+ getUpdateCount: function (id) {
212
+ var item = tree[id];
213
+ return item ? item.updateCount : 0;
214
+ },
215
+ getRootIDs: function () {
216
+ return Object.keys(rootIDs);
217
+ },
218
+ getRegisteredIDs: function () {
219
+ return Object.keys(tree);
220
+ }
221
+ };
222
+
223
+ module.exports = ReactComponentTreeDevtool;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Copyright 2016-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactComponentTreeTestUtils
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ var _assign = require('object-assign');
15
+
16
+ var _extends = _assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
17
+
18
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
19
+
20
+ var ReactComponentTreeDevtool = require('./ReactComponentTreeDevtool');
21
+
22
+ function getRootDisplayNames() {
23
+ return ReactComponentTreeDevtool.getRootIDs().map(ReactComponentTreeDevtool.getDisplayName);
24
+ }
25
+
26
+ function getRegisteredDisplayNames() {
27
+ return ReactComponentTreeDevtool.getRegisteredIDs().map(ReactComponentTreeDevtool.getDisplayName);
28
+ }
29
+
30
+ function expectTree(rootID, expectedTree, parentPath) {
31
+ var displayName = ReactComponentTreeDevtool.getDisplayName(rootID);
32
+ var ownerID = ReactComponentTreeDevtool.getOwnerID(rootID);
33
+ var parentID = ReactComponentTreeDevtool.getParentID(rootID);
34
+ var childIDs = ReactComponentTreeDevtool.getChildIDs(rootID);
35
+ var text = ReactComponentTreeDevtool.getText(rootID);
36
+ var element = ReactComponentTreeDevtool.getElement(rootID);
37
+ var path = parentPath ? parentPath + ' > ' + displayName : displayName;
38
+
39
+ function expectEqual(actual, expected, name) {
40
+ // Get Jasmine to print descriptive error messages.
41
+ // We pass path so that we know where the mismatch occurred.
42
+ expect(_defineProperty({
43
+ path: path
44
+ }, name, actual)).toEqual(_defineProperty({
45
+ path: path
46
+ }, name, expected));
47
+ }
48
+
49
+ if (expectedTree.parentDisplayName !== undefined) {
50
+ expectEqual(ReactComponentTreeDevtool.getDisplayName(parentID), expectedTree.parentDisplayName, 'parentDisplayName');
51
+ }
52
+ if (expectedTree.ownerDisplayName !== undefined) {
53
+ expectEqual(ReactComponentTreeDevtool.getDisplayName(ownerID), expectedTree.ownerDisplayName, 'ownerDisplayName');
54
+ }
55
+ if (expectedTree.parentID !== undefined) {
56
+ expectEqual(parentID, expectedTree.parentID, 'parentID');
57
+ }
58
+ if (expectedTree.text !== undefined) {
59
+ expectEqual(text, expectedTree.text, 'text');
60
+ expectEqual('' + element, expectedTree.text, 'element.toString()');
61
+ } else {
62
+ expectEqual(text, null, 'text');
63
+ }
64
+ if (expectedTree.element !== undefined) {
65
+ // TODO: Comparing elements makes tests run out of memory on errors.
66
+ // For now, compare just types.
67
+ expectEqual(element && element.type, expectedTree.element && expectedTree.element.type, 'element.type');
68
+ } else if (text == null) {
69
+ expectEqual(typeof element, 'object', 'typeof element');
70
+ }
71
+ if (expectedTree.children !== undefined) {
72
+ expectEqual(childIDs.length, expectedTree.children.length, 'children.length');
73
+ for (var i = 0; i < childIDs.length; i++) {
74
+ expectTree(childIDs[i], _extends({ parentID: rootID }, expectedTree.children[i]), path);
75
+ }
76
+ } else {
77
+ expectEqual(childIDs, [], 'childIDs');
78
+ }
79
+ }
80
+
81
+ var ReactComponentTreeTestUtils = {
82
+ expectTree: expectTree,
83
+ getRootDisplayNames: getRootDisplayNames,
84
+ getRegisteredDisplayNames: getRegisteredDisplayNames
85
+ };
86
+
87
+ module.exports = ReactComponentTreeTestUtils;
@@ -36,6 +36,8 @@ var shallowCompare = require('./shallowCompare');
36
36
  * complex data structures this mixin may have false-negatives for deeper
37
37
  * differences. Only mixin to components which have simple props and state, or
38
38
  * use `forceUpdate()` when you know deep data structures have changed.
39
+ *
40
+ * See https://facebook.github.io/react/docs/pure-render-mixin.html
39
41
  */
40
42
  var ReactComponentWithPureRenderMixin = {
41
43
  shouldComponentUpdate: function (nextProps, nextState) {
@@ -11,7 +11,8 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- var _assign = require('object-assign');
14
+ var _prodInvariant = require('./reactProdInvariant'),
15
+ _assign = require('object-assign');
15
16
 
16
17
  var ReactComponentEnvironment = require('./ReactComponentEnvironment');
17
18
  var ReactCurrentOwner = require('./ReactCurrentOwner');
@@ -20,28 +21,17 @@ var ReactErrorUtils = require('./ReactErrorUtils');
20
21
  var ReactInstanceMap = require('./ReactInstanceMap');
21
22
  var ReactInstrumentation = require('./ReactInstrumentation');
22
23
  var ReactNodeTypes = require('./ReactNodeTypes');
23
- var ReactPerf = require('./ReactPerf');
24
24
  var ReactPropTypeLocations = require('./ReactPropTypeLocations');
25
- var ReactPropTypeLocationNames = require('./ReactPropTypeLocationNames');
26
25
  var ReactReconciler = require('./ReactReconciler');
27
26
  var ReactUpdateQueue = require('./ReactUpdateQueue');
28
27
 
28
+ var checkReactTypeSpec = require('./checkReactTypeSpec');
29
+
29
30
  var emptyObject = require('fbjs/lib/emptyObject');
30
31
  var invariant = require('fbjs/lib/invariant');
31
32
  var shouldUpdateReactComponent = require('./shouldUpdateReactComponent');
32
33
  var warning = require('fbjs/lib/warning');
33
34
 
34
- function getDeclarationErrorAddendum(component) {
35
- var owner = component._currentElement._owner || null;
36
- if (owner) {
37
- var name = owner.getName();
38
- if (name) {
39
- return ' Check the render method of `' + name + '`.';
40
- }
41
- }
42
- return '';
43
- }
44
-
45
35
  function StatelessComponent(Component) {}
46
36
  StatelessComponent.prototype.render = function () {
47
37
  var Component = ReactInstanceMap.get(this)._currentElement.type;
@@ -53,6 +43,29 @@ StatelessComponent.prototype.render = function () {
53
43
  function warnIfInvalidElement(Component, element) {
54
44
  if (process.env.NODE_ENV !== 'production') {
55
45
  process.env.NODE_ENV !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0;
46
+ process.env.NODE_ENV !== 'production' ? warning(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component') : void 0;
47
+ }
48
+ }
49
+
50
+ function invokeComponentDidMountWithTimer() {
51
+ var publicInstance = this._instance;
52
+ if (this._debugID !== 0) {
53
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidMount');
54
+ }
55
+ publicInstance.componentDidMount();
56
+ if (this._debugID !== 0) {
57
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidMount');
58
+ }
59
+ }
60
+
61
+ function invokeComponentDidUpdateWithTimer(prevProps, prevState, prevContext) {
62
+ var publicInstance = this._instance;
63
+ if (this._debugID !== 0) {
64
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidUpdate');
65
+ }
66
+ publicInstance.componentDidUpdate(prevProps, prevState, prevContext);
67
+ if (this._debugID !== 0) {
68
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidUpdate');
56
69
  }
57
70
  }
58
71
 
@@ -111,10 +124,11 @@ var ReactCompositeComponentMixin = {
111
124
  this._currentElement = element;
112
125
  this._rootNodeID = null;
113
126
  this._instance = null;
114
- this._nativeParent = null;
115
- this._nativeContainerInfo = null;
127
+ this._hostParent = null;
128
+ this._hostContainerInfo = null;
116
129
 
117
130
  // See ReactUpdateQueue
131
+ this._updateBatchNumber = null;
118
132
  this._pendingElement = null;
119
133
  this._pendingStateQueue = null;
120
134
  this._pendingReplaceState = false;
@@ -131,26 +145,30 @@ var ReactCompositeComponentMixin = {
131
145
 
132
146
  // ComponentWillUnmount shall only be called once
133
147
  this._calledComponentWillUnmount = false;
148
+
149
+ if (process.env.NODE_ENV !== 'production') {
150
+ this._warnedAboutRefsInRender = false;
151
+ }
134
152
  },
135
153
 
136
154
  /**
137
155
  * Initializes the component, renders markup, and registers event listeners.
138
156
  *
139
157
  * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
140
- * @param {?object} nativeParent
141
- * @param {?object} nativeContainerInfo
158
+ * @param {?object} hostParent
159
+ * @param {?object} hostContainerInfo
142
160
  * @param {?object} context
143
161
  * @return {?string} Rendered markup to be inserted into the DOM.
144
162
  * @final
145
163
  * @internal
146
164
  */
147
- mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) {
165
+ mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
148
166
  this._context = context;
149
167
  this._mountOrder = nextMountID++;
150
- this._nativeParent = nativeParent;
151
- this._nativeContainerInfo = nativeContainerInfo;
168
+ this._hostParent = hostParent;
169
+ this._hostContainerInfo = hostContainerInfo;
152
170
 
153
- var publicProps = this._processProps(this._currentElement.props);
171
+ var publicProps = this._currentElement.props;
154
172
  var publicContext = this._processContext(context);
155
173
 
156
174
  var Component = this._currentElement.type;
@@ -163,7 +181,7 @@ var ReactCompositeComponentMixin = {
163
181
  if (!shouldConstruct(Component) && (inst == null || inst.render == null)) {
164
182
  renderedElement = inst;
165
183
  warnIfInvalidElement(Component, renderedElement);
166
- !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : invariant(false) : void 0;
184
+ !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : _prodInvariant('105', Component.displayName || Component.name || 'Component') : void 0;
167
185
  inst = new StatelessComponent(Component);
168
186
  }
169
187
 
@@ -209,7 +227,7 @@ var ReactCompositeComponentMixin = {
209
227
  if (initialState === undefined) {
210
228
  inst.state = initialState = null;
211
229
  }
212
- !(typeof initialState === 'object' && !Array.isArray(initialState)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0;
230
+ !(typeof initialState === 'object' && !Array.isArray(initialState)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0;
213
231
 
214
232
  this._pendingStateQueue = null;
215
233
  this._pendingReplaceState = false;
@@ -217,13 +235,17 @@ var ReactCompositeComponentMixin = {
217
235
 
218
236
  var markup;
219
237
  if (inst.unstable_handleError) {
220
- markup = this.performInitialMountWithErrorHandling(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
238
+ markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);
221
239
  } else {
222
- markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
240
+ markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
223
241
  }
224
242
 
225
243
  if (inst.componentDidMount) {
226
- transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
244
+ if (process.env.NODE_ENV !== 'production') {
245
+ transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this);
246
+ } else {
247
+ transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
248
+ }
227
249
  }
228
250
 
229
251
  return markup;
@@ -244,18 +266,42 @@ var ReactCompositeComponentMixin = {
244
266
 
245
267
  _constructComponentWithoutOwner: function (publicProps, publicContext) {
246
268
  var Component = this._currentElement.type;
269
+ var instanceOrElement;
247
270
  if (shouldConstruct(Component)) {
248
- return new Component(publicProps, publicContext, ReactUpdateQueue);
271
+ if (process.env.NODE_ENV !== 'production') {
272
+ if (this._debugID !== 0) {
273
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'ctor');
274
+ }
275
+ }
276
+ instanceOrElement = new Component(publicProps, publicContext, ReactUpdateQueue);
277
+ if (process.env.NODE_ENV !== 'production') {
278
+ if (this._debugID !== 0) {
279
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'ctor');
280
+ }
281
+ }
249
282
  } else {
250
- return Component(publicProps, publicContext, ReactUpdateQueue);
283
+ // This can still be an instance in case of factory components
284
+ // but we'll count this as time spent rendering as the more common case.
285
+ if (process.env.NODE_ENV !== 'production') {
286
+ if (this._debugID !== 0) {
287
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');
288
+ }
289
+ }
290
+ instanceOrElement = Component(publicProps, publicContext, ReactUpdateQueue);
291
+ if (process.env.NODE_ENV !== 'production') {
292
+ if (this._debugID !== 0) {
293
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');
294
+ }
295
+ }
251
296
  }
297
+ return instanceOrElement;
252
298
  },
253
299
 
254
- performInitialMountWithErrorHandling: function (renderedElement, nativeParent, nativeContainerInfo, transaction, context) {
300
+ performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
255
301
  var markup;
256
302
  var checkpoint = transaction.checkpoint();
257
303
  try {
258
- markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
304
+ markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
259
305
  } catch (e) {
260
306
  // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint
261
307
  transaction.rollback(checkpoint);
@@ -270,15 +316,25 @@ var ReactCompositeComponentMixin = {
270
316
 
271
317
  // Try again - we've informed the component about the error, so they can render an error message this time.
272
318
  // If this throws again, the error will bubble up (and can be caught by a higher error boundary).
273
- markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
319
+ markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
274
320
  }
275
321
  return markup;
276
322
  },
277
323
 
278
- performInitialMount: function (renderedElement, nativeParent, nativeContainerInfo, transaction, context) {
324
+ performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
279
325
  var inst = this._instance;
280
326
  if (inst.componentWillMount) {
327
+ if (process.env.NODE_ENV !== 'production') {
328
+ if (this._debugID !== 0) {
329
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillMount');
330
+ }
331
+ }
281
332
  inst.componentWillMount();
333
+ if (process.env.NODE_ENV !== 'production') {
334
+ if (this._debugID !== 0) {
335
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillMount');
336
+ }
337
+ }
282
338
  // When mounting, calls to `setState` by `componentWillMount` will set
283
339
  // `this._pendingStateQueue` without triggering a re-render.
284
340
  if (this._pendingStateQueue) {
@@ -292,15 +348,27 @@ var ReactCompositeComponentMixin = {
292
348
  }
293
349
 
294
350
  this._renderedNodeType = ReactNodeTypes.getType(renderedElement);
295
- this._renderedComponent = this._instantiateReactComponent(renderedElement);
351
+ var child = this._instantiateReactComponent(renderedElement);
352
+ this._renderedComponent = child;
353
+ if (process.env.NODE_ENV !== 'production') {
354
+ if (child._debugID !== 0 && this._debugID !== 0) {
355
+ ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);
356
+ }
357
+ }
358
+
359
+ var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context));
296
360
 
297
- var markup = ReactReconciler.mountComponent(this._renderedComponent, transaction, nativeParent, nativeContainerInfo, this._processChildContext(context));
361
+ if (process.env.NODE_ENV !== 'production') {
362
+ if (this._debugID !== 0) {
363
+ ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);
364
+ }
365
+ }
298
366
 
299
367
  return markup;
300
368
  },
301
369
 
302
- getNativeNode: function () {
303
- return ReactReconciler.getNativeNode(this._renderedComponent);
370
+ getHostNode: function () {
371
+ return ReactReconciler.getHostNode(this._renderedComponent);
304
372
  },
305
373
 
306
374
  /**
@@ -317,12 +385,22 @@ var ReactCompositeComponentMixin = {
317
385
 
318
386
  if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {
319
387
  inst._calledComponentWillUnmount = true;
388
+ if (process.env.NODE_ENV !== 'production') {
389
+ if (this._debugID !== 0) {
390
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUnmount');
391
+ }
392
+ }
320
393
  if (safely) {
321
394
  var name = this.getName() + '.componentWillUnmount()';
322
395
  ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));
323
396
  } else {
324
397
  inst.componentWillUnmount();
325
398
  }
399
+ if (process.env.NODE_ENV !== 'production') {
400
+ if (this._debugID !== 0) {
401
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUnmount');
402
+ }
403
+ }
326
404
  }
327
405
 
328
406
  if (this._renderedComponent) {
@@ -393,7 +471,7 @@ var ReactCompositeComponentMixin = {
393
471
  if (process.env.NODE_ENV !== 'production') {
394
472
  var Component = this._currentElement.type;
395
473
  if (Component.contextTypes) {
396
- this._checkPropTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);
474
+ this._checkContextTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);
397
475
  }
398
476
  }
399
477
  return maskedContext;
@@ -415,12 +493,12 @@ var ReactCompositeComponentMixin = {
415
493
  ReactInstrumentation.debugTool.onEndProcessingChildContext();
416
494
  }
417
495
  if (childContext) {
418
- !(typeof Component.childContextTypes === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0;
496
+ !(typeof Component.childContextTypes === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0;
419
497
  if (process.env.NODE_ENV !== 'production') {
420
- this._checkPropTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);
498
+ this._checkContextTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);
421
499
  }
422
500
  for (var name in childContext) {
423
- !(name in Component.childContextTypes) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : invariant(false) : void 0;
501
+ !(name in Component.childContextTypes) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name) : void 0;
424
502
  }
425
503
  return _assign({}, currentContext, childContext);
426
504
  }
@@ -428,62 +506,15 @@ var ReactCompositeComponentMixin = {
428
506
  },
429
507
 
430
508
  /**
431
- * Processes props by setting default values for unspecified props and
432
- * asserting that the props are valid. Does not mutate its argument; returns
433
- * a new props object with defaults merged in.
434
- *
435
- * @param {object} newProps
436
- * @return {object}
437
- * @private
438
- */
439
- _processProps: function (newProps) {
440
- if (process.env.NODE_ENV !== 'production') {
441
- var Component = this._currentElement.type;
442
- if (Component.propTypes) {
443
- this._checkPropTypes(Component.propTypes, newProps, ReactPropTypeLocations.prop);
444
- }
445
- }
446
- return newProps;
447
- },
448
-
449
- /**
450
- * Assert that the props are valid
509
+ * Assert that the context types are valid
451
510
  *
452
- * @param {object} propTypes Map of prop name to a ReactPropType
453
- * @param {object} props
511
+ * @param {object} typeSpecs Map of context field to a ReactPropType
512
+ * @param {object} values Runtime values that need to be type-checked
454
513
  * @param {string} location e.g. "prop", "context", "child context"
455
514
  * @private
456
515
  */
457
- _checkPropTypes: function (propTypes, props, location) {
458
- // TODO: Stop validating prop types here and only use the element
459
- // validation.
460
- var componentName = this.getName();
461
- for (var propName in propTypes) {
462
- if (propTypes.hasOwnProperty(propName)) {
463
- var error;
464
- try {
465
- // This is intentionally an invariant that gets caught. It's the same
466
- // behavior as without this statement except with a better message.
467
- !(typeof propTypes[propName] === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually ' + 'from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], propName) : invariant(false) : void 0;
468
- error = propTypes[propName](props, propName, componentName, location);
469
- } catch (ex) {
470
- error = ex;
471
- }
472
- if (error instanceof Error) {
473
- // We may want to extend this logic for similar errors in
474
- // top-level render calls, so I'm abstracting it away into
475
- // a function to minimize refactoring in the future
476
- var addendum = getDeclarationErrorAddendum(this);
477
-
478
- if (location === ReactPropTypeLocations.prop) {
479
- // Preface gives us something to blacklist in warning module
480
- process.env.NODE_ENV !== 'production' ? warning(false, 'Failed Composite propType: %s%s', error.message, addendum) : void 0;
481
- } else {
482
- process.env.NODE_ENV !== 'production' ? warning(false, 'Failed Context Types: %s%s', error.message, addendum) : void 0;
483
- }
484
- }
485
- }
486
- }
516
+ _checkContextTypes: function (typeSpecs, values, location) {
517
+ checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);
487
518
  },
488
519
 
489
520
  receiveComponent: function (nextElement, transaction, nextContext) {
@@ -505,10 +536,10 @@ var ReactCompositeComponentMixin = {
505
536
  performUpdateIfNecessary: function (transaction) {
506
537
  if (this._pendingElement != null) {
507
538
  ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);
508
- }
509
-
510
- if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
539
+ } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
511
540
  this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);
541
+ } else {
542
+ this._updateBatchNumber = null;
512
543
  }
513
544
  },
514
545
 
@@ -529,6 +560,8 @@ var ReactCompositeComponentMixin = {
529
560
  */
530
561
  updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {
531
562
  var inst = this._instance;
563
+ !(inst != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Attempted to update component `%s` that has already been unmounted (or failed to mount).', this.getName() || 'ReactCompositeComponent') : _prodInvariant('136', this.getName() || 'ReactCompositeComponent') : void 0;
564
+
532
565
  var willReceive = false;
533
566
  var nextContext;
534
567
  var nextProps;
@@ -541,13 +574,10 @@ var ReactCompositeComponentMixin = {
541
574
  willReceive = true;
542
575
  }
543
576
 
544
- // Distinguish between a props update versus a simple state update
545
- if (prevParentElement === nextParentElement) {
546
- // Skip checking prop types again -- we don't read inst.props to avoid
547
- // warning for DOM component props in this upgrade
548
- nextProps = nextParentElement.props;
549
- } else {
550
- nextProps = this._processProps(nextParentElement.props);
577
+ nextProps = nextParentElement.props;
578
+
579
+ // Not a simple state update but a props update
580
+ if (prevParentElement !== nextParentElement) {
551
581
  willReceive = true;
552
582
  }
553
583
 
@@ -555,17 +585,41 @@ var ReactCompositeComponentMixin = {
555
585
  // _pendingStateQueue which will ensure that any state updates gets
556
586
  // immediately reconciled instead of waiting for the next batch.
557
587
  if (willReceive && inst.componentWillReceiveProps) {
588
+ if (process.env.NODE_ENV !== 'production') {
589
+ if (this._debugID !== 0) {
590
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillReceiveProps');
591
+ }
592
+ }
558
593
  inst.componentWillReceiveProps(nextProps, nextContext);
594
+ if (process.env.NODE_ENV !== 'production') {
595
+ if (this._debugID !== 0) {
596
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillReceiveProps');
597
+ }
598
+ }
559
599
  }
560
600
 
561
601
  var nextState = this._processPendingState(nextProps, nextContext);
602
+ var shouldUpdate = true;
562
603
 
563
- var shouldUpdate = this._pendingForceUpdate || !inst.shouldComponentUpdate || inst.shouldComponentUpdate(nextProps, nextState, nextContext);
604
+ if (!this._pendingForceUpdate && inst.shouldComponentUpdate) {
605
+ if (process.env.NODE_ENV !== 'production') {
606
+ if (this._debugID !== 0) {
607
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'shouldComponentUpdate');
608
+ }
609
+ }
610
+ shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
611
+ if (process.env.NODE_ENV !== 'production') {
612
+ if (this._debugID !== 0) {
613
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'shouldComponentUpdate');
614
+ }
615
+ }
616
+ }
564
617
 
565
618
  if (process.env.NODE_ENV !== 'production') {
566
619
  process.env.NODE_ENV !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0;
567
620
  }
568
621
 
622
+ this._updateBatchNumber = null;
569
623
  if (shouldUpdate) {
570
624
  this._pendingForceUpdate = false;
571
625
  // Will set `this.props`, `this.state` and `this.context`.
@@ -631,7 +685,17 @@ var ReactCompositeComponentMixin = {
631
685
  }
632
686
 
633
687
  if (inst.componentWillUpdate) {
688
+ if (process.env.NODE_ENV !== 'production') {
689
+ if (this._debugID !== 0) {
690
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUpdate');
691
+ }
692
+ }
634
693
  inst.componentWillUpdate(nextProps, nextState, nextContext);
694
+ if (process.env.NODE_ENV !== 'production') {
695
+ if (this._debugID !== 0) {
696
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUpdate');
697
+ }
698
+ }
635
699
  }
636
700
 
637
701
  this._currentElement = nextElement;
@@ -643,7 +707,11 @@ var ReactCompositeComponentMixin = {
643
707
  this._updateRenderedComponent(transaction, unmaskedContext);
644
708
 
645
709
  if (hasComponentDidUpdate) {
646
- transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
710
+ if (process.env.NODE_ENV !== 'production') {
711
+ transaction.getReactMountReady().enqueue(invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext), this);
712
+ } else {
713
+ transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
714
+ }
647
715
  }
648
716
  },
649
717
 
@@ -660,13 +728,27 @@ var ReactCompositeComponentMixin = {
660
728
  if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
661
729
  ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));
662
730
  } else {
663
- var oldNativeNode = ReactReconciler.getNativeNode(prevComponentInstance);
731
+ var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);
664
732
  ReactReconciler.unmountComponent(prevComponentInstance, false);
665
733
 
666
734
  this._renderedNodeType = ReactNodeTypes.getType(nextRenderedElement);
667
- this._renderedComponent = this._instantiateReactComponent(nextRenderedElement);
668
- var nextMarkup = ReactReconciler.mountComponent(this._renderedComponent, transaction, this._nativeParent, this._nativeContainerInfo, this._processChildContext(context));
669
- this._replaceNodeWithMarkup(oldNativeNode, nextMarkup);
735
+ var child = this._instantiateReactComponent(nextRenderedElement);
736
+ this._renderedComponent = child;
737
+ if (process.env.NODE_ENV !== 'production') {
738
+ if (child._debugID !== 0 && this._debugID !== 0) {
739
+ ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);
740
+ }
741
+ }
742
+
743
+ var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context));
744
+
745
+ if (process.env.NODE_ENV !== 'production') {
746
+ if (this._debugID !== 0) {
747
+ ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);
748
+ }
749
+ }
750
+
751
+ this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);
670
752
  }
671
753
  },
672
754
 
@@ -675,8 +757,8 @@ var ReactCompositeComponentMixin = {
675
757
  *
676
758
  * @protected
677
759
  */
678
- _replaceNodeWithMarkup: function (oldNativeNode, nextMarkup) {
679
- ReactComponentEnvironment.replaceNodeWithMarkup(oldNativeNode, nextMarkup);
760
+ _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {
761
+ ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);
680
762
  },
681
763
 
682
764
  /**
@@ -684,7 +766,19 @@ var ReactCompositeComponentMixin = {
684
766
  */
685
767
  _renderValidatedComponentWithoutOwnerOrContext: function () {
686
768
  var inst = this._instance;
769
+
770
+ if (process.env.NODE_ENV !== 'production') {
771
+ if (this._debugID !== 0) {
772
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');
773
+ }
774
+ }
687
775
  var renderedComponent = inst.render();
776
+ if (process.env.NODE_ENV !== 'production') {
777
+ if (this._debugID !== 0) {
778
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');
779
+ }
780
+ }
781
+
688
782
  if (process.env.NODE_ENV !== 'production') {
689
783
  // We allow auto-mocks to proceed as if they're returning null.
690
784
  if (renderedComponent === undefined && inst.render._isMockFunction) {
@@ -710,7 +804,8 @@ var ReactCompositeComponentMixin = {
710
804
  }
711
805
  !(
712
806
  // TODO: An `isValidNode` function would probably be more appropriate
713
- renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : invariant(false) : void 0;
807
+ renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : _prodInvariant('109', this.getName() || 'ReactCompositeComponent') : void 0;
808
+
714
809
  return renderedComponent;
715
810
  },
716
811
 
@@ -724,7 +819,7 @@ var ReactCompositeComponentMixin = {
724
819
  */
725
820
  attachRef: function (ref, component) {
726
821
  var inst = this.getPublicInstance();
727
- !(inst != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : invariant(false) : void 0;
822
+ !(inst != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : _prodInvariant('110') : void 0;
728
823
  var publicComponentInstance = component.getPublicInstance();
729
824
  if (process.env.NODE_ENV !== 'production') {
730
825
  var componentName = component && component.getName ? component.getName() : 'a component';
@@ -779,12 +874,6 @@ var ReactCompositeComponentMixin = {
779
874
 
780
875
  };
781
876
 
782
- ReactPerf.measureMethods(ReactCompositeComponentMixin, 'ReactCompositeComponent', {
783
- mountComponent: 'mountComponent',
784
- updateComponent: 'updateComponent',
785
- _renderValidatedComponent: '_renderValidatedComponent'
786
- });
787
-
788
877
  var ReactCompositeComponent = {
789
878
 
790
879
  Mixin: ReactCompositeComponentMixin