Import tests from SpiderMonkey

This commit is contained in:
Ms2ger 2024-05-06 14:47:56 +02:00 committed by Philip Chimento
parent d0bda4d26f
commit 6ee9579acb
1619 changed files with 187575 additions and 0 deletions

View File

@ -0,0 +1,316 @@
/*---
defines: [msPerHour, TZ_ADJUST, UTC_01_JAN_1900, UTC_01_JAN_2000, UTC_29_FEB_2000, UTC_01_JAN_2005, inTimeZone, withLocale, Month, assertDateTime, runDSTOffsetCachingTestsFraction]
allow_unused: True
---*/
/**
* Date functions used by tests in Date suite
*/
(function(global) {
const msPerDay = 1000 * 60 * 60 * 24;
const msPerHour = 1000 * 60 * 60;
global.msPerHour = msPerHour;
// Offset of tester's time zone from UTC.
const TZ_DIFF = GetRawTimezoneOffset();
global.TZ_ADJUST = TZ_DIFF * msPerHour;
const UTC_01_JAN_1900 = -2208988800000;
const UTC_01_JAN_2000 = 946684800000;
const UTC_29_FEB_2000 = UTC_01_JAN_2000 + 31 * msPerDay + 28 * msPerDay;
const UTC_01_JAN_2005 = UTC_01_JAN_2000 + TimeInYear(2000) + TimeInYear(2001) +
TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004);
global.UTC_01_JAN_1900 = UTC_01_JAN_1900;
global.UTC_01_JAN_2000 = UTC_01_JAN_2000;
global.UTC_29_FEB_2000 = UTC_29_FEB_2000;
global.UTC_01_JAN_2005 = UTC_01_JAN_2005;
/*
* Originally, the test suite used a hard-coded value TZ_DIFF = -8.
* But that was only valid for testers in the Pacific Standard Time Zone!
* We calculate the proper number dynamically for any tester. We just
* have to be careful not to use a date subject to Daylight Savings Time...
*/
function GetRawTimezoneOffset() {
let t1 = new Date(2000, 1, 1).getTimezoneOffset();
let t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset();
// 1) Time zone without daylight saving time.
// 2) Northern hemisphere with daylight saving time.
if ((t1 - t2) >= 0)
return -t1 / 60;
// 3) Southern hemisphere with daylight saving time.
return -t2 / 60;
}
function DaysInYear(y) {
return y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 366 : 365;
}
function TimeInYear(y) {
return DaysInYear(y) * msPerDay;
}
function getDefaultTimeZone() {
var tz = getTimeZone();
switch (tz) {
case "EST":
case "EDT":
return "EST5EDT";
case "CST":
case "CDT":
return "CST6CDT";
case "MST":
case "MDT":
return "MST7MDT";
case "PST":
case "PDT":
return "PST8PDT";
default:
// Other time zones abbrevations are not supported.
return tz;
}
}
function getDefaultLocale() {
// If the default locale looks like a BCP-47 language tag, return it.
var locale = global.getDefaultLocale();
if (locale.match(/^[a-z][a-z0-9\-]+$/i))
return locale;
// Otherwise use undefined to reset to the default locale.
return undefined;
}
let defaultTimeZone = null;
let defaultLocale = null;
// Run the given test in the requested time zone.
function inTimeZone(tzname, fn) {
if (defaultTimeZone === null)
defaultTimeZone = getDefaultTimeZone();
setTimeZone(tzname);
try {
fn();
} finally {
setTimeZone(defaultTimeZone);
}
}
global.inTimeZone = inTimeZone;
// Run the given test with the requested locale.
function withLocale(locale, fn) {
if (defaultLocale === null)
defaultLocale = getDefaultLocale();
setDefaultLocale(locale);
try {
fn();
} finally {
setDefaultLocale(defaultLocale);
}
}
global.withLocale = withLocale;
const Month = {
January: 0,
February: 1,
March: 2,
April: 3,
May: 4,
June: 5,
July: 6,
August: 7,
September: 8,
October: 9,
November: 10,
December: 11,
};
global.Month = Month;
const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].join("|");
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].join("|");
const datePart = String.raw `(?:${weekdays}) (?:${months}) \d{2}`;
const timePart = String.raw `\d{4,6} \d{2}:\d{2}:\d{2} GMT[+-]\d{4}`;
const dateTimeRE = new RegExp(String.raw `^(${datePart} ${timePart})(?: \((.+)\))?$`);
function assertDateTime(date, expected, ...alternativeTimeZones) {
let actual = date.toString();
assertEq(dateTimeRE.test(expected), true, `${expected}`);
assertEq(dateTimeRE.test(actual), true, `${actual}`);
let [, expectedDateTime, expectedTimeZone] = dateTimeRE.exec(expected);
let [, actualDateTime, actualTimeZone] = dateTimeRE.exec(actual);
assertEq(actualDateTime, expectedDateTime);
// The time zone identifier is optional, so only compare its value if
// it's present in |actual| and |expected|.
if (expectedTimeZone !== undefined && actualTimeZone !== undefined) {
// Test against the alternative time zone identifiers if necessary.
if (actualTimeZone !== expectedTimeZone) {
for (let alternativeTimeZone of alternativeTimeZones) {
if (actualTimeZone === alternativeTimeZone) {
expectedTimeZone = alternativeTimeZone;
break;
}
}
}
assertEq(actualTimeZone, expectedTimeZone);
}
}
global.assertDateTime = assertDateTime;
})(this);
function runDSTOffsetCachingTestsFraction(part, parts)
{
var BUGNUMBER = 563938;
var summary = 'Cache DST offsets to improve SunSpider score';
print(BUGNUMBER + ": " + summary);
var MAX_UNIX_TIMET = 2145859200; // "2037-12-31T08:00:00.000Z" (PST8PDT based!)
var RANGE_EXPANSION_AMOUNT = 30 * 24 * 60 * 60;
/**
* Computes the time zone offset in minutes at the given timestamp.
*/
function tzOffsetFromUnixTimestamp(timestamp)
{
var d = new Date(NaN);
d.setTime(timestamp); // local slot = NaN, UTC slot = timestamp
return d.getTimezoneOffset(); // get UTC, calculate local => diff in minutes
}
/**
* Clear the DST offset cache, leaving it initialized to include a timestamp
* completely unlike the provided one (i.e. one very, very far away in time
* from it). Thus an immediately following lookup for the provided timestamp
* will cache-miss and compute a clean value.
*/
function clearDSTOffsetCache(undesiredTimestamp)
{
var opposite = (undesiredTimestamp + MAX_UNIX_TIMET / 2) % MAX_UNIX_TIMET;
// Generic purge to known, but not necessarily desired, state
tzOffsetFromUnixTimestamp(0);
tzOffsetFromUnixTimestamp(MAX_UNIX_TIMET);
// Purge to desired state. Cycle 2x in case opposite or undesiredTimestamp
// is close to 0 or MAX_UNIX_TIMET.
tzOffsetFromUnixTimestamp(opposite);
tzOffsetFromUnixTimestamp(undesiredTimestamp);
tzOffsetFromUnixTimestamp(opposite);
tzOffsetFromUnixTimestamp(undesiredTimestamp);
}
function computeCanonicalTZOffset(timestamp)
{
clearDSTOffsetCache(timestamp);
return tzOffsetFromUnixTimestamp(timestamp);
}
var TEST_TIMESTAMPS_SECONDS =
[
// Special-ish timestamps
0,
RANGE_EXPANSION_AMOUNT,
MAX_UNIX_TIMET,
];
var ONE_DAY = 24 * 60 * 60;
var EIGHTY_THREE_HOURS = 83 * 60 * 60;
var NINETY_EIGHT_HOURS = 98 * 60 * 60;
function nextIncrement(i)
{
return i === EIGHTY_THREE_HOURS ? NINETY_EIGHT_HOURS : EIGHTY_THREE_HOURS;
}
// Now add a long sequence of non-special timestamps, from a fixed range, that
// overlaps a DST change by "a bit" on each side. 67 days should be enough
// displacement that we can occasionally exercise the implementation's
// thirty-day expansion and the DST-offset-change logic. Use two different
// increments just to be safe and catch something a single increment might not.
var DST_CHANGE_DATE = 1268553600; // March 14, 2010
for (var t = DST_CHANGE_DATE - 67 * ONE_DAY,
i = nextIncrement(NINETY_EIGHT_HOURS),
end = DST_CHANGE_DATE + 67 * ONE_DAY;
t < end;
i = nextIncrement(i), t += i)
{
TEST_TIMESTAMPS_SECONDS.push(t);
}
var TEST_TIMESTAMPS =
TEST_TIMESTAMPS_SECONDS.map(function(v) { return v * 1000; });
/**************
* BEGIN TEST *
**************/
// Compute the correct time zone offsets for all timestamps to be tested.
var CORRECT_TZOFFSETS = TEST_TIMESTAMPS.map(computeCanonicalTZOffset);
// Intentionally and knowingly invoking every single logic path in the cache
// isn't easy for a human to get right (and know he's gotten it right), so
// let's do it the easy way: exhaustively try all possible four-date sequences
// selecting from our array of possible timestamps.
var sz = TEST_TIMESTAMPS.length;
var start = Math.floor((part - 1) / parts * sz);
var end = Math.floor(part / parts * sz);
print("Exhaustively testing timestamps " +
"[" + start + ", " + end + ") of " + sz + "...");
try
{
for (var i = start; i < end; i++)
{
print("Testing timestamp " + i + "...");
var t1 = TEST_TIMESTAMPS[i];
for (var j = 0; j < sz; j++)
{
var t2 = TEST_TIMESTAMPS[j];
for (var k = 0; k < sz; k++)
{
var t3 = TEST_TIMESTAMPS[k];
for (var w = 0; w < sz; w++)
{
var t4 = TEST_TIMESTAMPS[w];
clearDSTOffsetCache(t1);
var tzo1 = tzOffsetFromUnixTimestamp(t1);
var tzo2 = tzOffsetFromUnixTimestamp(t2);
var tzo3 = tzOffsetFromUnixTimestamp(t3);
var tzo4 = tzOffsetFromUnixTimestamp(t4);
assertEq(tzo1, CORRECT_TZOFFSETS[i]);
assertEq(tzo2, CORRECT_TZOFFSETS[j]);
assertEq(tzo3, CORRECT_TZOFFSETS[k]);
assertEq(tzo4, CORRECT_TZOFFSETS[w]);
}
}
}
}
}
catch (e)
{
assertEq(true, false,
"Error when testing with timestamps " +
i + ", " + j + ", " + k + ", " + w +
" (" + t1 + ", " + t2 + ", " + t3 + ", " + t4 + ")!");
}
reportCompare(true, true);
print("All tests passed!");
}

View File

@ -0,0 +1,114 @@
/*---
defines: [testJSON]
allow_unused: True
---*/
function testJSON(str, expectSyntaxError)
{
// Leading and trailing whitespace never affect parsing, so test the string
// multiple times with and without whitespace around it as it's easy and can
// potentially detect bugs.
// Try the provided string
try
{
JSON.parse(str);
reportCompare(false, expectSyntaxError,
"string <" + str + "> " +
"should" + (expectSyntaxError ? "n't" : "") + " " +
"have parsed as JSON");
}
catch (e)
{
if (!(e instanceof SyntaxError))
{
reportCompare(true, false,
"parsing string <" + str + "> threw a non-SyntaxError " +
"exception: " + e);
}
else
{
reportCompare(true, expectSyntaxError,
"string <" + str + "> " +
"should" + (expectSyntaxError ? "n't" : "") + " " +
"have parsed as JSON, exception: " + e);
}
}
// Now try the provided string with trailing whitespace
try
{
JSON.parse(str + " ");
reportCompare(false, expectSyntaxError,
"string <" + str + " > " +
"should" + (expectSyntaxError ? "n't" : "") + " " +
"have parsed as JSON");
}
catch (e)
{
if (!(e instanceof SyntaxError))
{
reportCompare(true, false,
"parsing string <" + str + " > threw a non-SyntaxError " +
"exception: " + e);
}
else
{
reportCompare(true, expectSyntaxError,
"string <" + str + " > " +
"should" + (expectSyntaxError ? "n't" : "") + " " +
"have parsed as JSON, exception: " + e);
}
}
// Now try the provided string with leading whitespace
try
{
JSON.parse(" " + str);
reportCompare(false, expectSyntaxError,
"string < " + str + "> " +
"should" + (expectSyntaxError ? "n't" : "") + " " +
"have parsed as JSON");
}
catch (e)
{
if (!(e instanceof SyntaxError))
{
reportCompare(true, false,
"parsing string < " + str + "> threw a non-SyntaxError " +
"exception: " + e);
}
else
{
reportCompare(true, expectSyntaxError,
"string < " + str + "> " +
"should" + (expectSyntaxError ? "n't" : "") + " " +
"have parsed as JSON, exception: " + e);
}
}
// Now try the provided string with whitespace surrounding it
try
{
JSON.parse(" " + str + " ");
reportCompare(false, expectSyntaxError,
"string < " + str + " > " +
"should" + (expectSyntaxError ? "n't" : "") + " " +
"have parsed as JSON");
}
catch (e)
{
if (!(e instanceof SyntaxError))
{
reportCompare(true, false,
"parsing string < " + str + " > threw a non-SyntaxError " +
"exception: " + e);
}
else
{
reportCompare(true, expectSyntaxError,
"string < " + str + " > " +
"should" + (expectSyntaxError ? "n't" : "") + " " +
"have parsed as JSON, exception: " + e);
}
}
}

View File

@ -0,0 +1,79 @@
/*---
defines: [assertNear]
allow_unused: True
---*/
// The nearest representable values to +1.0.
const ONE_PLUS_EPSILON = 1 + Math.pow(2, -52); // 0.9999999999999999
const ONE_MINUS_EPSILON = 1 - Math.pow(2, -53); // 1.0000000000000002
{
const fail = function (msg) {
var exc = new Error(msg);
try {
// Try to improve on exc.fileName and .lineNumber; leave exc.stack
// alone. We skip two frames: fail() and its caller, an assertX()
// function.
var frames = exc.stack.trim().split("\n");
if (frames.length > 2) {
var m = /@([^@:]*):([0-9]+)$/.exec(frames[2]);
if (m) {
exc.fileName = m[1];
exc.lineNumber = +m[2];
}
}
} catch (ignore) { throw ignore;}
throw exc;
};
let ENDIAN; // 0 for little-endian, 1 for big-endian.
// Return the difference between the IEEE 754 bit-patterns for a and b.
//
// This is meaningful when a and b are both finite and have the same
// sign. Then the following hold:
//
// * If a === b, then diff(a, b) === 0.
//
// * If a !== b, then diff(a, b) === 1 + the number of representable values
// between a and b.
//
const f = new Float64Array([0, 0]);
const u = new Uint32Array(f.buffer);
const diff = function (a, b) {
f[0] = a;
f[1] = b;
//print(u[1].toString(16) + u[0].toString(16) + " " + u[3].toString(16) + u[2].toString(16));
return Math.abs((u[3-ENDIAN] - u[1-ENDIAN]) * 0x100000000 + u[2+ENDIAN] - u[0+ENDIAN]);
};
// Set ENDIAN to the platform's endianness.
ENDIAN = 0; // try little-endian first
if (diff(2, 4) === 0x100000) // exact wrong answer we'll get on a big-endian platform
ENDIAN = 1;
assertEq(diff(2,4), 0x10000000000000);
assertEq(diff(0, Number.MIN_VALUE), 1);
assertEq(diff(1, ONE_PLUS_EPSILON), 1);
assertEq(diff(1, ONE_MINUS_EPSILON), 1);
var assertNear = function assertNear(a, b, tolerance=1) {
if (!Number.isFinite(b)) {
fail("second argument to assertNear (expected value) must be a finite number");
} else if (Number.isNaN(a)) {
fail("got NaN, expected a number near " + b);
} else if (!Number.isFinite(a)) {
if (b * Math.sign(a) < Number.MAX_VALUE)
fail("got " + a + ", expected a number near " + b);
} else {
// When the two arguments do not have the same sign bit, diff()
// returns some huge number. So if b is positive or negative 0,
// make target the zero that has the same sign bit as a.
var target = b === 0 ? a * 0 : b;
var err = diff(a, target);
if (err > tolerance) {
fail("got " + a + ", expected a number near " + b +
" (relative error: " + err + ")");
}
}
};
}

View File

@ -0,0 +1,14 @@
/*---
defines: [SOME_PRIMITIVE_VALUES]
allow_unused: True
---*/
// List of a few values that are not objects.
var SOME_PRIMITIVE_VALUES = [
undefined, null,
false,
-Infinity, -1.6e99, -1, -0, 0, Math.pow(2, -1074), 1, 4294967295,
Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER + 1, 1.6e99, Infinity, NaN,
"", "Phaedo",
Symbol(), Symbol("iterator"), Symbol.for("iterator"), Symbol.iterator
];

View File

@ -0,0 +1,261 @@
/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*---
defines: [testRegExp, makeExpectedMatch, checkRegExpMatch]
allow_unused: True
---*/
/*
* Date: 07 February 2001
*
* Functionality common to RegExp testing -
*/
//-----------------------------------------------------------------------------
(function(global) {
var MSG_PATTERN = '\nregexp = ';
var MSG_STRING = '\nstring = ';
var MSG_EXPECT = '\nExpect: ';
var MSG_ACTUAL = '\nActual: ';
var ERR_LENGTH = '\nERROR !!! match arrays have different lengths:';
var ERR_MATCH = '\nERROR !!! regexp failed to give expected match array:';
var ERR_NO_MATCH = '\nERROR !!! regexp FAILED to match anything !!!';
var ERR_UNEXP_MATCH = '\nERROR !!! regexp MATCHED when we expected it to fail !!!';
var CHAR_LBRACKET = '[';
var CHAR_RBRACKET = ']';
var CHAR_QT_DBL = '"';
var CHAR_QT = "'";
var CHAR_NL = '\n';
var CHAR_COMMA = ',';
var CHAR_SPACE = ' ';
var TYPE_STRING = typeof 'abc';
global.testRegExp = function testRegExp(statuses, patterns, strings, actualmatches, expectedmatches)
{
var status = '';
var pattern = new RegExp();
var string = '';
var actualmatch = new Array();
var expectedmatch = new Array();
var state = '';
var lActual = -1;
var lExpect = -1;
for (var i=0; i != patterns.length; i++)
{
status = statuses[i];
pattern = patterns[i];
string = strings[i];
actualmatch=actualmatches[i];
expectedmatch=expectedmatches[i];
state = getState(status, pattern, string);
description = status;
if(actualmatch)
{
actual = formatArray(actualmatch);
if(expectedmatch)
{
// expectedmatch and actualmatch are arrays -
lExpect = expectedmatch.length;
lActual = actualmatch.length;
var expected = formatArray(expectedmatch);
if (lActual != lExpect)
{
reportCompare(lExpect, lActual,
state + ERR_LENGTH +
MSG_EXPECT + expected +
MSG_ACTUAL + actual +
CHAR_NL
);
continue;
}
// OK, the arrays have same length -
if (expected != actual)
{
reportCompare(expected, actual,
state + ERR_MATCH +
MSG_EXPECT + expected +
MSG_ACTUAL + actual +
CHAR_NL
);
}
else
{
reportCompare(expected, actual, state)
}
}
else //expectedmatch is null - that is, we did not expect a match -
{
expected = expectedmatch;
reportCompare(expected, actual,
state + ERR_UNEXP_MATCH +
MSG_EXPECT + expectedmatch +
MSG_ACTUAL + actual +
CHAR_NL
);
}
}
else // actualmatch is null
{
if (expectedmatch)
{
actual = actualmatch;
reportCompare(expected, actual,
state + ERR_NO_MATCH +
MSG_EXPECT + expectedmatch +
MSG_ACTUAL + actualmatch +
CHAR_NL
);
}
else // we did not expect a match
{
// Being ultra-cautious. Presumably expectedmatch===actualmatch===null
expected = expectedmatch;
actual = actualmatch;
reportCompare (expectedmatch, actualmatch, state);
}
}
}
}
function getState(status, pattern, string)
{
/*
* Escape \n's, etc. to make them LITERAL in the presentation string.
* We don't have to worry about this in |pattern|; such escaping is
* done automatically by pattern.toString(), invoked implicitly below.
*
* One would like to simply do: string = string.replace(/(\s)/g, '\$1').
* However, the backreference $1 is not a literal string value,
* so this method doesn't work.
*
* Also tried string = string.replace(/(\s)/g, escape('$1'));
* but this just inserts the escape of the literal '$1', i.e. '%241'.
*/
string = string.replace(/\n/g, '\\n');
string = string.replace(/\r/g, '\\r');
string = string.replace(/\t/g, '\\t');
string = string.replace(/\v/g, '\\v');
string = string.replace(/\f/g, '\\f');
return (status + MSG_PATTERN + pattern + MSG_STRING + singleQuote(string));
}
/*
* If available, arr.toSource() gives more detail than arr.toString()
*
* var arr = Array(1,2,'3');
*
* arr.toSource()
* [1, 2, "3"]
*
* arr.toString()
* 1,2,3
*
* But toSource() doesn't exist in Rhino, so use our own imitation, below -
*
*/
function formatArray(arr)
{
try
{
return arr.toSource();
}
catch(e)
{
return toSource(arr);
}
}
/*
* Imitate SpiderMonkey's arr.toSource() method:
*
* a) Double-quote each array element that is of string type
* b) Represent |undefined| and |null| by empty strings
* c) Delimit elements by a comma + single space
* d) Do not add delimiter at the end UNLESS the last element is |undefined|
* e) Add square brackets to the beginning and end of the string
*/
function toSource(arr)
{
var delim = CHAR_COMMA + CHAR_SPACE;
var elt = '';
var ret = '';
var len = arr.length;
for (i=0; i<len; i++)
{
elt = arr[i];
switch(true)
{
case (typeof elt === TYPE_STRING) :
ret += doubleQuote(elt);
break;
case (elt === undefined || elt === null) :
break; // add nothing but the delimiter, below -
default:
ret += elt.toString();
}
if ((i < len-1) || (elt === undefined))
ret += delim;
}
return CHAR_LBRACKET + ret + CHAR_RBRACKET;
}
function doubleQuote(text)
{
return CHAR_QT_DBL + text + CHAR_QT_DBL;
}
function singleQuote(text)
{
return CHAR_QT + text + CHAR_QT;
}
global.makeExpectedMatch = function makeExpectedMatch(arr, index, input) {
var expectedMatch = {
index: index,
input: input,
length: arr.length,
};
for (var i = 0; i < arr.length; ++i)
expectedMatch[i] = arr[i];
return expectedMatch;
}
global.checkRegExpMatch = function checkRegExpMatch(actual, expected) {
assertEq(actual.length, expected.length);
for (var i = 0; i < actual.length; ++i)
assertEq(actual[i], expected[i]);
assertEq(actual.index, expected.index);
assertEq(actual.input, expected.input);
}
})(this);

