From 0dcef3ab171bd7f81c2f99e9366db3724aa7091b Mon Sep 17 00:00:00 2001 From: Erika <3019731+Princesseuh@users.noreply.github.com> Date: Mon, 29 Jul 2024 17:44:59 +0200 Subject: [PATCH] fix: check before writing to errors (#11566) * fix: check before writing to errors * fix: try using try catches * test: add * chore: changeset * nit: test name --- .changeset/violet-drinks-film.md | 5 +++++ packages/astro/e2e/errors.test.js | 6 ++++++ .../fixtures/errors/src/pages/dom-exception.astro | 3 +++ packages/astro/src/core/errors/dev/utils.ts | 14 +++++++++++--- 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 .changeset/violet-drinks-film.md create mode 100644 packages/astro/e2e/fixtures/errors/src/pages/dom-exception.astro diff --git a/.changeset/violet-drinks-film.md b/.changeset/violet-drinks-film.md new file mode 100644 index 000000000000..20098137fc6d --- /dev/null +++ b/.changeset/violet-drinks-film.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes DomException errors not being handled properly diff --git a/packages/astro/e2e/errors.test.js b/packages/astro/e2e/errors.test.js index 825fc7a9224c..600acd95b779 100644 --- a/packages/astro/e2e/errors.test.js +++ b/packages/astro/e2e/errors.test.js @@ -125,4 +125,10 @@ test.describe('Error display', () => { const message = (await getErrorOverlayContent(page)).message; expect(message).toMatch('can only be used in'); }); + + test('can handle DomException errors', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/dom-exception'), { waitUntil: 'networkidle' }); + const message = (await getErrorOverlayContent(page)).message; + expect(message).toMatch('The operation was aborted due to timeout'); + }); }); diff --git a/packages/astro/e2e/fixtures/errors/src/pages/dom-exception.astro b/packages/astro/e2e/fixtures/errors/src/pages/dom-exception.astro new file mode 100644 index 000000000000..99a5322d9979 --- /dev/null +++ b/packages/astro/e2e/fixtures/errors/src/pages/dom-exception.astro @@ -0,0 +1,3 @@ +--- +await fetch("https://example.com/", {signal: AbortSignal.timeout(5)}) +--- diff --git a/packages/astro/src/core/errors/dev/utils.ts b/packages/astro/src/core/errors/dev/utils.ts index c151b55cd712..341c815a6762 100644 --- a/packages/astro/src/core/errors/dev/utils.ts +++ b/packages/astro/src/core/errors/dev/utils.ts @@ -26,7 +26,9 @@ export function collectErrorMetadata(e: any, rootFolder?: URL | undefined): Erro err.forEach((error) => { if (e.stack) { const stackInfo = collectInfoFromStacktrace(e); - error.stack = stripAnsi(stackInfo.stack); + try { + error.stack = stripAnsi(stackInfo.stack); + } catch {} error.loc = stackInfo.loc; error.plugin = stackInfo.plugin; error.pluginCode = stackInfo.pluginCode; @@ -72,7 +74,11 @@ export function collectErrorMetadata(e: any, rootFolder?: URL | undefined): Erro // Strip ANSI for `message` property. Note that ESBuild errors may not have the property, // but it will be handled and added below, which is already ANSI-free if (error.message) { - error.message = stripAnsi(error.message); + try { + error.message = stripAnsi(error.message); + } catch { + // Setting `error.message` can fail here if the message is read-only, which for the vast majority of cases will never happen, however some somewhat obscure cases can cause this to happen. + } } }); @@ -84,7 +90,9 @@ export function collectErrorMetadata(e: any, rootFolder?: URL | undefined): Erro // ESBuild can give us a slightly better error message than the one in the error, so let's use it if (text) { - err[i].message = text; + try { + err[i].message = text; + } catch {} } if (location) {