From 176ba8cf95013f414ecdec6c510df6fdf24cbdb5 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 11 Sep 2009 18:46:42 +0200 Subject: [PATCH] jscript: Added Array.splice implementation. --- dlls/jscript/array.c | 114 +++++++++++++++++++++++++++++++++++++- dlls/jscript/tests/api.js | 72 ++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 3 deletions(-) diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index abef9dfaa6..f7239313bf 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -750,11 +750,118 @@ static HRESULT Array_sort(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS return S_OK; } +/* ECMA-262 3rd Edition 15.4.4.12 */ static HRESULT Array_splice(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, - VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) + VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { - FIXME("\n"); - return E_NOTIMPL; + DWORD length, start=0, delete_cnt=0, argc, i, add_args = 0; + DispatchEx *ret_array = NULL; + VARIANT v; + HRESULT hres = S_OK; + + TRACE("\n"); + + if(is_class(dispex, JSCLASS_ARRAY)) { + length = ((ArrayInstance*)dispex)->length; + }else { + hres = get_jsdisp_length(dispex, lcid, ei, &length); + if(FAILED(hres)) + return hres; + } + + argc = arg_cnt(dp); + if(argc >= 1) { + hres = to_integer(dispex->ctx, get_arg(dp,0), ei, &v); + if(FAILED(hres)) + return hres; + + if(V_VT(&v) == VT_I4) { + if(V_I4(&v) >= 0) + start = min(V_I4(&v), length); + else + start = -V_I4(&v) > length ? 0 : length + V_I4(&v); + }else { + start = V_R8(&v) < 0.0 ? 0 : length; + } + } + + if(argc >= 2) { + hres = to_integer(dispex->ctx, get_arg(dp,1), ei, &v); + if(FAILED(hres)) + return hres; + + if(V_VT(&v) == VT_I4) { + if(V_I4(&v) > 0) + delete_cnt = min(V_I4(&v), length-start); + }else if(V_R8(&v) > 0.0) { + delete_cnt = length-start; + } + + add_args = argc-2; + } + + if(retv) { + hres = create_array(dispex->ctx, 0, &ret_array); + if(FAILED(hres)) + return hres; + + for(i=0; SUCCEEDED(hres) && i < delete_cnt; i++) { + hres = jsdisp_propget_idx(dispex, start+i, lcid, &v, ei, caller); + if(hres == DISP_E_UNKNOWNNAME) + hres = S_OK; + else if(SUCCEEDED(hres)) + hres = jsdisp_propput_idx(ret_array, i, lcid, &v, ei, caller); + } + + if(SUCCEEDED(hres)) { + V_VT(&v) = VT_I4; + V_I4(&v) = delete_cnt; + + hres = jsdisp_propput_name(ret_array, lengthW, lcid, &v, ei, caller); + } + } + + if(add_args < delete_cnt) { + for(i = start; SUCCEEDED(hres) && i < length-delete_cnt; i++) { + hres = jsdisp_propget_idx(dispex, i+delete_cnt, lcid, &v, ei, caller); + if(hres == DISP_E_UNKNOWNNAME) + hres = jsdisp_delete_idx(dispex, i+add_args); + else if(SUCCEEDED(hres)) + hres = jsdisp_propput_idx(dispex, i+add_args, lcid, &v, ei, caller); + } + + for(i=length; SUCCEEDED(hres) && i != length-delete_cnt+add_args; i--) + hres = jsdisp_delete_idx(dispex, i-1); + }else if(add_args > delete_cnt) { + for(i=length-delete_cnt; SUCCEEDED(hres) && i != start; i--) { + hres = jsdisp_propget_idx(dispex, i+delete_cnt-1, lcid, &v, ei, caller); + if(hres == DISP_E_UNKNOWNNAME) + hres = jsdisp_delete_idx(dispex, i+add_args-1); + else if(SUCCEEDED(hres)) + hres = jsdisp_propput_idx(dispex, i+add_args-1, lcid, &v, ei, caller); + } + } + + for(i=0; SUCCEEDED(hres) && i < add_args; i++) + hres = jsdisp_propput_idx(dispex, start+i, lcid, get_arg(dp,i+2), ei, caller); + + if(SUCCEEDED(hres)) { + V_VT(&v) = VT_I4; + V_I4(&v) = length-delete_cnt+add_args; + hres = jsdisp_propput_name(dispex, lengthW, lcid, &v, ei, caller); + } + + if(FAILED(hres)) { + if(ret_array) + jsdisp_release(ret_array); + return hres; + } + + if(retv) { + V_VT(retv) = VT_DISPATCH; + V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret_array); + } + return S_OK; } /* ECMA-262 3rd Edition 15.4.4.2 */ @@ -778,6 +885,7 @@ static HRESULT Array_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, D return E_NOTIMPL; } +/* ECMA-262 3rd Edition 15.4.4.13 */ static HRESULT Array_unshift(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index 42d0683ce8..5ece7d51ce 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -668,6 +668,78 @@ arr[12] = 2; ok(arr.slice(5).toString() === "a,,,,,,,2", "arr.slice(5).toString() = " + arr.slice(5).toString()); ok(arr.slice(5).length === 8, "arr.slice(5).length = " + arr.slice(5).length); +arr = [1,2,3,4,5]; +tmp = arr.splice(2,2); +ok(tmp.toString() == "3,4", "arr.splice(2,2) returned " + tmp.toString()); +ok(arr.toString() == "1,2,5", "arr.splice(2,2) is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(2,2,"a"); +ok(tmp.toString() == "3,4", "arr.splice(2,2,'a') returned " + tmp.toString()); +ok(arr.toString() == "1,2,a,5", "arr.splice(2,2,'a') is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(2,2,'a','b','c'); +ok(tmp.toString() == "3,4", "arr.splice(2,2,'a','b','c') returned " + tmp.toString()); +ok(arr.toString() == "1,2,a,b,c,5", "arr.splice(2,2,'a','b','c') is " + arr.toString()); + +arr = [1,2,3,4,]; +tmp = arr.splice(2,2,'a','b','c'); +ok(tmp.toString() == "3,4", "arr.splice(2,2,'a','b','c') returned " + tmp.toString()); +ok(arr.toString() == "1,2,a,b,c,", "arr.splice(2,2,'a','b','c') is " + arr.toString()); + +arr = [1,2,3,4,]; +arr.splice(2,2,'a','b','c'); +ok(arr.toString() == "1,2,a,b,c,", "arr.splice(2,2,'a','b','c') is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(2,2,'a','b'); +ok(tmp.toString() == "3,4", "arr.splice(2,2,'a','b') returned " + tmp.toString()); +ok(arr.toString() == "1,2,a,b,5", "arr.splice(2,2,'a','b') is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(-1,2); +ok(tmp.toString() == "5", "arr.splice(-1,2) returned " + tmp.toString()); +ok(arr.toString() == "1,2,3,4", "arr.splice(-1,2) is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(-10,3); +ok(tmp.toString() == "1,2,3", "arr.splice(-10,3) returned " + tmp.toString()); +ok(arr.toString() == "4,5", "arr.splice(-10,3) is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(-10,100); +ok(tmp.toString() == "1,2,3,4,5", "arr.splice(-10,100) returned " + tmp.toString()); +ok(arr.toString() == "", "arr.splice(-10,100) is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(2,-1); +ok(tmp.toString() == "", "arr.splice(2,-1) returned " + tmp.toString()); +ok(arr.toString() == "1,2,3,4,5", "arr.splice(2,-1) is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(2); +ok(tmp.toString() == "", "arr.splice(2,-1) returned " + tmp.toString()); +ok(arr.toString() == "1,2,3,4,5", "arr.splice(2,-1) is " + arr.toString()); + +arr = [1,2,3,4,5]; +tmp = arr.splice(); +ok(tmp.toString() == "", "arr.splice(2,-1) returned " + tmp.toString()); +ok(arr.toString() == "1,2,3,4,5", "arr.splice(2,-1) is " + arr.toString()); + +obj = new Object(); +obj.length = 3; +obj[0] = 1; +obj[1] = 2; +obj[2] = 3; +tmp = Array.prototype.splice.call(obj, 1, 1, 'a', 'b'); +ok(tmp.toString() === "2", "obj.splice returned " + tmp); +ok(obj.length === 4, "obj.length = " + obj.length); +ok(obj[0] === 1, "obj[0] = " + obj[0]); +ok(obj[1] === 'a', "obj[1] = " + obj[1]); +ok(obj[2] === 'b', "obj[2] = " + obj[2]); +ok(obj[3] === 3, "obj[3] = " + obj[3]); + obj = new Object(); obj.length = 3; obj[0] = 1; -- 2.32.0.93.g670b81a890