This functions should also work with document fragments, in wine they only return NULL.
-- v3: mshtml: Implement HTMLDocument_get_body for document fragments.
From: Santino Mazza smazza@codeweavers.com
--- dlls/mshtml/tests/dom.c | 48 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 6a960bfa21f..91bc73fd2d0 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -10984,7 +10984,7 @@ static IHTMLDocument2 *create_docfrag(IHTMLDocument2 *doc) static void test_docfrag(IHTMLDocument2 *doc) { IHTMLDocument2 *frag, *owner_doc, *doc_node; - IHTMLElement *div, *body, *br; + IHTMLElement *div, *body, *br,*html; IHTMLElementCollection *col; IHTMLLocation *location; HRESULT hres; @@ -10998,6 +10998,13 @@ static void test_docfrag(IHTMLDocument2 *doc) ET_BR };
+ static const elem_type_t frag_types[] = { + ET_HTML, + ET_DIV, + ET_DIV, + ET_BODY + }; + frag = create_docfrag(doc);
test_disp((IUnknown*)frag, &DIID_DispHTMLDocument, &CLSID_HTMLDocument, L"[object]"); @@ -11030,6 +11037,45 @@ static void test_docfrag(IHTMLDocument2 *doc) test_elem_collection((IUnknown*)col, all_types, ARRAY_SIZE(all_types)); IHTMLElementCollection_Release(col);
+ html = test_create_elem(doc, L"HTML"); + test_elem_source_index(html, -1); + test_node_append_child((IUnknown*)frag, (IUnknown*)html); + test_elem_source_index(html, 0); + + div = test_create_elem(doc, L"DIV"); + test_elem_source_index(div, -1); + test_node_append_child((IUnknown*)html, (IUnknown*)div); + test_elem_source_index(div, 1); + IHTMLElement_Release(div); + + div = test_create_elem(doc, L"DIV"); + test_elem_source_index(div, -1); + test_node_append_child((IUnknown*)html, (IUnknown*)div); + test_elem_source_index(div, 2); + + body = test_create_elem(doc, L"BODY"); + test_elem_source_index(body, -1); + test_node_append_child((IUnknown*)div, (IUnknown*)body); + test_elem_source_index(body, 3); + IHTMLElement_Release(body); + IHTMLElement_Release(div); + IHTMLElement_Release(html); + + hres = IHTMLDocument2_get_body(frag, &body); + ok(hres == S_OK, "get_body failed: %08lx\n", hres); + todo_wine ok(body != NULL, "body == NULL\n"); + if (body) + IHTMLElement_Release(body); + + col = NULL; + hres = IHTMLDocument2_get_all(frag, &col); + todo_wine ok(hres == S_OK, "get_all failed: %08lx\n", hres); + todo_wine ok(col != NULL, "got null elements collection\n"); + if (col) { + test_elem_collection((IUnknown *) col, frag_types, ARRAY_SIZE(frag_types)); + IHTMLElementCollection_Release(col); + } + div = test_create_elem(frag, L"div"); owner_doc = get_owner_doc((IUnknown*)div); doc_node = get_doc_node(doc);
From: Santino Mazza smazza@codeweavers.com
--- dlls/mshtml/htmldoc.c | 4 ++-- dlls/mshtml/tests/dom.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 90c4706abee..ac471e9e1a8 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -495,8 +495,8 @@ static HRESULT WINAPI HTMLDocument_get_all(IHTMLDocument2 *iface, IHTMLElementCo TRACE("(%p)->(%p)\n", This, p);
if(!This->dom_document) { - WARN("NULL dom_document\n"); - return E_UNEXPECTED; + *p = create_all_collection(&This->node, FALSE); + return S_OK; }
nsres = nsIDOMDocument_GetDocumentElement(This->dom_document, &nselem); diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 91bc73fd2d0..a726801a43e 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -11069,8 +11069,8 @@ static void test_docfrag(IHTMLDocument2 *doc)
col = NULL; hres = IHTMLDocument2_get_all(frag, &col); - todo_wine ok(hres == S_OK, "get_all failed: %08lx\n", hres); - todo_wine ok(col != NULL, "got null elements collection\n"); + ok(hres == S_OK, "get_all failed: %08lx\n", hres); + ok(col != NULL, "got null elements collection\n"); if (col) { test_elem_collection((IUnknown *) col, frag_types, ARRAY_SIZE(frag_types)); IHTMLElementCollection_Release(col);
From: Santino Mazza smazza@codeweavers.com
--- dlls/mshtml/htmldoc.c | 10 ++++++++++ dlls/mshtml/tests/dom.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index ac471e9e1a8..e6555fbc3fc 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -538,6 +538,16 @@ static HRESULT WINAPI HTMLDocument_get_body(IHTMLDocument2 *iface, IHTMLElement return E_UNEXPECTED; } } + else { + nsAString nsnode_name; + nsIDOMDocumentFragment *frag; + + nsIDOMNode_QueryInterface(This->node.nsnode, &IID_nsIDOMDocumentFragment, (void**)&frag); + nsAString_InitDepend(&nsnode_name, L"BODY"); + nsIDOMDocumentFragment_QuerySelector(frag, &nsnode_name, (nsIDOMElement**)&nsbody); + nsAString_Finish(&nsnode_name); + nsIDOMDocumentFragment_Release(frag); + }
if(!nsbody) { *p = NULL; diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index a726801a43e..eea3dbe7126 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -11063,7 +11063,7 @@ static void test_docfrag(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_body(frag, &body); ok(hres == S_OK, "get_body failed: %08lx\n", hres); - todo_wine ok(body != NULL, "body == NULL\n"); + ok(body != NULL, "body == NULL\n"); if (body) IHTMLElement_Release(body);
On Fri Jan 6 17:08:20 2023 +0000, Santino Mazza wrote:
Oh, I used casting because in HTMLDocument3_createDocumentFragment it uses casting for passing nsIDOMDocumentFragment to create_document_fragment as nsIDOMNode
Yeah, I know it "works", it's just fragile and some would say ugly. :D
Down-casting in contrast is totally fine, since it inherits from nsIDOMNode. But the other way around isn't.
On Fri Jan 6 17:12:39 2023 +0000, Gabriel Ivăncescu wrote:
Yeah, I know it "works", it's just fragile and some would say ugly. :D Down-casting in contrast is totally fine, since it inherits from nsIDOMNode. But the other way around isn't.
Ohh makes sense
Gabriel Ivăncescu (@insn) commented about dlls/mshtml/htmldoc.c:
return E_UNEXPECTED; } }
- else if(This->node.nsnode) {
- else { nsAString nsnode_name;
nsIDOMDocumentFragment *frag;
nsAString_Init(&nsnode_name, L"BODY");
nsIDOMDocumentFragment_QuerySelector((nsIDOMDocumentFragment*)This->node.nsnode,
&nsnode_name, (nsIDOMElement**)&nsbody);
nsIDOMNode_QueryInterface(This->node.nsnode, &IID_nsIDOMDocumentFragment, (void**)&frag);
Please check the return value here for success and only query it if it succeeds. Note that an assert() is not enough, it's totally possible for it to fail (e.g. for XML documents, which are not fragments but not HTML documents either).