chore: rename to better name && add docs.

This commit is contained in:
Ansolve 2024-01-11 04:19:54 +08:00
parent ea07727f68
commit aa089a9d32
No known key found for this signature in database
GPG Key ID: 2F2873AC9538CC2D
9 changed files with 168 additions and 48 deletions

View File

@ -1,15 +1,19 @@
import { ErrorHandler } from './struct/index.js';
/**
* @typedef {import('./struct/interface/error-handler').ErrorHandler} ErrorHandler
* 从浏览器名到不同浏览器下异步处理方式的映射
*
* `key`的值同`get.coreInfo`函数返回值的第一个元素
*
* @type {Record<"firefox" | "chrome" | "safari" | "other", new () => PromiseErrorHandler>}
*/
export const promiseErrorHandlerMap = {
'chrome': ErrorHandler.ChromePromiseErrorHandler,
'firefox': ErrorHandler.FirefoxPromiseErrorHandler,
'safari': ErrorHandler.UnknownPromiseErrorHandler,
'other': ErrorHandler.UnknownPromiseErrorHandler
};
/**
* @type {Record<"firefox" | "chrome" | "safari" | "other", new () => ErrorHandler>}
* @typedef {import('./struct/interface/promise-error-handler.js').PromiseErrorHandler} PromiseErrorHandler
*/
export const errorHandlerMap = {
'chrome': ErrorHandler.ChromeErrorHandler,
'firefox': ErrorHandler.FirefoxErrorHandler,
'safari': ErrorHandler.UnknownErrorHandler,
'other': ErrorHandler.UnknownErrorHandler
};

View File

@ -1,25 +1,60 @@
/**
* @typedef {import('../interface/error-handler').ErrorHandler} ErrorHandler
* 关于`Google Chrome`的异步错误处理
*
* `Chrome`所用的`v8`引擎为`Error`提供了特有的报错栈堆处理函数用于用户自定义报错栈堆的内容
*
* 我们用到了`Error.prepareStackTrace(error, structuredStackTrace)`这个函数这个函数的信息可参考[这里](https://v8.dev/docs/stack-trace-api#customizing-stack-traces)
*
* 该函数提供了结构化的栈堆信息很幸运的是这个结构化的栈堆能直接告诉我们报错的文件以及位置故我们使用该函数让异步报错能直接定位原始位置
*
* @implements {PromiseErrorHandler}
*/
export class ChromePromiseErrorHandler {
/**
* @implements {ErrorHandler}
*/
export class ChromeErrorHandler {
/**
* 用于临时记录报错信息的列表通过`Error.prepareStackTrace`更新该列表
*
* @type {[Error, NodeJS.CallSite[]][]}
*/
#errorList;
constructor() {
this.#errorList = [];
}
/**
* @type {typeof Error.prepareStackTrace}
*/
#originErrorPrepareStackTrace;
/**
* 初始化`Error.prepareStackTrace`将该值赋值成我们需要的函数
*
* 未防止本来Error.prepareStackTrace便存在赋值的行为我们将原始值存储并在需要的函数中调用
*
* > 这或许就是本体扩展化的第一步小声
*/
onLoad() {
this.#errorList = [];
this.#originErrorPrepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = (error, stackTraces) => {
// 其实这步或许不需要
// 但真赋值了Error.prepareStackTrace的话保不齐会出现需要返回值的情况
const result = this.#originErrorPrepareStackTrace
? this.#originErrorPrepareStackTrace(error, stackTraces)
: void 0;
this.#errorList.push([error, stackTraces]);
return result;
};
}
/**
* 将原来可能的`Error.prepareStackTrace`赋值回去
*/
onUnload() {
Error.prepareStackTrace = this.#originErrorPrepareStackTrace;
}
/**
* 在获取报错的时候我们通过发生报错的`Promise`来进行捕获错误的操作
*
* 如果捕获出来的错误存放我们存报错栈堆的列表中则证明该错误能获取到栈堆由此来获取报错的地址和行列号
*
* @param {PromiseRejectionEvent} event
*/
@ -30,7 +65,7 @@ export class ChromeErrorHandler {
// @ts-ignore
window.onerror(
result[0].message,
result[1][0].getScriptNameOrSourceURL() || void 0,
result[1][0].getScriptNameOrSourceURL(),
result[1][0].getLineNumber() || void 0,
result[1][0].getColumnNumber() || void 0,
result[0]
@ -39,7 +74,14 @@ export class ChromeErrorHandler {
});
}
/**
* 正式报错时便不再需要报错信息了故直接清空列表释放内存
*/
onErrorPrepare() {
this.#errorList.length = 0;
}
}
/**
* @typedef {import('../interface/promise-error-handler').PromiseErrorHandler} PromiseErrorHandler
*/

