Signed-off-by: Gabriel Ivăncescu gabrielopcode@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);