Bug 1055472 - Part 7: Make the Date constructor properly subclassable. (r=Waldo)
authorEric Faust <efaustbmo@gmail.com>
Fri, 13 Nov 2015 18:22:21 -0800
changeset 275609 ad1086bc97448cdc735af0a012ef07a57bbf1698
parent 275608 628c1d07a0e985b01b5342473ef3d0af7a44701d
child 275610 e22cd35d3c39d5719a98a6602f75496f1d9672e8
push id68893
push userefaustbmo@gmail.com
push dateFri, 04 Dec 2015 06:36:43 +0000
treeherdermozilla-inbound@ca6084eaafbf [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 7: Make the Date constructor properly subclassable. (r=Waldo)
js/src/jsdate.cpp
js/src/jsdate.h
js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -3011,17 +3011,24 @@ static const JSFunctionSpec date_methods
     JS_FN(js_valueOf_str,        date_valueOf,            0,0),
     JS_SYM_FN(toPrimitive,       date_toPrimitive,        1,JSPROP_READONLY),
     JS_FS_END
 };
 
 static bool
 NewDateObject(JSContext* cx, const CallArgs& args, ClippedTime t)
 {
-    JSObject* obj = NewDateObjectMsec(cx, t);
+    MOZ_ASSERT(args.isConstructing());
+
+    RootedObject proto(cx);
+    RootedObject newTarget(cx, &args.newTarget().toObject());
+    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
+        return false;
+
+    JSObject* obj = NewDateObjectMsec(cx, t, proto);
     if (!obj)
         return false;
 
     args.rval().setObject(*obj);
     return true;
 }
 
 static bool
@@ -3255,19 +3262,19 @@ const Class DateObject::protoClass_ = {
         nullptr,
         nullptr,
         nullptr,
         ClassSpec::IsDelegated
     }
 };
 
 JSObject*
-js::NewDateObjectMsec(JSContext* cx, ClippedTime t)
+js::NewDateObjectMsec(JSContext* cx, ClippedTime t, HandleObject proto /* = nullptr */)
 {
-    JSObject* obj = NewBuiltinClassInstance(cx, &DateObject::class_);
+    JSObject* obj = NewObjectWithClassProto(cx, &DateObject::class_, proto);
     if (!obj)
         return nullptr;
     obj->as<DateObject>().setUTCTime(t);
     return obj;
 }
 
 JS_FRIEND_API(JSObject*)
 js::NewDateObject(JSContext* cx, int year, int mon, int mday,
--- a/js/src/jsdate.h
+++ b/js/src/jsdate.h
@@ -25,17 +25,17 @@ namespace js {
  * These functions provide a C interface to the date/time object
  */
 
 /*
  * Construct a new Date Object from a time value given in milliseconds UTC
  * since the epoch.
  */
 extern JSObject*
-NewDateObjectMsec(JSContext* cx, JS::ClippedTime t);
+NewDateObjectMsec(JSContext* cx, JS::ClippedTime t, JS::HandleObject proto = nullptr);
 
 /*
  * Construct a new Date Object from an exploded local time value.
  *
  * Assert that mon < 12 to help catch off-by-one user errors, which are common
  * due to the 0-based month numbering copied into JS from Java (java.util.Date
  * in 1995).
  */
--- a/js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
+++ b/js/src/tests/ecma_6/Class/extendBuiltinConstructors.js
@@ -1,19 +1,19 @@
 var test = `
 
-function testBuiltin(builtin) {
+function testBuiltin(builtin, ...args) {
     class inst extends builtin {
-        constructor() {
-            super();
+        constructor(...args) {
+            super(...args);
             this.called = true;
         }
     }
 
-    let instance = new inst();
+    let instance = new inst(...args);
     assertEq(instance instanceof inst, true);
     assertEq(instance instanceof builtin, true);
     assertEq(instance.called, true);
 }
 
 
 testBuiltin(Function);
 testBuiltin(Object);
@@ -21,16 +21,19 @@ testBuiltin(Boolean);
 testBuiltin(Error);
 testBuiltin(EvalError);
 testBuiltin(RangeError);
 testBuiltin(ReferenceError);
 testBuiltin(SyntaxError);
 testBuiltin(TypeError);
 testBuiltin(URIError);
 testBuiltin(Number);
+testBuiltin(Date);
+testBuiltin(Date, 5);
+testBuiltin(Date, 5, 10);
 
 `;
 
 if (classesEnabled())
     eval(test);
 
 if (typeof reportCompare === 'function')
     reportCompare(0,0,"OK");