Bug 980016 - Remove SpecialId. r=njn.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 10 Mar 2014 16:32:21 -0500
changeset 190052 45003a7ef6827703fd98b06904768444b7451380
parent 190051 78f1a88a4048155cb24ae3fa10e4b36f8aa08878
child 190053 bb77e0285652bcb3471f426b828279deac8c34ca
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs980016
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 980016 - Remove SpecialId. r=njn.
js/public/Class.h
js/src/builtin/TypedObject.cpp
js/src/builtin/TypedObject.h
js/src/jsapi.cpp
js/src/jsfriendapi.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsproxy.cpp
js/src/vm/ArrayBufferObject.cpp
js/src/vm/ArrayBufferObject.h
js/src/vm/Interpreter-inl.h
js/src/vm/ScopeObject.cpp
js/src/vm/SharedArrayObject.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/xpcprivate.h
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -26,130 +26,23 @@
 
 class JSFreeOp;
 struct JSFunctionSpec;
 
 namespace js {
 
 class Class;
 class FreeOp;
-class PropertyId;
 class PropertyName;
 class Shape;
-class SpecialId;
 
 // This is equal to JSFunction::class_.  Use it in places where you don't want
 // to #include jsfun.h.
 extern JS_FRIEND_DATA(const js::Class* const) FunctionClassPtr;
 
-static MOZ_ALWAYS_INLINE jsid
-SPECIALID_TO_JSID(const SpecialId &sid);
-
-/*
- * We partition the ways to refer to a property into three: by an index
- * (uint32_t); 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 is used for JSID_VOID, which
- * does not occur in JS scripts but may be used to indicate the absence of a
- * valid identifier.  In the future, a SpecialId may also be an object used by
- * Harmony-proposed private names.
- */
-class SpecialId
-{
-    uintptr_t bits_;
-
-    /* Needs access to raw bits. */
-    friend MOZ_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
-    friend class PropertyId;
-
-    static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
-    static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
-    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)
-    {
-        MOZ_ASSERT(&obj != nullptr);
-        MOZ_ASSERT((uintptr_t(&obj) & TYPE_MASK) == 0);
-    }
-
-    bool isObject() const {
-        return (bits_ & TYPE_MASK) == TYPE_OBJECT && bits_ != TYPE_OBJECT;
-    }
-
-    JSObject *toObject() const {
-        MOZ_ASSERT(isObject());
-        return reinterpret_cast<JSObject *>(bits_ & ~TYPE_MASK);
-    }
-
-    /* Empty */
-
-    static SpecialId empty() {
-        SpecialId sid(TYPE_OBJECT);
-        MOZ_ASSERT(sid.isEmpty());
-        return sid;
-    }
-
-    bool isEmpty() const {
-        return bits_ == TYPE_OBJECT;
-    }
-
-    /* Void */
-
-    static SpecialId voidId() {
-        SpecialId sid(TYPE_VOID);
-        MOZ_ASSERT(sid.isVoid());
-        return sid;
-    }
-
-    bool isVoid() const {
-        return bits_ == TYPE_VOID;
-    }
-};
-
-static MOZ_ALWAYS_INLINE jsid
-SPECIALID_TO_JSID(const SpecialId &sid)
-{
-    jsid id;
-    JSID_BITS(id) = sid.bits_;
-    MOZ_ASSERT_IF(sid.isObject(), JSID_IS_OBJECT(id) && JSID_TO_OBJECT(id) == sid.toObject());
-    MOZ_ASSERT_IF(sid.isVoid(), JSID_IS_VOID(id));
-    MOZ_ASSERT_IF(sid.isEmpty(), JSID_IS_EMPTY(id));
-    return id;
-}
-
-static MOZ_ALWAYS_INLINE bool
-JSID_IS_SPECIAL(jsid id)
-{
-    return JSID_IS_OBJECT(id) || JSID_IS_EMPTY(id) || JSID_IS_VOID(id);
-}
-
-static MOZ_ALWAYS_INLINE SpecialId
-JSID_TO_SPECIALID(jsid id)
-{
-    MOZ_ASSERT(JSID_IS_SPECIAL(id));
-    if (JSID_IS_OBJECT(id))
-        return SpecialId(*JSID_TO_OBJECT(id));
-    if (JSID_IS_EMPTY(id))
-        return SpecialId::empty();
-    MOZ_ASSERT(JSID_IS_VOID(id));
-    return SpecialId::voidId();
-}
-
-typedef JS::Handle<SpecialId> HandleSpecialId;
-
 } // namespace js
 
 // JSClass operation signatures.
 
 // Add or get a property named by id in obj.  Note the jsid id type -- id may
 // be a string (Unicode property identifier) or an int (element index).  The
 // *vp out parameter, on success, is the new property value after the action.
 typedef bool
