jscript: Pass jsthis internally without using DISPPARAMS.
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c
index 91a7b82..139b04d 100644
--- a/dlls/jscript/array.c
+++ b/dlls/jscript/array.c
@@ -646,7 +646,7 @@
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 7763512..86fcd85 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -291,7 +291,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 8117cb5..3b20e6a 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -1014,8 +1014,7 @@
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 @@
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 9643195..5cde8657 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -307,23 +307,23 @@
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 ae43285..ce1c541 100644
--- a/dlls/jscript/global.c
+++ b/dlls/jscript/global.c
@@ -117,7 +117,7 @@
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 f278b6a..b136651 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -207,7 +207,8 @@
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 @@
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 2adc605..1cc2048 100644
--- a/dlls/jscript/string.c
+++ b/dlls/jscript/string.c
@@ -728,7 +728,7 @@
}
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)