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