Bug 1153592 part 2 - Remove JSPROP_SHARED; ensure accessor props don't have slots. r=evilpie
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 26 Sep 2017 12:26:50 +0200
changeset 382981 57132aac9262cbe6077160cad75bc590fd60e92c
parent 382980 b4724648181dec232d4308f283df5db7e683afda
child 382982 eaf3b1eff03ce94c85d2066e1a517558bde2ac8c
push id32581
push userkwierso@gmail.com
push dateTue, 26 Sep 2017 22:55:05 +0000
treeherdermozilla-central@b7d8ae4a03c6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersevilpie
bugs1153592
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1153592 part 2 - Remove JSPROP_SHARED; ensure accessor props don't have slots. r=evilpie
dom/bindings/Codegen.py
dom/console/Console.cpp
dom/xbl/nsXBLProtoImplField.h
dom/xbl/nsXBLProtoImplProperty.cpp
js/src/ctypes/CTypes.cpp
js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
js/src/jsapi-tests/testDefineProperty.cpp
js/src/jsapi-tests/testDefinePropertyIgnoredAttributes.cpp
js/src/jsapi-tests/testSetProperty.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsgc.cpp
js/src/jsobj.cpp
js/src/shell/js.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/Debugger.cpp
js/src/vm/Interpreter.cpp
js/src/vm/NativeObject.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/Shape.cpp
js/src/vm/Shape.h
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2727,18 +2727,17 @@ class AttrDefiner(PropertyDefiner):
                 assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
 
     def generateArray(self, array, name):
         if len(array) == 0:
             return ""
 
         def flags(attr):
             unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else ""
-            enumerable = " | %s" % EnumerabilityFlags(attr)
-            return ("JSPROP_SHARED" + enumerable + unforgeable)
+            return EnumerabilityFlags(attr) + unforgeable
 
         def getter(attr):
             if self.static:
                 if attr.type.isPromise():
                     raise TypeError("Don't know how to handle "
                                     "static Promise-returning "
                                     "attribute %s.%s" %
                                     (self.descriptor.name,
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -1655,17 +1655,17 @@ Console::PopulateConsoleNotificationInTh
 
       js::SetFunctionNativeReserved(funObj, SLOT_STACKOBJ, stackVal);
       js::SetFunctionNativeReserved(funObj, SLOT_RAW_STACK,
                                     JS::PrivateValue(aData->mStack.get()));
 
       if (NS_WARN_IF(!JS_DefineProperty(aCx, eventObj, "stacktrace",
                                         JS_DATA_TO_FUNC_PTR(JSNative, funObj.get()),
                                         nullptr,
-                                        JSPROP_ENUMERATE | JSPROP_SHARED |
+                                        JSPROP_ENUMERATE |
                                         JSPROP_GETTER | JSPROP_SETTER))) {
         return false;
       }
     }
   }
 
   return true;
 }
--- a/dom/xbl/nsXBLProtoImplField.h
+++ b/dom/xbl/nsXBLProtoImplField.h
@@ -40,17 +40,17 @@ public:
                             JS::Handle<JSObject*> aTargetClassObject);
 
   nsresult Read(nsIObjectInputStream* aStream);
   nsresult Write(nsIObjectOutputStream* aStream);
 
   const char16_t* GetName() const { return mName; }
 
   unsigned AccessorAttributes() const {
-    return JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER |
+    return JSPROP_GETTER | JSPROP_SETTER |
            (mJSAttributes & (JSPROP_ENUMERATE | JSPROP_PERMANENT));
   }
 
   bool IsEmpty() const { return mFieldTextLength == 0; }
 
 protected:
   nsXBLProtoImplField* mNext;
   char16_t* mName;
--- a/dom/xbl/nsXBLProtoImplProperty.cpp
+++ b/dom/xbl/nsXBLProtoImplProperty.cpp
@@ -208,17 +208,17 @@ nsXBLProtoImplProperty::CompileMember(Au
                                       nullptr, getter, getterObject.address());
 
       delete getterText;
       deletedGetter = true;
 
       mGetter.SetJSFunction(getterObject);
 
       if (mGetter.GetJSFunction() && NS_SUCCEEDED(rv)) {
-        mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
+        mJSAttributes |= JSPROP_GETTER;
       }
       if (NS_FAILED(rv)) {
         mGetter.SetJSFunction(nullptr);
         mJSAttributes &= ~JSPROP_GETTER;
         /*chaining to return failure*/
       }
     }
   } // if getter is not empty
@@ -254,17 +254,17 @@ nsXBLProtoImplProperty::CompileMember(Au
                                       gPropertyArgs, setter,
                                       setterObject.address());
 
       delete setterText;
       deletedSetter = true;
       mSetter.SetJSFunction(setterObject);
 
       if (mSetter.GetJSFunction() && NS_SUCCEEDED(rv)) {
-        mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
+        mJSAttributes |= JSPROP_SETTER;
       }
       if (NS_FAILED(rv)) {
         mSetter.SetJSFunction(nullptr);
         mJSAttributes &= ~JSPROP_SETTER;
         /*chaining to return failure*/
       }
     }
   } // if setter wasn't empty....
