From 1182adb9bc336c2f05a148ccf3beb02f058f25fa Mon Sep 17 00:00:00 2001
From: Rick Waldron <waldron.rick@gmail.com>
Date: Wed, 4 Mar 2015 10:27:04 -0500
Subject: [PATCH] Import tests from Google V8 (Array isConcatSpreadable)

These tests are derived from the following files within the Google V8 project:

    	test/mjsunit/harmony/array-concat.js
---
 .../concat/Array.prototype.concat_arity.js    |  9 ++++
 ...ncat_array-like-length-to-string-throws.js | 22 +++++++++
 ...oncat_array-like-length-value-of-throws.js | 25 ++++++++++
 ...otype.concat_array-like-negative-length.js | 22 +++++++++
 ..._array-like-primitive-non-number-length.js | 20 ++++++++
 ...ototype.concat_array-like-string-length.js | 28 +++++++++++
 ...type.concat_array-like-to-length-throws.js | 21 +++++++++
 .../Array.prototype.concat_array-like.js      | 28 +++++++++++
 .../Array.prototype.concat_descriptor.js      | 11 +++++
 ...prototype.concat_holey-sloppy-arguments.js | 14 ++++++
 ...rray.prototype.concat_large-typed-array.js | 46 +++++++++++++++++++
 .../Array.prototype.concat_length-throws.js   | 23 ++++++++++
 .../Array.prototype.concat_no-prototype.js    | 10 ++++
 .../Array.prototype.concat_non-array.js       | 25 ++++++++++
 ...rototype.concat_sloppy-arguments-throws.js | 18 ++++++++
 ...type.concat_sloppy-arguments-with-dupes.js | 16 +++++++
 ...Array.prototype.concat_sloppy-arguments.js | 16 +++++++
 ...rray.prototype.concat_small-typed-array.js | 45 ++++++++++++++++++
 ...otype.concat_spreadable-boolean-wrapper.js | 36 +++++++++++++++
 ...ay.prototype.concat_spreadable-function.js | 31 +++++++++++++
 ...ototype.concat_spreadable-getter-throws.js | 22 +++++++++
 ...totype.concat_spreadable-number-wrapper.js | 36 +++++++++++++++
 ...ray.prototype.concat_spreadable-reg-exp.js | 34 ++++++++++++++
 ...ototype.concat_spreadable-sparse-object.js | 16 +++++++
 ...totype.concat_spreadable-string-wrapper.js | 25 ++++++++++
 ...Array.prototype.concat_strict-arguments.js | 16 +++++++
 .../Array/prototype/concat/S15.4.4.4_A3_T2.js |  2 +-
 .../Array/prototype/concat/S15.4.4.4_A3_T3.js |  2 +-
 28 files changed, 617 insertions(+), 2 deletions(-)
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_arity.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-to-string-throws.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-value-of-throws.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-negative-length.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-primitive-non-number-length.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-string-length.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-to-length-throws.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_descriptor.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_holey-sloppy-arguments.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_length-throws.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_no-prototype.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_non-array.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-throws.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-with-dupes.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-boolean-wrapper.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-function.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-getter-throws.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-number-wrapper.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-reg-exp.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-sparse-object.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper.js
 create mode 100644 test/built-ins/Array/prototype/concat/Array.prototype.concat_strict-arguments.js

diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_arity.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_arity.js
new file mode 100644
index 0000000000..11de52decb
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_arity.js
@@ -0,0 +1,9 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat arity
+---*/
+assert.sameValue(Array.prototype.concat.length, 1);
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-to-string-throws.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-to-string-throws.js
new file mode 100644
index 0000000000..176c632cfd
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-to-string-throws.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat array like length to string throws
+---*/
+function MyError() {}
+var obj = {
+  "length": { toString: function() {
+      throw new MyError();
+    }, valueOf: null
+  },
+  "1": "A",
+  "3": "B",
+  "5": "C"
+};
+obj[Symbol.isConcatSpreadable] = true;
+assert.throws(MyError, function() {
+  [].concat(obj);
+});
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-value-of-throws.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-value-of-throws.js
new file mode 100644
index 0000000000..982d38769d
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-value-of-throws.js
@@ -0,0 +1,25 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat array like length valueOf throws
+---*/
+function MyError() {}
+var obj = {
+  "length": {
+    valueOf: function() {
+      throw new MyError();
+    },
+    toString: null
+  },
+  "1": "A",
+  "3": "B",
+  "5": "C"
+};
+obj[Symbol.isConcatSpreadable] = true;
+assert.throws(MyError, function() {
+  [].concat(obj);
+});
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-negative-length.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-negative-length.js
new file mode 100644
index 0000000000..c16a442f27
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-negative-length.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat array like negative length
+includes: [compareArray.js]
+---*/
+var obj = {
+  "length": -6,
+  "1": "A",
+  "3": "B",
+  "5": "C"
+};
+obj[Symbol.isConcatSpreadable] = true;
+assert(compareArray([].concat(obj), []));
+obj.length = -6.7;
+assert(compareArray([].concat(obj), []));
+obj.length = "-6";
+assert(compareArray([].concat(obj), []));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-primitive-non-number-length.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-primitive-non-number-length.js
new file mode 100644
index 0000000000..01a242c3b1
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-primitive-non-number-length.js
@@ -0,0 +1,20 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat array like primitive non number length
+includes: [compareArray.js]
+---*/
+var obj = {
+  "1": "A",
+  "3": "B",
+  "5": "C"
+};
+obj[Symbol.isConcatSpreadable] = true;
+obj.length = {toString: function() { return "SIX"; }, valueOf: null };
+assert(compareArray([].concat(obj), []));
+obj.length = {toString: null, valueOf: function() { return "SIX"; } };
+assert(compareArray([].concat(obj), []));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-string-length.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-string-length.js
new file mode 100644
index 0000000000..d47ef8c6f3
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-string-length.js
@@ -0,0 +1,28 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat array like string length
+includes: [compareArray.js]
+---*/
+var obj = {
+  "length": "6",
+  "1": "A",
+  "3": "B",
+  "5": "C"
+};
+obj[Symbol.isConcatSpreadable] = true;
+var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
+var arr = ["X", "Y", "Z"];
+
+var expected = [
+  void 0, "A", void 0, "B", void 0, "C",
+  obj2,
+  "X", "Y", "Z"
+];
+var actual = Array.prototype.concat.call(obj, obj2, arr);
+
+assert(compareArray(actual, expected));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-to-length-throws.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-to-length-throws.js
new file mode 100644
index 0000000000..d0b7458dfa
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like-to-length-throws.js
@@ -0,0 +1,21 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat array like to length throws
+---*/
+var obj = {
+  "length": {valueOf: null, toString: null},
+  "1": "A",
+  "3": "B",
+  "5": "C"
+};
+obj[Symbol.isConcatSpreadable] = true;
+var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
+var arr = ["X", "Y", "Z"];
+assert.throws(TypeError, function() {
+  Array.prototype.concat.call(obj, obj2, arr);
+});
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like.js
new file mode 100644
index 0000000000..3cfe7e59b7
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_array-like.js
@@ -0,0 +1,28 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat array like
+includes: [compareArray.js]
+---*/
+var obj = {
+  "length": 6,
+  "1": "A",
+  "3": "B",
+  "5": "C"
+};
+obj[Symbol.isConcatSpreadable] = true;
+var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
+var arr = ["X", "Y", "Z"];
+
+var expected = [
+  void 0, "A", void 0, "B", void 0, "C",
+  obj2,
+  "X", "Y", "Z"
+];
+var actual = Array.prototype.concat.call(obj, obj2, arr);
+
+assert(compareArray(actual, expected));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_descriptor.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_descriptor.js
new file mode 100644
index 0000000000..b2c0a167f4
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_descriptor.js
@@ -0,0 +1,11 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat descriptor
+---*/
+var desc = Object.getOwnPropertyDescriptor(Array.prototype, "concat");
+assert.sameValue(desc.enumerable, false);
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_holey-sloppy-arguments.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_holey-sloppy-arguments.js
new file mode 100644
index 0000000000..8519574a0b
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_holey-sloppy-arguments.js
@@ -0,0 +1,14 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat holey sloppy arguments
+includes: [compareArray.js]
+---*/
+var args = (function(a) { return arguments; })(1,2,3);
+delete args[1];
+args[Symbol.isConcatSpreadable] = true;
+assert(compareArray([1, void 0, 3, 1, void 0, 3], [].concat(args, args)));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js
new file mode 100644
index 0000000000..d5f4e0e966
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js
@@ -0,0 +1,46 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat large typed array
+includes: [compareArray.js]
+---*/
+function concatTypedArray(type, elems, modulo) {
+  var items = new Array(elems);
+  var ta_by_len = new type(elems);
+  for (var i = 0; i < elems; ++i) {
+    ta_by_len[i] = items[i] = modulo === false ? i : elems % modulo;
+  }
+  var ta = new type(items);
+  assert(compareArray([].concat(ta, ta), [ta, ta]));
+  ta[Symbol.isConcatSpreadable] = true;
+  assert(compareArray([].concat(ta), items));
+
+  assert(compareArray([].concat(ta_by_len, ta_by_len), [ta_by_len, ta_by_len]));
+  ta_by_len[Symbol.isConcatSpreadable] = true;
+  assert(compareArray([].concat(ta_by_len), items));
+
+  // TypedArray with fake `length`.
+  ta = new type(1);
+  var defValue = ta[0];
+  var expected = new Array(4000);
+  expected[0] = defValue;
+
+  Object.defineProperty(ta, "length", { value: 4000 });
+  ta[Symbol.isConcatSpreadable] = true;
+  assert(compareArray([].concat(ta), expected));
+}
+
+var max = [Math.pow(2, 8), Math.pow(2, 16), Math.pow(2, 32), false, false];
+[
+  Uint8Array,
+  Uint16Array,
+  Uint32Array,
+  Float32Array,
+  Float64Array
+].forEach(function(ctor, i) {
+  concatTypedArray(ctor, 4000, max[i]);
+});
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_length-throws.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_length-throws.js
new file mode 100644
index 0000000000..4f40007370
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_length-throws.js
@@ -0,0 +1,23 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat length throws
+---*/
+function MyError() {}
+var obj = {};
+obj[Symbol.isConcatSpreadable] = true;
+Object.defineProperty(obj, "length", {
+  get: function() { throw new MyError(); }
+});
+
+assert.throws(MyError, function() {
+  [].concat(obj);
+});
+
+assert.throws(MyError, function() {
+  Array.prototype.concat.call(obj, 1, 2, 3);
+});
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_no-prototype.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_no-prototype.js
new file mode 100644
index 0000000000..ebd38238a8
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_no-prototype.js
@@ -0,0 +1,10 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat no prototype
+---*/
+assert.sameValue(Array.prototype.concat.prototype, void 0);
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_non-array.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_non-array.js
new file mode 100644
index 0000000000..a6ed1b23cf
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_non-array.js
@@ -0,0 +1,25 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: array-concat-non-array
+includes: [compareArray.js]
+---*/
+
+//
+// test262 --command "v8 --harmony-classes  --harmony_object_literals" array-concat-non-array
+//
+class NonArray {
+  constructor() {
+    Array.apply(this, arguments);
+  }
+}
+
+var obj = new NonArray(1,2,3);
+var result = Array.prototype.concat.call(obj, 4, 5, 6);
+assert.sameValue(Array, result.constructor);
+assert.sameValue(result instanceof NonArray, false);
+assert(compareArray(result, [obj,4,5,6]));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-throws.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-throws.js
new file mode 100644
index 0000000000..f13263f9bc
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-throws.js
@@ -0,0 +1,18 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat sloppy arguments throws
+---*/
+function MyError() {}
+var args = (function(a) { return arguments; })(1,2,3);
+Object.defineProperty(args, 0, {
+  get: function() { throw new MyError(); }
+});
+args[Symbol.isConcatSpreadable] = true;
+assert.throws(MyError, function() {
+  return [].concat(args, args);
+});
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-with-dupes.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-with-dupes.js
new file mode 100644
index 0000000000..7e5d67b2b1
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-with-dupes.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat sloppy arguments with dupes
+includes: [compareArray.js]
+---*/
+var args = (function(a, a, a) { return arguments; })(1,2,3);
+args[Symbol.isConcatSpreadable] = true;
+assert(compareArray([].concat(args, args), [1, 2, 3, 1, 2, 3]));
+
+Object.defineProperty(args, "length", { value: 6 });
+assert(compareArray([].concat(args), [1, 2, 3, void 0, void 0, void 0]));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments.js
new file mode 100644
index 0000000000..3cfc75df5e
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat sloppy arguments
+includes: [compareArray.js]
+---*/
+var args = (function(a, b, c) { return arguments; })(1,2,3);
+args[Symbol.isConcatSpreadable] = true;
+assert(compareArray([].concat(args, args), [1, 2, 3, 1, 2, 3]));
+
+Object.defineProperty(args, "length", { value: 6 });
+assert(compareArray([].concat(args), [1, 2, 3, void 0, void 0, void 0]));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js
new file mode 100644
index 0000000000..b126c746f3
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js
@@ -0,0 +1,45 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat small typed array
+includes: [compareArray.js]
+---*/
+function concatTypedArray(type, elems, modulo) {
+  var items = new Array(elems);
+  var ta_by_len = new type(elems);
+  for (var i = 0; i < elems; ++i) {
+    ta_by_len[i] = items[i] = modulo === false ? i : elems % modulo;
+  }
+  var ta = new type(items);
+  assert(compareArray([].concat(ta, ta), [ta, ta]));
+  ta[Symbol.isConcatSpreadable] = true;
+  assert(compareArray([].concat(ta), items));
+
+  assert(compareArray([].concat(ta_by_len, ta_by_len), [ta_by_len, ta_by_len]));
+  ta_by_len[Symbol.isConcatSpreadable] = true;
+  assert(compareArray([].concat(ta_by_len), items));
+
+  // TypedArray with fake `length`.
+  ta = new type(1);
+  var defValue = ta[0];
+  var expected = new Array(4000);
+  expected[0] = defValue;
+
+  Object.defineProperty(ta, "length", { value: 4000 });
+  ta[Symbol.isConcatSpreadable] = true;
+  assert(compareArray([].concat(ta), expected));
+}
+var max = [Math.pow(2, 8), Math.pow(2, 16), Math.pow(2, 32), false, false];
+[
+  Uint8Array,
+  Uint16Array,
+  Uint32Array,
+  Float32Array,
+  Float64Array
+].forEach(function(ctor, i) {
+  concatTypedArray(ctor, 1, max[i]);
+});
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-boolean-wrapper.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-boolean-wrapper.js
new file mode 100644
index 0000000000..b62193df4e
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-boolean-wrapper.js
@@ -0,0 +1,36 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat Symbol.isConcatSpreadable boolean wrapper
+includes: [compareArray.js]
+---*/
+var bool = new Boolean(true)
+// Boolean wrapper objects are not concat-spreadable by default
+assert(compareArray([bool], [].concat(bool)));
+
+// Boolean wrapper objects may be individually concat-spreadable
+bool[Symbol.isConcatSpreadable] = true;
+bool.length = 3;
+bool[0] = 1, bool[1] = 2, bool[2] = 3;
+assert(compareArray([1, 2, 3], [].concat(bool)));
+
+Boolean.prototype[Symbol.isConcatSpreadable] = true;
+// Boolean wrapper objects may be concat-spreadable
+assert(compareArray([], [].concat(new Boolean(true))));
+Boolean.prototype[0] = 1;
+Boolean.prototype[1] = 2;
+Boolean.prototype[2] = 3;
+Boolean.prototype.length = 3;
+assert(compareArray([1,2,3], [].concat(new Boolean(true))));
+
+// Boolean values are never concat-spreadable
+assert(compareArray([true], [].concat(true)));
+delete Boolean.prototype[Symbol.isConcatSpreadable];
+delete Boolean.prototype[0];
+delete Boolean.prototype[1];
+delete Boolean.prototype[2];
+delete Boolean.prototype.length;
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-function.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-function.js
new file mode 100644
index 0000000000..8a1d0edacb
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-function.js
@@ -0,0 +1,31 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat Symbol.isConcatSpreadable function
+includes: [compareArray.js]
+---*/
+var fn = function(a, b, c) {}
+// Functions are not concat-spreadable by default
+assert(compareArray([fn], [].concat(fn)));
+
+// Functions may be individually concat-spreadable
+fn[Symbol.isConcatSpreadable] = true;
+fn[0] = 1, fn[1] = 2, fn[2] = 3;
+assert(compareArray([1, 2, 3], [].concat(fn)));
+
+Function.prototype[Symbol.isConcatSpreadable] = true;
+// Functions may be concat-spreadable
+assert(compareArray([void 0, void 0, void 0], [].concat(function(a,b,c) {})));
+Function.prototype[0] = 1;
+Function.prototype[1] = 2;
+Function.prototype[2] = 3;
+assert(compareArray([1,2,3], [].concat(function(a, b, c) {})));
+
+delete Function.prototype[Symbol.isConcatSpreadable];
+delete Function.prototype[0];
+delete Function.prototype[1];
+delete Function.prototype[2];
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-getter-throws.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-getter-throws.js
new file mode 100644
index 0000000000..98e7d98de0
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-getter-throws.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat Symbol.isConcatSpreadable getter throws
+---*/
+function MyError() {}
+var obj = {};
+Object.defineProperty(obj, Symbol.isConcatSpreadable, {
+  get: function() { throw new MyError(); }
+});
+
+assert.throws(MyError, function() {
+  [].concat(obj);
+});
+
+assert.throws(MyError, function() {
+  Array.prototype.concat.call(obj, 1, 2, 3);
+});
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-number-wrapper.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-number-wrapper.js
new file mode 100644
index 0000000000..3319415333
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-number-wrapper.js
@@ -0,0 +1,36 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat Symbol.isConcatSpreadable number wrapper
+includes: [compareArray.js]
+---*/
+var num = new Number(true)
+// Number wrapper objects are not concat-spreadable by default
+assert(compareArray([num], [].concat(num)));
+
+// Number wrapper objects may be individually concat-spreadable
+num[Symbol.isConcatSpreadable] = true;
+num.length = 3;
+num[0] = 1, num[1] = 2, num[2] = 3;
+assert(compareArray([1, 2, 3], [].concat(num)));
+
+Number.prototype[Symbol.isConcatSpreadable] = true;
+// Number wrapper objects may be concat-spreadable
+assert(compareArray([], [].concat(new Number(123))));
+Number.prototype[0] = 1;
+Number.prototype[1] = 2;
+Number.prototype[2] = 3;
+Number.prototype.length = 3;
+assert(compareArray([1,2,3], [].concat(new Number(123))));
+
+// Number values are never concat-spreadable
+assert(compareArray([true], [].concat(true)));
+delete Number.prototype[Symbol.isConcatSpreadable];
+delete Number.prototype[0];
+delete Number.prototype[1];
+delete Number.prototype[2];
+delete Number.prototype.length;
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-reg-exp.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-reg-exp.js
new file mode 100644
index 0000000000..f3c60a3658
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-reg-exp.js
@@ -0,0 +1,34 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat Symbol.isConcatSpreadable reg exp
+includes: [compareArray.js]
+---*/
+var re = /abc/;
+// RegExps are not concat-spreadable by default
+assert(compareArray([].concat(re), [re]));
+
+// RegExps may be individually concat-spreadable
+re[Symbol.isConcatSpreadable] = true;
+re[0] = 1, re[1] = 2, re[2] = 3, re.length = 3;
+assert(compareArray([].concat(re), [1, 2, 3]));
+
+// RegExps may be concat-spreadable
+RegExp.prototype[Symbol.isConcatSpreadable] = true;
+RegExp.prototype.length = 3;
+
+assert(compareArray([].concat(/abc/), [void 0, void 0, void 0]));
+RegExp.prototype[0] = 1;
+RegExp.prototype[1] = 2;
+RegExp.prototype[2] = 3;
+assert(compareArray([].concat(/abc/), [1,2,3]));
+
+delete RegExp.prototype[Symbol.isConcatSpreadable];
+delete RegExp.prototype[0];
+delete RegExp.prototype[1];
+delete RegExp.prototype[2];
+delete RegExp.prototype.length;
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-sparse-object.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-sparse-object.js
new file mode 100644
index 0000000000..e657331386
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-sparse-object.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat Symbol.isConcatSpreadable sparse object
+includes: [compareArray.js]
+---*/
+var obj = { length: 5 };
+obj[Symbol.isConcatSpreadable] = true;
+assert(compareArray([void 0, void 0, void 0, void 0, void 0], [].concat(obj)));
+
+obj.length = 4000;
+assert(compareArray(new Array(4000), [].concat(obj)));
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper.js
new file mode 100644
index 0000000000..3983b68fcd
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper.js
@@ -0,0 +1,25 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat Symbol.isConcatSpreadable string wrapper
+includes: [compareArray.js]
+---*/
+var str1 = new String("yuck\uD83D\uDCA9")
+// String wrapper objects are not concat-spreadable by default
+assert(compareArray([str1], [].concat(str1)));
+
+// String wrapper objects may be individually concat-spreadable
+str1[Symbol.isConcatSpreadable] = true;
+assert(compareArray(["y", "u", "c", "k", "\uD83D", "\uDCA9"], [].concat(str1)));
+
+String.prototype[Symbol.isConcatSpreadable] = true;
+// String wrapper objects may be concat-spreadable
+assert(compareArray(["y", "u", "c", "k", "\uD83D", "\uDCA9"], [].concat(new String("yuck\uD83D\uDCA9"))));
+
+// String values are never concat-spreadable
+assert(compareArray(["yuck\uD83D\uDCA9"], [].concat("yuck\uD83D\uDCA9")));
+delete String.prototype[Symbol.isConcatSpreadable];
diff --git a/test/built-ins/Array/prototype/concat/Array.prototype.concat_strict-arguments.js b/test/built-ins/Array/prototype/concat/Array.prototype.concat_strict-arguments.js
new file mode 100644
index 0000000000..5c24876d17
--- /dev/null
+++ b/test/built-ins/Array/prototype/concat/Array.prototype.concat_strict-arguments.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/*---
+es6id: 22.1.3.1_3
+description: Array.prototype.concat strict arguments
+includes: [compareArray.js]
+---*/
+var args = (function(a, b, c) { "use strict"; return arguments; })(1,2,3);
+args[Symbol.isConcatSpreadable] = true;
+assert(compareArray([].concat(args, args), [1, 2, 3, 1, 2, 3]));
+
+Object.defineProperty(args, "length", { value: 6 });
+assert(compareArray([].concat(args), [1, 2, 3, void 0, void 0, void 0]));
diff --git a/test/built-ins/Array/prototype/concat/S15.4.4.4_A3_T2.js b/test/built-ins/Array/prototype/concat/S15.4.4.4_A3_T2.js
index 771862b347..68dc0eab1a 100644
--- a/test/built-ins/Array/prototype/concat/S15.4.4.4_A3_T2.js
+++ b/test/built-ins/Array/prototype/concat/S15.4.4.4_A3_T2.js
@@ -1,4 +1,4 @@
-// Copyright 2014 Ecma International.  All rights reserved.
+// Copyright (c) 2014 Ecma International.  All rights reserved.
 // See LICENSE or https://github.com/tc39/test262/blob/master/LICENSE
 
 /*---
diff --git a/test/built-ins/Array/prototype/concat/S15.4.4.4_A3_T3.js b/test/built-ins/Array/prototype/concat/S15.4.4.4_A3_T3.js
index 8435746525..f85c78b1bc 100644
--- a/test/built-ins/Array/prototype/concat/S15.4.4.4_A3_T3.js
+++ b/test/built-ins/Array/prototype/concat/S15.4.4.4_A3_T3.js
@@ -1,4 +1,4 @@
-// Copyright 2014 Ecma International.  All rights reserved.
+// Copyright (c) 2014 Ecma International.  All rights reserved.
 // See LICENSE or https://github.com/tc39/test262/blob/master/LICENSE
 
 /*---
-- 
GitLab