Bug 687621 - Further split ObjectOps to add a third property type (and temporarily a fourth to use for a property of indeterminate type), to encapsulate object-valued jsids and properties that don't fit in the property name/element distinction. r=luke
authorJeff Walden <jwalden@mit.edu>
Fri, 12 Aug 2011 14:26:48 -0400
changeset 77361 ff35c22fc423a082b3c875014a63ee08b76e2acd
parent 77360 2f1a5172cced699b9ba99b74148ef11637eb04e1
child 77362 b27c16ee468c2d5a694fd34472778d502dfb73b7
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersluke
bugs687621
milestone9.0a1
Bug 687621 - Further split ObjectOps to add a third property type (and temporarily a fourth to use for a property of indeterminate type), to encapsulate object-valued jsids and properties that don't fit in the property name/element distinction. r=luke
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsclass.h
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/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcwrappednativejsops.cpp
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2972,17 +2972,17 @@ struct JSClass {
     JSCheckAccessOp     checkAccess;
     JSNative            call;
     JSNative            construct;
     JSXDRObjectOp       xdrObject;
     JSHasInstanceOp     hasInstance;
     JSTraceOp           trace;
 
     JSClassInternal     reserved1;
-    void                *reserved[26];
+    void                *reserved[40];
 };
 
 #define JSCLASS_HAS_PRIVATE             (1<<0)  /* objects have private slot */
 #define JSCLASS_NEW_ENUMERATE           (1<<1)  /* has JSNewEnumerateOp hook */
 #define JSCLASS_NEW_RESOLVE             (1<<2)  /* has JSNewResolveOp hook */
 #define JSCLASS_PRIVATE_IS_NSISUPPORTS  (1<<3)  /* private is (nsISupports *) */
 #define JSCLASS_CONCURRENT_FINALIZER    (1<<4)  /* finalize is called on background thread */
 #define JSCLASS_NEW_RESOLVE_GETS_START  (1<<5)  /* JSNewResolveOp gets starting
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -748,16 +748,23 @@ array_lookupElement(JSContext *cx, JSObj
     if (JSObject *proto = obj->getProto())
         return proto->lookupElement(cx, index, objp, propp);
 
     *objp = NULL;
     *propp = NULL;
     return true;
 }
 
+static JSBool
+array_lookupSpecial(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+                    JSProperty **propp)
+{
+    return array_lookupProperty(cx, obj, id, objp, propp);
+}
+
 JSBool
 js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32 i;
     if (!js_IdIsIndex(id, &i)) {
         JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
@@ -852,16 +859,22 @@ array_getElement(JSContext *cx, JSObject
     if (!prop || !obj2->isNative())
         return true;
 
     const Shape *shape = (const Shape *) prop;
     return js_NativeGet(cx, obj, obj2, shape, JSGET_METHOD_BARRIER, vp);
 }
 
 static JSBool
+array_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+{
+    return array_getProperty(cx, obj, receiver, id, vp);
+}
+
+static JSBool
 slowarray_addProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     jsuint index, length;
 
     if (!js_IdIsIndex(id, &index))
         return JS_TRUE;
     length = obj->getArrayLength();
     if (index >= length)
@@ -945,16 +958,22 @@ array_setElement(JSContext *cx, JSObject
         return true;
     } while (false);
 
     if (!obj->makeDenseArraySlow(cx))
         return false;
     return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
 }
 
+static JSBool
+array_setSpecial(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+{
+    return array_setProperty(cx, obj, id, vp, strict);
+}
+
 JSBool
 js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
 {
     /*
      * Walk up the prototype chain and see if this indexed element already
      * exists. If we hit the end of the prototype chain, it's safe to set the
      * element on the original object.
      */
@@ -1047,44 +1066,63 @@ array_defineElement(JSContext *cx, JSObj
     if (!obj->makeDenseArraySlow(cx))
         return false;
     return js_DefineElement(cx, obj, index, value, getter, setter, attrs);
 }
 
 } // namespace js
 
 static JSBool
+array_defineSpecial(JSContext *cx, JSObject *obj, jsid id, const Value *value,
+                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    return array_defineProperty(cx, obj, id, value, getter, setter, attrs);
+}
+
+static JSBool
 array_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     *attrsp = JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)
         ? JSPROP_PERMANENT : JSPROP_ENUMERATE;
     return JS_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, jsid id, uintN *attrsp)
+{
+    return array_getAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 array_setAttributes(JSContext *cx, JSObject *obj, jsid id, 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, jsid id, uintN *attrsp)
+{
+    return array_setAttributes(cx, obj, id, attrsp);
+}
+
 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)
 {
     uint32 i;
 
@@ -1124,16 +1162,22 @@ array_deleteElement(JSContext *cx, JSObj
         return false;
 
     rval->setBoolean(true);
     return true;
 }
 
 } // namespace js
 
+static JSBool
+array_deleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
+{
+    return array_deleteProperty(cx, obj, id, rval, strict);
+}
+
 static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32 initLength = obj->getDenseArrayInitializedLength();
     MarkValueRange(trc, initLength, obj->getDenseArrayElements(), "element");
 }
