[PATCH 0/1] MR10063: mshtml: Add XMLSerializer implementation.
Based on !10025. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10063
From: Phiality <bakreski03@gmail.com> --- dlls/mshtml/mshtml_private.h | 5 +- dlls/mshtml/omnavigator.c | 150 ++++++++++++++++++++++++++++++ dlls/mshtml/tests/documentmode.js | 3 +- dlls/mshtml/tests/dom.js | 24 +++++ include/mshtmdid.h | 4 + include/mshtml.idl | 40 ++++++++ 6 files changed, 224 insertions(+), 2 deletions(-) diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index ce872249e62..e5236ed5f03 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -160,6 +160,7 @@ struct constructor; XDIID(DispHTMLWindow2) \ XDIID(DispHTMLXMLHttpRequest) \ XDIID(DispXDomainRequest) \ + XDIID(DispXMLSerializer) \ XDIID(DispSVGCircleElement) \ XDIID(DispSVGSVGElement) \ XDIID(DispSVGTSpanElement) \ @@ -176,6 +177,7 @@ struct constructor; XIID(IDOMUIEvent) \ XIID(IDOMDocumentType) \ XIID(IDOMParser) \ + XIID(IDOMXmlSerializer) \ XIID(IDocumentEvent) \ XIID(IDocumentRange) \ XIID(IDocumentSelector) \ @@ -530,7 +532,8 @@ typedef struct { X(Window) \ X(XDomainRequest) \ X(XMLDocument) \ - X(XMLHttpRequest) + X(XMLHttpRequest) \ + X(XMLSerializer) typedef enum { OBJID_NONE, diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index fc4d2f5b408..a3e2f1ab01f 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -451,6 +451,156 @@ static HRESULT init_dom_parser_ctor(struct constructor *constr) return S_OK; } +struct xml_serializer { + DispatchEx dispex; + IDOMXmlSerializer IDOMXmlSerializer_iface; +}; + +static inline struct xml_serializer *impl_from_IDOMXmlSerializer(IDOMXmlSerializer *iface) +{ + return CONTAINING_RECORD(iface, struct xml_serializer, IDOMXmlSerializer_iface); +} + +DISPEX_IDISPATCH_IMPL(xml_serializer, IDOMXmlSerializer, impl_from_IDOMXmlSerializer(iface)->dispex) + +static HRESULT WINAPI xml_serializer_serializeToString(IDOMXmlSerializer *iface, IHTMLDOMNode *node, BSTR *pString) +{ + struct xml_serializer *This = impl_from_IDOMXmlSerializer(iface); + HTMLDOMNode *dom_node; + nsAString nsstr; + HRESULT hres; + + TRACE("(%p)->(%p %p)\n", This, node, pString); + + if(!node || !pString) + return E_INVALIDARG; + + *pString = NULL; + + dom_node = unsafe_impl_from_IHTMLDOMNode(node); + if(!dom_node) { + WARN("not an HTMLDOMNode\n"); + return E_INVALIDARG; + } + + nsAString_Init(&nsstr, NULL); + hres = nsnode_to_nsstring(dom_node->nsnode, &nsstr); + if(SUCCEEDED(hres)) { + const WCHAR *str; + nsAString_GetData(&nsstr, &str); + *pString = SysAllocString(str); + if(!*pString) + hres = E_OUTOFMEMORY; + } + nsAString_Finish(&nsstr); + + return hres; +} + +static const IDOMXmlSerializerVtbl xml_serializer_vtbl = { + xml_serializer_QueryInterface, + xml_serializer_AddRef, + xml_serializer_Release, + xml_serializer_GetTypeInfoCount, + xml_serializer_GetTypeInfo, + xml_serializer_GetIDsOfNames, + xml_serializer_Invoke, + xml_serializer_serializeToString +}; + +static inline struct xml_serializer *xml_serializer_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, struct xml_serializer, dispex); +} + +static void *xml_serializer_query_interface(DispatchEx *dispex, REFIID riid) +{ + struct xml_serializer *This = xml_serializer_from_DispatchEx(dispex); + + if(IsEqualGUID(&IID_IDOMXmlSerializer, riid)) + return &This->IDOMXmlSerializer_iface; + + return NULL; +} + +static void xml_serializer_destructor(DispatchEx *dispex) +{ + struct xml_serializer *This = xml_serializer_from_DispatchEx(dispex); + free(This); +} + +static HRESULT init_xml_serializer_ctor(struct constructor*); + +static const dispex_static_data_vtbl_t xml_serializer_dispex_vtbl = { + .query_interface = xml_serializer_query_interface, + .destructor = xml_serializer_destructor, +}; + +static const tid_t xml_serializer_iface_tids[] = { + IDOMXmlSerializer_tid, + 0 +}; + +dispex_static_data_t XMLSerializer_dispex = { + .id = OBJID_XMLSerializer, + .init_constructor = &init_xml_serializer_ctor, + .vtbl = &xml_serializer_dispex_vtbl, + .disp_tid = DispXMLSerializer_tid, + .iface_tids = xml_serializer_iface_tids, +}; + +static HRESULT xml_serializer_ctor_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + struct constructor *This = constructor_from_DispatchEx(dispex); + struct xml_serializer *ret; + + TRACE("\n"); + + switch(flags) { + case DISPATCH_METHOD|DISPATCH_PROPERTYGET: + if(!res) + return E_INVALIDARG; + /* fall through */ + case DISPATCH_METHOD: + case DISPATCH_CONSTRUCT: + break; + default: + FIXME("flags %x not supported\n", flags); + return E_NOTIMPL; + } + + if(!(ret = calloc(1, sizeof(*ret)))) + return E_OUTOFMEMORY; + + ret->IDOMXmlSerializer_iface.lpVtbl = &xml_serializer_vtbl; + init_dispatch(&ret->dispex, &XMLSerializer_dispex, This->window, dispex_compat_mode(&This->dispex)); + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch*)&ret->IDOMXmlSerializer_iface; + return S_OK; +} + +static const dispex_static_data_vtbl_t xml_serializer_ctor_dispex_vtbl = { + .destructor = constructor_destructor, + .traverse = constructor_traverse, + .unlink = constructor_unlink, + .value = xml_serializer_ctor_value, +}; + +static dispex_static_data_t xml_serializer_ctor_dispex = { + .name = "XMLSerializer", + .constructor_id = OBJID_XMLSerializer, + .vtbl = &xml_serializer_ctor_dispex_vtbl, +}; + +static HRESULT init_xml_serializer_ctor(struct constructor *constr) +{ + init_dispatch(&constr->dispex, &xml_serializer_ctor_dispex, constr->window, + dispex_compat_mode(&constr->window->event_target.dispex)); + return S_OK; +} + typedef struct { DispatchEx dispex; IHTMLScreen IHTMLScreen_iface; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index dadd7ba6b04..71a14a7d322 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4453,6 +4453,7 @@ sync_test("prototype props", function() { check(DocumentFragment, [ ["attachEvent",9,10], ["detachEvent",9,10], "querySelector", "querySelectorAll", "removeNode", "replaceNode", "swapNode" ]); check(DocumentType, [ "entities", "internalSubset", "name", "notations", "publicId", "systemId" ]); check(DOMParser, [ "parseFromString" ]); + check(XMLSerializer, [ "serializeToString" ]); check(Element, [ "childElementCount", "clientHeight", "clientLeft", "clientTop", "clientWidth", ["fireEvent",9,10], "firstElementChild", "getAttribute", "getAttributeNS", "getAttributeNode", "getAttributeNodeNS", "getBoundingClientRect", "getClientRects", @@ -4895,7 +4896,7 @@ async_test("window own props", function() { ["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], - ["XMLHttpRequestEventTarget",10], "XMLSerializer" + ["XMLHttpRequestEventTarget",10] ]); next_test(); } diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index 92c1deb64d3..8502db62823 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -1170,3 +1170,27 @@ sync_test("document.open", function() { doc.close(); ok(doc.onclick === f, "doc.onclick != f"); }); + +sync_test("XMLSerializer", function() { + var serializer = new XMLSerializer(); + ok(serializer !== null, "XMLSerializer constructor returned null"); + ok(typeof serializer === "object", "XMLSerializer is not an object"); + + /* Test serializeToString with a simple element */ + var div = document.createElement("div"); + div.id = "testdiv"; + div.innerHTML = "test content"; + + var result = serializer.serializeToString(div); + ok(/<div .*id="testdiv">test content<\/div>/.test(result), "unexpected result " + result); + + /* Test with nested elements */ + div = document.createElement("div"); + div.innerHTML = '<span attr="attrval">nested</span>'; + result = serializer.serializeToString(div); + ok(/<div.*><span attr="attrval">nested<\/span><\/div>/.test(result), "unexpected result " + result); + + /* Test with text node */ + result = serializer.serializeToString(document.createTextNode("plain text")); + ok(result === "plain text", "serialized text node missing content: " + result); +}); diff --git a/include/mshtmdid.h b/include/mshtmdid.h index 45b22f6349f..a87c12c7de8 100644 --- a/include/mshtmdid.h +++ b/include/mshtmdid.h @@ -107,6 +107,7 @@ #define DISPID_XMLHTTPREQUEST DISPID_NORMAL_FIRST #define DISPID_XDOMAINREQUEST DISPID_NORMAL_FIRST #define DISPID_DOMPARSER DISPID_NORMAL_FIRST +#define DISPID_XMLSERIALIZER DISPID_NORMAL_FIRST #define DISPID_DOCUMENTCOMPATIBLEINFO_COLLECTION DISPID_NORMAL_FIRST #define DISPID_DOCUMENTCOMPATIBLEINFO DISPID_NORMAL_FIRST #define DISPID_XDOMAINREQUEST DISPID_NORMAL_FIRST @@ -4676,6 +4677,9 @@ /* IDOMParser */ #define DISPID_IDOMPARSER_PARSEFROMSTRING DISPID_DOMPARSER +/* IXMLSerializer */ +#define DISPID_IDOMXMLSERIALIZER_SERIALIZETOSTRING DISPID_XMLSERIALIZER + /* IEventTarget */ #define DISPID_IEVENTTARGET_ADDEVENTLISTENER DISPID_HTMLOBJECT+10 #define DISPID_IEVENTTARGET_REMOVEEVENTLISTENER DISPID_HTMLOBJECT+11 diff --git a/include/mshtml.idl b/include/mshtml.idl index 1d2896f88b8..14a05f7ff9a 100644 --- a/include/mshtml.idl +++ b/include/mshtml.idl @@ -30286,6 +30286,46 @@ coclass DOMParser interface IDOMParser; } +/***************************************************************************** + * IDOMXmlSerializer interface + */ +[ + object, + oleautomation, + dual, + uuid(3051077d-98b5-11cf-bb82-00aa00bdce0b) +] +interface IDOMXmlSerializer : IDispatch +{ + [id(DISPID_IDOMXMLSERIALIZER_SERIALIZETOSTRING)] + HRESULT serializeToString([in] IHTMLDOMNode *node, [retval, out] BSTR *pString); +} + +/***************************************************************************** + * DispXMLSerializer dispinterface + */ +[ + hidden, + uuid(305900ad-98b5-11cf-bb82-00aa00bdce0b) +] +dispinterface DispXMLSerializer +{ +properties: +methods: + [id(DISPID_IDOMXMLSERIALIZER_SERIALIZETOSTRING)] + BSTR serializeToString([in] IHTMLDOMNode *node); +} + +[ + noncreatable, + uuid(3051077e-98b5-11cf-bb82-00aa00bdce0b) +] +coclass XMLSerializer +{ + [default] dispinterface DispXMLSerializer; + interface IDOMXmlSerializer; +} + /***************************************************************************** * IXMLGenericParse interface */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10063
This merge request was approved by Jacek Caban. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10063
Gabriel Ivăncescu (@insn) commented about dlls/mshtml/tests/documentmode.js:
check(DocumentFragment, [ ["attachEvent",9,10], ["detachEvent",9,10], "querySelector", "querySelectorAll", "removeNode", "replaceNode", "swapNode" ]); check(DocumentType, [ "entities", "internalSubset", "name", "notations", "publicId", "systemId" ]); check(DOMParser, [ "parseFromString" ]); + check(XMLSerializer, [ "serializeToString" ]);
Just a nitpick, but I think it's nicer to place this alphabetically like all the others. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10063#note_129353
participants (3)
-
Gabriel Ivăncescu (@insn) -
Jacek Caban (@jacek) -
Phiality