Subj : Re: Confused about enumerating To : Brian Genisio From : Brendan Eich Date : Fri Feb 20 2004 10:53 pm Brian Genisio wrote: > I am creating an enumeration JSID based off of the Ids of the objects > in the collection. For a collection with two elements, I expect the > following to be printed, using my alert method: > > ALERT: length > ALERT: value1ID > ALERT: value2ID > > Instead, I see the following: > > ALERT: value1ID > ALERT: value2ID > > If I change my embedded code to give "Length", instead of "length", I > get the following: > > ALERT: Length > ALERT: value1ID > ALERT: value2ID > > If I keep the value to "length", but get rid of "length" as a defined > property of the object, it comes out the way I expect it. This is for the reason I said earlier: the code for for..in loops in jsinterp.c will suppress duplicate property id enumeration in the following sort of case: var p = {q: 0, r: 1}, o = {__proto__: p, q: 2, r: 3}; for (var i in o) print(i, o[i]); This script should print q 2 r 3 The jsinterp.c code will find q twice, once when enumerating o, and later when enumerating its prototype object p. In the latter case, it will suppress the enumeration of 'q' as the value of i because it looks up 'q' in o, the original object, and finds it first in o, which is not the same object as the one currently being enumerated, namely p. In your case, you haven't actually defined a property 'length' in the original object, so the lookup finds 'length' in the prototype, notices that that object is not the same as the one currently being enumerated, and suppresses the "duplicate". The moral is: don't lie in your enumerate implementation: return only ids that you will show as being in the object in question, via resolve if lazy (if reflecting properties only on demand), or getProperty if eager (if the property of that id in the class's object is being defined up front). In short, it seems your resolve hook is not consistent with your enumerate hook. You are enumerating 'length', but you are not resolving 'length'. That's always a bug. Second bug: you shouldn't allocate and free (via new and delete) a word of storage for an unsigned long. Just store an int-tagged jsval directly in *statep, using JSVAL_TO_INT and INT_TO_JSVAL. I doubt you'll overflow 2^30 - 1. What you are doing now with JSVAL_TO_PRIVATE and PRIVATE_TO_JSVAL is wrong. See the definitions of those macros in jsapi.h -- they are for decoding and encoding a pointer aligned on a (0 mod 2) or looser boundary as a jsval. PRIVATE_TO_JSVAL will turn an even unsigned long value into the next higher odd number, and JSVAL_TO_PRIVATE will turn an odd number into its lower even neighbor. /be .