Backed out changeset b4b619628d1d (bug 1103368) for b2g build bustage
authorWes Kocher <wkocher@mozilla.com>
Mon, 24 Nov 2014 17:03:44 -0800
changeset 241611 c80672f72db67fa665c49642f2a73801b27249d8
parent 241610 6a871ae07d1fc0293f5635b921366b07bddc4e1a
child 241612 56ebb99d774eef30488e7fcca268308ed15e0660
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1103368
milestone36.0a1
backs outb4b619628d1d1ffd28413d102f11ee89a7f77819
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
Backed out changeset b4b619628d1d (bug 1103368) for b2g build bustage
dom/base/nsDOMClassInfo.cpp
dom/bindings/BindingUtils.cpp
dom/bindings/Codegen.py
dom/indexedDB/ActorsParent.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/plugins/base/nsJSNPRuntime.cpp
dom/xbl/nsXBLBinding.cpp
js/ipc/JavaScriptShared.cpp
js/public/Class.h
js/src/asmjs/AsmJSModule.cpp
js/src/builtin/AtomicsObject.cpp
js/src/builtin/Intl.cpp
js/src/builtin/MapObject.cpp
js/src/builtin/SIMD.cpp
js/src/builtin/SymbolObject.cpp
js/src/builtin/TestingFunctions.cpp
js/src/builtin/TypedObject.cpp
js/src/builtin/WeakSetObject.cpp
js/src/ctypes/CTypes.cpp
js/src/ctypes/Library.cpp
js/src/gdb/gdb-tests.cpp
js/src/jit/IonCaches.cpp
js/src/jsapi-tests/testAddPropertyPropcache.cpp
js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
js/src/jsapi-tests/testChromeBuffer.cpp
js/src/jsapi-tests/testClassGetter.cpp
js/src/jsapi-tests/testFreshGlobalEvalRedefinition.cpp
js/src/jsapi-tests/testLookup.cpp
js/src/jsapi-tests/testNewObject.cpp
js/src/jsapi-tests/testObjectEmulatingUndefined.cpp
js/src/jsapi-tests/testOps.cpp
js/src/jsapi-tests/testPersistentRooted.cpp
js/src/jsapi-tests/testProfileStrings.cpp
js/src/jsapi-tests/testPropCache.cpp
js/src/jsapi-tests/testResolveRecursion.cpp
js/src/jsapi-tests/testWeakMap.cpp
js/src/jsapi-tests/tests.h
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jscntxtinlines.h
js/src/jsdate.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsiter.cpp
js/src/jsmath.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/json.cpp
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jsweakmap.cpp
js/src/perf/jsperf.cpp
js/src/proxy/BaseProxyHandler.cpp
js/src/proxy/Proxy.cpp
js/src/shell/js.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/ArrayBufferObject.cpp
js/src/vm/Debugger.cpp
js/src/vm/DebuggerMemory.cpp
js/src/vm/GeneratorObject.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/HelperThreads.cpp
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/NativeObject.cpp
js/src/vm/PIC.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpStatics.cpp
js/src/vm/SavedStacks.cpp
js/src/vm/ScopeObject.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/Shape-inl.h
js/src/vm/SharedArrayObject.cpp
js/src/vm/SharedTypedArrayObject.cpp
js/src/vm/TypedArrayObject.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/wrappers/XrayWrapper.cpp
netwerk/base/src/ProxyAutoConfig.cpp
toolkit/components/finalizationwitness/FinalizationWitnessService.cpp
toolkit/components/telemetry/Telemetry.cpp
xpcom/glue/tests/gtest/TestGCPostBarriers.cpp
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -425,17 +425,18 @@ NS_INTERFACE_MAP_BEGIN(nsDOMClassInfo)
   else
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIClassInfo)
 NS_INTERFACE_MAP_END
 
 
 static const JSClass sDOMConstructorProtoClass = {
-  "DOM Constructor.prototype", 0
+  "DOM Constructor.prototype", 0,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 
 static const char *
 CutPrefix(const char *aName) {
   static const char prefix_nsIDOM[] = "nsIDOM";
   static const char prefix_nsI[]    = "nsI";
 
@@ -2045,17 +2046,18 @@ nsWindowSH::NameStructEnabled(JSContext*
 }
 
 #ifdef RELEASE_BUILD
 #define USE_CONTROLLERS_SHIM
 #endif
 
 #ifdef USE_CONTROLLERS_SHIM
 static const JSClass ControllersShimClass = {
-    "XULControllers", 0
+    "XULControllers", 0,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 #endif
 
 // static
 nsresult
 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                           JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                           JS::MutableHandle<JSPropertyDescriptor> desc)
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1193,18 +1193,18 @@ ResolvePrototypeOrConstructor(JSContext*
     if (!protoOrIface) {
       return false;
     }
 
     cacheOnHolder = true;
 
     desc.object().set(wrapper);
     desc.setAttributes(attrs);
-    desc.setGetter(nullptr);
-    desc.setSetter(nullptr);
+    desc.setGetter(JS_PropertyStub);
+    desc.setSetter(JS_StrictPropertyStub);
     desc.value().set(JS::ObjectValue(*protoOrIface));
   }
   return JS_WrapPropertyDescriptor(cx, desc);
 }
 
 #ifdef DEBUG
 
 static void
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -430,18 +430,18 @@ class CGDOMJSClass(CGThing):
 
         return fill(
             """
             static const DOMJSClass Class = {
               { "${name}",
                 ${flags},
                 ${addProperty}, /* addProperty */
                 nullptr,               /* delProperty */
-                nullptr,               /* getProperty */
-                nullptr,               /* setProperty */
+                JS_PropertyStub,       /* getProperty */
+                JS_StrictPropertyStub, /* setProperty */
                 ${enumerate}, /* enumerate */
                 ${resolve}, /* resolve */
                 nullptr,               /* convert */
                 ${finalize}, /* finalize */
                 ${call}, /* call */
                 nullptr,               /* hasInstance */
                 nullptr,               /* construct */
                 ${trace}, /* trace */
@@ -646,18 +646,18 @@ class CGPrototypeJSClass(CGThing):
         return fill(
             """
             static const DOMIfaceAndProtoJSClass PrototypeClass = {
               {
                 "${name}Prototype",
                 JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(${slotCount}),
                 nullptr,               /* addProperty */
                 nullptr,               /* delProperty */
-                nullptr,               /* getProperty */
-                nullptr,               /* setProperty */
+                JS_PropertyStub,       /* getProperty */
+                JS_StrictPropertyStub, /* setProperty */
                 nullptr,               /* enumerate */
                 nullptr,               /* resolve */
                 nullptr,               /* convert */
                 nullptr,               /* finalize */
                 nullptr,               /* call */
                 nullptr,               /* hasInstance */
                 nullptr,               /* construct */
                 nullptr,               /* trace */
@@ -742,18 +742,18 @@ class CGInterfaceObjectJSClass(CGThing):
         return fill(
             """
             static const DOMIfaceAndProtoJSClass InterfaceObjectClass = {
               {
                 "Function",
                 JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(${slotCount}),
                 nullptr,               /* addProperty */
                 nullptr,               /* delProperty */
-                nullptr,               /* getProperty */
-                nullptr,               /* setProperty */
+                JS_PropertyStub,       /* getProperty */
+                JS_StrictPropertyStub, /* setProperty */
                 nullptr,               /* enumerate */
                 nullptr,               /* resolve */
                 nullptr,               /* convert */
                 nullptr,               /* finalize */
                 ${ctorname}, /* call */
                 ${hasInstance}, /* hasInstance */
                 ${ctorname}, /* construct */
                 nullptr,               /* trace */
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -14190,18 +14190,18 @@ CreateIndexOp::DoDatabaseWork(Transactio
   return NS_OK;
 }
 
 const JSClass CreateIndexOp::ThreadLocalJSRuntime::kGlobalClass = {
   "IndexedDBTransactionThreadGlobal",
   JSCLASS_GLOBAL_FLAGS,
   /* addProperty */ nullptr,
   /* delProperty */ nullptr,
-  /* getProperty */ nullptr,
-  /* setProperty */ nullptr,
+  /* getProperty */ JS_PropertyStub,
+  /* setProperty */ JS_StrictPropertyStub,
   /* enumerate */ nullptr,
   /* resolve */ nullptr,
   /* convert */ nullptr,
   /* finalize */ nullptr,
   /* call */ nullptr,
   /* hasInstance */ nullptr,
   /* construct */ nullptr,
   /* trace */ JS_GlobalObjectTraceHook
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -837,17 +837,21 @@ ClearStructuredCloneBuffer(JSAutoStructu
     aBuffer.clear();
   }
 }
 
 } // anonymous namespace
 
 const JSClass IDBObjectStore::sDummyPropJSClass = {
   "IDBObjectStore Dummy",
-  0 /* flags */
+  0 /* flags */,
+  nullptr /* addProperty */,
+  nullptr /* delProperty */,
+  JS_PropertyStub /* getProperty */,
+  JS_StrictPropertyStub /* setProperty */
 };
 
 IDBObjectStore::IDBObjectStore(IDBTransaction* aTransaction,
                                const ObjectStoreSpec* aSpec)
   : mTransaction(aTransaction)
   , mCachedKeyPath(JSVAL_VOID)
   , mSpec(aSpec)
   , mId(aSpec->metadata().id())
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -224,18 +224,19 @@ static bool
 NPObjectMember_Call(JSContext *cx, unsigned argc, JS::Value *vp);
 
 static void
 NPObjectMember_Trace(JSTracer *trc, JSObject *obj);
 
 static const JSClass sNPObjectMemberClass =
   {
     "NPObject Ambiguous Member class", JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS,
-    nullptr, nullptr, nullptr, nullptr,
-    nullptr, nullptr, NPObjectMember_Convert,
+    nullptr, nullptr,
+    JS_PropertyStub, JS_StrictPropertyStub, nullptr,
+    nullptr, NPObjectMember_Convert,
     NPObjectMember_Finalize, NPObjectMember_Call,
     nullptr, nullptr, NPObjectMember_Trace
   };
 
 static void
 OnWrapperDestroyed();
 
 static void
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -87,17 +87,18 @@ XBLEnumerate(JSContext *cx, JS::Handle<J
   return protoBinding->ResolveAllFields(cx, obj);
 }
 
 static const JSClass gPrototypeJSClass = {
     "XBL prototype JSClass",
     JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
     // Our one reserved slot holds the relevant nsXBLPrototypeBinding
     JSCLASS_HAS_RESERVED_SLOTS(1),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr,
+    JS_PropertyStub, JS_StrictPropertyStub,
     XBLEnumerate, nullptr,
     nullptr, XBLFinalize,
     nullptr, nullptr, nullptr, nullptr
 };
 
 // Implementation /////////////////////////////////////////////////////////////////
 
 // Constructors/Destructors
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -549,31 +549,35 @@ JavaScriptShared::fromDescriptor(JSConte
         out->getter() = 0;
     } else if (desc.hasGetterObject()) {
         JSObject *getter = desc.getterObject();
         ObjectVariant objVar;
         if (!toObjectVariant(cx, getter, &objVar))
             return false;
         out->getter() = objVar;
     } else {
-        MOZ_ASSERT(desc.getter() != JS_PropertyStub);
-        out->getter() = UnknownPropertyOp;
+        if (desc.getter() == JS_PropertyStub)
+            out->getter() = 0;
+        else
+            out->getter() = UnknownPropertyOp;
     }
 
     if (!desc.setter()) {
         out->setter() = 0;
     } else if (desc.hasSetterObject()) {
         JSObject *setter = desc.setterObject();
         ObjectVariant objVar;
         if (!toObjectVariant(cx, setter, &objVar))
             return false;
         out->setter() = objVar;
     } else {
-        MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
-        out->setter() = UnknownPropertyOp;
+        if (desc.setter() == JS_StrictPropertyStub)
+            out->setter() = 0;
+        else
+            out->setter() = UnknownPropertyOp;
     }
 
     return true;
 }
 
 bool
 UnknownPropertyStub(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
 {
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -277,24 +277,26 @@ typedef JSObject *
 
 typedef void
 (* FinalizeOp)(FreeOp *fop, JSObject *obj);
 
 #define JS_CLASS_MEMBERS(FinalizeOpType)                                      \
     const char          *name;                                                \
     uint32_t            flags;                                                \
                                                                               \
-    /* Function pointer members (may be null). */                             \
+    /* Mandatory function pointer members. */                                 \
     JSPropertyOp        addProperty;                                          \
     JSDeletePropertyOp  delProperty;                                          \
     JSPropertyOp        getProperty;                                          \
     JSStrictPropertyOp  setProperty;                                          \
     JSEnumerateOp       enumerate;                                            \
     JSResolveOp         resolve;                                              \
     JSConvertOp         convert;                                              \
+                                                                              \
+    /* Optional members (may be null). */                                     \
     FinalizeOpType      finalize;                                             \
     JSNative            call;                                                 \
     JSHasInstanceOp     hasInstance;                                          \
     JSNative            construct;                                            \
     JSTraceOp           trace
 
 // Callback for the creation of constructor and prototype objects.
 typedef JSObject *(*ClassObjectCreationOp)(JSContext *cx, JSProtoKey key);
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -934,27 +934,27 @@ AsmJSModuleObject_trace(JSTracer *trc, J
 {
     obj->as<AsmJSModuleObject>().module().trace(trc);
 }
 
 const Class AsmJSModuleObject::class_ = {
     "AsmJSModuleObject",
     JSCLASS_IS_ANONYMOUS | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(AsmJSModuleObject::RESERVED_SLOTS),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     AsmJSModuleObject_finalize,
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
+    nullptr,                 /* call        */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct   */
     AsmJSModuleObject_trace
 };
 
 AsmJSModuleObject *
 AsmJSModuleObject::create(ExclusiveContext *cx, ScopedJSDeletePtr<AsmJSModule> *module)
 {
     JSObject *obj = NewObjectWithGivenProto(cx, &AsmJSModuleObject::class_, nullptr, nullptr);
     if (!obj)
--- a/js/src/builtin/AtomicsObject.cpp
+++ b/js/src/builtin/AtomicsObject.cpp
@@ -140,17 +140,21 @@ MSC_FETCHBITOP(uint32_t, long, _Interloc
 # undef MSC_FETCHBITOP
 
 #elif defined(ENABLE_SHARED_ARRAY_BUFFER)
 # error "Either disable JS shared memory or use a compiler that supports C++11 atomics or GCC/clang atomics"
 #endif
 
 const Class AtomicsObject::class_ = {
     "Atomics",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Atomics)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Atomics),
+    nullptr,                 // addProperty
+    nullptr,                 // delProperty
+    JS_PropertyStub,
+    JS_StrictPropertyStub
 };
 
 static bool
 ReportBadArrayType(JSContext *cx)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_ATOMICS_BAD_ARRAY);
     return false;
 }
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -554,23 +554,23 @@ static const size_t INITIAL_CHAR_BUFFER_
 static void collator_finalize(FreeOp *fop, JSObject *obj);
 
 static const uint32_t UCOLLATOR_SLOT = 0;
 static const uint32_t COLLATOR_SLOTS_COUNT = 1;
 
 static const Class CollatorClass = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(COLLATOR_SLOTS_COUNT),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     collator_finalize
 };
 
 #if JS_HAS_TOSOURCE
 static bool
 collator_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1040,23 +1040,23 @@ js::intl_CompareStrings(JSContext *cx, u
 static void numberFormat_finalize(FreeOp *fop, JSObject *obj);
 
 static const uint32_t UNUMBER_FORMAT_SLOT = 0;
 static const uint32_t NUMBER_FORMAT_SLOTS_COUNT = 1;
 
 static const Class NumberFormatClass = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(NUMBER_FORMAT_SLOTS_COUNT),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     numberFormat_finalize
 };
 
 #if JS_HAS_TOSOURCE
 static bool
 numberFormat_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1497,23 +1497,23 @@ js::intl_FormatNumber(JSContext *cx, uns
 static void dateTimeFormat_finalize(FreeOp *fop, JSObject *obj);
 
 static const uint32_t UDATE_FORMAT_SLOT = 0;
 static const uint32_t DATE_TIME_FORMAT_SLOTS_COUNT = 1;
 
 static const Class DateTimeFormatClass = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(DATE_TIME_FORMAT_SLOTS_COUNT),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     dateTimeFormat_finalize
 };
 
 #if JS_HAS_TOSOURCE
 static bool
 dateTimeFormat_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1992,17 +1992,21 @@ js::intl_FormatDateTime(JSContext *cx, u
     return true;
 }
 
 
 /******************** Intl ********************/
 
 const Class js::IntlClass = {
     js_Object_str,
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Intl)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Intl),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 #if JS_HAS_TOSOURCE
 static bool
 intl_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setString(cx->names().Intl);
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -862,23 +862,23 @@ class MapIteratorObject : public NativeO
 };
 
 } /* anonymous namespace */
 
 const Class MapIteratorObject::class_ = {
     "Map Iterator",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(MapIteratorObject::SlotCount),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     MapIteratorObject::finalize
 };
 
 const JSFunctionSpec MapIteratorObject::methods[] = {
     JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
     JS_FN("next", next, 0, 0),
     JS_FS_END
 };
@@ -1006,27 +1006,27 @@ MapIteratorObject::next(JSContext *cx, u
 
 
 /*** Map *****************************************************************************************/
 
 const Class MapObject::class_ = {
     "Map",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Map),
-    nullptr, // addProperty
-    nullptr, // delProperty
-    nullptr, // getProperty
-    nullptr, // setProperty
-    nullptr, // enumerate
-    nullptr, // resolve
-    nullptr, // convert
+    nullptr,                 // addProperty
+    nullptr,                 // delProperty
+    JS_PropertyStub,         // getProperty
+    JS_StrictPropertyStub,   // setProperty
+    nullptr,                 // enumerate
+    nullptr,                 // resolve
+    nullptr,                 // convert
     finalize,
-    nullptr, // call
-    nullptr, // hasInstance
-    nullptr, // construct
+    nullptr,                 // call
+    nullptr,                 // hasInstance
+    nullptr,                 // construct
     mark
 };
 
 const JSPropertySpec MapObject::properties[] = {
     JS_PSG("size", size, 0),
     JS_PS_END
 };
 
@@ -1519,23 +1519,23 @@ class SetIteratorObject : public NativeO
 };
 
 } /* anonymous namespace */
 
 const Class SetIteratorObject::class_ = {
     "Set Iterator",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(SetIteratorObject::SlotCount),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     SetIteratorObject::finalize
 };
 
 const JSFunctionSpec SetIteratorObject::methods[] = {
     JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
     JS_FN("next", next, 0, 0),
     JS_FS_END
 };
@@ -1659,27 +1659,27 @@ SetIteratorObject::next(JSContext *cx, u
 
 
 /*** Set *****************************************************************************************/
 
 const Class SetObject::class_ = {
     "Set",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Set),
-    nullptr, // addProperty
-    nullptr, // delProperty
-    nullptr, // getProperty
-    nullptr, // setProperty
-    nullptr, // enumerate
-    nullptr, // resolve
-    nullptr, // convert
+    nullptr,                 // addProperty
+    nullptr,                 // delProperty
+    JS_PropertyStub,         // getProperty
+    JS_StrictPropertyStub,   // setProperty
+    nullptr,                 // enumerate
+    nullptr,                 // resolve
+    nullptr,                 // convert
     finalize,
-    nullptr, // call
-    nullptr, // hasInstance
-    nullptr, // construct
+    nullptr,                 // call
+    nullptr,                 // hasInstance
+    nullptr,                 // construct
     mark
 };
 
 const JSPropertySpec SetObject::properties[] = {
     JS_PSG("size", size, 0),
     JS_PS_END
 };
 
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -163,25 +163,28 @@ static bool type##SignMask(JSContext *cx
 }
     SIGN_MASK(Float32x4);
     SIGN_MASK(Int32x4);
 #undef SIGN_MASK
 
 const Class SimdTypeDescr::class_ = {
     "SIMD",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    call
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate   */
+    nullptr,                 /* resolve     */
+    nullptr,                 /* convert     */
+    nullptr,                 /* finalize    */
+    call,                    /* call        */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct   */
+    nullptr
 };
 
 // These classes just exist to group together various properties and so on.
 namespace js {
 class Int32x4Defn {
   public:
     static const SimdTypeDescr::Type type = SimdTypeDescr::TYPE_INT32;
     static const JSFunctionSpec TypeDescriptorMethods[];
@@ -345,17 +348,21 @@ SimdTypeDescr::call(JSContext *cx, unsig
     return true;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // SIMD class
 
 const Class SIMDObject::class_ = {
     "SIMD",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_SIMD)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_SIMD),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 JSObject *
 SIMDObject::initClass(JSContext *cx, Handle<GlobalObject *> global)
 {
     // SIMD relies on having the TypedObject module initialized.
     // In particular, the self-hosted code for array() wants
     // to be able to call GetTypedObjectModule(). It is NOT necessary
--- a/js/src/builtin/SymbolObject.cpp
+++ b/js/src/builtin/SymbolObject.cpp
@@ -14,22 +14,22 @@
 #include "vm/Symbol-inl.h"
 
 using JS::Symbol;
 using namespace js;
 
 const Class SymbolObject::class_ = {
     "Symbol",
     JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_Symbol),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
     convert
 };
 
 SymbolObject *
 SymbolObject::create(JSContext *cx, JS::Symbol *symbol)
 {
     JSObject *obj = NewBuiltinClassInstance(cx, &class_);
     if (!obj)
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -953,17 +953,21 @@ OOMAfterAllocations(JSContext *cx, unsig
         return false;
 
     OOM_maxAllocations = OOM_counter + count;
     return true;
 }
 #endif
 
 static const js::Class FakePromiseClass = {
-    "Promise", JSCLASS_IS_ANONYMOUS
+    "Promise", JSCLASS_IS_ANONYMOUS,
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub  /* setProperty */
 };
 
 static bool
 MakeFakePromise(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject scope(cx, cx->global());
     if (!scope)
@@ -999,23 +1003,23 @@ static unsigned finalizeCount = 0;
 static void
 finalize_counter_finalize(JSFreeOp *fop, JSObject *obj)
 {
     ++finalizeCount;
 }
 
 static const JSClass FinalizeCounterClass = {
     "FinalizeCounter", JSCLASS_IS_ANONYMOUS,
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub, /* setProperty */
+    nullptr,               /* enumerate */
+    nullptr,               /* resolve */
+    nullptr,               /* convert */
     finalize_counter_finalize
 };
 
 static bool
 MakeFinalizeObserver(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject scope(cx, JS::CurrentGlobalOrNull(cx));
@@ -1541,24 +1545,31 @@ class CloneBufferObject : public NativeO
 
     static void Finalize(FreeOp *fop, JSObject *obj) {
         obj->as<CloneBufferObject>().discard();
     }
 };
 
 const Class CloneBufferObject::class_ = {
     "CloneBuffer", JSCLASS_HAS_RESERVED_SLOTS(CloneBufferObject::NUM_SLOTS),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    Finalize
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub, /* setProperty */
+    nullptr,               /* enumerate */
+    nullptr,               /* resolve */
+    nullptr,               /* convert */
+    Finalize,
+    nullptr,                  /* call */
+    nullptr,                  /* hasInstance */
+    nullptr,                  /* construct */
+    nullptr,                  /* trace */
+    JS_NULL_CLASS_SPEC,
+    JS_NULL_CLASS_EXT,
+    JS_NULL_OBJECT_OPS
 };
 
 const JSPropertySpec CloneBufferObject::props_[] = {
     JS_PSGS("clonebuffer", getCloneBuffer, setCloneBuffer, 0),
     JS_PS_END
 };
 
 static bool
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -30,17 +30,21 @@ using mozilla::AssertedCast;
 using mozilla::CheckedInt32;
 using mozilla::DebugOnly;
 
 using namespace js;
 
 const Class js::TypedObjectModuleObject::class_ = {
     "TypedObject",
     JSCLASS_HAS_RESERVED_SLOTS(SlotCount) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_TypedObject)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_TypedObject),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 static const JSFunctionSpec TypedObjectMethods[] = {
     JS_SELF_HOSTED_FN("objectType", "TypeOfTypedObject", 1, 0),
     JS_SELF_HOSTED_FN("storage", "StorageOfTypedObject", 1, 0),
     JS_FS_END
 };
 
@@ -196,39 +200,43 @@ GetPrototype(JSContext *cx, HandleObject
  *
  * Every type descriptor has an associated prototype. Instances of
  * that type descriptor use this as their prototype. Per the spec,
  * typed object prototypes cannot be mutated.
  */
 
 const Class js::TypedProto::class_ = {
     "TypedProto",
-    JSCLASS_HAS_RESERVED_SLOTS(JS_TYPROTO_SLOTS)
+    JSCLASS_HAS_RESERVED_SLOTS(JS_TYPROTO_SLOTS),
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub  /* setProperty */
 };
 
 /***************************************************************************
  * Scalar type objects
  *
  * Scalar type objects like `uint8`, `uint16`, are all instances of
  * the ScalarTypeDescr class. Like all type objects, they have a reserved
  * slot pointing to a TypeRepresentation object, which is used to
  * distinguish which scalar type object this actually is.
  */
 
 const Class js::ScalarTypeDescr::class_ = {
     "Scalar",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub, /* setProperty */
+    nullptr,               /* enumerate */
+    nullptr,               /* resolve */
+    nullptr,               /* convert */
+    nullptr,               /* finalize */
     ScalarTypeDescr::call
 };
 
 const JSFunctionSpec js::ScalarTypeDescr::typeObjectMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
     {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
     JS_FS_END
@@ -304,24 +312,24 @@ ScalarTypeDescr::call(JSContext *cx, uns
  * many instances, and each instance has a reserved slot with a
  * TypeRepresentation object, which is used to distinguish which
  * reference type object this actually is.
  */
 
 const Class js::ReferenceTypeDescr::class_ = {
     "Reference",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub, /* setProperty */
+    nullptr,               /* enumerate */
+    nullptr,               /* resolve */
+    nullptr,               /* convert */
+    nullptr,               /* finalize */
     ReferenceTypeDescr::call
 };
 
 const JSFunctionSpec js::ReferenceTypeDescr::typeObjectMethods[] = {
     JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
     {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
     JS_FS_END
@@ -483,27 +491,28 @@ CreatePrototypeObjectForComplexTypeInsta
 
     result->initTypeDescrSlot(*descr);
     return result;
 }
 
 const Class ArrayTypeDescr::class_ = {
     "ArrayType",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    TypedObject::construct
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    nullptr,               /* enumerate */
+    nullptr,               /* resolve */
+    nullptr,               /* convert */
+    nullptr,               /* finalize */
+    nullptr,
+    nullptr,
+    TypedObject::construct,
+    nullptr
 };
 
 const JSPropertySpec ArrayMetaTypeDescr::typeObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec ArrayMetaTypeDescr::typeObjectMethods[] = {
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
@@ -706,25 +715,26 @@ js::IsTypedObjectArray(JSObject &obj)
  * StructType class
  */
 
 const Class StructTypeDescr::class_ = {
     "StructType",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
     nullptr, /* addProperty */
     nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
     nullptr, /* enumerate */
     nullptr, /* resolve */
     nullptr, /* convert */
     nullptr, /* finalize */
     nullptr, /* call */
     nullptr, /* hasInstance */
-    TypedObject::construct
+    TypedObject::construct,
+    nullptr  /* trace */
 };
 
 const JSPropertySpec StructMetaTypeDescr::typeObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec StructMetaTypeDescr::typeObjectMethods[] = {
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
@@ -2374,18 +2384,18 @@ LazyArrayBufferTable::sizeOfIncludingThi
  */
 
 #define DEFINE_TYPEDOBJ_CLASS(Name, Trace)        \
     const Class Name::class_ = {                         \
         # Name,                                          \
         Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS, \
         nullptr,        /* addProperty */                \
         nullptr,        /* delProperty */                \
-        nullptr,        /* getProperty */                \
-        nullptr,        /* setProperty */                \
+        JS_PropertyStub,                                 \
+        JS_StrictPropertyStub,                           \
         nullptr,        /* enumerate   */                \
         nullptr,        /* resolve     */                \
         nullptr,        /* convert     */                \
         nullptr,        /* finalize    */                \
         nullptr,        /* call        */                \
         nullptr,        /* hasInstance */                \
         nullptr,        /* construct   */                \
         Trace,                                           \
--- a/js/src/builtin/WeakSetObject.cpp
+++ b/js/src/builtin/WeakSetObject.cpp
@@ -17,17 +17,21 @@
 
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 
 const Class WeakSetObject::class_ = {
     "WeakSet",
     JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_CACHED_PROTO(JSProto_WeakSet) |
-    JSCLASS_HAS_RESERVED_SLOTS(WeakSetObject::RESERVED_SLOTS)
+    JSCLASS_HAS_RESERVED_SLOTS(WeakSetObject::RESERVED_SLOTS),
+    nullptr,                 // addProperty
+    nullptr,                 // delProperty
+    JS_PropertyStub,         // getProperty
+    JS_StrictPropertyStub    // setProperty
 };
 
 const JSPropertySpec WeakSetObject::properties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec WeakSetObject::methods[] = {
     JS_SELF_HOSTED_FN("add",    "WeakSet_add",    1, 0),
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -508,86 +508,90 @@ namespace UInt64 {
 /*******************************************************************************
 ** JSClass definitions and initialization functions
 *******************************************************************************/
 
 // Class representing the 'ctypes' object itself. This exists to contain the
 // JSCTypesCallbacks set of function pointers.
 static const JSClass sCTypesGlobalClass = {
   "ctypes",
-  JSCLASS_HAS_RESERVED_SLOTS(CTYPESGLOBAL_SLOTS)
+  JSCLASS_HAS_RESERVED_SLOTS(CTYPESGLOBAL_SLOTS),
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 static const JSClass sCABIClass = {
   "CABI",
-  JSCLASS_HAS_RESERVED_SLOTS(CABI_SLOTS)
+  JSCLASS_HAS_RESERVED_SLOTS(CABI_SLOTS),
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 // Class representing ctypes.{C,Pointer,Array,Struct,Function}Type.prototype.
 // This exists to give said prototypes a class of "CType", and to provide
 // reserved slots for stashing various other prototype objects.
 static const JSClass sCTypeProtoClass = {
   "CType",
   JSCLASS_HAS_RESERVED_SLOTS(CTYPEPROTO_SLOTS),
-  nullptr, nullptr, nullptr, nullptr,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
   nullptr, nullptr, nullptr, nullptr,
   ConstructAbstract, nullptr, ConstructAbstract
 };
 
 // Class representing ctypes.CData.prototype and the 'prototype' properties
 // of CTypes. This exists to give said prototypes a class of "CData".
 static const JSClass sCDataProtoClass = {
   "CData",
-  0
+  0,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 static const JSClass sCTypeClass = {
   "CType",
   JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(CTYPE_SLOTS),
-  nullptr, nullptr, nullptr, nullptr,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
   nullptr, nullptr, nullptr, CType::Finalize,
   CType::ConstructData, CType::HasInstance, CType::ConstructData,
   CType::Trace
 };
 
 static const JSClass sCDataClass = {
   "CData",
   JSCLASS_HAS_RESERVED_SLOTS(CDATA_SLOTS),
   nullptr, nullptr, ArrayType::Getter, ArrayType::Setter,
   nullptr, nullptr, nullptr, CData::Finalize,
   FunctionType::Call, nullptr, FunctionType::Call
 };
 
 static const JSClass sCClosureClass = {
   "CClosure",
   JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(CCLOSURE_SLOTS),
-  nullptr, nullptr, nullptr, nullptr,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
   nullptr, nullptr, nullptr, CClosure::Finalize,
   nullptr, nullptr, nullptr, CClosure::Trace
 };
 
 /*
  * Class representing the prototype of CDataFinalizer.
  */
 static const JSClass sCDataFinalizerProtoClass = {
   "CDataFinalizer",
-  0
+  0,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 /*
  * Class representing instances of CDataFinalizer.
  *
  * Instances of CDataFinalizer have both private data (with type
  * |CDataFinalizer::Private|) and slots (see |CDataFinalizerSlots|).
  */
 static const JSClass sCDataFinalizerClass = {
   "CDataFinalizer",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(CDATAFINALIZER_SLOTS),
-  nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, CDataFinalizer::Finalize
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
+  nullptr, nullptr, nullptr, CDataFinalizer::Finalize,
 };
 
 
 #define CTYPESFN_FLAGS \
   (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
 
 #define CTYPESCTOR_FLAGS \
   (CTYPESFN_FLAGS | JSFUN_CONSTRUCTOR)
@@ -751,35 +755,37 @@ static const JSPropertySpec sFunctionPro
 static const JSFunctionSpec sFunctionInstanceFunctions[] = {
   JS_FN("call", js_fun_call, 1, CDATAFN_FLAGS),
   JS_FN("apply", js_fun_apply, 2, CDATAFN_FLAGS),
   JS_FS_END
 };
 
 static const JSClass sInt64ProtoClass = {
   "Int64",
-  0
+  0,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 static const JSClass sUInt64ProtoClass = {
   "UInt64",
-  0
+  0,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 static const JSClass sInt64Class = {
   "Int64",
   JSCLASS_HAS_RESERVED_SLOTS(INT64_SLOTS),
-  nullptr, nullptr, nullptr, nullptr,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
   nullptr, nullptr, nullptr, Int64Base::Finalize
 };
 
 static const JSClass sUInt64Class = {
   "UInt64",
   JSCLASS_HAS_RESERVED_SLOTS(INT64_SLOTS),
-  nullptr, nullptr, nullptr, nullptr,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
   nullptr, nullptr, nullptr, Int64Base::Finalize
 };
 
 static const JSFunctionSpec sInt64StaticFunctions[] = {
   JS_FN("compare", Int64::Compare, 2, CTYPESFN_FLAGS),
   JS_FN("lo", Int64::Lo, 1, CTYPESFN_FLAGS),
   JS_FN("hi", Int64::Hi, 1, CTYPESFN_FLAGS),
   JS_FN("join", Int64::Join, 2, CTYPESFN_FLAGS),
--- a/js/src/ctypes/Library.cpp
+++ b/js/src/ctypes/Library.cpp
@@ -29,17 +29,17 @@ namespace Library
 ** JSObject implementation
 *******************************************************************************/
 
 typedef Rooted<JSFlatString*>    RootedFlatString;
 
 static const JSClass sLibraryClass = {
   "Library",
   JSCLASS_HAS_RESERVED_SLOTS(LIBRARY_SLOTS),
-  nullptr, nullptr, nullptr, nullptr,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
   nullptr, nullptr, nullptr, Library::Finalize
 };
 
 #define CTYPESFN_FLAGS \
   (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
 
 static const JSFunctionSpec sLibraryFunctions[] = {
   JS_FN("close",   Library::Close,   0, CTYPESFN_FLAGS),
--- a/js/src/gdb/gdb-tests.cpp
+++ b/js/src/gdb/gdb-tests.cpp
@@ -10,17 +10,17 @@
 #include "jsapi.h"
 #include "jsfriendapi.h"
 
 using namespace JS;
 
 /* The class of the global object. */
 const JSClass global_class = {
     "global", JSCLASS_GLOBAL_FLAGS,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, nullptr,
     nullptr, nullptr, nullptr,
     JS_GlobalObjectTraceHook
 };
 
 template<typename T>
 static inline T *
 checkPtr(T *ptr)
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -537,17 +537,17 @@ IsCacheableNoProperty(JSObject *obj, JSO
 {
     if (shape)
         return false;
 
     MOZ_ASSERT(!holder);
 
     // Just because we didn't find the property on the object doesn't mean it
     // won't magically appear through various engine hacks:
-    if (obj->getClass()->getProperty)
+    if (obj->getClass()->getProperty && obj->getClass()->getProperty != JS_PropertyStub)
         return false;
 
     // Don't generate missing property ICs if we skipped a non-native object, as
     // lookups may extend beyond the prototype chain (e.g.  for DOMProxy
     // proxies).
     JSObject *obj2 = obj;
     while (obj2) {
         if (!obj2->isNative())
--- a/js/src/jsapi-tests/testAddPropertyPropcache.cpp
+++ b/js/src/jsapi-tests/testAddPropertyPropcache.cpp
@@ -14,17 +14,20 @@ AddProperty(JSContext *cx, JS::HandleObj
 {
     callCount++;
     return true;
 }
 
 static const JSClass AddPropertyClass = {
     "AddPropertyTester",
     0,
-    AddProperty
+    AddProperty,
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 BEGIN_TEST(testAddPropertyHook)
 {
     /*
      * Do the test a bunch of times, because sometimes we seem to randomly
      * miss the propcache.
      */
--- a/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
+++ b/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
@@ -3,17 +3,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsapi-tests/tests.h"
 
 using namespace JS;
 
 static const JSClass CustomClass = {
   "CustomClass",
-  JSCLASS_HAS_RESERVED_SLOTS(1)
+  JSCLASS_HAS_RESERVED_SLOTS(1),
+  nullptr,
+  nullptr,
+  JS_PropertyStub,
+  JS_StrictPropertyStub
 };
 
 static const uint32_t CUSTOM_SLOT = 0;
 
 static bool
 IsCustomClass(JS::Handle<JS::Value> v)
 {
   return v.isObject() && JS_GetClass(&v.toObject()) == &CustomClass;
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -8,18 +8,18 @@
 
 static TestJSPrincipals system_principals(1);
 
 static const JSClass global_class = {
     "global",
     JSCLASS_IS_GLOBAL | JSCLASS_GLOBAL_FLAGS,
     nullptr,
     nullptr,
-    nullptr,
-    nullptr,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     JS_GlobalObjectTraceHook
--- a/js/src/jsapi-tests/testClassGetter.cpp
+++ b/js/src/jsapi-tests/testClassGetter.cpp
@@ -19,20 +19,21 @@ static bool test_prop_get( JSContext *cx
 }
 
 static bool
 PTest(JSContext* cx, unsigned argc, jsval *vp);
 
 static const JSClass ptestClass = {
     "PTest",
     JSCLASS_HAS_PRIVATE,
-    nullptr, // addProperty
-    nullptr, // delProperty
-    test_prop_get,
-    nullptr // setProperty
+
+    nullptr,               // add
+    nullptr,               // delete
+    test_prop_get,         // get
+    JS_StrictPropertyStub  // set
 };
 
 static bool
 PTest(JSContext* cx, unsigned argc, jsval *vp)
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     JSObject *obj = JS_NewObjectForConstructor(cx, &ptestClass, args);
     if (!obj)
--- a/js/src/jsapi-tests/testFreshGlobalEvalRedefinition.cpp
+++ b/js/src/jsapi-tests/testFreshGlobalEvalRedefinition.cpp
@@ -18,17 +18,17 @@ GlobalResolve(JSContext *cx, JS::HandleO
 {
     return JS_ResolveStandardClass(cx, obj, id, resolvedp);
 }
 
 BEGIN_TEST(testRedefineGlobalEval)
 {
     static const JSClass cls = {
         "global", JSCLASS_GLOBAL_FLAGS,
-        nullptr, nullptr, nullptr, nullptr,
+        nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
         GlobalEnumerate, GlobalResolve, nullptr,
         nullptr, nullptr, nullptr, nullptr,
         JS_GlobalObjectTraceHook
     };
 
     /* Create the global object. */
     JS::CompartmentOptions options;
     options.setVersion(JSVERSION_LATEST);
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -34,17 +34,21 @@ BEGIN_TEST(testLookup_bug522590)
     CHECK(!js::IsInternalFunctionObject(funobj));
 
     return true;
 }
 END_TEST(testLookup_bug522590)
 
 static const JSClass DocumentAllClass = {
     "DocumentAll",
-    JSCLASS_EMULATES_UNDEFINED
+    JSCLASS_EMULATES_UNDEFINED,
+    nullptr,
+    nullptr,
+    JS_PropertyStub,
+    JS_StrictPropertyStub
 };
 
 bool
 document_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *resolvedp)
 {
     // If id is "all", resolve document.all=true.
     JS::RootedValue v(cx);
     if (!JS_IdToValue(cx, id, &v))
@@ -71,17 +75,17 @@ document_resolve(JSContext *cx, JS::Hand
     }
 
     *resolvedp = false;
     return true;
 }
 
 static const JSClass document_class = {
     "document", 0,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, document_resolve, nullptr
 };
 
 BEGIN_TEST(testLookup_bug570195)
 {
     JS::RootedObject obj(cx, JS_NewObject(cx, &document_class, JS::NullPtr(), JS::NullPtr()));
     CHECK(obj);
     CHECK(JS_DefineProperty(cx, global, "document", obj, 0));
--- a/js/src/jsapi-tests/testNewObject.cpp
+++ b/js/src/jsapi-tests/testNewObject.cpp
@@ -91,17 +91,17 @@ BEGIN_TEST(testNewObject_1)
     CHECK_EQUAL(len, N);
     CHECK(JS_GetElement(cx, obj, N - 1, &v));
     CHECK_SAME(v, INT_TO_JSVAL(N - 1));
 
     // With JSClass.construct.
     static const JSClass cls = {
         "testNewObject_1",
         0,
-        nullptr, nullptr, nullptr, nullptr,
+        nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
         nullptr, nullptr, nullptr, nullptr,
         nullptr, nullptr, constructHook
     };
     JS::RootedObject ctor(cx, JS_NewObject(cx, &cls, JS::NullPtr(), JS::NullPtr()));
     CHECK(ctor);
     JS::RootedValue rt2(cx, OBJECT_TO_JSVAL(ctor));
     obj = JS_New(cx, ctor, JS::HandleValueArray::subarray(argv, 0, 3));
     CHECK(obj);
--- a/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp
+++ b/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp
@@ -1,17 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsapi-tests/tests.h"
 
 static const JSClass ObjectEmulatingUndefinedClass = {
     "ObjectEmulatingUndefined",
-    JSCLASS_EMULATES_UNDEFINED
+    JSCLASS_EMULATES_UNDEFINED,
+    nullptr,
+    nullptr,
+    JS_PropertyStub,
+    JS_StrictPropertyStub
 };
 
 static bool
 ObjectEmulatingUndefinedConstructor(JSContext *cx, unsigned argc, jsval *vp)
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     JSObject *obj = JS_NewObjectForConstructor(cx, &ObjectEmulatingUndefinedClass, args);
     if (!obj)
--- a/js/src/jsapi-tests/testOps.cpp
+++ b/js/src/jsapi-tests/testOps.cpp
@@ -17,17 +17,17 @@ my_convert(JSContext* context, JS::Handl
         return true;
     }
     return false;
 }
 
 static const JSClass myClass = {
     "MyClass",
     0,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, my_convert
 };
 
 static bool
 createMyObject(JSContext* context, unsigned argc, jsval *vp)
 {
     JS_BeginRequest(context);
 
--- a/js/src/jsapi-tests/testPersistentRooted.cpp
+++ b/js/src/jsapi-tests/testPersistentRooted.cpp
@@ -16,29 +16,29 @@ struct BarkWhenTracedClass {
     static void trace(JSTracer *trc, JSObject *obj) { traceCount++; }
     static void reset() { finalizeCount = 0; traceCount = 0; }
 };
 
 int BarkWhenTracedClass::finalizeCount;
 int BarkWhenTracedClass::traceCount;
 
 const JSClass BarkWhenTracedClass::class_ = {
-    "BarkWhenTracedClass", 0,
-    nullptr,
-    nullptr,
-    nullptr,
-    nullptr,
-    nullptr,
-    nullptr,
-    nullptr,
-    finalize,
-    nullptr,
-    nullptr,
-    nullptr,
-    trace
+  "BarkWhenTracedClass", 0,
+  nullptr,
+  nullptr,
+  JS_PropertyStub,
+  JS_StrictPropertyStub,
+  nullptr,
+  nullptr,
+  nullptr,
+  finalize,
+  nullptr,
+  nullptr,
+  nullptr,
+  trace
 };
 
 struct Kennel {
     PersistentRootedObject obj;
     explicit Kennel(JSContext *cx) : obj(cx) { }
     Kennel(JSContext *cx, const HandleObject &woof) : obj(cx, woof) { }
 };
 
--- a/js/src/jsapi-tests/testProfileStrings.cpp
+++ b/js/src/jsapi-tests/testProfileStrings.cpp
@@ -21,17 +21,17 @@ reset(JSContext *cx)
     psize = max_stack = 0;
     memset(pstack, 0, sizeof(pstack));
     cx->runtime()->spsProfiler.stringsReset();
     cx->runtime()->spsProfiler.enableSlowAssertions(true);
     js::EnableRuntimeProfilingStack(cx->runtime(), true);
 }
 
 static const JSClass ptestClass = {
-    "Prof", 0
+    "Prof", 0, nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 static bool
 test_fn(JSContext *cx, unsigned argc, jsval *vp)
 {
     max_stack = psize;
     return true;
 }
--- a/js/src/jsapi-tests/testPropCache.cpp
+++ b/js/src/jsapi-tests/testPropCache.cpp
@@ -14,17 +14,17 @@ CounterAdd(JSContext *cx, JS::HandleObje
 {
     g_counter++;
     return true;
 }
 
 static const JSClass CounterClass = {
     "Counter",  /* name */
     0,  /* flags */
-    CounterAdd
+    CounterAdd, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 BEGIN_TEST(testPropCache_bug505798)
 {
     g_counter = 0;
     EXEC("var x = {};");
     CHECK(JS_DefineObject(cx, global, "y", &CounterClass, JS::NullPtr(), JSPROP_ENUMERATE));
     EXEC("var arr = [x, y];\n"
--- a/js/src/jsapi-tests/testResolveRecursion.cpp
+++ b/js/src/jsapi-tests/testResolveRecursion.cpp
@@ -12,21 +12,21 @@
  * prevented.
  */
 
 BEGIN_TEST(testResolveRecursion)
 {
     static const JSClass my_resolve_class = {
         "MyResolve",
         JSCLASS_HAS_PRIVATE,
-        nullptr, // add
-        nullptr, // delete
-        nullptr, // get
-        nullptr, // set
-        nullptr, // enumerate
+        nullptr,               // add
+        nullptr,               // delete
+        JS_PropertyStub,       // get
+        JS_StrictPropertyStub, // set
+        nullptr,
         my_resolve
     };
 
     obj1 = obj2 = nullptr;
     JS::AddObjectRoot(cx, &obj1);
     JS::AddObjectRoot(cx, &obj2);
 
     obj1 = JS_NewObject(cx, &my_resolve_class, JS::NullPtr(), JS::NullPtr());
--- a/js/src/jsapi-tests/testWeakMap.cpp
+++ b/js/src/jsapi-tests/testWeakMap.cpp
@@ -133,28 +133,28 @@ static JSObject *GetKeyDelegate(JSObject
     return static_cast<JSObject*>(JS_GetPrivate(obj));
 }
 
 JSObject *newKey()
 {
     static const js::Class keyClass = {
         "keyWithDelgate",
         JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
-        nullptr, /* addProperty */
-        nullptr, /* delProperty */
-        nullptr, /* getProperty */
-        nullptr, /* setProperty */
-        nullptr, /* enumerate */
-        nullptr, /* resolve */
-        nullptr, /* convert */
-        nullptr, /* finalize */
-        nullptr, /* call */
-        nullptr, /* hasInstance */
-        nullptr, /* construct */
-        nullptr, /* trace */
+        nullptr,                 /* addProperty */
+        nullptr,                 /* delProperty */
+        JS_PropertyStub,         /* getProperty */
+        JS_StrictPropertyStub,   /* setProperty */
+        nullptr,                 /* enumerate */
+        nullptr,                 /* resolve */
+        nullptr,                 /* convert */
+        nullptr,                 /* finalize */
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
         JS_NULL_CLASS_SPEC,
         {
             nullptr,
             nullptr,
             false,
             GetKeyDelegate
         },
         JS_NULL_OBJECT_OPS
@@ -195,27 +195,27 @@ JSObject *newCCW(JS::HandleObject source
     return object;
 }
 
 JSObject *newDelegate()
 {
     static const JSClass delegateClass = {
         "delegate",
         JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_RESERVED_SLOTS(1),
-        nullptr, /* addProperty */
-        nullptr, /* delProperty */
-        nullptr, /* getProperty */
-        nullptr, /* setProperty */
-        nullptr, /* enumerate */
-        nullptr, /* resolve */
-        nullptr, /* convert */
-        nullptr, /* finalize */
-        nullptr, /* call */
-        nullptr, /* hasInstance */
-        nullptr, /* construct */
+        nullptr,                 /* addProperty */
+        nullptr,                 /* delProperty */
+        JS_PropertyStub,
+        JS_StrictPropertyStub,
+        nullptr,                 /* enumerate */
+        nullptr,                 /* resolve */
+        nullptr,                 /* convert */
+        nullptr,                 /* finalize */
+        nullptr,
+        nullptr,
+        nullptr,
         JS_GlobalObjectTraceHook
     };
 
     /* Create the global object. */
     JS::CompartmentOptions options;
     options.setVersion(JSVERSION_LATEST);
     JS::RootedObject global(cx);
     global = JS_NewGlobalObject(cx, &delegateClass, nullptr, JS::FireOnNewGlobalHook, options);
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -223,17 +223,17 @@ class JSAPITest
         return false;
     }
 
     JSAPITestString messages() const { return msgs; }
 
     static const JSClass * basicGlobalClass() {
         static const JSClass c = {
             "global", JSCLASS_GLOBAL_FLAGS,
-            nullptr, nullptr, nullptr, nullptr,
+            nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
             nullptr, nullptr, nullptr, nullptr,
             nullptr, nullptr, nullptr,
             JS_GlobalObjectTraceHook
         };
         return &c;
     }
 
   protected:
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3087,24 +3087,18 @@ class MutablePropertyDescriptorOperation
     JSStrictPropertyOp &setter() { return desc()->setter; }
     JS::MutableHandleValue value() {
         return JS::MutableHandleValue::fromMarkedLocation(&desc()->value);
     }
 
     void setEnumerable() { desc()->attrs |= JSPROP_ENUMERATE; }
     void setAttributes(unsigned attrs) { desc()->attrs = attrs; }
 
-    void setGetter(JSPropertyOp op) {
-        MOZ_ASSERT(op != JS_PropertyStub);
-        desc()->getter = op;
-    }
-    void setSetter(JSStrictPropertyOp op) {
-        MOZ_ASSERT(op != JS_StrictPropertyStub);
-        desc()->setter = op;
-    }
+    void setGetter(JSPropertyOp op) { desc()->getter = op; }
+    void setSetter(JSStrictPropertyOp op) { desc()->setter = op; }
     void setGetterObject(JSObject *obj) { desc()->getter = reinterpret_cast<JSPropertyOp>(obj); }
     void setSetterObject(JSObject *obj) { desc()->setter = reinterpret_cast<JSStrictPropertyOp>(obj); }
 
     JS::MutableHandleObject getterObject() {
         MOZ_ASSERT(this->hasGetterObject());
         return JS::MutableHandleObject::fromMarkedLocation(
                 reinterpret_cast<JSObject **>(&desc()->getter));
     }
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -462,18 +462,25 @@ array_length_getter(JSContext *cx, Handl
 static bool
 array_length_setter(JSContext *cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
 {
     if (!obj->is<ArrayObject>()) {
         // This array .length property was found on the prototype
         // chain. Ideally the setter should not have been called, but since
         // we're here, do an impression of SetPropertyByDefining.
         const Class *clasp = obj->getClass();
+        JSPropertyOp getter = clasp->getProperty;
+        if (getter == JS_PropertyStub)
+            getter = nullptr;
+        JSStrictPropertyOp setter = clasp->setProperty;
+        if (setter == JS_StrictPropertyStub)
+            setter = nullptr;
+
         return JSObject::defineProperty(cx, obj, cx->names().length, vp,
-                                        clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE);
+                                        getter, setter, JSPROP_ENUMERATE);
     }
 
     Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
     MOZ_ASSERT(arr->lengthIsWritable(),
                "setter shouldn't be called if property is non-writable");
     return ArraySetLength<SequentialExecution>(cx, arr, id, JSPROP_PERMANENT, vp, strict);
 }
 
@@ -3359,27 +3366,27 @@ CreateArrayPrototype(JSContext *cx, JSPr
 
     return arrayProto;
 }
 
 const Class ArrayObject::class_ = {
     "Array",
     JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
     array_addProperty,
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
-    nullptr, /* trace */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
+    nullptr,                 /* finalize */
+    nullptr,                 /* call */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct */
+    nullptr,                 /* trace */
     {
         GenericCreateConstructor<js_Array, 1, JSFunction::FinalizeKind>,
         CreateArrayPrototype,
         array_static_methods,
         array_methods
     }
 };
 
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -22,17 +22,21 @@
 
 #include "vm/BooleanObject-inl.h"
 
 using namespace js;
 using namespace js::types;
 
 const Class BooleanObject::class_ = {
     "Boolean",
-    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean)
+    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 MOZ_ALWAYS_INLINE bool
 IsBoolean(HandleValue v)
 {
     return v.isBoolean() || (v.isObject() && v.toObject().is<BooleanObject>());
 }
 
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -335,19 +335,16 @@ CallSetter(JSContext *cx, HandleObject o
     if (attrs & JSPROP_SETTER) {
         RootedValue opv(cx, CastAsObjectJsval(op));
         return InvokeGetterOrSetter(cx, obj, opv, 1, vp.address(), vp);
     }
 
     if (attrs & JSPROP_GETTER)
         return js_ReportGetterOnlyAssignment(cx, strict);
 
-    if (!op)
-        return true;
-
     return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp);
 }
 
 inline uintptr_t
 GetNativeStackLimit(ThreadSafeContext *cx)
 {
     StackKind kind;
     if (cx->isJSContext()) {
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -3015,28 +3015,28 @@ FinishDateClassInit(JSContext *cx, Handl
            baseops::DefineGeneric(cx, proto.as<NativeObject>(), toGMTStringId, toUTCStringFun,
                                   nullptr, nullptr, 0);
 }
 
 const Class DateObject::class_ = {
     js_Date_str,
     JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
     date_convert,
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
-    nullptr, /* trace */
+    nullptr,                 /* finalize */
+    nullptr,                 /* call */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct */
+    nullptr,                 /* trace */
     {
         GenericCreateConstructor<js_Date, MAXARGS, JSFunction::FinalizeKind>,
         GenericCreatePrototype,
         date_static_methods,
         date_methods,
         nullptr,
         FinishDateClassInit
     }
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -61,18 +61,18 @@ static const JSFunctionSpec exception_me
 #define IMPLEMENT_ERROR_SUBCLASS(name) \
     { \
         js_Error_str, /* yes, really */ \
         JSCLASS_IMPLEMENTS_BARRIERS | \
         JSCLASS_HAS_CACHED_PROTO(JSProto_##name) | \
         JSCLASS_HAS_RESERVED_SLOTS(ErrorObject::RESERVED_SLOTS), \
         nullptr,                 /* addProperty */ \
         nullptr,                 /* delProperty */ \
-        nullptr,                 /* getProperty */ \
-        nullptr,                 /* setProperty */ \
+        JS_PropertyStub,         /* getProperty */ \
+        JS_StrictPropertyStub,   /* setProperty */ \
         nullptr,                 /* enumerate */ \
         nullptr,                 /* resolve */ \
         nullptr,                 /* convert */ \
         exn_finalize, \
         nullptr,                 /* call        */ \
         nullptr,                 /* hasInstance */ \
         nullptr,                 /* construct   */ \
         nullptr,                 /* trace       */ \
@@ -91,18 +91,18 @@ const Class
 ErrorObject::classes[JSEXN_LIMIT] = {
     {
         js_Error_str,
         JSCLASS_IMPLEMENTS_BARRIERS |
         JSCLASS_HAS_CACHED_PROTO(JSProto_Error) |
         JSCLASS_HAS_RESERVED_SLOTS(ErrorObject::RESERVED_SLOTS),
         nullptr,                 /* addProperty */
         nullptr,                 /* delProperty */
-        nullptr,                 /* getProperty */
-        nullptr,                 /* setProperty */
+        JS_PropertyStub,         /* getProperty */
+        JS_StrictPropertyStub,   /* setProperty */
         nullptr,                 /* enumerate */
         nullptr,                 /* resolve */
         nullptr,                 /* convert */
         exn_finalize,
         nullptr,                 /* call        */
         nullptr,                 /* hasInstance */
         nullptr,                 /* construct   */
         nullptr,                 /* trace       */
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -274,25 +274,25 @@ namespace js {
     {                                                                                   \
         name,                                                                           \
         js::Class::NON_NATIVE |                                                         \
             JSCLASS_IS_PROXY |                                                          \
             JSCLASS_IMPLEMENTS_BARRIERS |                                               \
             flags,                                                                      \
         nullptr,                 /* addProperty */                                      \
         nullptr,                 /* delProperty */                                      \
-        nullptr,                 /* getProperty */                                      \
-        nullptr,                 /* setProperty */                                      \
+        JS_PropertyStub,         /* getProperty */                                      \
+        JS_StrictPropertyStub,   /* setProperty */                                      \
         nullptr,                 /* enumerate */                                        \
         nullptr,                 /* resolve */                                          \
         js::proxy_Convert,                                                              \
         js::proxy_Finalize,      /* finalize    */                                      \
-        nullptr,                 /* call        */                                      \
+        nullptr,                  /* call        */                                     \
         js::proxy_HasInstance,   /* hasInstance */                                      \
-        nullptr,                 /* construct   */                                      \
+        nullptr,             /* construct   */                                          \
         js::proxy_Trace,         /* trace       */                                      \
         JS_NULL_CLASS_SPEC,                                                             \
         ext,                                                                            \
         {                                                                               \
             js::proxy_LookupGeneric,                                                    \
             js::proxy_LookupProperty,                                                   \
             js::proxy_LookupElement,                                                    \
             js::proxy_DefineGeneric,                                                    \
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -890,18 +890,18 @@ CreateFunctionPrototype(JSContext *cx, J
 }
 
 const Class JSFunction::class_ = {
     js_Function_str,
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
     nullptr,                 /* addProperty */
     nullptr,                 /* delProperty */
-    nullptr,                 /* getProperty */
-    nullptr,                 /* setProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
     fun_enumerate,
     js::fun_resolve,
     nullptr,                 /* convert     */
     nullptr,                 /* finalize    */
     nullptr,                 /* call        */
     fun_hasInstance,
     nullptr,                 /* construct   */
     fun_trace,
@@ -2119,18 +2119,20 @@ js::DefineFunction(JSContext *cx, Handle
          * for more on this.
          */
         flags &= ~JSFUN_STUB_GSOPS;
         gop = nullptr;
         sop = nullptr;
     } else {
         gop = obj->getClass()->getProperty;
         sop = obj->getClass()->setProperty;
-        MOZ_ASSERT(gop != JS_PropertyStub);
-        MOZ_ASSERT(sop != JS_StrictPropertyStub);
+        if (gop == JS_PropertyStub)
+            gop = nullptr;
+        if (sop == JS_StrictPropertyStub)
+            sop = nullptr;
     }
 
     JSFunction::Flags funFlags;
     if (!native)
         funFlags = JSFunction::INTERPRETED_LAZY;
     else
         funFlags = JSAPIToJSFunctionFlags(flags);
 
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -918,64 +918,76 @@ PropertyIteratorObject::finalize(FreeOp 
 }
 
 const Class PropertyIteratorObject::class_ = {
     "Iterator",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator) |
     JSCLASS_HAS_PRIVATE |
     JSCLASS_BACKGROUND_FINALIZE,
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     finalize,
-    nullptr, /* call        */
-    nullptr, /* hasInstance */
-    nullptr, /* construct   */
-    trace
+    nullptr,                 /* call        */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct   */
+    trace,
 };
 
 enum {
     ArrayIteratorSlotIteratedObject,
     ArrayIteratorSlotNextIndex,
     ArrayIteratorSlotItemKind,
     ArrayIteratorSlotCount
 };
 
 const Class ArrayIteratorObject::class_ = {
     "Array Iterator",
     JSCLASS_IMPLEMENTS_BARRIERS |
-    JSCLASS_HAS_RESERVED_SLOTS(ArrayIteratorSlotCount)
+    JSCLASS_HAS_RESERVED_SLOTS(ArrayIteratorSlotCount),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 static const JSFunctionSpec array_iterator_methods[] = {
     JS_SELF_HOSTED_SYM_FN(iterator, "ArrayIteratorIdentity", 0, 0),
     JS_SELF_HOSTED_FN("next", "ArrayIteratorNext", 0, 0),
     JS_FS_END
 };
 
 static const Class StringIteratorPrototypeClass = {
     "String Iterator",
-    JSCLASS_IMPLEMENTS_BARRIERS
+    JSCLASS_IMPLEMENTS_BARRIERS,
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 enum {
     StringIteratorSlotIteratedObject,
     StringIteratorSlotNextIndex,
     StringIteratorSlotCount
 };
 
 const Class StringIteratorObject::class_ = {
     "String Iterator",
     JSCLASS_IMPLEMENTS_BARRIERS |
-    JSCLASS_HAS_RESERVED_SLOTS(StringIteratorSlotCount)
+    JSCLASS_HAS_RESERVED_SLOTS(StringIteratorSlotCount),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 static const JSFunctionSpec string_iterator_methods[] = {
     JS_SELF_HOSTED_SYM_FN(iterator, "StringIteratorIdentity", 0, 0),
     JS_SELF_HOSTED_FN("next", "StringIteratorNext", 0, 0),
     JS_FS_END
 };
 
@@ -1292,26 +1304,27 @@ stopiter_hasInstance(JSContext *cx, Hand
 {
     *bp = JS_IsStopIteration(v);
     return true;
 }
 
 const Class StopIterationObject::class_ = {
     "StopIteration",
     JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    stopiter_hasInstance
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
+    nullptr,                 /* finalize    */
+    nullptr,                 /* call        */
+    stopiter_hasInstance,
+    nullptr                  /* construct   */
 };
 
 /* static */ bool
 GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
 {
     RootedObject iteratorProto(cx);
     Value iteratorProtoVal = global->getPrototype(JSProto_Iterator);
     if (iteratorProtoVal.isObject()) {
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -73,17 +73,21 @@ MathCache::MathCache() {
 size_t
 MathCache::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
 {
     return mallocSizeOf(this);
 }
 
 const Class js::MathClass = {
     js_Math_str,
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Math)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Math),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 bool
 js::math_abs_handle(JSContext *cx, js::HandleValue v, js::MutableHandleValue r)
 {
     double x;
     if (!ToNumber(cx, v, &x))
         return false;
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -458,17 +458,21 @@ static const JSFunctionSpec number_funct
     JS_SELF_HOSTED_FN(js_isFinite_str, "Global_isFinite", 1,0),
     JS_FN(js_parseFloat_str,    num_parseFloat,      1,0),
     JS_FN(js_parseInt_str,      num_parseInt,        2,0),
     JS_FS_END
 };
 
 const Class NumberObject::class_ = {
     js_Number_str,
-    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number)
+    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 static bool
 Number(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Sample JS_CALLEE before clobbering. */
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -171,28 +171,28 @@ FinishObjectClassInit(JSContext *cx, JS:
         return false;
     return true;
 }
 
 
 const Class JSObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
-    nullptr, /* trace */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
+    nullptr,                 /* finalize */
+    nullptr,                 /* call */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct */
+    nullptr,                 /* trace */
     {
         CreateObjectConstructor,
         CreateObjectPrototype,
         object_static_methods,
         object_methods,
         object_properties,
         FinishObjectClassInit
     }
@@ -2722,19 +2722,19 @@ js_InitClass(JSContext *cx, HandleObject
              const Class *clasp, Native constructor, unsigned nargs,
              const JSPropertySpec *ps, const JSFunctionSpec *fs,
              const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs,
              NativeObject **ctorp, AllocKind ctorKind)
 {
     RootedObject protoProto(cx, protoProto_);
 
     /* Check function pointer members. */
-    MOZ_ASSERT(clasp->addProperty != JS_PropertyStub);
-    MOZ_ASSERT(clasp->getProperty != JS_PropertyStub);
-    MOZ_ASSERT(clasp->setProperty != JS_StrictPropertyStub);
+    MOZ_ASSERT(clasp->addProperty != JS_PropertyStub);  // (use null instead)
+    MOZ_ASSERT(clasp->getProperty);
+    MOZ_ASSERT(clasp->setProperty);
 
     RootedAtom atom(cx, Atomize(cx, clasp->name, strlen(clasp->name)));
     if (!atom)
         return nullptr;
 
     /*
      * All instances of the class will inherit properties from the prototype
      * object we are about to create (in DefineConstructorAndPrototype), which
@@ -3349,18 +3349,18 @@ js::GetPropertyPure(ThreadSafeContext *c
 {
     /* Deal with native objects. */
     NativeObject *obj2;
     Shape *shape;
     if (!LookupPropertyPureInline(cx, obj, id, &obj2, &shape))
         return false;
 
     if (!shape) {
-        /* Fail if we have a class getter op. */
-        if (obj->getClass()->getProperty)
+        /* Fail if we have a non-stub class op hooks. */
+        if (obj->getClass()->getProperty && obj->getClass()->getProperty != JS_PropertyStub)
             return false;
 
         if (obj->getOps()->getElement)
             return false;
 
         /* Vanilla native object, return undefined. */
         vp->setUndefined();
         return true;
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -32,17 +32,21 @@ using namespace js::gc;
 using namespace js::types;
 
 using mozilla::IsFinite;
 using mozilla::Maybe;
 using mozilla::RangedPtr;
 
 const Class js::JSONClass = {
     js_JSON_str,
-    JSCLASS_HAS_CACHED_PROTO(JSProto_JSON)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_JSON),
+    nullptr,                /* addProperty */
+    nullptr,                /* delProperty */
+    JS_PropertyStub,        /* getProperty */
+    JS_StrictPropertyStub   /* setProperty */
 };
 
 static inline bool
 IsQuoteSpecialCharacter(char16_t c)
 {
     static_assert('\b' < ' ', "'\\b' must be treated as special below");
     static_assert('\f' < ' ', "'\\f' must be treated as special below");
     static_assert('\n' < ' ', "'\\n' must be treated as special below");
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1343,27 +1343,27 @@ ScriptSourceObject::finalize(FreeOp *fop
     sso->source()->decref();
     sso->setReservedSlot(SOURCE_SLOT, PrivateValue(nullptr));
 }
 
 const Class ScriptSourceObject::class_ = {
     "ScriptSource",
     JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
     JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_IS_ANONYMOUS,
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                /* addProperty */
+    nullptr,                /* delProperty */
+    JS_PropertyStub,        /* getProperty */
+    JS_StrictPropertyStub,  /* setProperty */
+    nullptr,                /* enumerate */
+    nullptr,                /* resolve */
+    nullptr,                /* convert */
     finalize,
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
+    nullptr,                /* call        */
+    nullptr,                /* hasInstance */
+    nullptr,                /* construct   */
     trace
 };
 
 ScriptSourceObject *
 ScriptSourceObject::create(ExclusiveContext *cx, ScriptSource *source)
 {
     RootedObject object(cx, NewObjectWithGivenProto(cx, &class_, nullptr, cx->global()));
     if (!object)
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -417,20 +417,20 @@ js::str_resolve(JSContext *cx, HandleObj
     }
     return true;
 }
 
 const Class StringObject::class_ = {
     js_String_str,
     JSCLASS_HAS_RESERVED_SLOTS(StringObject::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_String),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
     str_enumerate,
     str_resolve
 };
 
 /*
  * Returns a JSString * for the |this| value associated with 'call', or throws
  * a TypeError if |this| is null or undefined.  This algorithm is the same as
  * calling CheckObjectCoercible(this), then returning ToString(this), as all
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -580,27 +580,27 @@ WeakMap_construct(JSContext *cx, unsigne
     args.rval().setObject(*obj);
     return true;
 }
 
 const Class WeakMapObject::class_ = {
     "WeakMap",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_CACHED_PROTO(JSProto_WeakMap),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     WeakMap_finalize,
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
+    nullptr,                 /* call        */
+    nullptr,                 /* construct   */
+    nullptr,                 /* xdrObject   */
     WeakMap_mark
 };
 
 static const JSFunctionSpec weak_map_methods[] = {
     JS_FN("has",    WeakMap_has, 1, 0),
     JS_FN("get",    WeakMap_get, 2, 0),
     JS_FN("delete", WeakMap_delete, 1, 0),
     JS_FN("set",    WeakMap_set, 2, 0),
--- a/js/src/perf/jsperf.cpp
+++ b/js/src/perf/jsperf.cpp
@@ -156,17 +156,17 @@ static const struct pm_const {
 
 #undef CONSTANT
 
 static bool pm_construct(JSContext* cx, unsigned argc, jsval* vp);
 static void pm_finalize(JSFreeOp* fop, JSObject* obj);
 
 static const JSClass pm_class = {
     "PerfMeasurement", JSCLASS_HAS_PRIVATE,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, pm_finalize
 };
 
 // Constructor and destructor
 
 static bool
 pm_construct(JSContext* cx, unsigned argc, jsval* vp)
 {
--- a/js/src/proxy/BaseProxyHandler.cpp
+++ b/js/src/proxy/BaseProxyHandler.cpp
@@ -50,18 +50,19 @@ BaseProxyHandler::get(JSContext *cx, Han
 
     Rooted<PropertyDescriptor> desc(cx);
     if (!getPropertyDescriptor(cx, proxy, id, &desc))
         return false;
     if (!desc.object()) {
         vp.setUndefined();
         return true;
     }
-    MOZ_ASSERT(desc.getter() != JS_PropertyStub);
-    if (!desc.getter()) {
+    if (!desc.getter() ||
+        (!desc.hasGetterObject() && desc.getter() == JS_PropertyStub))
+    {
         vp.set(desc.value());
         return true;
     }
     if (desc.hasGetterObject())
         return InvokeGetterOrSetter(cx, receiver, ObjectValue(*desc.getterObject()),
                                     0, nullptr, vp);
     if (!desc.isShared())
         vp.set(desc.value());
@@ -111,17 +112,16 @@ BaseProxyHandler::set(JSContext *cx, Han
                 return JSObject::reportReadOnly(cx, id, JSREPORT_ERROR);
             if (cx->compartment()->options().extraWarnings(cx))
                 return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
             return true;
         }
 
         // Nonstandard SpiderMonkey special case: setter ops.
         StrictPropertyOp setter = ownDesc.setter();
-        MOZ_ASSERT(setter != JS_StrictPropertyStub);
         if (setter && setter != JS_StrictPropertyStub)
             return CallSetter(cx, receiver, id, setter, ownDesc.attributes(), strict, vp);
 
         // Steps 5.c-d. Adapt for SpiderMonkey by using HasOwnProperty instead
         // of the standard [[GetOwnProperty]].
         bool existingDescriptor;
         if (!HasOwnProperty(cx, receiver, id, &existingDescriptor))
             return false;
@@ -130,20 +130,23 @@ BaseProxyHandler::set(JSContext *cx, Han
         unsigned attrs =
             existingDescriptor
             ? JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_PERMANENT
             : JSPROP_ENUMERATE;
 
         // A very old nonstandard SpiderMonkey extension: default to the Class
         // getter and setter ops.
         const Class *clasp = receiver->getClass();
-        MOZ_ASSERT(clasp->getProperty != JS_PropertyStub);
-        MOZ_ASSERT(clasp->setProperty != JS_StrictPropertyStub);
-        return JSObject::defineGeneric(cx, receiver, id, vp,
-                                       clasp->getProperty, clasp->setProperty, attrs);
+        PropertyOp getter = clasp->getProperty;
+        if (getter == JS_PropertyStub)
+            getter = nullptr;
+        setter = clasp->setProperty;
+        if (setter == JS_StrictPropertyStub)
+            setter = nullptr;
+        return JSObject::defineGeneric(cx, receiver, id, vp, getter, setter, attrs);
     }
 
     // Step 6.
     MOZ_ASSERT(ownDesc.isAccessorDescriptor());
     RootedObject setter(cx);
     if (ownDesc.hasSetterObject())
         setter = ownDesc.setterObject();
     if (!setter)
@@ -156,26 +159,25 @@ bool
 js::SetPropertyIgnoringNamedGetter(JSContext *cx, const BaseProxyHandler *handler,
                                    HandleObject proxy, HandleObject receiver,
                                    HandleId id, MutableHandle<PropertyDescriptor> desc,
                                    bool descIsOwn, bool strict, MutableHandleValue vp)
 {
     /* The control-flow here differs from ::get() because of the fall-through case below. */
     MOZ_ASSERT_IF(descIsOwn, desc.object());
     if (desc.object()) {
-        MOZ_ASSERT(desc.getter() != JS_PropertyStub);
-        MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
-
         // Check for read-only properties.
         if (desc.isReadonly()) {
             if (strict)
                 return Throw(cx, id, descIsOwn ? JSMSG_READ_ONLY : JSMSG_CANT_REDEFINE_PROP);
             return true;
         }
 
+        MOZ_ASSERT(desc.getter() != JS_PropertyStub);
+        MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
         if (desc.hasSetterObject() || desc.setter()) {
             if (!CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), strict, vp))
                 return false;
             if (!proxy->is<ProxyObject>() || proxy->as<ProxyObject>().handler() != handler)
                 return true;
             if (desc.isShared())
                 return true;
         }
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -334,36 +334,37 @@ Proxy::set(JSContext *cx, HandleObject p
     if (!handler->hasPrototype())
         return handler->set(cx, proxy, receiver, id, strict, vp);
 
     // If we have an existing (own or non-own) property with a setter, we want
     // to invoke that.
     Rooted<PropertyDescriptor> desc(cx);
     if (!Proxy::getPropertyDescriptor(cx, proxy, id, &desc))
         return false;
-    if (desc.object() && desc.setter()) {
-        MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
+    if (desc.object() && desc.setter() && desc.setter() != JS_StrictPropertyStub)
         return CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), strict, vp);
-    }
 
     if (desc.isReadonly()) {
         return strict ? Throw(cx, id, JSMSG_READ_ONLY) : true;
     }
 
     // Ok. Either there was no pre-existing property, or it was a value prop
     // that we're going to shadow. Either way, define a new own property.
     unsigned attrs =
         (desc.object() == proxy)
         ? JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_PERMANENT
         : JSPROP_ENUMERATE;
     const Class *clasp = receiver->getClass();
-    MOZ_ASSERT(clasp->getProperty != JS_PropertyStub);
-    MOZ_ASSERT(clasp->setProperty != JS_StrictPropertyStub);
-    return JSObject::defineGeneric(cx, receiver, id, vp, clasp->getProperty, clasp->setProperty,
-                                   attrs);
+    JSPropertyOp getter = clasp->getProperty;
+    if (getter == JS_PropertyStub)
+        getter = nullptr;
+    JSStrictPropertyOp setter = clasp->setProperty;
+    if (setter == JS_StrictPropertyStub)
+        setter = nullptr;
+    return JSObject::defineGeneric(cx, receiver, id, vp, getter, setter, attrs);
 }
 
 bool
 Proxy::getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
 {
     JS_CHECK_RECURSION(cx, return false);
     const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
     AutoEnterPolicy policy(cx, handler, proxy, JSID_VOIDHANDLE, BaseProxyHandler::ENUMERATE, true);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1014,17 +1014,30 @@ my_LargeAllocFailCallback(void *data)
     AutoKeepAtoms keepAtoms(cx->perThreadData);
     rt->gc.gc(GC_NORMAL, JS::gcreason::SHARED_MEMORY_LIMIT);
 }
 
 static const uint32_t CacheEntry_SOURCE = 0;
 static const uint32_t CacheEntry_BYTECODE = 1;
 
 static const JSClass CacheEntry_class = {
-    "CacheEntryObject", JSCLASS_HAS_RESERVED_SLOTS(2)
+    "CacheEntryObject", JSCLASS_HAS_RESERVED_SLOTS(2),
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub, /* setProperty */
+    nullptr,               /* enumerate */
+    nullptr,               /* resolve */
+    nullptr,               /* convert */
+    nullptr,               /* finalize */
+    nullptr,               /* call */
+    nullptr,               /* hasInstance */
+    nullptr,               /* construct */
+    nullptr,               /* trace */
+    JSCLASS_NO_INTERNAL_MEMBERS
 };
 
 static bool
 CacheEntry(JSContext* cx, unsigned argc, JS::Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() != 1 || !args[0].isString()) {
@@ -2551,17 +2564,18 @@ sandbox_resolve(JSContext *cx, HandleObj
     if (ToBoolean(v))
         return JS_ResolveStandardClass(cx, obj, id, resolvedp);
     return true;
 }
 
 static const JSClass sandbox_class = {
     "sandbox",
     JSCLASS_GLOBAL_FLAGS,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr,           nullptr,
+    JS_PropertyStub,   JS_StrictPropertyStub,
     sandbox_enumerate, sandbox_resolve,
     nullptr, nullptr,
     nullptr, nullptr, nullptr,
     JS_GlobalObjectTraceHook
 };
 
 static JSObject *
 NewSandbox(JSContext *cx, bool lazy)
@@ -3942,17 +3956,21 @@ GetMaxArgs(JSContext *cx, unsigned argc,
 
 static bool
 ObjectEmulatingUndefined(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     static const JSClass cls = {
         "ObjectEmulatingUndefined",
-        JSCLASS_EMULATES_UNDEFINED
+        JSCLASS_EMULATES_UNDEFINED,
+        nullptr,
+        nullptr,
+        JS_PropertyStub,
+        JS_StrictPropertyStub
     };
 
     RootedObject obj(cx, JS_NewObject(cx, &cls, JS::NullPtr(), JS::NullPtr()));
     if (!obj)
         return false;
     args.rval().setObject(*obj);
     return true;
 }
@@ -4759,17 +4777,18 @@ global_resolve(JSContext *cx, HandleObje
     if (!JS_ResolveStandardClass(cx, obj, id, resolvedp))
         return false;
 #endif
     return true;
 }
 
 static const JSClass global_class = {
     "global", JSCLASS_GLOBAL_FLAGS,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr,          nullptr,
+    JS_PropertyStub,  JS_StrictPropertyStub,
     global_enumerate, global_resolve,
     nullptr, nullptr,
     nullptr, nullptr, nullptr,
     JS_GlobalObjectTraceHook
 };
 
 /*
  * Define a FakeDOMObject constructor. It returns an object with a getter,
@@ -4874,17 +4893,30 @@ static const JSPropertySpec dom_props[] 
 };
 
 static const JSFunctionSpec dom_methods[] = {
     JS_FNINFO("doFoo", dom_genericMethod, &doFoo_methodinfo, 3, JSPROP_ENUMERATE),
     JS_FS_END
 };
 
 static const JSClass dom_class = {
-    "FakeDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2)
+    "FakeDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2),
+    nullptr,               /* addProperty */
+    nullptr,               /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub, /* setProperty */
+    nullptr,               /* enumerate */
+    nullptr,               /* resolve */
+    nullptr,               /* convert */
+    nullptr,               /* finalize */
+    nullptr,               /* call */
+    nullptr,               /* hasInstance */
+    nullptr,               /* construct */
+    nullptr,               /* trace */
+    JSCLASS_NO_INTERNAL_MEMBERS
 };
 
 #ifdef DEBUG
 static const JSClass *GetDomClass() {
     return &dom_class;
 }
 #endif
 
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -565,18 +565,18 @@ ArgumentsObject::trace(JSTracer *trc, JS
  */
 const Class NormalArgumentsObject::class_ = {
     "Arguments",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(NormalArgumentsObject::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Object) | JSCLASS_BACKGROUND_FINALIZE,
     nullptr,                 /* addProperty */
     args_delProperty,
-    nullptr,                 /* getProperty */
-    nullptr,                 /* setProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
     args_enumerate,
     args_resolve,
     nullptr,                 /* convert     */
     ArgumentsObject::finalize,
     nullptr,                 /* call        */
     nullptr,                 /* hasInstance */
     nullptr,                 /* construct   */
     ArgumentsObject::trace
@@ -589,18 +589,18 @@ const Class NormalArgumentsObject::class
  */
 const Class StrictArgumentsObject::class_ = {
     "Arguments",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(StrictArgumentsObject::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Object) | JSCLASS_BACKGROUND_FINALIZE,
     nullptr,                 /* addProperty */
     args_delProperty,
-    nullptr,                 /* getProperty */
-    nullptr,                 /* setProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
     strictargs_enumerate,
     strictargs_resolve,
     nullptr,                 /* convert     */
     ArgumentsObject::finalize,
     nullptr,                 /* call        */
     nullptr,                 /* hasInstance */
     nullptr,                 /* construct   */
     ArgumentsObject::trace
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -89,29 +89,33 @@ js::ToClampedIndex(JSContext *cx, Handle
  */
 
 /*
  * ArrayBufferObject (base)
  */
 
 const Class ArrayBufferObject::protoClass = {
     "ArrayBufferPrototype",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayBuffer)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayBuffer),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 const Class ArrayBufferObject::class_ = {
     "ArrayBuffer",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayBuffer) |
     JSCLASS_BACKGROUND_FINALIZE,
     nullptr,                 /* addProperty */
     nullptr,                 /* delProperty */
-    nullptr,                 /* getProperty */
-    nullptr,                 /* setProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
     nullptr,                 /* enumerate */
     nullptr,                 /* resolve */
     nullptr,                 /* convert */
     ArrayBufferObject::finalize,
     nullptr,        /* call        */
     nullptr,        /* hasInstance */
     nullptr,        /* construct   */
     ArrayBufferObject::trace,
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2342,17 +2342,17 @@ Debugger::finalize(FreeOp *fop, JSObject
         return;
     fop->delete_(dbg);
 }
 
 const Class Debugger::jsclass = {
     "Debugger",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUG_COUNT),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, Debugger::finalize,
     nullptr,              /* call        */
     nullptr,              /* hasInstance */
     nullptr,              /* construct   */
     Debugger::traceObject
 };
 
 /* static */ Debugger *
@@ -3822,17 +3822,17 @@ DebuggerScript_trace(JSTracer *trc, JSOb
         obj->as<NativeObject>().setPrivateUnbarriered(script);
     }
 }
 
 const Class DebuggerScript_class = {
     "Script",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGSCRIPT_COUNT),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, nullptr,
     nullptr,              /* call        */
     nullptr,              /* hasInstance */
     nullptr,              /* construct   */
     DebuggerScript_trace
 };
 
 JSObject *
@@ -4776,17 +4776,17 @@ DebuggerSource_trace(JSTracer *trc, JSOb
         obj->as<NativeObject>().setPrivateUnbarriered(referent);
     }
 }
 
 const Class DebuggerSource_class = {
     "Source",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGSOURCE_COUNT),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, nullptr,
     nullptr,              /* call        */
     nullptr,              /* hasInstance */
     nullptr,              /* construct   */
     DebuggerSource_trace
 };
 
 JSObject *
@@ -5122,17 +5122,17 @@ DebuggerFrame_maybeDecrementFrameScriptS
 static void
 DebuggerFrame_finalize(FreeOp *fop, JSObject *obj)
 {
     DebuggerFrame_freeScriptFrameIterData(fop, obj);
 }
 
 const Class DebuggerFrame_class = {
     "Frame", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGFRAME_COUNT),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, DebuggerFrame_finalize
 };
 
 static NativeObject *
 CheckThisFrame(JSContext *cx, const CallArgs &args, const char *fnname, bool checkLive)
 {
     if (!args.thisv().isObject()) {
         ReportObjectRequired(cx);
@@ -5340,17 +5340,18 @@ DebuggerFrame_getOlder(JSContext *cx, un
             return dbg->getScriptFrame(cx, iter, args.rval());
         }
     }
     args.rval().setNull();
     return true;
 }
 
 const Class DebuggerArguments_class = {
-    "Arguments", JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGARGUMENTS_COUNT)
+    "Arguments", JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGARGUMENTS_COUNT),
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 /* The getter used for each element of frame.arguments. See DebuggerFrame_getArguments. */
 static bool
 DebuggerArguments_getArg(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     int32_t i = args.callee().as<JSFunction>().getExtendedSlot(0).toInt32();
@@ -5852,17 +5853,17 @@ DebuggerObject_trace(JSTracer *trc, JSOb
         obj->as<NativeObject>().setPrivateUnbarriered(referent);
     }
 }
 
 const Class DebuggerObject_class = {
     "Object",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGOBJECT_COUNT),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, nullptr,
     nullptr,              /* call        */
     nullptr,              /* hasInstance */
     nullptr,              /* construct   */
     DebuggerObject_trace
 };
 
 static NativeObject *
@@ -6760,17 +6761,17 @@ DebuggerEnv_trace(JSTracer *trc, JSObjec
         obj->as<NativeObject>().setPrivateUnbarriered(referent);
     }
 }
 
 const Class DebuggerEnv_class = {
     "Environment",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGENV_COUNT),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, nullptr,
     nullptr,              /* call        */
     nullptr,              /* hasInstance */
     nullptr,              /* construct   */
     DebuggerEnv_trace
 };
 
 static NativeObject *
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -65,17 +65,22 @@ DebuggerMemory::construct(JSContext *cx,
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
                          "Debugger.Memory");
     return false;
 }
 
 /* static */ const Class DebuggerMemory::class_ = {
     "Memory",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
-    JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_COUNT)
+    JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_COUNT),
+
+    nullptr,               // addProperty
+    nullptr,               // delProperty
+    JS_PropertyStub,       // getProperty
+    JS_StrictPropertyStub  // setProperty
 };
 
 /* static */ DebuggerMemory *
 DebuggerMemory::checkThis(JSContext *cx, CallArgs &args, const char *fnName)
 {
     const Value &thisValue = args.thisv();
 
     if (!thisValue.isObject()) {
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -197,22 +197,30 @@ LegacyGeneratorObject::close(JSContext *
     args.setCallee(closeValue);
     args.setThis(ObjectValue(*genObj));
 
     return Invoke(cx, args);
 }
 
 const Class LegacyGeneratorObject::class_ = {
     "Generator",
-    JSCLASS_HAS_RESERVED_SLOTS(GeneratorObject::RESERVED_SLOTS)
+    JSCLASS_HAS_RESERVED_SLOTS(GeneratorObject::RESERVED_SLOTS),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 const Class StarGeneratorObject::class_ = {
     "Generator",
-    JSCLASS_HAS_RESERVED_SLOTS(GeneratorObject::RESERVED_SLOTS)
+    JSCLASS_HAS_RESERVED_SLOTS(GeneratorObject::RESERVED_SLOTS),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 static const JSFunctionSpec star_generator_methods[] = {
     JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
     JS_SELF_HOSTED_FN("next", "StarGeneratorNext", 1, 0),
     JS_SELF_HOSTED_FN("throw", "StarGeneratorThrow", 1, 0),
     JS_FS_END
 };
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -455,17 +455,17 @@ static void
 GlobalDebuggees_finalize(FreeOp *fop, JSObject *obj)
 {
     fop->delete_((GlobalObject::DebuggerVector *) obj->as<NativeObject>().getPrivate());
 }
 
 static const Class
 GlobalDebuggees_class = {
     "GlobalDebuggee", JSCLASS_HAS_PRIVATE,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, GlobalDebuggees_finalize
 };
 
 GlobalObject::DebuggerVector *
 GlobalObject::getDebuggers()
 {
     Value debuggers = getReservedSlot(DEBUGGERS);
     if (debuggers.isUndefined())
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -171,17 +171,18 @@ js::CancelOffThreadIonCompile(JSCompartm
             jit::FinishOffThreadBuilder(nullptr, builder);
         }
         builder = next;
     }
 }
 
 static const JSClass parseTaskGlobalClass = {
     "internal-parse-task-global", JSCLASS_GLOBAL_FLAGS,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr,          nullptr,
+    JS_PropertyStub,  JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, nullptr,
     nullptr, nullptr, nullptr,
     JS_GlobalObjectTraceHook
 };
 
 ParseTask::ParseTask(ExclusiveContext *cx, JSObject *exclusiveContextGlobal, JSContext *initCx,
                      const char16_t *chars, size_t length,
                      JS::OffThreadCompileCallback callback, void *callbackData)
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -549,18 +549,18 @@ TypeOfObjectOperation(JSObject *obj, JSR
     JSType type = js::TypeOfObject(obj);
     return TypeName(type, *rt->commonNames);
 }
 
 static MOZ_ALWAYS_INLINE bool
 InitElemOperation(JSContext *cx, HandleObject obj, HandleValue idval, HandleValue val)
 {
     MOZ_ASSERT(!val.isMagic(JS_ELEMENTS_HOLE));
-    MOZ_ASSERT(!obj->getClass()->getProperty);
-    MOZ_ASSERT(!obj->getClass()->setProperty);
+    MOZ_ASSERT(obj->getClass()->getProperty == JS_PropertyStub);
+    MOZ_ASSERT(obj->getClass()->setProperty == JS_StrictPropertyStub);
 
     RootedId id(cx);
     if (!ValueToId<CanGC>(cx, idval, &id))
         return false;
 
     return JSObject::defineGeneric(cx, obj, id, val, nullptr, nullptr, JSPROP_ENUMERATE);
 }
 
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -136,17 +136,18 @@ js::BoxNonStrictThis(JSContext *cx, cons
 
 #if JS_HAS_NO_SUCH_METHOD
 
 static const uint32_t JSSLOT_FOUND_FUNCTION = 0;
 static const uint32_t JSSLOT_SAVED_ID = 1;
 
 static const Class js_NoSuchMethodClass = {
     "NoSuchMethod",
-    JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS
+    JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 /*
  * When JSOP_CALLPROP or JSOP_CALLELEM does not find the method property of
  * the base object, we search for the __noSuchMethod__ method in the base.
  * If it exists, we store the method and the property's id into an object of
  * NoSuchMethod class and store this object into the callee's stack slot.
  * Later, Invoke will recognise such an object and transfer control to
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1787,24 +1787,22 @@ GetPropertyHelperInline(JSContext *cx,
         return false;
 
     if (!shape) {
         if (!allowGC)
             return false;
 
         vp.setUndefined();
 
-        if (JSPropertyOp getProperty = obj->getClass()->getProperty) {
-            if (!CallJSPropertyOp(cx, getProperty,
-                                  MaybeRooted<JSObject*, allowGC>::toHandle(obj),
-                                  MaybeRooted<jsid, allowGC>::toHandle(id),
-                                  MaybeRooted<Value, allowGC>::toMutableHandle(vp)))
-            {
-                return false;
-            }
+        if (!CallJSPropertyOp(cx, obj->getClass()->getProperty,
+                              MaybeRooted<JSObject*, allowGC>::toHandle(obj),
+                              MaybeRooted<jsid, allowGC>::toHandle(id),
+                              MaybeRooted<Value, allowGC>::toMutableHandle(vp)))
+        {
+            return false;
         }
 
         /*
          * Give a strict warning if foo.bar is evaluated by a script for an
          * object foo with no property named 'bar'.
          */
         if (vp.isUndefined()) {
             jsbytecode *pc = nullptr;
@@ -1976,29 +1974,31 @@ SetPropertyByDefining(typename Execution
     }
 
     // Invalidate SpiderMonkey-specific caches or bail.
     const Class *clasp = receiver->getClass();
     if (mode == ParallelExecution) {
         if (receiver->isDelegate())
             return false;
 
-        if (clasp->getProperty || !types::HasTypePropertyId(receiver, id, v))
+        if (clasp->getProperty != JS_PropertyStub || !types::HasTypePropertyId(receiver, id, v))
             return false;
     } else {
         // Purge the property cache of now-shadowed id in receiver's scope chain.
         if (!PurgeScopeChain(cxArg->asJSContext(), receiver, id))
             return false;
     }
 
     // Define the new data property.
     JSPropertyOp getter = clasp->getProperty;
+    if (getter == JS_PropertyStub)
+        getter = nullptr;
     JSStrictPropertyOp setter = clasp->setProperty;
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
+    if (setter == JS_StrictPropertyStub)
+        setter = nullptr;
     if (!receiver->is<NativeObject>()) {
         if (mode == ParallelExecution)
             return false;
         return JSObject::defineGeneric(cxArg->asJSContext(), receiver, id, v, getter, setter,
                                        JSPROP_ENUMERATE);
     }
     Rooted<NativeObject*> nativeReceiver(cxArg, &receiver->as<NativeObject>());
     return DefinePropertyOrElement<mode>(cxArg, nativeReceiver, id, getter, setter,
--- a/js/src/vm/PIC.cpp
+++ b/js/src/vm/PIC.cpp
@@ -297,17 +297,17 @@ static void
 ForOfPIC_traceObject(JSTracer *trc, JSObject *obj)
 {
     if (ForOfPIC::Chain *chain = ForOfPIC::fromJSObject(&obj->as<NativeObject>()))
         chain->mark(trc);
 }
 
 const Class ForOfPIC::jsclass = {
     "ForOfPIC", JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, ForOfPIC_finalize,
     nullptr,              /* call        */
     nullptr,              /* hasInstance */
     nullptr,              /* construct   */
     ForOfPIC_traceObject
 };
 
 /* static */ NativeObject *
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -261,27 +261,27 @@ RegExpObject::trace(JSTracer *trc, JSObj
     }
 }
 
 const Class RegExpObject::class_ = {
     js_RegExp_str,
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(RegExpObject::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
+    nullptr,                 /* finalize */
+    nullptr,                 /* call */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct */
     RegExpObject::trace
 };
 
 RegExpObject *
 RegExpObject::create(ExclusiveContext *cx, RegExpStatics *res, const char16_t *chars, size_t length,
                      RegExpFlag flags, TokenStream *tokenStream, LifoAlloc &alloc)
 {
     RegExpFlag staticsFlags = res->getFlags();
--- a/js/src/vm/RegExpStatics.cpp
+++ b/js/src/vm/RegExpStatics.cpp
@@ -33,27 +33,27 @@ resc_trace(JSTracer *trc, JSObject *obj)
     MOZ_ASSERT(pdata);
     RegExpStatics *res = static_cast<RegExpStatics *>(pdata);
     res->mark(trc);
 }
 
 const Class RegExpStaticsObject::class_ = {
     "RegExpStatics",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS,
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     resc_finalize,
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
+    nullptr,                 /* call        */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct   */
     resc_trace
 };
 
 RegExpStaticsObject *
 RegExpStatics::create(ExclusiveContext *cx, GlobalObject *parent)
 {
     NativeObject *obj = NewNativeObjectWithGivenProto(cx, &RegExpStaticsObject::class_, nullptr, parent);
     if (!obj)
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -135,24 +135,25 @@ SavedFrame::HashPolicy::rekey(Key &key, 
 {
     key = newKey;
 }
 
 /* static */ const Class SavedFrame::class_ = {
     "SavedFrame",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(SavedFrame::JSSLOT_COUNT),
-    nullptr, // addProperty
-    nullptr, // delProperty
-    nullptr, // getProperty
-    nullptr, // setProperty
-    nullptr, // enumerate
-    nullptr, // resolve
-    nullptr, // convert
-    SavedFrame::finalize
+
+    nullptr,               // addProperty
+    nullptr,               // delProperty
+    JS_PropertyStub,       // getProperty
+    JS_StrictPropertyStub, // setProperty
+    nullptr,               // enumerate
+    nullptr,               // resolve
+    nullptr,               // convert
+    SavedFrame::finalize   // finalize
 };
 
 /* static */ void
 SavedFrame::finalize(FreeOp *fop, JSObject *obj)
 {
     JSPrincipals *p = obj->as<SavedFrame>().getPrincipals();
     if (p) {
         JSRuntime *rt = obj->runtimeFromMainThread();
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -286,23 +286,31 @@ CallObject::createForStrictEval(JSContex
     RootedFunction callee(cx);
     RootedScript script(cx, frame.script());
     RootedObject scopeChain(cx, frame.scopeChain());
     return create(cx, script, scopeChain, callee);
 }
 
 const Class CallObject::class_ = {
     "Call",
-    JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS)
+    JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 const Class DeclEnvObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(DeclEnvObject::RESERVED_SLOTS) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Object)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 /*
  * Create a DeclEnvObject for a JSScript that is not initialized to any
  * particular callsite. This object can either be initialized (with an enclosing
  * scope and callee) or used as a template for jit compilation.
  */
 DeclEnvObject *
@@ -327,19 +335,21 @@ DeclEnvObject::createTemplateObject(JSCo
         return nullptr;
 
     // Assign a fixed slot to a property with the same name as the lambda.
     Rooted<jsid> id(cx, AtomToId(fun->atom()));
     const Class *clasp = obj->getClass();
     unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY;
 
     JSPropertyOp getter = clasp->getProperty;
+    if (getter == JS_PropertyStub)
+        getter = nullptr;
     JSStrictPropertyOp setter = clasp->setProperty;
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
+    if (setter == JS_StrictPropertyStub)
+        setter = nullptr;
 
     if (!NativeObject::putProperty<SequentialExecution>(cx, obj, id, getter, setter, lambdaSlot(),
                                                         attrs, 0)) {
         return nullptr;
     }
 
     MOZ_ASSERT(!obj->hasDynamicSlots());
     return &obj->as<DeclEnvObject>();
@@ -574,35 +584,39 @@ with_ThisObject(JSContext *cx, HandleObj
 {
     return &obj->as<DynamicWithObject>().withThis();
 }
 
 const Class StaticWithObject::class_ = {
     "WithTemplate",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(StaticWithObject::RESERVED_SLOTS) |
-    JSCLASS_IS_ANONYMOUS
+    JSCLASS_IS_ANONYMOUS,
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 const Class DynamicWithObject::class_ = {
     "With",
     JSCLASS_HAS_RESERVED_SLOTS(DynamicWithObject::RESERVED_SLOTS) |
     JSCLASS_IS_ANONYMOUS,
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
-    nullptr, /* trace */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
+    nullptr,                 /* finalize */
+    nullptr,                 /* call        */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct   */
+    nullptr,                 /* trace       */
     JS_NULL_CLASS_SPEC,
     JS_NULL_CLASS_EXT,
     {
         with_LookupGeneric,
         with_LookupProperty,
         with_LookupElement,
         with_DefineGeneric,
         with_DefineProperty,
@@ -724,17 +738,21 @@ StaticBlockObject::addVar(ExclusiveConte
                                                                   spp,
                                                                   /* allowDictionary = */ false);
 }
 
 const Class BlockObject::class_ = {
     "Block",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(BlockObject::RESERVED_SLOTS) |
-    JSCLASS_IS_ANONYMOUS
+    JSCLASS_IS_ANONYMOUS,
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 template<XDRMode mode>
 bool
 js::XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope,
                          MutableHandle<StaticBlockObject*> objp)
 {
     /* NB: Keep this in sync with CloneStaticBlockObject. */
@@ -1014,28 +1032,28 @@ uninitialized_DeleteGeneric(JSContext *c
     ReportUninitializedLexicalId(cx, id);
     return false;
 }
 
 const Class UninitializedLexicalObject::class_ = {
     "UninitializedLexical",
     JSCLASS_HAS_RESERVED_SLOTS(UninitializedLexicalObject::RESERVED_SLOTS) |
     JSCLASS_IS_ANONYMOUS,
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
-    nullptr, /* trace */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
+    nullptr,                 /* finalize */
+    nullptr,                 /* call        */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct   */
+    nullptr,                 /* trace       */
     JS_NULL_CLASS_SPEC,
     JS_NULL_CLASS_EXT,
     {
         uninitialized_LookupGeneric,
         uninitialized_LookupProperty,
         uninitialized_LookupElement,
         nullptr,             /* defineGeneric */
         nullptr,             /* defineProperty */
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -46,17 +46,18 @@ using JS::AutoCheckCannotGC;
 static void
 selfHosting_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 {
     PrintError(cx, stderr, message, report, true);
 }
 
 static const JSClass self_hosting_global_class = {
     "self-hosting-global", JSCLASS_GLOBAL_FLAGS,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr,          nullptr,
+    JS_PropertyStub,  JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, nullptr,
     nullptr, nullptr, nullptr,
     JS_GlobalObjectTraceHook
 };
 
 bool
 js::intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp)
 {
--- a/js/src/vm/Shape-inl.h
+++ b/js/src/vm/Shape-inl.h
@@ -91,19 +91,16 @@ Shape::set(JSContext* cx, HandleObject o
     if (attrs & JSPROP_SETTER) {
         Value fval = setterValue();
         return InvokeGetterOrSetter(cx, receiver, fval, 1, vp.address(), vp);
     }
 
     if (attrs & JSPROP_GETTER)
         return js_ReportGetterOnlyAssignment(cx, strict);
 
-    if (!setterOp())
-        return true;
-
     RootedId id(cx, propid());
 
     /*
      * |with (it) color='red';| ends up here.
      * Avoid exposing the With object to native setters.
      */
     if (obj->is<DynamicWithObject>()) {
         RootedObject nobj(cx, &obj->as<DynamicWithObject>().object());
--- a/js/src/vm/SharedArrayObject.cpp
+++ b/js/src/vm/SharedArrayObject.cpp
@@ -294,36 +294,40 @@ SharedArrayBufferObject::Finalize(FreeOp
 SharedArrayBufferObject::addSizeOfExcludingThis(JSObject *obj, mozilla::MallocSizeOf mallocSizeOf,
                                                 JS::ClassInfo *info)
 {
     info->objectsNonHeapElementsMapped += obj->as<SharedArrayBufferObject>().byteLength();
 }
 
 const Class SharedArrayBufferObject::protoClass = {
     "SharedArrayBufferPrototype",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_SharedArrayBuffer)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_SharedArrayBuffer),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 const Class SharedArrayBufferObject::class_ = {
     "SharedArrayBuffer",
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(SharedArrayBufferObject::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_SharedArrayBuffer),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate */
+    nullptr,                 /* resolve */
+    nullptr,                 /* convert */
     SharedArrayBufferObject::Finalize,
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
-    nullptr, /* trace */
+    nullptr,        /* call        */
+    nullptr,        /* hasInstance */
+    nullptr,        /* construct   */
+    nullptr,        /* trace */
     JS_NULL_CLASS_SPEC,
     JS_NULL_CLASS_EXT
 };
 
 JSObject *
 js_InitSharedArrayBufferClass(JSContext *cx, HandleObject obj)
 {
     MOZ_ASSERT(obj->isNative());
--- a/js/src/vm/SharedTypedArrayObject.cpp
+++ b/js/src/vm/SharedTypedArrayObject.cpp
@@ -701,18 +701,18 @@ IMPL_SHARED_TYPED_ARRAY_COMBINED_UNWRAPP
 #define IMPL_SHARED_TYPED_ARRAY_PROTO_CLASS(_typedArray)                       \
 {                                                                              \
     "Shared" #_typedArray "Prototype",                                         \
     JSCLASS_HAS_RESERVED_SLOTS(SharedTypedArrayObject::RESERVED_SLOTS) |       \
     JSCLASS_HAS_PRIVATE |                                                      \
     JSCLASS_HAS_CACHED_PROTO(JSProto_Shared##_typedArray),                     \
     nullptr,                 /* addProperty */                                 \
     nullptr,                 /* delProperty */                                 \
-    nullptr,                 /* getProperty */                                 \
-    nullptr,                 /* setProperty */                                 \
+    JS_PropertyStub,         /* getProperty */                                 \
+    JS_StrictPropertyStub,   /* setProperty */                                 \
     nullptr,                 /* enumerate   */                                 \
     nullptr,                 /* resolve     */                                 \
     nullptr,                 /* convert     */                                 \
     nullptr,                 /* finalize    */                                 \
     nullptr,                 /* call        */                                 \
     nullptr,                 /* hasInstance */                                 \
     nullptr,                 /* construct   */                                 \
     nullptr,                 /* trace  */                                      \
@@ -722,18 +722,18 @@ IMPL_SHARED_TYPED_ARRAY_COMBINED_UNWRAPP
 #define IMPL_SHARED_TYPED_ARRAY_FAST_CLASS(_typedArray)                        \
 {                                                                              \
     "Shared" #_typedArray,                                                     \
     JSCLASS_HAS_RESERVED_SLOTS(SharedTypedArrayObject::RESERVED_SLOTS) |       \
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |                        \
     JSCLASS_HAS_CACHED_PROTO(JSProto_Shared##_typedArray),                     \
     nullptr,                 /* addProperty */                                 \
     nullptr,                 /* delProperty */                                 \
-    nullptr,                 /* getProperty */                                 \
-    nullptr,                 /* setProperty */                                 \
+    JS_PropertyStub,         /* getProperty */                                 \
+    JS_StrictPropertyStub,   /* setProperty */                                 \
     nullptr,                 /* enumerate   */                                 \
     nullptr,                 /* resolve     */                                 \
     nullptr,                 /* convert     */                                 \
     nullptr,                 /* finalize    */                                 \
     nullptr,                 /* call        */                                 \
     nullptr,                 /* hasInstance */                                 \
     nullptr,                 /* construct   */                                 \
     nullptr,                 /* trace  */                                      \
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -797,18 +797,18 @@ TypedArrayObject::sharedTypedArrayProtot
     // slots.  (It's not clear this is desirable -- particularly applied to
     // the actual typed array prototypes, see below -- but it's what ES6
     // draft 20140824 requires.)  But this is about as much as we can do
     // until we implement @@toStringTag.
     "???",
     JSCLASS_HAS_CACHED_PROTO(JSProto_TypedArray),
     nullptr,                /* addProperty */
     nullptr,                /* delProperty */
-    nullptr,                /* getProperty */
-    nullptr,                /* setProperty */
+    JS_PropertyStub,        /* getProperty */
+    JS_StrictPropertyStub,  /* setProperty */
     nullptr,                /* enumerate */
     nullptr,                /* resolve */
     nullptr,                /* convert */
     nullptr,                /* finalize */
     nullptr,                /* call */
     nullptr,                /* hasInstance */
     nullptr,                /* construct */
     nullptr,                /* trace */
@@ -1752,18 +1752,18 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Flo
 #define IMPL_TYPED_ARRAY_CLASS(_typedArray)                                    \
 {                                                                              \
     #_typedArray,                                                              \
     JSCLASS_HAS_RESERVED_SLOTS(TypedArrayLayout::RESERVED_SLOTS) |             \
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |                        \
     JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray),                           \
     nullptr,                 /* addProperty */                                 \
     nullptr,                 /* delProperty */                                 \
-    nullptr,                 /* getProperty */                                 \
-    nullptr,                 /* setProperty */                                 \
+    JS_PropertyStub,         /* getProperty */                                 \
+    JS_StrictPropertyStub,   /* setProperty */                                 \
     nullptr,                 /* enumerate   */                                 \
     nullptr,                 /* resolve     */                                 \
     nullptr,                 /* convert     */                                 \
     nullptr,                 /* finalize    */                                 \
     nullptr,                 /* call        */                                 \
     nullptr,                 /* hasInstance */                                 \
     nullptr,                 /* construct   */                                 \
     TypedArrayObject::trace, /* trace  */                                      \
@@ -1795,28 +1795,28 @@ const Class TypedArrayObject::classes[Sc
      * Actually ({}).toString.call(Uint8Array.prototype) should throw, because
      * Uint8Array.prototype lacks the the typed array internal slots.  (Same as
      * with %TypedArray%.prototype.)  It's not clear this is desirable (see
      * above), but it's what we've always done, so keep doing it til we
      * implement @@toStringTag or ES6 changes.
      */ \
     #typedArray "Prototype", \
     JSCLASS_HAS_CACHED_PROTO(JSProto_##typedArray), \
-    nullptr, /* addProperty */ \
-    nullptr, /* delProperty */ \
-    nullptr, /* getProperty */ \
-    nullptr, /* setProperty */ \
-    nullptr, /* enumerate */ \
-    nullptr, /* resolve */ \
-    nullptr, /* convert */ \
-    nullptr, /* finalize */ \
-    nullptr, /* call */ \
-    nullptr, /* hasInstance */ \
-    nullptr, /* construct */ \
-    nullptr, /* trace  */ \
+    nullptr,                /* addProperty */ \
+    nullptr,                /* delProperty */ \
+    JS_PropertyStub,        /* getProperty */ \
+    JS_StrictPropertyStub,  /* setProperty */ \
+    nullptr,                /* enumerate   */ \
+    nullptr,                /* resolve     */ \
+    nullptr,                /* convert     */ \
+    nullptr,                /* finalize    */ \
+    nullptr,                /* call        */ \
+    nullptr,                /* hasInstance */ \
+    nullptr,                /* construct   */ \
+    nullptr,                /* trace  */ \
     { \
         typedArray::createConstructor, \
         typedArray::createPrototype, \
         nullptr, \
         nullptr, \
         nullptr, \
         nullptr, \
         JSProto_TypedArray \
@@ -1840,36 +1840,40 @@ TypedArrayObject::isOriginalLengthGetter
 {
     return native == TypedArray_lengthGetter;
 }
 
 const Class DataViewObject::protoClass = {
     "DataViewPrototype",
     JSCLASS_HAS_PRIVATE |
     JSCLASS_HAS_RESERVED_SLOTS(TypedArrayLayout::RESERVED_SLOTS) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_DataView)
+    JSCLASS_HAS_CACHED_PROTO(JSProto_DataView),
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub    /* setProperty */
 };
 
 const Class DataViewObject::class_ = {
     "DataView",
     JSCLASS_HAS_PRIVATE |
     JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(TypedArrayLayout::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_DataView),
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* convert */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
+    nullptr,                 /* addProperty */
+    nullptr,                 /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    nullptr,                 /* enumerate   */
+    nullptr,                 /* resolve     */
+    nullptr,                 /* convert     */
+    nullptr,                 /* finalize    */
+    nullptr,                 /* call        */
+    nullptr,                 /* hasInstance */
+    nullptr,                 /* construct   */
     ArrayBufferViewObject::trace
 };
 
 const JSFunctionSpec DataViewObject::jsfuncs[] = {
     JS_FN("getInt8",    DataViewObject::fun_getInt8,      1,0),
     JS_FN("getUint8",   DataViewObject::fun_getUint8,     1,0),
     JS_FN("getInt16",   DataViewObject::fun_getInt16,     2,0),
     JS_FN("getUint16",  DataViewObject::fun_getUint16,    2,0),
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -48,17 +48,25 @@
 using namespace mozilla;
 using namespace mozilla::scache;
 using namespace xpc;
 using namespace JS;
 
 // This JSClass exists to trick silly code that expects toString()ing the
 // global in a component scope to return something with "BackstagePass" in it
 // to continue working.
-static const JSClass kFakeBackstagePassJSClass = { "FakeBackstagePass" };
+static const JSClass kFakeBackstagePassJSClass =
+{
+    "FakeBackstagePass",
+    0,
+    nullptr,
+    nullptr,
+    JS_PropertyStub,
+    JS_StrictPropertyStub
+};
 
 static const char kXPConnectServiceContractID[] = "@mozilla.org/js/xpc/XPConnect;1";
 static const char kObserverServiceContractID[] = "@mozilla.org/observer-service;1";
 static const char kJSCachePrefix[] = "jsloader";
 
 #define HAVE_PR_MEMMAP
 
 /**
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -454,17 +454,17 @@ sandbox_addProperty(JSContext *cx, Handl
     return true;
 }
 
 #define XPCONNECT_SANDBOX_CLASS_METADATA_SLOT (XPCONNECT_GLOBAL_EXTRA_SLOT_OFFSET)
 
 static const js::Class SandboxClass = {
     "Sandbox",
     XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     sandbox_enumerate, sandbox_resolve, sandbox_convert,  sandbox_finalize,
     nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook,
     JS_NULL_CLASS_SPEC,
     {
       nullptr,      /* outerObject */
       nullptr,      /* innerObject */
       false,        /* isWrappedNative */
       nullptr,      /* weakmapKeyDelegateOp */
@@ -473,17 +473,17 @@ static const js::Class SandboxClass = {
     JS_NULL_OBJECT_OPS
 };
 
 // Note to whomever comes here to remove addProperty hooks: billm has promised
 // to do the work for this class.
 static const js::Class SandboxWriteToProtoClass = {
     "Sandbox",
     XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1),
-    sandbox_addProperty, nullptr, nullptr, nullptr,
+    sandbox_addProperty, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     sandbox_enumerate, sandbox_resolve, sandbox_convert,  sandbox_finalize,
     nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook,
     JS_NULL_CLASS_SPEC,
     {
       nullptr,      /* outerObject */
       nullptr,      /* innerObject */
       false,        /* isWrappedNative */
       nullptr,      /* weakmapKeyDelegateOp */
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -767,17 +767,18 @@ env_resolve(JSContext *cx, HandleObject 
         }
         *resolvedp = true;
     }
     return true;
 }
 
 static const JSClass env_class = {
     "environment", JSCLASS_HAS_PRIVATE,
-    nullptr, nullptr, nullptr, env_setProperty,
+    nullptr, nullptr,
+    JS_PropertyStub, env_setProperty,
     env_enumerate, env_resolve
 };
 
 /***************************************************************************/
 
 typedef enum JSShellErrNum {
 #define MSG_DEF(name, number, count, exception, format) \
     name = number,
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -1420,20 +1420,20 @@ nsXPCWrappedJSClass::GetInterfaceName()
 static void
 FinalizeStub(JSFreeOp *fop, JSObject *obj)
 {
 }
 
 static const JSClass XPCOutParamClass = {
     "XPCOutParam",
     0,
-    nullptr,   /* addProperty */
-    nullptr,   /* delProperty */
-    nullptr,   /* getProperty */
-    nullptr,   /* setProperty */
+    nullptr,
+    nullptr,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
     nullptr,   /* enumerate */
     nullptr,   /* resolve */
     nullptr,   /* convert */
     FinalizeStub,
     nullptr,   /* call */
     nullptr,   /* hasInstance */
     nullptr,   /* construct */
     nullptr    /* trace */
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -799,16 +799,18 @@ XPCWrappedNative::Init(HandleObject pare
     const JSClass* jsclazz = si ? si->GetJSClass() : Jsvalify(&XPC_WN_NoHelper_JSClass.base);
 
     // We should have the global jsclass flag if and only if we're a global.
     MOZ_ASSERT_IF(si, !!si->GetFlags().IsGlobalObject() == !!(jsclazz->flags & JSCLASS_IS_GLOBAL));
 
     MOZ_ASSERT(jsclazz &&
                jsclazz->name &&
                jsclazz->flags &&
+               jsclazz->getProperty &&
+               jsclazz->setProperty &&
                jsclazz->resolve &&
                jsclazz->convert &&
                jsclazz->finalize, "bad class");
 
     RootedObject protoJSObject(cx, HasProto() ?
                                    GetProto()->GetJSProtoObject() :
                                    JS_GetObjectPrototype(cx, parent));
     if (!protoJSObject) {
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -650,17 +650,17 @@ const XPCWrappedNativeJSClass XPC_WN_NoH
   { // base
     "XPCWrappedNative_NoHelper",    // name;
     WRAPPER_SLOTS |
     JSCLASS_PRIVATE_IS_NSISUPPORTS, // flags
 
     /* Mandatory non-null function pointer members. */
     XPC_WN_OnlyIWrite_AddPropertyStub, // addProperty
     XPC_WN_CantDeletePropertyStub,     // delProperty
-    nullptr,                           // getProperty
+    JS_PropertyStub,                   // getProperty
     XPC_WN_OnlyIWrite_SetPropertyStub, // setProperty
 
     XPC_WN_Shared_Enumerate,           // enumerate
     XPC_WN_NoHelper_Resolve,           // resolve
     XPC_WN_Shared_Convert,             // convert
     XPC_WN_NoHelper_Finalize,          // finalize
 
     /* Optionally non-null members start here. */
@@ -1117,23 +1117,23 @@ XPCNativeScriptableShared::PopulateJSCla
         delProperty = XPC_WN_MaybeResolvingDeletePropertyStub;
     else
         delProperty = XPC_WN_CantDeletePropertyStub;
     mJSClass.base.delProperty = delProperty;
 
     if (mFlags.WantGetProperty())
         mJSClass.base.getProperty = XPC_WN_Helper_GetProperty;
     else
-        mJSClass.base.getProperty = nullptr;
+        mJSClass.base.getProperty = JS_PropertyStub;
 
     JSStrictPropertyOp setProperty;
     if (mFlags.WantSetProperty())
         setProperty = XPC_WN_Helper_SetProperty;
     else if (mFlags.UseJSStubForSetProperty())
-        setProperty = nullptr;
+        setProperty = JS_StrictPropertyStub;
     else if (mFlags.AllowPropModsDuringResolve())
         setProperty = XPC_WN_MaybeResolvingStrictPropertyStub;
     else
         setProperty = XPC_WN_CannotModifyStrictPropertyStub;
     mJSClass.base.setProperty = setProperty;
 
     // We figure out most of the enumerate strategy at call time.
 
@@ -1390,18 +1390,18 @@ XPC_WN_ModsAllowed_Proto_Resolve(JSConte
 
 const js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass = {
     "XPC_WN_ModsAllowed_WithCall_Proto_JSClass", // name;
     WRAPPER_SLOTS, // flags;
 
     /* Function pointer members. */
     nullptr,                        // addProperty;
     nullptr,                        // delProperty;
-    nullptr,                        // getProperty;
-    nullptr,                        // setProperty;
+    JS_PropertyStub,                // getProperty;
+    JS_StrictPropertyStub,          // setProperty;
     XPC_WN_Shared_Proto_Enumerate,  // enumerate;
     XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
     nullptr,                        // convert;
     XPC_WN_Shared_Proto_Finalize,   // finalize;
 
     /* Optionally non-null members start here. */
     nullptr,                        // call;
     nullptr,                        // construct;
@@ -1415,18 +1415,18 @@ const js::Class XPC_WN_ModsAllowed_WithC
 
 const js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass = {
     "XPC_WN_ModsAllowed_NoCall_Proto_JSClass", // name;
     WRAPPER_SLOTS,                  // flags;
 
     /* Function pointer members. */
     nullptr,                        // addProperty;
     nullptr,                        // delProperty;
-    nullptr,                        // getProperty;
-    nullptr,                        // setProperty;
+    JS_PropertyStub,                // getProperty;
+    JS_StrictPropertyStub,          // setProperty;
     XPC_WN_Shared_Proto_Enumerate,  // enumerate;
     XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
     nullptr,                        // convert;
     XPC_WN_Shared_Proto_Finalize,   // finalize;
 
     /* Optionally non-null members start here. */
     nullptr,                         // call;
     nullptr,                         // construct;
@@ -1502,17 +1502,17 @@ XPC_WN_NoMods_Proto_Resolve(JSContext *c
 
 const js::Class XPC_WN_NoMods_WithCall_Proto_JSClass = {
     "XPC_WN_NoMods_WithCall_Proto_JSClass",    // name;
     WRAPPER_SLOTS,                             // flags;
 
     /* Mandatory non-null function pointer members. */
     XPC_WN_OnlyIWrite_Proto_AddPropertyStub,   // addProperty;
     XPC_WN_CantDeletePropertyStub,             // delProperty;
-    nullptr,                                   // getProperty;
+    JS_PropertyStub,                           // getProperty;
     XPC_WN_OnlyIWrite_Proto_SetPropertyStub,   // setProperty;
     XPC_WN_Shared_Proto_Enumerate,             // enumerate;
     XPC_WN_NoMods_Proto_Resolve,               // resolve;
     nullptr,                                   // convert;
     XPC_WN_Shared_Proto_Finalize,              // finalize;
 
     /* Optionally non-null members start here. */
     nullptr,                         // call;
@@ -1527,17 +1527,17 @@ const js::Class XPC_WN_NoMods_WithCall_P
 
 const js::Class XPC_WN_NoMods_NoCall_Proto_JSClass = {
     "XPC_WN_NoMods_NoCall_Proto_JSClass",      // name;
     WRAPPER_SLOTS,                             // flags;
 
     /* Mandatory non-null function pointer members. */
     XPC_WN_OnlyIWrite_Proto_AddPropertyStub,   // addProperty;
     XPC_WN_CantDeletePropertyStub,             // delProperty;
-    nullptr,                                   // getProperty;
+    JS_PropertyStub,                           // getProperty;
     XPC_WN_OnlyIWrite_Proto_SetPropertyStub,   // setProperty;
     XPC_WN_Shared_Proto_Enumerate,             // enumerate;
     XPC_WN_NoMods_Proto_Resolve,               // resolve;
     nullptr,                                   // convert;
     XPC_WN_Shared_Proto_Finalize,              // finalize;
 
     /* Optionally non-null members start here. */
     nullptr,                         // call;
@@ -1616,17 +1616,17 @@ XPC_WN_TearOff_ObjectMoved(JSObject *obj
 }
 
 const js::Class XPC_WN_Tearoff_JSClass = {
     "WrappedNative_TearOff",                   // name;
     WRAPPER_SLOTS,                             // flags;
 
     XPC_WN_OnlyIWrite_AddPropertyStub,         // addProperty;
     XPC_WN_CantDeletePropertyStub,             // delProperty;
-    nullptr,                                   // getProperty;
+    JS_PropertyStub,                           // getProperty;
     XPC_WN_OnlyIWrite_SetPropertyStub,         // setProperty;
     XPC_WN_TearOff_Enumerate,                  // enumerate;
     XPC_WN_TearOff_Resolve,                    // resolve;
     XPC_WN_Shared_Convert,                     // convert;
     XPC_WN_TearOff_Finalize,                   // finalize;
 
     /* Optionally non-null members start here. */
     nullptr,                                   // call
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -139,22 +139,24 @@ XrayTraits::setExpandoChain(JSContext *c
 // static
 XPCWrappedNative *
 XPCWrappedNativeXrayTraits::getWN(JSObject *wrapper)
 {
     return XPCWrappedNative::Get(getTargetObject(wrapper));
 }
 
 const JSClass XPCWrappedNativeXrayTraits::HolderClass = {
-    "NativePropertyHolder", JSCLASS_HAS_RESERVED_SLOTS(2)
+    "NativePropertyHolder", JSCLASS_HAS_RESERVED_SLOTS(2),
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 
 const JSClass JSXrayTraits::HolderClass = {
-    "JSXrayHolder", JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT)
+    "JSXrayHolder", JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
 };
 
 bool
 OpaqueXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsWrapper, HandleObject wrapper,
                                      HandleObject holder, HandleId id,
                                      MutableHandle<JSPropertyDescriptor> desc)
 {
     bool ok = XrayTraits::resolveOwnProperty(cx, jsWrapper, wrapper, holder, id, desc);
@@ -840,17 +842,17 @@ ExpandoObjectFinalize(JSFreeOp *fop, JSO
     // Release the principal.
     nsIPrincipal *principal = GetExpandoObjectPrincipal(obj);
     NS_RELEASE(principal);
 }
 
 const JSClass ExpandoObjectClass = {
     "XrayExpandoObject",
     JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_EXPANDO_COUNT),
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, ExpandoObjectFinalize
 };
 
 bool
 XrayTraits::expandoObjectMatchesConsumer(JSContext *cx,
                                          HandleObject expandoObject,
                                          nsIPrincipal *consumerOrigin,
                                          HandleObject exclusiveGlobal)
@@ -1223,20 +1225,20 @@ XPCWrappedNativeXrayTraits::resolveNativ
         // This is a method. Clone a function for it.
         if (!member->NewFunctionObject(ccx, iface, wrapper, desc.value().address())) {
             JS_ReportError(cx, "Failed to clone function object for native function");
             return false;
         }
 
         // Without a wrapper the function would live on the prototype. Since we
         // don't have one, we have to avoid calling the scriptable helper's
-        // GetProperty method for this property, so null out the getter and
+        // GetProperty method for this property, so stub out the getter and
         // setter here explicitly.
-        desc.setGetter(nullptr);
-        desc.setSetter(nullptr);
+        desc.setGetter(JS_PropertyStub);
+        desc.setSetter(JS_StrictPropertyStub);
     }
 
     if (!JS_WrapValue(cx, desc.value()) || !JS_WrapValue(cx, &fval))
         return false;
 
     if (desc.hasGetterObject())
         desc.setGetterObject(&fval.toObject());
     if (desc.hasSetterObject())
--- a/netwerk/base/src/ProxyAutoConfig.cpp
+++ b/netwerk/base/src/ProxyAutoConfig.cpp
@@ -598,17 +598,17 @@ private:
 
     return NS_OK;
   }
 };
 
 const JSClass JSRuntimeWrapper::sGlobalClass = {
   "PACResolutionThreadGlobal",
   JSCLASS_GLOBAL_FLAGS,
-  nullptr, nullptr, nullptr, nullptr,
+  nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
   nullptr, nullptr, nullptr,
   nullptr, nullptr, nullptr, nullptr,
   JS_GlobalObjectTraceHook
 };
 
 void
 ProxyAutoConfig::SetThreadLocalIndex(uint32_t index)
 {
--- a/toolkit/components/finalizationwitness/FinalizationWitnessService.cpp
+++ b/toolkit/components/finalizationwitness/FinalizationWitnessService.cpp
@@ -112,18 +112,18 @@ void Finalize(JSFreeOp *fop, JSObject *o
   // during shutdown. In that case, there is not much we can do.
 }
 
 static const JSClass sWitnessClass = {
   "FinalizationWitness",
   JSCLASS_HAS_RESERVED_SLOTS(WITNESS_INSTANCES_SLOTS),
   nullptr /* addProperty */,
   nullptr /* delProperty */,
-  nullptr /* getProperty */,
-  nullptr /* setProperty */,
+  JS_PropertyStub /* getProperty */,
+  JS_StrictPropertyStub /* setProperty */,
   nullptr /* enumerate */,
   nullptr /* resolve */,
   nullptr /* convert */,
   Finalize /* finalize */
 };
 
 bool IsWitness(JS::Handle<JS::Value> v)
 {
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -1262,17 +1262,18 @@ JSHistogram_Clear(JSContext *cx, unsigne
   return true;
 }
 
 nsresult
 WrapAndReturnHistogram(Histogram *h, JSContext *cx, JS::MutableHandle<JS::Value> ret)
 {
   static const JSClass JSHistogram_class = {
     "JSHistogram",  /* name */
-    JSCLASS_HAS_PRIVATE  /* flags */
+    JSCLASS_HAS_PRIVATE, /* flags */
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
   };
 
   JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &JSHistogram_class, JS::NullPtr(), JS::NullPtr()));
   if (!obj)
     return NS_ERROR_FAILURE;
   if (!(JS_DefineFunction(cx, obj, "add", JSHistogram_Add, 1, 0)
         && JS_DefineFunction(cx, obj, "snapshot", JSHistogram_Snapshot, 0, 0)
         && JS_DefineFunction(cx, obj, "clear", JSHistogram_Clear, 0, 0))) {
@@ -1438,17 +1439,18 @@ JSKeyedHistogram_Clear(JSContext *cx, un
   return true;
 }
 
 nsresult
 WrapAndReturnKeyedHistogram(KeyedHistogram *h, JSContext *cx, JS::MutableHandle<JS::Value> ret)
 {
   static const JSClass JSHistogram_class = {
     "JSKeyedHistogram",  /* name */
-    JSCLASS_HAS_PRIVATE  /* flags */
+    JSCLASS_HAS_PRIVATE, /* flags */
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub
   };
 
   JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &JSHistogram_class, JS::NullPtr(), JS::NullPtr()));
   if (!obj)
     return NS_ERROR_FAILURE;
   if (!(JS_DefineFunction(cx, obj, "add", JSKeyedHistogram_Add, 2, 0)
         && JS_DefineFunction(cx, obj, "snapshot", JSKeyedHistogram_Snapshot, 1, 0)
         && JS_DefineFunction(cx, obj, "keys", JSKeyedHistogram_Keys, 0, 0)
--- a/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp
+++ b/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp
@@ -85,17 +85,17 @@ RunTest(JSRuntime* rt, JSContext* cx, Ar
   JS_RemoveExtraGCRootsTracer(rt, TraceArray<ArrayT>, array);
 }
 
 static void
 CreateGlobalAndRunTest(JSRuntime* rt, JSContext* cx)
 {
   static const JSClass GlobalClass = {
     "global", JSCLASS_GLOBAL_FLAGS,
-    nullptr, nullptr, nullptr, nullptr,
+    nullptr, nullptr, JS_PropertyStub, JS_StrictPropertyStub,
     nullptr, nullptr, nullptr, nullptr,
     nullptr, nullptr, nullptr,
     JS_GlobalObjectTraceHook
   };
 
   JS::CompartmentOptions options;
   options.setVersion(JSVERSION_LATEST);
   JS::PersistentRootedObject global(cx);