mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1081660 - Remove property iterator from JSAPI. r=Waldo
This commit is contained in:
parent
66ce852993
commit
3808153161
@ -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;
|
||||
|
131
js/src/jsapi.cpp
131
js/src/jsapi.cpp
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user