Module: wine Branch: master Commit: dd9f8f7dbc7a9010a610dee25567cee384d57cfd URL: http://source.winehq.org/git/wine.git/?a=commit;h=dd9f8f7dbc7a9010a610dee255...
Author: Jacek Caban jacek@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();