Bug 1041586 - Use IsConcatSpreadable in Array.prototype.concat. r=arai
☠☠ backed out by fe492b1cbc39 ☠ ☠
authorTom Schuster <evilpies@gmail.com>
Sat, 16 Apr 2016 12:22:12 +0200
changeset 331402 2021fd52a8c9e4c19282b8dfd92f60974c9fd52e
parent 331401 db1b027cbeb1e04236b8fea7a62a25683e63e064
child 331403 35b1a010cb9fe88ee4975e7c7e6291096bd4a748
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1041586
milestone48.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 1041586 - Use IsConcatSpreadable in Array.prototype.concat. r=arai
js/src/builtin/Array.js
js/src/vm/GlobalObject.cpp
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -937,16 +937,33 @@ function ArraySpeciesCreate(originalArra
     // Step 7.
     if (!IsConstructor(C))
         ThrowTypeError(JSMSG_NOT_CONSTRUCTOR, "constructor property");
 
     // Step 8.
     return new C(length);
 }
 
+// ES 2017 draft (April 8, 2016) 22.1.3.1.1
+function IsConcatSpreadable(O) {
+    // Step 1.
+    if (!IsObject(O))
+        return false;
+
+    // Step 2.
+    var spreadable = O[std_isConcatSpreadable];
+
+    // Step 3.
+    if (spreadable !== undefined)
+        return ToBoolean(spreadable);
+
+    // Step 4.
+    return IsArray(O);
+}
+
 // ES 2016 draft Mar 25, 2016 22.1.3.1.
 // Note: Array.prototype.concat.length is 1.
 function ArrayConcat(arg1) {
     // Step 1.
     var O = ToObject(this);
 
     // Step 2.
     var A = ArraySpeciesCreate(O, 0);
@@ -960,18 +977,17 @@ function ArrayConcat(arg1) {
     var i = 0, argsLen = arguments.length;
 
     // Step 5.a (first element).
     var E = O;
 
     var k, len;
     while (true) {
         // Steps 5.b-c.
-        // IsArray should be replaced with IsConcatSpreadable (bug 1041586).
-        if (IsArray(E)) {
+        if (IsConcatSpreadable(E)) {
             // Step 5.c.ii.
             len = ToLength(E.length);
 
             // Step 5.c.iii.
             if (n + len > MAX_NUMERIC_INDEX)
                 ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
 
             if (IsPackedArray(E)) {
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -440,16 +440,24 @@ GlobalObject::initSelfHostingBuiltins(JS
 {
     // Define a top-level property 'undefined' with the undefined value.
     if (!DefineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
                         nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return false;
     }
 
+    RootedValue std_isConcatSpreadable(cx);
+    std_isConcatSpreadable.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::isConcatSpreadable));
+    if (!JS_DefineProperty(cx, global, "std_isConcatSpreadable", std_isConcatSpreadable,
+                           JSPROP_PERMANENT | JSPROP_READONLY))
+    {
+        return false;
+    }
+
     // Define a top-level property 'std_iterator' with the name of the method
     // used by for-of loops to create an iterator.
     RootedValue std_iterator(cx);
     std_iterator.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::iterator));
     if (!JS_DefineProperty(cx, global, "std_iterator", std_iterator,
                            JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return false;