[PATCH v3 04/17] mshtml: Implement HTMLElement's toString.

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Oct 6 10:11:34 CDT 2021


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/mshtml/htmlelem.c            | 181 +++++++++++++++++++++++++-----
 dlls/mshtml/tests/documentmode.js | 158 ++++++++++++++++++++++++++
 2 files changed, 310 insertions(+), 29 deletions(-)

diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index 2293a34..29deec9 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -46,32 +46,119 @@ typedef struct {
     HRESULT (*constructor)(HTMLDocumentNode*,nsIDOMElement*,HTMLElement**);
 } tag_desc_t;
 
+static HRESULT HTMLElement_Constr(HTMLDocumentNode*,nsIDOMElement*,HTMLElement**);
+
 static const tag_desc_t tag_descs[] = {
-    {L"A",         HTMLAnchorElement_Create},
-    {L"AREA",      HTMLAreaElement_Create},
-    {L"BODY",      HTMLBodyElement_Create},
-    {L"BUTTON",    HTMLButtonElement_Create},
-    {L"EMBED",     HTMLEmbedElement_Create},
-    {L"FORM",      HTMLFormElement_Create},
-    {L"FRAME",     HTMLFrameElement_Create},
-    {L"HEAD",      HTMLHeadElement_Create},
-    {L"HTML",      HTMLHtmlElement_Create},
-    {L"IFRAME",    HTMLIFrame_Create},
-    {L"IMG",       HTMLImgElement_Create},
-    {L"INPUT",     HTMLInputElement_Create},
-    {L"LABEL",     HTMLLabelElement_Create},
-    {L"LINK",      HTMLLinkElement_Create},
-    {L"META",      HTMLMetaElement_Create},
-    {L"OBJECT",    HTMLObjectElement_Create},
-    {L"OPTION",    HTMLOptionElement_Create},
-    {L"SCRIPT",    HTMLScriptElement_Create},
-    {L"SELECT",    HTMLSelectElement_Create},
-    {L"STYLE",     HTMLStyleElement_Create},
-    {L"TABLE",     HTMLTable_Create},
-    {L"TD",        HTMLTableCell_Create},
-    {L"TEXTAREA",  HTMLTextAreaElement_Create},
-    {L"TITLE",     HTMLTitleElement_Create},
-    {L"TR",        HTMLTableRow_Create}
+    {L"A",              HTMLAnchorElement_Create},
+    {L"ABBR",           HTMLElement_Constr},
+    {L"ACRONYM",        HTMLElement_Constr},
+    {L"ADDRESS",        HTMLElement_Constr},
+    {L"APPLET",         HTMLElement_Constr},
+    {L"AREA",           HTMLAreaElement_Create},
+    {L"ARTICLE",        HTMLElement_Constr},
+    {L"ASIDE",          HTMLElement_Constr},
+    {L"AUDIO",          HTMLElement_Constr},
+    {L"B",              HTMLElement_Constr},
+    {L"BASE",           HTMLElement_Constr},
+    {L"BASEFONT",       HTMLElement_Constr},
+    {L"BDO",            HTMLElement_Constr},
+    {L"BIG",            HTMLElement_Constr},
+    {L"BLOCKQUOTE",     HTMLElement_Constr},
+    {L"BODY",           HTMLBodyElement_Create},
+    {L"BR",             HTMLElement_Constr},
+    {L"BUTTON",         HTMLButtonElement_Create},
+    {L"CANVAS",         HTMLElement_Constr},
+    {L"CAPTION",        HTMLElement_Constr},
+    {L"CENTER",         HTMLElement_Constr},
+    {L"CITE",           HTMLElement_Constr},
+    {L"CODE",           HTMLElement_Constr},
+    {L"COL",            HTMLElement_Constr},
+    {L"COLGROUP",       HTMLElement_Constr},
+    {L"DATALIST",       HTMLElement_Constr},
+    {L"DD",             HTMLElement_Constr},
+    {L"DEL",            HTMLElement_Constr},
+    {L"DFN",            HTMLElement_Constr},
+    {L"DIR",            HTMLElement_Constr},
+    {L"DIV",            HTMLElement_Constr},
+    {L"DL",             HTMLElement_Constr},
+    {L"DT",             HTMLElement_Constr},
+    {L"EM",             HTMLElement_Constr},
+    {L"EMBED",          HTMLEmbedElement_Create},
+    {L"FIELDSET",       HTMLElement_Constr},
+    {L"FIGCAPTION",     HTMLElement_Constr},
+    {L"FIGURE",         HTMLElement_Constr},
+    {L"FONT",           HTMLElement_Constr},
+    {L"FOOTER",         HTMLElement_Constr},
+    {L"FORM",           HTMLFormElement_Create},
+    {L"FRAME",          HTMLFrameElement_Create},
+    {L"FRAMESET",       HTMLElement_Constr},
+    {L"H1",             HTMLElement_Constr},
+    {L"H2",             HTMLElement_Constr},
+    {L"H3",             HTMLElement_Constr},
+    {L"H4",             HTMLElement_Constr},
+    {L"H5",             HTMLElement_Constr},
+    {L"H6",             HTMLElement_Constr},
+    {L"HEAD",           HTMLHeadElement_Create},
+    {L"HEADER",         HTMLElement_Constr},
+    {L"HR",             HTMLElement_Constr},
+    {L"HTML",           HTMLHtmlElement_Create},
+    {L"I",              HTMLElement_Constr},
+    {L"IFRAME",         HTMLIFrame_Create},
+    {L"IMG",            HTMLImgElement_Create},
+    {L"INPUT",          HTMLInputElement_Create},
+    {L"INS",            HTMLElement_Constr},
+    {L"KBD",            HTMLElement_Constr},
+    {L"LABEL",          HTMLLabelElement_Create},
+    {L"LEGEND",         HTMLElement_Constr},
+    {L"LI",             HTMLElement_Constr},
+    {L"LINK",           HTMLLinkElement_Create},
+    {L"MAP",            HTMLElement_Constr},
+    {L"MARK",           HTMLElement_Constr},
+    {L"META",           HTMLMetaElement_Create},
+    {L"NAV",            HTMLElement_Constr},
+    {L"NOFRAMES",       HTMLElement_Constr},
+    {L"NOSCRIPT",       HTMLElement_Constr},
+    {L"OBJECT",         HTMLObjectElement_Create},
+    {L"OL",             HTMLElement_Constr},
+    {L"OPTGROUP",       HTMLElement_Constr},
+    {L"OPTION",         HTMLOptionElement_Create},
+    {L"P",              HTMLElement_Constr},
+    {L"PARAM",          HTMLElement_Constr},
+    {L"PRE",            HTMLElement_Constr},
+    {L"PROGRESS",       HTMLElement_Constr},
+    {L"Q",              HTMLElement_Constr},
+    {L"RP",             HTMLElement_Constr},
+    {L"RT",             HTMLElement_Constr},
+    {L"RUBY",           HTMLElement_Constr},
+    {L"S",              HTMLElement_Constr},
+    {L"SAMP",           HTMLElement_Constr},
+    {L"SCRIPT",         HTMLScriptElement_Create},
+    {L"SECTION",        HTMLElement_Constr},
+    {L"SELECT",         HTMLSelectElement_Create},
+    {L"SMALL",          HTMLElement_Constr},
+    {L"SOURCE",         HTMLElement_Constr},
+    {L"SPAN",           HTMLElement_Constr},
+    {L"STRIKE",         HTMLElement_Constr},
+    {L"STRONG",         HTMLElement_Constr},
+    {L"STYLE",          HTMLStyleElement_Create},
+    {L"SUB",            HTMLElement_Constr},
+    {L"SUP",            HTMLElement_Constr},
+    {L"TABLE",          HTMLTable_Create},
+    {L"TBODY",          HTMLElement_Constr},
+    {L"TD",             HTMLTableCell_Create},
+    {L"TEXTAREA",       HTMLTextAreaElement_Create},
+    {L"TFOOT",          HTMLElement_Constr},
+    {L"TH",             HTMLElement_Constr},
+    {L"THEAD",          HTMLElement_Constr},
+    {L"TITLE",          HTMLTitleElement_Create},
+    {L"TR",             HTMLTableRow_Create},
+    {L"TRACK",          HTMLElement_Constr},
+    {L"TT",             HTMLElement_Constr},
+    {L"U",              HTMLElement_Constr},
+    {L"UL",             HTMLElement_Constr},
+    {L"VAR",            HTMLElement_Constr},
+    {L"VIDEO",          HTMLElement_Constr},
+    {L"WBR",            HTMLElement_Constr}
 };
 
 static const tag_desc_t *get_tag_desc(const WCHAR *tag_name)
