Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 27 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /sanitizer-api/sanitizer-names.tenative.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
// Like assert_array_equals, but disregard element order.
function assert_array_same(actual, expected) {
assert_array_equals(actual.sort(), expected.sort());
}
// Element names:
const elems_valid = [
"p", "template", "span", "custom-elements", "potato",
// Arguments will be stringified, so anything that stringifies to a valid
// name is also valid.
123
];
const elems_invalid = [
"", {name: ""},
];
// Attribute names:
const attrs_valid = [
"href", "span",
];
const attrs_invalid = [
];
const all_elems = elems_valid.concat(elems_invalid);
const all_attrs = attrs_valid.concat(attrs_invalid);
for (const item of ["elements", "removeElements", "replaceWithChildrenElements"]) {
test(t => {
const sanitizer = new Sanitizer({[item]: all_elems});
assert_array_same(sanitizer.get()[item].map(x => x.name),
elems_valid.map(x => "" + x));
}, `Element names in config item: ${item}`);
}
for (const item of ["attributes", "removeAttributes"]) {
test(t => {
const sanitizer = new Sanitizer({[item]: all_attrs});
assert_array_same(sanitizer.get()[item].map(x => x.name),
attrs_valid.map(x => "" + x));
}, `Attribute names in config item: ${item}`);
}
// Quick sanity tests for namespaced elements.
// Each test case is a duo or triplet:
// - a Sanitizer config string for an element.
// - an HTML probe string.
// - the expected result. (If different from the probe.)
[
[ "p", "<p>Hello</p>" ],
[ "svg", "<svg>Hello</svg>", "" ],
[ { name: "svg", namespace: SVG_NS }, "<svg>Hello</svg>" ],
[ "math", "<math>Hello</math>", "" ],
[ { name: "math", namespace: SVG_NS }, "<math>Hello</math>", "" ],
[ { name: "math", namespace: MATHML_NS }, "<math>Hello</math>" ],
].forEach(([elem, probe, expected], index) => {
test(t => {
const div = document.createElement("div");
div.setHTML(probe, {sanitizer: {elements: [elem]}});
assert_equals(div.innerHTML, expected ?? probe);
}, `Namespaced elements #${index}: elements: [${JSON.stringify(elem)}]`);
});
// Same for attributes:
[
[ { name: "style"}, "<p style=\"bla\"></p>" ],
[ { name: "href"}, "<p href=\"bla\"></p>" ],
[ { name: "xlink:href"}, "<p xlink:href=\"bla\"></p>" ],
[ { name: "href", namespace: XLINK_NS}, "<p xlink:href=\"bla\"></p>", "<p></p>" ],
[ { name: "href", namespace: XLINK_NS}, "<p href='bla'></p>", "<p></p>" ],
[ { name: "href"}, "<p xlink:href='bla'></p>", "<p></p>" ],
].forEach(([attr, probe, expected], index) => {
test(t => {
const options = {attributes: [attr],
unknownMarkup: true};
const template = document.createElement("template");
template.setHTML(probe, {sanitizer: options});
assert_equals(template.innerHTML, expected ?? probe);
}, `Namespaced attributes #${index}: attributes: [${JSON.stringify(attr)}]`);
});
// Test for namespaced attribute inside namespace element
test(t => {
const probe = `<svg><a xlink:href="bla"></a></svg>`;
const options = {
elements: [
{name: "svg", namespace: SVG_NS},
{name: "a", namespace: SVG_NS, attributes: [
{ name: "href", namespace: XLINK_NS }
]}
],
unknownMarkup: true};
const template = document.createElement("template");
template.setHTML(probe, {sanitizer: options});
assert_equals(template.innerHTML, probe);
}, "Namespaced attribute xlink:href inside SVG tree");
// Names are case-senstive. Most element and attribute names are
// lower-cased, but "foreign content" like SVG and MathML have some
// mixed-cased names. Check this is supported. Check there is no
// case normalization.
[
[ "feBlend", "<feBlend></feBlend>" ],
[ "feColorMatrix", "<feColorMatrix></feColorMatrix>" ],
[ "textPath", "<textPath></textPath>" ],
].forEach(([elem, probe], index) => {
const sanitize = (elem, probe) => {
const options = {elements: [
{ name: "svg", namespace: SVG_NS },
{ name: elem, namespace: SVG_NS }
],
unknownMarkup: true};
const template = document.createElement("template");
template.setHTML(`<svg>${probe}</svg>`, {sanitizer: options});
return template.content.firstElementChild.innerHTML;
};
test(t => {
assert_equals(sanitize(elem, probe), probe);
}, `Mixed-case element names #${index}: "svg:${elem}"`);
test(t => {
assert_not_equals(sanitize(elem.toLowerCase(), probe), probe);
}, `Lower-case element names #${index}: "svg:${elem.toLowerCase()}"`);
test(t => {
assert_not_equals(sanitize(elem.toUpperCase(), probe), probe);
}, `Upper-case element names #${index}: "svg:${elem.toUpperCase()}"`);
});
</script>
</body>
</html>