Bug 1055472 - Part 10: Make the Set constructor properly subclassable. (r=Waldo)
authorEric Faust <efaustbmo@gmail.com>
Fri, 13 Nov 2015 18:22:21 -0800
changeset 309839 57cf6353c9fb31f250c26a93b8a460140359e572
parent 309838 ed1209c6d7e3f2e7dcdc430c53b1d83c323c47a7
child 309840 40b67434bff60d5a3a6a7a5aeeda6c7e1e83b70e
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1055472
milestone45.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 1055472 - Part 10: Make the Set constructor properly subclassable. (r=Waldo)
js/src/builtin/MapObject.cpp
js/src/builtin/MapObject.h
js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1063,29 +1063,29 @@ SetObject::add(JSContext* cx, HandleObje
         ReportOutOfMemory(cx);
         return false;
     }
     WriteBarrierPost(cx->runtime(), set, key.value());
     return true;
 }
 
 SetObject*
-SetObject::create(JSContext* cx)
+SetObject::create(JSContext* cx, HandleObject proto /* = nullptr */)
 {
-    SetObject* obj = NewBuiltinClassInstance<SetObject>(cx);
+    auto set = cx->make_unique<ValueSet>(cx->runtime());
+    if (!set || !set->init()) {
+        ReportOutOfMemory(cx);
+        return nullptr;
+    }
+
+    SetObject* obj = NewObjectWithClassProto<SetObject>(cx, proto);
     if (!obj)
         return nullptr;
 
-    ValueSet* set = cx->new_<ValueSet>(cx->runtime());
-    if (!set || !set->init()) {
-        js_delete(set);
-        ReportOutOfMemory(cx);
-        return nullptr;
-    }
-    obj->setPrivate(set);
+    obj->setPrivate(set.release());
     return obj;
 }
 
 void
 SetObject::mark(JSTracer* trc, JSObject* obj)
 {
     SetObject* setobj = static_cast<SetObject*>(obj);
     if (ValueSet* set = setobj->getData()) {
@@ -1105,17 +1105,22 @@ SetObject::finalize(FreeOp* fop, JSObjec
 bool
 SetObject::construct(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (!ThrowIfNotConstructing(cx, args, "Set"))
         return false;
 
-    Rooted<SetObject*> obj(cx, SetObject::create(cx));
+    RootedObject proto(cx);
+    RootedObject newTarget(cx, &args.newTarget().toObject());
+    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
+        return false;
+
+    Rooted<SetObject*> obj(cx, SetObject::create(cx, proto));
     if (!obj)
         return false;
 
     if (!args.get(0).isNullOrUndefined()) {
         RootedValue adderVal(cx);
         if (!GetProperty(cx, obj, obj, cx->names().add, &adderVal))
             return false;
 
--- a/js/src/builtin/MapObject.h
+++ b/js/src/builtin/MapObject.h
@@ -176,17 +176,17 @@ class SetObject : public NativeObject {
 
     static bool keys(JSContext *cx, HandleObject obj, JS::AutoValueVector *keys);
     static bool values(JSContext *cx, unsigned argc, Value *vp);
     static bool add(JSContext *cx, HandleObject obj, HandleValue key);
     static bool has(JSContext *cx, unsigned argc, Value *vp);
 
     // Publicly exposed Set calls for JSAPI access (webidl maplike/setlike
     // interfaces, etc.)
-    static SetObject* create(JSContext *cx);
+    static SetObject* create(JSContext *cx, HandleObject proto = nullptr);
     static uint32_t size(JSContext *cx, HandleObject obj);
     static bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
     static bool clear(JSContext *cx, HandleObject obj);
     static bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
     static bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
 
   private:
     static const JSPropertySpec properties[];
--- a/js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
+++ b/js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
@@ -28,16 +28,17 @@ testBuiltin(URIError);
 testBuiltin(Number);
 testBuiltin(Date);
 testBuiltin(Date, 5);
 testBuiltin(Date, 5, 10);
 testBuiltin(RegExp);
 testBuiltin(RegExp, /Regexp Argument/);
 testBuiltin(RegExp, "String Argument");
 testBuiltin(Map);
+testBuiltin(Set);
 
 `;
 
 if (classesEnabled())
     eval(test);
 
 if (typeof reportCompare === 'function')
     reportCompare(0,0,"OK");