Bug 687621 - Introduce js::SpecialId, encapsulating the non-index, non-string bizarro property names. r=luke
authorJeff Walden <jwalden@mit.edu>
Tue, 20 Sep 2011 14:34:11 -0700
changeset 77363 b117f5ff61dbff1f4b6067309f39f160cf96d21e
parent 77362 b27c16ee468c2d5a694fd34472778d502dfb73b7
child 77364 faa84974073b789f235b2d3ca74cefeb41c82860
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersluke
bugs687621
milestone9.0a1
Bug 687621 - Introduce js::SpecialId, encapsulating the non-index, non-string bizarro property names. r=luke
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsclass.h
js/src/jsobj.cpp
js/src/jsproxy.cpp
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jsxml.cpp
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -236,17 +236,17 @@ inline Anchor<T>::~Anchor()
 class Value
 {
   public:
     /*
      * N.B. the default constructor leaves Value unitialized. Adding a default
      * constructor prevents Value from being stored in a union.
      */
 
-    /*** Mutatators ***/
+    /*** Mutators ***/
 
     JS_ALWAYS_INLINE
     void setNull() {
         data.asBits = BUILD_JSVAL(JSVAL_TAG_NULL, 0).asBits;
     }
 
     JS_ALWAYS_INLINE
     void setUndefined() {
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -749,20 +749,20 @@ array_lookupElement(JSContext *cx, JSObj
         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,
+array_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
                     JSProperty **propp)
 {
-    return array_lookupProperty(cx, obj, id, objp, propp);
+    return array_lookupProperty(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
 }
 
 JSBool
 js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32 i;
@@ -859,19 +859,19 @@ 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)
+array_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
 {
-    return array_getProperty(cx, obj, receiver, id, vp);
+    return array_getProperty(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
 }
 
 static JSBool
 slowarray_addProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     jsuint index, length;
 
     if (!js_IdIsIndex(id, &index))
@@ -959,19 +959,19 @@ array_setElement(JSContext *cx, JSObject
     } 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)
+array_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
-    return array_setProperty(cx, obj, id, vp, strict);
+    return array_setProperty(cx, obj, SPECIALID_TO_JSID(sid), 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
@@ -1066,20 +1066,20 @@ 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,
+array_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
-    return array_defineProperty(cx, obj, id, value, getter, setter, 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)
 {
     *attrsp = JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)
         ? JSPROP_PERMANENT : JSPROP_ENUMERATE;
     return JS_TRUE;
@@ -1088,19 +1088,19 @@ array_getAttributes(JSContext *cx, JSObj
 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)
+array_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return array_getAttributes(cx, obj, id, attrsp);
+    return array_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), 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;
 }
@@ -1108,19 +1108,19 @@ array_setAttributes(JSContext *cx, JSObj
 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)
+array_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return array_setAttributes(cx, obj, id, attrsp);
+    return array_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), 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)
 {
@@ -1163,19 +1163,19 @@ array_deleteElement(JSContext *cx, JSObj
 
     rval->setBoolean(true);
     return true;
 }
 
 } // namespace js
 
 static JSBool
