diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 000cd72d57a9..729ecac85672 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1528,10 +1528,8 @@ NewIdArray(JSContext *cx, jsint length) ida = (JSIdArray *) cx->calloc(offsetof(JSIdArray, vector) + length * sizeof(jsval)); - if (ida) { - ida->self = ida; + if (ida) ida->length = length; - } return ida; } @@ -1545,7 +1543,6 @@ SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length) { JSIdArray *rida; - JS_ASSERT(ida->self == ida); rida = (JSIdArray *) JS_realloc(cx, ida, offsetof(JSIdArray, vector) + length * sizeof(jsval)); @@ -2664,7 +2661,7 @@ JS_SetScriptStackQuota(JSContext *cx, size_t quota) JS_PUBLIC_API(void) JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) { - cx->free(ida->self); + cx->free(ida); } JS_PUBLIC_API(JSBool) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index bda477679777..1886368953ae 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1603,7 +1603,6 @@ struct JSExtendedClass { #define JSCLASS_NO_RESERVED_MEMBERS 0,0,0 struct JSIdArray { - void *self; jsint length; jsid vector[1]; /* actually, length jsid words */ }; diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 6fbb772b40ca..b2e897fd7554 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -252,85 +252,83 @@ NativeIterator::allocate(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarr return ni; } -static NativeIterator * -Snapshot(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, uint32 slength, uint32 key) +static bool +Snapshot(JSContext *cx, JSObject *obj, uintN flags, AutoValueVector &props) { HashSet ht(cx); if (!(flags & JSITER_OWNONLY) && !ht.init(32)) - return NULL; - - AutoValueVector props(cx); + return false; JSObject *pobj = obj; - while (pobj) { + do { JSClass *clasp = pobj->getClass(); if (pobj->isNative() && pobj->map->ops->enumerate == js_Enumerate && !(clasp->flags & JSCLASS_NEW_ENUMERATE)) { if (!clasp->enumerate(cx, pobj)) - return NULL; + return false; if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props)) - return NULL; + return false; } else if (pobj->isDenseArray()) { if (!EnumerateDenseArrayProperties(cx, obj, pobj, flags, ht, props)) - return NULL; + return false; } else { if (pobj->isProxy()) { JSIdArray *ida; if (flags & JSITER_OWNONLY) { if (!JSProxy::enumerateOwn(cx, pobj, &ida)) - return NULL; + return false; } else { if (!JSProxy::enumerate(cx, pobj, &ida)) - return NULL; + return false; } AutoIdArray idar(cx, ida); for (size_t n = 0; n < size_t(ida->length); ++n) { if (!Enumerate(cx, obj, pobj, ida->vector[n], true, flags, ht, props)) - return NULL; + return false; } /* Proxy objects enumerate the prototype on their own, so we are done here. */ break; } jsval state; if (!pobj->enumerate(cx, JSENUMERATE_INIT, &state, NULL)) - return NULL; + return false; if (state == JSVAL_NATIVE_ENUMERATE_COOKIE) { if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props)) - return NULL; + return false; } else { while (true) { jsid id; if (!pobj->enumerate(cx, JSENUMERATE_NEXT, &state, &id)) - return NULL; + return false; if (state == JSVAL_NULL) break; if (!Enumerate(cx, obj, pobj, id, true, flags, ht, props)) - return NULL; + return false; } } } if (JS_UNLIKELY(pobj->isXML() || (flags & JSITER_OWNONLY))) break; + } while ((pobj = pobj->getProto()) != NULL); - pobj = pobj->getProto(); - } - - return NativeIterator::allocate(cx, obj, flags, sarray, slength, key, props.begin(), props.length()); + return true; } bool -NativeIteratorToJSIdArray(JSContext *cx, NativeIterator *ni, JSIdArray **idap) +VectorToIdArray(JSContext *cx, AutoValueVector &props, JSIdArray **idap) { - /* Morph the NativeIterator into a JSIdArray. The caller will deallocate it. */ - JS_ASSERT(sizeof(NativeIterator) > sizeof(JSIdArray)); - JS_ASSERT(ni->props_array == (jsid *) (ni + 1)); - size_t length = size_t(ni->props_end - ni->props_array); - JSIdArray *ida = (JSIdArray *) (uintptr_t(ni->props_array) - (sizeof(JSIdArray) - sizeof(jsid))); - ida->self = ni; - ida->length = length; - JS_ASSERT(&ida->vector[0] == &ni->props_array[0]); + JS_STATIC_ASSERT(sizeof(JSIdArray) > sizeof(jsid)); + size_t len = props.length(); + size_t idsz = len * sizeof(jsid); + size_t sz = (sizeof(JSIdArray) - sizeof(jsid)) + idsz; + JSIdArray *ida = static_cast(cx->malloc(sz)); + if (!ida) + return false; + + ida->length = static_cast(len); + memcpy(ida->vector, props.begin(), idsz); *idap = ida; return true; } @@ -338,10 +336,9 @@ NativeIteratorToJSIdArray(JSContext *cx, NativeIterator *ni, JSIdArray **idap) bool GetPropertyNames(JSContext *cx, JSObject *obj, uintN flags, JSIdArray **idap) { - NativeIterator *ni = Snapshot(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), NULL, 0, true); - if (!ni) - return false; - return NativeIteratorToJSIdArray(cx, ni, idap); + AutoValueVector props(cx); + return Snapshot(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), props) && + VectorToIdArray(cx, props, idap); } static inline bool @@ -497,7 +494,13 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, jsval *vp) /* Store in *vp to protect it from GC (callers must root vp). */ *vp = OBJECT_TO_JSVAL(iterobj); - NativeIterator *ni = Snapshot(cx, obj, flags, shapes.begin(), shapes.length(), key); + AutoValueVector props(cx); + if (!Snapshot(cx, obj, flags, props)) + return false; + + NativeIterator *ni = + NativeIterator::allocate(cx, obj, flags, shapes.begin(), shapes.length(), key, + props.begin(), props.length()); if (!ni) return false;