@jsenv/core 28.1.3 → 28.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.
Files changed (47) hide show
  1. package/dist/js/script_type_module_supervisor.js +8 -13
  2. package/dist/js/supervisor.js +690 -504
  3. package/dist/main.js +13277 -13170
  4. package/package.json +3 -3
  5. package/readme.md +3 -3
  6. package/src/build/build.js +960 -712
  7. package/src/build/inject_global_version_mappings.js +5 -20
  8. package/src/build/start_build_server.js +2 -2
  9. package/src/dev/start_dev_server.js +3 -2
  10. package/src/omega/compat/runtime_compat.js +9 -6
  11. package/src/omega/errors.js +3 -0
  12. package/src/omega/fetched_content_compliance.js +2 -2
  13. package/src/omega/kitchen.js +189 -145
  14. package/src/omega/server/file_service.js +104 -71
  15. package/src/omega/url_graph/url_graph_loader.js +77 -0
  16. package/src/omega/url_graph/url_info_transformations.js +12 -15
  17. package/src/omega/url_graph.js +115 -101
  18. package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +1 -0
  19. package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +34 -36
  20. package/src/plugins/autoreload/jsenv_plugin_hmr.js +3 -2
  21. package/src/plugins/bundling/js_module/{bundle_js_module.js → bundle_js_modules.js} +51 -14
  22. package/src/plugins/bundling/jsenv_plugin_bundling.js +2 -2
  23. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +11 -0
  24. package/src/plugins/inline/jsenv_plugin_html_inline_content.js +73 -62
  25. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +77 -89
  26. package/src/plugins/plugin_controller.js +26 -22
  27. package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +1 -0
  28. package/src/plugins/supervisor/client/script_type_module_supervisor.js +7 -9
  29. package/src/plugins/supervisor/client/supervisor.js +99 -52
  30. package/src/plugins/supervisor/jsenv_plugin_supervisor.js +2 -4
  31. package/src/plugins/transpilation/as_js_classic/async-to-promises.js +16 -0
  32. package/src/plugins/transpilation/as_js_classic/convert_js_module_to_js_classic.js +85 -0
  33. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +48 -190
  34. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_conversion.js +102 -0
  35. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +161 -240
  36. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_library.js +84 -0
  37. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_workers.js +19 -12
  38. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -24
  39. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +82 -52
  40. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +12 -13
  41. package/src/plugins/url_analysis/html/html_urls.js +91 -34
  42. package/src/plugins/url_analysis/js/js_urls.js +5 -4
  43. package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +1 -0
  44. package/src/test/execute_plan.js +3 -8
  45. package/src/build/inject_service_worker_urls.js +0 -78
  46. package/src/build/resync_resource_hints.js +0 -112
  47. package/src/omega/url_graph/url_graph_load.js +0 -74
@@ -1,21 +1,22 @@
1
1
  window.__supervisor__ = (() => {
2
2
  const notImplemented = () => {
3
- throw new Error(`window.__supervisor__.setup() not called`)
4
- }
5
- const executionResults = {}
3
+ throw new Error(`window.__supervisor__.setup() not called`);
4
+ };
5
+
6
+ const executionResults = {};
6
7
  const supervisor = {
7
8
  reportError: notImplemented,
8
9
  superviseScript: notImplemented,
9
10
  reloadSupervisedScript: notImplemented,
10
11
  getDocumentExecutionResult: notImplemented,
11
- executionResults,
12
- }
12
+ executionResults
13
+ };
14
+ let navigationStartTime;
13
15
 
14
- let navigationStartTime
15
16
  try {
16
- navigationStartTime = window.performance.timing.navigationStart
17
+ navigationStartTime = window.performance.timing.navigationStart;
17
18
  } catch (e) {
18
- navigationStartTime = Date.now()
19
+ navigationStartTime = Date.now();
19
20
  }
20
21
 
