mirror of https://github.com/tc39/test262.git
Import tests from SpiderMonkey
This commit is contained in:
parent
d0bda4d26f
commit
6ee9579acb
|
@ -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!");
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 + ")");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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
|
||||
];
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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, "");
|
||||
};
|
||||
})();
|
||||
|
||||
})();
|
|
@ -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);
|
|
@ -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 = () => {}
|
||||
}
|
|
@ -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);
|
||||
|
|
@ -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!");
|
|
@ -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();
|
||||
|
|
@ -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}));
|
||||
|
|
@ -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}));
|
||||
|
|
@ -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);
|
||||
|
|
@ -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]);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
@ -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();
|
||||
|
|
@ -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();
|
||||
|
|
@ -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();
|
||||
|
|
@ -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();
|
||||
|
|
@ -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,
|
||||
});
|
||||
|
|
@ -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}), []);
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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');
|
||||
|
|
@ -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);
|
||||
|
|
@ -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"]);
|
||||
|
|
@ -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];
|
||||
}
|
||||
|
|
@ -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"]);
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -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']);
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
@ -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);
|
||||
|
|
@ -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]");
|
||||
|
|
@ -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);
|
||||
|
|
@ -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,
|
||||
},
|
||||
}));
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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');
|
||||
|
|
@ -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);
|
||||
|
|
@ -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"]);
|
||||
|
||||
|
|
@ -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();
|
||||
|
|
@ -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");
|
|
@ -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");
|
||||
|
|
@ -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);
|
||||
|
|
@ -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!");
|
|
@ -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");
|
|
@ -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!");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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);
|
||||
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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');
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
@ -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");
|
|
@ -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");
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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!");
|
|
@ -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");
|
|
@ -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"]);
|
||||
|
|
@ -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();
|
||||
|
|
@ -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");
|
||||
|
||||
|
|
@ -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, , ,]));
|
||||
|
|
@ -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);
|
||||
|
|
@ -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([]);
|
||||
|
|
@ -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));
|
||||
|
|
@ -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,");
|
||||
|
|
@ -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");
|
|
@ -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]);
|
||||
}
|
||||
|
|
@ -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");
|
|
@ -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");
|
||||
|
|
@ -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!");
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -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");
|
||||
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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]);
|
||||
|
|
@ -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
Loading…
Reference in New Issue