Bug 1394835 part 5 - Split NativeDefineProperty in separate accessor vs data functions. r=evilpie
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 12 Sep 2017 16:41:12 +0200
changeset 380312 4498739037187b553b5428ad65b7c38238e6298f
parent 380311 09df59c389f58591b6bab860c3fa4a0183bf871e
child 380313 1a7b18c564269901ccb9a3fab6439e2479d63dd0
push id32486
push userarchaeopteryx@coole-files.de
push dateWed, 13 Sep 2017 09:28:25 +0000
treeherdermozilla-central@987326974635 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersevilpie
bugs1394835
milestone57.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 1394835 part 5 - Split NativeDefineProperty in separate accessor vs data functions. r=evilpie
js/src/builtin/SymbolObject.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/jsapi-tests/testForceLexicalInitialization.cpp
js/src/jsdate.cpp
js/src/jsfun.cpp
js/src/jsnum.cpp
js/src/json.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/Debugger.cpp
js/src/vm/Interpreter-inl.h
js/src/vm/NativeObject.cpp
js/src/vm/NativeObject.h
js/src/vm/ObjectGroup.cpp
js/src/vm/RegExpObject.cpp
--- a/js/src/builtin/SymbolObject.cpp
+++ b/js/src/builtin/SymbolObject.cpp
@@ -69,17 +69,17 @@ SymbolObject::initClass(JSContext* cx, H
     if (defineMembers) {
         // Define the well-known symbol properties, such as Symbol.iterator.
         ImmutablePropertyNamePtr* names = cx->names().wellKnownSymbolNames();
         RootedValue value(cx);
         unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT;
         WellKnownSymbols* wks = cx->runtime()->wellKnownSymbols;
         for (size_t i = 0; i < JS::WellKnownSymbolLimit; i++) {
             value.setSymbol(wks->get(i));
-            if (!NativeDefineProperty(cx, ctor, names[i], value, nullptr, nullptr, attrs))
+            if (!NativeDefineDataProperty(cx, ctor, names[i], value, attrs))
                 return nullptr;
         }
     }
 
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return nullptr;
 
     if (defineMembers) {
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -3691,26 +3691,20 @@ BytecodeEmitter::iteratorResultShape(uns
     // many properties we plan to have.
     gc::AllocKind kind = gc::GetGCObjectKind(2);
     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
     if (!obj)
         return false;
 
     Rooted<jsid> value_id(cx, NameToId(cx->names().value));
     Rooted<jsid> done_id(cx, NameToId(cx->names().done));
-    if (!NativeDefineProperty(cx, obj, value_id, UndefinedHandleValue, nullptr, nullptr,
-                              JSPROP_ENUMERATE))
-    {
-        return false;
-    }
-    if (!NativeDefineProperty(cx, obj, done_id, UndefinedHandleValue, nullptr, nullptr,
-                              JSPROP_ENUMERATE))
-    {
-        return false;
-    }
+    if (!NativeDefineDataProperty(cx, obj, value_id, UndefinedHandleValue, JSPROP_ENUMERATE))
+        return false;
+    if (!NativeDefineDataProperty(cx, obj, done_id, UndefinedHandleValue, JSPROP_ENUMERATE))
+        return false;
 
     ObjectBox* objbox = parser.newObjectBox(obj);
     if (!objbox)
         return false;
 
     *shape = objectList.add(objbox);
 
     return true;
@@ -6066,21 +6060,18 @@ BytecodeEmitter::emitDestructuringObjRes
         } else {
             uint32_t index;
             if (!makeAtomIndex(pnatom, &index))
                 return false;
 
             if (obj) {
                 MOZ_ASSERT(!obj->inDictionaryMode());
                 Rooted<jsid> id(cx, AtomToId(pnatom));
-                if (!NativeDefineProperty(cx, obj, id, UndefinedHandleValue, nullptr, nullptr,
-                                          JSPROP_ENUMERATE))
-                {
+                if (!NativeDefineDataProperty(cx, obj, id, UndefinedHandleValue, JSPROP_ENUMERATE))
                     return false;
-                }
                 if (obj->inDictionaryMode())
                     obj.set(nullptr);
             }
 
             if (!emitIndex32(JSOP_INITPROP, index))
                 return false;
         }
     }
@@ -9997,18 +9988,18 @@ BytecodeEmitter::emitPropertyList(ParseN
             if (!makeAtomIndex(key->pn_atom, &index))
                 return false;
 
             if (objp) {
                 MOZ_ASSERT(type == ObjectLiteral);
                 MOZ_ASSERT(!IsHiddenInitOp(op));
                 MOZ_ASSERT(!objp->inDictionaryMode());
                 Rooted<jsid> id(cx, AtomToId(key->pn_atom));
-                if (!NativeDefineProperty(cx, objp, id, UndefinedHandleValue, nullptr, nullptr,
-                                          JSPROP_ENUMERATE))
+                if (!NativeDefineDataProperty(cx, objp, id, UndefinedHandleValue,
+                                              JSPROP_ENUMERATE))
                 {
                     return false;
                 }
                 if (objp->inDictionaryMode())
                     objp.set(nullptr);
             }
 
             if (propdef->pn_right->isDirectRHSAnonFunction()) {
--- a/js/src/jsapi-tests/testForceLexicalInitialization.cpp
+++ b/js/src/jsapi-tests/testForceLexicalInitialization.cpp
@@ -17,17 +17,17 @@ BEGIN_TEST(testForceLexicalInitializatio
     JS::Rooted<js::LexicalEnvironmentObject*> env(
         cx, js::LexicalEnvironmentObject::createGlobal(cx, g));
 
     JS::RootedValue uninitialized(cx, JS::MagicValue(JS_UNINITIALIZED_LEXICAL));
     js::RootedPropertyName name(cx, Atomize(cx, "foopi", 4)->asPropertyName());
     JS::RootedId id(cx, NameToId(name));
     unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
-    CHECK(NativeDefineProperty(cx, env, id, uninitialized, nullptr, nullptr, attrs));
+    CHECK(NativeDefineDataProperty(cx, env, id, uninitialized, attrs));
 
     // Verify that "foopi" is uninitialized
     const JS::Value v = env->getSlot(env->lookup(cx, id)->slot());
     CHECK(v.isMagic(JS_UNINITIALIZED_LEXICAL));
 
     ForceLexicalInitialization(cx, env);
 
     // Verify that "foopi" has been initialized to undefined
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -3251,18 +3251,18 @@ FinishDateClassInit(JSContext* cx, Handl
     /*
      * Date.prototype.toGMTString has the same initial value as
      * Date.prototype.toUTCString.
      */
     RootedValue toUTCStringFun(cx);
     RootedId toUTCStringId(cx, NameToId(cx->names().toUTCString));
     RootedId toGMTStringId(cx, NameToId(cx->names().toGMTString));
     return NativeGetProperty(cx, proto.as<NativeObject>(), toUTCStringId, &toUTCStringFun) &&
-           NativeDefineProperty(cx, proto.as<NativeObject>(), toGMTStringId, toUTCStringFun,
-                                nullptr, nullptr, 0);
+           NativeDefineDataProperty(cx, proto.as<NativeObject>(), toGMTStringId, toUTCStringFun,
+                                    0);
 }
 
 static const ClassSpec DateObjectClassSpec = {
     GenericCreateConstructor<DateConstructor, 7, gc::AllocKind::FUNCTION>,
     CreateDatePrototype,
     date_static_methods,
     nullptr,
     date_methods,
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -540,21 +540,18 @@ fun_resolve(JSContext* cx, HandleObject 
 
             // Don't define an own .name property for unnamed functions.
             if (!name)
                 return true;
 
             v.setString(name);
         }
 
-        if (!NativeDefineProperty(cx, fun, id, v, nullptr, nullptr,
-                                  JSPROP_READONLY | JSPROP_RESOLVING))
-        {
+        if (!NativeDefineDataProperty(cx, fun, id, v, JSPROP_READONLY | JSPROP_RESOLVING))
             return false;
-        }
 
         if (isLength)
             fun->setResolvedLength();
         else
             fun->setResolvedName();
 
         *resolvedp = true;
         return true;
@@ -2404,21 +2401,19 @@ js::SetFunctionNameIfNoOwnName(JSContext
     if (!ValueToId<CanGC>(cx, name, &id))
         return false;
 
     RootedAtom funNameAtom(cx, IdToFunctionName(cx, id, prefixKind));
     if (!funNameAtom)
         return false;
 
     RootedValue funNameVal(cx, StringValue(funNameAtom));
-    if (!NativeDefineProperty(cx, fun, cx->names().name, funNameVal, nullptr, nullptr,
-                              JSPROP_READONLY))
-    {
+    if (!NativeDefineDataProperty(cx, fun, cx->names().name, funNameVal, JSPROP_READONLY))
         return false;
-    }
+
     return true;
 }
 
 JSFunction*
 js::DefineFunction(JSContext* cx, HandleObject obj, HandleId id, Native native,
                    unsigned nargs, unsigned flags, AllocKind allocKind /* = AllocKind::FUNCTION */)
 {
     RootedAtom atom(cx, IdToFunctionName(cx, id));
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1275,20 +1275,20 @@ js::InitNumberClass(JSContext* cx, Handl
     RootedValue parseFloatValue(cx, ObjectValue(*parseFloat));
     if (!DefineDataProperty(cx, ctor, parseFloatId, parseFloatValue, 0))
         return nullptr;
 
     RootedValue valueNaN(cx, cx->runtime()->NaNValue);
     RootedValue valueInfinity(cx, cx->runtime()->positiveInfinityValue);
 
     /* ES5 15.1.1.1, 15.1.1.2 */
-    if (!NativeDefineProperty(cx, global, cx->names().NaN, valueNaN, nullptr, nullptr,
-                              JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING) ||
-        !NativeDefineProperty(cx, global, cx->names().Infinity, valueInfinity, nullptr, nullptr,
-                              JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING))
+    if (!NativeDefineDataProperty(cx, global, cx->names().NaN, valueNaN,
+                                  JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING) ||
+        !NativeDefineDataProperty(cx, global, cx->names().Infinity, valueInfinity,
+                                  JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING))
     {
         return nullptr;
     }
 
     if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Number, ctor, numberProto))
         return nullptr;
 
     return numberProto;
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -750,17 +750,17 @@ js::Stringify(JSContext* cx, MutableHand
 
     /* Step 9. */
     RootedPlainObject wrapper(cx, NewBuiltinClassInstance<PlainObject>(cx));
     if (!wrapper)
         return false;
 
     /* Steps 10-11. */
     RootedId emptyId(cx, NameToId(cx->names().empty));
-    if (!NativeDefineProperty(cx, wrapper, emptyId, vp, nullptr, nullptr, JSPROP_ENUMERATE))
+    if (!NativeDefineDataProperty(cx, wrapper, emptyId, vp, JSPROP_ENUMERATE))
         return false;
 
     /* Step 12. */
     StringifyContext scx(cx, sb, gap, replacer, propertyList,
                          stringifyBehavior == StringifyBehavior::RestrictedSafe);
     if (!PreprocessValue(cx, wrapper, HandleId(emptyId), vp, &scx))
         return false;
     if (IsFilteredValue(vp))
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -513,40 +513,40 @@ MappedArgSetter(JSContext* cx, HandleObj
      * simple data property. Note that we rely on ArgumentsObject::obj_delProperty
      * to set the corresponding override-bit.
      * Note also that we must define the property instead of setting it in case
      * the user has changed the prototype to an object that has a setter for
      * this id.
      */
     ObjectOpResult ignored;
     return NativeDeleteProperty(cx, argsobj, id, ignored) &&
-           NativeDefineProperty(cx, argsobj, id, vp, nullptr, nullptr, attrs, result);
+           NativeDefineDataProperty(cx, argsobj, id, vp, attrs, result);
 }
 
 static bool
 DefineArgumentsIterator(JSContext* cx, Handle<ArgumentsObject*> argsobj)
 {
     RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator));
     HandlePropertyName shName = cx->names().ArrayValues;
     RootedAtom name(cx, cx->names().values);
     RootedValue val(cx);
     if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, 0, &val))
         return false;
-    return NativeDefineProperty(cx, argsobj, iteratorId, val, nullptr, nullptr, JSPROP_RESOLVING);
+    return NativeDefineDataProperty(cx, argsobj, iteratorId, val, JSPROP_RESOLVING);
 }
 
 /* static */ bool
 ArgumentsObject::reifyLength(JSContext* cx, Handle<ArgumentsObject*> obj)
 {
     if (obj->hasOverriddenLength())
         return true;
 
     RootedId id(cx, NameToId(cx->names().length));
     RootedValue val(cx, Int32Value(obj->initialLength()));
-    if (!NativeDefineProperty(cx, obj, id, val, nullptr, nullptr, JSPROP_RESOLVING))
+    if (!NativeDefineDataProperty(cx, obj, id, val, JSPROP_RESOLVING))
         return false;
 
     obj->markLengthOverridden();
     return true;
 }
 
 /* static */ bool
 ArgumentsObject::reifyIterator(JSContext* cx, Handle<ArgumentsObject*> obj)
@@ -589,21 +589,18 @@ MappedArgumentsObject::obj_resolve(JSCon
     } else {
         if (!JSID_IS_ATOM(id, cx->names().callee))
             return true;
 
         if (argsobj->hasOverriddenCallee())
             return true;
     }
 
-    if (!NativeDefineProperty(cx, argsobj, id, UndefinedHandleValue,
-                              MappedArgGetter, MappedArgSetter, attrs))
-    {
+    if (!NativeDefineAccessorProperty(cx, argsobj, id, MappedArgGetter, MappedArgSetter, attrs))
         return false;
-    }
 
     *resolvedp = true;
     return true;
 }
 
 /* static */ bool
 MappedArgumentsObject::obj_enumerate(JSContext* cx, HandleObject obj)
 {
@@ -756,17 +753,17 @@ UnmappedArgSetter(JSContext* cx, HandleO
 
     /*
      * For simplicity we use delete/define to replace the property with a
      * simple data property. Note that we rely on ArgumentsObject::obj_delProperty
      * to set the corresponding override-bit.
      */
     ObjectOpResult ignored;
     return NativeDeleteProperty(cx, argsobj, id, ignored) &&
-           NativeDefineProperty(cx, argsobj, id, vp, nullptr, nullptr, attrs, result);
+           NativeDefineDataProperty(cx, argsobj, id, vp, attrs, result);
 }
 
 /* static */ bool
 UnmappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
 {
     Rooted<UnmappedArgumentsObject*> argsobj(cx, &obj->as<UnmappedArgumentsObject>());
 
     if (JSID_IS_SYMBOL(id) && JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().iterator) {
@@ -797,17 +794,17 @@ UnmappedArgumentsObject::obj_resolve(JSC
             return true;
 
         attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED;
         getter = CastAsGetterOp(argsobj->global().getThrowTypeError());
         setter = CastAsSetterOp(argsobj->global().getThrowTypeError());
     }
 
     attrs |= JSPROP_RESOLVING;
-    if (!NativeDefineProperty(cx, argsobj, id, UndefinedHandleValue, getter, setter, attrs))
+    if (!NativeDefineAccessorProperty(cx, argsobj, id, getter, setter, attrs))
         return false;
 
     *resolvedp = true;
     return true;
 }
 
 /* static */ bool
 UnmappedArgumentsObject::obj_enumerate(JSContext* cx, HandleObject obj)
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1502,17 +1502,17 @@ Debugger::newCompletionValue(JSContext* 
 
       default:
         MOZ_CRASH("bad status passed to Debugger::newCompletionValue");
     }
 
     /* Common tail for JSTRAP_RETURN and JSTRAP_THROW. */
     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
     if (!obj ||
-        !NativeDefineProperty(cx, obj, key, value, nullptr, nullptr, JSPROP_ENUMERATE))
+        !NativeDefineDataProperty(cx, obj, key, value, JSPROP_ENUMERATE))
     {
         return false;
     }
 
     result.setObject(*obj);
     return true;
 }
 
@@ -7958,17 +7958,17 @@ DebuggerGenericEval(JSContext* cx, const
         if (!nenv)
             return false;
         RootedId id(cx);
         for (size_t i = 0; i < keys.length(); i++) {
             id = keys[i];
             cx->markId(id);
             MutableHandleValue val = values[i];
             if (!cx->compartment()->wrap(cx, val) ||
-                !NativeDefineProperty(cx, nenv, id, val, nullptr, nullptr, 0))
+                !NativeDefineDataProperty(cx, nenv, id, val, 0))
             {
                 return false;
             }
         }
 
         AutoObjectVector envChain(cx);
         if (!envChain.append(nenv))
             return false;
@@ -8462,34 +8462,34 @@ DebuggerArguments::create(JSContext* cx,
     if (!obj)
         return nullptr;
 
     SetReservedSlot(obj, FRAME_SLOT, ObjectValue(*frame));
 
     MOZ_ASSERT(referent.numActualArgs() <= 0x7fffffff);
     unsigned fargc = referent.numActualArgs();
     RootedValue fargcVal(cx, Int32Value(fargc));
-    if (!NativeDefineProperty(cx, obj, cx->names().length, fargcVal, nullptr, nullptr,
-                              JSPROP_PERMANENT | JSPROP_READONLY))
+    if (!NativeDefineDataProperty(cx, obj, cx->names().length, fargcVal,
+                                  JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return nullptr;
     }
 
     Rooted<jsid> id(cx);
     for (unsigned i = 0; i < fargc; i++) {
         RootedFunction getobj(cx);
         getobj = NewNativeFunction(cx, DebuggerArguments_getArg, 0, nullptr,
                                    gc::AllocKind::FUNCTION_EXTENDED);
         if (!getobj)
             return nullptr;
         id = INT_TO_JSID(i);
         if (!getobj ||
-            !NativeDefineProperty(cx, obj, id, UndefinedHandleValue,
-                                  JS_DATA_TO_FUNC_PTR(GetterOp, getobj.get()), nullptr,
-                                  JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_GETTER))
+            !NativeDefineAccessorProperty(cx, obj, id,
+                                          JS_DATA_TO_FUNC_PTR(GetterOp, getobj.get()), nullptr,
+                                          JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_GETTER))
         {
             return nullptr;
         }
         getobj->setExtendedSlot(0, Int32Value(i));
     }
 
     return &obj->as<DebuggerArguments>();
 }
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -361,17 +361,17 @@ SetNameOperation(JSContext* cx, JSScript
 inline bool
 DefLexicalOperation(JSContext* cx, Handle<LexicalEnvironmentObject*> lexicalEnv,
                     HandleObject varObj, HandlePropertyName name, unsigned attrs)
 {
     // Redeclaration checks should have already been done.
     MOZ_ASSERT(CheckLexicalNameConflict(cx, lexicalEnv, varObj, name));
     RootedId id(cx, NameToId(name));
     RootedValue uninitialized(cx, MagicValue(JS_UNINITIALIZED_LEXICAL));
-    return NativeDefineProperty(cx, lexicalEnv, id, uninitialized, nullptr, nullptr, attrs);
+    return NativeDefineDataProperty(cx, lexicalEnv, id, uninitialized, attrs);
 }
 
 inline bool
 DefLexicalOperation(JSContext* cx, LexicalEnvironmentObject* lexicalEnvArg,
                     JSObject* varObjArg, JSScript* script, jsbytecode* pc)
 {
     MOZ_ASSERT(*pc == JSOP_DEFLET || *pc == JSOP_DEFCONST);
     RootedPropertyName name(cx, script->getName(pc));
@@ -401,18 +401,17 @@ InitGlobalLexicalOperation(JSContext* cx
     lexicalEnv->setSlotWithType(cx, shape, value);
 }
 
 inline bool
 InitPropertyOperation(JSContext* cx, JSOp op, HandleObject obj, HandleId id, HandleValue rhs)
 {
     if (obj->is<PlainObject>() || obj->is<JSFunction>()) {
         unsigned propAttrs = GetInitDataPropAttrs(op);
-        return NativeDefineProperty(cx, obj.as<NativeObject>(), id, rhs, nullptr, nullptr,
-                                    propAttrs);
+        return NativeDefineDataProperty(cx, obj.as<NativeObject>(), id, rhs, propAttrs);
     }
 
     MOZ_ASSERT(obj->as<UnboxedPlainObject>().layout().lookup(id));
     return PutProperty(cx, obj, id, rhs, false);
 }
 
 inline bool
 DefVarOperation(JSContext* cx, HandleObject varobj, HandlePropertyName dn, unsigned attrs)
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1844,51 +1844,84 @@ js::NativeDefineProperty(JSContext* cx, 
     if (!AddOrChangeProperty<IsAddOrChange::AddOrChange>(cx, obj, id, desc))
         return false;
 
     // Step 10.
     return result.succeed();
 }
 
 bool
-js::NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
-                         HandleValue value, GetterOp getter, SetterOp setter, unsigned attrs,
-                         ObjectOpResult& result)
+js::NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
+                                 GetterOp getter, SetterOp setter, unsigned attrs,
+                                 ObjectOpResult& result)
 {
     Rooted<PropertyDescriptor> desc(cx);
-    desc.initFields(nullptr, value, attrs, getter, setter);
+    desc.initFields(nullptr, UndefinedHandleValue, attrs, getter, setter);
     return NativeDefineProperty(cx, obj, id, desc, result);
 }
 
 bool
-js::NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
-                         HandleValue value, JSGetterOp getter, JSSetterOp setter,
-                         unsigned attrs)
+js::NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
+                             HandleValue value, unsigned attrs, ObjectOpResult& result)
+{
+    Rooted<PropertyDescriptor> desc(cx);
+    desc.initFields(nullptr, value, attrs, nullptr, nullptr);
+    return NativeDefineProperty(cx, obj, id, desc, result);
+}
+
+bool
+js::NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
+                                 JSGetterOp getter, JSSetterOp setter, unsigned attrs)
 {
     ObjectOpResult result;
-    if (!NativeDefineProperty(cx, obj, id, value, getter, setter, attrs, result))
+    if (!NativeDefineAccessorProperty(cx, obj, id, getter, setter, attrs, result))
         return false;
     if (!result) {
         // Off-thread callers should not get here: they must call this
         // function only with known-valid arguments. Populating a new
         // PlainObject with configurable properties is fine.
         MOZ_ASSERT(!cx->helperThread());
         result.reportError(cx, obj, id);
         return false;
     }
     return true;
 }
 
 bool