21
22
  supervisor.setupReportException = ({
@@ -23,23 +24,24 @@ window.__supervisor__ = (() => {
23
24
  errorNotification,
24
25
  errorOverlay,
25
26
  errorBaseUrl,
26
- openInEditor,
27
+ openInEditor
27
28
  }) => {
28
- const DYNAMIC_IMPORT_FETCH_ERROR = "dynamic_import_fetch_error"
29
- const DYNAMIC_IMPORT_EXPORT_MISSING = "dynamic_import_export_missing"
30
- const DYNAMIC_IMPORT_SYNTAX_ERROR = "dynamic_import_syntax_error"
29
+ const DYNAMIC_IMPORT_FETCH_ERROR = "dynamic_import_fetch_error";
30
+ const DYNAMIC_IMPORT_EXPORT_MISSING = "dynamic_import_export_missing";
31
+ const DYNAMIC_IMPORT_SYNTAX_ERROR = "dynamic_import_syntax_error";
31
32
 
32
33
  const createException = ({
33
34
  reason,
34
35
  reportedBy,
35
36
  url,
36
37
  line,
37
- column,
38
+ column
38
39
  } = {}) => {
39
40
  const exception = {
40
41
  reason,
41
42
  reportedBy,
42
- isError: false, // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw
43
+ isError: false,
44
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw
43
45
  code: null,
44
46
  message: null,
45
47
  stack: null,
@@ -52,462 +54,526 @@ window.__supervisor__ = (() => {
52
54
  url: null,
53
55
  line: null,
54
56
  column: null,
55
- originalUrl: null,
56
- },
57
- }
57
+ originalUrl: null
58
+ }
59
+ };
58
60
 
59
61
  const writeBasicProperties = () => {
60
62
  if (reason === undefined) {
61
- exception.message = "undefined"
62
- return
63
+ exception.message = "undefined";
64
+ return;
63
65
  }
66
+
64
67
  if (reason === null) {
65
- exception.message = "null"
66
- return
68
+ exception.message = "null";
69
+ return;
67
70
  }
71
+
68
72
  if (typeof reason === "string") {
69
- exception.message = reason
70
- return
73
+ exception.message = reason;
74
+ return;
71
75
  }
76
+
72
77
  if (reason instanceof Error) {
73
- const error = reason
74
- let message = error.message
75
- exception.isError = true
78
+ const error = reason;
79
+ let message = error.message;
80
+ exception.isError = true;
81
+
76
82
  if (Error.captureStackTrace) {
77
83
  // stackTrace formatted by V8
78
- exception.message = message
79
- exception.stack = getErrorStackWithoutErrorMessage(error)
80
- exception.stackFormatIsV8 = true
81
- exception.stackSourcemapped = true
84
+ exception.message = message;
85
+ exception.stack = getErrorStackWithoutErrorMessage(error);
86
+ exception.stackFormatIsV8 = true;
87
+ exception.stackSourcemapped = true;
82
88
  } else {
83
- exception.message = message
84
- exception.stack = error.stack ? ` ${error.stack}` : null
85
- exception.stackFormatIsV8 = false
86
- exception.stackSourcemapped = false
89
+ exception.message = message;
90
+ exception.stack = error.stack ? ` ${error.stack}` : null;
91
+ exception.stackFormatIsV8 = false;
92
+ exception.stackSourcemapped = false;
87
93
  }
94
+
88
95
  if (error.reportedBy) {
89
- exception.reportedBy = error.reportedBy
96
+ exception.reportedBy = error.reportedBy;
90
97
  }
98
+
91
99
  if (error.url) {
92
- Object.assign(exception.site, resolveUrlSite({ url: error.url }))
100
+ Object.assign(exception.site, resolveUrlSite({
101
+ url: error.url
102
+ }));
93
103
  }
104
+
94
105
  if (error.needsReport) {
95
- exception.needsReport = true
106
+ exception.needsReport = true;
96
107
  }
97
- export_missing: {
108
+
109
+ {
98
110
  // chrome
99
111
  if (message.includes("does not provide an export named")) {
100
- exception.code = DYNAMIC_IMPORT_EXPORT_MISSING
101
- return
102
- }
103
- // firefox
112
+ exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
113
+ return;
114
+ } // firefox
115
+
116
+
104
117
  if (message.startsWith("import not found:")) {
105
- exception.code = DYNAMIC_IMPORT_EXPORT_MISSING
106
- return
107
- }
108
- // safari
118
+ exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
119
+ return;
120
+ } // safari
121
+
122
+
109
123
  if (message.startsWith("import binding name")) {
110
- exception.code = DYNAMIC_IMPORT_EXPORT_MISSING
111
- return
124
+ exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
125
+ return;
112
126
  }
113
127
  }
114
- js_syntax_error: {
128
+
129
+ {
115
130
  if (error.name === "SyntaxError" && typeof line === "number") {
116
- exception.code = DYNAMIC_IMPORT_SYNTAX_ERROR
117
- return
131
+ exception.code = DYNAMIC_IMPORT_SYNTAX_ERROR;
132
+ return;
118
133
  }
119
134
  }
120
- return
135
+
136
+ return;
121
137
  }
138
+
122
139
  if (typeof reason === "object") {
123
- exception.code = reason.code
124
- exception.message = reason.message
125
- exception.stack = reason.stack
140
+ exception.code = reason.code;
141
+ exception.message = reason.message;
142
+ exception.stack = reason.stack;
143
+
126
144
  if (reason.reportedBy) {
127
- exception.reportedBy = reason.reportedBy
145
+ exception.reportedBy = reason.reportedBy;
128
146
  }
147
+
129
148
  if (reason.url) {
130
- Object.assign(exception.site, resolveUrlSite({ url: reason.url }))
149
+ Object.assign(exception.site, resolveUrlSite({
150
+ url: reason.url
151
+ }));
131
152
  }
153
+
132
154
  if (reason.needsReport) {
133
- exception.needsReport = true
155
+ exception.needsReport = true;
134
156
  }
135
- return
157
+
158
+ return;
136
159
  }
137
- exception.message = JSON.stringify(reason)
138
- }
139
- writeBasicProperties()
140
160
 
141
- // first create a version of the stack with file://
161
+ exception.message = JSON.stringify(reason);
162
+ };
163
+
164
+ writeBasicProperties(); // first create a version of the stack with file://
142
165
  // (and use it to locate exception url+line+column)
166
+
143
167
  if (exception.stack) {
144
- exception.originalStack = exception.stack
145
- exception.stack = replaceUrls(
146
- exception.originalStack,
147
- (serverUrlSite) => {
148
- const fileUrlSite = resolveUrlSite(serverUrlSite)
149
- if (exception.site.url === null) {
150
- Object.assign(exception.site, fileUrlSite)
151
- }
152
- return stringifyUrlSite(fileUrlSite)
153
- },
154
- )
155
- }
156
- // then if it fails, use url+line+column passed
168
+ exception.originalStack = exception.stack;
169
+ exception.stack = replaceUrls(exception.originalStack, serverUrlSite => {
170
+ const fileUrlSite = resolveUrlSite(serverUrlSite);
171
+
172
+ if (exception.site.url === null) {
173
+ Object.assign(exception.site, fileUrlSite);
174
+ }
175
+
176
+ return stringifyUrlSite(fileUrlSite);
177
+ });
178
+ } // then if it fails, use url+line+column passed
179
+
180
+
157
181
  if (exception.site.url === null && url) {
158
182
  if (typeof line === "string") {
159
- line = parseInt(line)
183
+ line = parseInt(line);
160
184
  }
185
+
161
186
  if (typeof column === "string") {
162
- column = parseInt(column)
187
+ column = parseInt(column);
163
188
  }
164
- const fileUrlSite = resolveUrlSite({ url, line, column })
165
- if (
166
- fileUrlSite.isInline &&
167
- exception.code === DYNAMIC_IMPORT_SYNTAX_ERROR
168
- ) {
189
+
190
+ const fileUrlSite = resolveUrlSite({
191
+ url,
192
+ line,
193
+ column
194
+ });
195
+
196
+ if (fileUrlSite.isInline && exception.code === DYNAMIC_IMPORT_SYNTAX_ERROR) {
169
197
  // syntax error on inline script need line-1 for some reason
170
198
  if (Error.captureStackTrace) {
171
- fileUrlSite.line--
199
+ fileUrlSite.line--;
172
200
  } else {
173
201
  // firefox and safari need line-2
174
- fileUrlSite.line -= 2
202
+ fileUrlSite.line -= 2;
175
203
  }
176
204
  }
177
- Object.assign(exception.site, fileUrlSite)
205
+
206
+ Object.assign(exception.site, fileUrlSite);
178
207
  }
179
- exception.text = stringifyMessageAndStack(exception)
180
- return exception
181
- }
182
208
 
183
- const stringifyMessageAndStack = ({ message, stack }) => {
209
+ exception.text = stringifyMessageAndStack(exception);
210
+ return exception;
211
+ };
212
+
213
+ const stringifyMessageAndStack = ({
214
+ message,
215
+ stack
216
+ }) => {
184
217
  if (message && stack) {
185
- return `${message}\n${stack}`
218
+ return `${message}\n${stack}`;
186
219
  }
220
+
187
221
  if (stack) {
188
- return stack
222
+ return stack;
189
223
  }
190
- return message
191
- }
192
224
 
193
- const stringifyUrlSite = ({ url, line, column }) => {
194
- return typeof line === "number" && typeof column === "number"
195
- ? `${url}:${line}:${column}`
196
- : typeof line === "number"
197
- ? `${url}:${line}`
198
- : url
199
- }
225
+ return message;
226
+ };
227
+
228
+ const stringifyUrlSite = ({
229
+ url,
230
+ line,
231
+ column
232
+ }) => {
233
+ return typeof line === "number" && typeof column === "number" ? `${url}:${line}:${column}` : typeof line === "number" ? `${url}:${line}` : url;
234
+ };
235
+
236
+ const resolveUrlSite = ({
237
+ url,
238
+ line,
239
+ column
240
+ }) => {
241
+ const inlineUrlMatch = url.match(/@L([0-9]+)C([0-9]+)\-L([0-9]+)C([0-9]+)(\.[\w]+)$/);
200
242
 
201
- const resolveUrlSite = ({ url, line, column }) => {
202
- const inlineUrlMatch = url.match(
203
- /@L([0-9]+)C([0-9]+)\-L([0-9]+)C([0-9]+)(\.[\w]+)$/,
204
- )
205
243
  if (inlineUrlMatch) {
206
- const htmlUrl = url.slice(0, inlineUrlMatch.index)
207
- const tagLineStart = parseInt(inlineUrlMatch[1])
208
- const tagColumnStart = parseInt(inlineUrlMatch[2])
209
- const tagLineEnd = parseInt(inlineUrlMatch[3])
210
- const tagColumnEnd = parseInt(inlineUrlMatch[4])
211
- const extension = inlineUrlMatch[5]
212
- url = htmlUrl
213
- line = tagLineStart + (typeof line === "number" ? line : 0)
214
- // stackTrace formatted by V8 (chrome)
244
+ const htmlUrl = url.slice(0, inlineUrlMatch.index);
245
+ const tagLineStart = parseInt(inlineUrlMatch[1]);
246
+ const tagColumnStart = parseInt(inlineUrlMatch[2]);
247
+ const tagLineEnd = parseInt(inlineUrlMatch[3]);
248
+ const tagColumnEnd = parseInt(inlineUrlMatch[4]);
249
+ const extension = inlineUrlMatch[5];
250
+ url = htmlUrl;
251
+ line = tagLineStart + (typeof line === "number" ? line : 0); // stackTrace formatted by V8 (chrome)
252
+
215
253
  if (Error.captureStackTrace) {
216
- line--
254
+ line--;
217
255
  }
218
- column = tagColumnStart + (typeof column === "number" ? column : 0)
219
- const fileUrl = resolveFileUrl(url)
256
+
257
+ column = tagColumnStart + (typeof column === "number" ? column : 0);
258
+ const fileUrl = resolveFileUrl(url);
220
259
  return {
221
260
  isInline: true,
222
261
  serverUrl: url,
223
262
  originalUrl: `${fileUrl}@L${tagLineStart}C${tagColumnStart}-L${tagLineEnd}C${tagColumnEnd}${extension}`,
224
263
  url: fileUrl,
225
264
  line,
226
- column,
227
- }
265
+ column
266
+ };
228
267
  }
268
+
229
269
  return {
230
270
  isInline: false,
231
271
  serverUrl: url,
232
272
  url: resolveFileUrl(url),
233
273
  line,
234
- column,
235
- }
236
- }
274
+ column
275
+ };
276
+ };
277
+
278
+ const getErrorStackWithoutErrorMessage = error => {
279
+ let stack = error.stack;
280
+ const messageInStack = `${error.name}: ${error.message}`;
237
281
 
238
- const getErrorStackWithoutErrorMessage = (error) => {
239
- let stack = error.stack
240
- const messageInStack = `${error.name}: ${error.message}`
241
282
  if (stack.startsWith(messageInStack)) {
242
- stack = stack.slice(messageInStack.length)
283
+ stack = stack.slice(messageInStack.length);
243
284
  }
244
- const nextLineIndex = stack.indexOf("\n")
285
+
286
+ const nextLineIndex = stack.indexOf("\n");
287
+
245
288
  if (nextLineIndex > -1) {
246
- stack = stack.slice(nextLineIndex + 1)
289
+ stack = stack.slice(nextLineIndex + 1);
247
290
  }
248
- return stack
249
- }
250
291
 
251
- const resolveFileUrl = (url) => {
252
- let urlObject = new URL(url)
292
+ return stack;
293
+ };
294
+
295
+ const resolveFileUrl = url => {
296
+ let urlObject = new URL(url);
297
+
253
298
  if (urlObject.origin === window.origin) {
254
- urlObject = new URL(
255
- `${urlObject.pathname.slice(1)}${urlObject.search}`,
256
- rootDirectoryUrl,
257
- )
299
+ urlObject = new URL(`${urlObject.pathname.slice(1)}${urlObject.search}`, rootDirectoryUrl);
258
300
  }
301
+
259
302
  if (urlObject.href.startsWith("file:")) {
260
- const atFsIndex = urlObject.pathname.indexOf("/@fs/")
303
+ const atFsIndex = urlObject.pathname.indexOf("/@fs/");
304
+
261
305
  if (atFsIndex > -1) {
262
- const afterAtFs = urlObject.pathname.slice(atFsIndex + "/@fs/".length)
263
- return new URL(afterAtFs, "file:///").href
306
+ const afterAtFs = urlObject.pathname.slice(atFsIndex + "/@fs/".length);
307
+ return new URL(afterAtFs, "file:///").href;
264
308
  }
265
309
  }
266
- return urlObject.href
267
- }
268
310
 
269
- // `Error: yo
311
+ return urlObject.href;
312
+ }; // `Error: yo
270
313
  // at Object.execute (http://127.0.0.1:57300/build/src/__test__/file-throw.js:9:13)
