2024-05-01 [17:33:10.0504] I think `Variable.wrap` ends up being a very different thing from delimited snapshots -- delimited snapshots operate on sections of the stack that contain (possibly) multiple variables, without the caller needing to know which variables are involved, whereas `Variable.wrap` is a convenience method for something you can already do without any kind of snapshots (global or delimited) as long as you know the variable(s) you want to operate on [17:49:41.0850] Can you write example code of how delimited stacks would work? [18:02:14.0630] So, the system from the paper has "stack marks" as a different thing from "variables" because it already has the marks as part of delimited control... but in JS, without delimited continuations, I think you can just use a variable as a stack mark and get away with it. So it ends up looking something like... ``` Snapshot.partial(v: Variable): Snapshot ``` with the only difference being that when you capture a partial snapshot it captures all variables inside the most recent `v.run` (including `v`), and when you `run` a partial snapshot it instates that sequence of bindings on top of whatever variables are already in scope (perhaps shadowing some if they're in the current scope and also in the partial snapshot, but not clobbering anything that wasn't mentioned in the snapshot). [18:06:16.0091] You're probably going to ask "why would someone want this?" and one answer is: I went rifling through the literature for this because of Signals, which really seem like they want to capture and restore the _signal-related_ suffix of the context when running a memoized Computed... but where it doesn't seem to be helpful (and might cause problems) for this to capture or clobber the parts of the async context that were set up completely outside of any Computed [18:15:46.0387] There are a bunch of framework features in reactivity systems that all boil down to "save this when you create a Computed and restore it when you start rerunning it later on", and -- because Computeds are memoized -- it seems like it's basically always a bug for some sort of dynamic context (be it AsyncContext or manually managed with try/finally) to pass into a computed that's rerunning. When multiple callers all call `computed.get()` in some order, we want to be sure that the answer we saved into the computed didn't depend on which caller was first. If you have multiple frameworks doing their own extensions, they can save/restore their _own_ dynamic context using try/finally... but you run into problems if two frameworks have different extensions and don't know how to properly mask off each others'. Delimited snapshots nail this use case so well that I thought I'd try to float them and see if they seemed to help with any of the other ongoing AsyncContext mysteries [18:32:21.0490] (the signals framework features in question are stuff like... "ownership tree to implement hierarchical cleanup", "scoped error handlers to implement ErrorBoundary", "suspense context", "Context/Provider pattern for implicit parameters") [15:59:10.0795] @stephenbelanger:matrix.org Please message me with your email so that I can add you to the meetings! [15:59:43.0644] You were always meant to be invited, and I thought you were 😄 2024-05-02 [07:33:31.0454] Hey Justin Ridgewell, can you invite me to the meeting as well? Sentry just recently joined TC39, and it will be finalized by the June meeting (I believe so) [09:51:07.0374] Sure, just gotta send me your email [10:36:59.0582] @shaylew:matrix.org What's your GitHub handle? [11:07:44.0459] > <@jridgewell:matrix.org> @shaylew:matrix.org What's your GitHub handle? also shaylew there [13:22:32.0521] > <@yagiznizipli:matrix.org> Hey Justin Ridgewell, can you invite me to the meeting as well? Sentry just recently joined TC39, and it will be finalized by the June meeting (I believe so) As a provisional member, Sentry can participate like all other members in Ecma groups (just not the theoretical case of voting, which never comes up). If you've received a communication from Ecma which led you to believe otherwise, please let me know so that we can make the right edits to reduce this confusion. [13:23:46.0567] Also, regardless of that, I think we don't limit the AsyncContext meeting to delegates only – it's just that the invite is not public (not sure why though). [13:24:33.0632] there was talk of having a public calendar, but I don't know what happened with that [13:24:39.0760] * there was talk of having a public TC39 calendar, but I don't know what happened with that [13:31:39.0708] > <@abotella:igalia.com> there was talk of having a public TC39 calendar, but I don't know what happened with that To make a meeting public, we just have to ask for it to be made public on the Reflector [13:31:45.0625] do we all agree on that change? [13:32:48.0840] Honestly I’d prefer a permissive invite-only structure [13:32:58.0242] Everyone’s welcome, they just need to ask [13:33:26.0502] we could put the existence and time of the meeting on the public calendar, and direct people to join this channel and ask for call-in instructions [13:33:43.0683] Bryan English told me he spent 10 minutes trying to search for any evidence of the existence of this meeting and couldn't find ny [13:33:47.0635] * Bryan English told me he spent 10 minutes trying to search for any evidence of the existence of this meeting and couldn't find any [13:34:48.0550] Can they access reflector? [13:35:17.0419] no, since they're not Ecma members [13:35:26.0443] but even for Ecma members, the Reflector often isn't discoverable enough [13:36:48.0575] > <@littledan:matrix.org> we could put the existence and time of the meeting on the public calendar, and direct people to join this channel and ask for call-in instructions Let’s do that [13:39:06.0114] Or we could add it to the proposal README [13:40:58.0587] > <@jridgewell:matrix.org> Or we could add it to the proposal README why not both .gif [13:41:12.0702] Both [13:41:30.0260] A link to this matrix room in the readme (afaik this room is public) could be good. The agenda and notes are in the room description as well 2024-05-06 [04:54:07.0602] Apologies for the delay in sharing these docs. I needed to prune some company-specific bits and navigate our convoluted process for making Google Docs actually public. 😅 The first doc is a bunch of explanation on the problems we have with existing attempts at context management and some possible solutions we're iterating on to solve these problems in a more flexible way. https://docs.google.com/document/d/1v8tMzV51Cuz32-60dhopoIMIxWfy_epOIRwoL5LmKVc/edit?usp=sharing The second doc is partly relevant in that it describes an integration between the Diagnostics Channel concept and context management for the purpose of providing control to users to decide in which ways they want to propagate context for their specific store around particular points defined by library code as possibly interesting. https://docs.google.com/document/d/1DTZ2C5BKsoVRnU_ihyi93blF3cxXIbqqcIaSYurhBRk/edit?usp=sharing I additionally have some slides from a recent internal talk I can also share which covers this overlap more briefly, and with specific examples. https://docs.google.com/presentation/d/1jYO45MudKGPOtir5hK0_wB7XS0D_ksLe4j5NvC8YfTc/edit?usp=sharing [04:59:57.0810] Keep in mind these are written from the perspective of defining a generalized context management system which could exist in _many_ languages, so it doesn't get too deep into JS specifics. It also has some spots I still would like to improve, but what is shared is a snapshot-in-time copy of what the _current_ state is, so I will have to replicate future changes into these docs as it is deemed relevant. The main one is that I'm trying to think of a better expression of the context management part of the Window Channel concept in Diagnostics Channel to put more of the logic and explanation of its use into the context management space. I'm not yet sure if that involves having some additional ContextWindow construct or something like that...still thinking on that one. 🤔 [05:00:15.0586] * Keep in mind these are written from the perspective of defining a generalized context management system which could exist in _many_ languages, so it doesn't get too deep into JS specifics. It also has some spots I still would like to improve, but what is shared is a snapshot-in-time copy of what the _current_ state is, so I will have to replicate future changes into these docs as it is deemed relevant. The main one is that I'm trying to think of a better expression of the context management part of the Window Channel concept in Diagnostics Channel to put more of the logic and explanation of its use into the context management space. I'm not yet sure if that involves having some additional ContextWindow construct or something like that...still thinking on that one. 🤔 [05:00:37.0933] * Keep in mind these are written from the perspective of defining a generalized context management system which could exist in _many_ languages, so it doesn't get too deep into JS specifics. It also has some spots I still would like to improve, but what is shared is a snapshot-in-time copy of what the _current_ state is, so I will have to replicate future changes into these docs as it is deemed relevant. The main change I'm considering is thinking of a better expression of the context management part of the Window Channel concept in Diagnostics Channel to put more of the logic and explanation of its use into the context management space. I'm not yet sure if that involves having some additional ContextWindow construct or something like that...still thinking on that one. 🤔 [05:04:45.0389] Hey, thanks for taking the time and trouble to make these docs public! I'll try to take a look, at least at the context management one, sometime this week [05:50:26.0136] > <@littledan:matrix.org> As a provisional member, Sentry can participate like all other members in Ecma groups (just not the theoretical case of voting, which never comes up). If you've received a communication from Ecma which led you to believe otherwise, please let me know so that we can make the right edits to reduce this confusion. Afaik, we didn't receive anything from Ecma. [05:53:11.0155] > <@yagiznizipli:matrix.org> Afaik, we didn't receive anything from Ecma. OK, good, so welcome! [05:59:14.0480] Welcome Steven E ! [05:59:21.0668] we are now up to 3 Stevens [06:00:07.0160] Any of them ph's? [06:00:23.0075] /me raises hand [06:00:27.0042] Us v's are a good group [06:01:02.0205] Welcome! 😄 [06:04:00.0962] I can be less anonymous now! Happy to join [10:59:19.0633] Hi All. Chengzhong reached out to me to add the AsyncContext meeting to the public calendar. [10:59:22.0896] https://github.com/tc39/Reflector/issues/491 [11:00:51.0243] this is the issue to address that (though the invite list there is likely out-of-date. something to keep in mind, is that it is not a distinct meeting from the private calendar -- it is the same meeting shared across calendars (and this is an important feature) the meeting is always invite-based by nature -- the question is whether the invite list can be public, with the specific concern being to not release individuals' email addresses publicly without their consent as long as the meeting notes link can be public, then there is nothing in the meeting description that needs to change, as there is no information that _can't_ be public there I suggest that that the invite list is made private initially, so that the meeting can be added to the public calendar immediately. the question of the invite list being public has been the blocking issue for other meetings, and they continue to not get added to the public calendar because it goes unresolved. the invite list can be made public later, once everyone has approved (or removed) their email address for/from the invite if there are no objections, I am going to proceed with this [11:03:10.0970] I think the meeting in the private calendar has the Zoom link, and Justin Ridgewell mentioned he'd rather have the calendar entry be public but not the link, and to invite people as needed [11:03:23.0738] I don't have an opinion on that though [11:11:05.0788] > <@abotella:igalia.com> I think the meeting in the private calendar has the Zoom link, and Justin Ridgewell mentioned he'd rather have the calendar entry be public but not the link, and to invite people as needed hmm, this seems to defeat the purpose of having it on the public calendar [11:34:10.0408] I'm looking at the web integration of the `error` event on `window` (which is fired from JS execution errors), and I just noticed that we might need some extra work to make FinalizationRegistry work with that [11:34:51.0948] the way the FR cleanup job is spec'd, if any callback throws, it's up to the host to deal with that [11:35:28.0954] but after `CleanupFinalizationRegistry` returns, the host doesn't have access to the context [11:35:34.0336] * but after `CleanupFinalizationRegistry` returns, the host doesn't have access to the FR context [11:37:43.0664] and we probably want to make `error` work the same as `unhandledrejection` [11:37:58.0170] * and we probably want to make `error` work the same as `unhandledrejection`, so it'd have to store that context [15:10:37.0470] Chris de Almeida: the idea is that the meeting is public and open to join, and the process to get the link is to come in and ask us. No need to make the attendee list public—this can be a separate calendar invite which lacks the zoom link, the notes link and attendees, and only says the time and gives instructions to join this channel and ask for more information [15:18:21.0615] > <@littledan:matrix.org> Chris de Almeida: the idea is that the meeting is public and open to join, and the process to get the link is to come in and ask us. No need to make the attendee list public—this can be a separate calendar invite which lacks the zoom link, the notes link and attendees, and only says the time and gives instructions to join this channel and ask for more information it would be ideal if it were not two separate meetings, but that's alright. please provide the text for the new/public meeting description [15:19:24.0705] The notes are also publicly editable, which means they shouldn’t be shared to everyone [15:19:53.0799] (The notes are tied to my deactived Vercel account, so I can’t change the permissions) [15:23:42.0258] Can we create a new notes document and copy the contents? [15:24:52.0324] * Can we create a new notes document and copy the contents there? [15:25:20.0171] Someone else could, but I can’t as a Googler (our docs cannot be made publicly visible) [15:41:51.0045] Created a new one: https://docs.google.com/document/d/1pi-NMbqVhg2UuxQAZ4jOGDeHLlZGD_DJ7fyxHt_C2hs/edit [15:42:40.0173] Access granted to people that I have ail address in mind, please don’t be hesitant to ask for editor access by message me your address [15:42:53.0261] * Access granted to people that I have email address in mind, please don’t be hesitant to ask for editor access by message me your address [15:45:13.0770] * Access granted to people that I have email address in mind, please don’t be hesitant to ask for editor access by message me your address (still publicly viewable) 2024-05-07 [20:52:15.0250] Updated the calendar invite’s doc to that one [20:53:27.0125] @softwarechris:matrix.org Can you give me moderator access to the invite’s meet? That way we can publicize the link and still have it be invite-only (people can just ask to join during the meeting if they’re not on the invite yet) [21:31:11.0805] you already have calendar permission and are the organizer of the meeting. the web/video call settings are currently set to open access. keep in mind if you change it from `Open` to `Trusted`, even if people are on the invite, they can only join automatically if their email on the invite is associated with a google account. otherwise, they still need to be let in. and the only person that can let anyone in is you [21:32:12.0605] I recall that being a problem, and the reason why the web meeting settings were changed to `Open` [21:32:45.0607] Can only one person have that power? [21:36:50.0114] > <@jridgewell:matrix.org> Can only one person have that power? unfortunately, yes. the meeting organizer. you could use an alternate service that allows you to use cohosts or utilize a host key (which potentially anyone could use if they have the key). but I don't know of any workaround for google [21:36:53.0745] > <@jridgewell:matrix.org> Can only one person have that power? * unfortunately, yes. the meeting organizer. you could use an alternate service that allows you to use cohosts or utilize a host key (which potentially anyone could use if they have the key). but I don't know of any workaround for google meet [21:37:05.0408] * unfortunately, yes. the meeting organizer. you could use an alternate meeting platform that allows you to use cohosts or utilize a host key (which potentially anyone could use if they have the key). but I don't know of any workaround for google meet 2024-05-09 [09:27:53.0627] I'm wondering if we should have an AO that creates an AsyncContext.Variable object? [09:29:12.0168] I'm thinking about web specs that might use AsyncContext by creating a spec-internal variable [09:29:26.0212] and currently we restrict the keys of a mapping to be Variable instances [09:31:06.0832] it's not like those specs can't call the AsyncContext.Variable constructor, but they'd have to deal with abrupt completions and so on [09:32:17.0951] though I guess that would be fine if there are only a few specs doing something like that, and it can always be revisited later [09:38:06.0587] I think it's good to have, as like `AsyncContextSnapshot` and `AsyncContextSwap` 2024-05-13 [10:37:34.0525] Where are we in understanding https://github.com/tc39/proposal-async-context/issues/83 ? [11:42:13.0150] I talked with Dean Tribble on Friday, picking his brain from his Midori experience. I think the conclusion is that there is no way to abstract "calling" context in an API shape like AsyncContext. The biggest problem is that the most recent calling context may not be the one you really need, that providing more than one would result in unbounded calling context history, and that it would expose some implementation details about the execution order of the "callers". For telemetry / debugging use cases, one approach is to gather points at certain key times. For promises for example, you can give them an ID and "log" when they are resolved (potentially to another promise), when reactions are added and executed, etc.. Then you can correlate all this and recompose your execution graph. this of course sounds very similar to async_hooks, and is too powerful of an API to expose to "unprivileged" code. [12:03:27.0968] > <@mhofman:matrix.org> I talked with Dean Tribble on Friday, picking his brain from his Midori experience. I think the conclusion is that there is no way to abstract "calling" context in an API shape like AsyncContext. The biggest problem is that the most recent calling context may not be the one you really need, that providing more than one would result in unbounded calling context history, and that it would expose some implementation details about the execution order of the "callers". For telemetry / debugging use cases, one approach is to gather points at certain key times. For promises for example, you can give them an ID and "log" when they are resolved (potentially to another promise), when reactions are added and executed, etc.. Then you can correlate all this and recompose your execution graph. this of course sounds very similar to async_hooks, and is too powerful of an API to expose to "unprivileged" code. This makes sense; thanks for the summary. What does Dean recommend that we do for AsyncContext? [12:04:01.0285] "just choose something for each case" is the strategy that I was imagining; maybe too naive but it sounds like this is maybe what Dean is saying? [12:06:07.0309] I'm wondering if there's any way we could expose "just" the necessary information to hook up the extra follows-from links, or distinguish child vs following links. I think Stephen Belanger may have been asking for one of these, though I'm not sure. Did you discuss this topic with Dean? [12:12:54.0867] Yeah having a default of "snapshoting" at registration makes sense for AsyncContext. It's just that AsyncContext might not be the right API shape for telemetry use cases. And yes we tried to figure out how the necessary info could be exposed through AsyncContext, but couldn't find a way. [12:14:25.0008] I think the current shape of AsyncContext has a "good enough in practice" shape for telemetry since it matches what's done in Node.js today. Maybe something better is possible; certainly telemetry infrastructure can be trusted. [12:15:01.0185] Mathieu Hofman: Do you think we should continue with AsyncContext as currently proposed, without changes like #83? [12:32:19.0123] Are we also considering taking the smaller-scoped `callingContext` API off the table? [12:33:34.0532] #83 has made me pretty concerned about scope creep. But I'm also obviously concerned about my own pet use cases. I've got a meeting with Jatin this evening to hopefully nail down exactly what kind of registration- vs. call-time semantics we will need. 2024-05-14 [01:25:31.0956] So if context _always_ flows into _all_ branches, all we _actually_ need is the context as it was when it reached a merge barrier. For example, context flows into each of the promise-returning functions passed into a `Promise.all(...)`. Each of these branches can change their context along the path but will only ever have one value. When the value eventually reaches the merge barrier where it would get placed in the array the `Promise.all(...)` call resolves to it would capture the single context value in that branch and store it in a merge context array of equal length to the `Promise.all(...)` input and output size. The resulting merge context makes the most sense though if the resolve path is followed rather than the register path. If the register path is followed it just flattens same as the async/await issue I brought up, which means none of that merge context would reach anywhere useful if the register on the `Promise.all(...)` discards all that inner behaviour by binding around it. This is the sort of scenario why I want to have a way to get at calling context whenever a snapshot is restored. Either that or have a way to, on a per-store basis, reject the snapshot restore decision and keep using the value that propagated through the internal branch. Merge contexts are a bit weird though as it transforms a single value into an array of values, so I think it still makes sense to "pick a winner" for the default behaviour and just provide power users an additional power tool there, which might require a bit more manual intervention, to get at the full merge context list. [04:29:47.0480] While thinking about the rejection context of web APIs that take async callbacks, I realized that if you do something like this, there's no way to preserve the rejection context even if you explicitly want to: ```js asyncCb().catch(err => { if (something(err)) { return someValue; } else { throw err; } }); ``` [04:30:10.0897] at least that would be in the current spec text [04:30:22.0563] in Stephen's version it would work as expected [04:30:43.0910] * While thinking about the rejection context of web APIs that take async callbacks, I realized that if you do something like this, there's no way to preserve the original rejection context even if you explicitly want to: ```js asyncCb().catch(err => { if (something(err)) { return someValue; } else { throw err; } }); ``` [04:31:48.0717] fulfillment contexts aren't observable, but rejection contexts are with `unhandledrejection` [10:08:10.0040] ICYMI notes are here https://docs.google.com/document/d/1pi-NMbqVhg2UuxQAZ4jOGDeHLlZGD_DJ7fyxHt_C2hs/edit and please feel free to correct it [15:11:40.0056] > <@stephenhicks:matrix.org> #83 has made me pretty concerned about scope creep. But I'm also obviously concerned about my own pet use cases. I've got a meeting with Jatin this evening to hopefully nail down exactly what kind of registration- vs. call-time semantics we will need. I am curious what you found in that discussion [16:42:39.0618] Does anyone have a consolidated description of what “Stephen’s version” is? [16:43:14.0137] I mean in particular what the diff would be vs the current proposal (without the other superficial changes) [16:49:26.0563] Per-instance wrap is a convenience function, in my understanding. Did you get a chance to discuss that? I don’t see notes about it [16:50:21.0773] Did we ever get an answer on how callingContext would relate to Promise.all? 2024-05-15 [21:28:51.0748] One of my AI's was to go through Stephen's docs and try to figure out what the gist of it was. I think Stephen was also going to try to distill it down a bit further, though it was late for him by the end of the meeting. Variable.prototype.wrap is a convenience function and I think we agreed to more or less table it for now. But there's also a question of per-instance propagation configuration that is impossible to do in userland (i.e. some vars propagate via init/registration context, while others propagate via causal/calling context). Per a discussion today with Scott Haseley, it sounds like there's already some precedent for this in how v8 handles yield vs. normal CPED/attribution, in that the latter propagates over setTimeout while the former is dropped. In the case of multiple variable configs, I think it would boil down to having effectively two separate variable linked lists instead of one, and they're treated differently by snapshot swapping. This may not be infeasible, so it's maybe worth considering whether it leads to a good solution. We didn't get a chance to discuss callingContext, though (tbh) it's still my preferred option for ensuring the APM use case is viable - but we still need to figure out Promise.all. One (totally off-the-cuff) possibility would be to just stack up all the causal contexts, first-to-last. You know how many promises were merged, so you can pop that many contexts off the stack if you need them all. Upshot from discussion with Jatin was that he agreed that calling context is crucial, and figured that most userland schedulers (at least the ones he owns) would probably need to go with that default. Registration context is useless for our use of computed signals and effects (and he was particularly concerned about losing the ability to see causal context if/when Signals land in the standard), and we'd need to propagate causal context throughout all the stages of (user interaction) -> (lazy load, controller instantiation) -> (rpc fetch) -> (model cache update) -> (component rerender) in order to ensure tracing works correctly. These are all (currently) userland schedulers, at least, so it's possible, but ultimately the hope is to replace the model cache with signals. [21:30:46.0510] * One of my AI's was to go through Stephen's docs and try to figure out what the gist of it was. I think Stephen was also going to try to distill it down a bit further, though it was late for him by the end of the meeting. Variable.prototype.wrap is a convenience function and I think we agreed to more or less table it for now. But there's also a question of per-instance propagation configuration that is impossible to do in userland (i.e. some vars propagate via init/registration context, while others propagate via causal/calling context). Per a discussion today with Scott Haseley, it sounds like there's already some precedent for this in how v8 handles yield vs. normal CPED/attribution, in that the latter propagates over setTimeout while the former is dropped. In the case of multiple variable configs, I think it would boil down to having effectively two separate variable linked lists instead of one, and they're treated differently by snapshot swapping. This may not be infeasible, so it's maybe worth considering whether it leads to a good solution. We didn't get a chance to discuss callingContext, though (tbh) it's still my preferred option for ensuring the APM use case is viable, due to balancing the extra complexity and feasibility of ever actually landing this proposal, vs stalling out from trying to do too much - but we do still need to figure out Promise.all. One (totally off-the-cuff) possibility would be to just stack up all the causal contexts, first-to-last. You know how many promises were merged, so you can pop that many contexts off the stack if you need them all. Upshot from discussion with Jatin was that he agreed that calling context is crucial, and figured that most userland schedulers (at least the ones he owns) would probably need to go with that default. Registration context is useless for our use of computed signals and effects (and he was particularly concerned about losing the ability to see causal context if/when Signals land in the standard), and we'd need to propagate causal context throughout all the stages of (user interaction) -> (lazy load, controller instantiation) -> (rpc fetch) -> (model cache update) -> (component rerender) in order to ensure tracing works correctly. These are all (currently) userland schedulers, at least, so it's possible, but ultimately the hope is to replace the model cache with signals. [21:48:43.0463] I took a stap at implementing the stack-based Promise.all in userland with callingContext, and I ran into a brick wall because there's no way to actually stack multiple top-level frames: https://www.typescriptlang.org/play/?#code/CYUwxgNghgTiAEA7KBbEBnADlMCCC6AnomAMID2iALiAB5XwDeAUPPHZuTA5FOuvADKyTOgAW5BizZsYAV0QAeACoA+ABQAzRAC546gJTwAvKvjKDe5axnoqUKgEsw8AO4womRQDF29EIjAAt4KYE6UGtp63pbw3gDcNgC+NhxcDJqh4YjwYFAQEI6IAOYU1HRUKpG6+kam5rHKiSnMmSTZ8Jgw5CiO6CB4BSp+NIECAArdvf2KCgDWiOSuiKoA2gC6Gl09fRhWsZM7M4yrANLwRfBzIITkmubreniuUI40wCpnm0lm0vAQIAY6BE4kkTyIJDKNHoADphJ5QVQAD4KUCaIogYCJNhgSh2eBwdByCBUdB6eaLZYbEydKa7dAwlCedSGExmVEgdGITEGbH-QG5cgKBjGWlHDAwgElKhiPlwKhyGA5bmueCHaYgFmE8gQABuIAANASQAArcBUOq-GxsTRcfQAhiOGkABniF3gijFGoZUuKMrdjgA1IGjH8ZF76atHOsYTKAizdflLUxreHjUSSego+saYmIHy0xd7uoAITAhESC0pwvh8uiSs0gjEMiUaFUGF5ApFUqtios5Mq+BNyG92Hw+uSQy81PhpLsCD9as1th1xE01eVmHyRD9tlL5dsAD0h-gADkAPLKACiehlfXgwHIGCQkngAEc5G8EK4uHN4AAjcAoDkRc41yfJChKKEKjcRwClyCByH-QCYBnGtj3gMCN1fMQ+ioLhCCNKBAngXVnAQfUYHQKAYTYAB1BB-z4ZwIMIJAQExeAoDcKA2PwzpiQgNDCwwoUGG49BuwBeBNA8NAjVcXCwDEeB+hAFABHUBwZMcKiGGKaASENTDyHgNAjFxagPGAZx8JgQhhLTDDXDeFTAO7Lj-2k-icFwfhwK7EpBXKegBFgBBYH-N4PHsh8QEwGUjQUAF+Ec8MMKZQhAMwsQEE7SCexChg8HGABJTCoGuMK4oSlTsDkwEQBgWihwXcgFJAAByfV-nIOw0pkDCwNxGA4DCAKCug+h4FyuAuJIuM5sfDBEE6oEOJQEyAIini+PIAajxPYoBW0t4YQO40FSVIcIRbIqOwg7spqoXd6kHYc7rbOEQUrKcCxrJJp2XFJl0cYsAFpwdxYV4DMZ0jHlRVEH+2sfskLcFFesxtT1TVCWJUkuLCxBCAMIG0ySI11CamBkzDNM4DNMJqdG8nZwMVMQfgQHmmYIA [21:49:12.0666] * I took a stap at implementing the stack-based Promise.all in userland with callingContext, and I ran into a brick wall because there's no way to actually stack multiple top-level frames: [playground](https://www.typescriptlang.org/play/?#code/CYUwxgNghgTiAEA7KBbEBnADlMCCC6AnomAMID2iALiAB5XwDeAUPPHZuTA5FOuvADKyTOgAW5BizZsYAV0QAeACoA+ABQAzRAC546gJTwAvKvjKDe5axnoqUKgEsw8AO4womRQDF29EIjAAt4KYE6UGtp63pbw3gDcNgC+NhxcDJqh4YjwYFAQEI6IAOYU1HRUKpG6+kam5rHKiSnMmSTZ8Jgw5CiO6CB4BSp+NIECAArdvf2KCgDWiOSuiKoA2gC6Gl09fRhWsZM7M4yrANLwRfBzIITkmubreniuUI40wCpnm0lm0vAQIAY6BE4kkTyIJDKNHoADphJ5QVQAD4KUCaIogYCJNhgSh2eBwdByCBUdB6eaLZYbEydKa7dAwlCedSGExmVEgdGITEGbH-QG5cgKBjGWlHDAwgElKhiPlwKhyGA5bmueCHaYgFmE8gQABuIAANASQAArcBUOq-GxsTRcfQAhiOGkABniF3gijFGoZUuKMrdjgA1IGjH8ZF76atHOsYTKAizdflLUxreHjUSSego+saYmIHy0xd7uoAITAhESC0pwvh8uiSs0gjEMiUaFUGF5ApFUqtios5Mq+BNyG92Hw+uSQy81PhpLsCD9as1th1xE01eVmHyRD9tlL5dsAD0h-gADkAPLKACiehlfXgwHIGCQkngAEc5G8EK4uHN4AAjcAoDkRc41yfJChKKEKjcRwClyCByH-QCYBnGtj3gMCN1fMQ+ioLhCCNKBAngXVnAQfUYHQKAYTYAB1BB-z4ZwIMIJAQExeAoDcKA2PwzpiQgNDCwwoUGG49BuwBeBNA8NAjVcXCwDEeB+hAFABHUBwZMcKiGGKaASENTDyHgNAjFxagPGAZx8JgQhhLTDDXDeFTAO7Lj-2k-icFwfhwK7EpBXKegBFgBBYH-N4PHsh8QEwGUjQUAF+Ec8MMKZQhAMwsQEE7SCexChg8HGABJTCoGuMK4oSlTsDkwEQBgWihwXcgFJAAByfV-nIOw0pkDCwNxGA4DCAKCug+h4FyuAuJIuM5sfDBEE6oEOJQEyAIini+PIAajxPYoBW0t4YQO40FSVIcIRbIqOwg7spqoXd6kHYc7rbOEQUrKcCxrJJp2XFJl0cYsAFpwdxYV4DMZ0jHlRVEH+2sfskLcFFesxtT1TVCWJUkuLCxBCAMIG0ySI11CamBkzDNM4DNMJqdG8nZwMVMQfgQHmmYIA) [21:49:25.0424] * I took a stab at implementing the stack-based Promise.all in userland with callingContext, and I ran into a brick wall because there's no way to actually stack multiple top-level frames: [playground](https://www.typescriptlang.org/play/?#code/CYUwxgNghgTiAEA7KBbEBnADlMCCC6AnomAMID2iALiAB5XwDeAUPPHZuTA5FOuvADKyTOgAW5BizZsYAV0QAeACoA+ABQAzRAC546gJTwAvKvjKDe5axnoqUKgEsw8AO4womRQDF29EIjAAt4KYE6UGtp63pbw3gDcNgC+NhxcDJqh4YjwYFAQEI6IAOYU1HRUKpG6+kam5rHKiSnMmSTZ8Jgw5CiO6CB4BSp+NIECAArdvf2KCgDWiOSuiKoA2gC6Gl09fRhWsZM7M4yrANLwRfBzIITkmubreniuUI40wCpnm0lm0vAQIAY6BE4kkTyIJDKNHoADphJ5QVQAD4KUCaIogYCJNhgSh2eBwdByCBUdB6eaLZYbEydKa7dAwlCedSGExmVEgdGITEGbH-QG5cgKBjGWlHDAwgElKhiPlwKhyGA5bmueCHaYgFmE8gQABuIAANASQAArcBUOq-GxsTRcfQAhiOGkABniF3gijFGoZUuKMrdjgA1IGjH8ZF76atHOsYTKAizdflLUxreHjUSSego+saYmIHy0xd7uoAITAhESC0pwvh8uiSs0gjEMiUaFUGF5ApFUqtios5Mq+BNyG92Hw+uSQy81PhpLsCD9as1th1xE01eVmHyRD9tlL5dsAD0h-gADkAPLKACiehlfXgwHIGCQkngAEc5G8EK4uHN4AAjcAoDkRc41yfJChKKEKjcRwClyCByH-QCYBnGtj3gMCN1fMQ+ioLhCCNKBAngXVnAQfUYHQKAYTYAB1BB-z4ZwIMIJAQExeAoDcKA2PwzpiQgNDCwwoUGG49BuwBeBNA8NAjVcXCwDEeB+hAFABHUBwZMcKiGGKaASENTDyHgNAjFxagPGAZx8JgQhhLTDDXDeFTAO7Lj-2k-icFwfhwK7EpBXKegBFgBBYH-N4PHsh8QEwGUjQUAF+Ec8MMKZQhAMwsQEE7SCexChg8HGABJTCoGuMK4oSlTsDkwEQBgWihwXcgFJAAByfV-nIOw0pkDCwNxGA4DCAKCug+h4FyuAuJIuM5sfDBEE6oEOJQEyAIini+PIAajxPYoBW0t4YQO40FSVIcIRbIqOwg7spqoXd6kHYc7rbOEQUrKcCxrJJp2XFJl0cYsAFpwdxYV4DMZ0jHlRVEH+2sfskLcFFesxtT1TVCWJUkuLCxBCAMIG0ySI11CamBkzDNM4DNMJqdG8nZwMVMQfgQHmmYIA) [21:53:22.0968] I can see a few variants on callingContext: (1) it just puts the previous frame directly on top of the current one (i.e. behaves identical to Snapshot.run) - in this case, one could just _make_ it a snapshot? This makes it impossible to access deeper-nested ones, since `callingContext()` will just get you back to the previous (registration?) context. Unless maybe it takes a depth argument. In that case, the stacking might _just_ be possible. Or (2) it restores the entire context stack to whatever it looked like in the calling environment, such that a second `callingContext`would go back further in causation history. [04:07:39.0392] I made this small (-ish) example of how we're doing that differentiation between child-of and follows-from relationships and what we're trying to do with holding the minimum possible data in the store (just the ID). https://gist.github.com/Qard/6ceaca8bb792679e82c7693513baee0e [04:37:17.0878] In those examples we have a solution to the need to separate child-of and follows-from relationships, which is not _too_ terribly complicated, so we can live with that. And as I expressed previously the multiple follows-from thing is not _too_ terribly important as we at least get _one_ of the branches so we can still _mostly_ understand the execution structure. But we _do_ need to be able to flow through at least singular pathed merges like an await or then continuation of a single promise. The example above are meant to show that we are expecting something which logically _continues_ from a particular point is expected to be able to attribute itself from that. Whereas what we get _currently_ with both async/await and promises is a flat structure where all the `mysql.query` spans within those examples would get flattened up to linking with the http.server span, even if the second query has another query between it and the http handler starting. [04:37:42.0630] * In those examples we have a solution to the need to separate child-of and follows-from relationships, which is not _too_ terribly complicated, so we can live with that. And as I expressed previously the multiple follows-from thing is not _too_ terribly important as we at least get _one_ of the branches so we can still _mostly_ understand the execution structure. But we _do_ need to be able to flow through at least singular pathed merges like an await or then continuation of a single promise. The example above are meant to show that we are expecting something which logically _continues_ from a particular point is expected to be able to attribute itself from that. Whereas what we get _currently_ with both async/await and promises is a flat structure where all the `mysql.query` spans within those examples would get flattened up to linking with the http.server span, even if the second query has another query between it and the http handler starting. [04:37:58.0257] * In those examples we have a solution to the need to separate child-of and follows-from relationships, which is not _too_ terribly complicated, so we can live with that. And as I expressed previously the multiple follows-from thing is not _too_ terribly important as we at least get _one_ of the branches so we can still _mostly_ understand the execution structure. But we _do_ need to be able to flow through at least singular pathed merges like an await or then continuation of a single promise. The examples above are meant to show that we are expecting something which logically _continues_ from a particular point is expected to be able to attribute itself from that. Whereas what we get _currently_ with both async/await and promises is a flat structure where all the `mysql.query` spans within those examples would get flattened up to linking with the http.server span, even if the second query has another query between it and the http handler starting. [04:38:14.0551] * In those examples we have a solution to the need to separate child-of and follows-from relationships, which is not _too_ terribly complicated, so we can live with that. And as I expressed previously the multiple follows-from thing is not _too_ terribly important as we at least get _one_ of the branches so we can still _mostly_ understand the execution structure. But we _do_ need to be able to flow through at least singular pathed merges like an await or then continuation of a single promise. The examples above are meant to show that we are expecting something which logically _continues_ from a particular point is expected to be able to attribute itself to that. Whereas what we get _currently_ with both async/await and promises is a flat structure where all the `mysql.query` spans within those examples would get flattened up to linking with the http.server span, even if the second query has another query between it and the http handler starting. [07:37:17.0513] I am confused by general comments on registration time vs call time. Can we do more to dig into the detailed cases? (Am chatting with Jatin about this now too) [07:38:02.0412] Andreu had some sort of point by point analysis. What if we made that a Google Doc and then we could comment together on which things could/should be different for which use cases? [07:49:04.0939] In reality there will be a mix of both registration time and call time, so I have trouble understanding conversations which are phrases like “vs” [08:27:53.0387] A doc sounds like a good idea. Yes, there will be a mix, but there's more nuance than that. There's questions of consistency (e.g. button.addEventListener with a UI click vs.