Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 11 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /sanitizer-api/sethtml-with-trustedtypes-createParserOptions.tentative.html - WPT Dashboard Interop Dashboard
<!doctype html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/trusted-types/support/helper.sub.js"></script>
<meta
http-equiv="Content-Security-Policy"
content="require-trusted-types-for 'script';"
/>
</head>
<body>
<div id="container"></div>
<script>
const container = document.querySelector("#container");
// We have to replace this global because we are overriding the default policy from within the test.
let createParserOptions = (options) => ({
sanitizer: { removeElements: ["div"] },
});
let createHTML = (html) => html;
const cleanupPolicy = trustedTypes.createPolicy("cleanup", {
createHTML: (_) => "",
});
trustedTypes.createPolicy("default", {
createHTML: (html) => createHTML(html),
createParserOptions: (options) => createParserOptions(options),
});
const passthrough = trustedTypes.createPolicy("passthrough", {
createHTML: (html) => createHTML(html),
createParserOptions: (options) => options,
});
function cleanup() {}
function createTarget(target_type, t) {
t.add_cleanup(() => {
createParserOptions = (options) => ({
sanitizer: { removeElements: ["div"] },
});
createHTML = (html) => html;
});
const target = document.createElement("div");
switch (target_type) {
case "Element":
return target;
case "ShadowRoot":
return target.attachShadow({ mode: "open" });
}
}
const noCreateHTMLPolicy = trustedTypes.createPolicy("no-create-html", {
createParserOptions: (options) => options,
});
const noSanitizerPolicy = trustedTypes.createPolicy("no-sanitizer", {
createParserOptions: () => null,
});
for (const target of ["ShadowRoot", "Element"]) {
test((t) => {
const node = createTarget(target, t);
node.setHTMLUnsafe(
"<div id='allowed'><span id=forbidden></span></div>",
passthrough.createParserOptions({
sanitizer: { removeElements: ["span"] },
}),
);
assert_equals(node.querySelector("#forbidden"), null);
assert_not_equals(node.querySelector("#allowed"), null);
}, `${target}.setHTMLUnsafe: passing a TrustedHTMLParserOptions overrides default policy`);
test((t) => {
const node = createTarget(target, t);
node.setHTMLUnsafe(
"<div id='allowed'><span id=forbidden></span></div>",
noCreateHTMLPolicy.createParserOptions({
sanitizer: { removeElements: ["span"] },
}),
);
assert_equals(node.querySelector("#forbidden"), null);
assert_not_equals(node.querySelector("#allowed"), null);
}, `${target}.setHTMLUnsafe: policy with only createParserOptions allows raw strings when sanitizer is present`);
test((t) => {
const node = createTarget(target, t);
createHTML = (html) => {
throw new Error("createHTML failed");
};
assert_throws_js(Error, () => {
node.setHTMLUnsafe(
"<div id='allowed'><span id=forbidden></span></div>",
noSanitizerPolicy.createParserOptions({}),
);
});
}, `${target}.setHTMLUnsafe: TrustedHTMLParserOptions without sanitizer still requires createHTML`);
test((t) => {
const node = createTarget(target, t);
let createHTMLCalled = false;
createParserOptions = (options) => {
throw new Error("createParserOptions failed");
};
createHTML = (html) => {
createHTMLCalled = true;
return html;
};
assert_throws_js(Error, () => {
node.setHTMLUnsafe("<div id='allowed'></div>");
});
assert_false(createHTMLCalled, "createHTML should not have been called");
}, `${target}.setHTMLUnsafe: exception in default createParserOptions prevents createHTML from running`);
test((t) => {
const node = createTarget(target, t);
createParserOptions = (options) => ({
sanitizer: { removeElements: ["span"] },
});
createHTML = (html) => {
throw new Error("createHTML should not be called when sanitizer is present");
};
node.setHTMLUnsafe(
"<div id='allowed'><span id=forbidden></span></div>",
);
assert_equals(node.querySelector("#forbidden"), null);
assert_not_equals(node.querySelector("#allowed"), null);
}, `${target}.setHTMLUnsafe: default policy createParserOptions with sanitizer prevents createHTML from running`);
}
test((t) => {
const policy = trustedTypes.createPolicy("runscripts-reflect-policy", {
createParserOptions: (options) => options,
});
const optionsDefault = policy.createParserOptions({});
assert_true(optionsDefault instanceof TrustedHTMLParserOptions);
assert_false("runScripts" in optionsDefault, "TrustedHTMLParserOptions has no public runScripts member");
const optionsTrue = policy.createParserOptions({ runScripts: true });
assert_true(optionsTrue instanceof TrustedHTMLParserOptions);
assert_false("runScripts" in optionsTrue, "TrustedHTMLParserOptions has no public runScripts member");
const optionsFalse = policy.createParserOptions({ runScripts: false });
assert_true(optionsFalse instanceof TrustedHTMLParserOptions);
assert_false("runScripts" in optionsFalse, "TrustedHTMLParserOptions has no public runScripts member");
const div = document.createElement("div");
document.body.appendChild(div);
t.add_cleanup(() => div.remove());
window.did_run = false;
t.add_cleanup(() => { delete window.did_run; });
div.setHTMLUnsafe("<script>window.did_run = true;<" + "/script>", optionsDefault);
assert_false(window.did_run, "runScripts defaults to false in TrustedHTMLParserOptions");
div.setHTMLUnsafe("<script>window.did_run = true;<" + "/script>", optionsFalse);
assert_false(window.did_run, "runScripts false is respected in TrustedHTMLParserOptions");
div.setHTMLUnsafe("<script>window.did_run = true;<" + "/script>", optionsTrue);
assert_true(window.did_run, "runScripts true is respected in TrustedHTMLParserOptions");
}, "TrustedHTMLParserOptions applies runScripts option without exposing public members");
</script>
</body>
</html>