18:22
<Steve Hicks>
The current spec should preserve the context at .then() time, no? Are you expecting someAsyncApi’s rejection time?
I'm not seeing a specific code example, but I can imagine a few possibilities: (1) v.run(1, () => Promise.reject()).then(x => x) doesn't actually invoke the callback, so would it be reasonable to not change the rejection context? (2) It's also possible that the then handler runs in the causal context instead of the registration context - so regardless of whether or not it runs, it might still not lose the context.
18:29
<Steve Hicks>
I'm thinking a bit more right now about the idea of flowing around awaits (but maybe through yields?), but having nearly all callbacks run in the causal context by default. You could emulate flow-through behavior at the await site with a userland promiseSnapshot = (promise) => promise.then(() => new Snapshot(), () => new Snapshot()) helper function (you'd need to await promiseSnapshot(promise) to get ahold of it... so maybe there's a more performant option via a builtin, or something else we could carve out of those conceptual building blocks). And you can opt into registration context with a Snapshot.wrap anytime it's needed. So this seems to provide the most expressivity, I think the mental model is pretty self-consistent, and I don't think it runs afoul of SES requirements.
18:48
<Steve Hicks>
Maybe there's some way to actually replace the snapshot after resuming from an await, rather than needing to reference it via a snapshot variable, which is a lot more awkward - bounded enterWith for the whole snapshot, or something... there was some brief discussion about this sort of thing after the end of yesterday's meeting - does anyone have more thoughts to share about this?
19:51
<littledan>
I'm thinking a bit more right now about the idea of flowing around awaits (but maybe through yields?), but having nearly all callbacks run in the causal context by default. You could emulate flow-through behavior at the await site with a userland promiseSnapshot = (promise) => promise.then(() => new Snapshot(), () => new Snapshot()) helper function (you'd need to await promiseSnapshot(promise) to get ahold of it... so maybe there's a more performant option via a builtin, or something else we could carve out of those conceptual building blocks). And you can opt into registration context with a Snapshot.wrap anytime it's needed. So this seems to provide the most expressivity, I think the mental model is pretty self-consistent, and I don't think it runs afoul of SES requirements.
This is a good point. So we're really talking about what async/await does, and what is done by default everywhere, rather than making things totally impossible. But anyway, I believe Stephen Belanger 's point that, almost all of the time, we won't get people to actually opt into anything besides the default.
19:56
<Steve Hicks>
This is a good point. So we're really talking about what async/await does, and what is done by default everywhere, rather than making things totally impossible. But anyway, I believe Stephen Belanger 's point that, almost all of the time, we won't get people to actually opt into anything besides the default.
I think that's right, which is simultaneously why it's so important to pick good defaults, and also why it's probably impossible because I'm pretty sure there is no default that just works everywhere. >_<
19:57
<littledan>
It is good to see an example of Snapshot being used that way; it's easy to fall into the trap of thinking that snapshots are just for "flowing around"
19:57
<Steve Hicks>
We heard a bit from the zone.js folks last week - did anyone get a better sense of the importance of registration context from that?
19:58
<littledan>
my takeaway from their comments in this channel was that not using the causal path when available was sort of "to avoid Zalgo"
19:59
<littledan>
and I guess my thought is, we should just provide the additional information of the more specific causal context, and be OK with the Zalgo
20:01
<littledan>
Do we have any further questions for Jia Li ?
20:01
<Steve Hicks>
I still wonder if there's some way to frame it to give the right information when possible but still be 100% consistent...?
20:02
<littledan>
I still wonder if there's some way to frame it to give the right information when possible but still be 100% consistent...?
I think there's a story where we're being consistent: we'd always be using the most specific (i.e. causally recent) relevant context
20:49
<Andreu Botella>
I will have to read the logs, because I was sick Thursday to Saturday, and if I read most of that conversation, it's a blur now
20:59
<Andreu Botella>
The registration time zone is often what you want, on the other hand, eg for onload, setTimeout, etc. I don’t see how we could have any sort of consistent principle that you never get the registration context.
I think onload and setTimeout are two very different cases: setTimeout both schedules a task and registers the callback to run in that task; onload doesn't schedule
21:00
<Andreu Botella>
I don't know if they should be treated differently, but we shouldn't conflate them
21:05
<Andreu Botella>
I'm not really what to make about discussions about Zalgo – the truth is, many event types in the web platform might be run synchronously or asynchronously
21:06
<Andreu Botella>
so there's an underlying issue there already, that we can't fix
21:06
<littledan>
I don't know if they should be treated differently, but we shouldn't conflate them
sure, that's why I mentioned both cases, because they're different but you end up wanting to do the analogous thing
21:11
<Andreu Botella>
For an example of an event that might be fired synchronously or asynchronously: if you call window.print() after the page is done loading, it will synchronously print as well as fire the beforeprint and afterprint events; but if you call it while the page is loading, it will only print and fire those events after the page fully loads
21:17
<Andreu Botella>
(btw, this is "print" as in physically printing out the document, not logging some output)
21:21
<Andreu Botella>
would there be any reasonable use cases for the call-time context of el.click()?
21:21
<Andreu Botella>
If not, does that apply to window.print() as well?
21:25
<Andreu Botella>
Going with registration-time by default makes these issues less pressing, but it doesn't remove them
21:32
<Andreu Botella>
huh, I guess the print case doesn't really matter, since you can see the deferred case as it enqueuing a print task (it isn't spec'd like that, but it behaves like that), and so it'd have an async originating context
21:41
<Steve Hicks>
I think there's a story where we're being consistent: we'd always be using the most specific (i.e. causally recent) relevant context
I think that's tricky due to races - for example, the exact ordering of a promise resolving vs. the promise.then call would make one or the other context more recent. But I think we probably want to run in the same context (resolution vs registration) regardless of the order.
21:43
<Justin Ridgewell>
I'm thinking a bit more right now about the idea of flowing around awaits (but maybe through yields?), but having nearly all callbacks run in the causal context by default. You could emulate flow-through behavior at the await site with a userland promiseSnapshot = (promise) => promise.then(() => new Snapshot(), () => new Snapshot()) helper function (you'd need to await promiseSnapshot(promise) to get ahold of it... so maybe there's a more performant option via a builtin, or something else we could carve out of those conceptual building blocks). And you can opt into registration context with a Snapshot.wrap anytime it's needed. So this seems to provide the most expressivity, I think the mental model is pretty self-consistent, and I don't think it runs afoul of SES requirements.
I don’t understand how this snapshot would exist in a different context if we chose flows-around semantics. Are you proposing .then() and await operate differently?
21:55
<Andreu Botella>
would there be any reasonable use cases for the call-time context of el.click()?
I'm very interested to see if anyone has use cases for this, or for distinguishing el.click() from a user click. From an initial glance, it looks like many of the times where an event could have or not have an originating context, it's in similar cases (el.focus(), form.reset()...), where you have an API to do synchronously what could be done through user interaction.
21:56
<Andreu Botella>
(I guess form.reset() isn't possible through user interaction if you don't add a reset button. Does that difference matter?)
21:57
<Andreu Botella>
I guess it doesn't, since you can also el.click() on display: hidden elements
22:07
<Steve Hicks>
I don’t understand how this snapshot would exist in a different context if we chose flows-around semantics. Are you proposing .then() and await operate differently?
Maybe - I guess I'd say I'm considering proposing it. As it stands (and Stephen has pointed out), callbacks and promises behave differently.
22:08
<Steve Hicks>
But maybe there's a way to have the cake and eat it too, if the post-await continuation could opt into the resolution context somehow - i.e. the limited enterWith idea
22:08
<Steve Hicks>
(or something else along those lines)
22:09
<Steve Hicks>
and this is getting a lot more speculative, but maybe there's some way to instrument the promise that's being awaited to do this automatically? I'm not remotely sure what that could look like