[ES6] Implement Array.prototype.copyWithin
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 May 2015 18:23:59 +0000 (18:23 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 May 2015 18:23:59 +0000 (18:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=145107

Reviewed by Darin Adler.

Source/JavaScriptCore:

This patch implements ES6 Array.prototype.copyWithin.
It is intended to be used for copying the region to the other region
in the callee array itself safely (like memmove, not memcpy).
This function is proposed in the context of WebGL.

* builtins/Array.prototype.js:
(.maxWithPositives):
(.minWithMaybeNegativeZeroAndPositive):
(copyWithin):
* runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::finishCreation):
* tests/stress/array-copywithin.js: Added.
(shouldBe):
(shouldBeArray):
(shouldThrow):
(arrayToObject):
(valueOf):

LayoutTests:

* js/Object-getOwnPropertyNames-expected.txt:
* js/script-tests/Object-getOwnPropertyNames.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@184863 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/js/Object-getOwnPropertyNames-expected.txt
LayoutTests/js/script-tests/Object-getOwnPropertyNames.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/Array.prototype.js
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/tests/stress/array-copywithin.js [new file with mode: 0644]

index fcb511239ef2fe8dc547d5a9752a598e095afb0c..7bba57b46b4c20a100b8eed11cdf1b777c89af33 100644 (file)
@@ -1,3 +1,13 @@
+2015-05-26  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement Array.prototype.copyWithin
+        https://bugs.webkit.org/show_bug.cgi?id=145107
+
+        Reviewed by Darin Adler.
+
+        * js/Object-getOwnPropertyNames-expected.txt:
+        * js/script-tests/Object-getOwnPropertyNames.js:
+
 2015-05-25  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] Enable IndexedDB
