Skip to content

Commit 667c771

Browse files
committed
WIP Browser plugins
1 parent 02853cb commit 667c771

File tree

5 files changed

+70
-21
lines changed

5 files changed

+70
-21
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"lage",
2626
"maxcdn",
2727
"nameof",
28+
"ncaught",
2829
"tsproject",
2930
"webcompat"
3031
],

packages/browser/src/BrowserExceptionlessClient.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,6 @@ export class BrowserExceptionlessClient extends ExceptionlessClient {
5959
}
6060
}
6161

62-
//function processUnhandledException(stackTrace: TraceKit.StackTrace, options?: any): void {
63-
// const builder = ExceptionlessClient.default.createUnhandledException(new Error(stackTrace.message || (options || {}).status || "Script error"), "onerror");
64-
// builder.pluginContextData["@@_TraceKit.StackTrace"] = stackTrace;
65-
// builder.submit();
66-
//}
67-
6862
/*
6963
TODO: We currently are unable to parse string exceptions.
7064
function processJQueryAjaxError(event, xhr, settings, error:string): void {
@@ -85,15 +79,10 @@ export class BrowserExceptionlessClient extends ExceptionlessClient {
8579
//TraceKit.report.subscribe(processUnhandledException);
8680
//TraceKit.extendToAsynchronousCallbacks();
8781

88-
// window && window.addEventListener && window.addEventListener("beforeunload", function () {
89-
// ExceptionlessClient.default.config.queue.process(true);
90-
// });
9182

9283
// if (typeof $ !== "undefined" && $(document)) {
9384
// $(document).ajaxError(processJQueryAjaxError);
9485
// }
95-
96-
//(Error as any).stackTraceLimit = Infinity;
9786
//declare var $;
9887

9988
// browser plugin startup method wires up all handlers?
Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,72 @@
11
import {
22
ExceptionlessClient,
33
IEventPlugin,
4-
PluginContext
4+
PluginContext,
5+
nameof
56
} from "@exceptionless/core";
67

78
export class GlobalHandlerPlugin implements IEventPlugin {
89
public priority: number = 100;
910
public name: string = "GlobalHandlerPlugin";
1011

11-
private client: ExceptionlessClient = null;
12+
private _client: ExceptionlessClient = null;
1213

1314
public startup(context: PluginContext): Promise<void> {
14-
if (this.client) {
15+
if (this._client) {
1516
return;
1617
}
1718

18-
this.client = context.client;
19+
this._client = context.client;
1920
Error.stackTraceLimit = Infinity;
2021

2122
// TODO: Discus if we want to unwire this handler in suspend?
2223
const originalOnError: OnErrorEventHandlerNonNull = globalThis.onerror;
23-
globalThis.onerror = (event: Event | string, source?: string, lineno?: number, colno?: number, error?: Error): any => {
24-
/*
25-
const builder = this.client.createUnhandledException(new Error(stackTrace.message || (options || {}).status || "Script error"), "onerror");
26-
builder.pluginContextData["@@_TraceKit.StackTrace"] = stackTrace;
27-
void builder.submit(); // TODO: Handle async?
28-
*/
24+
globalThis.onerror = (event: Event | string, source?: string, lineno?: number, colno?: number, error?: Error) => {
25+
// TODO: Handle async
26+
void this._client.submitUnhandledException(error || this.buildError(event, source, lineno, colno), nameof<Window>("onerror"));
2927

3028
// eslint-disable-next-line prefer-rest-params
3129
return originalOnError ? originalOnError.apply(this, ...arguments) : false;
3230
};
3331

32+
const originalOnunhandledrejection = globalThis.onunhandledrejection;
33+
globalThis.onunhandledrejection = (pre: PromiseRejectionEvent) => {
34+
let error = pre.reason;
35+
try {
36+
const reason = (<any>pre).detail?.reason;
37+
if (reason) {
38+
error = reason;
39+
}
40+
// eslint-disable-next-line no-empty
41+
} catch (ex) { }
42+
43+
// TODO: Handle async
44+
void this._client.submitUnhandledException(error, nameof<Window>("onunhandledrejection"));
45+
46+
// eslint-disable-next-line prefer-rest-params
47+
return originalOnunhandledrejection ? originalOnunhandledrejection.apply(this, ...arguments) : false;
48+
};
49+
3450
return Promise.resolve();
3551
}
52+
53+
private buildError(event: Event | string, source?: string, lineno?: number, colno?: number): Error {
54+
let name: string = "Error";
55+
let message: string = Object.prototype.toString.call(event) === '[object ErrorEvent]' ? (<ErrorEvent>event).message : null;
56+
if (message) {
57+
const errorNameRegex: RegExp = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Aggregate|Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$)/i;
58+
const [_, errorName, errorMessage] = errorNameRegex.exec(message);
59+
if (errorName) {
60+
name = errorName;
61+
}
62+
if (errorMessage) {
63+
message = errorMessage;
64+
}
65+
}
66+
67+
const error = new Error(message || "Script error");
68+
error.name = name;
69+
error.stack = `at ${source || ""}:${!isNaN(lineno) ? lineno : 0}${!isNaN(colno) ? ":" + colno : ""}`;
70+
return error;
71+
}
3672
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {
2+
ExceptionlessClient,
3+
IEventPlugin,
4+
PluginContext
5+
} from "@exceptionless/core";
6+
7+
export class LifeCyclePlugin implements IEventPlugin {
8+
public priority: number = 100;
9+
public name: string = "LifeCyclePlugin";
10+
11+
private _client: ExceptionlessClient = null;
12+
13+
public startup(context: PluginContext): Promise<void> {
14+
if (this._client) {
15+
return;
16+
}
17+
18+
this._client = context.client;
19+
globalThis.addEventListener("beforeunload", async () => await this._client.processQueue());
20+
return Promise.resolve();
21+
}
22+
}

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,5 @@ export {
8282
startsWith,
8383
stringify,
8484
toBoolean,
85+
nameof
8586
} from "./Utils.js";

0 commit comments

Comments
 (0)