@@ -303,27 +303,27 @@ nsXBLProtoImplProperty::Read(nsIObjectIn
 
   AutoJSContext cx;
   JS::Rooted<JSObject*> getterObject(cx);
   if (aType == XBLBinding_Serialize_GetterProperty ||
       aType == XBLBinding_Serialize_GetterSetterProperty) {
     nsresult rv = XBL_DeserializeFunction(aStream, &getterObject);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
+    mJSAttributes |= JSPROP_GETTER;
   }
   mGetter.SetJSFunction(getterObject);
 
   JS::Rooted<JSObject*> setterObject(cx);
   if (aType == XBLBinding_Serialize_SetterProperty ||
       aType == XBLBinding_Serialize_GetterSetterProperty) {
     nsresult rv = XBL_DeserializeFunction(aStream, &setterObject);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
+    mJSAttributes |= JSPROP_SETTER;
   }
   mSetter.SetJSFunction(setterObject);
 
 #ifdef DEBUG
   mIsCompiled = true;
 #endif
 
   return NS_OK;
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -6115,17 +6115,17 @@ StructType::DefineInternal(JSContext* cx
       SetFunctionNativeReserved(setter, StructType::SLOT_FIELDNAME,
                                 StringValue(JS_FORGET_STRING_FLATNESS(name)));
       RootedObject setterObj(cx, JS_GetFunctionObject(setter));
 
       if (!JS_DefineUCProperty(cx, prototype,
              nameChars.twoByteChars(), name->length(),
              JS_DATA_TO_FUNC_PTR(JSNative, getterObj.get()),
              JS_DATA_TO_FUNC_PTR(JSNative, setterObj.get()),
-             JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER))
+             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER))
       {
         return false;
       }
 
       size_t fieldSize = CType::GetSize(fieldType);
       size_t fieldAlign = CType::GetAlignment(fieldType);
       size_t fieldOffset = Align(structSize, fieldAlign);
       // Check for overflow. Since we hold invariant that fieldSize % fieldAlign
--- a/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
+++ b/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
@@ -31,22 +31,22 @@ BEGIN_TEST(testDefineGetterSetterNonEnum
     CHECK(funSet);
     JS::RootedObject funSetObj(cx, JS_GetFunctionObject(funSet));
     JS::RootedValue vset(cx, JS::ObjectValue(*funSetObj));
 
     JS::RootedObject vObject(cx, vobj.toObjectOrNull());
     CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
                             JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funGetObj),
                             JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funSetObj),
-                            JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED | JSPROP_ENUMERATE));
+                            JSPROP_GETTER | JSPROP_SETTER | JSPROP_ENUMERATE));
 
     CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
                             JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funGetObj),
                             JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funSetObj),
-                            JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED | JSPROP_PERMANENT));
+                            JSPROP_GETTER | JSPROP_SETTER | JSPROP_PERMANENT));
 
     JS::Rooted<JS::PropertyDescriptor> desc(cx);
     CHECK(JS_GetOwnPropertyDescriptor(cx, vObject, PROPERTY_NAME, &desc));
     CHECK(desc.object());
     CHECK(desc.hasGetterObject());
     CHECK(desc.hasSetterObject());
     CHECK(!desc.configurable());
     CHECK(!desc.enumerable());
--- a/js/src/jsapi-tests/testDefineProperty.cpp
+++ b/js/src/jsapi-tests/testDefineProperty.cpp
@@ -12,12 +12,12 @@ BEGIN_TEST(testDefineProperty_bug564344)
     JS::RootedValue x(cx);
     EVAL("function f() {}\n"
          "var x = {p: f};\n"
          "x.p();  // brand x's scope\n"
          "x;", &x);
 
     JS::RootedObject obj(cx, x.toObjectOrNull());
     for (int i = 0; i < 2; i++)
-        CHECK(JS_DefineProperty(cx, obj, "q", JS::UndefinedHandleValue, JSPROP_SHARED));
+        CHECK(JS_DefineProperty(cx, obj, "q", JS::UndefinedHandleValue, 0));
     return true;
 }
 END_TEST(testDefineProperty_bug564344)
