Bug 648801 (new DOM list bindings) - Support more properties than 'length'. r=bz/jst/mrbkap.

--HG--
extra : rebase_source : 321d6cda4825e0db43dc5eb97b34a9d6c060f711
This commit is contained in:
Peter Van der Beken 2011-07-29 13:56:41 +02:00
parent 35c39aae23
commit 2980e5d4d8
2 changed files with 48 additions and 20 deletions

View File

@ -205,6 +205,11 @@ Class NodeList<nsINodeList>::sInterfaceClass = {
interface_hasInstance
};
template<>
NodeList<nsINodeList>::Properties NodeList<nsINodeList>::sProtoProperties[] = {
{ s_length_id, length_getter, NULL }
};
template<>
NodeList<nsINodeList>::Methods NodeList<nsINodeList>::sProtoMethods[] = {
{ s_item_id, &item, 1 }
@ -234,6 +239,11 @@ template<>
JSBool
NodeList<nsIHTMLCollection>::namedItem(JSContext *cx, uintN argc, jsval *vp);
template<>
NodeList<nsIHTMLCollection>::Properties NodeList<nsIHTMLCollection>::sProtoProperties[] = {
{ s_length_id, length_getter, NULL }
};
template<>
NodeList<nsIHTMLCollection>::Methods NodeList<nsIHTMLCollection>::sProtoMethods[] = {
{ s_item_id, &item, 1 },
@ -322,14 +332,14 @@ WrapObject(JSContext *cx, JSObject *scope, nsISupports *result,
template<class T>
JSBool
NodeList<T>::length_getter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
NodeList<T>::length_getter(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
if (!instanceIsNodeListObject(cx, obj, NULL))
return false;
PRUint32 length;
getNodeList(obj)->GetLength(&length);
JS_ASSERT(int32(length) >= 0);
vp->setInt32(length);
*vp = UINT_TO_JSVAL(length);
return true;
}
@ -506,10 +516,15 @@ NodeList<T>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, bool *ena
if (!interfacePrototype)
return NULL;
if (!JS_DefinePropertyById(cx, interfacePrototype, s_length_id,
JSVAL_VOID, length_getter, NULL,
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_SHARED))
for (size_t n = 0; n < NS_ARRAY_LENGTH(sProtoProperties); ++n) {
jsid id = sProtoProperties[n].id;
uintN attrs = JSPROP_ENUMERATE | JSPROP_SHARED;
if (!sProtoProperties[n].setter)
attrs |= JSPROP_READONLY;
if (!JS_DefinePropertyById(cx, interfacePrototype, id, JSVAL_VOID,
sProtoProperties[n].getter, sProtoProperties[n].setter, attrs))
return NULL;
}
for (size_t n = 0; n < NS_ARRAY_LENGTH(sProtoMethods); ++n) {
jsid id = sProtoMethods[n].id;
@ -525,9 +540,8 @@ NodeList<T>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, bool *ena
JSObject *interface = JS_NewObject(cx, Jsvalify(&sInterfaceClass), NULL, global);
if (!interface ||
!JS_DefinePropertyById(cx, interface, s_prototype_id,
OBJECT_TO_JSVAL(interfacePrototype), nsnull, nsnull,
JSPROP_PERMANENT | JSPROP_READONLY))
!JS_DefinePropertyById(cx, interface, s_prototype_id, OBJECT_TO_JSVAL(interfacePrototype),
nsnull, nsnull, JSPROP_PERMANENT | JSPROP_READONLY))
return NULL;
if (!JS_DefinePropertyById(cx, interfacePrototype, s_constructor_id,
@ -813,10 +827,14 @@ bool
NodeList<T>::cacheProtoShape(JSContext *cx, JSObject *proxy, JSObject *proto)
{
JSPropertyDescriptor desc;
if (!JS_GetPropertyDescriptorById(cx, proto, s_length_id, JSRESOLVE_QUALIFIED, &desc))
for (size_t n = 0; n < NS_ARRAY_LENGTH(sProtoProperties); ++n) {
jsid id = sProtoProperties[n].id;
if (!JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, &desc))
return false;
if (desc.obj != proto || desc.getter != length_getter)
if (desc.obj != proto || desc.getter != sProtoProperties[n].getter ||
desc.setter != sProtoProperties[n].setter)
return true; // don't cache
}
for (size_t n = 0; n < NS_ARRAY_LENGTH(sProtoMethods); ++n) {
jsid id = sProtoMethods[n].id;
@ -856,13 +874,17 @@ NodeList<T>::resolveNativeName(JSContext *cx, JSObject *proxy, jsid id, Property
{
JS_ASSERT(WrapperFactory::IsXrayWrapper(proxy));
if (id == s_length_id) {
desc->attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_SHARED;
for (size_t n = 0; n < NS_ARRAY_LENGTH(sProtoProperties); ++n) {
if (id == sProtoProperties[n].id) {
desc->attrs = JSPROP_ENUMERATE | JSPROP_SHARED;
if (!sProtoProperties[n].setter)
desc->attrs |= JSPROP_READONLY;
desc->obj = proxy;
desc->setter = nsnull;
desc->getter = length_getter;
desc->setter = sProtoProperties[n].setter;
desc->getter = sProtoProperties[n].getter;
return true;
}
}
for (size_t n = 0; n < NS_ARRAY_LENGTH(sProtoMethods); ++n) {
if (id == sProtoMethods[n].id) {

View File

@ -101,12 +101,18 @@ class NodeList : public NodeListBase {
static js::Class sInterfaceClass;
struct Properties {
jsid &id;
JSPropertyOp getter;
JSStrictPropertyOp setter;
};
struct Methods {
jsid &id;
JSNative native;
uintN nargs;
};
static Properties sProtoProperties[];
static Methods sProtoMethods[];
static bool instanceIsNodeListObject(JSContext *cx, JSObject *obj, JSObject *callee);
@ -119,7 +125,7 @@ class NodeList : public NodeListBase {
static uint32 getProtoShape(JSObject *obj);
static void setProtoShape(JSObject *obj, uint32 shape);
static JSBool length_getter(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
static JSBool length_getter(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
static JSBool item(JSContext *cx, uintN argc, jsval *vp);
static JSBool namedItem(JSContext *cx, uintN argc, jsval *vp);