What does HackerNews think of proposal-explicit-resource-managemen?

In addition to this, is the new (stage 3 even!)explicit resource management proposal[0], supported by TypeScript version >= 5.2[1]

Though I agree that async context is better fit for this generally, the ERM should be good for telemetry around objects that have defined lifetime semantics, which is a step in the right direction you can use today

[0]: https://github.com/tc39/proposal-explicit-resource-managemen...

[1]: https://www.totaltypescript.com/typescript-5-2-new-keyword-u...

TSC should fail the build if it doesn't have the destruction interface, the scope is the scope the variable is initialized in/under. It's very similar to C#'s usage of using.

Edit: It's also a pending Stage 3 proposal for EcmaScript.

https://github.com/tc39/proposal-explicit-resource-managemen...

There's a conversation I had with Ron Buckton, the proposal champion, mainly on this specific issue. [1]

Short answer: Yes, Disposable can leak if you forget "using" it. And it will leak if the Disposable is not guarded by advanced GC mechanisms like the FinalizationRegistry.

Unlike C# where it's relatively easier to utilize its GC to dispose undisposed resources [2], properly utilizing FinalizationRegistry to do the same thing in JavaScript is not that simple. In response to our conversation, Ron is proposing adding the use of FinalizationRegistry as a best practice note [3], but only for native handles. It's mainly meant for JS engine developers.

Most JS developers wrapping anything inside a Disposable would not go through the complexity of integrating with FinalizationRegistry, thus cannot gain the same level of memory-safety, and will leak if not "using" it.

IMO this design will cause a lot of problems, misuses and abuses. But making JS to look more like C# is on Microsoft's agenda so they are probably not going to change anything.

[1]: https://github.com/tc39/proposal-explicit-resource-managemen...

[2]: https://stackoverflow.com/a/538238/1481095

[3]: https://github.com/tc39/proposal-explicit-resource-managemen...

I think you’re confusing scope and reachability. Maintaining a reference to an object has nothing to with whether or when it’s disposed in this TC39 language enhancement. Such a system _does_ exist in Object finalizers, but it’s hard to use correctly, especially in a language where it’s very easy to inadvertently retain references via closures. Resource disposal of this type needs to be much more predictable and can’t be left to the whims of the runtime. The docs on finalizers and WeakRefs are full of warnings not to expect them to be predictable or reliable.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

With this new using syntax, resources are disposed of when the object they are tied to goes out of _lexical scope_, which doesn’t need to worry about the runtime or object lifetimes at all. This example from the TC39 proposal makes it pretty clear:

    function * g() {
      using handle = acquireFileHandle(); // block-scoped critical resource
    } // cleanup

    {
      using obj = g(); // block-scoped declaration
      const r = obj.next();
    } // calls finally blocks in `g`
https://github.com/tc39/proposal-explicit-resource-managemen...
I'm pretty sure that example won't work and is based on an old version.

But assuming a javascript implementation where it works, I don't know what you mean by "language rule". The spec says what "using" means, and it doesn't require any behavior the language doesn't already have. The old spec said "When try using is parsed with an Expression, an implicit block-scoped binding is created for the result of the expression.", and the new one says "When a using declaration is parsed with BindingIdentifier Initializer, the bindings created in the declaration are tracked for disposal at the end of the containing Block or Module". Then the spec has an example implementation written in javascript, with the value being added to a (non-user-accessible) list. https://github.com/tc39/proposal-explicit-resource-managemen...

Is that the language rule you wanted?

In my opinion, this is a flawed proposal. The disposer should not be a method on the object, because it means it cannot pass around the resource without the risk that the recipient of the resource disposes it themselves. A safer alternative is available- [item, disposer]. See this issue: https://github.com/tc39/proposal-explicit-resource-managemen...
I thought the same and I don't see motivation from it on the TC39 spec page [1] but I do see they have several examples that make use of the feature.

It makes me realize I've never really considered the memory implications of doing something like:

    const { someSmallPart } = getSomeMassiveObject();
I don't really know the lifetime of "massive object". Probably a bad on my part for not knowing if Javascript garbage collection is allowed to notice that the only thing with a reference is `someSmallPart` and could therefore release any other parts of the massive object. If the answer to that is "no" then there is no problem with the above pattern.

If the answer is "yes", then things could get complicated. e.g.

    async function getComplicatedObject() {
      const db = await db.getConnection( ... );
      const f = await file.open( ... );
      return { db, f, [Symbol.asyncDispose]: () => { 
        db.close()
        f.close()
      }
    }

    {
      await using { f } = getComplicatedObject();
      // ... more stuff with awaits where the GC might decide `db` isn't used so it can clean
    } // I would not expect a null ref error on `db` here when `asyncDispose` is called
I mean, you can handle the above even if the GC is allowed to be smart and discard `db` - it just makes it significantly more complicated and requires clever book-keeping.

1. https://github.com/tc39/proposal-explicit-resource-managemen...

This is not TypeScript-specific, it’s a stage-3 ECMA-262 proposal.

https://github.com/tc39/proposal-explicit-resource-managemen...

It’s a shame the author insisted on it looking like C# and sabotaged attempts to combine disposal with destructuring.

Also, there is no move operator without futzing around with DisposableStack. Though that could be introduced later; it’s not a day-zero design issue.

The proposal[1] explains several cases where try…finally is verbose or even can result in subtle errors. The upshot for me is that this feature adds RAII to JavaScript. It makes resource management convenient and more maintainable. Seems like a no brainer to me.

[1] https://github.com/tc39/proposal-explicit-resource-managemen...

The last example:

    {
      await using { connection } = getConnection();
      // Do stuff with connection
    } // Automatically closed!
edit: according to the ES proposal issues, this might be something that doesn't actually exist, on purpose (it's rather ambiguous as to what will be disposed of): https://github.com/tc39/proposal-explicit-resource-managemen...
Nice, so this is the equivalent of `with` and context mangers in Python. I like it.

I generally avoid new TS features (apart from typing that gets compiled away) until it looks like they are going to make their way into JavaScript, anyone know if thats being considered?

--

Edit: Yes it's being considered, looks likely, but not decided - https://github.com/tc39/proposal-explicit-resource-managemen...