@@ -1171,29 +1215,43 @@ Class js::ArrayClass = {
     NULL,           /* call        */
     NULL,           /* construct   */
     NULL,           /* xdrObject   */
     NULL,           /* hasInstance */
     array_trace,    /* trace       */
     JS_NULL_CLASS_EXT,
     {
         array_lookupProperty,
+        array_lookupProperty,
         array_lookupElement,
+        array_lookupSpecial,
+        array_defineProperty,
         array_defineProperty,
         array_defineElement,
+        array_defineSpecial,
+        array_getProperty,
         array_getProperty,
         array_getElement,
+        array_getSpecial,
+        array_setProperty,
         array_setProperty,
         array_setElement,
+        array_setSpecial,
+        array_getAttributes,
         array_getAttributes,
         array_getElementAttributes,
+        array_getSpecialAttributes,
+        array_setAttributes,
         array_setAttributes,
         array_setElementAttributes,
+        array_setSpecialAttributes,
+        array_deleteProperty,
         array_deleteProperty,
         array_deleteElement,
+        array_deleteSpecial,
         NULL,       /* enumerate      */
         array_typeOf,
         array_fix,
         NULL,       /* thisObject     */
         NULL,       /* clear          */
     }
 };
 
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -50,43 +50,71 @@
 
 namespace js {
 
 class AutoIdVector;
 
 /* js::Class operation signatures. */
 
 typedef JSBool
+(* LookupGenericOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+                    JSProperty **propp);
+typedef JSBool
 (* LookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
                  JSProperty **propp);
 typedef JSBool
 (* LookupElementOp)(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp,
                     JSProperty **propp);
 typedef JSBool
+(* LookupSpecialOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+                    JSProperty **propp);
+typedef JSBool
+(* DefineGenericOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
+                    PropertyOp getter, StrictPropertyOp setter, uintN attrs);
+typedef JSBool
 (* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                  PropertyOp getter, StrictPropertyOp setter, uintN attrs);
 typedef JSBool
 (* DefineElementOp)(JSContext *cx, JSObject *obj, uint32 index, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, uintN attrs);
 typedef JSBool
+(* DefineSpecialOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
+                    PropertyOp getter, StrictPropertyOp setter, uintN attrs);
+typedef JSBool
+(* GenericIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
+typedef JSBool
 (* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
 typedef JSBool
 (* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp);
 typedef JSBool
+(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
+typedef JSBool
+(* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
+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, jsid id, 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);
 typedef JSBool
 (* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 typedef JSBool
+(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, jsid id, 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);
 typedef JSBool
 (* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
+typedef JSBool
+(* DeleteSpecialOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
 typedef JSType
 (* TypeOfOp)(JSContext *cx, JSObject *obj);
 
 /*
  * Prepare to make |obj| non-extensible; in particular, fully resolve its properties.
  * On error, return false.
  * If |obj| is now ready to become non-extensible, set |*fixed| to true and return true.
  * If |obj| refuses to become non-extensible, set |*fixed| to false and return true; the
@@ -146,40 +174,55 @@ struct ClassExtension
      */
     bool                isWrappedNative;
 };
 
 #define JS_NULL_CLASS_EXT   {NULL,NULL,NULL,NULL,NULL,false}
 
 struct ObjectOps
 {
+    LookupGenericOp     lookupGeneric;
     LookupPropOp        lookupProperty;
     LookupElementOp     lookupElement;
+    LookupSpecialOp     lookupSpecial;
+    DefineGenericOp     defineGeneric;
     DefinePropOp        defineProperty;
     DefineElementOp     defineElement;
+    DefineSpecialOp     defineSpecial;
+    GenericIdOp         getGeneric;
     PropertyIdOp        getProperty;
     ElementIdOp         getElement;
+    SpecialIdOp         getSpecial;
+    StrictGenericIdOp   setGeneric;
     StrictPropertyIdOp  setProperty;
     StrictElementIdOp   setElement;
+    StrictSpecialIdOp   setSpecial;
+    GenericAttributesOp getGenericAttributes;
     AttributesOp        getAttributes;
     ElementAttributesOp getElementAttributes;
+    SpecialAttributesOp getSpecialAttributes;
+    GenericAttributesOp setGenericAttributes;
     AttributesOp        setAttributes;
     ElementAttributesOp setElementAttributes;
+    SpecialAttributesOp setSpecialAttributes;
+    DeleteGenericOp     deleteGeneric;
     DeleteIdOp          deleteProperty;
     DeleteElementOp     deleteElement;
+    DeleteSpecialOp     deleteSpecial;
 
     JSNewEnumerateOp    enumerate;
     TypeOfOp            typeOf;
     FixOp               fix;
     ObjectOp            thisObject;
     FinalizeOp          clear;
 };
 
 #define JS_NULL_OBJECT_OPS                                                    \
     {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,   \
+     NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,   \
      NULL,NULL,NULL,NULL,NULL}
 
 struct Class
 {
     JS_CLASS_MEMBERS;
     ClassExtension      ext;
     ObjectOps           ops;
     uint8               pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3273,91 +3273,127 @@ with_LookupElement(JSContext *cx, JSObje
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return with_LookupProperty(cx, obj, id, objp, propp);
 }
 
 static JSBool
+with_LookupSpecial(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp)
+{
+    return with_LookupProperty(cx, obj, id, objp, propp);
+}
+
+static JSBool
 with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     return obj->getProto()->getProperty(cx, id, vp);
 }
 
 static JSBool
 with_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return with_GetProperty(cx, obj, receiver, id, vp);
 }
 
 static JSBool
+with_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+{
+    return with_GetProperty(cx, obj, receiver, id, vp);
+}
+
+static JSBool
 with_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     return obj->getProto()->setProperty(cx, id, vp, strict);
 }
 
 static JSBool
 with_SetElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return with_SetProperty(cx, obj, id, vp, strict);
 }
 
 static JSBool
+with_SetSpecial(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+{
+    return with_SetProperty(cx, obj, id, vp, strict);
+}
+
+static JSBool
 with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     return obj->getProto()->getAttributes(cx, id, 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);
 }
 
 static JSBool
+with_GetSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return with_GetAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     return obj->getProto()->setAttributes(cx, id, 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);
 }
 
 static JSBool
+with_SetSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return with_SetAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     return obj->getProto()->deleteProperty(cx, id, rval, strict);
 }
 
 static JSBool
 with_DeleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return with_DeleteProperty(cx, obj, id, rval, strict);
 }
 
 static JSBool
