Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storing the context in which an exception was thrown in sync code #90

Open
andreubotella opened this issue May 16, 2024 · 0 comments
Open

Comments

@andreubotella
Copy link
Member

andreubotella commented May 16, 2024

While investigating the web integration of AsyncContext, I noticed that the error event on the window object would get fired with an originating context that might be unexpected. As a reminder, this event gets fired when an uncaught exception gets thrown in synchronous JS code – equivalent to process.on("uncaughtException") in Node.js.

function cb() {
  asyncVar.run("foo", () => {
    throw new Error();
  });
}

asyncVar.run("bar", () => {
  setTimeout(cb, 0);  // setTimeout fires an `error` event if `cb()` throws
});

// For the purposes of this discussion, let's assume that `error` event
// listeners always use the originating context.
window.addEventListener("error", () => {
  console.log(asyncVar.get());  // bar
});

With the current proposed spec text, the only thing that could be logged here is "bar" (or undefined). This is because the .run() methods always restore the previous context when the callback finishes running, whether that is a return or a throw. And therefore, the "foo" context gets lost before the code inside inside setTimeout that fires the error event is reached. (Note that unhandledrejection can keep the "foo" context.)

If we agree that the expected result here is "foo", then we could change the spec so that if a callback passed to .run() throws (synchronously), the context inside the run gets stored, and the last thrown context could be exposed to web specs. However, could it be worth exposing this to userland? (This might benefit at the very least Node.js and Deno, since their error event implementation happens in JS code, although that code would of course have access to features from the V8 embedding API.) If so, how would that API behave inside async functions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant