Bug 1081660 - Remove property iterator from JSAPI. r=Waldo

This commit is contained in:
Tom Schuster 2014-10-16 18:39:30 +02:00
parent 66ce852993
commit 3808153161
3 changed files with 20 additions and 183 deletions

View File

@ -2625,8 +2625,8 @@ ImplicitConvert(JSContext* cx,
if (val.isObject() && !sourceData) {
// Enumerate the properties of the object; if they match the struct
// specification, convert the fields.
RootedObject iter(cx, JS_NewPropertyIterator(cx, valObj));
if (!iter)
AutoIdArray props(cx, JS_Enumerate(cx, valObj));
if (!props)
return false;
// Convert into an intermediate, in case of failure.
@ -2637,13 +2637,15 @@ ImplicitConvert(JSContext* cx,
return false;
}
const FieldInfoHash* fields = StructType::GetFieldInfo(targetType);
if (props.length() != fields->count()) {
JS_ReportError(cx, "missing fields");
return false;
}
RootedId id(cx);
size_t i = 0;
while (1) {
if (!JS_NextProperty(cx, iter, &id))
return false;
if (JSID_IS_VOID(id))
break;
for (size_t i = 0; i < props.length(); ++i) {
id = props[i];
if (!JSID_IS_STRING(id)) {
JS_ReportError(cx, "property name is not a string");
@ -2663,14 +2665,6 @@ ImplicitConvert(JSContext* cx,
char* fieldData = intermediate.get() + field->mOffset;
if (!ImplicitConvert(cx, prop, field->mType, fieldData, false, nullptr))
return false;
++i;
}
const FieldInfoHash* fields = StructType::GetFieldInfo(targetType);
if (i != fields->count()) {
JS_ReportError(cx, "missing fields");
return false;
}
memcpy(buffer, intermediate.get(), structSize);
@ -4705,33 +4699,23 @@ ExtractStructField(JSContext* cx, jsval val, MutableHandleObject typeObj)
return nullptr;
}
RootedObject obj(cx, val.toObjectOrNull());
RootedObject iter(cx, JS_NewPropertyIterator(cx, obj));
if (!iter)
RootedObject obj(cx, &val.toObject());
AutoIdArray props(cx, JS_Enumerate(cx, obj));
if (!props)
return nullptr;
RootedId nameid(cx);
if (!JS_NextProperty(cx, iter, &nameid))
return nullptr;
if (JSID_IS_VOID(nameid)) {
JS_ReportError(cx, "struct field descriptors require a valid name and type");
return nullptr;
}
if (!JSID_IS_STRING(nameid)) {
JS_ReportError(cx, "struct field descriptors require a valid name and type");
return nullptr;
}
// make sure we have one, and only one, property
RootedId id(cx);
if (!JS_NextProperty(cx, iter, &id))
return nullptr;
if (!JSID_IS_VOID(id)) {
if (props.length() != 1) {
JS_ReportError(cx, "struct field descriptors must contain one property");
return nullptr;
}
RootedId nameid(cx, props[0]);
if (!JSID_IS_STRING(nameid)) {
JS_ReportError(cx, "struct field descriptors require a valid name and type");
return nullptr;
}
RootedValue propVal(cx);
if (!JS_GetPropertyById(cx, obj, nameid, &propVal))
return nullptr;

View File

@ -3620,137 +3620,6 @@ JS_Enumerate(JSContext *cx, HandleObject obj)
return ida;
}
/*
* XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
* prop_iterator_class somehow...
* + preserve the obj->enumerate API while optimizing the native object case
* + native case here uses a JSShape *, but that iterates in reverse!
* + so we make non-native match, by reverse-iterating after JS_Enumerating
*/
static const uint32_t JSSLOT_ITER_INDEX = 0;
static void
prop_iter_finalize(FreeOp *fop, JSObject *obj)
{
void *pdata = obj->as<NativeObject>().getPrivate();
if (!pdata)
return;
if (obj->as<NativeObject>().getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
/* Non-native case: destroy the ida enumerated when obj was created. */
JSIdArray *ida = (JSIdArray *) pdata;
fop->free_(ida);
}
}
static void
prop_iter_trace(JSTracer *trc, JSObject *obj)
{
void *pdata = obj->as<NativeObject>().getPrivate();
if (!pdata)
return;
if (obj->as<NativeObject>().getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) {
/*
* Native case: just mark the next property to visit. We don't need a
* barrier here because the pointer is updated via setPrivate, which
* always takes a barrier.
*/
Shape *tmp = static_cast<Shape *>(pdata);
MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
obj->as<NativeObject>().setPrivateUnbarriered(tmp);
} else {
/* Non-native case: mark each id in the JSIdArray private. */
JSIdArray *ida = (JSIdArray *) pdata;
MarkIdRange(trc, ida->length, ida->vector, "prop iter");
}
}
static const Class prop_iter_class = {
"PropertyIterator",
JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
prop_iter_finalize,
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
prop_iter_trace
};
JS_PUBLIC_API(JSObject *)
JS_NewPropertyIterator(JSContext *cx, HandleObject obj)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
RootedNativeObject iterobj(cx, NewNativeObjectWithClassProto(cx, &prop_iter_class,
nullptr, obj));
if (!iterobj)
return nullptr;
int index;
if (obj->isNative()) {
/* Native case: start with the last property in obj. */
iterobj->setPrivateGCThing(obj->lastProperty());
index = -1;
} else {
/* Non-native case: enumerate a JSIdArray and keep it via private. */
JSIdArray *ida = JS_Enumerate(cx, obj);
if (!ida)
return nullptr;
iterobj->setPrivate((void *)ida);
index = ida->length;
}
/* iterobj cannot escape to other threads here. */
iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
return iterobj;
}
JS_PUBLIC_API(bool)
JS_NextProperty(JSContext *cx, HandleObject iterobj, MutableHandleId idp)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, iterobj);
int32_t i = iterobj->as<NativeObject>().getSlot(JSSLOT_ITER_INDEX).toInt32();
if (i < 0) {
/* Native case: private data is a property tree node pointer. */
MOZ_ASSERT(iterobj->getParent()->isNative());
Shape *shape = static_cast<Shape *>(iterobj->as<NativeObject>().getPrivate());
while (shape->previous() && !shape->enumerable())
shape = shape->previous();
if (!shape->previous()) {
MOZ_ASSERT(shape->isEmptyShape());
idp.set(JSID_VOID);
} else {
iterobj->as<NativeObject>().setPrivateGCThing(const_cast<Shape *>(shape->previous().get()));
idp.set(shape->propid());
}
} else {
/* Non-native case: use the ida enumerated when iterobj was created. */
JSIdArray *ida = (JSIdArray *) iterobj->as<NativeObject>().getPrivate();
MOZ_ASSERT(i <= ida->length);
STATIC_ASSUME(i <= ida->length);
if (i == 0) {
idp.set(JSID_VOID);
} else {
idp.set(ida->vector[--i]);
iterobj->as<NativeObject>().setSlot(JSSLOT_ITER_INDEX, Int32Value(i));
}
}
return true;
}
JS_PUBLIC_API(jsval)
JS_GetReservedSlot(JSObject *obj, uint32_t index)
{

View File

@ -3305,22 +3305,6 @@ JS_ReleaseMappedArrayBufferContents(void *contents, size_t length);
extern JS_PUBLIC_API(JSIdArray *)
JS_Enumerate(JSContext *cx, JS::HandleObject obj);
/*
* Create an object to iterate over enumerable properties of obj, in arbitrary
* property definition order. NB: This differs from longstanding for..in loop
* order, which uses order of property definition in obj.
*/
extern JS_PUBLIC_API(JSObject *)
JS_NewPropertyIterator(JSContext *cx, JS::Handle<JSObject*> obj);
/*
* Return true on success with *idp containing the id of the next enumerable
* property to visit using iterobj, or JSID_IS_VOID if there is no such property
* left to visit. Return false on error.
*/
extern JS_PUBLIC_API(bool)
JS_NextProperty(JSContext *cx, JS::HandleObject iterobj, JS::MutableHandleId idp);
extern JS_PUBLIC_API(jsval)
JS_GetReservedSlot(JSObject *obj, uint32_t index);