Re: private name objects confusion
> Yep. Sorry, editing snafu -- I'd started to call it a non-issue when it > occurred to me that proxy authors would still have to know not to string > coerce keys. No big deal -- proxy authors should know better than to rely on > es5 invariants. Agreed. > Throw at the point where a unique name from a getOPN array is coerced to a > string. AFAICT this will always indicate a logic bug. One way to enforce this > would be to have getOPN (and enumerate?) hand out public objects with special > toStrings that throw. Meh. That's why I said there's "sane" way :) Yikes. :) > > Another alternative for unique-but-public names is simply to have a unique > string generator. It trivially maintains the invariants of getOPN and > for...in while still having the same user experience for getting and setting. > The downsides are that the string will probably be ugly and unpleasant for > debugging, and that there's no efficient way to ensure that the string > generated won't be one that's *never* been observed by the program so far. > You'd probably have to use UUIDs, which are ugly. > > Yes, this is precisely what I meant when I said a unique string could be > used. But again, I wonder if worth it. If a producer of unique name objects > can provide the internal string it's trivial to generate UUIDs (or any other > type of unique string) should they so choose. Right, this is already something you can express in the language. I sense YAGNI. > But from a spec standpoint is it a good idea to actively encourage the > toStringing of getOPN keys? What I meant was that we could not provide the visibility flag -- i.e., not have a notion of "unique names" at all -- but simply provide a makeUUID() function that produces a string which can be used directly as a property name. > A bigger problem: what happens when you have two unique name objects where > both have a "foo" internal string and you toString the result of getOPN? Bad > things, right? Right. This issue is why I suggested using UUID strings instead. It wouldn't be possible to have two properties with different unique names that produce the same UUID result of toString(). > Another alternative would be to explicitly disallow custom internal strings > for unique name objects, and give them a consistent toString behavior (e.g. > always generate unique strings). But this smells too, partly for the reasons > you pointed out, and also because the semantics of the two name types start > to diverge. Agreed. > So I wonder: what does this particular reflection buy you that you can't just > as easily attain by explicitly exposing your "visible" private name objects? The only thing is that you can't introspect on them conveniently. If you have access to a private name, it'd be nice to have a simple way of saying "give me all of the names, including the private names I know about." But I don't see a simple way of doing that other than something like a variant of getOPN: Object.getOwnPropertyNames(o, p) : function(Object, WeakMap?) -> [string | name] This version would produce an array of all property names including any private names that are in the given table. (This is technically a conservative extension of the existing ES5 getOPN but it could alternatively be provided as a different function.) Again, this would be implementable without providing it as a core API, so I'm not sure if it's worth it. Standardizing on this use of a map seems like it might be premature; you might want any number of different ways of representing "these are the private names I know about." Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: private name objects confusion
On Wed, Jul 27, 2011 at 7:21 PM, David Herman wrote: > > Understood WRT the forgeability of strings -- I was more concerned with > the potential hazard of toStringing the values of an own-names array, only > to find out you have several keys with the string value "undefined". Sure > you're doing it wrong, but string keys are an es5 invariant -- it's bound to > happen, as you hinted at in your reply. > > Yeah, this has come up several times in discussions. It's currently an > invariant that for...in and getOPN produce a sequence of strings with no > duplicates (though not in fully specified order), and exposing name objects > to these operations would break that invariant. > > > But now that you've clarified the reflection semantics it's clear that > this is not much of an non-issue for non-reflective "private" names, > > ITYM "not much of an issue", right? > Yep. Sorry, editing snafu -- I'd started to call it a non-issue when it occurred to me that proxy authors would still have to know not to string coerce keys. No big deal -- proxy authors should know better than to rely on es5 invariants. > > > just another note for proxy authors. Of course, if the visibility flag > becomes harmonious (and I really hope it does!) it's still a bit of a > problem for these "unique" names. There's no need for unforgeability here so > a unique string could be used, but it's probably too much magical and too > little help -- if unintentionally used (the result of an own-names string > coercion) it papers over a deeper semantic bug. Better would be to throw, > but there's no sane way to do that. > > Throw where, exactly? I don't quite follow you. > Throw at the point where a unique name from a getOPN array is coerced to a string. AFAICT this will always indicate a logic bug. One way to enforce this would be to have getOPN (and enumerate?) hand out public objects with special toStrings that throw. Meh. That's why I said there's "sane" way :) Another alternative for unique-but-public names is simply to have a unique > string generator. It trivially maintains the invariants of getOPN and > for...in while still having the same user experience for getting and > setting. The downsides are that the string will probably be ugly and > unpleasant for debugging, and that there's no efficient way to ensure that > the string generated won't be one that's *never* been observed by the > program so far. You'd probably have to use UUIDs, which are ugly. > Yes, this is precisely what I meant when I said a unique string could be used. But again, I wonder if worth it. If a producer of unique name objects can provide the internal string it's trivial to generate UUIDs (or any other type of unique string) should they so choose. But from a spec standpoint is it a good idea to actively encourage the toStringing of getOPN keys? A bigger problem: what happens when you have two unique name objects where both have a "foo" internal string and you toString the result of getOPN? Bad things, right? Another alternative would be to explicitly disallow custom internal strings for unique name objects, and give them a consistent toString behavior (e.g. always generate unique strings). But this smells too, partly for the reasons you pointed out, and also because the semantics of the two name types start to diverge. So I wonder: what does this particular reflection buy you that you can't just as easily attain by explicitly exposing your "visible" private name objects? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: private name objects confusion
> Understood WRT the forgeability of strings -- I was more concerned with the > potential hazard of toStringing the values of an own-names array, only to > find out you have several keys with the string value "undefined". Sure you're > doing it wrong, but string keys are an es5 invariant -- it's bound to happen, > as you hinted at in your reply. Yeah, this has come up several times in discussions. It's currently an invariant that for...in and getOPN produce a sequence of strings with no duplicates (though not in fully specified order), and exposing name objects to these operations would break that invariant. > But now that you've clarified the reflection semantics it's clear that this > is not much of an non-issue for non-reflective "private" names, ITYM "not much of an issue", right? > just another note for proxy authors. Of course, if the visibility flag > becomes harmonious (and I really hope it does!) it's still a bit of a problem > for these "unique" names. There's no need for unforgeability here so a unique > string could be used, but it's probably too much magical and too little help > -- if unintentionally used (the result of an own-names string coercion) it > papers over a deeper semantic bug. Better would be to throw, but there's no > sane way to do that. Throw where, exactly? I don't quite follow you. Another alternative for unique-but-public names is simply to have a unique string generator. It trivially maintains the invariants of getOPN and for...in while still having the same user experience for getting and setting. The downsides are that the string will probably be ugly and unpleasant for debugging, and that there's no efficient way to ensure that the string generated won't be one that's *never* been observed by the program so far. You'd probably have to use UUIDs, which are ugly. > Ah well, this is great stuff. Thanks again, Dave... Glad to hear it! Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: private name objects confusion
On Wed, Jul 27, 2011 at 5:02 PM, David Herman wrote: > > I've been exploring private name objects [1] and I'm a bit confused by a > few things in the proposal, especially the Reflection example... > > The page was out of date, sorry. I've updated the page to reflect the > agreement we came to in the last face-to-face, which was that private names > should not be reflected anywhere except to proxy traps. This leaks less > information than what was on the wiki. In particular, now you can't figure > out how many private names an object is carrying around. > Perfect! This is exactly what I was hoping for. [snip] I've separated this out on the wiki page as a remaining open issue. I'm not > sure if we've come to consensus about this case. (One concern was that > Object.getOwnPropertyNames() and for...in no longer are guaranteed to > produce strings, although this is mitigated by the toString() coercion of > the name objects.) > > > I also see no mention of what `str` should default to in Name.create, > even though it's defined as optional and is quite significant as the > name.public.toString return value. Is there something like a unique string > value planned for this? At the very least the proposal should hint at what > Name.create().public.toString() should return (assuming it's not undefined). > > This hasn't been settled yet. IMO, I don't think it needs to be guaranteed > to be unique. The uniqueness guarantee is about the *identity* of the > object, and strings are forgeable, even if they're unique at the time they > are created. > Understood WRT the forgeability of strings -- I was more concerned with the potential hazard of toStringing the values of an own-names array, only to find out you have several keys with the string value "undefined". Sure you're doing it wrong, but string keys are an es5 invariant -- it's bound to happen, as you hinted at in your reply. But now that you've clarified the reflection semantics it's clear that this is not much of an non-issue for non-reflective "private" names, just another note for proxy authors. Of course, if the visibility flag becomes harmonious (and I really hope it does!) it's still a bit of a problem for these "unique" names. There's no need for unforgeability here so a unique string could be used, but it's probably too much magical and too little help -- if unintentionally used (the result of an own-names string coercion) it papers over a deeper semantic bug. Better would be to throw, but there's no sane way to do that. Ah well, this is great stuff. Thanks again, Dave... Dean ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: private name objects confusion
> I've been exploring private name objects [1] and I'm a bit confused by a few > things in the proposal, especially the Reflection example... The page was out of date, sorry. I've updated the page to reflect the agreement we came to in the last face-to-face, which was that private names should not be reflected anywhere except to proxy traps. This leaks less information than what was on the wiki. In particular, now you can't figure out how many private names an object is carrying around. > Should this statement return ["foo", fooName.public] or ["foo", fooName]? If > the latter interpretation is correct, what advantage does a visible private > name have over a plain old non-enumerable property? Guaranteed uniqueness. For example, multiple separately developed libraries can monkey-patch the same shared prototype object with new unique names and they're guaranteed not to conflict. I've separated this out on the wiki page as a remaining open issue. I'm not sure if we've come to consensus about this case. (One concern was that Object.getOwnPropertyNames() and for...in no longer are guaranteed to produce strings, although this is mitigated by the toString() coercion of the name objects.) > I also see no mention of what `str` should default to in Name.create, even > though it's defined as optional and is quite significant as the > name.public.toString return value. Is there something like a unique string > value planned for this? At the very least the proposal should hint at what > Name.create().public.toString() should return (assuming it's not undefined). This hasn't been settled yet. IMO, I don't think it needs to be guaranteed to be unique. The uniqueness guarantee is about the *identity* of the object, and strings are forgeable, even if they're unique at the time they are created. > My apologies if some of this has been discussed Not at all; thanks for the feedback. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
private name objects confusion
I've been exploring private name objects [1] and I'm a bit confused by a few things in the proposal, especially the Reflection example... module Name = require "@name"; let o = { }; let name = Name.create("foo"); o[name] = "secret!"; ...let a = Object.getOwnPropertyNames(o);for (let i = 0; i < a.length; i++) { if (a[i] === name.public) ... else ...} The proposal defaults Name.create's visibility to false, so my first assumption was it's not supposed to show up at all in Object.getOwnPropertyNames(o) and it was just an oversight. But after rereading it a few times this line keeps throwing me (emphasis added): The visible argument determines whether the name is made *directly* visible to reflection API‘s. Another possible interpretation is that if the name is set to visible then getOwnPropertyNames would contain the name object, otherwise it would contain name.public. Another way to ask this, modifying the example slightly: module Name = require "@name"; let o = { foo: "public!" }; let fooName = Name.create("foo"); o[fooName] = "secret!"; Object.getOwnPropertyNames(o); Should this statement return ["foo"] or ["foo", fooName.public]? And if visibility were true: module Name = require "@name"; let o = { foo: "public!" }; let name = Name.create("foo", true); o[name] = "secret!"; Object.getOwnPropertyNames(o); Should this statement return ["foo", fooName.public] or ["foo", fooName]? If the latter interpretation is correct, what advantage does a visible private name have over a plain old non-enumerable property? I also see no mention of what `str` should default to in Name.create, even though it's defined as optional and is quite significant as the name.public.toString return value. Is there something like a unique string value planned for this? At the very least the proposal should hint at what Name.create().public.toString() should return (assuming it's not undefined). My apologies if some of this has been discussed -- the last I can find was in the TC39 meeting notes from May: Advanced to Harmony, with the big open issue of reflecting on private names. > [1] 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