mshtml: Added IHTMLElement4::setAttributeNode implementation.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2016-03-30 14:39:57 +02:00 committed by Alexandre Julliard
parent 423b7ba1d1
commit 17fcc112ad
4 changed files with 143 additions and 20 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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);
}