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

Allow other specs to add event listeners ergonomically #878

Open
domenic opened this issue Jul 13, 2020 · 16 comments
Open

Allow other specs to add event listeners ergonomically #878

domenic opened this issue Jul 13, 2020 · 16 comments

Comments

@domenic
Copy link
Member

domenic commented Jul 13, 2020

Background: whatwg/streams#1053 (comment), as well as the (on-pause) https://wicg.github.io/kv-storage/#add-a-simple-event-listener.

There are times when it is convenient for specs to listen to events. For Streams, we want to use the MessagePort infrastructure, and its message/messageerror events. @ricea states that there are tons of other places in Blink that similarly listen to events from C++.

Another instance of this is #493, where we decided to add a custom mechanism specific for AbortSignal. The downside noted there is that the ordering is not interleaved in an intuitive fashion with web-developer-added events. I'm not proposing we revisit that at the moment, although it might be a good idea after this issue settles.

From specs, adding such a listener is not currently easy, mainly because creating JS functions / Web IDL callbacks from algorithm steps is not currently easy. I think we should add something to make it easier.

Some options:

  1. Make it easy to create Web IDL callbacks from specs (so, this would probably become a Web IDL issue). Then Streams would write something like "Add an event listener with target and an event listener whose callback is an EventListener [that performs the following steps]:".

    • This could clean up https://streams.spec.whatwg.org/#blqs-internal-slots

    • The main downside of this is that the general case will need you to supply a length and name for the function, which is undesirable overhead for the event listener case. We could have Web IDL make these optional, with the understanding that the caller has to be very careful to pass them when they're observable... but I don't like it much.

  2. Make the DOM spec's event listener struct contain either an EventListener or some steps, and branch at the appropriate point.

  3. Add a wrapper algorithm (or modify "add an event listener") which accepts steps instead of EventListener instances, and converts at the boundary, so that an "event listener" struct always contains an EventListener.

I'm open to any of these, although I disprefer (1). I'd be happy to send a pull request for any of them if I can get some editor direction.

@annevk
Copy link
Member

annevk commented Jul 14, 2020

This seems to go somewhat counter to https://dom.spec.whatwg.org/#action-versus-occurance. I know that user agents have some internal infrastructure that looks like this, but it's not clear to me that it's also the right way to define this or even the right way to implement these things going forward.

@domenic
Copy link
Member Author

domenic commented Jul 14, 2020

Hmm, I don't see the contradiction. Why would a user agent listening for a message event be worse than a web developer listening for a message event?

@annevk
Copy link
Member

annevk commented Jul 14, 2020

Who has access to the event target?

@domenic
Copy link
Member Author

domenic commented Jul 14, 2020

The event target itself is not exposed to web developers, and is used as spec-internal bookkeeping (similar to how worker messaging is defined). But web developers can cause events to fire on it by writing into the other side of the transferred stream.

@annevk
Copy link
Member

annevk commented Jul 14, 2020

That kinda works I think, but I think the problem is that people might start using this mechanism in specifications for something it's not intended for.

@domenic
Copy link
Member Author

domenic commented Jul 14, 2020

I don't really understand. Why is adding event listeners something special that only web developers can do? What would be "not intended" about listening for events?

@annevk
Copy link
Member

annevk commented Jul 20, 2020

I suspect what implementations have is more similar to "event groups" in https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html in that userland cannot prevent those listeners from being run and that ordering is independent from userland ordering. And then additionally they probably check that the trusted flag is set for the event in most cases.

What we've done with AbortSignal is similar and could probably also be done with such a model, but it's not clear to me the complexity is worth it.

@annevk
Copy link
Member

annevk commented May 4, 2023

@domenic do you still think we should do this given the above or can this be closed?

@annevk annevk mentioned this issue May 4, 2023
4 tasks
@domenic
Copy link
Member Author

domenic commented May 4, 2023

Yes. Note that implementations directly use addEventListener for many events, e.g. that's how light dismiss or dialog-close-on-Esc is implemented, off the top of my head. Code search in each browser's code will find more instances.

@annevk
Copy link
Member

annevk commented May 4, 2023

@domenic but they use "event groups" or some such for that, right? So a developer-added listener cannot do preventDefault(). That's not compatible with just using the existing mechanism in DOM as-is. That requires quite a bit more effort.

@domenic
Copy link
Member Author

domenic commented May 4, 2023

That's not what I've seen. E.g. the dialog Esc handler can be prevented by canceling the keydown event. And I've seen no notion of anything like what you call "event groups" in the code.

@annevk
Copy link
Member

annevk commented May 4, 2023

I see, but that would not work for AbortSignal for instance contrary to what OP suggests. (Gecko definitely used to have something akin to event groups, but not sure what is there today. @smaug---- might know.)

@domenic
Copy link
Member Author

domenic commented May 4, 2023

Yeah, I accept #493 is a lost cause, although I still think we made the wrong decision there.

@annevk
Copy link
Member

annevk commented May 4, 2023

But that would mean if you give a signal to someone they can interfere with it actually working in the end. I very much doubt that is what we would have wanted as semantics. (Though maybe that means events are wrong as well since different pieces of userland can interfere with each other too.)

@domenic
Copy link
Member Author

domenic commented May 4, 2023

That's already true for web developer-created APIs that accept signals. (There's some existing issue on that.) Perhaps if we hadn't reserved special powers for the browser, and instead used the uniform interface that web developers also use, we would have been more likely to solve that problem.

@smaug----
Copy link
Collaborator

Gecko has "system event group", which can be used to implement default handling (as an example) using event listeners. Listeners in that group are called after the listeners in the default group - there is a separate event propagation for system group, all the listeners in the default group in all the targets are called first.

But usually default handling is implemented using internal (c++) PostHandleEvent callback. And there are native callbacks for pre-handling too (needed for example for checkbox). And we have WindowRoot on top of the Window in the event path etc, so there is plenty of flexibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants