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