+with_DeleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
+{
+    return with_DeleteProperty(cx, obj, id, rval, strict);
+}
+
+static JSBool
 with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                Value *statep, jsid *idp)
 {
     return obj->getProto()->enumerate(cx, enum_op, statep, idp);
 }
 
 static JSType
 with_TypeOf(JSContext *cx, JSObject *obj)
@@ -3387,29 +3423,43 @@ Class js::WithClass = {
     NULL,                    /* call        */
     NULL,                    /* construct   */
     NULL,                    /* xdrObject   */
     NULL,                    /* hasInstance */
     NULL,                    /* trace       */
     JS_NULL_CLASS_EXT,
     {
         with_LookupProperty,
+        with_LookupProperty,
         with_LookupElement,
-        NULL,                /* defineProperty */
-        NULL,                /* defineElement */
+        with_LookupSpecial,
+        NULL,             /* defineGeneric */
+        NULL,             /* defineProperty */
+        NULL,             /* defineElement */
+        NULL,             /* defineSpecial */
+        with_GetProperty,
         with_GetProperty,
         with_GetElement,
+        with_GetSpecial,
+        with_SetProperty,
         with_SetProperty,
         with_SetElement,
+        with_SetSpecial,
+        with_GetAttributes,
         with_GetAttributes,
         with_GetElementAttributes,
+        with_GetSpecialAttributes,
+        with_SetAttributes,
         with_SetAttributes,
         with_SetElementAttributes,
+        with_SetSpecialAttributes,
+        with_DeleteProperty,
         with_DeleteProperty,
         with_DeleteElement,
+        with_DeleteSpecial,
         with_Enumerate,
         with_TypeOf,
         NULL,             /* fix   */
         with_ThisObject,
         NULL,             /* clear */
     }
 };
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1436,22 +1436,21 @@ struct JSObject : js::gc::Cell {
                          JSStrictPropertyOp setter = JS_StrictPropertyStub,
                          uintN attrs = JSPROP_ENUMERATE)
     {
         js::DefineElementOp op = getOps()->defineElement;
         return (op ? op : js_DefineElement)(cx, this, index, &value, getter, setter, attrs);
     }
 
     inline JSBool getProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp);
-
     inline JSBool getElement(JSContext *cx, JSObject *receiver, uint32 index, js::Value *vp);
 
     inline JSBool getProperty(JSContext *cx, jsid id, js::Value *vp);
-
     inline JSBool getElement(JSContext *cx, uint32 index, js::Value *vp);
+    inline JSBool getSpecial(JSContext *cx, jsid id, js::Value *vp);
 
     JSBool setProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict) {
         if (getOps()->setProperty)
             return nonNativeSetProperty(cx, id, vp, strict);
         return js_SetPropertyHelper(cx, this, id, 0, vp, strict);
     }
 
     JSBool setElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict) {
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1120,16 +1120,22 @@ inline JSBool
 JSObject::deleteElement(JSContext *cx, uint32 index, js::Value *rval, JSBool strict)
 {
     jsid id;
     if (!js::IndexToId(cx, index, &id))
         return false;
     return deleteProperty(cx, id, rval, strict);
 }
 
+inline JSBool
+JSObject::getSpecial(JSContext *cx, jsid id, js::Value *vp)
+{
+    return getProperty(cx, id, vp);
+}
+
 static inline bool
 js_IsCallable(const js::Value &v)
 {
     return v.isObject() && v.toObject().isCallable();
 }
 
 inline JSObject *
 js_UnwrapWithObject(JSContext *cx, JSObject *withobj)
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -907,16 +907,22 @@ proxy_LookupElement(JSContext *cx, JSObj
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_LookupProperty(cx, obj, id, objp, propp);
 }
 
 static JSBool
+proxy_LookupSpecial(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp)
+{
+    return proxy_LookupProperty(cx, obj, id, objp, propp);
+}
+
+static JSBool
 proxy_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                      PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     id = js_CheckForStringIndex(id);
 
     AutoPropertyDescriptorRooter desc(cx);
     desc.obj = obj;
     desc.value = *value;
@@ -933,16 +939,23 @@ proxy_DefineElement(JSContext *cx, JSObj
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_DefineProperty(cx, obj, id, value, getter, setter, attrs);
 }
 
 static JSBool
+proxy_DefineSpecial(JSContext *cx, JSObject *obj, jsid id, const Value *value,
+                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    return proxy_DefineProperty(cx, obj, id, value, getter, setter, attrs);
+}
+
+static JSBool
 proxy_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     id = js_CheckForStringIndex(id);
 
     return JSProxy::get(cx, obj, receiver, id, vp);
 }
 
 static JSBool
@@ -950,16 +963,22 @@ proxy_GetElement(JSContext *cx, JSObject
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_GetProperty(cx, obj, receiver, id, vp);
 }
 
 static JSBool
+proxy_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+{
+    return proxy_GetProperty(cx, obj, receiver, id, vp);
+}
+
+static JSBool
 proxy_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     id = js_CheckForStringIndex(id);
 
     return JSProxy::set(cx, obj, obj, id, strict, vp);
 }
 
 static JSBool
@@ -967,16 +986,22 @@ proxy_SetElement(JSContext *cx, JSObject
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_SetProperty(cx, obj, id, vp, strict);
 }
 
 static JSBool