@@ -309,68 +202,53 @@ typedef bool
                     JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
 typedef bool
 (* LookupPropOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                  JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
 typedef bool
 (* LookupElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index,
                     JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
 typedef bool
-(* LookupSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
-                    JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
-typedef bool
 (* DefineGenericOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
                     JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 typedef bool
 (* DefinePropOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                  JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
                  unsigned attrs);
 typedef bool
 (* DefineElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
                     JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 typedef bool
-(* DefineSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
-                    JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
-                    unsigned attrs);
-typedef bool
 (* GenericIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
                 JS::MutableHandleValue vp);
 typedef bool
 (* PropertyIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
                  JS::Handle<PropertyName*> name, JS::MutableHandleValue vp);
 typedef bool
 (* ElementIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, uint32_t index,
                 JS::MutableHandleValue vp);
 typedef bool
-(* SpecialIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
-                HandleSpecialId sid, JS::MutableHandleValue vp);
-typedef bool
 (* StrictGenericIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                       JS::MutableHandleValue vp, bool strict);
 typedef bool
 (* StrictPropertyIdOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                        JS::MutableHandleValue vp, bool strict);
 typedef bool
 (* StrictElementIdOp)(JSContext *cx, JS::HandleObject obj, uint32_t index,
                       JS::MutableHandleValue vp, bool strict);
 typedef bool
-(* StrictSpecialIdOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
-                      JS::MutableHandleValue vp, bool strict);
-typedef bool
 (* GenericAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
 typedef bool
 (* PropertyAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                          unsigned *attrsp);
 typedef bool
 (* DeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                      bool *succeeded);
 typedef bool
 (* DeleteElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded);
-typedef bool
-(* DeleteSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, bool *succeeded);
 
 typedef bool
 (* WatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
 
 typedef bool
 (* UnwatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
 
 typedef bool
@@ -448,57 +326,52 @@ struct ClassExtension
 #define JS_NULL_CLASS_SPEC  {nullptr,nullptr,nullptr,nullptr,nullptr}
 #define JS_NULL_CLASS_EXT   {nullptr,nullptr,nullptr,false,nullptr}
 
 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;
     GenericAttributesOp setGenericAttributes;
     DeletePropertyOp    deleteProperty;
     DeleteElementOp     deleteElement;
-    DeleteSpecialOp     deleteSpecial;
     WatchOp             watch;
     UnwatchOp           unwatch;
     SliceOp             slice; // Optimized slice, can be null.
 
     JSNewEnumerateOp    enumerate;
     ObjectOp            thisObject;
 };
 
 #define JS_NULL_OBJECT_OPS                                                    \
     {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
      nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
-     nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
+     nullptr,nullptr}
 
 } // namespace js
 
 // Classes, objects, and properties.
 
 typedef void (*JSClassInternal)();
 
 struct JSClass {
     JS_CLASS_MEMBERS(JSFinalizeOp);
 
-    void                *reserved[36];
+    void                *reserved[31];
 };
 
 #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_IS_DOMJSCLASS           (1<<4)  // objects are DOM
 #define JSCLASS_IMPLEMENTS_BARRIERS     (1<<5)  // Correctly implements GC read
@@ -654,26 +527,11 @@ enum ESClassValue {
  */
 inline bool
 ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx);
 
 /* Just a helper that checks v.isObject before calling ObjectClassIs. */
 inline bool
 IsObjectWithClass(const JS::Value &v, ESClassValue classValue, JSContext *cx);
 
-inline bool
-IsPoisonedSpecialId(js::SpecialId iden)
-{
-    if (iden.isObject())
-        return JS::IsPoisonedPtr(iden.toObject());
-    return false;
-}
-
-template <> struct GCMethods<SpecialId>
-{
-    static SpecialId initial() { return SpecialId(); }
-    static ThingRootKind kind() { return THING_ROOT_ID; }
-    static bool poisoned(SpecialId id) { return IsPoisonedSpecialId(id); }
-};
-
 }  /* namespace js */
 
 #endif  /* js_Class_h */
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1689,25 +1689,16 @@ ReportPropertyError(JSContext *cx,
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                          errorNumber, propName);
 
     JS_free(cx, propName);
     return false;
 }
 
 bool
-TypedObject::obj_lookupSpecial(JSContext *cx, HandleObject obj,
-                              HandleSpecialId sid, MutableHandleObject objp,
-                              MutableHandleShape propp)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return obj_lookupGeneric(cx, obj, id, objp, propp);
-}
-
-bool
 TypedObject::obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
                               PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     return ReportPropertyError(cx, JSMSG_UNDEFINED_PROP, id);
 }
 
 bool
 TypedObject::obj_defineProperty(JSContext *cx, HandleObject obj,
@@ -1726,24 +1717,16 @@ TypedObject::obj_defineElement(JSContext
 
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::DefineElement(cx, delegate, index, v, getter, setter, attrs);
 }
 
 bool
-TypedObject::obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue v,
-                              PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs);
-}
-
-bool
 TypedObject::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
                            HandleId id, MutableHandleValue vp)
 {
     JS_ASSERT(obj->is<TypedObject>());
     Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
 
     // Dispatch elements to obj_getElement:
     uint32_t index;
@@ -1855,25 +1838,16 @@ TypedObject::obj_getArrayElement(JSConte
     }
 
     Rooted<SizedTypeDescr*> elementType(cx, &typeDescr->as<T>().elementType());
     size_t offset = elementType->size() * index;
     return Reify(cx, elementType, typedObj, offset, vp);
 }
 
 bool
-TypedObject::obj_getSpecial(JSContext *cx, HandleObject obj,
-                            HandleObject receiver, HandleSpecialId sid,
-                            MutableHandleValue vp)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return obj_getGeneric(cx, obj, receiver, id, vp);
-}
-
-bool
 TypedObject::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
                            MutableHandleValue vp, bool strict)
 {
     JS_ASSERT(obj->is<TypedObject>());
     Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
 
     uint32_t index;
     if (js_IdIsIndex(id, &index))
@@ -1965,25 +1939,16 @@ TypedObject::obj_setArrayElement(JSConte
 
     Rooted<SizedTypeDescr*> elementType(cx);
     elementType = &descr->as<T>().elementType();
     size_t offset = elementType->size() * index;
     return ConvertAndCopyTo(cx, elementType, typedObj, offset, vp);
 }
 
 bool
-TypedObject::obj_setSpecial(JSContext *cx, HandleObject obj,
-                             HandleSpecialId sid, MutableHandleValue vp,
-                             bool strict)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return obj_setGeneric(cx, obj, id, vp, strict);
-}
-
-bool
 TypedObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                      HandleId id, unsigned *attrsp)
 {
     uint32_t index;
     Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
     TypeRepresentation *typeRepr = typedObj->typeRepresentation();
 
     switch (typeRepr->kind()) {
@@ -2096,29 +2061,16 @@ TypedObject::obj_deleteElement(JSContext
         *succeeded = false;
         return true;
     }
 
     return JSObject::deleteElement(cx, proto, index, succeeded);
 }
 
 bool
-TypedObject::obj_deleteSpecial(JSContext *cx, HandleObject obj,
-                               HandleSpecialId sid, bool *succeeded)
-{
-    RootedObject proto(cx, obj->getProto());
-    if (!proto) {
-        *succeeded = false;
-        return true;
-    }
-
-    return JSObject::deleteSpecial(cx, proto, sid, succeeded);
-}
-
-bool
 TypedObject::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
                            MutableHandleValue statep, MutableHandleId idp)
 {
     uint32_t index;
 
     JS_ASSERT(obj->is<TypedObject>());
     Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
     TypeRepresentation *typeRepr = typedObj->typeRepresentation();
@@ -2237,34 +2189,29 @@ const Class TransparentTypedObject::clas
     nullptr,        /* hasInstance */
     TypedObject::obj_trace,
     JS_NULL_CLASS_SPEC,
     JS_NULL_CLASS_EXT,
     {
         TypedObject::obj_lookupGeneric,
         TypedObject::obj_lookupProperty,
         TypedObject::obj_lookupElement,
-        TypedObject::obj_lookupSpecial,
         TypedObject::obj_defineGeneric,
         TypedObject::obj_defineProperty,
         TypedObject::obj_defineElement,
-        TypedObject::obj_defineSpecial,
         TypedObject::obj_getGeneric,
         TypedObject::obj_getProperty,
         TypedObject::obj_getElement,
-        TypedObject::obj_getSpecial,
         TypedObject::obj_setGeneric,
         TypedObject::obj_setProperty,
         TypedObject::obj_setElement,
-        TypedObject::obj_setSpecial,
         TypedObject::obj_getGenericAttributes,
         TypedObject::obj_setGenericAttributes,
         TypedObject::obj_deleteProperty,
         TypedObject::obj_deleteElement,
-        TypedObject::obj_deleteSpecial,
         nullptr, nullptr, // watch/unwatch
         nullptr,   /* slice */
         TypedObject::obj_enumerate,
         nullptr, /* thisObject */
     }
 };
 
 static int32_t
