blob: 6e32ea6b05db5968a60b38ff375c860d96e690b6 [file] [log] [blame]
/* -*- 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/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 885553;
var summary = 'Array.prototype.find and Array.prototype.findIndex';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function isString(v, index, array)
{
assertEq(array[index], v);
return typeof v == 'string';
}
function dumpError(e)
{
var s = e.name + ': ' + e.message +
' File: ' + e.fileName +
', Line: ' + e.lineNumber +
', Stack: ' + e.stack;
return s;
}
var expect;
var actual;
var obj;
var strings = ['hello', 'Array', 'WORLD'];
var mixed = [0, '1', 2];
var sparsestrings = new Array();
sparsestrings[2] = 'sparse';
var arraylike = {0:0, 1:'string', 2:2, length:3};
// array for which JSObject::isIndexed() holds.
var indexedArray = [];
Object.defineProperty(indexedArray, 42, { get: function() { return 42; } });
Object.defineProperty(indexedArray, 142, { get: function() { return 'string'; } });
// find and findIndex have 1 required argument
expect = 1;
actual = Array.prototype.find.length;
reportCompare(expect, actual, 'Array.prototype.find.length == 1');
actual = Array.prototype.findIndex.length;
reportCompare(expect, actual, 'Array.prototype.findIndex.length == 1');
// throw TypeError if no predicate specified
expect = 'TypeError';
try
{
strings.find();
actual = 'no error';
}
catch(e)
{
actual = e.name;
}
reportCompare(expect, actual, 'Array.find(undefined) throws TypeError');
try
{
strings.findIndex();
actual = 'no error';
}
catch(e)
{
actual = e.name;
}
reportCompare(expect, actual, 'Array.findIndex(undefined) throws TypeError');
// Length gets treated as integer, not uint32
obj = { length: -4294967295, 0: 42 };
expected = undefined;
actual = Array.prototype.find.call(obj, () => true);
reportCompare(expected, actual, 'find correctly treats "length" as an integer');
expected = -1
actual = Array.prototype.findIndex.call(obj, () => true);
reportCompare(expected, actual, 'findIndex correctly treats "length" as an integer');
// test find and findIndex results
try
{
expect = 'hello';
actual = strings.find(isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'strings: find finds first string element');
try
{
expect = 0;
actual = strings.findIndex(isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'strings: findIndex finds first string element');
try
{
expect = '1';
actual = mixed.find(isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'mixed: find finds first string element');
try
{
expect = 1;
actual = mixed.findIndex(isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'mixed: findIndex finds first string element');
try
{
expect = 'sparse';
actual = sparsestrings.find(isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'sparsestrings: find finds first string element');
try
{
expect = 2;
actual = sparsestrings.findIndex(isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'sparsestrings: findIndex finds first string element');
try
{
expect = 'string';
actual = [].find.call(arraylike, isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'arraylike: find finds first string element');
try
{
expect = 1;
actual = [].findIndex.call(arraylike, isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'arraylike: findIndex finds first string element');
try
{
expect = 1;
actual = 0;
Array.prototype.find.call({get 0(){ actual++ }, length: 1}, ()=>true);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'arraylike with getter: getter only called once');
try
{
expect = 'string';
actual = [].find.call(indexedArray, isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'indexedArray: find finds first string element');
try
{
expect = 142;
actual = [].findIndex.call(indexedArray, isString);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, 'indexedArray: findIndex finds first string element');
// Bug 1058394 - Array#find and Array#findIndex no longer skip holes
var sparseArray = [,,1];
var sparseArrayWithInheritedDataProperty = Object.setPrototypeOf([,,1], {
__proto__: [].__proto__,
0 : 0
});
var sparseArrayWithInheritedAccessorProperty = Object.setPrototypeOf([,,1], {
__proto__: [].__proto__,
get 0(){
throw "get 0";
}
});
try
{
expect = undefined;
actual = sparseArray.find(() => true);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, "Don't skip holes in Array#find.");
try
{
expect = 0;
actual = sparseArray.findIndex(() => true);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, "Don't skip holes in Array#findIndex.");
try
{
expect = 0;
actual = sparseArrayWithInheritedDataProperty.find(v => v === 0);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, "Array#find can find inherited data property.");
try
{
expect = 0;
actual = sparseArrayWithInheritedDataProperty.findIndex(v => v === 0);
}
catch(e)
{
actual = dumpError(e);
}
reportCompare(expect, actual, "Array#findIndex can find inherited data property.");
try
{
expect = "get 0";
actual = sparseArrayWithInheritedAccessorProperty.find(() => true);
}
catch(e)
{
actual = e;
}
reportCompare(expect, actual, "Array#find can find inherited accessor property.");
try
{
expect = "get 0";
actual = sparseArrayWithInheritedAccessorProperty.findIndex(() => true);
}
catch(e)
{
actual = e;
}
reportCompare(expect, actual, "Array#findIndex can find inherited accessor property.");