+proxy_SetSpecial(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+{
+    return proxy_SetProperty(cx, obj, id, vp, strict);
+}
+
+static JSBool
 proxy_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     id = js_CheckForStringIndex(id);
 
     AutoPropertyDescriptorRooter desc(cx);
     if (!JSProxy::getOwnPropertyDescriptor(cx, obj, id, false, &desc))
         return false;
     *attrsp = desc.attrs;
@@ -988,16 +1013,22 @@ proxy_GetElementAttributes(JSContext *cx
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_GetAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
+proxy_GetSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return proxy_GetAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 proxy_SetAttributes(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 (!JSProxy::getOwnPropertyDescriptor(cx, obj, id, true, &desc))
         return false;
@@ -1010,16 +1041,22 @@ proxy_SetElementAttributes(JSContext *cx
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_SetAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
+proxy_SetSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return proxy_SetAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 proxy_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     id = js_CheckForStringIndex(id);
 
     // TODO: throwing away strict
     bool deleted;
     if (!JSProxy::delete_(cx, obj, id, &deleted) || !js_SuppressDeletedProperty(cx, obj, id))
         return false;
@@ -1031,16 +1068,22 @@ static JSBool
 proxy_DeleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_DeleteProperty(cx, obj, id, rval, strict);
 }
 
+static JSBool
+proxy_DeleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
+{
+    return proxy_DeleteProperty(cx, obj, id, rval, strict);
+}
+
 static void
 proxy_TraceObject(JSTracer *trc, JSObject *obj)
 {
     obj->getProxyHandler()->trace(trc, obj);
     MarkCrossCompartmentValue(trc, obj->getProxyPrivate(), "private");
     MarkCrossCompartmentValue(trc, obj->getProxyExtra(), "extra");
     if (obj->isFunctionProxy()) {
         MarkCrossCompartmentValue(trc, GetCall(obj), "call");
@@ -1118,29 +1161,43 @@ JS_FRIEND_DATA(Class) js::ObjectProxyCla
     NULL,                    /* call        */
     NULL,                    /* construct   */
     NULL,                    /* xdrObject   */
     proxy_HasInstance,       /* hasInstance */
     proxy_TraceObject,       /* trace       */
     JS_NULL_CLASS_EXT,
     {
         proxy_LookupProperty,
+        proxy_LookupProperty,
         proxy_LookupElement,
+        proxy_LookupSpecial,
+        proxy_DefineProperty,
         proxy_DefineProperty,
         proxy_DefineElement,
+        proxy_DefineSpecial,
+        proxy_GetProperty,
         proxy_GetProperty,
         proxy_GetElement,
+        proxy_GetSpecial,
+        proxy_SetProperty,
         proxy_SetProperty,
         proxy_SetElement,
+        proxy_SetSpecial,
+        proxy_GetAttributes,
         proxy_GetAttributes,
         proxy_GetElementAttributes,
+        proxy_GetSpecialAttributes,
+        proxy_SetAttributes,
         proxy_SetAttributes,
         proxy_SetElementAttributes,
+        proxy_SetSpecialAttributes,
+        proxy_DeleteProperty,
         proxy_DeleteProperty,
         proxy_DeleteElement,
+        proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         proxy_TypeOf,
         proxy_Fix,           /* fix             */
         NULL,                /* thisObject      */
         NULL,                /* clear           */
     }
 };
 
@@ -1165,29 +1222,43 @@ JS_FRIEND_DATA(Class) js::OuterWindowPro
     {
         NULL,                /* equality    */
         NULL,                /* outerObject */
         proxy_innerObject,
         NULL                 /* unused */
     },
     {
         proxy_LookupProperty,
+        proxy_LookupProperty,
         proxy_LookupElement,
+        proxy_LookupSpecial,
+        proxy_DefineProperty,
         proxy_DefineProperty,
         proxy_DefineElement,
+        proxy_DefineSpecial,
+        proxy_GetProperty,
         proxy_GetProperty,
         proxy_GetElement,
+        proxy_GetSpecial,
+        proxy_SetProperty,
         proxy_SetProperty,
         proxy_SetElement,
+        proxy_SetSpecial,
+        proxy_GetAttributes,
         proxy_GetAttributes,
         proxy_GetElementAttributes,
+        proxy_GetSpecialAttributes,
+        proxy_SetAttributes,
         proxy_SetAttributes,
         proxy_SetElementAttributes,
+        proxy_SetSpecialAttributes,
+        proxy_DeleteProperty,
         proxy_DeleteProperty,
         proxy_DeleteElement,
+        proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         NULL,                /* typeof          */
         NULL,                /* fix             */
         NULL,                /* thisObject      */
         NULL,                /* clear           */
     }
 };
 
@@ -1224,29 +1295,43 @@ JS_FRIEND_DATA(Class) js::FunctionProxyC
     proxy_Call,
     proxy_Construct,
     NULL,                    /* xdrObject   */
     FunctionClass.hasInstance,
     proxy_TraceFunction,     /* trace       */
     JS_NULL_CLASS_EXT,
     {
         proxy_LookupProperty,
+        proxy_LookupProperty,
         proxy_LookupElement,
+        proxy_LookupSpecial,
+        proxy_DefineProperty,
         proxy_DefineProperty,
         proxy_DefineElement,
+        proxy_DefineSpecial,
+        proxy_GetProperty,
         proxy_GetProperty,
         proxy_GetElement,
+        proxy_GetSpecial,
+        proxy_SetProperty,
         proxy_SetProperty,
         proxy_SetElement,
+        proxy_SetSpecial,
+        proxy_GetAttributes,
         proxy_GetAttributes,
         proxy_GetElementAttributes,
+        proxy_GetSpecialAttributes,
+        proxy_SetAttributes,
         proxy_SetAttributes,
         proxy_SetElementAttributes,
+        proxy_SetSpecialAttributes,
+        proxy_DeleteProperty,
         proxy_DeleteProperty,
         proxy_DeleteElement,
+        proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         proxy_TypeOf,
         NULL,                /* fix             */
         NULL,                /* thisObject      */
         NULL,                /* clear           */
     }
 };
 
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -306,16 +306,23 @@ ArrayBuffer::obj_lookupElement(JSContext
         return proto->lookupElement(cx, index, objp, propp);
 
     *objp = NULL;
     *propp = NULL;
     return true;
 }
 
 JSBool
+ArrayBuffer::obj_lookupSpecial(JSContext *cx, JSObject *obj, jsid id,
+                               JSObject **objp, JSProperty **propp)
+{
+    return obj_lookupProperty(cx, obj, id, objp, propp);
+}
+
+JSBool
 ArrayBuffer::obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
         return true;
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
@@ -329,16 +336,23 @@ ArrayBuffer::obj_defineElement(JSContext
 {
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_DefineElement(cx, delegate, index, v, getter, setter, attrs);
 }
 
 JSBool
+ArrayBuffer::obj_defineSpecial(JSContext *cx, JSObject *obj, jsid id, const Value *v,
+                               PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    return obj_defineProperty(cx, obj, id, v, getter, setter, attrs);
+}
+
+JSBool
 ArrayBuffer::obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     obj = getArrayBuffer(obj);
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         vp->setInt32(obj->arrayBufferByteLength());
         return true;
     }
 
@@ -353,16 +367,22 @@ ArrayBuffer::obj_getElement(JSContext *c
 {
     JSObject *delegate = DelegateObject(cx, getArrayBuffer(obj));
     if (!delegate)
         return false;
     return js_GetElement(cx, delegate, receiver, index, vp);
 }
 
 JSBool
+ArrayBuffer::obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+{
+    return obj_getProperty(cx, obj, receiver, id, vp);
+}
+
+JSBool
 ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
         return true;
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.protoAtom)) {
         // setting __proto__ = null
         // effectively removes the prototype chain.
@@ -417,16 +437,22 @@ ArrayBuffer::obj_setElement(JSContext *c
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
 
     return js_SetElementHelper(cx, delegate, index, 0, vp, strict);
 }
 
 JSBool
+ArrayBuffer::obj_setSpecial(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+{
+    return obj_setProperty(cx, obj, id, vp, strict);
+}
+
+JSBool
 ArrayBuffer::obj_getAttributes(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);
@@ -440,16 +466,22 @@ ArrayBuffer::obj_getElementAttributes(JS
 {
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_GetElementAttributes(cx, delegate, index, attrsp);
 }
 
 JSBool
+ArrayBuffer::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return obj_getAttributes(cx, obj, id, attrsp);
+}
+
+JSBool
 ArrayBuffer::obj_setAttributes(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;
     }
 
@@ -464,16 +496,22 @@ ArrayBuffer::obj_setElementAttributes(JS
 {
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_SetElementAttributes(cx, delegate, index, attrsp);
 }
 
 JSBool
+ArrayBuffer::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return obj_setSpecialAttributes(cx, obj, id, 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;
     }
 
     JSObject *delegate = DelegateObject(cx, obj);
@@ -487,16 +525,22 @@ ArrayBuffer::obj_deleteElement(JSContext
 {
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_DeleteElement(cx, delegate, index, rval, strict);
 }
 
 JSBool
+ArrayBuffer::obj_deleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
+{
+    return obj_deleteProperty(cx, obj, id, rval, strict);
+}
+
+JSBool
 ArrayBuffer::obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
               Value *statep, jsid *idp)
 {
     statep->setNull();
     return true;
 }
 
 JSType
@@ -645,45 +689,64 @@ TypedArray::obj_lookupElement(JSContext 
         return proto->lookupElement(cx, index, objp, propp);
 
     *objp = NULL;
     *propp = NULL;
     return true;
 }
 
 JSBool
+TypedArray::obj_lookupSpecial(JSContext *cx, JSObject *obj, jsid id,
+                              JSObject **objp, JSProperty **propp)
+{
+    return obj_lookupProperty(cx, obj, id, objp, propp);
+}
+
+JSBool
 TypedArray::obj_getAttributes(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_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
 {
     *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
 
 JSBool
+TypedArray::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return obj_getAttributes(cx, obj, id, attrsp);
+}
+
+JSBool
 TypedArray::obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, 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, jsid id, uintN *attrsp)
+{
+    return obj_setAttributes(cx, obj, id, attrsp);
+}
+
 /* static */ int
 TypedArray::lengthOffset()
 {
     return JSObject::getFixedSlotOffset(FIELD_LENGTH) + offsetof(jsval_layout, s.payload);
 }
 
 /* static */ int
 TypedArray::dataOffset()
@@ -931,16 +994,22 @@ class TypedArrayTemplate
 
         if (!prop || !obj2->isNative())
             return true;
 
         const Shape *shape = (Shape *) prop;
         return js_NativeGet(cx, obj, obj2, shape, JSGET_METHOD_BARRIER, vp);
     }
 
+    static JSBool
+    obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+    {
+        return obj_getProperty(cx, obj, receiver, id, vp);
+    }
+
     static bool
     setElementTail(JSContext *cx, JSObject *tarray, uint32 index, Value *vp, JSBool strict)
     {
         JS_ASSERT(tarray);
         JS_ASSERT(index < getLength(tarray));
 
         if (vp->isInt32()) {
             setIndex(tarray, index, NativeType(vp->toInt32()));
@@ -1031,16 +1100,22 @@ class TypedArrayTemplate
             vp->setUndefined();
             return true;
         }
 
         return setElementTail(cx, tarray, index, vp, strict);
     }
 
     static JSBool
+    obj_setSpecial(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+    {
+        return obj_setProperty(cx, obj, id, vp, strict);
+    }
+
+    static JSBool
     obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, uintN attrs)
     {
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
             return true;
 
         Value tmp = *v;
         return obj_setProperty(cx, obj, id, &tmp, false);
@@ -1050,16 +1125,23 @@ class TypedArrayTemplate
     obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, uintN attrs)
     {
         Value tmp = *v;
         return obj_setElement(cx, obj, index, &tmp, false);
     }
 
     static JSBool
+    obj_defineSpecial(JSContext *cx, JSObject *obj, jsid id, const Value *v,
+                      PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+    {
+        return obj_defineProperty(cx, obj, id, v, getter, setter, attrs);
+    }
+
+    static JSBool
     obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
     {
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
             rval->setBoolean(false);
             return true;
         }
 
         JSObject *tarray = TypedArray::getTypedArray(obj);
@@ -1085,16 +1167,22 @@ class TypedArrayTemplate
             return true;
         }
 
         rval->setBoolean(true);
         return true;
     }
 
     static JSBool
+    obj_deleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
+    {
+        return obj_deleteProperty(cx, obj, id, rval, strict);
+    }
+
+    static JSBool
     obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                   Value *statep, jsid *idp)
     {
         JSObject *tarray = getTypedArray(obj);
         JS_ASSERT(tarray);
 
         /*
          * Iteration is "length" (if JSENUMERATE_INIT_ALL), then [0, length).
@@ -1917,29 +2005,43 @@ Class js::ArrayBufferClass = {
     NULL,           /* call        */
     NULL,           /* construct   */
     NULL,           /* xdrObject   */
     NULL,           /* hasInstance */
     ArrayBuffer::obj_trace,
     JS_NULL_CLASS_EXT,
     {
         ArrayBuffer::obj_lookupProperty,
+        ArrayBuffer::obj_lookupProperty,
         ArrayBuffer::obj_lookupElement,
+        ArrayBuffer::obj_lookupSpecial,
+        ArrayBuffer::obj_defineProperty,
         ArrayBuffer::obj_defineProperty,
         ArrayBuffer::obj_defineElement,
+        ArrayBuffer::obj_defineSpecial,
+        ArrayBuffer::obj_getProperty,
         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_getElementAttributes,
+        ArrayBuffer::obj_getSpecialAttributes,
+        ArrayBuffer::obj_setAttributes,
         ArrayBuffer::obj_setAttributes,
         ArrayBuffer::obj_setElementAttributes,
+        ArrayBuffer::obj_setSpecialAttributes,
+        ArrayBuffer::obj_deleteProperty,
         ArrayBuffer::obj_deleteProperty,
         ArrayBuffer::obj_deleteElement,
+        ArrayBuffer::obj_deleteSpecial,
         ArrayBuffer::obj_enumerate,
         ArrayBuffer::obj_typeOf,
         NULL,       /* thisObject      */
         NULL,       /* clear           */
     }
 };
 
 JSPropertySpec ArrayBuffer::jsprops[] = {
@@ -2015,29 +2117,43 @@ JSFunctionSpec _typedArray::jsfuncs[] = 
     NULL,                    /* call        */                                 \
     NULL,                    /* construct   */                                 \
     NULL,                    /* xdrObject   */                                 \
     NULL,                    /* hasInstance */                                 \
     _typedArray::obj_trace,  /* trace       */                                 \
     JS_NULL_CLASS_EXT,                                                         \
     {                                                                          \
         _typedArray::obj_lookupProperty,                                       \
+        _typedArray::obj_lookupProperty,                                       \
         _typedArray::obj_lookupElement,                                        \
+        _typedArray::obj_lookupSpecial,                                        \
+        _typedArray::obj_defineProperty,                                       \
         _typedArray::obj_defineProperty,                                       \
         _typedArray::obj_defineElement,                                        \
+        _typedArray::obj_defineSpecial,                                        \
+        _typedArray::obj_getProperty,                                          \
         _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_getElementAttributes,                                 \
+        _typedArray::obj_getSpecialAttributes,                                 \
+        _typedArray::obj_setAttributes,                                        \
         _typedArray::obj_setAttributes,                                        \
         _typedArray::obj_setElementAttributes,                                 \
+        _typedArray::obj_setSpecialAttributes,                                 \
+        _typedArray::obj_deleteProperty,                                       \
         _typedArray::obj_deleteProperty,                                       \
         _typedArray::obj_deleteElement,                                        \
+        _typedArray::obj_deleteSpecial,                                        \
         _typedArray::obj_enumerate,                                            \
         _typedArray::obj_typeOf,                                               \
         NULL,                /* thisObject  */                                 \
         NULL,                /* clear       */                                 \
     }                                                                          \
 }
 
 template<class ArrayType>
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -78,54 +78,76 @@ struct JS_FRIEND_API(ArrayBuffer) {
     obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                        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, jsid id, JSObject **objp, JSProperty **propp);
+
+    static JSBool
     obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, uintN attrs);
 
     static JSBool
     obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v,
                       PropertyOp getter, StrictPropertyOp setter, uintN attrs);
 
     static JSBool
