Backed out changeset ba1d6ece1bc6 (bug 1103368)
authorWes Kocher <wkocher@mozilla.com>
Mon, 24 Nov 2014 17:04:06 -0800
changeset 217213 ae31d26695113dbe96aecb29e3055546526ec88b
parent 217212 56ebb99d774eef30488e7fcca268308ed15e0660
child 217214 cabeb902de6d41eebb69842ae69e0e073f1a7644
push id52260
push userkwierso@gmail.com
push dateTue, 25 Nov 2014 01:05:13 +0000
treeherdermozilla-inbound@2ca8635fe240 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1103368
milestone36.0a1
backs outba1d6ece1bc620b24c14d334c77ebddc7ad08528
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 ba1d6ece1bc6 (bug 1103368)
js/src/builtin/Intl.cpp
js/src/builtin/TypedObject.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsstr.cpp
js/src/proxy/BaseProxyHandler.cpp
js/src/proxy/Proxy.cpp
js/src/vm/DebuggerMemory.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/Interpreter.h
js/src/vm/NativeObject.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/SharedTypedArrayObject.cpp
js/src/vm/TypedArrayObject.cpp
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -452,18 +452,18 @@ intl_availableLocales(JSContext *cx, Cou
         if (!lang)
             return false;
         char *p;
         while ((p = strchr(lang, '_')))
             *p = '-';
         RootedAtom a(cx, Atomize(cx, lang, strlen(lang)));
         if (!a)
             return false;
-        if (!JSObject::defineProperty(cx, locales, a->asPropertyName(), t, nullptr, nullptr,
-                                      JSPROP_ENUMERATE))
+        if (!JSObject::defineProperty(cx, locales, a->asPropertyName(), t,
+                                      JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE))
         {
             return false;
         }
     }
 #endif
     result.setObject(*locales);
     return true;
 }
