[PATCH v8 09/11] mshtml: Fix getAttribute for props that weren't set yet in IE8 mode.

Gabriel Ivăncescu gabrielopcode at gmail.com
Thu Nov 25 08:00:45 CST 2021


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/mshtml/dispex.c              |  2 +-
 dlls/mshtml/htmlelem.c            | 57 ++++++++++++++++++++++++++-----
 dlls/mshtml/mshtml_private.h      |  1 +
 dlls/mshtml/tests/documentmode.js |  1 -
 4 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index 846a678..b9d43e8 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -535,7 +535,7 @@ static dispex_data_t *preprocess_dispex_data(dispex_static_data_t *desc, compat_
                     continue;
             }
 
-            func->hook = func->put_vtbl_off ? NULL : prop_hooks->ro_prop_hook;
+            func->hook = func->put_vtbl_off ? prop_hooks->rw_prop_hook : prop_hooks->ro_prop_hook;
         }
     }
 
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index b87e23d..d8ed0ac 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -1212,6 +1212,7 @@ static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttr
     nsresult nsres;
     DISPID dispid;
     HRESULT hres;
+    cpp_bool b;
 
     TRACE("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
 
@@ -1244,18 +1245,26 @@ static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttr
     }
 
     if(This->dom_element && compat_mode >= COMPAT_MODE_IE8 && get_dispid_type(dispid) == DISPEXPROP_BUILTIN) {
+        nsAString_InitDepend(&name_str, strAttributeName);
+
         if(is_readonly_builtin(&This->node.event_target.dispex, dispid)) {
-            nsAString_InitDepend(&name_str, strAttributeName);
             nsAString_InitDepend(&value_str, NULL);
             nsres = nsIDOMElement_GetAttribute(This->dom_element, &name_str, &value_str);
             nsAString_Finish(&name_str);
             return return_nsstr_variant(nsres, &value_str, 0, AttributeValue);
         }
 
-        hres = get_elem_attr_value_by_dispid(This, dispid, AttributeValue);
-        if(SUCCEEDED(hres) && V_VT(AttributeValue) != VT_BSTR) {
-            VariantClear(AttributeValue);
+        nsres = nsIDOMElement_HasAttribute(This->dom_element, &name_str, &b);
+        nsAString_Finish(&name_str);
+        if(NS_SUCCEEDED(nsres) && b) {
+            hres = get_elem_attr_value_by_dispid(This, dispid, AttributeValue);
+            if(SUCCEEDED(hres) && V_VT(AttributeValue) != VT_BSTR) {
+                VariantClear(AttributeValue);
+                V_VT(AttributeValue) = VT_NULL;
+            }
+        }else {
             V_VT(AttributeValue) = VT_NULL;
+            hres = S_OK;
         }
         return hres;
     }
@@ -1284,6 +1293,7 @@ static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strA
 {
     HTMLElement *This = impl_from_IHTMLElement(iface);
     compat_mode_t compat_mode = dispex_compat_mode(&This->node.event_target.dispex);
+    VARIANT_BOOL tmp;
     DISPID id;
     HRESULT hres;
 
@@ -1296,10 +1306,12 @@ static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strA
 
     if(compat_mode >= COMPAT_MODE_IE8) {
         *pfSuccess = element_has_attribute(This, strAttributeName);
-        if(*pfSuccess)
-            return element_remove_attribute(This, strAttributeName);
         if(compat_mode >= COMPAT_MODE_IE9)
-            return S_OK;
+            return *pfSuccess ? element_remove_attribute(This, strAttributeName) : S_OK;
+
+        /* remove the prop without influencing the return value */
+        if(*pfSuccess)
+            pfSuccess = &tmp;
     }
 
     hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, strAttributeName,
@@ -1332,7 +1344,10 @@ static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strA
         return S_OK;
     }
 
-    return remove_attribute(&This->node.event_target.dispex, id, pfSuccess);
+    hres = remove_attribute(&This->node.event_target.dispex, id, pfSuccess);
+    if(compat_mode >= COMPAT_MODE_IE8)
+        element_remove_attribute(This, strAttributeName);
+    return hres;
 }
 
 static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v)
@@ -6722,6 +6737,31 @@ static HRESULT ie8_ro_prop_hook(DispatchEx *dispex, BSTR name, LCID lcid, WORD f
     return S_OK;
 }
 
+static HRESULT ie8_rw_prop_hook(DispatchEx *dispex, BSTR name, LCID lcid, WORD flags,
+        DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
+{
+    HTMLElement *This = impl_from_DispatchEx(dispex);
+    nsAString name_str, val_str;
+    nsresult nsres;
+    cpp_bool b;
+
+    if(flags != DISPATCH_PROPERTYPUT || dp->cArgs != 1 || dp->cNamedArgs > 1 || V_VT(dp->rgvarg) != VT_BSTR ||
+       (dp->cNamedArgs == 1 && *dp->rgdispidNamedArgs != DISPID_PROPERTYPUT) || !This->dom_element)
+        return S_FALSE;
+
+    /* make sure attribute is set if it doesn't exist, for getAttribute checks */
+    nsAString_InitDepend(&name_str, name);
+    nsres = nsIDOMElement_HasAttribute(This->dom_element, &name_str, &b);
+    if(NS_SUCCEEDED(nsres) && !b) {
+        nsAString_InitDepend(&val_str, L"");
+        nsIDOMElement_SetAttribute(This->dom_element, &name_str, &val_str);
+        nsAString_Finish(&val_str);
+    }
+    nsAString_Finish(&name_str);
+
+    return S_FALSE;
+}
+
 const generic_prop_hooks_t *HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
 {
     static const dispex_hook_t elem2_ie11_hooks[] = {
@@ -6736,6 +6776,7 @@ const generic_prop_hooks_t *HTMLElement_init_dispex_info(dispex_data_t *info, co
     };
     static const generic_prop_hooks_t ie8_prop_hooks = {
         ie8_ro_prop_hook,
+        ie8_rw_prop_hook,
         ie8_prop_hooks_exclude_list
     };
 
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 0676a34..46da4a1 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -332,6 +332,7 @@ typedef struct {
 
 typedef struct {
     dispex_hook_invoke_t ro_prop_hook;
+    dispex_hook_invoke_t rw_prop_hook;
 
     const DISPID *exclude_list;
 } generic_prop_hooks_t;
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index bdd0a4a..6b3b9f3 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -1277,7 +1277,6 @@ sync_test("elem_attr", function() {
             var val = props[i].length > 2 ? props[i][2] : "test";
 
             r = elem.getAttribute(name);
-            todo_wine_if(v === 8 && props[i][0].substring(0, 2) !== "on").
             ok(r === (v < 8 && props[i].length > 1 ? props[i][1] : null), name + " attr before set = " + r);
             eval("elem." + name + " = \"" + val + "\"; r = elem." + name + ";");
             ok(r === val, "elem." + name + " = " + r);
-- 
2.31.1




More information about the wine-devel mailing list