@@ -2114,8 +2201,21 @@ static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *
 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
 {
     HTMLElement *This = impl_from_IHTMLElement(iface);
-    FIXME("(%p)->(%p)\n", This, String);
-    return E_NOTIMPL;
+    HRESULT hres;
+    VARIANT var;
+
+    TRACE("(%p)->(%p)\n", This, String);
+
+    if(!String)
+        return E_INVALIDARG;
+
+    hres = IDispatchEx_InvokeEx(&This->node.event_target.dispex.IDispatchEx_iface, DISPID_VALUE,
+                                LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, NULL, &var, NULL, NULL);
+    if(SUCCEEDED(hres)) {
+        assert(V_VT(&var) == VT_BSTR);
+        *String = V_BSTR(&var);
+    }
+    return hres;
 }
 
 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
@@ -6789,6 +6889,14 @@ static dispex_static_data_t HTMLElement_dispex = {
     HTMLElement_init_dispex_info
 };
 
+static dispex_static_data_t HTMLUnknownElement_dispex = {
+    L"HTMLUnknownElement",
+    &HTMLElement_event_target_vtbl.dispex_vtbl,
+    DispHTMLUnknownElement_tid,
+    HTMLElement_iface_tids,
+    HTMLElement_init_dispex_info
+};
+
 void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMElement *nselem, dispex_static_data_t *dispex_data)
 {
     This->IHTMLElement_iface.lpVtbl = &HTMLElementVtbl;
@@ -6810,7 +6918,7 @@ void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMElement *n
         nsIDOMHTMLElement *html_element;
         nsresult nsres;
 
-        HTMLDOMNode_Init(doc, &This->node, (nsIDOMNode*)nselem, dispex_data ? dispex_data : &HTMLElement_dispex);
+        HTMLDOMNode_Init(doc, &This->node, (nsIDOMNode*)nselem, dispex_data ? dispex_data : &HTMLUnknownElement_dispex);
 
         /* No AddRef, share reference with HTMLDOMNode */
         assert((nsIDOMNode*)nselem == This->node.nsnode);
@@ -6865,7 +6973,7 @@ HRESULT HTMLElement_Create(HTMLDocumentNode *doc, nsIDOMNode *nsnode, BOOL use_g
             elem = heap_alloc_zero(sizeof(HTMLElement));
             if(elem) {
                 elem->node.vtbl = &HTMLElementImplVtbl;
-                HTMLElement_Init(elem, doc, nselem, &HTMLElement_dispex);
+                HTMLElement_Init(elem, doc, nselem, &HTMLUnknownElement_dispex);
                 hres = S_OK;
             }else {
                 hres = E_OUTOFMEMORY;
@@ -6884,6 +6992,21 @@ HRESULT HTMLElement_Create(HTMLDocumentNode *doc, nsIDOMNode *nsnode, BOOL use_g
     return S_OK;
 }
 
+static HRESULT HTMLElement_Constr(HTMLDocumentNode *doc, nsIDOMElement *nselem, HTMLElement **elem)
+{
+    HTMLElement *ret;
+
+    ret = heap_alloc_zero(sizeof(*ret));
+    if(!ret)
+        return E_OUTOFMEMORY;
+
+    ret->node.vtbl = &HTMLElementImplVtbl;
+    HTMLElement_Init(ret, doc, nselem, &HTMLElement_dispex);
+
+    *elem = ret;
+    return S_OK;
+}
+
 HRESULT get_element(nsIDOMElement *nselem, HTMLElement **ret)
 {
     HTMLDOMNode *node;
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index c20f6ee..f62202a 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -19,6 +19,164 @@
 var compat_version;
 var tests = [];
 
+sync_test("builtin_toString", function() {
+    var tags = [
+        [ "abbr",            "Phrase" ],
+        [ "acronym",         "Phrase" ],
+        [ "address",         "Block" ],
+     // [ "applet",          "Applet" ],  // makes Windows pop up a dialog box
+        [ "article",         "" ],
+        [ "aside",           "" ],
+        [ "audio",           "Audio" ],
+        [ "b",               "Phrase" ],
+        [ "base",            "Base" ],
+        [ "basefont",        "BaseFont" ],
+        [ "bdi",             "Unknown" ],
+        [ "bdo",             "Phrase" ],
+        [ "big",             "Phrase" ],
+        [ "blockquote",      "Block" ],
+        [ "body",            "Body" ],
+        [ "br",              "BR" ],
+        [ "button",          "Button" ],
+        [ "canvas",          "Canvas" ],
+        [ "caption",         "TableCaption" ],
+        [ "center",          "Block" ],
+        [ "cite",            "Phrase" ],
+        [ "code",            "Phrase" ],
+        [ "col",             "TableCol" ],
+        [ "colgroup",        "TableCol" ],
+        [ "data",            "Unknown" ],
+        [ "datalist",        "DataList", 10 ],
+        [ "dd",              "DD" ],
+        [ "del",             "Mod" ],
+        [ "details",         "Unknown" ],
+        [ "dfn",             "Phrase" ],
+        [ "dialog",          "Unknown" ],
+        [ "dir",             "Directory" ],
+        [ "div",             "Div" ],
+        [ "dl",              "DList" ],
+        [ "dt",              "DT" ],
+        [ "em",              "Phrase" ],
+        [ "embed",           "Embed" ],
+        [ "fieldset",        "FieldSet" ],
+        [ "figcaption",      "" ],
+        [ "figure",          "" ],
+        [ "font",            "Font" ],
+        [ "footer",          "" ],
+        [ "form",            "Form" ],
+        [ "frame",           "Frame" ],
+        [ "frameset",        "FrameSet" ],
+        [ "h1",              "Heading" ],
+        [ "h2",              "Heading" ],
+        [ "h3",              "Heading" ],
+        [ "h4",              "Heading" ],
+        [ "h5",              "Heading" ],
+        [ "h6",              "Heading" ],
+        [ "h7",              "Unknown" ],
+        [ "head",            "Head" ],
+        [ "header",          "" ],
+        [ "hr",              "HR" ],
+        [ "html",            "Html" ],
+        [ "i",               "Phrase" ],
+        [ "iframe",          "IFrame" ],
+        [ "img",             "Image" ],
+        [ "input",           "Input" ],
+        [ "ins",             "Mod" ],
+        [ "kbd",             "Phrase" ],
+        [ "label",           "Label" ],
+        [ "legend",          "Legend" ],
+        [ "li",              "LI" ],
+        [ "link",            "Link" ],
+        [ "main",            "Unknown" ],
+        [ "map",             "Map" ],
+        [ "mark",            "" ],
+        [ "meta",            "Meta" ],
+        [ "meter",           "Unknown" ],
+        [ "nav",             "" ],
+        [ "noframes",        "" ],
+        [ "noscript",        "" ],
+        [ "object",          "Object" ],
+        [ "ol",              "OList" ],
+        [ "optgroup",        "OptGroup" ],
+        [ "option",          "Option" ],
+        [ "output",          "Unknown" ],
+        [ "p",               "Paragraph" ],
+        [ "param",           "Param" ],
+        [ "picture",         "Unknown" ],
+        [ "pre",             "Pre" ],
+        [ "progress",        "Progress", 10 ],
+        [ "q",               "Quote" ],
+        [ "rp",              "Phrase" ],
+        [ "rt",              "Phrase" ],
+        [ "ruby",            "Phrase" ],
+        [ "s",               "Phrase" ],
+        [ "samp",            "Phrase" ],
+        [ "script",          "Script" ],
+        [ "section",         "" ],
+        [ "select",          "Select" ],
+        [ "small",           "Phrase" ],
+        [ "source",          "Source" ],
+        [ "span",            "Span" ],
+        [ "strike",          "Phrase" ],
+        [ "strong",          "Phrase" ],
+        [ "style",           "Style" ],
+        [ "sub",             "Phrase" ],
+        [ "summary",         "Unknown" ],
+        [ "sup",             "Phrase" ],
+        [ "svg",             "Unknown" ],
+        [ "table",           "Table" ],
+        [ "tbody",           "TableSection" ],
+        [ "td",              "TableDataCell" ],
+        [ "template",        "Unknown" ],
+        [ "textarea",        "TextArea" ],
+        [ "tfoot",           "TableSection" ],
+        [ "th",              "TableHeaderCell" ],
+        [ "thead",           "TableSection" ],
+        [ "time",            "Unknown" ],
+        [ "title",           "Title" ],
+        [ "tr",              "TableRow" ],
+        [ "track",           "Track", 10 ],
+        [ "tt",              "Phrase" ],
+        [ "u",               "Phrase" ],
+        [ "ul",              "UList" ],
+        [ "var",             "Phrase" ],
+        [ "video",           "Video" ],
+        [ "wbr",             "" ],
+        [ "winetest",        "Unknown" ]
+    ];
+    var v = document.documentMode, e;
+
+    function test(msg, obj, name, tostr) {
+        var s;
+        if(!obj) {
+            win_skip(msg + " is buggy and not available, skipping");
+            return;
+        }
+        if(obj.toString) {
+            s = obj.toString();
+            todo_wine_if(name !== "HTMLElement" && s === "[object HTMLElement]").
+            ok(s === (tostr ? tostr : (v < 9 ? "[object]" : "[object " + name + "]")), msg + " toString returned " + s);
+        }
+        s = Object.prototype.toString.call(obj);
+        todo_wine_if(v >= 9 && name != "Object").
+        ok(s === (v < 9 ? "[object Object]" : "[object " + name + "]"), msg + " Object.toString returned " + s);
+    }
+
+    for(var i = 0; i < tags.length; i++)
+        if(tags[i].length < 3 || v >= tags[i][2])
+            test("tag '" + tags[i][0] + "'", document.createElement(tags[i][0]), "HTML" + tags[i][1] + "Element");
+
+    e = document.createElement("a");
+    ok(e.toString() === "", "tag 'a' (without href) toString returned " + e.toString());
+    e.href = "https://www.winehq.org/";
+    test("tag 'a'", e, "HTMLAnchorElement", "https://www.winehq.org/");
+
+    e = document.createElement("area");
+    ok(e.toString() === "", "tag 'area' (without href) toString returned " + e.toString());
+    e.href = "https://www.winehq.org/";
+    test("tag 'area'", e, "HTMLAreaElement", "https://www.winehq.org/");
+});
+
 sync_test("elem_props", function() {
     var elem = document.documentElement;
 
-- 
2.31.1




More information about the wine-devel mailing list