Async using syntax · Issue #1 · tc39/proposal-async-explicit-resource-management (original) (raw)
I've seen different syntax suggestions related to async disposal spread over different issues, in particular tc39/proposal-explicit-resource-management#16 tc39/proposal-explicit-resource-management#76 tc39/proposal-explicit-resource-management#84 #4. I wanted to concentrate the discussion in a single issue.
I'd first like to discuss the ongoing assumption that using
an async-disposable requires specific syntax.
The way I model the using
syntax is that a block containing a using
declaration implicitly creates a DisposableStack
. Every using
declaration implicitly results in a .use()
on the stack, and that exiting the block implicitly calls [Symbol.dispose]()
on the stack.
Now if we assume that we have a concept of "async blocks", instead of a DisposableStack
being implicitly created, it'd be an AsyncDisposableStack
. At that point any using
declaration would similarly call the .use()
of the implicit async disposable stack, which is a synchronous operation, and it's the exit of the "async block" which awaits the [Symbol.asyncDispose]()
call.
As such I would be against any syntax that uses the await
keyword for the using
declaration, as nothing is awaited at the declaration time. Similarly I would be against any syntax that doesn't use the await
keyword on the block as a marker of interleaving. I would be ok with a async using
declaration to be explicit, but I would consider that unnecessary verbosity.
Given the mental model above, I believe it would be entirely natural that for await (using r of ...)
, and using
declarations inside for-await-of
blocks in general, would implicitly use an AsyncDisposableStack
. for-await-of
is conceptually the only "async block" in the language at the moment. Then it become a matter of specifying what the syntax of an "async block" not tied to iteration looks like.