Module: wine Branch: master Commit: 5c819cb21bf947d40b9804a50431f135aa21f828 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5c819cb21bf947d40b9804a504...
Author: Jacek Caban jacek@codeweavers.com Date: Sat Aug 29 00:02:49 2009 +0200
jscript: Added Function.apply implementation.
---
dlls/jscript/function.c | 89 +++++++++++++++++++++++++++++++++++++++++++-- dlls/jscript/tests/api.js | 7 ++++ 2 files changed, 93 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 3ba4481..e8bfe75 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -346,11 +346,94 @@ static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISP return S_OK; }
+static HRESULT array_to_args(DispatchEx *arg_array, LCID lcid, jsexcept_t *ei, IServiceProvider *caller, + DISPPARAMS *args) +{ + VARIANT var, *argv; + DWORD length, i; + HRESULT hres; + + hres = jsdisp_propget_name(arg_array, lengthW, lcid, &var, ei, NULL/*FIXME*/); + if(FAILED(hres)) + return hres; + + hres = to_uint32(arg_array->ctx, &var, ei, &length); + VariantClear(&var); + if(FAILED(hres)) + return hres; + + argv = heap_alloc(length * sizeof(VARIANT)); + if(FAILED(hres)) + return E_OUTOFMEMORY; + + for(i=0; i<length; i++) { + hres = jsdisp_propget_idx(arg_array, i, lcid, argv+i, ei, caller); + if(FAILED(hres)) { + while(i--) + VariantClear(argv+i); + heap_free(argv); + return hres; + } + } + + args->cArgs = length; + args->rgvarg = argv; + return S_OK; +} + static HRESULT Function_apply(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; + FunctionInstance *function; + DISPPARAMS args = {NULL,NULL,0,0}; + DWORD argc, i; + IDispatch *this_obj; + HRESULT hres = S_OK; + + TRACE("\n"); + + if(!is_class(dispex, JSCLASS_FUNCTION)) { + FIXME("dispex is not a function\n"); + return E_FAIL; + } + + function = (FunctionInstance*)dispex; + argc = arg_cnt(dp); + + if(argc) { + hres = to_object(dispex->ctx, get_arg(dp,0), &this_obj); + if(FAILED(hres)) + return hres; + } + + if(argc >= 2) { + DispatchEx *arg_array = NULL; + + if(V_VT(get_arg(dp,1)) == VT_DISPATCH) { + arg_array = iface_to_jsdisp((IUnknown*)V_DISPATCH(get_arg(dp,1))); + if(!is_class(arg_array, JSCLASS_ARRAY) && !is_class(arg_array, JSCLASS_ARGUMENTS)) { + jsdisp_release(arg_array); + arg_array = NULL; + } + } + + if(arg_array) { + hres = array_to_args(arg_array, lcid, ei, caller, &args); + jsdisp_release(arg_array); + }else { + FIXME("throw TypeError"); + hres = E_FAIL; + } + } + + hres = call_function(function, this_obj, lcid, &args, retv, ei, caller); + + if(this_obj) + IDispatch_Release(this_obj); + for(i=0; i<args.cArgs; i++) + VariantClear(args.rgvarg+i); + heap_free(args.rgvarg); + return hres; }
static HRESULT Function_call(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index 06df0ae..75074a1 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -1137,12 +1137,19 @@ function callTest(argc) { callTest.call(tmp, 1, 1); callTest.call(tmp, 2, 1, 2);
+callTest.apply(tmp, [1, 1]); +callTest.apply(tmp, [2, 1, 2]); +(function () { callTest.apply(tmp, arguments); })(2,1,2); + function callTest2() { ok(this === tmp, "this !== tmp\n"); ok(arguments.length === 0, "callTest2: arguments.length = " + arguments.length + " expected 0"); }
callTest2.call(tmp); +callTest2.apply(tmp, []); +callTest2.apply(tmp); +(function () { callTest2.apply(tmp, arguments); })();
function callTest3() { ok(arguments.length === 0, "arguments.length = " + arguments.length + " expected 0");