--- a/js/src/jsapi-tests/testDefinePropertyIgnoredAttributes.cpp
+++ b/js/src/jsapi-tests/testDefinePropertyIgnoredAttributes.cpp
@@ -42,35 +42,35 @@ BEGIN_TEST(testDefinePropertyIgnoredAttr
     JS::Rooted<JS::PropertyDescriptor> desc(cx);
     JS::RootedValue defineValue(cx);
 
     // Try a getter. Allow it to fill in the defaults. Because we're passing a
     // JSNative, JS_DefineProperty will infer JSPROP_GETTER even though we
     // aren't passing it.
     CHECK(JS_DefineProperty(cx, obj, "foo",
                             Getter, nullptr,
-                            JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_PERMANENT | JSPROP_SHARED));
+                            JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_PERMANENT));
 
     CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "foo", &desc));
 
     // Note that JSPROP_READONLY is meaningless for accessor properties.
     CHECK(CheckDescriptor(desc, AccessorDescriptor, false, true, false));
 
     // Install another configurable property, so we can futz with it.
     CHECK(JS_DefineProperty(cx, obj, "bar",
                             Getter, nullptr,
-                            JSPROP_IGNORE_ENUMERATE | JSPROP_SHARED));
+                            JSPROP_IGNORE_ENUMERATE));
     CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "bar", &desc));
     CHECK(CheckDescriptor(desc, AccessorDescriptor, false, true, true));
 
     // Rewrite the descriptor to now be enumerable, leaving the configurability
     // unchanged.
     CHECK(JS_DefineProperty(cx, obj, "bar",
                             Getter, nullptr,
-                            JSPROP_IGNORE_PERMANENT | JSPROP_ENUMERATE | JSPROP_SHARED));
+                            JSPROP_IGNORE_PERMANENT | JSPROP_ENUMERATE));
     CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "bar", &desc));
     CHECK(CheckDescriptor(desc, AccessorDescriptor, true, true, true));
 
     // Now try the same game with a value property
     defineValue.setObject(*obj);
     CHECK(JS_DefineProperty(cx, obj, "baz", defineValue,
                             JSPROP_IGNORE_ENUMERATE |
                             JSPROP_IGNORE_READONLY |
--- a/js/src/jsapi-tests/testSetProperty.cpp
+++ b/js/src/jsapi-tests/testSetProperty.cpp
@@ -11,17 +11,17 @@ BEGIN_TEST(testSetProperty_NativeGetterS
 {
     JS::RootedObject obj(cx, JS_NewPlainObject(cx));
     CHECK(obj);
 
     CHECK(JS_DefineProperty(cx, global, "globalProp", obj, JSPROP_ENUMERATE));
 
     CHECK(JS_DefineProperty(cx, obj, "prop",
                             JS_PROPERTYOP_GETTER(NativeGet), nullptr,
-                            JSPROP_SHARED | JSPROP_PROPOP_ACCESSORS));
+                            JSPROP_PROPOP_ACCESSORS));
 
     EXEC("'use strict';                                     \n"
          "var error, passed = false;                        \n"
          "try                                               \n"
          "{                                                 \n"
          "  this.globalProp.prop = 42;                      \n"
          "  throw new Error('setting property succeeded!'); \n"
          "}                                                 \n"
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -870,21 +870,16 @@ static const uint8_t JSPROP_PERMANENT = 
 static const uint8_t JSPROP_PROPOP_ACCESSORS = 0x08;
 
 /* property holds getter function */
 static const uint8_t JSPROP_GETTER =           0x10;
 
 /* property holds setter function */
 static const uint8_t JSPROP_SETTER =           0x20;
 
-/* don't allocate a value slot for this property; don't copy the property on set
-   of the same-named property in an object that delegates to a prototype
-   containing this property */
-static const uint8_t JSPROP_SHARED =           0x40;
-
 /* internal JS engine use only */
 static const uint8_t JSPROP_INTERNAL_USE_BIT = 0x80;
 
 /* native that can be called as a ctor */
 static const unsigned JSFUN_CONSTRUCTOR =     0x400;
 
 /* | of all the JSFUN_* flags */
 static const unsigned JSFUN_FLAGS_MASK =      0x400;
@@ -2273,33 +2268,33 @@ inline int CheckIsSetterOp(JSSetterOp op
 
 /*
  * JSPropertySpec uses JSNativeWrapper.  These macros encapsulate the definition
  * of JSNative-backed JSPropertySpecs, by defining the JSNativeWrappers for
  * them.
  */
 #define JS_PSG(name, getter, flags) \
     JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, \
-                        JSPROP_SHARED)
+                        0)
 #define JS_PSGS(name, getter, setter, flags) \
     JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(setter), flags, \
-                         JSPROP_SHARED)
+                        0)
 #define JS_SYM_GET(symbol, getter, flags) \
     JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
-                        JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, JSPROP_SHARED)
+                        JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, 0)
 #define JS_SELF_HOSTED_GET(name, getterName, flags) \
     JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
-                         JSPROP_SHARED | JSPROP_GETTER)
+                        JSPROP_GETTER)
 #define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
     JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), SELFHOSTED_WRAPPER(setterName), \
-                         flags, JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER)
+                         flags, JSPROP_GETTER | JSPROP_SETTER)
 #define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \
     JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
                          SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
-                         JSPROP_SHARED | JSPROP_GETTER)
+                         JSPROP_GETTER)
 #define JS_STRING_PS(name, string, flags) \
     JS_PS_VALUE_SPEC(name, STRINGVALUE_WRAPPER(string), flags)
 #define JS_STRING_SYM_PS(symbol, string, flags) \
     JS_PS_VALUE_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
                      STRINGVALUE_WRAPPER(string), flags)
 #define JS_INT32_PS(name, value, flags) \
     JS_PS_VALUE_SPEC(name, INT32VALUE_WRAPPER(value), flags)
 #define JS_PS_END \
@@ -2859,41 +2854,38 @@ class WrappedPtrOperations<JS::PropertyD
     bool hasSetterObject() const { return has(JSPROP_SETTER); }
     JS::HandleObject setterObject() const {
         MOZ_ASSERT(hasSetterObject());
         return JS::HandleObject::fromMarkedLocation(
                 reinterpret_cast<JSObject* const*>(&desc().setter));
     }
 
     bool hasGetterOrSetter() const { return desc().getter || desc().setter; }
