diff options
author | 2023-08-11 08:56:12 -0400 | |
---|---|---|
committer | 2023-08-11 08:56:12 -0400 | |
commit | 405913cdf20b26407aa351c090f0a0859a4e6f54 (patch) | |
tree | 050570c2273e55f7827ba98de322fe2e83402cfb | |
parent | 87d4b18437c7565c48cad4bea81831c2a244ebb8 (diff) | |
download | astro-405913cdf20b26407aa351c090f0a0859a4e6f54.tar.gz astro-405913cdf20b26407aa351c090f0a0859a4e6f54.tar.zst astro-405913cdf20b26407aa351c090f0a0859a4e6f54.zip |
Prevent script re-execution on page evaluation (#8033)
-rw-r--r-- | .changeset/lovely-impalas-pretend.md | 5 | ||||
-rw-r--r-- | packages/astro/components/ViewTransitions.astro | 23 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro | 10 | ||||
-rw-r--r-- | packages/astro/e2e/view-transitions.test.js | 15 |
4 files changed, 53 insertions, 0 deletions
diff --git a/.changeset/lovely-impalas-pretend.md b/.changeset/lovely-impalas-pretend.md new file mode 100644 index 000000000..fc11a88e1 --- /dev/null +++ b/.changeset/lovely-impalas-pretend.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Prevent script re-evaluation on page transition diff --git a/packages/astro/components/ViewTransitions.astro b/packages/astro/components/ViewTransitions.astro index d8d5bd1d7..215cb5b38 100644 --- a/packages/astro/components/ViewTransitions.astro +++ b/packages/astro/components/ViewTransitions.astro @@ -63,9 +63,16 @@ const { fallback = 'animate' } = Astro.props as Props; return 'animate'; } + function markScriptsExec() { + for (const script of document.scripts) { + script.dataset.astroExec = ''; + } + } + function runScripts() { let wait = Promise.resolve(); for (const script of Array.from(document.scripts)) { + if(script.dataset.astroExec === '') continue; const s = document.createElement('script'); s.innerHTML = script.innerHTML; for (const attr of script.attributes) { @@ -77,6 +84,7 @@ const { fallback = 'animate' } = Astro.props as Props; } s.setAttribute(attr.name, attr.value); } + s.dataset.astroExec = ''; script.replaceWith(s); } return wait; @@ -100,6 +108,18 @@ const { fallback = 'animate' } = Astro.props as Props; const href = el.getAttribute('href'); return doc.head.querySelector(`link[rel=stylesheet][href="${href}"]`); } + if(el.tagName === 'SCRIPT') { + let s1 = el as HTMLScriptElement; + for(const s2 of doc.scripts) { + if( + // Inline + (s1.textContent && s1.textContent === s2.textContent) || + // External + (s1.type === s2.type && s1.src === s2.src)) { + return s2; + } + } + } return null; }; @@ -207,6 +227,7 @@ const { fallback = 'animate' } = Astro.props as Props; } finally { document.documentElement.removeAttribute('data-astro-transition'); await runScripts(); + markScriptsExec(); onload(); } } @@ -225,6 +246,8 @@ const { fallback = 'animate' } = Astro.props as Props; } if (supportsViewTransitions || getFallback() !== 'none') { + markScriptsExec(); + document.addEventListener('click', (ev) => { let link = ev.target; if (link instanceof Element && link.tagName !== 'A') { diff --git a/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro b/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro index 7016a1bf7..1c0f9bbdf 100644 --- a/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro +++ b/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro @@ -20,6 +20,16 @@ const { link } = Astro.props as Props; </style> <ViewTransitions /> <DarkMode /> + <meta name="script-executions" content="0"> + <script is:inline defer> + { + // Increment a global to see if this is running more than once + globalThis.scriptExecutions = globalThis.scriptExecutions == null ? -1 : globalThis.scriptExecutions; + globalThis.scriptExecutions++; + const el = document.querySelector('[name="script-executions"]'); + el.setAttribute('content', globalThis.scriptExecutions); + } + </script> </head> <body> <header transition:animate="morph"> diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js index f30cd9902..0a3235b90 100644 --- a/packages/astro/e2e/view-transitions.test.js +++ b/packages/astro/e2e/view-transitions.test.js @@ -279,4 +279,19 @@ test.describe('View Transitions', () => { // Count should remain await expect(cnt).toHaveText('6'); }); + + test('Scripts are only executed once', async ({ page, astro }) => { + // Go to page 1 + await page.goto(astro.resolveUrl('/one')); + const p = page.locator('#one'); + await expect(p, 'should have content').toHaveText('Page 1'); + + // go to page 2 + await page.click('#click-two'); + const article = page.locator('#twoarticle'); + await expect(article, 'should have script content').toHaveText('works'); + + const meta = page.locator('[name="script-executions"]'); + await expect(meta).toHaveAttribute('content', '0'); + }); }); |