@samitouri / QOS-React-2 / commits / bda199de04

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 *