Bug 691992 - Split getAttributes and setAttributes into property and generic forms, and use them throughout the engine. r=bhackett
authorJeff Walden <jwalden@mit.edu>
Tue, 04 Oct 2011 17:21:06 -0700
changeset 79618 5a848c512af7c8a28ba18d458e467c8bf1f9869c
parent 79617 bf09dbe3fcd74c455ce5b6196b1ee752089410d5
child 79619 9291abf9fd17b92023e62e33631b13b9732dd0ec
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs691992
milestone10.0a1
Bug 691992 - Split getAttributes and setAttributes into property and generic forms, and use them throughout the engine. r=bhackett
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsclass.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsproxy.cpp
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jsxml.cpp
js/src/shell/js.cpp
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3703,17 +3703,17 @@ GetPropertyDescriptorById(JSContext *cx,
         }
     } else {
         if (obj2->isProxy()) {
             JSAutoResolveFlags rf(cx, flags);
             return own
                    ? Proxy::getOwnPropertyDescriptor(cx, obj2, id, false, desc)
                    : Proxy::getPropertyDescriptor(cx, obj2, id, false, desc);
         }
-        if (!obj2->getAttributes(cx, id, &desc->attrs))
+        if (!obj2->getGenericAttributes(cx, id, &desc->attrs))
             return false;
         desc->getter = NULL;
         desc->setter = NULL;
         desc->value.setUndefined();
     }
     return true;
 }
 
@@ -3797,17 +3797,17 @@ SetPropertyAttributesById(JSContext *cx,
     if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
         return false;
     if (!prop || obj != obj2) {
         *foundp = false;
         return true;
     }
     JSBool ok = obj->isNative()
                 ? js_SetNativeAttributes(cx, obj, (Shape *) prop, attrs)
-                : obj->setAttributes(cx, id, &attrs);
+                : obj->setGenericAttributes(cx, id, &attrs);
     if (ok)
         *foundp = true;
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
                          uintN attrs, JSBool *foundp)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1087,54 +1087,72 @@ array_defineElement(JSContext *cx, JSObj
 static JSBool
 array_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     return array_defineProperty(cx, obj, SPECIALID_TO_JSID(sid), value, getter, setter, attrs);
 }
 
 static JSBool
-array_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+array_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     *attrsp = JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)
         ? JSPROP_PERMANENT : JSPROP_ENUMERATE;
-    return JS_TRUE;
+    return true;
+}
+
+static JSBool
+array_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    *attrsp = (name == cx->runtime->atomState.lengthAtom)
+              ? JSPROP_PERMANENT
+              : JSPROP_ENUMERATE;
+    return true;
 }
 
 static JSBool
 array_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     *attrsp = JSPROP_ENUMERATE;
     return true;
 }
 
 static JSBool
 array_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return array_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    *attrsp = JSPROP_ENUMERATE;
+    return true;
 }
 
 static JSBool
-array_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+array_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
+    return false;
+}
+
+static JSBool
+array_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 static JSBool
 array_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 static JSBool
 array_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return array_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