-    bool isShared() const { return has(JSPROP_SHARED); }
 
     JS::HandleObject object() const {
         return JS::HandleObject::fromMarkedLocation(&desc().obj);
     }
     unsigned attributes() const { return desc().attrs; }
     JSGetterOp getter() const { return desc().getter; }
     JSSetterOp setter() const { return desc().setter; }
 
     void assertValid() const {
 #ifdef DEBUG
         MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE | JSPROP_IGNORE_ENUMERATE |
                                      JSPROP_PERMANENT | JSPROP_IGNORE_PERMANENT |
                                      JSPROP_READONLY | JSPROP_IGNORE_READONLY |
                                      JSPROP_IGNORE_VALUE |
                                      JSPROP_GETTER |
                                      JSPROP_SETTER |
-                                     JSPROP_SHARED |
                                      JSPROP_REDEFINE_NONCONFIGURABLE |
                                      JSPROP_RESOLVING |
                                      SHADOWABLE)) == 0);
         MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE));
         MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT));
         if (isAccessorDescriptor()) {
-            MOZ_ASSERT(has(JSPROP_SHARED));
             MOZ_ASSERT(!has(JSPROP_READONLY));
             MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY));
             MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE));
             MOZ_ASSERT(!has(SHADOWABLE));
             MOZ_ASSERT(value().isUndefined());
             MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter());
             MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter());
         } else {
@@ -2912,17 +2904,16 @@ class WrappedPtrOperations<JS::PropertyD
     void assertComplete() const {
 #ifdef DEBUG
         assertValid();
         MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE |
                                      JSPROP_PERMANENT |
                                      JSPROP_READONLY |
                                      JSPROP_GETTER |
                                      JSPROP_SETTER |
-                                     JSPROP_SHARED |
                                      JSPROP_REDEFINE_NONCONFIGURABLE |
                                      JSPROP_RESOLVING |
                                      SHADOWABLE)) == 0);
         MOZ_ASSERT_IF(isAccessorDescriptor(), has(JSPROP_GETTER) && has(JSPROP_SETTER));
 #endif
     }
 
     void assertCompleteIfFound() const {
@@ -3013,22 +3004,22 @@ class MutableWrappedPtrOperations<JS::Pr
         desc().getter = op;
     }
     void setSetter(JSSetterOp op) {
         desc().setter = op;
     }
     void setGetterObject(JSObject* obj) {
         desc().getter = reinterpret_cast<JSGetterOp>(obj);
         desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
-        desc().attrs |= JSPROP_GETTER | JSPROP_SHARED;
+        desc().attrs |= JSPROP_GETTER;
     }
     void setSetterObject(JSObject* obj) {
         desc().setter = reinterpret_cast<JSSetterOp>(obj);
         desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
-        desc().attrs |= JSPROP_SETTER | JSPROP_SHARED;
+        desc().attrs |= JSPROP_SETTER;
     }
 
     JS::MutableHandleObject getterObject() {
         MOZ_ASSERT(this->hasGetterObject());
         return JS::MutableHandleObject::fromMarkedLocation(
                 reinterpret_cast<JSObject**>(&desc().getter));
     }
     JS::MutableHandleObject setterObject() {
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1042,17 +1042,17 @@ AddLengthProperty(JSContext* cx, HandleA
      * as accesses to 'length' will use the elements header.
      */
 
     RootedId lengthId(cx, NameToId(cx->names().length));
     MOZ_ASSERT(!obj->lookup(cx, lengthId));
 
     return NativeObject::addProperty(cx, obj, lengthId, array_length_getter, array_length_setter,
                                      SHAPE_INVALID_SLOT,
-                                     JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_SHADOWABLE,
+                                     JSPROP_PERMANENT | JSPROP_SHADOWABLE,
                                      0, /* allowDictionary = */ false);
 }
 
 static bool
 IsArrayConstructor(const JSObject* obj)
 {
     // This must only return true if v is *the* Array constructor for the
     // current compartment; we rely on the fact that any other Array
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -8652,17 +8652,17 @@ NewMemoryInfoObject(JSContext* cx)
     for (auto pair : getters) {
 #ifdef JS_MORE_DETERMINISTIC
         JSNative getter = DummyGetter;
 #else
         JSNative getter = pair.getter;
 #endif
         if (!JS_DefineProperty(cx, obj, pair.name,
                                getter, nullptr,
-                               JSPROP_ENUMERATE | JSPROP_SHARED))
+                               JSPROP_ENUMERATE))
         {
             return nullptr;
         }
     }
 
     RootedObject zoneObj(cx, JS_NewObject(cx, nullptr));
     if (!zoneObj)
         return nullptr;
@@ -8687,17 +8687,17 @@ NewMemoryInfoObject(JSContext* cx)
     for (auto pair : zoneGetters) {
  #ifdef JS_MORE_DETERMINISTIC
         JSNative getter = DummyGetter;
 #else
         JSNative getter = pair.getter;
 #endif
         if (!JS_DefineProperty(cx, zoneObj, pair.name,
                                getter, nullptr,
-                               JSPROP_ENUMERATE | JSPROP_SHARED))
+                               JSPROP_ENUMERATE))
         {
             return nullptr;
         }
     }
 
     return obj;
 }
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -356,17 +356,17 @@ js::ToPropertyDescriptor(JSContext* cx, 
             if (checkAccessors)
                 JS_TRY_OR_RETURN_FALSE(cx, CheckCallable(cx, &v.toObject(), js_getter_str));
             desc.setGetterObject(&v.toObject());
         } else if (!v.isUndefined()) {
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_GET_SET_FIELD,
                                       js_getter_str);
             return false;
         }
-        attrs |= JSPROP_GETTER | JSPROP_SHARED;
+        attrs |= JSPROP_GETTER;
     }
 
     // step 9
     id = NameToId(cx->names().set);
     if (!GetPropertyIfPresent(cx, obj, id, &v, &found))
         return false;
     hasGetOrSet |= found;
     if (found) {
@@ -374,33 +374,32 @@ js::ToPropertyDescriptor(JSContext* cx, 
             if (checkAccessors)
                 JS_TRY_OR_RETURN_FALSE(cx, CheckCallable(cx, &v.toObject(), js_setter_str));
             desc.setSetterObject(&v.toObject());
         } else if (!v.isUndefined()) {
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_GET_SET_FIELD,
                                       js_setter_str);
             return false;
         }
-        attrs |= JSPROP_SETTER | JSPROP_SHARED;
+        attrs |= JSPROP_SETTER;
     }
 
     // step 10
     if (hasGetOrSet) {
         if (!(attrs & JSPROP_IGNORE_READONLY) || !(attrs & JSPROP_IGNORE_VALUE)) {
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INVALID_DESCRIPTOR);
             return false;
         }
 
         // By convention, these bits are not used on accessor descriptors.
         attrs &= ~(JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE);
     }
 
     desc.setAttributes(attrs);
     MOZ_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
