Fix relative-time error and improve global error handler#37241
Fix relative-time error and improve global error handler#37241silverwind wants to merge 9 commits intogo-gitea:mainfrom
relative-time error and improve global error handler#37241Conversation
`navigator.language` can be the string `"undefined"` in Playwright Firefox (not just the undefined value), causing `Intl.DateTimeFormat` to throw `RangeError: invalid language tag: "undefined"`. The prior fix in go-gitea#37021 only handled the undefined value. Validate both the `lang` attribute and `navigator.language` through `Intl.Locale` and fall back to `'en'` if both yield invalid tags. Also enhances the global error UI: - Render the error stack trace (hidden, included when copying) - Add a copy-to-clipboard button with icon-swap feedback - Drop the "Open browser console" hint - Expose `copy` i18n key for the button's aria-label Fixes go-gitea#37239 Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
relative-time error with invalid navigator.languagerelative-time error and improve global error handler
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Rename `showGlobalErrorMessage` to `showGlobalError`, accept an `Error` as the first argument, and move the `"JavaScript error:"` / `"JavaScript promise rejection:"` prefix into the function. Replace raw `navigator.clipboard.writeText` with `clippie` and guard rapid clicks from stacking reset timeouts. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes a Playwright/headless-only relative-time locale parsing crash and enhances the frontend global error handler to better capture/copy debugging details, plus adds an e2e smoke test to catch homepage JS errors.
Changes:
- Make
relative-timelocale resolution resilient to invalidnavigator.languagevalues and add a regression unit test. - Replace
showGlobalErrorMessagewithshowGlobalError(Error, opts)and extend the global error UI with a copy-to-clipboard button that includes stack traces. - Add a Playwright test intended to ensure the homepage renders without JS errors.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| web_src/js/webcomponents/relative-time.ts | Safer language fallback when locale candidates are invalid. |
| web_src/js/webcomponents/relative-time.test.ts | Adds regression test for invalid navigator.language. |
| web_src/js/modules/errors.ts | New showGlobalError API + copy-with-stack UI + updated error event processing. |
| web_src/js/modules/errors.test.ts | Updates/extends unit tests for new error handler behavior. |
| web_src/js/features/common-page.ts | Migrates warning banners to the new showGlobalError API. |
| web_src/js/bootstrap.ts | Uses showGlobalError for early bootstrap failures. |
| tests/e2e/homepage.test.ts | Adds homepage smoke test asserting no global error UI is rendered. |
| templates/base/head_script.tmpl | Adds i18n.copy string to window.config for the new copy button label. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Keep the public signature as `showGlobalErrorMessage(msg, msgType?, stack?)` with a new third `stack` param. Minimizes the diff against main: bootstrap.ts and common-page.ts revert to their original call shape; only `processWindowErrorEvent` passes the new `stack` arg. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
- Drop the copy button's aria-label (and the newly-added i18n.copy key) so the error UI has no runtime dependency on window.config and works even when bootstrap triggers showGlobalErrorMessage due to a missing window.config. - Preserve newlines in multi-line messages (e.g. the ROOT_URL warning) via tw-whitespace-pre-line on .js-global-error-msg. - Always overwrite .js-global-error-stack so a previously-set stack doesn't linger when a later call has none. - Add networkidle wait to the homepage e2e so async JS errors have time to reach the global handler before the assertion; disable playwright/no-networkidle globally for e2e tests. - Simplify tests: shared beforeEach, drop redundant DOM-structure assertions, remove unneeded teardown plumbing. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Coverage is already provided by the `processWindowErrorEvent renders stack trace` test. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
Keep comments and `.toString()` choices consistent with main so the diff focuses on the actual behavioral changes. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
There was a problem hiding this comment.
No, the error message prompt is just for development purpose.
It should not be that complex. The more complex it becomes, the more potential bugs it will have. What if the code causes new errors again?
Do not make things unnecessarily complex.
If you need to read more about the error details, just open the browser's console, just like all the frontend developers do.
|
Stack trace must be accessible somehow because it's vital information and a small copy button achieves that in the least obtrusive way besides rendering it directly. "Open the console" is bad, some browsers might not even have a console, think about tablets or phones. Don't assume every user is on a desktop. |
Do you remember that you had objection when I introduced such "js error message prompt"? But now why you keep making it unnecessarily complex. Developers should open their console, look into the real source code with source map. In production build, your stack trace here is just garbled text
It is just your guess and imagination that "it needs to show stack for a user who uses a phone". |
|
It's more about that I always have to ask users to copy the error from the console than to screenshot/copy only the message because "Foo is undefined" is not debuggable without the stack trace. If you don't like the copy button, we could make it visible on-hover. |
How many times? Where are the related issues?
I don't accept any more useless change. |
At least 4-5 times, some on GitHub, some on Discord.
It is genuinely needed for debugging. |
|
If copy button is not to your liking, we can use a |
|
Can do with a general function like |
|
I will do the details+summary approach like that. |
Per review feedback (wxiaoguang), drop the copy button + explicit stack pre in favor of a native <details> expander: the message itself is the summary, clicking anywhere on the banner toggles the stack trace, and the stack renders in <pre><code> centered as a block with left-aligned text. Keeps the no-stack path identical to main. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
|
Ready again. now uses |
| await page.goto('/'); | ||
| await page.waitForLoadState('networkidle'); // eslint-disable-line playwright/no-networkidle | ||
| await assertNoJsError(page); | ||
| }); |
There was a problem hiding this comment.
Why such a strange special test for "homepage"? No page should have JS error


Fixes: #37239
Also enhances the global error UI per the issue's second half: the error message doubles as a
<summary>that expands to show the stack trace (<pre><code>) when clicked. The whole error banner is clickable, so users can easily copy-paste the stack into bug reports. Drops the "Open browser console to see more details." hint.Adds a generic e2e test that asserts no JS error on the homepage.
This PR was written with the help of Claude Opus 4.7