@@ -2570,34 +2517,29 @@ const Class OpaqueTypedObject::class_ = 
     nullptr,        /* hasInstance */
     TypedObject::obj_trace,
     JS_NULL_CLASS_SPEC,
     JS_NULL_CLASS_EXT,
     {
         TypedObject::obj_lookupGeneric,
         TypedObject::obj_lookupProperty,
         TypedObject::obj_lookupElement,
-        TypedObject::obj_lookupSpecial,
         TypedObject::obj_defineGeneric,
         TypedObject::obj_defineProperty,
         TypedObject::obj_defineElement,
-        TypedObject::obj_defineSpecial,
         TypedObject::obj_getGeneric,
         TypedObject::obj_getProperty,
         TypedObject::obj_getElement,
-        TypedObject::obj_getSpecial,
         TypedObject::obj_setGeneric,
         TypedObject::obj_setProperty,
         TypedObject::obj_setElement,
-        TypedObject::obj_setSpecial,
         TypedObject::obj_getGenericAttributes,
         TypedObject::obj_setGenericAttributes,
         TypedObject::obj_deleteProperty,
         TypedObject::obj_deleteElement,
-        TypedObject::obj_deleteSpecial,
         nullptr, nullptr, // watch/unwatch
         nullptr, // slice
         TypedObject::obj_enumerate,
         nullptr, /* thisObject */
     }
 };
 
 const JSFunctionSpec OpaqueTypedObject::handleStaticMethods[] = {
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -484,69 +484,54 @@ class TypedObject : public ArrayBufferVi
                                    HandlePropertyName name,
                                    MutableHandleObject objp,
                                    MutableHandleShape propp);
 
     static bool obj_lookupElement(JSContext *cx, HandleObject obj,
                                   uint32_t index, MutableHandleObject objp,
                                   MutableHandleShape propp);
 
-    static bool obj_lookupSpecial(JSContext *cx, HandleObject obj,
-                                  HandleSpecialId sid,
-                                  MutableHandleObject objp,
-                                  MutableHandleShape propp);
-
     static bool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
                                   PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 
     static bool obj_defineProperty(JSContext *cx, HandleObject obj,
                                    HandlePropertyName name, HandleValue v,
                                    PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 
     static bool obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
                                   PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 
-    static bool obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue v,
-                                  PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
-
     static bool obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
                                HandleId id, MutableHandleValue vp);
 
     static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
                                 HandlePropertyName name, MutableHandleValue vp);
 
     static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
                                uint32_t index, MutableHandleValue vp);
 
     static bool obj_getUnsizedArrayElement(JSContext *cx, HandleObject obj, HandleObject receiver,
                                          uint32_t index, MutableHandleValue vp);
 
-    static bool obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver,
-                               HandleSpecialId sid, MutableHandleValue vp);
-
     static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                MutableHandleValue vp, bool strict);
     static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                 MutableHandleValue vp, bool strict);
     static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
                                MutableHandleValue vp, bool strict);
-    static bool obj_setSpecial(JSContext *cx, HandleObject obj,
-                               HandleSpecialId sid, MutableHandleValue vp, bool strict);
 
     static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                          HandleId id, unsigned *attrsp);
     static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
                                          HandleId id, unsigned *attrsp);
 
     static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                    bool *succeeded);
     static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
                                   bool *succeeded);
-    static bool obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                                  bool *succeeded);
 
     static bool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
                               MutableHandleValue statep, MutableHandleId idp);
 
   public:
     // Each typed object contains a void* pointer pointing at the
     // binary data that it represents. (That data may be owned by this
     // object or this object may alias data owned by someone else.)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3432,20 +3432,16 @@ JS_SetUCProperty(JSContext *cx, HandleOb
 JS_PUBLIC_API(bool)
 JS_DeletePropertyById2(JSContext *cx, HandleObject obj, HandleId id, bool *result)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     JSAutoResolveFlags rf(cx, 0);
 
-    if (JSID_IS_SPECIAL(id)) {
-        Rooted<SpecialId> sid(cx, JSID_TO_SPECIALID(id));
-        return JSObject::deleteSpecial(cx, obj, sid, result);
-    }
     return JSObject::deleteByValue(cx, obj, IdToValue(id), result);
 }
 
 JS_PUBLIC_API(bool)
 JS_DeleteElement2(JSContext *cx, HandleObject obj, uint32_t index, bool *result)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -263,34 +263,29 @@ namespace js {
         constructOp,             /* construct   */                                      \
         js::proxy_Trace,         /* trace       */                                      \
         JS_NULL_CLASS_SPEC,                                                             \
         ext,                                                                            \
         {                                                                               \
             js::proxy_LookupGeneric,                                                    \
             js::proxy_LookupProperty,                                                   \
             js::proxy_LookupElement,                                                    \
-            js::proxy_LookupSpecial,                                                    \
             js::proxy_DefineGeneric,                                                    \
             js::proxy_DefineProperty,                                                   \
             js::proxy_DefineElement,                                                    \
-            js::proxy_DefineSpecial,                                                    \
             js::proxy_GetGeneric,                                                       \
             js::proxy_GetProperty,                                                      \
             js::proxy_GetElement,                                                       \
-            js::proxy_GetSpecial,                                                       \
             js::proxy_SetGeneric,                                                       \
             js::proxy_SetProperty,                                                      \
             js::proxy_SetElement,                                                       \
-            js::proxy_SetSpecial,                                                       \
             js::proxy_GetGenericAttributes,                                             \
             js::proxy_SetGenericAttributes,                                             \
             js::proxy_DeleteProperty,                                                   \
             js::proxy_DeleteElement,                                                    \
-            js::proxy_DeleteSpecial,                                                    \
             js::proxy_Watch, js::proxy_Unwatch,                                         \
             js::proxy_Slice,                                                            \
             nullptr,             /* enumerate       */                                  \
             nullptr,             /* thisObject      */                                  \
         }                                                                               \
     }
 
 #define PROXY_CLASS_DEF(name, extraSlots, flags, callOp, constructOp)   \
