From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/dom.c | 93 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 6 deletions(-)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 6fe0ef1584a..e8b0fd77179 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -2099,10 +2099,10 @@ static void _test_comment_text(unsigned line, IUnknown *unk, const WCHAR *extext }
#define create_attr(a,b) _create_attr(__LINE__,a,b) -static IHTMLDOMAttribute *_create_attr(unsigned line, IUnknown *unk, const char *name) +static IHTMLDOMAttribute *_create_attr(unsigned line, IUnknown *unk, const WCHAR *name) { IHTMLDocument5 *doc = _get_htmldoc5_iface(line, unk); - BSTR str = SysAllocString(L"Test"); + BSTR str = SysAllocString(name); IHTMLDOMAttribute *attr; HRESULT hres;
@@ -5618,6 +5618,78 @@ static IHTMLDOMAttribute *_get_elem_attr_node(unsigned line, IUnknown *unk, cons return attr; }
+#define get_elem6_attr_node(a,b,c) _get_elem6_attr_node(__LINE__,a,b,c) +static IHTMLDOMAttribute *_get_elem6_attr_node(unsigned line, IUnknown *unk, const WCHAR *attr_name, BOOL expect_success) +{ + BSTR str = SysAllocString(attr_name); + IHTMLDOMAttribute2 *attr2; + IHTMLDOMAttribute *attr; + IHTMLElement6 *elem; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement6, (void**)&elem); + ok_(__FILE__,line)(hres == S_OK, "Could not get IHTMLElement6: %08lx\n", hres); + + attr = (void*)0xdeadbeef; + hres = IHTMLElement6_getAttributeNode(elem, str, &attr2); + ok_(__FILE__,line)(hres == S_OK, "getAttributeNode failed: %08lx\n", hres); + if(expect_success) { + ok_(__FILE__,line)(attr2 != NULL, "attr = NULL\n"); + hres = IHTMLDOMAttribute2_QueryInterface(attr2, &IID_IHTMLDOMAttribute, (void**)&attr); + ok_(__FILE__,line)(hres == S_OK, "Could not get IHTMLDOMAttribute: %08lx\n", hres); + IHTMLDOMAttribute2_Release(attr2); + }else { + ok_(__FILE__,line)(!attr2, "attr = %p\n", attr2); + attr = NULL; + } + + IHTMLElement6_Release(elem); + SysFreeString(str); + return attr; +} + +#define get_elem_attr_node_via_disp(a,b,c) _get_elem_attr_node_via_disp(__LINE__,a,b,c) +static IHTMLDOMAttribute *_get_elem_attr_node_via_disp(unsigned line, IUnknown *unk, const WCHAR *attr_name, BOOL expect_success) +{ + IHTMLDOMAttribute *attr = NULL; + DISPPARAMS dp = { 0 }; + IDispatchEx *dispex; + VARIANT var, arg; + EXCEPINFO ei; + HRESULT hres; + DISPID id; + BSTR str; + + hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line)(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + + str = SysAllocString(L"getAttributeNode"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseSensitive, &id); + ok_(__FILE__,line)(hres == S_OK, "GetDispID failed: %08lx\n", hres); + SysFreeString(str); + + dp.cArgs = 1; + dp.rgvarg = &arg; + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = SysAllocString(attr_name); + + VariantInit(&var); + hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, DISPATCH_METHOD, &dp, &var, &ei, NULL); + ok_(__FILE__,line)(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + if(!expect_success) + ok_(__FILE__,line)(V_VT(&var) == VT_NULL, "V_VT(var) = %d\n", V_VT(&var)); + else { + ok_(__FILE__,line)(V_VT(&var) == VT_DISPATCH, "V_VT(var) = %d\n", V_VT(&var)); + ok_(__FILE__,line)(V_DISPATCH(&var) != NULL, "V_DISPATCH(var) == NULL\n"); + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IHTMLDOMAttribute, (void**)&attr); + ok_(__FILE__,line)(hres == S_OK, "Could not get IHTMLDOMAttribute: %08lx\n", hres); + } + IDispatchEx_Release(dispex); + VariantClear(&arg); + VariantClear(&var); + return attr; +} + #define get_attr_node_value(a,b,c) _get_attr_node_value(__LINE__,a,b,c) static void _get_attr_node_value(unsigned line, IHTMLDOMAttribute *attr, VARIANT *v, VARTYPE vt) { @@ -10818,16 +10890,25 @@ static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem) test_attr_specified(attr, has_attr ? VARIANT_TRUE : VARIANT_FALSE); test_attr_expando(attr, VARIANT_FALSE); IHTMLDOMAttribute_Release(attr); + attr = get_elem6_attr_node((IUnknown*)elem, elem_attr_props[i], has_attr); + if(attr) IHTMLDOMAttribute_Release(attr); + attr = get_elem_attr_node_via_disp((IUnknown*)elem, elem_attr_props[i], TRUE); + if(attr) IHTMLDOMAttribute_Release(attr); } for(i = 0; i < ARRAY_SIZE(elem_noattr_props); i++) { get_elem_attr_node((IUnknown*)elem, elem_noattr_props[i], FALSE); + get_elem6_attr_node((IUnknown*)elem, elem_noattr_props[i], FALSE); }
ok(elem_has_attr((IUnknown*)elem, L"emptyattr"), "elem does not have emptyattr"); - attr = get_elem_attr_node((IUnknown*)elem, L"emptyattr", TRUE); + attr = get_elem6_attr_node((IUnknown*)elem, L"emptyattr", TRUE); test_attr_specified(attr, VARIANT_TRUE); - test_attr_expando(attr, VARIANT_TRUE); test_attr_node(attr, doc); + IHTMLDOMAttribute_Release(attr); + + attr = get_elem_attr_node_via_disp((IUnknown*)elem, L"emptyattr", TRUE); + test_attr_specified(attr, VARIANT_TRUE); + test_attr_expando(attr, VARIANT_TRUE);
bstr = SysAllocString(L"emptyattr"); hres = IHTMLElement_removeAttribute(elem, bstr, 0, &vbool); @@ -10846,7 +10927,7 @@ static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem) IHTMLDOMAttribute_Release(attr);
/* Test created, detached attribute. */ - attr = create_attr((IUnknown*)doc, "Test"); + attr = create_attr((IUnknown*)doc, L"Test");
test_disp((IUnknown*)attr, &DIID_DispHTMLDOMAttribute, NULL, L"[object]"); test_ifaces((IUnknown*)attr, attr_iids); @@ -10888,7 +10969,7 @@ static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem) ok(iface_cmp((IUnknown*)attr2, (IUnknown*)attr), "attr2 != attr\n"); IHTMLDOMAttribute_Release(attr2);
- attr3 = create_attr((IUnknown*)doc, "Test"); + attr3 = create_attr((IUnknown*)doc, L"Test"); put_attr_value(attr3, L"replace test");
hres = IHTMLElement4_setAttributeNode(elem4, attr3, &attr2);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/dom.c | 275 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index e8b0fd77179..4f22895f3c3 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -1321,6 +1321,33 @@ static void _test_elem_attr(unsigned line, IHTMLElement *elem, const WCHAR *name VariantClear(&value); }
+#define test_elem_attr_todo(e,n,v) _test_elem_attr_todo(__LINE__,e,n,v) +static void _test_elem_attr_todo(unsigned line, IHTMLElement *elem, const WCHAR *name, const WCHAR *exval) +{ + VARIANT value; + BSTR tmp; + HRESULT hres; + + VariantInit(&value); + + tmp = SysAllocString(name); + hres = IHTMLElement_getAttribute(elem, tmp, 0, &value); + SysFreeString(tmp); + ok_(__FILE__,line) (hres == S_OK, "getAttribute failed: %08lx\n", hres); + + if(exval) { + todo_wine + ok_(__FILE__,line) (V_VT(&value) == VT_BSTR, "vt=%d\n", V_VT(&value)); + todo_wine + ok_(__FILE__,line) (!lstrcmpW(V_BSTR(&value), exval), "unexpected value %s\n", wine_dbgstr_w(V_BSTR(&value))); + }else { + todo_wine + ok_(__FILE__,line) (V_VT(&value) == VT_NULL, "vt=%d\n", V_VT(&value)); + } + + VariantClear(&value); +} + #define test_elem_offset(a,b) _test_elem_offset(__LINE__,a,b) static void _test_elem_offset(unsigned line, IUnknown *unk, const WCHAR *parent_tag) { @@ -13201,6 +13228,253 @@ static void test_document_mode_after_initnew(void) IHTMLDocument2_Release(doc); }
+static void test_attribute_node_across_modes(void) +{ + IHTMLDOMAttribute *attr, *attr_ie9, *old_attr; + IHTMLElement4 *elem4, *elem4_ie9; + IDispatchEx *dispex, *dispex_ie9; + IHTMLDocument2 *doc, *doc_ie9; + IHTMLElement *elem, *elem_ie9; + IPersistStreamInit *init; + DISPPARAMS dp = { 0 }; + IHTMLDocument6 *doc6; + IStream *stream; + BSTR name, bstr; + DISPID dispid; + HRESULT hres; + HGLOBAL mem; + SIZE_T len; + VARIANT v; + MSG msg; + + notif_doc = doc = create_document(); + if(!doc) + return; + doc_complete = FALSE; + + len = strlen(doc_blank); + mem = GlobalAlloc(0, len); + memcpy(mem, doc_blank, len); + hres = CreateStreamOnHGlobal(mem, TRUE, &stream); + ok(hres == S_OK, "Failed to create stream: %08lx.\n", hres); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); + ok(hres == S_OK, "QueryInterface(IID_IPersistStreamInit) failed: %08lx.\n", hres); + + IPersistStreamInit_Load(init, stream); + IPersistStreamInit_Release(init); + IStream_Release(stream); + + set_client_site(doc, TRUE); + do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + + while(!doc_complete && GetMessageW(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + notif_doc = doc_ie9 = create_document(); + if(!doc_ie9) { + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); + return; + } + doc_complete = FALSE; + + len = strlen(doc_blank_ie9); + mem = GlobalAlloc(0, len); + memcpy(mem, doc_blank_ie9, len); + hres = CreateStreamOnHGlobal(mem, TRUE, &stream); + ok(hres == S_OK, "Failed to create stream: %08lx.\n", hres); + + hres = IHTMLDocument2_QueryInterface(doc_ie9, &IID_IPersistStreamInit, (void**)&init); + ok(hres == S_OK, "QueryInterface(IID_IPersistStreamInit) failed: %08lx.\n", hres); + + IPersistStreamInit_Load(init, stream); + IPersistStreamInit_Release(init); + IStream_Release(stream); + + set_client_site(doc_ie9, TRUE); + do_advise((IUnknown*)doc_ie9, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + + while(!doc_complete && GetMessageW(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument6, (void**)&doc6); + ok(hres == S_OK, "Could not get IHTMLDocument6 interface: %08lx\n", hres); + V_VT(&v) = VT_EMPTY; + hres = IHTMLDocument6_get_documentMode(doc6, &v); + ok(hres == S_OK, "get_documentMode failed: %08lx\n", hres); + ok(V_VT(&v) == VT_R4, "V_VT(documentMode) = %u\n", V_VT(&v)); + ok(V_R4(&v) == 5, "documentMode = %f\n", V_R4(&v)); + IHTMLDocument6_Release(doc6); + + hres = IHTMLDocument2_QueryInterface(doc_ie9, &IID_IHTMLDocument6, (void**)&doc6); + ok(hres == S_OK, "Could not get IHTMLDocument6 interface: %08lx\n", hres); + V_VT(&v) = VT_EMPTY; + hres = IHTMLDocument6_get_documentMode(doc6, &v); + ok(hres == S_OK, "get_documentMode failed: %08lx\n", hres); + ok(V_VT(&v) == VT_R4, "V_VT(documentMode) = %u\n", V_VT(&v)); + ok(V_R4(&v) == 9, "documentMode = %f\n", V_R4(&v)); + IHTMLDocument6_Release(doc6); + + elem = doc_get_body(doc); + elem4 = get_elem4_iface((IUnknown*)elem); + dispex = get_dispex_iface((IUnknown*)elem); + elem_ie9 = doc_get_body(doc_ie9); + elem4_ie9 = get_elem4_iface((IUnknown*)elem_ie9); + dispex_ie9 = get_dispex_iface((IUnknown*)elem_ie9); + + name = SysAllocString(L"testattr"); + attr = create_attr((IUnknown*)doc, name); + put_attr_value(attr, L"attr"); + + attr_ie9 = create_attr((IUnknown*)doc_ie9, name); + put_attr_value(attr_ie9, L"attr_ie9"); + + test_attr_value(attr, L"attr"); + test_attr_value(attr_ie9, L"attr_ie9"); + + hres = IHTMLElement_GetIDsOfNames(elem, &IID_NULL, &name, 1, 0, &dispid); + ok(hres == DISP_E_UNKNOWNNAME, "GetIDsOfNames returned: %08lx\n", hres); + hres = IHTMLElement_GetIDsOfNames(elem_ie9, &IID_NULL, &name, 1, 0, &dispid); + ok(hres == DISP_E_UNKNOWNNAME, "GetIDsOfNames returned: %08lx\n", hres); + + hres = IHTMLElement4_setAttributeNode(elem4, attr_ie9, &old_attr); + ok(hres == S_OK, "setAttributeNode failed: %08lx\n", hres); + ok(!old_attr, "old_attr != NULL\n"); + + hres = IHTMLElement4_setAttributeNode(elem4_ie9, attr, &old_attr); + ok(hres == S_OK, "setAttributeNode failed: %08lx\n", hres); + ok(!old_attr, "old_attr != NULL\n"); + + test_attr_value(attr, L"attr"); + test_attr_value(attr_ie9, L"attr_ie9"); + test_elem_attr(elem, name, L"attr_ie9"); + test_elem_attr_todo(elem_ie9, name, L"attr"); + + hres = IHTMLElement_GetIDsOfNames(elem, &IID_NULL, &name, 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames returned: %08lx\n", hres); + hres = IDispatchEx_GetMemberName(dispex, dispid, &bstr); + ok(hres == S_OK, "GetMemberName failed: %08lx\n", hres); + ok(!wcscmp(bstr, name), "GetMemberName returned %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IHTMLElement_GetIDsOfNames(elem_ie9, &IID_NULL, &name, 1, 0, &dispid); + ok(hres == S_OK || hres == DISP_E_UNKNOWNNAME, "GetIDsOfNames returned: %08lx\n", hres); + if(hres == S_OK) { + hres = IDispatchEx_GetMemberName(dispex_ie9, dispid, &bstr); + todo_wine + ok(hres == E_INVALIDARG, "GetMemberName returned: %08lx\n", hres); + } + IHTMLDOMAttribute_Release(attr_ie9); + IHTMLDOMAttribute_Release(attr); + + attr = create_attr((IUnknown*)doc, name); + put_attr_value(attr, L"wine"); + + attr_ie9 = create_attr((IUnknown*)doc_ie9, name); + put_attr_value(attr_ie9, L"wine_ie9"); + + test_attr_value(attr, L"wine"); + test_attr_value(attr_ie9, L"wine_ie9"); + test_elem_attr(elem, name, L"attr_ie9"); + test_elem_attr_todo(elem_ie9, name, L"attr"); + + hres = IHTMLElement4_setAttributeNode(elem4, attr_ie9, &old_attr); + ok(hres == S_OK, "setAttributeNode failed: %08lx\n", hres); + test_attr_value(old_attr, L"attr_ie9"); + test_attr_value(attr_ie9, L"wine_ie9"); + test_elem_attr(elem, name, L"wine_ie9"); + IHTMLDOMAttribute_Release(old_attr); + + hres = IHTMLElement4_setAttributeNode(elem4_ie9, attr, &old_attr); + ok(hres == S_OK, "setAttributeNode failed: %08lx\n", hres); + test_attr_value(old_attr, L"attr"); + test_attr_value(attr, L"wine"); + test_elem_attr_todo(elem_ie9, name, L"wine"); + IHTMLDOMAttribute_Release(old_attr); + + IDispatchEx_Release(dispex_ie9); + IDispatchEx_Release(dispex); + + /* The attributes function in their actual compat modes, regardless of the element's mode */ + bstr = SysAllocString(L"firstChild"); + dispex = get_dispex_iface((IUnknown*)attr); + dispex_ie9 = get_dispex_iface((IUnknown*)attr_ie9); + + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); + hres = IDispatchEx_InvokeEx(dispex, dispid, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(firstChild) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) == NULL, "V_DISPATCH(firstChild) != NULL\n"); + VariantClear(&v); + + hres = IDispatchEx_GetDispID(dispex_ie9, bstr, fdexNameCaseSensitive, &dispid); + ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); + hres = IDispatchEx_InvokeEx(dispex_ie9, dispid, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL); + todo_wine + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + todo_wine + ok(V_VT(&v) == VT_DISPATCH, "V_VT(firstChild) = %d\n", V_VT(&v)); + todo_wine + ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(firstChild) == NULL\n"); + VariantClear(&v); + + IHTMLDOMAttribute_Release(attr_ie9); + IHTMLDOMAttribute_Release(attr); + IDispatchEx_Release(dispex_ie9); + IDispatchEx_Release(dispex); + SysFreeString(name); + + /* And obtaining unspecified builtins in IE9 elements with IHTMLElement4's getAttributeNode still has proper node */ + name = SysAllocString(L"title"); + hres = IHTMLElement4_getAttributeNode(elem4_ie9, name, &attr_ie9); + ok(hres == S_OK, "getAttributeNode failed: %08lx\n", hres); + todo_wine + ok(attr_ie9 != NULL, "attr_ie9 = NULL\n"); + if(!attr_ie9) + goto end; + + dispex_ie9 = get_dispex_iface((IUnknown*)attr_ie9); + hres = IDispatchEx_GetDispID(dispex_ie9, bstr, fdexNameCaseSensitive, &dispid); + ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); + hres = IDispatchEx_InvokeEx(dispex_ie9, dispid, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + ok(V_VT(&v) == VT_NULL, "V_VT(firstChild) = %d\n", V_VT(&v)); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = SysAllocString(L"test"); + hres = IHTMLElement_setAttribute(elem_ie9, name, v, 0); + ok(hres == S_OK, "setAttribute failed: %08lx\n", hres); + VariantClear(&v); + + hres = IDispatchEx_InvokeEx(dispex_ie9, dispid, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(firstChild) = %d\n", V_VT(&v)); + ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(firstChild) == NULL\n"); + IHTMLDOMAttribute_Release(attr_ie9); + IDispatchEx_Release(dispex_ie9); + +end: + SysFreeString(bstr); + SysFreeString(name); + VariantClear(&v); + + IHTMLElement4_Release(elem4_ie9); + IHTMLElement4_Release(elem4); + IHTMLElement_Release(elem_ie9); + IHTMLElement_Release(elem); + + set_client_site(doc_ie9, FALSE); + IHTMLDocument2_Release(doc_ie9); + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); +} + static DWORD WINAPI create_document_proc(void *param) { IHTMLDocument2 *doc = NULL; @@ -13334,6 +13608,7 @@ START_TEST(dom) test_default_content_charset(); test_document_mode_lock(); test_document_mode_after_initnew(); + test_attribute_node_across_modes(); test_threads();
/* Run this last since it messes with the process-wide user agent */
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/dom.js | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index bd7af124167..ff81bcc8c90 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -1103,4 +1103,49 @@ sync_test("attributeNode", function() { 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"]); + + attr = elem.getAttributeNode("attr"); + ok(attr.ownerDocument === document, "ownerDocument = " + attr.ownerDocument); + ok(attr.ownerElement === elem, "ownerElement = " + attr.ownerElement); + ok(attr.namespaceURI === null, "namespaceURI = " + attr.namespaceURI); + ok(attr.specified === true, "attr is not specified"); + ok(attr.textContent === "wine", "textContent = " + attr.textContent); + todo_wine. + ok(attr.hasChildNodes() === true, "attr doesn't have child nodes"); + todo_wine. + ok(attr.childNodes.length === 1, "child count = " + attr.childNodes.length); + if(attr.firstChild /* todo_wine */) { + ok(attr.firstChild.nodeType === 3, "child nodeType = " + attr.firstChild.nodeType); + ok(attr.firstChild.textContent === "wine", "child textContent = " + attr.firstChild.textContent); + } + + elem = document.createElement("span"); + try { + attr.appendChild(elem); + ok(false, "appendChild did not throw"); + }catch(e) { + todo_wine. + ok(e.message === "HierarchyRequestError", "appendChild threw " + e.message); + } + try { + attr.insertBefore(elem, null); + ok(false, "insertBefore did not throw"); + }catch(e) { + todo_wine. + ok(e.message === "HierarchyRequestError", "insertBefore threw " + e.message); + } + try { + attr.replaceChild(elem, attr.firstChild); + ok(false, "replaceChild did not throw"); + }catch(e) { + todo_wine. + ok(e.message === "HierarchyRequestError", "replaceChild threw " + e.message); + } + try { + attr.removeChild(attr.firstChild); + ok(false, "removeChild did not throw"); + }catch(e) { + todo_wine. + ok(e.message === "NotFoundError", "removeChild threw " + e.message); + } });
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/documentmode.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index fe272f0f08a..ae8212f0c48 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -486,10 +486,10 @@ sync_test("builtin_obj", function() { enumerator.moveNext(); ok(enumerator.atEnd(), "enumerator not at end"); }else { - elem = f.call.call(f, document, "div"); + elem1 = f.call.call(f, document, "div"); f = f.bind(document); - elem = f.apply(null, ["style"]); - document.body.appendChild(elem); + elem1 = f.apply(null, ["style"]); + document.body.appendChild(elem1);
try { var enumerator = new Enumerator(document.getElementsByTagName("style"));
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 5 +++- dlls/mshtml/htmlattr.c | 42 ++++++++++++++++++++++++++++++- dlls/mshtml/tests/documentmode.js | 35 +++++++++++++++++++++++++- dlls/mshtml/tests/dom.c | 1 + 4 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 92a3746f4e5..111f3377ff9 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1384,7 +1384,10 @@ HRESULT dispex_get_chain_builtin_id(DispatchEx *dispex, const WCHAR *name, DWORD const dispex_data_t *info = dispex->info; HRESULT hres;
- assert(compat_mode >= COMPAT_MODE_IE9); + hres = get_builtin_id(info, name, flags, pid); + if(hres != DISP_E_UNKNOWNNAME || compat_mode < COMPAT_MODE_IE9) + return hres; + info = info->desc->prototype_info[compat_mode - COMPAT_MODE_IE9];
for(;;) { hres = get_builtin_id(info, name, flags, pid); diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c index 0816ccefdbe..76c8f7dfa68 100644 --- a/dlls/mshtml/htmlattr.c +++ b/dlls/mshtml/htmlattr.c @@ -208,10 +208,50 @@ static HRESULT WINAPI HTMLDOMAttribute2_get_value(IHTMLDOMAttribute2 *iface, BST static HRESULT WINAPI HTMLDOMAttribute2_get_expando(IHTMLDOMAttribute2 *iface, VARIANT_BOOL *p) { HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); + const PRUnichar *name; + nsIDOMElement *nselem; + HTMLElement *elem; + nsAString nsname; + nsresult nsres; + HRESULT hres; + DISPID id;
TRACE("(%p)->(%p)\n", This, p);
- *p = variant_bool(!This->dom_attr && This->elem && get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN); + if(This->dom_attr) { + nsres = nsIDOMAttr_GetOwnerElement(This->dom_attr, &nselem); + assert(nsres == NS_OK); + if(!nselem) { + *p = VARIANT_FALSE; + return S_OK; + } + + hres = get_element(nselem, &elem); + nsIDOMElement_Release(nselem); + if(FAILED(hres)) + return hres; + + nsAString_InitDepend(&nsname, NULL); + nsres = nsIDOMAttr_GetName(This->dom_attr, &nsname); + if(NS_FAILED(nsres)) { + IHTMLElement2_Release(&elem->IHTMLElement2_iface); + return map_nsresult(nsres); + } + + nsAString_GetData(&nsname, &name); + hres = dispex_get_chain_builtin_id(&elem->node.event_target.dispex, name, fdexNameCaseInsensitive, &id); + nsAString_Finish(&nsname); + if(SUCCEEDED(hres)) + *p = variant_bool(dispex_builtin_is_noattr(&elem->node.event_target.dispex, id)); + else if(hres == DISP_E_UNKNOWNNAME) { + *p = VARIANT_TRUE; + hres = S_OK; + } + IHTMLElement2_Release(&elem->IHTMLElement2_iface); + return hres; + } + + *p = variant_bool(This->elem && get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN); return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index ae8212f0c48..13772b52606 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -580,7 +580,16 @@ sync_test("attr_props", function() {
elem.innerHTML = '<span id="test"></span>'; elem = elem.getElementsByTagName("span")[0]; - attr = elem.attributes[0]; + attr = elem.getAttributeNode("id"); + + if(v < 8) + ok(elem.attributes.length > 50, "attributes.length = " + elem.attributes.length); + else { + todo_wine_if(v === 8). + ok(elem.attributes.length === 1, "attributes.length = " + elem.attributes.length); + todo_wine_if(v === 8). + ok(elem.attributes[0] === attr, "attributes[0] != attr"); + }
function test_exposed(prop, expect) { if(expect) @@ -589,6 +598,13 @@ sync_test("attr_props", function() { ok(!(prop in attr), prop + " found in attribute."); }
+ function test_attr(expando, specified) { + var r = attr.expando; + ok(r === expando, attr.name + " attr.expando = " + r); + r = attr.specified; + ok(r === specified, attr.name + " attr.specified = " + r); + } + test_exposed("appendChild", true); test_exposed("attributes", true); test_exposed("childNodes", true); @@ -622,6 +638,23 @@ sync_test("attr_props", function() { test_exposed("specified", true); test_exposed("textContent", v >= 9); test_exposed("value", true); + test_attr(false, true); + + elem.setAttribute("test", "wine"); + elem.setAttribute("z-index", "foobar"); + + attr = elem.getAttributeNode("test"); + test_attr(true, true); + + attr = elem.getAttributeNode("z-index"); + test_attr(true, true); + + attr = elem.getAttributeNode("tabIndex"); + if(v < 8) + test_attr(false, false); + else + todo_wine_if(v === 8). + ok(attr === null, "tabIndex attr not null."); });
sync_test("doc_props", function() { diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 4f22895f3c3..26b487b9175 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -10930,6 +10930,7 @@ static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem) ok(elem_has_attr((IUnknown*)elem, L"emptyattr"), "elem does not have emptyattr"); attr = get_elem6_attr_node((IUnknown*)elem, L"emptyattr", TRUE); test_attr_specified(attr, VARIANT_TRUE); + test_attr_expando(attr, VARIANT_TRUE); test_attr_node(attr, doc); IHTMLDOMAttribute_Release(attr);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlattr.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c index 76c8f7dfa68..643313a8eef 100644 --- a/dlls/mshtml/htmlattr.c +++ b/dlls/mshtml/htmlattr.c @@ -549,6 +549,7 @@ static HRESULT WINAPI HTMLDOMAttribute3_get_ownerElement(IHTMLDOMAttribute3 *ifa if(dom_element) { HTMLElement *element; hres = get_element(dom_element, &element); + nsIDOMElement_Release(dom_element); if(SUCCEEDED(hres)) *p = &element->IHTMLElement2_iface; }else {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlattr.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/mshtml/htmlattr.c b/dlls/mshtml/htmlattr.c index 643313a8eef..634293a75b2 100644 --- a/dlls/mshtml/htmlattr.c +++ b/dlls/mshtml/htmlattr.c @@ -608,6 +608,7 @@ static void *HTMLDOMAttribute_query_interface(DispatchEx *dispex, REFIID riid) static void HTMLDOMAttribute_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) { HTMLDOMAttribute *This = impl_from_DispatchEx(dispex); + HTMLDOMNode_traverse(&This->node.event_target.dispex, cb);
if(This->doc) note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "doc", cb); @@ -619,6 +620,7 @@ static void HTMLDOMAttribute_traverse(DispatchEx *dispex, nsCycleCollectionTrave static void HTMLDOMAttribute_unlink(DispatchEx *dispex) { HTMLDOMAttribute *This = impl_from_DispatchEx(dispex); + HTMLDOMNode_unlink(&This->node.event_target.dispex);
if(This->doc) { HTMLDocumentNode *doc = This->doc;
This merge request was approved by Jacek Caban.
Let's skip the last patch, I'm not sure it's worth blurring node boundary for sake of saving a few lines of code. If we will have another need for that, we may change in then.