`getAttributeNS` is tested with the `setAttributeNS` implementation.
-- v2: 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 | 66 ++++++++++++++++++++++++++++++++++++++++-- dlls/mshtml/nsembed.c | 1 + 2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index d911d0a0433..f61f9be501f 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4813,8 +4813,40 @@ 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; + const PRUnichar *ns; + nsresult nsres; + HRESULT hres; + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName), AttributeValue); + + hres = variant_to_nsstr(pvarNS, FALSE, &ns_str); + if(FAILED(hres)) + return hres; + nsAString_GetData(&ns_str, &ns); + if(ns && !ns[0]) { + nsAString_Finish(&ns_str); + nsAString_InitDepend(&ns_str, NULL); + } + + if(!This->dom_element) { + FIXME("No dom_element\n"); + nsAString_Finish(&ns_str); + return E_NOTIMPL; + } + + 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 +6823,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 +6884,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 | 104 +++++++++++++++++++++++- dlls/mshtml/tests/documentmode.js | 128 ++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index f61f9be501f..0ebf6ac4924 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4852,8 +4852,46 @@ 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]) { + nsAString_Finish(&ns_str); + if(wcschr(strAttributeName, ':')) { + /* FIXME: Return NamespaceError */ + return E_FAIL; + } + nsAString_InitDepend(&ns_str, NULL); + } + + 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) @@ -6852,6 +6890,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) { @@ -6883,8 +6976,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} }; @@ -6902,7 +7000,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 | 59 +++++++++++++++++++++++++++++-- dlls/mshtml/tests/documentmode.js | 32 +++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 0ebf6ac4924..8a537dd4802 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4897,8 +4897,33 @@ 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; + const PRUnichar *ns; + nsresult nsres; + HRESULT hres; + + TRACE("(%p)->(%s %s)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName)); + + hres = variant_to_nsstr(pvarNS, FALSE, &ns_str); + if(FAILED(hres)) + return hres; + nsAString_GetData(&ns_str, &ns); + if(ns && !ns[0]) { + nsAString_Finish(&ns_str); + nsAString_InitDepend(&ns_str, NULL); + } + + if(!This->dom_element) { + FIXME("No dom_element\n"); + nsAString_Finish(&ns_str); + return E_NOTIMPL; + } + + 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) @@ -6945,6 +6970,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) { @@ -6983,6 +7037,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 | 61 ++++++++++++++++++++++++- dlls/mshtml/tests/documentmode.js | 74 +++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 8a537dd4802..4cc3a057861 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -4943,8 +4943,35 @@ 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; + const PRUnichar *ns; + nsresult nsres; + HRESULT hres; + cpp_bool r; + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(pvarNS), debugstr_w(name), pfHasAttribute); + + hres = variant_to_nsstr(pvarNS, FALSE, &ns_str); + if(FAILED(hres)) + return hres; + nsAString_GetData(&ns_str, &ns); + if(ns && !ns[0]) { + nsAString_Finish(&ns_str); + nsAString_InitDepend(&ns_str, NULL); + } + + if(!This->dom_element) { + FIXME("No dom_element\n"); + nsAString_Finish(&ns_str); + return E_NOTIMPL; + } + + 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) @@ -6886,6 +6913,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) { @@ -7035,6 +7091,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 4cc3a057861..31e356eec1e 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6549,8 +6549,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 31e356eec1e..cfcbc5dc795 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6585,8 +6585,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 cfcbc5dc795..00621dfa805 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6578,8 +6578,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 00621dfa805..b28b094a29b 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6636,8 +6636,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() {
On Wed Jul 27 14:50:47 2022 +0000, Gabriel Iv��ncescu wrote:
I'm not entirely sure if that would be correct in all cases, so I think I can keep it like this for now. For example for setAttributeNS, the namespace is not converted using change_type in IE9 mode, but the value is. Which means that it's not "generic" conversion on native either.
Actually on top of that, the attribute name is not converted either, in all modes.
Jacek Caban (@jacek) commented about dlls/mshtml/htmlelem.c:
{ 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;
- const PRUnichar *ns;
- nsresult nsres;
- HRESULT hres;
- TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(pvarNS), debugstr_w(strAttributeName), AttributeValue);
- hres = variant_to_nsstr(pvarNS, FALSE, &ns_str);
- if(FAILED(hres))
return hres;
- nsAString_GetData(&ns_str, &ns);
- if(ns && !ns[0]) {
Why do you still need it?
On Wed Jul 27 17:14:13 2022 +0000, Jacek Caban wrote:
Why do you still need it?
Do you mean the empty string check? I thought there was a difference between native and gecko wrt. empty namespaces, but it seems the tests still pass, so not sure honestly why I did it. I'll remove it, then.