Preserve Implicit Method Names
Summary: Changes the way we instrument methods for `ReactPerf` so that developer tools can assign implicit method names to measured functions. Reviewers: @zpao @sebmarkbage
yungsters committed
Nov 4, 2014 at 13:43 UTC
bda199de0440a8dd8d329f1443decd67b9792abc
6 files changed
+388
-390
src/browser/ui/ReactDOMComponent.js
+37
-40
@@ -171,28 +171,24 @@ ReactDOMComponent.Mixin = {
171
* @param {number} mountDepth number of components in the owner hierarchy
172
* @return {string} The computed markup.
173
*/
174
- mountComponent: ReactPerf.measure(
175
- 'ReactDOMComponent',
176
- 'mountComponent',
177
- function(rootID, transaction, mountDepth, context) {
178
- invariant(context !== undefined, "Context is required parameter");
179
- ReactComponent.Mixin.mountComponent.call(
180
- this,
181
- rootID,
182
- transaction,
183
- mountDepth,
184
- context
185
- );
186
- this._rootNodeID = rootID;
187
- assertValidProps(this._currentElement.props);
188
- var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>';
189
- return (
190
- this._createOpenTagMarkupAndPutListeners(transaction) +
191
- this._createContentMarkup(transaction, context) +
192
- closeTag
193
- );
194
- }
195
- ),
174
+ mountComponent: function(rootID, transaction, mountDepth, context) {
175
+ invariant(context !== undefined, "Context is required parameter");
176
+ ReactComponent.Mixin.mountComponent.call(
177
+ this,
178
+ rootID,
179
+ transaction,
180
+ mountDepth,
181
+ context
182
+ );
183
+ this._rootNodeID = rootID;
184
+ assertValidProps(this._currentElement.props);
185
+ var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>';
186
+ return (
187
+ this._createOpenTagMarkupAndPutListeners(transaction) +
188
+ this._createContentMarkup(transaction, context) +
189
+ closeTag
190
+ );
191
+ },
192
193
/**
194
* Creates markup for the open tag and all attributes.
@@ -319,24 +315,20 @@ ReactDOMComponent.Mixin = {
315
* @internal
316
* @overridable
317
*/
322
- updateComponent: ReactPerf.measure(
323
- 'ReactDOMComponent',
324
- 'updateComponent',
325
- function(transaction, prevElement, nextElement, context) {
326
- if(context === undefined) throw new Error("Context required for mounting");
327
- if(context === null) throw new Error("Assert: context is not null");
328
- assertValidProps(this._currentElement.props);
329
- ReactComponent.Mixin.updateComponent.call(
330
- this,
331
- transaction,
332
- prevElement,
333
- nextElement,
334
- context
335
- );
336
- this._updateDOMProperties(prevElement.props, transaction);
337
- this._updateDOMChildren(prevElement.props, transaction, context);
338
- }
339
- ),
318
+ updateComponent: function(transaction, prevElement, nextElement, context) {
319
+ if(context === undefined) throw new Error("Context required for mounting");
320
+ if(context === null) throw new Error("Assert: context is not null");
321
+ assertValidProps(this._currentElement.props);
322
+ ReactComponent.Mixin.updateComponent.call(
323
+ this,
324
+ transaction,
325
+ prevElement,
326
+ nextElement,
327
+ context
328
+ );
329
+ this._updateDOMProperties(prevElement.props, transaction);
330
+ this._updateDOMChildren(prevElement.props, transaction, context);
331
+ },
332
333
/**
334
* Reconciles the properties by detecting differences in property values and
@@ -504,6 +496,11 @@ ReactDOMComponent.Mixin = {
496
497
};
498
499
+ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
500
+ mountComponent: 'mountComponent',
501
+ updateComponent: 'updateComponent'
502
+});
503
+
504
assign(
505
ReactDOMComponent.prototype,
506
ReactComponent.Mixin,
src/browser/ui/ReactDOMIDOperations.js
+54
-72
@@ -50,27 +50,23 @@ var ReactDOMIDOperations = {
50
* @param {*} value New value of the property.
51
* @internal
52
*/
53
- updatePropertyByID: ReactPerf.measure(
54
- 'ReactDOMIDOperations',
55
- 'updatePropertyByID',
56
- function(id, name, value) {
57
- var node = ReactMount.getNode(id);
58
- invariant(
59
- !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
60
- 'updatePropertyByID(...): %s',
61
- INVALID_PROPERTY_ERRORS[name]
62
- );
63
-
64
- // If we're updating to null or undefined, we should remove the property
65
- // from the DOM node instead of inadvertantly setting to a string. This
66
- // brings us in line with the same behavior we have on initial render.
67
- if (value != null) {
68
- DOMPropertyOperations.setValueForProperty(node, name, value);
69
- } else {
70
- DOMPropertyOperations.deleteValueForProperty(node, name);
71
- }
53
+ updatePropertyByID: function(id, name, value) {
54
+ var node = ReactMount.getNode(id);
55
+ invariant(
56
+ !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
57
+ 'updatePropertyByID(...): %s',
58
+ INVALID_PROPERTY_ERRORS[name]
59
+ );
60
+
61
+ // If we're updating to null or undefined, we should remove the property
62
+ // from the DOM node instead of inadvertantly setting to a string. This
63
+ // brings us in line with the same behavior we have on initial render.
64
+ if (value != null) {
65
+ DOMPropertyOperations.setValueForProperty(node, name, value);
66
+ } else {
67
+ DOMPropertyOperations.deleteValueForProperty(node, name);
68
}
73
- ),
69
+ },
70
71
/**
72
* Updates a DOM node to remove a property. This should only be used to remove
@@ -80,19 +76,15 @@ var ReactDOMIDOperations = {
76
* @param {string} name A property name to remove, see `DOMProperty`.
77
* @internal
78
*/
83
- deletePropertyByID: ReactPerf.measure(
84
- 'ReactDOMIDOperations',
85
- 'deletePropertyByID',
86
- function(id, name, value) {
87
- var node = ReactMount.getNode(id);
88
- invariant(
89
- !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
90
- 'updatePropertyByID(...): %s',
91
- INVALID_PROPERTY_ERRORS[name]
92
- );
93
- DOMPropertyOperations.deleteValueForProperty(node, name, value);
94
- }
95
- ),
79
+ deletePropertyByID: function(id, name, value) {
80
+ var node = ReactMount.getNode(id);
81
+ invariant(
82
+ !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
83
+ 'updatePropertyByID(...): %s',
84
+ INVALID_PROPERTY_ERRORS[name]
85
+ );
86
+ DOMPropertyOperations.deleteValueForProperty(node, name, value);
87
+ },
88
89
/**
90
* Updates a DOM node with new style values. If a value is specified as '',
@@ -102,14 +94,10 @@ var ReactDOMIDOperations = {
94
* @param {object} styles Mapping from styles to values.
95
* @internal
96
*/
105
- updateStylesByID: ReactPerf.measure(
106
- 'ReactDOMIDOperations',
107
- 'updateStylesByID',
108
- function(id, styles) {
109
- var node = ReactMount.getNode(id);
110
- CSSPropertyOperations.setValueForStyles(node, styles);
111
- }
112
- ),
97
+ updateStylesByID: function(id, styles) {
98
+ var node = ReactMount.getNode(id);
99
+ CSSPropertyOperations.setValueForStyles(node, styles);
100
+ },
101
102
/**
103
* Updates a DOM node's innerHTML.
@@ -118,14 +106,10 @@ var ReactDOMIDOperations = {
106
* @param {string} html An HTML string.
107
* @internal
108
*/
121
- updateInnerHTMLByID: ReactPerf.measure(
122
- 'ReactDOMIDOperations',
123
- 'updateInnerHTMLByID',
124
- function(id, html) {
125
- var node = ReactMount.getNode(id);
126
- setInnerHTML(node, html);
127
- }
128
- ),
109
+ updateInnerHTMLByID: function(id, html) {
110
+ var node = ReactMount.getNode(id);
111
+ setInnerHTML(node, html);
112
+ },
113
114
/**
115
* Updates a DOM node's text content set by `props.content`.
@@ -134,14 +118,10 @@ var ReactDOMIDOperations = {
118
* @param {string} content Text content.
119
* @internal
120
*/
137
- updateTextContentByID: ReactPerf.measure(
138
- 'ReactDOMIDOperations',
139
- 'updateTextContentByID',
140
- function(id, content) {
141
- var node = ReactMount.getNode(id);
142
- DOMChildrenOperations.updateTextContent(node, content);
143
- }
144
- ),
121
+ updateTextContentByID: function(id, content) {
122
+ var node = ReactMount.getNode(id);
123
+ DOMChildrenOperations.updateTextContent(node, content);
124
+ },
125
126
/**
127
* Replaces a DOM node that exists in the document with markup.
@@ -151,14 +131,10 @@ var ReactDOMIDOperations = {
131
* @internal
132
* @see {Danger.dangerouslyReplaceNodeWithMarkup}
133
*/
154
- dangerouslyReplaceNodeWithMarkupByID: ReactPerf.measure(
155
- 'ReactDOMIDOperations',
156
- 'dangerouslyReplaceNodeWithMarkupByID',
157
- function(id, markup) {
134
+ dangerouslyReplaceNodeWithMarkupByID: function(id, markup) {
135
var node = ReactMount.getNode(id);
136
DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup);
160
- }
161
- ),
137
+ },
138
139
/**
140
* Updates a component's children by processing a series of updates.
@@ -167,16 +143,22 @@ var ReactDOMIDOperations = {
143
* @param {array<string>} markup List of markup strings.
144
* @internal
145
*/
170
- dangerouslyProcessChildrenUpdates: ReactPerf.measure(
171
- 'ReactDOMIDOperations',
172
- 'dangerouslyProcessChildrenUpdates',
173
- function(updates, markup) {
174
- for (var i = 0; i < updates.length; i++) {
175
- updates[i].parentNode = ReactMount.getNode(updates[i].parentID);
176
- }
177
- DOMChildrenOperations.processUpdates(updates, markup);
146
+ dangerouslyProcessChildrenUpdates: function(updates, markup) {
147
+ for (var i = 0; i < updates.length; i++) {
148
+ updates[i].parentNode = ReactMount.getNode(updates[i].parentID);
149
}
179
- )
150
+ DOMChildrenOperations.processUpdates(updates, markup);
151
+ }
152
};
153
154
+ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
155
+ updatePropertyByID: 'updatePropertyByID',
156
+ deletePropertyByID: 'deletePropertyByID',
157
+ updateStylesByID: 'updateStylesByID',
158
+ updateInnerHTMLByID: 'updateInnerHTMLByID',
159
+ updateTextContentByID: 'updateTextContentByID',
160
+ dangerouslyReplaceNodeWithMarkupByID: 'dangerouslyReplaceNodeWithMarkupByID',
161
+ dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates'
162
+});
163
+
164
module.exports = ReactDOMIDOperations;
src/browser/ui/ReactMount.js
+91
-93
@@ -319,50 +319,47 @@ var ReactMount = {
319
* @param {boolean} shouldReuseMarkup if we should skip the markup insertion
320
* @return {ReactComponent} nextComponent
321
*/
322
- _renderNewRootComponent: ReactPerf.measure(
323
- 'ReactMount',
324
- '_renderNewRootComponent',
325
- function(
326
- nextComponent,
327
- container,
328
- shouldReuseMarkup) {
329
- // Various parts of our code (such as ReactCompositeComponent's
330
- // _renderValidatedComponent) assume that calls to render aren't nested;
331
- // verify that that's the case.
332
- warning(
333
- ReactCurrentOwner.current == null,
334
- '_renderNewRootComponent(): Render methods should be a pure function ' +
335
- 'of props and state; triggering nested component updates from ' +
336
- 'render is not allowed. If necessary, trigger nested updates in ' +
337
- 'componentDidUpdate.'
338
- );
339
-
340
- var componentInstance = instantiateReactComponent(nextComponent, null);
341
- var reactRootID = ReactMount._registerComponent(
342
- componentInstance,
343
- container
344
- );
345
-
346
- var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
347
- transaction.perform(
348
- mountComponentIntoNode,
349
- componentInstance,
350
- reactRootID,
351
- container,
352
- transaction,
353
- shouldReuseMarkup
354
- );
355
- ReactUpdates.ReactReconcileTransaction.release(transaction);
356
-
357
- if (__DEV__) {
358
- // Record the root element in case it later gets transplanted.
359
- rootElementsByReactRootID[reactRootID] =
360
- getReactRootElementInContainer(container);
361
- }
322
+ _renderNewRootComponent: function(
323
+ nextComponent,
324
+ container,
325
+ shouldReuseMarkup
326
+ ) {
327
+ // Various parts of our code (such as ReactCompositeComponent's
328
+ // _renderValidatedComponent) assume that calls to render aren't nested;
329
+ // verify that that's the case.
330
+ warning(
331
+ ReactCurrentOwner.current == null,
332
+ '_renderNewRootComponent(): Render methods should be a pure function ' +
333
+ 'of props and state; triggering nested component updates from ' +
334
+ 'render is not allowed. If necessary, trigger nested updates in ' +
335
+ 'componentDidUpdate.'
336
+ );
337
+
338
+ var componentInstance = instantiateReactComponent(nextComponent, null);
339
+ var reactRootID = ReactMount._registerComponent(
340
+ componentInstance,
341
+ container
342
+ );
343
363
- return componentInstance;
344
+ var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
345
+ transaction.perform(
346
+ mountComponentIntoNode,
347
+ componentInstance,
348
+ reactRootID,
349
+ container,
350
+ transaction,
351
+ shouldReuseMarkup
352
+ );
353
+ ReactUpdates.ReactReconcileTransaction.release(transaction);
354
+
355
+ if (__DEV__) {
356
+ // Record the root element in case it later gets transplanted.
357
+ rootElementsByReactRootID[reactRootID] =
358
+ getReactRootElementInContainer(container);
359
}
365
- ),
360
+
361
+ return componentInstance;
362
+ },
363
364
/**
365
* Renders a React component into the DOM in the supplied `container`.
@@ -711,62 +708,58 @@ var ReactMount = {
708
);
709
},
710
714
- _mountImageIntoNode: ReactPerf.measure(
715
- 'ReactMount',
716
- '_mountImageIntoNode',
717
- function(markup, container, shouldReuseMarkup) {
718
- invariant(
719
- container && (
720
- container.nodeType === ELEMENT_NODE_TYPE ||
721
- container.nodeType === DOC_NODE_TYPE
722
- ),
723
- 'mountComponentIntoNode(...): Target container is not valid.'
724
- );
725
-
726
- if (shouldReuseMarkup) {
727
- if (ReactMarkupChecksum.canReuseMarkup(
728
- markup,
729
- getReactRootElementInContainer(container))) {
730
- return;
731
- } else {
732
- invariant(
733
- container.nodeType !== DOC_NODE_TYPE,
734
- 'You\'re trying to render a component to the document using ' +
735
- 'server rendering but the checksum was invalid. This usually ' +
736
- 'means you rendered a different component type or props on ' +
737
- 'the client from the one on the server, or your render() ' +
738
- 'methods are impure. React cannot handle this case due to ' +
739
- 'cross-browser quirks by rendering at the document root. You ' +
740
- 'should look for environment dependent code in your components ' +
741
- 'and ensure the props are the same client and server side.'
742
- );
711
+ _mountImageIntoNode: function(markup, container, shouldReuseMarkup) {
712
+ invariant(
713
+ container && (
714
+ container.nodeType === ELEMENT_NODE_TYPE ||
715
+ container.nodeType === DOC_NODE_TYPE
716
+ ),
717
+ 'mountComponentIntoNode(...): Target container is not valid.'
718
+ );
719
744
- if (__DEV__) {
745
- console.warn(
746
- 'React attempted to use reuse markup in a container but the ' +
747
- 'checksum was invalid. This generally means that you are ' +
748
- 'using server rendering and the markup generated on the ' +
749
- 'server was not what the client was expecting. React injected ' +
750
- 'new markup to compensate which works but you have lost many ' +
751
- 'of the benefits of server rendering. Instead, figure out ' +
752
- 'why the markup being generated is different on the client ' +
753
- 'or server.'
754
- );
755
- }
720
+ if (shouldReuseMarkup) {
721
+ if (ReactMarkupChecksum.canReuseMarkup(
722
+ markup,
723
+ getReactRootElementInContainer(container))) {
724
+ return;
725
+ } else {
726
+ invariant(
727
+ container.nodeType !== DOC_NODE_TYPE,
728
+ 'You\'re trying to render a component to the document using ' +
729
+ 'server rendering but the checksum was invalid. This usually ' +
730
+ 'means you rendered a different component type or props on ' +
731
+ 'the client from the one on the server, or your render() ' +
732
+ 'methods are impure. React cannot handle this case due to ' +
733
+ 'cross-browser quirks by rendering at the document root. You ' +
734
+ 'should look for environment dependent code in your components ' +
735
+ 'and ensure the props are the same client and server side.'
736
+ );
737
+
738
+ if (__DEV__) {
739
+ console.warn(
740
+ 'React attempted to use reuse markup in a container but the ' +
741
+ 'checksum was invalid. This generally means that you are ' +
742
+ 'using server rendering and the markup generated on the ' +
743
+ 'server was not what the client was expecting. React injected ' +
744
+ 'new markup to compensate which works but you have lost many ' +
745
+ 'of the benefits of server rendering. Instead, figure out ' +
746
+ 'why the markup being generated is different on the client ' +
747
+ 'or server.'
748
+ );
749
}
750
}
751
+ }
752
759
- invariant(
760
- container.nodeType !== DOC_NODE_TYPE,
761
- 'You\'re trying to render a component to the document but ' +
762
- 'you didn\'t use server rendering. We can\'t do this ' +
763
- 'without using server rendering due to cross-browser quirks. ' +
764
- 'See renderComponentToString() for server rendering.'
765
- );
753
+ invariant(
754
+ container.nodeType !== DOC_NODE_TYPE,
755
+ 'You\'re trying to render a component to the document but ' +
756
+ 'you didn\'t use server rendering. We can\'t do this ' +
757
+ 'without using server rendering due to cross-browser quirks. ' +
758
+ 'See renderComponentToString() for server rendering.'
759
+ );
760
767
- setInnerHTML(container, markup);
768
- }
769
- ),
761
+ setInnerHTML(container, markup);
762
+ },
763
764
/**
765
* React ID utilities.
@@ -785,6 +778,11 @@ var ReactMount = {
778
purgeID: purgeID
779
};
780
781
+ReactPerf.measureMethods(ReactMount, 'ReactMount', {
782
+ _renderNewRootComponent: '_renderNewRootComponent',
783
+ _mountImageIntoNode: '_mountImageIntoNode'
784
+});
785
+
786
// Deprecations (remove for 0.13)
787
ReactMount.renderComponent = deprecated(
788
'ReactMount',
src/core/ReactCompositeComponent.js
+164
-164
@@ -157,85 +157,81 @@ var ReactCompositeComponentMixin = assign({},
157
* @final
158
* @internal
159
*/
160
- mountComponent: ReactPerf.measure(
161
- 'ReactCompositeComponent',
162
- 'mountComponent',
163
- function(rootID, transaction, mountDepth, context) {
164
- invariant(context !== undefined, "Context is required parameter");
165
- ReactComponent.Mixin.mountComponent.call(
166
- this,
167
- rootID,
168
- transaction,
169
- mountDepth,
170
- context
171
- );
160
+ mountComponent: function(rootID, transaction, mountDepth, context) {
161
+ invariant(context !== undefined, "Context is required parameter");
162
+ ReactComponent.Mixin.mountComponent.call(
163
+ this,
164
+ rootID,
165
+ transaction,
166
+ mountDepth,
167
+ context
168
+ );
169
173
- this._context = context;
174
- this._rootNodeID = rootID;
170
+ this._context = context;
171
+ this._rootNodeID = rootID;
172
176
- var inst = this._instance;
173
+ var inst = this._instance;
174
178
- // Store a reference from the instance back to the internal representation
179
- ReactInstanceMap.set(inst, this);
175
+ // Store a reference from the instance back to the internal representation
176
+ ReactInstanceMap.set(inst, this);
177
181
- this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
178
+ this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
179
183
- inst.context = this._processContext(this._currentElement._context);
184
- if (__DEV__) {
185
- this._warnIfContextsDiffer(this._currentElement._context, context);
186
- }
187
- inst.props = this._processProps(this._currentElement.props);
180
+ inst.context = this._processContext(this._currentElement._context);
181
+ if (__DEV__) {
182
+ this._warnIfContextsDiffer(this._currentElement._context, context);
183
+ }
184
+ inst.props = this._processProps(this._currentElement.props);
185
189
- var initialState = inst.getInitialState ? inst.getInitialState() : null;
190
- if (__DEV__) {
191
- // We allow auto-mocks to proceed as if they're returning null.
192
- if (typeof initialState === 'undefined' &&
193
- inst.getInitialState._isMockFunction) {
194
- // This is probably bad practice. Consider warning here and
195
- // deprecating this convenience.
196
- initialState = null;
197
- }
198
- }
199
- invariant(
200
- typeof initialState === 'object' && !Array.isArray(initialState),
201
- '%s.getInitialState(): must return an object or null',
202
- inst.constructor.displayName || 'ReactCompositeComponent'
203
- );
204
- inst.state = initialState;
205
-
206
- this._pendingState = null;
207
- this._pendingForceUpdate = false;
208
-
209
- if (inst.componentWillMount) {
210
- inst.componentWillMount();
211
- // When mounting, calls to `setState` by `componentWillMount` will set
212
- // `this._pendingState` without triggering a re-render.
213
- if (this._pendingState) {
214
- inst.state = this._pendingState;
215
- this._pendingState = null;
216
- }
186
+ var initialState = inst.getInitialState ? inst.getInitialState() : null;
187
+ if (__DEV__) {
188
+ // We allow auto-mocks to proceed as if they're returning null.
189
+ if (typeof initialState === 'undefined' &&
190
+ inst.getInitialState._isMockFunction) {
191
+ // This is probably bad practice. Consider warning here and
192
+ // deprecating this convenience.
193
+ initialState = null;
194
}
195
+ }
196
+ invariant(
197
+ typeof initialState === 'object' && !Array.isArray(initialState),
198
+ '%s.getInitialState(): must return an object or null',
199
+ inst.constructor.displayName || 'ReactCompositeComponent'
200
+ );
201
+ inst.state = initialState;
202
219
- var renderedElement = this._renderValidatedComponent();
220
- this._renderedComponent = this._instantiateReactComponent(
221
- renderedElement,
222
- this._currentElement.type // The wrapping type
223
- );
203
+ this._pendingState = null;
204
+ this._pendingForceUpdate = false;
205
225
- // Done with mounting, `setState` will now trigger UI changes.
226
- this._compositeLifeCycleState = null;
227
- var markup = this._renderedComponent.mountComponent(
228
- rootID,
229
- transaction,
230
- mountDepth + 1,
231
- this._processChildContext(context)
232
- );
233
- if (inst.componentDidMount) {
234
- transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
206
+ if (inst.componentWillMount) {
207
+ inst.componentWillMount();
208
+ // When mounting, calls to `setState` by `componentWillMount` will set
209
+ // `this._pendingState` without triggering a re-render.
210
+ if (this._pendingState) {
211
+ inst.state = this._pendingState;
212
+ this._pendingState = null;
213
}
236
- return markup;
214
}
238
- ),
215
+
216
+ var renderedElement = this._renderValidatedComponent();
217
+ this._renderedComponent = this._instantiateReactComponent(
218
+ renderedElement,
219
+ this._currentElement.type // The wrapping type
220
+ );
221
+
222
+ // Done with mounting, `setState` will now trigger UI changes.
223
+ this._compositeLifeCycleState = null;
224
+ var markup = this._renderedComponent.mountComponent(
225
+ rootID,
226
+ transaction,
227
+ mountDepth + 1,
228
+ this._processChildContext(context)
229
+ );
230
+ if (inst.componentDidMount) {
231
+ transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
232
+ }
233
+ return markup;
234
+ },
235
236
/**
237
* Releases any resources allocated by `mountComponent`.
@@ -627,84 +623,82 @@ var ReactCompositeComponentMixin = assign({},
623
* @internal
624
* @overridable
625
*/
630
- updateComponent: ReactPerf.measure(
631
- 'ReactCompositeComponent',
632
- 'updateComponent',
633
- function(
634
- transaction,
635
- prevParentElement,
636
- nextParentElement,
637
- prevUnmaskedContext,
638
- nextUnmaskedContext) {
639
- // Update refs regardless of what shouldComponentUpdate returns
640
- ReactComponent.Mixin.updateComponent.call(
641
- this,
642
- transaction,
643
- prevParentElement,
644
- nextParentElement,
645
- prevUnmaskedContext,
646
- nextUnmaskedContext
647
- );
626
+ updateComponent: function(
627
+ transaction,
628
+ prevParentElement,
629
+ nextParentElement,
630
+ prevUnmaskedContext,
631
+ nextUnmaskedContext
632
+ ) {
633
+ // Update refs regardless of what shouldComponentUpdate returns
634
+ ReactComponent.Mixin.updateComponent.call(
635
+ this,
636
+ transaction,
637
+ prevParentElement,
638
+ nextParentElement,
639
+ prevUnmaskedContext,
640
+ nextUnmaskedContext
641
+ );
642
649
- var inst = this._instance;
643
+ var inst = this._instance;
644
651
- var prevContext = inst.context;
652
- var prevProps = inst.props;
653
- var nextContext = prevContext;
654
- var nextProps = prevProps;
655
- // Distinguish between a props update versus a simple state update
656
- if (prevParentElement !== nextParentElement) {
657
- nextContext = this._processContext(nextParentElement._context);
658
- nextProps = this._processProps(nextParentElement.props);
659
-
660
- this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
661
- if (inst.componentWillReceiveProps) {
662
- inst.componentWillReceiveProps(nextProps, nextContext);
663
- }
645
+ var prevContext = inst.context;
646
+ var prevProps = inst.props;
647
+ var nextContext = prevContext;
648
+ var nextProps = prevProps;
649
+ // Distinguish between a props update versus a simple state update
650
+ if (prevParentElement !== nextParentElement) {
651
+ nextContext = this._processContext(nextParentElement._context);
652
+ nextProps = this._processProps(nextParentElement.props);
653
+
654
+ this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
655
+ if (inst.componentWillReceiveProps) {
656
+ inst.componentWillReceiveProps(nextProps, nextContext);
657
}
658
+ }
659
666
- this._compositeLifeCycleState = null;
660
+ this._compositeLifeCycleState = null;
661
668
- var nextState = this._pendingState || inst.state;
669
- this._pendingState = null;
662
+ var nextState = this._pendingState || inst.state;
663
+ this._pendingState = null;
664
671
- var shouldUpdate =
672
- this._pendingForceUpdate ||
673
- !inst.shouldComponentUpdate ||
674
- inst.shouldComponentUpdate(nextProps, nextState, nextContext);
665
+ var shouldUpdate =
666
+ this._pendingForceUpdate ||
667
+ !inst.shouldComponentUpdate ||
668
+ inst.shouldComponentUpdate(nextProps, nextState, nextContext);
669
676
- if (__DEV__) {
677
- if (typeof shouldUpdate === "undefined") {
678
- console.warn(
679
- (inst.constructor.displayName || 'ReactCompositeComponent') +
680
- '.shouldComponentUpdate(): Returned undefined instead of a ' +
681
- 'boolean value. Make sure to return true or false.'
682
- );
683
- }
670
+ if (__DEV__) {
671
+ if (typeof shouldUpdate === "undefined") {
672
+ console.warn(
673
+ (inst.constructor.displayName || 'ReactCompositeComponent') +
674
+ '.shouldComponentUpdate(): Returned undefined instead of a ' +
675
+ 'boolean value. Make sure to return true or false.'
676
+ );
677
}
678
+ }
679
686
- if (!shouldUpdate) {
687
- // If it's determined that a component should not update, we still want
688
- // to set props and state but we shortcut the rest of the update.
689
- this._currentElement = nextParentElement;
690
- this._context = nextUnmaskedContext;
691
- inst.props = nextProps;
692
- inst.state = nextState;
693
- inst.context = nextContext;
694
- return;
695
- }
680
+ if (!shouldUpdate) {
681
+ // If it's determined that a component should not update, we still want
682
+ // to set props and state but we shortcut the rest of the update.
683
+ this._currentElement = nextParentElement;
684
+ this._context = nextUnmaskedContext;
685
+ inst.props = nextProps;
686
+ inst.state = nextState;
687
+ inst.context = nextContext;
688
+ return;
689
+ }
690
697
- this._pendingForceUpdate = false;
698
- // Will set `this.props`, `this.state` and `this.context`.
699
- this._performComponentUpdate(
700
- nextParentElement,
701
- nextProps,
702
- nextState,
703
- nextContext,
704
- transaction,
705
- nextUnmaskedContext
706
- );
707
- }),
691
+ this._pendingForceUpdate = false;
692
+ // Will set `this.props`, `this.state` and `this.context`.
693
+ this._performComponentUpdate(
694
+ nextParentElement,
695
+ nextProps,
696
+ nextState,
697
+ nextContext,
698
+ transaction,
699
+ nextUnmaskedContext
700
+ );
701
+ },
702
703
/**
704
* Merges new props and state, notifies delegate methods of update and
@@ -816,35 +810,31 @@ var ReactCompositeComponentMixin = assign({},
810
/**
811
* @private
812
*/
819
- _renderValidatedComponent: ReactPerf.measure(
820
- 'ReactCompositeComponent',
821
- '_renderValidatedComponent',
822
- function() {
823
- var renderedComponent;
824
- var previousContext = ReactContext.current;
825
- ReactContext.current = this._processChildContext(
826
- this._currentElement._context
827
- );
828
- ReactCurrentOwner.current = this;
829
- var inst = this._instance;
830
- try {
831
- renderedComponent =
832
- this._renderValidatedComponentWithoutOwnerOrContext();
833
- } finally {
834
- ReactContext.current = previousContext;
835
- ReactCurrentOwner.current = null;
836
- }
837
- invariant(
838
- // TODO: An `isValidNode` function would probably be more appropriate
839
- renderedComponent === null || renderedComponent === false ||
840
- ReactElement.isValidElement(renderedComponent),
841
- '%s.render(): A valid ReactComponent must be returned. You may have ' +
842
- 'returned undefined, an array or some other invalid object.',
843
- inst.constructor.displayName || 'ReactCompositeComponent'
844
- );
845
- return renderedComponent;
813
+ _renderValidatedComponent: function() {
814
+ var renderedComponent;
815
+ var previousContext = ReactContext.current;
816
+ ReactContext.current = this._processChildContext(
817
+ this._currentElement._context
818
+ );
819
+ ReactCurrentOwner.current = this;
820
+ var inst = this._instance;
821
+ try {
822
+ renderedComponent =
823
+ this._renderValidatedComponentWithoutOwnerOrContext();
824
+ } finally {
825
+ ReactContext.current = previousContext;
826
+ ReactCurrentOwner.current = null;
827
}
847
- ),
828
+ invariant(
829
+ // TODO: An `isValidNode` function would probably be more appropriate
830
+ renderedComponent === null || renderedComponent === false ||
831
+ ReactElement.isValidElement(renderedComponent),
832
+ '%s.render(): A valid ReactComponent must be returned. You may have ' +
833
+ 'returned undefined, an array or some other invalid object.',
834
+ inst.constructor.displayName || 'ReactCompositeComponent'
835
+ );
836
+ return renderedComponent;
837
+ },
838
839
/**
840
* Lazily allocates the refs object and stores `component` as `ref`.
@@ -1001,6 +991,16 @@ var ShallowMixin = assign({},
991
992
});
993
994
+ReactPerf.measureMethods(
995
+ ReactCompositeComponentMixin,
996
+ 'ReactCompositeComponent',
997
+ {
998
+ mountComponent: 'mountComponent',
999
+ updateComponent: 'updateComponent',
1000
+ _renderValidatedComponent: '_renderValidatedComponent'
1001
+ }
1002
+);
1003
+
1004
var ReactCompositeComponent = {
1005
1006
LifeCycle: CompositeLifeCycle,
src/core/ReactUpdates.js
+22
-21
@@ -159,30 +159,31 @@ function runBatchedUpdates(transaction) {
159
}
160
}
161
162
-var flushBatchedUpdates = ReactPerf.measure(
163
- 'ReactUpdates',
164
- 'flushBatchedUpdates',
165
- function() {
166
- // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents
167
- // array and perform any updates enqueued by mount-ready handlers (i.e.,
168
- // componentDidUpdate) but we need to check here too in order to catch
169
- // updates enqueued by setState callbacks and asap calls.
170
- while (dirtyComponents.length || asapEnqueued) {
171
- if (dirtyComponents.length) {
172
- var transaction = ReactUpdatesFlushTransaction.getPooled();
173
- transaction.perform(runBatchedUpdates, null, transaction);
174
- ReactUpdatesFlushTransaction.release(transaction);
175
- }
162
+var flushBatchedUpdates = function() {
163
+ // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents
164
+ // array and perform any updates enqueued by mount-ready handlers (i.e.,
165
+ // componentDidUpdate) but we need to check here too in order to catch
166
+ // updates enqueued by setState callbacks and asap calls.
167
+ while (dirtyComponents.length || asapEnqueued) {
168
+ if (dirtyComponents.length) {
169
+ var transaction = ReactUpdatesFlushTransaction.getPooled();
170
+ transaction.perform(runBatchedUpdates, null, transaction);
171
+ ReactUpdatesFlushTransaction.release(transaction);
172
+ }
173
177
- if (asapEnqueued) {
178
- asapEnqueued = false;
179
- var queue = asapCallbackQueue;
180
- asapCallbackQueue = CallbackQueue.getPooled();
181
- queue.notifyAll();
182
- CallbackQueue.release(queue);
183
- }
174
+ if (asapEnqueued) {
175
+ asapEnqueued = false;
176
+ var queue = asapCallbackQueue;
177
+ asapCallbackQueue = CallbackQueue.getPooled();
178
+ queue.notifyAll();
179
+ CallbackQueue.release(queue);
180
}
181
}
182
+};
183
+flushBatchedUpdates = ReactPerf.measure(
184
+ 'ReactUpdates',
185
+ 'flushBatchedUpdates',
186
+ flushBatchedUpdates
187
);
188
189
/**
src/test/ReactPerf.js
+20
@@ -29,6 +29,26 @@ var ReactPerf = {
29
*/
30
storedMeasure: _noMeasure,
31
32
+ /**
33
+ * @param {object} object
34
+ * @param {string} objectName
35
+ * @param {object<string>} methodNames
36
+ */
37
+ measureMethods: function(object, objectName, methodNames) {
38
+ if (__DEV__) {
39
+ for (var key in methodNames) {
40
+ if (!methodNames.hasOwnProperty(key)) {
41
+ continue;
42
+ }
43
+ object[key] = ReactPerf.measure(
44
+ objectName,
45
+ methodNames[key],
46
+ object[key]
47
+ );
48
+ }
49
+ }
50
+ },
51
+
52
/**
53
* Use this to wrap methods you want to measure. Zero overhead in production.
54
*