@@ -715,18 +715,21 @@ InitCollatorClass(JSContext *cx, HandleO
         return nullptr;
 
     // 10.2.1 and 10.3
     if (!IntlInitialize(cx, proto, cx->names().InitializeCollator, UndefinedHandleValue, options))
         return nullptr;
 
     // 8.1
     RootedValue ctorValue(cx, ObjectValue(*ctor));
-    if (!JSObject::defineProperty(cx, Intl, cx->names().Collator, ctorValue, nullptr, nullptr, 0))
+    if (!JSObject::defineProperty(cx, Intl, cx->names().Collator, ctorValue,
+                                  JS_PropertyStub, JS_StrictPropertyStub, 0))
+    {
         return nullptr;
+    }
 
     return ctor;
 }
 
 bool
 GlobalObject::initCollatorProto(JSContext *cx, Handle<GlobalObject*> global)
 {
     RootedNativeObject proto(cx, global->createBlankPrototype(cx, &CollatorClass));
@@ -1203,18 +1206,18 @@ InitNumberFormatClass(JSContext *cx, Han
         return nullptr;
 
     // 11.2.1 and 11.3
     if (!IntlInitialize(cx, proto, cx->names().InitializeNumberFormat, UndefinedHandleValue, options))
         return nullptr;
 
     // 8.1
     RootedValue ctorValue(cx, ObjectValue(*ctor));
-    if (!JSObject::defineProperty(cx, Intl, cx->names().NumberFormat, ctorValue, nullptr, nullptr,
-                                  0))
+    if (!JSObject::defineProperty(cx, Intl, cx->names().NumberFormat, ctorValue,
+                                  JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return nullptr;
     }
 
     return ctor;
 }
 
 bool
@@ -1660,17 +1663,17 @@ InitDateTimeFormatClass(JSContext *cx, H
 
     // 12.2.1 and 12.3
     if (!IntlInitialize(cx, proto, cx->names().InitializeDateTimeFormat, UndefinedHandleValue, options))
         return nullptr;
 
     // 8.1
     RootedValue ctorValue(cx, ObjectValue(*ctor));
     if (!JSObject::defineProperty(cx, Intl, cx->names().DateTimeFormat, ctorValue,
-                                  nullptr, nullptr, 0))
+                                  JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return nullptr;
     }
 
     return ctor;
 }
 
 bool
@@ -2035,18 +2038,21 @@ js_InitIntlClass(JSContext *cx, HandleOb
     // called with this being "the standard built-in Intl object". The global
     // object reserves slots to track standard built-in objects, but doesn't
     // normally keep references to non-constructors. This makes sure there is one.
     RootedObject Intl(cx, global->getOrCreateIntlObject(cx));
     if (!Intl)
         return nullptr;
 
     RootedValue IntlValue(cx, ObjectValue(*Intl));
-    if (!JSObject::defineProperty(cx, global, cx->names().Intl, IntlValue, nullptr, nullptr, 0))
+    if (!JSObject::defineProperty(cx, global, cx->names().Intl, IntlValue,
+                                  JS_PropertyStub, JS_StrictPropertyStub, 0))
+    {
         return nullptr;
+    }
 
     if (!JS_DefineFunctions(cx, Intl, intl_static_methods))
         return nullptr;
 
     if (!InitCollatorClass(cx, Intl, global))
         return nullptr;
     if (!InitNumberFormatClass(cx, Intl, global))
         return nullptr;
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -545,40 +545,48 @@ const JSFunctionSpec ArrayMetaTypeDescr:
 
 bool
 js::CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr descr)
 {
     // If data is transparent, also store the public slots.
     if (descr->transparent()) {
         // byteLength
         RootedValue typeByteLength(cx, Int32Value(descr->size()));
-        if (!JSObject::defineProperty(cx, descr, cx->names().byteLength, typeByteLength,
-                                      nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
+        if (!JSObject::defineProperty(cx, descr, cx->names().byteLength,
+                                      typeByteLength,
+                                      nullptr, nullptr,
+                                      JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return false;
         }
 
         // byteAlignment
         RootedValue typeByteAlignment(cx, Int32Value(descr->alignment()));
-        if (!JSObject::defineProperty(cx, descr, cx->names().byteAlignment, typeByteAlignment,
-                                      nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
+        if (!JSObject::defineProperty(cx, descr, cx->names().byteAlignment,
+                                      typeByteAlignment,
+                                      nullptr, nullptr,
+                                      JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return false;
         }
     } else {
         // byteLength
-        if (!JSObject::defineProperty(cx, descr, cx->names().byteLength, UndefinedHandleValue,
-                                      nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
+        if (!JSObject::defineProperty(cx, descr, cx->names().byteLength,
+                                      UndefinedHandleValue,
+                                      nullptr, nullptr,
+                                      JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return false;
         }
 
         // byteAlignment
-        if (!JSObject::defineProperty(cx, descr, cx->names().byteAlignment, UndefinedHandleValue,
-                                      nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
+        if (!JSObject::defineProperty(cx, descr, cx->names().byteAlignment,
+                                      UndefinedHandleValue,
+                                      nullptr, nullptr,
+                                      JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return false;
         }
     }
 
     return true;
 }
 
@@ -599,28 +607,26 @@ ArrayMetaTypeDescr::create(JSContext *cx
     obj->initReservedSlot(JS_DESCR_SLOT_STRING_REPR, StringValue(stringRepr));
     obj->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(elementType->alignment()));
     obj->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(size));
     obj->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(elementType->opaque()));
     obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE, ObjectValue(*elementType));
     obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH, Int32Value(length));
 
     RootedValue elementTypeVal(cx, ObjectValue(*elementType));
-    if (!JSObject::defineProperty(cx, obj, cx->names().elementType, elementTypeVal,
-                                  nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
-    {
+    if (!JSObject::defineProperty(cx, obj, cx->names().elementType,
+                                  elementTypeVal, nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
-    }
 
     RootedValue lengthValue(cx, NumberValue(length));
-    if (!JSObject::defineProperty(cx, obj, cx->names().length, lengthValue,
-                                  nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
-    {
+    if (!JSObject::defineProperty(cx, obj, cx->names().length,
+                                  lengthValue, nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
-    }
 
     if (!CreateUserSizeAndAlignmentProperties(cx, obj))
         return nullptr;
 
     Rooted<TypedProto*> prototypeObj(cx);
     prototypeObj = CreatePrototypeObjectForComplexTypeInstance(cx, obj, arrayTypePrototype);
     if (!prototypeObj)
         return nullptr;
@@ -954,24 +960,26 @@ StructMetaTypeDescr::create(JSContext *c
     }
 
     // Create data properties fieldOffsets and fieldTypes
     if (!JSObject::freeze(cx, userFieldOffsets))
         return nullptr;
     if (!JSObject::freeze(cx, userFieldTypes))
         return nullptr;
     RootedValue userFieldOffsetsValue(cx, ObjectValue(*userFieldOffsets));
-    if (!JSObject::defineProperty(cx, descr, cx->names().fieldOffsets, userFieldOffsetsValue,
-                                  nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
+    if (!JSObject::defineProperty(cx, descr, cx->names().fieldOffsets,
+                                  userFieldOffsetsValue, nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
     {
         return nullptr;
     }
     RootedValue userFieldTypesValue(cx, ObjectValue(*userFieldTypes));
-    if (!JSObject::defineProperty(cx, descr, cx->names().fieldTypes, userFieldTypesValue,
-                                  nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
+    if (!JSObject::defineProperty(cx, descr, cx->names().fieldTypes,
+                                  userFieldTypesValue, nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
     {
         return nullptr;
     }
 
     if (!CreateUserSizeAndAlignmentProperties(cx, descr))
         return nullptr;
 
     Rooted<TypedProto*> prototypeObj(cx);
@@ -1169,17 +1177,23 @@ DefineSimpleTypeDescr(JSContext *cx,
     Rooted<TypedProto*> proto(cx);
     proto = NewObjectWithProto<TypedProto>(cx, objProto, nullptr, TenuredObject);
     if (!proto)
         return false;
     proto->initTypeDescrSlot(*descr);
     descr->initReservedSlot(JS_DESCR_SLOT_TYPROTO, ObjectValue(*proto));
 
     RootedValue descrValue(cx, ObjectValue(*descr));
-    return JSObject::defineProperty(cx, module, className, descrValue, nullptr, nullptr, 0);
+    if (!JSObject::defineProperty(cx, module, className,
+                                  descrValue, nullptr, nullptr, 0))
+    {
+        return false;
+    }
+
+    return true;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
 template<typename T>
 static JSObject *
 DefineMetaTypeDescr(JSContext *cx,
                     Handle<GlobalObject*> global,
@@ -1209,21 +1223,21 @@ DefineMetaTypeDescr(JSContext *cx,
         return nullptr;
     RootedObject protoProto(cx);
     protoProto = NewObjectWithProto<JSObject>(cx, objProto,
                                               global, SingletonObject);
     if (!protoProto)
         return nullptr;
 
     RootedValue protoProtoValue(cx, ObjectValue(*protoProto));
-    if (!JSObject::defineProperty(cx, proto, cx->names().prototype, protoProtoValue,
-                                  nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
-    {
+    if (!JSObject::defineProperty(cx, proto, cx->names().prototype,
+                                  protoProtoValue,
+                                  nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
-    }
 
     // Create ctor itself
 
     const int constructorLength = 2;
     RootedFunction ctor(cx);
     ctor = global->createConstructor(cx, T::construct, className, constructorLength);
     if (!ctor ||
         !LinkConstructorAndPrototype(cx, ctor, proto) ||
@@ -1283,42 +1297,44 @@ GlobalObject::initTypedObjectModule(JSCo
 
     RootedObject arrayType(cx);
     arrayType = DefineMetaTypeDescr<ArrayMetaTypeDescr>(
         cx, global, module, TypedObjectModuleObject::ArrayTypePrototype);
     if (!arrayType)
         return false;
 
     RootedValue arrayTypeValue(cx, ObjectValue(*arrayType));
-    if (!JSObject::defineProperty(cx, module, cx->names().ArrayType, arrayTypeValue,
-                                  nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
-    {
+    if (!JSObject::defineProperty(cx, module, cx->names().ArrayType,
+                                  arrayTypeValue,
+                                  nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
         return false;
-    }
 
     // StructType.
 
     RootedObject structType(cx);
     structType = DefineMetaTypeDescr<StructMetaTypeDescr>(
         cx, global, module, TypedObjectModuleObject::StructTypePrototype);
     if (!structType)
         return false;
 
     RootedValue structTypeValue(cx, ObjectValue(*structType));
-    if (!JSObject::defineProperty(cx, module, cx->names().StructType, structTypeValue,
-                                  nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT))
-    {
+    if (!JSObject::defineProperty(cx, module, cx->names().StructType,
+                                  structTypeValue,
+                                  nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
         return false;
-    }
 
     // Everything is setup, install module on the global object:
     RootedValue moduleValue(cx, ObjectValue(*module));
     global->setConstructor(JSProto_TypedObject, moduleValue);
-    if (!JSObject::defineProperty(cx, global, cx->names().TypedObject, moduleValue,
-                                  nullptr, nullptr, 0))
+    if (!JSObject::defineProperty(cx, global, cx->names().TypedObject,
+                                  moduleValue,
+                                  nullptr, nullptr,
+                                  0))
     {
         return false;
     }
 
     return module;
 }
 
 JSObject *
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1247,17 +1247,18 @@ JS_ResolveStandardClass(JSContext *cx, H
 
     RootedString idstr(cx, JSID_TO_STRING(id));
 
     /* Check whether we're resolving 'undefined', and define it if so. */
     JSAtom *undefinedAtom = cx->names().undefined;
     if (idstr == undefinedAtom) {
         *resolved = true;
         return JSObject::defineProperty(cx, obj, undefinedAtom->asPropertyName(),
-                                        UndefinedHandleValue, nullptr, nullptr,
+                                        UndefinedHandleValue,
+                                        JS_PropertyStub, JS_StrictPropertyStub,
                                         JSPROP_PERMANENT | JSPROP_READONLY);
     }
 
     /* Try for class constructors/prototypes named by well-known atoms. */
     stdnm = LookupStdName(rt, idstr, standard_class_names);
 
     /* Try less frequently used top-level functions and constants. */
     if (!stdnm)
@@ -2846,29 +2847,16 @@ DefinePropertyById(JSContext *cx, Handle
     assertSameCompartment(cx, obj, id, value,
                           (attrs & JSPROP_GETTER)
                           ? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
                           : nullptr,
                           (attrs & JSPROP_SETTER)
                           ? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
                           : nullptr);
 
-    // In most places throughout the engine, a property with null getter and
-    // not JSPROP_GETTER/SETTER/SHARED has no getter, and the same for setters:
-    // it's just a plain old data property. However the JS_Define* APIs use
-    // null getter and setter to mean "default to the Class getProperty and
-    // setProperty ops".
-    if (!getter)
-        getter = obj->getClass()->getProperty;
-    if (!setter)
-        setter = obj->getClass()->setProperty;
-    if (getter == JS_PropertyStub)
-        getter = nullptr;
-    if (setter == JS_StrictPropertyStub)
-        setter = nullptr;
     return JSObject::defineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 JS_PUBLIC_API(bool)
 JS_DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                       unsigned attrs, Native getter, Native setter)
 {
     return DefinePropertyById(cx, obj, id, value,
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -458,29 +458,18 @@ array_length_getter(JSContext *cx, Handl
     } while (obj);
     return true;
 }
 
 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,
-                                        getter, setter, JSPROP_ENUMERATE);
+                                        nullptr, nullptr, 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);
 }
 
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -155,18 +155,21 @@ js_InitBooleanClass(JSContext *cx, Handl
     Handle<PropertyName*> valueOfName = cx->names().valueOf;
     RootedFunction
         valueOf(cx, NewFunction(cx, NullPtr(), bool_valueOf, 0, JSFunction::NATIVE_FUN,
                                 global, valueOfName));
     if (!valueOf)
         return nullptr;
 
     RootedValue value(cx, ObjectValue(*valueOf));
-    if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value, nullptr, nullptr, 0))
+    if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value,
+                                  JS_PropertyStub, JS_StrictPropertyStub, 0))
+    {
         return nullptr;
+    }
 
     if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Boolean, ctor, booleanProto))
         return nullptr;
 
     return booleanProto;
 }
 
 JSString *
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -502,18 +502,21 @@ ErrorObject::createProto(JSContext *cx, 
     JSExnType type = ExnTypeFromProtoKey(key);
     if (!ErrorObject::init(cx, err, type, nullptr, emptyStr, emptyStr, 0, 0, emptyStr))
         return nullptr;
 
     // The various prototypes also have .name in addition to the normal error
     // instance properties.
     RootedPropertyName name(cx, ClassName(key, cx));
     RootedValue nameValue(cx, StringValue(name));
-    if (!JSObject::defineProperty(cx, err, cx->names().name, nameValue, nullptr, nullptr, 0))
+    if (!JSObject::defineProperty(cx, err, cx->names().name, nameValue,
+                                  JS_PropertyStub, JS_StrictPropertyStub, 0))
+    {
         return nullptr;
+    }
 
     return errorProto;
 }
 
 /* static */ JSObject *
 ErrorObject::createConstructor(JSContext *cx, JSProtoKey key)
 {
     RootedObject ctor(cx);
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -414,30 +414,31 @@ ResolveInterpretedFunctionPrototype(JSCo
 
     RootedObject proto(cx, NewObjectWithGivenProto(cx, clasp, objProto, nullptr, SingletonObject));
     if (!proto)
         return nullptr;
 
     // Per ES5 15.3.5.2 a user-defined function's .prototype property is
     // initially non-configurable, non-enumerable, and writable.
     RootedValue protoVal(cx, ObjectValue(*proto));
-    if (!JSObject::defineProperty(cx, obj, cx->names().prototype, protoVal, nullptr, nullptr,
+    if (!JSObject::defineProperty(cx, obj, cx->names().prototype,
+                                  protoVal, JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT))
     {
         return nullptr;
     }
 
     // Per ES5 13.2 the prototype's .constructor property is configurable,
     // non-enumerable, and writable.  However, per the 15 July 2013 ES6 draft,
     // section 15.19.3, the .prototype of a generator function does not link
     // back with a .constructor.
     if (!isStarGenerator) {
         RootedValue objVal(cx, ObjectValue(*obj));
-        if (!JSObject::defineProperty(cx, proto, cx->names().constructor, objVal, nullptr, nullptr,
-                                      0))
+        if (!JSObject::defineProperty(cx, proto, cx->names().constructor,
+                                      objVal, JS_PropertyStub, JS_StrictPropertyStub, 0))
         {
             return nullptr;
         }
     }
 
     return proto;
 }
 
@@ -2114,25 +2115,21 @@ js::DefineFunction(JSContext *cx, Handle
     if (flags & JSFUN_STUB_GSOPS) {
         /*
          * JSFUN_STUB_GSOPS is a request flag only, not stored in fun->flags or
          * the defined property's attributes. This allows us to encode another,
          * internal flag using the same bit, JSFUN_EXPR_CLOSURE -- see jsfun.h
          * for more on this.
          */
         flags &= ~JSFUN_STUB_GSOPS;
+        gop = JS_PropertyStub;
+        sop = JS_StrictPropertyStub;
+    } else {
         gop = nullptr;
         sop = nullptr;
-    } else {
-        gop = obj->getClass()->getProperty;
-        sop = obj->getClass()->setProperty;
-        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/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -138,18 +138,19 @@ FinishObjectClassInit(JSContext *cx, JS:
         intrinsicsHolder = NewObjectWithGivenProto(cx, &JSObject::class_, proto, self,
                                                    TenuredObject);
         if (!intrinsicsHolder)
             return false;
     }
     self->setIntrinsicsHolder(intrinsicsHolder);
     /* Define a property 'global' with the current global as its value. */
     RootedValue global(cx, ObjectValue(*self));
-    if (!JSObject::defineProperty(cx, intrinsicsHolder, cx->names().global, global,
-                                  nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
+    if (!JSObject::defineProperty(cx, intrinsicsHolder, cx->names().global,
+                                  global, JS_PropertyStub, JS_StrictPropertyStub,
+                                  JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return false;
     }
 
     /*
      * Define self-hosted functions after setting the intrinsics holder
      * (which is needed to define self-hosted functions)
      */
@@ -2553,17 +2554,18 @@ DefineStandardSlot(JSContext *cx, Handle
             if (!NativeObject::addProperty(cx, global, id, nullptr, nullptr, slot, attrs, 0))
                 return false;
 
             named = true;
             return true;
         }
     }
 
-    named = JSObject::defineGeneric(cx, obj, id, v, nullptr, nullptr, attrs);
+    named = JSObject::defineGeneric(cx, obj, id,
+                                    v, JS_PropertyStub, JS_StrictPropertyStub, attrs);
     return named;
 }
 
 static void
 SetClassObject(JSObject *obj, JSProtoKey key, JSObject *cobj, JSObject *proto)
 {
     MOZ_ASSERT(!obj->getParent());
     if (!obj->is<GlobalObject>())
@@ -3015,26 +3017,32 @@ JSObject::constructHook() const
     return nullptr;
 }
 
 /* static */ bool
 JSObject::defineGeneric(ExclusiveContext *cx, HandleObject obj,
                         HandleId id, HandleValue value,
                         JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
     MOZ_ASSERT(!(attrs & JSPROP_PROPOP_ACCESSORS));
-
     js::DefineGenericOp op = obj->getOps()->defineGeneric;
     if (op) {
         if (!cx->shouldBeJSContext())
             return false;
         return op(cx->asJSContext(), obj, id, value, getter, setter, attrs);
     }
+
+    if (getter == nullptr)
+        getter = obj->getClass()->getProperty;
+    if (setter == nullptr)
+        setter = obj->getClass()->setProperty;
+    if (getter == JS_PropertyStub)
+        getter = nullptr;
+    if (setter == JS_StrictPropertyStub)
+        setter = nullptr;
     return baseops::DefineGeneric(cx, obj.as<NativeObject>(), id, value, getter, setter, attrs);
 }
 
 /* static */ bool
 JSObject::defineProperty(ExclusiveContext *cx, HandleObject obj,
                          PropertyName *name, HandleValue value,
                          JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
@@ -3042,25 +3050,31 @@ JSObject::defineProperty(ExclusiveContex
     return defineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 /* static */ bool
 JSObject::defineElement(ExclusiveContext *cx, HandleObject obj,
                         uint32_t index, HandleValue value,
                         JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
-
     js::DefineElementOp op = obj->getOps()->defineElement;
     if (op) {
         if (!cx->shouldBeJSContext())
             return false;
         return op(cx->asJSContext(), obj, index, value, getter, setter, attrs);
     }
+
+    if (!getter)
+        getter = obj->getClass()->getProperty;
+    if (!setter)
+        setter = obj->getClass()->setProperty;
+    if (getter == JS_PropertyStub)
+        getter = nullptr;
+    if (setter == JS_StrictPropertyStub)
+        setter = nullptr;
     return baseops::DefineElement(cx, obj.as<NativeObject>(), index, value, getter, setter, attrs);
 }
 
 /* static */ bool
 JSObject::lookupGeneric(JSContext *cx, HandleObject obj, js::HandleId id,
                         MutableHandleObject objp, MutableHandleShape propp)
 {
     /* NB: The logic of lookupGeneric is implicitly reflected in
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -595,30 +595,30 @@ class JSObject : public js::gc::Cell
         return lookupGeneric(cx, obj, id, objp, propp);
     }
 
     static inline bool lookupElement(JSContext *cx, js::HandleObject obj, uint32_t index,
                                      js::MutableHandleObject objp, js::MutableHandleShape propp);
 
     static bool defineGeneric(js::ExclusiveContext *cx, js::HandleObject obj,
                               js::HandleId id, js::HandleValue value,
-                              JSPropertyOp getter = nullptr,
-                              JSStrictPropertyOp setter = nullptr,
+                              JSPropertyOp getter = JS_PropertyStub,
+                              JSStrictPropertyOp setter = JS_StrictPropertyStub,
                               unsigned attrs = JSPROP_ENUMERATE);
 
     static bool defineProperty(js::ExclusiveContext *cx, js::HandleObject obj,
                                js::PropertyName *name, js::HandleValue value,
-                               JSPropertyOp getter = nullptr,
-                               JSStrictPropertyOp setter = nullptr,
+                               JSPropertyOp getter = JS_PropertyStub,
+                               JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                unsigned attrs = JSPROP_ENUMERATE);
 
     static bool defineElement(js::ExclusiveContext *cx, js::HandleObject obj,
                               uint32_t index, js::HandleValue value,
-                              JSPropertyOp getter = nullptr,
-                              JSStrictPropertyOp setter = nullptr,
+                              JSPropertyOp getter = JS_PropertyStub,
+                              JSStrictPropertyOp setter = JS_StrictPropertyStub,
                               unsigned attrs = JSPROP_ENUMERATE);
 
     static inline bool getGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                                   js::HandleId id, js::MutableHandleValue vp);
 
     static inline bool getGenericNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
                                       jsid id, js::Value *vp);
 
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -382,18 +382,22 @@ str_enumerate(JSContext *cx, HandleObjec
 {
     RootedString str(cx, obj->as<StringObject>().unbox());
     RootedValue value(cx);
     for (size_t i = 0, length = str->length(); i < length; i++) {
         JSString *str1 = NewDependentString(cx, str, i, 1);
         if (!str1)
             return false;
         value.setString(str1);
-        if (!JSObject::defineElement(cx, obj, i, value, nullptr, nullptr, STRING_ELEMENT_ATTRS))
+        if (!JSObject::defineElement(cx, obj, i, value,
+                                     JS_PropertyStub, JS_StrictPropertyStub,
+                                     STRING_ELEMENT_ATTRS))
+        {
             return false;
+        }
     }
 
     return true;
 }
 
 bool
 js::str_resolve(JSContext *cx, HandleObject obj, HandleId id, bool *resolvedp)
 {
--- a/js/src/proxy/BaseProxyHandler.cpp
+++ b/js/src/proxy/BaseProxyHandler.cpp
@@ -126,27 +126,17 @@ BaseProxyHandler::set(JSContext *cx, Han
         if (!HasOwnProperty(cx, receiver, id, &existingDescriptor))
             return false;
 
         // Steps 5.e-f.
         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();
-        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);
+        return JSObject::defineGeneric(cx, receiver, id, vp, nullptr, nullptr, attrs);
     }
 
     // Step 6.
     MOZ_ASSERT(ownDesc.isAccessorDescriptor());
     RootedObject setter(cx);
     if (ownDesc.hasSetterObject())
         setter = ownDesc.setterObject();
     if (!setter)
@@ -157,39 +147,66 @@ BaseProxyHandler::set(JSContext *cx, Han
 
 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()) {
+    if (descIsOwn) {
+        MOZ_ASSERT(desc.object());
+
         // 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 (desc.isReadonly())
+            return strict ? Throw(cx, id, JSMSG_READ_ONLY) : true;
+        if (!desc.setter()) {
+            // Be wary of the odd explicit undefined setter case possible through
+            // Object.defineProperty.
+            if (!desc.hasSetterObject())
+                desc.setSetter(JS_StrictPropertyStub);
+        } else if (desc.hasSetterObject() || desc.setter() != JS_StrictPropertyStub) {
             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;
         }
+        if (!desc.getter()) {
+            // Same as above for the null setter case.
+            if (!desc.hasGetterObject())
+                desc.setGetter(JS_PropertyStub);
+        }
         desc.value().set(vp.get());
-
-        if (descIsOwn)
-            return handler->defineProperty(cx, receiver, id, desc);
+        return handler->defineProperty(cx, receiver, id, desc);
+    }
+    if (desc.object()) {
+        // Check for read-only properties.
+        if (desc.isReadonly())
+            return strict ? Throw(cx, id, JSMSG_CANT_REDEFINE_PROP) : true;
+        if (!desc.setter()) {
+            // Be wary of the odd explicit undefined setter case possible through
+            // Object.defineProperty.
+            if (!desc.hasSetterObject())
+                desc.setSetter(JS_StrictPropertyStub);
+        } else if (desc.hasSetterObject() || desc.setter() != JS_StrictPropertyStub) {
+            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;
+        }
+        if (!desc.getter()) {
+            // Same as above for the null setter case.
+            if (!desc.hasGetterObject())
+                desc.setGetter(JS_PropertyStub);
+        }
+        desc.value().set(vp.get());
         return JSObject::defineGeneric(cx, receiver, id, desc.value(),
                                        desc.getter(), desc.setter(), desc.attributes());
     }
     desc.object().set(receiver);
     desc.value().set(vp.get());
     desc.setAttributes(JSPROP_ENUMERATE);
     desc.setGetter(nullptr);
     desc.setSetter(nullptr); // Pick up the class getter/setter.
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -347,24 +347,17 @@ Proxy::set(JSContext *cx, HandleObject p
     }
 
     // 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();
-    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);
+    return JSObject::defineGeneric(cx, receiver, id, vp, nullptr, nullptr, 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/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -448,17 +448,17 @@ class ByJSType {
 
         RootedValue stringsReport(cx);
         if (!strings.report(census, &stringsReport) ||
             !JSObject::defineProperty(cx, obj, cx->names().strings, stringsReport))
             return false;
 
         RootedValue otherReport(cx);
         if (!other.report(census, &otherReport) ||
-            !JSObject::defineProperty(cx, obj, cx->names().other, otherReport))
+            !JSObject::defineProperty(cx, obj, cx->names().other,   otherReport))
             return false;
 
         report.setObject(*obj);
         return true;
     }
 };
 
 // An assorter that categorizes nodes that are JSObjects by their class, and
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -274,17 +274,17 @@ GlobalObject::valueIsEval(Value val)
     return eval.isObject() && eval == val;
 }
 
 /* static */ bool
 GlobalObject::initStandardClasses(JSContext *cx, Handle<GlobalObject*> global)
 {
     /* Define a top-level property 'undefined' with the undefined value. */
     if (!JSObject::defineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
-                                  nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
+                                  JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return false;
     }
 
     for (size_t k = 0; k < JSProto_LIMIT; ++k) {
         if (!ensureConstructor(cx, global, static_cast<JSProtoKey>(k)))
             return false;
     }
@@ -321,17 +321,18 @@ InitBareBuiltinCtor(JSContext *cx, Handl
  * or functions.
  */
 /* static */ bool
 GlobalObject::initSelfHostingBuiltins(JSContext *cx, Handle<GlobalObject*> global,
                                       const JSFunctionSpec *builtins)
 {
     // Define a top-level property 'undefined' with the undefined value.
     if (!JSObject::defineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
-                                  nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
+                                  JS_PropertyStub, JS_StrictPropertyStub,
+                                  JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return false;
     }
 
     // Define a top-level property 'std_iterator' with the name of the method
     // used by for-of loops to create an iterator.
     RootedValue std_iterator(cx);
 #ifdef JS_HAS_SYMBOLS
@@ -429,20 +430,21 @@ GlobalObject::createBlankPrototypeInheri
 bool
 js::LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor_, JSObject *proto_)
 {
     RootedObject ctor(cx, ctor_), proto(cx, proto_);
 
     RootedValue protoVal(cx, ObjectValue(*proto));
     RootedValue ctorVal(cx, ObjectValue(*ctor));
 
-    return JSObject::defineProperty(cx, ctor, cx->names().prototype, protoVal,
-                                    nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY) &&
-           JSObject::defineProperty(cx, proto, cx->names().constructor, ctorVal,
-                                    nullptr, nullptr, 0);
+    return JSObject::defineProperty(cx, ctor, cx->names().prototype,
+                                    protoVal, JS_PropertyStub, JS_StrictPropertyStub,
+                                    JSPROP_PERMANENT | JSPROP_READONLY) &&
+           JSObject::defineProperty(cx, proto, cx->names().constructor,
+                                    ctorVal, JS_PropertyStub, JS_StrictPropertyStub, 0);
 }
 
 bool
 js::DefinePropertiesAndFunctions(JSContext *cx, HandleObject obj,
                                  const JSPropertySpec *ps, const JSFunctionSpec *fs)
 {
     if (ps && !JS_DefineProperties(cx, obj, ps))
         return false;
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -337,19 +337,18 @@ DefVarOrConstOperation(JSContext *cx, Ha
 
     RootedShape prop(cx);
     RootedObject obj2(cx);
     if (!JSObject::lookupProperty(cx, varobj, dn, &obj2, &prop))
         return false;
 
     /* Steps 8c, 8d. */
     if (!prop || (obj2 != varobj && varobj->is<GlobalObject>())) {
-        if (!JSObject::defineProperty(cx, varobj, dn, UndefinedHandleValue, nullptr, nullptr,
-                                      attrs))
-        {
+        if (!JSObject::defineProperty(cx, varobj, dn, UndefinedHandleValue, JS_PropertyStub,
+                                      JS_StrictPropertyStub, attrs)) {
             return false;
         }
     } else if (attrs & JSPROP_READONLY) {
         /*
          * Extension: ordinarily we'd be done here -- but for |const|.  If we
          * see a redeclaration that's |const|, we consider it a conflict.
          */
         unsigned oldAttrs;
@@ -549,18 +548,16 @@ 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 == 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
@@ -3680,24 +3680,28 @@ js::DefFunOperation(JSContext *cx, Handl
      * ECMA requires functions defined when entering Eval code to be
      * impermanent.
      */
     unsigned attrs = script->isActiveEval()
                      ? JSPROP_ENUMERATE
                      : JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
     /* Steps 5d, 5f. */
-    if (!shape || pobj != parent)
-        return JSObject::defineProperty(cx, parent, name, rval, nullptr, nullptr, attrs);
+    if (!shape || pobj != parent) {
+        return JSObject::defineProperty(cx, parent, name, rval, JS_PropertyStub,
+                                        JS_StrictPropertyStub, attrs);
+    }
 
     /* Step 5e. */
     MOZ_ASSERT(parent->isNative());
     if (parent->is<GlobalObject>()) {
-        if (shape->configurable())
-            return JSObject::defineProperty(cx, parent, name, rval, nullptr, nullptr, attrs);
+        if (shape->configurable()) {
+            return JSObject::defineProperty(cx, parent, name, rval, JS_PropertyStub,
+                                            JS_StrictPropertyStub, attrs);
+        }
 
         if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
             JSAutoByteString bytes;
             if (AtomToPrintableString(cx, name, &bytes)) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REDEFINE_PROP,
                                      bytes.ptr());
             }
 
@@ -3936,21 +3940,21 @@ js::InitGetterSetterOperation(JSContext 
     PropertyOp getter;
     StrictPropertyOp setter;
     unsigned attrs = JSPROP_ENUMERATE | JSPROP_SHARED;
 
     JSOp op = JSOp(*pc);
 
     if (op == JSOP_INITPROP_GETTER || op == JSOP_INITELEM_GETTER) {
         getter = CastAsPropertyOp(val);
-        setter = nullptr;
+        setter = JS_StrictPropertyStub;
         attrs |= JSPROP_GETTER;
     } else {
         MOZ_ASSERT(op == JSOP_INITPROP_SETTER || op == JSOP_INITELEM_SETTER);
-        getter = nullptr;
+        getter = JS_PropertyStub;
         setter = CastAsStrictPropertyOp(val);
         attrs |= JSPROP_SETTER;
     }
 
     RootedValue scratch(cx);
     return JSObject::defineGeneric(cx, obj, id, scratch, getter, setter, attrs);
 }
 
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -391,17 +391,18 @@ InitGetterSetterOperation(JSContext *cx,
 
 bool
 SpreadCallOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue thisv,
                     HandleValue callee, HandleValue arr, MutableHandleValue res);
 
 inline bool
 SetConstOperation(JSContext *cx, HandleObject varobj, HandlePropertyName name, HandleValue rval)
 {
-    return JSObject::defineProperty(cx, varobj, name, rval, nullptr, nullptr,
+    return JSObject::defineProperty(cx, varobj, name, rval,
+                                    JS_PropertyStub, JS_StrictPropertyStub,
                                     JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
 void
 ReportUninitializedLexical(JSContext *cx, HandlePropertyName name);
 
 void
 ReportUninitializedLexical(JSContext *cx, HandleScript script, jsbytecode *pc);
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1983,29 +1983,29 @@ SetPropertyByDefining(typename Execution
             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.
+    if (!receiver->is<NativeObject>()) {
+        if (mode == ParallelExecution)
+            return false;
+        return JSObject::defineGeneric(cxArg->asJSContext(), receiver, id, v,
+                                       clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE);
+    }
+    Rooted<NativeObject*> nativeReceiver(cxArg, &receiver->as<NativeObject>());
     JSPropertyOp getter = clasp->getProperty;
     if (getter == JS_PropertyStub)
         getter = nullptr;
     JSStrictPropertyOp setter = clasp->setProperty;
     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,
                                          JSPROP_ENUMERATE, v, true, strict);
 }
 
 /*
  * Implement "the rest of" assignment to a property when no property receiver[id]
  * was found anywhere on the prototype chain.
  *
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -212,17 +212,17 @@ intrinsic_MakeConstructible(JSContext *c
     MOZ_ASSERT(args[0].isObject());
     MOZ_ASSERT(args[0].toObject().is<JSFunction>());
     MOZ_ASSERT(args[1].isObject());
 
     // Normal .prototype properties aren't enumerable.  But for this to clone
     // correctly, it must be enumerable.
     RootedObject ctor(cx, &args[0].toObject());
     if (!JSObject::defineProperty(cx, ctor, cx->names().prototype, args[1],
-                                  nullptr, nullptr,
+                                  JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT))
     {
         return false;
     }
 
     ctor->as<JSFunction>().setIsSelfHostedConstructor();
     args.rval().setUndefined();
     return true;
--- a/js/src/vm/SharedTypedArrayObject.cpp
+++ b/js/src/vm/SharedTypedArrayObject.cpp
@@ -743,20 +743,24 @@ IMPL_SHARED_TYPED_ARRAY_COMBINED_UNWRAPP
 template<typename NativeType>
 bool
 SharedTypedArrayObjectTemplate<NativeType>::FinishClassInit(JSContext *cx,
                                                             HandleObject ctor,
                                                             HandleObject proto)
 {
     RootedValue bytesValue(cx, Int32Value(BYTES_PER_ELEMENT));
 
-    if (!JSObject::defineProperty(cx, ctor, cx->names().BYTES_PER_ELEMENT, bytesValue,
-                                  nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY) ||
-        !JSObject::defineProperty(cx, proto, cx->names().BYTES_PER_ELEMENT, bytesValue,
-                                  nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
+    if (!JSObject::defineProperty(cx, ctor,
+                                  cx->names().BYTES_PER_ELEMENT, bytesValue,
+                                  JS_PropertyStub, JS_StrictPropertyStub,
+                                  JSPROP_PERMANENT | JSPROP_READONLY) ||
+        !JSObject::defineProperty(cx, proto,
+                                  cx->names().BYTES_PER_ELEMENT, bytesValue,
+                                  JS_PropertyStub, JS_StrictPropertyStub,
+                                  JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return false;
     }
 
     return true;
 };
 
 IMPL_SHARED_TYPED_ARRAY_STATICS(Int8Array)
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -237,20 +237,24 @@ class TypedArrayObjectTemplate : public 
         return NewFunction(cx, ctorObj, class_constructor, 3, JSFunction::NATIVE_CTOR, global,
                            ClassName(key, cx), JSFunction::FinalizeKind);
     }
 
     static bool
     finishClassInit(JSContext *cx, HandleObject ctor, HandleObject proto)
     {
         RootedValue bytesValue(cx, Int32Value(BYTES_PER_ELEMENT));
-        if (!JSObject::defineProperty(cx, ctor, cx->names().BYTES_PER_ELEMENT, bytesValue,
-                                      nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY) ||
-            !JSObject::defineProperty(cx, proto, cx->names().BYTES_PER_ELEMENT, bytesValue,
-                                      nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
+        if (!JSObject::defineProperty(cx, ctor,
+                                      cx->names().BYTES_PER_ELEMENT, bytesValue,
+                                      JS_PropertyStub, JS_StrictPropertyStub,
+                                      JSPROP_PERMANENT | JSPROP_READONLY) ||
+            !JSObject::defineProperty(cx, proto,
+                                      cx->names().BYTES_PER_ELEMENT, bytesValue,
+                                      JS_PropertyStub, JS_StrictPropertyStub,
+                                      JSPROP_PERMANENT | JSPROP_READONLY))
         {
             return false;
         }
 
         RootedFunction fun(cx);
         fun = NewFunction(cx, NullPtr(), ArrayBufferObject::createTypedArrayFromBuffer<NativeType>,
                           0, JSFunction::NATIVE_FUN, cx->global(), NullPtr());
         if (!fun)