Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
// DO NOT IMPORT window.config HERE!
|
2024-02-29 06:20:53 +08:00
|
|
|
// to make sure the error handler always works, we should never import `window.config`, because
|
|
|
|
// some user's custom template breaks it.
|
2024-07-26 07:31:24 +08:00
|
|
|
import type {Intent} from './types.ts';
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
|
|
|
|
// This sets up the URL prefix used in webpack's chunk loading.
|
|
|
|
// This file must be imported before any lazy-loading is being attempted.
|
2023-08-31 10:46:44 +08:00
|
|
|
__webpack_public_path__ = `${window.config?.assetUrlPrefix ?? '/assets'}/`;
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
|
2024-07-26 07:31:24 +08:00
|
|
|
function shouldIgnoreError(err: Error) {
|
2024-05-06 00:34:13 +08:00
|
|
|
const ignorePatterns = [
|
|
|
|
'/assets/js/monaco.', // https://github.com/go-gitea/gitea/issues/30861 , https://github.com/microsoft/monaco-editor/issues/4496
|
|
|
|
];
|
|
|
|
for (const pattern of ignorePatterns) {
|
|
|
|
if (err.stack?.includes(pattern)) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2024-01-21 22:23:08 +08:00
|
|
|
|
2024-07-26 07:31:24 +08:00
|
|
|
export function showGlobalErrorMessage(msg: string, msgType: Intent = 'error') {
|
2024-05-06 00:34:13 +08:00
|
|
|
const msgContainer = document.querySelector('.page-content') ?? document.body;
|
|
|
|
const msgCompact = msg.replace(/\W/g, '').trim(); // compact the message to a data attribute to avoid too many duplicated messages
|
2024-07-26 07:31:24 +08:00
|
|
|
let msgDiv = msgContainer.querySelector<HTMLDivElement>(`.js-global-error[data-global-error-msg-compact="${msgCompact}"]`);
|
2024-01-21 22:23:08 +08:00
|
|
|
if (!msgDiv) {
|
|
|
|
const el = document.createElement('div');
|
2024-05-10 20:07:01 +08:00
|
|
|
el.innerHTML = `<div class="ui container js-global-error tw-my-[--page-spacing]"><div class="ui ${msgType} message tw-text-center tw-whitespace-pre-line"></div></div>`;
|
2024-07-26 07:31:24 +08:00
|
|
|
msgDiv = el.childNodes[0] as HTMLDivElement;
|
2024-01-21 22:23:08 +08:00
|
|
|
}
|
|
|
|
// merge duplicated messages into "the message (count)" format
|
|
|
|
const msgCount = Number(msgDiv.getAttribute(`data-global-error-msg-count`)) + 1;
|
|
|
|
msgDiv.setAttribute(`data-global-error-msg-compact`, msgCompact);
|
|
|
|
msgDiv.setAttribute(`data-global-error-msg-count`, msgCount.toString());
|
2024-05-10 20:07:01 +08:00
|
|
|
msgDiv.querySelector('.ui.message').textContent = msg + (msgCount > 1 ? ` (${msgCount})` : '');
|
2024-05-06 00:34:13 +08:00
|
|
|
msgContainer.prepend(msgDiv);
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
}
|
|
|
|
|
2024-07-26 07:31:24 +08:00
|
|
|
function processWindowErrorEvent({error, reason, message, type, filename, lineno, colno}: ErrorEvent & PromiseRejectionEvent) {
|
2024-02-29 06:20:53 +08:00
|
|
|
const err = error ?? reason;
|
2024-02-23 05:21:43 +08:00
|
|
|
const assetBaseUrl = String(new URL(__webpack_public_path__, window.location.origin));
|
2024-02-29 06:20:53 +08:00
|
|
|
const {runModeIsProd} = window.config ?? {};
|
2024-02-23 05:21:43 +08:00
|
|
|
|
2024-04-27 16:03:49 +08:00
|
|
|
// `error` and `reason` are not guaranteed to be errors. If the value is falsy, it is likely a
|
2024-02-29 06:20:53 +08:00
|
|
|
// non-critical event from the browser. We log them but don't show them to users. Examples:
|
|
|
|
// - https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors
|
|
|
|
// - https://github.com/mozilla-mobile/firefox-ios/issues/10817
|
|
|
|
// - https://github.com/go-gitea/gitea/issues/20240
|
|
|
|
if (!err) {
|
|
|
|
if (message) console.error(new Error(message));
|
|
|
|
if (runModeIsProd) return;
|
2023-08-22 10:30:02 +08:00
|
|
|
}
|
2024-02-23 05:21:43 +08:00
|
|
|
|
2024-05-06 00:34:13 +08:00
|
|
|
if (err instanceof Error) {
|
|
|
|
// If the error stack trace does not include the base URL of our script assets, it likely came
|
|
|
|
// from a browser extension or inline script. Do not show such errors in production.
|
|
|
|
if (!err.stack?.includes(assetBaseUrl) && runModeIsProd) return;
|
|
|
|
// Ignore some known errors that are unable to fix
|
|
|
|
if (shouldIgnoreError(err)) return;
|
2022-07-05 20:27:13 +08:00
|
|
|
}
|
2022-10-16 06:04:00 +08:00
|
|
|
|
2024-02-29 06:20:53 +08:00
|
|
|
let msg = err?.message ?? message;
|
|
|
|
if (lineno) msg += ` (${filename} @ ${lineno}:${colno})`;
|
|
|
|
const dot = msg.endsWith('.') ? '' : '.';
|
|
|
|
const renderedType = type === 'unhandledrejection' ? 'promise rejection' : type;
|
|
|
|
showGlobalErrorMessage(`JavaScript ${renderedType}: ${msg}${dot} Open browser console to see more details.`);
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function initGlobalErrorHandler() {
|
2023-08-22 10:30:02 +08:00
|
|
|
if (window._globalHandlerErrors?._inited) {
|
|
|
|
showGlobalErrorMessage(`The global error handler has been initialized, do not initialize it again`);
|
|
|
|
return;
|
|
|
|
}
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
if (!window.config) {
|
|
|
|
showGlobalErrorMessage(`Gitea JavaScript code couldn't run correctly, please check your custom templates`);
|
|
|
|
}
|
2024-02-29 06:20:53 +08:00
|
|
|
// we added an event handler for window error at the very beginning of <script> of page head the
|
|
|
|
// handler calls `_globalHandlerErrors.push` (array method) to record all errors occur before
|
|
|
|
// this init then in this init, we can collect all error events and show them.
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
for (const e of window._globalHandlerErrors || []) {
|
|
|
|
processWindowErrorEvent(e);
|
|
|
|
}
|
2024-02-29 06:20:53 +08:00
|
|
|
// then, change _globalHandlerErrors to an object with push method, to process further error
|
|
|
|
// events directly
|
2024-07-26 07:31:24 +08:00
|
|
|
// @ts-expect-error -- this should be refactored to not use a fake array
|
|
|
|
window._globalHandlerErrors = {_inited: true, push: (e: ErrorEvent & PromiseRejectionEvent) => processWindowErrorEvent(e)};
|
Show messages for users if the ROOT_URL is wrong, show JavaScript errors (#18971)
* ROOT_URL issues: some users did wrong to there app.ini config, then:
* The assets can not be loaded (AppSubUrl != "" and users try to access http://host:3000/)
*The ROOT_URL is wrong, then many URLs in Gitea are broken.
Now Gitea show enough information to users.
* JavaScript error issues, there are many users affected by JavaScript errors, some are caused by frontend bugs, some are caused by broken customized templates. If these JS errors can be found at first time, then maintainers do not need to ask about how bug occurs again and again.
* Some people like to modify the `head.tmpl`, so we separate the script part to `head_script.tmpl`, then it's much safer.
* use specialized CSS class "js-global-error", end users still have a chance to hide error messages by customized CSS styles.
2022-03-30 13:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
initGlobalErrorHandler();
|