Jacek Caban : jscript: Added Function.apply implementation.
Alexandre Julliard
julliard at winehq.org
Sat Aug 29 11:36:00 CDT 2009
Module: wine
Branch: master
Commit: 5c819cb21bf947d40b9804a50431f135aa21f828
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5c819cb21bf947d40b9804a50431f135aa21f828
Author: Jacek Caban <jacek at 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");
More information about the wine-cvs
mailing list