-array_deleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
+array_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
 {
-    return array_deleteProperty(cx, obj, id, rval, strict);
+    return array_deleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
 }
 
 static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32 initLength = obj->getDenseArrayInitializedLength();
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -46,75 +46,195 @@
  * object behavior and, e.g., allows custom slow layout.
  */
 #include "jsapi.h"
 #include "jsprvtd.h"
 
 namespace js {
 
 class AutoIdVector;
+class SpecialId;
+
+static JS_ALWAYS_INLINE jsid
+SPECIALID_TO_JSID(const SpecialId &sid);
+
+/*
+ * We partition the ways to refer to a property into three: by an index
+ * (uint32); by a string whose characters do not represent an index
+ * (PropertyName, see vm/String.h); and by various special values.
+ *
+ * Special values are encoded using SpecialId, which is layout-compatible but
+ * non-interconvertible with jsid.  A SpecialId may be: an object (used by E4X
+ * and perhaps eventually by Harmony-proposed private names); JSID_VOID, which
+ * does not occur in JS scripts but may be used to indicate the absence of a
+ * valid identifier; or JS_DEFAULT_XML_NAMESPACE_ID, if E4X is enabled.
+ */
+
+class SpecialId {
+    uintptr_t bits;
+
+    /* Needs access to raw bits. */
+    friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
+
+    static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
+    static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
+    static const uintptr_t TYPE_DEFAULT_XML_NAMESPACE = JSID_TYPE_DEFAULT_XML_NAMESPACE;
+    static const uintptr_t TYPE_MASK = JSID_TYPE_MASK;
+
+    SpecialId(uintptr_t bits) : bits(bits) { }
+
+  public:
+    SpecialId() : bits(TYPE_VOID) { }
+
+    /* Object-valued */
+
+    SpecialId(JSObject &obj)
+      : bits(uintptr_t(&obj) | TYPE_OBJECT)
+    {
+        JS_ASSERT(&obj != NULL);
+        JS_ASSERT((uintptr_t(&obj) & TYPE_MASK) == 0);
+    }
+
+    bool isObject() const {
+        return (bits & TYPE_MASK) == TYPE_OBJECT && bits != TYPE_OBJECT;
+    }
+
+    JSObject *toObject() const {
+        JS_ASSERT(isObject());
+        return reinterpret_cast<JSObject *>(bits & ~TYPE_MASK);
+    }
+
+    /* Empty */
+
+    static SpecialId empty() {
+        SpecialId sid(TYPE_OBJECT);
+        JS_ASSERT(sid.isEmpty());
+        return sid;
+    }
+
+    bool isEmpty() const {
+        return bits == TYPE_OBJECT;
+    }
+
+    /* Void */
+
+    static SpecialId voidId() {
+        SpecialId sid(TYPE_VOID);
+        JS_ASSERT(sid.isVoid());
+        return sid;
+    }
+
+    bool isVoid() const {
+        return bits == TYPE_VOID;
+    }
+
+    /* Default XML namespace */
+
+    static SpecialId defaultXMLNamespace() {
+        SpecialId sid(TYPE_DEFAULT_XML_NAMESPACE);
+        JS_ASSERT(sid.isDefaultXMLNamespace());
+        return sid;
+    }
+
+    bool isDefaultXMLNamespace() const {
+        return bits == TYPE_DEFAULT_XML_NAMESPACE;
+    }
+};
+
+static JS_ALWAYS_INLINE jsid
+SPECIALID_TO_JSID(const SpecialId &sid)
+{
+    jsid id;
+    JSID_BITS(id) = sid.bits;
+    JS_ASSERT_IF(sid.isObject(), JSID_IS_OBJECT(id) && JSID_TO_OBJECT(id) == sid.toObject());
+    JS_ASSERT_IF(sid.isVoid(), JSID_IS_VOID(id));
+    JS_ASSERT_IF(sid.isEmpty(), JSID_IS_EMPTY(id));
+    JS_ASSERT_IF(sid.isDefaultXMLNamespace(), JSID_IS_DEFAULT_XML_NAMESPACE(id));
+    return id;
+}
+
+static JS_ALWAYS_INLINE bool
+JSID_IS_SPECIAL(jsid id)
+{
+    return JSID_IS_OBJECT(id) || JSID_IS_EMPTY(id) || JSID_IS_VOID(id) ||
+           JSID_IS_DEFAULT_XML_NAMESPACE(id);
+}
+
+static JS_ALWAYS_INLINE SpecialId
+JSID_TO_SPECIALID(jsid id)
+{
+    JS_ASSERT(JSID_IS_SPECIAL(id));
+    if (JSID_IS_OBJECT(id))
+        return SpecialId(*JSID_TO_OBJECT(id));
+    if (JSID_IS_EMPTY(id))
+        return SpecialId::empty();
+    if (JSID_IS_VOID(id))
+        return SpecialId::voidId();
+    JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id));
+    return SpecialId::defaultXMLNamespace();
+}
 
 /* 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,
+(* LookupSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, 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,
+(* DefineSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, 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);
+(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, 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);
+(* 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);
 typedef JSBool
 (* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 typedef JSBool
-(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+(* 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);
 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);
+(* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, 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
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3273,19 +3273,19 @@ 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);
+with_LookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp)
+{
+    return with_LookupProperty(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
 }
 
 static JSBool
 with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     return obj->getProto()->getProperty(cx, id, vp);
 }
 
@@ -3294,19 +3294,19 @@ with_GetElement(JSContext *cx, JSObject 
 {
     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);
+with_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
+{
+    return with_GetProperty(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
 }
 
 static JSBool
 with_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     return obj->getProto()->setProperty(cx, id, vp, strict);
 }
 
@@ -3315,19 +3315,19 @@ with_SetElement(JSContext *cx, JSObject 
 {
     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);
+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);
 }
 
@@ -3336,19 +3336,19 @@ with_GetElementAttributes(JSContext *cx,
 {
     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);
+with_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
+{
+    return with_GetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 static JSBool
 with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     return obj->getProto()->setAttributes(cx, id, attrsp);
 }
 
@@ -3357,19 +3357,19 @@ with_SetElementAttributes(JSContext *cx,
 {
     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);
+with_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
+{
+    return with_SetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 static JSBool
 with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     return obj->getProto()->deleteProperty(cx, id, rval, strict);
 }
 
@@ -3378,19 +3378,19 @@ with_DeleteElement(JSContext *cx, JSObje
 {
     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);
+with_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
+{
+    return with_DeleteProperty(cx, obj, SPECIALID_TO_JSID(sid), 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);
 }
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -907,19 +907,19 @@ 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)
+proxy_LookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp)
 {
-    return proxy_LookupProperty(cx, obj, id, objp, propp);
+    return proxy_LookupProperty(cx, obj, SPECIALID_TO_JSID(sid), 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);
 
@@ -939,20 +939,20 @@ 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,
+proxy_DefineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
-    return proxy_DefineProperty(cx, obj, id, value, getter, setter, attrs);
+    return proxy_DefineProperty(cx, obj, SPECIALID_TO_JSID(sid), 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);
@@ -963,19 +963,19 @@ 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)
+proxy_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
 {
-    return proxy_GetProperty(cx, obj, receiver, id, vp);
+    return proxy_GetProperty(cx, obj, receiver, SPECIALID_TO_JSID(sid), 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);
@@ -986,19 +986,19 @@ 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)
+proxy_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
-    return proxy_SetProperty(cx, obj, id, vp, strict);
+    return proxy_SetProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
 }
 
 static JSBool
 proxy_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     id = js_CheckForStringIndex(id);
 
     AutoPropertyDescriptorRooter desc(cx);
@@ -1013,19 +1013,19 @@ 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)
+proxy_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return proxy_GetAttributes(cx, obj, id, attrsp);
+    return proxy_GetAttributes(cx, obj, SPECIALID_TO_JSID(sid), 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. */
@@ -1041,19 +1041,19 @@ 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)
+proxy_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return proxy_SetAttributes(cx, obj, id, attrsp);
+    return proxy_SetAttributes(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
@@ -1069,19 +1069,19 @@ proxy_DeleteElement(JSContext *cx, JSObj
 {
     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)
+proxy_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
 {
-    return proxy_DeleteProperty(cx, obj, id, rval, strict);
+    return proxy_DeleteProperty(cx, obj, SPECIALID_TO_JSID(sid), 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");
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -306,20 +306,20 @@ 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,
+ArrayBuffer::obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid,
                                JSObject **objp, JSProperty **propp)
 {
-    return obj_lookupProperty(cx, obj, id, objp, propp);
+    return obj_lookupProperty(cx, obj, SPECIALID_TO_JSID(sid), 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;
@@ -336,20 +336,20 @@ 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,
+ArrayBuffer::obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v,
                                PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
-    return obj_defineProperty(cx, obj, id, v, getter, setter, attrs);
+    return obj_defineProperty(cx, obj, SPECIALID_TO_JSID(sid), 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());
@@ -367,19 +367,19 @@ 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)
+ArrayBuffer::obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
 {
-    return obj_getProperty(cx, obj, receiver, id, vp);
+    return obj_getProperty(cx, obj, receiver, SPECIALID_TO_JSID(sid), 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;
 
@@ -437,19 +437,19 @@ 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)
+ArrayBuffer::obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
 {
-    return obj_setProperty(cx, obj, id, vp, strict);
+    return obj_setProperty(cx, obj, SPECIALID_TO_JSID(sid), 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;
@@ -466,19 +466,19 @@ 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)
+ArrayBuffer::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return obj_getAttributes(cx, obj, id, attrsp);
+    return obj_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), 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);
@@ -496,19 +496,19 @@ 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)
+ArrayBuffer::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return obj_setSpecialAttributes(cx, obj, id, attrsp);
+    return obj_setAttributes(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;
@@ -525,19 +525,19 @@ 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)
+ArrayBuffer::obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
 {
-    return obj_deleteProperty(cx, obj, id, rval, strict);
+    return obj_deleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
 }
 
 JSBool
 ArrayBuffer::obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
               Value *statep, jsid *idp)
 {
     statep->setNull();
     return true;
@@ -689,20 +689,20 @@ 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,
+TypedArray::obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid,
                               JSObject **objp, JSProperty **propp)
 {
-    return obj_lookupProperty(cx, obj, id, objp, propp);
+    return obj_lookupProperty(cx, obj, SPECIALID_TO_JSID(sid), 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;
@@ -712,19 +712,19 @@ TypedArray::obj_getAttributes(JSContext 
 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)
+TypedArray::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return obj_getAttributes(cx, obj, id, attrsp);
+    return obj_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), 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;
 }
@@ -732,19 +732,19 @@ TypedArray::obj_setAttributes(JSContext 
 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)
+TypedArray::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
 {
-    return obj_setAttributes(cx, obj, id, attrsp);
+    return obj_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
 }
 
 /* static */ int
 TypedArray::lengthOffset()
 {
     return JSObject::getFixedSlotOffset(FIELD_LENGTH) + offsetof(jsval_layout, s.payload);
 }
 
@@ -995,19 +995,19 @@ 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)
+    obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
     {
-        return obj_getProperty(cx, obj, receiver, id, vp);
+        return obj_getProperty(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
     }
 
     static bool
     setElementTail(JSContext *cx, JSObject *tarray, uint32 index, Value *vp, JSBool strict)
     {
         JS_ASSERT(tarray);
         JS_ASSERT(index < getLength(tarray));
 
@@ -1100,19 +1100,19 @@ 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)
+    obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
     {
-        return obj_setProperty(cx, obj, id, vp, strict);
+        return obj_setProperty(cx, obj, SPECIALID_TO_JSID(sid), 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;
@@ -1125,20 +1125,20 @@ 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,
+    obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v,
                       PropertyOp getter, StrictPropertyOp setter, uintN attrs)
     {
-        return obj_defineProperty(cx, obj, id, v, getter, setter, attrs);
+        return obj_defineProperty(cx, obj, SPECIALID_TO_JSID(sid), 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;
@@ -1167,19 +1167,19 @@ class TypedArrayTemplate
             return true;
         }
 
         rval->setBoolean(true);
         return true;
     }
 
     static JSBool
-    obj_deleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
+    obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
     {
-        return obj_deleteProperty(cx, obj, id, rval, strict);
+        return obj_deleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
     }
 
     static JSBool
     obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                   Value *statep, jsid *idp)
     {
         JSObject *tarray = getTypedArray(obj);
         JS_ASSERT(tarray);
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -78,74 +78,75 @@ 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);
+    obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, 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,
+    obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, 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);
+    obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, 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);
+    obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, 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);
+    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_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 
     static JSBool
