Bug 1298818 - Port test_bug411103.html to wpt; r=jst

This allows other UAs to use it, removes duplicated checks, and
increases the chance of us noticing if the spec changes.  Some of the
expected values in our mochitest were contrary to the spec.

I checked the new expected failures against the spec and the other UAs.
I filed a spec bug for one group because it was contrary to all UAs
(although IMO the spec makes more sense and the UAs are buggy), and the
others are fixed in the next patch.

MozReview-Commit-ID: 1j11XgfuErB
This commit is contained in:
Aryeh Gregor 2016-08-30 15:13:49 +03:00
parent 406b5cd4d6
commit 3b1cc7049b
10 changed files with 255 additions and 325 deletions

View File

@ -76,7 +76,6 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
[test_bug404748.html]
[test_bug406375.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
[test_bug411103.html]
[test_bug414291.html]
tags = openwindow
[test_bug427744.html]

View File

@ -1,188 +0,0 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=411103
-->
<head>
<title>Test for Bug 411103</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=411103">Mozilla Bug 411103</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<!-- XML's createElement and createElementNS aren't HTML's, of course -->
<iframe src="data:application/xml,%3Cfoo%3EXML%3C/foo%3E" name="xmlWindow"></iframe>
<!-- for good measure... -->
<iframe src="data:application/xhtml+xml,%3Chtml%20xmlns=%22http://www.w3.org/1999/xhtml%22%3E%3Cbody%3E%3Cp%3EXHTML%3C/p%3E%3C/body%3E%3C/html%3E"
name="xhtmlWindow"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
/** Test for Bug 411103 **/
var allNSTests =
[
{ args: [undefined, undefined] },
{ args: [null, undefined] },
{ args: [undefined, null] },
{ args: [null, null] },
{ args: [null, ""], code: 5 },
{ args: ["", null] },
{ args: ["", ""], code: 5 },
{ args: [null, "<div>"], code: 5 },
{ args: [null, "0div"], code: 5 },
{ args: [null, "di v"], code: 5 },
{ args: [null, "di<v"], code: 5 },
{ args: [null, "-div"], code: 5 },
{ args: [null, ".div"], code: 5 },
{ args: ["http://example.com/", "<div>"], code: 5 },
{ args: ["http://example.com/", "0div"], code: 5 },
{ args: ["http://example.com/", "di<v"], code: 5 },
{ args: ["http://example.com/", "-div"], code: 5 },
{ args: ["http://example.com/", ".div"], code: 5 },
{ args: [null, ":div"], code: 14 },
{ args: [null, "div:"], code: 14 },
{ args: ["http://example.com/", ":div"], code: 14 },
{ args: ["http://example.com/", "div:"], code: 14 },
{ args: [null, "d:iv"], code: 14 },
{ args: [null, "a:b:c"], code: 14, message: "valid XML name, invalid QName" },
{ args: ["http://example.com/", "a:b:c"], code: 14, message: "valid XML name, invalid QName" },
{ args: [null, "a::c"], code: 14, message: "valid XML name, invalid QName" },
{ args: ["http://example.com/", "a::c"], code: 14, message: "valid XML name, invalid QName" },
{ args: ["http://example.com/", "a:0"], code: 5, message: "valid XML name, not a valid QName" },
{ args: ["http://example.com/", "0:a"], code: 5, message: "0 at start makes it not a valid XML name" },
{ args: ["http://example.com/", "a:_"] },
{ args: ["http://example.com/", "a:\u0BC6"], code: 14,
message: "non-ASCII character after colon is CombiningChar, which is " +
"NCNameChar but not (Letter | \"_\") so invalid at start of " +
"NCName (but still a valid XML name, hence not 5)" },
{ args: ["http://example.com/", "\u0BC6:a"], code: 14,
message: "non-ASCII character after colon is CombiningChar, which is " +
"NCNameChar but not (Letter | \"_\") so invalid at start of " +
"NCName (Gecko chooses to throw 14 here, but either is valid " +
"as this is both an invalid XML name and an invalid QName)" },
{ args: ["http://example.com/", "a:a\u0BC6"] },
{ args: ["http://example.com/", "a\u0BC6:a"] },
{ args: ["http://example.com/", "xml:test"], code: 14, message: "binding xml prefix wrong" },
{ args: ["http://example.com/", "xmlns:test"], code: 14, message: "binding xmlns prefix wrong" },
{ args: ["http://www.w3.org/2000/xmlns/", "x:test"], code: 14, message: "binding namespace namespace to wrong prefix" },
{ args: ["http://www.w3.org/2000/xmlns/", "xmlns:test"] },
{ args: ["http://www.w3.org/XML/1998/namespace", "xml:test"] },
{ args: ["http://www.w3.org/XML/1998/namespace", "x:test"] },
];
var allNoNSTests =
[
{ args: [undefined] },
{ args: [null] },
{ args: [""], code: 5 },
{ args: ["<div>"], code: 5 },
{ args: ["0div"], code: 5 },
{ args: ["di v"], code: 5 },
{ args: ["di<v"], code: 5 },
{ args: ["-div"], code: 5 },
{ args: [".div"], code: 5 },
{ args: [":"], message: "valid XML name, invalid QName" },
{ args: [":div"], message: "valid XML name, invalid QName" },
{ args: ["div:"], message: "valid XML name, invalid QName" },
{ args: ["d:iv"] },
{ args: ["a:b:c"], message: "valid XML name, invalid QName" },
{ args: ["a::c"], message: "valid XML name, invalid QName" },
{ args: ["a::c:"], message: "valid XML name, invalid QName" },
{ args: ["a:0"], message: "valid XML name, not a valid QName" },
{ args: ["0:a"], code: 5, message: "0 at start makes it not a valid XML name" },
{ args: ["a:_"] },
{ args: ["a:\u0BC6"],
message: "non-ASCII character after colon is CombiningChar, which is " +
"valid in pre-namespace XML" },
{ args: ["\u0BC6:a"], code: 5, message: "not a valid start character" },
{ args: ["a:a\u0BC6"] },
{ args: ["a\u0BC6:a"] },
{ args: ["xml:test"] },
{ args: ["xmlns:test"] },
{ args: ["x:test"] },
{ args: ["xmlns:test"] },
];
function sourceify(v)
{
switch (typeof v)
{
case "undefined":
return v;
case "string":
return '"' + v.replace('"', '\\"') + '"';
default:
return String(v);
}
}
function sourceifyArgs(args)
{
var copy = new Array(args.length);
for (var i = 0, sz = args.length; i < sz; i++)
copy[i] = sourceify(args[i]);
return copy.join(", ");
}
function runTests(tests, methodName, document)
{
for (var i = 0, sz = tests.length; i < sz; i++)
{
var test = tests[i];
var argStr = sourceifyArgs(test.args);
try
{
document[methodName].apply(document, test.args);
var msg = "expected no exception for " +
"document." + methodName + "(" + argStr + ")";
if ("message" in test)
msg += "; " + test.message;
ok(!("code" in test), msg);
}
catch (e)
{
msg = "exception code for document." + methodName + "(" + argStr + ")";
if ("message" in test)
msg += "; " + test.message;
is(e.code, test.code || "no exception", msg);
}
}
}
function run()
{
// HTML document
runTests(allNSTests, "createElementNS", document);
runTests(allNoNSTests, "createElement", document);
// XML document
var xmlDocument = window.frames.xmlWindow.document;
runTests(allNSTests, "createElementNS", xmlDocument);
runTests(allNoNSTests, "createElement", xmlDocument);
// XHTML document, for good measure
var xhtmlDocument = window.frames.xhtmlWindow.document;
runTests(allNSTests, "createElementNS", xhtmlDocument);
runTests(allNoNSTests, "createElement", xhtmlDocument);
SimpleTest.finish();
}
window.addEventListener("load", run, false);
</script>
</pre>
</body>
</html>

View File

@ -45,18 +45,15 @@ int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
nmstrt = ns_aware; /* e.g. "a:0" should be valid if !ns_aware */
break;
case BT_NONASCII:
if (nmstrt && !IS_NMSTRT_CHAR_MINBPC(ptr)) {
/* If this is a valid name character and we're namespace-aware, the
QName is malformed. Otherwise, this character's invalid at the
start of a name (or, if we're namespace-aware, at the start of a
localpart). */
return (IS_NAME_CHAR_MINBPC(ptr) && ns_aware) ?
MOZ_EXPAT_MALFORMED :
MOZ_EXPAT_INVALID_CHARACTER;
}
if (!IS_NAME_CHAR_MINBPC(ptr)) {
if (!IS_NAME_CHAR_MINBPC(ptr) ||
(nmstrt && !*colon && !IS_NMSTRT_CHAR_MINBPC(ptr))) {
return MOZ_EXPAT_INVALID_CHARACTER;
}
if (nmstrt && *colon && !IS_NMSTRT_CHAR_MINBPC(ptr)) {
/* If a non-starting character like a number is right after the colon,
this is a namespace error, not invalid character */
return MOZ_EXPAT_MALFORMED;
}
nmstrt = 0;
break;
case BT_NMSTRT:

View File

@ -1,30 +1,18 @@
[DOMImplementation-createDocument.html]
type: testharness
[createDocument test 6: null,"̀foo",null,"INVALID_CHARACTER_ERR"]
expected: FAIL
bug: 1298818
[createDocument test 172: metadata for null,null,DocumentType node]
expected: FAIL
bug: 520969
[createDocument test 172: null,null,DocumentType node,null]
expected: FAIL
bug: 520969
[createDocument test 185: null,"",DocumentType node]
expected: FAIL
bug: 520969
[createDocument test: null,"̀foo",null,"INVALID_CHARACTER_ERR"]
[createDocument test: "http://example.com/","a:0",null,"NAMESPACE_ERR"]
expected: FAIL
bug: https://github.com/whatwg/dom/issues/319
[createDocument test: null,null,DocumentType node <!DOCTYPE html>,null]
expected: FAIL
bug: 520969
[createDocument test 170: metadata for null,null,DocumentType node <!DOCTYPE html>]
[createDocument test 195: metadata for null,null,DocumentType node <!DOCTYPE html>]
expected: FAIL
bug: 520969
[createDocument test: null,"",DocumentType node <!DOCTYPE html -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>]
expected: FAIL
bug: 520969

View File

@ -1,8 +1,14 @@
[Document-createElementNS.html]
type: testharness
[createElementNS test 6: null,"̀foo","INVALID_CHARACTER_ERR"]
[createElementNS test in HTML document: "http://example.com/","a:0","NAMESPACE_ERR"]
bug: https://github.com/whatwg/dom/issues/319
expected: FAIL
[createElementNS test: null,"̀foo","INVALID_CHARACTER_ERR"]
[createElementNS test in XML document: "http://example.com/","a:0","NAMESPACE_ERR"]
bug: https://github.com/whatwg/dom/issues/319
expected: FAIL
[createElementNS test in XHTML document: "http://example.com/","a:0","NAMESPACE_ERR"]
bug: https://github.com/whatwg/dom/issues/319
expected: FAIL

View File

@ -0,0 +1,2 @@
<!DOCTYPE html>
<html><head><title>Dummy XHTML document</title></head><body /></html>

View File

@ -0,0 +1 @@
<foo>Dummy XML document</foo>

View File

@ -9,6 +9,8 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<iframe src="/common/dummy.xml"></iframe>
<iframe src="/common/dummy.xhtml"></iframe>
<script>
function toASCIIUppercase(str) {
var diff = "a".charCodeAt(0) - "A".charCodeAt(0);
@ -22,37 +24,60 @@ function toASCIIUppercase(str) {
}
return res;
}
test(function() {
function toASCIILowercase(str) {
var diff = "a".charCodeAt(0) - "A".charCodeAt(0);
var res = "";
for (var i = 0; i < str.length; ++i) {
if ("A" <= str[i] && str[i] <= "Z") {
res += String.fromCharCode(str.charCodeAt(i) + diff);
} else {
res += str[i];
}
}
return res;
}
var HTMLNS = "http://www.w3.org/1999/xhtml",
valid = [
//[input, localName],
[undefined, "undefined"],
[null, "null"],
["foo", "foo"],
["f1oo", "f1oo"],
["foo1", "foo1"],
["f\u0300oo", "f\u0300oo"],
["foo\u0300", "foo\u0300"],
[":foo", ":foo"],
["f:oo", "f:oo"],
["foo:", "foo:"],
["xml", "xml"],
["xmlns", "xmlns"],
["xmlfoo", "xmlfoo"],
["xml:foo", "xml:foo"],
["xmlns:foo", "xmlns:foo"],
["xmlfoo:bar", "xmlfoo:bar"],
["svg", "svg"],
["math", "math"],
["FOO", "foo"],
["mar\u212a", "mar\u212a"],
["\u0130nput", "\u0130nput"],
["\u0131nput", "\u0131nput"]
undefined,
null,
"foo",
"f1oo",
"foo1",
"f\u0BC6",
"foo\u0BC6",
":",
":foo",
"f:oo",
"foo:",
"f:o:o",
"f::oo",
"f::oo:",
"foo:0",
"foo:_",
// combining char after :, invalid QName but valid Name
"foo:\u0BC6",
"foo:foo\u0BC6",
"foo\u0BC6:foo",
"xml",
"xmlns",
"xmlfoo",
"xml:foo",
"xmlns:foo",
"xmlfoo:bar",
"svg",
"math",
"FOO",
// Test that non-ASCII chars don't get uppercased/lowercased
"mar\u212a",
"\u0130nput",
"\u0131nput",
],
invalid = [
"",
"1foo",
"\u0300foo",
"1:foo",
"fo o",
"\u0BC6foo",
"}foo",
"f}oo",
"foo}",
@ -62,24 +87,71 @@ test(function() {
"<foo",
"foo>",
"<foo>",
"f<oo"
"f<oo",
"-foo",
".foo",
"\u0BC6",
]
var xmlIframe = document.querySelector('[src="/common/dummy.xml"]');
var xhtmlIframe = document.querySelector('[src="/common/dummy.xhtml"]');
function getWin(desc) {
if (desc == "HTML document") {
return window;
}
if (desc == "XML document") {
assert_equals(xmlIframe.contentDocument.documentElement.textContent,
"Dummy XML document", "XML document didn't load");
return xmlIframe.contentWindow;
}
if (desc == "XHTML document") {
assert_equals(xhtmlIframe.contentDocument.documentElement.textContent,
"Dummy XHTML document", "XHTML document didn't load");
return xhtmlIframe.contentWindow;
}
}
valid.forEach(function(t) {
test(function() {
var elt = document.createElement(t[0])
assert_true(elt instanceof Element)
assert_true(elt instanceof Node)
assert_equals(elt.localName, t[1])
assert_equals(elt.tagName, toASCIIUppercase(t[1]))
assert_equals(elt.prefix, null)
assert_equals(elt.namespaceURI, HTMLNS)
}, "createElement(" + format_value(t[0]) + ")");
["HTML document", "XML document", "XHTML document"].forEach(function(desc) {
async_test(function(testObj) {
window.addEventListener("load", function() {
testObj.step(function() {
var win = getWin(desc);
var doc = win.document;
var elt = doc.createElement(t)
assert_true(elt instanceof win.Element, "instanceof Element")
assert_true(elt instanceof win.Node, "instanceof Node")
assert_equals(elt.localName,
desc == "HTML document" ? toASCIILowercase(String(t))
: String(t),
"localName")
assert_equals(elt.tagName,
desc == "HTML document" ? toASCIIUppercase(String(t))
: String(t),
"tagName")
assert_equals(elt.prefix, null, "prefix")
assert_equals(elt.namespaceURI,
desc == "XML document" ? null : HTMLNS, "namespaceURI")
});
testObj.done();
});
}, "createElement(" + format_value(t) + ") in " + desc);
});
});
invalid.forEach(function(arg) {
test(function() {
assert_throws("INVALID_CHARACTER_ERR", function() { document.createElement(arg) })
}, "createElement(" + format_value(arg) + ")");
["HTML document", "XML document", "XHTML document"].forEach(function(desc) {
async_test(function(testObj) {
window.addEventListener("load", function() {
testObj.step(function() {
var doc = getWin(desc).document;
assert_throws("InvalidCharacterError",
function() { doc.createElement(arg) })
});
testObj.done();
});
}, "createElement(" + format_value(arg) + ") in " + desc);
});
});
})
</script>

View File

@ -6,8 +6,9 @@
<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>
test(function() {
var tests = createElementNS_tests.concat([
/* Arrays with three elements:
* the namespace argument
@ -31,18 +32,34 @@ test(function() {
["foo:", "", "INVALID_CHARACTER_ERR"],
])
tests.forEach(function(t, i) {
test(function() {
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(expected, function() { document.createElementNS(namespace, qualifiedName) })
assert_throws(expected, function() { doc.createElementNS(namespace, qualifiedName) })
} else {
var element = document.createElementNS(namespace, qualifiedName)
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, document)
assert_equals(element.ownerDocument, doc)
var qualified = String(qualifiedName), names = []
if (qualified.indexOf(":") >= 0) {
names = qualified.split(":", 2)
@ -53,12 +70,23 @@ test(function() {
assert_equals(element.localName, names[1])
assert_equals(element.tagName, qualified)
assert_equals(element.nodeName, qualified)
assert_equals(element.namespaceURI, namespace === undefined ? null : namespace)
assert_equals(element.namespaceURI,
namespace === undefined || namespace === "" ? null
: namespace)
}
}, "createElementNS test: " + t.map(format_value))
})
});
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");

View File

@ -4,12 +4,13 @@ var createElementNS_tests = [
* 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, "\u0300foo", "INVALID_CHARACTER_ERR"],
[null, "\u0BC6foo", "INVALID_CHARACTER_ERR"],
[null, "}foo", "INVALID_CHARACTER_ERR"],
[null, "f}oo", "INVALID_CHARACTER_ERR"],
[null, "foo}", "INVALID_CHARACTER_ERR"],
@ -21,9 +22,13 @@ var createElementNS_tests = [
[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", "NAMESPACE_ERR"],
[null, "f:oo", "NAMESPACE_ERR"],
[null, "foo:", "NAMESPACE_ERR"],
[null, "f:o:o", "NAMESPACE_ERR"],
[null, ":", "NAMESPACE_ERR"],
[null, "xml", null],
[null, "xmlns", "NAMESPACE_ERR"],
@ -32,9 +37,11 @@ var createElementNS_tests = [
[null, "xmlns:foo", "NAMESPACE_ERR"],
[null, "xmlfoo:bar", "NAMESPACE_ERR"],
[null, "null:xml", "NAMESPACE_ERR"],
["", null, null],
["", ":foo", "NAMESPACE_ERR"],
["", "f:oo", "NAMESPACE_ERR"],
["", "foo:", "NAMESPACE_ERR"],
[undefined, null, null],
[undefined, undefined, null],
[undefined, "foo", null],
[undefined, "1foo", "INVALID_CHARACTER_ERR"],
@ -43,6 +50,7 @@ var createElementNS_tests = [
[undefined, ":foo", "NAMESPACE_ERR"],
[undefined, "f:oo", "NAMESPACE_ERR"],
[undefined, "foo:", "NAMESPACE_ERR"],
[undefined, "f::oo", "NAMESPACE_ERR"],
[undefined, "xml", null],
[undefined, "xmlns", "NAMESPACE_ERR"],
[undefined, "xmlfoo", null],
@ -51,11 +59,28 @@ var createElementNS_tests = [
[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", "NAMESPACE_ERR"],
["http://example.com/", "f:oo", null],
["http://example.com/", "f:o:o", "NAMESPACE_ERR"],
["http://example.com/", "foo:", "NAMESPACE_ERR"],
["http://example.com/", "f::oo", "NAMESPACE_ERR"],
["http://example.com/", "a:0", "NAMESPACE_ERR"],
["http://example.com/", "0:a", "INVALID_CHARACTER_ERR"],
["http://example.com/", "a:_", null],
["http://example.com/", "a:\u0BC6", "NAMESPACE_ERR"],
["http://example.com/", "\u0BC6: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],