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

Add ReactInstrumentation

This adds `ReactInstrumentation` for the isomorphic package that uses the same approach as `ReactDOMInstrumentation`. Currently it is gated behind `__DEV__` but we will likely change this later to a runtime flag determined by whether there are any active listeners. The first few events we add here should be sufficient for React DevTools, as determined by the `hook.emit()` calls in https://github.com/facebook/react-devtools/blob/d90c43201617d5aef378669da926d79515b6a811/backend/attachRenderer.js. These events will also be useful for reconstructing the parent tree in the ReactPerf rewrite in #6046.

Dan Abramov committed Feb 18, 2016 at 22:52 UTC 3863330524d99b5ebedbfa65bc09fa46ae7fa8a6
4 files changed +101 -1
src/isomorphic/ReactDebugTool.js new
+65
@@ -0,0 +1,65 @@
1 +/**
2 + * Copyright 2016-present, Facebook, Inc.
3 + * All rights reserved.
4 + *
5 + * This source code is licensed under the BSD-style license found in the
6 + * LICENSE file in the root directory of this source tree. An additional grant
7 + * of patent rights can be found in the PATENTS file in the same directory.
8 + *
9 + * @providesModule ReactDebugTool
10 + */
11 +
12 +'use strict';
13 +
14 +var warning = require('warning');
15 +
16 +var eventHandlers = [];
17 +var handlerDoesThrowForEvent = {};
18 +
19 +function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {
20 + if (__DEV__) {
21 + eventHandlers.forEach(function(handler) {
22 + try {
23 + if (handler[handlerFunctionName]) {
24 + handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);
25 + }
26 + } catch (e) {
27 + warning(
28 + !handlerDoesThrowForEvent[handlerFunctionName],
29 + 'exception thrown by devtool while handling %s: %s',
30 + handlerFunctionName,
31 + e.message
32 + );
33 + handlerDoesThrowForEvent[handlerFunctionName] = true;
34 + }
35 + });
36 + }
37 +}
38 +
39 +var ReactDebugTool = {
40 + addDevtool(devtool) {
41 + eventHandlers.push(devtool);
42 + },
43 + removeDevtool(devtool) {
44 + for (var i = 0; i < eventHandlers.length; i++) {
45 + if (eventHandlers[i] === devtool) {
46 + eventHandlers.splice(i, 1);
47 + i--;
48 + }
49 + }
50 + },
51 + onMountRootComponent(internalInstance) {
52 + emitEvent('onMountRootComponent', internalInstance);
53 + },
54 + onMountComponent(internalInstance) {
55 + emitEvent('onMountComponent', internalInstance);
56 + },
57 + onUpdateComponent(internalInstance) {
58 + emitEvent('onUpdateComponent', internalInstance);
59 + },
60 + onUnmountComponent(internalInstance) {
61 + emitEvent('onUnmountComponent', internalInstance);
62 + },
63 +};
64 +
65 +module.exports = ReactDebugTool;
src/isomorphic/ReactInstrumentation.js new
+16
@@ -0,0 +1,16 @@
1 +/**
2 + * Copyright 2016-present, Facebook, Inc.
3 + * All rights reserved.
4 + *
5 + * This source code is licensed under the BSD-style license found in the
6 + * LICENSE file in the root directory of this source tree. An additional grant
7 + * of patent rights can be found in the PATENTS file in the same directory.
8 + *
9 + * @providesModule ReactInstrumentation
10 + */
11 +
12 +'use strict';
13 +
14 +var ReactDebugTool = require('ReactDebugTool');
15 +
16 +module.exports = {debugTool: ReactDebugTool};
src/renderers/dom/client/ReactMount.js
+5
@@ -20,6 +20,7 @@ var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
20 var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
21 var ReactElement = require('ReactElement');
22 var ReactFeatureFlags = require('ReactFeatureFlags');
23 +var ReactInstrumentation = require('ReactInstrumentation');
24 var ReactMarkupChecksum = require('ReactMarkupChecksum');
25 var ReactPerf = require('ReactPerf');
26 var ReactReconciler = require('ReactReconciler');
@@ -347,6 +348,10 @@ var ReactMount = {
348 var wrapperID = componentInstance._instance.rootID;
349 instancesByReactRootID[wrapperID] = componentInstance;
350
351 + if (__DEV__) {
352 + ReactInstrumentation.debugTool.onMountRootComponent(componentInstance);
353 + }
354 +
355 return componentInstance;
356 },
357
src/renderers/shared/reconciler/ReactReconciler.js
+15 -1
@@ -12,6 +12,7 @@
12 'use strict';
13
14 var ReactRef = require('ReactRef');
15 +var ReactInstrumentation = require('ReactInstrumentation');
16
17 /**
18 * Helper to call ReactRef.attachRefs with this composite component, split out
@@ -51,6 +52,9 @@ var ReactReconciler = {
52 internalInstance._currentElement.ref != null) {
53 transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
54 }
55 + if (__DEV__) {
56 + ReactInstrumentation.debugTool.onMountComponent(internalInstance);
57 + }
58 return markup;
59 },
60
@@ -70,7 +74,10 @@ var ReactReconciler = {
74 */
75 unmountComponent: function(internalInstance, safely) {
76 ReactRef.detachRefs(internalInstance, internalInstance._currentElement);
73 - return internalInstance.unmountComponent(safely);
77 + internalInstance.unmountComponent(safely);
78 + if (__DEV__) {
79 + ReactInstrumentation.debugTool.onUnmountComponent(internalInstance);
80 + }
81 },
82
83 /**
@@ -119,6 +126,10 @@ var ReactReconciler = {
126 internalInstance._currentElement.ref != null) {
127 transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
128 }
129 +
130 + if (__DEV__) {
131 + ReactInstrumentation.debugTool.onUpdateComponent(internalInstance);
132 + }
133 },
134
135 /**
@@ -133,6 +144,9 @@ var ReactReconciler = {
144 transaction
145 ) {
146 internalInstance.performUpdateIfNecessary(transaction);
147 + if (__DEV__) {
148 + ReactInstrumentation.debugTool.onUpdateComponent(internalInstance);
149 + }
150 },
151
152 };