From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 8 ++++ dlls/mshtml/omnavigator.c | 92 +++++++++++++++++++++++++++++++++++- dlls/mshtml/tests/es5.js | 50 +++++++++++++++++++- 3 files changed, 148 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 50f147531d1..de1fe07ab21 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1094,6 +1094,14 @@ struct HTMLFrameBase {
typedef struct nsDocumentEventListener nsDocumentEventListener;
+typedef enum { + DOCTYPE_INVALID = -1, + DOCTYPE_HTML, + DOCTYPE_XHTML, + DOCTYPE_XML, + DOCTYPE_SVG, +} document_type_t; + struct HTMLDocumentNode { HTMLDOMNode node;
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index c65fb675372..8ba88200c3c 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -32,6 +32,31 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
+static document_type_t document_type_from_content_type(const WCHAR *content_type) +{ + static const struct { + const WCHAR *content_type; + document_type_t doc_type; + } table[] = { + { L"application/xhtml+xml", DOCTYPE_XHTML }, + { L"application/xml", DOCTYPE_XML }, + { L"image/svg+xml", DOCTYPE_SVG }, + { L"text/html", DOCTYPE_HTML }, + { L"text/xml", DOCTYPE_XML }, + }; + unsigned int i, a = 0, b = ARRAY_SIZE(table); + int c; + + while(a < b) { + i = (a + b) / 2; + c = wcsicmp(table[i].content_type, content_type); + if(!c) return table[i].doc_type; + if(c > 0) b = i; + else a = i + 1; + } + return DOCTYPE_INVALID; +} + typedef struct HTMLPluginsCollection HTMLPluginsCollection; typedef struct HTMLMimeTypesCollection HTMLMimeTypesCollection;
@@ -272,6 +297,8 @@ void detach_dom_implementation(IHTMLDOMImplementation *iface) struct dom_parser { DispatchEx dispex; IDOMParser IDOMParser_iface; + + HTMLDocumentNode *doc; };
static inline struct dom_parser *impl_from_IDOMParser(IDOMParser *iface) @@ -284,9 +311,50 @@ DISPEX_IDISPATCH_IMPL(dom_parser, IDOMParser, impl_from_IDOMParser(iface)->dispe static HRESULT WINAPI dom_parser_parseFromString(IDOMParser *iface, BSTR string, BSTR mimeType, IHTMLDocument2 **ppNode) { struct dom_parser *This = impl_from_IDOMParser(iface); + document_type_t doc_type; + HRESULT hres; + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(string), debugstr_w(mimeType), ppNode); + + if(!string || !mimeType || (doc_type = document_type_from_content_type(mimeType)) == DOCTYPE_INVALID) + return E_INVALIDARG; + + if(doc_type == DOCTYPE_HTML) { + IHTMLDOMImplementation *impl_iface; + HTMLDOMImplementation *impl; + IHTMLDocument7 *html_doc; + IHTMLElement *html_elem; + HTMLDocumentNode *doc; + + hres = IHTMLDocument5_get_implementation(&This->doc->IHTMLDocument5_iface, &impl_iface); + if(FAILED(hres)) + return hres; + + impl = impl_from_IHTMLDOMImplementation(impl_iface); + hres = HTMLDOMImplementation2_createHTMLDocument(&impl->IHTMLDOMImplementation2_iface, NULL, &html_doc); + HTMLDOMImplementation_Release(impl_iface); + if(FAILED(hres)) + return hres; + doc = CONTAINING_RECORD(html_doc, HTMLDocumentNode, IHTMLDocument7_iface); + + hres = IHTMLDocument3_get_documentElement(&doc->IHTMLDocument3_iface, &html_elem); + if(FAILED(hres)) { + IHTMLDocument7_Release(html_doc); + return hres; + }
- FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(string), debugstr_w(mimeType), ppNode); + hres = IHTMLElement_put_innerHTML(html_elem, string); + IHTMLElement_Release(html_elem); + if(FAILED(hres)) { + IHTMLDocument7_Release(html_doc); + return hres; + }
+ *ppNode = &doc->IHTMLDocument2_iface; + return hres; + } + + FIXME("Not implemented for XML Document\n"); return E_NOTIMPL; }
@@ -316,6 +384,23 @@ static void *dom_parser_query_interface(DispatchEx *dispex, REFIID riid) return NULL; }
+static void dom_parser_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) +{ + struct dom_parser *This = dom_parser_from_DispatchEx(dispex); + if(This->doc) + note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "doc", cb); +} + +static void dom_parser_unlink(DispatchEx *dispex) +{ + struct dom_parser *This = dom_parser_from_DispatchEx(dispex); + if(This->doc) { + HTMLDocumentNode *doc = This->doc; + This->doc = NULL; + IHTMLDOMNode_Release(&doc->node.IHTMLDOMNode_iface); + } +} + static void dom_parser_destructor(DispatchEx *dispex) { struct dom_parser *This = dom_parser_from_DispatchEx(dispex); @@ -327,6 +412,8 @@ static HRESULT init_dom_parser_ctor(struct constructor*); static const dispex_static_data_vtbl_t dom_parser_dispex_vtbl = { .query_interface = dom_parser_query_interface, .destructor = dom_parser_destructor, + .traverse = dom_parser_traverse, + .unlink = dom_parser_unlink };
static const tid_t dom_parser_iface_tids[] = { @@ -367,6 +454,9 @@ static HRESULT dom_parser_ctor_value(DispatchEx *dispex, LCID lcid, WORD flags, return E_OUTOFMEMORY;
ret->IDOMParser_iface.lpVtbl = &dom_parser_vtbl; + ret->doc = This->window->doc; + IHTMLDOMNode_AddRef(&ret->doc->node.IHTMLDOMNode_iface); + init_dispatch(&ret->dispex, &DOMParser_dispex, This->window, dispex_compat_mode(&This->dispex));
V_VT(res) = VT_DISPATCH; diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 67f974bbacf..a0b4d758154 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2815,7 +2815,7 @@ sync_test("screen", function() { });
sync_test("DOMParser", function() { - var p, r = DOMParser.length; + var p, r = DOMParser.length, mimeType; ok(r === 0, "length = " + r);
p = DOMParser(); @@ -2823,6 +2823,54 @@ sync_test("DOMParser", function() { ok(r === DOMParser.prototype, "prototype of instance created without new = " + r); ok(p !== new DOMParser(), "DOMParser() == new DOMParser()"); ok(new DOMParser() !== new DOMParser(), "new DOMParser() == new DOMParser()"); + + var teststr = { toString: function() { return "<a name="test">wine</a>"; } }; + + // HTML mime types + mimeType = [ + "text/hTml" + ]; + for(var i = 0; i < mimeType.length; i++) { + var m = mimeType[i], html = p.parseFromString(teststr, m), e = external.getExpectedMimeType(m.toLowerCase()); + r = html.mimeType; + ok(r === e, "mimeType of HTML document with mime type " + m + " = " + r + ", expected " + e); + r = html.childNodes; + ok(r.length === 1 || r.length === 2, "childNodes.length of HTML document with mime type " + m + " = " + r.length); + var html_elem = r[r.length - 1]; + ok(html_elem.nodeName === "HTML", "child nodeName of HTML document with mime type " + m + " = " + html_elem.nodeName); + ok(html_elem.nodeValue === null, "child nodeValue of HTML document with mime type " + m + " = " + html_elem.nodeValue); + r = html.anchors; + ok(r.length === 1, "anchors.length of HTML document with mime type " + m + " = " + r.length); + r = r[0]; + ok(r.nodeName === "A", "anchor nodeName of HTML document with mime type " + m + " = " + r.nodeName); + ok(r.nodeValue === null, "anchor nodeValue of HTML document with mime type " + m + " = " + r.nodeValue); + r = r.parentNode; + ok(r.nodeName === "BODY", "anchor parent nodeName of HTML document with mime type " + m + " = " + r.nodeName); + ok(r.nodeValue === null, "anchor parent nodeValue of HTML document with mime type " + m + " = " + r.nodeValue); + r = r.parentNode; + ok(r === html_elem, "body parent of HTML document with mime type " + m + " = " + r); + } + + // Invalid mime types + mimeType = [ + "application/html", + "wine/test+xml", + "image/jpeg", + "text/plain", + "html", + "+xml", + "xml", + 42 + ]; + for(var i = 0; i < mimeType.length; i++) { + try { + p.parseFromString(teststr, mimeType[i]); + ok(false, "expected exception calling parseFromString with mime type " + mimeType[i]); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === E_INVALIDARG, "parseFromString with mime type " + mimeType[i] + " threw " + n); + } + } });
sync_test("builtin_func", function() {