wpt / trusted-types / navigate-to-javascript-url-009.html?frame

Open test on wpt.live | wpt.fyi

Runs: Chrome 158.0.8110.0 (wpt@5ffee20ed, 2026-10-17) | Firefox 160.0a1 (wpt@d8b153fad, 2026-10-16) | Safari 254 preview (wpt@51a43ba4a, 2026-10-17) | Ladybird 1.0-401b1 (wpt@470a7adf8, 2026-10-17) | Servo Servo 0.7 (wpt@df642c414, 2026-10-17) | Blitz fb8d6c15e (wpt@cd1d8aa5b, 2026-10-17)

ChromeFirefoxSafariLadybirdServoBlitz
Total1/11/11/11/10/1NOT RUN
SubtestChromeFirefoxSafariLadybirdServoBlitz
Removing the element from the default policy during the pre-navigation check of its javascript: URL src should not fire a load event at it.PASSPASSPASSPASSFAIL—

/trusted-types/navigate-to-javascript-url-009.html

<!DOCTYPE html>
<meta name="variant" content="?iframe">
<meta name="variant" content="?frame">
<meta http-equiv="Content-Security-Policy"
      content="require-trusted-types-for 'script'">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
  // A javascript: URL in the src attribute of a freshly inserted iframe or frame
  // is navigated to with initialInsertion set to true, which is the one case
  // where "navigate to a javascript: URL" fires a load event at the container
  // when no Document is produced. The default policy runs author code in the
  // middle of that algorithm, so it can remove the element first, leaving the
  // navigable without a container to fire the load event at.
  //
  // navigate-to-javascript-url-007-crash.html covers the same re-entrancy for a
  // window.location navigation, where initialInsertion is false and this branch
  // is not reached.
  promise_test(async _ => {
    let javaScriptExecuted = false;
    window.executeJavaScript = _ => { javaScriptExecuted = true; };

    let loadEvents = 0;
    const element = document.createElement(location.search.substring(1));
    element.addEventListener("load", _ => { loadEvents++; });
    element.src = "javascript:parent.executeJavaScript()";
    document.head.appendChild(element);

    // The policy container of the synthetic request is snapshotted from the
    // document that inserted the element, but the element's initial about:blank
    // document inherits the same CSP, so install the default policy on both to
    // keep the test independent of which global the pre-navigation check
    // consults. See https://github.com/w3c/trusted-types/issues/548.
    const removeElement = { createScript: s => { element.remove(); return s; } };
    trustedTypes.createPolicy("default", removeElement);
    element.contentWindow.trustedTypes.createPolicy("default", removeElement);

    // Wait for the queued navigation task to have run.
    if (window.requestIdleCallback) {
      await new Promise(resolve => requestIdleCallback(resolve));
    } else {
      await new Promise(resolve => requestAnimationFrame(_ => requestAnimationFrame(resolve)));
    }

    assert_false(javaScriptExecuted, "JavaScript shouldn't have been executed");
    assert_equals(loadEvents, 0, "No load event should be fired at the removed element");
  }, "Removing the element from the default policy during the pre-navigation check of its javascript: URL src should not fire a load event at it.");
</script>