You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
async_hooks: add SymbolDispose support to AsyncLocalStorage
This introduces explicit resource management support to
AsyncLocalStorage. In order to avoid unexpected leakage of an async
local storage value to outer scope, `asyncLocalStorage.run` requires a
callback to nest all sub-procedures in a new function scope. However,
when using `AsyncLocalStorage` with different function types, like
async generator, moving statements and expression to a new function
body could be evaluated in different ways.
For example, given an async generator:
```js
class C {
async* foo() {
await a();
yield b();
await c();
}
}
```
Then, if we want to modify the async local storage value for `b()` and
`c()`, simply moving statements would not work:
```js
const storage = new AsyncLocalStorage();
class C {
async* foo() {
await a();
storage.run(value, () => {
yield b(); // syntax error, arrow function is not a generator
await this.c(); // syntax error, arrow function is not async
});
}
}
```
Making the arrow function to be an async generator as well still
requires significant refactoring:
```js
const storage = new AsyncLocalStorage();
class C {
async* foo() {
await a();
yield* storage.run(value, async function*() => {
yield b(); // ok
await this.c(); // reference error, this is undefined
});
}
}
```
This could be potentially more convenient with `using` declarations:
```js
const storage = new AsyncLocalStorage();
class C {
async* foo() {
await a();
using _ = storage.disposableStore(value);
yield b();
await this.c();
}
}
```
However, creating a disposable without a `using` declaration could
still be a problem leading to leakage of the async local storage
value. To help identifying such mis-use, an
`ERR_ASYNC_LOCAL_STORAGE_NOT_DISPOSED` error is thrown if an
`AsyncLocalStorageDisposableStore` instance is not disposed at the end
of the synchronous execution.
0 commit comments