diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 11ae558429b..4dd59be79df 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -69,11 +69,90 @@ static HRESULT Array_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAM return S_OK; } -static HRESULT Array_concat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +static HRESULT concat_array(DispatchEx *array, ArrayInstance *obj, DWORD *len, LCID lcid, + jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + VARIANT var; + DWORD i; + HRESULT hres; + + for(i=0; i < obj->length; i++) { + hres = jsdisp_propget_idx(&obj->dispex, i, lcid, &var, ei, caller); + if(hres == DISP_E_UNKNOWNNAME) + continue; + if(FAILED(hres)) + return hres; + + hres = jsdisp_propput_idx(array, *len+i, lcid, &var, ei, caller); + VariantClear(&var); + if(FAILED(hres)) + return hres; + } + + *len += obj->length; + return S_OK; +} + +static HRESULT concat_obj(DispatchEx *array, IDispatch *obj, DWORD *len, LCID lcid, jsexcept_t *ei, IServiceProvider *caller) +{ + DispatchEx *jsobj; + VARIANT var; + HRESULT hres; + + jsobj = iface_to_jsdisp((IUnknown*)obj); + if(jsobj) { + if(is_class(jsobj, JSCLASS_ARRAY)) { + hres = concat_array(array, (ArrayInstance*)jsobj, len, lcid, ei, caller); + jsdisp_release(jsobj); + return hres; + } + jsdisp_release(jsobj); + } + + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = obj; + return jsdisp_propput_idx(array, (*len)++, lcid, &var, ei, caller); +} + +static HRESULT Array_concat(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) +{ + DispatchEx *ret; + DWORD len = 0; + HRESULT hres; + + TRACE("\n"); + + hres = create_array(dispex->ctx, 0, &ret); + if(FAILED(hres)) + return hres; + + hres = concat_obj(ret, (IDispatch*)_IDispatchEx_(dispex), &len, lcid, ei, caller); + if(SUCCEEDED(hres)) { + VARIANT *arg; + DWORD i; + + for(i=0; i < arg_cnt(dp); i++) { + arg = get_arg(dp, i); + if(V_VT(arg) == VT_DISPATCH) + hres = concat_obj(ret, V_DISPATCH(arg), &len, lcid, ei, caller); + else + hres = jsdisp_propput_idx(ret, len++, lcid, arg, ei, caller); + if(FAILED(hres)) + break; + } + } + + if(FAILED(hres)) + return hres; + + if(retv) { + V_VT(retv) = VT_DISPATCH; + V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret); + }else { + jsdisp_release(ret); + } + return S_OK; } static HRESULT array_join(DispatchEx *array, LCID lcid, DWORD length, const WCHAR *sep, VARIANT *retv, diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index 9fa392ee155..0dfa1780e21 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -104,6 +104,23 @@ ok(arr.sort() === arr, "arr.sort() !== arr"); for(var i=0; i < arr.length; i++) ok(arr[i] === tmp[i], "arr[" + i + "] = " + arr[i] + " expected " + tmp[i]); +var num = new Number(6); +arr = [0,1,2]; +tmp = arr.concat(3, [4,5], num); +ok(tmp !== arr, "tmp === arr"); +for(var i=0; i<6; i++) + ok(tmp[i] === i, "tmp[" + i + "] = " + tmp[i]); +ok(tmp[6] === num, "tmp[6] !== num"); +ok(tmp.length === 7, "tmp.length = " + tmp.length); + +arr = [].concat(); +ok(arr.length === 0, "arr.length = " + arr.lrngth); + +arr = [1,]; +tmp = arr.concat([2]); +ok(tmp.length === 3, "tmp.length = " + tmp.length); +ok(tmp[1] === undefined, "tmp[1] = " + tmp[1]); + var num = new Number(2); ok(num.toString() === "2", "num(2).toString !== 2"); var num = new Number();