"for-in", shadowing and deleting properties.

Gareth Smith gds at doc.ic.ac.uk
Thu May 9 09:48:08 PDT 2013


Hi Allen,

Allen Wirfs-Brock <allen at wirfs-brock.com> writes:
> My re-reading of of the ES5 language reconfirms that the distinct use
> of property and property name is very deliberate.  Let me know if any
> particular phrases seem ambiguous to you.

Ah excellent - thank you.

> Where I think the language is somewhat sloppy is in making a
> distinction being the examination of a property by the algorithm and
> exposing the name of a property to user code.  "Visiting" might mean
> either of these depending upon the surrounding context.

Ah - I think I may have been assuming that "visiting" meant exposing the
name of a property to user code.

> One requirement that we agreed upon in the ES5 days was that a
> particular for-in loop should process any property name at most
> once. This was agreed upon even though we knew that some existing
> implementations violated that requirement in some scenarios.  The
> language "A property name must not be visited more than once in any
> enumeration." was added as the statement of that requirement.  the use
> of "property name" was very deliberate in that context.

Excellent - the formalism I'm currently working on does guarantee this
property.

> We also agreed that if a non-enumerable property of a particular name
> is encountered, then that name will not be "visited" even if it is
> encountered for an enumerable property higher on the prototype
> change.

The formalism I'm currently working on seeks to guarantee the following
interpretation of this requirement, which I will give a number so I can
refer to it later.

(1) For some for-loop "for k in stmt", at the point which you enter a
particular iteration of your loop, the property stmt[k] will be
enumerable.

You are of course free to use Object.defineProperty to make it
non-enumerable as soon as you enter the loop body, so it cannot be
guaranteed to be enumerable at any other point in the loop body.

> My interpretation of that requirement is that it even extends
> to the case where the non-enumerable property is subsequently deleted
> and then a enumerable property of the same name is added to a
> prototype that has not yet been examined.

Then the formalism I'm working on seems to be strictly more permissive
than the one you're thinking of... Modulo my next question...

> Once a name has been
> determined to be non-enumerable, that determination can not change
> during an enumeration.

Once a name has been determined to be enumerable, can that determination
change to being non-enumerable? I think this ability seems to be a
necessary in order to guarantee property (1) above.

> I've created an ES6 generator that I believe conforms to the intent of the ES5 spec: https://gist.github.com/allenwb/5548164 
> It is also permitted (not not required) to use an algorithm that was
> more aggressive about finding and yielding new property names that are
> added during the lifetime of the generator.

Thanks!

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.


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!

Thanks,

Gareth.



More information about the es-discuss mailing list