diff --git a/src/core/drive/prefetch_cache.js b/src/core/drive/prefetch_cache.js index cb29aa238..bb9cec0ca 100644 --- a/src/core/drive/prefetch_cache.js +++ b/src/core/drive/prefetch_cache.js @@ -14,7 +14,7 @@ class PrefetchCache extends LRUCache { putLater(url, request, ttl) { this.#prefetchTimeout = setTimeout(() => { - request.perform() + request.perform().catch(() => this.evict(toCacheKey(url))) this.put(url, request, ttl) this.#prefetchTimeout = null }, this.prefetchDelay) diff --git a/src/tests/functional/link_prefetch_observer_tests.js b/src/tests/functional/link_prefetch_observer_tests.js index a40ea16dc..9ae795d9d 100644 --- a/src/tests/functional/link_prefetch_observer_tests.js +++ b/src/tests/functional/link_prefetch_observer_tests.js @@ -205,6 +205,25 @@ test("doesn't include a turbo-frame header when the link is inside a turbo frame }}) }) +test("it doesn't cause an unhandled rejection when a prefetch request fails", async ({ page }) => { + await goTo({ page, path: "/hover_to_prefetch.html" }) + + await page.evaluate(() => { + window.__unhandledRejections = [] + window.addEventListener("unhandledrejection", (event) => { + window.__unhandledRejections.push(event.reason?.message ?? String(event.reason)) + }) + }) + + await page.route("**/prefetched.html", (route) => route.abort("failed")) + + await page.hover("#anchor_for_prefetch") + await sleep(200) + + const unhandledRejections = await page.evaluate(() => window.__unhandledRejections) + expect(unhandledRejections).toHaveLength(0) +}) + test("it prefetches links with a delay", async ({ page }) => { await goTo({ page, path: "/hover_to_prefetch.html" })