+    return false;
 }
 
 namespace js {
 
 /* non-static for direct deletion of array elements within the engine */
 JSBool
 array_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
@@ -1244,22 +1262,22 @@ Class js::ArrayClass = {
         array_getGeneric,
         array_getProperty,
         array_getElement,
         array_getSpecial,
         array_setProperty,
         array_setProperty,
         array_setElement,
         array_setSpecial,
-        array_getAttributes,
-        array_getAttributes,
+        array_getGenericAttributes,
+        array_getPropertyAttributes,
         array_getElementAttributes,
         array_getSpecialAttributes,
-        array_setAttributes,
-        array_setAttributes,
+        array_setGenericAttributes,
+        array_setPropertyAttributes,
         array_setElementAttributes,
         array_setSpecialAttributes,
         array_deleteProperty,
         array_deleteProperty,
         array_deleteElement,
         array_deleteSpecial,
         NULL,       /* enumerate      */
         array_typeOf,
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -215,17 +215,17 @@ typedef JSBool
 (* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
 typedef JSBool
 (* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
 typedef JSBool
 (* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
 typedef JSBool
 (* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 typedef JSBool
-(* AttributesOp)(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+(* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp);
 typedef JSBool
 (* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 typedef JSBool
 (* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp);
 typedef JSBool
 (* DeleteGenericOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
 typedef JSBool
 (* DeleteIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
@@ -314,21 +314,21 @@ struct ObjectOps
     PropertyIdOp        getProperty;
     ElementIdOp         getElement;
     SpecialIdOp         getSpecial;
     StrictGenericIdOp   setGeneric;
     StrictPropertyIdOp  setProperty;
     StrictElementIdOp   setElement;
     StrictSpecialIdOp   setSpecial;
     GenericAttributesOp getGenericAttributes;
-    AttributesOp        getAttributes;
+    PropertyAttributesOp getPropertyAttributes;
     ElementAttributesOp getElementAttributes;
     SpecialAttributesOp getSpecialAttributes;
     GenericAttributesOp setGenericAttributes;
-    AttributesOp        setAttributes;
+    PropertyAttributesOp setPropertyAttributes;
     ElementAttributesOp setElementAttributes;
     SpecialAttributesOp setSpecialAttributes;
     DeleteGenericOp     deleteGeneric;
     DeleteIdOp          deleteProperty;
     DeleteElementOp     deleteElement;
     DeleteSpecialOp     deleteSpecial;
 
     JSNewEnumerateOp    enumerate;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -833,17 +833,17 @@ js::CheckRedeclaration(JSContext *cx, JS
 
     if (!obj->lookupGeneric(cx, id, &obj2, &prop))
         return false;
     if (!prop)
         return true;
     if (obj2->isNative()) {
         oldAttrs = ((Shape *) prop)->attributes();
     } else {
-        if (!obj2->getAttributes(cx, id, &oldAttrs))
+        if (!obj2->getGenericAttributes(cx, id, &oldAttrs))
             return false;
     }
 
     /* We allow redeclaring some non-readonly properties. */
     if (((oldAttrs | attrs) & JSPROP_READONLY) == 0) {
         /* Allow redeclaration of variables and functions. */
         if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
             return true;
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -866,17 +866,17 @@ SuppressDeletedPropertyHelper(JSContext 
                         AutoObjectRooter obj2(cx);
                         JSProperty *prop;
                         if (!proto.object()->lookupGeneric(cx, *idp, obj2.addr(), &prop))
                             return false;
                         if (prop) {
                             uintN attrs;
                             if (obj2.object()->isNative())
                                 attrs = ((Shape *) prop)->attributes();
-                            else if (!obj2.object()->getAttributes(cx, *idp, &attrs))
+                            else if (!obj2.object()->getGenericAttributes(cx, *idp, &attrs))
                                 return false;
 
                             if (attrs & JSPROP_ENUMERATE)
                                 continue;
                         }
                     }
 
                     /*
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1590,17 +1590,17 @@ js_PropertyIsEnumerable(JSContext *cx, J
      * of propertyIsEnumerable's name was a mistake.
      */
     if (pobj != obj) {
         vp->setBoolean(false);
         return true;
     }
 
     uintN attrs;
-    if (!pobj->getAttributes(cx, id, &attrs))
+    if (!pobj->getGenericAttributes(cx, id, &attrs))
         return false;
 
     vp->setBoolean((attrs & JSPROP_ENUMERATE) != 0);
     return true;
 }
 
 #if OLD_GETTER_SETTER_METHODS
 
@@ -1858,17 +1858,17 @@ GetOwnPropertyDescriptor(JSContext *cx, 
         if (desc->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
             doGet = false;
             if (desc->attrs & JSPROP_GETTER)
                 desc->getter = CastAsPropertyOp(shape->getterObject());
             if (desc->attrs & JSPROP_SETTER)
                 desc->setter = CastAsStrictPropertyOp(shape->setterObject());
         }
     } else {
-        if (!pobj->getAttributes(cx, id, &desc->attrs))
+        if (!pobj->getGenericAttributes(cx, id, &desc->attrs))
             return false;
     }
 
     if (doGet && !obj->getGeneric(cx, id, &desc->value))
         return false;
 
     desc->obj = obj;
     return true;
@@ -2745,32 +2745,32 @@ JSObject::sealOrFreeze(JSContext *cx, Im
 
     /* preventExtensions must slowify dense arrays, so we can assign to holes without checks. */
     JS_ASSERT(!isDenseArray());
 
     for (size_t i = 0, len = props.length(); i < len; i++) {
         jsid id = props[i];
 
         uintN attrs;
-        if (!getAttributes(cx, id, &attrs))
+        if (!getGenericAttributes(cx, id, &attrs))
             return false;
 
         /* Make all attributes permanent; if freezing, make data attributes read-only. */
         uintN new_attrs;
         if (it == FREEZE && !(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
             new_attrs = JSPROP_PERMANENT | JSPROP_READONLY;
         else
             new_attrs = JSPROP_PERMANENT;
 
         /* If we already have the attributes we need, skip the setAttributes call. */
         if ((attrs | new_attrs) == attrs)
             continue;
 
         attrs |= new_attrs;
-        if (!setAttributes(cx, id, &attrs))
+        if (!setGenericAttributes(cx, id, &attrs))
             return false;
     }
 
     return true;
 }
 
 bool
 JSObject::isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp)
@@ -2783,17 +2783,17 @@ JSObject::isSealedOrFrozen(JSContext *cx
     AutoIdVector props(cx);
     if (!GetPropertyNames(cx, this, JSITER_HIDDEN | JSITER_OWNONLY, &props))
         return false;
 
     for (size_t i = 0, len = props.length(); i < len; i++) {
         jsid id = props[i];
 
         uintN attrs;
-        if (!getAttributes(cx, id, &attrs))
+        if (!getGenericAttributes(cx, id, &attrs))
             return false;
 
         /*
          * If the property is configurable, this object is neither sealed nor
          * frozen. If the property is a writable data property, this object is
          * not frozen.
          */
         if (!(attrs & JSPROP_PERMANENT) ||
@@ -3332,55 +3332,61 @@ with_SetElement(JSContext *cx, JSObject 
 
 static JSBool
 with_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
     return with_SetProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
 }
 
 static JSBool
-with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
-{
-    return obj->getProto()->getAttributes(cx, id, attrsp);
+with_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return obj->getProto()->getGenericAttributes(cx, id, attrsp);
+}
+
+static JSBool
+with_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    return obj->getProto()->getPropertyAttributes(cx, name, attrsp);
 }
 
 static JSBool
 with_GetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
-    jsid id;
-    if (!IndexToId(cx, index, &id))
-        return false;
-    return with_GetAttributes(cx, obj, id, attrsp);
+    return obj->getProto()->getElementAttributes(cx, index, attrsp);
 }
 
 static JSBool
 with_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return with_GetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return obj->getProto()->getSpecialAttributes(cx, sid, attrsp);
 }
 
 static JSBool
-with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
-{
-    return obj->getProto()->setAttributes(cx, id, attrsp);
+with_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return obj->getProto()->setGenericAttributes(cx, id, attrsp);
+}
+
+static JSBool
+with_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    return obj->getProto()->setPropertyAttributes(cx, name, attrsp);
 }
 
 static JSBool
 with_SetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
-    jsid id;
-    if (!IndexToId(cx, index, &id))
-        return false;
-    return with_SetAttributes(cx, obj, id, attrsp);
+    return obj->getProto()->setElementAttributes(cx, index, attrsp);
 }
 
 static JSBool
 with_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return with_SetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return obj->getProto()->setSpecialAttributes(cx, sid, attrsp);
 }
 
 static JSBool
 with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     return obj->getProto()->deleteProperty(cx, id, rval, strict);
 }
 
@@ -3449,22 +3455,22 @@ Class js::WithClass = {
         with_GetGeneric,
         with_GetProperty,
         with_GetElement,
         with_GetSpecial,
         with_SetProperty,
         with_SetProperty,
         with_SetElement,
         with_SetSpecial,
-        with_GetAttributes,
-        with_GetAttributes,
+        with_GetGenericAttributes,
+        with_GetPropertyAttributes,
         with_GetElementAttributes,
         with_GetSpecialAttributes,
-        with_SetAttributes,
-        with_SetAttributes,
+        with_SetGenericAttributes,
+        with_SetPropertyAttributes,
         with_SetElementAttributes,
         with_SetSpecialAttributes,
         with_DeleteProperty,
         with_DeleteProperty,
         with_DeleteElement,
         with_DeleteSpecial,
         with_Enumerate,
         with_TypeOf,
@@ -6331,17 +6337,17 @@ js_GetAttributes(JSContext *cx, JSObject
     JSProperty *prop;
     if (!js_LookupProperty(cx, obj, id, &obj, &prop))
         return false;
     if (!prop) {
         *attrsp = 0;
         return true;
     }
     if (!obj->isNative())
-        return obj->getAttributes(cx, id, attrsp);
+        return obj->getGenericAttributes(cx, id, attrsp);
 
     const Shape *shape = (Shape *)prop;
     *attrsp = shape->attributes();
     return true;
 }
 
 JSBool
 js_GetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
@@ -6374,17 +6380,17 @@ js_SetAttributes(JSContext *cx, JSObject
 {
     JSProperty *prop;
     if (!js_LookupProperty(cx, obj, id, &obj, &prop))
         return false;
     if (!prop)
         return true;
     return obj->isNative()
            ? js_SetNativeAttributes(cx, obj, (Shape *) prop, *attrsp)
-           : obj->setAttributes(cx, id, attrsp);
+           : obj->setGenericAttributes(cx, id, attrsp);
 }
 
 JSBool
 js_SetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     JSProperty *prop;
     if (!js_LookupElement(cx, obj, index, &obj, &prop))
         return false;
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1396,32 +1396,25 @@ struct JSObject : js::gc::Cell {
             return nonNativeSetElement(cx, index, vp, strict);
         return js_SetElementHelper(cx, this, index, 0, vp, strict);
     }
 
     JSBool nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict);
 
     JSBool nonNativeSetElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict);
 
-    JSBool getAttributes(JSContext *cx, jsid id, uintN *attrsp) {
-        js::AttributesOp op = getOps()->getAttributes;
-        return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
-    }
+    inline JSBool getGenericAttributes(JSContext *cx, jsid id, uintN *attrsp);
+    inline JSBool getPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp);
+    inline JSBool getElementAttributes(JSContext *cx, uint32 index, uintN *attrsp);
+    inline JSBool getSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp);
 
-    JSBool getElementAttributes(JSContext *cx, uint32 index, uintN *attrsp) {
-        js::ElementAttributesOp op = getOps()->getElementAttributes;
-        return (op ? op : js_GetElementAttributes)(cx, this, index, attrsp);
-    }
-
-    inline JSBool setAttributes(JSContext *cx, jsid id, uintN *attrsp);
-
-    JSBool setElementAttributes(JSContext *cx, uint32 index, uintN *attrsp) {
-        js::ElementAttributesOp op = getOps()->setElementAttributes;
-        return (op ? op : js_SetElementAttributes)(cx, this, index, attrsp);
-    }
+    inline JSBool setGenericAttributes(JSContext *cx, jsid id, uintN *attrsp);
+    inline JSBool setPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp);
+    inline JSBool setElementAttributes(JSContext *cx, uint32 index, uintN *attrsp);
+    inline JSBool setSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp);
 
     inline JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval, JSBool strict);
 
     inline JSBool deleteElement(JSContext *cx, uint32 index, js::Value *rval, JSBool strict);
 
     JSBool enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp) {
         JSNewEnumerateOp op = getOps()->enumerate;
         return (op ? op : JS_EnumerateState)(cx, this, iterop, statep, idp);
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -121,24 +121,43 @@ JSObject::unbrand(JSContext *cx)
             return false;
         flags &= ~BRANDED;
     }
     setGeneric();
     return true;
 }
 
 inline JSBool
-JSObject::setAttributes(JSContext *cx, jsid id, uintN *attrsp)
+JSObject::setGenericAttributes(JSContext *cx, jsid id, uintN *attrsp)
 {
     js::types::MarkTypePropertyConfigured(cx, this, id);
-    js::AttributesOp op = getOps()->setAttributes;
+    js::GenericAttributesOp op = getOps()->setGenericAttributes;
     return (op ? op : js_SetAttributes)(cx, this, id, attrsp);
 }
 
 inline JSBool
+JSObject::setPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp)
+{
+    return setGenericAttributes(cx, ATOM_TO_JSID(name), attrsp);
+}
+
+inline JSBool
+JSObject::setElementAttributes(JSContext *cx, uint32 index, uintN *attrsp)
+{
+    js::ElementAttributesOp op = getOps()->setElementAttributes;
+    return (op ? op : js_SetElementAttributes)(cx, this, index, attrsp);
+}
+
+inline JSBool
+JSObject::setSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp)
+{
+    return setGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
+}
+
+inline JSBool
 JSObject::getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp)
 {
     js::GenericIdOp op = getOps()->getGeneric;
     if (op) {
         if (!op(cx, this, receiver, id, vp))
             return false;
     } else {
         if (!js_GetProperty(cx, this, receiver, id, vp))
@@ -1157,16 +1176,44 @@ JSObject::deleteElement(JSContext *cx, u
 }
 
 inline JSBool
 JSObject::getSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp)
 {
     return getGeneric(cx, SPECIALID_TO_JSID(sid), vp);
 }
 
+inline JSBool
+JSObject::getGenericAttributes(JSContext *cx, jsid id, uintN *attrsp)
+{
+    js::GenericAttributesOp op = getOps()->getGenericAttributes;
+    return (op ? op : js_GetAttributes)(cx, this, id, attrsp);    
+}
+
+inline JSBool
+JSObject::getPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp)
+{
+    return getGenericAttributes(cx, ATOM_TO_JSID(name), attrsp);
+}
+
+inline JSBool
+JSObject::getElementAttributes(JSContext *cx, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!js::IndexToId(cx, index, &id))
+        return false;
+    return getGenericAttributes(cx, id, attrsp);
+}
+
+inline JSBool
+JSObject::getSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp)
+{
+    return getGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
+}
+
 inline bool
 JSObject::isProxy() const
 {
     return js::IsProxy(this);
 }
 
 inline bool
 JSObject::isCrossCompartmentWrapper() const
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1035,68 +1035,80 @@ proxy_SetElement(JSContext *cx, JSObject
 
 static JSBool
 proxy_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
     return proxy_SetProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
 }
 
 static JSBool
