Module: wine Branch: master Commit: 60816b9f8adf1b70c1d1427440c4a9888caf33c5 URL: https://source.winehq.org/git/wine.git/?a=commit;h=60816b9f8adf1b70c1d142744...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Mar 14 14:30:57 2019 +0100
jscript: Add Array.prototype.map implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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,