View File

@ -0,0 +1,106 @@
/*---
defines: [assertSetContainsExactOrderedItems, SetLike, SetIteratorLike, LoggingProxy]
allow_unused: True
---*/
(function(global) {
// Save the primordial values.
const {Array, Error, Object, Proxy, Reflect, Set} = global;
const ArrayIsArray = Array.isArray;
const ReflectApply = Reflect.apply;
const ReflectDefineProperty = Reflect.defineProperty;
const ReflectGet = Reflect.get;
const ReflectGetPrototypeOf = Reflect.getPrototypeOf;
const SetPrototype = Set.prototype;
const SetPrototypeHas = SetPrototype.has;
const SetPrototypeSize = Object.getOwnPropertyDescriptor(SetPrototype, "size").get;
const SetPrototypeKeys = SetPrototype.keys;
const SetIteratorPrototypeNext = new Set().values().next;
function assertSetContainsExactOrderedItems(actual, expected) {
assertEq(ReflectGetPrototypeOf(actual), SetPrototype, "actual is a native Set object");
assertEq(ArrayIsArray(expected), true, "expected is an Array object");
assertEq(ReflectApply(SetPrototypeSize, actual, []), expected.length);
let index = 0;
let keys = ReflectApply(SetPrototypeKeys, actual, []);
while (true) {
let {done, value: item} = ReflectApply(SetIteratorPrototypeNext, keys, []);
if (done) {
break;
}
assertEq(item, expected[index], `Element at index ${index}:`);
index++;
}
}
global.assertSetContainsExactOrderedItems = assertSetContainsExactOrderedItems;
class SetLike {
#set;
constructor(values) {
this.#set = new Set(values);
}
get size() {
return ReflectApply(SetPrototypeSize, this.#set, []);
}
has(value) {
return ReflectApply(SetPrototypeHas, this.#set, [value]);
}
keys() {
let keys = ReflectApply(SetPrototypeKeys, this.#set, []);
return new SetIteratorLike(keys);
}
}
global.SetLike = SetLike;
class SetIteratorLike {
#keys;
constructor(keys) {
this.#keys = keys;
}
next() {
return ReflectApply(SetIteratorPrototypeNext, this.#keys, []);
}
// The |return| method of the iterator protocol is never called.
return() {
throw new Error("Unexpected call to |return| method");
}
// The |throw| method of the iterator protocol is never called.
throw() {
throw new Error("Unexpected call to |throw| method");
}
}
function LoggingProxy(obj, log) {
assertEq(ArrayIsArray(log), true);
let handler = new Proxy({
get(t, pk, r) {
ReflectDefineProperty(log, log.length, {
value: pk, writable: true, enumerable: true, configurable: true,
});
return ReflectGet(t, pk, r);
}
}, {
get(t, pk, r) {
ReflectDefineProperty(log, log.length, {
value: `[[${pk}]]`, writable: true, enumerable: true, configurable: true,
});
return ReflectGet(t, pk, r);
}
});
return {obj, proxy: new Proxy(obj, handler)};
}
global.LoggingProxy = LoggingProxy;
})(this);

View File

@ -0,0 +1,64 @@
/*---
defines: [runNormalizeTest]
allow_unused: True
---*/
function runNormalizeTest(test) {
function codePointsToString(points) {
return points.map(x => String.fromCodePoint(x)).join("");
}
function stringify(points) {
return points.map(x => x.toString(16)).join();
}
var source = codePointsToString(test.source);
var NFC = codePointsToString(test.NFC);
var NFD = codePointsToString(test.NFD);
var NFKC = codePointsToString(test.NFKC);
var NFKD = codePointsToString(test.NFKD);
var sourceStr = stringify(test.source);
var nfcStr = stringify(test.NFC);
var nfdStr = stringify(test.NFD);
var nfkcStr = stringify(test.NFKC);
var nfkdStr = stringify(test.NFKD);
/* NFC */
assertEq(source.normalize(), NFC, "NFC of " + sourceStr);
assertEq(NFC.normalize(), NFC, "NFC of " + nfcStr);
assertEq(NFD.normalize(), NFC, "NFC of " + nfdStr);
assertEq(NFKC.normalize(), NFKC, "NFC of " + nfkcStr);
assertEq(NFKD.normalize(), NFKC, "NFC of " + nfkdStr);
assertEq(source.normalize(undefined), NFC, "NFC of " + sourceStr);
assertEq(NFC.normalize(undefined), NFC, "NFC of " + nfcStr);
assertEq(NFD.normalize(undefined), NFC, "NFC of " + nfdStr);
assertEq(NFKC.normalize(undefined), NFKC, "NFC of " + nfkcStr);
assertEq(NFKD.normalize(undefined), NFKC, "NFC of " + nfkdStr);
assertEq(source.normalize("NFC"), NFC, "NFC of " + sourceStr);
assertEq(NFC.normalize("NFC"), NFC, "NFC of " + nfcStr);
assertEq(NFD.normalize("NFC"), NFC, "NFC of " + nfdStr);
assertEq(NFKC.normalize("NFC"), NFKC, "NFC of " + nfkcStr);
assertEq(NFKD.normalize("NFC"), NFKC, "NFC of " + nfkdStr);
/* NFD */
assertEq(source.normalize("NFD"), NFD, "NFD of " + sourceStr);
assertEq(NFC.normalize("NFD"), NFD, "NFD of " + nfcStr);
assertEq(NFD.normalize("NFD"), NFD, "NFD of " + nfdStr);
assertEq(NFKC.normalize("NFD"), NFKD, "NFD of " + nfkcStr);
assertEq(NFKD.normalize("NFD"), NFKD, "NFD of " + nfkdStr);
/* NFKC */
assertEq(source.normalize("NFKC"), NFKC, "NFKC of " + sourceStr);
assertEq(NFC.normalize("NFKC"), NFKC, "NFKC of " + nfcStr);
assertEq(NFD.normalize("NFKC"), NFKC, "NFKC of " + nfdStr);
assertEq(NFKC.normalize("NFKC"), NFKC, "NFKC of " + nfkcStr);
assertEq(NFKD.normalize("NFKC"), NFKC, "NFKC of " + nfkdStr);
/* NFKD */
assertEq(source.normalize("NFKD"), NFKD, "NFKD of " + sourceStr);
assertEq(NFC.normalize("NFKD"), NFKD, "NFKD of " + nfcStr);
assertEq(NFD.normalize("NFKD"), NFKD, "NFKD of " + nfdStr);
assertEq(NFKC.normalize("NFKD"), NFKD, "NFKD of " + nfkcStr);
assertEq(NFKD.normalize("NFKD"), NFKD, "NFKD of " + nfkdStr);
}

View File

@ -0,0 +1,49 @@
/*---
defines: [ISOFields, assertSameISOFields]
allow_unused: True
---*/
function ISOFields(monthDay) {
let re = /^(?<year>\d{4,6})-(?<month>\d{2})-(?<day>\d{2})\[u-ca=(?<calendar>[\w\-]+)\]$/;
let str = monthDay.toString({calendarName: "always"});
let match = str.match(re);
assertEq(match !== null, true, `can't match: ${str}`);
let {year, month, day, calendar} = match.groups;
let isoYear = Number(year);
let isoMonth = Number(month);
let isoDay = Number(day);
let date = Temporal.PlainDate.from(str);
let isoDate = date.withCalendar("iso8601");
assertEq(calendar, date.calendarId);
assertEq(isoYear, isoDate.year);
assertEq(isoMonth, isoDate.month);
assertEq(isoDay, isoDate.day);
return {
isoYear,
isoMonth,
isoDay,
calendar,
};
}
function assertSameISOFields(actual, expected) {
let actualFields = ISOFields(actual);
let expectedFields = ISOFields(expected);
assertEq(typeof actualFields.isoYear, "number");
assertEq(typeof actualFields.isoMonth, "number");
assertEq(typeof actualFields.isoDay, "number");
assertEq(actualFields.isoMonth > 0, true);
assertEq(actualFields.isoDay > 0, true);
assertEq(actualFields.isoYear, expectedFields.isoYear);
assertEq(actualFields.isoMonth, expectedFields.isoMonth);
assertEq(actualFields.isoDay, expectedFields.isoDay);
assertEq(actualFields.calendar, expectedFields.calendar);
}

View File

@ -0,0 +1,133 @@
/*---
defines: [typedArrayConstructors, sharedTypedArrayConstructors, anyTypedArrayConstructors, isSharedConstructor, isFloatConstructor, isUnsignedConstructor]
allow_unused: True
---*/
(function(global) {
"use strict";
const {
Float16Array, Float32Array, Float64Array, Object, Reflect, SharedArrayBuffer, WeakMap,
assertEq
} = global;
const {
apply: Reflect_apply,
construct: Reflect_construct,
} = Reflect;
const {
get: WeakMap_prototype_get,
has: WeakMap_prototype_has,
} = WeakMap.prototype;
const sharedConstructors = new WeakMap();
// Synthesize a constructor for a shared memory array from the constructor
// for unshared memory. This has "good enough" fidelity for many uses. In
// cases where it's not good enough, call isSharedConstructor for local
// workarounds.
function sharedConstructor(baseConstructor) {
// Create SharedTypedArray as a subclass of %TypedArray%, following the
// built-in %TypedArray% subclasses.
class SharedTypedArray extends Object.getPrototypeOf(baseConstructor) {
constructor(...args) {
var array = Reflect_construct(baseConstructor, args);
var {buffer, byteOffset, length} = array;
var sharedBuffer = new SharedArrayBuffer(buffer.byteLength);
var sharedArray = Reflect_construct(baseConstructor,
[sharedBuffer, byteOffset, length],
new.target);
for (var i = 0; i < length; i++)
sharedArray[i] = array[i];
assertEq(sharedArray.buffer, sharedBuffer);
return sharedArray;
}
}
// 22.2.5.1 TypedArray.BYTES_PER_ELEMENT
Object.defineProperty(SharedTypedArray, "BYTES_PER_ELEMENT",
{__proto__: null, value: baseConstructor.BYTES_PER_ELEMENT});
// 22.2.6.1 TypedArray.prototype.BYTES_PER_ELEMENT
Object.defineProperty(SharedTypedArray.prototype, "BYTES_PER_ELEMENT",
{__proto__: null, value: baseConstructor.BYTES_PER_ELEMENT});
// Share the same name with the base constructor to avoid calling
// isSharedConstructor() in multiple places.
Object.defineProperty(SharedTypedArray, "name",
{__proto__: null, value: baseConstructor.name});
sharedConstructors.set(SharedTypedArray, baseConstructor);
return SharedTypedArray;
}
/**
* All TypedArray constructors for unshared memory.
*/
const typedArrayConstructors = Object.freeze([
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
].concat(Float16Array ?? []));
/**
* All TypedArray constructors for shared memory.
*/
const sharedTypedArrayConstructors = Object.freeze(
typeof SharedArrayBuffer === "function"
? typedArrayConstructors.map(sharedConstructor)
: []
);
/**
* All TypedArray constructors for unshared and shared memory.
*/
const anyTypedArrayConstructors = Object.freeze([
...typedArrayConstructors, ...sharedTypedArrayConstructors,
]);
/**
* Returns `true` if `constructor` is a TypedArray constructor for shared
* memory.
*/
function isSharedConstructor(constructor) {
return Reflect_apply(WeakMap_prototype_has, sharedConstructors, [constructor]);
}
/**
* Returns `true` if `constructor` is a TypedArray constructor for shared
* or unshared memory, with an underlying element type of one of Float16, Float32
* or Float64.
*/
function isFloatConstructor(constructor) {
if (isSharedConstructor(constructor))
constructor = Reflect_apply(WeakMap_prototype_get, sharedConstructors, [constructor]);
return constructor == Float32Array || constructor == Float64Array || (Float16Array && constructor == Float16Array);
}
/**
* Returns `true` if `constructor` is a TypedArray constructor for shared
* or unshared memory, with an underlying element type of one of Uint8,
* Uint8Clamped, Uint16, or Uint32.
*/
function isUnsignedConstructor(constructor) {
if (isSharedConstructor(constructor))
constructor = Reflect_apply(WeakMap_prototype_get, sharedConstructors, [constructor]);
return constructor == Uint8Array ||
constructor == Uint8ClampedArray ||
constructor == Uint16Array ||
constructor == Uint32Array;
}
global.typedArrayConstructors = typedArrayConstructors;
global.sharedTypedArrayConstructors = sharedTypedArrayConstructors;
global.anyTypedArrayConstructors = anyTypedArrayConstructors;
global.isSharedConstructor = isSharedConstructor;
global.isFloatConstructor = isFloatConstructor;
global.isUnsignedConstructor = isUnsignedConstructor;
})(this);

View File

@ -0,0 +1,284 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*---
defines: [testDestructuringArrayDefault, formatArray, toSource]
allow_unused: True
---*/
(function(global) {
function func() {
}
class C {
foo() {
}
static foo() {
}
}
function test_one(pattern, val, opt) {
var stmts = [];
var i = 0;
var c;
stmts.push(`var ${pattern} = ${val};`);
for (var stmt of stmts) {
if (!opt.no_plain) {
eval(`
${stmt}
`);
}
if (!opt.no_func) {
eval(`
function f${i}() {
${stmt}
}
f${i}();
`);
i++;
eval(`
var f${i} = function foo() {
${stmt}
};
f${i}();
`);
i++;
eval(`
var f${i} = () => {
${stmt}
};
f${i}();
`);
i++;
}
if (!opt.no_gen) {
eval(`
function* g${i}() {
${stmt}
}
[...g${i}()];
`);
i++;
eval(`
var g${i} = function* foo() {
${stmt}
};
[...g${i}()];
`);
i++;
}
if (!opt.no_ctor) {
eval(`
class D${i} {
constructor() {
${stmt}
}
}
new D${i}();
`);
i++;
}
if (!opt.no_derived_ctor) {
if (opt.no_pre_super) {
eval(`
class D${i} extends C {
constructor() {
${stmt}
try { super(); } catch (e) {}
}
}
new D${i}();
`);
i++;
} else {
eval(`
class D${i} extends C {
constructor() {
super();
${stmt}
}
}
new D${i}();
`);
i++;
}
}
if (!opt.no_method) {
eval(`
class D${i} extends C {
method() {
${stmt}
}
static staticMethod() {
${stmt}
}
}
new D${i}().method();
D${i}.staticMethod();
`);
i++;
}
}
if (!opt.no_func_arg) {
eval(`
function f${i}(${pattern}) {}
f${i}(${val});
`);
i++;
eval(`
var f${i} = function foo(${pattern}) {};
f${i}(${val});
`);
i++;
eval(`
var f${i} = (${pattern}) => {};
f${i}(${val});
`);
i++;
}
if (!opt.no_gen_arg) {
eval(`
function* g${i}(${pattern}) {}
[...g${i}(${val})];
`);
i++;
eval(`
var g${i} = function* foo(${pattern}) {};
[...g${i}(${val})];
`);
i++;
}
}
function test(expr, opt={}) {
var pattern = `[a=${expr}, ...c]`;
test_one(pattern, "[]", opt);
test_one(pattern, "[1]", opt);
pattern = `[,a=${expr}]`;
test_one(pattern, "[]", opt);
test_one(pattern, "[1]", opt);
test_one(pattern, "[1, 2]", opt);
pattern = `[{x: [a=${expr}]}]`;
test_one(pattern, "[{x: [1]}]", opt);
pattern = `[x=[a=${expr}]=[]]`;
test_one(pattern, "[]", opt);
test_one(pattern, "[1]", opt);
pattern = `[x=[a=${expr}]=[1]]`;
test_one(pattern, "[]", opt);
test_one(pattern, "[1]", opt);
}
global.testDestructuringArrayDefault = test;
})(this);
(function(global) {
/*
* Date: 07 February 2001
*
* Functionality common to Array testing -
*/
//-----------------------------------------------------------------------------
var CHAR_LBRACKET = '[';
var CHAR_RBRACKET = ']';
var CHAR_QT_DBL = '"';
var CHAR_COMMA = ',';
var CHAR_SPACE = ' ';
var TYPE_STRING = typeof 'abc';
/*
* If available, arr.toSource() gives more detail than arr.toString()
*
* var arr = Array(1,2,'3');
*
* arr.toSource()
* [1, 2, "3"]
*
* arr.toString()
* 1,2,3
*
* But toSource() doesn't exist in Rhino, so use our own imitation, below -
*
*/
function formatArray(arr)
{
try
{
return arr.toSource();
}
catch(e)
{
return toSource(arr);
}
}
global.formatArray = formatArray;
/*
* Imitate SpiderMonkey's arr.toSource() method:
*
* a) Double-quote each array element that is of string type
* b) Represent |undefined| and |null| by empty strings
* c) Delimit elements by a comma + single space
* d) Do not add delimiter at the end UNLESS the last element is |undefined|
* e) Add square brackets to the beginning and end of the string
*/
function toSource(arr)
{
var delim = CHAR_COMMA + CHAR_SPACE;
var elt = '';
var ret = '';
var len = arr.length;
for (i=0; i<len; i++)
{
elt = arr[i];
switch(true)
{
case (typeof elt === TYPE_STRING) :
ret += doubleQuote(elt);
break;
case (elt === undefined || elt === null) :
break; // add nothing but the delimiter, below -
default:
ret += elt.toString();
}
if ((i < len-1) || (elt === undefined))
ret += delim;
}
return CHAR_LBRACKET + ret + CHAR_RBRACKET;
}
global.toSource = toSource;
function doubleQuote(text)
{
return CHAR_QT_DBL + text + CHAR_QT_DBL;
}
})(this);

View File

@ -0,0 +1,349 @@
/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*---
defines: [testRegExp, clone_object_check]
allow_unused: True
---*/
(function(global) {
/*
* Date: 07 February 2001
*
* Functionality common to RegExp testing -
*/
//-----------------------------------------------------------------------------
var MSG_PATTERN = '\nregexp = ';
var MSG_STRING = '\nstring = ';
var MSG_EXPECT = '\nExpect: ';
var MSG_ACTUAL = '\nActual: ';
var ERR_LENGTH = '\nERROR !!! match arrays have different lengths:';
var ERR_MATCH = '\nERROR !!! regexp failed to give expected match array:';
var ERR_NO_MATCH = '\nERROR !!! regexp FAILED to match anything !!!';
var ERR_UNEXP_MATCH = '\nERROR !!! regexp MATCHED when we expected it to fail !!!';
var CHAR_LBRACKET = '[';
var CHAR_RBRACKET = ']';
var CHAR_QT_DBL = '"';
var CHAR_QT = "'";
var CHAR_NL = '\n';
var CHAR_COMMA = ',';
var CHAR_SPACE = ' ';
var TYPE_STRING = typeof 'abc';
function testRegExp(statuses, patterns, strings, actualmatches, expectedmatches)
{
var status = '';
var pattern = new RegExp();
var string = '';
var actualmatch = new Array();
var expectedmatch = new Array();
var state = '';
var lActual = -1;
var lExpect = -1;
for (var i=0; i != patterns.length; i++)
{
status = statuses[i];
pattern = patterns[i];
string = strings[i];
actualmatch=actualmatches[i];
expectedmatch=expectedmatches[i];
state = getState(status, pattern, string);
description = status;
if(actualmatch)
{
actual = formatArray(actualmatch);
if(expectedmatch)
{
// expectedmatch and actualmatch are arrays -
lExpect = expectedmatch.length;
lActual = actualmatch.length;
var expected = formatArray(expectedmatch);
if (lActual != lExpect)
{
reportCompare(lExpect, lActual,
state + ERR_LENGTH +
MSG_EXPECT + expected +
MSG_ACTUAL + actual +
CHAR_NL
);
continue;
}
// OK, the arrays have same length -
if (expected != actual)
{
reportCompare(expected, actual,
state + ERR_MATCH +
MSG_EXPECT + expected +
MSG_ACTUAL + actual +
CHAR_NL
);
}
else
{
reportCompare(expected, actual, state)
}
}
else //expectedmatch is null - that is, we did not expect a match -
{
expected = expectedmatch;
reportCompare(expected, actual,
state + ERR_UNEXP_MATCH +
MSG_EXPECT + expectedmatch +
MSG_ACTUAL + actual +
CHAR_NL
);
}
}
else // actualmatch is null
{
if (expectedmatch)
{
actual = actualmatch;
reportCompare(expected, actual,
state + ERR_NO_MATCH +
MSG_EXPECT + expectedmatch +
MSG_ACTUAL + actualmatch +
CHAR_NL
);
}
else // we did not expect a match
{
// Being ultra-cautious. Presumably expectedmatch===actualmatch===null
expected = expectedmatch;
actual = actualmatch;
reportCompare (expectedmatch, actualmatch, state);
}
}
}
}
global.testRegExp = testRegExp;
function getState(status, pattern, string)
{
/*
* Escape \n's, etc. to make them LITERAL in the presentation string.
* We don't have to worry about this in |pattern|; such escaping is
* done automatically by pattern.toString(), invoked implicitly below.
*
* One would like to simply do: string = string.replace(/(\s)/g, '\$1').
* However, the backreference $1 is not a literal string value,
* so this method doesn't work.
*
* Also tried string = string.replace(/(\s)/g, escape('$1'));
* but this just inserts the escape of the literal '$1', i.e. '%241'.
*/
string = string.replace(/\n/g, '\\n');
string = string.replace(/\r/g, '\\r');
string = string.replace(/\t/g, '\\t');
string = string.replace(/\v/g, '\\v');
string = string.replace(/\f/g, '\\f');
return (status + MSG_PATTERN + pattern + MSG_STRING + singleQuote(string));
}
/*
* If available, arr.toSource() gives more detail than arr.toString()
*
* var arr = Array(1,2,'3');
*
* arr.toSource()
* [1, 2, "3"]
*
* arr.toString()
* 1,2,3
*
* But toSource() doesn't exist in Rhino, so use our own imitation, below -
*
*/
function formatArray(arr)
{
try
{
return arr.toSource();
}
catch(e)
{
return toSource(arr);
}
}
/*
* Imitate SpiderMonkey's arr.toSource() method:
*
* a) Double-quote each array element that is of string type
* b) Represent |undefined| and |null| by empty strings
* c) Delimit elements by a comma + single space
* d) Do not add delimiter at the end UNLESS the last element is |undefined|
* e) Add square brackets to the beginning and end of the string
*/
function toSource(arr)
{
var delim = CHAR_COMMA + CHAR_SPACE;
var elt = '';
var ret = '';
var len = arr.length;
for (i=0; i<len; i++)
{
elt = arr[i];
switch(true)
{
case (typeof elt === TYPE_STRING) :
ret += doubleQuote(elt);
break;
case (elt === undefined || elt === null) :
break; // add nothing but the delimiter, below -
default:
ret += elt.toString();
}
if ((i < len-1) || (elt === undefined))
ret += delim;
}
return CHAR_LBRACKET + ret + CHAR_RBRACKET;
}
function doubleQuote(text)
{
return CHAR_QT_DBL + text + CHAR_QT_DBL;
}
function singleQuote(text)
{
return CHAR_QT + text + CHAR_QT;
}
})(this);
(function(global) {
// The Worker constructor can take a relative URL, but different test runners
// run in different enough environments that it doesn't all just automatically
// work. For the shell, we use just a filename; for the browser, see browser.js.
var workerDir = '';
// Assert that cloning b does the right thing as far as we can tell.
// Caveat: getters in b must produce the same value each time they're
// called. We may call them several times.
//
// If desc is provided, then the very first thing we do to b is clone it.
// (The self-modifying object test counts on this.)
//
function clone_object_check(b, desc) {
function classOf(obj) {
return Object.prototype.toString.call(obj);
}
function ownProperties(obj) {
return Object.getOwnPropertyNames(obj).
map(function (p) { return [p, Object.getOwnPropertyDescriptor(obj, p)]; });
}
function isArrayLength(obj, pair) {
return Array.isArray(obj) && pair[0] == "length";
}
function isCloneable(obj, pair) {
return isArrayLength(obj, pair) || (typeof pair[0] === 'string' && pair[1].enumerable);
}
function notIndex(p) {
var u = p >>> 0;
return !("" + u == p && u != 0xffffffff);
}
function assertIsCloneOf(a, b, path) {
assertEq(a === b, false);
var ca = classOf(a);
assertEq(ca, classOf(b), path);
assertEq(Object.getPrototypeOf(a),
ca == "[object Object]" ? Object.prototype : Array.prototype,
path);
// 'b', the original object, may have non-enumerable or XMLName
// properties; ignore them (except .length, if it's an Array).
// 'a', the clone, should not have any non-enumerable properties
// (except .length, if it's an Array) or XMLName properties.
var pb = ownProperties(b).filter(function(element) {
return isCloneable(b, element);
});
var pa = ownProperties(a);
for (var i = 0; i < pa.length; i++) {
assertEq(typeof pa[i][0], "string", "clone should not have E4X properties " + path);
if (!isCloneable(a, pa[i])) {
throw new Error("non-cloneable clone property " + pa[i][0] + " " + path);
}
}
// Check that, apart from properties whose names are array indexes,
// the enumerable properties appear in the same order.
var aNames = pa.map(function (pair) { return pair[1]; }).filter(notIndex);
var bNames = pa.map(function (pair) { return pair[1]; }).filter(notIndex);
assertEq(aNames.join(","), bNames.join(","), path);
// Check that the lists are the same when including array indexes.
function byName(a, b) { a = a[0]; b = b[0]; return a < b ? -1 : a === b ? 0 : 1; }
pa.sort(byName);
pb.sort(byName);
assertEq(pa.length, pb.length, "should see the same number of properties " + path);
for (var i = 0; i < pa.length; i++) {
var aName = pa[i][0];
var bName = pb[i][0];
assertEq(aName, bName, path);
var path2 = path + "." + aName;
var da = pa[i][1];
var db = pb[i][1];
if (!isArrayLength(a, pa[i])) {
assertEq(da.configurable, true, path2);
}
assertEq(da.writable, true, path2);
assertEq("value" in da, true, path2);
var va = da.value;
var vb = b[pb[i][0]];
if (typeof va === "object" && va !== null)
queue.push([va, vb, path2]);
else
assertEq(va, vb, path2);
}
}
var banner = "while testing clone of " + (desc || JSON.stringify(b));
var a = deserialize(serialize(b));
var queue = [[a, b, banner]];
while (queue.length) {
var triple = queue.shift();
assertIsCloneOf(triple[0], triple[1], triple[2]);
}
return a; // for further testing
}
global.clone_object_check = clone_object_check;
})(this);

View File

@ -0,0 +1,21 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*---
defines: [assertFalse, assertTrue, assertNotEq, assertIteratorResult, assertIteratorNext, assertIteratorDone]
allow_unused: True
---*/
function assertFalse(a) { assertEq(a, false) }
function assertTrue(a) { assertEq(a, true) }
function assertNotEq(found, not_expected) { assertEq(Object.is(found, not_expected), false) }
function assertIteratorResult(result, value, done) {
assertDeepEq(result.value, value);
assertEq(result.done, done);
}
function assertIteratorNext(iter, value) {
assertIteratorResult(iter.next(), value, false);
}
function assertIteratorDone(iter, value) {
assertIteratorResult(iter.next(), value, true);
}

View File

@ -0,0 +1,67 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*---
defines: [getJSClass, findType, findClass, isObject]
allow_unused: True
---*/
/*
* Date: 14 Mar 2001
*
* SUMMARY: Utility functions for testing objects -
*
* Suppose obj is an instance of a native type, e.g. Number.
* Then obj.toString() invokes Number.prototype.toString().
* We would also like to access Object.prototype.toString().
*
* The difference is this: suppose obj = new Number(7).
* Invoking Number.prototype.toString() on this just returns 7.
* Object.prototype.toString() on this returns '[object Number]'.
*
* The getJSClass() function returns 'Number', the [[Class]] property of obj.
* See ECMA-262 Edition 3, 13-Oct-1999, Section 8.6.2
*/
//-----------------------------------------------------------------------------
var cnNoObject = 'Unexpected Error!!! Parameter to this function must be an object';
var cnNoClass = 'Unexpected Error!!! Cannot find Class property';
var cnObjectToString = Object.prototype.toString;
var GLOBAL = 'global';
// checks that it's safe to call findType()
function getJSClass(obj)
{
if (isObject(obj))
return findClass(findType(obj));
return cnNoObject;
}
function findType(obj)
{
return cnObjectToString.apply(obj);
}
// given '[object Number]', return 'Number'
function findClass(sType)
{
var re = /^\[.*\s+(\w+)\s*\]$/;
var a = sType.match(re);
if (a && a[1])
return a[1];
return cnNoClass;
}
function isObject(obj)
{
return obj instanceof Object;
}

381
harness/sm/non262-shell.js Normal file
View File

@ -0,0 +1,381 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*---
defines: [completesNormally, raisesException, deepEqual, makeIterator, Permutations, assertThrowsValue, assertThrownErrorContains, assertThrowsInstanceOfWithMessageCheck, assertThrowsInstanceOf, assertThrowsInstanceOfWithMessage, assertThrowsInstanceOfWithMessageContains, assertDeepEq]
allow_unused: True
---*/
(function() {
const undefined = void 0;
/*
* completesNormally(CODE) returns true if evaluating CODE (as eval
* code) completes normally (rather than throwing an exception).
*/
globalThis.completesNormally = function completesNormally(code) {
try {
eval(code);
return true;
} catch (exception) {
return false;
}
}
/*
* raisesException(EXCEPTION)(CODE) returns true if evaluating CODE (as
* eval code) throws an exception object that is an instance of EXCEPTION,
* and returns false if it throws any other error or evaluates
* successfully. For example: raises(TypeError)("0()") == true.
*/
globalThis.raisesException = function raisesException(exception) {
return function (code) {
try {
eval(code);
return false;
} catch (actual) {
return actual instanceof exception;
}
};
};
/*
* Return true if A is equal to B, where equality on arrays and objects
* means that they have the same set of enumerable properties, the values
* of each property are deep_equal, and their 'length' properties are
* equal. Equality on other types is ==.
*/
globalThis.deepEqual = function deepEqual(a, b) {
if (typeof a != typeof b)
return false;
if (typeof a == 'object') {
var props = {};
// For every property of a, does b have that property with an equal value?
for (var prop in a) {
if (!deepEqual(a[prop], b[prop]))
return false;
props[prop] = true;
}
// Are all of b's properties present on a?
for (var prop in b)
if (!props[prop])
return false;
// length isn't enumerable, but we want to check it, too.
return a.length == b.length;
}
if (a === b) {
// Distinguish 0 from -0, even though they are ===.
return a !== 0 || 1/a === 1/b;
}
// Treat NaNs as equal, even though NaN !== NaN.
// NaNs are the only non-reflexive values, i.e., if a !== a, then a is a NaN.
// isNaN is broken: it converts its argument to number, so isNaN("foo") => true
return a !== a && b !== b;
}
/** Make an iterator with a return method. */
globalThis.makeIterator = function makeIterator(overrides) {
var throwMethod;
if (overrides && overrides.throw)
throwMethod = overrides.throw;
var iterator = {
throw: throwMethod,
next: function(x) {
if (overrides && overrides.next)
return overrides.next(x);
return { done: false };
},
return: function(x) {
if (overrides && overrides.ret)
return overrides.ret(x);
return { done: true };
}
};
return function() { return iterator; };
};
/** Yield every permutation of the elements in some array. */
globalThis.Permutations = function* Permutations(items) {
if (items.length == 0) {
yield [];
} else {
items = items.slice(0);
for (let i = 0; i < items.length; i++) {
let swap = items[0];
items[0] = items[i];
items[i] = swap;
for (let e of Permutations(items.slice(1, items.length)))
yield [items[0]].concat(e);
}
}
};
if (typeof globalThis.assertThrowsValue === 'undefined') {
globalThis.assertThrowsValue = function assertThrowsValue(f, val, msg) {
var fullmsg;
try {
f();
} catch (exc) {
if ((exc === val) === (val === val) && (val !== 0 || 1 / exc === 1 / val))
return;
fullmsg = "Assertion failed: expected exception " + val + ", got " + exc;
}
if (fullmsg === undefined)
fullmsg = "Assertion failed: expected exception " + val + ", no exception thrown";
if (msg !== undefined)
fullmsg += " - " + msg;
throw new Error(fullmsg);
};
}
if (typeof globalThis.assertThrownErrorContains === 'undefined') {
globalThis.assertThrownErrorContains = function assertThrownErrorContains(thunk, substr) {
try {
thunk();
} catch (e) {
if (e.message.indexOf(substr) !== -1)
return;
throw new Error("Expected error containing " + substr + ", got " + e);
}
throw new Error("Expected error containing " + substr + ", no exception thrown");
};
}
if (typeof globalThis.assertThrowsInstanceOfWithMessageCheck === 'undefined') {
globalThis.assertThrowsInstanceOfWithMessageCheck = function assertThrowsInstanceOfWithMessageCheck(f, ctor, check, msg) {
var fullmsg;
try {
f();
} catch (exc) {
if (!(exc instanceof ctor))
fullmsg = `Assertion failed: expected exception ${ctor.name}, got ${exc}`;
else {
var result = check(exc.message);
if (!result)
fullmsg = `Assertion failed: expected exception with message, got ${exc}`;
else
return;
}
}
if (fullmsg === undefined)
fullmsg = `Assertion failed: expected exception ${ctor.name}, no exception thrown`;
if (msg !== undefined)
fullmsg += " - " + msg;
throw new Error(fullmsg);
};
}
if (typeof globalThis.assertThrowsInstanceOf === 'undefined') {
globalThis.assertThrowsInstanceOf = function assertThrowsInstanceOf(f, ctor, msg) {
assertThrowsInstanceOfWithMessageCheck(f, ctor, _ => true, msg);
};
}
if (typeof globalThis.assertThrowsInstanceOfWithMessage === 'undefined') {
globalThis.assertThrowsInstanceOfWithMessage = function assertThrowsInstanceOfWithMessage(f, ctor, expected, msg) {
assertThrowsInstanceOfWithMessageCheck(f, ctor, message => message === expected, msg);
}
}
if (typeof globalThis.assertThrowsInstanceOfWithMessageContains === 'undefined') {
globalThis.assertThrowsInstanceOfWithMessageContains = function assertThrowsInstanceOfWithMessageContains(f, ctor, substr, msg) {
assertThrowsInstanceOfWithMessageCheck(f, ctor, message => message.indexOf(substr) !== -1, msg);
}
}
globalThis.assertDeepEq = (function(){
var call = Function.prototype.call,
Array_isArray = Array.isArray,
Array_includes = call.bind(Array.prototype.includes),
Map_ = Map,
Error_ = Error,
Symbol_ = Symbol,
Symbol_keyFor = Symbol.keyFor,
Symbol_description = call.bind(Object.getOwnPropertyDescriptor(Symbol.prototype, "description").get),
Map_has = call.bind(Map.prototype.has),
Map_get = call.bind(Map.prototype.get),
Map_set = call.bind(Map.prototype.set),
Object_toString = call.bind(Object.prototype.toString),
Function_toString = call.bind(Function.prototype.toString),
Object_getPrototypeOf = Object.getPrototypeOf,
Object_hasOwnProperty = call.bind(Object.prototype.hasOwnProperty),
Object_getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor,
Object_isExtensible = Object.isExtensible,
Object_getOwnPropertyNames = Object.getOwnPropertyNames;
// Return true iff ES6 Type(v) isn't Object.
// Note that `typeof document.all === "undefined"`.
function isPrimitive(v) {
return (v === null ||
v === undefined ||
typeof v === "boolean" ||
typeof v === "number" ||
typeof v === "string" ||
typeof v === "symbol");
}
function assertSameValue(a, b, msg) {
try {
assertEq(a, b);
} catch (exc) {
throw Error_(exc.message + (msg ? " " + msg : ""));
}
}
function assertSameClass(a, b, msg) {
var ac = Object_toString(a), bc = Object_toString(b);
assertSameValue(ac, bc, msg);
switch (ac) {
case "[object Function]":
if (typeof isProxy !== "undefined" && !isProxy(a) && !isProxy(b))
assertSameValue(Function_toString(a), Function_toString(b), msg);
}
}
function at(prevmsg, segment) {
return prevmsg ? prevmsg + segment : "at _" + segment;
}
// Assert that the arguments a and b are thoroughly structurally equivalent.
//
// For the sake of speed, we cut a corner:
// var x = {}, y = {}, ax = [x];
// assertDeepEq([ax, x], [ax, y]); // passes (?!)
//
// Technically this should fail, since the two object graphs are different.
// (The graph of [ax, y] contains one more object than the graph of [ax, x].)
//
// To get technically correct behavior, pass {strictEquivalence: true}.
// This is slower because we have to walk the entire graph, and Object.prototype
// is big.
//
return function assertDeepEq(a, b, options) {
var strictEquivalence = options ? options.strictEquivalence : false;
function assertSameProto(a, b, msg) {
check(Object_getPrototypeOf(a), Object_getPrototypeOf(b), at(msg, ".__proto__"));
}
function failPropList(na, nb, msg) {
throw Error_("got own properties " + JSON.stringify(na) + ", expected " + JSON.stringify(nb) +
(msg ? " " + msg : ""));
}
function assertSameProps(a, b, msg) {
var na = Object_getOwnPropertyNames(a),
nb = Object_getOwnPropertyNames(b);
if (na.length !== nb.length)
failPropList(na, nb, msg);
// Ignore differences in whether Array elements are stored densely.
if (Array_isArray(a)) {
na.sort();
nb.sort();
}
for (var i = 0; i < na.length; i++) {
var name = na[i];
if (name !== nb[i])
failPropList(na, nb, msg);
var da = Object_getOwnPropertyDescriptor(a, name),
db = Object_getOwnPropertyDescriptor(b, name);
var pmsg = at(msg, /^[_$A-Za-z0-9]+$/.test(name)
? /0|[1-9][0-9]*/.test(name) ? "[" + name + "]" : "." + name
: "[" + JSON.stringify(name) + "]");
assertSameValue(da.configurable, db.configurable, at(pmsg, ".[[Configurable]]"));
assertSameValue(da.enumerable, db.enumerable, at(pmsg, ".[[Enumerable]]"));
if (Object_hasOwnProperty(da, "value")) {
if (!Object_hasOwnProperty(db, "value"))
throw Error_("got data property, expected accessor property" + pmsg);
check(da.value, db.value, pmsg);
} else {
if (Object_hasOwnProperty(db, "value"))
throw Error_("got accessor property, expected data property" + pmsg);
check(da.get, db.get, at(pmsg, ".[[Get]]"));
check(da.set, db.set, at(pmsg, ".[[Set]]"));
}
}
};
const wellKnownSymbols = Reflect.ownKeys(Symbol)
.map(key => Symbol[key])
.filter(value => typeof value === "symbol");
// The standard doesn't offer a convenient way to distinguish well-known
// symbols from user-created symbols.
function isSimilarSymbol(a, b) {
// Fast path for same symbols.
if (a === b) {
return true;
}
// 1. Symbol descriptions must match.
// 2. Either both symbols are in the registry or none is.
// 3. Neither symbol must be a well-known symbol, because those are
// already handled through the fast path.
return Symbol_description(a) === Symbol_description(b) &&
Symbol_keyFor(a) === Symbol_keyFor(b) &&
!Array_includes(wellKnownSymbols, a) &&
!Array_includes(wellKnownSymbols, b);
}
var ab = new Map_();
var bpath = new Map_();
function check(a, b, path) {
if (typeof a === "symbol") {
// Symbols are primitives, but they have identity.
// Symbol("x") !== Symbol("x") but
// assertDeepEq(Symbol("x"), Symbol("x")) should pass.
if (typeof b !== "symbol") {
throw Error_("got " + String(a) + ", expected " + String(b) + " " + path);
} else if (!isSimilarSymbol(a, b)) {
throw Error_("got " + String(a) + ", expected " + String(b) + " " + path);
} else if (Map_has(ab, a)) {
assertSameValue(Map_get(ab, a), b, path);
} else if (Map_has(bpath, b)) {
var bPrevPath = Map_get(bpath, b) || "_";
throw Error_("got distinct symbols " + at(path, "") + " and " +
at(bPrevPath, "") + ", expected the same symbol both places");
} else {
Map_set(ab, a, b);
Map_set(bpath, b, path);
}
} else if (isPrimitive(a)) {
assertSameValue(a, b, path);
} else if (isPrimitive(b)) {
throw Error_("got " + Object_toString(a) + ", expected " + String(b) + " " + path);
} else if (Map_has(ab, a)) {
assertSameValue(Map_get(ab, a), b, path);
} else if (Map_has(bpath, b)) {
var bPrevPath = Map_get(bpath, b) || "_";
throw Error_("got distinct objects " + at(path, "") + " and " + at(bPrevPath, "") +
", expected the same object both places");
} else {
Map_set(ab, a, b);
Map_set(bpath, b, path);
if (a !== b || strictEquivalence) {
assertSameClass(a, b, path);
assertSameProto(a, b, path);
assertSameProps(a, b, path);
assertSameValue(Object_isExtensible(a),
Object_isExtensible(b),
at(path, ".[[Extensible]]"));
}
}
}
check(a, b, "");
};
})();
})();

View File

@ -0,0 +1,69 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*---
defines: [testLenientAndStrict, parsesSuccessfully, parseRaisesException, returns]
allow_unused: True
---*/
(function(global) {
/*
* Return true if both of these return true:
* - LENIENT_PRED applied to CODE
* - STRICT_PRED applied to CODE with a use strict directive added to the front
*
* Run STRICT_PRED first, for testing code that affects the global environment
* in loose mode, but fails in strict mode.
*/
global.testLenientAndStrict = function testLenientAndStrict(code, lenient_pred, strict_pred) {
return (strict_pred("'use strict'; " + code) &&
lenient_pred(code));
}
/*
* parsesSuccessfully(CODE) returns true if CODE parses as function
* code without an error.
*/
global.parsesSuccessfully = function parsesSuccessfully(code) {
try {
Function(code);
return true;
} catch (exception) {
return false;
}
};
/*
* parseRaisesException(EXCEPTION)(CODE) returns true if parsing CODE
* as function code raises EXCEPTION.
*/
global.parseRaisesException = function parseRaisesException(exception) {
return function (code) {
try {
Function(code);
return false;
} catch (actual) {
return exception.prototype.isPrototypeOf(actual);
}
};
};
/*
* returns(VALUE)(CODE) returns true if evaluating CODE (as eval code)
* completes normally (rather than throwing an exception), yielding a value
* strictly equal to VALUE.
*/
global.returns = function returns(value) {
return function(code) {
try {
return eval(code) === value;
} catch (exception) {
return false;
}
}
}
})(this);

74
harness/sm/non262.js Normal file
View File

@ -0,0 +1,74 @@
/*---
defines: [printBugNumber, inSection, printStatus, writeHeaderToLog,
assertThrownErrorContains, assertThrowsInstanceOfWithMessageCheck, newGlobal, print, assertEq, reportCompare, reportMatch, createIsHTMLDDA, createExternalArrayBuffer,
enableGeckoProfilingWithSlowAssertions, enableGeckoProfiling, disableGeckoProfiling]
---*/
function printBugNumber() {}
function inSection() {}
function printStatus() {}
function writeHeaderToLog() {}
function assertThrownErrorContains(f, substr) {
try {
f();
} catch (exc) {
// Do not test error messages
return;
}
throw new Test262Error("Expected error containing " + substr + ", no exception thrown");
}
function assertThrowsInstanceOfWithMessageCheck(f, ctor, _check, msg) {
var fullmsg;
try {
f();
} catch (exc) {
if (exc instanceof ctor)
return;
fullmsg = `Assertion failed: expected exception ${ctor.name}, got ${exc}`;
}
if (fullmsg === undefined)
fullmsg = `Assertion failed: expected exception ${ctor.name}, no exception thrown`;
if (msg !== undefined)
fullmsg += " - " + msg;
throw new Error(fullmsg);
}
globalThis.createNewGlobal = function() {
return $262.createRealm().global
}
function print(...args) {
}
function assertEq(...args) {
assert.sameValue(...args)
}
function reportCompare(...args) {
assert.sameValue(...args)
}
function reportMatch(expectedRegExp, actual, description = "") {
assert.sameValue(typeof actual, "string",
`Type mismatch, expected string, actual type ${typeof actual}`);
assert.notSameValue(expectedRegExp.exec(actual), null,
`Expected match to '${expectedRegExp}', Actual value '${actual}'`);
}
if (globalThis.createIsHTMLDDA === undefined) {
globalThis.createIsHTMLDDA = function createIsHTMLDDA() {
return $262.IsHTMLDDA;
}
}
if (globalThis.createExternalArrayBuffer === undefined) {
globalThis.createExternalArrayBuffer = function createExternalArrayBuffer(size) {
return new ArrayBuffer(size);
}
}
if (globalThis.enableGeckoProfilingWithSlowAssertions === undefined) {
globalThis.enableGeckoProfilingWithSlowAssertions = globalThis.enableGeckoProfiling =
globalThis.disableGeckoProfiling = () => {}
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var a = [0, 1];
var iterations = 0;
for (var k in a) {
iterations++;
a.length = 1;
}
assert.sameValue(iterations, 1);

View File

@ -0,0 +1,33 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 548671;
var summary =
"Don't use a shared-permanent inherited property to implement " +
"[].length or (function(){}).length";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var a = [];
a.p = 1;
var x = Object.create(a);
assert.sameValue(x.length, 0);
assert.sameValue(x.p, 1);
assert.sameValue(a.length, 0);
print("All tests passed!");

View File

@ -0,0 +1,48 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
function basic() {
assert.sameValue([0].at(0), 0);
assert.sameValue([0].at(-1), 0);
assert.sameValue([].at(0), undefined);
assert.sameValue([].at(-1), undefined);
assert.sameValue([].at(1), undefined);
assert.sameValue([0, 1].at(0), 0);
assert.sameValue([0, 1].at(1), 1);
assert.sameValue([0, 1].at(-2), 0);
assert.sameValue([0, 1].at(-1), 1);
assert.sameValue([0, 1].at(2), undefined);
assert.sameValue([0, 1].at(-3), undefined);
assert.sameValue([0, 1].at(-4), undefined);
assert.sameValue([0, 1].at(Infinity), undefined);
assert.sameValue([0, 1].at(-Infinity), undefined);
assert.sameValue([0, 1].at(NaN), 0); // ToInteger(NaN) = 0
}
function obj() {
var o = {length: 0, [0]: "a", at: Array.prototype.at};
assert.sameValue(o.at(0), undefined);
assert.sameValue(o.at(-1), undefined);
o.length = 1;
assert.sameValue(o.at(0), "a");
assert.sameValue(o.at(-1), "a");
assert.sameValue(o.at(1), undefined);
assert.sameValue(o.at(-2), undefined);
}
basic();
obj();

View File

@ -0,0 +1,34 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
function test(otherGlobal) {
let arrays = [
["with", otherGlobal.Array.prototype.with.call([1,2,3], 1, 3)],
["toSpliced", otherGlobal.Array.prototype.toSpliced.call([1, 2, 3], 0, 1, 4, 5)],
["toReversed", otherGlobal.Array.prototype.toReversed.call([1, 2, 3])],
["toSorted", otherGlobal.Array.prototype.toSorted.call([1, 2, 3], (x, y) => y > x)]
]
// Test that calling each method in a different compartment returns an array, and that
// the returned array's prototype matches the other compartment's Array prototype,
// not this one.
for (const [name, arr] of arrays) {
assert.sameValue(arr instanceof Array, false, name + " returned an instance of Array");
assert.sameValue(arr instanceof otherGlobal.Array, true, name + " did not return an instance of new global's Array");
assert.sameValue(Object.getPrototypeOf(arr) !== Object.getPrototypeOf([1, 2, 3]), true,
name + " returned an object with a prototype from the wrong realm");
}
}
test(createNewGlobal());
test(createNewGlobal({newCompartment: true}));

View File

@ -0,0 +1,85 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
function test(otherGlobal) {
assert.sameValue(TypeError !== otherGlobal.TypeError, true);
assert.sameValue(Object.getPrototypeOf(TypeError) !== Object.getPrototypeOf(otherGlobal.TypeError), true);
assert.sameValue(RangeError !== otherGlobal.RangeError, true);
assert.sameValue(Object.getPrototypeOf(RangeError) !== Object.getPrototypeOf(otherGlobal.RangeError), true);
var arrayLike = {
get "0"() {
throw new Error("Get 0");
},
get "4294967295" () { // 2 ** 32 - 1
throw new Error("Get 2147483648");
},
get "4294967296" () { // 2 ** 32
throw new Error("Get 2147483648");
},
length: 2 ** 32
};
let gToSorted = otherGlobal.Array.prototype.toSorted;
let gToSpliced = otherGlobal.Array.prototype.toSpliced;
let gToReversed = otherGlobal.Array.prototype.toReversed;
let gWith = otherGlobal.Array.prototype.with;
let typeErrorCalls = [
["toSorted - bad comparator", () => gToSorted.call([], 5)],
["toSorted - this is null", () => gToSorted.call(null)],
["toSpliced - array too long", () => {
var oldLen = arrayLike.length;
arrayLike.length = 2**53 - 1;
gToSpliced.call(arrayLike, 0, 0, 1);
arrayLike.length = oldLen;
}]
]
let rangeErrorCalls = [
["toSorted - array too long", () => gToSorted.call(arrayLike)],
["toReversed - array too long", () => gToReversed.call(arrayLike)],
["toSpliced - adding elements would exceed max array length", () => gToSpliced.call(arrayLike, 0, 0)],
["with - index out of range", () => gWith.call([0, 1, 2], 3, 7)],
["with - negative index", () => gWith.call([0, 1, 2], -4, 7)],
["with - array too long", () => gWith.call(arrayLike, 0, 0)]
]
// For each erroneous case, make sure the error comes from
// the other realm (not this realm)
for (const [message, f] of typeErrorCalls) {
try {
f();
} catch (exc) {
assert.sameValue(exc instanceof TypeError, false, message + " threw TypeError from wrong realm");
assert.sameValue(exc instanceof otherGlobal.TypeError, true, message + " didn't throw TypeError from other realm");
assert.sameValue(Object.getPrototypeOf(exc) !== Object.getPrototypeOf(TypeError), true,
message + " TypeError has wrong prototype");
}
}
for (const [message, f] of rangeErrorCalls) {
try {
f();
} catch (exc) {
assert.sameValue(exc instanceof RangeError, false, message + " threw RangeError from wrong realm");
assert.sameValue(exc instanceof otherGlobal.RangeError, true, message + " didn't throw RangeError from other realm");
assert.sameValue(Object.getPrototypeOf(exc) !== Object.getPrototypeOf(RangeError), true,
message + " TypeError has wrong prototype");
}
}
}
test(createNewGlobal());
test(createNewGlobal({newCompartment: true}));

View File

@ -0,0 +1,34 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var BUGNUMBER = 1287520;
var summary = 'Array.prototype.concat should check HasProperty everytime for non-dense array';
print(BUGNUMBER + ": " + summary);
var a = [1, 2, 3];
a.constructor = {
[Symbol.species]: function(...args) {
var p = new Proxy(new Array(...args), {
defineProperty(target, propertyKey, receiver) {
if (propertyKey === "0") delete a[1];
return Reflect.defineProperty(target, propertyKey, receiver);
}
});
return p;
}
};
var p = a.concat();
assert.sameValue(0 in p, true);
assert.sameValue(1 in p, false);
assert.sameValue(2 in p, true);

View File

@ -0,0 +1,47 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
flags:
- onlyStrict
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
description: |
pending
esid: pending
---*/
"use strict";
const x = Object.freeze([1, 2, 3]);
let fakeArray = {
[Symbol.isConcatSpreadable]: true,
length: 2,
0: "hello",
1: "world"
}
assert.deepEqual(x.concat(fakeArray), [1, 2, 3, "hello", "world"]);
assert.deepEqual(x.concat(fakeArray, fakeArray), [1, 2, 3, "hello", "world", "hello", "world"]);
for (let truthy of [true, 3.41, "abc", Symbol(), {}]) {
let obj = {[Symbol.isConcatSpreadable]: truthy, length: 1, 0: "hey"}
assert.deepEqual(x.concat(obj), [1, 2, 3, "hey"]);
}
for (let notTruthy of [null, undefined, false, 0, NaN, ""]) {
let obj = {[Symbol.isConcatSpreadable]: notTruthy, length: 1, 0: "hey"}
assert.deepEqual(x.concat(obj), [1, 2, 3, obj]);
}
let array = [5, 4];
assert.deepEqual(x.concat(array), [1, 2, 3, 5, 4]);
// Can make arrays non-spreadable
array[Symbol.isConcatSpreadable] = false;
assert.deepEqual(x.concat(array), [1, 2, 3, [5, 4]]);
// Explicitly spreadable
array[Symbol.isConcatSpreadable] = true;
assert.deepEqual(x.concat(array), [1, 2, 3, 5, 4]);

View File

@ -0,0 +1,44 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
flags:
- onlyStrict
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
description: |
pending
esid: pending
---*/
"use strict";
// Primitive values should never be tried to spread
let primitives = [
10,
false,
Symbol()
// Can't change String.prototype.length
];
for (let value of primitives) {
let prototype = Object.getPrototypeOf(value);
prototype[Symbol.isConcatSpreadable] = true;
Object.defineProperty(prototype, "length", {
configurable: true,
get() {
// Should never invoke length getter
assert.sameValue(true, false);
},
});
let x = [1, 2].concat(value);
assert.deepEqual(x, [1, 2, value]);
delete prototype[Symbol.isConcatSpreadable];
delete prototype.length;
prototype.length;
}

View File

@ -0,0 +1,104 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 911147;
var summary = 'Array.prototype.fill';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
assert.sameValue(typeof [].fill, 'function');
assert.sameValue([].fill.length, 1);
// Default values for arguments and absolute values for negative start and end
// arguments are resolved correctly.
assert.deepEqual([].fill(1), []);
assert.deepEqual([1,1,1].fill(2), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, 1), [1,2,2]);
assert.deepEqual([1,1,1].fill(2, 1, 2), [1,2,1]);
assert.deepEqual([1,1,1].fill(2, -2), [1,2,2]);
assert.deepEqual([1,1,1].fill(2, -2, -1), [1,2,1]);
assert.deepEqual([1,1,1].fill(2, undefined), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, undefined, undefined), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, 1, undefined), [1,2,2]);
assert.deepEqual([1,1,1].fill(2, undefined, 1), [2,1,1]);
assert.deepEqual([1,1,1].fill(2, 2, 1), [1,1,1]);
assert.deepEqual([1,1,1].fill(2, -1, 1), [1,1,1]);
assert.deepEqual([1,1,1].fill(2, -2, 1), [1,1,1]);
assert.deepEqual([1,1,1].fill(2, 1, -2), [1,1,1]);
assert.deepEqual([1,1,1].fill(2, 0.1), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, 0.9), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, 1.1), [1,2,2]);
assert.deepEqual([1,1,1].fill(2, 0.1, 0.9), [1,1,1]);
assert.deepEqual([1,1,1].fill(2, 0.1, 1.9), [2,1,1]);
assert.deepEqual([1,1,1].fill(2, 0.1, 1.9), [2,1,1]);
assert.deepEqual([1,1,1].fill(2, -0), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, 0, -0), [1,1,1]);
assert.deepEqual([1,1,1].fill(2, NaN), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, 0, NaN), [1,1,1]);
assert.deepEqual([1,1,1].fill(2, false), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, true), [1,2,2]);
assert.deepEqual([1,1,1].fill(2, "0"), [2,2,2]);
assert.deepEqual([1,1,1].fill(2, "1"), [1,2,2]);
assert.deepEqual([1,1,1].fill(2, "-2"), [1,2,2]);
assert.deepEqual([1,1,1].fill(2, "-2", "-1"), [1,2,1]);
assert.deepEqual([1,1,1].fill(2, {valueOf: ()=>1}), [1,2,2]);
assert.deepEqual([1,1,1].fill(2, 0, {valueOf: ()=>1}), [2,1,1]);
// fill works generically for objects, too.
assert.deepEqual([].fill.call({length: 2}, 2), {0: 2, 1: 2, length: 2});
var setterCalled = false;
var objWithSetter = {set "0"(val) { setterCalled = true}, length: 1};
[].fill.call(objWithSetter, 2);
assert.sameValue(setterCalled, true);
var setHandlerCallCount = 0;
var proxy = new Proxy({length: 3}, {set(t, i, v, r) { setHandlerCallCount++; return true; }});
[].fill.call(proxy, 2);
assert.sameValue(setHandlerCallCount, 3);
var valueOfCallCount = 0;
var typedArray = new Uint8ClampedArray(3);
[].fill.call(typedArray, {valueOf: function() {valueOfCallCount++; return 2000;}});
assert.sameValue(valueOfCallCount, 3);
assert.sameValue(typedArray[0], 0xff);
// All remaining cases should throw.
var objWithGetterOnly = {get "0"() {return 1;}, length: 1};
var objWithReadOnlyProp = {length: 1};
Object.defineProperty(objWithReadOnlyProp, 0, {value: 1, writable: false});
var objWithNonconfigurableProp = {length: 1};
Object.defineProperty(objWithNonconfigurableProp, 0, {value: 1, configurable: false});
var frozenObj = {length: 1};
Object.freeze(frozenObj);
var frozenArray = [1, 1, 1];
Object.freeze(frozenArray);
assertThrowsInstanceOf(() => [].fill.call(objWithGetterOnly, 2), TypeError);
assertThrowsInstanceOf(() => [].fill.call(objWithReadOnlyProp, 2), TypeError);
assertThrowsInstanceOf(() => [].fill.call(objWithNonconfigurableProp, 2), TypeError);
assertThrowsInstanceOf(() => [].fill.call(frozenObj, 2), TypeError);
assertThrowsInstanceOf(() => [].fill.call(frozenArray, 2), TypeError);
assertThrowsInstanceOf(() => [].fill.call("111", 2), TypeError);
assertThrowsInstanceOf(() => [].fill.call(null, 2), TypeError);
assertThrowsInstanceOf(() => [].fill.call(undefined, 2), TypeError);

