Bug 1145058 - Annotate the SpeciesConstructor utility function with step-by-step comment numbering to make clear where we do (and do not!) follow the spec. Also fix issues related to our half-pretense of implementing this method without having first implemented the well-known @@species symbol. r=efaust
authorJeff Walden <jwalden@mit.edu>
Wed, 25 Mar 2015 23:33:49 -0400
changeset 264975 e0e5bd4702b302ccd29a5b2cdb34306599265574
parent 264974 7c2073c5cc7e3a1133937afd65b54d80aea424b2
child 264976 b3abbecbd3c1b145b743db740df70f6c87b2beaa
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1145058
milestone39.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 1145058 - Annotate the SpeciesConstructor utility function with step-by-step comment numbering to make clear where we do (and do not!) follow the spec. Also fix issues related to our half-pretense of implementing this method without having first implemented the well-known @@species symbol. r=efaust
js/src/builtin/Utilities.js
js/src/tests/ecma_6/TypedArray/slice.js
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -149,18 +149,40 @@ function GetIterator(obj, method) {
     // Step 5.
     if (!IsObject(iterator))
         ThrowError(JSMSG_NOT_ITERABLE, ToString(iterator));
 
     // Step 6.
     return iterator;
 }
 
+// ES6 draft 20150317 7.3.20.
 function SpeciesConstructor(obj, defaultConstructor) {
-    var C = obj.constructor;
-    if (C === undefined) {
+    // Step 1.
+    assert(IsObject(obj), "not passed an object");
+
+    // Steps 2-3.
+    var ctor = obj.constructor;
+
+    // Step 4.
+    if (ctor === undefined)
         return defaultConstructor;
-    }
-    if (!IsConstructor(C)) {
-        ThrowError(JSMSG_NOT_CONSTRUCTOR, DecompileArg(1, C));
-    }
-    return C;
+
+    // Step 5.
+    if (!IsObject(ctor))
+        ThrowError(JSMSG_NOT_NONNULL_OBJECT, "object's 'constructor' property");
+
+    // Steps 6-7.  We don't yet implement @@species and Symbol.species, so we
+    // don't implement this correctly right now.  Somebody fix this!
+    var s = /* ctor[Symbol.species] */ undefined;
+
+    // Step 8.
+    if (s === undefined || s === null)
+        return defaultConstructor;
+
+    // Step 9.
+    if (IsConstructor(s))
+        return s;
+
+    // Step 10.
+    ThrowError(JSMSG_NOT_CONSTRUCTOR,
+               "@@species property of object's constructor");
 }
--- a/js/src/tests/ecma_6/TypedArray/slice.js
+++ b/js/src/tests/ecma_6/TypedArray/slice.js
@@ -56,19 +56,22 @@ for (var constructor of constructors) {
     undefConstructor.constructor = undefined;
     assertDeepEq(undefConstructor.slice(1), new constructor(1));
 
     assertThrowsInstanceOf(() => {
         var strConstructor = new constructor;
         strConstructor.constructor = "not a constructor";
         strConstructor.slice(123);
     }, TypeError, "Assert that we have an invalid constructor");
-    assertThrowsInstanceOf(() => {
-        var mathConstructor = new constructor;
-        mathConstructor.constructor = Math.sin;
-        mathConstructor.slice(123);
-    }, TypeError, "Assert that we have an invalid constructor");
 
+    // If obj.constructor[@@species] is undefined or null -- which it has to be
+    // if we don't implement @@species -- then the default constructor is used.
+    var mathConstructor = new constructor(8);
+    mathConstructor.constructor = Math.sin;
+    assertDeepEq(mathConstructor.slice(4), new constructor(4));
+
+    assertEq("species" in Symbol, false,
+             "you've implemented @@species -- add real tests here!");
 }
 
 if (typeof reportCompare === "function")
     reportCompare(true, true);