@@ -313,67 +308,52 @@ proxy_LookupGeneric(JSContext *cx, JS::H
                     JS::MutableHandle<Shape*> propp);
 extern JS_FRIEND_API(bool)
 proxy_LookupProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                      JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
 extern JS_FRIEND_API(bool)
 proxy_LookupElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleObject objp,
                     JS::MutableHandle<Shape*> propp);
 extern JS_FRIEND_API(bool)
-proxy_LookupSpecial(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
-                    JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
-extern JS_FRIEND_API(bool)
 proxy_DefineGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
                     JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 extern JS_FRIEND_API(bool)
 proxy_DefineProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                      JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
                      unsigned attrs);
 extern JS_FRIEND_API(bool)
 proxy_DefineElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
                     JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 extern JS_FRIEND_API(bool)
-proxy_DefineSpecial(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
-                    JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
-                    unsigned attrs);
-extern JS_FRIEND_API(bool)
 proxy_GetGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
                  JS::MutableHandleValue vp);
 extern JS_FRIEND_API(bool)
 proxy_GetProperty(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
                   JS::Handle<PropertyName*> name, JS::MutableHandleValue vp);
 extern JS_FRIEND_API(bool)
 proxy_GetElement(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, uint32_t index,
                  JS::MutableHandleValue vp);
 extern JS_FRIEND_API(bool)
-proxy_GetSpecial(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
-                 HandleSpecialId sid, JS::MutableHandleValue vp);
-extern JS_FRIEND_API(bool)
 proxy_SetGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                  JS::MutableHandleValue bp, bool strict);
 extern JS_FRIEND_API(bool)
 proxy_SetProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                   JS::MutableHandleValue bp, bool strict);
 extern JS_FRIEND_API(bool)
 proxy_SetElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp,
                  bool strict);
 extern JS_FRIEND_API(bool)
-proxy_SetSpecial(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
-                 JS::MutableHandleValue vp, bool strict);
-extern JS_FRIEND_API(bool)
 proxy_GetGenericAttributes(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
 extern JS_FRIEND_API(bool)
 proxy_SetGenericAttributes(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
 extern JS_FRIEND_API(bool)
 proxy_DeleteProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                      bool *succeeded);
 extern JS_FRIEND_API(bool)
 proxy_DeleteElement(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded);
-extern JS_FRIEND_API(bool)
-proxy_DeleteSpecial(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, bool *succeeded);
 
 extern JS_FRIEND_API(void)
 proxy_Trace(JSTracer *trc, JSObject *obj);
 extern JS_FRIEND_API(JSObject *)
 proxy_WeakmapKeyDelegate(JSObject *obj);
 extern JS_FRIEND_API(bool)
 proxy_Convert(JSContext *cx, JS::HandleObject proxy, JSType hint, JS::MutableHandleValue vp);
 extern JS_FRIEND_API(void)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1701,19 +1701,16 @@ JSObject::nonNativeSetElement(JSContext 
 /* static */ bool
 JSObject::deleteByValue(JSContext *cx, HandleObject obj, const Value &property, bool *succeeded)
 {
     uint32_t index;
     if (IsDefinitelyIndex(property, &index))
         return deleteElement(cx, obj, index, succeeded);
 
     RootedValue propval(cx, property);
-    Rooted<SpecialId> sid(cx);
-    if (ValueIsSpecial(obj, &propval, &sid, cx))
-        return deleteSpecial(cx, obj, sid, succeeded);
 
     JSAtom *name = ToAtom<CanGC>(cx, propval);
     if (!name)
         return false;
 
     if (name->isIndex(&index))
         return deleteElement(cx, obj, index, succeeded);
 
@@ -3497,25 +3494,16 @@ JSObject::defineGeneric(ExclusiveContext
 JSObject::defineProperty(ExclusiveContext *cx, HandleObject obj,
                          PropertyName *name, HandleValue value,
                          JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
     RootedId id(cx, NameToId(name));
     return defineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
-/* static */ bool
-JSObject::defineSpecial(ExclusiveContext *cx, HandleObject obj,
-                        SpecialId sid, HandleValue value,
-                        JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return defineGeneric(cx, obj, id, value, getter, setter, attrs);
-}
-
 bool
 baseops::DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value,
                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     RootedId id(cx);
     if (index <= JSID_INT_MAX) {
         id = INT_TO_JSID(index);
         return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0);
@@ -4296,17 +4284,16 @@ js::HasOwnProperty(JSContext *cx, Handle
     RootedObject pobj(cx);
     RootedShape shape(cx);
     if (!HasOwnProperty<CanGC>(cx, obj->getOps()->lookupGeneric, obj, id, &pobj, &shape))
         return false;
     *resultp = (shape != nullptr);
     return true;
 }
 
-
 template <AllowGC allowGC>
 static MOZ_ALWAYS_INLINE bool
 NativeGetInline(JSContext *cx,
                 typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
                 typename MaybeRooted<JSObject*, allowGC>::HandleType receiver,
                 typename MaybeRooted<JSObject*, allowGC>::HandleType pobj,
                 typename MaybeRooted<Shape*, allowGC>::HandleType shape,
                 typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
@@ -5220,23 +5207,16 @@ baseops::DeleteElement(JSContext *cx, Ha
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return baseops::DeleteGeneric(cx, obj, id, succeeded);
 }
 
 bool
-baseops::DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, bool *succeeded)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return baseops::DeleteGeneric(cx, obj, id, succeeded);
-}
-
-bool
 js::WatchGuts(JSContext *cx, JS::HandleObject origObj, JS::HandleId id, JS::HandleObject callable)
 {
     RootedObject obj(cx, GetInnerObject(cx, origObj));
     if (obj->isNative()) {
         // Use sparse indexes for watched objects, as dense elements can be
         // written to without checking the watchpoint map.
         if (!JSObject::sparsifyDenseElements(cx, obj))
             return false;
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -146,19 +146,16 @@ SetAttributes(JSContext *cx, HandleObjec
 
 extern bool
 DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, bool *succeeded);
 
 extern bool
 DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succeeded);
 
 extern bool
-DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, bool *succeeded);
-
-extern bool
 DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded);
 
 extern bool
 Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
 
 extern bool
 Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
 
@@ -970,23 +967,16 @@ class JSObject : public js::ObjectImpl
 
     static bool lookupElement(JSContext *cx, js::HandleObject obj, uint32_t index,
                               js::MutableHandleObject objp, js::MutableHandleShape propp)
     {
         js::LookupElementOp op = obj->getOps()->lookupElement;
         return (op ? op : js::baseops::LookupElement)(cx, obj, index, objp, propp);
     }
 
-    static bool lookupSpecial(JSContext *cx, js::HandleObject obj, js::SpecialId sid,
-                              js::MutableHandleObject objp, js::MutableHandleShape propp)
-    {
-        JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
-        return lookupGeneric(cx, obj, id, objp, propp);
-    }
-
     static bool defineGeneric(js::ExclusiveContext *cx, js::HandleObject obj,
                               js::HandleId id, js::HandleValue value,
                               JSPropertyOp getter = JS_PropertyStub,
                               JSStrictPropertyOp setter = JS_StrictPropertyStub,
                               unsigned attrs = JSPROP_ENUMERATE);
 
     static bool defineProperty(js::ExclusiveContext *cx, js::HandleObject obj,
                                js::PropertyName *name, js::HandleValue value,
@@ -995,22 +985,16 @@ class JSObject : public js::ObjectImpl
                                unsigned attrs = JSPROP_ENUMERATE);
 
     static bool defineElement(js::ExclusiveContext *cx, js::HandleObject obj,
                               uint32_t index, js::HandleValue value,
                               JSPropertyOp getter = JS_PropertyStub,
                               JSStrictPropertyOp setter = JS_StrictPropertyStub,
                               unsigned attrs = JSPROP_ENUMERATE);
 
-    static bool defineSpecial(js::ExclusiveContext *cx, js::HandleObject obj,
-                              js::SpecialId sid, js::HandleValue value,
-                              JSPropertyOp getter = JS_PropertyStub,
-                              JSStrictPropertyOp setter = JS_StrictPropertyStub,
-                              unsigned attrs = JSPROP_ENUMERATE);
-
     static bool getGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                            js::HandleId id, js::MutableHandleValue vp)
     {
         JS_ASSERT(!!obj->getOps()->getGeneric == !!obj->getOps()->getProperty);
         js::GenericIdOp op = obj->getOps()->getGeneric;
         if (op) {
             if (!op(cx, obj, receiver, id, vp))
                 return false;
@@ -1043,24 +1027,16 @@ class JSObject : public js::ObjectImpl
         return getGenericNoGC(cx, obj, receiver, js::NameToId(name), vp);
     }
 
     static inline bool getElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                                   uint32_t index, js::MutableHandleValue vp);
     static inline bool getElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
                                       uint32_t index, js::Value *vp);
 
-    static bool getSpecial(JSContext *cx, js::HandleObject obj,
-                           js::HandleObject receiver, js::SpecialId sid,
-                           js::MutableHandleValue vp)
-    {
-        JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
-        return getGeneric(cx, obj, receiver, id, vp);
-    }
-
     static bool setGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                            js::HandleId id, js::MutableHandleValue vp, bool strict)
     {
         if (obj->getOps()->setGeneric)
             return nonNativeSetProperty(cx, obj, id, vp, strict);
         return js::baseops::SetPropertyHelper<js::SequentialExecution>(cx, obj, receiver, id, 0,
                                                                        vp, strict);
     }