View File

@ -0,0 +1,147 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Test corner cases of for-of iteration over Arrays.
// The current SetObject::construct method uses a ForOfIterator to extract
// values from the array, so we use that mechanism to test ForOfIterator here.
// Test the properties and prototype of a generator object.
function TestManySmallArrays() {
function doIter(f, arr) {
return f(...new Set(arr));
}
function fun(a, b, c) {
var result = 0;
for (var i = 0; i < arguments.length; i++)
result += arguments[i];
return result;
}
var TRUE_SUM = 0;
var N = 100;
var M = 3;
var sum = 0;
for (var i = 0; i < N; i++) {
var arr = new Array(M);
for (var j = 0; j < M; j++) {
arr[j] = j;
TRUE_SUM += j;
}
sum += doIter(fun, arr);
}
assert.sameValue(sum, TRUE_SUM);
}
TestManySmallArrays();
// Test the properties and prototype of a generator object.
function TestSingleSmallArray() {
function doIter(f, arr) {
return f(...new Set(arr));
}
function fun(a, b, c) {
var result = 0;
for (var i = 0; i < arguments.length; i++)
result += arguments[i];
return result;
}
var TRUE_SUM = 0;
var N = 100;
var M = 3;
var arr = new Array(M);
for (var j = 0; j < M; j++) {
arr[j] = j;
TRUE_SUM += j;
}
TRUE_SUM *= N;
var sum = 0;
for (var i = 0; i < N; i++) {
sum += doIter(fun, arr);
}
assert.sameValue(sum, TRUE_SUM);
}
TestSingleSmallArray();
function TestChangeArrayPrototype() {
function doIter(f, arr) {
return f(...new Set(arr));
}
function fun(a, b, c) {
var result = 0;
for (var i = 0; i < arguments.length; i++)
result += arguments[i];
return result;
}
var Proto1 = Object.create(Array.prototype);
var TRUE_SUM = 0;
var N = 100;
var MID = N/2;
var M = 3;
var arr = new Array(M);
var ARR_SUM = 0;
for (var j = 0; j < M; j++) {
arr[j] = j;
ARR_SUM += j;
}
var sum = 0;
for (var i = 0; i < N; i++) {
sum += doIter(fun, arr);
if (i == MID)
arr.__proto__ = Proto1;
TRUE_SUM += ARR_SUM;
}
assert.sameValue(sum, TRUE_SUM);
}
TestChangeArrayPrototype();
function TestChangeManyArrayShape() {
function doIter(f, arr) {
return f(...new Set(arr));
}
function fun(a, b, c) {
var result = 0;
for (var i = 0; i < arguments.length; i++)
result += arguments[i];
return result;
}
var TRUE_SUM = 0;
var N = 100;
var MID = N/2;
var M = 3;
var sum = 0;
for (var i = 0; i < N; i++) {
var arr = new Array(M);
var ARR_SUM = 0;
for (var j = 0; j < M; j++) {
arr[j] = j;
ARR_SUM += j;
}
arr['v_' + i] = i;
sum += doIter(fun, arr);
TRUE_SUM += ARR_SUM;
}
assert.sameValue(sum, TRUE_SUM);
}
TestChangeManyArrayShape();

View File

@ -0,0 +1,67 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Test corner cases of for-of iteration over Arrays.
// The current SetObject::construct method uses a ForOfIterator to extract
// values from the array, so we use that mechanism to test ForOfIterator here.
//
// Check case where ArrayIterator.prototype.next changes in the middle of iteration.
//
function TestChangeArrayIteratorNext() {
function doIter(f, arr) {
return f(...new Set(arr));
}
function fun(a, b, c) {
var result = 0;
for (var i = 0; i < arguments.length; i++)
result += arguments[i];
return result;
}
var GET_COUNT = 0;
function getter() {
GET_COUNT++;
if (GET_COUNT == MID)
iterProto.next = NewNext;
return M2;
}
var iter = ([])[Symbol.iterator]();
var iterProto = Object.getPrototypeOf(iter);
var OldNext = iterProto.next;
var NewNext = function () {
return OldNext.apply(this, arguments);
};
var TRUE_SUM = 0;
var N = 100;
var MID = N/2;
var M = 3;
var arr = new Array(M);
var ARR_SUM = 0;
for (var j = 0; j < M; j++) {
arr[j] = j;
ARR_SUM += j;
}
var M2 = (M/2)|0;
Object.defineProperty(arr, M2, {'get':getter});
var sum = 0;
for (var i = 0; i < N; i++) {
sum += doIter(fun, arr);
TRUE_SUM += ARR_SUM;
}
assert.sameValue(sum, TRUE_SUM);
}
TestChangeArrayIteratorNext();

View File

@ -0,0 +1,69 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Test corner cases of for-of iteration over Arrays.
// The current SetObject::construct method uses a ForOfIterator to extract
// values from the array, so we use that mechanism to test ForOfIterator here.
//
// Check array length increases changes during iteration.
//
function TestIncreaseArrayLength() {
function doIter(f, arr) {
return f(...new Set(arr));
}
function fun(a, b, c) {
var result = 0;
for (var i = 0; i < arguments.length; i++)
result += arguments[i];
return result;
}
var GET_COUNT = 0;
function getter() {
GET_COUNT++;
if (GET_COUNT == MID) {
ARR_SUM += arr.length;
arr.push(arr.length);
}
return M2;
}
var iter = ([])[Symbol.iterator]();
var iterProto = Object.getPrototypeOf(iter);
var OldNext = iterProto.next;
var NewNext = function () {
return OldNext.apply(this, arguments);
};
var TRUE_SUM = 0;
var N = 100;
var MID = N/2;
var M = 3;
var arr = new Array(M);
var ARR_SUM = 0;
for (var j = 0; j < M; j++) {
arr[j] = j;
ARR_SUM += j;
}
var M2 = (M/2)|0;
Object.defineProperty(arr, M2, {'get':getter});
var sum = 0;
for (var i = 0; i < N; i++) {
sum += doIter(fun, arr);
TRUE_SUM += ARR_SUM;
}
assert.sameValue(sum, TRUE_SUM);
}
TestIncreaseArrayLength();

View File

@ -0,0 +1,73 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Test corner cases of for-of iteration over Arrays.
// The current SetObject::construct method uses a ForOfIterator to extract
// values from the array, so we use that mechanism to test ForOfIterator here.
//
// Check array length decreases changes during iteration.
//
function TestDecreaseArrayLength() {
function doIter(f, arr) {
return f(...new Set(arr));
}
function fun(a, b, c) {
var result = 0;
for (var i = 0; i < arguments.length; i++)
result += arguments[i];
return result;
}
var GET_COUNT = 0;
function getter() {
GET_COUNT++;
if (GET_COUNT == MID) {
arr.length = 0;
}
return M2;
}
var iter = ([])[Symbol.iterator]();
var iterProto = Object.getPrototypeOf(iter);
var OldNext = iterProto.next;
var NewNext = function () {
return OldNext.apply(this, arguments);
};
var TRUE_SUM = 0;
var N = 100;
var MID = N/2;
var M = 3;
var arr = new Array(M);
var ARR_SUM = 0;
for (var j = 0; j < M; j++) {
arr[j] = j;
ARR_SUM += j;
}
var M2 = (M/2)|0;
Object.defineProperty(arr, M2, {'get':getter});
var sum = 0;
for (var i = 0; i < N; i++) {
var oldLen = arr.length;
sum += doIter(fun, arr);
var newLen = arr.length;
if (oldLen == newLen)
TRUE_SUM += arr.length > 0 ? ARR_SUM : 0;
else
TRUE_SUM += 1
}
assert.sameValue(sum, TRUE_SUM);
}
TestDecreaseArrayLength();

View File

@ -0,0 +1,192 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var BUGNUMBER = 1180306;
var summary = 'Array.from should close iterator on error';
print(BUGNUMBER + ": " + summary);
function test(ctor, { mapVal=undefined,
nextVal=undefined,
nextThrowVal=undefined,
modifier=undefined,
exceptionVal=undefined,
exceptionType=undefined,
closed=true }) {
let iterable = {
closed: false,
[Symbol.iterator]() {
let iterator = {
first: true,
next() {
if (this.first) {
this.first = false;
if (nextThrowVal)
throw nextThrowVal;
return nextVal;
}
return { value: undefined, done: true };
},
return() {
iterable.closed = true;
return {};
}
};
if (modifier)
modifier(iterator, iterable);
return iterator;
}
};
if (exceptionVal) {
let caught = false;
try {
ctor.from(iterable, mapVal);
} catch (e) {
assert.sameValue(e, exceptionVal);
caught = true;
}
assert.sameValue(caught, true);
} else if (exceptionType) {
assertThrowsInstanceOf(() => ctor.from(iterable, mapVal), exceptionType);
} else {
ctor.from(iterable, mapVal);
}
assert.sameValue(iterable.closed, closed);
}
// == Error cases with close ==
// ES 2017 draft 22.1.2.1 step 5.e.i.1.
// Cannot test.
// ES 2017 draft 22.1.2.1 step 5.e.vi.2.
test(Array, {
mapVal: () => { throw "map throws"; },
nextVal: { value: 1, done: false },
exceptionVal: "map throws",
closed: true,
});
// ES 2017 draft 22.1.2.1 step 5.e.ix.
class MyArray extends Array {
constructor() {
return new Proxy({}, {
defineProperty() {
throw "defineProperty throws";
}
});
}
}
test(MyArray, {
nextVal: { value: 1, done: false },
exceptionVal: "defineProperty throws",
closed: true,
});
// ES 2021 draft 7.4.6 step 5.
// if GetMethod fails, the thrown value should be ignored.
test(MyArray, {
nextVal: { value: 1, done: false },
modifier: (iterator, iterable) => {
Object.defineProperty(iterator, "return", {
get: function() {
iterable.closed = true;
throw "return getter throws";
}
});
},
exceptionVal: "defineProperty throws",
closed: true,
});
test(MyArray, {
nextVal: { value: 1, done: false },
modifier: (iterator, iterable) => {
Object.defineProperty(iterator, "return", {
get: function() {
iterable.closed = true;
return "non object";
}
});
},
exceptionVal: "defineProperty throws",
closed: true,
});
test(MyArray, {
nextVal: { value: 1, done: false },
modifier: (iterator, iterable) => {
Object.defineProperty(iterator, "return", {
get: function() {
iterable.closed = true;
// Non callable.
return {};
}
});
},
exceptionVal: "defineProperty throws",
closed: true,
});
// ES 2017 draft 7.4.6 steps 6.
// if return method throws, the thrown value should be ignored.
test(MyArray, {
nextVal: { value: 1, done: false },
modifier: (iterator, iterable) => {
iterator.return = function() {
iterable.closed = true;
throw "return throws";
};
},
exceptionVal: "defineProperty throws",
closed: true,
});
test(MyArray, {
nextVal: { value: 1, done: false },
modifier: (iterator, iterable) => {
iterator.return = function() {
iterable.closed = true;
return "non object";
};
},
exceptionVal: "defineProperty throws",
closed: true,
});
// == Error cases without close ==
// ES 2017 draft 22.1.2.1 step 5.e.iii.
test(Array, {
nextThrowVal: "next throws",
exceptionVal: "next throws",
closed: false,
});
test(Array, {
nextVal: { value: {}, get done() { throw "done getter throws"; } },
exceptionVal: "done getter throws",
closed: false,
});
// ES 2017 draft 22.1.2.1 step 5.e.v.
test(Array, {
nextVal: { get value() { throw "value getter throws"; }, done: false },
exceptionVal: "value getter throws",
closed: false,
});
// == Successful cases ==
test(Array, {
nextVal: { value: 1, done: false },
closed: false,
});

View File

@ -0,0 +1,59 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Array.from copies arrays.
var src = [1, 2, 3], copy = Array.from(src);
assert.sameValue(copy === src, false);
assert.sameValue(Array.isArray(copy), true);
assert.deepEqual(copy, src);
// Non-element properties are not copied.
var a = [0, 1];
a.name = "lisa";
assert.deepEqual(Array.from(a), [0, 1]);
// It's a shallow copy.
src = [[0], [1]];
copy = Array.from(src);
assert.sameValue(copy[0], src[0]);
assert.sameValue(copy[1], src[1]);
// Array.from can copy non-iterable objects, if they're array-like.
src = {0: "zero", 1: "one", length: 2};
copy = Array.from(src);
assert.sameValue(Array.isArray(copy), true);
assert.deepEqual(copy, ["zero", "one"]);
// Properties past the .length are not copied.
src = {0: "zero", 1: "one", 2: "two", 9: "nine", name: "lisa", length: 2};
assert.deepEqual(Array.from(src), ["zero", "one"]);
// If an object has neither an @@iterator method nor .length,
// then it's treated as zero-length.
assert.deepEqual(Array.from({}), []);
// Source object property order doesn't matter.
src = {length: 2, 1: "last", 0: "first"};
assert.deepEqual(Array.from(src), ["first", "last"]);
// Array.from does not preserve holes.
assert.deepEqual(Array.from(Array(3)), [undefined, undefined, undefined]);
assert.deepEqual(Array.from([, , 2, 3]), [undefined, undefined, 2, 3]);
assert.deepEqual(Array.from([0, , , ,]), [0, undefined, undefined, undefined]);
// Even on non-iterable objects.
assert.deepEqual(Array.from({length: 4}), [undefined, undefined, undefined, undefined]);
// Array.from should coerce negative lengths to zero.
assert.deepEqual(Array.from({length: -1}), []);

View File

@ -0,0 +1,64 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Array.from can be applied to any constructor.
// For example, the Date builtin constructor.
var d = Array.from.call(Date, ["A", "B"]);
assert.sameValue(Array.isArray(d), false);
assert.sameValue(Object.prototype.toString.call(d), "[object Date]");
assert.sameValue(Object.getPrototypeOf(d), Date.prototype);
assert.sameValue(d.length, 2);
assert.sameValue(d[0], "A");
assert.sameValue(d[1], "B");
// Or Object.
var obj = Array.from.call(Object, []);
assert.sameValue(Array.isArray(obj), false);
assert.sameValue(Object.getPrototypeOf(obj), Object.prototype);
assert.sameValue(Object.getOwnPropertyNames(obj).join(","), "length");
assert.sameValue(obj.length, 0);
// Or any JS function.
function C(arg) {
this.args = arguments;
}
var c = Array.from.call(C, {length: 1, 0: "zero"});
assert.sameValue(c instanceof C, true);
assert.sameValue(c.args.length, 1);
assert.sameValue(c.args[0], 1);
assert.sameValue(c.length, 1);
assert.sameValue(c[0], "zero");
// If the 'this' value passed to Array.from is not a constructor,
// a plain Array is created.
var arr = [3, 4, 5];
var nonconstructors = [
{}, Math, Object.getPrototypeOf, undefined, 17,
() => ({}) // arrow functions are not constructors
];
for (var v of nonconstructors) {
obj = Array.from.call(v, arr);
assert.sameValue(Array.isArray(obj), true);
assert.deepEqual(obj, arr);
}
// Array.from does not get confused if global.Array is replaced with another
// constructor.
function NotArray() {
}
var RealArray = Array;
NotArray.from = Array.from;
Array = NotArray;
assert.sameValue(RealArray.from([1]) instanceof RealArray, true);
assert.sameValue(NotArray.from([1]) instanceof NotArray, true);

View File

@ -0,0 +1,160 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Array.from throws if the argument is undefined or null.
assertThrowsInstanceOf(() => Array.from(), TypeError);
assertThrowsInstanceOf(() => Array.from(undefined), TypeError);
assertThrowsInstanceOf(() => Array.from(null), TypeError);
// Array.from throws if an element can't be defined on the new object.
function ObjectWithReadOnlyElement() {
Object.defineProperty(this, "0", {value: null});
this.length = 0;
}
ObjectWithReadOnlyElement.from = Array.from;
assert.deepEqual(ObjectWithReadOnlyElement.from([]), new ObjectWithReadOnlyElement);
assertThrowsInstanceOf(() => ObjectWithReadOnlyElement.from([1]), TypeError);
// The same, but via preventExtensions.
function InextensibleObject() {
Object.preventExtensions(this);
}
InextensibleObject.from = Array.from;
assertThrowsInstanceOf(() => InextensibleObject.from([1]), TypeError);
// We will now test this property, that Array.from throws if the .length can't
// be assigned, using several different kinds of object.
var obj;
function init(self) {
obj = self;
self[0] = self[1] = self[2] = self[3] = 0;
}
function testUnsettableLength(C, Exc) {
if (Exc === undefined)
Exc = TypeError; // the usual expected exception type
C.from = Array.from;
obj = null;
assertThrowsInstanceOf(() => C.from([]), Exc);
assert.sameValue(obj instanceof C, true);
for (var i = 0; i < 4; i++)
assert.sameValue(obj[0], 0);
obj = null;
assertThrowsInstanceOf(() => C.from([0, 10, 20, 30]), Exc);
assert.sameValue(obj instanceof C, true);
for (var i = 0; i < 4; i++)
assert.sameValue(obj[i], i * 10);
}
// Array.from throws if the new object's .length can't be assigned because
// there is no .length and the object is inextensible.
function InextensibleObject4() {
init(this);
Object.preventExtensions(this);
}
testUnsettableLength(InextensibleObject4);
// Array.from throws if the new object's .length can't be assigned because it's
// read-only.
function ObjectWithReadOnlyLength() {
init(this);
Object.defineProperty(this, "length", {configurable: true, writable: false, value: 4});
}
testUnsettableLength(ObjectWithReadOnlyLength);
// The same, but using a builtin type.
Uint8Array.from = Array.from;
assertThrowsInstanceOf(() => Uint8Array.from([]), TypeError);
// Array.from throws if the new object's .length can't be assigned because it
// inherits a readonly .length along the prototype chain.
function ObjectWithInheritedReadOnlyLength() {
init(this);
}
Object.defineProperty(ObjectWithInheritedReadOnlyLength.prototype,
"length",
{configurable: true, writable: false, value: 4});
testUnsettableLength(ObjectWithInheritedReadOnlyLength);
// The same, but using an object with a .length getter but no setter.
function ObjectWithGetterOnlyLength() {
init(this);
Object.defineProperty(this, "length", {configurable: true, get: () => 4});
}
testUnsettableLength(ObjectWithGetterOnlyLength);
// The same, but with a setter that throws.
function ObjectWithThrowingLengthSetter() {
init(this);
Object.defineProperty(this, "length", {
configurable: true,
get: () => 4,
set: () => { throw new RangeError("surprise!"); }
});
}
testUnsettableLength(ObjectWithThrowingLengthSetter, RangeError);
// Array.from throws if mapfn is neither callable nor undefined.
assertThrowsInstanceOf(() => Array.from([3, 4, 5], {}), TypeError);
assertThrowsInstanceOf(() => Array.from([3, 4, 5], "also not a function"), TypeError);
assertThrowsInstanceOf(() => Array.from([3, 4, 5], null), TypeError);
// Even if the function would not have been called.
assertThrowsInstanceOf(() => Array.from([], JSON), TypeError);
// If mapfn is not undefined and not callable, the error happens before anything else.
// Before calling the constructor, before touching the arrayLike.
var log = "";
function C() {
log += "C";
obj = this;
}
var p = new Proxy({}, {
has: function () { log += "1"; },
get: function () { log += "2"; },
getOwnPropertyDescriptor: function () { log += "3"; }
});
assertThrowsInstanceOf(() => Array.from.call(C, p, {}), TypeError);
assert.sameValue(log, "");
// If mapfn throws, the new object has already been created.
var arrayish = {
get length() { log += "l"; return 1; },
get 0() { log += "0"; return "q"; }
};
log = "";
var exc = {surprise: "ponies"};
assertThrowsValue(() => Array.from.call(C, arrayish, () => { throw exc; }), exc);
assert.sameValue(log, "lC0");
assert.sameValue(obj instanceof C, true);
// It's a TypeError if the @@iterator property is a primitive (except null and undefined).
for (var primitive of ["foo", 17, Symbol(), true]) {
assertThrowsInstanceOf(() => Array.from({[Symbol.iterator] : primitive}), TypeError);
}
assert.deepEqual(Array.from({[Symbol.iterator]: null}), []);
assert.deepEqual(Array.from({[Symbol.iterator]: undefined}), []);
// It's a TypeError if the iterator's .next() method returns a primitive.
for (var primitive of [undefined, null, 17]) {
assertThrowsInstanceOf(
() => Array.from({
[Symbol.iterator]() {
return {next() { return primitive; }};
}
}),
TypeError);
}

View File

@ -0,0 +1,58 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Array.from works on arguments objects.
(function () {
assert.deepEqual(Array.from(arguments), ["arg0", "arg1", undefined]);
})("arg0", "arg1", undefined);
// If an object has both .length and [@@iterator] properties, [@@iterator] is used.
var a = ['a', 'e', 'i', 'o', 'u'];
a[Symbol.iterator] = function* () {
for (var i = 5; i--; )
yield this[i];
};
var log = '';
function f(x) {
log += x;
return x + x;
}
var b = Array.from(a, f);
assert.deepEqual(b, ['uu', 'oo', 'ii', 'ee', 'aa']);
assert.sameValue(log, 'uoiea');
// In fact, if [@@iterator] is present, .length isn't queried at all.
var pa = new Proxy(a, {
has: function (target, id) {
if (id === "length")
throw new Error(".length should not be queried (has)");
return id in target;
},
get: function (target, id) {
if (id === "length")
throw new Error(".length should not be queried (get)");
return target[id];
},
getOwnPropertyDescriptor: function (target, id) {
if (id === "length")
throw new Error(".length should not be queried (getOwnPropertyDescriptor)");
return Object.getOwnPropertyDescriptor(target, id)
}
});
log = "";
b = Array.from(pa, f);
assert.deepEqual(b, ['uu', 'oo', 'ii', 'ee', 'aa']);
assert.sameValue(log, 'uoiea');

View File

@ -0,0 +1,21 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Array.from calls a length setter if present.
var hits = 0;
function C() {}
C.prototype = {set length(v) { hits++; }};
C.from = Array.from;
var copy = C.from(["A", "B"]);
assert.sameValue(hits, 1);

View File

@ -0,0 +1,49 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// If the mapfn argument to Array.from is undefined, don't map.
assert.deepEqual(Array.from([3, 4, 5], undefined), [3, 4, 5]);
assert.deepEqual(Array.from([4, 5, 6], undefined, Math), [4, 5, 6]);
// mapfn is called with two arguments: value and index.
var log = [];
function f() {
log.push(Array.from(arguments));
return log.length;
}
assert.deepEqual(Array.from(['a', 'e', 'i', 'o', 'u'], f), [1, 2, 3, 4, 5]);
assert.deepEqual(log, [['a', 0], ['e', 1], ['i', 2], ['o', 3], ['u', 4]]);
// If the object to be copied is non-iterable, mapfn is still called with two
// arguments.
log = [];
assert.deepEqual(Array.from({0: "zero", 1: "one", length: 2}, f), [1, 2]);
assert.deepEqual(log, [["zero", 0], ["one", 1]]);
// If the object to be copied is iterable and the constructor is not Array,
// mapfn is still called with two arguments.
log = [];
function C() {}
C.from = Array.from;
var c = new C;
c[0] = 1;
c[1] = 2;
c.length = 2;
assert.deepEqual(C.from(["zero", "one"], f), c);
assert.deepEqual(log, [["zero", 0], ["one", 1]]);
// The mapfn is called even if the value to be mapped is undefined.
assert.deepEqual(Array.from([0, 1, , 3], String), ["0", "1", "undefined", "3"]);
var arraylike = {length: 4, "0": 0, "1": 1, "3": 3};
assert.deepEqual(Array.from(arraylike, String), ["0", "1", "undefined", "3"]);

View File

@ -0,0 +1,29 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
for (let primitive of [true, 3.14, "hello", Symbol()]) {
let prototype = Object.getPrototypeOf(primitive);
Object.defineProperty(prototype, Symbol.iterator, {
configurable: true,
get() {
"use strict";
assert.sameValue(this, primitive);
return () => [this][Symbol.iterator]();
},
});
assert.sameValue(Array.from(primitive)[0], primitive);
delete prototype[Symbol.iterator];
}

View File

@ -0,0 +1,63 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Two tests involving Array.from and a Proxy.
var log = [];
function LoggingProxy(target) {
var h = {
defineProperty: function (t, id) {
log.push("define", id);
return true;
},
has: function (t, id) {
log.push("has", id);
return id in t;
},
get: function (t, id) {
log.push("get", id);
return t[id];
},
set: function (t, id, v) {
log.push("set", id);
t[id] = v;
return true;
}
};
return new Proxy(target || [], h);
}
// When the new object created by Array.from is a Proxy,
// Array.from calls handler.defineProperty to create new elements
// but handler.set to set the length.
LoggingProxy.from = Array.from;
LoggingProxy.from([3, 4, 5]);
assert.deepEqual(log, ["define", "0", "define", "1", "define", "2", "set", "length"]);
// When the argument passed to Array.from is a Proxy, Array.from
// calls handler.get on it.
log = [];
assert.deepEqual(Array.from(new LoggingProxy([3, 4, 5])), [3, 4, 5]);
assert.deepEqual(log, ["get", Symbol.iterator,
"get", "length", "get", "0",
"get", "length", "get", "1",
"get", "length", "get", "2",
"get", "length"]);
// Array-like iteration only gets the length once.
log = [];
var arr = [5, 6, 7];
arr[Symbol.iterator] = undefined;
assert.deepEqual(Array.from(new LoggingProxy(arr)), [5, 6, 7]);
assert.deepEqual(log, ["get", Symbol.iterator,
"get", "length", "get", "0", "get", "1", "get", "2"]);

View File

@ -0,0 +1,45 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
if (typeof createNewGlobal === 'function') {
// G.Array.from, where G is any global, produces an array whose prototype
// is G.Array.prototype.
var g = createNewGlobal();
var ga = g.Array.from([1, 2, 3]);
assert.sameValue(ga instanceof g.Array, true);
// Even if G.Array is not passed in as the 'this' value to the call.
var from = g.Array.from
var ga2 = from([1, 2, 3]);
assert.sameValue(ga2 instanceof g.Array, true);
// Array.from can be applied to a constructor from another realm.
var p = Array.from.call(g.Array, [1, 2, 3]);
assert.sameValue(p instanceof g.Array, true);
var q = g.Array.from.call(Array, [3, 4, 5]);
assert.sameValue(q instanceof Array, true);
// The default 'this' value received by a non-strict mapping function is
// that function's global, not Array.from's global or the caller's global.
var h = createNewGlobal(), result = undefined;
h.mainGlobal = this;
h.eval("function f() { mainGlobal.result = this; }");
g.Array.from.call(Array, [5, 6, 7], h.f);
// (Give each global in the test a name, for better error messages. But use
// globalName, because window.name is complicated.)
this.globalName = "main";
g.globalName = "g";
h.globalName = "h";
assert.sameValue(result.globalName, "h");
}

View File

@ -0,0 +1,31 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Array.from on a string iterates over the string.
assert.deepEqual(Array.from("test string"),
['t', 'e', 's', 't', ' ', 's', 't', 'r', 'i', 'n', 'g']);
// Array.from on a string handles surrogate pairs correctly.
var gclef = "\uD834\uDD1E"; // U+1D11E MUSICAL SYMBOL G CLEF
assert.deepEqual(Array.from(gclef), [gclef]);
assert.deepEqual(Array.from(gclef + " G"), [gclef, " ", "G"]);
// Array.from on a string calls the @@iterator method.
String.prototype[Symbol.iterator] = function* () { yield 1; yield 2; };
assert.deepEqual(Array.from("anything"), [1, 2]);
// If the iterator method is deleted, Strings are still arraylike.
delete String.prototype[Symbol.iterator];
assert.deepEqual(Array.from("works"), ['w', 'o', 'r', 'k', 's']);
assert.deepEqual(Array.from(gclef), ['\uD834', '\uDD1E']);

View File

@ -0,0 +1,21 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Check superficial features of Array.from.
var desc = Object.getOwnPropertyDescriptor(Array, "from");
assert.sameValue(desc.configurable, true);
assert.sameValue(desc.enumerable, false);
assert.sameValue(desc.writable, true);
assert.sameValue(Array.from.length, 1);
assertThrowsInstanceOf(() => new Array.from(), TypeError); // not a constructor

View File

@ -0,0 +1,56 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// The third argument to Array.from is passed as the 'this' value to the
// mapping function.
var hits = 0, obj = {};
function f(x) {
assert.sameValue(this, obj);
hits++;
}
Array.from(["a", "b", "c"], f, obj);
assert.sameValue(hits, 3);
// Without an argument, undefined is passed...
hits = 0;
function gs(x) {
"use strict";
assert.sameValue(this, undefined);
hits++;
}
Array.from("def", gs);
assert.sameValue(hits, 3);
// ...and if the mapping function is non-strict, that means the global is
// passed.
var global = this;
hits = 0;
function g(x) {
assert.sameValue(this, global);
hits++;
}
Array.from("ghi", g);
assert.sameValue(hits, 3);
// A primitive value can be passed.
for (var v of [0, "str", undefined]) {
hits = 0;
var mapfn = function h(x) {
"use strict";
assert.sameValue(this, v);
hits++;
};
Array.from("pq", mapfn, v);
assert.sameValue(hits, 2);
}

View File

