From: Gabriel Ivăncescu gabrielopcode@gmail.com
IE10 and up actually pass cloned data without converting them to strings, using the Structured Clone Algorithm. Implement support for the basic variant types for now.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 46 ++++++++++++++---- dlls/mshtml/htmlevent.h | 2 +- dlls/mshtml/htmlwindow.c | 71 +++++++++++++++++++++++++++- dlls/mshtml/mshtml_private_iface.idl | 2 + dlls/mshtml/tests/documentmode.js | 8 +++- 5 files changed, 117 insertions(+), 12 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 24c107487af..149611174f0 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -2314,7 +2314,7 @@ static void DOMCustomEvent_destroy(DOMEvent *event) typedef struct { DOMEvent event; IDOMMessageEvent IDOMMessageEvent_iface; - WCHAR *data; + VARIANT data; } DOMMessageEvent;
static inline DOMMessageEvent *impl_from_IDOMMessageEvent(IDOMMessageEvent *iface) @@ -2376,7 +2376,26 @@ static HRESULT WINAPI DOMMessageEvent_get_data(IDOMMessageEvent *iface, BSTR *p)
TRACE("(%p)->(%p)\n", This, p);
- return (*p = SysAllocString(This->data)) ? S_OK : E_OUTOFMEMORY; + if(V_VT(&This->data) != VT_BSTR) { + FIXME("non-string data\n"); + return E_NOTIMPL; + } + + return (*p = SysAllocString(V_BSTR(&This->data))) ? S_OK : E_OUTOFMEMORY; +} + +static HRESULT DOMMessageEvent_get_data_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, + EXCEPINFO *ei, IServiceProvider *caller) +{ + DOMMessageEvent *This = CONTAINING_RECORD(dispex, DOMMessageEvent, event.dispex); + + if(!(flags & DISPATCH_PROPERTYGET) || !res) + return S_FALSE; + + TRACE("(%p)->(%p)\n", This, res); + + V_VT(res) = VT_EMPTY; + return VariantCopy(res, &This->data); }
static HRESULT WINAPI DOMMessageEvent_get_origin(IDOMMessageEvent *iface, BSTR *p) @@ -2433,7 +2452,16 @@ static void *DOMMessageEvent_query_interface(DOMEvent *event, REFIID riid) static void DOMMessageEvent_destroy(DOMEvent *event) { DOMMessageEvent *message_event = DOMMessageEvent_from_DOMEvent(event); - heap_free(message_event->data); + VariantClear(&message_event->data); +} + +static void DOMMessageEvent_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode) +{ + static const dispex_hook_t hooks[] = { + {DISPID_IDOMMESSAGEEVENT_DATA, DOMMessageEvent_get_data_hook}, + {DISPID_UNKNOWN} + }; + dispex_info_add_interface(info, IDOMMessageEvent_tid, compat_mode >= COMPAT_MODE_IE10 ? hooks : NULL); }
typedef struct { @@ -2646,7 +2674,6 @@ static dispex_static_data_t DOMCustomEvent_dispex = {
static const tid_t DOMMessageEvent_iface_tids[] = { IDOMEvent_tid, - IDOMMessageEvent_tid, 0 };
@@ -2654,7 +2681,8 @@ dispex_static_data_t DOMMessageEvent_dispex = { L"MessageEvent", NULL, DispDOMMessageEvent_tid, - DOMMessageEvent_iface_tids + DOMMessageEvent_iface_tids, + DOMMessageEvent_init_dispex_info };
static const tid_t DOMProgressEvent_iface_tids[] = { @@ -2878,7 +2906,7 @@ HRESULT create_document_event(HTMLDocumentNode *doc, eventid_t event_id, DOMEven return S_OK; }
-HRESULT create_message_event(HTMLDocumentNode *doc, BSTR data, DOMEvent **ret) +HRESULT create_message_event(HTMLDocumentNode *doc, VARIANT *data, DOMEvent **ret) { DOMMessageEvent *message_event; DOMEvent *event; @@ -2889,9 +2917,11 @@ HRESULT create_message_event(HTMLDocumentNode *doc, BSTR data, DOMEvent **ret) return hres; message_event = DOMMessageEvent_from_DOMEvent(event);
- if(!(message_event->data = heap_strdupW(data))) { + V_VT(&message_event->data) = VT_EMPTY; + hres = VariantCopy(&message_event->data, data); + if(FAILED(hres)) { IDOMEvent_Release(&event->IDOMEvent_iface); - return E_OUTOFMEMORY; + return hres; }
*ret = event; diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h index d0c72d87a5d..ed11e660789 100644 --- a/dlls/mshtml/htmlevent.h +++ b/dlls/mshtml/htmlevent.h @@ -111,7 +111,7 @@ void dispatch_event(EventTarget*,DOMEvent*) DECLSPEC_HIDDEN; HRESULT create_document_event(HTMLDocumentNode*,eventid_t,DOMEvent**) DECLSPEC_HIDDEN; HRESULT create_document_event_str(HTMLDocumentNode*,const WCHAR*,IDOMEvent**) DECLSPEC_HIDDEN; HRESULT create_event_from_nsevent(nsIDOMEvent*,compat_mode_t,DOMEvent**) DECLSPEC_HIDDEN; -HRESULT create_message_event(HTMLDocumentNode*,BSTR,DOMEvent**) DECLSPEC_HIDDEN; +HRESULT create_message_event(HTMLDocumentNode*,VARIANT*,DOMEvent**) DECLSPEC_HIDDEN;
void init_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN; void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 64e6ae25849..8bc30ba395c 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -2218,6 +2218,7 @@ static HRESULT WINAPI HTMLWindow6_postMessage(IHTMLWindow6 *iface, BSTR msg, VAR HTMLWindow *This = impl_from_IHTMLWindow6(iface); DOMEvent *event; HRESULT hres; + VARIANT var;
FIXME("(%p)->(%s %s) semi-stub\n", This, debugstr_w(msg), debugstr_variant(&targetOrigin));
@@ -2226,7 +2227,9 @@ static HRESULT WINAPI HTMLWindow6_postMessage(IHTMLWindow6 *iface, BSTR msg, VAR return E_FAIL; }
- hres = create_message_event(This->inner_window->doc, msg, &event); + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = msg; + hres = create_message_event(This->inner_window->doc, &var, &event); if(FAILED(hres)) return hres;
@@ -3175,6 +3178,71 @@ static HRESULT WINAPI window_private_matchMedia(IWineHTMLWindowPrivate *iface, B return create_media_query_list(This, media_query, media_query_list); }
+static HRESULT WINAPI window_private_postMessage(IWineHTMLWindowPrivate *iface, VARIANT msg, BSTR targetOrigin, VARIANT transfer) +{ + HTMLWindow *This = impl_from_IWineHTMLWindowPrivateVtbl(iface); + HTMLInnerWindow *window = This->inner_window; + struct post_message_task *task; + DOMEvent *event; + HRESULT hres; + + TRACE("iface %p, msg %s, targetOrigin %s, transfer %s\n", iface, debugstr_variant(&msg), + debugstr_w(targetOrigin), debugstr_variant(&transfer)); + + if(V_VT(&transfer) != VT_EMPTY) + FIXME("transfer not implemented, ignoring\n"); + + switch(V_VT(&msg)) { + case VT_EMPTY: + case VT_NULL: + case VT_VOID: + case VT_I1: + case VT_I2: + case VT_I4: + case VT_I8: + case VT_UI1: + case VT_UI2: + case VT_UI4: + case VT_UI8: + case VT_INT: + case VT_UINT: + case VT_R4: + case VT_R8: + case VT_BOOL: + case VT_BSTR: + case VT_CY: + case VT_DATE: + case VT_DECIMAL: + case VT_HRESULT: + break; + case VT_ERROR: + V_VT(&msg) = VT_EMPTY; + break; + default: + FIXME("Unsupported vt %d\n", V_VT(&msg)); + return E_NOTIMPL; + } + + if(!window->doc) { + FIXME("No document\n"); + return E_FAIL; + } + + hres = create_message_event(window->doc, &msg, &event); + if(FAILED(hres)) + return hres; + + if(!(task = heap_alloc(sizeof(*task)))) { + IDOMEvent_Release(&event->IDOMEvent_iface); + return E_OUTOFMEMORY; + } + + task->event = event; + task->window = window; + IHTMLWindow2_AddRef(&task->window->base.IHTMLWindow2_iface); + return push_task(&task->header, post_message_proc, post_message_destr, window->task_magic); +} + static HRESULT WINAPI window_private_get_console(IWineHTMLWindowPrivate *iface, IDispatch **console) { HTMLWindow *This = impl_from_IWineHTMLWindowPrivateVtbl(iface); @@ -3202,6 +3270,7 @@ static const IWineHTMLWindowPrivateVtbl WineHTMLWindowPrivateVtbl = { window_private_cancelAnimationFrame, window_private_get_console, window_private_matchMedia, + window_private_postMessage, };
static inline HTMLWindow *impl_from_IWineHTMLWindowCompatPrivateVtbl(IWineHTMLWindowCompatPrivate *iface) diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl index a17960e493b..fc023473cc9 100644 --- a/dlls/mshtml/mshtml_private_iface.idl +++ b/dlls/mshtml/mshtml_private_iface.idl @@ -112,6 +112,8 @@ interface IWineHTMLWindowPrivate : IDispatch HRESULT console([retval, out] IDispatch **console); [id(53)] HRESULT matchMedia([in] BSTR media_query, [retval, out] IDispatch **media_query_list); + [id(54)] + HRESULT postMessage([in] VARIANT msg, [in] BSTR targetOrigin, [in, optional] VARIANT transfer); }
[ diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 76fa6bacac8..0ec4785450e 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -2078,10 +2078,14 @@ sync_test("__defineSetter__", function() { async_test("postMessage", function() { var v = document.documentMode; var onmessage_called = false; - window.onmessage = function() { + window.onmessage = function(e) { onmessage_called = true; + if(v < 9) + ok(e === undefined, "e = " + e); + else + ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data); next_test(); } - window.postMessage("test", "*"); + window.postMessage(10, "*"); ok(onmessage_called == (v < 9 ? true : false), "onmessage not called"); });