Skip to content

Instantly share code, notes, and snippets.

@DavidBruant
Created December 17, 2011 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidBruant/1490167 to your computer and use it in GitHub Desktop.
Save DavidBruant/1490167 to your computer and use it in GitHub Desktop.
Alternative proposal to privateName.public

Introduction

We've seen in the thread "Are Private name and Weak Map the same feature? and the Assoc API" that .public was here to prevent proxies from having access to a private name. This constructs results in a bigger efforts to use private names in coordination with proxies (need to access the public part and a map to retrieve the private name with the remaining danger of sharing the map with the wrong entities).

Sam Tobin-Hochstadt gave an example of a simple program we may not expect to leak a private name but would if private names passed through proxies and the program was used with a malicious proxy. I answered that we should consider changing the way we write program and I admit that I am myself a bit annoyed by this statement.

So here is a proposal where I think I can make both parties (those who don't want to write complicated programs to protect their private names and those who don't want to write complicated programs to make private names and proxies work together) happy.

Proposal

What about a 'trapped' boolean in the private name constructor?

It would work this way:

var n = new Name(false); // don't trap when used is a proxy
var p = new Proxy({}, maliciousHandler);

p[n] = 21; // the set trap is NOT called!
var v = p[n]; // the get trap is NOT called and v === 21

Basically, when the private name is created with the 'trapped' boolean to false, the proxy becomes oblivious to being called with these private names.

var n = new Name(true); // trap when used on a proxy
var p = new Proxy({}, {
    get:function(target, name, receiver){
        console.log(name === n);
        return target[name];
    },
    set:function(target, name, val, receiver){
        console.log(name === n);
        target[name] = val;
    }
});

p[n] = 21; // the set trap is called and logs 'true'
var v = p[n]; // the get trap is called, logs 'true' and v === 21

The name passed to the traps is the actual private name.

In the case exposed by Sam, using an untrapped name will do the trick, in my cases, using trapped names will do the trick as well. If someone wants some proxies (and by "proxies" I mean "untrusted third party") to have access to a secret and some not, then, i think it's fair to ask this person to have several secrets and dictionary and arbitrary complicated constructs to achieve her goal.

If as Sam suggested, most cases don't need proxies to have access to an information, let the default value of 'trapped' be 'false'.

I expect the following response: "but then the proxy does not reify the operation made on untrapped private names". It is true and it is true with the current proposal as well. Currently, maybe that the proxy traps something but it's using an altered information (which I'm not sure can really be considered as a true reification). At the end of the day, I don't think there is a feature loss in not calling a function or calling it with a virtually useless information. What I'm proposing is to make more explicit (a boolean in the private name constructor) whether or not we want a proxy to do something useful with a name.

Is it a good compromise?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment