LibWeb: Serialize HTML attribute names as per spec

This commit is contained in:
Lorenz A 2025-09-13 22:55:08 +02:00 committed by Jelle Raaijmakers
parent 4772e1b0c9
commit 47796e7967
3 changed files with 606 additions and 10 deletions

View File

@ -5205,22 +5205,39 @@ String HTMLParser::serialize_html_fragment(DOM::Node const& node, SerializableSh
builder.append(' ');
// An attribute's serialized name for the purposes of the previous paragraph must be determined as follows:
// NOTE: As far as I can tell, these steps are equivalent to just using the qualified name.
//
// -> If the attribute has no namespace:
// The attribute's serialized name is the attribute's local name.
if (!attribute.namespace_uri().has_value()) {
// The attribute's serialized name is the attribute's local name.
builder.append(attribute.local_name());
}
// -> If the attribute is in the XML namespace:
// The attribute's serialized name is the string "xml:" followed by the attribute's local name.
else if (attribute.namespace_uri() == Namespace::XML) {
// The attribute's serialized name is the string "xml:" followed by the attribute's local name.
builder.append("xml:"sv);
builder.append(attribute.local_name());
}
// -> If the attribute is in the XMLNS namespace and the attribute's local name is xmlns:
// The attribute's serialized name is the string "xmlns".
else if (attribute.namespace_uri() == Namespace::XMLNS && attribute.local_name() == "xmlns") {
// The attribute's serialized name is the string "xmlns".
builder.append("xmlns"sv);
}
// -> If the attribute is in the XMLNS namespace and the attribute's local name is not xmlns:
// The attribute's serialized name is the string "xmlns:" followed by the attribute's local name.
else if (attribute.namespace_uri() == Namespace::XMLNS) {
// The attribute's serialized name is the string "xmlns:" followed by the attribute's local name.
builder.append("xmlns:"sv);
builder.append(attribute.local_name());
}
// -> If the attribute is in the XLink namespace:
// The attribute's serialized name is the string "xlink:" followed by the attribute's local name.
else if (attribute.namespace_uri() == Namespace::XLink) {
// The attribute's serialized name is the string "xlink:" followed by the attribute's local name.
builder.append("xlink:"sv);
builder.append(attribute.local_name());
}
// -> If the attribute is in some other namespace:
// The attribute's serialized name is the attribute's qualified name.
builder.append(attribute.name());
else {
// The attribute's serialized name is the attribute's qualified name.
builder.append(attribute.name());
}
builder.append("=\""sv);
builder.append(escape_string(attribute.value().code_points(), AttributeMode::Yes));

View File

@ -0,0 +1,243 @@
Harness status: OK
Found 238 tests
238 Pass
Pass innerHTML 0
Pass innerHTML 1 <a></a>
Pass innerHTML 2 <a b="c"></a>
Pass innerHTML 3 <a b="c"></a>
Pass innerHTML 4 <a b="&amp;"></a>
Pass innerHTML 5 <a b="&nbsp;"></a>
Pass innerHTML 6 <a b="&quot;"></a>
Pass innerHTML 7 <a b="&lt;"></a>
Pass innerHTML 8 <a b="&gt;"></a>
Pass innerHTML 9 <a href="javascript:&quot;&lt;&gt;&quot;"></a>
Pass innerHTML 10 <svg xlink:href="a"></svg>
Pass innerHTML 11 <svg xmlns:svg="test"></svg>
Pass innerHTML 12 a
Pass innerHTML 13 &amp;
Pass innerHTML 14 &nbsp;
Pass innerHTML 15 &lt;
Pass innerHTML 16 &gt;
Pass innerHTML 17 "
Pass innerHTML 18 <style><&></style>
Pass innerHTML 19 <script type="test"><&></script>
Pass innerHTML 20 <&>
Pass innerHTML 21 <xmp><&></xmp>
Pass innerHTML 22 <iframe><&></iframe>
Pass innerHTML 23 <noembed><&></noembed>
Pass innerHTML 24 <noframes><&></noframes>
Pass innerHTML 25 <noscript><&></noscript>
Pass innerHTML 26 <!--data-->
Pass innerHTML 27 <a><b><c></c></b><d>e</d><f><g>h</g></f></a>
Pass innerHTML 28
Pass outerHTML 0 <span></span>
Pass outerHTML 1 <span><a></a></span>
Pass outerHTML 2 <span><a b="c"></a></span>
Pass outerHTML 3 <span><a b="c"></a></span>
Pass outerHTML 4 <span><a b="&amp;"></a></span>
Pass outerHTML 5 <span><a b="&nbsp;"></a></span>
Pass outerHTML 6 <span><a b="&quot;"></a></span>
Pass outerHTML 7 <span><a b="&lt;"></a></span>
Pass outerHTML 8 <span><a b="&gt;"></a></span>
Pass outerHTML 9 <span><a href="javascript:&quot;&lt;&gt;&quot;"></a></span>
Pass outerHTML 10 <span><svg xlink:href="a"></svg></span>
Pass outerHTML 11 <span><svg xmlns:svg="test"></svg></span>
Pass outerHTML 12 <span>a</span>
Pass outerHTML 13 <span>&amp;</span>
Pass outerHTML 14 <span>&nbsp;</span>
Pass outerHTML 15 <span>&lt;</span>
Pass outerHTML 16 <span>&gt;</span>
Pass outerHTML 17 <span>"</span>
Pass outerHTML 18 <span><style><&></style></span>
Pass outerHTML 19 <span><script type="test"><&></script></span>
Pass outerHTML 20 <script type="test"><&></script>
Pass outerHTML 21 <span><xmp><&></xmp></span>
Pass outerHTML 22 <span><iframe><&></iframe></span>
Pass outerHTML 23 <span><noembed><&></noembed></span>
Pass outerHTML 24 <span><noframes><&></noframes></span>
Pass outerHTML 25 <span><noscript><&></noscript></span>
Pass outerHTML 26 <span><!--data--></span>
Pass outerHTML 27 <span><a><b><c></c></b><d>e</d><f><g>h</g></f></a></span>
Pass outerHTML 28 <span b="c"></span>
Pass innerHTML Attribute in the XML namespace
Pass innerHTML Attribute in the XML namespace with the prefix not set to xml:
Pass innerHTML Non-'xmlns' attribute in the xmlns namespace
Pass innerHTML 'xmlns' attribute in the xmlns namespace
Pass innerHTML Attribute in non-standard namespace
Pass innerHTML <span> starting with U+000A
Pass outerHTML Attribute in the XML namespace
Pass outerHTML Attribute in the XML namespace with the prefix not set to xml:
Pass outerHTML Non-'xmlns' attribute in the xmlns namespace
Pass outerHTML 'xmlns' attribute in the xmlns namespace
Pass outerHTML Attribute in non-standard namespace
Pass outerHTML <span> starting with U+000A
Pass innerHTML <pre> context starting with U+000A
Pass innerHTML <textarea> context starting with U+000A
Pass innerHTML <listing> context starting with U+000A
Pass innerHTML <pre> context not starting with U+000A
Pass innerHTML <textarea> context not starting with U+000A
Pass innerHTML <listing> context not starting with U+000A
Pass innerHTML <pre> non-context starting with U+000A
Pass innerHTML <textarea> non-context starting with U+000A
Pass innerHTML <listing> non-context starting with U+000A
Pass innerHTML <pre> non-context not starting with U+000A
Pass innerHTML <textarea> non-context not starting with U+000A
Pass innerHTML <listing> non-context not starting with U+000A
Pass outerHTML <pre> context starting with U+000A
Pass outerHTML <textarea> context starting with U+000A
Pass outerHTML <listing> context starting with U+000A
Pass outerHTML <pre> context not starting with U+000A
Pass outerHTML <textarea> context not starting with U+000A
Pass outerHTML <listing> context not starting with U+000A
Pass outerHTML <pre> non-context starting with U+000A
Pass outerHTML <textarea> non-context starting with U+000A
Pass outerHTML <listing> non-context starting with U+000A
Pass outerHTML <pre> non-context not starting with U+000A
Pass outerHTML <textarea> non-context not starting with U+000A
Pass outerHTML <listing> non-context not starting with U+000A
Pass innerHTML Void context node area
Pass innerHTML Void context node base
Pass innerHTML Void context node basefont
Pass innerHTML Void context node bgsound
Pass innerHTML Void context node br
Pass innerHTML Void context node col
Pass innerHTML Void context node embed
Pass innerHTML Void context node frame
Pass innerHTML Void context node hr
Pass innerHTML Void context node img
Pass innerHTML Void context node input
Pass innerHTML Void context node keygen
Pass innerHTML Void context node link
Pass innerHTML Void context node meta
Pass innerHTML Void context node param
Pass innerHTML Void context node source
Pass innerHTML Void context node track
Pass innerHTML Void context node wbr
Pass innerHTML void as first child with following siblings area
Pass innerHTML void as first child with following siblings base
Pass innerHTML void as first child with following siblings basefont
Pass innerHTML void as first child with following siblings bgsound
Pass innerHTML void as first child with following siblings br
Pass innerHTML void as first child with following siblings col
Pass innerHTML void as first child with following siblings embed
Pass innerHTML void as first child with following siblings frame
Pass innerHTML void as first child with following siblings hr
Pass innerHTML void as first child with following siblings img
Pass innerHTML void as first child with following siblings input
Pass innerHTML void as first child with following siblings keygen
Pass innerHTML void as first child with following siblings link
Pass innerHTML void as first child with following siblings meta
Pass innerHTML void as first child with following siblings param
Pass innerHTML void as first child with following siblings source
Pass innerHTML void as first child with following siblings track
Pass innerHTML void as first child with following siblings wbr
Pass innerHTML void as second child with following siblings area
Pass innerHTML void as second child with following siblings base
Pass innerHTML void as second child with following siblings basefont
Pass innerHTML void as second child with following siblings bgsound
Pass innerHTML void as second child with following siblings br
Pass innerHTML void as second child with following siblings col
Pass innerHTML void as second child with following siblings embed
Pass innerHTML void as second child with following siblings frame
Pass innerHTML void as second child with following siblings hr
Pass innerHTML void as second child with following siblings img
Pass innerHTML void as second child with following siblings input
Pass innerHTML void as second child with following siblings keygen
Pass innerHTML void as second child with following siblings link
Pass innerHTML void as second child with following siblings meta
Pass innerHTML void as second child with following siblings param
Pass innerHTML void as second child with following siblings source
Pass innerHTML void as second child with following siblings track
Pass innerHTML void as second child with following siblings wbr
Pass innerHTML void as last child with preceding siblings area
Pass innerHTML void as last child with preceding siblings base
Pass innerHTML void as last child with preceding siblings basefont
Pass innerHTML void as last child with preceding siblings bgsound
Pass innerHTML void as last child with preceding siblings br
Pass innerHTML void as last child with preceding siblings col
Pass innerHTML void as last child with preceding siblings embed
Pass innerHTML void as last child with preceding siblings frame
Pass innerHTML void as last child with preceding siblings hr
Pass innerHTML void as last child with preceding siblings img
Pass innerHTML void as last child with preceding siblings input
Pass innerHTML void as last child with preceding siblings keygen
Pass innerHTML void as last child with preceding siblings link
Pass innerHTML void as last child with preceding siblings meta
Pass innerHTML void as last child with preceding siblings param
Pass innerHTML void as last child with preceding siblings source
Pass innerHTML void as last child with preceding siblings track
Pass innerHTML void as last child with preceding siblings wbr
Pass outerHTML Void context node area
Pass outerHTML Void context node base
Pass outerHTML Void context node basefont
Pass outerHTML Void context node bgsound
Pass outerHTML Void context node br
Pass outerHTML Void context node col
Pass outerHTML Void context node embed
Pass outerHTML Void context node frame
Pass outerHTML Void context node hr
Pass outerHTML Void context node img
Pass outerHTML Void context node input
Pass outerHTML Void context node keygen
Pass outerHTML Void context node link
Pass outerHTML Void context node meta
Pass outerHTML Void context node param
Pass outerHTML Void context node source
Pass outerHTML Void context node track
Pass outerHTML Void context node wbr
Pass outerHTML void as first child with following siblings area
Pass outerHTML void as first child with following siblings base
Pass outerHTML void as first child with following siblings basefont
Pass outerHTML void as first child with following siblings bgsound
Pass outerHTML void as first child with following siblings br
Pass outerHTML void as first child with following siblings col
Pass outerHTML void as first child with following siblings embed
Pass outerHTML void as first child with following siblings frame
Pass outerHTML void as first child with following siblings hr
Pass outerHTML void as first child with following siblings img
Pass outerHTML void as first child with following siblings input
Pass outerHTML void as first child with following siblings keygen
Pass outerHTML void as first child with following siblings link
Pass outerHTML void as first child with following siblings meta
Pass outerHTML void as first child with following siblings param
Pass outerHTML void as first child with following siblings source
Pass outerHTML void as first child with following siblings track
Pass outerHTML void as first child with following siblings wbr
Pass outerHTML void as second child with following siblings area
Pass outerHTML void as second child with following siblings base
Pass outerHTML void as second child with following siblings basefont
Pass outerHTML void as second child with following siblings bgsound
Pass outerHTML void as second child with following siblings br
Pass outerHTML void as second child with following siblings col
Pass outerHTML void as second child with following siblings embed
Pass outerHTML void as second child with following siblings frame
Pass outerHTML void as second child with following siblings hr
Pass outerHTML void as second child with following siblings img
Pass outerHTML void as second child with following siblings input
Pass outerHTML void as second child with following siblings keygen
Pass outerHTML void as second child with following siblings link
Pass outerHTML void as second child with following siblings meta
Pass outerHTML void as second child with following siblings param
Pass outerHTML void as second child with following siblings source
Pass outerHTML void as second child with following siblings track
Pass outerHTML void as second child with following siblings wbr
Pass outerHTML void as last child with preceding siblings area
Pass outerHTML void as last child with preceding siblings base
Pass outerHTML void as last child with preceding siblings basefont
Pass outerHTML void as last child with preceding siblings bgsound
Pass outerHTML void as last child with preceding siblings br
Pass outerHTML void as last child with preceding siblings col
Pass outerHTML void as last child with preceding siblings embed
Pass outerHTML void as last child with preceding siblings frame
Pass outerHTML void as last child with preceding siblings hr
Pass outerHTML void as last child with preceding siblings img
Pass outerHTML void as last child with preceding siblings input
Pass outerHTML void as last child with preceding siblings keygen
Pass outerHTML void as last child with preceding siblings link
Pass outerHTML void as last child with preceding siblings meta
Pass outerHTML void as last child with preceding siblings param
Pass outerHTML void as last child with preceding siblings source
Pass outerHTML void as last child with preceding siblings track
Pass outerHTML void as last child with preceding siblings wbr

View File

@ -0,0 +1,336 @@
<!DOCTYPE html>
<title>innerHTML in HTML</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<div id="log"></div>
<!-- test elments. Each has an expected innerHTML and outerHTML in an array in the <script>-->
<div id="test" style="display:none">
<span></span>
<span><a></a></span>
<span><a b=c></a></span>
<span><a b='c'></a></span>
<span><a b='&'></a></span>
<span><a b='&nbsp;'></a></span>
<span><a b='"'></a></span>
<span><a b="<"></a></span>
<span><a b=">"></a></span>
<span><a href="javascript:&quot;&lt;>&quot;"></a></span>
<span><svg xlink:href="a"></svg></span>
<span><svg xmlns:svg="test"></svg></span>
<span>a</span>
<span>&amp;</span>
<span>&nbsp;</span>
<span>&lt;</span>
<span>&gt;</span>
<span>&quot;</span>
<span><style><&></style></span>
<span><script type="test"><&></script></span>
<script type="test"><&></script>
<span><xmp><&></xmp></span>
<span><iframe><&></iframe></span>
<span><noembed><&></noembed></span>
<span><noframes><&></noframes></span>
<span><noscript><&></noscript></span>
<span><!--data--></span>
<span><a><b><c></c></b><d>e</d><f><g>h</g></f></a></span>
<span b=c></span>
</div>
<!-- TODO: template element -->
<script>
var test_data = document.getElementById("test").children;
var expected = [
["", "<span></span>"],
["<a></a>", "<span><a></a></span>"],
["<a b=\"c\"></a>", "<span><a b=\"c\"></a></span>"],
["<a b=\"c\"></a>", "<span><a b=\"c\"></a></span>"],
["<a b=\"&amp;\"></a>", "<span><a b=\"&amp;\"></a></span>"],
["<a b=\"&nbsp;\"></a>", "<span><a b=\"&nbsp;\"></a></span>"],
["<a b=\"&quot;\"></a>", "<span><a b=\"&quot;\"></a></span>"],
["<a b=\"&lt;\"></a>", "<span><a b=\"&lt;\"></a></span>"],
["<a b=\"&gt;\"></a>", "<span><a b=\"&gt;\"></a></span>"],
["<a href=\"javascript:&quot;&lt;&gt;&quot;\"></a>", "<span><a href=\"javascript:&quot;&lt;&gt;&quot;\"></a></span>"],
["<svg xlink:href=\"a\"></svg>", "<span><svg xlink:href=\"a\"></svg></span>"],
["<svg xmlns:svg=\"test\"></svg>", "<span><svg xmlns:svg=\"test\"></svg></span>"],
["a", "<span>a</span>"],
["&amp;", "<span>&amp;</span>"],
["&nbsp;", "<span>&nbsp;</span>"],
["&lt;", "<span>&lt;</span>"],
["&gt;", "<span>&gt;</span>"],
["\"", "<span>\"</span>"],
["<style><&></style>", "<span><style><&></style></span>"],
["<script type=\"test\"><&><\/script>", "<span><script type=\"test\"><&><\/script></span>"],
["<&>", "<script type=\"test\"><&><\/script>"],
["<xmp><&></xmp>", "<span><xmp><&></xmp></span>"],
["<iframe><&></iframe>", "<span><iframe><&></iframe></span>"],
["<noembed><&></noembed>", "<span><noembed><&></noembed></span>"],
["<noframes><&></noframes>", "<span><noframes><&></noframes></span>"],
["<noscript><&></noscript>", "<span><noscript><&></noscript></span>"],
["<!--data-->", "<span><!--data--></span>"],
["<a><b><c></c></b><d>e</d><f><g>h</g></f></a>", "<span><a><b><c></c></b><d>e</d><f><g>h</g></f></a></span>"],
["", "<span b=\"c\"></span>"]
];
var dom_tests = [
["Attribute in the XML namespace",
function() {
var span = document.createElement("span");
var svg = document.createElement("svg");
svg.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:foo", "test");
span.appendChild(svg);
return span;
},
'<svg xml:foo="test"></svg>',
'<span><svg xml:foo="test"></svg></span>'],
["Attribute in the XML namespace with the prefix not set to xml:",
function() {
var span = document.createElement("span");
var svg = document.createElement("svg");
svg.setAttributeNS("http://www.w3.org/XML/1998/namespace", "abc:foo", "test");
span.appendChild(svg);
return span;
},
'<svg xml:foo="test"></svg>',
'<span><svg xml:foo="test"></svg></span>'],
["Non-'xmlns' attribute in the xmlns namespace",
function() {
var span = document.createElement("span");
var svg = document.createElement("svg");
svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:foo", "test")
span.appendChild(svg);
return span;
},
'<svg xmlns:foo="test"></svg>',
'<span><svg xmlns:foo="test"></svg></span>'],
["'xmlns' attribute in the xmlns namespace",
function() {
var span = document.createElement("span");
var svg = document.createElement("svg");
svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "test")
span.appendChild(svg);
return span;
},
'<svg xmlns="test"></svg>',
'<span><svg xmlns="test"></svg></span>'],
["Attribute in non-standard namespace",
function() {
var span = document.createElement("span");
var svg = document.createElement("svg");
svg.setAttributeNS("fake_ns", "abc:def", "test")
span.appendChild(svg);
return span;
},
'<svg abc:def="test"></svg>',
'<span><svg abc:def="test"></svg></span>'],
["<span> starting with U+000A",
function() {
var elem = document.createElement("span");
elem.appendChild(document.createTextNode("\x0A"));
return elem;
},
"\x0A",
"<span>\x0A</span>"],
//TODO: Processing instructions
]
var text_elements = ["pre", "textarea", "listing"];
var text_tests = [
["<%text> context starting with U+000A",
function(elem) {
elem.appendChild(document.createTextNode("\x0A"));
return elem;
},
"\x0A",
"<%text>\x0A</%text>"],
["<%text> context not starting with U+000A",
function(elem) {
elem.appendChild(document.createTextNode("a\x0A"));
return elem;
},
"a\x0A",
"<%text>a\x0A</%text>"],
["<%text> non-context starting with U+000A",
function(elem) {
var span = document.createElement("span");
elem.appendChild(document.createTextNode("\x0A"));
span.appendChild(elem);
return span;
},
"<%text>\x0A</%text>",
"<span><%text>\x0A</%text></span>"],
["<%text> non-context not starting with U+000A",
function(elem) {
var span = document.createElement("span");
elem.appendChild(document.createTextNode("a\x0A"));
span.appendChild(elem);
return span;
},
"<%text>a\x0A</%text>",
"<span><%text>a\x0A</%text></span>"],
]
var void_elements = [
"area", "base", "basefont", "bgsound", "br", "col", "embed",
"frame", "hr", "img", "input", "keygen", "link",
"meta", "param", "source", "track", "wbr"
];
var void_tests = [
["Void context node",
function (void_elem) {
return void_elem;
},
"",
"<%void>"
],
["void as first child with following siblings",
function (void_elem) {
var span = document.createElement("span");
span.appendChild(void_elem);
span.appendChild(document.createElement("a")).appendChild(document.createTextNode("test"));
span.appendChild(document.createElement("b"))
return span
},
"<%void><a>test</a><b></b>",
"<span><%void><a>test</a><b></b></span>"
],
["void as second child with following siblings",
function (void_elem) {
var span = document.createElement("span");
span.appendChild(document.createElement("a")).appendChild(document.createTextNode("test"));
span.appendChild(void_elem);
span.appendChild(document.createElement("b"))
return span;
},
"<a>test</a><%void><b></b>",
"<span><a>test</a><%void><b></b></span>"
],
["void as last child with preceding siblings",
function (void_elem) {
var span = document.createElement("span");
span.appendChild(document.createElement("a")).appendChild(document.createTextNode("test"));
span.appendChild(document.createElement("b"))
span.appendChild(void_elem);
return span;
},
"<a>test</a><b></b><%void>",
"<span><a>test</a><b></b><%void></span>"
],
]
function cross_map(a1, a2, f) {
var rv = [];
a1.forEach(function(a1_elem) {
a2.forEach(function(a2_elem) {
rv.push(f(a1_elem, a2_elem));
})
});
return rv;
}
function innerHTML_test(func, elem, expected) {
assert_equals(func(elem).innerHTML, expected);
}
function outerHTML_test(func, elem, expected) {
assert_equals(func(elem).outerHTML, expected);
}
function make_void(name) {
var rv = document.createElement(name);
rv.appendChild(document.createElement("a")).appendChild(document.createComment("abc"))
rv.appendChild(document.createElement("b")).
appendChild(document.createElement("c")).
appendChild(document.createTextNode("abc"))
return rv;
}
function make_text(name) {
return document.createElement(name);
}
generate_tests(innerHTML_test,
expected.map(function(item, i) {
return ["innerHTML " + i + " " + expected[i][0],
function() {return test_data[i]},
null,
item[0]];
}))
generate_tests(outerHTML_test,
expected.map(function(item, i) {
return ["outerHTML " + i + " " + expected[i][1],
function() {return test_data[i]},
null,
item[1]];
}))
generate_tests(innerHTML_test,
dom_tests.map(function(item) {
return ["innerHTML " + item[0],
item[1],
null,
item[2]];
}))
generate_tests(outerHTML_test,
dom_tests.map(function(item) {
return ["outerHTML " + item[0],
item[1],
null,
item[3]];
}))
generate_tests(innerHTML_test,
cross_map(text_tests, text_elements,
function(test_data, elem_name) {
var rv = ["innerHTML " + test_data[0].replace(/%text/g, elem_name),
test_data[1],
document.createElement(elem_name),
test_data[2].replace(/%text/g, elem_name)];
return rv;
}))
generate_tests(outerHTML_test,
cross_map(text_tests, text_elements,
function(test_data, elem_name) {
var rv = ["outerHTML " + test_data[0].replace(/%text/g, elem_name),
test_data[1],
document.createElement(elem_name),
test_data[3].replace(/%text/g, elem_name)];
return rv;
}))
generate_tests(innerHTML_test,
cross_map(void_tests, void_elements,
function(test_data, elem_name) {
var rv = ["innerHTML " + test_data[0] + " " + elem_name,
test_data[1],
make_void(elem_name),
test_data[2].replace(/%void/g, elem_name)];
return rv;
}))
generate_tests(outerHTML_test,
cross_map(void_tests, void_elements,
function(test_data, elem_name) {
var rv = ["outerHTML " + test_data[0] + " " + elem_name,
test_data[1],
make_void(elem_name),
test_data[3].replace(/%void/g, elem_name)];
return rv;
}))
</script>