-proxy_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+proxy_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     id = js_CheckForStringIndex(id);
 
     AutoPropertyDescriptorRooter desc(cx);
     if (!Proxy::getOwnPropertyDescriptor(cx, obj, id, false, &desc))
         return false;
     *attrsp = desc.attrs;
     return true;
 }
 
 static JSBool
+proxy_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    return proxy_GetGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp);
+}
+
+static JSBool
 proxy_GetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
-    return proxy_GetAttributes(cx, obj, id, attrsp);
+    return proxy_GetGenericAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
 proxy_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return proxy_GetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return proxy_GetGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 static JSBool
-proxy_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+proxy_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     id = js_CheckForStringIndex(id);
 
     /* Lookup the current property descriptor so we have setter/getter/value. */
     AutoPropertyDescriptorRooter desc(cx);
     if (!Proxy::getOwnPropertyDescriptor(cx, obj, id, true, &desc))
         return false;
     desc.attrs = (*attrsp & (~JSPROP_SHORTID));
     return Proxy::defineProperty(cx, obj, id, &desc);
 }
 
 static JSBool
+proxy_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    return proxy_SetGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp);
+}
+
+static JSBool
 proxy_SetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
-    return proxy_SetAttributes(cx, obj, id, attrsp);
+    return proxy_SetGenericAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
 proxy_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return proxy_SetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return proxy_SetGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 static JSBool
 proxy_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     id = js_CheckForStringIndex(id);
 
     // TODO: throwing away strict
