diff --git a/quickjs.c b/quickjs.c index c6fcd5a..b0253a4 100644 --- a/quickjs.c +++ b/quickjs.c @@ -36440,13 +36440,21 @@ static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } +enum { + ArrayFind, + ArrayFindIndex, + ArrayFindLast, + ArrayFindLastIndex, +}; + static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int findIndex) + int argc, JSValueConst *argv, int mode) { JSValueConst func, this_arg; JSValueConst args[3]; JSValue obj, val, index_val, res; - int64_t len, k; + int64_t len, k, end; + int dir; index_val = JS_UNDEFINED; val = JS_UNDEFINED; @@ -36462,7 +36470,17 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, if (argc > 1) this_arg = argv[1]; - for(k = 0; k < len; k++) { + k = 0; + dir = 1; + end = len; + if (mode == ArrayFindLast || mode == ArrayFindLastIndex) { + k = len - 1; + dir = -1; + end = -1; + } + + // TODO(bnoordhuis) add fast path for fast arrays + for(; k != end; k += dir) { index_val = JS_NewInt64(ctx, k); if (JS_IsException(index_val)) goto exception; @@ -36476,7 +36494,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, if (JS_IsException(res)) goto exception; if (JS_ToBoolFree(ctx, res)) { - if (findIndex) { + if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) { JS_FreeValue(ctx, val); JS_FreeValue(ctx, obj); return index_val; @@ -36490,7 +36508,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, index_val); } JS_FreeValue(ctx, obj); - if (findIndex) + if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) return JS_NewInt32(ctx, -1); else return JS_UNDEFINED; @@ -37542,8 +37560,10 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce ), JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight ), JS_CFUNC_DEF("fill", 1, js_array_fill ), - JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, 0 ), - JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, 1 ), + JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, ArrayFind ), + JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, ArrayFindIndex ), + JS_CFUNC_MAGIC_DEF("findLast", 1, js_array_find, ArrayFindLast ), + JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_array_find, ArrayFindLastIndex ), JS_CFUNC_DEF("indexOf", 1, js_array_indexOf ), JS_CFUNC_DEF("lastIndexOf", 1, js_array_lastIndexOf ), JS_CFUNC_DEF("includes", 1, js_array_includes ), @@ -47104,6 +47124,8 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) "fill" "\0" "find" "\0" "findIndex" "\0" + "findLast" "\0" + "findLastIndex" "\0" "flat" "\0" "flatMap" "\0" "includes" "\0" diff --git a/test262.conf b/test262.conf index 09151f4..cdf622f 100644 --- a/test262.conf +++ b/test262.conf @@ -55,7 +55,7 @@ __setter__ AggregateError align-detached-buffer-semantics-with-web-reality arbitrary-module-namespace-names=skip -array-find-from-last=skip +array-find-from-last array-grouping=skip Array.fromAsync=skip Array.prototype.at diff --git a/test262_errors.txt b/test262_errors.txt index b0d2d6f..cb8a5b3 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -187,6 +187,102 @@ test262/test/built-ins/RegExp/prototype/Symbol.replace/get-unicode-error.js:26: test262/test/built-ins/RegExp/prototype/Symbol.replace/get-unicode-error.js:26: strict mode: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all test262/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js:62: Test262Error: String.prototype.localeCompare considers ö (\u006f\u0308) ≠ ö (\u00f6). test262/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js:62: strict mode: Test262Error: String.prototype.localeCompare considers ö (\u006f\u0308) ≠ ö (\u00f6). +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/get-length-ignores-length-prop.js:40: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/get-length-ignores-length-prop.js:40: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-call-changes-value.js:30: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-call-changes-value.js:30: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-call-parameters.js:28: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-call-parameters.js:28: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-call-this-non-strict.js:27: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-call-this-strict.js:25: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-may-detach-buffer.js:36: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-may-detach-buffer.js:36: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-not-called-on-empty-array.js:25: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/predicate-not-called-on-empty-array.js:25: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/return-abrupt-from-predicate-call.js:22: Test262Error: Expected a Test262Error but got a TypeError (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/return-abrupt-from-predicate-call.js:22: strict mode: Test262Error: Expected a Test262Error but got a TypeError (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/return-found-value-predicate-result-is-true.js:27: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/return-found-value-predicate-result-is-true.js:27: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/return-undefined-if-predicate-returns-false-value.js:27: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/BigInt/return-undefined-if-predicate-returns-false-value.js:27: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/get-length-ignores-length-prop.js:39: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/get-length-ignores-length-prop.js:39: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/invoked-as-func.js:21: Test262Error: Expected SameValue(«undefined», «function») to be true +test262/test/built-ins/TypedArray/prototype/findLast/invoked-as-func.js:21: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true +test262/test/built-ins/TypedArray/prototype/findLast/invoked-as-method.js:21: Test262Error: Expected SameValue(«undefined», «function») to be true +test262/test/built-ins/TypedArray/prototype/findLast/invoked-as-method.js:21: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true +test262/test/built-ins/TypedArray/prototype/findLast/length.js:26: TypeError: cannot read property 'length' of undefined +test262/test/built-ins/TypedArray/prototype/findLast/length.js:26: strict mode: TypeError: cannot read property 'length' of undefined +test262/test/built-ins/TypedArray/prototype/findLast/name.js:23: TypeError: cannot read property 'name' of undefined +test262/test/built-ins/TypedArray/prototype/findLast/name.js:23: strict mode: TypeError: cannot read property 'name' of undefined +test262/test/built-ins/TypedArray/prototype/findLast/not-a-constructor.js:25: Test262Error: isConstructor invoked with a non-function value +test262/test/built-ins/TypedArray/prototype/findLast/not-a-constructor.js:25: strict mode: Test262Error: isConstructor invoked with a non-function value +test262/test/built-ins/TypedArray/prototype/findLast/predicate-call-changes-value.js:30: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-call-changes-value.js:30: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-call-parameters.js:28: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-call-parameters.js:28: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-call-this-non-strict.js:27: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-call-this-strict.js:25: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-may-detach-buffer.js:36: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-may-detach-buffer.js:36: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-not-called-on-empty-array.js:25: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/predicate-not-called-on-empty-array.js:25: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/prop-desc.js:15: Test262Error: obj should have an own property findLast +test262/test/built-ins/TypedArray/prototype/findLast/prop-desc.js:15: strict mode: Test262Error: obj should have an own property findLast +test262/test/built-ins/TypedArray/prototype/findLast/return-abrupt-from-predicate-call.js:22: Test262Error: Expected a Test262Error but got a TypeError (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/return-abrupt-from-predicate-call.js:22: strict mode: Test262Error: Expected a Test262Error but got a TypeError (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/return-found-value-predicate-result-is-true.js:27: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/return-found-value-predicate-result-is-true.js:27: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/return-undefined-if-predicate-returns-false-value.js:27: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLast/return-undefined-if-predicate-returns-false-value.js:27: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/get-length-ignores-length-prop.js:40: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/get-length-ignores-length-prop.js:40: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-call-changes-value.js:29: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-call-changes-value.js:29: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-call-parameters.js:29: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-call-parameters.js:29: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-call-this-non-strict.js:29: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-call-this-strict.js:27: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-may-detach-buffer.js:35: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-may-detach-buffer.js:35: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-not-called-on-empty-array.js:29: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/predicate-not-called-on-empty-array.js:29: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-abrupt-from-predicate-call.js:21: Test262Error: Expected a Test262Error but got a TypeError (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-abrupt-from-predicate-call.js:21: strict mode: Test262Error: Expected a Test262Error but got a TypeError (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-index-predicate-result-is-true.js:28: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-index-predicate-result-is-true.js:28: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-negative-one-if-predicate-returns-false-value.js:28: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/BigInt/return-negative-one-if-predicate-returns-false-value.js:28: strict mode: TypeError: not a function (Testing with BigInt64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/get-length-ignores-length-prop.js:40: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/get-length-ignores-length-prop.js:40: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/invoked-as-func.js:23: Test262Error: Expected SameValue(«undefined», «function») to be true +test262/test/built-ins/TypedArray/prototype/findLastIndex/invoked-as-func.js:23: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true +test262/test/built-ins/TypedArray/prototype/findLastIndex/invoked-as-method.js:23: Test262Error: Expected SameValue(«undefined», «function») to be true +test262/test/built-ins/TypedArray/prototype/findLastIndex/invoked-as-method.js:23: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true +test262/test/built-ins/TypedArray/prototype/findLastIndex/length.js:26: TypeError: cannot read property 'length' of undefined +test262/test/built-ins/TypedArray/prototype/findLastIndex/length.js:26: strict mode: TypeError: cannot read property 'length' of undefined +test262/test/built-ins/TypedArray/prototype/findLastIndex/name.js:23: TypeError: cannot read property 'name' of undefined +test262/test/built-ins/TypedArray/prototype/findLastIndex/name.js:23: strict mode: TypeError: cannot read property 'name' of undefined +test262/test/built-ins/TypedArray/prototype/findLastIndex/not-a-constructor.js:25: Test262Error: isConstructor invoked with a non-function value +test262/test/built-ins/TypedArray/prototype/findLastIndex/not-a-constructor.js:25: strict mode: Test262Error: isConstructor invoked with a non-function value +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-call-changes-value.js:29: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-call-changes-value.js:29: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-call-parameters.js:29: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-call-parameters.js:29: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-call-this-non-strict.js:29: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-call-this-strict.js:27: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-may-detach-buffer.js:35: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-may-detach-buffer.js:35: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-not-called-on-empty-array.js:29: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/predicate-not-called-on-empty-array.js:29: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/prop-desc.js:15: Test262Error: obj should have an own property findLastIndex +test262/test/built-ins/TypedArray/prototype/findLastIndex/prop-desc.js:15: strict mode: Test262Error: obj should have an own property findLastIndex +test262/test/built-ins/TypedArray/prototype/findLastIndex/return-abrupt-from-predicate-call.js:21: Test262Error: Expected a Test262Error but got a TypeError (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/return-abrupt-from-predicate-call.js:21: strict mode: Test262Error: Expected a Test262Error but got a TypeError (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/return-index-predicate-result-is-true.js:28: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/return-index-predicate-result-is-true.js:28: strict mode: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/return-negative-one-if-predicate-returns-false-value.js:28: TypeError: not a function (Testing with Float64Array.) +test262/test/built-ins/TypedArray/prototype/findLastIndex/return-negative-one-if-predicate-returns-false-value.js:28: strict mode: TypeError: not a function (Testing with Float64Array.) test262/test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js:30: TypeError: out-of-bound numeric index (Testing with Float64Array.) test262/test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js:30: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.) test262/test/built-ins/TypedArray/prototype/sort/sort-tonumber.js:30: TypeError: ArrayBuffer is detached (Testing with Float64Array.)