5

Why would you want to revoke a proxy? Could you provide a practical application of Proxy.revocable()?

Based on the MDN Proxy.revocable() documentation I understand it allows garbage collection. However, wouldn't it also allow garbage collection if you just deleted the Proxy object?

Addendum: If there is something wrong with this question, please let me know what it is and I will gladly rephrase it or add additional information.

@Amy:

I thought it seemed like it was an unnecessary builtin feature, since I could create a revocable proxy like so:

function createRevocable(o,handlers){
 var revoked = false
 var handlerWrapper = {
  get(...args){
   if(revoked){
    throw Error('Sorry, this object went poof.')
   }
   if(typeof handlers.get == 'function'){
    return handlers.get(...args)
   }else{
    return Reflect.get(...args)
   }
  }
 }
 var p = new Proxy(o,Object.assign({},handlers,handlerWrapper))
 var r = function(){
  revoked = true
 }
 return {r,p}
}

var a = createRevocable({a:1},{})
var prox = a.p
var revoke = a.r
console.log(prox.a) //1
revoke()
console.log(prox.a)

However, it seems that garbage collection really is the issue, since I can revoke access from the object, but cannot delete the internal reference to it inside the Proxy object. Unless...

function createRevocable(o,handlers){
 var revoked = false
 var proxyProxyHandlers = {
  get(target,prop,rec){
   if(revoked){
    throw Error('Sorry, this object went poof.')
   }
   return p[prop]
  }
  ,//etc...
 }
 var p = new Proxy(o,handlers)
 var proxyProxy = new Proxy(Object.create(null),proxyProxyHandlers)

 var r = function(){
    // Delete the one and only reference to the proxy:
  delete p
  revoked = true
 }
 return {r,p:proxyProxy}
}

var a = createRevocable({a:1},{})
var prox = a.p
var revoke = a.r
console.log(prox.a) //1
revoke()
console.log(prox.a)

So, by creating a two layered proxy you can create a garbage collectable and revocable proxy. So, why is it built in? Ease of use? Or am I missing something? It's not entirely garbage collectable though, there is still a thin wrapper with a reference to an object with a null prototype.

ADJenks
  • 2,973
  • 27
  • 38
  • 2
    Say you have these proxies throughout your system. And you want to remove one, but you can't be sure you've removed it from everywhere in the system. Revoking it makes it so that the proxy will throw an error if its used; letting you track down and remove that usage. –  Feb 12 '20 at 21:28
  • 1
    Or perhaps you have a third-party library that issues these proxies. It can't control how those proxies will be used outside the library, but when it wants to be damn sure users of the library must not continue to use an expired proxy, it can revoke it and there's nothing that other system can do except ask for another proxy. –  Feb 12 '20 at 21:29
  • @Amy thank you for your examples. I have responded to you further in my question. – ADJenks Feb 12 '20 at 22:43
  • It's unclear what you mean by "*if you just deleted the Proxy object*" – Bergi Feb 12 '20 at 22:46
  • @Bergi I mean delete the Proxy() to allow garbage collection. `var test = {p:new Proxy({a:1},{})}; delete test.p; console.log(test.p.a);` >TypeError: test.b is undefined. – ADJenks Feb 12 '20 at 22:52
  • @ADJenks That only deletes the `p` property of your `test` object, not the proxy. For the proxy and its garbage collection there's no difference to just having done `test.p = undefined`. – Bergi Feb 12 '20 at 22:53
  • 1
    Yes, so if that is the last remaining reference to it, it should be garbage collected. – ADJenks Feb 12 '20 at 22:54
  • [This](https://exploringjs.com/es6/ch_proxies.html#_revocable-references) might provide some insights. Yes, you could implement it yourself, albeit much more complicated and slower. It is mostly a utility feature. Although one [backed by theory](http://wiki.erights.org/wiki/Walnut/Secure_Distributed_Computing/Capability_Patterns#Revocable_Capabilities), and probably the initial design envisioned some very different usecase than we commonly find today. See also https://brendaneich.com/2010/11/proxy-inception/ – Bergi Feb 12 '20 at 23:20
  • @Bergi I had to access the first link via [web.archive](https://web.archive.org/web/20190629142604/https://exploringjs.com/es6/ch_proxies.html) because it timed out for some reason. It is however a nice resource. So, it's a very common pattern for security purposes when passing between environments. It could be implemented manually, but security related features are never good to implement manually. I appreciate your comments, now please post a real answer. So a good real world example is passing objects into a Caja vm through it's "membrane". – ADJenks Feb 13 '20 at 00:12

1 Answers1

2

The revocable feature allows the target to be inaccessible and elligable for GC even though there are still references to its proxy. This is useful when we want to 'cancel' access to the underlying resource that we provided earlier, in some library for example.

The default behaviour of GC is still in effect, ie removing references to the proxy and its target will also allow it to be elligable for GC.

chantey
  • 4,252
  • 1
  • 35
  • 40
  • I thought the garbage collection concern was addressed in the second code snippet. By creating a thin wrapper allowing me to " 'cancel' access to the underlying resource", I believe the target becomes eligible for GC. So, is `Proxy.revokable()` simply a convenience method, or does it do something more for the language beyond my second version of `createRevocable()`? – ADJenks Feb 01 '22 at 19:20
  • The mechanism is implemented in js engines which operate on a lower level than what your example has access to, maybe having a read of the [source](https://github.com/v8/v8/blob/5fe0aa3bc79c0a9d3ad546b79211f07105f09585/src/objects/objects.cc#L2958) will provide you with some answers. – chantey Feb 02 '22 at 01:41
  • Good point. Thank you. I'll take a look. – ADJenks Feb 02 '22 at 18:14
  • There's too much code there for me to mull through in my spare time and it's still unclear to me whether this needs to be a built-in feature or if it's just sugar. Until anyone adds any further detail, I'll give you the point. – ADJenks Sep 22 '22 at 20:04