diff --git a/noname/util/browser.js b/noname/util/browser.js new file mode 100644 index 000000000..e4f01edd7 --- /dev/null +++ b/noname/util/browser.js @@ -0,0 +1,15 @@ +import { ErrorHandler } from './struct/index.js'; + +/** + * @typedef {import('./struct/interface/error-handler').ErrorHandler} ErrorHandler + */ + +/** + * @type {Record<"firefox" | "chrome" | "safari" | "other", new () => ErrorHandler>} + */ +export const errorHandlerMap = { + 'chrome': ErrorHandler.ChromeErrorHandler, + 'firefox': ErrorHandler.FirefoxErrorHandler, + 'safari': ErrorHandler.UnknownErrorHandler, + 'other': ErrorHandler.UnknownErrorHandler +}; diff --git a/noname/util/struct/error-handler/chrome.js b/noname/util/struct/error-handler/chrome.js new file mode 100644 index 000000000..f84972caf --- /dev/null +++ b/noname/util/struct/error-handler/chrome.js @@ -0,0 +1,45 @@ + +/** + * @typedef {import('../interface/error-handler').ErrorHandler} ErrorHandler + */ + +/** + * @implements {ErrorHandler} + */ +export class ChromeErrorHandler { + #errorList; + + constructor() { + this.#errorList = []; + } + + onLoad() { + Error.prepareStackTrace = (error, stackTraces) => { + this.#errorList.push([error, stackTraces]); + }; + } + + /** + * + * @param {PromiseRejectionEvent} event + */ + onHandle(event) { + event.promise.catch((error) => { + const result = this.#errorList.find(savedError => savedError[0] === error); + if (result) { + // @ts-ignore + window.onerror( + result[0].message, + result[1][0].getScriptNameOrSourceURL() || void 0, + result[1][0].getLineNumber() || void 0, + result[1][0].getColumnNumber() || void 0, + result[0] + ); + } + }); + } + + onErrorPrepare() { + this.#errorList.length = 0; + } +} diff --git a/noname/util/struct/error-handler/firefox.js b/noname/util/struct/error-handler/firefox.js new file mode 100644 index 000000000..7242d4608 --- /dev/null +++ b/noname/util/struct/error-handler/firefox.js @@ -0,0 +1,32 @@ + +/** + * @typedef {import('../interface/error-handler').ErrorHandler} ErrorHandler + */ + +/** + * @implements {ErrorHandler} + */ +export class FirefoxErrorHandler { + /** + * + * @param {PromiseRejectionEvent} event + */ + onHandle(event) { + event.promise.catch((error) => { + if (typeof error === 'object' && error instanceof Error) { + // Firefox在大环境下默认情况必须要那么多ts-ignore + // @ts-ignore + window.onerror( + error.message, + // @ts-ignore + error.fileName, + // @ts-ignore + error.lineNumber, + // @ts-ignore + error.columnNumber, + error + ); + } + }); + } +} diff --git a/noname/util/struct/error-handler/index.js b/noname/util/struct/error-handler/index.js new file mode 100644 index 000000000..008b99c30 --- /dev/null +++ b/noname/util/struct/error-handler/index.js @@ -0,0 +1,4 @@ + +export { ChromeErrorHandler } from './chrome.js'; +export { FirefoxErrorHandler } from './firefox.js'; +export { UnknownErrorHandler } from './unknown.js'; diff --git a/noname/util/struct/error-handler/unknown.js b/noname/util/struct/error-handler/unknown.js new file mode 100644 index 000000000..58a8a5223 --- /dev/null +++ b/noname/util/struct/error-handler/unknown.js @@ -0,0 +1,23 @@ + +/** + * @typedef {import('../interface/error-handler').ErrorHandler} ErrorHandler + */ + +/** + * @implements {ErrorHandler} + */ +export class UnknownErrorHandler { + /** + * + * @param {PromiseRejectionEvent} event + */ + onHandle(event) { + event.promise.catch((error) => { + if (typeof error === 'object' && error instanceof Error) { + // 非chrome和firefox就自生自灭吧 + // Safari也是,反正没办法解决问题就解决提问的人 + throw error; + } + }); + } +} diff --git a/noname/util/struct/index.js b/noname/util/struct/index.js new file mode 100644 index 000000000..a941314c9 --- /dev/null +++ b/noname/util/struct/index.js @@ -0,0 +1,2 @@ + +export * as ErrorHandler from './error-handler/index.js'; diff --git a/noname/util/struct/interface/error-handler.d.ts b/noname/util/struct/interface/error-handler.d.ts new file mode 100644 index 000000000..83c700e25 --- /dev/null +++ b/noname/util/struct/interface/error-handler.d.ts @@ -0,0 +1,10 @@ + +export interface ErrorHandler { + onLoad?(): void | Promise + + onHandle?(event: PromiseRejectionEvent): void | Promise + + onErrorPrepare?(): void + + onErrorFinish?(): void +} diff --git a/noname/util/struct/interface/index.d.ts b/noname/util/struct/interface/index.d.ts new file mode 100644 index 000000000..c14ee03e9 --- /dev/null +++ b/noname/util/struct/interface/index.d.ts @@ -0,0 +1,2 @@ + +export { ErrorHandler } from './error-handler'