Subj : Re: Confused about enumerating To : netscape.public.mozilla.jseng From : Brian Genisio Date : Thu Feb 19 2004 07:43 am Brendan Eich wrote: > > That difference does not account for what is going on. Are you defining > the length property on the prototype (via JS_InitClass)? If so, the > for..in code will not find it if there is a length property in the > original object (the one being enumerated). The for..in code suppresses > ids of shadowed properties in prototypes. If the original object's > length property names an empty string value, that might explain what you > are seeing -- but you have to show a test case and its input and output. > > Code excerpts from your embedding might be helpful too. > > /be Sure :) ( I really appreciate the help ) Here is the test code in Javascript. getCollection() will simply return a collection object, much like an array, but it enumerates differently: ///////////////////////////////// var myColl = getCollection(); for(name in myColl) alert (name); ///////////////////////////////// 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. In my embedded code, I initialize the object like this (cut and pasted from many places): ////////////////////////////////////////////////////////////////////// // Define the properties for the collection JSPropertySpec m_properties[] = { {"length", JS_COLLECTION_LENGTH_PROP, JSPROP_ENUMERATE }, { 0 } }; // Init the class with the other specifications JS_InitClass(glob_cx, glob_obj, parent_obj, m_classSpec, Constructor, 2, m_properties, m_methods, NULL, NULL); /////////////////////////////////////////////////////////////////////// Then, in my enumeration code, my state variable is an int, representing the current index of the collection to be enumerated. I initialize it to -1, so if I get -1, I give the length, and increment the value to 0. If I get between 0 and the length-1 of the collection, I return the given object's id if it exists, or the current index. Here is my code for the JSENUMERATE_NEXT request: ///////////////////////////////////////////////////////////////////////// // In the next state, we look at the current state, return the idp, and // update the state. privColl is the private data in the object case JSENUMERATE_NEXT: // Get the current state current_index = (unsigned long*)JSVAL_TO_PRIVATE(*statep); // In the case of -1, we will send the length if(*current_index == (unsigned long)(-1)) { // For some reason, "length" does not work here. JS_ValueToId(cx, STRING_TO_JSVAL(JS_InternString(cx, "length")), idp); // After this, start enumerating the actual values *current_index = 0; *statep = PRIVATE_TO_JSVAL(current_index); } // if the state is a value within range of the collection, // return the indexed ID else if(*current_index < privColl->length() && *current_index >= 0) { // Storage for the name of the property const char* name; // Get the item Item *tmpItem = privColl->item(*current_index); // If an ID exists, set the name to the ID. If not, set it to // the current index if(!tmpItem->id().empty()) name = tmpItem->id().c_str(); else name = itoa(*current_index, tmp_str, 10); // Translate the name to a JS ID value JS_ValueToId(cx, STRING_TO_JSVAL(JS_InternString(cx, name)), idp); // Update the current state *current_index = *current_index + 1; *statep = PRIVATE_TO_JSVAL(current_index); } // If we get here, then we have exhausted the enumeration. // Delete the state, and tell the JS engine we are done with JSVAL_NULL else { delete current_index; *statep = JSVAL_NULL; } break; /////////////////////////////////////////////////////// Thanks, Brian .