Skip to content

Commit 5d84eeb

Browse files
authored
fix(browser): log ErrorEvent.message when unhandled ErrorEvent.error is null (#9322)
1 parent 23ff7c3 commit 5d84eeb

File tree

5 files changed

+61
-2
lines changed

5 files changed

+61
-2
lines changed

packages/browser/src/client/public/error-catcher.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ function catchWindowErrors(errorEvent, prop, cb) {
3131
cb(e)
3232
}
3333
else {
34-
console.error(e[prop])
34+
// `ErrorEvent` doesn't necessary have `ErrotEvent.error` defined
35+
// but some has `ErrorEvent.message` defined, e.g. ResizeObserver error.
36+
// https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent/error
37+
// https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors
38+
console.error(e.message ? new Error(e.message) : e)
3539
}
3640
}
3741
const addEventListener = window.addEventListener.bind(window)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { test } from "vitest";
2+
3+
test("ResizeObserver error", async () => {
4+
const divElem = document.createElement("div");
5+
divElem.style.width = "100px";
6+
divElem.style.height = "100px";
7+
document.body.appendChild(divElem);
8+
9+
const resizeObserver = new ResizeObserver((entries) => {
10+
for (const entry of entries) {
11+
(entry.target as HTMLElement).style.width =
12+
`${entry.contentBoxSize[0].inlineSize + 10}px`;
13+
}
14+
});
15+
const promise = Promise.withResolvers();
16+
window.addEventListener("error", (event) => {
17+
if (event.message.includes("ResizeObserver loop")) {
18+
promise.resolve(null);
19+
}
20+
});
21+
resizeObserver.observe(divElem);
22+
await promise.promise;
23+
resizeObserver.unobserve(divElem);
24+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { fileURLToPath } from 'node:url'
2+
import { defineConfig } from 'vitest/config'
3+
import { instances, provider } from '../../settings'
4+
5+
export default defineConfig({
6+
cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),
7+
test: {
8+
browser: {
9+
enabled: true,
10+
provider,
11+
instances,
12+
headless: true,
13+
},
14+
},
15+
})

test/browser/settings.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ const devInstances: BrowserInstanceOption[] = [
2020
const playwrightInstances: BrowserInstanceOption[] = [
2121
{ browser: 'chromium' },
2222
{ browser: 'firefox' },
23-
{ browser: 'webkit' },
23+
// hard to setup playwright webkit on some machines (e.g. ArchLinux)
24+
// this allows skipping it locally by BROWSER_NO_WEBKIT=true
25+
...(process.env.BROWSER_NO_WEBKIT ? [] : [{ browser: 'webkit' as const }]),
2426
]
2527

2628
const webdriverioInstances: BrowserInstanceOption[] = [

test/browser/specs/unhandled.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,17 @@ test('disables tracking', async () => {
3737
})
3838
expect(stderr).toBe('')
3939
})
40+
41+
test('print unhandled non error', async () => {
42+
const { testTree, stderr } = await runBrowserTests({
43+
root: './fixtures/unhandled-non-error',
44+
})
45+
expect(stderr).toContain('[Error: ResizeObserver loop completed with undelivered notifications.]')
46+
expect(testTree()).toMatchInlineSnapshot(`
47+
{
48+
"basic.test.ts": {
49+
"ResizeObserver error": "passed",
50+
},
51+
}
52+
`)
53+
})

0 commit comments

Comments
 (0)