-    MOZ_ASSERT_IF(attrs & (JSPROP_GETTER | JSPROP_SETTER), attrs & JSPROP_SHARED);
     return true;
 }
 
 Result<>
 js::CheckPropertyDescriptorAccessors(JSContext* cx, Handle<PropertyDescriptor> desc)
 {
     if (desc.hasGetterObject())
         MOZ_TRY(CheckCallable(cx, desc.getterObject(), js_getter_str));
@@ -420,17 +419,17 @@ js::CompletePropertyDescriptor(MutableHa
         if (!desc.hasWritable())
             desc.attributesRef() |= JSPROP_READONLY;
         desc.attributesRef() &= ~(JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE);
     } else {
         if (!desc.hasGetterObject())
             desc.setGetterObject(nullptr);
         if (!desc.hasSetterObject())
             desc.setSetterObject(nullptr);
-        desc.attributesRef() |= JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED;
+        desc.attributesRef() |= JSPROP_GETTER | JSPROP_SETTER;
     }
     if (!desc.hasConfigurable())
         desc.attributesRef() |= JSPROP_PERMANENT;
     desc.attributesRef() &= ~(JSPROP_IGNORE_PERMANENT | JSPROP_IGNORE_ENUMERATE);
 
     desc.assertComplete();
 }
 
