18:55 | <Andreu Botella> | Steve Hicks: You previously mentioned that with a single property name on events, developers would have to look up which would be the source of that snapshot for each event. If most events with async sources don't propagate the context but some do, wouldn't developers also have to look up when the context is propagated? |
18:55 | <Andreu Botella> | and I suspect that would be a lot harder to google |
19:55 | <Steve Hicks> | Steve Hicks: You previously mentioned that with a single property name on events, developers would have to look up which would be the source of that snapshot for each event. If most events with async sources don't propagate the context but some do, wouldn't developers also have to look up when the context is propagated? |
19:59 | <Andreu Botella> | last time I checked there were 250+ event names in the web platform (which is not the same as distinct events, since e.g. the error event on window is very different from the error event on say WebSocket ) |
20:00 | <Andreu Botella> | only those that have async sources matter here, but I don't think there's a good way to get the full list of those, short of analyzing every single one |
20:01 | <Andreu Botella> | although maybe there's a way to analyze e.g. chromium code to get a partial list of events that are guaranteed to have async sources |
20:01 | <Steve Hicks> | I can ask my internal chrome contacts to see if they've got any pointers |
20:03 | <Andreu Botella> | one thing nicolo-ribaudo pointed out is that we could try to reach out to JS educators, maybe giving some example APIs for libraries that would be using AsyncContext, and let developers tell us which events they'd use those libraries with |
20:03 | <Andreu Botella> | since we have a selection bias in that first-party developers won't be engaging because they will not be using AsyncContext directly most of the time |
20:04 | <Steve Hicks> | that's an interesting approach - I'm a little unsure of what it would mean to use an event with a library, though. |
20:05 | <Steve Hicks> | I imagine a tracing or DI library is generally pretty orthogonal from the event system, so it more comes down to just what events your application uses at all |
20:07 | <Andreu Botella> | I'm not familiar with DI systems at all, so I'll have to trust you on that |
20:07 | <littledan> | by DI here, it's referring to the same kind of thing as React Context |
20:07 | <littledan> | it'll be good for us all to become familiar with these things, as they're a potentially important use of AsyncContext |
20:08 | <littledan> | an example of a framework that uses this DI terminology is Vue https://vuejs.org/guide/components/provide-inject |
20:11 | <Steve Hicks> | Well, I think there's a lot more to DI than what react context does (or else I may have a too-limited view of what react context is about, since my primary experience is just to avoid prop drilling). For instance, it's typically used to inject top-level/singleton services, like schedulers, RPC clients, or data stores. My experience with DI is mostly on the server via Guice (in Java) but in that context, it's a pretty different flavor from drilling props. A lot of the motivation tends to be looser coupling to support testing and late-loading. |
20:13 | <Steve Hicks> | Andreu Botella: you mentioned 250+ event names, but presumably this also doesn't include (e.g.) custom element lifecycle callbacks, mutation/intersection observers, etc. |
20:14 | <Andreu Botella> | for custom element callbacks, as far as I'm aware they're always either triggered synchronously from JS code, or caused by a user or browser event, so I don't think there are any possible async sources |
20:16 | <Andreu Botella> | for observers, most of them bunch multiple observations, so calling the callback with only one of them would be a merge |
20:17 | <Andreu Botella> | in the document I describe exposing the snapshot for each of them in the observation object, if it would be useful |
20:18 | <Andreu Botella> | Chengzhong Wu pointed out that for PerformanceObserver they would be |
20:19 | <Chengzhong Wu> | Yeah, resource timing in fetch is only available from PerformanceObserver so it is useful to get each resource timing event's relevant context snapshot |
20:33 | <Andreu Botella> | another important question: if we use the top-level context for user/browser-sourced events, would users of AsyncContext need a way to tell whether it is the top-level context? or would every possible use only care about its own variables, and it could check whether they have the default values? |
20:35 | <Andreu Botella> | I'm thinking of userland schedulers, which would have no variables, they would just store a snapshot – is there any use case where it would make sense to do that inside an event listener, and where the scheduler would want to replace the snapshot if it's empty? |
20:41 | <Steve Hicks> | for custom element callbacks, as far as I'm aware they're always either triggered synchronously from JS code, or caused by a user or browser event, so I don't think there are any possible async sources |
20:42 | <Andreu Botella> | there's never good terminology for this stuff 😮💨 |
20:43 | <Andreu Botella> | when I say async source, I'm discouting events caused by user or browser interactions |
20:44 | <Steve Hicks> | Ah, I thought "user" meant "developer". So you're not counting a UI click initiating a click event as an async source? |
20:47 | <Andreu Botella> | if we go with not using registration-time always, then we'd have one consistent behavior for events fired synchronously from the action of some JS code, and another consistent behavior (whether top-level context or registration context) for events that were not fired due to the action of some JS code in the same agent |
20:48 | <Andreu Botella> | what I'm concerned with is cases where you have JS code starting an async operation in the browser that eventually fires an event |
20:48 | <Andreu Botella> | since the spec and browser changes for those events would have to be handled manually, and it's unfeasible to handle every single one of them in the initial rollout |
20:49 | <Steve Hicks> | Do you have an example of "JS code starting an async operation in the browser that eventually fires an event"? Are you thinking of e.g. XHR? |
20:50 | <Andreu Botella> | XHR is a good and common example, which is why I keep using it, but there are many others |
20:51 | <Andreu Botella> | a lot of those are obscure though |
20:53 | <Steve Hicks> | I'm not optimistic, but is there any way to hedge here? When we're rolling out userland APIs internally, we try to lock things down as much as possible at the outset so that not-yet-defined behavior is an early error. I'm not coming up with any good way to fail fast if anyone were to try to rely on a specific choice of context in the interim before we figure out what the correct default is. |
20:53 | <littledan> | Well, I think there's a lot more to DI than what react context does (or else I may have a too-limited view of what react context is about, since my primary experience is just to avoid prop drilling). For instance, it's typically used to inject top-level/singleton services, like schedulers, RPC clients, or data stores. My experience with DI is mostly on the server via Guice (in Java) but in that context, it's a pretty different flavor from drilling props. A lot of the motivation tends to be looser coupling to support testing and late-loading. |
20:55 | <Andreu Botella> | I'm not optimistic, but is there any way to hedge here? When we're rolling out userland APIs internally, we try to lock things down as much as possible at the outset so that not-yet-defined behavior is an early error. I'm not coming up with any good way to fail fast if anyone were to try to rely on a specific choice of context in the interim before we figure out what the correct default is. |
20:57 | <Steve Hicks> | The sledgehammer approach would just be to make variable.get() throw until a new snapshot is restored, but I don't see that flying. |
20:58 | <Steve Hicks> | (and even then, people end up depending on errors, etc... web compat is a pain) |
20:59 | <Justin Ridgewell> | The only future proof default is no context |
20:59 | <Justin Ridgewell> | Provide both originating and registration via properties |
21:02 | <Steve Hicks> | I don't think that satisfies the goal that AC-unaware user code does the right thing by defualt. And it doesn't really leave the door open to providing a different context later (e.g. we have a beginTrace API that starts a new trace if there's not one currently active, or opens a child span if there is. But changing an event from no-context to registration context (for example) ends up changing this behavior, which isn't good. |
21:46 | <Steve Hicks> | Backing up a bit, I wonder how many events are actually ambiguous. I suspect that the majority will be pretty clear. It's a lot of upfront work, but if we can narrow down the list of events that we really don't know what to do with, that might make it easier to talk about. Is something like https://www.w3.org/wiki/List_of_events a good place to start? |
21:51 | <Andreu Botella> | that looks very outdated, but it might be a place to start |
21:52 | <Andreu Botella> | the definitive list of events is probably https://github.com/w3c/webref/tree/main/ed/events, scraped directly from web specs |
21:52 | <Andreu Botella> | although not all of those are specs that are far along in the process to be implementable in browsers, let alone implemented |
21:58 | <Andreu Botella> | I have a buggy script somewhere that can take webref data and filter it based on MDN's compat data, I can pull it out and try to make it work on events tomorrow if you think it would be useful |