From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 27 +++++++++++++++++++++++++++ dlls/mshtml/htmlelem.c | 21 +++++++++++++++++++++ dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/documentmode.js | 7 +++---- 4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 77eec049912..e9ef3ea9f98 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -701,6 +701,33 @@ dispex_prop_type_t get_dispid_type(DISPID id) return DISPEXPROP_BUILTIN; }
+BOOL is_custom_attribute(DispatchEx *dispex, const WCHAR *name) +{ + compat_mode_t compat_mode = dispex->info->compat_mode; + const dispex_data_t *info = dispex->info; + func_info_t **funcs = info->name_table; + DWORD a, b, i; + int c; + + assert(compat_mode >= COMPAT_MODE_IE9); + + for(;;) { + info = object_descriptors[info->desc->prototype_id]->prototype_info[compat_mode - COMPAT_MODE_IE9]; + funcs = info->name_table; + + for(a = 0, b = info->name_cnt; a < b;) { + i = (a + b) / 2; + c = wcsicmp(funcs[i]->name, name); + if(!c) + return (funcs[i]->func_disp_idx >= 0); + if(c > 0) b = i; + else a = i + 1; + } + if(!info->desc->prototype_id) + return DISP_E_UNKNOWNNAME; + } +} + static HRESULT variant_copy(VARIANT *dest, VARIANT *src) { if(V_VT(src) == VT_BSTR && !V_BSTR(src)) { diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index d1a7451b6fa..f988d394b45 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -552,6 +552,24 @@ static HTMLDOMAttribute *find_attr_in_list(HTMLAttributeCollection *attrs, DISPI return ret; }
+static DISPID get_dispid_for_nsattr(HTMLElement *elem, nsIDOMAttr *nsattr) +{ + DISPID dispid = 0; + nsAString nsstr; + + nsAString_InitDepend(&nsstr, NULL); + if(SUCCEEDED(nsIDOMAttr_GetName(nsattr, &nsstr))) { + const PRUnichar *name; + nsAString_GetData(&nsstr, &name); + + /* Supply a dummy non-builtin dispid so it can be checked for expando */ + if(is_custom_attribute(&elem->node.event_target.dispex, name)) + dispid = MSHTML_DISPID_CUSTOM_MIN; + nsAString_Finish(&nsstr); + } + return dispid; +} + typedef struct { DispatchEx dispex; IHTMLRect IHTMLRect_iface; @@ -4450,6 +4468,7 @@ static HRESULT WINAPI HTMLElement4_setAttributeNode(IHTMLElement4 *iface, IHTMLD IHTMLAttributeCollection_Release(&attrs->IHTMLAttributeCollection_iface); return E_FAIL; } + dispid = get_dispid_for_nsattr(This, nsattr); replace = NULL; if(oldnsattr) { replace = find_attr_in_list(attrs, 0, oldnsattr, NULL); @@ -7818,6 +7837,8 @@ static inline HRESULT get_domattr(HTMLAttributeCollection *This, DISPID id, nsID HRESULT hres;
if(!(*attr = find_attr_in_list(This, id, nsattr, list_pos))) { + if(nsattr) + id = get_dispid_for_nsattr(This->elem, nsattr); hres = HTMLDOMAttribute_Create(NULL, This->elem, id, This->elem->node.doc, nsattr, attr); if(FAILED(hres)) return hres; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 94f64bdb7ca..bc262292829 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -622,6 +622,7 @@ void dispex_props_unlink(DispatchEx*); HRESULT change_type(VARIANT*,VARIANT*,VARTYPE,IServiceProvider*); HRESULT dispex_get_dprop_ref(DispatchEx*,const WCHAR*,BOOL,VARIANT**); HRESULT get_dispids(tid_t,DWORD*,DISPID**); +BOOL is_custom_attribute(DispatchEx*,const WCHAR*); HRESULT remove_attribute(DispatchEx*,DISPID,VARIANT_BOOL*); HRESULT dispex_get_dynid(DispatchEx*,const WCHAR*,BOOL,DISPID*); void release_typelib(void); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 6cd970e9000..6e0c4dcb549 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -585,9 +585,8 @@ sync_test("attr_props", function() { ok(!(prop in attr), prop + " found in attribute."); }
- function test_attr(expando, specified, expando_todo) { + function test_attr(expando, specified) { var r = attr.expando; - todo_wine_if(expando_todo). ok(r === expando, attr.name + " attr.expando = " + r); r = attr.specified; ok(r === specified, attr.name + " attr.specified = " + r); @@ -629,10 +628,10 @@ sync_test("attr_props", function() { test_attr(false, true);
attr = elem.getAttributeNode("test"); - test_attr(true, true, v >= 9); + test_attr(true, true);
attr = elem.getAttributeNode("z-index"); - test_attr(true, true, v >= 9); + test_attr(true, true);
attr = elem.getAttributeNode("tabIndex"); if(v < 8)