@jsenv/core 28.0.2 → 28.1.2
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/controllable_child_process.mjs +1 -2
- package/dist/controllable_worker_thread.mjs +1 -2
- package/dist/js/autoreload.js +25 -9
- package/dist/js/execute_using_dynamic_import.js +804 -1
- package/dist/js/script_type_module_supervisor.js +122 -0
- package/dist/js/supervisor.js +915 -0
- package/dist/main.js +432 -492
- package/package.json +13 -13
- package/readme.md +1 -1
- package/src/build/inject_global_version_mappings.js +3 -3
- package/src/dev/start_dev_server.js +2 -2
- package/src/execute/execute.js +1 -1
- package/src/execute/run.js +26 -38
- package/src/execute/runtimes/browsers/from_playwright.js +51 -77
- package/src/execute/runtimes/node/node_child_process.js +36 -36
- package/src/execute/runtimes/node/node_worker_thread.js +36 -36
- package/src/omega/kitchen.js +12 -9
- package/src/omega/omega_server.js +2 -2
- package/src/omega/server/file_service.js +2 -2
- package/src/omega/url_graph/url_info_transformations.js +8 -1
- package/src/plugins/autoreload/client/reload.js +20 -7
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +4 -4
- package/src/plugins/import_meta_hot/html_hot_dependencies.js +2 -2
- package/src/plugins/importmap/jsenv_plugin_importmap.js +5 -3
- package/src/plugins/inject_globals/inject_globals.js +3 -3
- package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -1
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +10 -5
- package/src/plugins/plugins.js +5 -5
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +4 -4
- package/src/plugins/supervisor/client/script_type_module_supervisor.js +99 -0
- package/src/plugins/supervisor/client/supervisor.js +915 -0
- package/src/plugins/{html_supervisor/jsenv_plugin_html_supervisor.js → supervisor/jsenv_plugin_supervisor.js} +128 -102
- package/src/plugins/toolbar/client/execution/toolbar_execution.js +1 -1
- package/src/plugins/toolbar/jsenv_plugin_toolbar.js +4 -4
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +7 -5
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +5 -4
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +13 -7
- package/src/plugins/transpilation/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +6 -4
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -2
- package/src/plugins/url_analysis/html/html_urls.js +11 -10
- package/src/test/coverage/babel_plugin_instrument.js +1 -35
- package/src/test/coverage/empty_coverage_factory.js +1 -1
- package/src/test/execute_plan.js +7 -3
- package/src/test/execute_test_plan.js +2 -1
- package/src/test/logs_file_execution.js +49 -8
- package/dist/js/html_supervisor_installer.js +0 -1091
- package/dist/js/html_supervisor_setup.js +0 -89
- package/dist/js/uneval.js +0 -804
- package/src/plugins/html_supervisor/client/error_formatter.js +0 -426
- package/src/plugins/html_supervisor/client/error_in_notification.js +0 -21
- package/src/plugins/html_supervisor/client/error_overlay.js +0 -191
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +0 -315
- package/src/plugins/html_supervisor/client/html_supervisor_setup.js +0 -89
- package/src/plugins/html_supervisor/client/perf_browser.js +0 -17
- package/src/plugins/html_supervisor/client/uneval_exception.js +0 -8
|
@@ -1,1091 +0,0 @@
|
|
|
1
|
-
import { u as uneval } from "./uneval.js";
|
|
2
|
-
|
|
3
|
-
const unevalException = value => {
|
|
4
|
-
if (value && value.hasOwnProperty("toString")) {
|
|
5
|
-
delete value.toString;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return uneval(value, {
|
|
9
|
-
ignoreSymbols: true
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const formatError = (error, {
|
|
14
|
-
rootDirectoryUrl,
|
|
15
|
-
errorBaseUrl,
|
|
16
|
-
openInEditor,
|
|
17
|
-
url,
|
|
18
|
-
line,
|
|
19
|
-
column
|
|
20
|
-
}) => {
|
|
21
|
-
let {
|
|
22
|
-
message,
|
|
23
|
-
stack
|
|
24
|
-
} = normalizeErrorParts(error);
|
|
25
|
-
let errorDetailsPromiseReference = {
|
|
26
|
-
current: null
|
|
27
|
-
};
|
|
28
|
-
let tip = `Reported by the browser while executing <code>${window.location.pathname}${window.location.search}</code>.`;
|
|
29
|
-
let errorUrlSite;
|
|
30
|
-
const errorMeta = extractErrorMeta(error, {
|
|
31
|
-
url,
|
|
32
|
-
line,
|
|
33
|
-
column
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const resolveUrlSite = ({
|
|
37
|
-
url,
|
|
38
|
-
line,
|
|
39
|
-
column
|
|
40
|
-
}) => {
|
|
41
|
-
if (typeof line === "string") line = parseInt(line);
|
|
42
|
-
if (typeof column === "string") column = parseInt(column);
|
|
43
|
-
const inlineUrlMatch = url.match(/@L([0-9]+)C([0-9]+)\-L([0-9]+)C([0-9]+)(\.[\w]+)$/);
|
|
44
|
-
|
|
45
|
-
if (inlineUrlMatch) {
|
|
46
|
-
const htmlUrl = url.slice(0, inlineUrlMatch.index);
|
|
47
|
-
const tagLineStart = parseInt(inlineUrlMatch[1]);
|
|
48
|
-
const tagColumnStart = parseInt(inlineUrlMatch[2]);
|
|
49
|
-
const tagLineEnd = parseInt(inlineUrlMatch[3]);
|
|
50
|
-
const tagColumnEnd = parseInt(inlineUrlMatch[4]);
|
|
51
|
-
const extension = inlineUrlMatch[5];
|
|
52
|
-
url = htmlUrl;
|
|
53
|
-
line = tagLineStart + (typeof line === "number" ? line : 0); // stackTrace formatted by V8 (chrome)
|
|
54
|
-
|
|
55
|
-
if (Error.captureStackTrace) {
|
|
56
|
-
line--;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (errorMeta.type === "dynamic_import_syntax_error") {
|
|
60
|
-
// syntax error on inline script need line-1 for some reason
|
|
61
|
-
if (Error.captureStackTrace) {
|
|
62
|
-
line--;
|
|
63
|
-
} else {
|
|
64
|
-
// firefox and safari need line-2
|
|
65
|
-
line -= 2;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
column = tagColumnStart + (typeof column === "number" ? column : 0);
|
|
70
|
-
const fileUrl = resolveFileUrl(url);
|
|
71
|
-
return {
|
|
72
|
-
isInline: true,
|
|
73
|
-
originalUrl: `${fileUrl}@L${tagLineStart}C${tagColumnStart}-L${tagLineEnd}C${tagColumnEnd}${extension}`,
|
|
74
|
-
url: fileUrl,
|
|
75
|
-
line,
|
|
76
|
-
column
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
isInline: false,
|
|
82
|
-
url: resolveFileUrl(url),
|
|
83
|
-
line,
|
|
84
|
-
column
|
|
85
|
-
};
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const resolveFileUrl = url => {
|
|
89
|
-
let urlObject = new URL(url);
|
|
90
|
-
|
|
91
|
-
if (urlObject.origin === window.origin) {
|
|
92
|
-
urlObject = new URL(`${urlObject.pathname.slice(1)}${urlObject.search}`, rootDirectoryUrl);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (urlObject.href.startsWith("file:")) {
|
|
96
|
-
const atFsIndex = urlObject.pathname.indexOf("/@fs/");
|
|
97
|
-
|
|
98
|
-
if (atFsIndex > -1) {
|
|
99
|
-
const afterAtFs = urlObject.pathname.slice(atFsIndex + "/@fs/".length);
|
|
100
|
-
return new URL(afterAtFs, "file:///").href;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return urlObject.href;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const generateClickableText = text => {
|
|
108
|
-
const textWithHtmlLinks = makeLinksClickable(text, {
|
|
109
|
-
createLink: (url, {
|
|
110
|
-
line,
|
|
111
|
-
column
|
|
112
|
-
}) => {
|
|
113
|
-
const urlSite = resolveUrlSite({
|
|
114
|
-
url,
|
|
115
|
-
line,
|
|
116
|
-
column
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
if (!errorUrlSite && text === stack) {
|
|
120
|
-
onErrorLocated(urlSite);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (errorBaseUrl) {
|
|
124
|
-
if (urlSite.url.startsWith(rootDirectoryUrl)) {
|
|
125
|
-
urlSite.url = `${errorBaseUrl}${urlSite.url.slice(rootDirectoryUrl.length)}`;
|
|
126
|
-
} else {
|
|
127
|
-
urlSite.url = "file:///mocked_for_snapshots";
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const urlWithLineAndColumn = formatUrlWithLineAndColumn(urlSite);
|
|
132
|
-
return {
|
|
133
|
-
href: url.startsWith("file:") && openInEditor ? `javascript:window.fetch('/__open_in_editor__/${urlWithLineAndColumn}')` : urlSite.url,
|
|
134
|
-
text: urlWithLineAndColumn
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
return textWithHtmlLinks;
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const formatErrorText = ({
|
|
142
|
-
message,
|
|
143
|
-
stack,
|
|
144
|
-
codeFrame
|
|
145
|
-
}) => {
|
|
146
|
-
let text;
|
|
147
|
-
|
|
148
|
-
if (message && stack) {
|
|
149
|
-
text = `${generateClickableText(message)}\n${generateClickableText(stack)}`;
|
|
150
|
-
} else if (stack) {
|
|
151
|
-
text = generateClickableText(stack);
|
|
152
|
-
} else {
|
|
153
|
-
text = generateClickableText(message);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (codeFrame) {
|
|
157
|
-
text += `\n\n${generateClickableText(codeFrame)}`;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return text;
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
const onErrorLocated = urlSite => {
|
|
164
|
-
errorUrlSite = urlSite;
|
|
165
|
-
|
|
166
|
-
errorDetailsPromiseReference.current = (async () => {
|
|
167
|
-
try {
|
|
168
|
-
if (errorMeta.type === "dynamic_import_fetch_error") {
|
|
169
|
-
const response = await window.fetch(`/__get_error_cause__/${urlSite.isInline ? urlSite.originalUrl : urlSite.url}`);
|
|
170
|
-
|
|
171
|
-
if (response.status !== 200) {
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const causeInfo = await response.json();
|
|
176
|
-
|
|
177
|
-
if (!causeInfo) {
|
|
178
|
-
return null;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const causeText = causeInfo.code === "NOT_FOUND" ? formatErrorText({
|
|
182
|
-
message: causeInfo.reason,
|
|
183
|
-
stack: causeInfo.codeFrame
|
|
184
|
-
}) : formatErrorText({
|
|
185
|
-
message: causeInfo.stack,
|
|
186
|
-
stack: causeInfo.codeFrame
|
|
187
|
-
});
|
|
188
|
-
return {
|
|
189
|
-
cause: causeText
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (urlSite.line !== undefined) {
|
|
194
|
-
let resourceToFetch = `/__get_code_frame__/${formatUrlWithLineAndColumn(urlSite)}`;
|
|
195
|
-
|
|
196
|
-
if (!Error.captureStackTrace) {
|
|
197
|
-
resourceToFetch += `?remap`;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const response = await window.fetch(resourceToFetch);
|
|
201
|
-
const codeFrame = await response.text();
|
|
202
|
-
return {
|
|
203
|
-
codeFrame: formatErrorText({
|
|
204
|
-
message: codeFrame
|
|
205
|
-
})
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
} catch (e) {
|
|
209
|
-
// happens if server is closed for instance
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return null;
|
|
214
|
-
})();
|
|
215
|
-
}; // error.stack is more reliable than url/line/column reported on window error events
|
|
216
|
-
// so use it only when error.stack is not available
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (url && !stack && // ignore window.reportError() it gives no valuable info
|
|
220
|
-
!url.endsWith("html_supervisor_installer.js")) {
|
|
221
|
-
onErrorLocated(resolveUrlSite({
|
|
222
|
-
url,
|
|
223
|
-
line,
|
|
224
|
-
column
|
|
225
|
-
}));
|
|
226
|
-
} else if (errorMeta.url) {
|
|
227
|
-
onErrorLocated(resolveUrlSite(errorMeta));
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
theme: error && error.cause && error.cause.code === "PARSE_ERROR" ? "light" : "dark",
|
|
232
|
-
title: "An error occured",
|
|
233
|
-
text: formatErrorText({
|
|
234
|
-
message,
|
|
235
|
-
stack
|
|
236
|
-
}),
|
|
237
|
-
tip: `${tip}
|
|
238
|
-
<br />
|
|
239
|
-
Click outside to close.`,
|
|
240
|
-
errorDetailsPromise: errorDetailsPromiseReference.current
|
|
241
|
-
};
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
const extractErrorMeta = (error, {
|
|
245
|
-
line
|
|
246
|
-
}) => {
|
|
247
|
-
if (!error) {
|
|
248
|
-
return {};
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const {
|
|
252
|
-
message
|
|
253
|
-
} = error;
|
|
254
|
-
|
|
255
|
-
if (!message) {
|
|
256
|
-
return {};
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
{
|
|
260
|
-
// chrome
|
|
261
|
-
if (message.includes("does not provide an export named")) {
|
|
262
|
-
return {
|
|
263
|
-
type: "dynamic_import_export_missing"
|
|
264
|
-
};
|
|
265
|
-
} // firefox
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (message.startsWith("import not found:")) {
|
|
269
|
-
return {
|
|
270
|
-
type: "dynamic_import_export_missing",
|
|
271
|
-
browser: "firefox"
|
|
272
|
-
};
|
|
273
|
-
} // safari
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
if (message.startsWith("import binding name")) {
|
|
277
|
-
return {
|
|
278
|
-
type: "dynamic_import_export_missing"
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
{
|
|
284
|
-
if (error.name === "SyntaxError" && typeof line === "number") {
|
|
285
|
-
return {
|
|
286
|
-
type: "dynamic_import_syntax_error"
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
{
|
|
292
|
-
// chrome
|
|
293
|
-
if (message.startsWith("Failed to fetch dynamically imported module: ")) {
|
|
294
|
-
const url = error.message.slice("Failed to fetch dynamically imported module: ".length);
|
|
295
|
-
return {
|
|
296
|
-
type: "dynamic_import_fetch_error",
|
|
297
|
-
url
|
|
298
|
-
};
|
|
299
|
-
} // firefox
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (message === "error loading dynamically imported module") {
|
|
303
|
-
return {
|
|
304
|
-
type: "dynamic_import_fetch_error"
|
|
305
|
-
};
|
|
306
|
-
} // safari
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (message === "Importing a module script failed.") {
|
|
310
|
-
return {
|
|
311
|
-
type: "dynamic_import_fetch_error"
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return {};
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
const formatUrlWithLineAndColumn = ({
|
|
320
|
-
url,
|
|
321
|
-
line,
|
|
322
|
-
column
|
|
323
|
-
}) => {
|
|
324
|
-
return line === undefined && column === undefined ? url : column === undefined ? `${url}:${line}` : `${url}:${line}:${column}`;
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
const normalizeErrorParts = error => {
|
|
328
|
-
if (error === undefined) {
|
|
329
|
-
return {
|
|
330
|
-
message: "undefined"
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (error === null) {
|
|
335
|
-
return {
|
|
336
|
-
message: "null"
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (typeof error === "string") {
|
|
341
|
-
return {
|
|
342
|
-
message: error
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
if (error instanceof Error) {
|
|
347
|
-
if (error.name === "SyntaxError") {
|
|
348
|
-
return {
|
|
349
|
-
message: error.message
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (error.cause && error.cause.code === "PARSE_ERROR") {
|
|
354
|
-
if (error.messageHTML) {
|
|
355
|
-
return {
|
|
356
|
-
message: error.messageHTML
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
return {
|
|
361
|
-
message: error.message
|
|
362
|
-
};
|
|
363
|
-
} // stackTrace formatted by V8
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (Error.captureStackTrace) {
|
|
367
|
-
return {
|
|
368
|
-
message: error.message,
|
|
369
|
-
stack: getErrorStackWithoutErrorMessage(error)
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
return {
|
|
374
|
-
message: error.message,
|
|
375
|
-
stack: error.stack ? ` ${error.stack}` : null
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (typeof error === "object") {
|
|
380
|
-
return error;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return {
|
|
384
|
-
message: JSON.stringify(error)
|
|
385
|
-
};
|
|
386
|
-
};
|
|
387
|
-
|
|
388
|
-
const getErrorStackWithoutErrorMessage = error => {
|
|
389
|
-
let stack = error.stack;
|
|
390
|
-
const messageInStack = `${error.name}: ${error.message}`;
|
|
391
|
-
|
|
392
|
-
if (stack.startsWith(messageInStack)) {
|
|
393
|
-
stack = stack.slice(messageInStack.length);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const nextLineIndex = stack.indexOf("\n");
|
|
397
|
-
|
|
398
|
-
if (nextLineIndex > -1) {
|
|
399
|
-
stack = stack.slice(nextLineIndex + 1);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
return stack;
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
const makeLinksClickable = (string, {
|
|
406
|
-
createLink = url => url
|
|
407
|
-
}) => {
|
|
408
|
-
// normalize line breaks
|
|
409
|
-
string = string.replace(/\n/g, "\n");
|
|
410
|
-
string = escapeHtml(string); // render links
|
|
411
|
-
|
|
412
|
-
string = stringToStringWithLink(string, {
|
|
413
|
-
transform: (url, {
|
|
414
|
-
line,
|
|
415
|
-
column
|
|
416
|
-
}) => {
|
|
417
|
-
const {
|
|
418
|
-
href,
|
|
419
|
-
text
|
|
420
|
-
} = createLink(url, {
|
|
421
|
-
line,
|
|
422
|
-
column
|
|
423
|
-
});
|
|
424
|
-
return link({
|
|
425
|
-
href,
|
|
426
|
-
text
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
});
|
|
430
|
-
return string;
|
|
431
|
-
};
|
|
432
|
-
|
|
433
|
-
const escapeHtml = string => {
|
|
434
|
-
return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
435
|
-
}; // `Error: yo
|
|
436
|
-
// at Object.execute (http://127.0.0.1:57300/build/src/__test__/file-throw.js:9:13)
|
|
437
|
-
// at doExec (http://127.0.0.1:3000/src/__test__/file-throw.js:452:38)
|
|
438
|
-
// at postOrderExec (http://127.0.0.1:3000/src/__test__/file-throw.js:448:16)
|
|
439
|
-
// at http://127.0.0.1:3000/src/__test__/file-throw.js:399:18`.replace(/(?:https?|ftp|file):\/\/(.*+)$/gm, (...args) => {
|
|
440
|
-
// debugger
|
|
441
|
-
// })
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
const stringToStringWithLink = (source, {
|
|
445
|
-
transform = url => {
|
|
446
|
-
return {
|
|
447
|
-
href: url,
|
|
448
|
-
text: url
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
} = {}) => {
|
|
452
|
-
return source.replace(/(?:https?|ftp|file):\/\/\S+/gm, match => {
|
|
453
|
-
let linkHTML = "";
|
|
454
|
-
const lastChar = match[match.length - 1]; // hotfix because our url regex sucks a bit
|
|
455
|
-
|
|
456
|
-
const endsWithSeparationChar = lastChar === ")" || lastChar === ":";
|
|
457
|
-
|
|
458
|
-
if (endsWithSeparationChar) {
|
|
459
|
-
match = match.slice(0, -1);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
const lineAndColumnPattern = /:([0-9]+):([0-9]+)$/;
|
|
463
|
-
const lineAndColumMatch = match.match(lineAndColumnPattern);
|
|
464
|
-
|
|
465
|
-
if (lineAndColumMatch) {
|
|
466
|
-
const lineAndColumnString = lineAndColumMatch[0];
|
|
467
|
-
const lineNumber = lineAndColumMatch[1];
|
|
468
|
-
const columnNumber = lineAndColumMatch[2];
|
|
469
|
-
linkHTML = transform(match.slice(0, -lineAndColumnString.length), {
|
|
470
|
-
line: lineNumber,
|
|
471
|
-
column: columnNumber
|
|
472
|
-
});
|
|
473
|
-
} else {
|
|
474
|
-
const linePattern = /:([0-9]+)$/;
|
|
475
|
-
const lineMatch = match.match(linePattern);
|
|
476
|
-
|
|
477
|
-
if (lineMatch) {
|
|
478
|
-
const lineString = lineMatch[0];
|
|
479
|
-
const lineNumber = lineMatch[1];
|
|
480
|
-
linkHTML = transform(match.slice(0, -lineString.length), {
|
|
481
|
-
line: lineNumber
|
|
482
|
-
});
|
|
483
|
-
} else {
|
|
484
|
-
linkHTML = transform(match, {});
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
if (endsWithSeparationChar) {
|
|
489
|
-
return `${linkHTML}${lastChar}`;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
return linkHTML;
|
|
493
|
-
});
|
|
494
|
-
};
|
|
495
|
-
|
|
496
|
-
const link = ({
|
|
497
|
-
href,
|
|
498
|
-
text = href
|
|
499
|
-
}) => `<a href="${href}">${text}</a>`;
|
|
500
|
-
|
|
501
|
-
const JSENV_ERROR_OVERLAY_TAGNAME = "jsenv-error-overlay";
|
|
502
|
-
const displayErrorInDocument = (error, {
|
|
503
|
-
rootDirectoryUrl,
|
|
504
|
-
errorBaseUrl,
|
|
505
|
-
openInEditor,
|
|
506
|
-
url,
|
|
507
|
-
line,
|
|
508
|
-
column,
|
|
509
|
-
codeFrame
|
|
510
|
-
}) => {
|
|
511
|
-
const {
|
|
512
|
-
theme,
|
|
513
|
-
title,
|
|
514
|
-
text,
|
|
515
|
-
tip,
|
|
516
|
-
errorDetailsPromise
|
|
517
|
-
} = formatError(error, {
|
|
518
|
-
rootDirectoryUrl,
|
|
519
|
-
errorBaseUrl,
|
|
520
|
-
openInEditor,
|
|
521
|
-
url,
|
|
522
|
-
line,
|
|
523
|
-
column,
|
|
524
|
-
codeFrame
|
|
525
|
-
});
|
|
526
|
-
let jsenvErrorOverlay = new JsenvErrorOverlay({
|
|
527
|
-
theme,
|
|
528
|
-
title,
|
|
529
|
-
text,
|
|
530
|
-
tip,
|
|
531
|
-
errorDetailsPromise
|
|
532
|
-
});
|
|
533
|
-
document.querySelectorAll(JSENV_ERROR_OVERLAY_TAGNAME).forEach(node => {
|
|
534
|
-
node.parentNode.removeChild(node);
|
|
535
|
-
});
|
|
536
|
-
document.body.appendChild(jsenvErrorOverlay);
|
|
537
|
-
|
|
538
|
-
const removeErrorOverlay = () => {
|
|
539
|
-
if (jsenvErrorOverlay && jsenvErrorOverlay.parentNode) {
|
|
540
|
-
document.body.removeChild(jsenvErrorOverlay);
|
|
541
|
-
jsenvErrorOverlay = null;
|
|
542
|
-
}
|
|
543
|
-
};
|
|
544
|
-
|
|
545
|
-
if (window.__reloader__) {
|
|
546
|
-
window.__reloader__.onstatuschange = () => {
|
|
547
|
-
if (window.__reloader__.status === "reloading") {
|
|
548
|
-
removeErrorOverlay();
|
|
549
|
-
}
|
|
550
|
-
};
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
return removeErrorOverlay;
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
class JsenvErrorOverlay extends HTMLElement {
|
|
557
|
-
constructor({
|
|
558
|
-
theme,
|
|
559
|
-
title,
|
|
560
|
-
text,
|
|
561
|
-
tip,
|
|
562
|
-
errorDetailsPromise
|
|
563
|
-
}) {
|
|
564
|
-
super();
|
|
565
|
-
this.root = this.attachShadow({
|
|
566
|
-
mode: "open"
|
|
567
|
-
});
|
|
568
|
-
this.root.innerHTML = `
|
|
569
|
-
<style>
|
|
570
|
-
${overlayCSS}
|
|
571
|
-
</style>
|
|
572
|
-
<div class="backdrop"></div>
|
|
573
|
-
<div class="overlay" data-theme=${theme}>
|
|
574
|
-
<h1 class="title">
|
|
575
|
-
${title}
|
|
576
|
-
</h1>
|
|
577
|
-
<pre class="text">${text}</pre>
|
|
578
|
-
<div class="tip">
|
|
579
|
-
${tip}
|
|
580
|
-
</div>
|
|
581
|
-
</div>`;
|
|
582
|
-
|
|
583
|
-
this.root.querySelector(".backdrop").onclick = () => {
|
|
584
|
-
if (!this.parentNode) {
|
|
585
|
-
// not in document anymore
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
this.root.querySelector(".backdrop").onclick = null;
|
|
590
|
-
this.parentNode.removeChild(this);
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
if (errorDetailsPromise) {
|
|
594
|
-
errorDetailsPromise.then(errorDetails => {
|
|
595
|
-
if (!errorDetails || !this.parentNode) {
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
const {
|
|
600
|
-
codeFrame,
|
|
601
|
-
cause
|
|
602
|
-
} = errorDetails;
|
|
603
|
-
|
|
604
|
-
if (codeFrame) {
|
|
605
|
-
this.root.querySelector(".text").innerHTML += `\n\n${codeFrame}`;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
if (cause) {
|
|
609
|
-
const causeIndented = prefixRemainingLines(cause, " ");
|
|
610
|
-
this.root.querySelector(".text").innerHTML += `\n [cause]: ${causeIndented}`;
|
|
611
|
-
}
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
const prefixRemainingLines = (text, prefix) => {
|
|
619
|
-
const lines = text.split(/\r?\n/);
|
|
620
|
-
const firstLine = lines.shift();
|
|
621
|
-
let result = firstLine;
|
|
622
|
-
let i = 0;
|
|
623
|
-
|
|
624
|
-
while (i < lines.length) {
|
|
625
|
-
const line = lines[i];
|
|
626
|
-
i++;
|
|
627
|
-
result += line.length ? `\n${prefix}${line}` : `\n`;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
return result;
|
|
631
|
-
};
|
|
632
|
-
|
|
633
|
-
if (customElements && !customElements.get(JSENV_ERROR_OVERLAY_TAGNAME)) {
|
|
634
|
-
customElements.define(JSENV_ERROR_OVERLAY_TAGNAME, JsenvErrorOverlay);
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
const overlayCSS = `
|
|
638
|
-
:host {
|
|
639
|
-
position: fixed;
|
|
640
|
-
z-index: 99999;
|
|
641
|
-
top: 0;
|
|
642
|
-
left: 0;
|
|
643
|
-
width: 100%;
|
|
644
|
-
height: 100%;
|
|
645
|
-
overflow-y: scroll;
|
|
646
|
-
margin: 0;
|
|
647
|
-
background: rgba(0, 0, 0, 0.66);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
.backdrop {
|
|
651
|
-
position: absolute;
|
|
652
|
-
left: 0;
|
|
653
|
-
right: 0;
|
|
654
|
-
top: 0;
|
|
655
|
-
bottom: 0;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
.overlay {
|
|
659
|
-
position: relative;
|
|
660
|
-
background: rgba(0, 0, 0, 0.95);
|
|
661
|
-
width: 800px;
|
|
662
|
-
margin: 30px auto;
|
|
663
|
-
padding: 25px 40px;
|
|
664
|
-
padding-top: 0;
|
|
665
|
-
overflow: hidden; /* for h1 margins */
|
|
666
|
-
border-radius: 4px 8px;
|
|
667
|
-
box-shadow: 0 20px 40px rgb(0 0 0 / 30%), 0 15px 12px rgb(0 0 0 / 20%);
|
|
668
|
-
box-sizing: border-box;
|
|
669
|
-
font-family: monospace;
|
|
670
|
-
direction: ltr;
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
h1 {
|
|
674
|
-
color: red;
|
|
675
|
-
text-align: center;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
pre {
|
|
679
|
-
overflow: auto;
|
|
680
|
-
max-width: 100%;
|
|
681
|
-
/* padding is nice + prevents scrollbar from hiding the text behind it */
|
|
682
|
-
/* does not work nicely on firefox though https://bugzilla.mozilla.org/show_bug.cgi?id=748518 */
|
|
683
|
-
padding: 20px;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
.tip {
|
|
687
|
-
border-top: 1px solid #999;
|
|
688
|
-
padding-top: 12px;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
[data-theme="dark"] {
|
|
692
|
-
color: #999;
|
|
693
|
-
}
|
|
694
|
-
[data-theme="dark"] pre {
|
|
695
|
-
background: #111;
|
|
696
|
-
border: 1px solid #333;
|
|
697
|
-
color: #eee;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
[data-theme="light"] {
|
|
701
|
-
color: #EEEEEE;
|
|
702
|
-
}
|
|
703
|
-
[data-theme="light"] pre {
|
|
704
|
-
background: #1E1E1E;
|
|
705
|
-
border: 1px solid white;
|
|
706
|
-
color: #EEEEEE;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
pre a {
|
|
710
|
-
color: inherit;
|
|
711
|
-
}`;
|
|
712
|
-
|
|
713
|
-
const {
|
|
714
|
-
Notification
|
|
715
|
-
} = window;
|
|
716
|
-
|
|
717
|
-
const displayErrorNotificationNotAvailable = () => {};
|
|
718
|
-
|
|
719
|
-
const displayErrorNotificationImplementation = (error, {
|
|
720
|
-
icon
|
|
721
|
-
} = {}) => {
|
|
722
|
-
if (Notification.permission === "granted") {
|
|
723
|
-
const notification = new Notification("An error occured", {
|
|
724
|
-
lang: "en",
|
|
725
|
-
body: error ? error.stack : "undefined",
|
|
726
|
-
icon
|
|
727
|
-
});
|
|
728
|
-
|
|
729
|
-
notification.onclick = () => {
|
|
730
|
-
window.focus();
|
|
731
|
-
};
|
|
732
|
-
}
|
|
733
|
-
};
|
|
734
|
-
|
|
735
|
-
const displayErrorNotification = typeof Notification === "function" ? displayErrorNotificationImplementation : displayErrorNotificationNotAvailable;
|
|
736
|
-
|
|
737
|
-
const {
|
|
738
|
-
__html_supervisor__
|
|
739
|
-
} = window;
|
|
740
|
-
const supervisedScripts = [];
|
|
741
|
-
const installHtmlSupervisor = ({
|
|
742
|
-
rootDirectoryUrl,
|
|
743
|
-
logs,
|
|
744
|
-
measurePerf,
|
|
745
|
-
errorOverlay,
|
|
746
|
-
errorBaseUrl,
|
|
747
|
-
openInEditor
|
|
748
|
-
}) => {
|
|
749
|
-
|
|
750
|
-
const scriptExecutionResults = {};
|
|
751
|
-
let collectCalled = false;
|
|
752
|
-
let pendingExecutionCount = 0;
|
|
753
|
-
let resolveScriptExecutionsPromise;
|
|
754
|
-
const scriptExecutionsPromise = new Promise(resolve => {
|
|
755
|
-
resolveScriptExecutionsPromise = resolve;
|
|
756
|
-
});
|
|
757
|
-
|
|
758
|
-
const onExecutionStart = name => {
|
|
759
|
-
scriptExecutionResults[name] = null; // ensure execution order is reflected into the object
|
|
760
|
-
|
|
761
|
-
pendingExecutionCount++;
|
|
762
|
-
|
|
763
|
-
if (measurePerf) {
|
|
764
|
-
performance.mark(`execution_start`);
|
|
765
|
-
}
|
|
766
|
-
};
|
|
767
|
-
|
|
768
|
-
const onExecutionSettled = (name, executionResult) => {
|
|
769
|
-
if (measurePerf) {
|
|
770
|
-
performance.measure(`execution`, `execution_start`);
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
scriptExecutionResults[name] = executionResult;
|
|
774
|
-
pendingExecutionCount--;
|
|
775
|
-
|
|
776
|
-
if (pendingExecutionCount === 0 && collectCalled) {
|
|
777
|
-
resolveScriptExecutionsPromise();
|
|
778
|
-
}
|
|
779
|
-
};
|
|
780
|
-
|
|
781
|
-
const onExecutionError = (executionResult, {
|
|
782
|
-
currentScript,
|
|
783
|
-
errorExposureInNotification = false
|
|
784
|
-
}) => {
|
|
785
|
-
const error = executionResult.error;
|
|
786
|
-
|
|
787
|
-
if (error && error.code === "NETWORK_FAILURE") {
|
|
788
|
-
if (currentScript) {
|
|
789
|
-
const currentScriptErrorEvent = new Event("error");
|
|
790
|
-
currentScript.dispatchEvent(currentScriptErrorEvent);
|
|
791
|
-
}
|
|
792
|
-
} else if (typeof error === "object") {
|
|
793
|
-
const globalErrorEvent = new Event("error");
|
|
794
|
-
globalErrorEvent.filename = error.filename;
|
|
795
|
-
globalErrorEvent.lineno = error.line || error.lineno;
|
|
796
|
-
globalErrorEvent.colno = error.column || error.columnno;
|
|
797
|
-
globalErrorEvent.message = error.message;
|
|
798
|
-
window.dispatchEvent(globalErrorEvent);
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
if (errorExposureInNotification) {
|
|
802
|
-
displayErrorNotification(error);
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
executionResult.exceptionSource = unevalException(error);
|
|
806
|
-
delete executionResult.error;
|
|
807
|
-
};
|
|
808
|
-
|
|
809
|
-
const getNavigationStartTime = () => {
|
|
810
|
-
try {
|
|
811
|
-
return window.performance.timing.navigationStart;
|
|
812
|
-
} catch (e) {
|
|
813
|
-
return Date.now();
|
|
814
|
-
}
|
|
815
|
-
};
|
|
816
|
-
|
|
817
|
-
const performExecution = async ({
|
|
818
|
-
src,
|
|
819
|
-
type,
|
|
820
|
-
currentScript,
|
|
821
|
-
execute // https://developer.mozilla.org/en-US/docs/web/html/element/script
|
|
822
|
-
|
|
823
|
-
}, {
|
|
824
|
-
reload = false
|
|
825
|
-
} = {}) => {
|
|
826
|
-
if (logs) {
|
|
827
|
-
console.group(`[jsenv] loading ${type} ${src}`);
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
onExecutionStart(src);
|
|
831
|
-
let completed;
|
|
832
|
-
let result;
|
|
833
|
-
let error;
|
|
834
|
-
const urlObject = new URL(src, window.location);
|
|
835
|
-
|
|
836
|
-
if (reload) {
|
|
837
|
-
urlObject.searchParams.set("hmr", Date.now());
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
__html_supervisor__.currentExecution = {
|
|
841
|
-
type: type === "module" ? "dynamic_import" : "script_injection",
|
|
842
|
-
url: urlObject.href
|
|
843
|
-
};
|
|
844
|
-
|
|
845
|
-
try {
|
|
846
|
-
result = await execute(urlObject.href);
|
|
847
|
-
completed = true;
|
|
848
|
-
} catch (e) {
|
|
849
|
-
completed = false;
|
|
850
|
-
error = e;
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
if (completed) {
|
|
854
|
-
const executionResult = {
|
|
855
|
-
status: "completed",
|
|
856
|
-
namespace: result,
|
|
857
|
-
coverage: window.__coverage__
|
|
858
|
-
};
|
|
859
|
-
onExecutionSettled(src, executionResult);
|
|
860
|
-
|
|
861
|
-
if (logs) {
|
|
862
|
-
console.log(`${type} load ended`);
|
|
863
|
-
console.groupEnd();
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
__html_supervisor__.currentExecution = null;
|
|
867
|
-
return;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
const executionResult = {
|
|
871
|
-
status: "errored",
|
|
872
|
-
coverage: window.__coverage__
|
|
873
|
-
};
|
|
874
|
-
|
|
875
|
-
if (error.name === "SyntaxError") ;
|
|
876
|
-
|
|
877
|
-
executionResult.error = error;
|
|
878
|
-
onExecutionSettled(src, executionResult);
|
|
879
|
-
onExecutionError(executionResult, {
|
|
880
|
-
currentScript
|
|
881
|
-
});
|
|
882
|
-
|
|
883
|
-
{
|
|
884
|
-
if (typeof window.reportError === "function") {
|
|
885
|
-
window.reportError(error);
|
|
886
|
-
} else {
|
|
887
|
-
console.error(error);
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
if (logs) {
|
|
892
|
-
console.groupEnd();
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
__html_supervisor__.currentExecution = null;
|
|
896
|
-
};
|
|
897
|
-
|
|
898
|
-
const classicExecutionQueue = createExecutionQueue(performExecution);
|
|
899
|
-
const deferedExecutionQueue = createExecutionQueue(performExecution);
|
|
900
|
-
deferedExecutionQueue.waitFor(new Promise(resolve => {
|
|
901
|
-
if (document.readyState === "interactive" || document.readyState === "complete") {
|
|
902
|
-
resolve();
|
|
903
|
-
} else {
|
|
904
|
-
document.addEventListener("readystatechange", () => {
|
|
905
|
-
if (document.readyState === "interactive") {
|
|
906
|
-
resolve();
|
|
907
|
-
}
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
}));
|
|
911
|
-
|
|
912
|
-
__html_supervisor__.addScriptToExecute = async scriptToExecute => {
|
|
913
|
-
if (!supervisedScripts.includes(scriptToExecute)) {
|
|
914
|
-
supervisedScripts.push(scriptToExecute);
|
|
915
|
-
|
|
916
|
-
scriptToExecute.reload = () => {
|
|
917
|
-
return performExecution(scriptToExecute, {
|
|
918
|
-
reload: true
|
|
919
|
-
});
|
|
920
|
-
};
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
if (scriptToExecute.async) {
|
|
924
|
-
performExecution(scriptToExecute);
|
|
925
|
-
return;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
const useDeferQueue = scriptToExecute.defer || scriptToExecute.type === "module";
|
|
929
|
-
|
|
930
|
-
if (useDeferQueue) {
|
|
931
|
-
const classicExecutionPromise = classicExecutionQueue.getPromise();
|
|
932
|
-
|
|
933
|
-
if (classicExecutionPromise) {
|
|
934
|
-
deferedExecutionQueue.waitFor(classicExecutionPromise);
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
deferedExecutionQueue.executeAsap(scriptToExecute);
|
|
938
|
-
} else {
|
|
939
|
-
classicExecutionQueue.executeAsap(scriptToExecute);
|
|
940
|
-
}
|
|
941
|
-
};
|
|
942
|
-
|
|
943
|
-
__html_supervisor__.collectScriptResults = async () => {
|
|
944
|
-
collectCalled = true;
|
|
945
|
-
|
|
946
|
-
if (pendingExecutionCount === 0) {
|
|
947
|
-
resolveScriptExecutionsPromise();
|
|
948
|
-
} else {
|
|
949
|
-
await scriptExecutionsPromise;
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
let status = "completed";
|
|
953
|
-
let exceptionSource = "";
|
|
954
|
-
Object.keys(scriptExecutionResults).forEach(key => {
|
|
955
|
-
const scriptExecutionResult = scriptExecutionResults[key];
|
|
956
|
-
|
|
957
|
-
if (scriptExecutionResult.status === "errored") {
|
|
958
|
-
status = "errored";
|
|
959
|
-
exceptionSource = scriptExecutionResult.exceptionSource;
|
|
960
|
-
}
|
|
961
|
-
});
|
|
962
|
-
return {
|
|
963
|
-
status,
|
|
964
|
-
...(status === "errored" ? {
|
|
965
|
-
exceptionSource
|
|
966
|
-
} : {}),
|
|
967
|
-
startTime: getNavigationStartTime(),
|
|
968
|
-
endTime: Date.now(),
|
|
969
|
-
scriptExecutionResults
|
|
970
|
-
};
|
|
971
|
-
};
|
|
972
|
-
|
|
973
|
-
const {
|
|
974
|
-
scriptsToExecute
|
|
975
|
-
} = __html_supervisor__;
|
|
976
|
-
const copy = scriptsToExecute.slice();
|
|
977
|
-
scriptsToExecute.length = 0;
|
|
978
|
-
copy.forEach(scriptToExecute => {
|
|
979
|
-
__html_supervisor__.addScriptToExecute(scriptToExecute);
|
|
980
|
-
});
|
|
981
|
-
|
|
982
|
-
if (errorOverlay) {
|
|
983
|
-
const onErrorReportedByBrowser = (error, {
|
|
984
|
-
url,
|
|
985
|
-
line,
|
|
986
|
-
column
|
|
987
|
-
}) => {
|
|
988
|
-
displayErrorInDocument(error, {
|
|
989
|
-
rootDirectoryUrl,
|
|
990
|
-
errorBaseUrl,
|
|
991
|
-
openInEditor,
|
|
992
|
-
url,
|
|
993
|
-
line,
|
|
994
|
-
column
|
|
995
|
-
});
|
|
996
|
-
};
|
|
997
|
-
|
|
998
|
-
window.addEventListener("error", errorEvent => {
|
|
999
|
-
if (!errorEvent.isTrusted) {
|
|
1000
|
-
// ignore custom error event (not sent by browser)
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
const {
|
|
1005
|
-
error,
|
|
1006
|
-
filename,
|
|
1007
|
-
lineno,
|
|
1008
|
-
colno
|
|
1009
|
-
} = errorEvent;
|
|
1010
|
-
onErrorReportedByBrowser(error, {
|
|
1011
|
-
url: filename,
|
|
1012
|
-
line: lineno,
|
|
1013
|
-
column: colno
|
|
1014
|
-
});
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
|
-
};
|
|
1018
|
-
|
|
1019
|
-
__html_supervisor__.reloadSupervisedScript = ({
|
|
1020
|
-
type,
|
|
1021
|
-
src
|
|
1022
|
-
}) => {
|
|
1023
|
-
const supervisedScript = supervisedScripts.find(supervisedScriptCandidate => {
|
|
1024
|
-
if (type && supervisedScriptCandidate.type !== type) {
|
|
1025
|
-
return false;
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
if (supervisedScriptCandidate.src !== src) {
|
|
1029
|
-
return false;
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
return true;
|
|
1033
|
-
});
|
|
1034
|
-
|
|
1035
|
-
if (supervisedScript) {
|
|
1036
|
-
supervisedScript.reload();
|
|
1037
|
-
}
|
|
1038
|
-
};
|
|
1039
|
-
|
|
1040
|
-
const superviseScriptTypeModule = ({
|
|
1041
|
-
src,
|
|
1042
|
-
isInline
|
|
1043
|
-
}) => {
|
|
1044
|
-
__html_supervisor__.addScriptToExecute({
|
|
1045
|
-
src,
|
|
1046
|
-
type: "module",
|
|
1047
|
-
isInline,
|
|
1048
|
-
execute: url => import(url)
|
|
1049
|
-
});
|
|
1050
|
-
};
|
|
1051
|
-
|
|
1052
|
-
const createExecutionQueue = execute => {
|
|
1053
|
-
const scripts = [];
|
|
1054
|
-
let promiseToWait = null;
|
|
1055
|
-
|
|
1056
|
-
const waitFor = async promise => {
|
|
1057
|
-
promiseToWait = promise;
|
|
1058
|
-
promiseToWait.then(() => {
|
|
1059
|
-
promiseToWait = null;
|
|
1060
|
-
dequeue();
|
|
1061
|
-
}, () => {
|
|
1062
|
-
promiseToWait = null;
|
|
1063
|
-
dequeue();
|
|
1064
|
-
});
|
|
1065
|
-
};
|
|
1066
|
-
|
|
1067
|
-
const executeAsap = async script => {
|
|
1068
|
-
if (promiseToWait) {
|
|
1069
|
-
scripts.push(script);
|
|
1070
|
-
return;
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
waitFor(execute(script));
|
|
1074
|
-
};
|
|
1075
|
-
|
|
1076
|
-
const dequeue = () => {
|
|
1077
|
-
const scriptWaiting = scripts.shift();
|
|
1078
|
-
|
|
1079
|
-
if (scriptWaiting) {
|
|
1080
|
-
__html_supervisor__.addScriptToExecute(scriptWaiting);
|
|
1081
|
-
}
|
|
1082
|
-
};
|
|
1083
|
-
|
|
1084
|
-
return {
|
|
1085
|
-
waitFor,
|
|
1086
|
-
executeAsap,
|
|
1087
|
-
getPromise: () => promiseToWait
|
|
1088
|
-
};
|
|
1089
|
-
};
|
|
1090
|
-
|
|
1091
|
-
export { installHtmlSupervisor, superviseScriptTypeModule };
|