[PATCH 12/14] mshtml: Fix getAttribute for props that weren't set yet in IE8 mode.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Tue Nov 16 08:29:31 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 b30ca97..7824f6f 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 edc0e8e..62bf2fa 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -1219,6 +1219,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);
@@ -1251,18 +1252,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;
}
@@ -1293,6 +1302,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;
@@ -1305,10 +1315,12 @@ static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strA
if(compat_mode >= COMPAT_MODE_IE8) {
*pfSuccess = element_has_attribute(This, strAttributeName);
- if(*pfSuccess == VARIANT_TRUE)
- return element_remove_attribute(This, strAttributeName);
if(compat_mode >= COMPAT_MODE_IE9)
- return S_OK;
+ return (*pfSuccess == VARIANT_TRUE) ? element_remove_attribute(This, strAttributeName) : S_OK;
+
+ /* remove the prop without influencing the return value */
+ if(*pfSuccess == VARIANT_TRUE)
+ pfSuccess = &tmp;
}
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, strAttributeName,
@@ -1341,7 +1353,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)
@@ -6731,6 +6746,31 @@ static HRESULT ie8_ro_prop_hook(DispatchEx *dispex, DISPID id, BSTR name, LCID l
return S_OK;
}
+static HRESULT ie8_rw_prop_hook(DispatchEx *dispex, DISPID id, 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[] = {
@@ -6745,6 +6785,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 7683b73..afe75d6 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 d5fee5f..4f87316 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -1251,7 +1251,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