@shaper.org/core 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.d.mts +226 -68
- package/dist/client/index.mjs +263 -87
- package/dist/runtime/error-tracker.ts +133 -73
- package/package.json +1 -1
package/dist/client/index.d.mts
CHANGED
|
@@ -1,58 +1,159 @@
|
|
|
1
1
|
import { ErrorPayload, FullReloadPayload, PrunePayload, UpdatePayload } from "vite/types/hmrPayload.js";
|
|
2
2
|
import { ViteHotContext } from "vite/types/hot.js";
|
|
3
3
|
|
|
4
|
-
//#region src/client/
|
|
5
|
-
type
|
|
6
|
-
|
|
4
|
+
//#region src/client/vite-hook.d.ts
|
|
5
|
+
type ViteUpdateCallback = ((data: UpdatePayload, timestamp: number) => void) | null;
|
|
6
|
+
type VitePruneCallback = ((data: PrunePayload, timestamp: number) => void) | null;
|
|
7
|
+
type VitFullReloadCallback = ((data: FullReloadPayload, timestamp: number) => void) | null;
|
|
8
|
+
type ViteErrorCallback = ((data: ErrorPayload, timestamp: number) => void) | null;
|
|
9
|
+
type ViteInvalidateCallback = ((data: any, timestamp: number) => void) | null;
|
|
10
|
+
type ViteWebSocketConnectCallback = ((data: any, timestamp: number) => void) | null;
|
|
11
|
+
type ViteWebSocketDisconnectCallback = ((data: any, timestamp: number) => void) | null;
|
|
12
|
+
declare class ViteHook {
|
|
13
|
+
private hmr;
|
|
14
|
+
constructor();
|
|
15
|
+
hotExists(hmr: ViteHotContext | undefined): hmr is ViteHotContext;
|
|
16
|
+
onBeforeUpdate(fn?: ViteUpdateCallback): void;
|
|
17
|
+
onAfterUpdate(fn?: ViteUpdateCallback): void;
|
|
18
|
+
onBeforePrune(fn?: VitePruneCallback): void;
|
|
19
|
+
onBeforeFullReload(fn?: VitFullReloadCallback): void;
|
|
20
|
+
onError(fn?: ViteErrorCallback): void;
|
|
21
|
+
onInvalidate(fn?: ViteInvalidateCallback): void;
|
|
22
|
+
onWsConnect(fn?: ViteWebSocketConnectCallback): void;
|
|
23
|
+
onWsDisconnect(fn?: ViteWebSocketDisconnectCallback): void;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/client/types/base.d.ts
|
|
27
|
+
interface BasePostMessage {
|
|
7
28
|
message: any;
|
|
8
|
-
type:
|
|
29
|
+
type: string;
|
|
9
30
|
object: "shaper-post-message";
|
|
10
31
|
}
|
|
11
|
-
interface
|
|
12
|
-
name: string;
|
|
13
|
-
path: string;
|
|
14
|
-
file: string;
|
|
15
|
-
}
|
|
16
|
-
interface ServerReadyMessage extends PostMessage {
|
|
32
|
+
interface ServerReadyMessage extends BasePostMessage {
|
|
17
33
|
type: "server-ready";
|
|
18
34
|
message: {
|
|
19
35
|
satus: "ok";
|
|
20
36
|
};
|
|
21
37
|
}
|
|
22
|
-
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/client/types/inspector.d.ts
|
|
40
|
+
interface SelectedNode {
|
|
41
|
+
file: string;
|
|
42
|
+
line: number;
|
|
43
|
+
column: number;
|
|
44
|
+
attributes: Record<string, string>;
|
|
45
|
+
}
|
|
46
|
+
interface InspectorSelectedNodeMessage extends BasePostMessage {
|
|
47
|
+
type: "inspector-selected-node";
|
|
48
|
+
message: SelectedNode;
|
|
49
|
+
}
|
|
50
|
+
interface InspectorNode {
|
|
51
|
+
id: string;
|
|
52
|
+
tag: string;
|
|
53
|
+
children: InspectorNode[];
|
|
54
|
+
}
|
|
55
|
+
interface InspectorTreeUpdateMessage extends BasePostMessage {
|
|
56
|
+
type: "inspector-tree-update";
|
|
57
|
+
message: {
|
|
58
|
+
tree: InspectorNode;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/client/types/network.d.ts
|
|
63
|
+
interface NetworkRequest {
|
|
64
|
+
url: string;
|
|
65
|
+
method: string;
|
|
66
|
+
status: number;
|
|
67
|
+
statusText: string;
|
|
68
|
+
requestBody: string | undefined;
|
|
69
|
+
timestamp: string;
|
|
70
|
+
origin: string;
|
|
71
|
+
headers: Record<string, string>;
|
|
72
|
+
responseBody: string | undefined;
|
|
73
|
+
duration: number;
|
|
74
|
+
}
|
|
75
|
+
interface NetworkRequestMessage extends BasePostMessage {
|
|
76
|
+
message: NetworkRequest;
|
|
77
|
+
type: "network-request";
|
|
78
|
+
}
|
|
79
|
+
interface NetworkRequestChunkMessage extends BasePostMessage {
|
|
80
|
+
message: NetworkRequest;
|
|
81
|
+
type: "network-request-chunk";
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/client/types/route-event.d.ts
|
|
85
|
+
interface RouteInfo {
|
|
86
|
+
name: string;
|
|
87
|
+
path: string;
|
|
88
|
+
file: string;
|
|
89
|
+
}
|
|
90
|
+
interface AllRoutesMessage extends BasePostMessage {
|
|
23
91
|
type: "all-routes";
|
|
24
92
|
message: {
|
|
25
93
|
routes: RouteInfo[];
|
|
26
94
|
};
|
|
27
95
|
}
|
|
28
|
-
interface RouteChangeMessage extends
|
|
96
|
+
interface RouteChangeMessage extends BasePostMessage {
|
|
29
97
|
type: "route-change";
|
|
30
98
|
message: RouteInfo;
|
|
31
99
|
}
|
|
32
|
-
interface RouteRefreshMessage extends
|
|
100
|
+
interface RouteRefreshMessage extends BasePostMessage {
|
|
33
101
|
type: "route-refresh";
|
|
34
102
|
message: RouteInfo;
|
|
35
103
|
}
|
|
36
|
-
|
|
37
|
-
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/client/types/runtime.d.ts
|
|
106
|
+
interface ConsoleLog {
|
|
107
|
+
level: "log" | "warn" | "error";
|
|
108
|
+
message: string;
|
|
109
|
+
fingerprint: string;
|
|
38
110
|
timestamp: number;
|
|
39
|
-
|
|
40
|
-
|
|
111
|
+
type: "CONSOLE";
|
|
112
|
+
}
|
|
113
|
+
interface ConsoleMessage extends BasePostMessage {
|
|
114
|
+
message: ConsoleLog;
|
|
115
|
+
type: "console";
|
|
116
|
+
}
|
|
117
|
+
interface UnhandledRejection {
|
|
118
|
+
message: string;
|
|
41
119
|
stack: string;
|
|
42
|
-
|
|
43
|
-
|
|
120
|
+
readyState: string;
|
|
121
|
+
userAgent: string;
|
|
122
|
+
rootPresent: boolean;
|
|
123
|
+
hasBlankScreen: boolean;
|
|
124
|
+
scripts: string[];
|
|
125
|
+
fingerprint: string;
|
|
126
|
+
timestamp: number;
|
|
127
|
+
type: "UNHANDLED_REJECTION";
|
|
44
128
|
}
|
|
45
|
-
interface
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
column: number;
|
|
49
|
-
attributes: Record<string, string>;
|
|
129
|
+
interface UnhandledRejectionMessage extends BasePostMessage {
|
|
130
|
+
message: UnhandledRejection;
|
|
131
|
+
type: "unhandled-rejection";
|
|
50
132
|
}
|
|
51
|
-
interface
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
133
|
+
interface RuntimeError {
|
|
134
|
+
message: string;
|
|
135
|
+
lineno: number;
|
|
136
|
+
colno: number;
|
|
137
|
+
filename: string | undefined;
|
|
138
|
+
stack: string;
|
|
139
|
+
readyState: DocumentReadyState;
|
|
140
|
+
userAgent: string;
|
|
141
|
+
rootPresent: boolean;
|
|
142
|
+
scripts: string[];
|
|
143
|
+
hasBlankScreen: boolean;
|
|
144
|
+
fingerprint: string;
|
|
145
|
+
timestamp: number;
|
|
146
|
+
type: "RUNTIME_ERROR";
|
|
55
147
|
}
|
|
148
|
+
interface RuntimeErrorMessage extends BasePostMessage {
|
|
149
|
+
message: RuntimeError;
|
|
150
|
+
type: "runtime-error";
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/client/types/message.d.ts
|
|
154
|
+
type PostMessage = ConsoleMessage | UnhandledRejectionMessage | RuntimeErrorMessage | AllRoutesMessage | RouteRefreshMessage | RouteChangeMessage | ServerReadyMessage | InspectorSelectedNodeMessage | InspectorTreeUpdateMessage | NetworkRequestMessage | NetworkRequestChunkMessage;
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/client/iframe-post-message.d.ts
|
|
56
157
|
declare class IframePostMessageClient {
|
|
57
158
|
authHost: string;
|
|
58
159
|
private receiveCallbacks;
|
|
@@ -68,8 +169,10 @@ declare class IframePostMessageClient {
|
|
|
68
169
|
sendAllRoutes(routes: RouteInfo[]): void;
|
|
69
170
|
sendRouteChange(route: RouteInfo): void;
|
|
70
171
|
sendRouteRefresh(route: RouteInfo): void;
|
|
71
|
-
|
|
72
|
-
|
|
172
|
+
sendRuntimeError(runtimeError: RuntimeError): void;
|
|
173
|
+
sendUnhandledRejection(error: UnhandledRejection): void;
|
|
174
|
+
sendConsoleMessage(consoleMessage: ConsoleLog): void;
|
|
175
|
+
sendNetworkRequest(request: NetworkRequest): void;
|
|
73
176
|
sendSelectedNode(node: SelectedNode): void;
|
|
74
177
|
sendTree(tree: InspectorNode): void;
|
|
75
178
|
}
|
|
@@ -86,59 +189,114 @@ interface WorkspaceModeMessage extends ReceiveBaseMessage {
|
|
|
86
189
|
};
|
|
87
190
|
}
|
|
88
191
|
declare const isWorkspaceModeEvent: (event: MessageEvent<any>) => event is MessageEvent<WorkspaceModeMessage>;
|
|
89
|
-
interface
|
|
90
|
-
type: "
|
|
192
|
+
interface SetSelectNodeMessage extends ReceiveBaseMessage {
|
|
193
|
+
type: "SET_SELECT_NODE";
|
|
194
|
+
data: {
|
|
195
|
+
id: string;
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
declare const isSetSelectNodeEvent: (event: MessageEvent<any>) => event is MessageEvent<SetSelectNodeMessage>;
|
|
199
|
+
interface SetHoverNodeMessage extends ReceiveBaseMessage {
|
|
200
|
+
type: "SET_HOVER_NODE";
|
|
91
201
|
data: {
|
|
92
202
|
id: string;
|
|
93
|
-
property: string;
|
|
94
|
-
value: string;
|
|
95
203
|
};
|
|
96
204
|
}
|
|
97
|
-
declare const
|
|
98
|
-
interface
|
|
99
|
-
type: "
|
|
205
|
+
declare const isSetHoverNodeEvent: (event: MessageEvent<any>) => event is MessageEvent<SetSelectNodeMessage>;
|
|
206
|
+
interface UpdatePropsEvent {
|
|
207
|
+
type: "update_props";
|
|
100
208
|
data: {
|
|
101
|
-
|
|
209
|
+
id: string;
|
|
102
210
|
property: string;
|
|
103
211
|
value: string;
|
|
104
|
-
}
|
|
212
|
+
};
|
|
105
213
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
type: "SET_SELECT_NODE";
|
|
214
|
+
interface AddFontEvent {
|
|
215
|
+
type: "add_font";
|
|
109
216
|
data: {
|
|
110
217
|
id: string;
|
|
218
|
+
url: string;
|
|
111
219
|
};
|
|
112
220
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
type: "SET_HOVER_NODE";
|
|
221
|
+
interface SetTextContentEvent {
|
|
222
|
+
type: "set_text_content";
|
|
116
223
|
data: {
|
|
117
224
|
id: string;
|
|
225
|
+
content: string;
|
|
118
226
|
};
|
|
119
227
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
type ViteErrorCallback = ((data: ErrorPayload, timestamp: number) => void) | null;
|
|
127
|
-
type ViteInvalidateCallback = ((data: any, timestamp: number) => void) | null;
|
|
128
|
-
type ViteWebSocketConnectCallback = ((data: any, timestamp: number) => void) | null;
|
|
129
|
-
type ViteWebSocketDisconnectCallback = ((data: any, timestamp: number) => void) | null;
|
|
130
|
-
declare class ViteHook {
|
|
131
|
-
private hmr;
|
|
132
|
-
constructor();
|
|
133
|
-
hotExists(hmr: ViteHotContext | undefined): hmr is ViteHotContext;
|
|
134
|
-
onBeforeUpdate(fn?: ViteUpdateCallback): void;
|
|
135
|
-
onAfterUpdate(fn?: ViteUpdateCallback): void;
|
|
136
|
-
onBeforePrune(fn?: VitePruneCallback): void;
|
|
137
|
-
onBeforeFullReload(fn?: VitFullReloadCallback): void;
|
|
138
|
-
onError(fn?: ViteErrorCallback): void;
|
|
139
|
-
onInvalidate(fn?: ViteInvalidateCallback): void;
|
|
140
|
-
onWsConnect(fn?: ViteWebSocketConnectCallback): void;
|
|
141
|
-
onWsDisconnect(fn?: ViteWebSocketDisconnectCallback): void;
|
|
228
|
+
type PatchEvent = UpdatePropsEvent | AddFontEvent | SetTextContentEvent;
|
|
229
|
+
interface UpdateBatchMessage extends ReceiveBaseMessage {
|
|
230
|
+
type: "UPDATE_BATCH";
|
|
231
|
+
data: {
|
|
232
|
+
events: PatchEvent[];
|
|
233
|
+
};
|
|
142
234
|
}
|
|
235
|
+
declare const isUpdateBatchEvent: (event: MessageEvent<any>) => event is MessageEvent<UpdateBatchMessage>;
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/client/error-parser.d.ts
|
|
238
|
+
declare function serialize(value: unknown, depth?: number, maxDepth?: number, seen?: WeakSet<any>): any;
|
|
239
|
+
declare function hasMatchingStackFrame(error: unknown): boolean;
|
|
240
|
+
declare function formatReason(response: Response): string;
|
|
241
|
+
declare function extractResourceError(event: Event): {
|
|
242
|
+
message: string;
|
|
243
|
+
lineno: number;
|
|
244
|
+
colno: number;
|
|
245
|
+
filename: string;
|
|
246
|
+
stack: string;
|
|
247
|
+
readyState: DocumentReadyState;
|
|
248
|
+
userAgent: string;
|
|
249
|
+
rootPresent: boolean;
|
|
250
|
+
scripts: string[];
|
|
251
|
+
} | null;
|
|
252
|
+
declare function getRuntimeFingerprint(errorEvent: ErrorEvent): string;
|
|
253
|
+
declare function parseError({
|
|
254
|
+
message,
|
|
255
|
+
lineno,
|
|
256
|
+
colno,
|
|
257
|
+
filename,
|
|
258
|
+
error
|
|
259
|
+
}: {
|
|
260
|
+
message: string;
|
|
261
|
+
lineno: number;
|
|
262
|
+
colno: number;
|
|
263
|
+
filename?: string;
|
|
264
|
+
error?: any;
|
|
265
|
+
}): {
|
|
266
|
+
message: string;
|
|
267
|
+
lineno: number;
|
|
268
|
+
colno: number;
|
|
269
|
+
filename: string | undefined;
|
|
270
|
+
stack: any;
|
|
271
|
+
readyState: DocumentReadyState;
|
|
272
|
+
userAgent: string;
|
|
273
|
+
rootPresent: boolean;
|
|
274
|
+
scripts: string[];
|
|
275
|
+
};
|
|
276
|
+
declare function parseViteError({
|
|
277
|
+
message,
|
|
278
|
+
lineno,
|
|
279
|
+
colno,
|
|
280
|
+
filename,
|
|
281
|
+
stack,
|
|
282
|
+
frame
|
|
283
|
+
}: {
|
|
284
|
+
message: string;
|
|
285
|
+
lineno?: number;
|
|
286
|
+
colno?: number;
|
|
287
|
+
filename?: string;
|
|
288
|
+
stack: any;
|
|
289
|
+
frame?: string;
|
|
290
|
+
}): {
|
|
291
|
+
message: string;
|
|
292
|
+
lineno: number;
|
|
293
|
+
colno: number;
|
|
294
|
+
filename: string | undefined;
|
|
295
|
+
stack: any;
|
|
296
|
+
readyState: DocumentReadyState;
|
|
297
|
+
userAgent: string;
|
|
298
|
+
rootPresent: boolean;
|
|
299
|
+
scripts: string[];
|
|
300
|
+
};
|
|
143
301
|
//#endregion
|
|
144
|
-
export { AllRoutesMessage, IframePostMessageClient, InspectorNode,
|
|
302
|
+
export { AddFontEvent, AllRoutesMessage, BasePostMessage, ConsoleLog, ConsoleMessage, IframePostMessageClient, InspectorNode, InspectorSelectedNodeMessage, InspectorTreeUpdateMessage, NetworkRequest, NetworkRequestChunkMessage, NetworkRequestMessage, PatchEvent, PostMessage, ReceiveBaseMessage, RouteChangeMessage, RouteInfo, RouteRefreshMessage, RuntimeError, RuntimeErrorMessage, SelectedNode, ServerReadyMessage, SetHoverNodeMessage, SetSelectNodeMessage, SetTextContentEvent, UnhandledRejection, UnhandledRejectionMessage, UpdateBatchMessage, UpdatePropsEvent, ViteHook, WorkspaceModeMessage, extractResourceError, formatReason, getRuntimeFingerprint, hasMatchingStackFrame, isSetHoverNodeEvent, isSetSelectNodeEvent, isUpdateBatchEvent, isWorkspaceModeEvent, parseError, parseViteError, serialize };
|
package/dist/client/index.mjs
CHANGED
|
@@ -1,3 +1,81 @@
|
|
|
1
|
+
//#region src/client/vite-hook.ts
|
|
2
|
+
var ViteHook = class {
|
|
3
|
+
hmr;
|
|
4
|
+
constructor() {
|
|
5
|
+
this.hmr = import.meta.hot;
|
|
6
|
+
}
|
|
7
|
+
hotExists(hmr) {
|
|
8
|
+
if (hmr) return true;
|
|
9
|
+
console.error("HotContext does not exists");
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
onBeforeUpdate(fn = null) {
|
|
13
|
+
if (!this.hotExists(this.hmr)) return;
|
|
14
|
+
this.hmr.on("vite:beforeUpdate", (data) => {
|
|
15
|
+
const timestamp = Date.now();
|
|
16
|
+
console.debug("beforeUpdate");
|
|
17
|
+
fn && fn(data, timestamp);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
onAfterUpdate(fn = null) {
|
|
21
|
+
if (!this.hotExists(this.hmr)) return;
|
|
22
|
+
this.hmr.on("vite:afterUpdate", (data) => {
|
|
23
|
+
const timestamp = Date.now();
|
|
24
|
+
console.debug("afterUpdate");
|
|
25
|
+
fn && fn(data, timestamp);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
onBeforePrune(fn = null) {
|
|
29
|
+
if (!this.hotExists(this.hmr)) return;
|
|
30
|
+
this.hmr.on("vite:beforePrune", (data) => {
|
|
31
|
+
const timestamp = Date.now();
|
|
32
|
+
console.debug("beforePrune");
|
|
33
|
+
fn && fn(data, timestamp);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
onBeforeFullReload(fn = null) {
|
|
37
|
+
if (!this.hotExists(this.hmr)) return;
|
|
38
|
+
this.hmr.on("vite:beforeFullReload", (data) => {
|
|
39
|
+
const timestamp = Date.now();
|
|
40
|
+
console.debug("beforeFullReload");
|
|
41
|
+
fn && fn(data, timestamp);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
onError(fn = null) {
|
|
45
|
+
if (!this.hotExists(this.hmr)) return;
|
|
46
|
+
this.hmr.on("vite:error", (data) => {
|
|
47
|
+
const timestamp = Date.now();
|
|
48
|
+
console.debug("error");
|
|
49
|
+
fn && fn(data, timestamp);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
onInvalidate(fn = null) {
|
|
53
|
+
if (!this.hotExists(this.hmr)) return;
|
|
54
|
+
this.hmr.on("vite:invalidate", (data) => {
|
|
55
|
+
const timestamp = Date.now();
|
|
56
|
+
console.debug("invalidate");
|
|
57
|
+
fn && fn(data, timestamp);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
onWsConnect(fn = null) {
|
|
61
|
+
if (!this.hotExists(this.hmr)) return;
|
|
62
|
+
this.hmr.on("vite:ws:connect", (data) => {
|
|
63
|
+
const timestamp = Date.now();
|
|
64
|
+
console.debug("ws:connect");
|
|
65
|
+
fn && fn(data, timestamp);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
onWsDisconnect(fn = null) {
|
|
69
|
+
if (!this.hotExists(this.hmr)) return;
|
|
70
|
+
this.hmr.on("vite:ws:disconnect", (data) => {
|
|
71
|
+
const timestamp = Date.now();
|
|
72
|
+
console.debug(":ws:disconnect");
|
|
73
|
+
fn && fn(data, timestamp);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
1
79
|
//#region src/client/iframe-post-message.ts
|
|
2
80
|
var IframePostMessageClient = class {
|
|
3
81
|
authHost;
|
|
@@ -14,7 +92,20 @@ var IframePostMessageClient = class {
|
|
|
14
92
|
if (!route.file.startsWith("src")) throw Error(`Invalid route file, route file should be relative to the root got: ${route.file}`);
|
|
15
93
|
}
|
|
16
94
|
_send(message) {
|
|
17
|
-
window.parent
|
|
95
|
+
if (!window.parent || !message || typeof message !== "object" || !message.object) return;
|
|
96
|
+
if ((() => {
|
|
97
|
+
try {
|
|
98
|
+
const fromAncestor = window.location?.ancestorOrigins?.item?.(0);
|
|
99
|
+
if (fromAncestor) return new URL(fromAncestor).origin;
|
|
100
|
+
} catch {}
|
|
101
|
+
try {
|
|
102
|
+
if (document.referrer) return new URL(document.referrer).origin;
|
|
103
|
+
} catch {}
|
|
104
|
+
return null;
|
|
105
|
+
})() !== this.authHost) return;
|
|
106
|
+
try {
|
|
107
|
+
window.parent.postMessage(message, this.authHost);
|
|
108
|
+
} catch {}
|
|
18
109
|
}
|
|
19
110
|
/**
|
|
20
111
|
* Allow consumers to register callbacks for incoming messages.
|
|
@@ -47,12 +138,14 @@ var IframePostMessageClient = class {
|
|
|
47
138
|
this._send(message);
|
|
48
139
|
}
|
|
49
140
|
sendRouteChange(route) {
|
|
141
|
+
console.log("routechange client", route);
|
|
50
142
|
this._ensure_route_file(route);
|
|
51
143
|
const message = {
|
|
52
144
|
type: "route-change",
|
|
53
145
|
message: { ...route },
|
|
54
146
|
object: "shaper-post-message"
|
|
55
147
|
};
|
|
148
|
+
console.log("routechange client message", message);
|
|
56
149
|
this._send(message);
|
|
57
150
|
}
|
|
58
151
|
sendRouteRefresh(route) {
|
|
@@ -64,15 +157,38 @@ var IframePostMessageClient = class {
|
|
|
64
157
|
};
|
|
65
158
|
this._send(message);
|
|
66
159
|
}
|
|
67
|
-
|
|
160
|
+
sendRuntimeError(runtimeError) {
|
|
161
|
+
const message = {
|
|
162
|
+
type: "runtime-error",
|
|
163
|
+
message: runtimeError,
|
|
164
|
+
object: "shaper-post-message"
|
|
165
|
+
};
|
|
166
|
+
this._send(message);
|
|
167
|
+
}
|
|
168
|
+
sendUnhandledRejection(error) {
|
|
169
|
+
const message = {
|
|
170
|
+
type: "unhandled-rejection",
|
|
171
|
+
message: error,
|
|
172
|
+
object: "shaper-post-message"
|
|
173
|
+
};
|
|
174
|
+
this._send(message);
|
|
175
|
+
}
|
|
176
|
+
sendConsoleMessage(consoleMessage) {
|
|
68
177
|
const message = {
|
|
69
|
-
type: "
|
|
70
|
-
message:
|
|
178
|
+
type: "console",
|
|
179
|
+
message: consoleMessage,
|
|
180
|
+
object: "shaper-post-message"
|
|
181
|
+
};
|
|
182
|
+
this._send(message);
|
|
183
|
+
}
|
|
184
|
+
sendNetworkRequest(request) {
|
|
185
|
+
const message = {
|
|
186
|
+
type: "network-request",
|
|
187
|
+
message: request,
|
|
71
188
|
object: "shaper-post-message"
|
|
72
189
|
};
|
|
73
190
|
this._send(message);
|
|
74
191
|
}
|
|
75
|
-
sendConsole() {}
|
|
76
192
|
sendSelectedNode(node) {
|
|
77
193
|
const message = {
|
|
78
194
|
type: "inspector-selected-node",
|
|
@@ -93,96 +209,156 @@ var IframePostMessageClient = class {
|
|
|
93
209
|
const isWorkspaceModeEvent = (event) => {
|
|
94
210
|
return event.data.type === "WORKSPACE_MODE";
|
|
95
211
|
};
|
|
96
|
-
const isNodeAttributesPatchEvent = (event) => {
|
|
97
|
-
return event.data.type === "NODE_ATTRIBUTES_PATCH";
|
|
98
|
-
};
|
|
99
|
-
const isNodeAttributesPatchBatchEvent = (event) => {
|
|
100
|
-
return event.data.type === "NODE_ATTRIBUTES_PATCH_BATCH";
|
|
101
|
-
};
|
|
102
212
|
const isSetSelectNodeEvent = (event) => {
|
|
103
213
|
return event.data.type === "SET_SELECT_NODE";
|
|
104
214
|
};
|
|
105
215
|
const isSetHoverNodeEvent = (event) => {
|
|
106
216
|
return event.data.type === "SET_HOVER_NODE";
|
|
107
217
|
};
|
|
218
|
+
const isUpdateBatchEvent = (event) => {
|
|
219
|
+
return event.data.type === "UPDATE_BATCH";
|
|
220
|
+
};
|
|
108
221
|
|
|
109
222
|
//#endregion
|
|
110
|
-
//#region src/client/
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
onBeforeFullReload(fn = null) {
|
|
146
|
-
if (!this.hotExists(this.hmr)) return;
|
|
147
|
-
this.hmr.on("vite:beforeFullReload", (data) => {
|
|
148
|
-
const timestamp = Date.now();
|
|
149
|
-
console.debug("beforeFullReload");
|
|
150
|
-
fn && fn(data, timestamp);
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
onError(fn = null) {
|
|
154
|
-
if (!this.hotExists(this.hmr)) return;
|
|
155
|
-
this.hmr.on("vite:error", (data) => {
|
|
156
|
-
const timestamp = Date.now();
|
|
157
|
-
console.debug("error");
|
|
158
|
-
fn && fn(data, timestamp);
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
onInvalidate(fn = null) {
|
|
162
|
-
if (!this.hotExists(this.hmr)) return;
|
|
163
|
-
this.hmr.on("vite:invalidate", (data) => {
|
|
164
|
-
const timestamp = Date.now();
|
|
165
|
-
console.debug("invalidate");
|
|
166
|
-
fn && fn(data, timestamp);
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
onWsConnect(fn = null) {
|
|
170
|
-
if (!this.hotExists(this.hmr)) return;
|
|
171
|
-
this.hmr.on("vite:ws:connect", (data) => {
|
|
172
|
-
const timestamp = Date.now();
|
|
173
|
-
console.debug("ws:connect");
|
|
174
|
-
fn && fn(data, timestamp);
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
onWsDisconnect(fn = null) {
|
|
178
|
-
if (!this.hotExists(this.hmr)) return;
|
|
179
|
-
this.hmr.on("vite:ws:disconnect", (data) => {
|
|
180
|
-
const timestamp = Date.now();
|
|
181
|
-
console.debug(":ws:disconnect");
|
|
182
|
-
fn && fn(data, timestamp);
|
|
183
|
-
});
|
|
223
|
+
//#region src/client/error-parser.ts
|
|
224
|
+
const VITE_DEP_PATH_REGEX = /\/(?:node_modules\/)?\.vite\/deps\//i;
|
|
225
|
+
const DYNAMIC_IMPORT_FAILURE_REGEX = /failed to fetch dynamically imported module|error loading dynamically imported module|failed to load module script|importing a module script failed|expected a javascript-or-wasm module script|failed to load resource|resource load failed|disallowed mime type|net::err_aborted/i;
|
|
226
|
+
const DIRECT_ERROR_FIELDS = [
|
|
227
|
+
"message",
|
|
228
|
+
"stack",
|
|
229
|
+
"filename",
|
|
230
|
+
"url",
|
|
231
|
+
"src",
|
|
232
|
+
"href"
|
|
233
|
+
];
|
|
234
|
+
const NESTED_ERROR_FIELDS = [
|
|
235
|
+
"error",
|
|
236
|
+
"reason",
|
|
237
|
+
"cause"
|
|
238
|
+
];
|
|
239
|
+
function serialize(value, depth = 0, maxDepth = 5, seen = /* @__PURE__ */ new WeakSet()) {
|
|
240
|
+
if (depth > maxDepth) return "[MaxDepthReached]";
|
|
241
|
+
if (value === null || value === void 0) return value;
|
|
242
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
243
|
+
if (typeof value === "bigint") return value.toString();
|
|
244
|
+
if (typeof value === "function") return `[Function ${value.name || "anonymous"}]`;
|
|
245
|
+
if (typeof value === "symbol") return value.toString();
|
|
246
|
+
if (typeof value === "object") {
|
|
247
|
+
if (seen.has(value)) return "[Circular]";
|
|
248
|
+
seen.add(value);
|
|
249
|
+
if (value instanceof Error) return {
|
|
250
|
+
name: value.name,
|
|
251
|
+
message: value.message,
|
|
252
|
+
stack: value.stack
|
|
253
|
+
};
|
|
254
|
+
if (Array.isArray(value)) return value.slice(0, 100).map((v) => serialize(v, depth + 1, maxDepth, seen));
|
|
255
|
+
const out = {};
|
|
256
|
+
for (const k of Object.keys(value).slice(0, 100)) out[k] = serialize(value[k], depth + 1, maxDepth, seen);
|
|
257
|
+
return out;
|
|
184
258
|
}
|
|
185
|
-
|
|
259
|
+
return String(value);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Converts arbitrary values into readable text.
|
|
263
|
+
*/
|
|
264
|
+
function stringifyError(value) {
|
|
265
|
+
if (!value) return "";
|
|
266
|
+
if (typeof value === "string") return value;
|
|
267
|
+
if (Array.isArray(value)) return value.map(stringifyError).join("\n");
|
|
268
|
+
if (value instanceof Error) return [value.message, value.stack].filter(Boolean).join("\n");
|
|
269
|
+
if (typeof value === "object") return Object.values(value).map(stringifyError).join("\n");
|
|
270
|
+
return JSON.stringify(value);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Recursively extracts error-related strings
|
|
274
|
+
* from arbitrary nested structures.
|
|
275
|
+
*/
|
|
276
|
+
function extractStackLines(value) {
|
|
277
|
+
if (!value) return [];
|
|
278
|
+
if (typeof value === "string") return [value];
|
|
279
|
+
if (value instanceof Error) return [stringifyError(value)];
|
|
280
|
+
if (Array.isArray(value)) return value.flatMap(extractStackLines);
|
|
281
|
+
if (typeof value !== "object") return [];
|
|
282
|
+
const object = value;
|
|
283
|
+
const directText = DIRECT_ERROR_FIELDS.map((field) => stringifyError(object[field])).filter(Boolean).join("\n");
|
|
284
|
+
const nestedText = NESTED_ERROR_FIELDS.flatMap((field) => extractStackLines(object[field]));
|
|
285
|
+
return directText ? [directText, ...nestedText] : nestedText;
|
|
286
|
+
}
|
|
287
|
+
function hasMatchingStackFrame(error) {
|
|
288
|
+
return extractStackLines(error).some((line) => {
|
|
289
|
+
const matchesViteChunkPath = VITE_DEP_PATH_REGEX.test(line);
|
|
290
|
+
const matchesDynamicImportFailure = DYNAMIC_IMPORT_FAILURE_REGEX.test(line);
|
|
291
|
+
return matchesViteChunkPath && matchesDynamicImportFailure;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
function formatReason(response) {
|
|
295
|
+
const cleanedUrl = response.url ?? "";
|
|
296
|
+
const statusText = response.statusText && response.statusText.length > 0 ? response.statusText : "(no status text)";
|
|
297
|
+
let message = `Server responded with ${response.status} ${statusText}`;
|
|
298
|
+
if (cleanedUrl) message += ` at ${cleanedUrl}`;
|
|
299
|
+
return message;
|
|
300
|
+
}
|
|
301
|
+
function extractResourceError(event) {
|
|
302
|
+
const target = event.target;
|
|
303
|
+
if (!(target instanceof HTMLElement)) return null;
|
|
304
|
+
let url = "";
|
|
305
|
+
if ("src" in target && typeof target.src === "string") url = target.src;
|
|
306
|
+
else if ("href" in target && typeof target.href === "string") url = target.href;
|
|
307
|
+
if (!url) return null;
|
|
308
|
+
const payload = {
|
|
309
|
+
message: `Failed to load resource: ${url}`,
|
|
310
|
+
lineno: 0,
|
|
311
|
+
colno: 0,
|
|
312
|
+
filename: url,
|
|
313
|
+
stack: `Resource load failed at ${url}`,
|
|
314
|
+
readyState: document.readyState,
|
|
315
|
+
userAgent: navigator.userAgent,
|
|
316
|
+
rootPresent: !!document.getElementById("root"),
|
|
317
|
+
scripts: Array.from(document.scripts || []).slice(0, 25).map((script) => script.src ? script.src : script.textContent?.slice(0, 80) || "inline")
|
|
318
|
+
};
|
|
319
|
+
return hasMatchingStackFrame(payload) ? payload : null;
|
|
320
|
+
}
|
|
321
|
+
function getRuntimeFingerprint(errorEvent) {
|
|
322
|
+
const { lineno, colno, filename, message } = errorEvent;
|
|
323
|
+
return `${message}|${filename}|${lineno}|${colno}`;
|
|
324
|
+
}
|
|
325
|
+
function formatResponseError(response) {
|
|
326
|
+
const url = response.url ?? "";
|
|
327
|
+
const baseMessage = `Server responded with ${response.status} ${response.statusText || "(no status text)"}`;
|
|
328
|
+
return url ? `${baseMessage} at ${url}` : baseMessage;
|
|
329
|
+
}
|
|
330
|
+
function parseError({ message, lineno, colno, filename, error }) {
|
|
331
|
+
const scriptsSnapshot = Array.from(document.scripts || []).slice(0, 25).map((script) => script.src ? script.src : script.textContent?.slice(0, 80) || "inline");
|
|
332
|
+
let finalMessage = message;
|
|
333
|
+
if (error instanceof Response || message.includes("[object Response]") && error && typeof error === "object" && "status" in error) finalMessage = formatResponseError(error);
|
|
334
|
+
return {
|
|
335
|
+
message: finalMessage,
|
|
336
|
+
lineno,
|
|
337
|
+
colno,
|
|
338
|
+
filename: filename ?? void 0,
|
|
339
|
+
stack: error?.stack,
|
|
340
|
+
readyState: document.readyState,
|
|
341
|
+
userAgent: navigator.userAgent,
|
|
342
|
+
rootPresent: !!document.getElementById("root"),
|
|
343
|
+
scripts: scriptsSnapshot
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function parseViteError({ message, lineno, colno, filename, stack, frame }) {
|
|
347
|
+
const scriptsSnapshot = Array.from(document.scripts || []).slice(0, 25).map((script) => script.src ? script.src : script.textContent?.slice(0, 80) || "inline");
|
|
348
|
+
let finalMessage = message;
|
|
349
|
+
if (frame) finalMessage = `${frame}\n${finalMessage}\n`;
|
|
350
|
+
return {
|
|
351
|
+
message: finalMessage,
|
|
352
|
+
lineno: lineno ?? 0,
|
|
353
|
+
colno: colno ?? 0,
|
|
354
|
+
filename: filename ?? void 0,
|
|
355
|
+
stack: stack ?? void 0,
|
|
356
|
+
readyState: document.readyState,
|
|
357
|
+
userAgent: navigator.userAgent,
|
|
358
|
+
rootPresent: !!document.getElementById("root"),
|
|
359
|
+
scripts: scriptsSnapshot
|
|
360
|
+
};
|
|
361
|
+
}
|
|
186
362
|
|
|
187
363
|
//#endregion
|
|
188
|
-
export { IframePostMessageClient, ViteHook,
|
|
364
|
+
export { IframePostMessageClient, ViteHook, extractResourceError, formatReason, getRuntimeFingerprint, hasMatchingStackFrame, isSetHoverNodeEvent, isSetSelectNodeEvent, isUpdateBatchEvent, isWorkspaceModeEvent, parseError, parseViteError, serialize };
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
serialize,
|
|
3
|
+
hasMatchingStackFrame,
|
|
4
|
+
formatReason,
|
|
5
|
+
IframePostMessageClient,
|
|
6
|
+
ViteHook,
|
|
7
|
+
extractResourceError,
|
|
8
|
+
parseError,
|
|
9
|
+
getRuntimeFingerprint,
|
|
10
|
+
parseViteError,
|
|
11
|
+
} from "../client";
|
|
3
12
|
|
|
4
13
|
class ErrorTracker {
|
|
5
14
|
public vHook: ViteHook;
|
|
@@ -23,54 +32,49 @@ class ErrorTracker {
|
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
formatConsoleMessage(args: unknown[]): string {
|
|
26
|
-
let
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
let stack = null;
|
|
36
|
+
const err = new Error();
|
|
37
|
+
if (err.stack) stack = err.stack.split("\n").slice(2).join("\n");
|
|
38
|
+
|
|
39
|
+
const raw = args.map((a) => serialize(a));
|
|
40
|
+
const text = raw
|
|
41
|
+
.map((m) =>
|
|
42
|
+
typeof m === "string"
|
|
43
|
+
? m
|
|
44
|
+
: JSON.stringify(m, null, 2)?.slice(0, 10_000),
|
|
45
|
+
)
|
|
46
|
+
.join(" ");
|
|
47
|
+
|
|
48
|
+
const message = (stack ? `${text}\n${stack}` : text).slice(0, 10_000);
|
|
49
|
+
|
|
50
|
+
return message;
|
|
41
51
|
}
|
|
42
52
|
|
|
43
53
|
handleConsoleInterception() {
|
|
44
|
-
type
|
|
54
|
+
type level = keyof typeof original;
|
|
45
55
|
|
|
46
|
-
const
|
|
56
|
+
const original = {
|
|
47
57
|
log: console.log,
|
|
48
58
|
warn: console.warn,
|
|
49
59
|
error: console.error,
|
|
50
60
|
trace: console.trace,
|
|
51
|
-
// debug: console.debug,
|
|
52
61
|
};
|
|
53
|
-
for (let
|
|
54
|
-
console[
|
|
55
|
-
|
|
56
|
-
...args: unknown[]
|
|
57
|
-
) {
|
|
58
|
-
originalConsole[logLevel].apply(this, args);
|
|
62
|
+
for (let level of Object.keys(original) as level[]) {
|
|
63
|
+
console[level] = (...args: unknown[]) => {
|
|
64
|
+
original[level].apply(console, args);
|
|
59
65
|
|
|
60
66
|
const message = this.formatConsoleMessage(args);
|
|
61
|
-
|
|
62
67
|
if (!message) return;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
if (level === "error" || level === "warn") {
|
|
69
|
+
this.iframeClient.sendConsoleMessage({
|
|
70
|
+
level,
|
|
71
|
+
message,
|
|
72
|
+
fingerprint: `${level}|${message}`,
|
|
68
73
|
timestamp: Date.now(),
|
|
69
|
-
|
|
70
|
-
has_blank_screen: this.isBlankScreen(),
|
|
74
|
+
type: "CONSOLE",
|
|
71
75
|
});
|
|
72
76
|
}
|
|
73
|
-
}
|
|
77
|
+
};
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
|
|
@@ -78,55 +82,111 @@ class ErrorTracker {
|
|
|
78
82
|
this.vHook.onError((data) => {
|
|
79
83
|
console.debug("[vite-shaper] vite:error", data);
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
const message = data.err.message;
|
|
86
|
+
const filename = data.err.loc?.file;
|
|
87
|
+
const lineno = data.err.loc?.line;
|
|
88
|
+
const colno = data.err.loc?.column;
|
|
89
|
+
const stack = data.err.stack;
|
|
90
|
+
const frame = data.err.frame;
|
|
91
|
+
|
|
92
|
+
const dataError = parseViteError({
|
|
93
|
+
message,
|
|
94
|
+
filename,
|
|
95
|
+
lineno,
|
|
96
|
+
colno,
|
|
97
|
+
stack,
|
|
98
|
+
frame,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
this.iframeClient.sendRuntimeError({
|
|
102
|
+
...dataError,
|
|
103
|
+
hasBlankScreen: this.isBlankScreen(),
|
|
104
|
+
fingerprint: `${dataError.message}|${dataError.filename}|${dataError.lineno}|${dataError.colno}`,
|
|
105
|
+
type: "RUNTIME_ERROR",
|
|
83
106
|
timestamp: Date.now(),
|
|
84
|
-
|
|
85
|
-
has_blank_screen: this.isBlankScreen(),
|
|
86
|
-
};
|
|
87
|
-
if (data.err.loc) {
|
|
88
|
-
error = {
|
|
89
|
-
...error,
|
|
90
|
-
lineno: data.err.loc.line,
|
|
91
|
-
colno: data.err.loc.column,
|
|
92
|
-
filename: data.err.loc.file,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
this.iframeClient.sendError(error);
|
|
107
|
+
});
|
|
96
108
|
});
|
|
97
109
|
}
|
|
98
110
|
|
|
99
111
|
handleUnhandledrejection() {
|
|
100
|
-
window.addEventListener("unhandledrejection", (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
113
|
+
const reason = event.reason;
|
|
114
|
+
|
|
115
|
+
const isResponseError = reason instanceof Response;
|
|
116
|
+
const shouldIgnore = hasMatchingStackFrame(reason);
|
|
117
|
+
|
|
118
|
+
if (!isResponseError && !reason?.stack && !shouldIgnore) return;
|
|
119
|
+
|
|
120
|
+
const fingerprint = isResponseError
|
|
121
|
+
? `Response|${reason.status}|${reason.url}`
|
|
122
|
+
: reason?.stack || reason?.message || String(reason);
|
|
123
|
+
|
|
124
|
+
const message = isResponseError
|
|
125
|
+
? formatReason(reason)
|
|
126
|
+
: reason?.message ||
|
|
127
|
+
String(reason || "Unhandled promise rejection");
|
|
128
|
+
|
|
129
|
+
const stack = isResponseError
|
|
130
|
+
? `Response ${reason.status} at ${reason.url ?? "(unknown)"}`
|
|
131
|
+
: reason?.stack || String(reason);
|
|
132
|
+
|
|
133
|
+
const scripts = Array.from(document.scripts || [])
|
|
134
|
+
.slice(0, 25)
|
|
135
|
+
.map((script) => {
|
|
136
|
+
if (script.src) return script.src;
|
|
137
|
+
return script.textContent?.slice(0, 80) || "inline";
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
this.iframeClient.sendUnhandledRejection({
|
|
141
|
+
message,
|
|
142
|
+
stack,
|
|
143
|
+
readyState: document.readyState,
|
|
144
|
+
userAgent: navigator.userAgent,
|
|
145
|
+
rootPresent: !!document.getElementById("root"),
|
|
146
|
+
hasBlankScreen: this.isBlankScreen(),
|
|
147
|
+
scripts,
|
|
148
|
+
fingerprint,
|
|
104
149
|
timestamp: Date.now(),
|
|
105
|
-
|
|
106
|
-
has_blank_screen: this.isBlankScreen(),
|
|
150
|
+
type: "UNHANDLED_REJECTION",
|
|
107
151
|
});
|
|
108
152
|
});
|
|
109
153
|
}
|
|
110
154
|
|
|
111
155
|
handleError() {
|
|
112
|
-
window.addEventListener(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
156
|
+
window.addEventListener(
|
|
157
|
+
"error",
|
|
158
|
+
(event) => {
|
|
159
|
+
if (!(event instanceof ErrorEvent)) {
|
|
160
|
+
const resourceError = extractResourceError(event);
|
|
161
|
+
|
|
162
|
+
if (!resourceError) return;
|
|
163
|
+
|
|
164
|
+
const fingerprint = `resource|${resourceError.filename}`;
|
|
165
|
+
|
|
166
|
+
this.iframeClient.sendRuntimeError({
|
|
167
|
+
...resourceError,
|
|
168
|
+
hasBlankScreen: this.isBlankScreen(),
|
|
169
|
+
fingerprint,
|
|
170
|
+
timestamp: Date.now(),
|
|
171
|
+
type: "RUNTIME_ERROR",
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const fingerprint = getRuntimeFingerprint(event);
|
|
178
|
+
const errorData = parseError(event);
|
|
179
|
+
|
|
180
|
+
this.iframeClient.sendRuntimeError({
|
|
181
|
+
...errorData,
|
|
182
|
+
hasBlankScreen: this.isBlankScreen(),
|
|
183
|
+
fingerprint,
|
|
184
|
+
timestamp: Date.now(),
|
|
185
|
+
type: "RUNTIME_ERROR",
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
true,
|
|
189
|
+
);
|
|
130
190
|
}
|
|
131
191
|
}
|
|
132
192
|
|