From: Gabriel Ivăncescu gabrielopcode@gmail.com
Native modes IE10 and up implement XML documents as children of the DocumentPrototype, which have standard IHTMLDocument interfaces. But previous modes do not, but instead have the IXMLDOMDocument interface (which suggests it uses msxml like now).
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmldoc.c | 47 ++++++++++++++++++++++++++++-- dlls/mshtml/mshtml_private.h | 11 +++++++ dlls/mshtml/tests/documentmode.js | 6 +++- dlls/mshtml/tests/xhr.js | 22 ++++++++++++++ dlls/mshtml/tests/xmlhttprequest.c | 15 ++++++++++ dlls/mshtml/xmlhttprequest.c | 14 +++++++++ 6 files changed, 112 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 7255e8d9ec3..542382bf4d0 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -39,8 +39,39 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
+static dispex_static_data_t *const dispex_from_document_type[] = { + [DOCTYPE_HTML] = &HTMLDocument_dispex, + [DOCTYPE_XHTML] = &XMLDocument_dispex, + [DOCTYPE_XML] = &XMLDocument_dispex, + [DOCTYPE_SVG] = &XMLDocument_dispex, +}; + static HRESULT create_document_fragment(nsIDOMNode *nsnode, HTMLDocumentNode *doc_node, HTMLDocumentNode **ret);
+static document_type_t get_doc_type(nsIDOMDocument *nsdoc) +{ + document_type_t doc_type; + const PRUnichar *str; + nsAString nsstr; + nsresult nsres; + + nsAString_Init(&nsstr, NULL); + nsres = nsIDOMDocument_GetContentType(nsdoc, &nsstr); + assert(nsres == NS_OK); + + nsAString_GetData(&nsstr, &str); + if(!wcscmp(str, L"text/html")) + doc_type = DOCTYPE_HTML; + else if(!wcscmp(str, L"application/xhtml+xml")) + doc_type = DOCTYPE_XHTML; + else if(!wcscmp(str, L"image/svg+xml")) + doc_type = DOCTYPE_SVG; + else + doc_type = DOCTYPE_XML; + nsAString_Finish(&nsstr); + return doc_type; +} + HRESULT get_doc_elem_by_id(HTMLDocumentNode *doc, const WCHAR *id, HTMLElement **ret) { nsIDOMNodeList *nsnode_list; @@ -5634,7 +5665,7 @@ static HTMLInnerWindow *HTMLDocumentNode_get_script_global(DispatchEx *dispex, d if(This->node.vtbl != &HTMLDocumentNodeImplVtbl) *dispex_data = &DocumentFragment_dispex; else - *dispex_data = This->document_mode < COMPAT_MODE_IE11 ? &Document_dispex : &HTMLDocument_dispex; + *dispex_data = This->document_mode < COMPAT_MODE_IE11 ? &Document_dispex : dispex_from_document_type[This->doc_type]; return This->script_global; }
@@ -5870,6 +5901,17 @@ dispex_static_data_t HTMLDocument_dispex = { .min_compat_mode = COMPAT_MODE_IE11, };
+dispex_static_data_t XMLDocument_dispex = { + .id = OBJID_XMLDocument, + .prototype_id = OBJID_Document, + .vtbl = &HTMLDocument_event_target_vtbl.dispex_vtbl, + .disp_tid = DispHTMLDocument_tid, + .iface_tids = HTMLDocumentNode_iface_tids, + .init_info = HTMLDocumentNode_init_dispex_info, + .js_flags = HOSTOBJ_VOLATILE_FILL, + .min_compat_mode = COMPAT_MODE_IE11, +}; + static HTMLDocumentNode *alloc_doc_node(HTMLDocumentObj *doc_obj, HTMLInnerWindow *window, HTMLInnerWindow *script_global) { HTMLDocumentNode *doc; @@ -5927,6 +5969,7 @@ HRESULT create_document_node(nsIDOMDocument *nsdoc, GeckoBrowser *browser, HTMLI doc = alloc_doc_node(doc_obj, window, script_global); if(!doc) return E_OUTOFMEMORY; + doc->doc_type = get_doc_type(nsdoc);
if(parent_mode >= COMPAT_MODE_IE9) { TRACE("using parent mode %u\n", parent_mode); @@ -5946,7 +5989,7 @@ HRESULT create_document_node(nsIDOMDocument *nsdoc, GeckoBrowser *browser, HTMLI doc->html_document = NULL; }
- HTMLDOMNode_Init(doc, &doc->node, (nsIDOMNode*)doc->dom_document, &HTMLDocument_dispex); + HTMLDOMNode_Init(doc, &doc->node, (nsIDOMNode*)doc->dom_document, dispex_from_document_type[doc->doc_type]);
init_document_mutation(doc); doc_init_events(doc); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 50f147531d1..6686772110a 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -510,6 +510,7 @@ typedef struct { X(TextRange) \ X(UIEvent) \ X(Window) \ + X(XMLDocument) \ X(XMLHttpRequest)
typedef enum { @@ -1094,6 +1095,15 @@ struct HTMLFrameBase {
typedef struct nsDocumentEventListener nsDocumentEventListener;
+/* NOTE: Update arrays at top of htmldoc.c if you change this */ +typedef enum { + DOCTYPE_INVALID = -1, + DOCTYPE_HTML, + DOCTYPE_XHTML, + DOCTYPE_XML, + DOCTYPE_SVG, +} document_type_t; + struct HTMLDocumentNode { HTMLDOMNode node;
@@ -1149,6 +1159,7 @@ struct HTMLDocumentNode { unsigned int content_ready : 1; unsigned int unload_sent : 1;
+ document_type_t doc_type; IHTMLDOMImplementation *dom_implementation; IHTMLNamespaceCollection *namespaces;
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 6809b957b2f..17b4919457d 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -981,6 +981,7 @@ sync_test("window_props", function() { test_exposed("matchMedia", v >= 10); test_exposed("Document", v >= 9); test_exposed("HTMLDocument", v === 8 || v >= 11, v === 8); + test_exposed("XMLDocument", v >= 11); test_exposed("DOMParser", v >= 9); test_exposed("MutationObserver", v >= 11); test_exposed("PageTransitionEvent", v >= 11); @@ -3868,6 +3869,7 @@ sync_test("prototypes", function() { else { check(document, HTMLDocument.prototype, "html document"); check(HTMLDocument.prototype, Document.prototype, "html document prototype"); + check(XMLDocument.prototype, Document.prototype, "xml document prototype"); } check(Document.prototype, Node.prototype, "document prototype"); check(window, Window.prototype, "window"); @@ -4412,6 +4414,8 @@ sync_test("prototype props", function() { check(StyleSheet, [ "disabled", "href", "media", "ownerNode", "parentStyleSheet", "title", "type" ]); check(Text, [ "removeNode", "replaceNode", "replaceWholeText", "splitText", "swapNode", "wholeText" ], [ "replaceWholeText", "wholeText" ]); check(UIEvent, [ "detail", "initUIEvent", "view" ], null, [ "deviceSessionId" ]); + if(v >= 11) + check(XMLDocument, []); });
sync_test("constructors", function() { @@ -4585,7 +4589,7 @@ async_test("window own props", function() { ["TrackEvent",10], ["TransitionEvent",10], "TreeWalker", ["Uint16Array",10], ["Uint32Array",10], ["Uint8Array",10], ["Uint8ClampedArray",11], ["URL",10], ["ValidityState",10], ["VideoPlaybackQuality",11], ["WebGLActiveInfo",11], ["WebGLBuffer",11], ["WebGLContextEvent",11], ["WebGLFramebuffer",11], ["WebGLObject",11], ["WebGLProgram",11], ["WebGLRenderbuffer",11], ["WebGLRenderingContext",11], ["WebGLShader",11], ["WebGLShaderPrecisionFormat",11], ["WebGLTexture",11], ["WebGLUniformLocation",11], ["WEBGL_compressed_texture_s3tc",11], - ["WEBGL_debug_renderer_info",11], ["WebSocket",10], "WheelEvent", ["Worker",10], ["XDomainRequest",9,10], ["XMLDocument",11], ["XMLHttpRequestEventTarget",10], "XMLSerializer" + ["WEBGL_debug_renderer_info",11], ["WebSocket",10], "WheelEvent", ["Worker",10], ["XDomainRequest",9,10], ["XMLHttpRequestEventTarget",10], "XMLSerializer" ]); next_test(); } diff --git a/dlls/mshtml/tests/xhr.js b/dlls/mshtml/tests/xhr.js index cc543e7cec8..46aed46624c 100644 --- a/dlls/mshtml/tests/xhr.js +++ b/dlls/mshtml/tests/xhr.js @@ -22,6 +22,7 @@ var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<a name="test">wine</a> async_test("async_xhr", function() { var xhr = new XMLHttpRequest(); var complete_cnt = 0, loadstart = false; + var v = document.documentMode;
xhr.onreadystatechange = function() { if(xhr.readyState != 4) @@ -30,6 +31,26 @@ async_test("async_xhr", function() { ok(xhr.responseText === xml, "unexpected responseText " + xhr.responseText); ok(xhr.responseXML !== null, "unexpected null responseXML");
+ var x = xhr.responseXML, r = Object.prototype.toString.call(x); + ok(r === (v < 10 ? "[object Object]" : (v < 11 ? "[object Document]" : "[object XMLDocument]")), + "XML document Object.toString = " + r); + + r = Object.getPrototypeOf(x); + if(v < 10) + ok(r === null, "prototype of returned XML document = " + r); + else if(v < 11) + ok(r === window.Document.prototype, "prototype of returned XML document = " + r); + else + ok(r === window.XMLDocument.prototype, "prototype of returned XML document = " + r); + + if(v < 10) { + ok(!("anchors" in x), "anchors is in returned XML document"); + ok(Object.prototype.hasOwnProperty.call(x, "createElement"), "createElement not a prop of returned XML document"); + }else { + ok("anchors" in x, "anchors not in returned XML document"); + ok(!x.hasOwnProperty("createElement"), "createElement is a prop of returned XML document"); + } + if(complete_cnt++ && !("onloadend" in xhr)) next_test(); } @@ -229,6 +250,7 @@ async_test("content_types", function() { var xml_types = [ "text/xmL", "apPliCation/xml", + "application/xHtml+xml", "image/SvG+xml", "Wine/Test+xml", "++Xml", diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c index 6226461a502..44132160520 100644 --- a/dlls/mshtml/tests/xmlhttprequest.c +++ b/dlls/mshtml/tests/xmlhttprequest.c @@ -519,10 +519,14 @@ static void _set_request_header(unsigned line, IHTMLXMLHttpRequest *xhr, const W static void test_responseXML(const WCHAR *expect_text) { IDispatch *disp; + IHTMLDocument2 *html_doc; IXMLDOMDocument *xmldom; IObjectSafety *safety; + IHTMLDOMNode *node; DWORD enabled = 0, supported = 0; + DISPID dispid; HRESULT hres; + BSTR str;
disp = NULL; hres = IHTMLXMLHttpRequest_get_responseXML(xhr, &disp); @@ -545,6 +549,17 @@ static void test_responseXML(const WCHAR *expect_text) "Expected enabled: (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), got 0x%08lx\n", enabled); IObjectSafety_Release(safety);
+ hres = IXMLDOMDocument_QueryInterface(xmldom, &IID_IHTMLDOMNode, (void**)&node); + ok(hres == E_NOINTERFACE, "QueryInterface(IHTMLDOMNode) returned: %08lx\n", hres); + + hres = IXMLDOMDocument_QueryInterface(xmldom, &IID_IHTMLDocument2, (void**)&html_doc); + ok(hres == E_NOINTERFACE, "QueryInterface(IHTMLDocument2) returned: %08lx\n", hres); + + str = SysAllocString(L"anchors"); + hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &str, 1, LOCALE_USER_DEFAULT, &dispid); + ok(hres == DISP_E_UNKNOWNNAME, "GetIDsOfNames("anchors") returned: %08lx\n", hres); + SysFreeString(str); + if(!expect_text) test_illegal_xml(xmldom);
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 3097792c620..61561d3a2b7 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -576,6 +576,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *if }
if(dispex_compat_mode(&This->event_target.dispex) >= COMPAT_MODE_IE10) { + HTMLDocumentNode *doc; nsIDOMDocument *nsdoc; nsresult nsres;
@@ -586,7 +587,20 @@ static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *if *p = NULL; return S_OK; } + + if(!This->window->base.outer_window || !This->window->base.outer_window->browser) + hres = E_UNEXPECTED; + else + hres = create_document_node(nsdoc, This->window->base.outer_window->browser, NULL, This->window, + dispex_compat_mode(&This->window->event_target.dispex), &doc); nsIDOMDocument_Release(nsdoc); + if(FAILED(hres)) + return hres; + + /* make sure dispex info is initialized */ + dispex_compat_mode(&doc->node.event_target.dispex); + *p = (IDispatch*)&doc->IHTMLDocument2_iface; + return S_OK; }
hres = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&xmldoc);