From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/htmldoc.c | 13 ------------- dlls/mshtml/htmlnode.c | 11 ++++------- dlls/mshtml/htmltextnode.c | 13 ------------- 3 files changed, 4 insertions(+), 33 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 3c3c344309a..05c98e0f377 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -235,28 +235,15 @@ static const IDOMDocumentTypeVtbl DocumentTypeVtbl = { DocumentType_get_internalSubset };
-static inline DocumentType *DocumentType_from_HTMLDOMNode(HTMLDOMNode *iface) -{ - return CONTAINING_RECORD(iface, DocumentType, node); -} - static inline DocumentType *DocumentType_from_DispatchEx(DispatchEx *iface) { return CONTAINING_RECORD(iface, DocumentType, node.event_target.dispex); }
-static HRESULT DocumentType_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode, HTMLDOMNode **ret) -{ - DocumentType *This = DocumentType_from_HTMLDOMNode(iface); - - return create_doctype_node(This->node.doc, nsnode, ret); -} - static const cpc_entry_t DocumentType_cpc[] = {{NULL}};
static const NodeImplVtbl DocumentTypeImplVtbl = { .cpc_entries = DocumentType_cpc, - .clone = DocumentType_clone };
static void *DocumentType_query_interface(DispatchEx *dispex, REFIID riid) diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index d838325a953..6b8daa00aea 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -705,7 +705,10 @@ static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fD return E_FAIL; }
- hres = This->vtbl->clone(This, nsnode, &new_node); + if(This->vtbl->clone) + hres = This->vtbl->clone(This, nsnode, &new_node); + else + hres = create_node(This->doc, nsnode, &new_node); nsIDOMNode_Release(nsnode); if(FAILED(hres)) return hres; @@ -1300,11 +1303,6 @@ void HTMLDOMNode_destructor(DispatchEx *dispex) free(This); }
-static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret) -{ - return create_node(This->doc, nsnode, ret); -} - void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode) { static const dispex_hook_t ie9_hooks[] = { @@ -1357,7 +1355,6 @@ static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
static const NodeImplVtbl HTMLDOMNodeImplVtbl = { .cpc_entries = HTMLDOMNode_cpc, - .clone = HTMLDOMNode_clone };
void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode, dispex_static_data_t *dispex_data) diff --git a/dlls/mshtml/htmltextnode.c b/dlls/mshtml/htmltextnode.c index 63886a4083c..217f123f086 100644 --- a/dlls/mshtml/htmltextnode.c +++ b/dlls/mshtml/htmltextnode.c @@ -370,18 +370,6 @@ static const IHTMLDOMTextNode2Vtbl HTMLDOMTextNode2Vtbl = { HTMLDOMTextNode2_replaceData };
-static inline HTMLDOMTextNode *impl_from_HTMLDOMNode(HTMLDOMNode *iface) -{ - return CONTAINING_RECORD(iface, HTMLDOMTextNode, node); -} - -static HRESULT HTMLDOMTextNode_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode, HTMLDOMNode **ret) -{ - HTMLDOMTextNode *This = impl_from_HTMLDOMNode(iface); - - return HTMLDOMTextNode_Create(This->node.doc, nsnode, ret); -} - static inline HTMLDOMTextNode *impl_from_DispatchEx(DispatchEx *iface) { return CONTAINING_RECORD(iface, HTMLDOMTextNode, node.event_target.dispex); @@ -405,7 +393,6 @@ static const cpc_entry_t HTMLDOMTextNode_cpc[] = {{NULL}};
static const NodeImplVtbl HTMLDOMTextNodeImplVtbl = { .cpc_entries = HTMLDOMTextNode_cpc, - .clone = HTMLDOMTextNode_clone };
static const dispex_static_data_vtbl_t Text_dispex_vtbl = {
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/htmlattr.c | 127 +++++++++++++++++++++++++++++++---- dlls/mshtml/htmldoc.c | 28 +++++++- dlls/mshtml/htmlelem.c | 53 ++++++++++++--- dlls/mshtml/htmlnode.c | 14 +++- dlls/mshtml/mshtml_private.h | 7 +- 5 files changed, 199 insertions(+), 30 deletions(-)
diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c index f98356e19db..9b1544d06f0 100644 --- a/dlls/mshtml/htmlattr.c +++ b/dlls/mshtml/htmlattr.c @@ -37,7 +37,7 @@ static inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute *i return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute_iface); }
-DISPEX_IDISPATCH_IMPL(HTMLDOMAttribute, IHTMLDOMAttribute, impl_from_IHTMLDOMAttribute(iface)->dispex) +DISPEX_IDISPATCH_IMPL(HTMLDOMAttribute, IHTMLDOMAttribute, impl_from_IHTMLDOMAttribute(iface)->node.event_target.dispex)
static HRESULT WINAPI HTMLDOMAttribute_get_nodeName(IHTMLDOMAttribute *iface, BSTR *p) { @@ -45,6 +45,9 @@ static HRESULT WINAPI HTMLDOMAttribute_get_nodeName(IHTMLDOMAttribute *iface, BS
TRACE("(%p)->(%p)\n", This, p);
+ if(This->dom_attr) + return IHTMLDOMNode_get_nodeName(&This->node.IHTMLDOMNode_iface, p); + if(!This->elem) { if(!This->name) { FIXME("No name available\n"); @@ -65,6 +68,9 @@ static HRESULT WINAPI HTMLDOMAttribute_put_nodeValue(IHTMLDOMAttribute *iface, V
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
+ if(This->dom_attr) + return IHTMLDOMNode_put_nodeValue(&This->node.IHTMLDOMNode_iface, v); + if(!This->elem) return VariantCopy(&This->value, &v);
@@ -78,6 +84,9 @@ static HRESULT WINAPI HTMLDOMAttribute_get_nodeValue(IHTMLDOMAttribute *iface, V
TRACE("(%p)->(%p)\n", This, p);
+ if(This->dom_attr) + return IHTMLDOMNode_get_nodeValue(&This->node.IHTMLDOMNode_iface, p); + if(!This->elem) return VariantCopy(p, &This->value);
@@ -93,6 +102,14 @@ static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, V
TRACE("(%p)->(%p)\n", This, p);
+ if(This->dom_attr) { + cpp_bool b; + nsres = nsIDOMAttr_GetSpecified(This->dom_attr, &b); + assert(nsres == NS_OK); + *p = variant_bool(b); + return S_OK; + } + if(!This->elem || !This->elem->dom_element) { *p = VARIANT_FALSE; return S_OK; @@ -131,7 +148,7 @@ static inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute2(IHTMLDOMAttribute2 return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute2_iface); }
-DISPEX_IDISPATCH_IMPL(HTMLDOMAttribute2, IHTMLDOMAttribute2, impl_from_IHTMLDOMAttribute2(iface)->dispex) +DISPEX_IDISPATCH_IMPL(HTMLDOMAttribute2, IHTMLDOMAttribute2, impl_from_IHTMLDOMAttribute2(iface)->node.event_target.dispex)
static HRESULT WINAPI HTMLDOMAttribute2_get_name(IHTMLDOMAttribute2 *iface, BSTR *p) { @@ -162,6 +179,15 @@ static HRESULT WINAPI HTMLDOMAttribute2_get_value(IHTMLDOMAttribute2 *iface, BST
TRACE("(%p)->(%p)\n", This, p);
+ if(This->dom_attr) { + nsAString nsstr; + nsresult nsres; + + nsAString_Init(&nsstr, NULL); + nsres = nsIDOMAttr_GetValue(This->dom_attr, &nsstr); + return return_nsstr(nsres, &nsstr, p); + } + V_VT(&val) = VT_EMPTY; if(This->elem) hres = get_elem_attr_value_by_dispid(This->elem, This->dispid, &val); @@ -185,7 +211,7 @@ static HRESULT WINAPI HTMLDOMAttribute2_get_expando(IHTMLDOMAttribute2 *iface, V
TRACE("(%p)->(%p)\n", This, p);
- *p = variant_bool(This->elem && get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN); + *p = variant_bool(!This->dom_attr && This->elem && get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN); return S_OK; }
@@ -275,6 +301,9 @@ static HRESULT WINAPI HTMLDOMAttribute2_get_ownerDocument(IHTMLDOMAttribute2 *if
TRACE("(%p)->(%p)\n", This, p);
+ if(This->dom_attr) + return IHTMLDOMNode2_get_ownerDocument(&This->node.IHTMLDOMNode2_iface, p); + *p = (IDispatch*)&This->doc->IHTMLDocument2_iface; IDispatch_AddRef(*p); return S_OK; @@ -348,6 +377,16 @@ static HRESULT WINAPI HTMLDOMAttribute2_cloneNode(IHTMLDOMAttribute2 *iface, VAR
TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode);
+ if(This->dom_attr) { + IHTMLDOMNode *node; + hres = IHTMLDOMNode_cloneNode(&This->node.IHTMLDOMNode_iface, fDeep, &node); + if(SUCCEEDED(hres)) { + hres = IHTMLDOMNode_QueryInterface(node, &IID_IHTMLDOMAttribute, (void **)clonedNode); + IHTMLDOMNode_Release(node); + } + return hres; + } + if(This->elem) { hres = dispex_prop_name(&This->elem->node.event_target.dispex, This->dispid, &name); if(FAILED(hres)) @@ -407,7 +446,7 @@ static inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute3(IHTMLDOMAttribute3 return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute3_iface); }
-DISPEX_IDISPATCH_IMPL(HTMLDOMAttribute3, IHTMLDOMAttribute3, impl_from_IHTMLDOMAttribute3(iface)->dispex) +DISPEX_IDISPATCH_IMPL(HTMLDOMAttribute3, IHTMLDOMAttribute3, impl_from_IHTMLDOMAttribute3(iface)->node.event_target.dispex)
static HRESULT WINAPI HTMLDOMAttribute3_put_nodeValue(IHTMLDOMAttribute3 *iface, VARIANT v) { @@ -460,6 +499,24 @@ static HRESULT WINAPI HTMLDOMAttribute3_get_ownerElement(IHTMLDOMAttribute3 *ifa
TRACE("(%p)->(%p)\n", This, p);
+ if(This->dom_attr) { + nsIDOMElement *dom_element; + nsresult nsres; + HRESULT hres = S_OK; + + nsres = nsIDOMAttr_GetOwnerElement(This->dom_attr, &dom_element); + assert(nsres == NS_OK); + if(dom_element) { + HTMLElement *element; + hres = get_element(dom_element, &element); + if(SUCCEEDED(hres)) + *p = &element->IHTMLElement2_iface; + }else { + *p = NULL; + } + return hres; + } + if(!This->elem) { *p = NULL; return S_OK; @@ -488,7 +545,7 @@ static const IHTMLDOMAttribute3Vtbl HTMLDOMAttribute3Vtbl = {
static inline HTMLDOMAttribute *impl_from_DispatchEx(DispatchEx *iface) { - return CONTAINING_RECORD(iface, HTMLDOMAttribute, dispex); + return CONTAINING_RECORD(iface, HTMLDOMAttribute, node.event_target.dispex); }
static void *HTMLDOMAttribute_query_interface(DispatchEx *dispex, REFIID riid) @@ -501,8 +558,10 @@ static void *HTMLDOMAttribute_query_interface(DispatchEx *dispex, REFIID riid) return &This->IHTMLDOMAttribute2_iface; if(IsEqualGUID(&IID_IHTMLDOMAttribute3, riid)) return &This->IHTMLDOMAttribute3_iface; - - return NULL; + if(!This->dom_attr) + return NULL; + /* FIXME: We shouldn't expose IHTMLDOMNode* interfaces */ + return HTMLDOMNode_query_interface(&This->node.event_target.dispex, riid); }
static void HTMLDOMAttribute_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) @@ -573,6 +632,38 @@ HTMLDOMAttribute *unsafe_impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute *iface) return iface->lpVtbl == &HTMLDOMAttributeVtbl ? impl_from_IHTMLDOMAttribute(iface) : NULL; }
+static const cpc_entry_t HTMLDOMAttribute_cpc[] = {{NULL}}; + +static const NodeImplVtbl HTMLDOMAttributeNodeVtbl = { + .cpc_entries = HTMLDOMAttribute_cpc, +}; + +HRESULT get_attr_node(nsIDOMAttr *dom_attr, HTMLDOMAttribute **ret) +{ + HTMLDOMNode *node; + HRESULT hres; + + hres = get_node((nsIDOMNode *)dom_attr, TRUE, &node); + if(FAILED(hres)) + return hres; + assert(node->vtbl == &HTMLDOMAttributeNodeVtbl); + *ret = impl_from_DispatchEx(&node->event_target.dispex); + return S_OK; +} + +static HTMLDOMAttribute *alloc_attribute(void) +{ + HTMLDOMAttribute *ret; + + if (!(ret = calloc(1, sizeof(*ret)))) + return NULL; + + ret->IHTMLDOMAttribute_iface.lpVtbl = &HTMLDOMAttributeVtbl; + ret->IHTMLDOMAttribute2_iface.lpVtbl = &HTMLDOMAttribute2Vtbl; + ret->IHTMLDOMAttribute3_iface.lpVtbl = &HTMLDOMAttribute3Vtbl; + return ret; +} + HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dispid, HTMLDocumentNode *doc, HTMLDOMAttribute **attr) { @@ -580,17 +671,13 @@ HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dis HTMLDOMAttribute *ret; HRESULT hres;
- ret = calloc(1, sizeof(*ret)); - if(!ret) + if(!(ret = alloc_attribute())) return E_OUTOFMEMORY;
- ret->IHTMLDOMAttribute_iface.lpVtbl = &HTMLDOMAttributeVtbl; - ret->IHTMLDOMAttribute2_iface.lpVtbl = &HTMLDOMAttribute2Vtbl; - ret->IHTMLDOMAttribute3_iface.lpVtbl = &HTMLDOMAttribute3Vtbl; ret->dispid = dispid; ret->elem = elem;
- init_dispatch(&ret->dispex, &Attr_dispex, doc->script_global, + init_dispatch(&ret->node.event_target.dispex, &Attr_dispex, doc->script_global, dispex_compat_mode(&doc->script_global->event_target.dispex));
/* For attributes attached to an element, (elem,dispid) pair should be valid used for its operation. */ @@ -622,3 +709,17 @@ HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dis *attr = ret; return S_OK; } + +HRESULT create_attr_node(HTMLDocumentNode *doc, nsIDOMAttr *dom_attr, HTMLDOMAttribute **ret) +{ + HTMLDOMAttribute *attr; + + if(!(attr = alloc_attribute())) + return E_OUTOFMEMORY; + + attr->node.vtbl = &HTMLDOMAttributeNodeVtbl; + HTMLDOMNode_Init(doc, &attr->node, (nsIDOMNode *)dom_attr, &Attr_dispex); + attr->dom_attr = dom_attr; /* share reference with HTMLDOMNode */ + *ret = attr; + return S_OK; +} diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 05c98e0f377..7255e8d9ec3 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -3522,13 +3522,35 @@ static HRESULT WINAPI HTMLDocument7_createElement(IHTMLDocument7 *iface, BSTR bs return IHTMLDocument2_createElement(&This->IHTMLDocument2_iface, bstrTag, newElem); }
-static HRESULT WINAPI HTMLDocument7_createAttribute(IHTMLDocument7 *iface, BSTR bstrAttrName, IHTMLDOMAttribute **ppAttribute) +static HRESULT WINAPI HTMLDocument7_createAttribute(IHTMLDocument7 *iface, BSTR name, IHTMLDOMAttribute **p) { HTMLDocumentNode *This = impl_from_IHTMLDocument7(iface); + HTMLDOMAttribute *attr; + nsIDOMAttr *nsattr; + nsAString nsstr; + nsresult nsres; + HRESULT hres; + + TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), p);
- TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrAttrName), ppAttribute); + if(!This->dom_document) { + FIXME("NULL dom_document\n"); + return E_FAIL; + }
- return IHTMLDocument5_createAttribute(&This->IHTMLDocument5_iface, bstrAttrName, ppAttribute); + nsAString_InitDepend(&nsstr, name); + nsres = nsIDOMDocument_CreateAttribute(This->dom_document, &nsstr, &nsattr); + nsAString_Finish(&nsstr); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + + hres = create_attr_node(This, nsattr, &attr); + nsIDOMAttr_Release(nsattr); + if(FAILED(hres)) + return hres; + + *p = &attr->IHTMLDOMAttribute_iface; + return S_OK; }
static HRESULT WINAPI HTMLDocument7_getElementsByClassName(IHTMLDocument7 *iface, BSTR v, IHTMLElementCollection **pel) diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 22ac9fec0dc..a3b2bee3817 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4442,6 +4442,31 @@ static HRESULT WINAPI HTMLElement4_setAttributeNode(IHTMLElement4 *iface, IHTMLD if(!attr) return E_INVALIDARG;
+ if(attr->dom_attr) { + HTMLDOMAttribute *prev_attr; + nsIDOMAttr *prev_nsattr; + nsresult nsres; + + if(!This->dom_element) { + FIXME("no DOM element\n"); + return E_NOTIMPL; + } + + nsres = nsIDOMElement_SetAttributeNode(This->dom_element, attr->dom_attr, &prev_nsattr); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + if(!prev_nsattr) { + *ppretAttribute = NULL; + return S_OK; + } + + hres = get_attr_node(prev_nsattr, &prev_attr); + nsIDOMAttr_Release(prev_nsattr); + if(SUCCEEDED(hres)) + *ppretAttribute = &prev_attr->IHTMLDOMAttribute_iface; + return hres; + } + if(attr->elem) { WARN("Tried to set already attached attribute.\n"); return E_INVALIDARG; @@ -4752,21 +4777,29 @@ static HRESULT WINAPI HTMLElement6_removeAttribute(IHTMLElement6 *iface, BSTR st static HRESULT WINAPI HTMLElement6_getAttributeNode(IHTMLElement6 *iface, BSTR strAttributeName, IHTMLDOMAttribute2 **ppretAttribute) { HTMLElement *This = impl_from_IHTMLElement6(iface); - IHTMLDOMAttribute *attr; + HTMLDOMAttribute *attr; + nsIDOMAttr *nsattr = NULL; + nsresult nsres; HRESULT hres;
- WARN("(%p)->(%s %p) forwarding to IHTMLElement4\n", This, debugstr_w(strAttributeName), ppretAttribute); - - hres = IHTMLElement4_getAttributeNode(&This->IHTMLElement4_iface, strAttributeName, &attr); - if(FAILED(hres)) - return hres; + TRACE("(%p)->(%s %p)\n", This, debugstr_w(strAttributeName), ppretAttribute);
- if(attr) { - hres = IHTMLDOMAttribute_QueryInterface(attr, &IID_IHTMLDOMAttribute2, (void**)ppretAttribute); - IHTMLDOMAttribute_Release(attr); - }else { + if(This->dom_element) { + nsAString nsstr; + nsAString_Init(&nsstr, strAttributeName); + nsres = nsIDOMElement_GetAttributeNode(This->dom_element, &nsstr, &nsattr); + nsAString_Finish(&nsstr); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + } + if(!nsattr) { *ppretAttribute = NULL; + return S_OK; } + hres = get_attr_node(nsattr, &attr); + nsIDOMAttr_Release(nsattr); + if(SUCCEEDED(hres)) + *ppretAttribute = &attr->IHTMLDOMAttribute2_iface; return hres; }
diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index 6b8daa00aea..0d9a5259935 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -1431,9 +1431,17 @@ static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNod *ret = &comment->node; break; } - case ATTRIBUTE_NODE: - ERR("Called on attribute node\n"); - return E_UNEXPECTED; + case ATTRIBUTE_NODE: { + HTMLDOMAttribute *attr; + nsIDOMAttr *nsattr; + nsresult nsres; + nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMAttr, (void **)&nsattr); + assert(nsres == NS_OK); + hres = create_attr_node(doc, nsattr, &attr); + if(SUCCEEDED(hres)) + *ret = &attr->node; + return hres; + } default: { HTMLDOMNode *node;
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 5a067967a8b..0d3e5fa63a2 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1337,11 +1337,14 @@ struct HTMLAttributeCollection { };
typedef struct { - DispatchEx dispex; + HTMLDOMNode node; /* only dispex is valid if dom_attr is NULL */ IHTMLDOMAttribute IHTMLDOMAttribute_iface; IHTMLDOMAttribute2 IHTMLDOMAttribute2_iface; IHTMLDOMAttribute3 IHTMLDOMAttribute3_iface;
+ /* Gecko attr for proper nodes, when non-NULL other fields are invalid */ + nsIDOMAttr *dom_attr; + /* value is valid only for detached attributes (when elem == NULL). */ VARIANT value; /* name must be valid for detached attributes */ @@ -1356,6 +1359,8 @@ typedef struct { HTMLDOMAttribute *unsafe_impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute*);
HRESULT HTMLDOMAttribute_Create(const WCHAR*,HTMLElement*,DISPID,HTMLDocumentNode*,HTMLDOMAttribute**); +HRESULT create_attr_node(HTMLDocumentNode *doc, nsIDOMAttr *dom_attr, HTMLDOMAttribute **ret); +HRESULT get_attr_node(nsIDOMAttr *dom_attr, HTMLDOMAttribute **ret);
HRESULT HTMLElement_Create(HTMLDocumentNode*,nsIDOMNode*,BOOL,HTMLElement**); HRESULT HTMLCommentElement_Create(HTMLDocumentNode*,nsIDOMNode*,HTMLElement**);
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/htmlelem.c | 16 ++++++++++++++-- dlls/mshtml/mshtml_private.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index a3b2bee3817..0813d08d2a0 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -8330,8 +8330,14 @@ static HRESULT WINAPI HTMLAttributeCollection4_item(IHTMLAttributeCollection4 *i static HRESULT WINAPI HTMLAttributeCollection4_get_length(IHTMLAttributeCollection4 *iface, LONG *p) { HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection4(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + UINT32 length = 0; + + TRACE("(%p)->(%p)\n", This, p); + + if(This->dom_attrs) + nsIDOMMozNamedAttrMap_GetLength(This->dom_attrs, &length); + *p = length; + return S_OK; }
static const IHTMLAttributeCollection4Vtbl HTMLAttributeCollection4Vtbl = { @@ -8378,6 +8384,8 @@ static void HTMLAttributeCollection_traverse(DispatchEx *dispex, nsCycleCollecti HTMLAttributeCollection *This = HTMLAttributeCollection_from_DispatchEx(dispex); HTMLDOMAttribute *attr;
+ if(This->dom_attrs) + note_cc_edge((nsISupports*)This->dom_attrs, "dom_attrs", cb); LIST_FOR_EACH_ENTRY(attr, &This->attrs, HTMLDOMAttribute, entry) note_cc_edge((nsISupports*)&attr->IHTMLDOMAttribute_iface, "attr", cb); if(This->elem) @@ -8387,6 +8395,7 @@ static void HTMLAttributeCollection_traverse(DispatchEx *dispex, nsCycleCollecti static void HTMLAttributeCollection_unlink(DispatchEx *dispex) { HTMLAttributeCollection *This = HTMLAttributeCollection_from_DispatchEx(dispex); + unlink_ref(&This->dom_attrs); while(!list_empty(&This->attrs)) { HTMLDOMAttribute *attr = LIST_ENTRY(list_head(&This->attrs), HTMLDOMAttribute, entry);
@@ -8513,6 +8522,9 @@ HRESULT HTMLElement_get_attr_col(HTMLDOMNode *iface, HTMLAttributeCollection **a init_dispatch(&This->attrs->dispex, &NamedNodeMap_dispex, This->node.doc->script_global, dispex_compat_mode(&This->node.event_target.dispex));
+ if(This->dom_element) + nsIDOMElement_GetAttributes(This->dom_element, &This->attrs->dom_attrs); + *ac = This->attrs; IHTMLAttributeCollection_AddRef(&This->attrs->IHTMLAttributeCollection_iface); return S_OK; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 0d3e5fa63a2..3dc41bae967 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1332,6 +1332,7 @@ struct HTMLAttributeCollection { IHTMLAttributeCollection3 IHTMLAttributeCollection3_iface; IHTMLAttributeCollection4 IHTMLAttributeCollection4_iface;
+ nsIDOMMozNamedAttrMap *dom_attrs; HTMLElement *elem; struct list attrs; };
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/htmlelem.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 0813d08d2a0..8e488ce1f3a 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -8323,8 +8323,27 @@ static HRESULT WINAPI HTMLAttributeCollection4_removeNamedItem(IHTMLAttributeCol static HRESULT WINAPI HTMLAttributeCollection4_item(IHTMLAttributeCollection4 *iface, LONG index, IHTMLDOMAttribute2 **p) { HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection4(iface); - FIXME("(%p)->(%ld %p)\n", This, index, p); - return E_NOTIMPL; + HTMLDOMAttribute *attr = NULL; + nsIDOMAttr *nsattr; + nsresult nsres; + HRESULT hres; + + TRACE("(%p)->(%ld %p)\n", This, index, p); + + if(This->dom_attrs) { + nsres = nsIDOMMozNamedAttrMap_Item(This->dom_attrs, index, &nsattr); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + if(nsattr) { + hres = get_attr_node(nsattr, &attr); + nsIDOMAttr_Release(nsattr); + if(FAILED(hres)) + return hres; + } + } + + *p = attr ? &attr->IHTMLDOMAttribute2_iface : NULL; + return S_OK; }
static HRESULT WINAPI HTMLAttributeCollection4_get_length(IHTMLAttributeCollection4 *iface, LONG *p)
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/htmlelem.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 8e488ce1f3a..5df5029aed6 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -8300,8 +8300,30 @@ static HRESULT WINAPI HTMLAttributeCollection4_getNamedItem(IHTMLAttributeCollec IHTMLDOMAttribute2 **p) { HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection4(iface); - FIXME("(%p)->(%s %p)\n", This, debugstr_w(name), p); - return E_NOTIMPL; + HTMLDOMAttribute *attr = NULL; + nsIDOMAttr *nsattr; + nsresult nsres; + HRESULT hres; + + TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), p); + + if(This->dom_attrs) { + nsAString nsstr; + nsAString_Init(&nsstr, name); + nsres = nsIDOMMozNamedAttrMap_GetNamedItem(This->dom_attrs, &nsstr, &nsattr); + nsAString_Finish(&nsstr); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + if(nsattr) { + hres = get_attr_node(nsattr, &attr); + nsIDOMAttr_Release(nsattr); + if(FAILED(hres)) + return hres; + } + } + + *p = attr ? &attr->IHTMLDOMAttribute2_iface : NULL; + return S_OK; }
static HRESULT WINAPI HTMLAttributeCollection4_setNamedItem(IHTMLAttributeCollection4 *iface,
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/htmlattr.c | 2 + dlls/mshtml/htmlelem.c | 73 ++++++++++++++++++++++++++++--- dlls/mshtml/tests/documentmode.js | 3 ++ dlls/mshtml/tests/dom.js | 53 +++++++++++++++++++++- 4 files changed, 123 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c index 9b1544d06f0..0816ccefdbe 100644 --- a/dlls/mshtml/htmlattr.c +++ b/dlls/mshtml/htmlattr.c @@ -609,6 +609,8 @@ static const dispex_static_data_vtbl_t HTMLDOMAttribute_dispex_vtbl = {
static void HTMLDOMAttribute_init_dispex_info(dispex_data_t *info, compat_mode_t mode) { + if(mode >= COMPAT_MODE_IE9) + HTMLDOMNode_init_dispex_info(info, mode); if(mode >= COMPAT_MODE_IE8) dispex_info_add_interface(info, IHTMLDOMAttribute3_tid, NULL); } diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 5df5029aed6..fe57bc0dfef 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -8465,6 +8465,46 @@ static HRESULT HTMLAttributeCollection_get_dispid(DispatchEx *dispex, const WCHA
TRACE("(%p)->(%s %lx %p)\n", This, debugstr_w(name), flags, dispid);
+ if(dispex_compat_mode(&This->dispex) >= COMPAT_MODE_IE9) { + nsIDOMAttr *nsattr, *iter; + UINT32 length, i; + nsAString nsstr; + nsresult nsres; + + if(!This->dom_attrs) + return DISP_E_UNKNOWNNAME; + nsIDOMMozNamedAttrMap_GetLength(This->dom_attrs, &length); + + if(name[0] >= '0' && name[0] <= '9') { + WCHAR *end_ptr; + i = wcstoul(name, &end_ptr, 10); + if(!*end_ptr) { + if(i < length) { + *dispid = MSHTML_DISPID_CUSTOM_MIN + i; + return S_OK; + } + } + } + + nsAString_Init(&nsstr, name); + nsres = nsIDOMMozNamedAttrMap_GetNamedItem(This->dom_attrs, &nsstr, &nsattr); + nsAString_Finish(&nsstr); + if(NS_FAILED(nsres) || !nsattr) + return DISP_E_UNKNOWNNAME; + + for(i = 0; i < length; i++) { + nsres = nsIDOMMozNamedAttrMap_Item(This->dom_attrs, i, &iter); + assert(nsres == NS_OK); + nsIDOMAttr_Release(iter); + if(iter == nsattr) + break; + } + + assert(i < length); + *dispid = MSHTML_DISPID_CUSTOM_MIN + i; + return S_OK; + } + hres = get_attr_dispid_by_name(This, name, dispid); if(FAILED(hres)) return hres; @@ -8494,6 +8534,20 @@ static HRESULT HTMLAttributeCollection_invoke(DispatchEx *dispex, DISPID id, LCI
pos = id-MSHTML_DISPID_CUSTOM_MIN;
+ if(dispex_compat_mode(&This->dispex) >= COMPAT_MODE_IE9) { + IHTMLDOMAttribute2 *attr; + HRESULT hres; + + hres = IHTMLAttributeCollection4_item(&This->IHTMLAttributeCollection4_iface, pos, &attr); + if(FAILED(hres)) + return hres; + if(!attr) + return DISP_E_MEMBERNOTFOUND; + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch *)attr; + return S_OK; + } + LIST_FOR_EACH_ENTRY(iter, &This->attrs, HTMLDOMAttribute, entry) { if(!pos) { IHTMLDOMAttribute_AddRef(&iter->IHTMLDOMAttribute_iface); @@ -8524,18 +8578,23 @@ static const dispex_static_data_vtbl_t HTMLAttributeCollection_dispex_vtbl = { .invoke = HTMLAttributeCollection_invoke, };
-const tid_t NamedNodeMap_iface_tids[] = { - IHTMLAttributeCollection_tid, - IHTMLAttributeCollection2_tid, - IHTMLAttributeCollection3_tid, - 0 -}; +static void NamedNodeMap_init_dispex_info(dispex_data_t *info, compat_mode_t mode) +{ + if(mode >= COMPAT_MODE_IE9) { + dispex_info_add_interface(info, IHTMLAttributeCollection4_tid, NULL); + }else if(mode == COMPAT_MODE_IE8) { + dispex_info_add_interface(info, IHTMLAttributeCollection3_tid, NULL); + }else { + dispex_info_add_interface(info, IHTMLAttributeCollection_tid, NULL); + dispex_info_add_interface(info, IHTMLAttributeCollection2_tid, NULL); + } +}
dispex_static_data_t NamedNodeMap_dispex = { .id = OBJID_NamedNodeMap, .vtbl = &HTMLAttributeCollection_dispex_vtbl, .disp_tid = DispHTMLAttributeCollection_tid, - .iface_tids = NamedNodeMap_iface_tids, + .init_info = NamedNodeMap_init_dispex_info, };
HRESULT HTMLElement_get_attr_col(HTMLDOMNode *iface, HTMLAttributeCollection **ac) diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index e231c4c090c..fe272f0f08a 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3923,6 +3923,7 @@ sync_test("prototype props", function() { test_own_props(constr.prototype, name, props, todos, flaky); }
+ check(Attr, [ "expando", "name", "ownerElement", "specified", "value" ]); check(CharacterData, [ "appendData", "data", "deleteData", "insertData", "length", "replaceData", "substringData" ]); check(Comment, [ "text" ]); check(CSSStyleDeclaration, [ @@ -4222,6 +4223,8 @@ sync_test("prototype props", function() { "posHeight", "posLeft", "posRight", "posTop", "posWidth", "textDecorationBlink", "textDecorationLineThrough", "textDecorationNone", "textDecorationOverline", "textDecorationUnderline" ]); + check(NamedNodeMap, [ "getNamedItem", "getNamedItemNS", "item", "length", "removeNamedItem", "removeNamedItemNS", + "setNamedItem", "setNamedItemNS" ]); check(Node, [ "ATTRIBUTE_NODE", "CDATA_SECTION_NODE", "COMMENT_NODE", "DOCUMENT_FRAGMENT_NODE", "DOCUMENT_NODE", "DOCUMENT_POSITION_CONTAINED_BY", "DOCUMENT_POSITION_CONTAINS", "DOCUMENT_POSITION_DISCONNECTED", diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index 1ca70c5726d..bd7af124167 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -1044,12 +1044,63 @@ sync_test("importNode", function() { sync_test("attributeNode", function() { document.body.innerHTML = '<div id="test" attr="wine"></div>'; var elem = document.getElementById("test"); - var attr = elem.attributes[0]; + var attr, clone, prev, ret;
+ attr = elem.attributes["id"]; ok(attr.ownerDocument === document, "ownerDocument = " + attr.ownerDocument); ok(attr.ownerElement === elem, "ownerElement = " + attr.ownerElement); + ok(attr.specified === true, "attr.specified = " + attr.expando); + ok(attr.expando === false, "attr.expando = " + attr.expando); + ok(attr.value === "test", "attr.value = " + attr.value); + ok(attr.name === "id", "attr.name = " + attr.name); + + clone = attr.cloneNode(true); + ok(clone.ownerDocument === document, "ownerDocument = " + clone.ownerDocument); + ok(clone.ownerElement === null, "ownerElement = " + clone.ownerElement); + ok(clone.specified === true, "clone.specified = " + clone.expando); + ok(clone.expando === false, "clone.expando = " + clone.expando); + ok(clone.value === "test", "clone.value = " + clone.value); + ok(clone.name === "id", "clone.name = " + clone.name); + + ok(elem.getAttributeNode("id") === attr, 'elem.getAttributeNode("id") = ' + elem.getAttributeNode("id")); + ok(elem.attributes.getNamedItem("id") === attr, "unexpected id named item"); + ok(elem.getAttributeNode("nonexistent") === null, + 'elem.getAttributeNode("nonexistent") = ' + elem.getAttributeNode("nonexistent")); + ok(elem.attributes.getNamedItem("nonexistent") === null, + 'elem.attributes.getNamedItem("nonexistent") = ' + elem.attributes.getNamedItem("nonexistent")); + ok(elem.attributes.length === 2, "elem.attributes.length = " + elem.attributes.length); + ok(elem.attributes[0] == attr || elem.attributes[1] === attr, "attr not found in elem.attributes"); + ok(elem.attributes.item(0) == attr || elem.attributes.item(1) === attr, "attr not found in items"); + ok(elem.attributes.item(2) == null, "item(2) = " + elem.attributes.item(2)); + prev = attr;
attr = document.createAttribute("id"); ok(attr.ownerDocument === document, "detached attr ownerDocument = " + attr.ownerDocument); ok(attr.ownerElement === null, "detached attr ownerElement = " + attr.ownerElement); + ok(attr.specified === true, "attr.specified = " + attr.specified); + ok(attr.expando === false, "attr.expando = " + attr.expando); + ok(attr.value === "", "attr.value = " + attr.value); + ok(attr.name === "id", "attr.name = " + attr.name); + attr.value = "new"; + + ret = elem.setAttributeNode(attr); + ok(ret === prev, "ret != prev"); + ok(elem.getAttributeNode("id") === attr, "unexpected id attr"); + ok(elem.getAttribute("id") === "new", "unexpected id attr value " + elem.getAttribute("id")); + + attr = document.createAttribute("test"); + attr.value = "test"; + ret = elem.setAttributeNode(attr); + ok(ret === null, "ret != null"); + ok(elem.attributes.length === 3, "elem.attributes.length = " + elem.attributes.length); + ok(elem.getAttributeNode("test") === attr, "unexpected test attr"); + ok(elem.attributes.getNamedItem("test") === attr, "unexpected test named item"); + ok(elem.getAttribute("test") === "test", "unexpected test attr value " + elem.getAttribute("id")); + ok(elem.attributes.item(3) == null, "item(3) = " + elem.attributes.item(3)); + + attr = elem.getAttributeNode("style"); + ok(attr === null, "found style attribute node"); + attr = elem.attributes.getNamedItem("style"); + ok(attr === null, "found style attribute named item"); + ok(!("style" in elem.attributes), "found style in attribute collection " + elem.attributes["style"]); });
From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/tests/dom.c | 133 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index cd13f73ba17..6fe0ef1584a 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -3813,8 +3813,9 @@ static void test_attr_collection_disp(IDispatch *disp, LONG len, IHTMLElement *e ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); SysFreeString(bstr);
- ok(dispid == dispid_attr1 || dispid == dispid_attr2 || dispid == dispid_attr3, - "indexed dispid isn't one of the attr dispids\n"); + if(compat_mode < COMPAT_IE9) + ok(dispid == dispid_attr1 || dispid == dispid_attr2 || dispid == dispid_attr3, + "indexed dispid isn't one of the attr dispids\n");
bstr = SysAllocString(L"attr1"); hres = IHTMLElement_removeAttribute(elem, bstr, 0, &vbool); @@ -3824,7 +3825,10 @@ static void test_attr_collection_disp(IDispatch *disp, LONG len, IHTMLElement *e
hres = IDispatchEx_GetMemberName(dispex, dispid_attr1, &bstr); ok(hres == S_OK, "GetMemberName failed: %08lx\n", hres); - ok(wcscmp(bstr, L"attr1"), "GetMemberName still returned attr1 after removal\n"); + if(compat_mode >= COMPAT_IE9) + ok(!wcscmp(bstr, L"attr1"), "GetMemberName returned %s after removal\n", debugstr_w(bstr)); + else + ok(wcscmp(bstr, L"attr1"), "GetMemberName still returned attr1 after removal\n"); SysFreeString(bstr);
bstr = SysAllocString(buf); @@ -3864,7 +3868,8 @@ static void test_attr_collection_disp(IDispatch *disp, LONG len, IHTMLElement *e
hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); - ok(dispid != dispid_attr1, "attr1 after re-added dispid == dispid_attr1\n"); + if(compat_mode < COMPAT_IE9) + ok(dispid != dispid_attr1, "attr1 after re-added dispid == dispid_attr1\n"); ok(dispid != dispid_attr2, "attr1 after re-added dispid == dispid_attr2\n"); ok(dispid != dispid_attr3, "attr1 after re-added dispid == dispid_attr3\n"); SysFreeString(bstr); @@ -3874,15 +3879,20 @@ static void test_attr_collection_disp(IDispatch *disp, LONG len, IHTMLElement *e
static void test_attr_collection(IHTMLElement *elem) { + IHTMLAttributeCollection4 *attr_col4; + IHTMLAttributeCollection2 *attr_col2; IHTMLAttributeCollection *attr_col; + IHTMLDOMAttribute2 *dom_attr2; + IHTMLDOMAttribute *dom_attr; + LONG i, len, checked, len_ie9; IDispatch *disp, *attr; IEnumVARIANT *enum_var; - LONG i, len, checked; IHTMLDOMNode *node; IUnknown *enum_unk; VARIANT id, val; ULONG fetched; HRESULT hres; + BSTR bstr; BSTR name;
hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLDOMNode, (void**)&node); @@ -3900,10 +3910,18 @@ static void test_attr_collection(IHTMLElement *elem)
hres = IDispatch_QueryInterface(disp, &IID_IHTMLAttributeCollection, (void**)&attr_col); ok(hres == S_OK, "QueryInterface failed: %08lx\n", hres); + hres = IDispatch_QueryInterface(disp, &IID_IHTMLAttributeCollection2, (void**)&attr_col2); + ok(hres == S_OK, "QueryInterface failed: %08lx\n", hres); + hres = IDispatch_QueryInterface(disp, &IID_IHTMLAttributeCollection4, (void**)&attr_col4); + ok(hres == S_OK, "QueryInterface failed: %08lx\n", hres);
hres = IHTMLAttributeCollection_get_length(attr_col, &i); ok(hres == S_OK, "get_length failed: %08lx\n", hres); - ok(i > 3, "length = %ld\n", i); + ok(i > 4, "length = %ld\n", i); + + hres = IHTMLAttributeCollection4_get_length(attr_col4, &len_ie9); + ok(hres == S_OK, "get_length failed: %08lx\n", hres); + ok(len_ie9 == 4, "length = %ld\n", len_ie9);
V_VT(&val) = VT_I4; V_I4(&val) = 1; @@ -3914,6 +3932,7 @@ static void test_attr_collection(IHTMLElement *elem)
hres = IHTMLAttributeCollection_get_length(attr_col, &len); ok(hres == S_OK, "get_length failed: %08lx\n", hres); + todo_wine_if(compat_mode >= COMPAT_IE9) ok(len == i+1, "get_length returned %ld, expected %ld\n", len, i+1);
hres = IHTMLAttributeCollection_get__newEnum(attr_col, &enum_unk); @@ -3933,6 +3952,7 @@ static void test_attr_collection(IHTMLElement *elem) checked += test_attr_collection_attr(attr, i); IDispatch_Release(attr); } + todo_wine_if(compat_mode >= COMPAT_IE9) ok(checked==5, "invalid number of specified attributes (%ld)\n", checked);
checked = 0; @@ -3948,6 +3968,7 @@ static void test_attr_collection(IHTMLElement *elem) checked += test_attr_collection_attr(V_DISPATCH(&val), i); IDispatch_Release(V_DISPATCH(&val)); } + todo_wine_if(compat_mode >= COMPAT_IE9) ok(checked==5, "invalid number of specified attributes (%ld)\n", checked);
fetched = 0; @@ -3967,10 +3988,106 @@ static void test_attr_collection(IHTMLElement *elem) ok(hres == E_INVALIDARG, "item failed: %08lx\n", hres); VariantClear(&id);
- test_attr_collection_disp(disp, len, elem); + test_attr_collection_disp(disp, compat_mode >= COMPAT_IE9 ? len_ie9 : len, elem); + + bstr = SysAllocString(L"attr1"); + dom_attr = NULL; + hres = IHTMLAttributeCollection2_getNamedItem(attr_col2, bstr, &dom_attr); + ok(hres == S_OK, "getNamedItem failed: %08lx\n", hres); + todo_wine_if(compat_mode >= COMPAT_IE9) + ok(dom_attr != NULL, "getNamedItem returned null\n"); + if(dom_attr) + test_no_iface((IUnknown*)dom_attr, &IID_IHTMLDOMNode); + + dom_attr2 = NULL; + hres = IHTMLAttributeCollection4_getNamedItem(attr_col4, bstr, &dom_attr2); + ok(hres == S_OK, "getNamedItem failed: %08lx\n", hres); + todo_wine + test_no_iface((IUnknown*)dom_attr2, &IID_IHTMLDOMNode); + SysFreeString(bstr); + + if(dom_attr) { + todo_wine + ok(iface_cmp((IUnknown*)dom_attr, (IUnknown*)dom_attr2), "attr != attr2\n"); + IHTMLDOMAttribute_Release(dom_attr); + } + IHTMLDOMAttribute2_Release(dom_attr2); + + bstr = SysAllocString(L"style"); + dom_attr = NULL; + hres = IHTMLAttributeCollection2_getNamedItem(attr_col2, bstr, &dom_attr); + ok(hres == S_OK, "getNamedItem failed: %08lx\n", hres); + todo_wine_if(compat_mode >= COMPAT_IE9) + ok(dom_attr != NULL, "style attribute not found\n"); + if(dom_attr) + IHTMLDOMAttribute_Release(dom_attr); + + dom_attr2 = (void *)0xdeadbeef; + hres = IHTMLAttributeCollection4_getNamedItem(attr_col4, bstr, &dom_attr2); + ok(hres == S_OK, "getNamedItem failed: %08lx\n", hres); + ok(!dom_attr2, "style attribute found\n"); + SysFreeString(bstr); + + hres = IHTMLAttributeCollection4_get_length(attr_col4, &len_ie9); + ok(hres == S_OK, "get_length failed: %08lx\n", hres); + todo_wine_if(compat_mode < COMPAT_IE9) + ok(len_ie9 == 6, "length = %ld\n", len_ie9); + + V_VT(&id) = VT_I4; + V_I4(&id) = len_ie9; + hres = IHTMLAttributeCollection_item(attr_col, &id, &attr); + ok(hres == S_OK, "getNamedItem failed: %08lx\n", hres); + ok(attr != NULL, "attr = NULL\n"); + IDispatch_Release(attr); + + dom_attr2 = (void*)0xdeadbeef; + hres = IHTMLAttributeCollection4_item(attr_col4, len_ie9, &dom_attr2); + ok(hres == S_OK, "getNamedItem failed: %08lx\n", hres); + ok(!dom_attr2, "attr = NULL\n");
IDispatch_Release(disp); IHTMLAttributeCollection_Release(attr_col); + IHTMLAttributeCollection2_Release(attr_col2); + IHTMLAttributeCollection4_Release(attr_col4); +} + +static void test_attributes(IHTMLDocument2 *doc, IHTMLElement *parent) +{ + IHTMLDOMAttribute2 *attr2; + IHTMLDOMNode *elem_node; + IHTMLElement6 *elem6; + IHTMLElement *elem; + BSTR bstr; + HRESULT hres; + + test_elem_set_innerhtml((IUnknown*)parent, + L"<div id="attr" attr1="attr1" attr2 attr3="attr3"></div>"); + elem_node = get_first_child((IUnknown*)parent); + + elem = get_elem_iface((IUnknown*)elem_node); + test_attr_collection(elem); + + hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLElement6, (void**)&elem6); + ok(hres == S_OK, "Could not get IHTMLElement6: %08lx\n", hres); + + bstr = SysAllocString(L"attr1"); + hres = IHTMLElement6_getAttributeNode(elem6, bstr, &attr2); + SysFreeString(bstr); + ok(hres == S_OK, "getAttributeNode failed: %08lx\n", hres); + todo_wine + test_no_iface((IUnknown*)attr2, &IID_IHTMLDOMNode); + IHTMLDOMAttribute2_Release(attr2); + + bstr = SysAllocString(L"style"); + attr2 = (void*)0xdeadbeef; + hres = IHTMLElement6_getAttributeNode(elem6, bstr, &attr2); + SysFreeString(bstr); + ok(hres == S_OK, "getAttributeNode failed: %08lx\n", hres); + ok(!attr2, "getAttributeNode returned %p\n", attr2); + + IHTMLElement6_Release(elem6); + IHTMLElement_Release(elem); + IHTMLDOMNode_Release(elem_node); }
static void test_attr_collection_builtins(IHTMLDocument2 *doc) @@ -10082,7 +10199,6 @@ static void test_elems(IHTMLDocument2 *doc) elem = get_elem_by_id(doc, L"attr", TRUE); if(elem) { test_dynamic_properties(elem); - test_attr_collection(elem); test_contenteditable((IUnknown*)elem); IHTMLElement_Release(elem); } @@ -11121,6 +11237,7 @@ static void test_dom_elements(IHTMLDocument2 *doc) test_textarea_element(doc, div); test_form_element(doc, div); test_svg_element(doc, div); + test_attributes(doc, div);
IHTMLElement_Release(div); }