@@ -1220,22 +1232,22 @@ JS_FRIEND_DATA(Class) js::ObjectProxyCla
         proxy_GetGeneric,
         proxy_GetProperty,
         proxy_GetElement,
         proxy_GetSpecial,
         proxy_SetProperty,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
-        proxy_GetAttributes,
-        proxy_GetAttributes,
+        proxy_GetGenericAttributes,
+        proxy_GetPropertyAttributes,
         proxy_GetElementAttributes,
         proxy_GetSpecialAttributes,
-        proxy_SetAttributes,
-        proxy_SetAttributes,
+        proxy_SetGenericAttributes,
+        proxy_SetPropertyAttributes,
         proxy_SetElementAttributes,
         proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         proxy_TypeOf,
@@ -1281,22 +1293,22 @@ JS_FRIEND_DATA(Class) js::OuterWindowPro
         proxy_GetGeneric,
         proxy_GetProperty,
         proxy_GetElement,
         proxy_GetSpecial,
         proxy_SetProperty,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
-        proxy_GetAttributes,
-        proxy_GetAttributes,
+        proxy_GetGenericAttributes,
+        proxy_GetPropertyAttributes,
         proxy_GetElementAttributes,
         proxy_GetSpecialAttributes,
-        proxy_SetAttributes,
-        proxy_SetAttributes,
+        proxy_SetGenericAttributes,
+        proxy_SetPropertyAttributes,
         proxy_SetElementAttributes,
         proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         NULL,                /* typeof          */