271
314
  // at doExec (http://127.0.0.1:3000/src/__test__/file-throw.js:452:38)
272
315
  // at postOrderExec (http://127.0.0.1:3000/src/__test__/file-throw.js:448:16)
273
316
  // at http://127.0.0.1:3000/src/__test__/file-throw.js:399:18`.replace(/(?:https?|ftp|file):\/\/(.*+)$/gm, (...args) => {
274
317
  // debugger
275
318
  // })
319
+
320
+
276
321
  const replaceUrls = (source, replace) => {
277
- return source.replace(/(?:https?|ftp|file):\/\/\S+/gm, (match) => {
278
- let replacement = ""
279
- const lastChar = match[match.length - 1]
322
+ return source.replace(/(?:https?|ftp|file):\/\/\S+/gm, match => {
323
+ let replacement = "";
324
+ const lastChar = match[match.length - 1]; // hotfix because our url regex sucks a bit
325
+
326
+ const endsWithSeparationChar = lastChar === ")" || lastChar === ":";
280
327
 
281
- // hotfix because our url regex sucks a bit
282
- const endsWithSeparationChar = lastChar === ")" || lastChar === ":"
283
328
  if (endsWithSeparationChar) {
284
- match = match.slice(0, -1)
329
+ match = match.slice(0, -1);
285
330
  }
286
331
 
287
- const lineAndColumnPattern = /:([0-9]+):([0-9]+)$/
288
- const lineAndColumMatch = match.match(lineAndColumnPattern)
332
+ const lineAndColumnPattern = /:([0-9]+):([0-9]+)$/;
333
+ const lineAndColumMatch = match.match(lineAndColumnPattern);
334
+
289
335
  if (lineAndColumMatch) {
290
- const lineAndColumnString = lineAndColumMatch[0]
291
- const lineString = lineAndColumMatch[1]
292
- const columnString = lineAndColumMatch[2]
336
+ const lineAndColumnString = lineAndColumMatch[0];
337
+ const lineString = lineAndColumMatch[1];
338
+ const columnString = lineAndColumMatch[2];
293
339
  replacement = replace({
294
340
  url: match.slice(0, -lineAndColumnString.length),
295
341
  line: lineString ? parseInt(lineString) : null,
296
- column: columnString ? parseInt(columnString) : null,
297
- })
342
+ column: columnString ? parseInt(columnString) : null
343
+ });
298
344
  } else {
299
- const linePattern = /:([0-9]+)$/
300
- const lineMatch = match.match(linePattern)
345
+ const linePattern = /:([0-9]+)$/;
346
+ const lineMatch = match.match(linePattern);
347
+
301
348
  if (lineMatch) {
302
- const lineString = lineMatch[0]
349
+ const lineString = lineMatch[0];
303
350
  replacement = replace({
304
351
  url: match.slice(0, -lineString.length),
305
- line: lineString ? parseInt(lineString) : null,
306
- })
352
+ line: lineString ? parseInt(lineString) : null
353
+ });
307
354
  } else {
308
355
  replacement = replace({
309
- url: match,
310
- })
356
+ url: match
357
+ });
311
358
  }