@@ -1076,24 +1052,16 @@ class JSObject : public js::ObjectImpl
     static bool setElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                            uint32_t index, js::MutableHandleValue vp, bool strict)
     {
         if (obj->getOps()->setElement)
             return nonNativeSetElement(cx, obj, index, vp, strict);
         return js::baseops::SetElementHelper(cx, obj, receiver, index, 0, vp, strict);
     }
 
-    static bool setSpecial(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
-                           js::SpecialId sid, js::MutableHandleValue vp, bool strict)
-    {
-        JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
-        return setGeneric(cx, obj, receiver, id, vp, strict);
-    }
-
-
     static bool nonNativeSetProperty(JSContext *cx, js::HandleObject obj,
                                      js::HandleId id, js::MutableHandleValue vp, bool strict);
     static bool nonNativeSetElement(JSContext *cx, js::HandleObject obj,
                                     uint32_t index, js::MutableHandleValue vp, bool strict);
 
     static bool getGenericAttributes(JSContext *cx, js::HandleObject obj,
                                      js::HandleId id, unsigned *attrsp)
     {
@@ -1104,18 +1072,16 @@ class JSObject : public js::ObjectImpl
     static inline bool setGenericAttributes(JSContext *cx, js::HandleObject obj,
                                             js::HandleId id, unsigned *attrsp);
 
     static inline bool deleteProperty(JSContext *cx, js::HandleObject obj,
                                       js::HandlePropertyName name,
                                       bool *succeeded);
     static inline bool deleteElement(JSContext *cx, js::HandleObject obj,
                                      uint32_t index, bool *succeeded);
-    static inline bool deleteSpecial(JSContext *cx, js::HandleObject obj,
-                                     js::HandleSpecialId sid, bool *succeeded);
     static bool deleteByValue(JSContext *cx, js::HandleObject obj,
                               const js::Value &property, bool *succeeded);
 
     static inline bool watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                              JS::HandleObject callable);
     static inline bool unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
 
     static bool enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp iterop,
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -57,26 +57,16 @@ JSObject::deleteElement(JSContext *cx, j
     if (!js::IndexToId(cx, index, &id))
         return false;
     js::types::MarkTypePropertyNonData(cx, obj, id);
     js::DeleteElementOp op = obj->getOps()->deleteElement;
     return (op ? op : js::baseops::DeleteElement)(cx, obj, index, succeeded);
 }
 
 /* static */ inline bool
-JSObject::deleteSpecial(JSContext *cx, js::HandleObject obj, js::HandleSpecialId sid,
-                        bool *succeeded)
-{
-    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
-    js::types::MarkTypePropertyNonData(cx, obj, id);
-    js::DeleteSpecialOp op = obj->getOps()->deleteSpecial;
-    return (op ? op : js::baseops::DeleteSpecial)(cx, obj, sid, succeeded);
-}
-
-/* static */ inline bool
 JSObject::watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                 JS::HandleObject callable)
 {
     js::WatchOp op = obj->getOps()->watch;
     return (op ? op : js::baseops::Watch)(cx, obj, id, callable);
 }
 
 /* static */ inline bool
