Puetz Kevin A : jscript: Fix `this` within IDispatchEx::InvokeEx.

Alexandre Julliard julliard at winehq.org
Thu Jul 23 16:36:56 CDT 2020


Module: wine
Branch: master
Commit: b60c4c6ef60c768d8eb823eb830c7bd35028ea6d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b60c4c6ef60c768d8eb823eb830c7bd35028ea6d

Author: Puetz Kevin A <PuetzKevinA at 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 at JohnDeere.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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)




More information about the wine-cvs mailing list