@@ -1354,22 +1366,22 @@ JS_FRIEND_DATA(Class) js::FunctionProxyC
         proxy_GetGeneric,
         proxy_GetProperty,
         proxy_GetElement,
         proxy_GetSpecial,
         proxy_SetProperty,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
-        proxy_GetAttributes,
-        proxy_GetAttributes,
+        proxy_GetGenericAttributes,
+        proxy_GetPropertyAttributes,
         proxy_GetElementAttributes,
         proxy_GetSpecialAttributes,
-        proxy_SetAttributes,
-        proxy_SetAttributes,
+        proxy_SetGenericAttributes,
+        proxy_SetPropertyAttributes,
         proxy_SetElementAttributes,
         proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         proxy_TypeOf,
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -457,72 +457,84 @@ ArrayBuffer::obj_setElement(JSContext *c
 
 JSBool
 ArrayBuffer::obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
     return obj_setProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
 }
 
 JSBool
-ArrayBuffer::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+ArrayBuffer::obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         *attrsp = JSPROP_PERMANENT | JSPROP_READONLY;
         return true;
     }
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_GetAttributes(cx, delegate, id, attrsp);
 }
 
 JSBool
+ArrayBuffer::obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    return obj_getGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp);
+}
+
+JSBool
 ArrayBuffer::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_GetElementAttributes(cx, delegate, index, attrsp);
 }
 
 JSBool
 ArrayBuffer::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return obj_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return obj_getGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 JSBool
