"for-in", shadowing and deleting properties.

Allen Wirfs-Brock allen at wirfs-brock.com
Thu May 9 11:26:24 PDT 2013

On May 9, 2013, at 9:48 AM, Gareth Smith wrote:

> Hi Allen,
> Allen Wirfs-Brock <allen at wirfs-brock.com> writes:
>> ...
> I may well be mistaken, but I think it is possible to force your
> generator to appear to visit a non-enumerable property. The first way I
> thought of is definitely a bit convoluted:
> --8<---------------cut here---------------start------------->8---
> grandproto_ob = {x:1};
> proto_ob = {y:2, __proto__:grandproto_ob};
> ob = {__proto__:proto_ob};
> for (k in ob) {
>    alert("ob."+k+" has value: "ob[k]);
>    if(k===y) {
>        Object.defineProperty(ob, "x", {value: 3, enumerable: false})
>    }
> }
> // I think you'll see the following alerts:
> // "ob.y has value 2"
> // "ob.x has value 3"
> --8<---------------cut here---------------end--------------->8---
> Assuming that I've read your generator code right, and my example
> interacts with it in the way that I expect: then is this behaviour you
> intended?
> If this behaviour is what you intended, then it seems to mean that my
> property (1) isn't weak enough.

I think what you are doing here falls under the "newly added properties are not guaranteed to be visited" rule.  However, I think this is also one of the situations where it makes a difference on whether "visited" is interpreted to mean returned to the user or processed by this algorithm.  This is a case where "processed" was the intended meaning.

Behind all this was the basic idea that an implementation was not required to keep looking for new properties (or changes of attributes) in objects that have already been processed by the algorithm.  With my generator algorithm and you test case, "x" only gets added to obj after the algorithm has already processed obj and moved on to proto_ob so the algorithm is allowed to ignore that added property and any shadowing effect it might of had. 

> You haven't mentioned guarantees of enumeration as (whether x is
> definitely guaranteed to be printed out in the two examples in my
> original email) as properties that everyone in ES5 agreed upon, so I'm
> going to continue to assume that I should specify those as permissively
> as possible. I'd be very interested to hear if (1) is too strong though!

right, (1) would require that the second predicate clause in line 10 of my generator:
   if (desc && desc.enumerable) yield name;
be augmented with an additional search starting with the original obj for a shadowing non-numerable property with the same name.  This was the sort of processing that some (most?) existing implementations didn't do and we didn't want to require it but neither did we have any agreemnt to forbid it.  So, either result is acceptable.  If you code is dependent upon either specific  result for this case then you're screwed.  Don't do it.

      if (desc && desc.enumerable) yield name;
      if (desc && desc.enumerable) yield name;
      if (desc && desc.enumerable) yield name;

      if (desc && desc.enumerable) yield name;

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130509/044c35c1/attachment.html>

More information about the es-discuss mailing list