From 417770a3a5c04c951fbdc967a3e3bc6dddee701b Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 24 Jan 2023 20:43:33 +0100 Subject: [PATCH] fix: better iframe navigation - uses postMessage to trigger the inner SvelteKit's goto method - monkeypatches iframe's history.pushState to use replaceState instead to not create history entries, keeping the parent window's navigation order intact --- content/tutorial/common/src/__client.js | 60 ++++++------------------ src/routes/tutorial/[slug]/Output.svelte | 4 +- 2 files changed, 16 insertions(+), 48 deletions(-) diff --git a/content/tutorial/common/src/__client.js b/content/tutorial/common/src/__client.js index e9bca1cbb..9bb819c93 100644 --- a/content/tutorial/common/src/__client.js +++ b/content/tutorial/common/src/__client.js @@ -15,54 +15,22 @@ window.alert = (message) => { }; window.addEventListener('message', async (e) => { - if (e.data.type === 'fetch') { - const names = e.data.names; - - const transformed = await Promise.all( - names.map(async (name) => { - const res = await fetch(name); - return { - name, - code: await res.text() - }; - }) - ); - - const css_files = []; - - for (const { name, code } of transformed) { - if ( - name.endsWith('.svelte') && - code.includes('svelte&type=style&lang.css') - ) { - css_files.push(name + '?svelte&type=style&lang.css'); - } - } - - if (css_files.length > 0) { - const css_transformed = await Promise.all( - css_files.map(async (name) => { - const res = await fetch(name); - return { - name, - code: await res.text() - }; - }) - ); - - transformed.push(...css_transformed); - } - - parent.postMessage( - { - type: 'fetch-result', - data: transformed - }, - '*' - ); + // Belts and braces against malicious messages + if (e.data.type === 'goto' && e.data.path?.startsWith('/')) { + // SvelteKit's client.js will pick this up + const a = document.createElement('a'); + a.href = e.data.path; + document.firstElementChild.append(a); + a.click(); + a.remove(); } }); +history.pushState = function (state, title, url) { + // Don't create a new history entry for better back/forward navigation in the parent window + history.replaceState(state, title, url); +}; + function ping() { parent.postMessage( { @@ -90,7 +58,7 @@ if (import.meta.hot) { }); } -/** +/** * The iframe sometimes takes focus control in ways we can't prevent * while the editor is focussed. Refocus the editor in these cases. */ diff --git a/src/routes/tutorial/[slug]/Output.svelte b/src/routes/tutorial/[slug]/Output.svelte index e566260a7..a65aeedb6 100644 --- a/src/routes/tutorial/[slug]/Output.svelte +++ b/src/routes/tutorial/[slug]/Output.svelte @@ -213,7 +213,7 @@ if (new_path) { ignore_path_change = true; [history_bwd, history_fwd] = [history_bwd.slice(0, -1), [path, ...history_fwd]]; - route_to(new_path); + iframe.contentWindow?.postMessage({ type: 'goto', path: new_path }, '*'); } } @@ -222,7 +222,7 @@ if (new_path) { ignore_path_change = true; [history_bwd, history_fwd] = [[...history_bwd, path], history_fwd.slice(1)]; - route_to(new_path); + iframe.contentWindow?.postMessage({ type: 'goto', path: new_path }, '*'); } }