-ArrayBuffer::obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+ArrayBuffer::obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_CANT_SET_ARRAY_ATTRS);
         return false;
     }
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_SetAttributes(cx, delegate, id, attrsp);
 }
 
 JSBool
+ArrayBuffer::obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    return obj_setGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp);
+}
+
+JSBool
 ArrayBuffer::obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_SetElementAttributes(cx, delegate, index, attrsp);
 }
 
 JSBool
 ArrayBuffer::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return obj_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return obj_setGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 JSBool
 ArrayBuffer::obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         rval->setBoolean(false);
         return true;
@@ -717,55 +729,70 @@ TypedArray::obj_lookupElement(JSContext 
 JSBool
 TypedArray::obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid,
                               JSObject **objp, JSProperty **propp)
 {
     return obj_lookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
 }
 
 JSBool
-TypedArray::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+TypedArray::obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     *attrsp = (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
               ? JSPROP_PERMANENT | JSPROP_READONLY
               : JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
 
 JSBool
+TypedArray::obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
+    return true;
+}
+
+JSBool
 TypedArray::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
 
 JSBool
 TypedArray::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return obj_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return obj_getGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 JSBool
-TypedArray::obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+TypedArray::obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
+    return false;
+}
+
+JSBool
+TypedArray::obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 JSBool
 TypedArray::obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 JSBool
 TypedArray::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return obj_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
