Proposal: Reflecting on non-string property names

Tom Van Cutsem at
Sun Dec 2 11:16:09 PST 2012

2012/12/2 Allen Wirfs-Brock <allen at>

> I still think making [[OwnPropertyKeys]] produce an iterator makes sense.
>  But it probably means we have to change how we think about the its
> invariants as we can't necessarily check all of the values such an iterator
> may yield before returning it from the Proxy implementation of
> [[OwnPropertyKeys]].  We can however have that [[OwnPropertyKeys]] wrap the
> iterator returned by the ownKeys trap with another iterator that does an
> invariant check of the individual values returned by the trap provided
> iterator.

Indeed. I had previously thought of a similar iterator-wrapping strategy
for protecting the enumerate() trap.

> The first issue, with that approach, is whether such delayed invariant
> checking is acceptable. For example, returning a key that doesn't exist in
> a frozen target would throw on the call that would return
> that key rather than when calling Object.getOwnPropertyKeys.  (However,
> Object.getOwnProperyNames/keys would still appear to throw immediately,
> because they drain the iterator).  This delayed checking seems ok to me,
> but you probably need to think about it from the perspective of membranes
> and similar Proxy use cases.

I also think delayed checks are fine.

One difference with a deferred invariant check is that is to obtain a own
> property keys iterator before a Proxy object/target is frozen but not check
> its values until after it is frozen.  In this case, the keys produced by
> the iterator would not necessarily meet the target own property invariants
> of a frozen object.  However, I don't see that is significantly different
> from the current array valued calls which also can produce key values that
> may no longer be valid after the objet is frozen.

Indeed, but I agree with your statement below that probably the result of
ownKeys only makes sense if one determined that the proxy was frozen before
starting the enumeration.

> Deferred checking can easily enforce that a "new property key" isn't
> return returned (from the iterator) for a frozen object. It can also
> determine that all own property keys are returned for a frozen object
> (immediately before throwing IterationComplete check if the number of keys
> already yielded equals the number of own properties of the target, if not
> throw to indicate the invariant violation).
> What isn't so easily do is make sure that for non-frozen objects all
> non-configurable property keys are returned. To do this would probably
> require accumulating every yielded key and then checking that list against
> the actual target properties immediately before StopIteration.


> This makes be think that this final invariant perhaps isn't so important,
> even for the present non-iterator based definition of getOwnPropetyNames.
> Basically for non-frozen/sealed objects any point in time list of property
> keys may become stale before it is used. It may include keys that are no
> longer used and may miss keys that are now used.  Any inclusion decisions
> based upon the configurability of individual properties may no longer be
> valid.
> We've talked before about the need of a reliable property list for "deep
> freezing" objects.  In seems for situations like that you would want to
> separately determine if the object is sealed/frozen before calling
> Reflect.ownKeys.  If it is frozen/sealed, you can depend upon the results.
>  If not, that final invariant (and probably the others) doesn't really
> guarantee much.

Right. Enumeration has weird invariants because of the complex state-space
of JS object invariants. For frozen objects, the invariants become
relatively easy to check (as you say: check if each enumerated key is an
own property of target, and count whether the total number of generated
keys equals the total amount of own properties of the target). For
non-frozen objects, things are more complicated.

Are you suggesting that we only enforce invariants if the proxy/target are
really frozen at the start of enumeration, and give up on invariants in all
other cases? I think this would be sufficient for most practical use cases,
but it would be the first time that we visibly treat "frozen" objects
specially (all other invariants are expressed only in terms of
non-extensibility or non-configurability of individual properties)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list