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.
Files changed (114) hide show
  1. package/README.md +3 -0
  2. package/dist/JSXTransformer.js +13448 -0
  3. package/dist/react-with-addons.js +20235 -0
  4. package/dist/react-with-addons.min.js +22 -0
  5. package/dist/react.js +18443 -0
  6. package/dist/react.min.js +21 -0
  7. package/lib/AutoFocusMixin.js +3 -1
  8. package/lib/BeforeInputEventPlugin.js +222 -0
  9. package/lib/CSSPropertyOperations.js +3 -3
  10. package/lib/{ReactMountReady.js → CallbackQueue.js} +32 -24
  11. package/lib/ChangeEventPlugin.js +1 -1
  12. package/lib/CompositionEventPlugin.js +5 -1
  13. package/lib/DOMChildrenOperations.js +33 -20
  14. package/lib/DOMProperty.js +51 -21
  15. package/lib/DOMPropertyOperations.js +28 -16
  16. package/lib/DefaultEventPluginOrder.js +1 -0
  17. package/lib/EventConstants.js +1 -0
  18. package/lib/EventListener.js +5 -2
  19. package/lib/EventPluginHub.js +2 -5
  20. package/lib/EventPluginRegistry.js +6 -4
  21. package/lib/EventPluginUtils.js +11 -1
  22. package/lib/ExecutionEnvironment.js +8 -2
  23. package/lib/{DefaultDOMPropertyConfig.js → HTMLDOMPropertyConfig.js} +41 -58
  24. package/lib/LinkedValueUtils.js +26 -28
  25. package/lib/LocalEventTrapMixin.js +52 -0
  26. package/lib/React.js +39 -3
  27. package/lib/ReactBrowserComponentMixin.js +46 -0
  28. package/lib/{ReactEventEmitter.js → ReactBrowserEventEmitter.js} +115 -94
  29. package/lib/ReactCSSTransitionGroup.js +12 -10
  30. package/lib/ReactCSSTransitionGroupChild.js +2 -5
  31. package/lib/ReactChildren.js +31 -10
  32. package/lib/ReactComponent.js +119 -223
  33. package/lib/ReactComponentBrowserEnvironment.js +3 -36
  34. package/lib/ReactComponentWithPureRenderMixin.js +54 -0
  35. package/lib/ReactCompositeComponent.js +249 -287
  36. package/lib/ReactDOM.js +25 -23
  37. package/lib/ReactDOMButton.js +2 -1
  38. package/lib/ReactDOMComponent.js +42 -23
  39. package/lib/ReactDOMForm.js +7 -12
  40. package/lib/ReactDOMIDOperations.js +2 -31
  41. package/lib/ReactDOMImg.js +7 -13
  42. package/lib/ReactDOMInput.js +2 -1
  43. package/lib/ReactDOMOption.js +11 -7
  44. package/lib/ReactDOMSelect.js +18 -16
  45. package/lib/ReactDOMSelection.js +35 -10
  46. package/lib/ReactDOMTextarea.js +9 -7
  47. package/lib/ReactDefaultBatchingStrategy.js +3 -3
  48. package/lib/ReactDefaultInjection.js +27 -14
  49. package/lib/ReactDefaultPerf.js +28 -11
  50. package/lib/ReactDefaultPerfAnalysis.js +4 -0
  51. package/lib/ReactDescriptor.js +251 -0
  52. package/lib/ReactDescriptorValidator.js +283 -0
  53. package/lib/ReactEmptyComponent.js +78 -0
  54. package/lib/ReactEventEmitterMixin.js +1 -3
  55. package/lib/ReactEventListener.js +189 -0
  56. package/lib/ReactInjection.js +8 -2
  57. package/lib/ReactInputSelection.js +2 -1
  58. package/lib/ReactLink.js +24 -0
  59. package/lib/ReactMount.js +61 -21
  60. package/lib/ReactMultiChild.js +18 -13
  61. package/lib/ReactOwner.js +6 -1
  62. package/lib/ReactPropTransferer.js +44 -29
  63. package/lib/ReactPropTypes.js +226 -242
  64. package/lib/ReactPutListenerQueue.js +2 -2
  65. package/lib/ReactReconcileTransaction.js +21 -20
  66. package/lib/ReactServerRendering.js +41 -11
  67. package/lib/ReactServerRenderingTransaction.js +115 -0
  68. package/lib/ReactTestUtils.js +39 -21
  69. package/lib/ReactTextComponent.js +21 -13
  70. package/lib/ReactTransitionChildMapping.js +2 -2
  71. package/lib/ReactTransitionEvents.js +19 -0
  72. package/lib/ReactTransitionGroup.js +9 -6
  73. package/lib/ReactUpdates.js +139 -22
  74. package/lib/ReactWithAddons.js +8 -3
  75. package/lib/SVGDOMPropertyConfig.js +97 -0
  76. package/lib/SimpleEventPlugin.js +7 -1
  77. package/lib/SyntheticInputEvent.js +52 -0
  78. package/lib/SyntheticKeyboardEvent.js +33 -4
  79. package/lib/SyntheticMouseEvent.js +3 -0
  80. package/lib/SyntheticTouchEvent.js +4 -1
  81. package/lib/SyntheticUIEvent.js +24 -2
  82. package/lib/Transaction.js +0 -32
  83. package/lib/cloneWithProps.js +10 -8
  84. package/lib/createFullPageComponent.js +1 -1
  85. package/lib/dangerousStyleValue.js +11 -5
  86. package/lib/{ReactComponentEnvironment.js → emptyObject.js} +6 -5
  87. package/lib/escapeTextForBrowser.js +2 -3
  88. package/lib/flattenChildren.js +9 -7
  89. package/lib/focusNode.js +33 -0
  90. package/lib/getEventKey.js +35 -5
  91. package/lib/getEventModifierState.js +52 -0
  92. package/lib/getMarkupWrap.js +2 -0
  93. package/lib/getTextContentAccessor.js +1 -1
  94. package/lib/hyphenate.js +3 -0
  95. package/lib/hyphenateStyleName.js +46 -0
  96. package/lib/instantiateReactComponent.js +62 -0
  97. package/lib/invariant.js +17 -19
  98. package/lib/isNode.js +1 -1
  99. package/lib/{objMap.js → mapObject.js} +8 -3
  100. package/lib/mergeHelpers.js +11 -0
  101. package/lib/mergeInto.js +3 -2
  102. package/lib/monitorCodeUse.js +37 -0
  103. package/lib/onlyChild.js +3 -3
  104. package/lib/performance.js +33 -0
  105. package/lib/performanceNow.js +5 -14
  106. package/lib/setInnerHTML.js +77 -0
  107. package/lib/shouldUpdateReactComponent.js +14 -28
  108. package/lib/toArray.js +1 -1
  109. package/lib/traverseAllChildren.js +9 -5
  110. package/lib/update.js +171 -0
  111. package/package.json +4 -3
  112. package/lib/ReactEventTopLevelCallback.js +0 -149
  113. package/lib/createObjectFrom.js +0 -61
  114. package/lib/objMapKeyVal.js +0 -47