312
359
  }
360
+
313
361
  if (endsWithSeparationChar) {
314
- return `${replacement}${lastChar}`
362
+ return `${replacement}${lastChar}`;
315
363
  }
316
- return replacement
317
- })
318
- }
319
364
 
320
- let formatError
321
- error_formatter: {
322
- formatError = (exceptionInfo) => {
365
+ return replacement;
366
+ });
367
+ };
368
+
369
+ let formatError;
370
+
371
+ {
372
+ formatError = exceptionInfo => {
323
373
  const errorParts = {
324
374
  theme: "dark",
325
375
  title: "An error occured",
326
376
  text: "",
327
377
  tip: "",
328
- errorDetailsPromise: null,
329
- }
330
- const tips = []
331
- tips.push("Click outside to close.")
332
- errorParts.tip = tips.join(`\n <br />\n `)
378
+ errorDetailsPromise: null
379
+ };
380
+ const tips = [];
381
+ tips.push("Click outside to close.");
382
+ errorParts.tip = tips.join(`\n <br />\n `);
333
383
 
334
- const generateClickableText = (text) => {
384
+ const generateClickableText = text => {
335
385
  const textWithHtmlLinks = makeLinksClickable(text, {
336
- createLink: ({ url, line, column }) => {
337
- const urlSite = resolveUrlSite({ url, line, column })
386
+ createLink: ({
387
+ url,
388
+ line,
389
+ column
390
+ }) => {
391
+ const urlSite = resolveUrlSite({
392
+ url,
393
+ line,
394
+ column
395
+ });
396
+
338
397
  if (errorBaseUrl) {
339
398
  if (urlSite.url.startsWith(rootDirectoryUrl)) {
340
- urlSite.url = `${errorBaseUrl}${urlSite.url.slice(
341
- rootDirectoryUrl.length,
342
- )}`
399
+ urlSite.url = `${errorBaseUrl}${urlSite.url.slice(rootDirectoryUrl.length)}`;
343
400
  } else {
344
- urlSite.url = "file:///mocked_for_snapshots"
401
+ urlSite.url = "file:///mocked_for_snapshots";
345
402
  }
346
403
  }
347
- const urlWithLineAndColumn = stringifyUrlSite(urlSite)
404
+
405
+ const urlWithLineAndColumn = stringifyUrlSite(urlSite);
348
406
  return {
349
- href:
350
- urlSite.url.startsWith("file:") && openInEditor
351
- ? `javascript:window.fetch('/__open_in_editor__/${encodeURIComponent(
352
- urlWithLineAndColumn,
353
- )}')`
354
- : urlSite.url,
355
- text: urlWithLineAndColumn,
356
- }
357
- },
358
- })
359
- return textWithHtmlLinks
360
- }
407
+ href: urlSite.url.startsWith("file:") && openInEditor ? `javascript:window.fetch('/__open_in_editor__/${encodeURIComponent(urlWithLineAndColumn)}')` : urlSite.url,
408
+ text: urlWithLineAndColumn
409
+ };
410
+ }
411
+ });
412
+ return textWithHtmlLinks;
413
+ };
361
414
 
362
415
  errorParts.text = stringifyMessageAndStack({
363
- message: exceptionInfo.message
364
- ? generateClickableText(exceptionInfo.message)
365
- : "",
366
- stack: exceptionInfo.stack
367
- ? generateClickableText(exceptionInfo.stack)
368
- : "",
369
- })
416
+ message: exceptionInfo.message ? generateClickableText(exceptionInfo.message) : "",
417
+ stack: exceptionInfo.stack ? generateClickableText(exceptionInfo.stack) : ""
418
+ });
419
+
370
420
  if (exceptionInfo.site.url) {
371
421
  errorParts.errorDetailsPromise = (async () => {
372
422
  try {
373
- if (
374
- exceptionInfo.code === DYNAMIC_IMPORT_FETCH_ERROR ||
375
- exceptionInfo.reportedBy === "script_error_event"
376
- ) {
377
- const response = await window.fetch(
378
- `/__get_error_cause__/${encodeURIComponent(
379
- exceptionInfo.site.isInline
380
- ? exceptionInfo.site.originalUrl
381
- : exceptionInfo.site.url,
382
- )}`,
383
- )
423
+ if (exceptionInfo.code === DYNAMIC_IMPORT_FETCH_ERROR || exceptionInfo.reportedBy === "script_error_event") {
424
+ const response = await window.fetch(`/__get_error_cause__/${encodeURIComponent(exceptionInfo.site.isInline ? exceptionInfo.site.originalUrl : exceptionInfo.site.url)}`);
425
+
384
426
  if (response.status !== 200) {
385
- return null
427
+ return null;
386
428
  }
387
- const causeInfo = await response.json()
429
+
430
+ const causeInfo = await response.json();
431
+
388
432
  if (!causeInfo) {
389
- return null
433
+ return null;
390
434
  }
391
- const causeText =
392
- causeInfo.code === "NOT_FOUND"
393
- ? stringifyMessageAndStack({
394
- message: generateClickableText(causeInfo.reason),
395
- stack: generateClickableText(causeInfo.codeFrame),
396
- })
397
- : stringifyMessageAndStack({
398
- message: generateClickableText(causeInfo.stack),
399
- stack: generateClickableText(causeInfo.codeFrame),
400
- })
435
+
436
+ const causeText = causeInfo.code === "NOT_FOUND" ? stringifyMessageAndStack({
437
+ message: generateClickableText(causeInfo.reason),
438
+ stack: generateClickableText(causeInfo.codeFrame)
439
+ }) : stringifyMessageAndStack({
440
+ message: generateClickableText(causeInfo.stack),
441
+ stack: generateClickableText(causeInfo.codeFrame)
442
+ });
401
443
  return {
402
- cause: causeText,
403
- }
444
+ cause: causeText
445
+ };
404
446
  }
405
- if (
406
- exceptionInfo.site.line !== undefined &&
407
- // code frame showing internal window.reportError is pointless
408
- !exceptionInfo.site.url.endsWith(
409
- `script_type_module_supervisor.js`,
410
- )
411
- ) {
412
- const urlToFetch = new URL(
413
- `/__get_code_frame__/${encodeURIComponent(
414
- stringifyUrlSite(exceptionInfo.site),
415
- )}`,
416
- window.origin,
417
- )
447
+
448
+ if (exceptionInfo.site.line !== undefined && // code frame showing internal window.reportError is pointless
449
+ !exceptionInfo.site.url.endsWith(`script_type_module_supervisor.js`)) {
450
+ const urlToFetch = new URL(`/__get_code_frame__/${encodeURIComponent(stringifyUrlSite(exceptionInfo.site))}`, window.origin);
451
+
418
452
  if (!exceptionInfo.stackSourcemapped) {
419
- urlToFetch.searchParams.set("remap", "")
453
+ urlToFetch.searchParams.set("remap", "");
420
454
  }
421
- const response = await window.fetch(urlToFetch)
455
+
456
+ const response = await window.fetch(urlToFetch);
457
+
422
458
  if (response.status !== 200) {
423
- return null
459
+ return null;
424
460
  }
425
- const codeFrame = await response.text()
461
+
462
+ const codeFrame = await response.text();
426
463
  return {
427
- codeFrame: generateClickableText(codeFrame),
428
- }
464
+ codeFrame: generateClickableText(codeFrame)
465
+ };
429
466
  }
430
467
  } catch (e) {
431
468
  // happens if server is closed for instance
432
- return null
469
+ return null;
433
470
  }
434
- return null
435
- })()
471
+
472
+ return null;
473
+ })();
436
474
  }
