Ducks, Rabbits, and Privacy

Kevin Reid kpreid at google.com
Wed Jan 23 14:45:42 PST 2013


On Wed, Jan 23, 2013 at 11:15 AM, Russell Leggett <russell.leggett at gmail.com
> wrote:

> Perhaps I should have included a link:
>>
>> http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/plugin/domado.js?spec=svn5223&r=5223#359
>>
>> The idea is that 'Confidence' introduces a 'class with private fields' as
>> if in Java: each object which has a private state record is considered to
>> be an instance. The private record is used identically to Kevin Smith's
>> examples, but my analogue of getPrivate on a new object fails hard rather
>> than creating one — analogous to a ClassCastException.
>>
>
> I apologize for being lazy, but you provide an example of this being used
> and not just the implementation?
>

All of the examples within Caja are rather hairy, so I'll translate the
above Purse-using-makePrivate example into the style which I would write it
using Confidence. Note that *this is code that runs now, under ES5*; if I
had left in the class syntax that was used in the original then it would
have been identical except for the different choices of names.

If you would like me to discuss an actual example from Caja instead, feel
free to ask.

    var PurseConf = new Confidence('Purse');
    var m = PurseConf.protectMethod;
    var p = PurseConf.p;
    function Purse() {
        PurseConf.confide(this);
        p(this).balance = 0;
    }
    Purse.prototype.getBalance = function() {
        return p(this).balance;
    };
    Purse.prototype.makePurse = function() { return new Purse; };
    Purse.prototype.deposit = m(function(amount, srcPurse) {
        p(srcPurse).balance -= amount;
        p(this).balance += amount;
    });

Note that the deposit method's protectMethod wrapper ensures that it will
not be invoked with a bogus 'this', which would otherwise allow srcPurse to
be drained to nowhere by crashing on the second line; this is not actually
useful here since purses may be unreferenced, but in other cases such a
precondition may be important.

Note that when both protectMethod and p are used, there is a redundant
WeakMap lookup. An alternate design would be for the protectMethod wrapper
to pass an additional argument to the wrapped function which is the
private-state record. This could be considered to have the advantage of
encouraging defining explicit operators on the private state (wrapped
functions) rather than just 'pulling it out of the object'.

I am not arguing that something like this is the right abstraction for
private state in ES6; only, given that the idea has arisen independently, I
note that we have some prior experience with it, and it has turned out
mostly all right. However, ignoring efficiency of implementation on current
ES5, I would myself rather see a mechanism which did not have any
private-state-record object, but rather had a separate 'symbol' object
identifying each 'private property'; this has the advantage of ensuring the
smallest 'scope' of the access to private state. For example, when a
'class' has private state and it has a 'subclass' which has additional
private state, the private-state-record pattern encourages the subclass to
use the same record (if it is defined in the same place and so has access)
which, besides increasing the chance of name collisions, also means that
the subtype's methods do not automatically fail when applied to instances
of the supertype and so may have unintended consequences.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130123/ebf0d767/attachment.html>


More information about the es-discuss mailing list