@@ -3521,17 +3520,16 @@ DumpProperty(const NativeObject* obj, Sh
 {
     jsid id = shape.propid();
     uint8_t attrs = shape.attributes();
 
     out.printf("    ((js::Shape*) %p) ", (void*) &shape);
     if (attrs & JSPROP_ENUMERATE) out.put("enumerate ");
     if (attrs & JSPROP_READONLY) out.put("readonly ");
     if (attrs & JSPROP_PERMANENT) out.put("permanent ");
-    if (attrs & JSPROP_SHARED) out.put("shared ");
 
     if (shape.hasGetterValue())
         out.printf("getterValue=%p ", (void*) shape.getterObject());
     else if (!shape.hasDefaultGetter())
         out.printf("getterOp=%p ", JS_FUNC_TO_DATA_PTR(void*, shape.getterOp()));
 
     if (shape.hasSetterValue())
         out.printf("setterValue=%p ", (void*) shape.setterObject());
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -7268,17 +7268,17 @@ static const JSJitInfo doFoo_methodinfo 
     false,    /* isAlwaysInSlot */
     false,    /* isLazilyCachedInSlot */
     false,    /* isTypedMethod */
     0         /* slotIndex */
 };
 
 static const JSPropertySpec dom_props[] = {
     {"x",
-     JSPROP_SHARED | JSPROP_ENUMERATE,
+     JSPROP_ENUMERATE,
      { {
         { { dom_genericGetter, &dom_x_getterinfo } },
         { { dom_genericSetter, &dom_x_setterinfo } }
      } },
     },
     JS_PS_END
 };
 
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -571,17 +571,17 @@ MappedArgumentsObject::obj_resolve(JSCon
             return true;
 
         if (!DefineArgumentsIterator(cx, argsobj))
             return false;
         *resolvedp = true;
         return true;
     }
 
-    unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE | JSPROP_RESOLVING;
+    unsigned attrs = JSPROP_SHADOWABLE | JSPROP_RESOLVING;
     if (JSID_IS_INT(id)) {
         uint32_t arg = uint32_t(JSID_TO_INT(id));
         if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
             return true;
 
         attrs |= JSPROP_ENUMERATE;
     } else if (JSID_IS_ATOM(id, cx->names().length)) {
         if (argsobj->hasOverriddenLength())
@@ -771,34 +771,34 @@ UnmappedArgumentsObject::obj_resolve(JSC
             return true;
 
         if (!DefineArgumentsIterator(cx, argsobj))
             return false;
         *resolvedp = true;
         return true;
     }
 
-    unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
+    unsigned attrs = JSPROP_SHADOWABLE;
     GetterOp getter = UnmappedArgGetter;
     SetterOp setter = UnmappedArgSetter;
 
     if (JSID_IS_INT(id)) {
         uint32_t arg = uint32_t(JSID_TO_INT(id));
         if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
             return true;
 
         attrs |= JSPROP_ENUMERATE;
     } else if (JSID_IS_ATOM(id, cx->names().length)) {
         if (argsobj->hasOverriddenLength())
             return true;
     } else {
         if (!JSID_IS_ATOM(id, cx->names().callee))
             return true;
 
-        attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED;
+        attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER;
         getter = CastAsGetterOp(argsobj->global().getThrowTypeError());
         setter = CastAsSetterOp(argsobj->global().getThrowTypeError());
     }
 
     attrs |= JSPROP_RESOLVING;
     if (!NativeDefineAccessorProperty(cx, argsobj, id, getter, setter, attrs))
         return false;
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -8479,17 +8479,17 @@ DebuggerArguments::create(JSContext* cx,
         getobj = NewNativeFunction(cx, DebuggerArguments_getArg, 0, nullptr,
                                    gc::AllocKind::FUNCTION_EXTENDED);
         if (!getobj)
             return nullptr;
         id = INT_TO_JSID(i);
         if (!getobj ||
             !NativeDefineAccessorProperty(cx, obj, id,
                                           JS_DATA_TO_FUNC_PTR(GetterOp, getobj.get()), nullptr,
-                                          JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_GETTER))
+                                          JSPROP_ENUMERATE | JSPROP_GETTER))
         {
             return nullptr;
         }
         getobj->setExtendedSlot(0, Int32Value(i));
     }
 
     return &obj->as<DebuggerArguments>();
 }
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -4800,20 +4800,20 @@ js::GetInitDataPropAttrs(JSOp op)
 
 bool
 js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleId id,
                               HandleObject val)
 {
     MOZ_ASSERT(val->isCallable());
     GetterOp getter;
     SetterOp setter;
-    unsigned attrs = JSPROP_SHARED;
 
     JSOp op = JSOp(*pc);
 
+    unsigned attrs = 0;
     if (!IsHiddenInitOp(op))
         attrs |= JSPROP_ENUMERATE;
 
     if (op == JSOP_INITPROP_GETTER || op == JSOP_INITELEM_GETTER ||
         op == JSOP_INITHIDDENPROP_GETTER || op == JSOP_INITHIDDENELEM_GETTER)
     {
         getter = CastAsGetterOp(val);
         setter = nullptr;
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -2059,18 +2059,16 @@ js::NativeGetOwnPropertyDescriptor(JSCon
         return false;
     if (!prop) {
         desc.object().set(nullptr);
         return true;
     }
 
     desc.setAttributes(GetPropertyAttributes(obj, prop));
     if (desc.isAccessorDescriptor()) {
-        MOZ_ASSERT(desc.isShared());
-
         // The result of GetOwnPropertyDescriptor() must be either undefined or
         // a complete property descriptor (per ES6 draft rev 32 (2015 Feb 2)
         // 6.1.7.3, Invariants of the Essential Internal Methods).
         //
         // It is an unfortunate fact that in SM, properties can exist that have
         // JSPROP_GETTER or JSPROP_SETTER but not both. In these cases, rather
         // than return true with desc incomplete, we fill out the missing
         // getter or setter with a null, following CompletePropertyDescriptor.
@@ -2090,17 +2088,16 @@ js::NativeGetOwnPropertyDescriptor(JSCon
         desc.value().setUndefined();
     } else {
         // This is either a straight-up data property or (rarely) a
         // property with a JSGetterOp/JSSetterOp. The latter must be
         // reported to the caller as a plain data property, so clear
         // desc.getter/setter, and mask away the SHARED bit.
         desc.setGetter(nullptr);
         desc.setSetter(nullptr);
-        desc.attributesRef() &= ~JSPROP_SHARED;
 
         if (prop.isDenseOrTypedArrayElement()) {
             desc.value().set(obj->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
         } else {
             RootedShape shape(cx, prop.shape());
             if (!NativeGetExistingProperty(cx, obj, obj, shape, desc.value()))
                 return false;
         }
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -619,24 +619,24 @@ intrinsic_DefineProperty(JSContext* cx, 
         attrs |= JSPROP_IGNORE_VALUE;
 
     if (attributes & ACCESSOR_DESCRIPTOR_KIND) {
         Value getter = args[3];
         MOZ_ASSERT(getter.isObject() || getter.isNullOrUndefined());
         if (getter.isObject())
             desc.setGetterObject(&getter.toObject());
         if (!getter.isNull())
-            attrs |= JSPROP_GETTER | JSPROP_SHARED;
+            attrs |= JSPROP_GETTER;
 
         Value setter = args[4];
         MOZ_ASSERT(setter.isObject() || setter.isNullOrUndefined());
         if (setter.isObject())
             desc.setSetterObject(&setter.toObject());
         if (!setter.isNull())
-            attrs |= JSPROP_SETTER | JSPROP_SHARED;
+            attrs |= JSPROP_SETTER;
 
         // By convention, these bits are not used on accessor descriptors.
         attrs &= ~(JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE);
     }
 
     desc.setAttributes(attrs);
     desc.assertValid();
 
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -676,17 +676,17 @@ AssertCanChangeAttrs(Shape* shape, unsig
     if (shape->configurable())
         return;
 
     /* A permanent property must stay permanent. */
     MOZ_ASSERT(attrs & JSPROP_PERMANENT);
 
     /* Reject attempts to remove a slot from the permanent data property. */
     MOZ_ASSERT_IF(shape->isDataDescriptor() && shape->hasSlot(),
-                  !(attrs & (JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED)));
+                  !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
 #endif
 }
 
 /* static */ Shape*
 NativeObject::putProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
                           GetterOp getter, SetterOp setter, uint32_t slot, unsigned attrs,
                           unsigned flags)
 {
@@ -740,17 +740,18 @@ NativeObject::putProperty(JSContext* cx,
 
     /*
      * If the caller wants to allocate a slot, but doesn't care which slot,
      * copy the existing shape's slot into slot so we can match shape, if all
      * other members match.
      */
     bool hadSlot = shape->hasSlot();
     uint32_t oldSlot = shape->maybeSlot();
-    if (!(attrs & JSPROP_SHARED) && slot == SHAPE_INVALID_SLOT && hadSlot)
+    bool needSlot = !getter && !setter;
+    if (needSlot && slot == SHAPE_INVALID_SLOT && hadSlot)
         slot = oldSlot;
 
     Rooted<UnownedBaseShape*> nbase(cx);
     {
         RootedShape shape(cx, obj->lastProperty());
         nbase = GetBaseShapeForNewShape(cx, shape, id);
         if (!nbase)
             return nullptr;
@@ -772,17 +773,17 @@ NativeObject::putProperty(JSContext* cx,
         if (!toDictionaryMode(cx, obj))
             return nullptr;
         ShapeTable* table = obj->lastProperty()->maybeTable(keep);
         MOZ_ASSERT(table);
         entry = &table->search<MaybeAdding::NotAdding>(shape->propid(), keep);
         shape = entry->shape();
     }
 
-    MOZ_ASSERT_IF(shape->hasSlot() && !(attrs & JSPROP_SHARED), shape->slot() == slot);
+    MOZ_ASSERT_IF(shape->hasSlot() && needSlot, shape->slot() == slot);
 
     if (obj->inDictionaryMode()) {
         /*
          * Updating some property in a dictionary-mode object. Create a new
          * shape for the existing property, and also generate a new shape for
          * the last property of the dictionary (unless the modified property
          * is also the last property).
          */
@@ -794,28 +795,26 @@ NativeObject::putProperty(JSContext* cx,
             return nullptr;
         if (!updateLast && !NativeObject::generateOwnShape(cx, obj))
             return nullptr;
 
         /*
          * FIXME bug 593129 -- slot allocation and NativeObject *this must move
          * out of here!
          */
-        if (slot == SHAPE_INVALID_SLOT && !(attrs & JSPROP_SHARED)) {
+        if (slot == SHAPE_INVALID_SLOT && needSlot) {
             if (!allocDictionarySlot(cx, obj, &slot))
                 return nullptr;
         }
 
         if (updateLast)
             shape->base()->adoptUnowned(nbase);
         else
             shape->base_ = nbase;
 
-        MOZ_ASSERT_IF(attrs & (JSPROP_GETTER | JSPROP_SETTER), attrs & JSPROP_SHARED);
-
         shape->setSlot(slot);
         shape->attrs = uint8_t(attrs);
         shape->flags = flags | Shape::IN_DICTIONARY | (accessorShape ? Shape::ACCESSOR_SHAPE : 0);
         if (shape->isAccessorShape()) {
             AccessorShape& accShape = shape->asAccessorShape();
             accShape.rawGetter = getter;
             accShape.rawSetter = setter;
             GetterSetterWriteBarrierPost(&accShape);
@@ -869,21 +868,22 @@ NativeObject::putProperty(JSContext* cx,
     return shape;
 }
 
 /* static */ Shape*
 NativeObject::changeProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
                              unsigned attrs, GetterOp getter, SetterOp setter)
 {
     MOZ_ASSERT(obj->containsPure(shape));
-    MOZ_ASSERT_IF(attrs & (JSPROP_GETTER | JSPROP_SETTER), attrs & JSPROP_SHARED);
 
     /* Allow only shared (slotless) => unshared (slotful) transition. */
-    MOZ_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
-               !(attrs & JSPROP_SHARED));
+#ifdef DEBUG
+    bool needSlot = !getter && !setter;
+    MOZ_ASSERT_IF(shape->hasSlot() != needSlot, needSlot);
+#endif
 
     MarkTypePropertyNonData(cx, obj, shape->propid());
 
     AssertCanChangeAttrs(shape, attrs);
 
     if (shape->attrs == attrs && shape->getter() == getter && shape->setter() == setter)
         return shape;
 
@@ -1795,17 +1795,16 @@ Shape::dump(js::GenericPrinter& out) con
         int first = 1;
         out.putChar('(');
 #define DUMP_ATTR(name, display) if (attrs & JSPROP_##name) out.put(&(" " #display)[first]), first = 0
         DUMP_ATTR(ENUMERATE, enumerate);
         DUMP_ATTR(READONLY, readonly);
         DUMP_ATTR(PERMANENT, permanent);
         DUMP_ATTR(GETTER, getter);
         DUMP_ATTR(SETTER, setter);
-        DUMP_ATTR(SHARED, shared);
 #undef  DUMP_ATTR
         out.putChar(')');
     }
 
     out.printf("flags %x ", flags);
     if (flags) {
         int first = 1;
         out.putChar('(');
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -1008,17 +1008,17 @@ class Shape : public gc::TenuredCell
                attrs == aattrs &&
                getter() == rawGetter &&
                setter() == rawSetter;
     }
 
     BaseShape* base() const { return base_.get(); }
 
     bool hasSlot() const {
-        return (attrs & JSPROP_SHARED) == 0;
+        return !isEmptyShape() && !getter() && !setter();
     }
     uint32_t slot() const { MOZ_ASSERT(hasSlot() && !hasMissingSlot()); return maybeSlot(); }
     uint32_t maybeSlot() const {
         return slotInfo & SLOT_MASK;
     }
 
     bool isEmptyShape() const {
         MOZ_ASSERT_IF(JSID_IS_EMPTY(propid_), hasMissingSlot());
@@ -1445,17 +1445,16 @@ struct StackShape
         rawSetter(nullptr),
         slot_(slot),
         attrs(uint8_t(attrs)),
         flags(uint8_t(flags))
     {
         MOZ_ASSERT(base);
         MOZ_ASSERT(!JSID_IS_VOID(propid));
         MOZ_ASSERT(slot <= SHAPE_INVALID_SLOT);
-        MOZ_ASSERT_IF(attrs & (JSPROP_GETTER | JSPROP_SETTER), attrs & JSPROP_SHARED);
     }
 
     explicit StackShape(Shape* shape)
       : base(shape->base()->unowned()),
         propid(shape->propidRef()),
         rawGetter(shape->getter()),
         rawSetter(shape->setter()),
         slot_(shape->maybeSlot()),
@@ -1468,17 +1467,20 @@ struct StackShape
             flags |= Shape::ACCESSOR_SHAPE;
         else
             flags &= ~Shape::ACCESSOR_SHAPE;
 
         this->rawGetter = rawGetter;
         this->rawSetter = rawSetter;
     }
 
-    bool hasSlot() const { return (attrs & JSPROP_SHARED) == 0; }
+    bool hasSlot() const {
+        MOZ_ASSERT(!JSID_IS_EMPTY(propid));
+        return !rawGetter && !rawSetter;
+    }
     bool hasMissingSlot() const { return maybeSlot() == SHAPE_INVALID_SLOT; }
 
     uint32_t slot() const { MOZ_ASSERT(hasSlot() && !hasMissingSlot()); return slot_; }
     uint32_t maybeSlot() const { return slot_; }
 
     void setSlot(uint32_t slot) {
         MOZ_ASSERT(slot <= SHAPE_INVALID_SLOT);
         slot_ = slot;
@@ -1541,17 +1543,16 @@ Shape::Shape(const StackShape& other, ui
 #ifdef DEBUG
     gc::AllocKind allocKind = getAllocKind();
     MOZ_ASSERT_IF(other.isAccessorShape(), allocKind == gc::AllocKind::ACCESSOR_SHAPE);
     MOZ_ASSERT_IF(allocKind == gc::AllocKind::SHAPE, !other.isAccessorShape());
 #endif
 
     MOZ_ASSERT_IF(!isEmptyShape(), AtomIsMarked(zone(), propid()));
 
-    MOZ_ASSERT_IF(attrs & (JSPROP_GETTER | JSPROP_SETTER), attrs & JSPROP_SHARED);
     kids.setNull();
 }
 
 // This class is used to update any shapes in a zone that have nursery objects
 // as getters/setters.  It updates the pointers and the shapes' entries in the
 // parents' KidsHash tables.
 class NurseryShapesRef : public gc::BufferableRef
 {
@@ -1562,17 +1563,17 @@ class NurseryShapesRef : public gc::Buff
     void trace(JSTracer* trc) override;
 };
 
 inline
 Shape::Shape(UnownedBaseShape* base, uint32_t nfixed)
   : base_(base),
     propid_(JSID_EMPTY),
     slotInfo(SHAPE_INVALID_SLOT | (nfixed << FIXED_SLOTS_SHIFT)),
-    attrs(JSPROP_SHARED),
+    attrs(0),
     flags(0),
     parent(nullptr)
 {
     MOZ_ASSERT(base);
     kids.setNull();
 }
 
 inline GetterOp
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1365,17 +1365,17 @@ XRE_XPCShellMain(int argc, char** argv, 
             }
 
             nsAutoString workingDirectory;
             if (GetCurrentWorkingDirectory(workingDirectory))
                 gWorkingDirectory = &workingDirectory;
 
             JS_DefineProperty(cx, glob, "__LOCATION__",
                               GetLocationProperty, nullptr,
-                              JSPROP_SHARED);
+                              0);
 
             {
                 // We are almost certainly going to run script here, so we need an
                 // AutoEntryScript. This is Gecko-specific and not in any spec.
                 AutoEntryScript aes(backstagePass, "xpcshell argument processing");
 
                 // If an exception is thrown, we'll set our return code
                 // appropriately, and then let the AutoEntryScript destructor report
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -345,17 +345,17 @@ DefinePropertyIfFound(XPCCallContext& cc
 
             if (!fun)
                 return false;
 
             RootedObject funobj(ccx, JS_GetFunctionObject(fun));
             if (!funobj)
                 return false;
 
-            propFlags |= JSPROP_GETTER | JSPROP_SHARED;
+            propFlags |= JSPROP_GETTER;
             propFlags &= ~JSPROP_ENUMERATE;
 
             AutoResolveName arn(ccx, id);
             if (resolved)
                 *resolved = true;
             return JS_DefinePropertyById(ccx, obj, id,
                                          JS_DATA_TO_FUNC_PTR(JSNative, funobj.get()),
                                          nullptr,
@@ -429,17 +429,17 @@ DefinePropertyIfFound(XPCCallContext& cc
             *resolved = true;
         return JS_DefinePropertyById(ccx, obj, id, funval, propFlags);
     }
 
     // else...
 
     MOZ_ASSERT(member->IsAttribute(), "way broken!");
 
-    propFlags |= JSPROP_GETTER | JSPROP_SHARED;
+    propFlags |= JSPROP_GETTER;
     propFlags &= ~JSPROP_READONLY;
     JSObject* funobj = funval.toObjectOrNull();
     JSNative getter = JS_DATA_TO_FUNC_PTR(JSNative, funobj);
     JSNative setter;
     if (member->IsWritableAttribute()) {
         propFlags |= JSPROP_SETTER;
         setter = JS_DATA_TO_FUNC_PTR(JSNative, funobj);
     } else {
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -1538,19 +1538,16 @@ XPCWrappedNativeXrayTraits::resolveNativ
             return false;
         }
 
         unsigned attrs = desc.attributes();
         attrs |= JSPROP_GETTER;
         if (member->IsWritableAttribute())
             attrs |= JSPROP_SETTER;
 
-        // Make the property shared on the holder so no slot is allocated
-        // for it. This avoids keeping garbage alive through that slot.
-        attrs |= JSPROP_SHARED;
         desc.setAttributes(attrs);
     } else {
         // This is a method. Clone a function for it.
         if (!member->NewFunctionObject(ccx, iface, wrapper, desc.value().address())) {
             JS_ReportErrorASCII(cx, "Failed to clone function object for native function");
             return false;
         }
 
@@ -1646,17 +1643,17 @@ XrayTraits::resolveOwnProperty(JSContext
     // Handle .wrappedJSObject for subsuming callers. This should move once we
     // sort out own-ness for the holder.
     if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_WRAPPED_JSOBJECT) &&
         WrapperFactory::AllowWaiver(wrapper))
     {
         if (!JS_AlreadyHasOwnPropertyById(cx, holder, id, &found))
             return false;
         if (!found && !JS_DefinePropertyById(cx, holder, id, wrappedJSObject_getter, nullptr,
-                                             JSPROP_ENUMERATE | JSPROP_SHARED)) {
+                                             JSPROP_ENUMERATE)) {
             return false;
         }
         if (!JS_GetOwnPropertyDescriptorById(cx, holder, id, desc))
             return false;
         desc.object().set(wrapper);
         return true;
     }