Module: wine Branch: master Commit: b60c4c6ef60c768d8eb823eb830c7bd35028ea6d URL: https://source.winehq.org/git/wine.git/?a=commit;h=b60c4c6ef60c768d8eb823eb8...
Author: Puetz Kevin A PuetzKevinA@JohnDeere.com Date: Thu Jul 23 22:25:38 2020 +0200
jscript: Fix `this` within IDispatchEx::InvokeEx.
Latent bug revealed by 614ea7e6243ead003bcfe4624895154972f3445f; Now that cross-context calls go through disp_call* instead of jsdisp_call*, and thus through InvokeEx, the `this` pointer is lost when calling methods inherited from a prototype.
Signed-off-by: Kevin Puetz PuetzKevinA@JohnDeere.com Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/jscript/dispex.c | 8 +++-- dlls/jscript/tests/run.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 4 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 2ba706252b..f49d5da971 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -419,8 +419,8 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t return hres; } case PROP_PROTREF: - return invoke_prop_func(This->prototype, jsthis, This->prototype->props+prop->u.ref, - flags, argc, argv, r, caller); + return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, + This->prototype->props+prop->u.ref, flags, argc, argv, r, caller); case PROP_JSVAL: { if(!is_object_instance(prop->u.val)) { FIXME("invoke %s\n", debugstr_jsval(prop->u.val)); @@ -429,7 +429,9 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val));
- return disp_call_value(This->ctx, get_object(prop->u.val), jsthis, flags, argc, argv, r); + return disp_call_value(This->ctx, get_object(prop->u.val), + jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface, + flags, argc, argv, r); } case PROP_ACCESSOR: FIXME("accessor\n"); diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index 675bd819ee..7cd0755497 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -2784,7 +2784,7 @@ static void test_invokeex(void) DISPPARAMS dp = {NULL}; IActiveScript *script; IDispatchEx *dispex; - VARIANT v; + VARIANT v, arg; BSTR str; HRESULT hres;
@@ -2834,6 +2834,93 @@ static void test_invokeex(void)
IDispatchEx_Release(dispex); IActiveScript_Release(script); + + /* test InvokeEx following prototype chain of builtin object (PROP_PROTREF) */ + hres = parse_script_expr(L"o = new Array(); o.push("foo"); o", &v, &script); + ok(hres == S_OK, "parse_script_expr failed: %08x\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v)); + + hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + VariantClear(&v); + + str = SysAllocString(L"push"); + hres = IDispatchEx_GetDispID(dispex, str, 0, &func_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + + dp.rgvarg = &arg; + dp.cArgs = 1; + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = SysAllocString(L"bar"); + + hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + SysFreeString(V_BSTR(&arg)); + + str = SysAllocString(L"join"); + hres = IDispatchEx_GetDispID(dispex, str, 0, &func_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + + V_BSTR(&arg) = SysAllocString(L";"); + hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + SysFreeString(V_BSTR(&arg)); + ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v)); + ok(!lstrcmpW(V_BSTR(&v), L"foo;bar"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v))); + + VariantClear(&v); + + dp.rgvarg = NULL; + dp.cArgs = 0; + + IDispatchEx_Release(dispex); + IActiveScript_Release(script); + + /* test InvokeEx following prototype chain of JScript objects (PROP_JSVAL) */ + hres = parse_script_expr(L"function c() { this.func = function() { return this.prop1 * this.prop2 };" + L"this.prop1 = 6; this.prop2 = 9; }; var o = new c(); o.prop2 = 7; o", + &v, &script); + ok(hres == S_OK, "parse_script_expr failed: %08x\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v)); + + hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + VariantClear(&v); + + str = SysAllocString(L"prop1"); + hres = IDispatchEx_GetDispID(dispex, str, 0, &prop_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + + hres = IDispatchEx_InvokeEx(dispex, prop_id, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 6, "V_I4(v) = %d\n", V_I4(&v)); + + str = SysAllocString(L"prop2"); + hres = IDispatchEx_GetDispID(dispex, str, 0, &prop_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + + hres = IDispatchEx_InvokeEx(dispex, prop_id, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 7, "V_I4(v) = %d\n", V_I4(&v)); + + str = SysAllocString(L"func"); + hres = IDispatchEx_GetDispID(dispex, str, 0, &func_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + + hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 42, "V_I4(v) = %s\n", wine_dbgstr_variant(&v)); + + IDispatchEx_Release(dispex); + IActiveScript_Release(script); }
static void test_eval(void)