+    obj_defineSpecial(JSContext *cx, JSObject *obj, jsid id, const Value *v,
+                      PropertyOp getter, StrictPropertyOp setter, uintN attrs);
+
+    static JSBool
     obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
 
     static JSBool
     obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp);
 
     static JSBool
+    obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
+
+    static JSBool
     obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
 
     static JSBool
     obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
 
     static JSBool
+    obj_setSpecial(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
+
+    static JSBool
     obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
     static JSBool
     obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 
     static JSBool
+    obj_getSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+
+    static JSBool
     obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
     static JSBool
     obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 
     static JSBool
+    obj_setSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, 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);
 
     static JSBool
+    obj_deleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict);
+
+    static JSBool
     obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                   Value *statep, jsid *idp);
 
     static JSType
     obj_typeOf(JSContext *cx, JSObject *obj);
 
     static JSObject *
     getArrayBuffer(JSObject *obj);
@@ -184,22 +206,26 @@ struct JS_FRIEND_API(TypedArray) {
     static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static JSBool prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
 
     static JSBool obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                                      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, jsid id,
+                                    JSObject **objp, JSProperty **propp);
 
     static JSBool obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
     static JSBool obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
+    static JSBool obj_getSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
     static JSBool obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
     static JSBool obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
