Jacek Caban : jscript: Added Function.[[call]] implementation.

Alexandre Julliard julliard at winehq.org
Thu Sep 11 08:00:44 CDT 2008


Module: wine
Branch: master
Commit: dd9f8f7dbc7a9010a610dee25567cee384d57cfd
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=dd9f8f7dbc7a9010a610dee25567cee384d57cfd

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Sep 10 21:06:09 2008 +0200

jscript: Added Function.[[call]] implementation.

---

 dlls/jscript/engine.c      |   24 +++++++++
 dlls/jscript/function.c    |  121 ++++++++++++++++++++++++++++++++++++++++++-
 dlls/jscript/tests/lang.js |    2 +
 3 files changed, 144 insertions(+), 3 deletions(-)

diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index fa15b40..275943a 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -120,6 +120,30 @@ static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
         IDispatch_AddRef(disp);
 }
 
+HRESULT scope_push(scope_chain_t *scope, DispatchEx *obj, scope_chain_t **ret)
+{
+    scope_chain_t *new_scope;
+
+    new_scope = heap_alloc(sizeof(scope_chain_t));
+    if(!new_scope)
+        return E_OUTOFMEMORY;
+
+    new_scope->ref = 1;
+
+    IDispatchEx_AddRef(_IDispatchEx_(obj));
+    new_scope->obj = obj;
+
+    if(scope) {
+        scope_addref(scope);
+        new_scope->next = scope;
+    }else {
+        new_scope->next = NULL;
+    }
+
+    *ret = new_scope;
+    return S_OK;
+}
+
 void scope_release(scope_chain_t *scope)
 {
     if(--scope->ref)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index a9c61e0..3cd63f5 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -46,6 +46,99 @@ static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p',
 static const WCHAR propertyIsEnumerableW[] = {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
 
+static IDispatch *get_this(DISPPARAMS *dp)
+{
+    DWORD i;
+
+    for(i=0; i < dp->cNamedArgs; i++) {
+        if(dp->rgdispidNamedArgs[i] == DISPID_THIS) {
+            if(V_VT(dp->rgvarg+i) == VT_DISPATCH)
+                return V_DISPATCH(dp->rgvarg+i);
+
+            WARN("This is not VT_DISPATCH\n");
+            return NULL;
+        }
+    }
+
+    TRACE("no this passed\n");
+    return NULL;
+}
+
+static HRESULT create_var_disp(FunctionInstance *function, LCID lcid, DISPPARAMS *dp, jsexcept_t *ei,
+                               IServiceProvider *caller, DispatchEx **ret)
+{
+    DispatchEx *var_disp;
+    HRESULT hres;
+
+    hres = create_dispex(function->dispex.ctx, NULL, NULL, &var_disp);
+    if(FAILED(hres))
+        return hres;
+
+    *ret = var_disp;
+    return S_OK;
+}
+
+static HRESULT invoke_source(FunctionInstance *function, IDispatch *this_obj, LCID lcid, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    DispatchEx *var_disp;
+    exec_ctx_t *exec_ctx;
+    scope_chain_t *scope;
+    HRESULT hres;
+
+    if(!function->source) {
+        FIXME("no source\n");
+        return E_FAIL;
+    }
+
+    hres = create_var_disp(function, lcid, dp, ei, caller, &var_disp);
+    if(FAILED(hres))
+        return hres;
+
+    hres = scope_push(function->scope_chain, var_disp, &scope);
+    if(SUCCEEDED(hres)) {
+        hres = create_exec_ctx(this_obj, var_disp, scope, &exec_ctx);
+        scope_release(scope);
+    }
+    if(FAILED(hres))
+        return hres;
+
+    hres = exec_source(exec_ctx, function->parser, function->source, ei, retv);
+    exec_release(exec_ctx);
+
+    return hres;
+}
+
+static HRESULT invoke_function(FunctionInstance *function, LCID lcid, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    IDispatch *this_obj;
+
+    if(!(this_obj = get_this(dp)))
+        this_obj = (IDispatch*)_IDispatchEx_(function->dispex.ctx->script_disp);
+
+    return invoke_source(function, this_obj, lcid, dp, retv, ei, caller);
+}
+
+static HRESULT invoke_value_proc(FunctionInstance *function, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+    DispatchEx *this_obj = NULL;
+    IDispatch *this_disp;
+    HRESULT hres;
+
+    this_disp = get_this(dp);
+    if(this_disp)
+        this_obj = iface_to_jsdisp((IUnknown*)this_disp);
+
+    hres = function->value_proc(this_obj ? this_obj : function->dispex.ctx->script_disp, lcid,
+                                flags, dp, retv, ei, caller);
+
+    if(this_obj)
+        jsdisp_release(this_obj);
+    return hres;
+}
+
 static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
 {
@@ -123,10 +216,32 @@ static HRESULT Function_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags,
 }
 
 static HRESULT Function_value(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;
+
+    TRACE("\n");
+
+    if(dispex->builtin_info->class != JSCLASS_FUNCTION) {
+        ERR("dispex is not a function\n");
+        return E_FAIL;
+    }
+
+    function = (FunctionInstance*)dispex;
+
+    switch(flags) {
+    case DISPATCH_METHOD:
+        if(function->value_proc)
+            return invoke_value_proc(function, lcid, flags, dp, retv, ei, caller);
+
+        return invoke_function(function, lcid, dp, retv, ei, caller);
+
+    default:
+        FIXME("not implemented flags %x\n", flags);
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
 }
 
 static void Function_destructor(DispatchEx *dispex)
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index 4c26c2f..b21a9e8 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -70,4 +70,6 @@ ok(typeof(String) === "function", "typeof(String) is not function");
 ok(typeof(ScriptEngine) === "function", "typeof(ScriptEngine) is not function");
 ok(typeof(this) === "object", "typeof(this) is not object");
 
+ok(testFunc1(true, "test") === true, "testFunc1 not returned true");
+
 reportSuccess();




More information about the wine-cvs mailing list