From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 68 ++++++++++++++++--------------- dlls/mshtml/htmldoc.c | 8 +++- dlls/mshtml/htmlwindow.c | 3 +- dlls/mshtml/mshtml_private.h | 7 ++-- dlls/mshtml/tests/documentmode.js | 10 +++-- dlls/mshtml/tests/events.c | 1 - 6 files changed, 56 insertions(+), 41 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 823b7283d7a..77eec049912 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1861,34 +1861,6 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) } }
-HRESULT dispex_to_string(DispatchEx *dispex, BSTR *ret) -{ - static const WCHAR prefix[8] = L"[object "; - static const WCHAR suffix[] = L"]"; - WCHAR buf[ARRAY_SIZE(prefix) + ARRAY_SIZE(dispex->info->desc->prototype_name) + ARRAY_SIZE(suffix)], *p = buf; - compat_mode_t compat_mode = dispex_compat_mode(dispex); - const char *name = dispex->info->name; - - if(!ret) - return E_INVALIDARG; - - memcpy(p, prefix, sizeof(prefix)); - p += ARRAY_SIZE(prefix); - if(compat_mode < COMPAT_MODE_IE9) - p--; - else { - if(dispex->info->vtbl->get_name) - name = dispex->info->vtbl->get_name(dispex); - while(*name) - *p++ = *name++; - assert(p + ARRAY_SIZE(suffix) - buf <= ARRAY_SIZE(buf)); - } - memcpy(p, suffix, sizeof(suffix)); - - *ret = SysAllocString(buf); - return *ret ? S_OK : E_OUTOFMEMORY; -} - static dispex_data_t *ensure_dispex_info(dispex_static_data_t *desc, compat_mode_t compat_mode) { if(!desc->info_cache[compat_mode]) { @@ -1933,22 +1905,23 @@ static BOOL ensure_real_info(DispatchEx *dispex) compat_mode_t compat_mode; HTMLInnerWindow *script_global; DispatchEx *prototype = NULL; + dispex_static_data_t *data;
if(dispex->info != dispex->info->desc->delayed_init_info) return TRUE;
- script_global = dispex->info->vtbl->get_script_global(dispex); + script_global = dispex->info->vtbl->get_script_global(dispex, &data); compat_mode = script_global->doc->document_mode;
- if(compat_mode >= COMPAT_MODE_IE9 && dispex->info->desc->id) { - HRESULT hres = get_prototype(script_global, dispex->info->desc->id, &prototype); + if(compat_mode >= COMPAT_MODE_IE9 && data->id) { + HRESULT hres = get_prototype(script_global, data->id, &prototype); if(FAILED(hres)) { ERR("could not get prototype: %08lx\n", hres); return FALSE; } }
- if (!(dispex->info = ensure_dispex_info(dispex->info->desc, compat_mode))) + if(!(dispex->info = ensure_dispex_info(data, compat_mode))) return FALSE; init_host_object(dispex, script_global, prototype); return TRUE; @@ -1961,6 +1934,37 @@ compat_mode_t dispex_compat_mode(DispatchEx *dispex) return dispex->info->compat_mode; }
+HRESULT dispex_to_string(DispatchEx *dispex, BSTR *ret) +{ + static const WCHAR prefix[8] = L"[object "; + static const WCHAR suffix[] = L"]"; + WCHAR buf[ARRAY_SIZE(prefix) + ARRAY_SIZE(dispex->info->desc->prototype_name) + ARRAY_SIZE(suffix)], *p = buf; + compat_mode_t compat_mode = dispex_compat_mode(dispex); + const char *name; + + if(!ret) + return E_INVALIDARG; + + memcpy(p, prefix, sizeof(prefix)); + p += ARRAY_SIZE(prefix); + if(compat_mode < COMPAT_MODE_IE9) + p--; + else { + if(!ensure_real_info(dispex)) + return E_OUTOFMEMORY; + name = dispex->info->name; + if(dispex->info->vtbl->get_name) + name = dispex->info->vtbl->get_name(dispex); + while(*name) + *p++ = *name++; + assert(p + ARRAY_SIZE(suffix) - buf <= ARRAY_SIZE(buf)); + } + memcpy(p, suffix, sizeof(suffix)); + + *ret = SysAllocString(buf); + return *ret ? S_OK : E_OUTOFMEMORY; +} + static inline DispatchEx *impl_from_IWineJSDispatchHost(IWineJSDispatchHost *iface) { return CONTAINING_RECORD(iface, DispatchEx, IWineJSDispatchHost_iface); diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 1ff8eaf4c19..8c26292ee85 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -5532,13 +5532,17 @@ static HRESULT HTMLDocumentNode_get_prop_desc(DispatchEx *dispex, DISPID id, str return S_OK; }
-static HTMLInnerWindow *HTMLDocumentNode_get_script_global(DispatchEx *dispex) +static HTMLInnerWindow *HTMLDocumentNode_get_script_global(DispatchEx *dispex, dispex_static_data_t **dispex_data) { HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
TRACE("(%p) using %u compat mode\n", This, This->document_mode);
lock_document_mode(This); + if(This->node.vtbl != &HTMLDocumentNodeImplVtbl) + *dispex_data = &DocumentFragment_dispex; + else + *dispex_data = This->document_mode < COMPAT_MODE_IE11 ? &Document_dispex : &HTMLDocument_dispex; return This->script_global; }
@@ -5708,6 +5712,7 @@ static void HTMLDocumentNode_init_dispex_info(dispex_data_t *info, compat_mode_t dispex_static_data_t Document_dispex = { .id = PROT_Document, .prototype_id = PROT_Node, + .vtbl = &HTMLDocument_event_target_vtbl.dispex_vtbl, .disp_tid = DispHTMLDocument_tid, .iface_tids = HTMLDocumentNode_iface_tids, .init_info = HTMLDocumentNode_init_dispex_info, @@ -5720,6 +5725,7 @@ dispex_static_data_t HTMLDocument_dispex = { .disp_tid = DispHTMLDocument_tid, .iface_tids = HTMLDocumentNode_iface_tids, .init_info = HTMLDocumentNode_init_dispex_info, + .min_compat_mode = COMPAT_MODE_IE11, };
static HTMLDocumentNode *alloc_doc_node(HTMLDocumentObj *doc_obj, HTMLInnerWindow *window, HTMLInnerWindow *script_global) diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 3624c128cca..22e1efb3171 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -4058,10 +4058,11 @@ HRESULT HTMLWindow_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_ return hres; }
-static HTMLInnerWindow *HTMLWindow_get_script_global(DispatchEx *dispex) +static HTMLInnerWindow *HTMLWindow_get_script_global(DispatchEx *dispex, dispex_static_data_t **dispex_data) { HTMLInnerWindow *This = impl_from_DispatchEx(dispex); lock_document_mode(This->doc); + *dispex_data = &Window_dispex; return This; }
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 19a546e269f..f3ba8f75c15 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -351,6 +351,7 @@ typedef struct dispex_dynamic_data_t dispex_dynamic_data_t;
typedef struct DispatchEx DispatchEx; typedef struct nsCycleCollectionTraversalCallback nsCycleCollectionTraversalCallback; +typedef struct dispex_static_data_t dispex_static_data_t;
typedef struct { UINT_PTR x; @@ -402,7 +403,7 @@ typedef struct { HRESULT (*disp_invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
/* Used by objects that want to delay their compat mode initialization until actually needed */ - HTMLInnerWindow *(*get_script_global)(DispatchEx*); + HTMLInnerWindow *(*get_script_global)(DispatchEx*,dispex_static_data_t**);
/* Used by objects that want to populate some dynamic props on initialization */ HRESULT (*populate_props)(DispatchEx*); @@ -510,7 +511,7 @@ typedef enum { PROT_LAST, } prototype_id_t;
-typedef struct { +struct dispex_static_data_t { const char *name; const dispex_static_data_vtbl_t *vtbl; const tid_t disp_tid; @@ -527,7 +528,7 @@ typedef struct { compat_mode_t min_compat_mode; compat_mode_t max_compat_mode; char prototype_name[64]; -} dispex_static_data_t; +};
#define X(name) extern dispex_static_data_t name ## _dispex; ALL_PROTOTYPES diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index aa47927a284..a943fcbe532 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -300,7 +300,7 @@ sync_test("builtin_toString", function() { if(clientRects) test("clientRect", clientRects[0], "ClientRect"); if(clientRects) test("clientRects", clientRects, "ClientRectList"); if(currentStyle) test("currentStyle", currentStyle, "MSCurrentStyleCSSProperties"); - if(v >= 11 /* todo_wine */) test("document", document, v < 11 ? "Document" : "HTMLDocument"); + test("document", document, v < 11 ? "Document" : "HTMLDocument"); test("elements", document.getElementsByTagName("body"), "HTMLCollection"); test("history", window.history, "History"); test("implementation", document.implementation, "DOMImplementation"); @@ -675,6 +675,8 @@ sync_test("window_props", function() { test_exposed("performance", true); test_exposed("console", v >= 10); test_exposed("matchMedia", v >= 10); + test_exposed("Document", v >= 9); + test_exposed("HTMLDocument", v === 8 || v >= 11, v === 8); test_exposed("MutationObserver", v >= 11); test_exposed("PageTransitionEvent", v >= 11); test_exposed("ProgressEvent", v >= 10); @@ -3481,11 +3483,13 @@ sync_test("prototypes", function() { check(Node.prototype, Object.prototype, "node prototype"); check(sessionStorage, Storage.prototype, "storage"); check(Storage.prototype, Object.prototype, "storage prototype"); - if(v >= 11) { + if(v < 11) + check(document, Document.prototype, "html document"); + else { check(document, HTMLDocument.prototype, "html document"); check(HTMLDocument.prototype, Document.prototype, "html document prototype"); - check(Document.prototype, Node.prototype, "document prototype"); } + check(Document.prototype, Node.prototype, "document prototype"); check(window, Window.prototype, "window"); check(Window.prototype, Object.prototype, "window prototype"); check(new XMLHttpRequest(), XMLHttpRequest.prototype, "xhr"); diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 6950c1e2a08..135b5ab4060 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -4209,7 +4209,6 @@ static void test_doc_obj(IHTMLDocument2 *doc) bstr = NULL; hres = IHTMLDocument2_toString(doc, &bstr); ok(hres == S_OK, "toString failed: %08lx\n", hres); - todo_wine_if(document_mode >= 9) ok(!wcscmp(bstr, (document_mode < 9 ? L"[object]" : L"[object Document]")), "toString returned %s\n", wine_dbgstr_w(bstr)); SysFreeString(bstr);