437
- return errorParts
438
- }
439
475
 
440
- const makeLinksClickable = (
441
- string,
442
- { createLink = ({ url }) => url },
443
- ) => {
476
+ return errorParts;
477
+ };
478
+
479
+ const makeLinksClickable = (string, {
480
+ createLink = ({
481
+ url
482
+ }) => url
483
+ }) => {
444
484
  // normalize line breaks
445
- string = string.replace(/\n/g, "\n")
446
- string = escapeHtml(string)
447
- // render links
448
- string = replaceUrls(string, ({ url, line, column }) => {
449
- const { href, text } = createLink({ url, line, column })
450
- return link({ href, text })
451
- })
452
- return string
453
- }
485
+ string = string.replace(/\n/g, "\n");
486
+ string = escapeHtml(string); // render links
454
487
 
455
- const escapeHtml = (string) => {
456
- return string
457
- .replace(/&/g, "&amp;")
458
- .replace(/</g, "&lt;")
459
- .replace(/>/g, "&gt;")
460
- .replace(/"/g, "&quot;")
461
- .replace(/'/g, "&#039;")
462
- }
488
+ string = replaceUrls(string, ({
489
+ url,
490
+ line,
491
+ column
492
+ }) => {
493
+ const {
494
+ href,
495
+ text
496
+ } = createLink({
497
+ url,
498
+ line,
499
+ column
500
+ });
501
+ return link({
502
+ href,
503
+ text
504
+ });
505
+ });
506
+ return string;
507
+ };
508
+
509
+ const escapeHtml = string => {
510
+ return string.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
511
+ };
463
512
 
464
- const link = ({ href, text = href }) => `<a href="${href}">${text}</a>`
513
+ const link = ({
514
+ href,
515
+ text = href
516
+ }) => `<a href="${href}">${text}</a>`;
465
517
  }
466
518
 
