From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 8 ++++++++ dlls/mshtml/tests/documentmode.js | 4 ++++ 2 files changed, 12 insertions(+)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 111f3377ff9..b7284c8b935 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2007,6 +2007,14 @@ BOOL dispex_builtin_is_noattr(DispatchEx *dispex, DISPID id) hres = get_builtin_func(dispex->info, id, &func); assert(SUCCEEDED(hres));
+ if(func->func_disp_idx >= 0 && dispex->dynamic_data && dispex->dynamic_data->func_disps) { + func_obj_entry_t *entry = dispex->dynamic_data->func_disps + func->func_disp_idx; + + if(entry->func_obj && (V_VT(&entry->val) != VT_DISPATCH || + V_DISPATCH(&entry->val) != (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface)) + return FALSE; + } + return func->noattr; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 13772b52606..f6d61ec01d4 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -642,6 +642,7 @@ sync_test("attr_props", function() {
elem.setAttribute("test", "wine"); elem.setAttribute("z-index", "foobar"); + elem.setAttribute("removeAttribute", "funcattr");
attr = elem.getAttributeNode("test"); test_attr(true, true); @@ -649,6 +650,9 @@ sync_test("attr_props", function() { attr = elem.getAttributeNode("z-index"); test_attr(true, true);
+ attr = elem.getAttributeNode("removeAttribute"); + ok(attr !== null, "removeAttribute attr = null"); + attr = elem.getAttributeNode("tabIndex"); if(v < 8) test_attr(false, false);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 14 ++++++++++++++ dlls/mshtml/htmlelem.c | 5 +++++ dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/documentmode.js | 16 ++++++++++++++++ 4 files changed, 36 insertions(+)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index b7284c8b935..eee1c851cf4 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2018,6 +2018,20 @@ BOOL dispex_builtin_is_noattr(DispatchEx *dispex, DISPID id) return func->noattr; }
+BOOL dispex_prop_is_noattr(DispatchEx *dispex, DISPID id) +{ + func_info_t *func; + HRESULT hres; + + if(get_dispid_type(id) != DISPEXPROP_BUILTIN) + return FALSE; + + hres = get_builtin_func(dispex->info, id, &func); + assert(SUCCEEDED(hres)); + + return func->func_disp_idx < 0 && func->noattr; +} + static inline DispatchEx *impl_from_IWineJSDispatchHost(IWineJSDispatchHost *iface) { return CONTAINING_RECORD(iface, DispatchEx, IWineJSDispatchHost_iface); diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index fe57bc0dfef..dd7962de2a1 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -1169,6 +1169,11 @@ static HRESULT set_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, V return S_OK; }
+ if(dispid != DISPID_IHTMLELEMENT_CLASSNAME && dispex_prop_is_noattr(&elem->node.event_target.dispex, dispid)) { + /* Unimplemented in IE < 8 */ + return E_NOTIMPL; + } + return dispex_prop_put(&elem->node.event_target.dispex, dispid, LOCALE_SYSTEM_DEFAULT, v, &ei, NULL); }
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 3dc41bae967..b002c94a2f2 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -637,6 +637,7 @@ const void *dispex_get_vtbl(DispatchEx*); void dispex_info_add_interface(dispex_data_t*,tid_t,const dispex_hook_t*); void dispex_info_add_dispids(dispex_data_t*,tid_t,const DISPID*); compat_mode_t dispex_compat_mode(DispatchEx*); +BOOL dispex_prop_is_noattr(DispatchEx*,DISPID); HRESULT dispex_to_string(DispatchEx*,BSTR*); HRESULT dispex_call_builtin(DispatchEx *dispex, DISPID id, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index f6d61ec01d4..06f5d588a4a 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -644,6 +644,15 @@ sync_test("attr_props", function() { elem.setAttribute("z-index", "foobar"); elem.setAttribute("removeAttribute", "funcattr");
+ try { + elem.setAttribute("offsetLeft", "0"); + ok(v >= 8, "setAttribute(offsetLeft) didn't throw"); + }catch(e) { + todo_wine_if(v === 8). + ok(v < 8, "setAttribute(offsetLeft) threw"); + ok(e.number === 0x04001 - 0x80000000, "setAttribute(offsetLeft) threw " + e.number); + } + attr = elem.getAttributeNode("test"); test_attr(true, true);
@@ -653,6 +662,13 @@ sync_test("attr_props", function() { attr = elem.getAttributeNode("removeAttribute"); ok(attr !== null, "removeAttribute attr = null");
+ attr = elem.getAttributeNode("offsetLeft"); + if(v < 8) + ok(attr === null, "offsetLeft attr != null"); + else + todo_wine_if(v === 8). + ok(attr !== null, "offsetLeft attr = null"); + attr = elem.getAttributeNode("tabIndex"); if(v < 8) test_attr(false, false);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
'expando' returns TRUE on non-builtin attributes (builtin attributes are only the builtin props, not methods), while 'specified' always returns TRUE on any non-builtin attribute as long as it has a user-defined value (e.g. for builtin methods, their slot must be non-default), which is an extension to just checking the dynamic props.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 37 +++++++++++++++++++++++++++++++ dlls/mshtml/htmlattr.c | 4 ++-- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/tests/documentmode.js | 2 +- 4 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index eee1c851cf4..16bd4613806 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1875,6 +1875,43 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) } }
+BOOL is_builtin_attribute(DispatchEx *dispex, DISPID id) +{ + func_info_t *func; + + if(get_dispid_type(id) != DISPEXPROP_BUILTIN) + return FALSE; + + if(FAILED(get_builtin_func(dispex->info, id, &func))) + return FALSE; + + return func->func_disp_idx < 0; +} + +BOOL is_builtin_value(DispatchEx *dispex, DISPID id) +{ + func_info_t *func; + + if(get_dispid_type(id) != DISPEXPROP_BUILTIN) + return FALSE; + + if(FAILED(get_builtin_func(dispex->info, id, &func))) + return FALSE; + + if(func->func_disp_idx < 0) + return TRUE; + + if(dispex->dynamic_data && dispex->dynamic_data->func_disps) { + func_obj_entry_t *entry = dispex->dynamic_data->func_disps + func->func_disp_idx; + + if(entry->func_obj && (V_VT(&entry->val) != VT_DISPATCH || + V_DISPATCH(&entry->val) != (IDispatch*)&entry->func_obj->dispex.IWineJSDispatchHost_iface)) + return FALSE; + } + + return TRUE; +} + static dispex_data_t *ensure_dispex_info(dispex_static_data_t *desc, compat_mode_t compat_mode) { if(!desc->info_cache[compat_mode]) { diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c index 634293a75b2..1e6ffed6de8 100644 --- a/dlls/mshtml/htmlattr.c +++ b/dlls/mshtml/htmlattr.c @@ -115,7 +115,7 @@ static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, V return S_OK; }
- if(get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN) { + if(!is_builtin_value(&This->elem->node.event_target.dispex, This->dispid)) { *p = VARIANT_TRUE; return S_OK; } @@ -251,7 +251,7 @@ static HRESULT WINAPI HTMLDOMAttribute2_get_expando(IHTMLDOMAttribute2 *iface, V return hres; }
- *p = variant_bool(This->elem && get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN); + *p = variant_bool(This->elem && !is_builtin_attribute(&This->elem->node.event_target.dispex, This->dispid)); return S_OK; }
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index b002c94a2f2..9f1055be75a 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -630,6 +630,8 @@ HRESULT change_type(VARIANT*,VARIANT*,VARTYPE,IServiceProvider*); HRESULT dispex_get_dprop_ref(DispatchEx*,const WCHAR*,BOOL,VARIANT**); HRESULT get_dispids(tid_t,DWORD*,DISPID**); HRESULT remove_attribute(DispatchEx*,DISPID,VARIANT_BOOL*); +BOOL is_builtin_attribute(DispatchEx*,DISPID); +BOOL is_builtin_value(DispatchEx*,DISPID); HRESULT dispex_get_dynid(DispatchEx*,const WCHAR*,BOOL,DISPID*); void release_typelib(void); HRESULT get_class_typeinfo(const CLSID*,ITypeInfo**); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 06f5d588a4a..6fcc526f7e3 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -660,7 +660,7 @@ sync_test("attr_props", function() { test_attr(true, true);
attr = elem.getAttributeNode("removeAttribute"); - ok(attr !== null, "removeAttribute attr = null"); + test_attr(true, true);
attr = elem.getAttributeNode("offsetLeft"); if(v < 8)