From f0dd9748da83e1174b7c2fd2f29ade871e3b7db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= Date: Tue, 3 May 2022 18:17:11 +0300 Subject: [PATCH] jscript: Implement Array.prototype.some. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gabriel Ivăncescu Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/jscript/array.c | 67 ++++++++++++++++++++++++++++++++++++++++ dlls/mshtml/tests/es5.js | 34 ++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 5373610294d..c88b39185dc 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -1414,6 +1414,72 @@ done: return hres; } +static HRESULT Array_some(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + IDispatch *context_obj = NULL, *callback; + jsval_t value, args[3], res; + BOOL boolval, ret = FALSE; + unsigned length, i; + jsdisp_t *jsthis; + HRESULT hres; + + TRACE("\n"); + + hres = get_length(ctx, vthis, &jsthis, &length); + if(FAILED(hres)) + return hres; + + /* FIXME: check IsCallable */ + if(!argc || !is_object_instance(argv[0])) { + FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined())); + hres = E_INVALIDARG; + goto done; + } + callback = get_object(argv[0]); + + if(argc > 1 && !is_undefined(argv[1])) { + if(!is_object_instance(argv[1])) { + FIXME("Unsupported context this %s\n", debugstr_jsval(argv[1])); + hres = E_NOTIMPL; + goto done; + } + context_obj = get_object(argv[1]); + } + + for(i = 0; i < length; i++) { + hres = jsdisp_get_idx(jsthis, i, &value); + if(FAILED(hres)) { + if(hres == DISP_E_UNKNOWNNAME) + continue; + goto done; + } + args[0] = value; + args[1] = jsval_number(i); + args[2] = jsval_obj(jsthis); + hres = disp_call_value(ctx, callback, context_obj, DISPATCH_METHOD, ARRAY_SIZE(args), args, &res); + jsval_release(value); + if(FAILED(hres)) + goto done; + + hres = to_boolean(res, &boolval); + jsval_release(res); + if(FAILED(hres)) + goto done; + if(boolval) { + ret = TRUE; + break; + } + } + + if(r) + *r = jsval_bool(ret); + hres = S_OK; +done: + jsdisp_release(jsthis); + return hres; +} + /* ECMA-262 3rd Edition 15.4.4.13 */ static HRESULT Array_unshift(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) @@ -1518,6 +1584,7 @@ static const builtin_prop_t Array_props[] = { {L"reverse", Array_reverse, PROPF_METHOD}, {L"shift", Array_shift, PROPF_METHOD}, {L"slice", Array_slice, PROPF_METHOD|2}, + {L"some", Array_some, PROPF_METHOD|PROPF_ES5|1}, {L"sort", Array_sort, PROPF_METHOD|1}, {L"splice", Array_splice, PROPF_METHOD|2}, {L"toLocaleString", Array_toLocaleString, PROPF_METHOD}, diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 6bef2933d1f..1b498262060 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -233,6 +233,40 @@ sync_test("filter", function() { test([true,"b",42,Math,arr[9],"c"], function(v) { return v; }, Object); }); +sync_test("every & some", function() { + ok(Array.prototype.every.length === 1, "every.length = " + Array.prototype.every.length); + ok(Array.prototype.some.length === 1, "some.length = " + Array.prototype.some.length); + var arr = ["foobar"]; + + function test(expect_every, expect_some, fn, expect_this) { + var cb = function(v, i, a) { + ok(a === arr, "unexpected array " + arr); + ok(v === arr[i], "value = " + v + ", expected " + arr[i]); + ok(this === (expect_this ? expect_this : window), "this = " + this + ", expected " + expect_this); + return fn(v); + }; + r = expect_this ? Array.prototype.every.call(arr, cb, expect_this) : Array.prototype.every.call(arr, cb); + ok(r === expect_every, "'every' = " + r); + r = expect_this ? Array.prototype.some.call(arr, cb, expect_this) : Array.prototype.some.call(arr, cb); + ok(r === expect_some, "'some' = " + r); + } + + delete arr[0]; + test(true, false, function(v) { return false; }); + test(true, false, function(v) { return true; }); + + arr = [1,"2",3]; + test(true, true, function(v) { return true; }); + test(true, true, function(v) { if(arr[1] === "2") delete arr[1]; return typeof v === "number"; }); + test(true, true, function(v) { if(arr[arr.length - 1] !== "a") arr.push("a"); return typeof v === "number"; }, Object); + test(false, true, function(v) { return typeof v === "number"; }, Object); + + arr = [0,null,undefined,false]; + test(false, false, function(v) { return v; }); + arr.push(1); + test(false, true, function(v) { return v; }); +}); + sync_test("forEach", function() { ok(Array.prototype.forEach.length === 1, "forEach.length = " + Array.prototype.forEach.length);