13:11 | <nicolo-ribaudo> | 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.
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
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 .
|
13:14 | <nicolo-ribaudo> | Also, I'm seeing in the notes a question about how long the bootstrap context lives.
The effects on that of
Event.captureFallbackContext(() => { addEventListener("foo", () => {}); });
are the same as
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)
|
13:21 | <nicolo-ribaudo> | Also, I'm seeing in the notes a question about how long the bootstrap context lives.
The effects on that of
Event.captureFallbackContext(() => { addEventListener("foo", () => {}); });
are the same as
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:
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
|
21:31 | <Steve Hicks> | 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 (or other specs) can piggyback on the same boundaries?
|