@@ -1053,29 +1043,16 @@ IsObjectWithClass(const Value &v, ESClas
 {
     if (!v.isObject())
         return false;
     RootedObject obj(cx, &v.toObject());
     return ObjectClassIs(obj, classValue, cx);
 }
 
 static MOZ_ALWAYS_INLINE bool
-ValueMightBeSpecial(const Value &propval)
-{
-    return propval.isObject();
-}
-
-static MOZ_ALWAYS_INLINE bool
-ValueIsSpecial(JSObject *obj, MutableHandleValue propval, MutableHandle<SpecialId> sidp,
-               JSContext *cx)
-{
-    return false;
-}
-
-static MOZ_ALWAYS_INLINE bool
 NewObjectMetadata(ExclusiveContext *cxArg, JSObject **pmetadata)
 {
     // The metadata callback is invoked before each created object, except when
     // analysis/compilation is active, to avoid recursion.
     JS_ASSERT(!*pmetadata);
     if (JSContext *cx = cxArg->maybeJSContext()) {
         if (MOZ_UNLIKELY((size_t)cx->compartment()->hasObjectMetadataCallback()) &&
             !cx->compartment()->activeAnalysis)
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -2820,24 +2820,16 @@ js::proxy_LookupElement(JSContext *cx, H
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_LookupGeneric(cx, obj, id, objp, propp);
 }
 
 bool
-js::proxy_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                        MutableHandleObject objp, MutableHandleShape propp)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return proxy_LookupGeneric(cx, obj, id, objp, propp);
-}
-
-bool
 js::proxy_DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                         PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     Rooted<PropertyDescriptor> desc(cx);
     desc.object().set(obj);
     desc.value().set(value);
     desc.setAttributes(attrs);
     desc.setGetter(getter);
@@ -2859,24 +2851,16 @@ js::proxy_DefineElement(JSContext *cx, H
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_DefineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 bool
-js::proxy_DefineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue value,
-                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return proxy_DefineGeneric(cx, obj, id, value, getter, setter, attrs);
-}
-
-bool
 js::proxy_GetGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
                      MutableHandleValue vp)
 {
     return Proxy::get(cx, obj, receiver, id, vp);
 }
 
 bool
 js::proxy_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
@@ -2892,24 +2876,16 @@ js::proxy_GetElement(JSContext *cx, Hand
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_GetGeneric(cx, obj, receiver, id, vp);
 }
 
 bool
-js::proxy_GetSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid,
-                     MutableHandleValue vp)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return proxy_GetGeneric(cx, obj, receiver, id, vp);
-}
-
-bool
 js::proxy_SetGeneric(JSContext *cx, HandleObject obj, HandleId id,
                      MutableHandleValue vp, bool strict)
 {
     return Proxy::set(cx, obj, obj, id, strict, vp);
 }
 
 bool
 js::proxy_SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
@@ -2925,24 +2901,16 @@ js::proxy_SetElement(JSContext *cx, Hand
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_SetGeneric(cx, obj, id, vp, strict);
 }
 
 bool
-js::proxy_SetSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                     MutableHandleValue vp, bool strict)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return proxy_SetGeneric(cx, obj, id, vp, strict);
-}
-
-bool
 js::proxy_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     Rooted<PropertyDescriptor> desc(cx);
     if (!Proxy::getOwnPropertyDescriptor(cx, obj, id, &desc, 0))
         return false;
     *attrsp = desc.attributes();
     return true;
 }
@@ -2979,23 +2947,16 @@ bool
 js::proxy_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succeeded)
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return proxy_DeleteGeneric(cx, obj, id, succeeded);
 }
 
-bool
-js::proxy_DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, bool *succeeded)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return proxy_DeleteGeneric(cx, obj, id, succeeded);
-}
-
 void
 js::proxy_Trace(JSTracer *trc, JSObject *obj)
 {
     JS_ASSERT(obj->is<ProxyObject>());
     ProxyObject::trace(trc, obj);
 }
 
 /* static */ void
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -127,34 +127,29 @@ const Class ArrayBufferObject::class_ = 
     nullptr,        /* construct   */
     ArrayBufferObject::obj_trace,
     JS_NULL_CLASS_SPEC,
     JS_NULL_CLASS_EXT,
     {
         ArrayBufferObject::obj_lookupGeneric,
         ArrayBufferObject::obj_lookupProperty,
         ArrayBufferObject::obj_lookupElement,
-        ArrayBufferObject::obj_lookupSpecial,
         ArrayBufferObject::obj_defineGeneric,
         ArrayBufferObject::obj_defineProperty,
         ArrayBufferObject::obj_defineElement,
-        ArrayBufferObject::obj_defineSpecial,
         ArrayBufferObject::obj_getGeneric,
         ArrayBufferObject::obj_getProperty,
         ArrayBufferObject::obj_getElement,
-        ArrayBufferObject::obj_getSpecial,
         ArrayBufferObject::obj_setGeneric,
         ArrayBufferObject::obj_setProperty,
         ArrayBufferObject::obj_setElement,
-        ArrayBufferObject::obj_setSpecial,
         ArrayBufferObject::obj_getGenericAttributes,
         ArrayBufferObject::obj_setGenericAttributes,
         ArrayBufferObject::obj_deleteProperty,
         ArrayBufferObject::obj_deleteElement,
-        ArrayBufferObject::obj_deleteSpecial,
         nullptr, nullptr, /* watch/unwatch */
         nullptr,          /* slice */
         ArrayBufferObject::obj_enumerate,
         nullptr,          /* thisObject      */
     }
 };
 
 const JSFunctionSpec ArrayBufferObject::jsfuncs[] = {
@@ -1026,24 +1021,16 @@ ArrayBufferObject::obj_lookupElement(JSC
         return JSObject::lookupElement(cx, proto, index, objp, propp);
 
     objp.set(nullptr);
     propp.set(nullptr);
     return true;
 }
 
 bool
-ArrayBufferObject::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                                     MutableHandleObject objp, MutableHandleShape propp)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return obj_lookupGeneric(cx, obj, id, objp, propp);
-}
-
-bool
 ArrayBufferObject::obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
                                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
@@ -1067,24 +1054,16 @@ ArrayBufferObject::obj_defineElement(JSC
 
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::DefineElement(cx, delegate, index, v, getter, setter, attrs);
 }
 
 bool
-ArrayBufferObject::obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue v,
-                                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs);
-}
-
-bool
 ArrayBufferObject::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
                                   HandleId id, MutableHandleValue vp)
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::GetProperty(cx, delegate, receiver, id, vp);
 }
@@ -1106,25 +1085,16 @@ ArrayBufferObject::obj_getElement(JSCont
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::GetElement(cx, delegate, receiver, index, vp);
 }
 
 bool
-ArrayBufferObject::obj_getSpecial(JSContext *cx, HandleObject obj,
-                                  HandleObject receiver, HandleSpecialId sid,
-                                  MutableHandleValue vp)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return obj_getGeneric(cx, obj, receiver, id, vp);
-}
-
-bool
 ArrayBufferObject::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                   MutableHandleValue vp, bool strict)
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
 
     return baseops::SetPropertyHelper<SequentialExecution>(cx, delegate, obj, id, 0, vp, strict);
@@ -1145,24 +1115,16 @@ ArrayBufferObject::obj_setElement(JSCont
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
 
     return baseops::SetElementHelper(cx, delegate, obj, index, 0, vp, strict);
 }
 
 bool
