Fix Trusted Types navigation and fragment history loops

This commit is contained in:
Clintchiz committed 2026-09-30 14:21:13 +05:30
1 parent 1179fc2810
commit 5eae6f3b3c
4 files changed
+62 -6

No files matched your search

+26 -3
View File
@@ -32,6 +32,21 @@ export const NAV_RUNTIME = String.raw`
window.__wrnexusNavInstalled = true;
var navigationPolicy = null;
if (window.trustedTypes) {
try {
navigationPolicy = window.trustedTypes.createPolicy("wrnexus-navigation", {
createHTML: function (value) { return value; },
createScriptURL: function (value) { return value; },
});
} catch (_) {
// A restrictive policy may disallow client navigation. Keep the native
// document navigation fallback without weakening the site's CSP.
}
}
var renderedRoute = location.pathname + location.search;
var APP_ID = "app";
var inFlight = null;
var memory = Object.create(null);
@@ -341,7 +356,7 @@ export const NAV_RUNTIME = String.raw`
);
},
);
element.src = src;
element.src = navigationPolicy ? navigationPolicy.createScriptURL(src) : src;
if (!script.hasAttribute("async")) {
element.async = false;
}
@@ -518,7 +533,9 @@ export const NAV_RUNTIME = String.raw`
}
function hardNavigate(url) {
location.href = url;
var destination = new URL(url, location.href);
if (destination.href === location.href) location.reload();
else location.href = destination.href;
}
function render(html, url, isPop) {
@@ -526,7 +543,7 @@ export const NAV_RUNTIME = String.raw`
try {
doc = new DOMParser().parseFromString(
html,
navigationPolicy ? navigationPolicy.createHTML(html) : html,
"text/html",
);
} catch (_) {
@@ -627,6 +644,8 @@ export const NAV_RUNTIME = String.raw`
}
var renderedUrl = new URL(url, location.href);
renderedRoute = renderedUrl.pathname + renderedUrl.search;
restorePage(url, isPop);
dispatchNavigationEvent(url);
@@ -737,6 +756,10 @@ export const NAV_RUNTIME = String.raw`
window.addEventListener(
"popstate",
function () {
// Native fragment navigation also emits popstate. The document is
// already rendered: fetching it again loses form edits and can loop
// when a rejected render falls back to the same fragment URL.
if (location.pathname + location.search === renderedRoute) return;
navigate(location.href, true);
},
);