Show React events in the timeline when ReactPerf is active (#7549)
* Show React events in the timeline when ReactPerf is active This currently only seems to work on Chrome. * Address Chrome issue
Dan Abramov committed
Aug 24, 2016 at 18:40 UTC
0a248ee7b953d5c207b87d2840bd4295891760e2
1 file changed
+65
src/renderers/shared/ReactDebugTool.js
+65
@@ -192,6 +192,63 @@ function resumeCurrentLifeCycleTimer() {
192
currentTimerType = timerType;
193
}
194
195
+var lastMarkTimeStamp = null;
196
+var canUsePerformanceMeasure =
197
+ typeof performance !== 'undefined' &&
198
+ typeof performance.mark === 'function' &&
199
+ typeof performance.clearMarks === 'function' &&
200
+ typeof performance.measure === 'function' &&
201
+ typeof performance.clearMeasures === 'function';
202
+
203
+function shouldMark(debugID) {
204
+ if (!isProfiling || !canUsePerformanceMeasure) {
205
+ return false;
206
+ }
207
+ var element = ReactComponentTreeHook.getElement(debugID);
208
+ if (element == null || typeof element !== 'object') {
209
+ return false;
210
+ }
211
+ var isHostElement = typeof element.type === 'string';
212
+ if (isHostElement) {
213
+ return false;
214
+ }
215
+ return true;
216
+}
217
+
218
+function markBegin(debugID, markType) {
219
+ if (!shouldMark(debugID)) {
220
+ return;
221
+ }
222
+
223
+ var markName = `${debugID}::${markType}`;
224
+ lastMarkTimeStamp = performanceNow();
225
+ performance.mark(markName);
226
+}
227
+
228
+function markEnd(debugID, markType) {
229
+ if (!shouldMark(debugID)) {
230
+ return;
231
+ }
232
+
233
+ var markName = `${debugID}::${markType}`;
234
+ var displayName = ReactComponentTreeHook.getDisplayName(debugID);
235
+
236
+ // Chrome has an issue of dropping markers recorded too fast:
237
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=640652
238
+ // To work around this, we will not report very small measurements.
239
+ // I determined the magic number by tweaking it back and forth.
240
+ // 0.05ms was enough to prevent the issue, but I set it to 0.1ms to be safe.
241
+ // When the bug is fixed, we can `measure()` unconditionally if we want to.
242
+ var timeStamp = performanceNow();
243
+ if (timeStamp - lastMarkTimeStamp > 0.1) {
244
+ var measurementName = `${displayName} [${markType}]`;
245
+ performance.measure(measurementName, markName);
246
+ }
247
+
248
+ performance.clearMarks(markName);
249
+ performance.clearMeasures(measurementName);
250
+}
251
+
252
var ReactDebugTool = {
253
addHook(hook) {
254
hooks.push(hook);
@@ -244,11 +301,13 @@ var ReactDebugTool = {
301
onBeginLifeCycleTimer(debugID, timerType) {
302
checkDebugID(debugID);
303
emitEvent('onBeginLifeCycleTimer', debugID, timerType);
304
+ markBegin(debugID, timerType);
305
beginLifeCycleTimer(debugID, timerType);
306
},
307
onEndLifeCycleTimer(debugID, timerType) {
308
checkDebugID(debugID);
309
endLifeCycleTimer(debugID, timerType);
310
+ markEnd(debugID, timerType);
311
emitEvent('onEndLifeCycleTimer', debugID, timerType);
312
},
313
onError(debugID) {
@@ -279,25 +338,31 @@ var ReactDebugTool = {
338
checkDebugID(debugID);
339
checkDebugID(parentDebugID, true);
340
emitEvent('onBeforeMountComponent', debugID, element, parentDebugID);
341
+ markBegin(debugID, 'mount');
342
},
343
onMountComponent(debugID) {
344
checkDebugID(debugID);
345
+ markEnd(debugID, 'mount');
346
emitEvent('onMountComponent', debugID);
347
},
348
onBeforeUpdateComponent(debugID, element) {
349
checkDebugID(debugID);
350
emitEvent('onBeforeUpdateComponent', debugID, element);
351
+ markBegin(debugID, 'update');
352
},
353
onUpdateComponent(debugID) {
354
checkDebugID(debugID);
355
+ markEnd(debugID, 'update');
356
emitEvent('onUpdateComponent', debugID);
357
},
358
onBeforeUnmountComponent(debugID) {
359
checkDebugID(debugID);
360
emitEvent('onBeforeUnmountComponent', debugID);
361
+ markBegin(debugID, 'unmount');
362
},
363
onUnmountComponent(debugID) {
364
checkDebugID(debugID);
365
+ markEnd(debugID, 'unmount');
366
emitEvent('onUnmountComponent', debugID);
367
},
368
onTestEvent() {