Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Explicitly Managed Resource" as an object field #229

Closed
dtkdtk opened this issue Jun 2, 2024 · 4 comments · May be fixed by #232
Closed

"Explicitly Managed Resource" as an object field #229

dtkdtk opened this issue Jun 2, 2024 · 4 comments · May be fixed by #232

Comments

@dtkdtk
Copy link

dtkdtk commented Jun 2, 2024

Is this use case thought out? Is there a syntax like { using propKey: propValue } or { propKey: using propValue } ?
As far as I understand, the only way to put a disposable resource into an object is to declare a using variable outside the object, and then create an object field with that variable:

using myResource = new MyResource();
const resources = {
    myResource
};

However, I think that for this case too, syntax should be provided. For example:

const buffers = {
    myResource: using new myResource();
};

Also: If an object is deleted, are the "Explicitly Managed Resources" fields deleted correctly?

@mhofman
Copy link
Member

mhofman commented Jun 3, 2024

What semantics are you looking for exactly?

the only way to put a disposable resource into an object is to declare a using variable outside the object, and then create an object field with that variable

That will likely not do what you expect. When the scope reaches the end, your resource will be disposed, and your object will simply hold onto a disposed resource. You likely want to "move" the disposal responsibility onto the owner object.

Also: If an object is deleted, are the "Explicitly Managed Resources" fields deleted correctly?

There is no such thing a "an object is deleted" in JavaScript. You probably mean "an object gets garbage collected". This proposal is about explicit resource management, whereas garbage collection is not explicit. A collected object does not (and cannot) trigger any explicit disposal logic. A good summary of such discussions can be found at #213 (comment)

Taking the explicit nature of the proposal into consideration, semantics for using field that could make sense would be to automatically make the object a disposable itself. To rewrite your example above:

function makeBuffers() {
  return {
      using myResource: new myResource();
  }; // object literal implicitly has a `[Symbol.dispose]` property
}

using buffers = makeBuffers();

However beyond this simple use case, you'll quickly notice that you may want to do some work between when you obtain your resource in the maker, and when you return the object. At that point, you should be using a disposable stack to manage your resources:

function makeBuffers() {
  using stack = new DisposableStack();
  const myResource = stack.use(new myResource());

  doSomeInit(myResource);

  const disposer = stack.move();
  return {
    myResource,
    [Symbol.dispose]() {
      disposer.dispose()
    }
  };
}

using buffers = makeBuffers();

Admittedly "moving" the disposable stack to the object's dispose is a little clunky, but I'm not sure there is a much better approach here. Also since you don't want to expose the internal disposer, I don't see how any "per field" syntax could help here. What we may need is a userland helper that moves the stack onto the object:

function moveToDisposeFunction(stack) {
  const disposer = stack.move();
  return disposer.dispose.bind(disposer);
}

function makeBuffers() {
  using stack = new DisposableStack();
  const myResource = stack.use(new myResource());

  doSomeInit(myResource);

  return {
    myResource,
    [Symbol.dispose]: moveToDisposeFunction(stack),
  };
}

using buffers = makeBuffers();

@dtkdtk
Copy link
Author

dtkdtk commented Jun 3, 2024

Thanks for your answer. It completely covers the issue.

Also: If an object is deleted, are the "Explicitly Managed Resources" fields deleted correctly?

Let me rephrase: When a non-explicitly managed object containing explicitly managed resources goes out of scope, are the @@dispose methods of those resources called?
However, you already answered that question: "Yes".
After researching more examples (including yours), I found a better solution. Although using DisposableStack makes my task a bit more complicated, it may be better than creating a new syntax to automate actions with a disposable stack.

I don't see a problem here anymore.

@dtkdtk dtkdtk closed this as completed Jun 3, 2024
@rbuckton
Copy link
Collaborator

rbuckton commented Jun 3, 2024

What we may need is a userland helper that moves the stack onto the object:

I originally had that capability with DisposableStack.prototype.dispose being a getter for a bound method, but that approach was rejected by some on the committee.

@mhofman
Copy link
Member

mhofman commented Jun 3, 2024

I originally had that capability with DisposableStack.prototype.dispose being a getter for a bound method, but that approach was rejected by some on the committee.

Yeah I thought I remembered something along those lines. Wondering if it may be worth revisiting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants