New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ReactInstrumentation #6068
Merged
Merged
Add ReactInstrumentation #6068
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** | ||
* Copyright 2016-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* @providesModule ReactDebugTool | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var warning = require('warning'); | ||
|
||
var eventHandlers = []; | ||
var handlerDoesThrowForEvent = {}; | ||
|
||
function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) { | ||
if (__DEV__) { | ||
eventHandlers.forEach(function(handler) { | ||
try { | ||
if (handler[handlerFunctionName]) { | ||
handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5); | ||
} | ||
} catch (e) { | ||
warning( | ||
!handlerDoesThrowForEvent[handlerFunctionName], | ||
'exception thrown by devtool while handling %s: %s', | ||
handlerFunctionName, | ||
e.message | ||
); | ||
handlerDoesThrowForEvent[handlerFunctionName] = true; | ||
} | ||
}); | ||
} | ||
} | ||
|
||
var ReactDebugTool = { | ||
addDevtool(devtool) { | ||
eventHandlers.push(devtool); | ||
}, | ||
removeDevtool(devtool) { | ||
for (var i = 0; i < eventHandlers.length; i++) { | ||
if (eventHandlers[i] === devtool) { | ||
eventHandlers.splice(i, 1); | ||
i--; | ||
} | ||
} | ||
}, | ||
onMountRootComponent(internalInstance) { | ||
emitEvent('onMountRootComponent', internalInstance); | ||
}, | ||
onMountComponent(internalInstance) { | ||
emitEvent('onMountComponent', internalInstance); | ||
}, | ||
onUpdateComponent(internalInstance) { | ||
emitEvent('onUpdateComponent', internalInstance); | ||
}, | ||
onUnmountComponent(internalInstance) { | ||
emitEvent('onUnmountComponent', internalInstance); | ||
}, | ||
}; | ||
|
||
module.exports = ReactDebugTool; | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Copyright 2016-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* @providesModule ReactInstrumentation | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var ReactDebugTool = require('ReactDebugTool'); | ||
|
||
module.exports = {debugTool: ReactDebugTool}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ var ReactDOMContainerInfo = require('ReactDOMContainerInfo'); | |
var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); | ||
var ReactElement = require('ReactElement'); | ||
var ReactFeatureFlags = require('ReactFeatureFlags'); | ||
var ReactInstrumentation = require('ReactInstrumentation'); | ||
var ReactMarkupChecksum = require('ReactMarkupChecksum'); | ||
var ReactPerf = require('ReactPerf'); | ||
var ReactReconciler = require('ReactReconciler'); | ||
|
@@ -347,6 +348,10 @@ var ReactMount = { | |
var wrapperID = componentInstance._instance.rootID; | ||
instancesByReactRootID[wrapperID] = componentInstance; | ||
|
||
if (__DEV__) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I put these behind |
||
ReactInstrumentation.debugTool.onMountRootComponent(componentInstance); | ||
} | ||
|
||
return componentInstance; | ||
}, | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are going to need a debug tool specific to each renderer. Does it make sense to also have a shared isomorphic ReactDebugTool for just a few lifecycle mehods? Especially when some of the lifecycles may not exist for some renderers (eg. ServerSideRendering, if/when that gets split out). Intuitively, it feels simpler/cleaner if all the debug tools just always live in the individual renderers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was acting on @sebmarkbage’s comment in #6046 (comment).
We can definitely do it per renderer (especially considering that for now, we’ll have to do profiling calls in #6046 per renderer anyway). However even for profiling calls the longer term is to have shared reconciliation logic and do them in generic way, per #6046 (comment):
The tools that rely on ReactInstrumentation will have to make some assumptions. I think that “components get mounted, updated, and unmounted” is a good one. Yes, it means that these hooks never fire on the server, but what practical difference does it make? On the other hand, as a benefit React DevTools extension can work with any renderer out of the box (pretty much like it does now, but without the monkey patching).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I have no strong objections. I think it's a little unfortunate to have two places to install the subtally-different debug tools, which is my main complaint, but I'm willing to defer to @sebmarkbage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes sense if you think about what making a refactor would mean for the normal algorithm. These methods are required to exist. If we add an event to isomorphic code, then that would break every other renderer (as in ART, DOM, RN) out there until they get added. If they're part of isomorphic code then it doesn't break. It will just emit unknown events to the handlers.