@jsenv/plugin-supervisor 1.3.9 → 1.4.1

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.
@@ -160,16 +160,20 @@ window.__supervisor__ = (() => {
160
160
  }
161
161
  const scriptLoadPromise = getScriptLoadPromise(currentScriptClone);
162
162
  parentNode.replaceChild(currentScriptClone, nodeToReplace);
163
- const { detectedBy, failed, error } = await scriptLoadPromise;
163
+ const { detectedBy, failed, errorEvent } = await scriptLoadPromise;
164
164
  if (failed) {
165
+ const messageDefault = `Error while loading script`;
166
+ const { error, message, filename, lineno, colno } = errorEvent;
165
167
  if (detectedBy === "script_error_event") {
166
168
  // window.error won't be dispatched for this error
167
- reportErrorBackToBrowser(error);
169
+ reportErrorBackToBrowser(error || errorEvent);
168
170
  }
169
- fail(error, {
170
- message: `Error while loading script: ${urlObject.href}`,
171
+ fail(error || message || messageDefault, {
172
+ message: messageDefault,
171
173
  reportedBy: "script_error_event",
172
- url: urlObject.href,
174
+ url: filename || urlObject.href,
175
+ line: lineno,
176
+ column: colno,
173
177
  });
174
178
  if (detectedBy === "script_error_event") {
175
179
  supervisor.reportException(result.exception);
@@ -222,7 +226,7 @@ window.__supervisor__ = (() => {
222
226
  return result;
223
227
  } catch (e) {
224
228
  fail(e, {
225
- message: `Error while importing module: ${urlObject.href}`,
229
+ message: `Error while importing module`,
226
230
  reportedBy: "dynamic_import",
227
231
  url: urlObject.href,
228
232
  });
@@ -268,16 +272,21 @@ window.__supervisor__ = (() => {
268
272
  const scriptLoadResultPromise =
269
273
  getScriptLoadPromise(currentScriptClone);
270
274
  parentNode.replaceChild(currentScriptClone, nodeToReplace);
271
- const { detectedBy, failed, error } = await scriptLoadResultPromise;
275
+ const { detectedBy, failed, errorEvent } =
276
+ await scriptLoadResultPromise;
272
277
 
273
278
  if (failed) {
279
+ const messageDefault = `Error while loading module`;
280
+ const { error, message, filename, lineno, colno } = errorEvent;
274
281
  // if (detectedBy === "script_error_event") {
275
282
  // reportErrorBackToBrowser(error)
276
283
  // }
277
- fail(error, {
278
- message: `Error while loading module: ${urlObject.href}`,
284
+ fail(error || message || messageDefault, {
285
+ message: messageDefault,
279
286
  reportedBy: "script_error_event",
280
- url: urlObject.href,
287
+ url: filename || urlObject.href,
288
+ line: lineno,
289
+ column: colno,
281
290
  });
282
291
  if (detectedBy === "script_error_event") {
283
292
  supervisor.reportException(result.exception);
@@ -435,10 +444,11 @@ window.__supervisor__ = (() => {
435
444
  stackSourcemapped: null,
436
445
  stackOriginal: "", // the stack from runtime, not normalized to v8
437
446
  stackTrace: "", // the stack trace (without error name and message)
447
+ stackFrames: undefined,
438
448
  withServerUrls: {
439
449
  message: "",
440
- stackTrace: "",
441
450
  stack: "",
451
+ stackTrace: "",
442
452
  },
443
453
  meta: null,
444
454
  site: {
@@ -463,78 +473,154 @@ window.__supervisor__ = (() => {
463
473
  exception.message = reason;
464
474
  return;
465
475
  }
466
- if (reason instanceof Error) {
467
- const error = reason;
468
- exception.isError = true;
469
- exception.name = error.name || "Error";
470
- exception.message = error.message || "";
471
- if (
472
- Error.captureStackTrace &&
473
- // captureStackTrace exists on webkit but error.stack is not v8
474
- !isWebkitOrSafari
475
- ) {
476
- // stackTrace formatted by V8
477
- exception.stackSourcemapped = true;
478
- exception.stack = error.stack;
479
- exception.stackTrace = getErrorStackTrace(error);
480
- } else if (error.stack) {
481
- exception.stackSourcemapped = false;
482
- exception.stackTrace = error.stack;
483
- exception.stack = stringifyStack(exception);
484
- }
476
+ if (typeof reason !== "object") {
477
+ exception.message = JSON.stringify(reason);
478
+ return;
479
+ }
480
+ // isError can be false when reason is an ErrorEvent for instance
481
+ exception.isError = reason instanceof Error;
482
+ exception.name = reason.name || "Error";
483
+ exception.message = reason.message || message || "";
485
484
 
486
- if (error.reportedBy) {
487
- exception.reportedBy = error.reportedBy;
488
- }
489
- if (error.url) {
490
- Object.assign(exception.site, resolveUrlSite({ url: error.url }));
491
- }
492
- export_missing: {
493
- // chrome
494
- if (error.message.includes("does not provide an export named")) {
495
- exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
496
- return;
497
- }
498
- // firefox
499
- if (
500
- error.message.startsWith("import not found:") ||
501
- error.message.startsWith("ambiguous indirect export:")
502
- ) {
503
- exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
504
- return;
485
+ let stackFrames;
486
+ if (
487
+ exception.isError &&
488
+ Error.captureStackTrace &&
489
+ // captureStackTrace exists on webkit but error.stack is not v8
490
+ !isWebkitOrSafari
491
+ ) {
492
+ // stackTrace formatted by V8
493
+ const { prepareStackTrace } = Error;
494
+ Error.prepareStackTrace = (e, callSites) => {
495
+ Error.prepareStackTrace = prepareStackTrace;
496
+
497
+ const getPropertiesFromEvalOrigin = (origin) => {
498
+ // Most eval() calls are in this format
499
+ const topLevelEvalMatch =
500
+ /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin);
501
+ if (topLevelEvalMatch) {
502
+ const source = topLevelEvalMatch[2];
503
+ const line = Number(topLevelEvalMatch[3]);
504
+ const column = topLevelEvalMatch[4] - 1;
505
+ return {
506
+ url: source,
507
+ line,
508
+ column,
509
+ };
510
+ }
511
+ // Parse nested eval() calls using recursion
512
+ const nestedEvalMatch = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
513
+ if (nestedEvalMatch) {
514
+ return getPropertiesFromEvalOrigin(nestedEvalMatch[2]);
515
+ }
516
+ return null;
517
+ };
518
+
519
+ stackFrames = [];
520
+ for (const callSite of callSites) {
521
+ const url =
522
+ callSite.getFileName() || callSite.getScriptNameOrSourceURL();
523
+ const line = callSite.getLineNumber();
524
+ const column = callSite.getColumnNumber();
525
+ const site = resolveUrlSite({ url, line, column });
526
+ const stackFrame = {
527
+ raw: ` at ${String(callSite)}`,
528
+ url: site.url,
529
+ line: site.line,
530
+ column: site.column,
531
+ functionName: callSite.getFunctionName(),
532
+ isNative: callSite.isNative(),
533
+ isEval: callSite.isEval(),
534
+ isConstructor: callSite.isConstructor(),
535
+ isAsync: callSite.isAsync(),
536
+ evalSite: null,
537
+ };
538
+ if (stackFrame.isEval) {
539
+ const evalOrigin = stackFrame.getEvalOrigin();
540
+ if (evalOrigin) {
541
+ stackFrame.evalSite = getPropertiesFromEvalOrigin(evalOrigin);
542
+ }
543
+ }
544
+ stackFrames.push(stackFrame);
505
545
  }
506
- // safari
507
- if (error.message.startsWith("import binding name")) {
508
- exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
509
- return;
546
+ let stackTrace = "";
547
+ for (const stackFrame of stackFrames) {
548
+ if (stackTrace) stackTrace += "\n";
549
+ stackTrace += stackFrame.raw;
510
550
  }
511
- if (error.message.includes("Importing a module script failed")) {
512
- exception.code = DYNAMIC_IMPORT_FETCH_ERROR;
513
- return;
551
+ exception.stackTrace = stackTrace;
552
+
553
+ let stack = "";
554
+ const name = reason.name || "Error";
555
+ const message = reason.message || "";
556
+ stack += `${name}: ${message}`;
557
+ if (stackTrace) {
558
+ stack += `\n${stackTrace}`;
514
559
  }
515
- }
516
- js_syntax_error: {
517
- if (error.name === "SyntaxError" && typeof line === "number") {
518
- exception.code = DYNAMIC_IMPORT_SYNTAX_ERROR;
519
- return;
560
+ return stack;
561
+ };
562
+
563
+ exception.stackSourcemapped = true;
564
+ exception.stack = reason.stack;
565
+ if (stackFrames === undefined) {
566
+ // Error.prepareStackTrace not trigerred
567
+ // - reason is not an error
568
+ // - reason.stack already get
569
+ Error.prepareStackTrace = prepareStackTrace;
570
+ exception.stackTrace = getErrorStackTrace(reason);
571
+ } else {
572
+ exception.stackFrames = stackFrames;
573
+ const [firstCallFrame] = stackFrames;
574
+ if (
575
+ exception.site.url === null &&
576
+ firstCallFrame &&
577
+ firstCallFrame.url
578
+ ) {
579
+ Object.assign(exception.site, {
580
+ url: firstCallFrame.url,
581
+ line: firstCallFrame.line,
582
+ column: firstCallFrame.column,
583
+ });
520
584
  }
521
585
  }
522
- return;
586
+ } else {
587
+ exception.stackSourcemapped = false;
588
+ exception.stackTrace = reason.stack;
589
+ exception.stack = stringifyStack(exception);
523
590
  }
524
- if (typeof reason === "object") {
525
- // happens when reason is an Event for instance
526
- exception.code = reason.code;
527
- exception.message = reason.message || message;
528
- exception.stack = reason.stack;
529
- if (reason.reportedBy) {
530
- exception.reportedBy = reason.reportedBy;
591
+
592
+ if (exception.site.url === null && reason.url) {
593
+ Object.assign(exception.site, resolveUrlSite({ url: reason.url }));
594
+ }
595
+ export_missing: {
596
+ // chrome
597
+ if (exception.message.includes("does not provide an export named")) {
598
+ exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
531
599
  }
532
- if (reason.url) {
533
- Object.assign(exception.site, resolveUrlSite({ url: reason.url }));
600
+ // firefox
601
+ if (
602
+ exception.message.startsWith("import not found:") ||
603
+ exception.message.startsWith("ambiguous indirect export:")
604
+ ) {
605
+ exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
606
+ }
607
+ // safari
608
+ if (exception.message.startsWith("import binding name")) {
609
+ exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
610
+ }
611
+ if (exception.message.includes("Importing a module script failed")) {
612
+ exception.code = DYNAMIC_IMPORT_FETCH_ERROR;
613
+ }
614
+ }
615
+ js_syntax_error: {
616
+ if (
617
+ !exception.code &&
618
+ exception.name === "SyntaxError" &&
619
+ typeof line === "number"
620
+ ) {
621
+ exception.code = DYNAMIC_IMPORT_SYNTAX_ERROR;
534
622
  }
535
- return;
536
623
  }
537
- exception.message = JSON.stringify(reason);
538
624
  };
539
625
  writeBasicProperties();
540
626
 
@@ -549,7 +635,8 @@ window.__supervisor__ = (() => {
549
635
  const fileUrlSite = resolveUrlSite({ url, line, column });
550
636
  if (
551
637
  fileUrlSite.isInline &&
552
- exception.code === DYNAMIC_IMPORT_SYNTAX_ERROR
638
+ exception.name === "SyntaxError" &&
639
+ exception.code !== DYNAMIC_IMPORT_EXPORT_MISSING
553
640
  ) {
554
641
  // syntax error on inline script need line-1 for some reason
555
642
  fileUrlSite.line = fileUrlSite.line - 1;
@@ -588,14 +675,15 @@ window.__supervisor__ = (() => {
588
675
  return exception;
589
676
  };
590
677
 
591
- const stringifyStack = ({ name, message, stackTrace }) => {
592
- let stack;
678
+ const stringifyStack = ({ codeFrame, name, message, stackTrace }) => {
679
+ let stack = "";
680
+ if (codeFrame) {
681
+ stack += `${codeFrame}\n`;
682
+ }
593
683
  if (name && message) {
594
- stack = `${name}: ${message}`;
684
+ stack += `${name}: ${message}`;
595
685
  } else if (message) {
596
- stack = message;
597
- } else {
598
- stack = "";
686
+ stack += message;
599
687
  }
600
688
  if (stackTrace) {
601
689
  stack += `\n${stackTrace}`;
@@ -737,153 +825,6 @@ window.__supervisor__ = (() => {
737
825
  });
738
826
  };
739
827
 
740
- let formatError;
741
- error_formatter: {
742
- formatError = (exceptionInfo) => {
743
- const errorParts = {
744
- theme: "dark",
745
- title: "An error occured",
746
- text: "",
747
- tip: "",
748
- errorDetailsPromise: null,
749
- };
750
- const tips = [];
751
- tips.push("Click outside to close.");
752
- errorParts.tip = tips.join(`\n <br />\n `);
753
-
754
- const generateClickableText = (text) => {
755
- const textWithHtmlLinks = makeLinksClickable(text, {
756
- createLink: ({ url, line, column }) => {
757
- const urlSite = resolveUrlSite({ url, line, column });
758
- if (errorBaseUrl) {
759
- if (urlSite.url.startsWith(rootDirectoryUrl)) {
760
- urlSite.url = `${errorBaseUrl}${urlSite.url.slice(
761
- rootDirectoryUrl.length,
762
- )}`;
763
- } else {
764
- urlSite.url = "file:///mocked_for_snapshots";
765
- }
766
- }
767
- const urlWithLineAndColumn = stringifyUrlSite(urlSite);
768
- return {
769
- href:
770
- urlSite.url.startsWith("file:") && openInEditor
771
- ? `javascript:window.fetch('/__open_in_editor__/${encodeURIComponent(
772
- urlWithLineAndColumn,
773
- )}')`
774
- : urlSite.url,
775
- text: urlWithLineAndColumn,
776
- };
777
- },
778
- });
779
- return textWithHtmlLinks;
780
- };
781
-
782
- errorParts.text = stringifyStack({
783
- name: exceptionInfo.name,
784
- message: exceptionInfo.message
785
- ? generateClickableText(exceptionInfo.message)
786
- : "",
787
- stackTrace: exceptionInfo.stackTrace
788
- ? generateClickableText(exceptionInfo.stackTrace)
789
- : "",
790
- });
791
- if (exceptionInfo.site.url) {
792
- errorParts.errorDetailsPromise = (async () => {
793
- if (!serverIsJsenvDevServer) {
794
- return null;
795
- }
796
- try {
797
- if (
798
- exceptionInfo.code === DYNAMIC_IMPORT_FETCH_ERROR ||
799
- exceptionInfo.reportedBy === "script_error_event"
800
- ) {
801
- const response = await window.fetch(
802
- `/__get_error_cause__/${encodeURIComponent(
803
- exceptionInfo.site.isInline
804
- ? exceptionInfo.site.originalUrl
805
- : exceptionInfo.site.url,
806
- )}`,
807
- );
808
- if (response.status !== 200) {
809
- return null;
810
- }
811
- const causeInfo = await response.json();
812
- if (!causeInfo) {
813
- return null;
814
- }
815
- const causeText =
816
- causeInfo.code === "NOT_FOUND"
817
- ? stringifyStack({
818
- name: causeInfo.name,
819
- message: generateClickableText(causeInfo.reason),
820
- stackTrace: generateClickableText(causeInfo.codeFrame),
821
- })
822
- : stringifyStack({
823
- name: causeInfo.name,
824
- message: generateClickableText(causeInfo.stack),
825
- stackTrace: generateClickableText(causeInfo.codeFrame),
826
- });
827
- return {
828
- cause: causeText,
829
- };
830
- }
831
- if (exceptionInfo.site.line !== undefined) {
832
- const urlToFetch = new URL(
833
- `/__get_code_frame__/${encodeURIComponent(
834
- stringifyUrlSite(exceptionInfo.site),
835
- )}`,
836
- window.origin,
837
- );
838
- if (!exceptionInfo.stackSourcemapped) {
839
- urlToFetch.searchParams.set("remap", "");
840
- }
841
- const response = await window.fetch(urlToFetch);
842
- if (response.status !== 200) {
843
- return null;
844
- }
845
- const codeFrame = await response.text();
846
- return {
847
- codeFrame: generateClickableText(codeFrame),
848
- };
849
- }
850
- } catch (e) {
851
- // happens if server is closed for instance
852
- return null;
853
- }
854
- return null;
855
- })();
856
- }
857
- return errorParts;
858
- };
859
-
860
- const makeLinksClickable = (
861
- string,
862
- { createLink = ({ url }) => url },
863
- ) => {
864
- // normalize line breaks
865
- string = string.replace(/\n/g, "\n");
866
- string = escapeHtml(string);
867
- // render links
868
- string = replaceUrls(string, ({ url, line, column }) => {
869
- const { href, text } = createLink({ url, line, column });
870
- return link({ href, text });
871
- });
872
- return string;
873
- };
874
-
875
- const escapeHtml = (string) => {
876
- return string
877
- .replace(/&/g, "&amp;")
878
- .replace(/</g, "&lt;")
879
- .replace(/>/g, "&gt;")
880
- .replace(/"/g, "&quot;")
881
- .replace(/'/g, "&#039;");
882
- };
883
-
884
- const link = ({ href, text = href }) => `<a href="${href}">${text}</a>`;
885
- }
886
-
887
828
  let displayErrorNotification;
888
829
  error_notification: {
889
830
  const { Notification } = window;
@@ -928,51 +869,178 @@ window.__supervisor__ = (() => {
928
869
  };
929
870
 
930
871
  class JsenvErrorOverlay extends HTMLElement {
931
- constructor({ theme, title, text, tip, errorDetailsPromise }) {
872
+ constructor(exception) {
932
873
  super();
933
- this.root = this.attachShadow({ mode: "open" });
934
- this.root.innerHTML = `
874
+ const root = this.attachShadow({ mode: "open" });
875
+ const tips = [];
876
+ tips.push("Click outside to close.");
877
+ const tip = tips.join(`\n <br />\n `);
878
+ root.innerHTML = `
935
879
  <style>
936
880
  ${overlayCSS}
937
881
  </style>
938
882
  <div class="backdrop"></div>
939
- <div class="overlay" data-theme=${theme}>
883
+ <div class="overlay" data-theme="dark">
940
884
  <h1 class="title">
941
- ${title}
885
+ An error occured
942
886
  </h1>
943
- <pre class="text">${text}</pre>
887
+ <pre class="text"></pre>
944
888
  <div class="tip">
945
889
  ${tip}
946
890
  </div>
947
891
  </div>`;
948
- this.root.querySelector(".backdrop").onclick = () => {
892
+ root.querySelector(".backdrop").onclick = () => {
949
893
  if (!this.parentNode) {
950
894
  // not in document anymore
951
895
  return;
952
896
  }
953
- this.root.querySelector(".backdrop").onclick = null;
897
+ root.querySelector(".backdrop").onclick = null;
954
898
  this.parentNode.removeChild(this);
955
899
  };
956
- if (errorDetailsPromise) {
957
- errorDetailsPromise.then((errorDetails) => {
958
- if (!errorDetails || !this.parentNode) {
959
- return;
900
+
901
+ const renderException = () => {
902
+ const { cause = {} } = exception;
903
+ const { trace = {} } = cause;
904
+
905
+ root.querySelector(".text").innerHTML = stringifyStack({
906
+ codeFrame: trace.codeFrame
907
+ ? generateClickableText(trace.codeFrame)
908
+ : "",
909
+ name: exception.name,
910
+ message: exception.message
911
+ ? generateClickableText(exception.message)
912
+ : "",
913
+ stackTrace: exception.stackTrace
914
+ ? generateClickableText(exception.stackTrace)
915
+ : "",
916
+ });
917
+ if (cause) {
918
+ const causeText = stringifyStack({
919
+ name: cause.name,
920
+ message: cause.reason
921
+ ? generateClickableText(cause.reason)
922
+ : cause.stack
923
+ ? generateClickableText(cause.stack)
924
+ : "",
925
+ });
926
+ if (causeText) {
927
+ const causeTextIndented = prefixRemainingLines(causeText, " ");
928
+ root.querySelector(".text").innerHTML +=
929
+ `\n [cause]: ${causeTextIndented}`;
960
930
  }
961
- const { codeFrame, cause } = errorDetails;
962
- if (codeFrame) {
963
- this.root.querySelector(".text").innerHTML +=
964
- `\n\n${codeFrame}`;
931
+ }
932
+ if (
933
+ !exception.stackTrace &&
934
+ (exception.reportedBy === "script_error_event" ||
935
+ exception.reportedBy === "window_error_event" ||
936
+ exception.name === "SyntaxError" ||
937
+ exception.code === DYNAMIC_IMPORT_FETCH_ERROR ||
938
+ exception.code === DYNAMIC_IMPORT_EXPORT_MISSING ||
939
+ exception.code === DYNAMIC_IMPORT_SYNTAX_ERROR)
940
+ ) {
941
+ let traceSite = stringifyUrlSite(trace);
942
+ if (traceSite) {
943
+ root.querySelector(".text").innerHTML +=
944
+ `\n at ${generateClickableText(traceSite)}`;
965
945
  }
966
- if (cause) {
967
- const causeIndented = prefixRemainingLines(cause, " ");
968
- this.root.querySelector(".text").innerHTML +=
969
- `\n [cause]: ${causeIndented}`;
946
+ }
947
+ };
948
+ renderException();
949
+ if (exception.site.url && serverIsJsenvDevServer) {
950
+ (async () => {
951
+ try {
952
+ if (
953
+ exception.code === DYNAMIC_IMPORT_FETCH_ERROR ||
954
+ exception.reportedBy === "script_error_event"
955
+ ) {
956
+ const response = await window.fetch(
957
+ `/__get_error_cause__/${encodeURIComponent(
958
+ exception.site.isInline
959
+ ? exception.site.originalUrl
960
+ : exception.site.url,
961
+ )}`,
962
+ );
963
+ if (response.status !== 200) {
964
+ return;
965
+ }
966
+ const causeInfo = await response.json();
967
+ if (!causeInfo) {
968
+ return;
969
+ }
970
+ exception.cause = causeInfo;
971
+ renderException();
972
+ return;
973
+ }
974
+ if (exception.site.line !== undefined) {
975
+ const urlToFetch = new URL(
976
+ `/__get_cause_trace__/${encodeURIComponent(
977
+ stringifyUrlSite(exception.site),
978
+ )}`,
979
+ window.origin,
980
+ );
981
+ if (!exception.stackSourcemapped) {
982
+ urlToFetch.searchParams.set("remap", "");
983
+ }
984
+ const response = await window.fetch(urlToFetch);
985
+ if (response.status !== 200) {
986
+ return;
987
+ }
988
+ const causeTrace = await response.json();
989
+ exception.cause = {
990
+ trace: causeTrace,
991
+ };
992
+ renderException();
993
+ return;
994
+ }
995
+ } catch (e) {
996
+ // happens if server is closed for instance
997
+ return;
970
998
  }
971
- });
999
+ })();
972
1000
  }
973
1001
  }
974
1002
  }
975
-
1003
+ const generateClickableText = (text) => {
1004
+ const textWithHtmlLinks = makeLinksClickable(text, {
1005
+ createLink: ({ url, line, column }) => {
1006
+ const urlSite = resolveUrlSite({ url, line, column });
1007
+ if (errorBaseUrl) {
1008
+ if (urlSite.url.startsWith(rootDirectoryUrl)) {
1009
+ urlSite.url = `${errorBaseUrl}${urlSite.url.slice(
1010
+ rootDirectoryUrl.length,
1011
+ )}`;
1012
+ } else {
1013
+ urlSite.url = "file:///mocked_for_snapshots";
1014
+ }
1015
+ }
1016
+ const urlWithLineAndColumn = stringifyUrlSite(urlSite);
1017
+ return {
1018
+ href:
1019
+ urlSite.url.startsWith("file:") && openInEditor
1020
+ ? `javascript:window.fetch('/__open_in_editor__/${encodeURIComponent(
1021
+ urlWithLineAndColumn,
1022
+ )}')`
1023
+ : urlSite.url,
1024
+ text: urlWithLineAndColumn,
1025
+ };
1026
+ },
1027
+ });
1028
+ return textWithHtmlLinks;
1029
+ };
1030
+ const makeLinksClickable = (
1031
+ string,
1032
+ { createLink = ({ url }) => url },
1033
+ ) => {
1034
+ // normalize line breaks
1035
+ string = string.replace(/\r\n/g, "\n");
1036
+ string = escapeHtml(string);
1037
+ // render links
1038
+ string = replaceUrls(string, ({ url, line, column }) => {
1039
+ const { href, text } = createLink({ url, line, column });
1040
+ return link({ href, text });
1041
+ });
1042
+ return string;
1043
+ };
976
1044
  const prefixRemainingLines = (text, prefix) => {
977
1045
  const lines = text.split(/\r?\n/);
978
1046
  const firstLine = lines.shift();
@@ -985,6 +1053,15 @@ window.__supervisor__ = (() => {
985
1053
  }
986
1054
  return result;
987
1055
  };
1056
+ const escapeHtml = (string) => {
1057
+ return string
1058
+ .replace(/&/g, "&amp;")
1059
+ .replace(/</g, "&lt;")
1060
+ .replace(/>/g, "&gt;")
1061
+ .replace(/"/g, "&quot;")
1062
+ .replace(/'/g, "&#039;");
1063
+ };
1064
+ const link = ({ href, text = href }) => `<a href="${href}">${text}</a>`;
988
1065
 
989
1066
  if (customElements && !customElements.get(JSENV_ERROR_OVERLAY_TAGNAME)) {
990
1067
  customElements.define(JSENV_ERROR_OVERLAY_TAGNAME, JsenvErrorOverlay);
@@ -1069,17 +1146,8 @@ window.__supervisor__ = (() => {
1069
1146
 
1070
1147
  supervisor.createException = createException;
1071
1148
  supervisor.reportException = (exception) => {
1072
- const { theme, title, text, tip, errorDetailsPromise } =
1073
- formatError(exception);
1074
-
1075
1149
  if (errorOverlay) {
1076
- const removeErrorOverlay = displayJsenvErrorOverlay({
1077
- theme,
1078
- title,
1079
- text,
1080
- tip,
1081
- errorDetailsPromise,
1082
- });
1150
+ const removeErrorOverlay = displayJsenvErrorOverlay(exception);
1083
1151
  if (window.__reloader__) {
1084
1152
  const onchange = window.__reloader__.status.onchange;
1085
1153
  window.__reloader__.status.onchange = () => {
@@ -1092,8 +1160,8 @@ window.__supervisor__ = (() => {
1092
1160
  }
1093
1161
  if (errorNotification) {
1094
1162
  displayErrorNotification({
1095
- title,
1096
- text,
1163
+ title: "An error occured",
1164
+ text: "todo",
1097
1165
  });
1098
1166
  }
1099
1167
  return exception;
@@ -1114,6 +1182,7 @@ window.__supervisor__ = (() => {
1114
1182
  // when error is reported within a worker error is null
1115
1183
  // but there is a message property on errorEvent
1116
1184
  reportedBy: "window_error_event",
1185
+ message,
1117
1186
  url: filename,
1118
1187
  line: lineno,
1119
1188
  column: colno,
@@ -1159,7 +1228,7 @@ window.__supervisor__ = (() => {
1159
1228
  resolve({
1160
1229
  detectedBy: "window_error_event",
1161
1230
  failed: true,
1162
- error: errorEvent,
1231
+ errorEvent,
1163
1232
  });
1164
1233
  }
1165
1234
  };
@@ -1172,7 +1241,7 @@ window.__supervisor__ = (() => {
1172
1241
  resolve({
1173
1242
  detectedBy: "script_error_event",
1174
1243
  failed: true,
1175
- error: errorEvent,
1244
+ errorEvent,
1176
1245
  });
1177
1246
  });
1178
1247
  script.addEventListener("load", () => {