Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<meta charset="utf-8">
<title>CDATA sections in fragment parsing depend only on the adjusted current node's namespace</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// After processing each token, the tree construction stage sets the tokenizer's
// "CDATA sections allowed" flag. Per the markup declaration open state, CDATA is
// allowed whenever there is an adjusted current node and it is not an element in
// the HTML namespace. Integration points are NOT a consideration: the only thing
// that matters is the adjusted current node's namespace.
//
// When fragment-parsing with only the root DocumentFragment on the open elements
// stack, the adjusted current node is the context element (not the
// DocumentFragment). So for a context element in a non-HTML namespace, CDATA
// sections are allowed even if that element is an integration point.
//
// The input "x<![CDATA[y]]>" is used because:
// 1. "x" is emitted as a character token first
// 2. After processing "x", the tree builder sets tokenizer flags
// 3. "<![CDATA[y]]>" is then tokenized with those flags
//
// If CDATA is allowed, "y" becomes text content (textContent === "xy").
// If CDATA is disallowed, "<![CDATA[y]]>" becomes a bogus comment.
// MathML text integration points: still in the MathML namespace, so CDATA is allowed.
for (const tagName of ["mi", "mo", "mn", "ms", "mtext"]) {
test(function() {
const el = document.createElementNS("http://www.w3.org/1998/Math/MathML", tagName);
el.innerHTML = "x<![CDATA[y]]>";
assert_equals(el.textContent, "xy",
"CDATA should be parsed as character data because the adjusted current node is not in the HTML namespace");
assert_equals(el.childNodes.length, 1, "should have a single text node");
assert_equals(el.firstChild.nodeType, Node.TEXT_NODE, "child should be a text node");
}, "CDATA allowed when fragment-parsing with <" + tagName + "> context (MathML text integration point)");
}
// SVG HTML integration points: still in the SVG namespace, so CDATA is allowed.
for (const tagName of ["foreignObject", "desc", "title"]) {
test(function() {
const el = document.createElementNS("http://www.w3.org/2000/svg", tagName);
el.innerHTML = "x<![CDATA[y]]>";
assert_equals(el.textContent, "xy",
"CDATA should be parsed as character data because the adjusted current node is not in the HTML namespace");
assert_equals(el.childNodes.length, 1, "should have a single text node");
assert_equals(el.firstChild.nodeType, Node.TEXT_NODE, "child should be a text node");
}, "CDATA allowed when fragment-parsing with <" + tagName + "> context (SVG HTML integration point)");
}
// Non-integration-point foreign element: also in a non-HTML namespace, so CDATA is allowed.
test(function() {
const el = document.createElementNS("http://www.w3.org/2000/svg", "path");
el.innerHTML = "x<![CDATA[y]]>";
assert_equals(el.textContent, "xy",
"CDATA should be parsed as character data for non-integration-point foreign elements");
}, "CDATA allowed when fragment-parsing with <path> context (non-integration-point SVG element)");
// Control: an HTML context element. The adjusted current node is in the HTML
// namespace, so CDATA is NOT allowed and "<![CDATA[y]]>" is a bogus comment.
test(function() {
const el = document.createElement("div");
el.innerHTML = "x<![CDATA[y]]>";
assert_equals(el.firstChild.nodeType, Node.TEXT_NODE, "first child should be a text node");
assert_equals(el.firstChild.data, "x", "text node should contain only 'x'");
assert_equals(el.childNodes.length, 2, "should have 2 child nodes (text + comment)");
assert_equals(el.lastChild.nodeType, Node.COMMENT_NODE,
"CDATA should be parsed as a bogus comment for an HTML context element");
assert_equals(el.lastChild.data, "[CDATA[y]]", "bogus comment data");
}, "CDATA not allowed when fragment-parsing with <div> context (HTML element)");
</script>