forked from LadybirdBrowser/ladybird
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LibWeb: Do not give the HTML namespace to elements when parsing XML
While the code that did this referred to the HTML spec, other browsers appear not to have this behavior when parsing XML, and it breaks a WPT subtest. This change does not appear to break any tests, and fixes 1 WPT subtest.
- Loading branch information
Showing
3 changed files
with
272 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
Tests/LibWeb/Text/expected/wpt-import/domparsing/XMLSerializer-serializeToString.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
Summary | ||
|
||
Harness status: OK | ||
|
||
Rerun | ||
|
||
Found 24 tests | ||
|
||
8 Pass | ||
16 Fail | ||
Details | ||
Result Test Name MessagePass check XMLSerializer.serializeToString method could parsing xmldoc to string | ||
Pass check XMLSerializer.serializeToString method could parsing document to string | ||
Pass Check if the default namespace is correctly reset. | ||
Pass Check if there is no redundant empty namespace declaration. | ||
Fail Check if redundant xmlns="..." is dropped. | ||
Pass Check if inconsistent xmlns="..." is dropped. | ||
Fail Check if an attribute with namespace and no prefix is serialized with the nearest-declared prefix | ||
Fail Check if an attribute with namespace and no prefix is serialized with the nearest-declared prefix even if the prefix is assigned to another namespace. | ||
Fail Check if the prefix of an attribute is replaced with another existing prefix mapped to the same namespace URI. | ||
Fail Check if the prefix of an attribute is NOT preserved in a case where neither its prefix nor its namespace URI is not already used. | ||
Fail Check if the prefix of an attribute is replaced with a generated one in a case where the prefix is already mapped to a different namespace URI. | ||
Fail check XMLSerializer.serializeToString escapes attribute values for roundtripping | ||
Fail Check if attribute serialization takes into account of following xmlns:* attributes | ||
Fail Check if attribute serialization takes into account of the same prefix declared in an ancestor element | ||
Fail Check if start tag serialization drops element prefix if the namespace is same as inherited default namespace. | ||
Fail Check if start tag serialization finds an appropriate prefix. | ||
Fail Check if start tag serialization takes into account of its xmlns:* attributes | ||
Fail Check if start tag serialization applied the original prefix even if it is declared in an ancestor element. | ||
Fail Check if start tag serialization does NOT apply the default namespace if its namespace is declared in an ancestor. | ||
Pass | ||
Fail Check if "ns1" is generated even if the element already has xmlns:ns1. | ||
Fail Check if no special handling for XLink namespace unlike HTML serializer. | ||
Pass Check if document fragment serializes. | ||
Pass Check children were included for void elements |
237 changes: 237 additions & 0 deletions
237
Tests/LibWeb/Text/input/wpt-import/domparsing/XMLSerializer-serializeToString.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
<!DOCTYPE HTML> | ||
<meta charset=utf-8> | ||
<html> | ||
<head> | ||
<title>domparsing Test: XMLSerializer.serializeToString</title> | ||
<script src="../resources/testharness.js"></script> | ||
<script src="../resources/testharnessreport.js"></script> | ||
</head> | ||
<body> | ||
<h1>domparsing_XMLSerializer_serializeToString</h1> | ||
<script> | ||
const XMLNS_URI = 'http://www.w3.org/2000/xmlns/'; | ||
|
||
function createXmlDoc(){ | ||
var input = '<?xml version="1.0" encoding="UTF-8"?><root><child1>value1</child1></root>'; | ||
var parser = new DOMParser(); | ||
return parser.parseFromString(input, 'text/xml'); | ||
} | ||
|
||
// Returns the root element. | ||
function parse(xmlString) { | ||
return (new DOMParser()).parseFromString(xmlString, 'text/xml').documentElement; | ||
} | ||
|
||
function serialize(node) { | ||
return (new XMLSerializer()).serializeToString(node); | ||
} | ||
|
||
test(function() { | ||
var root = createXmlDoc().documentElement; | ||
assert_equals(serialize(root), '<root><child1>value1</child1></root>'); | ||
}, 'check XMLSerializer.serializeToString method could parsing xmldoc to string'); | ||
|
||
test(function() { | ||
var root = parse('<html><head></head><body><div></div><span></span></body></html>'); | ||
assert_equals(serialize(root.ownerDocument), '<html><head/><body><div/><span/></body></html>'); | ||
}, 'check XMLSerializer.serializeToString method could parsing document to string'); | ||
|
||
test(function() { | ||
var root = createXmlDoc().documentElement; | ||
var element = root.ownerDocument.createElementNS('urn:foo', 'another'); | ||
var child1 = root.firstChild; | ||
root.replaceChild(element, child1); | ||
element.appendChild(child1); | ||
assert_equals(serialize(root), '<root><another xmlns="urn:foo"><child1 xmlns="">value1</child1></another></root>'); | ||
}, 'Check if the default namespace is correctly reset.'); | ||
|
||
test(function() { | ||
var root = parse('<root xmlns="urn:bar"><outer xmlns=""><inner>value1</inner></outer></root>'); | ||
assert_equals(serialize(root), '<root xmlns="urn:bar"><outer xmlns=""><inner>value1</inner></outer></root>'); | ||
}, 'Check if there is no redundant empty namespace declaration.'); | ||
|
||
// https://github.com/w3c/DOM-Parsing/issues/47 | ||
test(function() { | ||
assert_equals(serialize(parse('<root><child xmlns=""/></root>')), | ||
'<root><child/></root>'); | ||
assert_equals(serialize(parse('<root xmlns=""><child xmlns=""/></root>')), | ||
'<root><child/></root>'); | ||
assert_equals(serialize(parse('<root xmlns="u1"><child xmlns="u1"/></root>')), | ||
'<root xmlns="u1"><child/></root>'); | ||
}, 'Check if redundant xmlns="..." is dropped.'); | ||
|
||
test(function() { | ||
const root = parse('<root xmlns="uri1"/>'); | ||
const child = root.ownerDocument.createElement('child'); | ||
child.setAttributeNS(XMLNS_URI, 'xmlns', 'FAIL1'); | ||
root.appendChild(child); | ||
const child2 = root.ownerDocument.createElementNS('uri2', 'child2'); | ||
child2.setAttributeNS(XMLNS_URI, 'xmlns', 'FAIL2'); | ||
root.appendChild(child2); | ||
const child3 = root.ownerDocument.createElementNS('uri1', 'child3'); | ||
child3.setAttributeNS(XMLNS_URI, 'xmlns', 'FAIL3'); | ||
root.appendChild(child3); | ||
const child4 = root.ownerDocument.createElementNS('uri4', 'child4'); | ||
child4.setAttributeNS(XMLNS_URI, 'xmlns', 'uri4'); | ||
root.appendChild(child4); | ||
const child5 = root.ownerDocument.createElement('child5'); | ||
child5.setAttributeNS(XMLNS_URI, 'xmlns', ''); | ||
root.appendChild(child5); | ||
assert_equals(serialize(root), '<root xmlns="uri1"><child xmlns=""/><child2 xmlns="uri2"/><child3/><child4 xmlns="uri4"/><child5 xmlns=""/></root>'); | ||
}, 'Check if inconsistent xmlns="..." is dropped.'); | ||
|
||
test(function() { | ||
let root = parse('<r xmlns:xx="uri"></r>'); | ||
root.setAttributeNS('uri', 'name', 'v'); | ||
assert_equals(serialize(root), '<r xmlns:xx="uri" xx:name="v"/>'); | ||
|
||
let root2 = parse('<r xmlns:xx="uri"><b/></r>'); | ||
let child = root2.firstChild; | ||
child.setAttributeNS('uri', 'name', 'v'); | ||
assert_equals(serialize(root2), '<r xmlns:xx="uri"><b xx:name="v"/></r>'); | ||
|
||
let root3 = parse('<r xmlns:x0="uri" xmlns:x2="uri"><b xmlns:x1="uri"/></r>'); | ||
let child3 = root3.firstChild; | ||
child3.setAttributeNS('uri', 'name', 'v'); | ||
assert_equals(serialize(root3), | ||
'<r xmlns:x0="uri" xmlns:x2="uri"><b xmlns:x1="uri" x1:name="v"/></r>', | ||
'Should choose the nearest prefix'); | ||
}, 'Check if an attribute with namespace and no prefix is serialized with the nearest-declared prefix'); | ||
|
||
// https://github.com/w3c/DOM-Parsing/issues/45 | ||
test(function() { | ||
let root = parse('<el1 xmlns:p="u1" xmlns:q="u1"><el2 xmlns:q="u2"/></el1>'); | ||
root.firstChild.setAttributeNS('u1', 'name', 'v'); | ||
assert_equals(serialize(root), | ||
'<el1 xmlns:p="u1" xmlns:q="u1"><el2 xmlns:q="u2" q:name="v"/></el1>'); | ||
}, 'Check if an attribute with namespace and no prefix is serialized with the nearest-declared prefix even if the prefix is assigned to another namespace.'); | ||
|
||
test(function() { | ||
let root = parse('<r xmlns:xx="uri"></r>'); | ||
root.setAttributeNS('uri', 'p:name', 'v'); | ||
assert_equals(serialize(root), '<r xmlns:xx="uri" xx:name="v"/>'); | ||
|
||
let root2 = parse('<r xmlns:xx="uri"><b/></r>'); | ||
let child = root2.firstChild; | ||
child.setAttributeNS('uri', 'p:name', 'value'); | ||
assert_equals(serialize(root2), | ||
'<r xmlns:xx="uri"><b xx:name="value"/></r>'); | ||
}, 'Check if the prefix of an attribute is replaced with another existing prefix mapped to the same namespace URI.'); | ||
|
||
// https://github.com/w3c/DOM-Parsing/issues/29 | ||
test(function() { | ||
let root = parse('<r xmlns:xx="uri"></r>'); | ||
root.setAttributeNS('uri2', 'p:name', 'value'); | ||
assert_equals(serialize(root), | ||
'<r xmlns:xx="uri" xmlns:ns1="uri2" ns1:name="value"/>'); | ||
}, 'Check if the prefix of an attribute is NOT preserved in a case where neither its prefix nor its namespace URI is not already used.'); | ||
|
||
test(function() { | ||
let root = parse('<r xmlns:xx="uri"></r>'); | ||
root.setAttributeNS('uri2', 'xx:name', 'value'); | ||
assert_equals(serialize(root), | ||
'<r xmlns:xx="uri" xmlns:ns1="uri2" ns1:name="value"/>'); | ||
}, 'Check if the prefix of an attribute is replaced with a generated one in a case where the prefix is already mapped to a different namespace URI.'); | ||
|
||
test(function() { | ||
var root = parse('<root />'); | ||
root.setAttribute('attr', '\t'); | ||
assert_in_array(serialize(root), [ | ||
'<root attr="	"/>', '<root attr="	"/>']); | ||
root.setAttribute('attr', '\n'); | ||
assert_in_array(serialize(root), [ | ||
'<root attr="
"/>', '<root attr=" "/>']); | ||
root.setAttribute('attr', '\r'); | ||
assert_in_array(serialize(root), [ | ||
'<root attr="
"/>', '<root attr=" "/>']); | ||
}, 'check XMLSerializer.serializeToString escapes attribute values for roundtripping'); | ||
|
||
test(function() { | ||
const root = (new Document()).createElement('root'); | ||
root.setAttributeNS('uri1', 'p:foobar', 'value1'); | ||
root.setAttributeNS(XMLNS_URI, 'xmlns:p', 'uri2'); | ||
assert_equals(serialize(root), '<root xmlns:ns1="uri1" ns1:foobar="value1" xmlns:p="uri2"/>'); | ||
}, 'Check if attribute serialization takes into account of following xmlns:* attributes'); | ||
|
||
test(function() { | ||
const root = parse('<root xmlns:p="uri1"><child/></root>'); | ||
root.firstChild.setAttributeNS('uri2', 'p:foobar', 'v'); | ||
assert_equals(serialize(root), '<root xmlns:p="uri1"><child xmlns:ns1="uri2" ns1:foobar="v"/></root>'); | ||
}, 'Check if attribute serialization takes into account of the same prefix declared in an ancestor element'); | ||
|
||
test(function() { | ||
assert_equals(serialize(parse('<root><child/></root>')), '<root><child/></root>'); | ||
assert_equals(serialize(parse('<root xmlns="u1"><p:child xmlns:p="u1"/></root>')), '<root xmlns="u1"><child xmlns:p="u1"/></root>'); | ||
}, 'Check if start tag serialization drops element prefix if the namespace is same as inherited default namespace.'); | ||
|
||
test(function() { | ||
const root = parse('<root xmlns:p1="u1"><child xmlns:p2="u1"/></root>'); | ||
const child2 = root.ownerDocument.createElementNS('u1', 'child2'); | ||
root.firstChild.appendChild(child2); | ||
assert_equals(serialize(root), '<root xmlns:p1="u1"><child xmlns:p2="u1"><p2:child2/></child></root>'); | ||
}, 'Check if start tag serialization finds an appropriate prefix.'); | ||
|
||
test(function() { | ||
const root = (new Document()).createElementNS('uri1', 'p:root'); | ||
root.setAttributeNS(XMLNS_URI, 'xmlns:p', 'uri2'); | ||
assert_equals(serialize(root), '<ns1:root xmlns:ns1="uri1" xmlns:p="uri2"/>'); | ||
}, 'Check if start tag serialization takes into account of its xmlns:* attributes'); | ||
|
||
test(function() { | ||
const root = (new Document()).createElement('root'); | ||
root.setAttributeNS(XMLNS_URI, 'xmlns:p', 'uri2'); | ||
const child = root.ownerDocument.createElementNS('uri1', 'p:child'); | ||
root.appendChild(child); | ||
assert_equals(serialize(root), '<root xmlns:p="uri2"><p:child xmlns:p="uri1"/></root>'); | ||
}, 'Check if start tag serialization applied the original prefix even if it is declared in an ancestor element.'); | ||
|
||
// https://github.com/w3c/DOM-Parsing/issues/52 | ||
test(function() { | ||
assert_equals(serialize(parse('<root xmlns:x="uri1"><table xmlns="uri1"></table></root>')), | ||
'<root xmlns:x="uri1"><x:table xmlns="uri1"/></root>'); | ||
}, 'Check if start tag serialization does NOT apply the default namespace if its namespace is declared in an ancestor.'); | ||
|
||
test(function() { | ||
const root = parse('<root><child1/><child2/></root>'); | ||
root.firstChild.setAttributeNS('uri1', 'attr1', 'value1'); | ||
root.firstChild.setAttributeNS('uri2', 'attr2', 'value2'); | ||
root.lastChild.setAttributeNS('uri3', 'attr3', 'value3'); | ||
assert_equals(serialize(root), '<root><child1 xmlns:ns1="uri1" ns1:attr1="value1" xmlns:ns2="uri2" ns2:attr2="value2"/><child2 xmlns:ns3="uri3" ns3:attr3="value3"/></root>'); | ||
}, 'Check if generated prefixes match to "ns${index}".'); | ||
|
||
// https://github.com/w3c/DOM-Parsing/issues/44 | ||
// According to 'DOM Parsing and Serialization' draft as of 2018-12-11, | ||
// 'generate a prefix' result can conflict with an existing xmlns:ns* declaration. | ||
test(function() { | ||
const root = parse('<root xmlns:ns2="uri2"><child xmlns:ns1="uri1"/></root>'); | ||
root.firstChild.setAttributeNS('uri3', 'attr1', 'value1'); | ||
assert_equals(serialize(root), '<root xmlns:ns2="uri2"><child xmlns:ns1="uri1" xmlns:ns1="uri3" ns1:attr1="value1"/></root>'); | ||
}, 'Check if "ns1" is generated even if the element already has xmlns:ns1.'); | ||
|
||
test(function() { | ||
const root = (new Document()).createElement('root'); | ||
root.setAttributeNS('http://www.w3.org/1999/xlink', 'href', 'v'); | ||
assert_equals(serialize(root), '<root xmlns:ns1="http://www.w3.org/1999/xlink" ns1:href="v"/>'); | ||
|
||
const root2 = (new Document()).createElement('root'); | ||
root2.setAttributeNS('http://www.w3.org/1999/xlink', 'xl:type', 'v'); | ||
assert_equals(serialize(root2), '<root xmlns:xl="http://www.w3.org/1999/xlink" xl:type="v"/>'); | ||
}, 'Check if no special handling for XLink namespace unlike HTML serializer.'); | ||
|
||
test(function() { | ||
var root = new DocumentFragment; | ||
root.append(document.createElement('div')); | ||
root.append(document.createElement('span')); | ||
assert_equals(serialize(root), '<div xmlns="http://www.w3.org/1999/xhtml"></div><span xmlns="http://www.w3.org/1999/xhtml"></span>'); | ||
}, 'Check if document fragment serializes.'); | ||
|
||
test(function () { | ||
const root = document.createElement("img"); | ||
root.append(document.createElement("style")); | ||
root.append(document.createElement("style")); | ||
assert_equals(serialize(root), '<img xmlns=\"http://www.w3.org/1999/xhtml\"><style></style><style></style></img>'); | ||
}, 'Check children were included for void elements') | ||
|
||
</script> | ||
</body> | ||
</html> |