2012/8/1 Tom Van Cutsem <[email protected]> > 2012/8/1 David Bruant <[email protected]> > >> Le 01/08/2012 09:07, Tom Van Cutsem a écrit : >> >> 2012/7/31 David Bruant <[email protected]> >> >>> [...] >>> >> Maybe the details I propose are not perfect, but I think there is a >>> game-changer in the idea of a handler being able to share with the JS >>> implementation which secrets it knows. >>> >> >> I don't like it. It introduces mutable state into the proxy-handler >> protocol, which is currently fully functional. >> >> I partially disagree. One of the reason I chose Set/WeakSet in my >> demonstration is that the after-trap code would only call Set.prototype.has >> (the built-in one, not the dynamic one for security reasons), leaving the >> API somewhat fully functional. >> knownPrivateNames could be made a function with signature Name -> Boolean >> (I would prefer too), but if the after-trap code calls it with the private >> name as argument, it leaks the private name, so that cannot work... or >> maybe there is a way. >> > > I should have phrased that differently: currently, the handler can be a > stateless/immutable object, and as a result, you can have a single handler > handle many proxies. Associating a mutable (Weak)Set by default with each > handler destroys that simple model. >
True. That's the reason I changed my proposal to have a property that's a function and not a set/map anymore: "An idea to have knownPrivateNames or rather isPrivateNameKnown a function and make sure this function doesn't leak private names to the handler would be to enforce isPrivateNameKnown to be a bound function of the built-in Set.prototype.has. The after-trap can make sure of that by comparing [[TargetFunction]] (which cannot be faked by user code) and the built-in capability. As far as I can tell, it would work also with function proxies if the target is such a bound function, so this is membrane-proof." It would preserve the statelessness and immutability property. Also, since a handler's properties may be mutable, you have to account for >> the fact that a trap can be updated, thus there is the potential issue of >> the handler's internal state growing out of date. >> >> As you're saying below, handlers will often need weakmaps to tack >> additional state, so guarding internal state consistency is already a >> problem in the current setting. >> > > To me, the fact that this special "isPrivateNameKnown" property must be a > built-in WeakMap > It is a function, now. > or some such, to guarantee that the private name doesn't leak, signals > that we are just shifting the problem. Now we have yet another kind of > interaction point with the handler where we must make sure the private name > does not leak. > With the constraint of being a bound function of some predefined built-ins that only return booleans, I think we're good. Also, the gains are not at all clear to me. Are there big savings to be had? > We are in a situation where user code needs to prove its knowledge of some secret to the engine for it to procede with some operations. The current proposal asks the handler writer to do all the work him/herself. For that, the before-trap substitues a private name with a public name, the handler writer needs to do the opposite mapping back if it knows the secret and the after-trap can procede. When the same private name comes in, the before-trap has lost all track that the proxy knows this private name and redoes the private -> public subsitution and the trap has to prove again something it has already proven. I agree that it works, but the fact that the handler has no way to say "hey, I know this private name already" seems unfortunate. My proposal suggests to move a bit of the work that the user has to do to a cooperation with the engine. The idea is to provide a way for the proxy to express its knowledge of secrets so that the private->public->private dance is not necessary anymore. If you have a way to prove you know a secret before the trap is called, then the engine can just pass the private name direclty, no need for the public part. The "big saving" is that the public->private mapping and return value boilerplate code to be put in all name-accepting traps is entirely replaced by a one-liner in the handler definition. Something like "isPrivateNameKnown: Set.prototype.has.bind(privateNamesIKnow)" (privateNamesIKnow is either shared in handler function scopes or as a handler property or something else, left at the discretion of the author). It's likely to be a slightly bit more efficient in both time (no need for the after-trap private name checking, no need for public->private nor for the 2-properties array) and memory (no need for public counterparts any longer). Also, public->private resolution and returning the right private name seems more error prone than if you're being handed the private name directly as an argument. Maybe debatable. One downside is that it's a bit more work for implementors. Also, enforcing a function bound to the built-in Set/WeakSet/Map/WeakMap.prototype.has capability is a bit strong on proxy authors, but I think it's an acceptable constraint if it removes the public counterpart and the need to prove things you have already proven. >From a different point of view, we currently have a communication protocol between trap and "around-trap" that's scoped at the singular a trap-call level: knowledge on whether you know a name has a trap call lifetime. The engine cannot know that the same trap for the same handler has proven knowledge of a name. It even less knows if 2 trap calls of the same handler share knowledge of a given private name. My proposal suggests to push the scope to a handler level: knowledge on whether you know a name has a (potentially) infinite lifetime, but is still local to the handler. This knowledge scope seems more appropriate to how objects work. But it requires cooperation from the underlying platform. In your proposed design, the "after-trap" still needs to verify whether the > handler knows the private name > It does not. The before-trap needs to verify, but after that, you're good to go. you've proven you know the name, it's passed as argument directly, you can play with the target and the private name directly, no need for after-trap mediation. by doing a lookup in some associative data structure. > Function call, now. > But the trap will most likely already need to do such a lookup itself (the > handler will itself likely need to check whether its knows the name). > If the before-trap checks whether you know the name, it can pass the private name directly as an argument. The trap being called with the private name as argument requires to know the name. > In that case, the handler just returns the private name as a result and > the proxy readily verifies, no extra lookup required. > > I can also imagine that some handlers will have a specific private name in > scope and can just return it as-is, without ever needing an associative > data structure to hold the private name. At that point, your proposed > mechanism adds more overhead by requiring that handler to store the value > in the map/set, and by making the proxy do an additional lookup. > If you've put the private name you know in the set, the before-trap is aware of it, can provide it as argument directly and you don't need the public->private decyphering. The engine does a lookup so that I don't need to. The number of lookups seems equivalent. David
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

