[PATCH 6/7] mshtml: Allocate DISPIDs only for actual attributes in HTMLAttributeCollection.

Gabriel Ivăncescu gabrielopcode at gmail.com
Fri Oct 1 08:12:47 CDT 2021


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---

Presently, even toString() is exposed as an attribute, because it's a
builtin of the element, which makes no sense.

 dlls/mshtml/htmlattr.c            | 21 ++++-----------------
 dlls/mshtml/htmlelem.c            | 31 ++++++++++++++++++++++++++++++-
 dlls/mshtml/mshtml_private.h      |  1 +
 dlls/mshtml/tests/documentmode.js | 31 +++++++++++++++++++++++++++++++
 4 files changed, 66 insertions(+), 18 deletions(-)

diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c
index dc8c45e..b293d91 100644
--- a/dlls/mshtml/htmlattr.c
+++ b/dlls/mshtml/htmlattr.c
@@ -174,10 +174,7 @@ static HRESULT WINAPI HTMLDOMAttribute_get_nodeValue(IHTMLDOMAttribute *iface, V
 static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, VARIANT_BOOL *p)
 {
     HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
-    nsIDOMAttr *nsattr;
-    nsAString nsname;
     BSTR name;
-    nsresult nsres;
     HRESULT hres;
 
     TRACE("(%p)->(%p)\n", This, p);
@@ -196,22 +193,12 @@ static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, V
     if(FAILED(hres))
         return hres;
 
-    /* FIXME: This is not exactly right, we have some attributes that don't map directly to Gecko attributes. */
-    nsAString_InitDepend(&nsname, name);
-    nsres = nsIDOMElement_GetAttributeNode(This->elem->dom_element, &nsname, &nsattr);
-    nsAString_Finish(&nsname);
+    hres = is_elem_attr_specified(This->elem, name);
     SysFreeString(name);
-    if(NS_FAILED(nsres))
-        return E_FAIL;
+    if(FAILED(hres))
+        return hres;
 
-    /* If the Gecko attribute node can be found, we know that the attribute is specified.
-       There is no point in calling GetSpecified */
-    if(nsattr) {
-        nsIDOMAttr_Release(nsattr);
-        *p = VARIANT_TRUE;
-    }else {
-        *p = VARIANT_FALSE;
-    }
+    *p = (hres == S_OK) ? VARIANT_TRUE : VARIANT_FALSE;
     return S_OK;
 }
 
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index b07de03..c285a21 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -7169,6 +7169,28 @@ static HRESULT WINAPI HTMLAttributeCollection_Invoke(IHTMLAttributeCollection *i
             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
 }
 
+HRESULT is_elem_attr_specified(HTMLElement *elem, const WCHAR *name)
+{
+    nsIDOMAttr *nsattr;
+    nsAString nsname;
+    nsresult nsres;
+
+    /* FIXME: This is not exactly right, we have some attributes that don't map directly to Gecko attributes. */
+    nsAString_InitDepend(&nsname, name);
+    nsres = nsIDOMElement_GetAttributeNode(elem->dom_element, &nsname, &nsattr);
+    nsAString_Finish(&nsname);
+    if(NS_FAILED(nsres))
+        return E_FAIL;
+
+    /* If the Gecko attribute node can be found, we know that the attribute is specified.
+       There is no point in calling GetSpecified */
+    if(nsattr) {
+        nsIDOMAttr_Release(nsattr);
+        return S_OK;
+    }
+    return S_FALSE;
+}
+
 static HRESULT get_attr_dispid_by_idx(HTMLAttributeCollection *This, LONG *idx, DISPID *dispid)
 {
     IDispatchEx *dispex = &This->elem->node.event_target.dispex.IDispatchEx_iface;
@@ -7222,7 +7244,14 @@ static inline HRESULT get_attr_dispid_by_name(HTMLAttributeCollection *This, BST
 
     hres = IDispatchEx_GetDispID(&This->elem->node.event_target.dispex.IDispatchEx_iface,
             name, fdexNameCaseInsensitive, id);
-    return hres;
+    if(FAILED(hres))
+        return hres;
+
+    if(get_dispid_type(*id) != DISPEXPROP_BUILTIN)
+        return S_OK;
+
+    hres = is_elem_attr_specified(This->elem, name);
+    return (hres == S_FALSE) ? DISP_E_UNKNOWNNAME : hres;
 }
 
 static inline HRESULT get_domattr(HTMLAttributeCollection *This, DISPID id, LONG *list_pos, HTMLDOMAttribute **attr)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index c1e7e78..624963a 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -1161,6 +1161,7 @@ HRESULT create_child_collection(nsIDOMNodeList*,compat_mode_t,IHTMLDOMChildrenCo
 HRESULT attr_value_to_string(VARIANT*) DECLSPEC_HIDDEN;
 HRESULT get_elem_attr_value_by_dispid(HTMLElement*,DISPID,VARIANT*) DECLSPEC_HIDDEN;
 HRESULT get_elem_source_index(HTMLElement*,LONG*) DECLSPEC_HIDDEN;
+HRESULT is_elem_attr_specified(HTMLElement*,const WCHAR*) DECLSPEC_HIDDEN;
 
 nsresult get_elem_attr_value(nsIDOMElement*,const WCHAR*,nsAString*,const PRUnichar**) DECLSPEC_HIDDEN;
 HRESULT elem_string_attr_getter(HTMLElement*,const WCHAR*,BOOL,BSTR*) DECLSPEC_HIDDEN;
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index c20f6ee..41d7a6b 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -785,4 +785,35 @@ sync_test("elem_attr", function() {
     ok(r === "cls2", "class attr = " + r);
     r = elem.getAttribute("className");
     ok(r === "cls3", "className attr = " + r);
+
+    function test_exposed(prop, expect) {
+        if(expect)
+            ok(prop in elem.attributes, prop + " not found in elem.attributes.");
+        else
+            ok(!(prop in elem.attributes), prop + " found in elem.attributes.");
+    }
+
+    test_exposed("className", v >= 8);
+    test_exposed("doScroll", false);
+    test_exposed("readyState", false);
+    test_exposed("clientTop", false);
+    if (v >= 9 /* todo_wine */) test_exposed("title", v < 9);
+    test_exposed("querySelectorAll", false);
+    test_exposed("textContent", false);
+    test_exposed("prefix", false);
+    test_exposed("firstElementChild", false);
+    test_exposed("onsubmit", false);
+    test_exposed("getElementsByClassName", false);
+    test_exposed("removeAttributeNS", false);
+    test_exposed("addEventListener", false);
+    test_exposed("hasAttribute", false);
+    test_exposed("removeEventListener", false);
+    test_exposed("dispatchEvent", false);
+    test_exposed("msSetPointerCapture", false);
+    if (v >= 9 /* todo_wine */) test_exposed("spellcheck", v < 9);
+
+    if(v < 9)
+        test_exposed("toString", false);
+    else if(false /* todo_wine */)
+        ok(!elem.attributes.hasOwnProperty("toString"), "toString found in elem.attributes.");
 });
-- 
2.31.1




More information about the wine-devel mailing list