jscript: Add Array.prototype.map implementation.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
120bf0eba9
commit
60816b9f8a
|
@ -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 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 unshiftW[] = {'u','n','s','h','i','f','t',0};
|
||||||
static const WCHAR indexOfW[] = {'i','n','d','e','x','O','f',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};
|
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;
|
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 */
|
/* 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,
|
static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
|
||||||
jsval_t *r)
|
jsval_t *r)
|
||||||
|
@ -1146,6 +1208,7 @@ static const builtin_prop_t Array_props[] = {
|
||||||
{indexOfW, Array_indexOf, PROPF_METHOD|PROPF_ES5|1},
|
{indexOfW, Array_indexOf, PROPF_METHOD|PROPF_ES5|1},
|
||||||
{joinW, Array_join, PROPF_METHOD|1},
|
{joinW, Array_join, PROPF_METHOD|1},
|
||||||
{lengthW, NULL,0, Array_get_length, Array_set_length},
|
{lengthW, NULL,0, Array_get_length, Array_set_length},
|
||||||
|
{mapW, Array_map, PROPF_METHOD|PROPF_ES5|1},
|
||||||
{popW, Array_pop, PROPF_METHOD},
|
{popW, Array_pop, PROPF_METHOD},
|
||||||
{pushW, Array_push, PROPF_METHOD|1},
|
{pushW, Array_push, PROPF_METHOD|1},
|
||||||
{reverseW, Array_reverse, PROPF_METHOD},
|
{reverseW, Array_reverse, PROPF_METHOD},
|
||||||
|
|
|
@ -190,6 +190,7 @@ function test_javascript() {
|
||||||
test_exposed("forEach", Array.prototype, v >= 9);
|
test_exposed("forEach", Array.prototype, v >= 9);
|
||||||
test_exposed("indexOf", Array.prototype, v >= 9);
|
test_exposed("indexOf", Array.prototype, v >= 9);
|
||||||
test_exposed("trim", String.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. */
|
/* FIXME: IE8 implements weird semi-functional property descriptors. */
|
||||||
if(v != 8) {
|
if(v != 8) {
|
||||||
|
|
|
@ -130,6 +130,50 @@ function test_isArray() {
|
||||||
next_test();
|
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() {
|
function test_identifier_keywords() {
|
||||||
var o = {
|
var o = {
|
||||||
if: 1,
|
if: 1,
|
||||||
|
@ -625,6 +669,7 @@ var tests = [
|
||||||
test_indexOf,
|
test_indexOf,
|
||||||
test_array_forEach,
|
test_array_forEach,
|
||||||
test_isArray,
|
test_isArray,
|
||||||
|
test_array_map,
|
||||||
test_identifier_keywords,
|
test_identifier_keywords,
|
||||||
test_getOwnPropertyDescriptor,
|
test_getOwnPropertyDescriptor,
|
||||||
test_defineProperty,
|
test_defineProperty,
|
||||||
|
|
Loading…
Reference in New Issue