+    static JSBool obj_setSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, 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);
     static void * getDataOffset(JSObject *obj);
 
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -4749,16 +4749,22 @@ xml_lookupElement(JSContext *cx, JSObjec
         return false;
 
     *objp = obj;
     *propp = (JSProperty *) shape;
     return true;
 }
 
 static JSBool
+xml_lookupSpecial(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp)
+{
+    return xml_lookupProperty(cx, obj, id, objp, propp);
+}
+
+static JSBool
 xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     if (IsFunctionObject(*v) || getter || setter ||
         (attrs & JSPROP_ENUMERATE) == 0 ||
         (attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) {
         return js_DefineProperty(cx, obj, id, v, getter, setter, attrs);
     }
@@ -4773,16 +4779,23 @@ xml_defineElement(JSContext *cx, JSObjec
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return xml_defineProperty(cx, obj, id, v, getter, setter, attrs);
 }
 
 static JSBool
+xml_defineSpecial(JSContext *cx, JSObject *obj, jsid id, const Value *v,
+                  PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    return xml_defineProperty(cx, obj, id, v, getter, setter, attrs);
+}
+
+static JSBool
 xml_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     if (JSID_IS_DEFAULT_XML_NAMESPACE(id)) {
         vp->setUndefined();
         return JS_TRUE;
     }
 
     return GetProperty(cx, obj, id, vp);
@@ -4793,31 +4806,43 @@ xml_getElement(JSContext *cx, JSObject *
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return xml_getProperty(cx, obj, receiver, id, vp);
 }
 
 static JSBool
+xml_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+{
+    return xml_getProperty(cx, obj, receiver, id, vp);
+}
+
+static JSBool
 xml_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     return PutProperty(cx, obj, id, strict, vp);
 }
 
 static JSBool
 xml_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return xml_setProperty(cx, obj, id, vp, strict);
 }
 
 static JSBool