467
- let displayErrorNotification
468
- error_notification: {
469
- const { Notification } = window
470
- displayErrorNotification =
471
- typeof Notification === "function"
472
- ? ({ title, text, icon }) => {
473
- if (Notification.permission === "granted") {
474
- const notification = new Notification(title, {
475
- lang: "en",
476
- body: text,
477
- icon,
478
- })
479
- notification.onclick = () => {
480
- window.focus()
481
- }
482
- }
483
- }
484
- : () => {}
519
+ let displayErrorNotification;
520
+
521
+ {
522
+ const {
523
+ Notification
524
+ } = window;
525
+ displayErrorNotification = typeof Notification === "function" ? ({
526
+ title,
527
+ text,
528
+ icon
529
+ }) => {
530
+ if (Notification.permission === "granted") {
531
+ const notification = new Notification(title, {
532
+ lang: "en",
533
+ body: text,
534
+ icon
535
+ });
536
+
537
+ notification.onclick = () => {
538
+ window.focus();
539
+ };
540
+ }
541
+ } : () => {};
485
542
  }
486
543
 
487
- const JSENV_ERROR_OVERLAY_TAGNAME = "jsenv-error-overlay"
488
- let displayJsenvErrorOverlay
489
- error_overlay: {
490
- displayJsenvErrorOverlay = (params) => {
491
- let jsenvErrorOverlay = new JsenvErrorOverlay(params)
492
- document
493
- .querySelectorAll(JSENV_ERROR_OVERLAY_TAGNAME)
494
- .forEach((node) => {
495
- node.parentNode.removeChild(node)
496
- })
497
- document.body.appendChild(jsenvErrorOverlay)
544
+ const JSENV_ERROR_OVERLAY_TAGNAME = "jsenv-error-overlay";
545
+ let displayJsenvErrorOverlay;
546
+
547
+ {
548
+ displayJsenvErrorOverlay = params => {
549
+ let jsenvErrorOverlay = new JsenvErrorOverlay(params);
550
+ document.querySelectorAll(JSENV_ERROR_OVERLAY_TAGNAME).forEach(node => {
551
+ node.parentNode.removeChild(node);
552
+ });
553
+ document.body.appendChild(jsenvErrorOverlay);
554
+
498
555
  const removeErrorOverlay = () => {
499
556
  if (jsenvErrorOverlay && jsenvErrorOverlay.parentNode) {
500
- document.body.removeChild(jsenvErrorOverlay)
501
- jsenvErrorOverlay = null
557
+ document.body.removeChild(jsenvErrorOverlay);
558
+ jsenvErrorOverlay = null;
502
559
  }
503
- }
504
- return removeErrorOverlay
505
- }
560
+ };
561
+
562
+ return removeErrorOverlay;
563
+ };
506
564
 
507
565
  class JsenvErrorOverlay extends HTMLElement {
508
- constructor({ theme, title, text, tip, errorDetailsPromise }) {
509
- super()
510
- this.root = this.attachShadow({ mode: "open" })
566
+ constructor({
567
+ theme,
568
+ title,
569
+ text,
570
+ tip,
571
+ errorDetailsPromise
572
+ }) {
573
+ super();
574
+ this.root = this.attachShadow({
575
+ mode: "open"
576
+ });
511
577
  this.root.innerHTML = `
512
578
  <style>
513
579
  ${overlayCSS}
@@ -521,50 +587,60 @@ window.__supervisor__ = (() => {
521
587
  <div class="tip">
522
588
  ${tip}
523
589
  </div>
524
- </div>`
590
+ </div>`;
591
+
525
592
  this.root.querySelector(".backdrop").onclick = () => {
526
593
  if (!this.parentNode) {
527
594
  // not in document anymore
528
- return
595
+ return;
529
596
  }
530
- this.root.querySelector(".backdrop").onclick = null
531
- this.parentNode.removeChild(this)
532
- }
597
+
598
+ this.root.querySelector(".backdrop").onclick = null;
599
+ this.parentNode.removeChild(this);
600
+ };
601
+
533
602
  if (errorDetailsPromise) {
534
- errorDetailsPromise.then((errorDetails) => {
603
+ errorDetailsPromise.then(errorDetails => {
535
604
  if (!errorDetails || !this.parentNode) {
536
- return
605
+ return;
537
606
  }
538
- const { codeFrame, cause } = errorDetails
607
+
608
+ const {
609
+ codeFrame,
610
+ cause
611
+ } = errorDetails;
612
+
539
613
  if (codeFrame) {
540
- this.root.querySelector(".text").innerHTML += `\n\n${codeFrame}`
614
+ this.root.querySelector(".text").innerHTML += `\n\n${codeFrame}`;
541
615
  }
616
+
542
617
  if (cause) {
543
- const causeIndented = prefixRemainingLines(cause, " ")
544
- this.root.querySelector(
545
- ".text",
546
- ).innerHTML += `\n [cause]: ${causeIndented}`
618
+ const causeIndented = prefixRemainingLines(cause, " ");
619
+ this.root.querySelector(".text").innerHTML += `\n [cause]: ${causeIndented}`;
547
620
  }
548
- })
621
+ });
549
622
  }
550
623
  }
624
+
551
625
  }
552
626
 
553
627
  const prefixRemainingLines = (text, prefix) => {
554
- const lines = text.split(/\r?\n/)
555
- const firstLine = lines.shift()
556
- let result = firstLine
557
- let i = 0
628
+ const lines = text.split(/\r?\n/);
629
+ const firstLine = lines.shift();
630
+ let result = firstLine;
631
+ let i = 0;
632
+
558
633
  while (i < lines.length) {
559
- const line = lines[i]
560
- i++
561
- result += line.length ? `\n${prefix}${line}` : `\n`
634
+ const line = lines[i];
635
+ i++;
636
+ result += line.length ? `\n${prefix}${line}` : `\n`;
562
637
  }
563
- return result
564
- }
638
+
639
+ return result;
640
+ };
565
641
 
566
642
  if (customElements && !customElements.get(JSENV_ERROR_OVERLAY_TAGNAME)) {
567
- customElements.define(JSENV_ERROR_OVERLAY_TAGNAME, JsenvErrorOverlay)
643
+ customElements.define(JSENV_ERROR_OVERLAY_TAGNAME, JsenvErrorOverlay);
568
644
  }
569
645
 
570
646
  const overlayCSS = `
@@ -641,13 +717,19 @@ window.__supervisor__ = (() => {
641
717
 
642
718
  pre a {
643
719
  color: inherit;
644
- }`
720
+ }`;
645
721
  }
646
722
 
647
- supervisor.createException = createException
648
- supervisor.reportException = (exception) => {
649
- const { theme, title, text, tip, errorDetailsPromise } =
650
- formatError(exception)
723
+ supervisor.createException = createException;
724
+
725
+ supervisor.reportException = exception => {
726
+ const {
727
+ theme,
728
+ title,
729
+ text,
730
+ tip,
731
+ errorDetailsPromise
732
+ } = formatError(exception);
651
733
 
652
734
  if (errorOverlay) {
653
735
  const removeErrorOverlay = displayJsenvErrorOverlay({
@@ -655,30 +737,41 @@ window.__supervisor__ = (() => {
655
737
  title,
656
738
  text,
657
739
  tip,
658
- errorDetailsPromise,
659
- })
740
+ errorDetailsPromise
741
+ });
742
+
660
743
  if (window.__reloader__) {
661
744
  window.__reloader__.onstatuschange = () => {
662
745
  if (window.__reloader__.status === "reloading") {
663
- removeErrorOverlay()
746
+ removeErrorOverlay();
664
747
  }
665
- }
748
+ };
666
749
  }
667
750
  }
751
+
668
752
  if (errorNotification) {
669
753
  displayErrorNotification({
670
754
  title,
671
- text,
672
- })
755
+ text
756
+ });
673
757
  }
674
- return exception
675
- }
676
- window.addEventListener("error", (errorEvent) => {
758
+
759
+ return exception;
760
+ };
761
+
762
+ window.addEventListener("error", errorEvent => {
677
763
  if (!errorEvent.isTrusted) {
678
764
  // ignore custom error event (not sent by browser)
679
- return
765
+ return;
680
766
  }
681
- const { error, message, filename, lineno, colno } = errorEvent
767
+
768
+ const {
769
+ error,
770
+ message,
771
+ filename,
772
+ lineno,
773
+ colno
774
+ } = errorEvent;
682
775
  const exception = supervisor.createException({
683
776
  // when error is reported within a worker error is null
684
777
  // but there is a message property on errorEvent
@@ -686,166 +779,249 @@ window.__supervisor__ = (() => {
686
779
  reportedBy: "window_error_event",
687
780
  url: filename,
688
781
  line: lineno,
689
- column: colno,
690
- })
691
- supervisor.reportException(exception)
692
- })
693
- window.addEventListener("unhandledrejection", (event) => {
782
+ column: colno
783
+ });
784
+ supervisor.reportException(exception);
785
+ });
786
+ window.addEventListener("unhandledrejection", event => {
694
787
  if (event.defaultPrevented) {
695
- return
788
+ return;
696
789
  }
790
+
697
791
  const exception = supervisor.createException({
698
792
  reason: event.reason,
699
- reportedBy: "window_unhandledrejection_event",
700
- })
701
- supervisor.reportException(exception)
702
- })
703
- }
793
+ reportedBy: "window_unhandledrejection_event"
794
+ });
795
+ supervisor.reportException(exception);
796
+ });
797
+ };
704
798
 
