Ensure lifecycle timers are stopped on errors (#7548)
* Ensure lifecycle timers are stopped on errors Fixes #7349 * Address review feedback and add an extra test
Dan Abramov committed
Aug 24, 2016 at 19:18 UTC
a229cdba7fd00799d82c1bab23704220d47e6331
4 files changed
+419
-200
src/renderers/dom/__tests__/ReactDOMProduction-test.js
+88
@@ -86,6 +86,94 @@ describe('ReactDOMProduction', function() {
86
expect(container.childNodes.length).toBe(0);
87
});
88
89
+ it('should call lifecycle methods', function() {
90
+ var log = [];
91
+ class Component extends React.Component {
92
+ state = {y: 1};
93
+ shouldComponentUpdate(nextProps, nextState) {
94
+ log.push(['shouldComponentUpdate', nextProps, nextState]);
95
+ return nextProps.x !== this.props.x || nextState.y !== this.state.y;
96
+ }
97
+ componentWillMount() {
98
+ log.push(['componentWillMount']);
99
+ }
100
+ componentDidMount() {
101
+ log.push(['componentDidMount']);
102
+ }
103
+ componentWillReceiveProps(nextProps) {
104
+ log.push(['componentWillReceiveProps', nextProps]);
105
+ }
106
+ componentWillUpdate(nextProps, nextState) {
107
+ log.push(['componentWillUpdate', nextProps, nextState]);
108
+ }
109
+ componentDidUpdate(prevProps, prevState) {
110
+ log.push(['componentDidUpdate', prevProps, prevState]);
111
+ }
112
+ componentWillUnmount() {
113
+ log.push(['componentWillUnmount']);
114
+ }
115
+ render() {
116
+ log.push(['render']);
117
+ return null;
118
+ }
119
+ }
120
+
121
+ var container = document.createElement('div');
122
+ var inst = ReactDOM.render(
123
+ <Component x={1} />,
124
+ container
125
+ );
126
+ expect(log).toEqual([
127
+ ['componentWillMount'],
128
+ ['render'],
129
+ ['componentDidMount'],
130
+ ]);
131
+ log = [];
132
+
133
+ inst.setState({y: 2});
134
+ expect(log).toEqual([
135
+ ['shouldComponentUpdate', {x: 1}, {y: 2}],
136
+ ['componentWillUpdate', {x: 1}, {y: 2}],
137
+ ['render'],
138
+ ['componentDidUpdate', {x: 1}, {y: 1}],
139
+ ]);
140
+ log = [];
141
+
142
+ inst.setState({y: 2});
143
+ expect(log).toEqual([
144
+ ['shouldComponentUpdate', {x: 1}, {y: 2}],
145
+ ]);
146
+ log = [];
147
+
148
+ ReactDOM.render(
149
+ <Component x={2} />,
150
+ container
151
+ );
152
+ expect(log).toEqual([
153
+ ['componentWillReceiveProps', {x: 2}],
154
+ ['shouldComponentUpdate', {x: 2}, {y: 2}],
155
+ ['componentWillUpdate', {x: 2}, {y: 2}],
156
+ ['render'],
157
+ ['componentDidUpdate', {x: 1}, {y: 2}],
158
+ ]);
159
+ log = [];
160
+
161
+ ReactDOM.render(
162
+ <Component x={2} />,
163
+ container
164
+ );
165
+ expect(log).toEqual([
166
+ ['componentWillReceiveProps', {x: 2}],
167
+ ['shouldComponentUpdate', {x: 2}, {y: 2}],
168
+ ]);
169
+ log = [];
170
+
171
+ ReactDOM.unmountComponentAtNode(container);
172
+ expect(log).toEqual([
173
+ ['componentWillUnmount'],
174
+ ]);
175
+ });
176
+
177
it('should throw with an error code in production', function() {
178
expect(function() {
179
class Component extends React.Component {
src/renderers/shared/ReactDebugTool.js
-6
@@ -310,12 +310,6 @@ var ReactDebugTool = {
310
markEnd(debugID, timerType);
311
emitEvent('onEndLifeCycleTimer', debugID, timerType);
312
},
313
- onError(debugID) {
314
- if (currentTimerDebugID != null) {
315
- endLifeCycleTimer(currentTimerDebugID, currentTimerType);
316
- }
317
- emitEvent('onError', debugID);
318
- },
313
onBeginProcessingChildContext() {
314
emitEvent('onBeginProcessingChildContext');
315
},
src/renderers/shared/__tests__/ReactPerf-test.js
+204
@@ -516,4 +516,208 @@ describe('ReactPerf', function() {
516
renderCount: 2,
517
}]);
518
});
519
+
520
+ it('should not print errant warnings if render() throws', () => {
521
+ var container = document.createElement('div');
522
+ var thrownErr = new Error('Muhaha!');
523
+
524
+ class Evil extends React.Component {
525
+ render() {
526
+ throw thrownErr;
527
+ }
528
+ }
529
+
530
+ ReactPerf.start();
531
+ try {
532
+ ReactDOM.render(
533
+ <div>
534
+ <LifeCycle />
535
+ <Evil />
536
+ </div>,
537
+ container
538
+ );
539
+ } catch (err) {
540
+ if (err !== thrownErr) {
541
+ throw err;
542
+ }
543
+ }
544
+ ReactPerf.stop();
545
+ });
546
+
547
+ it('should not print errant warnings if componentWillMount() throws', () => {
548
+ var container = document.createElement('div');
549
+ var thrownErr = new Error('Muhaha!');
550
+
551
+ class Evil extends React.Component {
552
+ componentWillMount() {
553
+ throw thrownErr;
554
+ }
555
+ render() {
556
+ return <div />;
557
+ }
558
+ }
559
+
560
+ ReactPerf.start();
561
+ try {
562
+ ReactDOM.render(
563
+ <div>
564
+ <LifeCycle />
565
+ <Evil />
566
+ </div>,
567
+ container
568
+ );
569
+ } catch (err) {
570
+ if (err !== thrownErr) {
571
+ throw err;
572
+ }
573
+ }
574
+ ReactPerf.stop();
575
+ });
576
+
577
+ it('should not print errant warnings if componentDidMount() throws', () => {
578
+ var container = document.createElement('div');
579
+ var thrownErr = new Error('Muhaha!');
580
+
581
+ class Evil extends React.Component {
582
+ componentDidMount() {
583
+ throw thrownErr;
584
+ }
585
+ render() {
586
+ return <div />;
587
+ }
588
+ }
589
+
590
+ ReactPerf.start();
591
+ try {
592
+ ReactDOM.render(
593
+ <div>
594
+ <LifeCycle />
595
+ <Evil />
596
+ </div>,
597
+ container
598
+ );
599
+ } catch (err) {
600
+ if (err !== thrownErr) {
601
+ throw err;
602
+ }
603
+ }
604
+ ReactPerf.stop();
605
+ });
606
+
607
+ it('should not print errant warnings if portal throws in render()', () => {
608
+ var container = document.createElement('div');
609
+ var thrownErr = new Error('Muhaha!');
610
+
611
+ class Evil extends React.Component {
612
+ render() {
613
+ throw thrownErr;
614
+ }
615
+ }
616
+ class EvilPortal extends React.Component {
617
+ componentWillMount() {
618
+ var portalContainer = document.createElement('div');
619
+ ReactDOM.render(<Evil />, portalContainer);
620
+ }
621
+ render() {
622
+ return <div />;
623
+ }
624
+ }
625
+
626
+ ReactPerf.start();
627
+ try {
628
+ ReactDOM.render(
629
+ <div>
630
+ <LifeCycle />
631
+ <EvilPortal />
632
+ </div>,
633
+ container
634
+ );
635
+ } catch (err) {
636
+ if (err !== thrownErr) {
637
+ throw err;
638
+ }
639
+ }
640
+ ReactDOM.unmountComponentAtNode(container);
641
+ ReactPerf.stop();
642
+ });
643
+
644
+ it('should not print errant warnings if portal throws in componentWillMount()', () => {
645
+ var container = document.createElement('div');
646
+ var thrownErr = new Error('Muhaha!');
647
+
648
+ class Evil extends React.Component {
649
+ componentWillMount() {
650
+ throw thrownErr;
651
+ }
652
+ render() {
653
+ return <div />;
654
+ }
655
+ }
656
+ class EvilPortal extends React.Component {
657
+ componentWillMount() {
658
+ var portalContainer = document.createElement('div');
659
+ ReactDOM.render(<Evil />, portalContainer);
660
+ }
661
+ render() {
662
+ return <div />;
663
+ }
664
+ }
665
+
666
+ ReactPerf.start();
667
+ try {
668
+ ReactDOM.render(
669
+ <div>
670
+ <LifeCycle />
671
+ <EvilPortal />
672
+ </div>,
673
+ container
674
+ );
675
+ } catch (err) {
676
+ if (err !== thrownErr) {
677
+ throw err;
678
+ }
679
+ }
680
+ ReactDOM.unmountComponentAtNode(container);
681
+ ReactPerf.stop();
682
+ });
683
+
684
+ it('should not print errant warnings if portal throws in componentDidMount()', () => {
685
+ var container = document.createElement('div');
686
+ var thrownErr = new Error('Muhaha!');
687
+
688
+ class Evil extends React.Component {
689
+ componentDidMount() {
690
+ throw thrownErr;
691
+ }
692
+ render() {
693
+ return <div />;
694
+ }
695
+ }
696
+ class EvilPortal extends React.Component {
697
+ componentWillMount() {
698
+ var portalContainer = document.createElement('div');
699
+ ReactDOM.render(<Evil />, portalContainer);
700
+ }
701
+ render() {
702
+ return <div />;
703
+ }
704
+ }
705
+
706
+ ReactPerf.start();
707
+ try {
708
+ ReactDOM.render(
709
+ <div>
710
+ <LifeCycle />
711
+ <EvilPortal />
712
+ </div>,
713
+ container
714
+ );
715
+ } catch (err) {
716
+ if (err !== thrownErr) {
717
+ throw err;
718
+ }
719
+ }
720
+ ReactDOM.unmountComponentAtNode(container);
721
+ ReactPerf.stop();
722
+ });
723
});
src/renderers/shared/stack/reconciler/ReactCompositeComponent.js
+127
-194
@@ -62,40 +62,6 @@ function warnIfInvalidElement(Component, element) {
62
}
63
}
64
65
-function invokeComponentDidMountWithTimer() {
66
- var publicInstance = this._instance;
67
- if (this._debugID !== 0) {
68
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
69
- this._debugID,
70
- 'componentDidMount'
71
- );
72
- }
73
- publicInstance.componentDidMount();
74
- if (this._debugID !== 0) {
75
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
76
- this._debugID,
77
- 'componentDidMount'
78
- );
79
- }
80
-}
81
-
82
-function invokeComponentDidUpdateWithTimer(prevProps, prevState, prevContext) {
83
- var publicInstance = this._instance;
84
- if (this._debugID !== 0) {
85
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
86
- this._debugID,
87
- 'componentDidUpdate'
88
- );
89
- }
90
- publicInstance.componentDidUpdate(prevProps, prevState, prevContext);
91
- if (this._debugID !== 0) {
92
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
93
- this._debugID,
94
- 'componentDidUpdate'
95
- );
96
- }
97
-}
98
-
65
function shouldConstruct(Component) {
66
return !!(Component.prototype && Component.prototype.isReactComponent);
67
}
@@ -104,6 +70,23 @@ function isPureComponent(Component) {
70
return !!(Component.prototype && Component.prototype.isPureReactComponent);
71
}
72
73
+// Separated into a function to contain deoptimizations caused by try/finally.
74
+function measureLifeCyclePerf(fn, debugID, timerType) {
75
+ if (debugID === 0) {
76
+ // Top-level wrappers (see ReactMount) and empty components (see
77
+ // ReactDOMEmptyComponent) are invisible to hooks and devtools.
78
+ // Both are implementation details that should go away in the future.
79
+ return fn();
80
+ }
81
+
82
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(debugID, timerType);
83
+ try {
84
+ return fn();
85
+ } finally {
86
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(debugID, timerType);
87
+ }
88
+}
89
+
90
/**
91
* ------------------ The Life-Cycle of a Composite Component ------------------
92
*
@@ -364,7 +347,13 @@ var ReactCompositeComponentMixin = {
347
348
if (inst.componentDidMount) {
349
if (__DEV__) {
367
- transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this);
350
+ transaction.getReactMountReady().enqueue(() => {
351
+ measureLifeCyclePerf(
352
+ () => inst.componentDidMount(),
353
+ this._debugID,
354
+ 'componentDidMount'
355
+ );
356
+ });
357
} else {
358
transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
359
}
@@ -408,47 +397,30 @@ var ReactCompositeComponentMixin = {
397
updateQueue
398
) {
399
var Component = this._currentElement.type;
411
- var instanceOrElement;
400
+
401
if (doConstruct) {
402
if (__DEV__) {
414
- if (this._debugID !== 0) {
415
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
416
- this._debugID,
417
- 'ctor'
418
- );
419
- }
420
- }
421
- instanceOrElement = new Component(publicProps, publicContext, updateQueue);
422
- if (__DEV__) {
423
- if (this._debugID !== 0) {
424
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
425
- this._debugID,
426
- 'ctor'
427
- );
428
- }
403
+ return measureLifeCyclePerf(
404
+ () => new Component(publicProps, publicContext, updateQueue),
405
+ this._debugID,
406
+ 'ctor'
407
+ );
408
+ } else {
409
+ return new Component(publicProps, publicContext, updateQueue);
410
}
411
+ }
412
+
413
+ // This can still be an instance in case of factory components
414
+ // but we'll count this as time spent rendering as the more common case.
415
+ if (__DEV__) {
416
+ return measureLifeCyclePerf(
417
+ () => Component(publicProps, publicContext, updateQueue),
418
+ this._debugID,
419
+ 'render'
420
+ );
421
} else {
431
- // This can still be an instance in case of factory components
432
- // but we'll count this as time spent rendering as the more common case.
433
- if (__DEV__) {
434
- if (this._debugID !== 0) {
435
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
436
- this._debugID,
437
- 'render'
438
- );
439
- }
440
- }
441
- instanceOrElement = Component(publicProps, publicContext, updateQueue);
442
- if (__DEV__) {
443
- if (this._debugID !== 0) {
444
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
445
- this._debugID,
446
- 'render'
447
- );
448
- }
449
- }
422
+ return Component(publicProps, publicContext, updateQueue);
423
}
451
- return instanceOrElement;
424
},
425
426
performInitialMountWithErrorHandling: function(
@@ -463,11 +435,6 @@ var ReactCompositeComponentMixin = {
435
try {
436
markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
437
} catch (e) {
466
- if (__DEV__) {
467
- if (this._debugID !== 0) {
468
- ReactInstrumentation.debugTool.onError();
469
- }
470
- }
438
// Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint
439
transaction.rollback(checkpoint);
440
this._instance.unstable_handleError(e);
@@ -488,23 +455,21 @@ var ReactCompositeComponentMixin = {
455
456
performInitialMount: function(renderedElement, hostParent, hostContainerInfo, transaction, context) {
457
var inst = this._instance;
458
+
459
+ var debugID = 0;
460
+ if (__DEV__) {
461
+ debugID = this._debugID;
462
+ }
463
+
464
if (inst.componentWillMount) {
465
if (__DEV__) {
493
- if (this._debugID !== 0) {
494
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
495
- this._debugID,
496
- 'componentWillMount'
497
- );
498
- }
499
- }
500
- inst.componentWillMount();
501
- if (__DEV__) {
502
- if (this._debugID !== 0) {
503
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
504
- this._debugID,
505
- 'componentWillMount'
506
- );
507
- }
466
+ measureLifeCyclePerf(
467
+ () => inst.componentWillMount(),
468
+ debugID,
469
+ 'componentWillMount'
470
+ );
471
+ } else {
472
+ inst.componentWillMount();
473
}
474
// When mounting, calls to `setState` by `componentWillMount` will set
475
// `this._pendingStateQueue` without triggering a re-render.
@@ -526,25 +491,19 @@ var ReactCompositeComponentMixin = {
491
);
492
this._renderedComponent = child;
493
529
- var selfDebugID = 0;
530
- if (__DEV__) {
531
- selfDebugID = this._debugID;
532
- }
494
var markup = ReactReconciler.mountComponent(
495
child,
496
transaction,
497
hostParent,
498
hostContainerInfo,
499
this._processChildContext(context),
539
- selfDebugID
500
+ debugID
501
);
502
503
if (__DEV__) {
543
- if (this._debugID !== 0) {
544
- ReactInstrumentation.debugTool.onSetChildren(
545
- this._debugID,
546
- child._debugID !== 0 ? [child._debugID] : []
547
- );
504
+ if (debugID !== 0) {
505
+ var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
506
+ ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
507
}
508
}
509
@@ -565,30 +524,24 @@ var ReactCompositeComponentMixin = {
524
if (!this._renderedComponent) {
525
return;
526
}
527
+
528
var inst = this._instance;
529
530
if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {
531
inst._calledComponentWillUnmount = true;
572
- if (__DEV__) {
573
- if (this._debugID !== 0) {
574
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
575
- this._debugID,
576
- 'componentWillUnmount'
577
- );
578
- }
579
- }
532
+
533
if (safely) {
534
var name = this.getName() + '.componentWillUnmount()';
535
ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));
536
} else {
584
- inst.componentWillUnmount();
585
- }
586
- if (__DEV__) {
587
- if (this._debugID !== 0) {
588
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
537
+ if (__DEV__) {
538
+ measureLifeCyclePerf(
539
+ () => inst.componentWillUnmount(),
540
this._debugID,
541
'componentWillUnmount'
542
);
543
+ } else {
544
+ inst.componentWillUnmount();
545
}
546
}
547
}
@@ -679,13 +632,21 @@ var ReactCompositeComponentMixin = {
632
_processChildContext: function(currentContext) {
633
var Component = this._currentElement.type;
634
var inst = this._instance;
682
- if (__DEV__) {
683
- ReactInstrumentation.debugTool.onBeginProcessingChildContext();
684
- }
685
- var childContext = inst.getChildContext && inst.getChildContext();
686
- if (__DEV__) {
687
- ReactInstrumentation.debugTool.onEndProcessingChildContext();
635
+ var childContext;
636
+
637
+ if (inst.getChildContext) {
638
+ if (__DEV__) {
639
+ ReactInstrumentation.debugTool.onBeginProcessingChildContext();
640
+ try {
641
+ childContext = inst.getChildContext();
642
+ } finally {
643
+ ReactInstrumentation.debugTool.onEndProcessingChildContext();
644
+ }
645
+ } else {
646
+ childContext = inst.getChildContext();
647
+ }
648
}
649
+
650
if (childContext) {
651
invariant(
652
typeof Component.childContextTypes === 'object',
@@ -831,21 +792,13 @@ var ReactCompositeComponentMixin = {
792
// immediately reconciled instead of waiting for the next batch.
793
if (willReceive && inst.componentWillReceiveProps) {
794
if (__DEV__) {
834
- if (this._debugID !== 0) {
835
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
836
- this._debugID,
837
- 'componentWillReceiveProps'
838
- );
839
- }
840
- }
841
- inst.componentWillReceiveProps(nextProps, nextContext);
842
- if (__DEV__) {
843
- if (this._debugID !== 0) {
844
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
845
- this._debugID,
846
- 'componentWillReceiveProps'
847
- );
848
- }
795
+ measureLifeCyclePerf(
796
+ () => inst.componentWillReceiveProps(nextProps, nextContext),
797
+ this._debugID,
798
+ 'componentWillReceiveProps',
799
+ );
800
+ } else {
801
+ inst.componentWillReceiveProps(nextProps, nextContext);
802
}
803
}
804
@@ -855,21 +808,13 @@ var ReactCompositeComponentMixin = {
808
if (!this._pendingForceUpdate) {
809
if (inst.shouldComponentUpdate) {
810
if (__DEV__) {
858
- if (this._debugID !== 0) {
859
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
860
- this._debugID,
861
- 'shouldComponentUpdate'
862
- );
863
- }
864
- }
865
- shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
866
- if (__DEV__) {
867
- if (this._debugID !== 0) {
868
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
869
- this._debugID,
870
- 'shouldComponentUpdate'
871
- );
872
- }
811
+ shouldUpdate = measureLifeCyclePerf(
812
+ () => inst.shouldComponentUpdate(nextProps, nextState, nextContext),
813
+ this._debugID,
814
+ 'shouldComponentUpdate'
815
+ );
816
+ } else {
817
+ shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
818
}
819
} else {
820
if (this._compositeType === CompositeTypes.PureClass) {
@@ -975,21 +920,13 @@ var ReactCompositeComponentMixin = {
920
921
if (inst.componentWillUpdate) {
922
if (__DEV__) {
978
- if (this._debugID !== 0) {
979
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
980
- this._debugID,
981
- 'componentWillUpdate'
982
- );
983
- }
984
- }
985
- inst.componentWillUpdate(nextProps, nextState, nextContext);
986
- if (__DEV__) {
987
- if (this._debugID !== 0) {
988
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
989
- this._debugID,
990
- 'componentWillUpdate'
991
- );
992
- }
923
+ measureLifeCyclePerf(
924
+ () => inst.componentWillUpdate(nextProps, nextState, nextContext),
925
+ this._debugID,
926
+ 'componentWillUpdate'
927
+ );
928
+ } else {
929
+ inst.componentWillUpdate(nextProps, nextState, nextContext);
930
}
931
}
932
@@ -1003,10 +940,13 @@ var ReactCompositeComponentMixin = {
940
941
if (hasComponentDidUpdate) {
942
if (__DEV__) {
1006
- transaction.getReactMountReady().enqueue(
1007
- invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext),
1008
- this
1009
- );
943
+ transaction.getReactMountReady().enqueue(() => {
944
+ measureLifeCyclePerf(
945
+ inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext),
946
+ this._debugID,
947
+ 'componentDidUpdate'
948
+ );
949
+ });
950
} else {
951
transaction.getReactMountReady().enqueue(
952
inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext),
@@ -1026,6 +966,12 @@ var ReactCompositeComponentMixin = {
966
var prevComponentInstance = this._renderedComponent;
967
var prevRenderedElement = prevComponentInstance._currentElement;
968
var nextRenderedElement = this._renderValidatedComponent();
969
+
970
+ var debugID = 0;
971
+ if (__DEV__) {
972
+ debugID = this._debugID;
973
+ }
974
+
975
if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
976
ReactReconciler.receiveComponent(
977
prevComponentInstance,
@@ -1045,25 +991,19 @@ var ReactCompositeComponentMixin = {
991
);
992
this._renderedComponent = child;
993
1048
- var selfDebugID = 0;
1049
- if (__DEV__) {
1050
- selfDebugID = this._debugID;
1051
- }
994
var nextMarkup = ReactReconciler.mountComponent(
995
child,
996
transaction,
997
this._hostParent,
998
this._hostContainerInfo,
999
this._processChildContext(context),
1058
- selfDebugID
1000
+ debugID
1001
);
1002
1003
if (__DEV__) {
1062
- if (this._debugID !== 0) {
1063
- ReactInstrumentation.debugTool.onSetChildren(
1064
- this._debugID,
1065
- child._debugID !== 0 ? [child._debugID] : []
1066
- );
1004
+ if (debugID !== 0) {
1005
+ var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
1006
+ ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
1007
}
1008
}
1009
@@ -1093,23 +1033,16 @@ var ReactCompositeComponentMixin = {
1033
*/
1034
_renderValidatedComponentWithoutOwnerOrContext: function() {
1035
var inst = this._instance;
1036
+ var renderedComponent;
1037
1038
if (__DEV__) {
1098
- if (this._debugID !== 0) {
1099
- ReactInstrumentation.debugTool.onBeginLifeCycleTimer(
1100
- this._debugID,
1101
- 'render'
1102
- );
1103
- }
1104
- }
1105
- var renderedComponent = inst.render();
1106
- if (__DEV__) {
1107
- if (this._debugID !== 0) {
1108
- ReactInstrumentation.debugTool.onEndLifeCycleTimer(
1109
- this._debugID,
1110
- 'render'
1111
- );
1112
- }
1039
+ renderedComponent = measureLifeCyclePerf(
1040
+ () => inst.render(),
1041
+ this._debugID,
1042
+ 'render'
1043
+ );
1044
+ } else {
1045
+ renderedComponent = inst.render();
1046
}
1047
1048
if (__DEV__) {