+xml_setSpecial(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+{
+    return xml_setProperty(cx, obj, id, vp, strict);
+}
+
+static JSBool
 xml_getAttributes(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;
@@ -4828,16 +4853,22 @@ xml_getElementAttributes(JSContext *cx, 
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return xml_getAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
+xml_getSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return xml_getAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 xml_setAttributes(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,
@@ -4852,16 +4883,22 @@ xml_setElementAttributes(JSContext *cx, 
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return xml_setAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
+xml_setSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
+{
+    return xml_setAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     JSXML *xml;
     jsval idval;
     uint32 index;
     JSObject *nameqn;
     jsid funid;
 
@@ -4923,16 +4960,22 @@ xml_deleteElement(JSContext *cx, JSObjec
      */
     if (!obj->nativeEmpty() && !js_DeleteElement(cx, obj, index, rval, false))
         return false;
 
     rval->setBoolean(true);
     return true;
 }
 
+static JSBool
+xml_deleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
+{
+    return xml_deleteProperty(cx, obj, id, rval, strict);
+}
+
 static JSString *
 xml_toString_helper(JSContext *cx, JSXML *xml);
 
 JSBool
 xml_convert(JSContext *cx, JSObject *obj, JSType hint, Value *rval)
 {
     JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
     JS_ASSERT(obj->isXML());
@@ -5222,29 +5265,43 @@ JS_FRIEND_DATA(Class) js::XMLClass = {
     NULL,                 /* call        */
     NULL,                 /* construct   */
     NULL,                 /* xdrObject   */
     xml_hasInstance,
     xml_trace,
     JS_NULL_CLASS_EXT,
     {
         xml_lookupProperty,
+        xml_lookupProperty,
         xml_lookupElement,
+        xml_lookupSpecial,
+        xml_defineProperty,
         xml_defineProperty,
         xml_defineElement,
+        xml_defineSpecial,
+        xml_getProperty,
         xml_getProperty,
         xml_getElement,
+        xml_getSpecial,
+        xml_setProperty,
         xml_setProperty,
         xml_setElement,
+        xml_setSpecial,
+        xml_getAttributes,
         xml_getAttributes,
         xml_getElementAttributes,
+        xml_getSpecialAttributes,
+        xml_setAttributes,
         xml_setAttributes,
         xml_setElementAttributes,
+        xml_setSpecialAttributes,
+        xml_deleteProperty,
         xml_deleteProperty,
         xml_deleteElement,
+        xml_deleteSpecial,
         xml_enumerate,
         xml_typeOf,
         xml_fix,
         NULL,       /* thisObject     */
         xml_clear
     }
 };
 
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -1383,53 +1383,81 @@ extern void
 XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj);
 
 extern JSObject*
 XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
 
 // Macros to initialize Object or Function like XPC_WN classes
 #define XPC_WN_WithCall_ObjectOps                                             \
     {                                                                         \
+        nsnull, /* lookupGeneric */                                           \
         nsnull, /* lookupProperty */                                          \
         nsnull, /* lookupElement */                                           \
+        nsnull, /* lookupSpecial */                                           \
+        nsnull, /* defineGeneric */                                           \
         nsnull, /* defineProperty */                                          \
         nsnull, /* defineElement */                                           \
+        nsnull, /* defineSpecial */                                           \
+        nsnull, /* getGeneric    */                                           \
         nsnull, /* getProperty    */                                          \
         nsnull, /* getElement    */                                           \
+        nsnull, /* getSpecial    */                                           \
+        nsnull, /* setGeneric    */                                           \
         nsnull, /* setProperty    */                                          \
         nsnull, /* setElement    */                                           \
+        nsnull, /* setSpecial    */                                           \
+        nsnull, /* getGenericAttributes  */                                   \
         nsnull, /* getAttributes  */                                          \
         nsnull, /* getElementAttributes  */                                   \
+        nsnull, /* getSpecialAttributes  */                                   \
+        nsnull, /* setGenericAttributes  */                                   \
         nsnull, /* setAttributes  */                                          \
         nsnull, /* setElementAttributes  */                                   \
+        nsnull, /* setSpecialAttributes  */                                   \
+        nsnull, /* deleteGeneric */                                           \
         nsnull, /* deleteProperty */                                          \
         nsnull, /* deleteElement */                                           \
+        nsnull, /* deleteSpecial */                                           \
         XPC_WN_JSOp_Enumerate,                                                \
         XPC_WN_JSOp_TypeOf_Function,                                          \
         nsnull, /* fix            */                                          \
         XPC_WN_JSOp_ThisObject,                                               \
         XPC_WN_JSOp_Clear                                                     \
     }
 
 #define XPC_WN_NoCall_ObjectOps                                               \
     {                                                                         \
+        nsnull, /* lookupGeneric */                                           \
         nsnull, /* lookupProperty */                                          \
         nsnull, /* lookupElement */                                           \
+        nsnull, /* lookupSpecial */                                           \
+        nsnull, /* defineGeneric */                                           \
         nsnull, /* defineProperty */                                          \
         nsnull, /* defineElement */                                           \
+        nsnull, /* defineSpecial */                                           \
+        nsnull, /* getGeneric    */                                           \
         nsnull, /* getProperty    */                                          \
         nsnull, /* getElement    */                                           \
+        nsnull, /* getSpecial    */                                           \
+        nsnull, /* setGeneric    */                                           \
         nsnull, /* setProperty    */                                          \
         nsnull, /* setElement    */                                           \
+        nsnull, /* setSpecial    */                                           \
+        nsnull, /* getGenericAttributes  */                                   \
         nsnull, /* getAttributes  */                                          \
         nsnull, /* getElementAttributes  */                                   \
+        nsnull, /* getSpecialAttributes  */                                   \
+        nsnull, /* setGenericAttributes  */                                   \
         nsnull, /* setAttributes  */                                          \
         nsnull, /* setElementAttributes  */                                   \
+        nsnull, /* setSpecialAttributes  */                                   \
+        nsnull, /* deleteGeneric */                                           \
         nsnull, /* deleteProperty */                                          \
         nsnull, /* deleteElement */                                           \
+        nsnull, /* deleteSpecial */                                           \
         XPC_WN_JSOp_Enumerate,                                                \
         XPC_WN_JSOp_TypeOf_Object,                                            \
         nsnull, /* fix            */                                          \
         XPC_WN_JSOp_ThisObject,                                               \
         XPC_WN_JSOp_Clear                                                     \
     }
 
 // Maybe this macro should check for class->enumerate ==
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -901,30 +901,44 @@ js::Class XPC_WN_NoHelper_JSClass = {
         nsnull, // innerObject
         nsnull, // iteratorObject
         nsnull, // unused
         true,   // isWrappedNative
     },
    
     // ObjectOps
     {
+        nsnull, // lookupGeneric
         nsnull, // lookupProperty
         nsnull, // lookupElement
+        nsnull, // lookupSpecial
+        nsnull, // defineGeneric
         nsnull, // defineProperty
         nsnull, // defineElement
+        nsnull, // defineSpecial
+        nsnull, // getGeneric
         nsnull, // getProperty
         nsnull, // getElement
+        nsnull, // getSpecial
+        nsnull, // setGeneric
         nsnull, // setProperty
         nsnull, // setElement
+        nsnull, // setSpecial
+        nsnull, // getGenericAttributes
         nsnull, // getAttributes
         nsnull, // getElementAttributes
+        nsnull, // getSpecialAttributes
+        nsnull, // setGenericAttributes
         nsnull, // setAttributes
         nsnull, // setElementAttributes
+        nsnull, // setSpecialAttributes
+        nsnull, // deleteGeneric
         nsnull, // deleteProperty
         nsnull, // deleteElement
+        nsnull, // deleteSpecial
         XPC_WN_JSOp_Enumerate,
         XPC_WN_JSOp_TypeOf_Object,
         nsnull, // fix
         XPC_WN_JSOp_ThisObject,
         XPC_WN_JSOp_Clear
     }
 };