Jacek Caban : jscript: Add Array.prototype.reduce implementation.
Alexandre Julliard
julliard at winehq.org
Thu Jun 4 16:08:03 CDT 2020
Module: wine
Branch: master
Commit: 3c72034b72014a087eae8d181252c67cb0782e28
URL: https://source.winehq.org/git/wine.git/?a=commit;h=3c72034b72014a087eae8d181252c67cb0782e28
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu Jun 4 17:30:22 2020 +0200
jscript: Add Array.prototype.reduce implementation.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/jscript/array.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++-
dlls/mshtml/tests/es5.js | 47 ++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c
index 5d50b9249e..7941031e49 100644
--- a/dlls/jscript/array.c
+++ b/dlls/jscript/array.c
@@ -1048,7 +1048,7 @@ static HRESULT Array_map(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned
return hres;
}
- /* Fixme check IsCallable */
+ /* FIXME: check IsCallable */
if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined()));
return E_INVALIDARG;
@@ -1094,6 +1094,74 @@ static HRESULT Array_map(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned
return hres;
}
+static HRESULT Array_reduce(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ IDispatch *context_this = NULL, *callback;
+ jsval_t callback_args[4], acc, new_acc;
+ BOOL have_value = FALSE;
+ jsdisp_t *jsthis;
+ DWORD length, k;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ hres = get_length(ctx, vthis, &jsthis, &length);
+ if(FAILED(hres)) {
+ FIXME("Could not get length\n");
+ return hres;
+ }
+
+ /* Fixme check IsCallable */
+ if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined()));
+ return E_INVALIDARG;
+ }
+ callback = get_object(argv[0]);
+
+ if(argc > 1) {
+ have_value = TRUE;
+ hres = jsval_copy(argv[1], &acc);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ for(k = 0; k < length; k++) {
+ hres = jsdisp_get_idx(jsthis, k, &callback_args[1]);
+ if(hres == DISP_E_UNKNOWNNAME)
+ continue;
+ if(FAILED(hres))
+ break;
+
+ if(!have_value) {
+ have_value = TRUE;
+ acc = callback_args[1];
+ continue;
+ }
+
+ callback_args[0] = acc;
+ callback_args[2] = jsval_number(k);
+ callback_args[3] = jsval_obj(jsthis);
+ hres = disp_call_value(ctx, callback, context_this, DISPATCH_METHOD, ARRAY_SIZE(callback_args), callback_args, &new_acc);
+ jsval_release(callback_args[1]);
+ if(FAILED(hres))
+ break;
+
+ jsval_release(acc);
+ acc = new_acc;
+ }
+
+ if(SUCCEEDED(hres) && !have_value) {
+ WARN("No array element\n");
+ hres = JS_E_INVALID_ACTION;
+ }
+
+ if(SUCCEEDED(hres) && r)
+ *r = acc;
+ else if(have_value)
+ jsval_release(acc);
+ return hres;
+}
+
/* ECMA-262 3rd Edition 15.4.4.13 */
static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
@@ -1198,6 +1266,7 @@ static const builtin_prop_t Array_props[] = {
{L"map", Array_map, PROPF_METHOD|PROPF_ES5|1},
{L"pop", Array_pop, PROPF_METHOD},
{L"push", Array_push, PROPF_METHOD|1},
+ {L"reduce", Array_reduce, PROPF_METHOD|PROPF_ES5|1},
{L"reverse", Array_reverse, PROPF_METHOD},
{L"shift", Array_shift, PROPF_METHOD},
{L"slice", Array_slice, PROPF_METHOD|2},
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index c179ca143f..f268eba24c 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -881,3 +881,50 @@ sync_test("keys", function() {
ok(Object.keys.length === 1, "Object.keys.length = " + Object.keys.length);
});
+
+sync_test("reduce", function() {
+ var r, array;
+
+ r = [1,2,3].reduce(function(a, value) { return a + value + 10; });
+ ok(r === 26, "reduce() returned " + r);
+
+ r = [1,2,3].reduce(function(a, value) { return a + value + 10; }, 1);
+ ok(r === 37, "reduce() returned " + r);
+
+ r = [1,2,3].reduce(function(a, value) { return a + value; }, "str");
+ ok(r === "str123", "reduce() returned " + r);
+
+ array = [1,2,3];
+ r = array.reduce(function(a, value, index, src) {
+ ok(src === array, "src != array");
+ return a + "(" + index + "," + value + ")";
+ }, "str");
+ ok(r === "str(0,1)(1,2)(2,3)", "reduce() returned " + r);
+
+ r = [1,2,3].reduce(function(a, value, index, src) {
+ src[0] = false;
+ delete src[1];
+ src[2] = "test";
+ return a + value;
+ }, "");
+ ok(r === "1test", "reduce() returned " + r);
+
+ r = [1].reduce(function(a) { return 0; });
+ ok(r === 1, "[1].reduce() returned " + r);
+
+ r = [1].reduce(function(a) { return 0; }, 2);
+ ok(r === 0, "[1].reduce(2) returned " + r);
+
+ r = [].reduce(function(a) { return 0; }, 2);
+ ok(r === 2, "[].reduce(2) returned " + r);
+
+ r = [].reduce(function(a) { return 0; }, undefined);
+ ok(r === undefined, "[].reduce(undefined) returned " + r);
+
+ try {
+ [].reduce(function(a) { return 0; });
+ ok(false, "expected exception");
+ }catch(e) {trace(e.message);}
+
+ ok(Array.prototype.reduce.length === 1, "Array.prototype.reduce.length = " + Array.prototype.reduce.length);
+});
More information about the wine-cvs
mailing list