-ArrayBufferObject::obj_setSpecial(JSContext *cx, HandleObject obj,
-                                  HandleSpecialId sid, MutableHandleValue vp, bool strict)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return obj_setGeneric(cx, obj, id, vp, strict);
-}
-
-bool
 ArrayBufferObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                             HandleId id, unsigned *attrsp)
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::GetAttributes(cx, delegate, id, attrsp);
 }
@@ -1193,26 +1155,16 @@ ArrayBufferObject::obj_deleteElement(JSC
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::DeleteElement(cx, delegate, index, succeeded);
 }
 
 bool
-ArrayBufferObject::obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                                     bool *succeeded)
-{
-    RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
-    if (!delegate)
-        return false;
-    return baseops::DeleteSpecial(cx, delegate, sid, succeeded);
-}
-
-bool
 ArrayBufferObject::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
                                  MutableHandleValue statep, MutableHandleId idp)
 {
     statep.setNull();
     return true;
 }
 
 /*
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -85,62 +85,48 @@ class ArrayBufferObject : public JSObjec
     static void obj_trace(JSTracer *trc, JSObject *obj);
 
     static bool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                   MutableHandleObject objp, MutableHandleShape propp);
     static bool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                    MutableHandleObject objp, MutableHandleShape propp);
     static bool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
                                   MutableHandleObject objp, MutableHandleShape propp);
-    static bool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                                  MutableHandleObject objp, MutableHandleShape propp);
 
     static bool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
                                   PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     static bool obj_defineProperty(JSContext *cx, HandleObject obj,
                                    HandlePropertyName name, HandleValue v,
                                    PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     static bool obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
                                   PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
-    static bool obj_defineSpecial(JSContext *cx, HandleObject obj,
-                                  HandleSpecialId sid, HandleValue v,
-                                  PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 
     static bool obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
                                HandleId id, MutableHandleValue vp);
-
     static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
                                 HandlePropertyName name, MutableHandleValue vp);
-
     static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
                                uint32_t index, MutableHandleValue vp);
 
-    static bool obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver,
-                               HandleSpecialId sid, MutableHandleValue vp);
-
     static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                MutableHandleValue vp, bool strict);
     static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                 MutableHandleValue vp, bool strict);
     static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
                                MutableHandleValue vp, bool strict);
-    static bool obj_setSpecial(JSContext *cx, HandleObject obj,
-                               HandleSpecialId sid, MutableHandleValue vp, bool strict);
 
     static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                          HandleId id, unsigned *attrsp);
     static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
                                          HandleId id, unsigned *attrsp);
 
     static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                    bool *succeeded);
     static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
                                   bool *succeeded);
-    static bool obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                                  bool *succeeded);
 
     static bool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
                               MutableHandleValue statep, MutableHandleId idp);
 
     static void sweep(JSCompartment *rt);
 
     static void resetArrayBufferList(JSCompartment *rt);
     static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -340,29 +340,16 @@ GetObjectElementOperation(JSContext *cx,
 
             RootedObject obj(cx, objArg);
             if (!JSObject::getElement(cx, obj, obj, index, res))
                 return false;
             objArg = obj;
             break;
         }
 
-        if (ValueMightBeSpecial(rref)) {
-            RootedObject obj(cx, objArg);
-            Rooted<SpecialId> special(cx);
-            res.set(rref);
-            if (ValueIsSpecial(obj, res, &special, cx)) {
-                if (!JSObject::getSpecial(cx, obj, obj, special, res))
-                    return false;
-                objArg = obj;
-                break;
-            }
-            objArg = obj;
-        }
-
         JSAtom *name = ToAtom<NoGC>(cx, rref);
         if (name) {
             if (name->isIndex(&index)) {
                 if (JSObject::getElementNoGC(cx, objArg, objArg, index, res.address()))
                     break;
             } else {
                 if (JSObject::getPropertyNoGC(cx, objArg, objArg, name->asPropertyName(), res.address()))
                     break;
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -453,24 +453,16 @@ with_LookupElement(JSContext *cx, Handle
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return with_LookupGeneric(cx, obj, id, objp, propp);
 }
 
 static bool
-with_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                   MutableHandleObject objp, MutableHandleShape propp)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return with_LookupGeneric(cx, obj, id, objp, propp);
-}
-
-static bool
 with_GetGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
                 MutableHandleValue vp)
 {
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
     return JSObject::getGeneric(cx, actual, actual, id, vp);
 }
 
 static bool
@@ -487,24 +479,16 @@ with_GetElement(JSContext *cx, HandleObj
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return with_GetGeneric(cx, obj, receiver, id, vp);
 }
 
 static bool
-with_GetSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid,
-                MutableHandleValue vp)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return with_GetGeneric(cx, obj, receiver, id, vp);
-}
-
-static bool
 with_SetGeneric(JSContext *cx, HandleObject obj, HandleId id,
                 MutableHandleValue vp, bool strict)
 {
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
     return JSObject::setGeneric(cx, actual, actual, id, vp, strict);
 }
 
 static bool
@@ -519,24 +503,16 @@ static bool
 with_SetElement(JSContext *cx, HandleObject obj, uint32_t index,
                 MutableHandleValue vp, bool strict)
 {
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
     return JSObject::setElement(cx, actual, actual, index, vp, strict);
 }
 
 static bool
-with_SetSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                MutableHandleValue vp, bool strict)
-{
-    RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
-    return JSObject::setSpecial(cx, actual, actual, sid, vp, strict);
-}
-
-static bool
 with_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
     return JSObject::getGenericAttributes(cx, actual, id, attrsp);
 }
 
 static bool
 with_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
@@ -556,24 +532,16 @@ with_DeleteProperty(JSContext *cx, Handl
 static bool
 with_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index,
                    bool *succeeded)
 {
     RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
     return JSObject::deleteElement(cx, actual, index, succeeded);
 }
 
-static bool
-with_DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                   bool *succeeded)
-{
-    RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
-    return JSObject::deleteSpecial(cx, actual, sid, succeeded);
-}
-
 static JSObject *
 with_ThisObject(JSContext *cx, HandleObject obj)
 {
     return &obj->as<DynamicWithObject>().withThis();
 }
 
 const Class StaticWithObject::class_ = {
     "WithTemplate",
@@ -606,34 +574,29 @@ const Class DynamicWithObject::class_ = 
     nullptr,                 /* construct   */
     nullptr,                 /* trace       */
     JS_NULL_CLASS_SPEC,
     JS_NULL_CLASS_EXT,
     {
         with_LookupGeneric,
         with_LookupProperty,
         with_LookupElement,
-        with_LookupSpecial,
         nullptr,             /* defineGeneric */
         nullptr,             /* defineProperty */
         nullptr,             /* defineElement */
-        nullptr,             /* defineSpecial */
         with_GetGeneric,
         with_GetProperty,
         with_GetElement,
-        with_GetSpecial,
         with_SetGeneric,
         with_SetProperty,
         with_SetElement,
-        with_SetSpecial,
         with_GetGenericAttributes,
         with_SetGenericAttributes,
         with_DeleteProperty,
         with_DeleteElement,
-        with_DeleteSpecial,
         nullptr, nullptr,    /* watch/unwatch */
         nullptr,             /* slice */
         nullptr,             /* enumerate (native enumeration of target doesn't work) */
         with_ThisObject,
     }
 };
 
 /*****************************************************************************/
