`getAttributeNS` is tested with the `setAttributeNS` implementation.
-- v3: mshtml: Implement HTMLTitleElement's text property. mshtml: Implement childElementCount for Elements. mshtml: Implement previousElementSibling for Elements. mshtml: Implement nextElementSibling for Elements. mshtml: Implement lastElementChild for Elements. mshtml: Implement hasAttributeNS for Elements. mshtml: Implement removeAttributeNS for Elements. mshtml: Implement setAttributeNS for Elements. mshtml: Implement getAttributeNS for Elements.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 59 ++++++++++++++++++++++++++++++++++++++++-- dlls/mshtml/nsembed.c | 1 + 2 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index d911d0a0433..c220d0a5aeb 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4813,8 +4813,33 @@ static HRESULT WINAPI HTMLElement6_Invoke(IHTMLElement6 *iface, DISPID dispIdMem static HRESULT WINAPI HTMLElement6_getAttributeNS(IHTMLElement6 *iface, VARIANT *pvarNS, BSTR strAttributeName, VARIANT *AttributeValue) { HTMLElement *This = impl_from_IHTMLElement6(iface); - FIXME("(%p)->(%s %s %p)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName), AttributeValue); - return E_NOTIMPL; + nsAString ns_str, name_str, value_str; + nsresult nsres; + HRESULT hres; + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName), AttributeValue); + + if(!This->dom_element) { + FIXME("No dom_element\n"); + return E_NOTIMPL; + } + + hres = variant_to_nsstr(pvarNS, FALSE, &ns_str); + if(FAILED(hres)) + return hres; + + nsAString_InitDepend(&name_str, strAttributeName); + nsAString_InitDepend(&value_str, NULL); + nsres = nsIDOMElement_GetAttributeNS(This->dom_element, &ns_str, &name_str, &value_str); + nsAString_Finish(&ns_str); + nsAString_Finish(&name_str); + + hres = return_nsstr_variant(nsres, &value_str, 0, AttributeValue); + if(FAILED(hres) || V_VT(AttributeValue) != VT_NULL) + return hres; + V_VT(AttributeValue) = VT_BSTR; + V_BSTR(AttributeValue) = SysAllocString(L""); + return V_BSTR(AttributeValue) ? S_OK : E_OUTOFMEMORY; }
static HRESULT WINAPI HTMLElement6_setAttributeNS(IHTMLElement6 *iface, VARIANT *pvarNS, BSTR strAttributeName, VARIANT *pvarAttributeValue) @@ -6791,6 +6816,35 @@ static IHTMLEventObj *HTMLElement_set_current_event(DispatchEx *dispex, IHTMLEve return default_set_current_event(This->node.doc->window, event); }
+static HRESULT IHTMLElement6_getAttributeNS_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + VARIANT args[2]; + HRESULT hres; + DISPPARAMS new_dp = { args, NULL, 2, 0 }; + + if(!(flags & DISPATCH_METHOD) || dp->cArgs < 2 || dp->cNamedArgs) + return S_FALSE; + + switch(V_VT(&dp->rgvarg[dp->cArgs - 1])) { + case VT_EMPTY: + case VT_BSTR: + case VT_NULL: + return S_FALSE; + default: + break; + } + + hres = change_type(&args[1], &dp->rgvarg[dp->cArgs - 1], VT_BSTR, caller); + if(FAILED(hres)) + return hres; + args[0] = dp->rgvarg[dp->cArgs - 2]; + + hres = dispex_call_builtin(dispex, DISPID_IHTMLELEMENT6_GETATTRIBUTENS, &new_dp, res, ei, caller); + VariantClear(&args[1]); + return hres; +} + static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -6823,6 +6877,7 @@ static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, WORD flags, D void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode) { static const dispex_hook_t elem6_ie10_hooks[] = { + {DISPID_IHTMLELEMENT6_GETATTRIBUTENS, IHTMLElement6_getAttributeNS_hook}, {DISPID_IHTMLELEMENT6_IE9_SETATTRIBUTE, IHTMLElement6_setAttribute_hook}, {DISPID_UNKNOWN} }; diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 8f456b40ef2..c7683a6d06d 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -998,6 +998,7 @@ HRESULT variant_to_nsstr(VARIANT *v, BOOL hex_int, nsAString *nsstr) WCHAR buf[32];
switch(V_VT(v)) { + case VT_EMPTY: case VT_NULL: nsAString_InitDepend(nsstr, NULL); return S_OK;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 100 ++++++++++++++++++++++- dlls/mshtml/tests/documentmode.js | 128 ++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index c220d0a5aeb..9d17d63b606 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4845,8 +4845,42 @@ static HRESULT WINAPI HTMLElement6_getAttributeNS(IHTMLElement6 *iface, VARIANT static HRESULT WINAPI HTMLElement6_setAttributeNS(IHTMLElement6 *iface, VARIANT *pvarNS, BSTR strAttributeName, VARIANT *pvarAttributeValue) { HTMLElement *This = impl_from_IHTMLElement6(iface); - FIXME("(%p)->(%s %s %s)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName), debugstr_variant(pvarAttributeValue)); - return E_NOTIMPL; + nsAString ns_str, name_str, value_str; + const PRUnichar *ns; + nsresult nsres; + HRESULT hres; + + TRACE("(%p)->(%s %s %s)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName), debugstr_variant(pvarAttributeValue)); + + hres = variant_to_nsstr(pvarNS, FALSE, &ns_str); + if(FAILED(hres)) + return hres; + nsAString_GetData(&ns_str, &ns); + if((!ns || !ns[0]) && wcschr(strAttributeName, ':')) { + /* FIXME: Return NamespaceError */ + return E_FAIL; + } + + if(!This->dom_element) { + FIXME("No dom_element\n"); + nsAString_Finish(&ns_str); + return E_NOTIMPL; + } + + hres = variant_to_nsstr(pvarAttributeValue, FALSE, &value_str); + if(FAILED(hres)) { + nsAString_Finish(&ns_str); + return hres; + } + + nsAString_InitDepend(&name_str, strAttributeName); + nsres = nsIDOMElement_SetAttributeNS(This->dom_element, &ns_str, &name_str, &value_str); + nsAString_Finish(&ns_str); + nsAString_Finish(&name_str); + nsAString_Finish(&value_str); + if(NS_FAILED(nsres)) + WARN("SetAttributeNS failed: %08lx\n", nsres); + return map_nsresult(nsres); }
static HRESULT WINAPI HTMLElement6_removeAttributeNS(IHTMLElement6 *iface, VARIANT *pvarNS, BSTR strAttributeName) @@ -6845,6 +6879,61 @@ static HRESULT IHTMLElement6_getAttributeNS_hook(DispatchEx *dispex, WORD flags, return hres; }
+static HRESULT IHTMLElement6_setAttributeNS_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + BOOL ns_conv = FALSE, val_conv = FALSE; + VARIANT args[3]; + HRESULT hres; + DISPPARAMS new_dp = { args, NULL, 3, 0 }; + + if(!(flags & DISPATCH_METHOD) || dp->cArgs < 3 || dp->cNamedArgs) + return S_FALSE; + + if(dispex_compat_mode(dispex) < COMPAT_MODE_IE10) + args[2] = dp->rgvarg[dp->cArgs - 1]; + else { + switch(V_VT(&dp->rgvarg[dp->cArgs - 1])) { + case VT_EMPTY: + case VT_BSTR: + case VT_NULL: + args[2] = dp->rgvarg[dp->cArgs - 1]; + break; + default: + hres = change_type(&args[2], &dp->rgvarg[dp->cArgs - 1], VT_BSTR, caller); + if(FAILED(hres)) + return hres; + ns_conv = TRUE; + break; + } + } + + switch(V_VT(&dp->rgvarg[dp->cArgs - 3])) { + case VT_EMPTY: + case VT_BSTR: + case VT_NULL: + if(!ns_conv) + return S_FALSE; + args[0] = dp->rgvarg[dp->cArgs - 3]; + break; + default: + hres = change_type(&args[0], &dp->rgvarg[dp->cArgs - 3], VT_BSTR, caller); + if(FAILED(hres)) { + if(ns_conv) + VariantClear(&args[2]); + return hres; + } + val_conv = TRUE; + break; + } + + args[1] = dp->rgvarg[dp->cArgs - 2]; + hres = dispex_call_builtin(dispex, DISPID_IHTMLELEMENT6_SETATTRIBUTENS, &new_dp, res, ei, caller); + if(ns_conv) VariantClear(&args[2]); + if(val_conv) VariantClear(&args[0]); + return hres; +} + static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -6876,8 +6965,13 @@ static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, WORD flags, D
void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode) { + static const dispex_hook_t elem6_ie9_hooks[] = { + {DISPID_IHTMLELEMENT6_SETATTRIBUTENS, IHTMLElement6_setAttributeNS_hook}, + {DISPID_UNKNOWN} + }; static const dispex_hook_t elem6_ie10_hooks[] = { {DISPID_IHTMLELEMENT6_GETATTRIBUTENS, IHTMLElement6_getAttributeNS_hook}, + {DISPID_IHTMLELEMENT6_SETATTRIBUTENS, IHTMLElement6_setAttributeNS_hook}, {DISPID_IHTMLELEMENT6_IE9_SETATTRIBUTE, IHTMLElement6_setAttribute_hook}, {DISPID_UNKNOWN} }; @@ -6895,7 +6989,7 @@ void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode) dispex_info_add_interface(info, IElementSelector_tid, NULL);
if(mode >= COMPAT_MODE_IE9) { - dispex_info_add_interface(info, IHTMLElement6_tid, mode >= COMPAT_MODE_IE10 ? elem6_ie10_hooks : NULL); + dispex_info_add_interface(info, IHTMLElement6_tid, mode >= COMPAT_MODE_IE10 ? elem6_ie10_hooks : elem6_ie9_hooks); dispex_info_add_interface(info, IElementTraversal_tid, NULL); }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 299d46e5727..9e7c3ac1d9d 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1408,6 +1408,134 @@ sync_test("elem_attr", function() { } });
+sync_test("elem_attrNS", function() { + var v = document.documentMode; + if(v < 9) return; /* not available */ + + var specialspace_ns = "http://www.mozilla.org/ns/specialspace"; + var svg_ns = "http://www.w3.org/2000/svg"; + + var elem = document.createElement("div"), r; + + elem.setAttributeNS(specialspace_ns, "spec:align", "left"); + r = elem.getAttribute("spec:align"); + ok(r === "left", "spec:align = " + r); + r = elem.getAttribute("align"); + ok(r === null, "align = " + r); + r = elem.getAttributeNS(null, "spec:align"); + ok(r === "", "null spec:align = " + r); + r = elem.getAttributeNS(null, "align"); + ok(r === "", "null align = " + r); + r = elem.getAttributeNS(svg_ns, "spec:align"); + ok(r === "", "svg spec:align = " + r); + r = elem.getAttributeNS(svg_ns, "align"); + ok(r === "", "svg align = " + r); + r = elem.getAttributeNS(specialspace_ns, "spec:align"); + ok(r === "", "specialspace spec:align = " + r); + r = elem.getAttributeNS(specialspace_ns, "align"); + ok(r === "left", "specialspace align = " + r); + + try { + elem.setAttributeNS(null, "spec:align", "right"); + ok(false, "expected exception setting qualified attr with null ns"); + }catch(ex) { + todo_wine. + ok(ex.message === "NamespaceError", "setAttributeNS(null, 'spec:align', 'right') threw " + ex.message); + } + try { + elem.setAttributeNS("", "spec:align", "right"); + ok(false, "expected exception setting qualified attr with empty ns"); + }catch(ex) { + todo_wine. + ok(ex.message === "NamespaceError", "setAttributeNS('', 'spec:align', 'right') threw " + ex.message); + } + elem.setAttributeNS(null, "align", "right"); + r = elem.getAttribute("spec:align"); + ok(r === "left", "spec:align (null) = " + r); + r = elem.getAttribute("align"); + ok(r === "right", "align (null) = " + r); + r = elem.getAttributeNS(null, "spec:align"); + ok(r === "", "null spec:align (null) = " + r); + r = elem.getAttributeNS(null, "align"); + ok(r === "right", "null align (null) = " + r); + r = elem.getAttributeNS(svg_ns, "spec:align"); + ok(r === "", "svg spec:align (null) = " + r); + r = elem.getAttributeNS(svg_ns, "align"); + ok(r === "", "svg align (null) = " + r); + r = elem.getAttributeNS(specialspace_ns, "spec:align"); + ok(r === "", "specialspace spec:align (null) = " + r); + r = elem.getAttributeNS(specialspace_ns, "align"); + ok(r === "left", "specialspace align (null) = " + r); + + elem.setAttribute("align", "center"); + r = elem.getAttributeNS(null, "spec:align"); + ok(r === "", "null spec:align (non-NS) = " + r); + r = elem.getAttributeNS(null, "align"); + ok(r === "center", "null align (non-NS) = " + r); + r = elem.getAttributeNS(svg_ns, "spec:align"); + ok(r === "", "svg spec:align (non-NS) = " + r); + r = elem.getAttributeNS(svg_ns, "align"); + ok(r === "", "svg align (non-NS) = " + r); + r = elem.getAttributeNS(specialspace_ns, "spec:align"); + ok(r === "", "specialspace spec:align (non-NS) = " + r); + r = elem.getAttributeNS(specialspace_ns, "align"); + ok(r === "left", "specialspace align (non-NS) = " + r); + + elem.setAttribute("emptynsattr", "none"); + elem.setAttributeNS("", "emptynsattr", "test"); + r = elem.getAttribute("emptynsattr"); + ok(r === "test", "emptynsattr without NS = " + r); + elem.setAttributeNS(null, "emptynsattr", "wine"); + r = elem.getAttribute("emptynsattr"); + ok(r === "wine", "emptynsattr without NS = " + r); + elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns"); + r = elem.getAttribute("emptynsattr"); + ok(r === "wine", "emptynsattr without NS = " + r); + r = elem.getAttributeNS("", "emptynsattr"); + ok(r === "wine", "emptynsattr empty ns = " + r); + r = elem.getAttributeNS(null, "emptynsattr"); + ok(r === "wine", "emptynsattr null ns = " + r); + r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === "ns", "emptynsattr specialspace ns = " + r); + + var ns = {}; + ns.toString = function() { return "toString namespace"; } + ns.valueOf = function() { return "valueOf namespace"; } + elem.setAttributeNS(ns, "foobar", "test"); + r = elem.getAttribute("foobar"); + ok(r === "test", "foobar without NS = " + r); + r = elem.getAttributeNS(ns, "foobar"); + ok(r === "test", "foobar = " + r); + r = elem.getAttributeNS("toString namespace", "foobar"); + ok(r === (v < 10 ? "" : "test"), "foobar (toString namespace) = " + r); + r = elem.getAttributeNS("valueOf namespace", "foobar"); + ok(r === (v < 10 ? "test" : ""), "foobar (valueOf namespace) = " + r); + + var arr = [3]; + elem.setAttributeNS(svg_ns, "testattr", arr); + r = elem.getAttributeNS(svg_ns, "testattr"); + ok(r === "3", "testattr = " + r); + ok(elem.testattr === undefined, "elem.testattr = " + elem.testattr); + + arr.toString = function() { return 42; } + elem.setAttributeNS(svg_ns, "testattr", arr); + r = elem.getAttributeNS(svg_ns, "testattr"); + ok(r === "42", "testattr with custom toString = " + r); + + arr.valueOf = function() { return "arrval"; } + elem.setAttributeNS(svg_ns, "testattr", arr); + r = elem.getAttributeNS(svg_ns, "testattr"); + ok(r === "42", "testattr with custom valueOf = " + r); + + elem.setAttributeNS(svg_ns, "boolattr", true); + r = elem.getAttributeNS(svg_ns, "boolattr"); + ok(r === "true", "boolattr = " + r); + + elem.setAttributeNS(svg_ns, "numattr", 13); + r = elem.getAttributeNS(svg_ns, "numattr"); + ok(r === "13", "numattr = " + r); +}); + sync_test("builtins_diffs", function() { var v = document.documentMode;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 52 +++++++++++++++++++++++++++++-- dlls/mshtml/tests/documentmode.js | 32 +++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 9d17d63b606..d73b11e7c50 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4886,8 +4886,26 @@ static HRESULT WINAPI HTMLElement6_setAttributeNS(IHTMLElement6 *iface, VARIANT static HRESULT WINAPI HTMLElement6_removeAttributeNS(IHTMLElement6 *iface, VARIANT *pvarNS, BSTR strAttributeName) { HTMLElement *This = impl_from_IHTMLElement6(iface); - FIXME("(%p)->(%s %s)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName)); - return E_NOTIMPL; + nsAString ns_str, name_str; + nsresult nsres; + HRESULT hres; + + TRACE("(%p)->(%s %s)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName)); + + if(!This->dom_element) { + FIXME("No dom_element\n"); + return E_NOTIMPL; + } + + hres = variant_to_nsstr(pvarNS, FALSE, &ns_str); + if(FAILED(hres)) + return hres; + + nsAString_InitDepend(&name_str, strAttributeName); + nsres = nsIDOMElement_RemoveAttributeNS(This->dom_element, &ns_str, &name_str); + nsAString_Finish(&ns_str); + nsAString_Finish(&name_str); + return map_nsresult(nsres); }
static HRESULT WINAPI HTMLElement6_getAttributeNodeNS(IHTMLElement6 *iface, VARIANT *pvarNS, BSTR name, IHTMLDOMAttribute2 **ppretAttribute) @@ -6934,6 +6952,35 @@ static HRESULT IHTMLElement6_setAttributeNS_hook(DispatchEx *dispex, WORD flags, return hres; }
+static HRESULT IHTMLElement6_removeAttributeNS_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + VARIANT args[2]; + HRESULT hres; + DISPPARAMS new_dp = { args, NULL, 2, 0 }; + + if(!(flags & DISPATCH_METHOD) || dp->cArgs < 2 || dp->cNamedArgs) + return S_FALSE; + + switch(V_VT(&dp->rgvarg[dp->cArgs - 1])) { + case VT_EMPTY: + case VT_BSTR: + case VT_NULL: + return S_FALSE; + default: + break; + } + + hres = change_type(&args[1], &dp->rgvarg[dp->cArgs - 1], VT_BSTR, caller); + if(FAILED(hres)) + return hres; + args[0] = dp->rgvarg[dp->cArgs - 2]; + + hres = dispex_call_builtin(dispex, DISPID_IHTMLELEMENT6_REMOVEATTRIBUTENS, &new_dp, res, ei, caller); + VariantClear(&args[1]); + return hres; +} + static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -6972,6 +7019,7 @@ void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode) static const dispex_hook_t elem6_ie10_hooks[] = { {DISPID_IHTMLELEMENT6_GETATTRIBUTENS, IHTMLElement6_getAttributeNS_hook}, {DISPID_IHTMLELEMENT6_SETATTRIBUTENS, IHTMLElement6_setAttributeNS_hook}, + {DISPID_IHTMLELEMENT6_REMOVEATTRIBUTENS, IHTMLElement6_removeAttributeNS_hook}, {DISPID_IHTMLELEMENT6_IE9_SETATTRIBUTE, IHTMLElement6_setAttribute_hook}, {DISPID_UNKNOWN} }; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 9e7c3ac1d9d..32b74677822 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1480,6 +1480,7 @@ sync_test("elem_attrNS", function() { ok(r === "", "specialspace spec:align (non-NS) = " + r); r = elem.getAttributeNS(specialspace_ns, "align"); ok(r === "left", "specialspace align (non-NS) = " + r); + elem.removeAttributeNS(null, "spec:align");
elem.setAttribute("emptynsattr", "none"); elem.setAttributeNS("", "emptynsattr", "test"); @@ -1498,6 +1499,30 @@ sync_test("elem_attrNS", function() { r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); ok(r === "ns", "emptynsattr specialspace ns = " + r);
+ elem.removeAttributeNS("", "emptynsattr"); + r = elem.getAttribute("emptynsattr"); + ok(r === "ns", "emptynsattr without NS after remove = " + r); + r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === "ns", "emptynsattr specialspace ns after empty remove = " + r); + elem.setAttribute("emptynsattr", "test"); + r = elem.getAttribute("emptynsattr"); + ok(r === "test", "emptynsattr without NS after re-set = " + r); + r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === "test", "emptynsattr specialspace ns after empty re-set = " + r); + + elem.removeAttribute("emptynsattr"); + r = elem.getAttribute("emptynsattr"); + ok(r === null, "emptynsattr without NS after non-NS remove = " + r); + r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === "", "emptynsattr specialspace ns after non-NS remove = " + r); + + elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns"); + elem.removeAttributeNS(svg_ns, "emptynsattr"); + r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === "ns", "emptynsattr specialspace ns after wrong NS remove = " + r); + r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === "ns", "emptynsattr specialspace ns after remove = " + r); + var ns = {}; ns.toString = function() { return "toString namespace"; } ns.valueOf = function() { return "valueOf namespace"; } @@ -1516,16 +1541,23 @@ sync_test("elem_attrNS", function() { r = elem.getAttributeNS(svg_ns, "testattr"); ok(r === "3", "testattr = " + r); ok(elem.testattr === undefined, "elem.testattr = " + elem.testattr); + elem.removeAttributeNS(svg_ns, "testattr"); + r = elem.getAttributeNS(svg_ns, "testattr"); + ok(r === "", "testattr after remove = " + r);
arr.toString = function() { return 42; } elem.setAttributeNS(svg_ns, "testattr", arr); r = elem.getAttributeNS(svg_ns, "testattr"); ok(r === "42", "testattr with custom toString = " + r); + elem.removeAttributeNS(svg_ns, "testattr"); + r = elem.getAttributeNS(svg_ns, "testattr"); + ok(r === "", "testattr with custom toString after remove = " + r);
arr.valueOf = function() { return "arrval"; } elem.setAttributeNS(svg_ns, "testattr", arr); r = elem.getAttributeNS(svg_ns, "testattr"); ok(r === "42", "testattr with custom valueOf = " + r); + elem.removeAttributeNS(svg_ns, "testattr");
elem.setAttributeNS(svg_ns, "boolattr", true); r = elem.getAttributeNS(svg_ns, "boolattr");
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 54 +++++++++++++++++++++- dlls/mshtml/tests/documentmode.js | 74 +++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index d73b11e7c50..d658519fc17 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4925,8 +4925,28 @@ static HRESULT WINAPI HTMLElement6_setAttributeNodeNS(IHTMLElement6 *iface, IHTM static HRESULT WINAPI HTMLElement6_hasAttributeNS(IHTMLElement6 *iface, VARIANT *pvarNS, BSTR name, VARIANT_BOOL *pfHasAttribute) { HTMLElement *This = impl_from_IHTMLElement6(iface); - FIXME("(%p)->(%s %s %p)\n", This, debugstr_variant(pvarNS), debugstr_w(name), pfHasAttribute); - return E_NOTIMPL; + nsAString ns_str, name_str; + nsresult nsres; + HRESULT hres; + cpp_bool r; + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(pvarNS), debugstr_w(name), pfHasAttribute); + + if(!This->dom_element) { + FIXME("No dom_element\n"); + return E_NOTIMPL; + } + + hres = variant_to_nsstr(pvarNS, FALSE, &ns_str); + if(FAILED(hres)) + return hres; + + nsAString_InitDepend(&name_str, name); + nsres = nsIDOMElement_HasAttributeNS(This->dom_element, &ns_str, &name_str, &r); + nsAString_Finish(&ns_str); + nsAString_Finish(&name_str); + *pfHasAttribute = variant_bool(NS_SUCCEEDED(nsres) && r); + return S_OK; }
static HRESULT WINAPI HTMLElement6_getAttribute(IHTMLElement6 *iface, BSTR strAttributeName, VARIANT *AttributeValue) @@ -6868,6 +6888,35 @@ static IHTMLEventObj *HTMLElement_set_current_event(DispatchEx *dispex, IHTMLEve return default_set_current_event(This->node.doc->window, event); }
+static HRESULT IHTMLElement6_hasAttributeNS_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + VARIANT args[2]; + HRESULT hres; + DISPPARAMS new_dp = { args, NULL, 2, 0 }; + + if(!(flags & DISPATCH_METHOD) || dp->cArgs < 2 || dp->cNamedArgs) + return S_FALSE; + + switch(V_VT(&dp->rgvarg[dp->cArgs - 1])) { + case VT_EMPTY: + case VT_BSTR: + case VT_NULL: + return S_FALSE; + default: + break; + } + + hres = change_type(&args[1], &dp->rgvarg[dp->cArgs - 1], VT_BSTR, caller); + if(FAILED(hres)) + return hres; + args[0] = dp->rgvarg[dp->cArgs - 2]; + + hres = dispex_call_builtin(dispex, DISPID_IHTMLELEMENT6_HASATTRIBUTENS, &new_dp, res, ei, caller); + VariantClear(&args[1]); + return hres; +} + static HRESULT IHTMLElement6_getAttributeNS_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { @@ -7017,6 +7066,7 @@ void HTMLElement_init_dispex_info(dispex_data_t *info, compat_mode_t mode) {DISPID_UNKNOWN} }; static const dispex_hook_t elem6_ie10_hooks[] = { + {DISPID_IHTMLELEMENT6_HASATTRIBUTENS, IHTMLElement6_hasAttributeNS_hook}, {DISPID_IHTMLELEMENT6_GETATTRIBUTENS, IHTMLElement6_getAttributeNS_hook}, {DISPID_IHTMLELEMENT6_SETATTRIBUTENS, IHTMLElement6_setAttributeNS_hook}, {DISPID_IHTMLELEMENT6_REMOVEATTRIBUTENS, IHTMLElement6_removeAttributeNS_hook}, diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 32b74677822..52b433f1577 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1418,20 +1418,36 @@ sync_test("elem_attrNS", function() { var elem = document.createElement("div"), r;
elem.setAttributeNS(specialspace_ns, "spec:align", "left"); + r = elem.hasAttribute("spec:align"); + ok(r === true, "spec:align does not exist"); r = elem.getAttribute("spec:align"); ok(r === "left", "spec:align = " + r); + r = elem.hasAttribute("align"); + ok(r === false, "align exists"); r = elem.getAttribute("align"); ok(r === null, "align = " + r); + r = elem.hasAttributeNS(null, "spec:align"); + ok(r === false, "null spec:align exists"); r = elem.getAttributeNS(null, "spec:align"); ok(r === "", "null spec:align = " + r); + r = elem.hasAttributeNS(null, "spec:align"); + ok(r === false, "null align exists"); r = elem.getAttributeNS(null, "align"); ok(r === "", "null align = " + r); + r = elem.hasAttributeNS(svg_ns, "spec:align"); + ok(r === false, "svg spec:align exists"); r = elem.getAttributeNS(svg_ns, "spec:align"); ok(r === "", "svg spec:align = " + r); + r = elem.hasAttributeNS(svg_ns, "align"); + ok(r === false, "svg align exists"); r = elem.getAttributeNS(svg_ns, "align"); ok(r === "", "svg align = " + r); + r = elem.hasAttributeNS(specialspace_ns, "spec:align"); + ok(r === false, "specialspace spec:align exists"); r = elem.getAttributeNS(specialspace_ns, "spec:align"); ok(r === "", "specialspace spec:align = " + r); + r = elem.hasAttributeNS(specialspace_ns, "align"); + ok(r === true, "specialspace align does not exist"); r = elem.getAttributeNS(specialspace_ns, "align"); ok(r === "left", "specialspace align = " + r);
@@ -1452,56 +1468,98 @@ sync_test("elem_attrNS", function() { elem.setAttributeNS(null, "align", "right"); r = elem.getAttribute("spec:align"); ok(r === "left", "spec:align (null) = " + r); + r = elem.hasAttribute("align"); + ok(r === true, "align (null) does not exist"); r = elem.getAttribute("align"); ok(r === "right", "align (null) = " + r); + r = elem.hasAttributeNS(null, "spec:align"); + ok(r === false, "null spec:align exists"); r = elem.getAttributeNS(null, "spec:align"); ok(r === "", "null spec:align (null) = " + r); + r = elem.hasAttributeNS(null, "align"); + ok(r === true, "null align does not exist"); r = elem.getAttributeNS(null, "align"); ok(r === "right", "null align (null) = " + r); + r = elem.hasAttributeNS(svg_ns, "spec:align"); + ok(r === false, "svg spec:align (null) exists"); r = elem.getAttributeNS(svg_ns, "spec:align"); ok(r === "", "svg spec:align (null) = " + r); + r = elem.hasAttributeNS(svg_ns, "align"); + ok(r === false, "svg align (null) exists"); r = elem.getAttributeNS(svg_ns, "align"); ok(r === "", "svg align (null) = " + r); + r = elem.hasAttributeNS(specialspace_ns, "spec:align"); + ok(r === false, "specialspace_ns spec:align (null) exists"); r = elem.getAttributeNS(specialspace_ns, "spec:align"); ok(r === "", "specialspace spec:align (null) = " + r); + r = elem.hasAttributeNS(specialspace_ns, "align"); + ok(r === true, "specialspace align (null) does not exist"); r = elem.getAttributeNS(specialspace_ns, "align"); ok(r === "left", "specialspace align (null) = " + r);
elem.setAttribute("align", "center"); + r = elem.hasAttributeNS(null, "spec:align"); + ok(r === false, "null spec:align (non-NS) exists"); r = elem.getAttributeNS(null, "spec:align"); ok(r === "", "null spec:align (non-NS) = " + r); + r = elem.hasAttributeNS(null, "align"); + ok(r === true, "null align (non-NS) does not exist"); r = elem.getAttributeNS(null, "align"); ok(r === "center", "null align (non-NS) = " + r); + r = elem.hasAttributeNS(svg_ns, "spec:align"); + ok(r === false, "svg spec:align (non-NS) exists"); r = elem.getAttributeNS(svg_ns, "spec:align"); ok(r === "", "svg spec:align (non-NS) = " + r); + r = elem.hasAttributeNS(svg_ns, "align"); + ok(r === false, "svg align (non-NS) exists"); r = elem.getAttributeNS(svg_ns, "align"); ok(r === "", "svg align (non-NS) = " + r); + r = elem.hasAttributeNS(specialspace_ns, "spec:align"); + ok(r === false, "specialspace spec:align (non-NS) exists"); r = elem.getAttributeNS(specialspace_ns, "spec:align"); ok(r === "", "specialspace spec:align (non-NS) = " + r); + r = elem.hasAttributeNS(specialspace_ns, "align"); + ok(r === true, "specialspace align (non-NS) does not exist"); r = elem.getAttributeNS(specialspace_ns, "align"); ok(r === "left", "specialspace align (non-NS) = " + r); elem.removeAttributeNS(null, "spec:align");
elem.setAttribute("emptynsattr", "none"); elem.setAttributeNS("", "emptynsattr", "test"); + r = elem.hasAttribute("emptynsattr"); + ok(r === true, "emptynsattr without NS does not exist"); r = elem.getAttribute("emptynsattr"); ok(r === "test", "emptynsattr without NS = " + r); elem.setAttributeNS(null, "emptynsattr", "wine"); + r = elem.hasAttribute("emptynsattr"); + ok(r === true, "emptynsattr without NS does not exist"); r = elem.getAttribute("emptynsattr"); ok(r === "wine", "emptynsattr without NS = " + r); elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns"); + r = elem.hasAttribute("emptynsattr"); + ok(r === true, "emptynsattr without NS does not exist"); r = elem.getAttribute("emptynsattr"); ok(r === "wine", "emptynsattr without NS = " + r); + r = elem.hasAttributeNS("", "emptynsattr"); + ok(r === true, "emptynsattr empty ns does not exist"); r = elem.getAttributeNS("", "emptynsattr"); ok(r === "wine", "emptynsattr empty ns = " + r); + r = elem.hasAttributeNS(null, "emptynsattr"); + ok(r === true, "emptynsattr null ns does not exist"); r = elem.getAttributeNS(null, "emptynsattr"); ok(r === "wine", "emptynsattr null ns = " + r); + r = elem.hasAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === true, "emptynsattr specialspace ns does not exist"); r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); ok(r === "ns", "emptynsattr specialspace ns = " + r);
elem.removeAttributeNS("", "emptynsattr"); + r = elem.hasAttribute("emptynsattr"); + ok(r === true, "emptynsattr without NS after remove does not exist"); r = elem.getAttribute("emptynsattr"); ok(r === "ns", "emptynsattr without NS after remove = " + r); + r = elem.hasAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === true, "emptynsattr specialspace ns after empty remove does not exist"); r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); ok(r === "ns", "emptynsattr specialspace ns after empty remove = " + r); elem.setAttribute("emptynsattr", "test"); @@ -1511,15 +1569,23 @@ sync_test("elem_attrNS", function() { ok(r === "test", "emptynsattr specialspace ns after empty re-set = " + r);
elem.removeAttribute("emptynsattr"); + r = elem.hasAttribute("emptynsattr"); + ok(r === false, "emptynsattr without NS after non-NS remove exists"); r = elem.getAttribute("emptynsattr"); ok(r === null, "emptynsattr without NS after non-NS remove = " + r); + r = elem.hasAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === false, "emptynsattr specialspace ns after non-NS remove exists"); r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); ok(r === "", "emptynsattr specialspace ns after non-NS remove = " + r);
elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns"); elem.removeAttributeNS(svg_ns, "emptynsattr"); + r = elem.hasAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === true, "emptynsattr specialspace ns after wrong NS remove does not exist"); r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); ok(r === "ns", "emptynsattr specialspace ns after wrong NS remove = " + r); + r = elem.hasAttributeNS(specialspace_ns, "emptynsattr"); + ok(r === true, "emptynsattr specialspace ns after remove does not exist"); r = elem.getAttributeNS(specialspace_ns, "emptynsattr"); ok(r === "ns", "emptynsattr specialspace ns after remove = " + r);
@@ -1527,12 +1593,20 @@ sync_test("elem_attrNS", function() { ns.toString = function() { return "toString namespace"; } ns.valueOf = function() { return "valueOf namespace"; } elem.setAttributeNS(ns, "foobar", "test"); + r = elem.hasAttribute("foobar"); + ok(r === true, "foobar without NS does not exist"); r = elem.getAttribute("foobar"); ok(r === "test", "foobar without NS = " + r); + r = elem.hasAttributeNS(ns, "foobar"); + ok(r === true, "foobar does not exist"); r = elem.getAttributeNS(ns, "foobar"); ok(r === "test", "foobar = " + r); + r = elem.hasAttributeNS("toString namespace", "foobar"); + ok(r === (v < 10 ? false : true), "foobar (toString namespace) " + (v < 10 ? "exists" : "does not exist")); r = elem.getAttributeNS("toString namespace", "foobar"); ok(r === (v < 10 ? "" : "test"), "foobar (toString namespace) = " + r); + r = elem.hasAttributeNS("valueOf namespace", "foobar"); + ok(r === (v < 10 ? true : false), "foobar (valueOf namespace) = " + (v < 10 ? "does not exist" : "exists")); r = elem.getAttributeNS("valueOf namespace", "foobar"); ok(r === (v < 10 ? "test" : ""), "foobar (valueOf namespace) = " + r);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 26 ++++++++++++++++++++++++-- dlls/mshtml/tests/dom.js | 5 ++++- 2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index d658519fc17..69decc66a30 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6524,8 +6524,30 @@ static HRESULT WINAPI ElementTraversal_get_firstElementChild(IElementTraversal * static HRESULT WINAPI ElementTraversal_get_lastElementChild(IElementTraversal *iface, IHTMLElement **p) { HTMLElement *This = impl_from_IElementTraversal(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMElement *nselem = NULL; + HTMLElement *elem; + HRESULT hres; + + TRACE("(%p)->(%p)\n", This, p); + + if(!This->dom_element) { + *p = NULL; + return S_OK; + } + + nsIDOMElement_GetLastElementChild(This->dom_element, &nselem); + if(!nselem) { + *p = NULL; + return S_OK; + } + + hres = get_element(nselem, &elem); + nsIDOMElement_Release(nselem); + if(FAILED(hres)) + return hres; + + *p = &elem->IHTMLElement_iface; + return S_OK; }
static HRESULT WINAPI ElementTraversal_get_previousElementSibling(IElementTraversal *iface, IHTMLElement **p) diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index 3939dd95642..bd6fbf3793b 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -89,12 +89,15 @@ sync_test("textContent", function() {
sync_test("ElementTraversal", function() { var div = document.createElement("div"); - div.innerHTML = "abc<b>bold</b><script>/* */<script><div>text</div>def"; + div.innerHTML = "abc<b>bold</b><script>/* */</script><div>text</div>def"; ok(div.firstElementChild.outerHTML === "<b>bold</b>", "div.firstElementChild.outerHTML = " + div.firstElementChild.outerHTML); + ok(div.lastElementChild.outerHTML === "<div>text</div>", + "div.lastElementChild.outerHTML = " + div.lastElementChild.outerHTML);
div.innerHTML = "abc"; ok(div.firstElementChild === null, "div.firstElementChild = " + div.firstElementChild); + ok(div.lastElementChild === null, "div.lastElementChild = " + div.lastElementChild);
ok(!("firstElementChild" in document), "firstElementChild found in document"); });
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 26 ++++++++++++++++++++++++-- dlls/mshtml/tests/dom.js | 5 +++++ 2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 69decc66a30..8515d0b59da 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6560,8 +6560,30 @@ static HRESULT WINAPI ElementTraversal_get_previousElementSibling(IElementTraver static HRESULT WINAPI ElementTraversal_get_nextElementSibling(IElementTraversal *iface, IHTMLElement **p) { HTMLElement *This = impl_from_IElementTraversal(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMElement *nselem = NULL; + HTMLElement *elem; + HRESULT hres; + + TRACE("(%p)->(%p)\n", This, p); + + if(!This->dom_element) { + *p = NULL; + return S_OK; + } + + nsIDOMElement_GetNextElementSibling(This->dom_element, &nselem); + if(!nselem) { + *p = NULL; + return S_OK; + } + + hres = get_element(nselem, &elem); + nsIDOMElement_Release(nselem); + if(FAILED(hres)) + return hres; + + *p = &elem->IHTMLElement_iface; + return S_OK; }
static HRESULT WINAPI ElementTraversal_get_childElementCount(IElementTraversal *iface, LONG *p) diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index bd6fbf3793b..e164c9502ff 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -94,12 +94,17 @@ sync_test("ElementTraversal", function() { "div.firstElementChild.outerHTML = " + div.firstElementChild.outerHTML); ok(div.lastElementChild.outerHTML === "<div>text</div>", "div.lastElementChild.outerHTML = " + div.lastElementChild.outerHTML); + ok(div.firstElementChild.nextElementSibling.outerHTML === "<script>/* */</script>", + "div.firstElementChild.nextElementSibling.outerHTML = " + div.firstElementChild.nextElementSibling.outerHTML); + ok(div.lastElementChild.nextElementSibling === null, + "div.lastElementChild.nextElementSibling = " + div.lastElementChild.nextElementSibling);
div.innerHTML = "abc"; ok(div.firstElementChild === null, "div.firstElementChild = " + div.firstElementChild); ok(div.lastElementChild === null, "div.lastElementChild = " + div.lastElementChild);
ok(!("firstElementChild" in document), "firstElementChild found in document"); + ok(!("nextElementSibling" in document), "nextElementSibling found in document"); });
sync_test("head", function() {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 26 ++++++++++++++++++++++++-- dlls/mshtml/tests/dom.js | 4 ++++ 2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 8515d0b59da..e728a667f20 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6553,8 +6553,30 @@ static HRESULT WINAPI ElementTraversal_get_lastElementChild(IElementTraversal *i static HRESULT WINAPI ElementTraversal_get_previousElementSibling(IElementTraversal *iface, IHTMLElement **p) { HTMLElement *This = impl_from_IElementTraversal(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMElement *nselem = NULL; + HTMLElement *elem; + HRESULT hres; + + TRACE("(%p)->(%p)\n", This, p); + + if(!This->dom_element) { + *p = NULL; + return S_OK; + } + + nsIDOMElement_GetPreviousElementSibling(This->dom_element, &nselem); + if(!nselem) { + *p = NULL; + return S_OK; + } + + hres = get_element(nselem, &elem); + nsIDOMElement_Release(nselem); + if(FAILED(hres)) + return hres; + + *p = &elem->IHTMLElement_iface; + return S_OK; }
static HRESULT WINAPI ElementTraversal_get_nextElementSibling(IElementTraversal *iface, IHTMLElement **p) diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index e164c9502ff..93b4dc196ec 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -98,6 +98,10 @@ sync_test("ElementTraversal", function() { "div.firstElementChild.nextElementSibling.outerHTML = " + div.firstElementChild.nextElementSibling.outerHTML); ok(div.lastElementChild.nextElementSibling === null, "div.lastElementChild.nextElementSibling = " + div.lastElementChild.nextElementSibling); + ok(div.lastElementChild.previousElementSibling.outerHTML === "<script>/* */</script>", + "div.lastElementChild.previousElementSibling.outerHTML = " + div.lastElementChild.previousElementSibling.outerHTML); + ok(div.firstElementChild.previousElementSibling === null, + "div.firstElementChild.previousElementSibling = " + div.firstElementChild.previousElementSibling);
div.innerHTML = "abc"; ok(div.firstElementChild === null, "div.firstElementChild = " + div.firstElementChild);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlelem.c | 11 +++++++++-- dlls/mshtml/tests/dom.js | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index e728a667f20..c8ca0494cef 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6611,8 +6611,15 @@ static HRESULT WINAPI ElementTraversal_get_nextElementSibling(IElementTraversal static HRESULT WINAPI ElementTraversal_get_childElementCount(IElementTraversal *iface, LONG *p) { HTMLElement *This = impl_from_IElementTraversal(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + UINT32 count = 0; + + TRACE("(%p)->(%p)\n", This, p); + + if(This->dom_element) + nsIDOMElement_GetChildElementCount(This->dom_element, &count); + + *p = count; + return S_OK; }
static const IElementTraversalVtbl ElementTraversalVtbl = { diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index 93b4dc196ec..231633b0712 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -90,6 +90,7 @@ sync_test("textContent", function() { sync_test("ElementTraversal", function() { var div = document.createElement("div"); div.innerHTML = "abc<b>bold</b><script>/* */</script><div>text</div>def"; + ok(div.childElementCount === 3, "div.childElementCount = " + div.childElementCount); ok(div.firstElementChild.outerHTML === "<b>bold</b>", "div.firstElementChild.outerHTML = " + div.firstElementChild.outerHTML); ok(div.lastElementChild.outerHTML === "<div>text</div>", @@ -104,9 +105,11 @@ sync_test("ElementTraversal", function() { "div.firstElementChild.previousElementSibling = " + div.firstElementChild.previousElementSibling);
div.innerHTML = "abc"; + ok(div.childElementCount === 0, "div.childElementCount = " + div.childElementCount); ok(div.firstElementChild === null, "div.firstElementChild = " + div.firstElementChild); ok(div.lastElementChild === null, "div.lastElementChild = " + div.lastElementChild);
+ ok(!("childElementCount" in document), "childElementCount found in document"); ok(!("firstElementChild" in document), "firstElementChild found in document"); ok(!("nextElementSibling" in document), "nextElementSibling found in document"); });
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlhead.c | 22 ++++++++++++++++++---- dlls/mshtml/tests/dom.js | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/htmlhead.c b/dlls/mshtml/htmlhead.c index 1bad06ee9d7..786d60ae227 100644 --- a/dlls/mshtml/htmlhead.c +++ b/dlls/mshtml/htmlhead.c @@ -103,15 +103,29 @@ static HRESULT WINAPI HTMLTitleElement_Invoke(IHTMLTitleElement *iface, DISPID d static HRESULT WINAPI HTMLTitleElement_put_text(IHTMLTitleElement *iface, BSTR v) { HTMLTitleElement *This = impl_from_IHTMLTitleElement(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(v)); - return E_NOTIMPL; + nsAString text; + nsresult nsres; + + TRACE("(%p)->(%s)\n", This, debugstr_w(v)); + + nsAString_InitDepend(&text, v); + nsres = nsIDOMNode_SetTextContent(This->element.node.nsnode, &text); + nsAString_Finish(&text); + + return map_nsresult(nsres); }
static HRESULT WINAPI HTMLTitleElement_get_text(IHTMLTitleElement *iface, BSTR *p) { HTMLTitleElement *This = impl_from_IHTMLTitleElement(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsAString text; + nsresult nsres; + + TRACE("(%p)->(%p)\n", This, p); + + nsAString_InitDepend(&text, NULL); + nsres = nsIDOMNode_GetTextContent(This->element.node.nsnode, &text); + return return_nsstr(nsres, &text, p); }
static const IHTMLTitleElementVtbl HTMLTitleElementVtbl = { diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index 231633b0712..fcbca0f4b2f 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -533,6 +533,24 @@ sync_test("title", function() { elem.title = "test"; ok(elem.title === "test", "div.title = " + elem.title); ok(elem.getAttribute("title") === "test", "title attribute = " + elem.getAttribute("title")); + + var orig = document.title; + document.title = "w i n e test"; + var title = document.getElementsByTagName("title")[0]; + ok(title.text === "w i n e test", "<title> element text = " + title.text); + title.text = "winetest"; + ok(title.text === "winetest", "<title> element text after change = " + title.text); + ok(document.title === "winetest", "document.title after <title> change = " + document.title); + + elem = document.createElement("title"); + ok(elem.text === "", "detached <title> element text = " + elem.text); + elem.text = "foobar"; + ok(elem.text === "foobar", "detached <title> element text after change = " + elem.text); + ok(document.title === "winetest", "document.title after detached <title> change = " + document.title); + + title.parentNode.replaceChild(elem, title); + ok(document.title === "foobar", "document.title after <title> replaced = " + document.title); + document.title = orig; });
sync_test("disabled", function() {