Skip to content

Do we need new syntax? #76

@mhofman

Description

@mhofman

While reviewing the latest state of this proposal the other day, it struck me that, as the readme mentions, the mechanism to perform block scope finalization already exists in JavaScript today in the form of iterators and for-of statements. This can be leveraged to build a purely API based approach to explicit resource management following closely the patterns adopted by this proposal:

for (const { using } of Disposable) {
  const resource = using(getResource());
  resource.doSomething();
  const other = using(resource.getOther());
  const stuff = other.doStuff();
  using(() => cleanUpStuff(stuff));
} // automatically cleanup, even when something throws

I actually spent this weekend implementing such a library to demonstrate that all use cases covered by the readme can seemingly be adapted to this approach, without the need to add any new syntax to the language.
https://github.com/mhofman/disposator/

While a for-of statement can be awkward at first, the code stays fairly readable. A similar approach was proposed in #10. As discussed there, JavaScript iterators are essentially the dispose and cursor patterns mixed together, and what this approach does is to neuter the cursor pattern to only leave the dispose pattern.

With a widely adopted library or built-in API, I believe this approach could become pretty natural. I also believe the block scope is more explicit in some regard than the current direction of the syntax additions, especially around the interleaving points for asynchronous code. See #68

One limitation of using for-of is that errors thrown during iterator close are shadowed by errors thrown during the iteration block (with no way to detect the iterator close is due to a throw). I would argue this is a separate problem that we should consider investigating (e.g. we could add an extra argument to iterator.return()). This is similar (but opposite) of errors thrown in a finally block shadowing an error thrown in the try block.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions