Bug 572577 - Make property enumeration mechanisms fill in a provided vector of names, rather than return a JSIdArray. r=gal

This commit is contained in:
Jeff Walden
2010-06-16 14:12:21 -07:00
parent 51b3dbf67c
commit f99f798e94
3 changed files with 39 additions and 40 deletions

View File

@@ -1528,10 +1528,8 @@ NewIdArray(JSContext *cx, jsint length)
ida = (JSIdArray *) ida = (JSIdArray *)
cx->calloc(offsetof(JSIdArray, vector) + length * sizeof(jsval)); cx->calloc(offsetof(JSIdArray, vector) + length * sizeof(jsval));
if (ida) { if (ida)
ida->self = ida;
ida->length = length; ida->length = length;
}
return ida; return ida;
} }
@@ -1545,7 +1543,6 @@ SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length)
{ {
JSIdArray *rida; JSIdArray *rida;
JS_ASSERT(ida->self == ida);
rida = (JSIdArray *) rida = (JSIdArray *)
JS_realloc(cx, ida, JS_realloc(cx, ida,
offsetof(JSIdArray, vector) + length * sizeof(jsval)); offsetof(JSIdArray, vector) + length * sizeof(jsval));
@@ -2664,7 +2661,7 @@ JS_SetScriptStackQuota(JSContext *cx, size_t quota)
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
{ {
cx->free(ida->self); cx->free(ida);
} }
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)

View File

@@ -1603,7 +1603,6 @@ struct JSExtendedClass {
#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0 #define JSCLASS_NO_RESERVED_MEMBERS 0,0,0
struct JSIdArray { struct JSIdArray {
void *self;
jsint length; jsint length;
jsid vector[1]; /* actually, length jsid words */ jsid vector[1]; /* actually, length jsid words */
}; };

View File

@@ -252,85 +252,83 @@ NativeIterator::allocate(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarr
return ni; return ni;
} }
static NativeIterator * static bool
Snapshot(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, uint32 slength, uint32 key) Snapshot(JSContext *cx, JSObject *obj, uintN flags, AutoValueVector &props)
{ {
HashSet<jsid> ht(cx); HashSet<jsid> ht(cx);
if (!(flags & JSITER_OWNONLY) && !ht.init(32)) if (!(flags & JSITER_OWNONLY) && !ht.init(32))
return NULL; return false;
AutoValueVector props(cx);
JSObject *pobj = obj; JSObject *pobj = obj;
while (pobj) { do {
JSClass *clasp = pobj->getClass(); JSClass *clasp = pobj->getClass();
if (pobj->isNative() && if (pobj->isNative() &&
pobj->map->ops->enumerate == js_Enumerate && pobj->map->ops->enumerate == js_Enumerate &&
!(clasp->flags & JSCLASS_NEW_ENUMERATE)) { !(clasp->flags & JSCLASS_NEW_ENUMERATE)) {
if (!clasp->enumerate(cx, pobj)) if (!clasp->enumerate(cx, pobj))
return NULL; return false;
if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props)) if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props))
return NULL; return false;
} else if (pobj->isDenseArray()) { } else if (pobj->isDenseArray()) {
if (!EnumerateDenseArrayProperties(cx, obj, pobj, flags, ht, props)) if (!EnumerateDenseArrayProperties(cx, obj, pobj, flags, ht, props))
return NULL; return false;
} else { } else {
if (pobj->isProxy()) { if (pobj->isProxy()) {
JSIdArray *ida; JSIdArray *ida;
if (flags & JSITER_OWNONLY) { if (flags & JSITER_OWNONLY) {
if (!JSProxy::enumerateOwn(cx, pobj, &ida)) if (!JSProxy::enumerateOwn(cx, pobj, &ida))
return NULL; return false;
} else { } else {
if (!JSProxy::enumerate(cx, pobj, &ida)) if (!JSProxy::enumerate(cx, pobj, &ida))
return NULL; return false;
} }
AutoIdArray idar(cx, ida); AutoIdArray idar(cx, ida);
for (size_t n = 0; n < size_t(ida->length); ++n) { for (size_t n = 0; n < size_t(ida->length); ++n) {
if (!Enumerate(cx, obj, pobj, ida->vector[n], true, flags, ht, props)) 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. */ /* Proxy objects enumerate the prototype on their own, so we are done here. */
break; break;
} }
jsval state; jsval state;
if (!pobj->enumerate(cx, JSENUMERATE_INIT, &state, NULL)) if (!pobj->enumerate(cx, JSENUMERATE_INIT, &state, NULL))
return NULL; return false;
if (state == JSVAL_NATIVE_ENUMERATE_COOKIE) { if (state == JSVAL_NATIVE_ENUMERATE_COOKIE) {
if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props)) if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props))
return NULL; return false;
} else { } else {
while (true) { while (true) {
jsid id; jsid id;
if (!pobj->enumerate(cx, JSENUMERATE_NEXT, &state, &id)) if (!pobj->enumerate(cx, JSENUMERATE_NEXT, &state, &id))
return NULL; return false;
if (state == JSVAL_NULL) if (state == JSVAL_NULL)
break; break;
if (!Enumerate(cx, obj, pobj, id, true, flags, ht, props)) if (!Enumerate(cx, obj, pobj, id, true, flags, ht, props))
return NULL; return false;
} }
} }
} }
if (JS_UNLIKELY(pobj->isXML() || (flags & JSITER_OWNONLY))) if (JS_UNLIKELY(pobj->isXML() || (flags & JSITER_OWNONLY)))
break; break;
} while ((pobj = pobj->getProto()) != NULL);
pobj = pobj->getProto(); return true;
}
return NativeIterator::allocate(cx, obj, flags, sarray, slength, key, props.begin(), props.length());
} }
bool 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_STATIC_ASSERT(sizeof(JSIdArray) > sizeof(jsid));
JS_ASSERT(sizeof(NativeIterator) > sizeof(JSIdArray)); size_t len = props.length();
JS_ASSERT(ni->props_array == (jsid *) (ni + 1)); size_t idsz = len * sizeof(jsid);
size_t length = size_t(ni->props_end - ni->props_array); size_t sz = (sizeof(JSIdArray) - sizeof(jsid)) + idsz;
JSIdArray *ida = (JSIdArray *) (uintptr_t(ni->props_array) - (sizeof(JSIdArray) - sizeof(jsid))); JSIdArray *ida = static_cast<JSIdArray *>(cx->malloc(sz));
ida->self = ni; if (!ida)
ida->length = length; return false;
JS_ASSERT(&ida->vector[0] == &ni->props_array[0]);
ida->length = static_cast<jsint>(len);
memcpy(ida->vector, props.begin(), idsz);
*idap = ida; *idap = ida;
return true; return true;
} }
@@ -338,10 +336,9 @@ NativeIteratorToJSIdArray(JSContext *cx, NativeIterator *ni, JSIdArray **idap)
bool bool
GetPropertyNames(JSContext *cx, JSObject *obj, uintN flags, JSIdArray **idap) GetPropertyNames(JSContext *cx, JSObject *obj, uintN flags, JSIdArray **idap)
{ {
NativeIterator *ni = Snapshot(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), NULL, 0, true); AutoValueVector props(cx);
if (!ni) return Snapshot(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), props) &&
return false; VectorToIdArray(cx, props, idap);
return NativeIteratorToJSIdArray(cx, ni, idap);
} }
static inline bool 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). */ /* Store in *vp to protect it from GC (callers must root vp). */
*vp = OBJECT_TO_JSVAL(iterobj); *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) if (!ni)
return false; return false;