705
799
  supervisor.setup = ({
706
800
  rootDirectoryUrl,
707
801
  logs,
708
- measurePerf,
709
802
  errorOverlay,
710
803
  errorBaseUrl,
711
- openInEditor,
804
+ openInEditor
712
805
  }) => {
713
806
  supervisor.setupReportException({
714
807
  rootDirectoryUrl,
715
808
  errorOverlay,
716
809
  errorBaseUrl,
717
- openInEditor,
718
- })
810
+ openInEditor
811
+ });
812
+ const supervisedScripts = [];
813
+ const pendingPromises = []; // respect execution order
814
+ // - wait for classic scripts to be done (non async)
815
+ // - wait module script previous execution (non async)
816
+ // see https://gist.github.com/jakub-g/385ee6b41085303a53ad92c7c8afd7a6#typemodule-vs-non-module-typetextjavascript-vs-script-nomodule
817
+
818
+ const executionQueue = [];
819
+ let executing = false;
820
+
821
+ const addToExecutionQueue = async execution => {
822
+ if (execution.async) {
823
+ execution.start();
824
+ return;
825
+ }
826
+
827
+ if (executing) {
828
+ executionQueue.push(execution);
829
+ return;
830
+ }
719
831
 
720
- const supervisedScripts = []
721
- const scriptExecutionPromises = []
722
- supervisor.createExecution = ({ type, src, async, execute }) => {
832
+ startThenDequeue(execution);
833
+ };
834
+
835
+ const startThenDequeue = async execution => {
836
+ executing = true;
837
+ const promise = execution.start();
838
+ await promise;
839
+ executing = false;
840
+
841
+ if (executionQueue.length) {
842
+ const nextExecution = executionQueue.shift();
843
+ startThenDequeue(nextExecution);
844
+ }
845
+ };
846
+
847
+ supervisor.addExecution = ({
848
+ type,
849
+ src,
850
+ async,
851
+ execute
852
+ }) => {
723
853
  const execution = {
724
854
  type,
725
855
  src,
726
856
  async,
727
- execute,
728
- }
857
+ execute
858
+ };
859
+
729
860
  execution.start = () => {
730
- return superviseExecution(execution, { isReload: false })
731
- }
861
+ return superviseExecution(execution, {
862
+ isReload: false
863
+ });
864
+ };
865
+
732
866
  execution.reload = () => {
733
- return superviseExecution(execution, { isReload: true })
734
- }
735
- supervisedScripts.push(execution)
736
- return execution
737
- }
738
- const superviseExecution = async (execution, { isReload }) => {
867
+ return superviseExecution(execution, {
868
+ isReload: true
869
+ });
870
+ };
871
+
872
+ supervisedScripts.push(execution);
873
+ return addToExecutionQueue(execution);
874
+ };
875
+
876
+ const superviseExecution = async (execution, {
877
+ isReload
878
+ }) => {
739
879
  if (logs) {
740
- console.group(`[jsenv] loading ${execution.type} ${execution.src}`)
741
- }
742
- if (measurePerf) {
743
- performance.mark(`execution_start`)
880
+ console.group(`[jsenv] loading ${execution.type} ${execution.src}`);
744
881
  }
882
+
745
883
  const executionResult = {
746
884
  status: "pending",
747
- startTime: Date.now(),
748
- endTime: null,
885
+ loadDuration: null,
886
+ executionDuration: null,
887
+ duration: null,
749
888
  exception: null,
750
889
  namespace: null,
751
- coverage: null,
752
- }
753
- executionResults[execution.src] = executionResult
754
- let resolveScriptExecutionPromise
755
- const scriptExecutionPromise = new Promise((resolve) => {
756
- resolveScriptExecutionPromise = () => {
757
- executionResult.endTime = Date.now()
758
- if (measurePerf) {
759
- performance.measure(`execution`, `execution_start`)
760
- }
761
- resolve()
890
+ coverage: null
891
+ };
892
+ executionResults[execution.src] = executionResult;
893
+
894
+ const monitorScriptLoad = () => {
895
+ const loadStartTime = Date.now();
896
+ let resolveScriptLoadPromise;
897
+ const scriptLoadPromise = new Promise(resolve => {
898
+ resolveScriptLoadPromise = resolve;
899
+ });
900
+ pendingPromises.push(scriptLoadPromise);
901
+ return () => {
902
+ const loadEndTime = Date.now();
903
+ executionResult.loadDuration = loadEndTime - loadStartTime;
904
+ resolveScriptLoadPromise();
905
+ };
906
+ };
907
+
908
+ const monitorScriptExecution = () => {
909
+ const executionStartTime = Date.now();
910
+ let resolveExecutionPromise;
911
+ const executionPromise = new Promise(resolve => {
912
+ resolveExecutionPromise = resolve;
913
+ });
914
+ pendingPromises.push(executionPromise);
915
+ return () => {
916
+ executionResult.coverage = window.__coverage__;
917
+ executionResult.executionDuration = Date.now() - executionStartTime;
918
+ executionResult.duration = executionResult.loadDuration + executionResult.executionDuration;
919
+ resolveExecutionPromise();
920
+ };
921
+ };
922
+
923
+ const onError = e => {
924
+ executionResult.status = "errored";
925
+ const exception = supervisor.createException({
926
+ reason: e
927
+ });
928
+
929
+ if (exception.needsReport) {
930
+ supervisor.reportException(exception);
762
931
  }
763
- })
764
- scriptExecutionPromise.execution = execution
765
- scriptExecutionPromises.push(scriptExecutionPromise)
932
+
933
+ executionResult.exception = exception;
934
+ };
935
+
936
+ const scriptLoadDone = monitorScriptLoad();
937
+
766
938
  try {
767
- const result = await execution.execute({ isReload })
768
- executionResult.status = "completed"
769
- executionResult.namespace = result
770
- executionResult.coverage = window.__coverage__
939
+ const result = await execution.execute({
940
+ isReload
941
+ });
942
+
771
943
  if (logs) {
772
- console.log(`${execution.type} load ended`)
773
- console.groupEnd()
944
+ console.log(`${execution.type} load ended`);
945
+ console.groupEnd();
774
946
  }
775
- resolveScriptExecutionPromise()
776
- } catch (e) {
777
- executionResult.status = "errored"
778
- const exception = supervisor.createException({
779
- reason: e,
780
- })
781
- if (exception.needsReport) {
782
- supervisor.reportException(exception)
947
+
948
+ executionResult.status = "loaded";
949
+ scriptLoadDone();
950
+ const scriptExecutionDone = monitorScriptExecution();
951
+
952
+ if (execution.type === "js_classic") {
953
+ executionResult.status = "completed";
954
+ scriptExecutionDone();
955
+ } else if (execution.type === "js_module") {
956
+ result.executionPromise.then(namespace => {
957
+ executionResult.status = "completed";
958
+ executionResult.namespace = namespace;
959
+ scriptExecutionDone();
960
+ }, e => {
961
+ onError(e);
962
+ scriptExecutionDone();
963
+ });
783
964
  }
784
- executionResult.exception = exception
785
- executionResult.coverage = window.__coverage__
965
+ } catch (e) {
786
966
  if (logs) {
787
- console.groupEnd()
967
+ console.groupEnd();
788
968
  }
789
- resolveScriptExecutionPromise()
790
- }
791
- }
792
969
 
793
- // respect execution order
794
- // - wait for classic scripts to be done (non async)
795
- // - wait module script previous execution (non async)
796
- // see https://gist.github.com/jakub-g/385ee6b41085303a53ad92c7c8afd7a6#typemodule-vs-non-module-typetextjavascript-vs-script-nomodule
797
- supervisor.getPreviousExecutionDonePromise = async () => {
798
- const previousNonAsyncScriptExecutions = scriptExecutionPromises.filter(
799
- (promise) => !promise.execution.async,
800
- )
801
- await Promise.all(previousNonAsyncScriptExecutions)
802
- }
803
- supervisor.superviseScript = async ({ src, async }) => {
804
- const { currentScript } = document
805
- const parentNode = currentScript.parentNode
806
- if (!async) {
807
- await supervisor.getPreviousExecutionDonePromise()
970
+ onError(e);
971
+ scriptLoadDone();
808
972
  }
809
- let nodeToReplace
810
- let currentScriptClone
811
- const execution = supervisor.createExecution({
973
+ };
974
+
975
+ supervisor.superviseScript = async ({
976
+ src,
977
+ async
978
+ }) => {
979
+ const {
980
+ currentScript
981
+ } = document;
982
+ const parentNode = currentScript.parentNode;
983
+ let nodeToReplace;
984
+ let currentScriptClone;
985
+ return supervisor.addExecution({
812
986
  src,
813
987
  type: "js_classic",
814
988
  async,
815
- execute: async ({ isReload }) => {
816
- const urlObject = new URL(src, window.location)
989
+ execute: async ({
990
+ isReload
991
+ }) => {
992
+ const urlObject = new URL(src, window.location);
817
993
  const loadPromise = new Promise((resolve, reject) => {
818
994
  // do not use script.cloneNode()
819
995
  // bcause https://stackoverflow.com/questions/28771542/why-dont-clonenode-script-tags-execute
820
- currentScriptClone = document.createElement("script")
821
- // browsers set async by default when creating script(s)
996
+ currentScriptClone = document.createElement("script"); // browsers set async by default when creating script(s)
822
997
  // we want an exact copy to preserves how code is executed
823
- currentScriptClone.async = false
824
- Array.from(currentScript.attributes).forEach((attribute) => {
825
- currentScriptClone.setAttribute(
826
- attribute.nodeName,
827
- attribute.nodeValue,
828
- )
829
- })
998
+
999
+ currentScriptClone.async = false;
1000
+ Array.from(currentScript.attributes).forEach(attribute => {
1001
+ currentScriptClone.setAttribute(attribute.nodeName, attribute.nodeValue);
1002
+ });
1003
+
830
1004
  if (isReload) {
831
- urlObject.searchParams.set("hmr", Date.now())
832
- nodeToReplace = currentScriptClone
833
- currentScriptClone.src = urlObject.href
1005
+ urlObject.searchParams.set("hmr", Date.now());
1006
+ nodeToReplace = currentScriptClone;
1007
+ currentScriptClone.src = urlObject.href;
834
1008
  } else {
835
- currentScriptClone.removeAttribute("jsenv-plugin-owner")
836
- currentScriptClone.removeAttribute("jsenv-plugin-action")
837
- currentScriptClone.removeAttribute("inlined-from-src")
838
- currentScriptClone.removeAttribute("original-position")
839
- currentScriptClone.removeAttribute("original-src-position")
840
- nodeToReplace = currentScript
841
- currentScriptClone.src = src
1009
+ currentScriptClone.removeAttribute("jsenv-plugin-owner");
1010
+ currentScriptClone.removeAttribute("jsenv-plugin-action");
1011
+ currentScriptClone.removeAttribute("inlined-from-src");
1012
+ currentScriptClone.removeAttribute("original-position");
1013
+ currentScriptClone.removeAttribute("original-src-position");
1014
+ nodeToReplace = currentScript;
1015
+ currentScriptClone.src = src;
842
1016
  }
843
- currentScriptClone.addEventListener("error", reject)
844
- currentScriptClone.addEventListener("load", resolve)
845
- parentNode.replaceChild(currentScriptClone, nodeToReplace)
846
- })
1017
+
1018
+ currentScriptClone.addEventListener("error", reject);
1019
+ currentScriptClone.addEventListener("load", resolve);
1020
+ parentNode.replaceChild(currentScriptClone, nodeToReplace);
1021
+ });
1022
+
847
1023
  try {
848
- await loadPromise
1024
+ await loadPromise;
849
1025
  } catch (e) {
850
1026
  // eslint-disable-next-line no-throw-literal
851
1027
  throw {
@@ -853,63 +1029,73 @@ window.__supervisor__ = (() => {
853
1029
  reportedBy: "script_error_event",
854
1030
  url: urlObject.href,
855
1031
  // window.error won't be dispatched for this error
856
- needsReport: true,
857
- }
858
- }
859
- },
860
- })
861
- return execution.start()
862
- }
863
- supervisor.reloadSupervisedScript = ({ type, src }) => {
864
- const supervisedScript = supervisedScripts.find(
865
- (supervisedScriptCandidate) => {
866
- if (type && supervisedScriptCandidate.type !== type) {
867
- return false
868
- }
869
- if (supervisedScriptCandidate.src !== src) {
870
- return false
1032
+ needsReport: true
1033
+ };
871
1034
  }
872
- return true
873
- },
874
- )
1035
+ }
1036
+ });
1037
+ };
1038
+
1039
+ supervisor.reloadSupervisedScript = ({
1040
+ type,
1041
+ src
1042
+ }) => {
1043
+ const supervisedScript = supervisedScripts.find(supervisedScriptCandidate => {
1044
+ if (type && supervisedScriptCandidate.type !== type) {
1045
+ return false;
1046
+ }
1047
+
1048
+ if (supervisedScriptCandidate.src !== src) {
1049
+ return false;
1050
+ }
1051
+
1052
+ return true;
1053
+ });
1054
+
875
1055
  if (supervisedScript) {
876
- supervisedScript.reload()
1056
+ supervisedScript.reload();
877
1057
  }
878
- }
1058
+ };
1059
+
879
1060
  supervisor.getDocumentExecutionResult = async () => {
880
1061
  // just to be super safe and ensure any <script type="module"> got a chance to execute
881
- const documentReadyPromise = new Promise((resolve) => {
1062
+ const documentReadyPromise = new Promise(resolve => {
882
1063
  if (document.readyState === "complete") {
883
- resolve()
884
- return
1064
+ resolve();
1065
+ return;
885
1066
  }
1067
+
886
1068
  const loadCallback = () => {
887
- window.removeEventListener("load", loadCallback)
888
- resolve()
889
- }
890
- window.addEventListener("load", loadCallback)
891
- })
892
- await documentReadyPromise
1069
+ window.removeEventListener("load", loadCallback);
1070
+ resolve();
1071
+ };
1072
+
1073
+ window.addEventListener("load", loadCallback);
1074
+ });
1075
+ await documentReadyPromise;
1076
+
893
1077
  const waitScriptExecutions = async () => {
894
- const numberOfScripts = scriptExecutionPromises.length
895
- await Promise.all(scriptExecutionPromises)
896
- // new scripts added while the other where executing
1078
+ const numberOfPromises = pendingPromises.length;
1079
+ await Promise.all(pendingPromises); // new scripts added while the other where executing
897
1080
  // (should happen only on webkit where
898
1081
  // script might be added after window load event)
899
- if (scriptExecutionPromises.length > numberOfScripts) {
900
- await waitScriptExecutions()
1082
+
1083
+ await new Promise(resolve => setTimeout(resolve));
1084
+
1085
+ if (pendingPromises.length > numberOfPromises) {
1086
+ await waitScriptExecutions();
901
1087
  }
902
- }
903
- await waitScriptExecutions()
1088
+ };
904
1089
 
1090
+ await waitScriptExecutions();
905
1091
  return {
906
1092
  status: "completed",
907
1093
  executionResults,
908
1094
  startTime: navigationStartTime,
909
- endTime: Date.now(),
910
- }
911
- }
912
- }
1095
+ endTime: Date.now()
1096
+ };
1097
+ };
1098
+ };
913
1099
 
914
- return supervisor
915
- })()
1100
+ return supervisor;
1101
+ })();