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

DOM: Test {mouse,}wheel and touch{move,start} events are non-cancelable when there are no non-passive event listeners #34464

Merged
merged 18 commits into from
Jul 5, 2022

Conversation

zcorpan
Copy link
Member

@zcorpan zcorpan commented Jun 16, 2022

Test that events are not cancelable when there are no non-passive event listeners, and cancelable when there are non-passive event listeners.

Follows https://w3c.github.io/touch-events/#cancelability

In particular, a user agent may generate only uncancelable touch events when it observes that there are no non-passive listeners for the event.

...and the same for wheel events and mousewheel events, but that is not yet defined in https://w3c.github.io/uievents/#cancelability-of-wheel-events . The relevant issue is w3c/uievents#282

@zcorpan
Copy link
Member Author

zcorpan commented Jun 16, 2022

The tests pass in Chrome, but fail in Firefox and Safari because:

For wheel/mousewheel

Firefox: ERROR message: Unknown action type: [object String] "wheel"

Safari:

ERROR message: Encountered invalid 'type' and 'pointerType' combination in payload: {
    actions =     (
                {
            deltaX = 0;
            deltaY = 100;
            origin = viewport;
            type = scroll;
            x = 588;
            y = 375;
        }
    );
    id = 1;
    type = wheel;
}

For touchmove/touchstart:

Firefox: ERROR message: Unknown pointerType: touch

Safari: TIMEOUT

Both Firefox and Safari on wpt CI are with touch support disabled, so maybe not testable until we test with builds/devices where touch support is enabled.

@zcorpan
Copy link
Member Author

zcorpan commented Jun 16, 2022

@zcorpan
Copy link
Member Author

zcorpan commented Jun 16, 2022

I used separate demos for mousewheel and wheel because at least in Chrome, when there were wheel event listeners, it would only fire wheel events, not mousewheel events. I suppose it's because pages can listen for both, but expect only one of them. (Not sure if this is specified, mousewheel isn't even mentioned in UI Events.)

@zcorpan
Copy link
Member Author

zcorpan commented Jun 16, 2022

I tried testing multiple events, but could not reproduce passive after non-passive with testdriver.js.

If the concept of default passive event listeners is unrelated to whether a previous event was preventDefault()ed, I'll remove that from these tests.

Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

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

So I left an inline comment about passive vs. non-cancelable, but I'm wondering if there's a bigger problem there... or maybe I'm just not understanding.

Basically, is there any evidence that passive-ness is involved here at all? It seems like everything could be explained by browsers just firing non-cancelable events. Whereas the point of passive is to allow certain listeners to have no-op preventDefault(), even if the event can be preventDefault()ed by other listeners and thus has cancelable = true.

EDIT: maybe the evidence is that if you set passive: false explicitly, that overrides the default behavior? But in that case cancelable should be true, whereas these tests expect false for non-divs...

@zcorpan
Copy link
Member Author

zcorpan commented Jun 28, 2022

This tests that the events are non-cancellable as allowed in https://w3c.github.io/touch-events/#cancelability and ... not yet in https://w3c.github.io/uievents/#cancelability-of-wheel-events . The issue is w3c/uievents#282 -- I can submit a PR to fix the spec.

In particular, a user agent may generate only uncancelable touch events when it observes that there are no non-passive listeners for the event.

I'm not sure why this is only a "may", and not a "must" or at least "should". I'll file an issue. Edit: w3c/touch-events#130

@domenic
Copy link
Member

domenic commented Jun 28, 2022

Hmm, so that is very weird. So basically, if you do addEventListener(..., { passive: false }) explicitly, then the UA will allow cancelable = true... but if you do addEventListener(...) alone, then cancelable = false?

I would have expected cancelable to not change, and always be true, but passive listeners would do nothing when they call preventDefault(). That is what being a passive listener means, after all! The extra complication of flipping cancelable depending on what is going on with the listeners seems really unnecessary...

@zcorpan
Copy link
Member Author

zcorpan commented Jun 28, 2022

I guess the browser would be lying if it fired events with cancelable = true that are not in fact cancelable. You wouldn't know without registering a non-passive listener, of course. I guess there could be a race condition between the browser queueing an event to be fired (non-cancelable) and the page registering a non-passive listener?

@zcorpan
Copy link
Member Author

zcorpan commented Jun 28, 2022

@domenic I've opened a new PR with the strategy discussed in #34464 (comment) which doesn't rely on the related but separate intervention to fire cancelable events when there are no non-passive listeners:

#34623

@zcorpan zcorpan changed the title DOM: Test passive/non-passive {mouse,}wheel and touch{move,start} events on window, document, body, div DOM: Test {mouse,}wheel and touch{move,start} events are non-cancelable when there are no non-passive event listeners Jun 28, 2022
@zcorpan
Copy link
Member Author

zcorpan commented Jun 28, 2022