-    obj_setSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    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);
 
     static JSBool
-    obj_deleteSpecial(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict);
+    obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, 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);
 
@@ -206,26 +207,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,
+    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_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
-    static JSBool obj_getSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, 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_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
-    static JSBool obj_setSpecialAttributes(JSContext *cx, JSObject *obj, jsid id, 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);
     static void * getDataOffset(JSObject *obj);
 
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -4749,19 +4749,19 @@ 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);
+xml_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp)
+{
+    return xml_lookupProperty(cx, obj, SPECIALID_TO_JSID(sid), 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 ||
@@ -4779,20 +4779,20 @@ 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,
+xml_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v,
                   PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
-    return xml_defineProperty(cx, obj, id, v, getter, setter, attrs);
+    return xml_defineProperty(cx, obj, SPECIALID_TO_JSID(sid), 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;
@@ -4806,40 +4806,46 @@ 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);
+xml_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
+{
+    return xml_getProperty(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
+}
+
+static JSBool
+xml_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+{
+    return PutProperty(cx, obj, id, strict, vp);
 }
 
 static JSBool
 xml_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
-    return PutProperty(cx, obj, id, strict, vp);
+    return xml_setGeneric(cx, obj, id, vp, strict);
 }
 
 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);
+    return xml_setGeneric(cx, obj, id, vp, strict);
+}
+
+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)
 {
     JSBool found;
     if (!HasProperty(cx, obj, IdToJsval(id), &found))
         return false;
@@ -4853,19 +4859,19 @@ 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);
+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)
 {
     JSBool found;
     if (!HasProperty(cx, obj, IdToJsval(id), &found))
         return false;
@@ -4883,19 +4889,19 @@ 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);
+xml_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp)
+{
+    return xml_setAttributes(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;
@@ -4961,19 +4967,19 @@ 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);
+xml_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
+{
+    return xml_deleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
 }
 
 static JSString *
 xml_toString_helper(JSContext *cx, JSXML *xml);
 
 JSBool
 xml_convert(JSContext *cx, JSObject *obj, JSType hint, Value *rval)
 {