View File

@ -1,13 +1,17 @@
/**
* @typedef {import('../interface/error-handler').ErrorHandler} ErrorHandler
* 关于`Mozilla Firefox`的异步错误处理
*
* 很幸运Mozilla直接为`Firefox`的报错提供了地址和行列号故我们能直接获取到要获取的信息不用像`v8`那样通过栈堆获取
*
* 虽然但是我们还是需要判断一下捕获的报错是否是错误
*
* @implements {PromiseErrorHandler}
*/
/**
* @implements {ErrorHandler}
*/
export class FirefoxErrorHandler {
export class FirefoxPromiseErrorHandler {
/**
* 在获取报错的时候我们通过发生报错的`Promise`来进行捕获错误的操作
*
* 如果捕获到的错误是`Error`则能直接通过`Firefox`的特性来获取地址和行列号
*
* @param {PromiseRejectionEvent} event
*/
@ -30,3 +34,7 @@ export class FirefoxErrorHandler {
});
}
}
/**
* @typedef {import('../interface/promise-error-handler').PromiseErrorHandler} PromiseErrorHandler
*/

View File

@ -1,4 +1,13 @@
/**
* 关于不同浏览器下对异步错误的处理方式
*
* 目前已实现的浏览器如下
*
* - `Google Chrome`包括`electron``cordova`以及`crosswalk`
* - `Mozilla Firefox`
*
*/
export { ChromeErrorHandler } from './chrome.js';
export { FirefoxErrorHandler } from './firefox.js';
export { UnknownErrorHandler } from './unknown.js';
export { ChromePromiseErrorHandler } from './chrome.js';
export { FirefoxPromiseErrorHandler } from './firefox.js';
export { UnknownPromiseErrorHandler } from './unknown.js';

View File

@ -1,23 +1,31 @@
/**
* @typedef {import('../interface/error-handler').ErrorHandler} ErrorHandler
* 关于除已实现浏览器外其余浏览器的异步错误处理
*
* 很遗憾对于这类浏览器因为标准未涉及报错栈堆或地址及行列号故我们只能直接暴力的throw出我们捕获道德错误
*
* 尽管我们还是会为了这类浏览器判断是不是捕获到了一个`Error`
*
* 总之虽然这里跟Safari无关但我们还是为新时代IE默哀一秒
*
* @implements {PromiseErrorHandler}
*/
/**
* @implements {ErrorHandler}
*/
export class UnknownErrorHandler {
export class UnknownPromiseErrorHandler {
/**
* 在获取报错的时候我们通过发生报错的`Promise`来进行捕获错误的操作
*
* 如果捕获到的错误是`Error`...我们只能暴力的将`Error`再次`throw`出去
*
* @param {PromiseRejectionEvent} event
*/
onHandle(event) {
event.promise.catch((error) => {
if (typeof error === 'object' && error instanceof Error) {
// 非chrome和firefox就自生自灭吧
// Safari也是反正没办法解决问题就解决提问的人
throw error;
}
});
}
}
/**
* @typedef {import('../interface/promise-error-handler').PromiseErrorHandler} PromiseErrorHandler
*/

View File

@ -1,2 +1,5 @@
/**
* 无名杀内部所需要的数据结构
*/
export * as ErrorHandler from './error-handler/index.js';

View File

@ -1,10 +0,0 @@
export interface ErrorHandler {
onLoad?(): void | Promise<void>
onHandle?(event: PromiseRejectionEvent): void | Promise<void>
onErrorPrepare?(): void
onErrorFinish?(): void
}

View File

@ -1,2 +1,5 @@
/**
*
*/
export { ErrorHandler } from './error-handler'
export { PromiseErrorHandler } from './promise-error-handler'

View File

@ -0,0 +1,53 @@
/**
*
*/
export interface PromiseErrorHandler {
/**
*
*
*
*
*
*/
onLoad?(): void | Promise<void>
/**
*
*
*
*
* 使
*
*
*/
onUnload?(): void | Promise<void>
/**
* `unhandledrejection`
*
*
*
*
*
* @param event -
*/
onHandle?(event: PromiseRejectionEvent): void | Promise<void>
/**
* `window.onerror`
*
* `window.onerror`
*
*
*/
onErrorPrepare?(): void
/**
* `window.onerror`****
*
* `window.onerror`
*
*
*/
onErrorFinish?(): void
}