@@ -18,9 +18,12 @@
18
18
 
19
19
  "use strict";
20
20
 
21
+ var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
21
22
  var ReactCompositeComponent = require("./ReactCompositeComponent");
22
23
  var ReactDOM = require("./ReactDOM");
23
24
 
25
+ var warning = require("./warning");
26
+
24
27
  // Store a reference to the <option> `ReactDOMComponent`.
25
28
  var option = ReactDOM.option;
26
29
 
@@ -30,15 +33,16 @@ var option = ReactDOM.option;
30
33
  var ReactDOMOption = ReactCompositeComponent.createClass({
31
34
  displayName: 'ReactDOMOption',
32
35
 
36
+ mixins: [ReactBrowserComponentMixin],
37
+
33
38
  componentWillMount: function() {
34
39
  // TODO (yungsters): Remove support for `selected` in <option>.
35
- if (this.props.selected != null) {
36
- if ("production" !== process.env.NODE_ENV) {
37
- console.warn(
38
- 'Use the `defaultValue` or `value` props on <select> instead of ' +
39
- 'setting `selected` on <option>.'
40
- );
41
- }
40
+ if ("production" !== process.env.NODE_ENV) {
41
+ ("production" !== process.env.NODE_ENV ? warning(
42
+ this.props.selected == null,
43
+ 'Use the `defaultValue` or `value` props on <select> instead of ' +
44
+ 'setting `selected` on <option>.'
45
+ ) : null);
42
46
  }
43
47
  },
44
48
 
@@ -20,10 +20,10 @@
20
20
 
21
21
  var AutoFocusMixin = require("./AutoFocusMixin");
22
22
  var LinkedValueUtils = require("./LinkedValueUtils");
23
+ var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
23
24
  var ReactCompositeComponent = require("./ReactCompositeComponent");
24
25
  var ReactDOM = require("./ReactDOM");
25
26
 
26
- var invariant = require("./invariant");
27
27
  var merge = require("./merge");
28
28
 
29
29
  // Store a reference to the <select> `ReactDOMComponent`.
@@ -38,19 +38,19 @@ function selectValueType(props, propName, componentName) {
38
38
  return;
39
39
  }
40
40
  if (props.multiple) {
41
- ("production" !== process.env.NODE_ENV ? invariant(
42
- Array.isArray(props[propName]),
43
- 'The `%s` prop supplied to <select> must be an array if `multiple` is ' +
44
- 'true.',
45
- propName
46
- ) : invariant(Array.isArray(props[propName])));
41
+ if (!Array.isArray(props[propName])) {
42
+ return new Error(
43
+ ("The `" + propName + "` prop supplied to <select> must be an array if ") +
44
+ ("`multiple` is true.")
45
+ );
46
+ }
47
47
  } else {
48
- ("production" !== process.env.NODE_ENV ? invariant(
49
- !Array.isArray(props[propName]),
50
- 'The `%s` prop supplied to <select> must be a scalar value if ' +
51
- '`multiple` is false.',
52
- propName
53
- ) : invariant(!Array.isArray(props[propName])));
48
+ if (Array.isArray(props[propName])) {
49
+ return new Error(
50
+ ("The `" + propName + "` prop supplied to <select> must be a scalar ") +
51
+ ("value if `multiple` is false.")
52
+ );
53
+ }
54
54
  }
55
55
  }
56
56
 
@@ -103,7 +103,7 @@ function updateOptions(component, propValue) {
103
103
  var ReactDOMSelect = ReactCompositeComponent.createClass({
104
104
  displayName: 'ReactDOMSelect',
105
105
 
106
- mixins: [AutoFocusMixin, LinkedValueUtils.Mixin],
106
+ mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
107
107
 
108
108
  propTypes: {
109
109
  defaultValue: selectValueType,
@@ -141,9 +141,11 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({
141
141
  updateOptions(this, LinkedValueUtils.getValue(this));
142
142
  },
143
143
 
144
- componentDidUpdate: function() {
144
+ componentDidUpdate: function(prevProps) {
145
145
  var value = LinkedValueUtils.getValue(this);
146
- if (value != null) {
146
+ var prevMultiple = !!prevProps.multiple;
147
+ var multiple = !!this.props.multiple;
148
+ if (value != null || prevMultiple !== multiple) {
147
149
  updateOptions(this, value);
148
150
  }
149
151
  },
@@ -18,9 +18,20 @@
18
18
 
19
19
  "use strict";
20
20
 
21
+ var ExecutionEnvironment = require("./ExecutionEnvironment");
22
+
21
23
  var getNodeForCharacterOffset = require("./getNodeForCharacterOffset");
22
24
  var getTextContentAccessor = require("./getTextContentAccessor");
23
25
 
26
+ /**
27
+ * While `isCollapsed` is available on the Selection object and `collapsed`
28
+ * is available on the Range object, IE11 sometimes gets them wrong.
29
+ * If the anchor/focus nodes and offsets are the same, the range is collapsed.
30
+ */
31
+ function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {
32
+ return anchorNode === focusNode && anchorOffset === focusOffset;
33
+ }
34
+
24
35
  /**
25
36
  * Get the appropriate anchor and focus node/offset pairs for IE.
26
37
  *
@@ -71,13 +82,31 @@ function getModernOffsets(node) {
71
82
  var focusOffset = selection.focusOffset;
72
83
 
73
84
  var currentRange = selection.getRangeAt(0);
74
- var rangeLength = currentRange.toString().length;
85
+
86
+ // If the node and offset values are the same, the selection is collapsed.
87
+ // `Selection.isCollapsed` is available natively, but IE sometimes gets
88
+ // this value wrong.
89
+ var isSelectionCollapsed = isCollapsed(
90
+ selection.anchorNode,
91
+ selection.anchorOffset,
92
+ selection.focusNode,
93
+ selection.focusOffset
94
+ );
95
+
96
+ var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;
75
97
 
76
98
  var tempRange = currentRange.cloneRange();
77
99
  tempRange.selectNodeContents(node);
78
100
  tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);
79
101
 
80
- var start = tempRange.toString().length;
102
+ var isTempRangeCollapsed = isCollapsed(
103
+ tempRange.startContainer,
104
+ tempRange.startOffset,
105
+ tempRange.endContainer,
106
+ tempRange.endOffset
107
+ );
108
+
109
+ var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;
81
110
  var end = start + rangeLength;
82
111
 
83
112
  // Detect whether the selection is backward.
@@ -167,23 +196,19 @@ function setModernOffsets(node, offsets) {
167
196
  }
168
197
  }
169
198
 
199
+ var useIEOffsets = ExecutionEnvironment.canUseDOM && document.selection;
200
+
170
201
  var ReactDOMSelection = {
171
202
  /**
172
203
  * @param {DOMElement} node
173
204
  */
174
- getOffsets: function(node) {
175
- var getOffsets = document.selection ? getIEOffsets : getModernOffsets;
176
- return getOffsets(node);
177
- },
205
+ getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,
178
206
 
179
207
  /**
180
208
  * @param {DOMElement|DOMTextNode} node
181
209
  * @param {object} offsets
182
210
  */
183
- setOffsets: function(node, offsets) {
184
- var setOffsets = document.selection ? setIEOffsets : setModernOffsets;
185
- setOffsets(node, offsets);
186
- }
211
+ setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets
187
212
  };
188
213
 
189
214
  module.exports = ReactDOMSelection;
@@ -21,12 +21,15 @@
21
21
  var AutoFocusMixin = require("./AutoFocusMixin");
22
22
  var DOMPropertyOperations = require("./DOMPropertyOperations");
23
23
  var LinkedValueUtils = require("./LinkedValueUtils");
24
+ var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
24
25
  var ReactCompositeComponent = require("./ReactCompositeComponent");
25
26
  var ReactDOM = require("./ReactDOM");
26
27
 
27
28
  var invariant = require("./invariant");
28
29
  var merge = require("./merge");
29
30
 
31
+ var warning = require("./warning");
32
+
30
33
  // Store a reference to the <textarea> `ReactDOMComponent`.
31
34
  var textarea = ReactDOM.textarea;
32
35
 
@@ -48,7 +51,7 @@ var textarea = ReactDOM.textarea;
48
51
  var ReactDOMTextarea = ReactCompositeComponent.createClass({
49
52
  displayName: 'ReactDOMTextarea',
50
53
 
51
- mixins: [AutoFocusMixin, LinkedValueUtils.Mixin],
54
+ mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
52
55
 
53
56
  getInitialState: function() {
54
57
  var defaultValue = this.props.defaultValue;
@@ -56,10 +59,11 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
56
59
  var children = this.props.children;
57
60
  if (children != null) {
58
61
  if ("production" !== process.env.NODE_ENV) {
59
- console.warn(
62
+ ("production" !== process.env.NODE_ENV ? warning(
63
+ false,
60
64
  'Use the `defaultValue` or `value` props instead of setting ' +
61
65
  'children on <textarea>.'
62
- );
66
+ ) : null);
63
67
  }
64
68
  ("production" !== process.env.NODE_ENV ? invariant(
65
69
  defaultValue == null,
@@ -84,8 +88,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
84
88
  // `textContent` (unnecessary since we update value).
85
89
  // The initial value can be a boolean or object so that's why it's
86
90
  // forced to be a string.
87
- initialValue: '' + (value != null ? value : defaultValue),
88
- value: defaultValue
91
+ initialValue: '' + (value != null ? value : defaultValue)
89
92
  };
90
93
  },
91
94
 
@@ -97,7 +100,6 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
97
100
  render: function() {
98
101
  // Clone `this.props` so we don't mutate the input.
99
102
  var props = merge(this.props);
100
- var value = LinkedValueUtils.getValue(this);
101
103
 
102
104
  ("production" !== process.env.NODE_ENV ? invariant(
103
105
  props.dangerouslySetInnerHTML == null,
@@ -105,7 +107,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
105
107
  ) : invariant(props.dangerouslySetInnerHTML == null));
106
108
 
107
109
  props.defaultValue = null;
108
- props.value = value != null ? value : this.state.value;
110
+ props.value = null;
109
111
  props.onChange = this._handleChange;
110
112
 
111
113
  // Always set children to the same thing. In IE9, the selection range will
@@ -58,16 +58,16 @@ var ReactDefaultBatchingStrategy = {
58
58
  * Call the provided function in a context within which calls to `setState`
59
59
  * and friends are batched such that components aren't updated unnecessarily.
60
60
  */
61
- batchedUpdates: function(callback, param) {
61
+ batchedUpdates: function(callback, a, b) {
62
62
  var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
63
63
 
64
64
  ReactDefaultBatchingStrategy.isBatchingUpdates = true;
65
65
 
66
66
  // The code is written this way to avoid extra allocations
67
67
  if (alreadyBatchingUpdates) {
68
- callback(param);
68
+ callback(a, b);
69
69
  } else {
70
- transaction.perform(callback, null, param);
70
+ transaction.perform(callback, null, a, b);
71
71
  }
72
72
  }
73
73
  };
@@ -18,19 +18,19 @@
18
18
 
19
19
  "use strict";
20
20
 
21
- var ReactInjection = require("./ReactInjection");
22
-
23
- var ExecutionEnvironment = require("./ExecutionEnvironment");
24
-
25
- var DefaultDOMPropertyConfig = require("./DefaultDOMPropertyConfig");
26
-
21
+ var BeforeInputEventPlugin = require("./BeforeInputEventPlugin");
27
22
  var ChangeEventPlugin = require("./ChangeEventPlugin");
28
23
  var ClientReactRootIndex = require("./ClientReactRootIndex");
29
24
  var CompositionEventPlugin = require("./CompositionEventPlugin");
30
25
  var DefaultEventPluginOrder = require("./DefaultEventPluginOrder");
31
26
  var EnterLeaveEventPlugin = require("./EnterLeaveEventPlugin");
27
+ var ExecutionEnvironment = require("./ExecutionEnvironment");
28
+ var HTMLDOMPropertyConfig = require("./HTMLDOMPropertyConfig");
32
29
  var MobileSafariClickEventPlugin = require("./MobileSafariClickEventPlugin");
33
- var ReactEventTopLevelCallback = require("./ReactEventTopLevelCallback");
30
+ var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
31
+ var ReactComponentBrowserEnvironment =
32
+ require("./ReactComponentBrowserEnvironment");
33
+ var ReactDefaultBatchingStrategy = require("./ReactDefaultBatchingStrategy");
34
34
  var ReactDOM = require("./ReactDOM");
35
35
  var ReactDOMButton = require("./ReactDOMButton");
36
36
  var ReactDOMForm = require("./ReactDOMForm");
@@ -39,19 +39,20 @@ var ReactDOMInput = require("./ReactDOMInput");
39
39
  var ReactDOMOption = require("./ReactDOMOption");
40
40
  var ReactDOMSelect = require("./ReactDOMSelect");
41
41
  var ReactDOMTextarea = require("./ReactDOMTextarea");
42
+ var ReactEventListener = require("./ReactEventListener");
43
+ var ReactInjection = require("./ReactInjection");
42
44
  var ReactInstanceHandles = require("./ReactInstanceHandles");
43
45
  var ReactMount = require("./ReactMount");
44
46
  var SelectEventPlugin = require("./SelectEventPlugin");
45
47
  var ServerReactRootIndex = require("./ServerReactRootIndex");
46
48
  var SimpleEventPlugin = require("./SimpleEventPlugin");
47
-
48
- var ReactDefaultBatchingStrategy = require("./ReactDefaultBatchingStrategy");
49
+ var SVGDOMPropertyConfig = require("./SVGDOMPropertyConfig");
49
50
 
50
51
  var createFullPageComponent = require("./createFullPageComponent");
51
52
 
52
53
  function inject() {
53
- ReactInjection.EventEmitter.injectTopLevelCallbackCreator(
54
- ReactEventTopLevelCallback
54
+ ReactInjection.EventEmitter.injectReactEventListener(
55
+ ReactEventListener
55
56
  );
56
57
 
57
58
  /**
@@ -71,7 +72,8 @@ function inject() {
71
72
  ChangeEventPlugin: ChangeEventPlugin,
72
73
  CompositionEventPlugin: CompositionEventPlugin,
73
74
  MobileSafariClickEventPlugin: MobileSafariClickEventPlugin,
74
- SelectEventPlugin: SelectEventPlugin
75
+ SelectEventPlugin: SelectEventPlugin,
76
+ BeforeInputEventPlugin: BeforeInputEventPlugin
75
77
  });
76
78
 
77
79
  ReactInjection.DOM.injectComponentClasses({
@@ -85,12 +87,21 @@ function inject() {
85
87
 
86
88
  html: createFullPageComponent(ReactDOM.html),
87
89
  head: createFullPageComponent(ReactDOM.head),
88
- title: createFullPageComponent(ReactDOM.title),
89
90
  body: createFullPageComponent(ReactDOM.body)
90
91
  });
91
92
 
92
- ReactInjection.DOMProperty.injectDOMPropertyConfig(DefaultDOMPropertyConfig);
93
+ // This needs to happen after createFullPageComponent() otherwise the mixin
94
+ // gets double injected.
95
+ ReactInjection.CompositeComponent.injectMixin(ReactBrowserComponentMixin);
96
+
97
+ ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);
98
+ ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);
93
99
 
100
+ ReactInjection.EmptyComponent.injectEmptyComponent(ReactDOM.noscript);
101
+
102
+ ReactInjection.Updates.injectReconcileTransaction(
103
+ ReactComponentBrowserEnvironment.ReactReconcileTransaction
104
+ );
94
105
  ReactInjection.Updates.injectBatchingStrategy(
95
106
  ReactDefaultBatchingStrategy
96
107
  );
@@ -101,6 +112,8 @@ function inject() {
101
112
  ServerReactRootIndex.createReactRootIndex
102
113
  );
103
114
 
115
+ ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);
116
+
104
117
  if ("production" !== process.env.NODE_ENV) {
105
118
  var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
106
119
  if ((/[?&]react_perf\b/).test(url)) {
@@ -30,8 +30,13 @@ function roundFloat(val) {
30
30
  return Math.floor(val * 100) / 100;
31
31
  }
32
32
 
33
+ function addValue(obj, key, val) {
34
+ obj[key] = (obj[key] || 0) + val;
35
+ }
36
+
33
37
  var ReactDefaultPerf = {
34
38
  _allMeasurements: [], // last item in the list is the current one
39
+ _mountStack: [0],
35
40
  _injected: false,
36
41
 
37
42
  start: function() {
@@ -58,15 +63,15 @@ var ReactDefaultPerf = {
58
63
  return {
59
64
  'Component class name': item.componentName,
60
65
  'Total inclusive time (ms)': roundFloat(item.inclusive),
61
- 'Total exclusive time (ms)': roundFloat(item.exclusive),
62
- 'Exclusive time per instance (ms)': roundFloat(item.exclusive / item.count),
66
+ 'Exclusive mount time (ms)': roundFloat(item.exclusive),
67
+ 'Exclusive render time (ms)': roundFloat(item.render),
68
+ 'Mount time per instance (ms)': roundFloat(item.exclusive / item.count),
69
+ 'Render time per instance (ms)': roundFloat(item.render / item.count),
63
70
  'Instances': item.count
64
71
  };
65
72
  }));
66
- console.log(
67
- 'Total time:',
68
- ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
69
- );
73
+ // TODO: ReactDefaultPerfAnalysis.getTotalTime() does not return the correct
74
+ // number.
70
75
  },
71
76
 
72
77
  printInclusive: function(measurements) {
@@ -149,6 +154,7 @@ var ReactDefaultPerf = {
149
154
  ReactDefaultPerf._allMeasurements.push({
150
155
  exclusive: {},
151
156
  inclusive: {},
157
+ render: {},
152
158
  counts: {},
153
159
  writes: {},
154
160
  displayNames: {},
@@ -211,22 +217,33 @@ var ReactDefaultPerf = {
211
217
  args[0] :
212
218
  this._rootNodeID;
213
219
  var isRender = fnName === '_renderValidatedComponent';
220
+ var isMount = fnName === 'mountComponent';
221
+
222
+ var mountStack = ReactDefaultPerf._mountStack;
214
223
  var entry = ReactDefaultPerf._allMeasurements[
215
224
  ReactDefaultPerf._allMeasurements.length - 1
216
225
  ];
217
226
 
218
227
  if (isRender) {
219
- entry.counts[rootNodeID] = entry.counts[rootNodeID] || 0;
220
- entry.counts[rootNodeID] += 1;
228
+ addValue(entry.counts, rootNodeID, 1);
229
+ } else if (isMount) {
230
+ mountStack.push(0);
221
231
  }
222
232
 
223
233
  start = performanceNow();
224
234
  rv = func.apply(this, args);
225
235
  totalTime = performanceNow() - start;
226
236
 
227
- var typeOfLog = isRender ? entry.exclusive : entry.inclusive;
228
- typeOfLog[rootNodeID] = typeOfLog[rootNodeID] || 0;
229
- typeOfLog[rootNodeID] += totalTime;
237
+ if (isRender) {
238
+ addValue(entry.render, rootNodeID, totalTime);
239
+ } else if (isMount) {
240
+ var subMountTime = mountStack.pop();
241
+ mountStack[mountStack.length - 1] += totalTime;
242
+ addValue(entry.exclusive, rootNodeID, totalTime - subMountTime);
243
+ addValue(entry.inclusive, rootNodeID, totalTime);
244
+ } else {
245
+ addValue(entry.inclusive, rootNodeID, totalTime);
246
+ }
230
247
 
231
248
  entry.displayNames[rootNodeID] = {
232
249
  current: this.constructor.displayName,
@@ -80,8 +80,12 @@ function getExclusiveSummary(measurements) {
80
80
  componentName: displayName,
81
81
  inclusive: 0,
82
82
  exclusive: 0,
83
+ render: 0,
83
84
  count: 0
84
85
  };
86
+ if (measurement.render[id]) {
87
+ candidates[displayName].render += measurement.render[id];
88
+ }
85
89
  if (measurement.exclusive[id]) {
86
90
  candidates[displayName].exclusive += measurement.exclusive[id];
87
91
  }