Security Demands Simplicity (was: Private Slots)

Herby Vojčík herby at mailbox.sk
Thu Jan 17 09:44:04 PST 2013



Mark S. Miller wrote:
> I also agree with David that unique symbols are not an encapsulation
> mechanism, but rather, merely a mechanism to avoid namespace
> collisions.
>
> However, after the "Private Slots" thread, I spent a sleepless night
> chewing on getting rid of private symbols. I now think we should.
> Going back to my earlier
>
>
> On Wed, Jan 16, 2013 at 12:37 PM, Mark S. Miller<erights at google.com>  wrote:
>> My position on private symbols.
>>
>> My position on classes is and has always been that classes are worth
>> introducing into the language *only* if they give us, or can be used
>> with, an affordable means for true object encapsulation. Assuming
>> Allen is right about what actual implementors will do (which I find
>> plausible) then WeakMaps are not that means.
>
> I still have this position on classes. But I no longer buy that
> pessimistic conclusion about WeakMaps. Consider how WeakMaps would be
> used by the expansion of classes-with-private. Just 'cause it's on the
> top of my head, below I use the old representation of one WeakMap per
> class providing access to a record of all the private state. For the
> same reason, I'll use the encapsulation of the Purse example without
> any of the numeric checks.
>
> class Purse { ... an example w/o and w/ external WeakMap
>
> Thus, no matter what the spec says, normatively or not, about expected
> storage costs, competitive pressures will drive JS engine implementors
> to make this efficient. The way to make this efficient is by the
> technique previously discussed -- hang the private state off of the
> object, not the weakmap. Use the weakmap only as an unforgeable token
> for naming and accessing this state. If we get rid of private symbols,
> we should expect this pattern of usage of WeakMap to have the same
> cost that private symbols would have had. We can help implementors
> achieve that by having this expansion call instead
> "WeakMap(USE_KEY_LIFETIME_HINT)" or whatever it is called. Then
> implementations would not have to recognize the pattern by other
> means.
>
> Complexity is the enemy of security. We already have four
> encapsulation mechanisms in ES6 in addition to private symbols:
> 1) functions encapsulating lexical variables
> 2) WeakMaps
> 3) proxies encapsulating handlers and targets
> 4) modules encapsulating what they don't export.
>
> With enough spec and engineering effort, any of these could be grown
> into a means for providing efficient class/object encapsulation. Of
> them, I think #2 is most plausible. Even is we find #2 does not work
> out, we should think about growing one of the other candidates as an
> alternative to private symbols. Security demands simplicity, and
> semantic simplicity is more important than implementation simplicity.
>

This leads me to the question: Are symbols needed at all (even unique 
ones)? They could be implemented using WeakMap (or any other "external 
encapsulator) as well. The only difference is, they would be known and 
reflectanle.

Thus (including my idea in "Private symbols as WeakMap sugar"), if we 
could write

   obj[prop]

and mean

   [[isExternalEncapsulator]](prop) ? prop.get(obj) : legacy obj[prop]

then WeakMaps will simply have @@isExternalEncapsulator return true.

The reflectability is the only other matter to be solved. In case of 
symbols, API like gOPN and Object.keys() was not touched, and other API 
must have been added to include symbols.

So, thinking about it, if there were no symbols at all but there were 
(more generic) encapsulators, one can simply add APIs to return visible 
encapsulators, the same as it return symbols now (the encapsulators need 
to know if they are reflectable or not, of course).

I think there may be less confusion because encapsulators would clearly 
be different beasts than properties; symbols tried to be as similar as 
possible but even then they need different API.

> --
>      Cheers,
>      --MarkM

Herby

P.S.: Now that I think about it, encapsulators need to be weak, so they 
do not keep an instance living; therefore probably only WeakMaps are 
legible to be one.

So alternative proposal is to allow obj[wm] and to allow wm to set 
itself and reflectable/nonreflectable when used in obj[wm]. Thus, wms 
can replace symbols altogether.

P.P.S.: Or not (reacting to "only WeakMaps are legible"). It can be done 
other way: all the external encapsulator are weak by default (in a 
sense, their pointer to instance is not treated as strong). Probably 
just a crazy thought experiment... but in that way, one need no WeakMap, 
just a Map used as external encapsulator to have weak Map ;-)


More information about the es-discuss mailing list