-
Notifications
You must be signed in to change notification settings - Fork 47.2k
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
Avoid "Member not found exception" in IE10 #7343
Avoid "Member not found exception" in IE10 #7343
Conversation
a159cf0
to
bb3de73
Compare
Looks like this fails because
Any suggestions? |
|
I do mean https://bytes.com/topic/javascript/answers/515951-typeof-operator-returns-unknown-instead-undefined I tried to get around this by doing |
What the... perhaps eslint is ok with it if you assign "unknown" to a constant and compare with that instead? If the warning can't be disabled (make an issue for eslint perhaps?). |
I'm seeing conflicting information on this from every source (what and which browsers are affected) and I haven't been able to find any code to actually reproduce it. Do you have it? |
It's definitely bizarre. This issue was filed in #7320. I realize that I never linked it up. The following gist will reproduce the problem: https://gist.github.com/nhunzaker/79d48674f543a3bf0977667c2513e9ac IE9Likewise, entering text in the "Stops propagation" here will raise the same exception: IE10Entering text in the "Stops propagation" input will raise a "Member not found" exception: IE 11, Edge 13, Edge 14Gets it right: I haven't figured out a way to reproduce this outside of React. As you've mentioned, the documentation is fuzzy at best. I think there might be something going on in |
Okay. Here we go. For whatever reason in IE9-10, a ton of properties are not found in the event backing the SyntheticEvent dispatching change: I wish I could provide a spec on how IE treats these events. When I create a custom event:
Seems fine. I totally get the aversion to committing a hack like |
From some experimentation it seems its the Also, FYI for anyone trying to understand this. This is because we're listening to the
IMHO, I don't really see an issue, it works and it's precise. If eslint is the only issue then working around it seems fine to me at least, either by comparing to a constant (if that works) or putting in a separate file and disabling eslint in that file. On another note (and I may be totally off here), but I'm curious why we even stop propagation of native events at all, they're all document listeners so unless I'm mistaken nothing good comes from cancelling them in the first place? We might still want to change that in the future, so it makes sense to fix it... it just struck me as odd. |
Chiming in, no need for a separate file, this should work: // eslint-disable-next-line valid-typeof
if (typeof x === 'unknown') {
/* … */
} (if |
bb3de73
to
76d6232
Compare
@mxstbr Beat me to it! Done. |
For completeness: |
Did a quick test, and my initial impression is that we don't need to invoke them directly at all. It seems like the only reason to do it would be so that the native event reference indicates that stopPropagation has been applied. |
} else { | ||
} else if (typeof event.cancelBubble !== 'unknown') { // eslint-disable-line valid-typeof | ||
// <= IE10 throws a "Member not found" error if the cancelBubble | ||
// attribute is accessed from an onChange event. A typeof check of "unknown" |
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.
Perhaps clarify that this is because of "propertychange"
and not because of actual change events.
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.
Got it:
// The ChangeEventPlugin registers a "propertychange" event for
// IE. This event does not support bubbling or cancelling, and
// any references to cancelBubble throw "Member not found". A
// typeof check of "unknown" circumvents this issue (and is also
// IE specific).
76d6232
to
27b5587
Compare
'change' custom events raise "Member not found" in <= IE10. To circumvent this, the SyntheticEvent class now checks for "typeof event.cancelBubble !== 'unknown'". This eliminates this exception and maintains the expected bubbling functionality. Addresses facebook#7320.
27b5587
to
1a64911
Compare
Alright. I think I'm set! |
Anything else to follow up on here? |
@@ -135,9 +135,15 @@ Object.assign(SyntheticEvent.prototype, { | |||
|
|||
if (event.stopPropagation) { | |||
event.stopPropagation(); | |||
} else { | |||
} else if (typeof event.cancelBubble !== 'unknown') { // eslint-disable-line valid-typeof |
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'm assuming this fails the lint line length rule?
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.
Technically no, though it's against the React style guide all the same.
ESLint seems to struggle with else if
. The only other valid option I can manage is:
if (event.stopPropagation) {
event.stopPropagation();
/* eslint-disable valid-typeof */
} else if (typeof event.cancelBubble !== 'unknown') {
/* eslint-enable valid-typeof */
}
Or we could flip the if to place typeof event.cancelBubble
before the event.stopPropagation
check.
I know this is annoying and silly. Thank you for your patience on this.
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'm care-face on this (not my decision). If it's a problem just leave it as is and they'll complain if need be.
I fail to see how this can be harmful (EDIT: The PR that is). The only thing that strikes me as odd I guess is that this doesn't really solve the problem, it just prevents an error right? So technically, you can stop propagation of onchange with this, but in IE<=10 it will not actually do it? It might make sense to throw a warning or something as well perhaps? |
It works as expected. The bubbling is handled by the synthetic event system. Best I can tell, the whole reason for the stopPropagation logic is for interaction with code that might be listening to to the DOM nodes themselves (from a lifecycle hook or something). Given the following code: function onChange (event) {
event.stopPropagation()
}
ReactDOM.render((
<div onChange={ () => alert('Noooo!') }>
<input defaultValue="hey" onChange={ onChange } />
</div>
),document.getElementById('container')) It behaves as one would expect. The onChange callback on the parent is never fired. If you remove |
Oh right right, that still happens. Yeah, then I have nothing to object to :) 👍 |
Okay, thanks! |
Hizzah! |
I believe this only fixes half the problem. This same logic will also need to be added to |
@g-palmer Cool. I can send out a PR with this change, unless you would like to. |
Explanation and similar change as facebook#7343 Addresses facebook#7320
@nhunzaker If you don't mind, I'd like to go ahead and make the change real quick |
I don't mind. Go for it! |
Explanation, discussion, and similar change as facebook#7343 Addresses facebook#7320
Explanation, discussion, and similar change as facebook#7343 Addresses facebook#7320
Explanation, discussion, and similar change as facebook#7343 Addresses facebook#7320
In <= IE10, custom change events raise "Member not found" when accessing 'cancelBubble' . To circumvent this, the SyntheticEvent class now checks for "typeof event.cancelBubble !== 'unknown'". This eliminates this exception and maintains the expected bubbling functionality.
I'd never heard of
typeof x === 'unknown'
before, but it seems to be a goofy JScript thing. I discovered it in the jQuery issue tracker:https://bugs.jquery.com/ticket/10004
I've confirmed that this preserves bubbling functionality from IE9-11, Safari, Chrome, and Firefox.
This technically is not a problem on
master
, but it fixes the issue for15-stable
and I'm sort of curious what other events have this same issue.