dom: declare document.createElementsNS

This commit is contained in:
Pierre Tachoire
2023-11-16 15:48:54 +01:00
parent 05d31eb63e
commit 4a15456418
4 changed files with 424 additions and 0 deletions

View File

@@ -36,6 +36,11 @@ pub const Document = struct {
return Element.toInterface(e);
}
pub fn _createElementNS(self: *parser.Document, ns: []const u8, tag_name: []const u8) ElementUnion {
const e = parser.documentCreateElementNS(self, ns, tag_name);
return Element.toInterface(e);
}
// We can't simply use libdom dom_document_get_elements_by_tag_name here.
// Indeed, netsurf implemented a previous dom spec when
// getElementsByTagName returned a NodeList.

View File

@@ -752,6 +752,12 @@ pub inline fn documentCreateElement(doc: *Document, tag_name: []const u8) *Eleme
return elem.?;
}
pub inline fn documentCreateElementNS(doc: *Document, ns: []const u8, tag_name: []const u8) *Element {
var elem: ?*Element = undefined;
_ = documentVtable(doc).dom_document_create_element_ns.?(doc, stringFromData(ns), stringFromData(tag_name), &elem);
return elem.?;
}
// DocumentHTML
pub const DocumentHTML = c.dom_html_document;

View File

@@ -0,0 +1,224 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Document.createElementNS</title>
<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="Document-createElementNS.js"></script>
<div id="log"></div>
<iframe src="/common/dummy.xml"></iframe>
<iframe src="/common/dummy.xhtml"></iframe>
<script>
var tests = createElementNS_tests.concat([
/* Arrays with three elements:
* the namespace argument
* the qualifiedName argument
* the expected exception, or null if none
*/
["", "", "INVALID_CHARACTER_ERR"],
[null, "", "INVALID_CHARACTER_ERR"],
[undefined, "", "INVALID_CHARACTER_ERR"],
["http://example.com/", null, null],
["http://example.com/", "", "INVALID_CHARACTER_ERR"],
["/", null, null],
["/", "", "INVALID_CHARACTER_ERR"],
["http://www.w3.org/XML/1998/namespace", null, null],
["http://www.w3.org/XML/1998/namespace", "", "INVALID_CHARACTER_ERR"],
["http://www.w3.org/2000/xmlns/", null, "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "", "INVALID_CHARACTER_ERR"],
["foo:", null, null],
["foo:", "", "INVALID_CHARACTER_ERR"],
])
var xmlIframe = document.querySelector('[src="/common/dummy.xml"]');
var xhtmlIframe = document.querySelector('[src="/common/dummy.xhtml"]');
function runTest(t, i, desc) {
async_test(function(testObj) {
window.addEventListener("load", function() {
testObj.step(function() {
var doc;
if (desc == "HTML document") {
doc = document;
} else if (desc == "XML document") {
doc = xmlIframe.contentDocument;
// Make sure we're testing the right document
assert_equals(doc.documentElement.textContent, "Dummy XML document");
} else if (desc == "XHTML document") {
doc = xhtmlIframe.contentDocument;
assert_equals(doc.documentElement.textContent, "Dummy XHTML document");
}
var namespace = t[0], qualifiedName = t[1], expected = t[2]
if (expected != null) {
assert_throws_dom(expected, doc.defaultView.DOMException, function() {doc.createElementNS(namespace, qualifiedName) });
} else {
var element = doc.createElementNS(namespace, qualifiedName)
assert_not_equals(element, null)
assert_equals(element.nodeType, Node.ELEMENT_NODE)
assert_equals(element.nodeType, element.ELEMENT_NODE)
assert_equals(element.nodeValue, null)
assert_equals(element.ownerDocument, doc)
var qualified = String(qualifiedName), names = []
if (qualified.indexOf(":") >= 0) {
names = qualified.split(":", 2)
} else {
names = [null, qualified]
}
assert_equals(element.prefix, names[0])
assert_equals(element.localName, names[1])
assert_equals(element.tagName, qualified)
assert_equals(element.nodeName, qualified)
assert_equals(element.namespaceURI,
namespace === undefined || namespace === "" ? null
: namespace)
}
});
testObj.done();
});
}, "createElementNS test in " + desc + ": " + t.map(format_value))
}
tests.forEach(function(t, i) {
runTest(t, i, "HTML document")
runTest(t, i, "XML document")
runTest(t, i, "XHTML document")
})
test(function() {
var HTMLNS = "http://www.w3.org/1999/xhtml";
var element = document.createElementNS(HTMLNS, "span");
assert_equals(element.namespaceURI, HTMLNS);
assert_equals(element.prefix, null);
assert_equals(element.localName, "span");
assert_equals(element.tagName, "SPAN");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
assert_true(element instanceof HTMLSpanElement, "Should be an HTMLSpanElement");
}, "Lower-case HTML element without a prefix");
test(function() {
var HTMLNS = "http://www.w3.org/1999/xhtml";
var element = document.createElementNS(HTMLNS, "html:span");
assert_equals(element.namespaceURI, HTMLNS);
assert_equals(element.prefix, "html");
assert_equals(element.localName, "span");
assert_equals(element.tagName, "HTML:SPAN");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
assert_true(element instanceof HTMLSpanElement, "Should be an HTMLSpanElement");
}, "Lower-case HTML element with a prefix");
test(function() {
var element = document.createElementNS("test", "span");
assert_equals(element.namespaceURI, "test");
assert_equals(element.prefix, null);
assert_equals(element.localName, "span");
assert_equals(element.tagName, "span");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "Lower-case non-HTML element without a prefix");
test(function() {
var element = document.createElementNS("test", "html:span");
assert_equals(element.namespaceURI, "test");
assert_equals(element.prefix, "html");
assert_equals(element.localName, "span");
assert_equals(element.tagName, "html:span");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "Lower-case non-HTML element with a prefix");
test(function() {
var HTMLNS = "http://www.w3.org/1999/xhtml";
var element = document.createElementNS(HTMLNS, "SPAN");
assert_equals(element.namespaceURI, HTMLNS);
assert_equals(element.prefix, null);
assert_equals(element.localName, "SPAN");
assert_equals(element.tagName, "SPAN");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
assert_true(element instanceof HTMLUnknownElement, "Should be an HTMLUnknownElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "Upper-case HTML element without a prefix");
test(function() {
var HTMLNS = "http://www.w3.org/1999/xhtml";
var element = document.createElementNS(HTMLNS, "html:SPAN");
assert_equals(element.namespaceURI, HTMLNS);
assert_equals(element.prefix, "html");
assert_equals(element.localName, "SPAN");
assert_equals(element.tagName, "HTML:SPAN");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "Upper-case HTML element with a prefix");
test(function() {
var element = document.createElementNS("test", "SPAN");
assert_equals(element.namespaceURI, "test");
assert_equals(element.prefix, null);
assert_equals(element.localName, "SPAN");
assert_equals(element.tagName, "SPAN");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "Upper-case non-HTML element without a prefix");
test(function() {
var element = document.createElementNS("test", "html:SPAN");
assert_equals(element.namespaceURI, "test");
assert_equals(element.prefix, "html");
assert_equals(element.localName, "SPAN");
assert_equals(element.tagName, "html:SPAN");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "Upper-case non-HTML element with a prefix");
test(function() {
var element = document.createElementNS(null, "span");
assert_equals(element.namespaceURI, null);
assert_equals(element.prefix, null);
assert_equals(element.localName, "span");
assert_equals(element.tagName, "span");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "null namespace");
test(function() {
var element = document.createElementNS(undefined, "span");
assert_equals(element.namespaceURI, null);
assert_equals(element.prefix, null);
assert_equals(element.localName, "span");
assert_equals(element.tagName, "span");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "undefined namespace");
test(function() {
var element = document.createElementNS("", "span");
assert_equals(element.namespaceURI, null);
assert_equals(element.prefix, null);
assert_equals(element.localName, "span");
assert_equals(element.tagName, "span");
assert_true(element instanceof Node, "Should be a Node");
assert_true(element instanceof Element, "Should be an Element");
assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
}, "empty string namespace");
</script>

View File

@@ -0,0 +1,189 @@
var createElementNS_tests = [
/* Arrays with three elements:
* the namespace argument
* the qualifiedName argument
* the expected exception, or null if none
*/
[null, null, null],
[null, undefined, null],
[null, "foo", null],
[null, "1foo", "INVALID_CHARACTER_ERR"],
[null, "f1oo", null],
[null, "foo1", null],
[null, "\u0BC6foo", null],
[null, "\u037Efoo", "INVALID_CHARACTER_ERR"],
[null, "}foo", "INVALID_CHARACTER_ERR"],
[null, "f}oo", "INVALID_CHARACTER_ERR"],
[null, "foo}", "INVALID_CHARACTER_ERR"],
[null, "\uFFFFfoo", "INVALID_CHARACTER_ERR"],
[null, "f\uFFFFoo", "INVALID_CHARACTER_ERR"],
[null, "foo\uFFFF", "INVALID_CHARACTER_ERR"],
[null, "<foo", "INVALID_CHARACTER_ERR"],
[null, "foo>", "INVALID_CHARACTER_ERR"],
[null, "<foo>", "INVALID_CHARACTER_ERR"],
[null, "f<oo", "INVALID_CHARACTER_ERR"],
[null, "^^", "INVALID_CHARACTER_ERR"],
[null, "fo o", "INVALID_CHARACTER_ERR"],
[null, "-foo", "INVALID_CHARACTER_ERR"],
[null, ".foo", "INVALID_CHARACTER_ERR"],
[null, ":foo", "INVALID_CHARACTER_ERR"],
[null, "f:oo", "NAMESPACE_ERR"],
[null, "foo:", "INVALID_CHARACTER_ERR"],
[null, "f:o:o", "INVALID_CHARACTER_ERR"],
[null, ":", "INVALID_CHARACTER_ERR"],
[null, "xml", null],
[null, "xmlns", "NAMESPACE_ERR"],
[null, "xmlfoo", null],
[null, "xml:foo", "NAMESPACE_ERR"],
[null, "xmlns:foo", "NAMESPACE_ERR"],
[null, "xmlfoo:bar", "NAMESPACE_ERR"],
[null, "null:xml", "NAMESPACE_ERR"],
["", null, null],
["", ":foo", "INVALID_CHARACTER_ERR"],
["", "f:oo", "NAMESPACE_ERR"],
["", "foo:", "INVALID_CHARACTER_ERR"],
[undefined, null, null],
[undefined, undefined, null],
[undefined, "foo", null],
[undefined, "1foo", "INVALID_CHARACTER_ERR"],
[undefined, "f1oo", null],
[undefined, "foo1", null],
[undefined, ":foo", "INVALID_CHARACTER_ERR"],
[undefined, "f:oo", "NAMESPACE_ERR"],
[undefined, "foo:", "INVALID_CHARACTER_ERR"],
[undefined, "f::oo", "INVALID_CHARACTER_ERR"],
[undefined, "xml", null],
[undefined, "xmlns", "NAMESPACE_ERR"],
[undefined, "xmlfoo", null],
[undefined, "xml:foo", "NAMESPACE_ERR"],
[undefined, "xmlns:foo", "NAMESPACE_ERR"],
[undefined, "xmlfoo:bar", "NAMESPACE_ERR"],
["http://example.com/", "foo", null],
["http://example.com/", "1foo", "INVALID_CHARACTER_ERR"],
["http://example.com/", "<foo>", "INVALID_CHARACTER_ERR"],
["http://example.com/", "fo<o", "INVALID_CHARACTER_ERR"],
["http://example.com/", "-foo", "INVALID_CHARACTER_ERR"],
["http://example.com/", ".foo", "INVALID_CHARACTER_ERR"],
["http://example.com/", "f1oo", null],
["http://example.com/", "foo1", null],
["http://example.com/", ":foo", "INVALID_CHARACTER_ERR"],
["http://example.com/", "f:oo", null],
["http://example.com/", "f:o:o", "INVALID_CHARACTER_ERR"],
["http://example.com/", "foo:", "INVALID_CHARACTER_ERR"],
["http://example.com/", "f::oo", "INVALID_CHARACTER_ERR"],
["http://example.com/", "a:0", "INVALID_CHARACTER_ERR"],
["http://example.com/", "0:a", "INVALID_CHARACTER_ERR"],
["http://example.com/", "a:_", null],
["http://example.com/", "a:\u0BC6", null],
["http://example.com/", "a:\u037E", "INVALID_CHARACTER_ERR"],
["http://example.com/", "a:\u0300", "INVALID_CHARACTER_ERR"],
["http://example.com/", "\u0BC6:a", null],
["http://example.com/", "\u0300:a", "INVALID_CHARACTER_ERR"],
["http://example.com/", "\u037E:a", "INVALID_CHARACTER_ERR"],
["http://example.com/", "a:a\u0BC6", null],
["http://example.com/", "a\u0BC6:a", null],
["http://example.com/", "xml:test", "NAMESPACE_ERR"],
["http://example.com/", "xmlns:test", "NAMESPACE_ERR"],
["http://example.com/", "test:xmlns", null],
["http://example.com/", "xmlns", "NAMESPACE_ERR"],
["http://example.com/", "_:_", null],
["http://example.com/", "_:h0", null],
["http://example.com/", "_:test", null],
["http://example.com/", "l_:_", null],
["http://example.com/", "ns:_0", null],
["http://example.com/", "ns:a0", null],
["http://example.com/", "ns0:test", null],
["http://example.com/", "a.b:c", null],
["http://example.com/", "a-b:c", null],
["http://example.com/", "xml", null],
["http://example.com/", "XMLNS", null],
["http://example.com/", "xmlfoo", null],
["http://example.com/", "xml:foo", "NAMESPACE_ERR"],
["http://example.com/", "XML:foo", null],
["http://example.com/", "xmlns:foo", "NAMESPACE_ERR"],
["http://example.com/", "XMLNS:foo", null],
["http://example.com/", "xmlfoo:bar", null],
["http://example.com/", "prefix::local", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:{", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:}", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:~", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:'", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:!", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:@", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:#", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:$", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:%", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:^", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:&", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:*", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:(", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:)", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:+", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:=", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:[", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:]", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:\\", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:/", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:;", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:`", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:<", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:>", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:,", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:a ", "INVALID_CHARACTER_ERR"],
["http://example.com/", "namespaceURI:\"", "INVALID_CHARACTER_ERR"],
["/", "foo", null],
["/", "1foo", "INVALID_CHARACTER_ERR"],
["/", "f1oo", null],
["/", "foo1", null],
["/", ":foo", "INVALID_CHARACTER_ERR"],
["/", "f:oo", null],
["/", "foo:", "INVALID_CHARACTER_ERR"],
["/", "xml", null],
["/", "xmlns", "NAMESPACE_ERR"],
["/", "xmlfoo", null],
["/", "xml:foo", "NAMESPACE_ERR"],
["/", "xmlns:foo", "NAMESPACE_ERR"],
["/", "xmlfoo:bar", null],
["http://www.w3.org/XML/1998/namespace", "foo", null],
["http://www.w3.org/XML/1998/namespace", "1foo", "INVALID_CHARACTER_ERR"],
["http://www.w3.org/XML/1998/namespace", "f1oo", null],
["http://www.w3.org/XML/1998/namespace", "foo1", null],
["http://www.w3.org/XML/1998/namespace", ":foo", "INVALID_CHARACTER_ERR"],
["http://www.w3.org/XML/1998/namespace", "f:oo", null],
["http://www.w3.org/XML/1998/namespace", "foo:", "INVALID_CHARACTER_ERR"],
["http://www.w3.org/XML/1998/namespace", "xml", null],
["http://www.w3.org/XML/1998/namespace", "xmlns", "NAMESPACE_ERR"],
["http://www.w3.org/XML/1998/namespace", "xmlfoo", null],
["http://www.w3.org/XML/1998/namespace", "xml:foo", null],
["http://www.w3.org/XML/1998/namespace", "xmlns:foo", "NAMESPACE_ERR"],
["http://www.w3.org/XML/1998/namespace", "xmlfoo:bar", null],
["http://www.w3.org/XML/1998/namespaces", "xml:foo", "NAMESPACE_ERR"],
["http://www.w3.org/xml/1998/namespace", "xml:foo", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "foo", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "1foo", "INVALID_CHARACTER_ERR"],
["http://www.w3.org/2000/xmlns/", "f1oo", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "foo1", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", ":foo", "INVALID_CHARACTER_ERR"],
["http://www.w3.org/2000/xmlns/", "f:oo", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "foo:", "INVALID_CHARACTER_ERR"],
["http://www.w3.org/2000/xmlns/", "xml", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "xmlns", null],
["http://www.w3.org/2000/xmlns/", "xmlfoo", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "xml:foo", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "xmlns:foo", null],
["http://www.w3.org/2000/xmlns/", "xmlfoo:bar", "NAMESPACE_ERR"],
["http://www.w3.org/2000/xmlns/", "foo:xmlns", "NAMESPACE_ERR"],
["foo:", "foo", null],
["foo:", "1foo", "INVALID_CHARACTER_ERR"],
["foo:", "f1oo", null],
["foo:", "foo1", null],
["foo:", ":foo", "INVALID_CHARACTER_ERR"],
["foo:", "f:oo", null],
["foo:", "foo:", "INVALID_CHARACTER_ERR"],
["foo:", "xml", null],
["foo:", "xmlns", "NAMESPACE_ERR"],
["foo:", "xmlfoo", null],
["foo:", "xml:foo", "NAMESPACE_ERR"],
["foo:", "xmlns:foo", "NAMESPACE_ERR"],
["foo:", "xmlfoo:bar", null],
]