@ -0,0 +1,51 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Author: Emilio Cobos Álvarez <ecoal95@gmail.com>
*/
var BUGNUMBER = 1310744;
var summary = "Dense array properties shouldn't be modified when they're frozen";
print(BUGNUMBER + ": " + summary);
var a = Object.freeze([4, 5, 1]);
function assertArrayIsExpected() {
assert.sameValue(a.length, 3);
assert.sameValue(a[0], 4);
assert.sameValue(a[1], 5);
assert.sameValue(a[2], 1);
}
assertThrowsInstanceOf(() => a.reverse(), TypeError);
assertThrowsInstanceOf(() => a.shift(), TypeError);
assertThrowsInstanceOf(() => a.unshift(0), TypeError);
assertThrowsInstanceOf(() => a.sort(function() {}), TypeError);
assertThrowsInstanceOf(() => a.pop(), TypeError);
assertThrowsInstanceOf(() => a.fill(0), TypeError);
assertThrowsInstanceOf(() => a.splice(0, 1, 1), TypeError);
assertThrowsInstanceOf(() => a.push("foo"), TypeError);
assertThrowsInstanceOf(() => { "use strict"; a.length = 5; }, TypeError);
assertThrowsInstanceOf(() => { "use strict"; a[2] = "foo"; }, TypeError);
assertThrowsInstanceOf(() => { "use strict"; delete a[0]; }, TypeError);
assertThrowsInstanceOf(() => a.splice(Math.a), TypeError);
// Shouldn't throw, since this is not strict mode, but shouldn't change the
// value of the property.
a.length = 5;
a[2] = "foo";
assert.sameValue(delete a[0], false);
assertArrayIsExpected();

View File

@ -0,0 +1,27 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Author: Emilio Cobos Álvarez <ecoal95@gmail.com>
*/
var BUGNUMBER = 1312948;
var summary = "Freezing a dictionary mode object with a length property should make Object.isFrozen report true";
print(BUGNUMBER + ": " + summary);
/* Convert to dictionary mode */
delete Array.prototype.slice;
Object.freeze(Array.prototype);
assert.sameValue(Object.isFrozen(Array.prototype), true);

View File

@ -0,0 +1,18 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var BUGNUMBER = 1180290;
var summary = 'Array getters should have get prefix';
print(BUGNUMBER + ": " + summary);
assert.sameValue(Object.getOwnPropertyDescriptor(Array, Symbol.species).get.name, "get [Symbol.species]");

View File

@ -0,0 +1,27 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var array = [1, 2, 3];
var calls = 0;
var grouped = Object.groupBy(array, () => {
calls++;
return {
toString() {
return "a";
}
}
});
assert.sameValue(calls, 3);

View File

@ -0,0 +1,24 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var array = [0];
var grouped = Object.groupBy(array, () => "length");
assert.deepEqual(grouped, Object.create(null, {
length: {
value: [0],
writable: true,
enumerable: true,
configurable: true,
},
}));

View File

@ -0,0 +1,98 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
function isNeg(x) {
if (Object.is(x, -0) || x < 0) {
return true;
}
return false;
}
{
const a1 = [-Infinity, -2, -1, -0, 0, 1, 2, Infinity];
const expectedObj = { neg: [-Infinity, -2, -1, -0], pos: [0, 1, 2, Infinity] };
Object.setPrototypeOf(expectedObj, null);
const groupedArray = Object.groupBy(a1, x => isNeg(x) ? 'neg' : 'pos');
const mappedArray = Map.groupBy(a1, x => isNeg(x) ? 'neg' : 'pos');
assert.sameValue(Object.getPrototypeOf(groupedArray), null)
assert.deepEqual(groupedArray, expectedObj);
assert.deepEqual(mappedArray.get("neg"), expectedObj["neg"]);
assert.deepEqual(mappedArray.get("pos"), expectedObj["pos"]);
const expectedObj2 = {"undefined": [1,2,3]}
Object.setPrototypeOf(expectedObj2, null);
assert.deepEqual(Object.groupBy([1,2,3], () => {}), expectedObj2);
assert.deepEqual(Object.groupBy([], () => {}), Object.create(null));
assert.deepEqual((Map.groupBy([1,2,3], () => {})).get(undefined), [1,2,3]);
assert.sameValue((Map.groupBy([1,2,3], () => {})).size, 1);
const negMappedArray = Map.groupBy(a1, x => isNeg(x) ? -0 : 0);
assert.deepEqual(negMappedArray.get(0), a1);
assert.deepEqual(negMappedArray.size, 1);
assertThrowsInstanceOf(() => Object.groupBy([], undefined), TypeError);
assertThrowsInstanceOf(() => Object.groupBy([], null), TypeError);
assertThrowsInstanceOf(() => Object.groupBy([], 0), TypeError);
assertThrowsInstanceOf(() => Object.groupBy([], ""), TypeError);
assertThrowsInstanceOf(() => Map.groupBy([], undefined), TypeError);
assertThrowsInstanceOf(() => Map.groupBy([], null), TypeError);
assertThrowsInstanceOf(() => Map.groupBy([], 0), TypeError);
assertThrowsInstanceOf(() => Map.groupBy([], ""), TypeError);
}
const array = [ 'test' ];
Object.defineProperty(Map.prototype, 4, {
get() {
throw new Error('monkey-patched Map get call');
},
set(v) {
throw new Error('monkey-patched Map set call');
},
has(v) {
throw new Error('monkey-patched Map has call');
}
});
const map1 = Map.groupBy(array, key => key.length);
assert.sameValue('test', map1.get(4)[0])
Object.defineProperty(Array.prototype, '4', {
set(v) {
throw new Error('user observable array set');
},
get() {
throw new Error('user observable array get');
}
});
const map2 = Map.groupBy(array, key => key.length);
const arr = Object.groupBy(array, key => key.length);
assert.sameValue('test', map2.get(4)[0])
assert.sameValue('test', arr[4][0])
Object.defineProperty(Object.prototype, "foo", {
get() { throw new Error("user observable object get"); },
set(v) { throw new Error("user observable object set"); }
});
Object.groupBy([1, 2, 3], () => 'foo');
// Ensure property key is correctly accessed
count = 0;
p = Object.groupBy([1], () => ({ toString() { count++; return 10 } }));
assert.sameValue(count, 1);
Map.groupBy([1], () => ({ toString() { count++; return 10 } }));
assert.sameValue(count, 1);

View File

@ -0,0 +1,25 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Array with trailing hole as explicit "magic elements hole".
assert.sameValue([,].includes(), true);
assert.sameValue([,].includes(undefined), true);
assert.sameValue([,].includes(undefined, 0), true);
assert.sameValue([,].includes(null), false);
assert.sameValue([,].includes(null, 0), false);
// Array with trailing hole with no explicit "magic elements hole".
assert.sameValue(Array(1).includes(), true);
assert.sameValue(Array(1).includes(undefined), true);
assert.sameValue(Array(1).includes(undefined, 0), true);
assert.sameValue(Array(1).includes(null), false);
assert.sameValue(Array(1).includes(null, 0), false);

View File

@ -0,0 +1,65 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var BUGNUMBER = 1069063;
var summary = "Implement Array.prototype.includes";
print(BUGNUMBER + ": " + summary);
assert.sameValue(typeof [].includes, "function");
assert.sameValue([].includes.length, 1);
assertTrue([1, 2, 3].includes(2));
assertTrue([1,,2].includes(2));
assertTrue([1, 2, 3].includes(2, 1));
assertTrue([1, 2, 3].includes(2, -2));
assertTrue([1, 2, 3].includes(2, -100));
assertTrue([Object, Function, Array].includes(Function));
assertTrue([-0].includes(0));
assertTrue([NaN].includes(NaN));
assertTrue([,].includes());
assertTrue(staticIncludes("123", "2"));
assertTrue(staticIncludes({length: 3, 1: 2}, 2));
assertTrue(staticIncludes({length: 3, 1: 2, get 3(){throw ""}}, 2));
assertTrue(staticIncludes({length: 3, get 1() {return 2}}, 2));
assertTrue(staticIncludes({__proto__: {1: 2}, length: 3}, 2));
assertTrue(staticIncludes(new Proxy([1], {get(){return 2}}), 2));
assertFalse([1, 2, 3].includes("2"));
assertFalse([1, 2, 3].includes(2, 2));
assertFalse([1, 2, 3].includes(2, -1));
assertFalse([undefined].includes(NaN));
assertFalse([{}].includes({}));
assertFalse(staticIncludes({length: 3, 1: 2}, 2, 2));
assertFalse(staticIncludes({length: 3, get 0(){delete this[1]}, 1: 2}, 2));
assertFalse(staticIncludes({length: -100, 0: 1}, 1));
assertThrowsInstanceOf(() => staticIncludes(), TypeError);
assertThrowsInstanceOf(() => staticIncludes(null), TypeError);
assertThrowsInstanceOf(() => staticIncludes({get length(){throw TypeError()}}), TypeError);
assertThrowsInstanceOf(() => staticIncludes({length: 3, get 1() {throw TypeError()}}, 2), TypeError);
assertThrowsInstanceOf(() => staticIncludes({__proto__: {get 1() {throw TypeError()}}, length: 3}, 2), TypeError);
assertThrowsInstanceOf(() => staticIncludes(new Proxy([1], {get(){throw TypeError()}})), TypeError);
function assertTrue(v) {
assert.sameValue(v, true);
}
function assertFalse(v) {
assert.sameValue(v, false);
}
function staticIncludes(o, v, f) {
return [].includes.call(o, v, f);
}

View File

@ -0,0 +1,24 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var testArray = [1, 2, 3]
assert.sameValue(testArray['0' + '\0'], undefined);
assert.sameValue(testArray['1' + '\0' + 'aaaa'], undefined)
assert.sameValue(testArray['\0' + '2'], undefined);
assert.sameValue(testArray['\0' + ' 2'], undefined);
testArray['\0'] = 'hello';
testArray[' \0'] = 'world';
assert.sameValue(testArray['\0'], 'hello');
assert.sameValue(testArray[' \0'], 'world');

View File

@ -0,0 +1,13 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
assert.sameValue([17].indexOf(17, -0), +0);

View File