@domenic OK I've changed this PR to isolate testing of cancelable when there are passive listeners vs when there are non-passive listeners.

Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

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

Generally looks good. However, I do think we should expand the test coverage in two ways:

  • We should also test touchend, and show that this does not apply to touchend. Right now it seems an implementation could pass by just applying this to every event.

  • We should test synthetic events (with dispatchEvent()). Ideally test both the proper event type (e.g. TouchEvent) and a non-correct event type (e.g. Event). I don't actually know what the behavior will be for these...

There are other cases that might be worth testing, such as:

  • passive: undefined. Right now we are assuming that the behavior of DOM: Test that some event listeners are passive by default #34623 means passive: undefined is the same as passive: true for some events, but it feels like this area is messy enough that assuming everything is compositional and can be tested independently is not entirely justified.

  • one passive: true listener and one passive: false listener. (Should behave the same as one passive: false listener, IIUC.)

However I don't think these latter are worth testing if they cause a bunch of new files to get generated and need maintenance. If you can merge some files, e.g. test all of passive: true, passive: false, and passive: undefined in a single file, or test all of the events in a single file, or both, then expanding the test matrix might be reasonable. But maybe that is a bad idea for some reason, I am not sure.

@zcorpan
Copy link
Member Author

zcorpan commented Jun 29, 2022

This intervention might apply to touchend, actually. It's not very clear in the spec what the expected behavior is, but it says that cancelable varies, so maybe it should apply. I filed w3c/touch-events#133 to get some clarity here.

@zcorpan
Copy link
Member Author

zcorpan commented Jun 29, 2022

  • We should test synthetic events (with dispatchEvent()). Ideally test both the proper event type (e.g. TouchEvent) and a non-correct event type (e.g. Event). I don't actually know what the behavior will be for these...

I don't think there's anything special going on for synthetic events, but we can test it to verify that that is indeed the case.

@zcorpan
Copy link
Member Author

zcorpan commented Jun 30, 2022

I think I've addressed your comments @domenic.

Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

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

LGTM with test name/title nit. However upon reviewing the synthetic-events-cancelable test I realized it was kind of silly. Since you are on the one dispatching the event then it makes sense it will just follow the normal default. And since the normal default is cancelable = false then of course there's no chance for the intervention to apply.

So, feel free to delete that extra test if you want, now that I realize it was not really a tricky case after all.

@zcorpan zcorpan force-pushed the bocoup/more-passive-events branch from 4183e08 to d891764 Compare July 4, 2022 16:01
@zcorpan
Copy link
Member Author

zcorpan commented Jul 4, 2022

Suggested commit message

DOM: Events are non-cancelable when no non-passive listeners

Test that `wheel`, `mousewheel`, `touchstart`, `touchmove` events are not cancelable when there are no non-passive event listeners, and cancelable when there are non-passive event listeners.

Follows https://w3c.github.io/touch-events/#cancelability and https://w3c.github.io/uievents/#cancelability-of-wheel-events

The `mousewheel` event is not yet defined: https://github.com/w3c/uievents/issues/331

@zcorpan
Copy link
Member Author

zcorpan commented Jul 4, 2022

CI failed to install Safari TP:

WARNING:install:Did not find any STP URLs

https://dev.azure.com/web-platform-tests/wpt/_build/results?buildId=83977&view=logs&jobId=44ec0541-331f-516a-1683-b860fdd2ecd9&j=44ec0541-331f-516a-1683-b860fdd2ecd9&t=90ea950a-2ef3-5f6e-551d-e9a4bef4254f

I tried rebasing but it didn't help. cc @web-platform-tests/admins

@gsnedders
Copy link
Member

gsnedders commented Jul 5, 2022

CI failed to install Safari TP:

WARNING:install:Did not find any STP URLs

https://dev.azure.com/web-platform-tests/wpt/_build/results?buildId=83977&view=logs&jobId=44ec0541-331f-516a-1683-b860fdd2ecd9&j=44ec0541-331f-516a-1683-b860fdd2ecd9&t=90ea950a-2ef3-5f6e-551d-e9a4bef4254f

I tried rebasing but it didn't help. cc @web-platform-tests/admins

3fc0804 should fix that (but, also, like, file new issues for things that are broken like this; that's more discoverable for others and there's no direct need for admin intervention here).

@zcorpan zcorpan force-pushed the bocoup/more-passive-events branch from d891764 to a252b67 Compare July 5, 2022 14:46
@zcorpan
Copy link
Member Author

zcorpan commented Jul 5, 2022

Thanks @gsnedders!

@zcorpan zcorpan enabled auto-merge (squash) July 5, 2022 14:50
@zcorpan zcorpan merged commit 95d4bd9 into master Jul 5, 2022
@zcorpan zcorpan deleted the bocoup/more-passive-events branch July 5, 2022 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants