Gabriel Ivăncescu : jscript: Implement Array.prototype.filter.
Alexandre Julliard
julliard at winehq.org
Tue May 3 15:39:25 CDT 2022
Module: wine
Branch: master
Commit: c603fb490ab2ff22948b43f2d3c0c9e7848e0d08
URL: https://source.winehq.org/git/wine.git/?a=commit;h=c603fb490ab2ff22948b43f2d3c0c9e7848e0d08
Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date: Tue May 3 18:17:09 2022 +0300
jscript: Implement Array.prototype.filter.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/jscript/array.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++
dlls/mshtml/tests/es5.js | 28 ++++++++++++++++++
2 files changed, 103 insertions(+)
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c
index e9a8fb5e330..fae761a71cc 100644
--- a/dlls/jscript/array.c
+++ b/dlls/jscript/array.c
@@ -1023,6 +1023,80 @@ static HRESULT Array_toLocaleString(script_ctx_t *ctx, jsval_t vthis, WORD flags
return hres;
}
+static HRESULT Array_filter(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;
+ unsigned length, i, j = 0;
+ jsdisp_t *jsthis, *arr;
+ HRESULT hres;
+ BOOL boolval;
+
+ 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]);
+ }
+
+ hres = create_array(ctx, 0, &arr);
+ if(FAILED(hres))
+ goto done;
+
+ for(i = 0; i < length; i++) {
+ hres = jsdisp_get_idx(jsthis, i, &value);
+ if(FAILED(hres)) {
+ if(hres == DISP_E_UNKNOWNNAME) {
+ hres = S_OK;
+ continue;
+ }
+ break;
+ }
+ 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);
+ if(SUCCEEDED(hres)) {
+ hres = to_boolean(res, &boolval);
+ jsval_release(res);
+ if(SUCCEEDED(hres) && boolval)
+ hres = jsdisp_propput_idx(arr, j++, value);
+ }
+ jsval_release(value);
+ if(FAILED(hres))
+ break;
+ }
+
+ if(FAILED(hres)) {
+ jsdisp_release(arr);
+ goto done;
+ }
+ set_length(arr, j);
+
+ if(r)
+ *r = jsval_obj(arr);
+done:
+ jsdisp_release(jsthis);
+ return hres;
+}
+
static HRESULT Array_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
{
@@ -1365,6 +1439,7 @@ static void Array_on_put(jsdisp_t *dispex, const WCHAR *name)
static const builtin_prop_t Array_props[] = {
{L"concat", Array_concat, PROPF_METHOD|1},
+ {L"filter", Array_filter, PROPF_METHOD|PROPF_ES5|1},
{L"forEach", Array_forEach, PROPF_METHOD|PROPF_ES5|1},
{L"indexOf", Array_indexOf, PROPF_METHOD|PROPF_ES5|1},
{L"join", Array_join, PROPF_METHOD|1},
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 8b1c3071917..6bef2933d1f 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -205,6 +205,34 @@ sync_test("indexOf", function() {
expect([1,2,3], [2, 1.9], 1);
});
+sync_test("filter", function() {
+ ok(Array.prototype.filter.length === 1, "filter.length = " + Array.prototype.filter.length);
+
+ var arr = ["a","foobar",true,"b",42,0,Math,null,undefined,[1,2,3,"4"]];
+ delete arr[1];
+
+ function test(expect, fn, expect_this) {
+ var mismatch = false, r = 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.filter.call(arr, r, expect_this) : Array.prototype.filter.call(arr, r);
+ ok(r.length === expect.length, "filtered array length = " + r.length + ", expected " + expect.length);
+ for(var i = 0; i < r.length; i++)
+ if(r[i] !== expect[i])
+ mismatch = true;
+ ok(!mismatch, "filtered array = " + r + ", expected " + expect);
+ }
+
+ test([], function(v) { return false; });
+ test(["a",true,"b",42,0,Math,null,undefined,arr[9]], function(v) { if(arr[1] === "foobar") delete arr[1]; return true; });
+ test(["a","b"], function(v) { if(v === "b") delete arr[0]; return typeof v === "string"; });
+ test(["b"], function(v) { if(arr[arr.length - 1] !== "c") arr.push("c"); return typeof v === "string"; });
+ test([true,"b",42,Math,arr[9],"c"], function(v) { return v; }, Object);
+});
+
sync_test("forEach", function() {
ok(Array.prototype.forEach.length === 1, "forEach.length = " + Array.prototype.forEach.length);
More information about the wine-cvs
mailing list