From: Gabriel Ivăncescu gabrielopcode@gmail.com
Because we're supposed to translate styles here to what Gecko expects via the style table, we don't actually need to look up the *real* prototypes on the object (what it has currently in js code), but rather just the builtin list of style props of the object, which must include all the styles supported. So we look into the entire builtin prototype chain.
remove_attribute also only deals with builtin dispids, so it makes no sense to use it on the output of GetDispID in IE9+ modes. Legacy modes do remove all props though, added tests to confirm this.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 30 ++++++++++++++++++++++++------ dlls/mshtml/htmlstyle.c | 7 +++++-- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/documentmode.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 292ff8fa165..7cd74476492 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1321,19 +1321,19 @@ static HRESULT get_builtin_func(dispex_data_t *data, DISPID id, func_info_t **re return DISP_E_MEMBERNOTFOUND; }
-static HRESULT get_builtin_id(DispatchEx *This, const WCHAR *name, DWORD grfdex, DISPID *ret) +static HRESULT get_builtin_id(const dispex_data_t *info, const WCHAR *name, DWORD grfdex, DISPID *ret) { - int min = 0, max = This->info->name_cnt - 1, n, c; + int min = 0, max = info->name_cnt - 1, n, c;
while(min <= max) { n = (min+max)/2;
- c = wcsicmp(This->info->name_table[n]->name, name); + c = wcsicmp(info->name_table[n]->name, name); if(!c) { - if((grfdex & fdexNameCaseSensitive) && wcscmp(This->info->name_table[n]->name, name)) + if((grfdex & fdexNameCaseSensitive) && wcscmp(info->name_table[n]->name, name)) break;
- *ret = This->info->name_table[n]->id; + *ret = info->name_table[n]->id; return S_OK; }
@@ -1346,6 +1346,24 @@ static HRESULT get_builtin_id(DispatchEx *This, const WCHAR *name, DWORD grfdex, return DISP_E_UNKNOWNNAME; }
+HRESULT dispex_get_chain_builtin_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID *pid) +{ + compat_mode_t compat_mode = dispex->info->compat_mode; + const dispex_data_t *info = dispex->info; + HRESULT hres; + + assert(compat_mode >= COMPAT_MODE_IE9); + + for(;;) { + hres = get_builtin_id(info, name, flags, pid); + if(hres != DISP_E_UNKNOWNNAME) + return hres; + if(!info->desc->prototype_id) + return DISP_E_UNKNOWNNAME; + info = object_descriptors[info->desc->prototype_id]->prototype_info[compat_mode - COMPAT_MODE_IE9]; + } +} + HRESULT change_type(VARIANT *dst, VARIANT *src, VARTYPE vt, IServiceProvider *caller) { V_VT(dst) = VT_EMPTY; @@ -2049,7 +2067,7 @@ HRESULT dispex_get_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID return hres; }
- hres = get_builtin_id(dispex, name, flags, pid); + hres = get_builtin_id(dispex->info, name, flags, pid); if(hres != DISP_E_UNKNOWNNAME) return hres;
diff --git a/dlls/mshtml/htmlstyle.c b/dlls/mshtml/htmlstyle.c index 33655698d43..92dd9f853be 100644 --- a/dlls/mshtml/htmlstyle.c +++ b/dlls/mshtml/htmlstyle.c @@ -2936,12 +2936,15 @@ static HRESULT WINAPI HTMLStyle_removeAttribute(IHTMLStyle *iface, BSTR strAttri
style_entry = lookup_style_tbl(&This->css_style, strAttributeName); if(!style_entry) { + DWORD fdex = (lFlags & 1) ? fdexNameCaseSensitive : fdexNameCaseInsensitive; compat_mode_t compat_mode = dispex_compat_mode(&This->css_style.dispex); DISPID dispid; unsigned i;
- hres = dispex_get_id(&This->css_style.dispex, strAttributeName, - (lFlags & 1) ? fdexNameCaseSensitive : fdexNameCaseInsensitive, &dispid); + if(compat_mode < COMPAT_MODE_IE9) + hres = IWineJSDispatchHost_GetDispID(&This->css_style.dispex.IWineJSDispatchHost_iface, strAttributeName, fdex, &dispid); + else + hres = dispex_get_chain_builtin_id(&This->css_style.dispex, strAttributeName, fdex, &dispid); if(hres != S_OK) { *pfSuccess = VARIANT_FALSE; return S_OK; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index b190e7c4dc8..b006202befd 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -629,6 +629,7 @@ HRESULT dispex_prop_get(DispatchEx *dispex, DISPID id, LCID lcid, VARIANT *r, EX IServiceProvider *caller); HRESULT dispex_prop_put(DispatchEx *dispex, DISPID id, LCID lcid, VARIANT *v, EXCEPINFO *ei, IServiceProvider *caller); +HRESULT dispex_get_chain_builtin_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID *pid); HRESULT dispex_get_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID *pid); HRESULT dispex_next_id(DispatchEx *dispex, DISPID id, DISPID *ret); HRESULT dispex_prop_name(DispatchEx *dispex, DISPID id, BSTR *ret); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 071f76c11f0..306d65e5768 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -2596,6 +2596,36 @@ sync_test("builtins_diffs", function() { } });
+sync_test("style attribute", function() { + var r, v = document.documentMode, s = document.createElement("div").style; + + s.setAttribute("background-color", "black"); + s.foobar = "white"; + + r = s.getAttribute("background-color"); + ok(r === "black", "background-color = " + r); + r = s.foobar; + ok(r === "white", "foobar prop = " + r); + + r = s.removeAttribute("background-color"); + ok(r === true, "removeAttribute(background-color) returned " + r); + r = s.removeAttribute("border"); + ok(r === false, "removeAttribute(border) returned " + r); + r = s.removeAttribute("foobar"); + ok(r === (v < 9 ? true : false), "removeAttribute(foobar) returned " + r); + r = s.removeAttribute("barfoo"); + ok(r === false, "removeAttribute(barfoo) returned " + r); + + r = s.getAttribute("background-color"); + ok(r === "", "background-color after remove = " + r); + if(v < 9) + ok(!("foobar" in s), "foobar in style after remove"); + else { + r = s.foobar; + ok(r === "white", "foobar prop after remove = " + r); + } +}); + sync_test("nullDisp", function() { var v = document.documentMode, nullDisp = external.nullDisp, r;