-js::NativeDefineProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
-                         HandleValue value, JSGetterOp getter, JSSetterOp setter,
-                         unsigned attrs)
+js::NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
+                             HandleValue value, unsigned attrs)
+{
+    ObjectOpResult result;
+    if (!NativeDefineDataProperty(cx, obj, id, value, attrs, result))
+        return false;
+    if (!result) {
+        // Off-thread callers should not get here: they must call this
+        // function only with known-valid arguments. Populating a new
+        // PlainObject with configurable properties is fine.
+        MOZ_ASSERT(!cx->helperThread());
+        result.reportError(cx, obj, id);
+        return false;
+    }
+    return true;
+}
+
+bool
+js::NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
+                                 JSGetterOp getter, JSSetterOp setter, unsigned attrs)
 {
     RootedId id(cx, NameToId(name));
-    return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs);
+    return NativeDefineAccessorProperty(cx, obj, id, getter, setter, attrs);
+}
+
+bool
+js::NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
+                             HandleValue value, unsigned attrs)
+{
+    RootedId id(cx, NameToId(name));
+    return NativeDefineDataProperty(cx, obj, id, value, attrs);
 }
 
 static bool
 DefineNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
                           HandleValue v, ObjectOpResult& result)
 {
     // Optimized NativeDefineProperty() version for known absent properties.
 
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -1388,29 +1388,40 @@ NativeObject::privateWriteBarrierPre(voi
  */
 
 extern bool
 NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
                      Handle<JS::PropertyDescriptor> desc,
                      ObjectOpResult& result);
 
 extern bool
-NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
-                     JSGetterOp getter, JSSetterOp setter, unsigned attrs,
-                     ObjectOpResult& result);
+NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
+                             JSGetterOp getter, JSSetterOp setter, unsigned attrs,
+                             ObjectOpResult& result);
+
+extern bool
+NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
+                         unsigned attrs, ObjectOpResult& result);
 
 /* If the result out-param is omitted, throw on failure. */
 extern bool
-NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
-                     JSGetterOp getter, JSSetterOp setter, unsigned attrs);
+NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
+                             JSGetterOp getter, JSSetterOp setter, unsigned attrs);
 
 extern bool
-NativeDefineProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
-                     HandleValue value, JSGetterOp getter, JSSetterOp setter,
-                     unsigned attrs);
+NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
+                         unsigned attrs);
+
+extern bool
+NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
+                             JSGetterOp getter, JSSetterOp setter, unsigned attrs);
+
+extern bool
+NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
+                         HandleValue value, unsigned attrs);
 
 extern bool
 NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool* foundp);
 
 extern bool
 NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, HandleId id,
                                MutableHandle<JS::PropertyDescriptor> desc);
 
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -1197,17 +1197,17 @@ AddPlainObjectProperties(JSContext* cx, 
                          IdValuePair* properties, size_t nproperties)
 {
     RootedId propid(cx);
     RootedValue value(cx);
 
     for (size_t i = 0; i < nproperties; i++) {
         propid = properties[i].id;
         value = properties[i].value;
-        if (!NativeDefineProperty(cx, obj, propid, value, nullptr, nullptr, JSPROP_ENUMERATE))
+        if (!NativeDefineDataProperty(cx, obj, propid, value, JSPROP_ENUMERATE))
             return false;
     }
 
     return true;
 }
 
 PlainObject*
 js::NewPlainObjectWithProperties(JSContext* cx, IdValuePair* properties, size_t nproperties,
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -1217,26 +1217,23 @@ RegExpCompartment::createMatchResultTemp
     Rooted<TaggedProto> proto(cx, templateObject->taggedProto());
     ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto);
     if (!group)
         return matchResultTemplateObject_; // = nullptr
     templateObject->setGroup(group);
 
     /* Set dummy index property */
     RootedValue index(cx, Int32Value(0));
-    if (!NativeDefineProperty(cx, templateObject, cx->names().index, index, nullptr, nullptr,
-                              JSPROP_ENUMERATE))
-    {
+    if (!NativeDefineDataProperty(cx, templateObject, cx->names().index, index, JSPROP_ENUMERATE))
         return matchResultTemplateObject_; // = nullptr
-    }
 
     /* Set dummy input property */
     RootedValue inputVal(cx, StringValue(cx->runtime()->emptyString));
-    if (!NativeDefineProperty(cx, templateObject, cx->names().input, inputVal, nullptr, nullptr,
-                              JSPROP_ENUMERATE))
+    if (!NativeDefineDataProperty(cx, templateObject, cx->names().input, inputVal,
+                                  JSPROP_ENUMERATE))
     {
         return matchResultTemplateObject_; // = nullptr
     }
 
     // Make sure that the properties are in the right slots.
     DebugOnly<Shape*> shape = templateObject->lastProperty();
     MOZ_ASSERT(shape->previous()->slot() == 0 &&
                shape->previous()->propidRef() == NameToId(cx->names().index));