Bug 1055472 - Part 16: Make the String constructor properly subclassable. (r=Waldo)
☠☠ backed out by 652bd59cdb51 ☠ ☠
authorEric Faust <efaustbmo@gmail.com>
Fri, 13 Nov 2015 18:22:22 -0800
changeset 273444 6ed32cadfc3126c34644ee37658b6a752b477d44
parent 273443 2f0b0b246e25f83fd88a7b06fa91945a16645097
child 273445 41be086be0e814c60ab3ae3a498f877e81815af1
push id16334
push usercbook@mozilla.com
push dateFri, 20 Nov 2015 13:35:22 +0000
treeherderfx-team@0947ebd84fec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1055472
milestone45.0a1
Bug 1055472 - Part 16: Make the String constructor properly subclassable. (r=Waldo)
js/src/jit/BaselineIC.cpp
js/src/jsstr.cpp
js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
js/src/vm/StringObject-inl.h
js/src/vm/StringObject.h
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5703,17 +5703,17 @@ GetTemplateObjectForNative(JSContext* cx
         res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, 0, TenuredObject));
         if (!res)
             return false;
         return true;
     }
 
     if (native == StringConstructor) {
         RootedString emptyString(cx, cx->runtime()->emptyString);
-        res.set(StringObject::create(cx, emptyString, TenuredObject));
+        res.set(StringObject::create(cx, emptyString, /* proto = */ nullptr, TenuredObject));
         return !!res;
     }
 
     if (native == obj_create && args.length() == 1 && args[0].isObjectOrNull()) {
         RootedObject proto(cx, args[0].toObjectOrNull());
         res.set(ObjectCreateImpl(cx, proto, TenuredObject));
         return !!res;
     }
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -4076,17 +4076,22 @@ js::StringConstructor(JSContext* cx, uns
         str = ToString<CanGC>(cx, args[0]);
         if (!str)
             return false;
     } else {
         str = cx->runtime()->emptyString;
     }
 
     if (args.isConstructing()) {
-        StringObject* strobj = StringObject::create(cx, str);
+        RootedObject proto(cx);
+        RootedObject newTarget(cx, &args.newTarget().toObject());
+        if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
+            return false;
+
+        StringObject* strobj = StringObject::create(cx, str, proto);
         if (!strobj)
             return false;
         args.rval().setObject(*strobj);
         return true;
     }
 
     args.rval().setString(str);
     return true;
--- a/js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
+++ b/js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
@@ -53,16 +53,17 @@ testBuiltin(RegExp, "String Argument");
 testBuiltin(Map);
 testBuiltin(Set);
 testBuiltin(WeakMap);
 testBuiltin(WeakSet);
 testBuiltin(ArrayBuffer);
 testBuiltinTypedArrays();
 testBuiltin(DataView, new ArrayBuffer());
 testBuiltin(DataView, new (newGlobal().ArrayBuffer)());
+testBuiltin(String);
 
 `;
 
 if (classesEnabled())
     eval(test);
 
 if (typeof reportCompare === 'function')
     reportCompare(0,0,"OK");
--- a/js/src/vm/StringObject-inl.h
+++ b/js/src/vm/StringObject-inl.h
@@ -28,19 +28,19 @@ StringObject::init(JSContext* cx, Handle
     MOZ_ASSERT(self->lookup(cx, NameToId(cx->names().length))->slot() == LENGTH_SLOT);
 
     self->setStringThis(str);
 
     return true;
 }
 
 inline StringObject*
-StringObject::create(JSContext* cx, HandleString str, NewObjectKind newKind)
+StringObject::create(JSContext* cx, HandleString str, HandleObject proto, NewObjectKind newKind)
 {
-    JSObject* obj = NewBuiltinClassInstance(cx, &class_, newKind);
+    JSObject* obj = NewObjectWithClassProto(cx, &class_, proto, newKind);
     if (!obj)
         return nullptr;
     Rooted<StringObject*> strobj(cx, &obj->as<StringObject>());
     if (!strobj->init(cx, str))
         return nullptr;
     return strobj;
 }
 
--- a/js/src/vm/StringObject.h
+++ b/js/src/vm/StringObject.h
@@ -24,16 +24,17 @@ class StringObject : public NativeObject
 
     static const Class class_;
 
     /*
      * Creates a new String object boxing the given string.  The object's
      * [[Prototype]] is determined from context.
      */
     static inline StringObject* create(JSContext* cx, HandleString str,
+                                       HandleObject proto = nullptr,
                                        NewObjectKind newKind = GenericObject);
 
     /*
      * Compute the initial shape to associate with fresh String objects, which
      * encodes the initial length property. Return the shape after changing
      * |obj|'s last property to it.
      */
     static Shape*