-
Notifications
You must be signed in to change notification settings - Fork 48.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
Fix window.event in development (#11687) #11696
Conversation
packages/shared/ReactErrorUtils.js
Outdated
@@ -185,6 +190,9 @@ if (__DEV__) { | |||
// nested call would trigger the fake event handlers of any call higher | |||
// in the stack. | |||
fakeNode.removeEventListener(evtType, callCallback, false); | |||
if (windowEvent && window.event !== windowEvent) { | |||
window.event = windowEvent; |
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.
Have you verified that the browsers that support window.event
define it as a writable property?
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've verified that the fixture works in Chrome, Safari and IE 11. Firefox does not support this. Is there a complete list of browsers I should try and support, or any support for running the tests/fixtures in a large set of real browser environments?
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.
It might be good to test in IE9 and IE10 as well if they support it.
Does this get properly reset after the event dispatch is complete? We need to be sure that window.event
doesn't start persisting, since it should only be defined while an event is in progress.
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.
Good call on checking. It does not work in IE 9 or 10 or 11 (I'm not sure how I persuaded myself that it did before), as it fails with "Assignment to read-only properties is not allowed in strict mode".
The event does get reset correctly in Chrome and Safari, and I've added a check for that to the fixture.
There are two other approaches I considered, but neither seem to work:
- Instead of
window.event =
, defining a property on window that returns the correct event. This works to return the correct event object (as far as I can tell), but the event object is unusable in IE 9 or 10 (it does work in IE 11) because any attempt to access the event's properties throws "Member not found". - Instead of creating a new fake event to dispatch, just re-dispatching window.event. (this fails with an error that "event is already being dispatched")
For now I've updated this pull request to not preserve window.event in IE at all. If it would be preferred, I can make it work in IE 11 using window.defineProperty
— it still will not work in IE9 or 10, but it can be made to not crash.
packages/shared/ReactErrorUtils.js
Outdated
@@ -185,6 +190,9 @@ if (__DEV__) { | |||
// nested call would trigger the fake event handlers of any call higher | |||
// in the stack. | |||
fakeNode.removeEventListener(evtType, callCallback, false); | |||
if (windowEvent && window.event !== windowEvent) { |
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 would prefer a strict check here (e.g. typeof windowEvent !== 'undefined' || windowEvent !== null
, depending on what actually happens).
@@ -55,6 +55,34 @@ describe('ReactErrorUtils', () => { | |||
expect(context.didCall).toBe(true); | |||
}); | |||
|
|||
if (!__DEV__ && window.hasOwnProperty('event')) { |
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.
So is this always false
? Then this shouldn't be a test at all if it never executes.
You could, however, "polyfill" window.event
in jsdom yourself somehow.
Re: #11696 (comment) If we can't find a solution that works consistently it may be better for us to document this as a limitation of the synthetic event system. Even though |
@gaearon I've updated the checks to be more precise, and removed the test that cannot be run :). @aweary I'd very much like to have this work in development — in production it works just fine already. For more of the backstory see #11687. If it would be better to make it work in IE 11 too I can do that, it's just more code. |
Could you please fix the CI and merge conflicts? |
Will do. |
done! |
@gaearon It looks like |
// in IE as it crashes in strict mode. | ||
if ( | ||
typeof window.event !== 'undefined' && | ||
window.hasOwnProperty('event') |
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's the story behind this?
Why does window.hasOwnProperty('event')
tell us whether it's writable?
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.
@gaearon Thanks for looking into this.
It is useful for two reasons, only one of which I added to the comment:
- Running
window.event = event
on IE <= 10 throws an error"SCRIPT3: Member Not Found"
. As far as I can tell, this has nothing to do with anything other than "running in IE <= 10". So I needed at least a feature check for these browsers. - Firefox does not support
window.event
at all. So I wanted a check for browsers that usually have an event property on window.
By happy coincidence this check does both. I've updated the comment, and rebased over your latest changes.
Please let me know if I can improve this more, as this is currently the main thing holding us back on 16.2.
Before this change in development window.event was overridden in invokeGuardedCallback. After this change window.event is preserved in the browsers that support it.
Details of bundled changes.Comparing: 5550ed4...1a710d3 react-dom
react-art
react-test-renderer
react-reconciler
react-native-renderer
Generated by 🚫 dangerJS |
Which browsers have you tested this on? |
Lastest Chrome, Safari, Firefox, IE 11, 10, 9 |
Can you please also test iOS Safari and Android? |
Also checked on my iPhone's Safari, and a friend's Android Chrome at it works as expected. |
Cool. Thanks! |
👍 Thank you for all your help! |
Fixes #11687
The code change is relatively simple, but I had to add a fixture to test
this as window.event is not supported by JSDom.
I included a commented-out test copying the pattern of another test in
that file, but I'm not sure how much value that adds so would happily
remove it.