diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2555b5a572..8331a39b73 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -290,6 +290,7 @@ Function | Purpose
`assert.sameValue(actual, expected, message)` | throw a new Test262Error instance if the first two arguments are not [the same value](https://tc39.github.io/ecma262/#sec-samevalue); accepts an optional string message explaining the scenario and what should have happened
`assert.notSameValue(actual, unexpected, message)` | throw a new Test262Error instance if the first two arguments are [the same value](https://tc39.github.io/ecma262/#sec-samevalue); accepts an optional string message explaining the scenario and what should have happened
`assert.throws(expectedErrorConstructor, fn, message)` | throw a new Test262Error instance if the provided function does not throw an error or if the constructor of the value thrown does not match the provided constructor; accepts an optional string message explaining the scenario and what should have happened
+`assert.compareArray(actual, expected, message)` | throw a new Test262Error instance if the first two arguments have differing `length` or there is an array index less than that length at which their respective elements are not [the same value](https://tc39.github.io/ecma262/#sec-samevalue); accepts an optional string message explaining the scenario and what should have happened
`$DONOTEVALUATE()` | throw an exception if the code gets evaluated. This may only be used in [negative test cases for parsing errors](#handling-errors-and-negative-test-cases).
`throw "Test262: This statement should not be evaluated.";` | throw an exception if the code gets evaluated. Use this if the test file has the `raw` flag and it's a negative test case for parsing error.
diff --git a/harness/assert.js b/harness/assert.js
index 70fb490fd9..7ced0cd0b4 100644
--- a/harness/assert.js
+++ b/harness/assert.js
@@ -101,6 +101,45 @@ assert.throws = function (expectedErrorConstructor, func, message) {
throw new Test262Error(message);
};
+function isPrimitive(value) {
+ return !value || (typeof value !== 'object' && typeof value !== 'function');
+}
+
+assert.compareArray = function (actual, expected, message) {
+ message = message === undefined ? '' : message;
+
+ if (typeof message === 'symbol') {
+ message = message.toString();
+ }
+
+ if (isPrimitive(actual)) {
+ assert(false, `Actual argument [${actual}] shouldn't be primitive. ${message}`);
+ } else if (isPrimitive(expected)) {
+ assert(false, `Expected argument [${expected}] shouldn't be primitive. ${message}`);
+ }
+ var result = compareArray(actual, expected);
+ if (result) return;
+
+ var format = compareArray.format;
+ assert(false, `Actual ${format(actual)} and expected ${format(expected)} should have the same contents. ${message}`);
+};
+
+function compareArray(a, b) {
+ if (b.length !== a.length) {
+ return false;
+ }
+ for (var i = 0; i < a.length; i++) {
+ if (!assert._isSameValue(b[i], a[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+compareArray.format = function (arrayLike) {
+ return `[${Array.prototype.map.call(arrayLike, String).join(', ')}]`;
+};
+
assert._formatIdentityFreeValue = function formatIdentityFreeValue(value) {
switch (value === null ? 'null' : typeof value) {
case 'string':
diff --git a/harness/compareArray.js b/harness/compareArray.js
index 2af35eeae3..dfeef3fe6b 100644
--- a/harness/compareArray.js
+++ b/harness/compareArray.js
@@ -2,49 +2,6 @@
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
- Compare the contents of two arrays
+ Deprecated now that compareArray is defined in assert.js.
defines: [compareArray]
---*/
-
-function compareArray(a, b) {
- if (b.length !== a.length) {
- return false;
- }
-
- for (var i = 0; i < a.length; i++) {
- if (!compareArray.isSameValue(b[i], a[i])) {
- return false;
- }
- }
- return true;
-}
-
-compareArray.isSameValue = function(a, b) {
- if (a === 0 && b === 0) return 1 / a === 1 / b;
- if (a !== a && b !== b) return true;
-
- return a === b;
-};
-
-compareArray.format = function(arrayLike) {
- return `[${[].map.call(arrayLike, String).join(', ')}]`;
-};
-
-assert.compareArray = function(actual, expected, message) {
- message = message === undefined ? '' : message;
-
- if (typeof message === 'symbol') {
- message = message.toString();
- }
-
- assert(actual != null, `Actual argument shouldn't be nullish. ${message}`);
- assert(expected != null, `Expected argument shouldn't be nullish. ${message}`);
- var format = compareArray.format;
- var result = compareArray(actual, expected);
-
- // The following prevents actual and expected from being iterated and evaluated
- // more than once unless absolutely necessary.
- if (!result) {
- assert(false, `Actual ${format(actual)} and expected ${format(expected)} should have the same contents. ${message}`);
- }
-};
diff --git a/test/harness/compare-array-falsy-arguments.js b/test/harness/compare-array-falsy-arguments.js
index 1b17976401..9cbc38acd2 100644
--- a/test/harness/compare-array-falsy-arguments.js
+++ b/test/harness/compare-array-falsy-arguments.js
@@ -20,9 +20,9 @@ function assertThrows(func, errorMessage) {
assert(caught, `Expected ${func} to throw, but it didn't.`);
}
-assertThrows(() => assert.compareArray(), "Actual argument shouldn't be nullish. ");
-assertThrows(() => assert.compareArray(null, []), "Actual argument shouldn't be nullish. ");
-assertThrows(() => assert.compareArray(null, [], "foo"), "Actual argument shouldn't be nullish. foo");
+assertThrows(() => assert.compareArray(), "Actual argument [undefined] shouldn't be primitive. ");
+assertThrows(() => assert.compareArray(null, []), "Actual argument [null] shouldn't be primitive. ");
+assertThrows(() => assert.compareArray(null, [], "foo"), "Actual argument [null] shouldn't be primitive. foo");
-assertThrows(() => assert.compareArray([]), "Expected argument shouldn't be nullish. ");
-assertThrows(() => assert.compareArray([], undefined, "foo"), "Expected argument shouldn't be nullish. foo");
+assertThrows(() => assert.compareArray([]), "Expected argument [undefined] shouldn't be primitive. ");
+assertThrows(() => assert.compareArray([], undefined, "foo"), "Expected argument [undefined] shouldn't be primitive. foo");
diff --git a/test/staging/built-ins/RegExp/named-groups/duplicate-named-groups-replace.js b/test/staging/built-ins/RegExp/named-groups/duplicate-named-groups-replace.js
index cf4d9e5368..72abd134ff 100644
--- a/test/staging/built-ins/RegExp/named-groups/duplicate-named-groups-replace.js
+++ b/test/staging/built-ins/RegExp/named-groups/duplicate-named-groups-replace.js
@@ -4,25 +4,24 @@
/*---
description: Test replace function with duplicate names in alteration.
features: [regexp-duplicate-named-groups]
-includes: [compareArray.js]
---*/
-assert.compareArray(
+assert.sameValue(
'2xyy', 'xxyy'.replace(/(?:(?:(?x)|(?y))\k)/, '2$'));
-assert.compareArray(
+assert.sameValue(
'x2zyyxxy',
'xzzyyxxy'.replace(
/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k)/, '2$'));
-assert.compareArray(
+assert.sameValue(
'2x(x,)yy', 'xxyy'.replace(/(?:(?:(?x)|(?y))\k)/, '2$($1,$2)'));
-assert.compareArray(
+assert.sameValue(
'x2z(,,,,z)yyxxy',
'xzzyyxxy'.replace(
/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k)/,
'2$($1,$2,$3,$4,$5)'));
-assert.compareArray(
+assert.sameValue(
'2x2y', 'xxyy'.replace(/(?:(?:(?x)|(?y))\k)/g, '2$'));
-assert.compareArray(
+assert.sameValue(
'x2z2y2xy',
'xzzyyxxy'.replace(
/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k)/g, '2$'));
diff --git a/test/staging/built-ins/RegExp/named-groups/duplicate-named-groups-search.js b/test/staging/built-ins/RegExp/named-groups/duplicate-named-groups-search.js
index 3796b5bc41..7d3b31b3b4 100644
--- a/test/staging/built-ins/RegExp/named-groups/duplicate-named-groups-search.js
+++ b/test/staging/built-ins/RegExp/named-groups/duplicate-named-groups-search.js
@@ -4,10 +4,9 @@
/*---
description: Test search function with duplicate names in alteration.
features: [regexp-duplicate-named-groups]
-includes: [compareArray.js]
---*/
-assert.compareArray(3, 'abcxyz'.search(/(?x)|(?y)/));
-assert.compareArray(3, 'abcxyz'.search(/(?y)|(?x)/));
-assert.compareArray(1, 'aybcxyz'.search(/(?x)|(?y)/));
-assert.compareArray(1, 'aybcxyz'.search(/(?y)|(?x)/));
+assert.sameValue(3, 'abcxyz'.search(/(?x)|(?y)/));
+assert.sameValue(3, 'abcxyz'.search(/(?y)|(?x)/));
+assert.sameValue(1, 'aybcxyz'.search(/(?x)|(?y)/));
+assert.sameValue(1, 'aybcxyz'.search(/(?y)|(?x)/));
diff --git a/test/staging/sm/String/AdvanceStringIndex.js b/test/staging/sm/String/AdvanceStringIndex.js
index b474c0bee9..ab00180990 100644
--- a/test/staging/sm/String/AdvanceStringIndex.js
+++ b/test/staging/sm/String/AdvanceStringIndex.js
@@ -21,19 +21,19 @@ assert.compareArray("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".match(/\uD83D\uDC38|
// ==== String.prototype.replace ====
// empty string replacement (optimized)
-assert.compareArray("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uD83D|X|/gu, ""),
+assert.sameValue("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uD83D|X|/gu, ""),
"\uD83D\uDC38\uD83D\uDC39\uD83D\uDC3A");
-assert.compareArray("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uDC38|X|/gu, ""),
+assert.sameValue("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uDC38|X|/gu, ""),
"\uD83D\uDC38\uD83D\uDC39\uD83D\uDC3A");
-assert.compareArray("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uD83D\uDC38|X|/gu, ""),
+assert.sameValue("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uD83D\uDC38|X|/gu, ""),
"\uD83D\uDC39\uD83D\uDC3A");
// non-empty string replacement
-assert.compareArray("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uD83D|X|/gu, "x"),
+assert.sameValue("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uD83D|X|/gu, "x"),
"x\uD83D\uDC38x\uD83D\uDC39xx\uD83D\uDC3Ax");
-assert.compareArray("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uDC38|X|/gu, "x"),
+assert.sameValue("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uDC38|X|/gu, "x"),
"x\uD83D\uDC38x\uD83D\uDC39xx\uD83D\uDC3Ax");
-assert.compareArray("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uD83D\uDC38|X|/gu, "x"),
+assert.sameValue("\uD83D\uDC38\uD83D\uDC39X\uD83D\uDC3A".replace(/\uD83D\uDC38|X|/gu, "x"),
"xx\uD83D\uDC39xx\uD83D\uDC3Ax");
// ==== String.prototype.split ====