Security Demands Simplicity (was: Private Slots)

Axel Rauschmayer axel at
Thu Jan 17 09:43:27 PST 2013

Right. That could work in favor of this approach.

On Jan 17, 2013, at 18:35 , Brandon Benvie <brandon at> wrote:

> Well keep in mind that Symbols of any type already require using a new function, getOwnKeys (or whatever the name is) so they are already essentially "super non-enumerable". They are reflectable if someone really wants to see them, but they are never reflected in Object.keys, Object.getOwnPropertyNames, or enumeration.
> On Thu, Jan 17, 2013 at 12:32 PM, Axel Rauschmayer <axel at> wrote:
> Can we separate of concerns?
> 1. I love symbols.
> 2. I also love the idea that you can mark properties as private, as invisible to the outside. Currently I prefix my properties with `_` to do so, but it’s an ugly namespace pollution.
> 3. But, for me and probably most applications, the privacy does not have to be bullet proof. For the rare cases where we need. bullet-proofing, weak maps might be enough.
> 4. Enumerability still seems like something that only exists because for for-in. Unfortunately, it can’t take up role #2, because so many things are already non-enumerable that are clearly public.
> Does that mean that the current ES6 model could be simplified? For example: another property attribute `visible`, making properties invisible. Not sure where the invisibility matters: at an IDE level, when you do an expansion (e.g. type `myobj.`). Or should it also be hidden from all current iteration operations (Object.getOwnPropertyNames() etc.)? In either case, there would still be a way of iterating over all properties, making copying etc. straightforward.
> On Jan 17, 2013, at 18:00 , "Mark S. Miller" <erights at> wrote:
>> First, I agree with David that security is important, both for
>> security per se and for modularity in general. ES5 improved the
>> language when it fixed the accidental leaks between the world of
>> objects and scope-chain objects, like thrown functions. ES5/strict
>> improved the language when it made functions really encapsulated,
>> poisoned caller and arguments, and repaired the remaining violations
>> of static scoping. ES6 modules and CommonJS/Node modules were born and
>> remain encapsulated. I have not heard anyone suggesting any of these
>> would be improved by introducing pliers for opening them against their
>> will (except in a debugger, which is a different issue). Tons of code
>> have been written in ES3. We still made the world a better place when
>> we plugged its leaks.
>> I also agree with David that unique symbols are not an encapsulation
>> mechanism, but rather, merely a mechanism to avoid namespace
>> collisions.
>> As for Java's reflective breakage of "private",
>> <>.
>> 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> 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 {
>>    constructor(private balance) {
>>    getBalance() { return balance; }
>>    makePurse() { return Purse(0); }
>>    deposit(amount, srcPurse) {
>>        private(srcPurse).balance -= amount;
>>        balance += amount;
>>    }
>> }
>> expansion
>> let Purse = (function() {
>>    let amp = WeakMap();
>>    function Purse(balance) {
>>        amp.set(this, Object.seal({
>>            get balance() { return balance; },
>>            set balance(newBalance) { balance = newBalance; }
>>        }));
>>    }
>>    Purse.prototype = {
>>        getBalance: function() { return balance; },
>>        makePurse: function() { return Purse(0); },
>>        deposit: function(amount, srcPurse) {
>>            amp.get(srcPurse).balance -= amount;
>>        }
>>    }
>>    return Purse;
>> })();
>> Ignore the issues about whether we should use one WeakMap per class
>> and a private record as above, or a WeakMap per private field name
>> declaration.
>> Ignore the use of accessors so that private field names track
>> variables. If we had instead stored the state in the private field and
>> compiled getBalance to use the field, that doesn't affect the
>> important issue.
>> **********************
>> Notice that the lifetime of amp cannot be shorter than the lifetimes
>> of the Point instances, since the instances retain amp, and these
>> instances are the only objects ever stored as keys in amp.
>> **********************
>> For this usage common pattern, the lifetime of the keys of amp cannot
>> outlive the lifetime of amp.
>> 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.
>> --
>>    Cheers,
>>    --MarkM
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at
> -- 
> Dr. Axel Rauschmayer
> axel at
> home:
> twitter:
> blog:

Dr. Axel Rauschmayer
axel at


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list