-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Use devtool for unknown property warning #5590
Merged
jimfb
merged 3 commits into
facebook:master
from
jimfb:use-devtool-for-unknown-property-warning
Dec 24, 2015
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
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
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,66 @@ | ||
/** | ||
* Copyright 2013-2015, 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 ReactDOMDebugTool | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var ReactDOMUnknownPropertyDevtool = require('ReactDOMUnknownPropertyDevtool'); | ||
|
||
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 ReactDOMDebugTool = { | ||
addDevtool(devtool) { | ||
eventHandlers.push(devtool); | ||
}, | ||
removeDevtool(devtool) { | ||
for (var i = 0; i < eventHandlers.length; i++) { | ||
if (eventHandlers[i] === devtool) { | ||
eventHandlers.splice(i, 1); | ||
i--; | ||
} | ||
} | ||
}, | ||
onCreateMarkupForProperty(name, value) { | ||
emitEvent('onCreateMarkupForProperty', name, value); | ||
}, | ||
onSetValueForProperty(node, name, value) { | ||
emitEvent('onSetValueForProperty', node, name, value); | ||
}, | ||
onDeleteValueForProperty(node, name) { | ||
emitEvent('onDeleteValueForProperty', node, name); | ||
}, | ||
}; | ||
|
||
ReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool); | ||
|
||
module.exports = ReactDOMDebugTool; |
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 2013-2015, 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 ReactDOMInstrumentation | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var ReactDOMDebugTool = require('ReactDOMDebugTool'); | ||
|
||
module.exports = {debugTool: ReactDOMDebugTool}; | ||
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
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
87 changes: 87 additions & 0 deletions
87
src/renderers/dom/shared/devtools/ReactDOMUnknownPropertyDevtool.js
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,87 @@ | ||
/** | ||
* Copyright 2013-2015, 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 ReactDOMUnknownPropertyDevtool | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var DOMProperty = require('DOMProperty'); | ||
var EventPluginRegistry = require('EventPluginRegistry'); | ||
|
||
var warning = require('warning'); | ||
|
||
if (__DEV__) { | ||
var reactProps = { | ||
children: true, | ||
dangerouslySetInnerHTML: true, | ||
key: true, | ||
ref: true, | ||
}; | ||
var warnedProperties = {}; | ||
|
||
var warnUnknownProperty = function(name) { | ||
if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) { | ||
return; | ||
} | ||
if (reactProps.hasOwnProperty(name) && reactProps[name] || | ||
warnedProperties.hasOwnProperty(name) && warnedProperties[name]) { | ||
return; | ||
} | ||
|
||
warnedProperties[name] = true; | ||
var lowerCasedName = name.toLowerCase(); | ||
|
||
// data-* attributes should be lowercase; suggest the lowercase version | ||
var standardName = ( | ||
DOMProperty.isCustomAttribute(lowerCasedName) ? | ||
lowerCasedName : | ||
DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? | ||
DOMProperty.getPossibleStandardName[lowerCasedName] : | ||
null | ||
); | ||
|
||
// For now, only warn when we have a suggested correction. This prevents | ||
// logging too much when using transferPropsTo. | ||
warning( | ||
standardName == null, | ||
'Unknown DOM property %s. Did you mean %s?', | ||
name, | ||
standardName | ||
); | ||
|
||
var registrationName = ( | ||
EventPluginRegistry.possibleRegistrationNames.hasOwnProperty( | ||
lowerCasedName | ||
) ? | ||
EventPluginRegistry.possibleRegistrationNames[lowerCasedName] : | ||
null | ||
); | ||
|
||
warning( | ||
registrationName == null, | ||
'Unknown event handler property %s. Did you mean `%s`?', | ||
name, | ||
registrationName | ||
); | ||
}; | ||
} | ||
|
||
var ReactDOMUnknownPropertyDevtool = { | ||
onCreateMarkupForProperty(name, value) { | ||
warnUnknownProperty(name); | ||
}, | ||
onSetValueForProperty(node, name, value) { | ||
warnUnknownProperty(name); | ||
}, | ||
onDeleteValueForProperty(node, name) { | ||
warnUnknownProperty(name); | ||
}, | ||
} | ||
|
||
module.exports = ReactDOMUnknownPropertyDevtool; |
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.
What is the difference between “debug tool” and a “dev tool”? I got tripped by this a couple of times because I write a
Devtool
but I’m then adding it to aDebugTool
which I refer to asReactDOMInstrumentation.debugTool
. Why is there more than one layer of indirection?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.
There is only ever one debug tool. A debug tool doesn't (necessarily) have the overhead of emitting events, so it is suitable for collecting ultra-accurate performance metrics.
The default debug tool is an event emitter, into which you can plug dev tools.
A dev tool is something that is not performance critical. Things like emitting warnings, high-level performance metrics, interactive chrome extensions, etc. You want to maintain good performance, but you're willing to eat the cost of event delegation for the purposes of a slightly better API (ie. the ability to have multiple devtools at the same time, functions you don't implement are ignored, errors thrown in a devtool don't take down the app, etc).
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.
Thank you for explaining. I’m curious because I wonder how something like Chrome extension would work once we port it to use this API. Currently Chrome extension works with production builds. Would that no longer be the case (presumably because production builds would use a noop debug tool)?
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.
Correct, my guess is that devtools would only work in dev mode, but it's an easy thing to change if we change our minds.
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.
To add more context, I am adding some events that will be useful both to React DevTools and new ReactPerf in #6068. If those are DEV-only, the new ReactPerf would also be DEV-only which would defeat the purpose of ReactPerf. How would debug tool / devtool distinction handle this problem?
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 Sebastian was thinking about creating a third build called "profile", which follows all the "production" codepaths with the exception of having debugtool enabled.
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.
Do these different builds have any overlap with the feature flags such as https://github.com/facebook/react/blob/3b96650e39ddda5ba49245713ef16dbc52d25e9e/src/shared/utils/ReactFeatureFlags.js?
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.
Yes, eventually. Right now it's controlled by
__DEV__
, and is not as simple as just replacing all__DEV__
s with a feature flag for reasons around dead code elimination.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.
Thanks, @jimfb. The “eventually” part is all I need to know :)