index 3a9c1882cc5f1780afeec1386a4e2413ec32bb1c..45dde12e7e0a3ca6df6ebee7b1b50147443ca1e2 100644 (file)
@@ -46,7 +46,7 @@ PASS getSortedOwnPropertyNames(Object.prototype) is ['__defineGetter__', '__defi
 PASS getSortedOwnPropertyNames(Function) is ['length', 'name', 'prototype']
 PASS getSortedOwnPropertyNames(Function.prototype) is ['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString']
 PASS getSortedOwnPropertyNames(Array) is ['from', 'isArray', 'length', 'name', 'of', 'prototype']
-PASS getSortedOwnPropertyNames(Array.prototype) is ['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift', 'values']
+PASS getSortedOwnPropertyNames(Array.prototype) is ['concat', 'constructor', 'copyWithin', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift', 'values']
 PASS getSortedOwnPropertyNames(String) is ['fromCharCode', 'fromCodePoint', 'length', 'name', 'prototype', 'raw']
 PASS getSortedOwnPropertyNames(String.prototype) is ['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'codePointAt', 'concat', 'constructor', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']
 PASS getSortedOwnPropertyNames(Boolean) is ['length', 'name', 'prototype']
index dd9ecad2dbb60eec3f291fca1512fbd698ff18ac..ff459f150900b1751c7847c49828e0e6a5cba8c7 100644 (file)
@@ -55,7 +55,7 @@ var expectedPropertyNamesSet = {
     "Function": "['length', 'name', 'prototype']",
     "Function.prototype": "['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString']",
     "Array": "['from', 'isArray', 'length', 'name', 'of', 'prototype']",
-    "Array.prototype": "['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift', 'values']",
+    "Array.prototype": "['concat', 'constructor', 'copyWithin', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift', 'values']",
     "String": "['fromCharCode', 'fromCodePoint', 'length', 'name', 'prototype', 'raw']",
     "String.prototype": "['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'codePointAt', 'concat', 'constructor', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']",
     "Boolean": "['length', 'name', 'prototype']",
index 0366de8d1978cabe3dcfc9bbbb427ab8f2fd52ba..675012d66d6948fd5e92fe57007df2f0210d616a 100644 (file)
@@ -1,3 +1,28 @@
+2015-05-26  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement Array.prototype.copyWithin
+        https://bugs.webkit.org/show_bug.cgi?id=145107
+
+        Reviewed by Darin Adler.
+
+        This patch implements ES6 Array.prototype.copyWithin.
+        It is intended to be used for copying the region to the other region
+        in the callee array itself safely (like memmove, not memcpy).
+        This function is proposed in the context of WebGL.
+
+        * builtins/Array.prototype.js:
+        (.maxWithPositives):
+        (.minWithMaybeNegativeZeroAndPositive):
+        (copyWithin):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::ArrayPrototype::finishCreation):
+        * tests/stress/array-copywithin.js: Added.
+        (shouldBe):
+        (shouldBeArray):
+        (shouldThrow):
+        (arrayToObject):
+        (valueOf):
+
 2015-05-26  Dan Bernstein  <mitz@apple.com>
 
         <rdar://problem/21104551> Update build settings
index 28b2bbe5b71280ab128e9dea768f3304c0e76352..b7a334beb6e78759f535638f22e4dfbbf680e59e 100644 (file)
@@ -455,3 +455,61 @@ function sort(comparator)
     comparatorSort(array, comparator);
     return array;
 }
+
+function copyWithin(target, start)
+{
+    "use strict";
+
+    function maxWithPositives(a, b)
+    {
+        return (a < b) ? b : a;
+    }
+
+    function minWithMaybeNegativeZeroAndPositive(maybeNegativeZero, positive)
+    {
+        return (maybeNegativeZero < positive) ? maybeNegativeZero : positive;
+    }
+
+    var thisValue = this;
+    if (thisValue === null || thisValue === undefined)
+        throw new @TypeError("Array.copyWithin requires that |this| be not null or undefined");
+    var thisObject = @Object(thisValue);
+
+    var length = @ToLength(thisObject.length);
+
+    var relativeTarget = @ToInteger(target);
+    var to = (relativeTarget < 0) ? maxWithPositives(length + relativeTarget, 0) : minWithMaybeNegativeZeroAndPositive(relativeTarget, length);
+
+    var relativeStart = @ToInteger(start);
+    var from = (relativeStart < 0) ? maxWithPositives(length + relativeStart, 0) : minWithMaybeNegativeZeroAndPositive(relativeStart, length);
+
+    var relativeEnd;
+    if (arguments.length >= 3) {
+        var end = arguments[2];
+        if (end === undefined)
+            relativeEnd = length;
+        else
+            relativeEnd = @ToInteger(end);
+    } else
+        relativeEnd = length;
+
+    var finalValue = (relativeEnd < 0) ? maxWithPositives(length + relativeEnd, 0) : minWithMaybeNegativeZeroAndPositive(relativeEnd, length);
+
+    var count = minWithMaybeNegativeZeroAndPositive(finalValue - from, length - to);
+
+    var direction = 1;
+    if (from < to && to < from + count) {
+        direction = -1;
+        from = from + count - 1;
+        to = to + count - 1;
+    }
+
+    for (var i = 0; i < count; ++i, from += direction, to += direction) {
+        if (from in thisObject)
+            thisObject[to] = thisObject[from];
+        else
+            delete thisObject[to];
+    }
+
+    return thisObject;
+}
index a4bb3d3d807c54045a1cb7c02546db6af1be2039..96d34d65e08c9e7ef3bd95b8314abcfd3ade860b 100644 (file)
@@ -117,6 +117,7 @@ void ArrayPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     JSC_BUILTIN_FUNCTION("find", arrayPrototypeFindCodeGenerator, DontEnum);
     JSC_BUILTIN_FUNCTION("findIndex", arrayPrototypeFindIndexCodeGenerator, DontEnum);
     JSC_BUILTIN_FUNCTION("includes", arrayPrototypeIncludesCodeGenerator, DontEnum);
+    JSC_BUILTIN_FUNCTION("copyWithin", arrayPrototypeCopyWithinCodeGenerator, DontEnum);
     
     if (!globalObject->runtimeFlags().isSymbolDisabled()) {
         JSObject* unscopables = constructEmptyObject(globalObject->globalExec(), globalObject->nullPrototypeObjectStructure());
diff --git a/Source/JavaScriptCore/tests/stress/array-copywithin.js b/Source/JavaScriptCore/tests/stress/array-copywithin.js
new file mode 100644 (file)
index 0000000..ff7d410
--- /dev/null
@@ -0,0 +1,277 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldBeArray(actual, expected) {
+    shouldBe(actual.length, expected.length);
+    for (var i = 0; i < expected.length; ++i) {
+        try {
+            shouldBe(actual[i], expected[i]);
+        } catch(e) {
+            print(JSON.stringify(actual));
+            throw e;
+        }
+    }
+}
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+shouldBe([].copyWithin.name, 'copyWithin');
+shouldBe([].copyWithin.length, 2);
+shouldBe(Array.prototype.hasOwnProperty('copyWithin'), true);
+shouldBe(JSON.stringify(Object.getOwnPropertyDescriptor(Array.prototype, 'copyWithin')), '{"writable":true,"enumerable":false,"configurable":true}');
+
+// 1 arguments.
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-5), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-4), [1, 1, 2, 3, 4]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-2), [1, 2, 3, 1, 2]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-1), [1, 2, 3, 4, 1]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(1), [1, 1, 2, 3, 4]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(2), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(3), [1, 2, 3, 1, 2]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(4), [1, 2, 3, 4, 1]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(5), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(6), [1, 2, 3, 4, 5]);
+
+// 2 arguments.
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 0), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 1), [2, 3, 4, 5, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 2), [3, 4, 5, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 3), [4, 5, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 4), [5, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 5), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 6), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(1, 3), [1, 4, 5, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(2, 3), [1, 2, 4, 5, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(3, 3), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(4, 3), [1, 2, 3, 4, 4]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(5, 3), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(6, 3), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-1, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-1, -2), [1, 2, 3, 4, 4]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-1, -3), [1, 2, 3, 4, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -3), [3, 4, 5, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -8), [1, 2, 3, 4, 5]);
+
+// 3 arguments.
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 3, 4), [4, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 0, 5), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 1, 1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 1, 2), [2, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 1, 3), [2, 3, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 1, 4), [2, 3, 4, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 1, 5), [2, 3, 4, 5, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 1, 6), [2, 3, 4, 5, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(2, 1, 3), [1, 2, 2, 3, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(6, 1, 3), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -0, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 0, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -1, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -2, -1), [4, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -3, -1), [3, 4, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -4, -1), [2, 3, 4, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -5, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -6, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, 0, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -1, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -2, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -3, -2), [3, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -4, -2), [2, 3, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -5, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -6, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -0, -1), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, 0, -1), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -1, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -2, -1), [1, 2, 4, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -3, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -4, -1), [1, 2, 2, 3, 4]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -5, -1), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -6, -1), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, 0, -2), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -1, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -2, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -3, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -4, -2), [1, 2, 2, 3, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -5, -2), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -6, -2), [1, 2, 1, 2, 3]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -1, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -1, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -1, -3), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -1, -4), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -1, -5), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(0, -1, -6), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -2, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -2, -3), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -2, -4), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-3, -2, -5), [1, 2, 3, 4, 5]);
+
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -0, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 0, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 0, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 0, 5), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 1, 1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 1, 2), [2, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 1, 3), [2, 3, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 1, 4), [2, 3, 4, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 1, 5), [2, 3, 4, 5, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 1, 6), [2, 3, 4, 5, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 1, 3), [2, 3, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 1, 3), [2, 3, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, 3, 4), [4, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -2, -1), [4, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -3, -1), [3, 4, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -4, -1), [2, 3, 4, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -5, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -6, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -2, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -3, -2), [3, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -4, -2), [2, 3, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -5, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -6, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -2, -1), [4, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -3, -1), [3, 4, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -4, -1), [2, 3, 4, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -5, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -6, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -2, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -3, -2), [3, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -4, -2), [2, 3, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -5, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -6, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -1), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -3), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -4), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -5), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -1, -6), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -2, -2), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -2, -3), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -2, -4), [1, 2, 3, 4, 5]);
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-6, -2, -5), [1, 2, 3, 4, 5]);
+
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(NaN, 1), [1, 2, 3, 4, 5].copyWithin(0, 1));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(NaN, NaN, 1), [1, 2, 3, 4, 5].copyWithin(0, 0, 1));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(NaN, NaN, NaN), [1, 2, 3, 4, 5].copyWithin(0, 0, 0));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(Infinity, 0, 1), [1, 2, 3, 4, 5].copyWithin(5, 0, 1));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(Infinity, Infinity, 1), [1, 2, 3, 4, 5].copyWithin(5, 5, 1));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(1, Infinity, 1), [1, 2, 3, 4, 5].copyWithin(1, 5, 1));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(1, -Infinity, 1), [1, 2, 3, 4, 5].copyWithin(1, 0, 1));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(-Infinity, 0, 1), [1, 2, 3, 4, 5].copyWithin(0, 0, 1));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(1, 0, Infinity), [1, 2, 3, 4, 5].copyWithin(1, 0, 5));
+shouldBeArray([1, 2, 3, 4, 5].copyWithin(1, 0, -Infinity), [1, 2, 3, 4, 5].copyWithin(1, 0, 0));
+
+var copyWithin = Array.prototype.copyWithin;
+
+function arrayToObject(array) {
+    var object = {};
+    for (var [key, value] of array.entries()) {
+        object[key] = value;
+    }
+    object.length = array.length;
+    return object;
+}
+var object = arrayToObject([1, 2, 3, 4, 5]);
+object.length = -Infinity;
+shouldBeArray(copyWithin.call(object, 1), { length: -Infinity });
+shouldBe(JSON.stringify(copyWithin.call(object, 1)), '{"0":1,"1":2,"2":3,"3":4,"4":5,"length":null}');
+
+var object = arrayToObject([1, 2, 3, 4, 5]);
+object.length = -Infinity;
+shouldBe(JSON.stringify(copyWithin.call(object, 1)), '{"0":1,"1":2,"2":3,"3":4,"4":5,"length":null}');
+
+var array = [1, 2, 3, 4, 5];
+var same = array.copyWithin(0, 3);
+shouldBeArray(same, [4, 5, 3, 4, 5]);
+shouldBeArray(array, [4, 5, 3, 4, 5]);
+shouldBe(same, array);
+
+shouldBe(JSON.stringify([].copyWithin.call({length: 5, 3: 1}, 0, 3)), '{"0":1,"3":1,"length":5}');
+shouldBe(JSON.stringify([].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4)), '{"0":4,"1":2,"2":3,"3":4,"4":5}');
+
+shouldBe(JSON.stringify([].copyWithin.call({length: 5.5, 3: 1}, 0, 3)), '{"0":1,"3":1,"length":5.5}');
+shouldBe(JSON.stringify([].copyWithin.call({length: 5.5, 3: 1}, 0.1, 3)), '{"0":1,"3":1,"length":5.5}');
+shouldBe(JSON.stringify([].copyWithin.call({length: 5.5, 3: 1}, 0.1, 3.3)), '{"0":1,"3":1,"length":5.5}');
+shouldBe(JSON.stringify([].copyWithin.call({length: 5.5, 3: 1}, 0.1, 3.8)), '{"0":1,"3":1,"length":5.5}');
+shouldBe(JSON.stringify([].copyWithin.call({length: 5.5, 3: 1}, 0.1, 4.1)), '{"3":1,"length":5.5}');
+
+var object = arrayToObject([1, 2, 3, 4, 5]);
+delete object[2];
+delete object[3];
+delete object[4];
+var result = copyWithin.call(object, 0, 3, 5);
+shouldBe(JSON.stringify(result), '{"length":5}');
+
+// 'copyWithin' in Array's @unscopables
+(function () {
+    var array = [];
+    var copyWithin = 42;
+    var forEach = 42;
+    with (array) {
+        shouldBe(copyWithin, 42);
+        shouldBe(forEach, [].forEach);
+    }
+}());
+
+shouldThrow(function () {
+    Array.prototype.copyWithin.call(undefined);
+}, 'TypeError: Array.copyWithin requires that |this| be not null or undefined');
+
+shouldThrow(function () {
+    Array.prototype.copyWithin.call(null);
+}, 'TypeError: Array.copyWithin requires that |this| be not null or undefined');
+
+
+function valueOf(code) {
+    return {
+        valueOf() {
+            throw new Error(code);
+        }
+    };
+}
+
+shouldThrow(function () {
+    var object = arrayToObject([1, 2, 3, 4, 5]);
+    object.length = valueOf(0);
+    copyWithin.call(object, valueOf(1), valueOf(2), valueOf(3));
+}, 'Error: 0');
+
+shouldThrow(function () {
+    var object = arrayToObject([1, 2, 3, 4, 5]);
+    copyWithin.call(object, valueOf(1), valueOf(2), valueOf(3));
+}, 'Error: 1');
+
+shouldThrow(function () {
+    var object = arrayToObject([1, 2, 3, 4, 5]);
+    copyWithin.call(object, 0, valueOf(2), valueOf(3));
+}, 'Error: 2');
+
+shouldThrow(function () {
+    var object = arrayToObject([1, 2, 3, 4, 5]);
+    copyWithin.call(object, 0, 1, valueOf(3));
+}, 'Error: 3');
+
+shouldThrow(function () {
+    var object = arrayToObject([1, 2, 3, 4, 5]);
+    Object.freeze(object);
+    copyWithin.call(object, 0, 1, 2);
+}, 'TypeError: Attempted to assign to readonly property.');