--- a/js/src/vm/SharedArrayObject.cpp
+++ b/js/src/vm/SharedArrayObject.cpp
@@ -315,34 +315,29 @@ const Class SharedArrayBufferObject::cla
     nullptr,        /* construct   */
     ArrayBufferObject::obj_trace,
     JS_NULL_CLASS_SPEC,
     JS_NULL_CLASS_EXT,
     {
         ArrayBufferObject::obj_lookupGeneric,
         ArrayBufferObject::obj_lookupProperty,
         ArrayBufferObject::obj_lookupElement,
-        ArrayBufferObject::obj_lookupSpecial,
         ArrayBufferObject::obj_defineGeneric,
         ArrayBufferObject::obj_defineProperty,
         ArrayBufferObject::obj_defineElement,
-        ArrayBufferObject::obj_defineSpecial,
         ArrayBufferObject::obj_getGeneric,
         ArrayBufferObject::obj_getProperty,
         ArrayBufferObject::obj_getElement,
-        ArrayBufferObject::obj_getSpecial,
         ArrayBufferObject::obj_setGeneric,
         ArrayBufferObject::obj_setProperty,
         ArrayBufferObject::obj_setElement,
-        ArrayBufferObject::obj_setSpecial,
         ArrayBufferObject::obj_getGenericAttributes,
         ArrayBufferObject::obj_setGenericAttributes,
         ArrayBufferObject::obj_deleteProperty,
         ArrayBufferObject::obj_deleteElement,
-        ArrayBufferObject::obj_deleteSpecial,
         nullptr, nullptr, /* watch/unwatch */
         nullptr,          /* slice */
         ArrayBufferObject::obj_enumerate,
         nullptr,          /* thisObject      */
     }
 };
 
 JSObject *
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -687,34 +687,29 @@ const XPCWrappedNativeJSClass XPC_WN_NoH
         true,   // isWrappedNative
     },
 
     // ObjectOps
     {
         nullptr, // lookupGeneric
         nullptr, // lookupProperty
         nullptr, // lookupElement
-        nullptr, // lookupSpecial
         nullptr, // defineGeneric
         nullptr, // defineProperty
         nullptr, // defineElement
-        nullptr, // defineSpecial
         nullptr, // getGeneric
         nullptr, // getProperty
         nullptr, // getElement
-        nullptr, // getSpecial
         nullptr, // setGeneric
         nullptr, // setProperty
         nullptr, // setElement
-        nullptr, // setSpecial
         nullptr, // getGenericAttributes
         nullptr, // setGenericAttributes
         nullptr, // deleteProperty
         nullptr, // deleteElement
-        nullptr, // deleteSpecial
         nullptr, nullptr, // watch/unwatch
         nullptr, // slice
         XPC_WN_JSOp_Enumerate,
         XPC_WN_JSOp_ThisObject,
     }
   },
   0 // interfacesBitmap
 };
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -902,63 +902,53 @@ extern JSObject*
 XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
 
 // Macros to initialize Object or Function like XPC_WN classes
 #define XPC_WN_WithCall_ObjectOps                                             \
     {                                                                         \
         nullptr, /* lookupGeneric */                                          \
         nullptr, /* lookupProperty */                                         \
         nullptr, /* lookupElement */                                          \
-        nullptr, /* lookupSpecial */                                          \
         nullptr, /* defineGeneric */                                          \
         nullptr, /* defineProperty */                                         \
         nullptr, /* defineElement */                                          \
-        nullptr, /* defineSpecial */                                          \
         nullptr, /* getGeneric    */                                          \
         nullptr, /* getProperty    */                                         \
         nullptr, /* getElement    */                                          \
-        nullptr, /* getSpecial    */                                          \
         nullptr, /* setGeneric    */                                          \
         nullptr, /* setProperty    */                                         \
         nullptr, /* setElement    */                                          \
-        nullptr, /* setSpecial    */                                          \
         nullptr, /* getGenericAttributes  */                                  \
         nullptr, /* setGenericAttributes  */                                  \
         nullptr, /* deleteProperty */                                         \
         nullptr, /* deleteElement */                                          \
-        nullptr, /* deleteSpecial */                                          \
         nullptr, nullptr, /* watch/unwatch */                                 \
         nullptr, /* slice */                                                  \
         XPC_WN_JSOp_Enumerate,                                                \
         XPC_WN_JSOp_ThisObject,                                               \
     }
 
 #define XPC_WN_NoCall_ObjectOps                                               \
     {                                                                         \
         nullptr, /* lookupGeneric */                                          \
         nullptr, /* lookupProperty */                                         \
         nullptr, /* lookupElement */                                          \
-        nullptr, /* lookupSpecial */                                          \
         nullptr, /* defineGeneric */                                          \
         nullptr, /* defineProperty */                                         \
         nullptr, /* defineElement */                                          \
-        nullptr, /* defineSpecial */                                          \
         nullptr, /* getGeneric    */                                          \
         nullptr, /* getProperty    */                                         \
         nullptr, /* getElement    */                                          \
-        nullptr, /* getSpecial    */                                          \
         nullptr, /* setGeneric    */                                          \
         nullptr, /* setProperty    */                                         \
         nullptr, /* setElement    */                                          \
-        nullptr, /* setSpecial    */                                          \
         nullptr, /* getGenericAttributes  */                                  \
         nullptr, /* setGenericAttributes  */                                  \
         nullptr, /* deleteProperty */                                         \
         nullptr, /* deleteElement */                                          \
-        nullptr, /* deleteSpecial */                                          \
         nullptr, nullptr, /* watch/unwatch */                                 \
         nullptr, /* slice */                                                  \
         XPC_WN_JSOp_Enumerate,                                                \
         XPC_WN_JSOp_ThisObject,                                               \
     }
 
 // Maybe this macro should check for class->enumerate ==
 // XPC_WN_Shared_Proto_Enumerate or something rather than checking for