jscript: Pass jsthis internally without using DISPPARAMS.

This commit is contained in:
Jacek Caban 2012-06-21 10:48:10 +02:00 committed by Alexandre Julliard
parent 17ff7829d3
commit 1dd4cbc491
7 changed files with 119 additions and 40 deletions

View File

@ -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;

View File

@ -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, &params, retv, ei);
vdisp_release(&vthis);
}else {
/* Function object calls are special case */
hres = Function_invoke(This, flags, &params, retv, ei);
hres = Function_invoke(This, jsthis, flags, &params, 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(&params, 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, &params, 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, &params, 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;

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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)