Jacek Caban : jscript: Add Array.prototype.map implementation.

Alexandre Julliard julliard at winehq.org
Thu Mar 14 18:33:21 CDT 2019


Module: wine
Branch: master
Commit: 60816b9f8adf1b70c1d1427440c4a9888caf33c5
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=60816b9f8adf1b70c1d1427440c4a9888caf33c5

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Mar 14 14:30:57 2019 +0100

jscript: Add Array.prototype.map implementation.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/jscript/array.c              | 63 +++++++++++++++++++++++++++++++++++++++
 dlls/mshtml/tests/documentmode.js |  1 +
 dlls/mshtml/tests/es5.js          | 45 ++++++++++++++++++++++++++++
 3 files changed, 109 insertions(+)

diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c
index 28289cb..a7b1f02 100644
--- a/dlls/jscript/array.c
+++ b/dlls/jscript/array.c
@@ -49,6 +49,7 @@ static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
 static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
 static const WCHAR unshiftW[] = {'u','n','s','h','i','f','t',0};
 static const WCHAR indexOfW[] = {'i','n','d','e','x','O','f',0};
+static const WCHAR mapW[] = {'m','a','p',0};
 
 static const WCHAR default_separatorW[] = {',',0};
 
@@ -1044,6 +1045,67 @@ static HRESULT Array_indexOf(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsi
     return S_OK;
 }
 
+static HRESULT Array_map(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[3], mapped_value;
+    jsdisp_t *jsthis, *array;
+    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) {
+        if(!is_object_instance(argv[1]) || !get_object(argv[1])) {
+            FIXME("Unsupported context this %s\n", debugstr_jsval(argv[1]));
+            return E_NOTIMPL;
+        }
+        context_this = get_object(argv[1]);
+    }
+
+    hres = create_array(ctx, length, &array);
+    if(FAILED(hres))
+        return hres;
+
+    for(k = 0; k < length; k++) {
+        hres = jsdisp_get_idx(jsthis, k, &callback_args[0]);
+        if(hres == DISP_E_UNKNOWNNAME)
+            continue;
+        if(FAILED(hres))
+            break;
+
+        callback_args[1] = jsval_number(k);
+        callback_args[2] = jsval_obj(jsthis);
+        hres = disp_call_value(ctx, callback, context_this, DISPATCH_METHOD, 3, callback_args, &mapped_value);
+        jsval_release(callback_args[0]);
+        if(FAILED(hres))
+            break;
+
+        hres = jsdisp_propput_idx(array, k, mapped_value);
+        if(FAILED(hres))
+            break;
+    }
+
+    if(SUCCEEDED(hres) && r)
+        *r = jsval_obj(array);
+    else
+        jsdisp_release(array);
+    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)
@@ -1146,6 +1208,7 @@ static const builtin_prop_t Array_props[] = {
     {indexOfW,               Array_indexOf,              PROPF_METHOD|PROPF_ES5|1},
     {joinW,                  Array_join,                 PROPF_METHOD|1},
     {lengthW,                NULL,0,                     Array_get_length, Array_set_length},
+    {mapW,                   Array_map,                  PROPF_METHOD|PROPF_ES5|1},
     {popW,                   Array_pop,                  PROPF_METHOD},
     {pushW,                  Array_push,                 PROPF_METHOD|1},
     {reverseW,               Array_reverse,              PROPF_METHOD},
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 1e8fabd..1cbf13e 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -190,6 +190,7 @@ function test_javascript() {
     test_exposed("forEach", Array.prototype, v >= 9);
     test_exposed("indexOf", Array.prototype, v >= 9);
     test_exposed("trim", String.prototype, v >= 9);
+    test_exposed("map", Array.prototype, v >= 9);
 
     /* FIXME: IE8 implements weird semi-functional property descriptors. */
     if(v != 8) {
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 69fe0fe..6cfee81 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -130,6 +130,50 @@ function test_isArray() {
     next_test();
 }
 
+function test_array_map() {
+    var calls, m, arr, ctx;
+
+    /* basic map call with context */
+    calls = "";
+    arr = [1,2,3];
+    ctx = {};
+    m = arr.map(function(x, i, a) {
+        ok(this === ctx, "this != ctx");
+        ok(i === x - 1, "i = " + i);
+        ok(a === arr, "a != arr");
+        calls += x + ",";
+        return x * 2;
+    }, ctx);
+    ok(calls === "1,2,3,", "calls = " + calls);
+    ok(m.join() === "2,4,6", "m = " + m);
+
+    /* non-array object as this argument */
+    calls = "";
+    arr = { 1: "one", 2: "two", 3: "three", length: 3 };
+    m = Array.prototype.map.call(arr, function(x, i) {
+        calls += i + ":" + x + ",";
+        return x + "!";
+    });
+    ok(calls === "1:one,2:two,", "calls = " + calls);
+    ok(m.join() === ",one!,two!", "m = " + m);
+    ok(!("0" in m), "0 is in m");
+
+    /* mutate array in callback */
+    calls = "";
+    arr = [1,2,3];
+    m = Array.prototype.map.call(arr, function(x, i) {
+        calls += i + ":" + x + ",";
+        for(var j = i; j < arr.length; j++)
+            arr[j]++;
+        arr.push(i * i);
+        return x - 1;
+    });
+    ok(calls === "0:1,1:3,2:5,", "calls = " + calls);
+    ok(m.join() === "0,2,4", "m = " + m);
+
+    next_test();
+}
+
 function test_identifier_keywords() {
     var o = {
         if: 1,
@@ -625,6 +669,7 @@ var tests = [
     test_indexOf,
     test_array_forEach,
     test_isArray,
+    test_array_map,
     test_identifier_keywords,
     test_getOwnPropertyDescriptor,
     test_defineProperty,




More information about the wine-cvs mailing list