Issue #2246 - Implement Array find from last.

Based on the implementation from Mozilla bug 1704385.
This commit is contained in:
Job Bautista 2023-01-12 21:42:27 +08:00 committed by roytam1
commit bbb91e4833
5 changed files with 161 additions and 0 deletions

View file

@ -1210,6 +1210,72 @@ function ArrayAt(index) {
return O[k];
}
// https://github.com/tc39/proposal-array-find-from-last
// Array.prototype.findLast ( predicate, thisArg )
function ArrayFindLast(predicate/*, thisArg*/) {
/* Steps 1. */
var O = ToObject(this);
/* Steps 2. */
var len = ToLength(O.length);
/* Step 3. */
if (arguments.length === 0) {
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.findLast");
}
if (!IsCallable(predicate)) {
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
}
var T = arguments.length > 1 ? arguments[1] : undefined;
/* Step 4-5. */
for (var k = len - 1; k >= 0; k--) {
/* Steps 5.a-b. */
var kValue = O[k];
/* Steps 5.c-d. */
if (callContentFunction(predicate, T, kValue, k, O)) {
return kValue;
}
}
/* Step 6. */
return undefined;
}
// https://github.com/tc39/proposal-array-find-from-last
// Array.prototype.findLastIndex ( predicate, thisArg )
function ArrayFindLastIndex(predicate/*, thisArg*/) {
/* Steps 1. */
var O = ToObject(this);
/* Steps 2. */
var len = ToLength(O.length);
/* Step 3. */
if (arguments.length === 0) {
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.findLastIndex");
}
if (!IsCallable(predicate)) {
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
}
var T = arguments.length > 1 ? arguments[1] : undefined;
/* Step 4-5. */
for (var k = len - 1; k >= 0; k--) {
/* Steps 5.a-b. */
var kValue = O[k];
/* Steps 5.c-d. */
if (callContentFunction(predicate, T, kValue, k, O)) {
return k;
}
}
/* Step 6. */
return -1;
}
function ArrayStaticConcat(arr, arg1) {
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.concat');

View file

@ -1347,6 +1347,91 @@ function TypedArrayAt(index) {
return obj[k];
}
// https://github.com/tc39/proposal-array-find-from-last
// %TypedArray%.prototype.findLast ( predicate, thisArg )
function TypedArrayFindLast(predicate/*, thisArg*/) {
// Step 1.
var O = this;
// Step 2.
var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O);
// If we got here, `this` is either a typed array or a wrapper for one.
// Step 3.
var len;
if (isTypedArray) {
len = TypedArrayLength(O);
} else {
len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod");
}
// Step 4.
if (arguments.length === 0) {
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.findLast");
}
if (!IsCallable(predicate)) {
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
}
var thisArg = arguments.length > 1 ? arguments[1] : void 0;
// Steps 5-6.
for (var k = len - 1; k >= 0; k--) {
// Steps 6.a-b.
var kValue = O[k];
// Steps 6.c-d.
if (callContentFunction(predicate, thisArg, kValue, k, O)) {
return kValue;
}
}
// Step 7.
return undefined;
}
// https://github.com/tc39/proposal-array-find-from-last
// %TypedArray%.prototype.findLastIndex ( predicate, thisArg )
function TypedArrayFindLastIndex(predicate/*, thisArg*/) {
// Step 1.
var O = this;
// Step 2.
var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O);
// If we got here, `this` is either a typed array or a wrapper for one.
// Step 3.
var len;
if (isTypedArray) {
len = TypedArrayLength(O);
} else {
len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod");
}
// Step 4.
if (arguments.length === 0) {
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.findLastIndex");
}
if (!IsCallable(predicate)) {
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
}
var thisArg = arguments.length > 1 ? arguments[1] : void 0;
// Steps 5-6.
for (var k = len - 1; k >= 0; k--) {
// Steps 6.a-f.
if (callContentFunction(predicate, thisArg, O[k], k, O)) {
return k;
}
}
// Step 7.
return -1;
}
// ES6 draft rev30 (2014/12/24) 22.2.3.30 %TypedArray%.prototype.values()
function TypedArrayValues() {
// Step 1.

View file

@ -3191,6 +3191,10 @@ static const JSFunctionSpec array_methods[] = {
/* ES2022 additions */
JS_SELF_HOSTED_FN("at", "ArrayAt", 1,0),
/* ES2023 proposals */
JS_SELF_HOSTED_FN("findLast", "ArrayFindLast", 1,0),
JS_SELF_HOSTED_FN("findLastIndex", "ArrayFindLastIndex", 1,0),
JS_FS_END
};
@ -3356,6 +3360,8 @@ array_proto_finish(JSContext* cx, JS::HandleObject ctor, JS::HandleObject proto)
!DefineProperty(cx, unscopables, cx->names().fill, value) ||
!DefineProperty(cx, unscopables, cx->names().find, value) ||
!DefineProperty(cx, unscopables, cx->names().findIndex, value) ||
!DefineProperty(cx, unscopables, cx->names().findLast, value) ||
!DefineProperty(cx, unscopables, cx->names().findLastIndex, value) ||
!DefineProperty(cx, unscopables, cx->names().flat, value) ||
!DefineProperty(cx, unscopables, cx->names().flatMap, value) ||
!DefineProperty(cx, unscopables, cx->names().includes, value) ||

View file

@ -135,6 +135,8 @@
macro(finally, finally_, "finally") \
macro(find, find, "find") \
macro(findIndex, findIndex, "findIndex") \
macro(findLast, findLast, "findLast") \
macro(findLastIndex, findLastIndex, "findLastIndex") \
macro(firstDayOfWeek, firstDayOfWeek, "firstDayOfWeek") \
macro(fix, fix, "fix") \
macro(flags, flags, "flags") \

View file

@ -1486,6 +1486,8 @@ TypedArrayObject::protoFunctions[] = {
JS_SELF_HOSTED_FN("filter", "TypedArrayFilter", 1, 0),
JS_SELF_HOSTED_FN("find", "TypedArrayFind", 1, 0),
JS_SELF_HOSTED_FN("findIndex", "TypedArrayFindIndex", 1, 0),
JS_SELF_HOSTED_FN("findLast", "TypedArrayFindLast", 1, 0),
JS_SELF_HOSTED_FN("findLastIndex", "TypedArrayFindLastIndex", 1, 0),
JS_SELF_HOSTED_FN("forEach", "TypedArrayForEach", 1, 0),
JS_SELF_HOSTED_FN("indexOf", "TypedArrayIndexOf", 2, 0),
JS_SELF_HOSTED_FN("join", "TypedArrayJoin", 1, 0),