+    return false;
 }
 
 /* static */ int
 TypedArray::lengthOffset()
 {
     return JSObject::getFixedSlotOffset(FIELD_LENGTH) + offsetof(jsval_layout, s.payload);
 }
 
@@ -2040,22 +2067,22 @@ Class js::ArrayBufferClass = {
         ArrayBuffer::obj_getGeneric,
         ArrayBuffer::obj_getProperty,
         ArrayBuffer::obj_getElement,
         ArrayBuffer::obj_getSpecial,
         ArrayBuffer::obj_setProperty,
         ArrayBuffer::obj_setProperty,
         ArrayBuffer::obj_setElement,
         ArrayBuffer::obj_setSpecial,
-        ArrayBuffer::obj_getAttributes,
-        ArrayBuffer::obj_getAttributes,
+        ArrayBuffer::obj_getGenericAttributes,
+        ArrayBuffer::obj_getPropertyAttributes,
         ArrayBuffer::obj_getElementAttributes,
         ArrayBuffer::obj_getSpecialAttributes,
-        ArrayBuffer::obj_setAttributes,
-        ArrayBuffer::obj_setAttributes,
+        ArrayBuffer::obj_setGenericAttributes,
+        ArrayBuffer::obj_setPropertyAttributes,
         ArrayBuffer::obj_setElementAttributes,
         ArrayBuffer::obj_setSpecialAttributes,
         ArrayBuffer::obj_deleteProperty,
         ArrayBuffer::obj_deleteProperty,
         ArrayBuffer::obj_deleteElement,
         ArrayBuffer::obj_deleteSpecial,
         ArrayBuffer::obj_enumerate,
         ArrayBuffer::obj_typeOf,
@@ -2144,30 +2171,30 @@ JSFunctionSpec _typedArray::jsfuncs[] = 
         _typedArray::obj_lookupGeneric,                                        \
         _typedArray::obj_lookupProperty,                                       \
         _typedArray::obj_lookupElement,                                        \
         _typedArray::obj_lookupSpecial,                                        \
         _typedArray::obj_defineProperty,                                       \
         _typedArray::obj_defineProperty,                                       \
         _typedArray::obj_defineElement,                                        \
         _typedArray::obj_defineSpecial,                                        \
-        _typedArray::obj_getGeneric,                                          \
+        _typedArray::obj_getGeneric,                                           \
         _typedArray::obj_getProperty,                                          \
         _typedArray::obj_getElement,                                           \
         _typedArray::obj_getSpecial,                                           \
         _typedArray::obj_setProperty,                                          \
         _typedArray::obj_setProperty,                                          \
         _typedArray::obj_setElement,                                           \
         _typedArray::obj_setSpecial,                                           \
-        _typedArray::obj_getAttributes,                                        \
-        _typedArray::obj_getAttributes,                                        \
+        _typedArray::obj_getGenericAttributes,                                 \
+        _typedArray::obj_getPropertyAttributes,                                \
         _typedArray::obj_getElementAttributes,                                 \
         _typedArray::obj_getSpecialAttributes,                                 \
-        _typedArray::obj_setAttributes,                                        \
-        _typedArray::obj_setAttributes,                                        \
+        _typedArray::obj_setGenericAttributes,                                 \
+        _typedArray::obj_setPropertyAttributes,                                \
         _typedArray::obj_setElementAttributes,                                 \
         _typedArray::obj_setSpecialAttributes,                                 \
         _typedArray::obj_deleteProperty,                                       \
         _typedArray::obj_deleteProperty,                                       \
         _typedArray::obj_deleteElement,                                        \
         _typedArray::obj_deleteSpecial,                                        \
         _typedArray::obj_enumerate,                                            \
         _typedArray::obj_typeOf,                                               \
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -117,30 +117,30 @@ struct JS_FRIEND_API(ArrayBuffer) {
 
     static JSBool
     obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
 
     static JSBool
     obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
 
     static JSBool
-    obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
-
+    obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    static JSBool
+    obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp);
     static JSBool
     obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
-
     static JSBool
     obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp);
 
     static JSBool
-    obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
-
+    obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    static JSBool
+    obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp);
     static JSBool
     obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
