13:11 | <Andreu Botella> | I was thinking that the unhandled rejection context here is
|
13:11 | <Andreu Botella> | so shouldn't it be the same for sync unhandled errors? |
13:29 | <littledan> | I don't understand what you're getting at; the async/await case is different since it corresponds to a bunch of nested try/catch/rethrow patterns. |
13:30 | <Andreu Botella> | will that be obvious to developers? |
13:31 | <littledan> | no, developers will expect that the inner place where the error inside the async/await is the source. But making it "also broken" for sync exceptions won't fix that expectation. |
20:29 | <Steve Hicks> | Are we talking about the callback's context or the one that's hung on the unhandledrejection /error event? If the former, I'm arguing it should always be registration context. Would it be possible for event.errorSnapshot to be "baz" even for the unhandledrejection case? |
20:32 | <Steve Hicks> | I've come around to the view that one of the advantages of heterogeneous access to causal contexts (which I was arguing against a few weeks ago) is that you can target more clearly exactly which context you get. |
20:32 | <littledan> | I think we're talking about the supplemental context that exists as a property |
20:32 | <littledan> | even for that there's a lot of decisions to make! |
20:33 | <Steve Hicks> | yes there are |
20:33 | <littledan> | we could expose a whole bunch of them, but IMO one of them will probably be good enough to start, and people won't really be so great at choosing between a bunch of them anyway |
20:33 | <Steve Hicks> | so i guess i'm asking, is there a reasonable way to spec it so that the unhandled rejection is also baz? |
20:34 | <Steve Hicks> | right, I don't think we should expose a ton |
20:34 | <littledan> | so i guess i'm asking, is there a reasonable way to spec it so that the unhandled rejection is also baz? |
20:35 | <Stephen Belanger> | IMO error construction should capture a context snapshot and you can read out of that later by accessing some property on that error. |
20:35 | <littledan> | jinx |
20:35 | <Stephen Belanger> | Yeah. |
20:35 | <littledan> | (I prefer allocated better than first thrown too) |
20:35 | <Steve Hicks> | i think that's a good balance |
20:36 | <Stephen Belanger> | First thrown is a bit mysterious but possibly more correct. You need extra logic to detect if it already HAS a context on a rethrow though. |
20:36 | <littledan> | first thrown is sad-feeling because it means mutating an object. what if the same thing is thrown twice? anyway that is not very pragmatic motivation, it's my theorist side talking |
20:37 | <Stephen Belanger> | Yeah. Almost makes more sense to not be attached to the Error object, but then where would you put it? |
20:37 | <littledan> | but we might still need a causative context for unhandled rejections in case they aren't error objects |
20:38 | <Stephen Belanger> | True. |
20:38 | <littledan> | Yeah. Almost makes more sense to not be attached to the Error object, but then where would you put it? |
20:38 | <Stephen Belanger> | For unhandledRejection we probably would need the point it throws and not an Error property given you can throw non-errors and unfortunately sometimes people do. 😐 |
20:39 | <Steve Hicks> | unhandledrejection isn't dispatched synchronously, so it's a little more awkward |
20:39 | <Steve Hicks> | ideally it could reuse the same mechanism for synchronous events (i.e. dispatchEvent captures the snapshot) |
20:40 | <littledan> | as we've previously reasoned, we could either store the context when the Promise is allocated (as in Node) or rejected (as in the current spec). I guess in either case, it could be in the Promise itself, and then it's only read by the unhandled rejection thing. |
20:41 | <Stephen Belanger> | Capturing on dispatchEvent also means we could have anything be able to access both register time and call time contexts. 🤔 |
20:41 | <littledan> | I previously convinced myself that the rejected-time context is definitely way better, but now, with distance, I could see that either could be OK... |
20:41 | <littledan> | Capturing on dispatchEvent also means we could have anything be able to access both register time and call time contexts. 🤔 |
20:41 | <littledan> | unless you mean the internal equivalent |
20:41 | <Stephen Belanger> | Yes, internal equivalent. |
20:42 | <Steve Hicks> | reject-time means you're not making as many unused snapshots |
20:42 | <littledan> | Yes, internal equivalent. |
20:42 | <littledan> | reject-time means you're not making as many unused snapshots |
20:43 | <littledan> | we're not doing an allocation, in particular |
20:43 | <Steve Hicks> | is there a concern about lifetime management? |
20:43 | <littledan> | is there a concern about lifetime management? |
20:43 | <littledan> | via the getter |
20:43 | <Stephen Belanger> | yeah so conversations with DOM people like Anne seemed to point to, we'd only get this little by little, for particular things where it made sense, since it's complicated and depends on that particular API's details |
20:43 | <littledan> | or maybe that's too weird and un-getter-like? |
20:44 | <littledan> | the alternative is, you eagerly stash a pointer to the underlying data structure, but somehow you can dynamically type check that, and on first access, you replace it with a snapshot in place, and subsequent accesses notice that it's already a snapshot |
20:45 | <Steve Hicks> | well, IMO we should give a fresh object identity for the snapshot each time you use it, so we don't have to worry about that |
20:45 | <littledan> | I mean…that’s possibly fine? We just need to make a bunch of individual cases for each API, which it seemed like Andreu was already doing the research work for? |
20:46 | <littledan> | Not sure we're talking about the same thing? IIUC there was concern about when a snapshot was no longer reachable (hence all the explicit resource management discussions) and if we've got a never-will-be-used snapshot hanging on a long-lived promise, that could confuse it |
20:46 | <littledan> | I don't see a solution to this lifetime question |
20:46 | <Stephen Belanger> | Selfishly, APM’s probably won’t care as we’re focused on servers where most of those APIs don’t exist anyway. 😅 |
20:47 | <littledan> | well, some people care about client-side performance monitoring, but I take it that's not your team |
20:47 | <littledan> | I guess the lifetime thing might be especially bad for something like Error objects, where it might be really non-obvious what you're keeping around |
20:48 | <Steve Hicks> | you could have HostPromiseRejectionHandler add/remove it? |
20:48 | <littledan> | and you can imagine keeping errors around |
20:48 | <littledan> | you could have HostPromiseRejectionHandler add/remove it? |
20:48 | <Steve Hicks> | well, some people care about client-side performance monitoring, but I take it that's not your team |
20:49 | <Steve Hicks> | it would modify the error? |
20:50 | <littledan> | oh, right... yeah that makes sense, the unhandled rejection can only happen once. (In fact, maybe the spec doesn't even say any of this, since it's implied by unreachability.) But this doesn't handle the error issue. |
20:50 | <Justin Ridgewell> | For unhandledRejection we probably would need the point it throws and not an Error property given you can throw non-errors and unfortunately sometimes people do. 😐 |
20:50 | <Justin Ridgewell> | as we've previously reasoned, we could either store the context when the Promise is allocated (as in Node) or rejected (as in the current spec). I guess in either case, it could be in the Promise itself, and then it's only read by the unhandled rejection thing. ”foo” context |
20:50 | <littledan> | I’d honestly be happy saying that’s an anti-pattern and you don’t get the correct context in this case. |
20:51 | <littledan> | I don’t think this helps in Andreu’s code sample, unless we’re expecting the |
20:51 | <Steve Hicks> | Google also cares about throwing non-errors, but we believe the solution is "Don't do that" rather than bloating the standards to account for it |
20:52 | <littledan> | well, maybe we can look into the "don't do that" path... maybe Chengzhong can follow up on this? |
20:52 | <littledan> | Chengzhong Wu: ^ |
20:53 | <Steve Hicks> | well, maybe we can look into the "don't do that" path... maybe Chengzhong can follow up on this? throw x s to throw trackNonError(x) that throws a real error with a stack trace asynchronously so as to at least get some logging in place to identify all the offenders |
20:54 | <Justin Ridgewell> | Are you suggesting we attach the context onto the error instead of just running the unhandledRejectionHandler in the correct context? |
20:54 | <Steve Hicks> | Are you suggesting we attach the context onto the error instead of just running the |
20:55 | <Steve Hicks> | at that point, maybe there's not as much of a reason to even attach a context to unhandledrejection ? |
20:55 | <littledan> | Are you suggesting we attach the context onto the error instead of just running the |
20:55 | <littledan> | if we get the rejection's context, it could be exposed in the event |
20:57 | <Steve Hicks> | I'm still hopeful that maybe we can get a more general resolution context for promises, but my understanding is that littledan has reason to think that's not feasible |
20:58 | <littledan> | I think a general resolution context for all promises would be seen as an information leak, but again that's not a very pragmatic reason for anything. Definitely it's easier to just capture the context where resolve()/reject() was done, rather than have that somehow be propagated across .then() as we've previously discussed. |
21:02 | <littledan> | with the semantics I'm picturing for capturing causal contexts for all Promises, for async functions, the resolve/reject context would be boring: it would be the context when the async function was called |
21:03 | <littledan> | it would only be something different if you call the promise constructor/withResolvers |
21:06 | <Chengzhong Wu> | well, maybe we can look into the "don't do that" path... maybe Chengzhong can follow up on this? |
21:07 | <littledan> | I am not a fan of granting "throw" super power in spec to recover stacks and contexts either. Definitely, people can throw primitive values, just don't do that |
21:08 | <Chengzhong Wu> | I think it could be a property of PromiseRejectionEvent/ErrorEvent, as documented in https://github.com/tc39/proposal-async-context/pull/94/files#diff-85367a6a792209cf5826726990ddd1f0fd7a572bac4162097bc5e7e192aa625cR295, updated today |
21:09 | <Chengzhong Wu> | Well, I think this could be definitely in its own piece of document expansion. |
21:09 | <littledan> | isn't putting a context in ErrorEvent giving those superpowers? |
21:10 | <Chengzhong Wu> | ErrorEvents are errors captured at the host level |
21:10 | <Chengzhong Wu> | "throw" itself doesn't have this superpower |
21:10 | <Chengzhong Wu> | so this won't have a re-throw problem |
21:38 | <Steve Hicks> | Hosts already compute stack traces at error construction time, so it seems pretty reasonable to also copy the context pointer at the same time. But I'm a little fuzzy on how this proposal interacts with that, since EcmaScript doesn't even mention stack anywhere, even non-normatively. |
21:39 | <Steve Hicks> | Where are we planning on documenting the various DOM interactions? |
21:39 | <Chengzhong Wu> | Hosts already compute stack traces at error construction time, so it seems pretty reasonable to also copy the context pointer at the same time. But I'm a little fuzzy on how this proposal interacts with that, since EcmaScript doesn't even mention |
21:40 | <littledan> | Where are we planning on documenting the various DOM interactions? |
21:42 | <littledan> | it's being worked at https://github.com/tc39/proposal-error-stacks. |
21:42 | <littledan> | I don't think there's active work in that repo either, given that browsers expressed requirements and that was demotivating |
21:43 | <Chengzhong Wu> | 😅 "stalled for years" |
21:48 | <littledan> | yeah I think if you don't really get to make a big point about this happening "for years" when it's a reasonable thing requested and you just decided to not do it. "stalled for years" implies that something is actually happening. |
22:03 | <Stephen Belanger> | well, some people care about client-side performance monitoring, but I take it that's not your team |
22:35 | <littledan> | client monitoring in general? I'm curious whether Steve Hicks 's effort is for refining present monitoring, or making a new system that doesn't exist yet. |
22:38 | <littledan> | My goal is to build a reasonable basis for client-side monitoring, not reaching either extreme of "focus on server side now, do client side later" or "expose everything interesting that goes on in the client" |