From 1dd4cbc49110c1133270004e4a408610c3f6f066 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 21 Jun 2012 10:48:10 +0200 Subject: [PATCH] jscript: Pass jsthis internally without using DISPPARAMS. --- dlls/jscript/array.c | 2 +- dlls/jscript/dispex.c | 135 +++++++++++++++++++++++++++++++--------- dlls/jscript/engine.c | 5 +- dlls/jscript/function.c | 8 +-- dlls/jscript/global.c | 2 +- dlls/jscript/jscript.h | 5 +- dlls/jscript/string.c | 2 +- 7 files changed, 119 insertions(+), 40 deletions(-) diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 91a7b826255..139b04d6388 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -646,7 +646,7 @@ static HRESULT sort_cmp(script_ctx_t *ctx, jsdisp_t *cmp_func, VARIANT *v1, VARI args[0] = *v2; args[1] = *v1; - hres = jsdisp_call_value(cmp_func, DISPATCH_METHOD, &dp, &res, ei); + hres = jsdisp_call_value(cmp_func, NULL, DISPATCH_METHOD, &dp, &res, ei); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 7763512db15..86fcd85ba9e 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -291,7 +291,7 @@ static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, BOOL search_p return hres; } -static HRESULT set_this(DISPPARAMS *dp, DISPPARAMS *olddp, IDispatch *jsthis) +static HRESULT set_this(DISPPARAMS *dp, const DISPPARAMS *olddp, IDispatch *jsthis) { VARIANTARG *oldargs; int i; @@ -333,6 +333,24 @@ static HRESULT set_this(DISPPARAMS *dp, DISPPARAMS *olddp, IDispatch *jsthis) return S_OK; } +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 convert_params(const DISPPARAMS *dp, VARIANT *buf, DISPPARAMS *ret) { BOOL need_conversion = FALSE; @@ -382,7 +400,7 @@ static HRESULT convert_params(const DISPPARAMS *dp, VARIANT *buf, DISPPARAMS *re return S_OK; } -static HRESULT invoke_prop_func(jsdisp_t *This, jsdisp_t *jsthis, dispex_prop_t *prop, WORD flags, +static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t *prop, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { HRESULT hres; @@ -401,15 +419,18 @@ static HRESULT invoke_prop_func(jsdisp_t *This, jsdisp_t *jsthis, dispex_prop_t if(FAILED(hres)) return hres; - if(prop->name || jsthis->builtin_info->class != JSCLASS_FUNCTION) { + if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) { vdisp_t vthis; - set_jsdisp(&vthis, jsthis); + if(jsthis) + set_disp(&vthis, jsthis); + else + set_jsdisp(&vthis, This); hres = prop->u.p->invoke(This->ctx, &vthis, flags, ¶ms, retv, ei); vdisp_release(&vthis); }else { /* Function object calls are special case */ - hres = Function_invoke(This, flags, ¶ms, retv, ei); + hres = Function_invoke(This, jsthis, flags, ¶ms, retv, ei); } if(params.rgvarg != buf && params.rgvarg != dp->rgvarg) heap_free(params.rgvarg); @@ -418,8 +439,6 @@ static HRESULT invoke_prop_func(jsdisp_t *This, jsdisp_t *jsthis, dispex_prop_t case PROP_PROTREF: return invoke_prop_func(This->prototype, jsthis, This->prototype->props+prop->u.ref, flags, dp, retv, ei, caller); case PROP_VARIANT: { - DISPPARAMS new_dp; - if(V_VT(&prop->u.var) != VT_DISPATCH) { FIXME("invoke vt %d\n", V_VT(&prop->u.var)); return E_FAIL; @@ -427,19 +446,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, jsdisp_t *jsthis, dispex_prop_t TRACE("call %s %p\n", debugstr_w(prop->name), V_DISPATCH(&prop->u.var)); - hres = set_this(&new_dp, dp, to_disp(jsthis)); - if(FAILED(hres)) - return hres; - - hres = disp_call(This->ctx, V_DISPATCH(&prop->u.var), DISPID_VALUE, flags, &new_dp, retv, ei); - - if(new_dp.rgvarg != dp->rgvarg) { - heap_free(new_dp.rgvarg); - if(new_dp.cNamedArgs > 1) - heap_free(new_dp.rgdispidNamedArgs); - } - - return hres; + return disp_call_value(This->ctx, V_DISPATCH(&prop->u.var), jsthis, flags, dp, retv, ei); } default: ERR("type %d\n", prop->type); @@ -732,7 +739,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc /* fall through */ case DISPATCH_METHOD: case DISPATCH_CONSTRUCT: - hres = invoke_prop_func(This, This, prop, wFlags, pdp, pvarRes, &jsexcept, pspCaller); + hres = invoke_prop_func(This, get_this(pdp), prop, wFlags, pdp, pvarRes, &jsexcept, pspCaller); break; case DISPATCH_PROPERTYGET: hres = prop_get(This, prop, pdp, pvarRes, &jsexcept, pspCaller); @@ -1055,14 +1062,21 @@ HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID * return DISP_E_UNKNOWNNAME; } -HRESULT jsdisp_call_value(jsdisp_t *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) +HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) { - vdisp_t vdisp; HRESULT hres; - set_jsdisp(&vdisp, jsthis); - hres = jsthis->builtin_info->value_prop.invoke(jsthis->ctx, &vdisp, flags, dp, retv, ei); - vdisp_release(&vdisp); + TRACE("args %p\n", dp->rgvarg); + + if(is_class(jsfunc, JSCLASS_FUNCTION)) { + hres = Function_invoke(jsfunc, jsthis, flags, dp, retv, ei); + }else { + vdisp_t vdisp; + + set_disp(&vdisp, jsthis); + hres = jsfunc->builtin_info->value_prop.invoke(jsfunc->ctx, &vdisp, flags, dp, retv, ei); + vdisp_release(&vdisp); + } return hres; } @@ -1078,7 +1092,7 @@ HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, DISPPARAMS *dp, VARIA if(!prop) return DISP_E_MEMBERNOTFOUND; - return invoke_prop_func(disp, disp, prop, flags, dp, retv, ei, NULL); + return invoke_prop_func(disp, to_disp(disp), prop, flags, dp, retv, ei, NULL); } HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, DISPPARAMS *dp, VARIANT *retv, @@ -1095,7 +1109,7 @@ HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, DISPPARA if(retv) V_VT(retv) = VT_EMPTY; - return invoke_prop_func(disp, disp, prop, flags, dp, retv, ei, NULL); + return invoke_prop_func(disp, to_disp(disp), prop, flags, dp, retv, ei, NULL); } HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) @@ -1146,6 +1160,71 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DIS return S_OK; } +HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei) +{ + DISPPARAMS params; + jsdisp_t *jsdisp; + IDispatchEx *dispex; + HRESULT hres; + + jsdisp = iface_to_jsdisp((IUnknown*)disp); + if(jsdisp) { + if(flags & DISPATCH_PROPERTYPUT) { + FIXME("disp_call(propput) on builtin object\n"); + return E_FAIL; + } + + hres = jsdisp_call_value(jsdisp, jsthis, flags, dp, retv, ei); + jsdisp_release(jsdisp); + return hres; + } + + memset(ei, 0, sizeof(*ei)); + if(retv && arg_cnt(dp)) + flags |= DISPATCH_PROPERTYGET; + + if(jsthis) { + hres = set_this(¶ms, dp, jsthis); + if(FAILED(hres)) + return hres; + }else { + params = *dp; + } + + if(retv) + V_VT(retv) = VT_EMPTY; + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if(SUCCEEDED(hres)) { + hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, ctx->lcid, flags, ¶ms, retv, &ei->ei, + &ctx->jscaller->IServiceProvider_iface); + IDispatchEx_Release(dispex); + }else { + UINT err = 0; + + if(flags == DISPATCH_CONSTRUCT) { + WARN("IDispatch cannot be constructor\n"); + return DISP_E_MEMBERNOTFOUND; + } + + TRACE("using IDispatch\n"); + hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, ctx->lcid, flags, ¶ms, retv, &ei->ei, &err); + } + + if(params.rgvarg != dp->rgvarg) { + heap_free(params.rgvarg); + if(params.cNamedArgs > 1) + heap_free(params.rgdispidNamedArgs); + } + + if(FAILED(hres)) + return hres; + + if(retv) + ensure_retval_type(retv); + return S_OK; +} + HRESULT jsdisp_propput_name(jsdisp_t *obj, const WCHAR *name, VARIANT *val, jsexcept_t *ei) { dispex_prop_t *prop; diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 8117cb5dc19..3b20e6aede4 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -1014,8 +1014,7 @@ static HRESULT interp_new(exec_ctx_t *ctx) return throw_type_error(ctx->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL); jsstack_to_dp(ctx, arg, &dp); - hres = disp_call(ctx->script, V_DISPATCH(constr), DISPID_VALUE, - DISPATCH_CONSTRUCT, &dp, &v, ctx->ei); + hres = disp_call_value(ctx->script, V_DISPATCH(constr), NULL, DISPATCH_CONSTRUCT, &dp, &v, ctx->ei); if(FAILED(hres)) return hres; @@ -1039,7 +1038,7 @@ static HRESULT interp_call(exec_ctx_t *ctx) return throw_type_error(ctx->script, ctx->ei, JS_E_INVALID_PROPERTY, NULL); jsstack_to_dp(ctx, argn, &dp); - hres = disp_call(ctx->script, V_DISPATCH(objv), DISPID_VALUE, DISPATCH_METHOD, &dp, + hres = disp_call_value(ctx->script, V_DISPATCH(objv), NULL, DISPATCH_METHOD, &dp, do_ret ? &v : NULL, ctx->ei); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 964319572f3..5cde865725b 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -307,23 +307,23 @@ static HRESULT function_to_string(FunctionInstance *function, BSTR *ret) return S_OK; } -HRESULT Function_invoke(jsdisp_t *func_this, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) +HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) { FunctionInstance *function; - TRACE("\n"); + TRACE("func %p this %p\n", func_this, jsthis); assert(is_class(func_this, JSCLASS_FUNCTION)); function = (FunctionInstance*)func_this; if(function->value_proc) - return invoke_value_proc(function->dispex.ctx, function, get_this(dp), flags, dp, retv, ei); + return invoke_value_proc(function->dispex.ctx, function, jsthis, flags, dp, retv, ei); if(flags == DISPATCH_CONSTRUCT) return invoke_constructor(function->dispex.ctx, function, dp, retv, ei); assert(flags == DISPATCH_METHOD); - return invoke_source(function->dispex.ctx, function, get_this(dp), dp, retv, ei); + return invoke_source(function->dispex.ctx, function, jsthis, dp, retv, ei); } static HRESULT Function_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index ae43285123d..ce1c5411823 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -117,7 +117,7 @@ static HRESULT constructor_call(jsdisp_t *constr, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei) { if(flags != DISPATCH_PROPERTYGET) - return jsdisp_call_value(constr, flags, dp, retv, ei); + return jsdisp_call_value(constr, NULL, flags, dp, retv, ei); jsdisp_addref(constr); var_set_jsdisp(retv, constr); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index f278b6a10d3..b1366518c2a 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -207,7 +207,8 @@ HRESULT init_dispex(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DEC HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN; HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN; -HRESULT jsdisp_call_value(jsdisp_t*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN; +HRESULT disp_call_value(script_ctx_t*,IDispatch*,IDispatch*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN; +HRESULT jsdisp_call_value(jsdisp_t*,IDispatch*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN; HRESULT jsdisp_call(jsdisp_t*,DISPID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN; HRESULT jsdisp_call_name(jsdisp_t*,const WCHAR*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN; HRESULT disp_propget(script_ctx_t*,IDispatch*,DISPID,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN; @@ -225,7 +226,7 @@ VARIANT_BOOL jsdisp_is_own_prop(jsdisp_t *obj, BSTR name) DECLSPEC_HIDDEN; HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD, jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN; -HRESULT Function_invoke(jsdisp_t*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*); +HRESULT Function_invoke(jsdisp_t*,IDispatch*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*); HRESULT throw_eval_error(script_ctx_t*,jsexcept_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; HRESULT throw_generic_error(script_ctx_t*,jsexcept_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN; diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 2adc6054419..1cc20488d9e 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -728,7 +728,7 @@ static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func, const WCHAR *str, mat } if(SUCCEEDED(hres)) - hres = jsdisp_call_value(func, DISPATCH_METHOD, &dp, &var, ei); + hres = jsdisp_call_value(func, NULL, DISPATCH_METHOD, &dp, &var, ei); for(i=0; i < parens_cnt+3; i++) { if(i != parens_cnt+1)