[PATCH v3 06/12] mshtml: Stringify attribute values in IE8+ mode when using setAttribute.

Gabriel Ivăncescu gabrielopcode at gmail.com
Thu Nov 18 10:44:45 CST 2021


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

Simplifies the next patch.

 dlls/mshtml/htmlelem.c       | 40 ++++++++++++++++++++++++++++--------
 dlls/mshtml/mshtml_private.h |  1 +
 dlls/mshtml/nsembed.c        | 24 +++++++++++++++++++++-
 3 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index f5500a3..07dea49 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -1086,34 +1086,56 @@ static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttr
                                                VARIANT AttributeValue, LONG lFlags)
 {
     HTMLElement *This = impl_from_IHTMLElement(iface);
+    compat_mode_t compat_mode = dispex_compat_mode(&This->node.event_target.dispex);
+    BOOL stringify = compat_mode >= COMPAT_MODE_IE8;
+    nsAString name_str, value_str;
+    BOOL needs_free = FALSE;
+    nsresult nsres;
     DISPID dispid;
     HRESULT hres;
 
     TRACE("(%p)->(%s %s %08x)\n", This, debugstr_w(strAttributeName), debugstr_variant(&AttributeValue), lFlags);
 
-    if(This->dom_element && dispex_compat_mode(&This->node.event_target.dispex) >= COMPAT_MODE_IE8) {
-        nsAString name_str, value_str;
-        nsresult nsres;
-
-        hres = variant_to_nsstr(&AttributeValue, 0, &value_str);
+    if(stringify) {
+        hres = variant_to_nsstr(&AttributeValue, VARIANT_TO_NSSTR_BSTR_DEPEND, &value_str);
         if(FAILED(hres))
             return hres;
 
+        if((V_VT(&AttributeValue) & ~VT_BYREF) != VT_BSTR)
+            needs_free = TRUE;
+
+        V_VT(&AttributeValue) = VT_BSTR;
+        nsAString_GetData(&value_str, (const WCHAR**)&V_BSTR(&AttributeValue));
+
+        if(!V_BSTR(&AttributeValue)) {
+            V_VT(&AttributeValue) = VT_NULL;
+            needs_free = FALSE;
+        }
+    }
+
+    if(stringify && This->dom_element) {
         nsAString_InitDepend(&name_str, strAttributeName);
         nsres = nsIDOMElement_SetAttribute(This->dom_element, &name_str, &value_str);
         nsAString_Finish(&name_str);
-        nsAString_Finish(&value_str);
         if(NS_FAILED(nsres))
             WARN("SetAttribute failed: %08x\n", nsres);
-        return map_nsresult(nsres);
+        hres = map_nsresult(nsres);
+        goto done;
     }
 
     hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, strAttributeName,
             (lFlags&ATTRFLAG_CASESENSITIVE ? fdexNameCaseSensitive : fdexNameCaseInsensitive) | fdexNameEnsure, &dispid);
     if(FAILED(hres))
-        return hres;
+        goto done;
+
+    hres = set_elem_attr_value_by_dispid(This, dispid, &AttributeValue);
 
-    return set_elem_attr_value_by_dispid(This, dispid, &AttributeValue);
+done:
+    if(stringify)
+        nsAString_Finish(&value_str);
+    if(needs_free)
+        SysFreeString(V_BSTR(&AttributeValue));
+    return hres;
 }
 
 HRESULT get_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, VARIANT *ret)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 66cd10a..3f04c62 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -1016,6 +1016,7 @@ HRESULT variant_to_nsstr(VARIANT*,DWORD,nsAString*) DECLSPEC_HIDDEN;
 HRESULT return_nsform(nsresult,nsIDOMHTMLFormElement*,IHTMLFormElement**) DECLSPEC_HIDDEN;
 
 #define VARIANT_TO_NSSTR_HEX_INT     0x01
+#define VARIANT_TO_NSSTR_BSTR_DEPEND 0x02
 
 nsICommandParams *create_nscommand_params(void) DECLSPEC_HIDDEN;
 HRESULT nsnode_to_nsstring(nsIDOMNode*,nsAString*) DECLSPEC_HIDDEN;
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c
index 5eb4edc..10d8bcf 100644
--- a/dlls/mshtml/nsembed.c
+++ b/dlls/mshtml/nsembed.c
@@ -1012,6 +1012,13 @@ HRESULT variant_to_nsstr(VARIANT *v, DWORD flags, nsAString *nsstr)
 
     case VT_I4:
         wsprintfW(buf, (flags & VARIANT_TO_NSSTR_HEX_INT) ? L"#%06x" : L"%d", V_I4(v));
+        if(flags & VARIANT_TO_NSSTR_BSTR_DEPEND) {
+            BSTR bstr = SysAllocString(buf);
+            if(!bstr)
+                return E_OUTOFMEMORY;
+            nsAString_InitDepend(nsstr, bstr);
+            break;
+        }
         nsAString_Init(nsstr, buf);
         break;
 
@@ -1022,6 +1029,10 @@ HRESULT variant_to_nsstr(VARIANT *v, DWORD flags, nsAString *nsstr)
         if(FAILED(hres))
             return hres;
 
+        if(flags & VARIANT_TO_NSSTR_BSTR_DEPEND) {
+            nsAString_InitDepend(nsstr, V_BSTR(&var));
+            break;
+        }
         nsAString_Init(nsstr, V_BSTR(&var));
         SysFreeString(V_BSTR(&var));
         break;
@@ -1040,15 +1051,26 @@ HRESULT variant_to_nsstr(VARIANT *v, DWORD flags, nsAString *nsstr)
             return hres;
 
         if(V_VT(&var) == VT_BSTR) {
+            if(flags & VARIANT_TO_NSSTR_BSTR_DEPEND) {
+                nsAString_InitDepend(nsstr, V_BSTR(&var));
+                break;
+            }
             nsAString_Init(nsstr, V_BSTR(&var));
             SysFreeString(V_BSTR(&var));
             break;
         }
         if(V_VT(&var) == (VT_BSTR | VT_BYREF)) {
+            if(flags & VARIANT_TO_NSSTR_BSTR_DEPEND) {
+                BSTR bstr = SysAllocString(*V_BSTRREF(&var));
+                if(!bstr)
+                    return E_OUTOFMEMORY;
+                nsAString_InitDepend(nsstr, bstr);
+                break;
+            }
             nsAString_Init(nsstr, *V_BSTRREF(&var));
             break;
         }
-        hres = variant_to_nsstr(&var, hex_int, nsstr);
+        hres = variant_to_nsstr(&var, flags, nsstr);
         VariantClear(&var);
         return hres;
     }
-- 
2.31.1




More information about the wine-devel mailing list