-
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
Fix wheel/touch browser locking in IE and Safari #9333
Conversation
@@ -151,6 +152,39 @@ var topEventMapping = { | |||
topWheel: 'wheel', |
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.
This object is the exact same as EventConstants
, sans the values. Has there been any thought on consolidating them into EventConstants
?
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, please send a follow-up to consolidate these! Would be nice to have 'Browser' or 'DOM' in the name too.
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.
👍
@@ -948,6 +833,7 @@ ReactDOMComponent.Mixin = { | |||
DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey); | |||
} | |||
} | |||
|
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 going to kill some of this whitespace noise.
d26fc06
to
e61ddae
Compare
Talked through how to deal with invalid nesting with @spicyj. I'm sure there's some extra work here, but I think it's in a good spot to review. |
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 this is good overall. A couple inlines.
Are we able to add touch events too? They can block scrolling on touch devices. We should be careful around the behavior for touch events on a node that gets removed though. Currently I think you lose move/end events if a node is removed while touching. We might even want to change this but should be conscious of it. Maybe best in a separate PR.
It used to be that we needed to remove listeners when a node is unmounted (a fix ages ago was in c62c2c5). I believe this is no longer necessary since we no longer track nodes by hierarchical IDs but I'm mentioning it for completeness and posterity.
@@ -151,6 +152,39 @@ var topEventMapping = { | |||
topWheel: 'wheel', |
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, please send a follow-up to consolidate these! Would be nice to have 'Browser' or 'DOM' in the name too.
@@ -224,7 +258,7 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, { | |||
* @param {string} registrationName Name of listener (e.g. `onClick`). | |||
* @param {object} contentDocumentHandle Document which owns the container | |||
*/ | |||
listenTo: function(registrationName, contentDocumentHandle) { | |||
listenTo: function(registrationName, contentDocumentHandle, node) { | |||
var mountAt = contentDocumentHandle; | |||
var isListening = getListeningForDocument(mountAt); |
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.
Can we add a 'Doc' somewhere in this name for clarity?
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.
Yep!
topTouchMove: true, | ||
topTouchStart: true, | ||
topTouchCancel: true, | ||
topTouchEnd: true, |
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.
@spicyj I've added touch cancel and touch end to the list here ☝️. They'll get attached locally now.
8911065
to
a655b5b
Compare
Having some trouble |
I tried to fix the conflict with master, let's see if CI passes. |
I'll work on getting CI to pass later today. @spicyj I've pushed up some stuff to address your feedback, and I have a PR nearly done which consolidates the event names. It just needs to be rebased with master. Beyond that, I wonder if it is a good idea to add some DOM fixtures for media events. |
@spicyj Could you take over rebasing this PR so that @nhunzaker can continue work on #7311 and not worry about this one? |
This is a follow up to facebook#9333. This commit removes some duplication of event names and renames the EventConstants module to BrowserEventConstants.
This is a follow up to facebook#9333. This commit removes some duplication of event names and renames the EventConstants module to BrowserEventConstants.
This is a follow up to facebook#9333. This commit removes some duplication of event names and renames the EventConstants module to BrowserEventConstants.
This is a follow up to facebook#9333. This commit removes some duplication of event names and renames the EventConstants module to BrowserEventConstants.
This is a follow up to facebook#9333. This commit removes some duplication of event names and renames the EventConstants module to BrowserEventConstants.
d338a43
to
1ad7e85
Compare
Upstreamed this with my other PR that consolidated the event list. |
@philipp-spiess Ah good deal. I can just make them attach with bubbling. We only need capture for scroll/wheel. |
Scroll events need to be attached locally in order to receive rendering optimizations in Firefox, Edge, and Safari. Unfortunately, scroll events can be nested. When attached locally, events bubble up through both the DOM and React event systems. This commit adds a module that tracks what events have dispatched. When possible, it uses a WeakSet to test membership. When the event is fully dispatched, it should be released with GC. For browsers that do not support WeakSets, this module modifies the event with a flag. This needs to be tested in IE.
Prior work included an event listener on the root container that would release events from tracking. This is not necessary. Instead, we can track the last currentTarget to see if the dispatch should be counted. This appears to work for both bubbling and capture. Assuming the following markup: ```html <div id="top" onScroll={...}> <div id="middle" onScroll={...}> <div id="bottom" onScroll={...} /> </div> </div> ``` Assume all levels have a local scroll listener. If we dispatch from the bottom: 1. The first target is the "top", because we assign it as captured. Capture works in reverse. 2. "middle" is skipped because the event is tracked to "top" 3. "bottom" is skipped because the event is trakced to "top" This means that only one synthetic event dispatch occurs once.
d8aadd3
to
d8b88fa
Compare
d8b88fa
to
e7884fc
Compare
@philipp-spiess moved touch events to bubbling and I added a test suite that verifies the bubble order on the react end (it's the same between capture and bubble, but using capture would definitely break existing expectations with events outside of react) Are these valuable tests? It was useful for me to work through them, but I'm not sure if they give us any extra coverage. |
I think it makes sense. If we plan on handling touch events separately, we should at least make sure they still behave similarly. |
Supporting bubbling on touch added an edge case where re-dispatching the same event below the last dispatch ignores the second dispatch incorrectly. I've pushed up that failing case. I'm about out of ideas, but inspiration might strike. |
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution. |
Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you! |
In order for Firefox, Edge, and Safari to optimize scroll rendering, scroll events must be attached locally.
The React synthetic event system isn't really built to handle this, attaching events locally causes a dispatch to the React Synthetic event system, which is problematic for nested scroll event handlers. To work around that, this PR adds a deduping mechanism that track what native events have already dispatched, bailing early if they have already been processed
Testing
I have forked @nolanlawson's wheel jank example and built it with this branch's version of React. You can view the difference by doing the following:
Related issues: #1254 (comment)