diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index f6684d9d6ee..b86b7513477 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -3741,6 +3741,11 @@ static HRESULT WINAPI DOMMessageEvent_get_data(IDOMMessageEvent *iface, BSTR *p)
TRACE("(%p)->(%p)\n", This, p);
+ if(V_VT(&This->data) == VT_EMPTY) {
+ *p = SysAllocString(L"");
+ return S_OK;
+ }
+
if(V_VT(&This->data) != VT_BSTR) {
FIXME("non-string data\n");
return E_NOTIMPL;
@@ -3792,9 +3797,48 @@ static HRESULT WINAPI DOMMessageEvent_initMessageEvent(IDOMMessageEvent *iface,
BSTR last_event_id, IHTMLWindow2 *source)
{
DOMMessageEvent *This = impl_from_IDOMMessageEvent(iface);
- FIXME("(%p)->(%s %x %x %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
+ BSTR new_origin = NULL;
+ BSTR new_data = NULL;
+ HRESULT hres;
+
+ TRACE("(%p)->(%s %x %x %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
debugstr_w(data), debugstr_w(origin), debugstr_w(last_event_id), source);
- return E_NOTIMPL;
+
+ if(This->event.target) {
+ TRACE("called on already dispatched event\n");
+ return S_OK;
+ }
+
+ if((data && !(new_data = SysAllocString(data))) ||
+ (origin && !(new_origin = SysAllocString(origin)))) {
+ hres = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ hres = IDOMEvent_initEvent(&This->event.IDOMEvent_iface, type, can_bubble, cancelable);
+ if(FAILED(hres))
+ goto fail;
+
+ if(new_data) {
+ VariantClear(&This->data);
+ V_VT(&This->data) = VT_BSTR;
+ V_BSTR(&This->data) = new_data;
+ }
+ if(new_origin) {
+ SysFreeString(This->origin);
+ This->origin = new_origin;
+ }
+ if(This->source)
+ IHTMLWindow2_Release(This->source);
+ This->source = source;
+ if(source)
+ IHTMLWindow2_AddRef(source);
+ return S_OK;
+
+fail:
+ SysFreeString(new_origin);
+ SysFreeString(new_data);
+ return hres;
}
static const IDOMMessageEventVtbl DOMMessageEventVtbl = {
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 94183ad015e..5249e042182 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -2919,6 +2919,32 @@ sync_test("MutationObserver", function() {
test_exposed("takeRecords");
});
+sync_test("initMessageEvent", function() {
+ var e, v = document.documentMode;
+ if(!document.createEvent)
+ return;
+ e = document.createEvent("MessageEvent");
+ ok(e.data === (v < 10 ? "" : undefined), "e.data = " + e.data);
+ ok(e.bubbles === false, "bubbles = " + e.bubbles);
+ ok(e.cancelable === false, "cancelable = " + e.cancelable);
+ ok(e.source === null, "e.source = " + e.source);
+ ok(e.origin === "", "e.origin = " + e.origin);
+
+ e.initMessageEvent("blah", true, true, 137, "wine", 1234, window);
+ ok(e.data === "137", "e.data = " + e.data);
+ ok(e.bubbles === true, "bubbles = " + e.bubbles);
+ ok(e.cancelable === true, "cancelable = " + e.cancelable);
+ ok(e.source === window, "e.source = " + e.source);
+ ok(e.origin === "wine", "e.origin = " + e.origin);
+
+ e.initMessageEvent("abcd", false, false, "testdata", "origin", 42, null);
+ ok(e.data === "testdata", "e.data = " + e.data);
+ ok(e.bubbles === false, "bubbles = " + e.bubbles);
+ ok(e.cancelable === false, "cancelable = " + e.cancelable);
+ ok(e.source === null, "e.source = " + e.source);
+ ok(e.origin === "origin", "e.origin = " + e.origin);
+});
+
async_test("postMessage", function() {
var v = document.documentMode;
var onmessage_called = false;
@@ -2930,6 +2956,9 @@ async_test("postMessage", function() {
ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data);
ok(e.source === window, "e.source = " + e.source);
ok(e.origin === "http://winetest.example.org", "e.origin = " + e.origin);
+
+ e = document.createEvent("MessageEvent");
+ ok(e.data === (v < 10 ? "" : undefined), "created e.data = " + e.data);
next_test();
}
}
diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c
index 0dd622b15c3..9760d6bcb9a 100644
--- a/dlls/mshtml/tests/events.c
+++ b/dlls/mshtml/tests/events.c
@@ -3345,6 +3345,136 @@ static void test_message_event(IHTMLDocument2 *doc)
VariantClear(&v[1]);
IHTMLWindow2_Release(child);
IDispatchEx_Release(dispex);
+
+ if(document_mode >= 9) {
+ IDOMMessageEvent *msg_event = NULL;
+ IDocumentEvent *doc_event;
+ IHTMLWindow2 *source;
+ IDOMEvent *event;
+ UINT argerr;
+
+ hres = IHTMLDocument2_QueryInterface(doc, &IID_IDocumentEvent, (void**)&doc_event);
+ ok(hres == S_OK, "Could not get IDocumentEvent iface: %08lx\n", hres);
+
+ bstr = SysAllocString(L"MessageEvent");
+ hres = IDocumentEvent_createEvent(doc_event, bstr, &event);
+ ok(hres == S_OK, "createEvent failed: %08lx\n", hres);
+ IDocumentEvent_Release(doc_event);
+ SysFreeString(bstr);
+
+ hres = IDOMEvent_QueryInterface(event, &IID_IDOMMessageEvent, (void**)&msg_event);
+ ok(hres == S_OK, "Could not get IDOMMessageEvent iface: %08lx\n", hres);
+ ok(msg_event != NULL, "msg_event = NULL\n");
+ IDOMEvent_Release(event);
+
+ hres = IDOMMessageEvent_get_source(msg_event, &source);
+ ok(hres == S_OK, "get_source failed: %08lx\n", hres);
+ ok(source == NULL, "uninitialized source != NULL\n");
+
+ hres = IDOMMessageEvent_get_origin(msg_event, &bstr);
+ ok(hres == S_OK, "get_origin failed: %08lx\n", hres);
+ ok(!bstr, "uninitialized origin = %s\n", wine_dbgstr_w(bstr));
+
+ /* IE10+ crash when using the get_data from the interface (because it's not a string yet?) */
+ if(document_mode < 10) {
+ hres = IDOMMessageEvent_get_data(msg_event, &bstr);
+ ok(hres == S_OK, "get_data failed: %08lx\n", hres);
+ ok(!wcscmp(bstr, L""), "uninitialized data = %s\n", wine_dbgstr_w(bstr));
+ SysFreeString(bstr);
+
+ bstr = SysAllocString(L"foobar");
+ hres = IDOMMessageEvent_initMessageEvent(msg_event, bstr, VARIANT_FALSE, VARIANT_FALSE, bstr, bstr, NULL, window);
+ ok(hres == S_OK, "initMessageEvent failed: %08lx\n", hres);
+ SysFreeString(bstr);
+
+ hres = IDOMMessageEvent_get_data(msg_event, &bstr);
+ ok(hres == S_OK, "get_data failed: %08lx\n", hres);
+ ok(!wcscmp(bstr, L"foobar"), "data = %s\n", wine_dbgstr_w(bstr));
+ SysFreeString(bstr);
+
+ hres = IDOMMessageEvent_get_source(msg_event, &source);
+ ok(hres == S_OK, "get_source failed: %08lx\n", hres);
+ ok(source == window, "source != window\n");
+ IHTMLWindow2_Release(source);
+
+ hres = IDOMMessageEvent_get_origin(msg_event, &bstr);
+ ok(hres == S_OK, "get_origin failed: %08lx\n", hres);
+ ok(!wcscmp(bstr, L"foobar"), "origin = %s\n", wine_dbgstr_w(bstr));
+ SysFreeString(bstr);
+
+ bstr = SysAllocString(L"barfoo");
+ hres = IDOMMessageEvent_initMessageEvent(msg_event, bstr, VARIANT_FALSE, VARIANT_FALSE, NULL, NULL, NULL, NULL);
+ ok(hres == S_OK, "initMessageEvent failed: %08lx\n", hres);
+ SysFreeString(bstr);
+
+ hres = IDOMMessageEvent_get_data(msg_event, &bstr);
+ ok(hres == S_OK, "get_data failed: %08lx\n", hres);
+ ok(!wcscmp(bstr, L"foobar"), "data = %s\n", wine_dbgstr_w(bstr));
+ SysFreeString(bstr);
+
+ hres = IDOMMessageEvent_get_source(msg_event, &source);
+ ok(hres == S_OK, "get_source failed: %08lx\n", hres);
+ ok(source == NULL, "source != NULL\n");
+
+ hres = IDOMMessageEvent_get_origin(msg_event, &bstr);
+ ok(hres == S_OK, "get_origin failed: %08lx\n", hres);
+ ok(broken(!bstr) /* win10-21h2 */ || !wcscmp(bstr, L"foobar"), "origin = %s\n", wine_dbgstr_w(bstr));
+ SysFreeString(bstr);
+ }else {
+ bstr = SysAllocString(L"data");
+ hres = IDOMMessageEvent_GetIDsOfNames(msg_event, &IID_NULL, &bstr, 1, 0, &dispid);
+ ok(hres == S_OK, "GetIDsOfNames(data) failed: %08lx\n", hres);
+ SysFreeString(bstr);
+
+ dp.cArgs = 0;
+ dp.rgvarg = NULL;
+ hres = IDOMMessageEvent_Invoke(msg_event, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &v[0], NULL, &argerr);
+ ok(hres == S_OK, "Invoke(data) failed: %08lx\n", hres);
+ ok(V_VT(&v[0]) == VT_EMPTY, "V_VT(uninitialized data) = %d\n", V_VT(&v[0]));
+
+ bstr = SysAllocString(L"foobar");
+ hres = IDOMMessageEvent_initMessageEvent(msg_event, bstr, VARIANT_FALSE, VARIANT_FALSE, bstr, bstr, NULL, window);
+ ok(hres == S_OK, "initMessageEvent failed: %08lx\n", hres);
+ SysFreeString(bstr);
+
+ hres = IDOMMessageEvent_Invoke(msg_event, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &v[0], NULL, &argerr);
+ ok(hres == S_OK, "Invoke(data) failed: %08lx\n", hres);
+ ok(V_VT(&v[0]) == VT_BSTR, "V_VT(data) = %d\n", V_VT(&v[0]));
+ ok(!wcscmp(V_BSTR(&v[0]), L"foobar"), "V_BSTR(data) = %s\n", wine_dbgstr_w(V_BSTR(&v[0])));
+ VariantClear(&v[0]);
+
+ hres = IDOMMessageEvent_get_source(msg_event, &source);
+ ok(hres == S_OK, "get_source failed: %08lx\n", hres);
+ ok(source == window, "source != window\n");
+ IHTMLWindow2_Release(source);
+
+ hres = IDOMMessageEvent_get_origin(msg_event, &bstr);
+ ok(hres == S_OK, "get_origin failed: %08lx\n", hres);
+ ok(!wcscmp(bstr, L"foobar"), "origin = %s\n", wine_dbgstr_w(bstr));
+ SysFreeString(bstr);
+
+ bstr = SysAllocString(L"barfoo");
+ hres = IDOMMessageEvent_initMessageEvent(msg_event, bstr, VARIANT_FALSE, VARIANT_FALSE, NULL, NULL, NULL, NULL);
+ ok(hres == S_OK, "initMessageEvent failed: %08lx\n", hres);
+ SysFreeString(bstr);
+
+ hres = IDOMMessageEvent_Invoke(msg_event, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &v[0], NULL, &argerr);
+ ok(hres == S_OK, "Invoke(data) failed: %08lx\n", hres);
+ ok(V_VT(&v[0]) == VT_BSTR, "V_VT(data) = %d\n", V_VT(&v[0]));
+ ok(!wcscmp(V_BSTR(&v[0]), L"foobar"), "V_BSTR(data) = %s\n", wine_dbgstr_w(V_BSTR(&v[0])));
+
+ hres = IDOMMessageEvent_get_source(msg_event, &source);
+ ok(hres == S_OK, "get_source failed: %08lx\n", hres);
+ ok(source == NULL, "source != NULL\n");
+
+ hres = IDOMMessageEvent_get_origin(msg_event, &bstr);
+ ok(hres == S_OK, "get_origin failed: %08lx\n", hres);
+ ok(broken(!bstr) /* win10-21h2 */ || !wcscmp(bstr, L"foobar"), "origin = %s\n", wine_dbgstr_w(bstr));
+ SysFreeString(bstr);
+ }
+
+ IDOMMessageEvent_Release(msg_event);
+ }
}
static void test_visibilitychange(IHTMLDocument2 *doc)
diff --git a/dlls/mshtml/tests/events.js b/dlls/mshtml/tests/events.js
index a130917cfda..9282d48bacc 100644
--- a/dlls/mshtml/tests/events.js
+++ b/dlls/mshtml/tests/events.js
@@ -835,6 +835,7 @@ async_test("message event", function() {
return;
}
listener_called = true;
+ e.initMessageEvent("blah", true, true, "barfoo", "wine", 1234, window);
ok(e.data === "test", "e.data = " + e.data);
ok(e.bubbles === false, "bubbles = " + e.bubbles);
ok(e.cancelable === false, "cancelable = " + e.cancelable);