tc39 / proposal-mass-proxy-revocation

Proposal for revoking proxies en masse.
MIT License
5 stars 1 forks source link

Relation to Explicit Resource Management proposal? #19

Open ajvincent opened 1 year ago

ajvincent commented 1 year ago

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

At the November 2022 TC39 plenary, @rbuckton stated he believed the DisposableStack or AsyncDisposableStack could help out with proxy revocation. I want to understand better how.

There are four main objects we're dealing with when it comes to proxies, five if we count this proposal:

  1. The proxy itself
  2. Its shadow target
  3. Its proxy handler
  4. The revoker function, which clears the shadow target and the proxy handler from the internal slots of the proxy.
  5. The shared revocation signal from this proposal.

Which of these would be used with DisposableStack and how?

If it's the revoker, that might be simplest via stack.defer(revoker), but I'm skeptical of this. (a) We'd still have to create the revoker in the first place, to give to the stack - and avoiding the need to create revokers is a major goal of this proposal. (b) I've demonstrated both in V8 and in Spidermonkey that the revoker holds a strong reference to the proxy (a memory leak), something which is probably unintentional (but also not a spec bug).

If it's the proxy, I have concerns about knocking out proxies which other objects or proxies might refer to via a property or a prototype chain.

If it's the proxy handler, I note the handler is likely to be shared by many proxies and the membrane likely holds a strong reference to it too.

If it's the proxy's shadow target, that might work, since it's supposed to be unique to the proxy. That said, a careful reading of the specification (section 10.5) shows that the traps aren't explicitly checking whether the shadow target still exists or not. So we could introduce a spec bug or a crash in implementing engines.

These are just my initial thoughts, other than a question for the other proposal, which is "What happens if two stacks reference the same object or callback?", or more generally, "what happens if two references own an object, and one of them is a disposable stack?"

ajvincent commented 1 year ago

Reading back on the TC39 plenary notes, there is a suggestion of passing the revoker to DisposableStack.defer(), and then the JS engine recognizing it as a revoker function and dropping the reference, so it can manage the proxy's slots directly.

I'm not sure how that will play out.

Jack-Works commented 1 year ago

It will work if the engine chooses to optimize it. It still creates a little GC pressure. If you create a lot of proxies at once that might be a problem.