Hi, I couldn't post on es-discuss yesterday, so I rewrote my message and posted it on github [1]. Here is the markdown source:
# PART 1: The same feature? When looked abstractly, both private name and weak maps propose an equivalent feature: a mapping between 2 unforgeable references and a value. Both allow to share a secret with someone assuming the knowledge of 2 unforgeable entities. Both have the interesting property of symmetric non-discoverability: * Given an object, you can't list all private names * Given a private name, you can't list all objects which have this name as a property * Given a weak map, you can't list all objects used as keys * Given an object, you can't list all weak maps using this object as key This can be used in WeakMaps to optimize garbage collection. As it turns out, the same thing stands for private names: If nothing holds a reference to a private name, all related slots in objects can be garbage-collected as well. There are a couple of differences: * A private property can be made non-configurable & non-writable * A private name can refer to an accessor property I claim that these can be reimplemented by overriding the WeakMap API. I'm open to discussion on whether there are cases that can be implemented with one API and not the other. For the rest of this message, I'll assume that it's the same feature with 2 different syntax. # PART 2: A more generic syntax Unfortunately, private names and WeakMaps (and maps and sets...) both define a special new sort of object to work. What about an API that would allow to associate any 2 objects and bind a "secret" value to the association? `````JavaScript // In one part of the code var o1 = {}, o2 = {}; var a = Assoc(o1, o2); a.set(37); // ... // In another component which has a reference to both o1 and o2 var myA = Assoc(o1, o2); myA.get(); // 37 ````` In order to unseal a secret associated with 2 objects, you need a reference to both, that's it. Exactly like with WeakMaps, exactly like with private names. ## Part 2.1: where I pretend I can reimplement WeakMaps with the Assoc API `````JavaScript WeakMap = function(){ var weakMapIdentity = {}; var presence = {}; return { get: function(o){ return Assoc(weakMapIdentity, o).get(); }, set: function(o, val){ Assoc(presence, o).set(true); return Assoc(weakMapIdentity, o).set(val); }, has: function(o){ return !!Assoc(presence, o).get(); }, delete = function(o){ Assoc(presence, o).set(undefined); } } } ````` Interestingly, 2 identities are required to emulate weakmaps. One for the values (weakMapIdentity) and one to consider presence of keys. In my opinion, the WeakMap API should be separated into 2 APIs. One with get/set and the other with add/remove/has which would find the natural name of WeakSet. ## Part 2.2: where I go further and get a bit crazy Some properties: * Assoc() === Assoc // why waste a reference? :-p * Assoc(o) !== o * Assoc(o) === Assoc(o) * Assoc(Assoc(o)) === Assoc(o) * Assoc(o, o) === Assoc(o) * Assoc(o1, o2) === Assoc(o2, o1) The Assoc API could be extended with any number of arguments. The resulting object represents the association of all objects passed as arguments. * Assoc(o1, o2, o3) === Assoc(Assoc(o1, o2), o3) === Assoc(o1, Assoc(o2, o3)) * ...and these applies to any number of arguments. Long story short, the Assoc function only cares about whether or not you pass it the right references to unseal the secret. And you should not care about passing the objects in the "right order". If I want to keep a secret from you, I'll create an unforgeable reference; I won't try to "obscure" it by not telling you the order in which you should pass the objects to Assoc Of course, since there is no discoverability of associations, all good garbage collection optimizations are kept. With association objects, I think we can have a uniform base to play with objects without having to invent new sorts of objects (WeakMaps, Sets, Maps, etc.) while keeping the possibility to implement (hopefully as efficiently) these abstractions. I've had some comments from Erik Corry on Twitter. [2] "Can you add a private property to a frozen object?" => This is not discussed in the proposal [4]. I would guess not. It may be a difference indeed between WeakMaps and private names, but I think it'd be possible to enhance the WeakMap API to allow either that a weakmap stops accepting keys or that an object is banned from all weakmaps (which are 2 different view of non-extensibility) I forgot to say that the Assoc API was a first shot and of course some additional primitives may be handy. This is what I'd like to explore. [3] "For private names you can make a polyfill based on ES5 non-enumerability and random strings. Can u do that with Assoc?" => The polyfill would be only partial, because properties would appear anyway with Object.getOwnPropertyNames which defeats the purpose of private names. Moreover, there would always be a risk of collision (which can't happen with private names thanks to the unforgeability property). Private names have been added because they add something that lack to the language. The Assoc API would do the same and any polyfill could only be partial (same goes for WeakMaps) David [1] https://gist.github.com/1483744 [2] https://twitter.com/#!/erikcorry/status/147589242246275073 [3] https://twitter.com/#!/erikcorry/status/147588955611729920 [4] http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss