2024-10-01 [13:10:09.0174] https://github.com/tc39/agendas/pull/1703 2024-10-07 [01:41:13.0061] Way too late, but I just added slides for this week's update: https://github.com/tc39/agendas/pull/1716 2024-10-11 [10:35:41.0136] Hello 👋 I wrote down an alternative proposal for the integration of AsyncContext with events, to run the event handlers using the dispatch context rather than the registration context. I don't know if I will be able to join the meeting on Tuesday (and if I will, I'll be there just for the first 30 minutes), but I'd love if you could take a look :) https://hackmd.io/@nicolo-ribaudo/rJhdk8HyJe 2024-10-24 [06:11:46.0655] Justin Ridgewell As you asked last time, here is an example where there is a significant difference between keeping the fallback stack and not doing it. ```js const appID = new AsyncContext.Variable(); appID.run("Red", () => Event.captureFallbackContext(red)); appID.run("Blue", () => Event.captureFallbackContext(blue)); addEventListener('unhandledrejection', () => { console.log(`There has been an unhandled promise rejection in app ${appID.get()}`); }); ``` where `red` is defined as ```js export function red() { document.addEventListener("click", () => { Promise.reject() }); } ``` when the user clicks on the document, this logs `There has been an unhandled promise rejection in app Red`. If instead `Blue` runs `document.click()`: - with the current proposal, it would log `There has been an unhandled promise rejection in app Red` - if we don't save the stack and just use the fallback when the event comes from the browser, it would log `There has been an unhandled promise rejection in app Blue` [06:14:49.0554] Also, I'm seeing in the notes a question about how long the bootstrap context lives. The effects on that of ```js Event.captureFallbackContext(() => { addEventListener("foo", () => {}); }); ``` are the same as ```js addEventListener("foo", AsyncContext.Snapshot.wrap(() => {})); ``` - `Event.captureFallbackContext` only holds the context alive if there are event listeners registered inside it - differently from the other "let's always go with the registration context" approach, this only captures the context when explicitly asked to (through the `.captureFallbackContext` API) [06:21:25.0879] > <@nicolo-ribaudo:matrix.org> Also, I'm seeing in the notes a question about how long the bootstrap context lives. > > The effects on that of > ```js > Event.captureFallbackContext(() => { addEventListener("foo", () => {}); }); > ``` > are the same as > ```js > addEventListener("foo", AsyncContext.Snapshot.wrap(() => {})); > ``` > > - `Event.captureFallbackContext` only holds the context alive if there are event listeners registered inside it > - differently from the other "let's always go with the registration context" approach, this only captures the context when explicitly asked to (through the `.captureFallbackContext` API) Also, a big difference is that the use case of `captureFallbackContext` is to call it "a few times" and "close to the top-level", while event listeners are used all over the place. So the number of different snapshots captured is in general significantly smaller. Example: ```js Event.captureFallbackContext(() => { varOne.run(1, () => addEventListener("foo", () => {})); varTwo.run(2, () => addEventListener("foo", () => {})); }); ``` only captures one context, while the approach where we use the registration context by default would capture two different contexts [06:30:32.0278] * Justin Ridgewell As you asked last time, here is an example where there is a significant difference between keeping the fallback stack and not doing it. ```js Event.captureFallbackContext(() => { // this establishes the "root context", which is actually implicitly done by the browser const appID = new AsyncContext.Variable(); appID.run("Red", () => Event.captureFallbackContext(red)); appID.run("Blue", () => Event.captureFallbackContext(blue)); addEventListener('unhandledrejection', () => { console.log(`There has been an unhandled promise rejection in app ${appID.get()}`); }); }); ``` where `red` is defined as ```js export function red() { document.addEventListener("click", () => { Promise.reject() }); } ``` **With the current "stack" proposal** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app Red`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app Red`. **Without the stack, only using the fallback for browser-dispatched events** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app Red`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app Blue`. **Without the stack, using the fallback when the event not dispatched from within the same "fallback zone"** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app undefined`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app undefined`. [06:31:19.0552] * Justin Ridgewell As you asked last time, here is an example where there is a significant difference between keeping the fallback stack and not doing it. ```js Event.captureFallbackContext(() => { // this establishes the "root context", // which is actually implicitly done by the // browser. This call is just to show it // explicitly. const appID = new AsyncContext.Variable(); appID.run("Red", () => Event.captureFallbackContext(red)); appID.run("Blue", () => Event.captureFallbackContext(blue)); addEventListener('unhandledrejection', () => { console.log(`There has been an unhandled promise rejection in app ${appID.get()}`); }); }); ``` where `red` is defined as ```js export function red() { document.addEventListener("click", () => { Promise.reject() }); } ``` **With the current "stack" proposal** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app Red`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app Red`. **Without the stack, only using the fallback for browser-dispatched events** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app Red`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app Blue`. **Without the stack, using the fallback when the event not dispatched from within the same "fallback zone"** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app undefined`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app undefined`. [06:31:25.0396] * Justin Ridgewell As you asked last time, here is an example where there is a significant difference between keeping the fallback stack and not doing it. ```js Event.captureFallbackContext(() => { // this establishes the "root context", // which is actually implicitly done by the // browser. This call is just to show it // explicitly. const appID = new AsyncContext.Variable(); appID.run("Red", () => Event.captureFallbackContext(red)); appID.run("Blue", () => Event.captureFallbackContext(blue)); addEventListener('unhandledrejection', () => { console.log(`There has been an unhandled promise rejection in app ${appID.get()}`); }); }); ``` where `red` is defined as ```js export function red() { document.addEventListener("click", () => { Promise.reject() }); } ``` **With the current "stack" proposal** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app Red`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app Red`. **Without the stack, only using the fallback for browser-dispatched events** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app Red`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app Blue`. **Without the stack, using the fallback when the event not dispatched from within the same "fallback zone"** - when the user clicks on the document, it logs `There has been an unhandled promise rejection in app undefined`. - if Blue runs `document.click()`, it logs `There has been an unhandled promise rejection in app undefined`. [14:31:45.0241] I had a question about the interaction between this and other non-event systems - suppose a framework provides lifecycle callbacks and it makes sense to have a similar treatment - do we end up nesting `Event.captureFallbackContext(() => Framework.captureFallbackContext(() => ...))`? Or does it make sense to generalize via (strawman) ``` namespace AsyncContext { const fallbackSnapshot = new Variable({defaultValue: new Snapshot()}); export function captureFallback(fn) { return fallbackSnapshot.run(new Snapshot(), fn); } export function wrapFallback(fn) { const savedFallback = fallbackSnapshot.get(); return () => savedFallback.isParentOfCurrentContext() ? fn() : savedFallback.run(fn); } } ``` and then frameworks can piggyback on the same boundaries? [14:31:54.0384] * I had a question about the interaction between this and other non-event systems - suppose a framework provides lifecycle callbacks and it makes sense to have a similar treatment - do we end up nesting `Event.captureFallbackContext(() => Framework.captureFallbackContext(() => ...))`? Or does it make sense to generalize via (strawman) ```javascript namespace AsyncContext { const fallbackSnapshot = new Variable({defaultValue: new Snapshot()}); export function captureFallback(fn) { return fallbackSnapshot.run(new Snapshot(), fn); } export function wrapFallback(fn) { const savedFallback = fallbackSnapshot.get(); return () => savedFallback.isParentOfCurrentContext() ? fn() : savedFallback.run(fn); } } ``` and then frameworks can piggyback on the same boundaries? [14:32:36.0079] * I had a question about the interaction between this and other non-event systems - suppose a framework provides lifecycle callbacks and it makes sense to have a similar treatment - do we end up nesting `Event.captureFallbackContext(() => Framework.captureFallbackContext(() => ...))`? Or does it make sense to generalize via (strawman) ```javascript namespace AsyncContext { const fallbackSnapshot = new Variable({defaultValue: new Snapshot()}); export function captureFallback(fn) { return fallbackSnapshot.run(new Snapshot(), fn); } export function wrapFallback(fn) { const savedFallback = fallbackSnapshot.get(); return () => savedFallback.isParentOfCurrentContext() ? fn() : savedFallback.run(fn); } } ``` and then frameworks (or other specs) can piggyback on the same boundaries? 2024-10-29 [07:14:29.0151] Hey, I noticed that the AsyncContext meeting seems to be set in UTC time, which means it will be at a different time until spring for any timezones going out of DST soon [07:15:15.0157] * Hey, I noticed that the AsyncContext meeting seems to be set in UTC time, which means it will be at a different time until spring for any timezones going out of DST soon or already [07:15:37.0407] and for me, that makes it conflict with a meeting which I could skip once in a while, but not every time [07:49:20.0488] I have conflicts after the timezone change. Maybe we can move the meeting an hour after the current time, starting next time in November? [07:52:29.0692] * I have conflicts after the timezone change as well. Maybe we can move the meeting an hour after the current time, starting next time in November? [07:53:39.0510] we're talking 5 PM UK, 6 PM CET, 1 PM ET, 10 AM PT, right? [08:00:00.0700] after the timezone change, the meeting time now is 4pm-5pm UTC. The proposed new time is 5pm-6pm UTC [08:37:38.0479] It's always a weird couple weeks when Europe has changed time zones but US hasn't yet (or vice versa). If only everybody just kept everything pinned to UTC, it wouldn't be an issue... 🤔 [08:37:54.0027] this time it's just one week btw [08:41:56.0449] lol let's cancel daylight saving times [08:43:26.0683] Let's pin the meeting to US timezones rather than UTC? Right now it's pinned to UTC [08:44:13.0076] sounds good to me [09:04:51.0814] The meeting is happening now, 5 of us in the room 2024-10-30 [13:58:28.0187] > <@littledan:matrix.org> My experience is that programming against UTC ends up being more disruptive because conflicts are scheduled in local time. Anyway, agree that we should worry about this in November. as the prophecy foretold