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.