javascriptes6-proxy

What is a revocable proxy in JavaScript for?


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.


Solution

  • 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.