-
     static JSBool
     obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp);
 
     static JSBool
     obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict);
 
     static JSBool
     obj_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict);
@@ -217,21 +217,23 @@ struct JS_FRIEND_API(TypedArray) {
                                     JSObject **objp, JSProperty **propp);
     static JSBool obj_lookupProperty(JSContext *cx, JSObject *obj, PropertyName *name,
                                      JSObject **objp, JSProperty **propp);
     static JSBool obj_lookupElement(JSContext *cx, JSObject *obj, uint32 index,
                                     JSObject **objp, JSProperty **propp);
     static JSBool obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid,
                                     JSObject **objp, JSProperty **propp);
 
-    static JSBool obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    static JSBool obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    static JSBool obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp);
     static JSBool obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
     static JSBool obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp);
 
-    static JSBool obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    static JSBool obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    static JSBool obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp);
     static JSBool obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
     static JSBool obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp);
 
     static JSUint32 getLength(JSObject *obj);
     static JSUint32 getByteOffset(JSObject *obj);
     static JSUint32 getByteLength(JSObject *obj);
     static JSUint32 getType(JSObject *obj);
     static JSObject * getBuffer(JSObject *obj);
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -4872,69 +4872,81 @@ xml_setElement(JSContext *cx, JSObject *
 
 static JSBool
 xml_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
     return xml_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
 }
 
 static JSBool
-xml_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+xml_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     JSBool found;
     if (!HasProperty(cx, obj, IdToJsval(id), &found))
         return false;
 
     *attrsp = found ? JSPROP_ENUMERATE : 0;
     return JS_TRUE;
 }
 
 static JSBool
+xml_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    return xml_getGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp);
+}
+
+static JSBool
 xml_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
-    return xml_getAttributes(cx, obj, id, attrsp);
+    return xml_getGenericAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
 xml_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return xml_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
-}
-
-static JSBool
-xml_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+    return xml_getGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+}
+
+static JSBool
+xml_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     JSBool found;
     if (!HasProperty(cx, obj, IdToJsval(id), &found))
         return false;
 
     if (found) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_CANT_SET_XML_ATTRS);
         return false;
     }
     return true;
 }
 
 static JSBool
+xml_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp)
+{
+    return xml_setGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp);
+}
+
+static JSBool
 xml_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
-    return xml_setAttributes(cx, obj, id, attrsp);
+    return xml_setGenericAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
 xml_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return xml_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return xml_setGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 static JSBool
 xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     JSXML *xml;
     jsval idval;
     uint32 index;
@@ -5319,22 +5331,22 @@ JS_FRIEND_DATA(Class) js::XMLClass = {
         xml_getGeneric,
         xml_getProperty,
         xml_getElement,
         xml_getSpecial,
         xml_setProperty,
         xml_setProperty,
         xml_setElement,
         xml_setSpecial,
-        xml_getAttributes,
-        xml_getAttributes,
+        xml_getGenericAttributes,
+        xml_getPropertyAttributes,
         xml_getElementAttributes,
         xml_getSpecialAttributes,
-        xml_setAttributes,
-        xml_setAttributes,
+        xml_setGenericAttributes,
+        xml_setPropertyAttributes,
         xml_setElementAttributes,
         xml_setSpecialAttributes,
         xml_deleteProperty,
         xml_deleteProperty,
         xml_deleteElement,
         xml_deleteSpecial,
         xml_enumerate,
         xml_typeOf,
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3161,17 +3161,17 @@ CopyProperty(JSContext *cx, JSObject *ob
         if (!desc.obj)
             return true;
     } else {
         if (!referent->lookupGeneric(cx, id, objp, &prop))
             return false;
         if (*objp != referent)
             return true;
         if (!referent->getGeneric(cx, id, &desc.value) ||
-            !referent->getAttributes(cx, id, &desc.attrs)) {
+            !referent->getGenericAttributes(cx, id, &desc.attrs)) {
             return false;
         }
         desc.attrs &= JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
         desc.getter = JS_PropertyStub;
         desc.setter = JS_StrictPropertyStub;
         desc.shortid = 0;
     }