Module: wine Branch: master Commit: 17fcc112ade167e602dc46981e8239b3ce576b51 URL: http://source.winehq.org/git/wine.git/?a=commit;h=17fcc112ade167e602dc46981e...
Author: Jacek Caban jacek@codeweavers.com Date: Wed Mar 30 14:39:57 2016 +0200
mshtml: Added IHTMLElement4::setAttributeNode implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/mshtml/htmlattr.c | 5 +++ dlls/mshtml/htmlelem.c | 96 ++++++++++++++++++++++++++++++++++++-------- dlls/mshtml/mshtml_private.h | 7 +++- dlls/mshtml/tests/dom.c | 55 ++++++++++++++++++++++++- 4 files changed, 143 insertions(+), 20 deletions(-)
diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c index 7a11245..e994eec 100644 --- a/dlls/mshtml/htmlattr.c +++ b/dlls/mshtml/htmlattr.c @@ -491,6 +491,11 @@ static dispex_static_data_t HTMLDOMAttribute_dispex = { HTMLDOMAttribute_iface_tids };
+HTMLDOMAttribute *unsafe_impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute *iface) +{ + return iface->lpVtbl == &HTMLDOMAttributeVtbl ? impl_from_IHTMLDOMAttribute(iface) : NULL; +} + HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dispid, HTMLDOMAttribute **attr) { HTMLAttributeCollection *col; diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index c7090e6..0329f1b 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -612,14 +612,27 @@ static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMembe wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); }
+static HRESULT set_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, VARIANT *v) +{ + DISPID propput_dispid = DISPID_PROPERTYPUT; + DISPPARAMS dp = {v, &propput_dispid, 1, 1}; + EXCEPINFO ei; + + if(dispid == DISPID_IHTMLELEMENT_STYLE) { + TRACE("Ignoring call on style attribute\n"); + return S_OK; + } + + return IDispatchEx_InvokeEx(&elem->node.event_target.dispex.IDispatchEx_iface, dispid, + LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL); +} + static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName, VARIANT AttributeValue, LONG lFlags) { HTMLElement *This = impl_from_IHTMLElement(iface); + DISPID dispid; HRESULT hres; - DISPID dispid, dispidNamed = DISPID_PROPERTYPUT; - DISPPARAMS dispParams; - EXCEPINFO excep;
TRACE("(%p)->(%s %s %08x)\n", This, debugstr_w(strAttributeName), debugstr_variant(&AttributeValue), lFlags);
@@ -628,18 +641,7 @@ static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttr if(FAILED(hres)) return hres;
- if(dispid == DISPID_IHTMLELEMENT_STYLE) { - TRACE("Ignoring call on style attribute\n"); - return S_OK; - } - - dispParams.cArgs = 1; - dispParams.cNamedArgs = 1; - dispParams.rgdispidNamedArgs = &dispidNamed; - dispParams.rgvarg = &AttributeValue; - - return IDispatchEx_InvokeEx(&This->node.event_target.dispex.IDispatchEx_iface, dispid, - LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParams, NULL, &excep, NULL); + return set_elem_attr_value_by_dispid(This, dispid, &AttributeValue); }
HRESULT get_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, VARIANT *ret) @@ -3718,8 +3720,68 @@ static HRESULT WINAPI HTMLElement4_setAttributeNode(IHTMLElement4 *iface, IHTMLD IHTMLDOMAttribute **ppretAttribute) { HTMLElement *This = impl_from_IHTMLElement4(iface); - FIXME("(%p)->(%p %p)\n", This, pattr, ppretAttribute); - return E_NOTIMPL; + HTMLDOMAttribute *attr, *iter, *replace = NULL; + HTMLAttributeCollection *attrs; + DISPID dispid; + HRESULT hres; + + TRACE("(%p)->(%p %p)\n", This, pattr, ppretAttribute); + + attr = unsafe_impl_from_IHTMLDOMAttribute(pattr); + if(!attr) + return E_INVALIDARG; + + if(attr->elem) { + WARN("Tried to set already attached attribute.\n"); + return E_INVALIDARG; + } + + hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface, + attr->name, fdexNameCaseInsensitive|fdexNameEnsure, &dispid); + if(FAILED(hres)) + return hres; + + hres = HTMLElement_get_attr_col(&This->node, &attrs); + if(FAILED(hres)) + return hres; + + LIST_FOR_EACH_ENTRY(iter, &attrs->attrs, HTMLDOMAttribute, entry) { + if(iter->dispid == dispid) { + replace = iter; + break; + } + } + + if(replace) { + hres = get_elem_attr_value_by_dispid(This, dispid, &replace->value); + if(FAILED(hres)) { + WARN("could not get attr value: %08x\n", hres); + V_VT(&replace->value) = VT_EMPTY; + } + if(!replace->name) { + replace->name = attr->name; + attr->name = NULL; + } + list_add_head(&replace->entry, &attr->entry); + list_remove(&replace->entry); + replace->elem = NULL; + }else { + list_add_tail(&attrs->attrs, &attr->entry); + } + + IHTMLDOMAttribute_AddRef(&attr->IHTMLDOMAttribute_iface); + attr->elem = This; + attr->dispid = dispid; + + IHTMLAttributeCollection_Release(&attrs->IHTMLAttributeCollection_iface); + + hres = set_elem_attr_value_by_dispid(This, dispid, &attr->value); + if(FAILED(hres)) + WARN("Could not set attribute value: %08x\n", hres); + VariantClear(&attr->value); + + *ppretAttribute = replace ? &replace->IHTMLDOMAttribute_iface : NULL; + return S_OK; }
static HRESULT WINAPI HTMLElement4_removeAttributeNode(IHTMLElement4 *iface, IHTMLDOMAttribute *pattr, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 611cb8b..37c33d5 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -943,15 +943,18 @@ typedef struct {
LONG ref;
- /* name and value are valid only for detached attributes (when elem == NULL). */ - WCHAR *name; + /* value is valid only for detached attributes (when elem == NULL). */ VARIANT value; + /* name must be valid for detached attributes */ + WCHAR *name;
HTMLElement *elem; DISPID dispid; struct list entry; } HTMLDOMAttribute;
+HTMLDOMAttribute *unsafe_impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute*) DECLSPEC_HIDDEN; + HRESULT HTMLDOMAttribute_Create(const WCHAR*,HTMLElement*,DISPID,HTMLDOMAttribute**) DECLSPEC_HIDDEN;
HRESULT HTMLElement_Create(HTMLDocumentNode*,nsIDOMNode*,BOOL,HTMLElement**) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 6d6a1e8..dcff793 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -8524,8 +8524,10 @@ static void test_elems(IHTMLDocument2 *doc)
static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem) { - IHTMLDOMAttribute *attr, *attr2; + IHTMLDOMAttribute *attr, *attr2, *attr3; + IHTMLElement4 *elem4; VARIANT v; + HRESULT hres;
get_elem_attr_node((IUnknown*)elem, "noattr", FALSE);
@@ -8636,6 +8638,57 @@ static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem) SysFreeString(V_BSTR(&v)); test_attr_value(attr, "testing");
+ elem4 = get_elem4_iface((IUnknown*)elem); + + hres = IHTMLElement4_setAttributeNode(elem4, attr, &attr2); + ok(hres == S_OK, "setAttributeNode failed: %08x\n", hres); + ok(!attr2, "attr2 != NULL\n"); + + test_elem_attr(elem, "Test", "testing"); + put_attr_value(attr, "new value"); + test_elem_attr(elem, "Test", "new value"); + + attr2 = get_elem_attr_node((IUnknown*)elem, "Test", TRUE); + ok(iface_cmp((IUnknown*)attr2, (IUnknown*)attr), "attr2 != attr\n"); + IHTMLDOMAttribute_Release(attr2); + + attr3 = create_attr((IUnknown*)doc, "Test"); + put_attr_value(attr3, "replace test"); + + hres = IHTMLElement4_setAttributeNode(elem4, attr3, &attr2); + ok(hres == S_OK, "setAttributeNode failed: %08x\n", hres); + ok(iface_cmp((IUnknown*)attr2, (IUnknown*)attr), "attr2 != attr\n"); + IHTMLDOMAttribute_Release(attr2); + + test_elem_attr(elem, "Test", "replace test"); + test_attr_value(attr, "new value"); + test_attr_value(attr3, "replace test"); + + attr2 = get_elem_attr_node((IUnknown*)elem, "Test", TRUE); + ok(iface_cmp((IUnknown*)attr2, (IUnknown*)attr3), "attr2 != attr3\n"); + IHTMLDOMAttribute_Release(attr2); + + put_attr_value(attr, "new value2"); + test_elem_attr(elem, "Test", "replace test"); + test_attr_value(attr, "new value2"); + test_attr_value(attr3, "replace test"); + + put_attr_value(attr3, "new replace value"); + test_elem_attr(elem, "Test", "new replace value"); + test_attr_value(attr, "new value2"); + test_attr_value(attr3, "new replace value"); + + /* Attached attributes cause errors. */ + hres = IHTMLElement4_setAttributeNode(elem4, attr3, &attr2); + ok(hres == E_INVALIDARG, "setAttributeNode failed: %08x, expected E_INVALIDARG\n", hres); + IHTMLDOMAttribute_Release(attr3); + + attr2 = get_elem_attr_node((IUnknown*)elem, "id", TRUE); + hres = IHTMLElement4_setAttributeNode(elem4, attr2, &attr3); + ok(hres == E_INVALIDARG, "setAttributeNode failed: %08x, expected E_INVALIDARG\n", hres); + IHTMLDOMAttribute_Release(attr2); + + IHTMLElement4_Release(elem4); IHTMLDOMAttribute_Release(attr); }