зеркало из https://github.com/mozilla/gecko-dev.git
Bug 885553 - Implement ES6 Array.prototype.find and Array.prototype.findIndex. r=jwalden
--HG-- extra : rebase_source : ca717dae292897561f503ab2d5964f02915f5067
This commit is contained in:
Родитель
0139cd9c05
Коммит
f78fd42a4c
|
@ -391,3 +391,78 @@ function ArrayStaticReduceRight(list, callbackfn) {
|
|||
else
|
||||
return callFunction(ArrayReduceRight, list, callbackfn);
|
||||
}
|
||||
|
||||
/* ES6 draft 2013-05-14 15.4.3.23. */
|
||||
function ArrayFind(predicate/*, thisArg*/) {
|
||||
/* Steps 1-2. */
|
||||
var O = ToObject(this);
|
||||
|
||||
/* Steps 3-5. */
|
||||
var len = ToInteger(O.length);
|
||||
|
||||
/* Step 6. */
|
||||
if (arguments.length === 0)
|
||||
ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.find');
|
||||
if (!IsCallable(predicate))
|
||||
ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
|
||||
|
||||
/* Step 7. */
|
||||
var T = arguments.length > 1 ? arguments[1] : undefined;
|
||||
|
||||
/* Steps 8-9. */
|
||||
/* Steps a (implicit), and e. */
|
||||
/* Note: this will hang in some corner-case situations, because of IEEE-754 numbers'
|
||||
* imprecision for large values. Example:
|
||||
* var obj = { 18014398509481984: true, length: 18014398509481988 };
|
||||
* Array.prototype.find.call(obj, () => true);
|
||||
*/
|
||||
for (var k = 0; k < len; k++) {
|
||||
/* Steps b and c (implicit) */
|
||||
if (k in O) {
|
||||
/* Step d. */
|
||||
var kValue = O[k];
|
||||
if (callFunction(predicate, T, kValue, k, O))
|
||||
return kValue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 10. */
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* ES6 draft 2013-05-14 15.4.3.23. */
|
||||
function ArrayFindIndex(predicate/*, thisArg*/) {
|
||||
/* Steps 1-2. */
|
||||
var O = ToObject(this);
|
||||
|
||||
/* Steps 3-5. */
|
||||
var len = ToInteger(O.length);
|
||||
|
||||
/* Step 6. */
|
||||
if (arguments.length === 0)
|
||||
ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.find');
|
||||
if (!IsCallable(predicate))
|
||||
ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
|
||||
|
||||
/* Step 7. */
|
||||
var T = arguments.length > 1 ? arguments[1] : undefined;
|
||||
|
||||
/* Steps 8-9. */
|
||||
/* Steps a (implicit), and e. */
|
||||
/* Note: this will hang in some corner-case situations, because of IEEE-754 numbers'
|
||||
* imprecision for large values. Example:
|
||||
* var obj = { 18014398509481984: true, length: 18014398509481988 };
|
||||
* Array.prototype.find.call(obj, () => true);
|
||||
*/
|
||||
for (var k = 0; k < len; k++) {
|
||||
/* Steps b and c (implicit) */
|
||||
if (k in O) {
|
||||
/* Step d. */
|
||||
if (callFunction(predicate, T, O[k], k, O))
|
||||
return k;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 10. */
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -2727,6 +2727,10 @@ static const JSFunctionSpec array_methods[] = {
|
|||
{"some", {NULL, NULL}, 1,0, "ArraySome"},
|
||||
{"every", {NULL, NULL}, 1,0, "ArrayEvery"},
|
||||
|
||||
/* ES6 additions */
|
||||
{"find", {NULL, NULL}, 1,0, "ArrayFind"},
|
||||
{"findIndex", {NULL, NULL}, 1,0, "ArrayFindIndex"},
|
||||
|
||||
JS_FN("iterator", JS_ArrayIterator, 0,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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)
|
||||
{
|
||||
reportCompare(v, array[index], 'isString: check callback argument consistency');
|
||||
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; } })
|
||||
|
||||
// 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');
|
Загрузка…
Ссылка в новой задаче