@ -0,0 +1,49 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [compareArray.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
function makeArray(array) {
var log = [];
Object.setPrototypeOf(array, new Proxy(Array.prototype, new Proxy({
has(t, pk) {
log.push(`Has:${String(pk)}`);
return Reflect.has(t, pk);
},
}, {
get(t, pk, r) {
if (pk in t)
return Reflect.get(t, pk, r);
throw new Error(`Unexpected trap "${pk}" called`);
}
})));
return {array, log};
}
var {array, log} = makeArray([1, null, 3]);
Array.prototype.indexOf.call(array, 100, {
valueOf() {
array.length = 0;
return 0;
}
});
assert.compareArray(log, ["Has:0", "Has:1", "Has:2"]);
var {array, log} = makeArray([5, undefined, 7]);
Array.prototype.lastIndexOf.call(array, 100, {
valueOf() {
array.length = 0;
return 2;
}
});
assert.compareArray(log, ["Has:2", "Has:1", "Has:0"]);

View File

@ -0,0 +1,75 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var global = this;
var otherGlobal = createNewGlobal();
var thisGlobal = () => global;
var alternateGlobals = (function(i) {
return () => (i++ % 2) === 0 ? global : otherGlobal;
})(0);
function performTests(pickGlobal)
{
// Base case.
assert.sameValue(Array.isArray([]), true);
// Simple case: proxy to an array.
var proxy = new (pickGlobal()).Proxy([], {});
assert.sameValue(Array.isArray(proxy), true);
// Recursive proxy ultimately terminating in an array.
for (var i = 0; i < 10; i++) {
proxy = new (pickGlobal()).Proxy(proxy, {});
assert.sameValue(Array.isArray(proxy), true);
}
// Revocable proxy to an array.
var revocable = (pickGlobal()).Proxy.revocable([], {});
proxy = revocable.proxy;
assert.sameValue(Array.isArray(proxy), true);
// Recursive proxy ultimately terminating in a revocable proxy to an array.
for (var i = 0; i < 10; i++) {
proxy = new (pickGlobal()).Proxy(proxy, {});
assert.sameValue(Array.isArray(proxy), true);
}
// Revoked proxy to (formerly) an array.
revocable.revoke();
assertThrowsInstanceOf(() => Array.isArray(revocable.proxy), TypeError);
// Recursive proxy ultimately terminating in a revoked proxy to an array.
assertThrowsInstanceOf(() => Array.isArray(proxy), TypeError);
}
performTests(thisGlobal);
performTests(alternateGlobals);
function crossGlobalTest()
{
var array = new otherGlobal.Array();
// Array from another global.
assert.sameValue(Array.isArray(array), true);
// Proxy to an array from another global.
assert.sameValue(Array.isArray(new Proxy(array, {})), true);
// Other-global proxy to an array from that selfsame global.
assert.sameValue(Array.isArray(new otherGlobal.Proxy(array, {})), true);
}
crossGlobalTest();

View File

@ -0,0 +1,86 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
print("ES5: Array.prototype.join");
/**************
* BEGIN TEST *
**************/
var count;
var stringifyCounter = { toString: function() { count++; return "obj"; } };
var arr = [1, 2, 3, 4, 5];
assert.sameValue(arr.join(), "1,2,3,4,5");
assert.sameValue(arr.join(","), "1,2,3,4,5");
assert.sameValue(arr.join(undefined), "1,2,3,4,5");
assert.sameValue(arr.join(4), "142434445");
assert.sameValue(arr.join(""), "12345");
count = 0;
assert.sameValue(arr.join(stringifyCounter), "1obj2obj3obj4obj5");
assert.sameValue(count, 1);
var holey = [1, 2, , 4, 5];
assert.sameValue(holey.join(), "1,2,,4,5");
assert.sameValue(holey.join(","), "1,2,,4,5");
assert.sameValue(holey.join(undefined), "1,2,,4,5");
assert.sameValue(holey.join(4), "14244445");
count = 0;
assert.sameValue(holey.join(stringifyCounter), "1obj2objobj4obj5");
assert.sameValue(count, 1);
var nully = [1, 2, 3, null, 5];
assert.sameValue(nully.join(), "1,2,3,,5");
assert.sameValue(nully.join(","), "1,2,3,,5");
assert.sameValue(nully.join(undefined), "1,2,3,,5");
assert.sameValue(nully.join(4), "14243445");
count = 0;
assert.sameValue(nully.join(stringifyCounter), "1obj2obj3objobj5");
assert.sameValue(count, 1);
var undefiney = [1, undefined, 3, 4, 5];
assert.sameValue(undefiney.join(), "1,,3,4,5");
assert.sameValue(undefiney.join(","), "1,,3,4,5");
assert.sameValue(undefiney.join(undefined), "1,,3,4,5");
assert.sameValue(undefiney.join(4), "14434445");
count = 0;
assert.sameValue(undefiney.join(stringifyCounter), "1objobj3obj4obj5");
assert.sameValue(count, 1);
var log = '';
arr = {length: {valueOf: function () { log += "L"; return 2; }},
0: "x", 1: "z"};
var sep = {toString: function () { log += "S"; return "y"; }};
assert.sameValue(Array.prototype.join.call(arr, sep), "xyz");
assert.sameValue(log, "LS");
var funky =
{
toString: function()
{
Array.prototype[1] = "chorp";
Object.prototype[3] = "fnord";
return "funky";
}
};
var trailingHoles = [0, funky, /* 2 */, /* 3 */,];
assert.sameValue(trailingHoles.join(""), "0funkyfnord");
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,45 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [compareArray.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Test that Array.prototype.join doesn't call the [[HasProperty]] internal
// method of objects.
var log = [];
var array = [];
var proxy = new Proxy(array, new Proxy({}, {
get(t, trap, r) {
return (t, pk, ...more) => {
log.push(`${trap}:${String(pk)}`);
return Reflect[trap](t, pk, ...more);
};
}
}));
var result;
result = Array.prototype.join.call(proxy);
assert.compareArray(log, [ "get:length" ]);
assert.sameValue(result, "");
log.length = 0;
array.push(1);
result = Array.prototype.join.call(proxy);
assert.compareArray(log, [ "get:length", "get:0" ]);
assert.sameValue(result, "1");
log.length = 0;
array.push(2);
result = Array.prototype.join.call(proxy);
assert.compareArray(log, [ "get:length", "get:0", "get:1" ]);
assert.sameValue(result, "1,2");

View File

@ -0,0 +1,13 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
assert.sameValue([17].lastIndexOf(17, -0), +0);

View File

@ -0,0 +1,74 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 600392;
var summary =
'Object.preventExtensions([]).length = 0 should do nothing, not throw';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function testEmpty()
{
var a = [];
assert.sameValue(a.length, 0);
assert.sameValue(Object.preventExtensions(a), a);
assert.sameValue(a.length, 0);
a.length = 0;
assert.sameValue(a.length, 0);
}
testEmpty();
function testEmptyStrict()
{
"use strict";
var a = [];
assert.sameValue(a.length, 0);
assert.sameValue(Object.preventExtensions(a), a);
assert.sameValue(a.length, 0);
a.length = 0;
assert.sameValue(a.length, 0);
}
testEmptyStrict();
function testNonEmpty()
{
var a = [1, 2, 3];
assert.sameValue(a.length, 3);
assert.sameValue(Object.preventExtensions(a), a);
assert.sameValue(a.length, 3);
a.length = 0;
assert.sameValue(a.length, 0);
}
testNonEmpty();
function testNonEmptyStrict()
{
"use strict";
var a = [1, 2, 3];
assert.sameValue(a.length, 3);
assert.sameValue(Object.preventExtensions(a), a);
assert.sameValue(a.length, 3);
a.length = 0;
assert.sameValue(a.length, 0);
}
testNonEmptyStrict();
/******************************************************************************/
print("All tests passed!");

View File

@ -0,0 +1,73 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 858381;
var summary = "No-op array length redefinition";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var arr;
// initializedLength == capacity == length
// 6 == 6 == 6
arr = Object.defineProperty([0, 1, 2, 3, 4, 5], "length", { writable: false });
Object.defineProperty(arr, "length", { value: 6 });
Object.defineProperty(arr, "length", { writable: false });
Object.defineProperty(arr, "length", { configurable: false });
Object.defineProperty(arr, "length", { writable: false, configurable: false });
Object.defineProperty(arr, "length", { writable: false, value: 6 });
Object.defineProperty(arr, "length", { configurable: false, value: 6 });
Object.defineProperty(arr, "length", { writable: false, configurable: false, value: 6 });
// initializedLength == capacity < length
// 6 == 6 < 8
arr = Object.defineProperty([0, 1, 2, 3, 4, 5], "length", { value: 8, writable: false });
Object.defineProperty(arr, "length", { value: 8 });
Object.defineProperty(arr, "length", { writable: false });
Object.defineProperty(arr, "length", { configurable: false });
Object.defineProperty(arr, "length", { writable: false, configurable: false });
Object.defineProperty(arr, "length", { writable: false, value: 8 });
Object.defineProperty(arr, "length", { configurable: false, value: 8 });
Object.defineProperty(arr, "length", { writable: false, configurable: false, value: 8 });
// initializedLength < capacity == length
// 7 < 8 == 8
arr = Object.defineProperty([0, 1, 2, 3, 4, 5, 6, /* hole */, ], "length",
{ value: 8, writable: false });
Object.defineProperty(arr, "length", { value: 8 });
Object.defineProperty(arr, "length", { writable: false });
Object.defineProperty(arr, "length", { configurable: false });
Object.defineProperty(arr, "length", { writable: false, configurable: false });
Object.defineProperty(arr, "length", { writable: false, value: 8 });
Object.defineProperty(arr, "length", { configurable: false, value: 8 });
Object.defineProperty(arr, "length", { writable: false, configurable: false, value: 8 });
// initializedLength < capacity < length
// 3 < 6 < 8
arr = Object.defineProperty([0, 1, 2], "length", { value: 8, writable: false });
Object.defineProperty(arr, "length", { value: 8 });
Object.defineProperty(arr, "length", { writable: false });
Object.defineProperty(arr, "length", { configurable: false });
Object.defineProperty(arr, "length", { writable: false, configurable: false });
Object.defineProperty(arr, "length", { writable: false, value: 8 });
Object.defineProperty(arr, "length", { configurable: false, value: 8 });
Object.defineProperty(arr, "length", { writable: false, configurable: false, value: 8 });
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,71 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 657298;
var summary = 'Various quirks of setting array length properties to objects';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function invokeConversionTwice1()
{
var count = 0;
[].length = { valueOf: function() { count++; return 1; } };
assert.sameValue(count, 2);
}
invokeConversionTwice1();
function invokeConversionTwice2()
{
var count = 0;
[].length = { toString: function() { count++; return 1; }, valueOf: null };
assert.sameValue(count, 2);
}
invokeConversionTwice2();
function dontOverwriteError1()
{
try
{
[].length = { valueOf: {}, toString: {} };
throw new Error("didn't throw a TypeError");
}
catch (e)
{
assert.sameValue(e instanceof TypeError, true,
"expected a TypeError running out of conversion options, got " + e);
}
}
dontOverwriteError1();
function dontOverwriteError2()
{
try
{
[].length = { valueOf: function() { throw "error"; } };
throw new Error("didn't throw a TypeError");
}
catch (e)
{
assert.sameValue(e, "error", "expected 'error' from failed conversion, got " + e);
}
}
dontOverwriteError2();
/******************************************************************************/
print("All tests passed!");

View File

@ -0,0 +1,113 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 858381;
var summary =
"Array length redefinition behavior with non-configurable elements";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function addDataProperty(obj, prop, value, enumerable, configurable, writable)
{
var desc =
{ enumerable: enumerable,
configurable: configurable,
writable: writable,
value: value };
Object.defineProperty(obj, prop, desc);
}
function nonstrict()
{
var arr = [0, , 2, , , 5];
addDataProperty(arr, 31415926, "foo", true, true, true);
addDataProperty(arr, 123456789, "bar", true, true, false);
addDataProperty(arr, 8675309, "qux", false, true, true);
addDataProperty(arr, 1735039, "eit", false, true, false);
addDataProperty(arr, 987654321, "fun", false, true, false);
// non-array indexes to spice things up
addDataProperty(arr, "foopy", "sdfsd", false, false, false);
addDataProperty(arr, 4294967296, "psych", true, false, false);
addDataProperty(arr, 4294967295, "psych", true, false, false);
addDataProperty(arr, 27182818, "eep", false, false, false);
// Truncate...but only as far as possible.
arr.length = 1;
assert.sameValue(arr.length, 27182819);
var props = Object.getOwnPropertyNames(arr).sort();
var expected =
["0", "2", "5", "1735039", "8675309", "27182818",
"foopy", "4294967296", "4294967295", "length"].sort();
assert.sameValue(props.length, expected.length);
for (var i = 0; i < props.length; i++)
assert.sameValue(props[i], expected[i], "unexpected property: " + props[i]);
}
nonstrict();
function strict()
{
"use strict";
var arr = [0, , 2, , , 5];
addDataProperty(arr, 31415926, "foo", true, true, true);
addDataProperty(arr, 123456789, "bar", true, true, false);
addDataProperty(arr, 8675309, "qux", false, true, true);
addDataProperty(arr, 1735039, "eit", false, true, false);
addDataProperty(arr, 987654321, "fun", false, true, false);
// non-array indexes to spice things up
addDataProperty(arr, "foopy", "sdfsd", false, false, false);
addDataProperty(arr, 4294967296, "psych", true, false, false);
addDataProperty(arr, 4294967295, "psych", true, false, false);
addDataProperty(arr, 27182818, "eep", false, false, false);
try
{
arr.length = 1;
throw new Error("didn't throw?!");
}
catch (e)
{
assert.sameValue(e instanceof TypeError, true,
"non-configurable property should trigger TypeError, got " + e);
}
assert.sameValue(arr.length, 27182819);
var props = Object.getOwnPropertyNames(arr).sort();
var expected =
["0", "2", "5", "1735039", "8675309", "27182818",
"foopy", "4294967296", "4294967295", "length"].sort();
assert.sameValue(props.length, expected.length);
for (var i = 0; i < props.length; i++)
assert.sameValue(props[i], expected[i], "unexpected property: " + props[i]);
}
strict();
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,51 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 858381;
var summary =
"Array length redefinition behavior with non-configurable elements";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var arr = [0, 1, 2];
Object.defineProperty(arr, 1, { configurable: false });
try
{
Object.defineProperty(arr, "length", { value: 0, writable: false });
}
catch (e)
{
assert.sameValue(e instanceof TypeError, true,
"must throw TypeError when array truncation would have to remove " +
"non-configurable elements");
}
assert.sameValue(arr.length, 2, "length is highest remaining index plus one");
var desc = Object.getOwnPropertyDescriptor(arr, "length");
assert.sameValue(desc !== undefined, true);
assert.sameValue(desc.value, 2);
assert.sameValue(desc.writable, false);
assert.sameValue(desc.enumerable, false);
assert.sameValue(desc.configurable, false);
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,104 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 858381;
var summary =
"Array length setting/truncating with non-dense, indexed elements";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function testTruncateDenseAndSparse()
{
var arr;
// initialized length 16, capacity same
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
// plus a sparse element
arr[987654321] = 987654321;
// lop off the sparse element and half the dense elements, shrink capacity
arr.length = 8;
assert.sameValue(987654321 in arr, false);
assert.sameValue(arr[987654321], undefined);
assert.sameValue(arr.length, 8);
}
testTruncateDenseAndSparse();
function testTruncateSparse()
{
// initialized length 8, capacity same
var arr = [0, 1, 2, 3, 4, 5, 6, 7];
// plus a sparse element
arr[987654321] = 987654321;
// lop off the sparse element, leave initialized length/capacity unchanged
arr.length = 8;
assert.sameValue(987654321 in arr, false);
assert.sameValue(arr[987654321], undefined);
assert.sameValue(arr.length, 8);
}
testTruncateSparse();
function testTruncateDenseAndSparseShrinkCapacity()
{
// initialized length 11, capacity...somewhat larger, likely 16
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// plus a sparse element
arr[987654321] = 987654321;
// lop off the sparse element, reduce initialized length, reduce capacity
arr.length = 8;
assert.sameValue(987654321 in arr, false);
assert.sameValue(arr[987654321], undefined);
assert.sameValue(arr.length, 8);
}
testTruncateDenseAndSparseShrinkCapacity();
function testTruncateSparseShrinkCapacity()
{
// initialized length 8, capacity same
var arr = [0, 1, 2, 3, 4, 5, 6, 7];
// capacity expands to accommodate, initialized length remains same (not equal
// to capacity or length)
arr[15] = 15;
// now no elements past initialized length
delete arr[15];
// ...except a sparse element
arr[987654321] = 987654321;
// trims sparse element, doesn't change initialized length, shrinks capacity
arr.length = 8;
assert.sameValue(987654321 in arr, false);
assert.sameValue(arr[987654321], undefined);
assert.sameValue(arr.length, 8);
}
testTruncateSparseShrinkCapacity();
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,37 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 858381;
var summary = 'Object.freeze([]).pop() must throw a TypeError';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
try
{
Object.freeze([]).pop();
throw new Error("didn't throw");
}
catch (e)
{
assert.sameValue(e instanceof TypeError, true,
"should have thrown TypeError, instead got: " + e);
}
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,67 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [compareArray.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Test that Array.prototype.pop doesn't call the [[HasProperty]] internal
// method of objects when retrieving the element at the last index.
var log = [];
var array = [];
var proxy = new Proxy(array, new Proxy({}, {
get(t, trap, r) {
return (t, pk, ...more) => {
log.push(`${trap}:${String(pk)}`);
return Reflect[trap](t, pk, ...more);
};
}
}));
var result;
result = Array.prototype.pop.call(proxy);
assert.compareArray(log, [
"get:length",
"set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
]);
assert.sameValue(result, undefined);
log.length = 0;
array.push(1);
result = Array.prototype.pop.call(proxy);
assert.compareArray(log, [
"get:length",
"get:0", "deleteProperty:0",
"set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
]);
assert.sameValue(result, 1);
log.length = 0;
array.push(2, 3);
result = Array.prototype.pop.call(proxy);
assert.compareArray(log, [
"get:length",
"get:1", "deleteProperty:1",
"set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
]);
assert.sameValue(result, 3);
log.length = 0;
array.push(4, 5);
result = Array.prototype.pop.call(proxy);
assert.compareArray(log, [
"get:length",
"get:2", "deleteProperty:2",
"set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
]);
assert.sameValue(result, 5);

View File

@ -0,0 +1,96 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 909602;
var summary =
"Array.prototype.pop shouldn't touch elements greater than length on " +
"non-arrays";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function doTest(obj, index)
{
// print("testing " + JSON.stringify(obj) + " with index " + index);
assert.sameValue(Array.prototype.pop.call(obj), undefined);
assert.sameValue(index in obj, true);
assert.sameValue(obj[index], 42);
}
// not-super-much-later element
// non-zero length
function testPop1()
{
var obj = { length: 2, 3: 42 };
doTest(obj, 3);
}
for (var i = 0; i < 50; i++)
testPop1();
// zero length
function testPop2()
{
var obj = { length: 0, 3: 42 };
doTest(obj, 3);
}
for (var i = 0; i < 50; i++)
testPop2();
// much-later (but dense) element
// non-zero length
function testPop3()
{
var obj = { length: 2, 55: 42 };
doTest(obj, 55);
}
for (var i = 0; i < 50; i++)
testPop3();
// zero length
function testPop4()
{
var obj = { length: 0, 55: 42 };
doTest(obj, 55);
}
for (var i = 0; i < 50; i++)
testPop4();
// much much much later (sparse) element
// non-zero length
function testPop5()
{
var obj = { length: 2, 65530: 42 };
doTest(obj, 65530);
}
for (var i = 0; i < 50; i++)
testPop5();
// zero length
function testPop6()
{
var obj = { length: 0, 65530: 42 };
doTest(obj, 65530);
}
for (var i = 0; i < 50; i++)
testPop6();
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,29 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 866580;
var summary = "Assertion redefining length property of a frozen array";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var arr = Object.freeze([]);
Object.defineProperty(arr, "length", {});
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,39 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 880591;
var summary =
"Assertion redefining length property of a frozen dictionary-mode array";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function convertToDictionaryMode(arr)
{
Object.defineProperty(arr, 0, { configurable: true });
Object.defineProperty(arr, 1, { configurable: true });
delete arr[0];
}
var arr = [];
convertToDictionaryMode(arr);
Object.freeze(arr);
Object.defineProperty(arr, "length", {});
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,48 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 866700;
var summary = "Assertion redefining non-writable length to a non-numeric value";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var count = 0;
var convertible =
{
valueOf: function()
{
count++;
return 0;
}
};
var arr = [];
Object.defineProperty(arr, "length", { value: 0, writable: false });
Object.defineProperty(arr, "length", { value: convertible });
assert.sameValue(count, 2);
Object.defineProperty(arr, "length", { value: convertible });
assert.sameValue(count, 4);
assert.sameValue(arr.length, 0);
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,61 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 866700;
var summary = "Assertion redefining non-writable length to a non-numeric value";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var count = 0;
var convertible =
{
valueOf: function()
{
count++;
if (count > 2)
return 0;
throw new SyntaxError("fnord");
}
};
var arr = [];
Object.defineProperty(arr, "length", { value: 0, writable: false });
try
{
Object.defineProperty(arr, "length",
{
value: convertible,
writable: true,
configurable: true,
enumerable: true
});
throw new Error("didn't throw");
}
catch (e)
{
assert.sameValue(e instanceof SyntaxError, true, "expected SyntaxError, got " + e);
}
assert.sameValue(count, 1);
assert.sameValue(arr.length, 0);
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,35 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 866700;
var summary = "Assertion redefining non-writable length to a non-numeric value";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var arr = [];
Object.defineProperty(arr, "length", { value: 0, writable: false });
// Per Array's magical behavior, the value in the descriptor gets canonicalized
// *before* SameValue comparisons occur, so this shouldn't throw.
Object.defineProperty(arr, "length", { value: '' });
assert.sameValue(arr.length, 0);
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,70 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 386030;
var summary = 'Array.reduce should ignore holes';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
printBugNumber(BUGNUMBER);
printStatus (summary);
function add(a, b) { return a + b; }
function testreduce(v) { return v == 3 ? "PASS" : "FAIL"; }
expect = 'PASS';
try {
a = new Array(2);
a[1] = 3;
actual = testreduce(a.reduce(add));
} catch (e) {
actual = "FAIL, reduce";
}
assert.sameValue(expect, actual, summary + ': 1');
try {
a = new Array(2);
a[0] = 3;
actual = testreduce(a.reduceRight(add));
} catch (e) {
actual = "FAIL, reduceRight";
}
assert.sameValue(expect, actual, summary + ': 2');
try {
a = new Array(2);
a.reduce(add);
actual = "FAIL, empty reduce";
} catch (e) {
actual = "PASS";
}
assert.sameValue(expect, actual, summary + ': 3');
try {
a = new Array(2);
print(a.reduceRight(add));
actual = "FAIL, empty reduceRight";
} catch (e) {
actual = "PASS";
}
assert.sameValue(expect, actual, summary + ': 4');
}

View File

@ -0,0 +1,33 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 424954;
var summary = 'Do not crash with [].concat(null)';
var actual = 'No Crash';
var expect = 'No Crash';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
printBugNumber(BUGNUMBER);
printStatus (summary);
[].concat(null);
assert.sameValue(expect, actual, summary);
}

View File

@ -0,0 +1,26 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 566651;
var summary = 'setting array.length to null should not throw an uncatchable exception';
var actual = 0;
var expect = 0;
printBugNumber(BUGNUMBER);
printStatus (summary);
var a = [];
a.length = null;
assert.sameValue(expect, actual, summary);

View File

@ -0,0 +1,17 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var b = Object.create(Array.prototype);
b.length = 12;
assert.sameValue(b.length, 12);

View File

@ -0,0 +1,18 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
function test() {
delete arguments[1];
return Array.prototype.join.call(arguments);
}
assert.sameValue(test(1,2,3), "1,,3");
Object.prototype[1] = "ponies!!!1";
assert.sameValue(test(1,2,3), "1,ponies!!!1,3");

View File

@ -0,0 +1,93 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 858677;
var summary =
"[].reverse should swap elements low to high using accesses to low " +
"elements, then accesses to high elements";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var observed = [];
// (0, 7) hits the lowerExists/upperExists case.
// (1, 6) hits the !lowerExists/upperExists case.
// (2, 5) hits the lowerExists/!upperExists case.
// (3, 4) hits the !lowerExists/!upperExists case.
//
// It'd be a good idea to have a second version of this test at some point
// where the "array" being reversed is a proxy, to detect proper ordering of
// getproperty, hasproperty, setproperty into a hole, and deleteproperty from a
// non-configurable element. But at present our Array.prototype.reverse
// implementation probably doesn't conform fully to all this (because our
// internal MOP is still slightly off), so punt for now.
var props =
{
0: {
configurable: true,
get: function() { observed.push("index 0 get"); return "index 0 get"; },
set: function(v) { observed.push("index 0 set: " + v); }
},
/* 1: hole */
2: {
configurable: true,
get: function() { observed.push("index 2 get"); return "index 2 get"; },
set: function(v) { observed.push("index 2 set: " + v); }
},
/* 3: hole */
/* 4: hole */
/* 5: hole */
6: {
configurable: true,
get: function() { observed.push("index 6 get"); return "index 6 get"; },
set: function(v) { observed.push("index 6 set: " + v); }
},
7: {
configurable: true,
get: function() { observed.push("index 7 get"); return "index 7 get"; },
set: function(v) { observed.push("index 7 set: " + v); }
},
};
var arr = Object.defineProperties(new Array(8), props);
arr.reverse();
var expectedObserved =
["index 0 get", "index 7 get", "index 0 set: index 7 get", "index 7 set: index 0 get",
"index 6 get",
"index 2 get"
/* nothing for 3/4 */];
print(observed);
// Do this before the assertions below futz even more with |observed|.
assert.sameValue(observed.length, expectedObserved.length);
for (var i = 0; i < expectedObserved.length; i++)
assert.sameValue(observed[i], expectedObserved[i]);
assert.sameValue(arr[0], "index 0 get"); // no deletion, setting doesn't overwrite
assert.sameValue(arr[1], "index 6 get"); // copies result of getter
assert.sameValue(2 in arr, false); // deleted
assert.sameValue(3 in arr, false); // never there
assert.sameValue(4 in arr, false); // never there
assert.sameValue(arr[5], "index 2 get"); // copies result of getter
assert.sameValue(6 in arr, false); // deleted
assert.sameValue(arr[7], "index 7 get"); // no deletion, setter doesn't overwrite
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,69 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
function ensureSetterCalledOnce(fn, value, index) {
var setterCalled = false;
Object.defineProperty(Array.prototype, index, {
configurable: true,
set: function(v) {
assert.sameValue(setterCalled, false);
setterCalled = true;
assert.sameValue(v, value);
}
});
assert.sameValue(setterCalled, false);
fn();
assert.sameValue(setterCalled, true);
delete Array.prototype[index];
}
ensureSetterCalledOnce(function() {
[].push("push");
}, "push", 0);
ensureSetterCalledOnce(function() {
[/* hole */, "reverse"].reverse();
}, "reverse", 0);
ensureSetterCalledOnce(function() {
["reverse", /* hole */,].reverse();
}, "reverse", 1);
ensureSetterCalledOnce(function() {
[/* hole */, "shift"].shift();
}, "shift", 0);
ensureSetterCalledOnce(function() {
[/* hole */, "sort"].sort();
}, "sort", 0);
ensureSetterCalledOnce(function() {
[/* hole */, undefined].sort();
}, undefined, 0);
ensureSetterCalledOnce(function() {
[].splice(0, 0, "splice");
}, "splice", 0);
ensureSetterCalledOnce(function() {
[/* hole */, "splice"].splice(0, 1);
}, "splice", 0);
ensureSetterCalledOnce(function(v) {
["splice", /* hole */,].splice(0, 0, "item");
}, "splice", 1);
ensureSetterCalledOnce(function() {
[].unshift("unshift");
}, "unshift", 0);

View File

@ -0,0 +1,73 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [compareArray.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Test that Array.prototype.shift doesn't call the [[HasProperty]] internal
// method of objects when retrieving the element at index 0.
var log = [];
var array = [];
var proxy = new Proxy(array, new Proxy({}, {
get(t, trap, r) {
return (t, pk, ...more) => {
log.push(`${trap}:${String(pk)}`);
return Reflect[trap](t, pk, ...more);
};
}
}));
var result;
result = Array.prototype.shift.call(proxy);
assert.compareArray(log, [
"get:length",
"set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
]);
assert.sameValue(result, undefined);
log.length = 0;
array.push(1);
result = Array.prototype.shift.call(proxy);
assert.compareArray(log, [
"get:length",
"get:0",
"deleteProperty:0",
"set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
]);
assert.sameValue(result, 1);
log.length = 0;
array.push(2, 3);
result = Array.prototype.shift.call(proxy);
assert.compareArray(log, [
"get:length",
"get:0",
"has:1", "get:1", "set:0", "getOwnPropertyDescriptor:0", "defineProperty:0",
"deleteProperty:1",
"set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
]);
assert.sameValue(result, 2);
log.length = 0;
array.push(4, 5);
result = Array.prototype.shift.call(proxy);
assert.compareArray(log, [
"get:length",
"get:0",
"has:1", "get:1", "set:0", "getOwnPropertyDescriptor:0", "defineProperty:0",
"has:2", "get:2", "set:1", "getOwnPropertyDescriptor:1", "defineProperty:1",
"deleteProperty:2",
"set:length", "getOwnPropertyDescriptor:length", "defineProperty:length"
]);
assert.sameValue(result, 3);

View File

@ -0,0 +1,22 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var BUGNUMBER = 1247701;
var summary = 'Array.prototype.shift on a dense array with holes should update for-in enumeration properties.';
print(BUGNUMBER + ": " + summary);
var x = ["a", , "b", , "c", "d" , "e", "f", "g"];
for (var p in x) {
assert.sameValue(p in x, true);
x.shift();
}

View File

@ -0,0 +1,28 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 604971;
var summary = 'array.sort compare-function gets incorrect this';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
[1, 2, 3].sort(function() { "use strict"; assert.sameValue(this, undefined); });
/******************************************************************************/
print("All tests passed!");

View File

@ -0,0 +1,37 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 664528;
var summary =
"Sorting an array containing only holes and |undefined| should move all " +
"|undefined| to the start of the array";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var a = [, , , undefined];
a.sort();
assert.sameValue(a.hasOwnProperty(0), true);
assert.sameValue(a[0], undefined);
assert.sameValue(a.hasOwnProperty(1), false);
assert.sameValue(a.hasOwnProperty(2), false);
assert.sameValue(a.hasOwnProperty(3), false);
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,46 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [compareArray.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Calls Array.prototype.sort and tests that properties are deleted in the same order in the
// native and the self-hosted implementation.
function createProxy() {
var deleted = [];
var proxy = new Proxy([, , 0], {
deleteProperty(t, pk){
deleted.push(pk);
return delete t[pk];
}
});
return {proxy, deleted};
}
function compareFn(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
}
// Sort an array without a comparator function. This calls the native sort implementation.
var {proxy, deleted} = createProxy();
assert.compareArray(deleted, []);
proxy.sort()
assert.compareArray(deleted, ["1", "2"]);
// Now sort an array with a comparator function. This calls the self-hosted sort implementation.
var {proxy, deleted} = createProxy();
assert.compareArray(deleted, []);
proxy.sort(compareFn);
assert.compareArray(deleted, ["1", "2"]);

View File

@ -0,0 +1,31 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Array.prototype.sort throws if the comparator is neither undefined nor
// a callable object.
// Use a zero length array, so we can provide any kind of callable object
// without worrying that the function is actually a valid comparator function.
const array = new Array(0);
// Throws if the comparator is neither undefined nor callable.
for (let invalidComparator of [null, 0, true, Symbol(), {}, []]) {
assertThrowsInstanceOf(() => array.sort(invalidComparator), TypeError);
}
// Doesn't throw if the comparator is undefined or a callable object.
for (let validComparator of [undefined, () => {}, Math.max, class {}, new Proxy(function(){}, {})]) {
array.sort(validComparator);
}
// Also doesn't throw if no comparator was provided at all.
array.sort();

View File

@ -0,0 +1,42 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
function sortTypedArray(comparator) {
// Create a typed array with three elements, but also add an own "length"
// property with the value `2` to restrict the range of elements which
// will be sorted by Array.prototype.sort().
var ta = new Int8Array([3, 2, 1]);
Object.defineProperty(ta, "length", {value: 2});
// Sort with Array.prototype.sort(), not %TypedArray%.prototype.sort()!
Array.prototype.sort.call(ta, comparator);
return ta;
}
// Comparators using the form |return a - b| are special-cased in
// Array.prototype.sort().
function optimizedComparator(a, b) {
return a - b;
}
// This comparator doesn't compile to the byte code sequence which gets
// special-cased in Array.prototype.sort().
function nonOptimizedComparator(a, b) {
var d = a - b;
return d;
}
// Both comparators should produce the same result.
assert.sameValue(sortTypedArray(optimizedComparator).toString(), "2,3,1");
assert.sameValue(sortTypedArray(nonOptimizedComparator).toString(), "2,3,1");

View File

@ -0,0 +1,74 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// We should preserve holes when sorting sparce arrays.
// See bug: 1246860
function denseCount(arr) {
var c = 0;
for (var i = 0; i < arr.length; i++)
if (i in arr)
c++;
return c;
}
let a = [,,,,,,,,,,,,,,,,,,,,{size: 1},{size: 2}];
let b = [,,,,,,,,,,,,,,,,,,,,{size: 1},{size: 2}].sort();
let c = [,,,,,,,,,,,,,,,,,,,,{size: 1},{size: 2}].sort((a, b) => {+a.size - +b.size});
assert.sameValue(a.length, 22);
assert.sameValue(denseCount(a), 2);
assert.sameValue(a.length, b.length);
assert.sameValue(b.length, c.length);
assert.sameValue(denseCount(a), denseCount(b));
assert.sameValue(denseCount(b), denseCount(c));
let superSparce = new Array(5000);
superSparce[0] = 99;
superSparce[4000] = 0;
superSparce[4999] = -1;
assert.sameValue(superSparce.length, 5000);
assert.sameValue(denseCount(superSparce), 3);
superSparce.sort((a, b) => 1*a-b);
assert.sameValue(superSparce.length, 5000);
assert.sameValue(denseCount(superSparce), 3);
assert.sameValue(superSparce[0], -1);
assert.sameValue(superSparce[1], 0);
assert.sameValue(superSparce[2], 99);
let allHoles = new Array(2600);
assert.sameValue(allHoles.length, 2600);
assert.sameValue(denseCount(allHoles), 0);
allHoles.sort((a, b) => 1*a-b);
assert.sameValue(allHoles.length, 2600);
assert.sameValue(denseCount(allHoles), 0);
let oneHole = new Array(2600);
oneHole[1399] = {size: 27};
assert.sameValue(oneHole.length, 2600);
assert.sameValue(denseCount(oneHole), 1);
oneHole.sort((a, b) => {+a.size - +b.size});
assert.deepEqual(oneHole[0], {size: 27});
assert.sameValue(oneHole.length, 2600);
assert.sameValue(denseCount(oneHole), 1);
// Sealed objects should be sortable, including those with holes (so long
// as the holes appear at the end, so that they don't need to be moved).
assert.deepEqual(Object.seal([0, 99, -1]).sort((x, y) => 1 * x - y),
Object.seal([-1, 0, 99]));
assert.deepEqual(Object.seal([1, 5, 4, , ,]).sort((x, y) => 1 * x - y),
Object.seal([1, 4, 5, , ,]));

View File

@ -0,0 +1,25 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [compareArray.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var array = ["not-a-number", "also-not-a-number"];
var copy = [...array];
// The sort comparator must be exactly equal to the bytecode pattern:
//
// JSOp::GetArg 0/1
// JSOp::GetArg 1/0
// JSOp::Sub
// JSOp::Return
array.sort(function(a, b) { return a - b; });
assert.compareArray(array, copy);

View File

@ -0,0 +1,48 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Ensure, via proxy, that only get, set, delete, has, and getOwnPropertyDescriptor
// are touched during sorting.
const handler = {
set: function(target, prop, value) {
target[prop] = value;
return value;
},
getPrototypeOf: () => { throw "You shouldn't touch getPrototypeOf!" },
setPrototypeOf: () => { throw "You shouldn't touch setPrototypeOf!" },
isExtensible: () => { throw "You shouldn't touch isExtensible!" },
preventExtensions: () => { throw "You shouldn't touch preventExtensions!" },
defineProperty: () => { throw "You shouldn't touch defineProperty!" },
ownKeys: () => { throw "You shouldn't touch ownKeys!" },
apply: () => { throw "You shouldn't touch apply!" },
construct: () => { throw "You shouldn't touch construct!" },
}
function testArray(arr) {
let proxy = new Proxy(arr, handler)
// The supplied comparators trigger a JavaScript implemented sort.
proxy.sort((x, y) => 1 * x - y);
arr.sort((x, y) => 1 * x - y);
for (let i in arr)
assert.sameValue(arr[i], proxy[i]);
}
testArray([-1]);
testArray([5, -1, 2, 99]);
testArray([5, -1, , , , 2, 99]);
testArray([]);

View File

@ -0,0 +1,42 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Sort every possible permutation of some arrays.
function sortAllPermutations(data, comparefn) {
for (let permutation of Permutations(Array.from(data))) {
let sorted = (Array.from(permutation)).sort(comparefn);
for (let i in sorted) {
assert.sameValue(sorted[i], data[i],
[`[${permutation}].sort(${comparefn})`,
`returned ${sorted}, expected ${data}`].join(' '));
}
}
}
let lex = [2112, "bob", "is", "my", "name"];
let nans = [1/undefined, NaN, Number.NaN]
let num1 = [-11, 0, 0, 100, 101];
let num2 = [-11, 100, 201234.23, undefined, undefined];
sortAllPermutations(lex);
sortAllPermutations(nans);
sortAllPermutations(nans, (x, y) => x - y);
// Multiplication kills comparator optimization.
sortAllPermutations(nans, (x, y) => (1*x - 1*y));
sortAllPermutations(num1, (x, y) => x - y);
sortAllPermutations(num1, (x, y) => (1*x - 1*y));
sortAllPermutations(num2, (x, y) => x - y);
sortAllPermutations(num2, (x, y) => (1*x - 1*y));

View File

@ -0,0 +1,191 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
var BUGNUMBER = 1165052;
var summary = 'Use ArraySpeciesCreate in Array.prototype.{concat,filter,map,slice,splice}.';
print(BUGNUMBER + ": " + summary);
function test(funcName, args, expectedLength, expectedLogs) {
// modified @@species
function FakeArray(n) {
this.length = n;
}
var a = [1, 2, 3, 4, 5];
a.constructor = {
[Symbol.species]: FakeArray
};
var b = a[funcName](...args);
assert.sameValue(b.constructor, FakeArray);
function FakeArrayWithSpecies(n) {
this.length = n;
}
FakeArrayWithSpecies[Symbol.species] = FakeArrayWithSpecies;
a = [1, 2, 3, 4, 5];
a.constructor = FakeArrayWithSpecies;
b = a[funcName](...args);
assert.sameValue(b.constructor, FakeArrayWithSpecies);
function FakeArrayWithHook(n) {
return new Proxy(new FakeArray(n), {
set(that, name, value) {
logs += "set:" + name + ":" + value + ",";
return true;
},
defineProperty(that, name, desc) {
logs += "define:" + name + ":" + desc.value + ":" + desc.configurable + ":" + desc.enumerable + ":" + desc.writable + ",";
return true;
}
});
}
var logs = "";
var ctorProxy = new Proxy({}, {
get(that, name) {
logs += "c-get:" + name.toString() + ",";
if (name == Symbol.species)
return FakeArrayWithHook;
return undefined;
}
});
a = new Proxy([1, 2, 3, 4, 5], {
get(that, name) {
logs += "get:" + name.toString() + ",";
if (name == "constructor")
return ctorProxy;
return that[name];
}
});
b = a[funcName](...args);
assert.sameValue(b.constructor, FakeArray);
assert.sameValue(Object.keys(b).sort().join(","), "length");
assert.sameValue(b.length, expectedLength);
assert.sameValue(logs, expectedLogs);
// no @@species
a = [1, 2, 3, 4, 5];
a.constructor = FakeArray;
b = a[funcName](...args);
assert.sameValue(b.constructor, Array);
a = [1, 2, 3, 4, 5];
a.constructor = {
[Symbol.species]: undefined
};
b = a[funcName](...args);
assert.sameValue(b.constructor, Array);
a = [1, 2, 3, 4, 5];
a.constructor = {
[Symbol.species]: null
};
b = a[funcName](...args);
assert.sameValue(b.constructor, Array);
// invalid @@species
for (var species of [0, 1.1, true, false, "a", /a/, Symbol.iterator, [], {}]) {
a = [1, 2, 3, 4, 5];
a.constructor = {
[Symbol.species]: species
};
assertThrowsInstanceOf(() => a[funcName](...args), TypeError);
}
// undefined constructor
a = [1, 2, 3, 4, 5];
a.constructor = undefined;
b = a[funcName](...args);
assert.sameValue(b.constructor, Array);
// invalid constructor
for (var ctor of [null, 0, 1.1, true, false, "a", Symbol.iterator]) {
a = [1, 2, 3, 4, 5];
a.constructor = ctor;
assertThrowsInstanceOf(() => a[funcName](...args), TypeError);
}
// not an array
a = new Proxy({
0: 1, 1: 2, 2: 3, 3: 4, 4: 5,
length: 5,
[funcName]: Array.prototype[funcName]
}, {
get(that, name) {
assert.sameValue(name !== "constructor", true);
return that[name];
}
});
b = a[funcName](...args);
assert.sameValue(b.constructor, Array);
// @@species from different global
var g = createNewGlobal();
g.eval("function FakeArray(n) { this.length = n; }");
a = [1, 2, 3, 4, 5];
a.constructor = {
[Symbol.species]: g.FakeArray
};
b = a[funcName](...args);
assert.sameValue(b.constructor, g.FakeArray);
a = [1, 2, 3, 4, 5];
a.constructor = {
[Symbol.species]: g.Array
};
b = a[funcName](...args);
assert.sameValue(b.constructor, g.Array);
// constructor from different global
g.eval("function FakeArrayWithSpecies(n) { this.length = n; }");
g.eval("FakeArrayWithSpecies[Symbol.species] = FakeArrayWithSpecies;");
a = [1, 2, 3, 4, 5];
a.constructor = g.FakeArrayWithSpecies;
b = a[funcName](...args);
assert.sameValue(b.constructor, g.FakeArrayWithSpecies);
g.eval("var a = [1, 2, 3, 4, 5];");
b = Array.prototype[funcName].apply(g.a, args);
assert.sameValue(b.constructor, Array);
// running in different global
b = g.a[funcName](...args);
assert.sameValue(b.constructor, g.Array);
// subclasses
// not-modified @@species
eval(`
class ${funcName}Class extends Array {
}
a = new ${funcName}Class(1, 2, 3, 4, 5);
b = a[funcName](...args);
assert.sameValue(b.constructor, ${funcName}Class);
`);
// modified @@species
eval(`
class ${funcName}Class2 extends Array {
static get [Symbol.species]() {
return Date;
}
}
a = new ${funcName}Class2(1, 2, 3, 4, 5);
b = a[funcName](...args);
assert.sameValue(b.constructor, Date);
`);
}
test("concat", [], 0, "get:concat,get:constructor,c-get:Symbol(Symbol.species),get:Symbol(Symbol.isConcatSpreadable),get:length,get:0,define:0:1:true:true:true,get:1,define:1:2:true:true:true,get:2,define:2:3:true:true:true,get:3,define:3:4:true:true:true,get:4,define:4:5:true:true:true,set:length:5,");
test("filter", [x => x % 2], 0, "get:filter,get:length,get:constructor,c-get:Symbol(Symbol.species),get:0,define:0:1:true:true:true,get:1,get:2,define:1:3:true:true:true,get:3,get:4,define:2:5:true:true:true,");
test("map", [x => x * 2], 5, "get:map,get:length,get:constructor,c-get:Symbol(Symbol.species),get:0,define:0:2:true:true:true,get:1,define:1:4:true:true:true,get:2,define:2:6:true:true:true,get:3,define:3:8:true:true:true,get:4,define:4:10:true:true:true,");
test("slice", [], 5, "get:slice,get:length,get:constructor,c-get:Symbol(Symbol.species),get:0,define:0:1:true:true:true,get:1,define:1:2:true:true:true,get:2,define:2:3:true:true:true,get:3,define:3:4:true:true:true,get:4,define:4:5:true:true:true,set:length:5,");
test("splice", [0, 5], 5, "get:splice,get:length,get:constructor,c-get:Symbol(Symbol.species),get:0,define:0:1:true:true:true,get:1,define:1:2:true:true:true,get:2,define:2:3:true:true:true,get:3,define:3:4:true:true:true,get:4,define:4:5:true:true:true,set:length:5,");

View File

@ -0,0 +1,51 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 668024;
var summary =
'Array.prototype.splice should define, not set, the elements of the array ' +
'it returns';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
Object.defineProperty(Object.prototype, 2,
{
set: function(v)
{
throw new Error("setter on Object.prototype called!");
},
get: function() { return "fnord"; },
enumerable: false,
configurable: true
});
var arr = [0, 1, 2, 3, 4, 5];
var removed = arr.splice(0, 6);
assert.sameValue(arr.length, 0);
assert.sameValue(removed.length, 6);
assert.sameValue(removed[0], 0);
assert.sameValue(removed[1], 1);
assert.sameValue(removed[2], 2);
assert.sameValue(removed[3], 3);
assert.sameValue(removed[4], 4);
assert.sameValue(removed[5], 5);
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,57 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [compareArray.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
// Case 1: splice() removes an element from the array.
{
let array = [];
array.push(0, 1, 2);
array.constructor = {
[Symbol.species]: function(n) {
// Increase the initialized length of the array.
array.push(3, 4, 5);
// Make the length property non-writable.
Object.defineProperty(array, "length", {writable: false});
return new Array(n);
}
}
assertThrowsInstanceOf(() => Array.prototype.splice.call(array, 0, 1), TypeError);
assert.sameValue(array.length, 6);
assert.compareArray(array, [1, 2, /* hole */, 3, 4, 5]);
}
// Case 2: splice() adds an element to the array.
{
let array = [];
array.push(0, 1, 2);
array.constructor = {
[Symbol.species]: function(n) {
// Increase the initialized length of the array.
array.push(3, 4, 5);
// Make the length property non-writable.
Object.defineProperty(array, "length", {writable: false});
return new Array(n);
}
}
assertThrowsInstanceOf(() => Array.prototype.splice.call(array, 0, 0, 123), TypeError);
assert.sameValue(array.length, 6);
assert.compareArray(array, [123, 0, 1, 2, 4, 5]);
}

View File

@ -0,0 +1,66 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 668024;
var summary =
'Array.prototype.splice, when it deletes elements, should make sure any ' +
'deleted but not visited elements are suppressed from subsequent enumeration';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var arr = [0, 1, 2, 3, 4, 5, , 7];
var seen = [];
var sawOneBeforeThree = true;
for (var p in arr)
{
if (p === "1")
{
// The order of enumeration of properties is unspecified, so technically,
// it would be kosher to enumerate "1" last, say, such that all properties
// in the array actually were enumerated, including an index which splice
// would delete. Don't flag that case as a failure. (SpiderMonkey doesn't
// do this, and neither do any of the other browser engines, but it is
// permissible behavior.)
if (seen.indexOf("3") >= 0)
{
sawOneBeforeThree = false;
break;
}
arr.splice(2, 3);
}
seen.push(p);
}
if (sawOneBeforeThree)
{
// ES5 12.6.4 states:
//
// If a property that has not yet been visited during enumeration is
// deleted, then it will not be visited.
//
// So if we haven't seen "3" by the time we see "1", the splice call above
// will delete "3", and therefore we must not see it.
assert.sameValue(seen.indexOf("3"), -1);
}
/******************************************************************************/
print("Tests complete");

View File

@ -0,0 +1,49 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
const max = Number.MAX_SAFE_INTEGER;
assert.sameValue(Array.prototype.indexOf.call({length: Infinity, [max - 1]: 'test'}, 'test', max - 3), max - 1);
assert.sameValue(Array.prototype.lastIndexOf.call({length: Infinity, [max - 2]: 'test', [max - 1]: 'test2'}, 'test'), max - 2);
// ToLength doesn't truncate Infinity to zero, so the callback should be invoked
assertThrowsValue(() => Array.prototype.every.call({length: Infinity, [0]: undefined}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.some.call({length: Infinity, [0]: undefined}, () => { throw "invoked" }), "invoked");
// Timeout before calling our callback
// assertThrowsValue(() => Array.prototype.sort.call({length: Infinity}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.forEach.call({length: Infinity, [0]: undefined}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.filter.call({length: Infinity, [0]: undefined}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.reduce.call({length: Infinity, [0]: undefined, [1]: undefined}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.reduceRight.call({length: Infinity, [max - 1]: undefined, [max - 2]: undefined}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.find.call({length: Infinity}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.findIndex.call({length: Infinity}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.fill.call({length: Infinity, set "0"(v) { throw "invoked"; }}, () => { throw "invoked" }), "invoked");
assertThrowsValue(() => Array.prototype.copyWithin.call({length: Infinity, get [max - 2]() { throw "invoked"; }}, max - 2, max - 2), "invoked");
assert.sameValue(Array.prototype.includes.call({length: Infinity, [max - 1]: "test"}, "test", max - 3), true);
// Invoking the Array constructor with MAX_SAFE_INTEGER will throw, 0 won't
assertThrowsInstanceOf(() => Array.from({length: Infinity}), RangeError);
// Make sure ArraySpeciesCreate is called with ToLength applied to the length property
var proxy = new Proxy([], {
get(target, property) {
if (property === "length")
return Infinity;
assert.sameValue(property, "constructor");
function fakeConstructor(length) { assert.sameValue(length, max); throw "invoked"; };
fakeConstructor[Symbol.species] = fakeConstructor;
return fakeConstructor;
}
})
assertThrowsValue(() => Array.prototype.map.call(proxy, () => { }), "invoked");

View File

@ -0,0 +1,40 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 562446;
var summary = 'ES5: Array.prototype.toLocaleString';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var o;
o = { length: 2, 0: 7, 1: { toLocaleString: function() { return "baz" } } };
assert.sameValue(Array.prototype.toLocaleString.call(o), "7,baz");
o = {};
assert.sameValue(Array.prototype.toLocaleString.call(o), "");
var log = '';
arr = {length: {valueOf: function () { log += "L"; return 2; }},
0: "x", 1: "z"};
assert.sameValue(Array.prototype.toLocaleString.call(arr), "x,z");
assert.sameValue(log, "L");
/******************************************************************************/
print("All tests passed!");

View File

@ -0,0 +1,35 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
if (typeof Intl !== "object") {
const localeSep = [,,].toLocaleString();
const obj = {
toLocaleString() {
assert.sameValue(arguments.length, 0);
return "pass";
}
};
// Ensure no arguments are passed to the array elements.
// - Single element case.
assert.sameValue([obj].toLocaleString(), "pass");
// - More than one element.
assert.sameValue([obj, obj].toLocaleString(), "pass" + localeSep + "pass");
// Ensure no arguments are passed to the array elements even if supplied.
const locales = {}, options = {};
// - Single element case.
assert.sameValue([obj].toLocaleString(locales, options), "pass");
// - More than one element.
assert.sameValue([obj, obj].toLocaleString(locales, options), "pass" + localeSep + "pass");
}

View File

@ -0,0 +1,23 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
flags:
- onlyStrict
includes: [sm/non262-shell.js, sm/non262.js]
description: |
pending
esid: pending
---*/
"use strict";
Object.defineProperty(String.prototype, "toLocaleString", {
get() {
assert.sameValue(typeof this, "string");
return function() { return typeof this; };
}
})
assert.sameValue(["test"].toLocaleString(), "string");

View File

@ -0,0 +1,135 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
const startIndices = [
-10, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 10,
];
const deleteCounts = [
0, 1, 2, 3, 4, 5, 10,
];
const insertCounts = [
0, 1, 2, 3, 4, 5, 10,
];
const itemsList = insertCounts.map(count => {
return new Array(count).fill(0);
});
const arrays = [
// Dense no holes.
[],
[1],
[1,2],
[1,2,3],
[1,2,3,4],
[1,2,3,4,5,6,7,8],
// Dense trailing holes.
[,],
[1,,],
[1,2,,],
[1,2,3,,],
[1,2,3,4,,],
[1,2,3,4,5,6,7,8,,],
// Dense leading holes.
[,],
[,1],
[,1,2],
[,1,2,3],
[,1,2,3,4],
[,1,2,3,4,5,6,7,8],
// Dense with holes.
[1,,3],
[1,2,,4],
[1,,3,,5,6,,8],
];
const objects = arrays.map(array => {
let obj = {
length: array.length,
};
for (let i = 0; i < array.length; ++i) {
if (i in array) {
obj[i] = array[i];
}
}
return obj;
});
const objectsWithLargerDenseInitializedLength = arrays.map(array => {
let obj = {
length: array.length,
};
for (let i = 0; i < array.length; ++i) {
if (i in array) {
obj[i] = array[i];
}
}
// Add some extra dense elements after |length|.
for (let i = 0; i < 5; ++i) {
obj[array.length + i] = "extra";
}
return obj;
});
const thisValues = [
...arrays,
...objects,
...objectsWithLargerDenseInitializedLength,
];
for (let thisValue of thisValues) {
for (let startIndex of startIndices) {
for (let deleteCount of deleteCounts) {
for (let items of itemsList) {
let res = Array.prototype.toSpliced.call(thisValue, startIndex, deleteCount, ...items);
// Array.prototype.toSpliced(), steps 3-6.
let actualStart;
if (startIndex < 0) {
actualStart = Math.max(thisValue.length + startIndex, 0);
} else {
actualStart = Math.min(startIndex, thisValue.length);
}
// Array.prototype.toSpliced(), step 10.
let actualDeleteCount = Math.min(Math.max(0, deleteCount), thisValue.length - actualStart);
let newLength = thisValue.length + items.length - actualDeleteCount;
assert.sameValue(res.length, newLength);
for (let i = 0; i < actualStart; ++i) {
assert.sameValue(Object.hasOwn(res, i), true);
assert.sameValue(res[i], thisValue[i]);
}
for (let i = 0; i < items.length; ++i) {
assert.sameValue(Object.hasOwn(res, actualStart + i), true);
assert.sameValue(res[actualStart + i], items[i]);
}
for (let i = 0; i < newLength - actualStart - items.length; ++i) {
assert.sameValue(Object.hasOwn(res, actualStart + items.length + i), true);
assert.sameValue(res[actualStart + items.length + i],
thisValue[actualStart + actualDeleteCount + i]);
}
}
}
}
}

View File

@ -0,0 +1,35 @@
// Copyright (C) 2024 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
includes: [deepEqual.js, sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
Object.defineProperty(Array.prototype, 0, {
set() {
throw "bad 0";
},
});
Object.defineProperty(Array.prototype, 1, {
set() {
throw "bad 1";
},
});
assert.deepEqual([].toSpliced(0, 0, 1), [1]);
assert.deepEqual([0].toSpliced(0, 0, 0), [0, 0]);
assert.deepEqual([0].toSpliced(0, 0, 1), [1, 0]);
assert.deepEqual([0].toSpliced(0, 1, 0), [0]);
assert.deepEqual([0].toSpliced(0, 1, 1), [1]);
assert.deepEqual([0].toSpliced(1, 0, 0), [0, 0]);
assert.deepEqual([0].toSpliced(1, 0, 1), [0, 1]);
assert.deepEqual([0].toSpliced(1, 1, 0), [0, 0]);
assert.deepEqual([0].toSpliced(1, 1, 1), [0, 1]);

View File

@ -0,0 +1,55 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
/*---
includes: [sm/non262-shell.js, sm/non262.js]
flags:
- noStrict
description: |
pending
esid: pending
---*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 562446;
var summary = 'ES5: Array.prototype.toString';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var o;
o = { join: function() { assert.sameValue(arguments.length, 0); return "ohai"; } };
assert.sameValue(Array.prototype.toString.call(o), "ohai");
o = {};
assert.sameValue(Array.prototype.toString.call(o), "[object Object]");
Array.prototype.join = function() { return "kthxbai"; };
assert.sameValue(Array.prototype.toString.call([]), "kthxbai");
o = { join: 17 };
assert.sameValue(Array.prototype.toString.call(o), "[object Object]");
o = { get join() { throw 42; } };
try
{
var str = Array.prototype.toString.call(o);
assert.sameValue(true, false,
"expected an exception calling [].toString on an object with a " +
"join getter that throws, got " + str + " instead");
}
catch (e)
{
assert.sameValue(e, 42,
"expected thrown e === 42 when calling [].toString on an object " +
"with a join getter that throws, got " + e);
}
/******************************************************************************/
print("All tests passed!");

Some files were not shown because too many files have changed in this diff Show More