Skip to content
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 movementX/Y polyfill with capture events #19672

Merged
merged 2 commits into from Aug 21, 2020
Merged

Conversation

gaearon
Copy link
Collaborator

@gaearon gaearon commented Aug 21, 2020

This is a blocker I need to resolve for #19648.

Our movementX/Y polyfill is currently broken with the modern event system if you use a capture event. This is because it diffs the screenX/Y with the last event's values, but now we have two synthetic events per one native event (due to capture and bubble phase). So we create an event in the capture phase, set its movementX/Y, and then we create another object in the bubble phase, and its movementX/Y is calculated to be 0 (because it is diffed with the event we just created earlier).

To fix this, I am pulling this logic out in one place and update both movementX and movementY values together and only if the native event has changed. This means we retain one last mouse event at a time (when the polyfill is used, which is IE11-only). Seems ok.

Test Plan

Added a test that previously failed.

I also manually tested by forcing the polyfill to always be used and running it with this fixture:

        <div style={{
          width: '100vw',
          height: '100vh',
          background: 'red'
        }}
          onMouseDown={e => {
            if (e.movementX !== e.nativeEvent.movementX) {
              console.error('noooooo', e.movementX, e.nativeEvent.movementX)
            }
            if (e.movementY !== e.nativeEvent.movementY) {
              console.error('noooooo', e.movementY, e.nativeEvent.movementY)
            }
          }}
          onMouseDownCapture={e => {
            if (e.movementX !== e.nativeEvent.movementX) {
              console.error('noooooo', e.movementX, e.nativeEvent.movementX)
            }
            if (e.movementY !== e.nativeEvent.movementY) {
              console.error('noooooo', e.movementY, e.nativeEvent.movementY)
            }
          }}
          onMouseMove={e => {
            if (e.movementX !== e.nativeEvent.movementX) {
              console.error('noooooo', e.movementX, e.nativeEvent.movementX)
            }
            if (e.movementY !== e.nativeEvent.movementY) {
              console.error('noooooo', e.movementY, e.nativeEvent.movementY)
            }
          }}
          onMouseMoveCapture={e => {
            if (e.movementX !== e.nativeEvent.movementX) {
              console.error('noooooo', e.movementX, e.nativeEvent.movementX)
            }
            if (e.movementY !== e.nativeEvent.movementY) {
              console.error('noooooo', e.movementY, e.nativeEvent.movementY)
            }
          }}
          onMouseUp={e => {
            if (e.movementX !== e.nativeEvent.movementX) {
              console.error('noooooo', e.movementX, e.nativeEvent.movementX)
            }
            if (e.movementY !== e.nativeEvent.movementY) {
              console.error('noooooo', e.movementY, e.nativeEvent.movementY)
            }
          }}
          onMouseUpCapture={e => {
            if (e.movementX !== e.nativeEvent.movementX) {
              console.error('noooooo', e.movementX, e.nativeEvent.movementX)
            }
            if (e.movementY !== e.nativeEvent.movementY) {
              console.error('noooooo', e.movementY, e.nativeEvent.movementY)
            }
          }}
        />,

Clicking and moving works as expected (no violations). There is a calculation bug every time after we move cursor outside the screen and bring it back, but this bug existed in 16 too, and I don't think it's worth fixing. (We'll remove the polyfill eventually anyway).

@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Aug 21, 2020
@codesandbox-ci
Copy link

codesandbox-ci bot commented Aug 21, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit f976c48:

Sandbox Source
React Configuration

@sizebot
Copy link

sizebot commented Aug 21, 2020

No significant bundle size changes to report.

Size changes (experimental)

Generated by 🚫 dangerJS against f976c48

@sizebot
Copy link

sizebot commented Aug 21, 2020

No significant bundle size changes to report.

Size changes (stable)

Generated by 🚫 dangerJS against f976c48

@gaearon gaearon merged commit 90d212d into facebook:master Aug 21, 2020
@gaearon gaearon deleted the mouse branch August 21, 2020 15:59
trueadm referenced this pull request in reactjs/react.dev Aug 28, 2020
lastMovementX = 0;
lastMovementY = 0;
}
lastMouseEvent = event;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this GC root the event? This seems like a leak.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will root only one (the very last) mouse event, and only on IE11, so this should not be an issue.

This was referenced Mar 15, 2021
koto pushed a commit to koto/react that referenced this pull request Jun 15, 2021
* Fix movementX/Y polyfill with capture events

* Remove unnecesary call for better inlining
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants