5 Dec
2025
5 Dec
'25
8:23 p.m.
On Fri Dec 5 20:23:44 2025 +0000, Jacek Caban wrote:
The failing test shows that jscript should use the old-style flags when calling external objects with `DISPID_VALUE`. It would be useful to add a similar test for non-`DISPID_VALUE` calls. If those behave the same way as `DISPID_VALUE`, then we’ll need a different solution. Sadly it looks like that's right and we'll need a different solution, unless I messed up something. Here's the (cleaned?) test:
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 1c5f5dd..4e1fa97 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -2455,7 +2455,7 @@ async_test("weakmap_obj", function() {
ok(e.number === 0xa13fd - 0x80000000, "set('test') threw " + e.number);
}
try {
- r = s.set(external.testHostContext(true), 1);
+ r = s.set(external.testHostContext(1), 1);
ok(false, "set(host_obj) did not throw");
}catch(e) {
ok(e.number === 0xa13fd - 0x80000000, "set(host_obj) threw " + e.number);
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 150736d..ac133e6 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -2749,17 +2749,19 @@ sync_test("globals override", function() {
});
sync_test("host this", function() {
- var tests = [ undefined, null, external.nullDisp, function() {}, [0], "foobar", true, 42, new Number(42), external.testHostContext(true), window, document ];
+ var tests = [ undefined, null, external.nullDisp, function() {}, [0], "foobar", true, 42, new Number(42), external.testHostContext(1), window, document ];
var i, obj = Object.create(Function.prototype);
// only pure js objects are passed as 'this' (regardless of prototype)
- [137].forEach(external.testHostContext(true), obj);
- Function.prototype.apply.call(external.testHostContext(true), obj, [137, 0, {}]);
+ [137].forEach(external.testHostContext(1), obj);
+ Function.prototype.apply.call(external.testHostContext(1), obj, [137, 0, {}]);
for(i = 0; i < tests.length; i++) {
- [137].forEach(external.testHostContext(false), tests[i]);
- Function.prototype.apply.call(external.testHostContext(false), tests[i], [137, 0, {}]);
+ [137].forEach(external.testHostContext(0), tests[i]);
+ Function.prototype.apply.call(external.testHostContext(0), tests[i], [137, 0, {}]);
}
+
+ i = external.testHostContext(2).prop(42);
});
sync_test("head_setter", function() {
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c
index 2703ba6..56c2848 100644
--- a/dlls/mshtml/tests/script.c
+++ b/dlls/mshtml/tests/script.c
@@ -160,6 +160,7 @@ DEFINE_EXPECT(GetTypeInfo);
#define DISPID_SCRIPT_TESTPROP2 0x100001
#define DISPID_REFTEST_GET 0x100000
#define DISPID_REFTEST_REF 0x100001
+#define DISPID_TESTHOSTCTX_PROP 0x100000
#define DISPID_EXTERNAL_OK 0x300000
#define DISPID_EXTERNAL_TRACE 0x300001
@@ -971,6 +972,52 @@ static IDispatchExVtbl testHostContextDisp_no_this_vtbl = {
static IDispatchEx testHostContextDisp_no_this = { &testHostContextDisp_no_this_vtbl };
+static HRESULT WINAPI testHostContextDisp_with_prop_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
+{
+ if(!lstrcmpW(bstrName, L"prop")) {
+ *pid = DISPID_TESTHOSTCTX_PROP;
+ return S_OK;
+ }
+
+ ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testHostContextDisp_with_prop_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
+ VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
+{
+ ok(id == DISPID_TESTHOSTCTX_PROP, "id = %ld\n", id);
+ ok(wFlags == (DISPATCH_PROPERTYGET | DISPATCH_METHOD), "wFlags = %x\n", wFlags);
+ ok(pdp != NULL, "pdp == NULL\n");
+ ok(pdp->cArgs == 1, "pdp->cArgs = %d\n", pdp->cArgs);
+ ok(pdp->cNamedArgs == 0, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs);
+ ok(V_VT(&pdp->rgvarg[0]) == VT_I4, "V_VT(rgvarg[0]) = %d\n", V_VT(&pdp->rgvarg[0]));
+ ok(V_I4(&pdp->rgvarg[0]) == 42, "V_I4(rgvarg[0]) = %ld\n", V_I4(&pdp->rgvarg[0]));
+ ok(!pdp->rgdispidNamedArgs, "pdp->rgdispidNamedArgs != NULL\n");
+ ok(pvarRes != NULL, "pvarRes = NULL\n");
+ return S_OK;
+}
+
+static IDispatchExVtbl testHostContextDisp_with_prop_vtbl = {
+ DispatchEx_QueryInterface,
+ DispatchEx_AddRef,
+ DispatchEx_Release,
+ DispatchEx_GetTypeInfoCount,
+ DispatchEx_GetTypeInfo,
+ DispatchEx_GetIDsOfNames,
+ DispatchEx_Invoke,
+ testHostContextDisp_with_prop_GetDispID,
+ testHostContextDisp_with_prop_InvokeEx,
+ DispatchEx_DeleteMemberByName,
+ DispatchEx_DeleteMemberByDispID,
+ DispatchEx_GetMemberProperties,
+ DispatchEx_GetMemberName,
+ DispatchEx_GetNextDispID,
+ DispatchEx_GetNameSpaceParent
+};
+
+static IDispatchEx testHostContextDisp_with_prop = { &testHostContextDisp_with_prop_vtbl };
+
struct refTestObj
{
IDispatchEx IDispatchEx_iface;
@@ -1455,9 +1502,10 @@ static HRESULT WINAPI externalDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID
ok(pei != NULL, "pei == NULL\n");
ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
- ok(V_VT(pdp->rgvarg) == VT_BOOL, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg));
+ ok(V_VT(pdp->rgvarg) == VT_I4, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg));
V_VT(pvarRes) = VT_DISPATCH;
- V_DISPATCH(pvarRes) = (IDispatch*)(V_BOOL(pdp->rgvarg) ? &testHostContextDisp : &testHostContextDisp_no_this);
+ V_DISPATCH(pvarRes) = (IDispatch*)(V_I4(pdp->rgvarg) == 0 ? &testHostContextDisp_no_this :
+ V_I4(pdp->rgvarg) == 1 ? &testHostContextDisp : &testHostContextDisp_with_prop);
return S_OK;
case DISPID_EXTERNAL_GETMIMETYPE:
And it still expects `DISPATCH_PROPERTYGET | DISPATCH_METHOD`. So I guess it will be postponed due to code freeze. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9660#note_125003