July 26, 2012 TC39 Meeting Notes

David Bruant bruant.d at gmail.com
Wed Aug 1 11:25:34 PDT 2012


2012/8/1 Tom Van Cutsem <tomvc.be at gmail.com>

> 2012/8/1 David Bruant <bruant.d at gmail.com>
>
>>  Le 01/08/2012 09:07, Tom Van Cutsem a écrit :
>>
>> 2012/7/31 David Bruant <bruant.d at gmail.com>
>>
>>> [...]
>>>
>> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120801/b420a1d9/attachment.html>


More information about the es-discuss mailing list