@jsenv/plugin-supervisor 1.4.0 → 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.
- package/dist/js/supervisor.js +309 -256
- package/dist/jsenv_plugin_supervisor.js +118 -139
- package/package.json +4 -4
- package/src/client/supervisor.js +332 -263
- package/src/jsenv_plugin_supervisor.js +16 -10
package/dist/js/supervisor.js
CHANGED
|
@@ -163,17 +163,27 @@ window.__supervisor__ = (() => {
|
|
|
163
163
|
const {
|
|
164
164
|
detectedBy,
|
|
165
165
|
failed,
|
|
166
|
-
|
|
166
|
+
errorEvent
|
|
167
167
|
} = await scriptLoadPromise;
|
|
168
168
|
if (failed) {
|
|
169
|
+
const messageDefault = "Error while loading script";
|
|
170
|
+
const {
|
|
171
|
+
error,
|
|
172
|
+
message,
|
|
173
|
+
filename,
|
|
174
|
+
lineno,
|
|
175
|
+
colno
|
|
176
|
+
} = errorEvent;
|
|
169
177
|
if (detectedBy === "script_error_event") {
|
|
170
178
|
// window.error won't be dispatched for this error
|
|
171
|
-
reportErrorBackToBrowser(error);
|
|
179
|
+
reportErrorBackToBrowser(error || errorEvent);
|
|
172
180
|
}
|
|
173
|
-
fail(error, {
|
|
174
|
-
message:
|
|
181
|
+
fail(error || message || messageDefault, {
|
|
182
|
+
message: messageDefault,
|
|
175
183
|
reportedBy: "script_error_event",
|
|
176
|
-
url: urlObject.href
|
|
184
|
+
url: filename || urlObject.href,
|
|
185
|
+
line: lineno,
|
|
186
|
+
column: colno
|
|
177
187
|
});
|
|
178
188
|
if (detectedBy === "script_error_event") {
|
|
179
189
|
supervisor.reportException(result.exception);
|
|
@@ -236,7 +246,7 @@ window.__supervisor__ = (() => {
|
|
|
236
246
|
return result;
|
|
237
247
|
} catch (e) {
|
|
238
248
|
fail(e, {
|
|
239
|
-
message: "Error while importing module
|
|
249
|
+
message: "Error while importing module",
|
|
240
250
|
reportedBy: "dynamic_import",
|
|
241
251
|
url: urlObject.href
|
|
242
252
|
});
|
|
@@ -289,16 +299,26 @@ window.__supervisor__ = (() => {
|
|
|
289
299
|
const {
|
|
290
300
|
detectedBy,
|
|
291
301
|
failed,
|
|
292
|
-
|
|
302
|
+
errorEvent
|
|
293
303
|
} = await scriptLoadResultPromise;
|
|
294
304
|
if (failed) {
|
|
305
|
+
const messageDefault = "Error while loading module";
|
|
306
|
+
const {
|
|
307
|
+
error,
|
|
308
|
+
message,
|
|
309
|
+
filename,
|
|
310
|
+
lineno,
|
|
311
|
+
colno
|
|
312
|
+
} = errorEvent;
|
|
295
313
|
// if (detectedBy === "script_error_event") {
|
|
296
314
|
// reportErrorBackToBrowser(error)
|
|
297
315
|
// }
|
|
298
|
-
fail(error, {
|
|
299
|
-
message:
|
|
316
|
+
fail(error || message || messageDefault, {
|
|
317
|
+
message: messageDefault,
|
|
300
318
|
reportedBy: "script_error_event",
|
|
301
|
-
url: urlObject.href
|
|
319
|
+
url: filename || urlObject.href,
|
|
320
|
+
line: lineno,
|
|
321
|
+
column: colno
|
|
302
322
|
});
|
|
303
323
|
if (detectedBy === "script_error_event") {
|
|
304
324
|
supervisor.reportException(result.exception);
|
|
@@ -471,10 +491,11 @@ window.__supervisor__ = (() => {
|
|
|
471
491
|
// the stack from runtime, not normalized to v8
|
|
472
492
|
stackTrace: "",
|
|
473
493
|
// the stack trace (without error name and message)
|
|
494
|
+
stackFrames: undefined,
|
|
474
495
|
withServerUrls: {
|
|
475
496
|
message: "",
|
|
476
|
-
|
|
477
|
-
|
|
497
|
+
stack: "",
|
|
498
|
+
stackTrace: ""
|
|
478
499
|
},
|
|
479
500
|
meta: null,
|
|
480
501
|
site: {
|
|
@@ -498,76 +519,140 @@ window.__supervisor__ = (() => {
|
|
|
498
519
|
exception.message = reason;
|
|
499
520
|
return;
|
|
500
521
|
}
|
|
501
|
-
if (reason
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
522
|
+
if (typeof reason !== "object") {
|
|
523
|
+
exception.message = JSON.stringify(reason);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
// isError can be false when reason is an ErrorEvent for instance
|
|
527
|
+
exception.isError = reason instanceof Error;
|
|
528
|
+
exception.name = reason.name || "Error";
|
|
529
|
+
exception.message = reason.message || message || "";
|
|
530
|
+
let stackFrames;
|
|
531
|
+
if (exception.isError && Error.captureStackTrace &&
|
|
532
|
+
// captureStackTrace exists on webkit but error.stack is not v8
|
|
533
|
+
!isWebkitOrSafari) {
|
|
534
|
+
// stackTrace formatted by V8
|
|
535
|
+
const {
|
|
536
|
+
prepareStackTrace
|
|
537
|
+
} = Error;
|
|
538
|
+
Error.prepareStackTrace = (e, callSites) => {
|
|
539
|
+
Error.prepareStackTrace = prepareStackTrace;
|
|
540
|
+
const getPropertiesFromEvalOrigin = origin => {
|
|
541
|
+
// Most eval() calls are in this format
|
|
542
|
+
const topLevelEvalMatch = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin);
|
|
543
|
+
if (topLevelEvalMatch) {
|
|
544
|
+
const source = topLevelEvalMatch[2];
|
|
545
|
+
const line = Number(topLevelEvalMatch[3]);
|
|
546
|
+
const column = topLevelEvalMatch[4] - 1;
|
|
547
|
+
return {
|
|
548
|
+
url: source,
|
|
549
|
+
line,
|
|
550
|
+
column
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
// Parse nested eval() calls using recursion
|
|
554
|
+
const nestedEvalMatch = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
|
|
555
|
+
if (nestedEvalMatch) {
|
|
556
|
+
return getPropertiesFromEvalOrigin(nestedEvalMatch[2]);
|
|
557
|
+
}
|
|
558
|
+
return null;
|
|
559
|
+
};
|
|
560
|
+
stackFrames = [];
|
|
561
|
+
for (const callSite of callSites) {
|
|
562
|
+
const url = callSite.getFileName() || callSite.getScriptNameOrSourceURL();
|
|
563
|
+
const line = callSite.getLineNumber();
|
|
564
|
+
const column = callSite.getColumnNumber();
|
|
565
|
+
const site = resolveUrlSite({
|
|
566
|
+
url,
|
|
567
|
+
line,
|
|
568
|
+
column
|
|
569
|
+
});
|
|
570
|
+
const stackFrame = {
|
|
571
|
+
raw: " at ".concat(String(callSite)),
|
|
572
|
+
url: site.url,
|
|
573
|
+
line: site.line,
|
|
574
|
+
column: site.column,
|
|
575
|
+
functionName: callSite.getFunctionName(),
|
|
576
|
+
isNative: callSite.isNative(),
|
|
577
|
+
isEval: callSite.isEval(),
|
|
578
|
+
isConstructor: callSite.isConstructor(),
|
|
579
|
+
isAsync: callSite.isAsync(),
|
|
580
|
+
evalSite: null
|
|
581
|
+
};
|
|
582
|
+
if (stackFrame.isEval) {
|
|
583
|
+
const evalOrigin = stackFrame.getEvalOrigin();
|
|
584
|
+
if (evalOrigin) {
|
|
585
|
+
stackFrame.evalSite = getPropertiesFromEvalOrigin(evalOrigin);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
stackFrames.push(stackFrame);
|
|
536
589
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
590
|
+
let stackTrace = "";
|
|
591
|
+
for (const stackFrame of stackFrames) {
|
|
592
|
+
if (stackTrace) stackTrace += "\n";
|
|
593
|
+
stackTrace += stackFrame.raw;
|
|
541
594
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
595
|
+
exception.stackTrace = stackTrace;
|
|
596
|
+
let stack = "";
|
|
597
|
+
const name = reason.name || "Error";
|
|
598
|
+
const message = reason.message || "";
|
|
599
|
+
stack += "".concat(name, ": ").concat(message);
|
|
600
|
+
if (stackTrace) {
|
|
601
|
+
stack += "\n".concat(stackTrace);
|
|
545
602
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
603
|
+
return stack;
|
|
604
|
+
};
|
|
605
|
+
exception.stackSourcemapped = true;
|
|
606
|
+
exception.stack = reason.stack;
|
|
607
|
+
if (stackFrames === undefined) {
|
|
608
|
+
// Error.prepareStackTrace not trigerred
|
|
609
|
+
// - reason is not an error
|
|
610
|
+
// - reason.stack already get
|
|
611
|
+
Error.prepareStackTrace = prepareStackTrace;
|
|
612
|
+
exception.stackTrace = getErrorStackTrace(reason);
|
|
613
|
+
} else {
|
|
614
|
+
exception.stackFrames = stackFrames;
|
|
615
|
+
const [firstCallFrame] = stackFrames;
|
|
616
|
+
if (exception.site.url === null && firstCallFrame && firstCallFrame.url) {
|
|
617
|
+
Object.assign(exception.site, {
|
|
618
|
+
url: firstCallFrame.url,
|
|
619
|
+
line: firstCallFrame.line,
|
|
620
|
+
column: firstCallFrame.column
|
|
621
|
+
});
|
|
551
622
|
}
|
|
552
623
|
}
|
|
553
|
-
|
|
624
|
+
} else {
|
|
625
|
+
exception.stackSourcemapped = false;
|
|
626
|
+
exception.stackTrace = reason.stack;
|
|
627
|
+
exception.stack = stringifyStack(exception);
|
|
554
628
|
}
|
|
555
|
-
if (
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
629
|
+
if (exception.site.url === null && reason.url) {
|
|
630
|
+
Object.assign(exception.site, resolveUrlSite({
|
|
631
|
+
url: reason.url
|
|
632
|
+
}));
|
|
633
|
+
}
|
|
634
|
+
{
|
|
635
|
+
// chrome
|
|
636
|
+
if (exception.message.includes("does not provide an export named")) {
|
|
637
|
+
exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
|
|
562
638
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
639
|
+
// firefox
|
|
640
|
+
if (exception.message.startsWith("import not found:") || exception.message.startsWith("ambiguous indirect export:")) {
|
|
641
|
+
exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
|
|
642
|
+
}
|
|
643
|
+
// safari
|
|
644
|
+
if (exception.message.startsWith("import binding name")) {
|
|
645
|
+
exception.code = DYNAMIC_IMPORT_EXPORT_MISSING;
|
|
646
|
+
}
|
|
647
|
+
if (exception.message.includes("Importing a module script failed")) {
|
|
648
|
+
exception.code = DYNAMIC_IMPORT_FETCH_ERROR;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
{
|
|
652
|
+
if (!exception.code && exception.name === "SyntaxError" && typeof line === "number") {
|
|
653
|
+
exception.code = DYNAMIC_IMPORT_SYNTAX_ERROR;
|
|
567
654
|
}
|
|
568
|
-
return;
|
|
569
655
|
}
|
|
570
|
-
exception.message = JSON.stringify(reason);
|
|
571
656
|
};
|
|
572
657
|
writeBasicProperties();
|
|
573
658
|
|
|
@@ -584,7 +669,7 @@ window.__supervisor__ = (() => {
|
|
|
584
669
|
line,
|
|
585
670
|
column
|
|
586
671
|
});
|
|
587
|
-
if (fileUrlSite.isInline && exception.
|
|
672
|
+
if (fileUrlSite.isInline && exception.name === "SyntaxError" && exception.code !== DYNAMIC_IMPORT_EXPORT_MISSING) {
|
|
588
673
|
// syntax error on inline script need line-1 for some reason
|
|
589
674
|
fileUrlSite.line = fileUrlSite.line - 1;
|
|
590
675
|
}
|
|
@@ -617,17 +702,19 @@ window.__supervisor__ = (() => {
|
|
|
617
702
|
return exception;
|
|
618
703
|
};
|
|
619
704
|
const stringifyStack = ({
|
|
705
|
+
codeFrame,
|
|
620
706
|
name,
|
|
621
707
|
message,
|
|
622
708
|
stackTrace
|
|
623
709
|
}) => {
|
|
624
|
-
let stack;
|
|
710
|
+
let stack = "";
|
|
711
|
+
if (codeFrame) {
|
|
712
|
+
stack += "".concat(codeFrame, "\n");
|
|
713
|
+
}
|
|
625
714
|
if (name && message) {
|
|
626
|
-
stack
|
|
715
|
+
stack += "".concat(name, ": ").concat(message);
|
|
627
716
|
} else if (message) {
|
|
628
|
-
stack
|
|
629
|
-
} else {
|
|
630
|
-
stack = "";
|
|
717
|
+
stack += message;
|
|
631
718
|
}
|
|
632
719
|
if (stackTrace) {
|
|
633
720
|
stack += "\n".concat(stackTrace);
|
|
@@ -764,140 +851,6 @@ window.__supervisor__ = (() => {
|
|
|
764
851
|
return replacement;
|
|
765
852
|
});
|
|
766
853
|
};
|
|
767
|
-
let formatError;
|
|
768
|
-
{
|
|
769
|
-
formatError = exceptionInfo => {
|
|
770
|
-
const errorParts = {
|
|
771
|
-
theme: "dark",
|
|
772
|
-
title: "An error occured",
|
|
773
|
-
text: "",
|
|
774
|
-
tip: "",
|
|
775
|
-
errorDetailsPromise: null
|
|
776
|
-
};
|
|
777
|
-
const tips = [];
|
|
778
|
-
tips.push("Click outside to close.");
|
|
779
|
-
errorParts.tip = tips.join("\n <br />\n ");
|
|
780
|
-
const generateClickableText = text => {
|
|
781
|
-
const textWithHtmlLinks = makeLinksClickable(text, {
|
|
782
|
-
createLink: ({
|
|
783
|
-
url,
|
|
784
|
-
line,
|
|
785
|
-
column
|
|
786
|
-
}) => {
|
|
787
|
-
const urlSite = resolveUrlSite({
|
|
788
|
-
url,
|
|
789
|
-
line,
|
|
790
|
-
column
|
|
791
|
-
});
|
|
792
|
-
if (errorBaseUrl) {
|
|
793
|
-
if (urlSite.url.startsWith(rootDirectoryUrl)) {
|
|
794
|
-
urlSite.url = "".concat(errorBaseUrl).concat(urlSite.url.slice(rootDirectoryUrl.length));
|
|
795
|
-
} else {
|
|
796
|
-
urlSite.url = "file:///mocked_for_snapshots";
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
const urlWithLineAndColumn = stringifyUrlSite(urlSite);
|
|
800
|
-
return {
|
|
801
|
-
href: urlSite.url.startsWith("file:") && openInEditor ? "javascript:window.fetch('/__open_in_editor__/".concat(encodeURIComponent(urlWithLineAndColumn), "')") : urlSite.url,
|
|
802
|
-
text: urlWithLineAndColumn
|
|
803
|
-
};
|
|
804
|
-
}
|
|
805
|
-
});
|
|
806
|
-
return textWithHtmlLinks;
|
|
807
|
-
};
|
|
808
|
-
errorParts.text = stringifyStack({
|
|
809
|
-
name: exceptionInfo.name,
|
|
810
|
-
message: exceptionInfo.message ? generateClickableText(exceptionInfo.message) : "",
|
|
811
|
-
stackTrace: exceptionInfo.stackTrace ? generateClickableText(exceptionInfo.stackTrace) : ""
|
|
812
|
-
});
|
|
813
|
-
if (exceptionInfo.site.url) {
|
|
814
|
-
errorParts.errorDetailsPromise = (async () => {
|
|
815
|
-
if (!serverIsJsenvDevServer) {
|
|
816
|
-
return null;
|
|
817
|
-
}
|
|
818
|
-
try {
|
|
819
|
-
if (exceptionInfo.code === DYNAMIC_IMPORT_FETCH_ERROR || exceptionInfo.reportedBy === "script_error_event") {
|
|
820
|
-
const response = await window.fetch("/__get_error_cause__/".concat(encodeURIComponent(exceptionInfo.site.isInline ? exceptionInfo.site.originalUrl : exceptionInfo.site.url)));
|
|
821
|
-
if (response.status !== 200) {
|
|
822
|
-
return null;
|
|
823
|
-
}
|
|
824
|
-
const causeInfo = await response.json();
|
|
825
|
-
if (!causeInfo) {
|
|
826
|
-
return null;
|
|
827
|
-
}
|
|
828
|
-
const causeText = causeInfo.code === "NOT_FOUND" ? stringifyStack({
|
|
829
|
-
name: causeInfo.name,
|
|
830
|
-
message: generateClickableText(causeInfo.reason),
|
|
831
|
-
stackTrace: generateClickableText(causeInfo.codeFrame)
|
|
832
|
-
}) : stringifyStack({
|
|
833
|
-
name: causeInfo.name,
|
|
834
|
-
message: generateClickableText(causeInfo.stack),
|
|
835
|
-
stackTrace: generateClickableText(causeInfo.codeFrame)
|
|
836
|
-
});
|
|
837
|
-
return {
|
|
838
|
-
cause: causeText
|
|
839
|
-
};
|
|
840
|
-
}
|
|
841
|
-
if (exceptionInfo.site.line !== undefined) {
|
|
842
|
-
const urlToFetch = new URL("/__get_code_frame__/".concat(encodeURIComponent(stringifyUrlSite(exceptionInfo.site))), window.origin);
|
|
843
|
-
if (!exceptionInfo.stackSourcemapped) {
|
|
844
|
-
urlToFetch.searchParams.set("remap", "");
|
|
845
|
-
}
|
|
846
|
-
const response = await window.fetch(urlToFetch);
|
|
847
|
-
if (response.status !== 200) {
|
|
848
|
-
return null;
|
|
849
|
-
}
|
|
850
|
-
const codeFrame = await response.text();
|
|
851
|
-
return {
|
|
852
|
-
codeFrame: generateClickableText(codeFrame)
|
|
853
|
-
};
|
|
854
|
-
}
|
|
855
|
-
} catch (e) {
|
|
856
|
-
// happens if server is closed for instance
|
|
857
|
-
return null;
|
|
858
|
-
}
|
|
859
|
-
return null;
|
|
860
|
-
})();
|
|
861
|
-
}
|
|
862
|
-
return errorParts;
|
|
863
|
-
};
|
|
864
|
-
const makeLinksClickable = (string, {
|
|
865
|
-
createLink = ({
|
|
866
|
-
url
|
|
867
|
-
}) => url
|
|
868
|
-
}) => {
|
|
869
|
-
// normalize line breaks
|
|
870
|
-
string = string.replace(/\n/g, "\n");
|
|
871
|
-
string = escapeHtml(string);
|
|
872
|
-
// render links
|
|
873
|
-
string = replaceUrls(string, ({
|
|
874
|
-
url,
|
|
875
|
-
line,
|
|
876
|
-
column
|
|
877
|
-
}) => {
|
|
878
|
-
const {
|
|
879
|
-
href,
|
|
880
|
-
text
|
|
881
|
-
} = createLink({
|
|
882
|
-
url,
|
|
883
|
-
line,
|
|
884
|
-
column
|
|
885
|
-
});
|
|
886
|
-
return link({
|
|
887
|
-
href,
|
|
888
|
-
text
|
|
889
|
-
});
|
|
890
|
-
});
|
|
891
|
-
return string;
|
|
892
|
-
};
|
|
893
|
-
const escapeHtml = string => {
|
|
894
|
-
return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
895
|
-
};
|
|
896
|
-
const link = ({
|
|
897
|
-
href,
|
|
898
|
-
text = href
|
|
899
|
-
}) => "<a href=\"".concat(href, "\">").concat(text, "</a>");
|
|
900
|
-
}
|
|
901
854
|
let displayErrorNotification;
|
|
902
855
|
{
|
|
903
856
|
const {
|
|
@@ -941,46 +894,151 @@ window.__supervisor__ = (() => {
|
|
|
941
894
|
return removeErrorOverlay;
|
|
942
895
|
};
|
|
943
896
|
class JsenvErrorOverlay extends HTMLElement {
|
|
944
|
-
constructor({
|
|
945
|
-
theme,
|
|
946
|
-
title,
|
|
947
|
-
text,
|
|
948
|
-
tip,
|
|
949
|
-
errorDetailsPromise
|
|
950
|
-
}) {
|
|
897
|
+
constructor(exception) {
|
|
951
898
|
super();
|
|
952
|
-
|
|
899
|
+
const root = this.attachShadow({
|
|
953
900
|
mode: "open"
|
|
954
901
|
});
|
|
955
|
-
|
|
956
|
-
|
|
902
|
+
const tips = [];
|
|
903
|
+
tips.push("Click outside to close.");
|
|
904
|
+
const tip = tips.join("\n <br />\n ");
|
|
905
|
+
root.innerHTML = "\n<style>\n ".concat(overlayCSS, "\n</style>\n<div class=\"backdrop\"></div>\n<div class=\"overlay\" data-theme=\"dark\">\n <h1 class=\"title\">\n An error occured\n </h1>\n <pre class=\"text\"></pre>\n <div class=\"tip\">\n ").concat(tip, "\n </div>\n</div>");
|
|
906
|
+
root.querySelector(".backdrop").onclick = () => {
|
|
957
907
|
if (!this.parentNode) {
|
|
958
908
|
// not in document anymore
|
|
959
909
|
return;
|
|
960
910
|
}
|
|
961
|
-
|
|
911
|
+
root.querySelector(".backdrop").onclick = null;
|
|
962
912
|
this.parentNode.removeChild(this);
|
|
963
913
|
};
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
914
|
+
const renderException = () => {
|
|
915
|
+
const {
|
|
916
|
+
cause = {}
|
|
917
|
+
} = exception;
|
|
918
|
+
const {
|
|
919
|
+
trace = {}
|
|
920
|
+
} = cause;
|
|
921
|
+
root.querySelector(".text").innerHTML = stringifyStack({
|
|
922
|
+
codeFrame: trace.codeFrame ? generateClickableText(trace.codeFrame) : "",
|
|
923
|
+
name: exception.name,
|
|
924
|
+
message: exception.message ? generateClickableText(exception.message) : "",
|
|
925
|
+
stackTrace: exception.stackTrace ? generateClickableText(exception.stackTrace) : ""
|
|
926
|
+
});
|
|
927
|
+
if (cause) {
|
|
928
|
+
const causeText = stringifyStack({
|
|
929
|
+
name: cause.name,
|
|
930
|
+
message: cause.reason ? generateClickableText(cause.reason) : cause.stack ? generateClickableText(cause.stack) : ""
|
|
931
|
+
});
|
|
932
|
+
if (causeText) {
|
|
933
|
+
const causeTextIndented = prefixRemainingLines(causeText, " ");
|
|
934
|
+
root.querySelector(".text").innerHTML += "\n [cause]: ".concat(causeTextIndented);
|
|
968
935
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
this.root.querySelector(".text").innerHTML += "\n\n".concat(codeFrame);
|
|
936
|
+
}
|
|
937
|
+
if (!exception.stackTrace && (exception.reportedBy === "script_error_event" || exception.reportedBy === "window_error_event" || exception.name === "SyntaxError" || exception.code === DYNAMIC_IMPORT_FETCH_ERROR || exception.code === DYNAMIC_IMPORT_EXPORT_MISSING || exception.code === DYNAMIC_IMPORT_SYNTAX_ERROR)) {
|
|
938
|
+
let traceSite = stringifyUrlSite(trace);
|
|
939
|
+
if (traceSite) {
|
|
940
|
+
root.querySelector(".text").innerHTML += "\n at ".concat(generateClickableText(traceSite));
|
|
975
941
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
renderException();
|
|
945
|
+
if (exception.site.url && serverIsJsenvDevServer) {
|
|
946
|
+
(async () => {
|
|
947
|
+
try {
|
|
948
|
+
if (exception.code === DYNAMIC_IMPORT_FETCH_ERROR || exception.reportedBy === "script_error_event") {
|
|
949
|
+
const response = await window.fetch("/__get_error_cause__/".concat(encodeURIComponent(exception.site.isInline ? exception.site.originalUrl : exception.site.url)));
|
|
950
|
+
if (response.status !== 200) {
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
const causeInfo = await response.json();
|
|
954
|
+
if (!causeInfo) {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
exception.cause = causeInfo;
|
|
958
|
+
renderException();
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
if (exception.site.line !== undefined) {
|
|
962
|
+
const urlToFetch = new URL("/__get_cause_trace__/".concat(encodeURIComponent(stringifyUrlSite(exception.site))), window.origin);
|
|
963
|
+
if (!exception.stackSourcemapped) {
|
|
964
|
+
urlToFetch.searchParams.set("remap", "");
|
|
965
|
+
}
|
|
966
|
+
const response = await window.fetch(urlToFetch);
|
|
967
|
+
if (response.status !== 200) {
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
const causeTrace = await response.json();
|
|
971
|
+
exception.cause = {
|
|
972
|
+
trace: causeTrace
|
|
973
|
+
};
|
|
974
|
+
renderException();
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
} catch (e) {
|
|
978
|
+
// happens if server is closed for instance
|
|
979
|
+
return;
|
|
979
980
|
}
|
|
980
|
-
});
|
|
981
|
+
})();
|
|
981
982
|
}
|
|
982
983
|
}
|
|
983
984
|
}
|
|
985
|
+
const generateClickableText = text => {
|
|
986
|
+
const textWithHtmlLinks = makeLinksClickable(text, {
|
|
987
|
+
createLink: ({
|
|
988
|
+
url,
|
|
989
|
+
line,
|
|
990
|
+
column
|
|
991
|
+
}) => {
|
|
992
|
+
const urlSite = resolveUrlSite({
|
|
993
|
+
url,
|
|
994
|
+
line,
|
|
995
|
+
column
|
|
996
|
+
});
|
|
997
|
+
if (errorBaseUrl) {
|
|
998
|
+
if (urlSite.url.startsWith(rootDirectoryUrl)) {
|
|
999
|
+
urlSite.url = "".concat(errorBaseUrl).concat(urlSite.url.slice(rootDirectoryUrl.length));
|
|
1000
|
+
} else {
|
|
1001
|
+
urlSite.url = "file:///mocked_for_snapshots";
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
const urlWithLineAndColumn = stringifyUrlSite(urlSite);
|
|
1005
|
+
return {
|
|
1006
|
+
href: urlSite.url.startsWith("file:") && openInEditor ? "javascript:window.fetch('/__open_in_editor__/".concat(encodeURIComponent(urlWithLineAndColumn), "')") : urlSite.url,
|
|
1007
|
+
text: urlWithLineAndColumn
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
return textWithHtmlLinks;
|
|
1012
|
+
};
|
|
1013
|
+
const makeLinksClickable = (string, {
|
|
1014
|
+
createLink = ({
|
|
1015
|
+
url
|
|
1016
|
+
}) => url
|
|
1017
|
+
}) => {
|
|
1018
|
+
// normalize line breaks
|
|
1019
|
+
string = string.replace(/\r\n/g, "\n");
|
|
1020
|
+
string = escapeHtml(string);
|
|
1021
|
+
// render links
|
|
1022
|
+
string = replaceUrls(string, ({
|
|
1023
|
+
url,
|
|
1024
|
+
line,
|
|
1025
|
+
column
|
|
1026
|
+
}) => {
|
|
1027
|
+
const {
|
|
1028
|
+
href,
|
|
1029
|
+
text
|
|
1030
|
+
} = createLink({
|
|
1031
|
+
url,
|
|
1032
|
+
line,
|
|
1033
|
+
column
|
|
1034
|
+
});
|
|
1035
|
+
return link({
|
|
1036
|
+
href,
|
|
1037
|
+
text
|
|
1038
|
+
});
|
|
1039
|
+
});
|
|
1040
|
+
return string;
|
|
1041
|
+
};
|
|
984
1042
|
const prefixRemainingLines = (text, prefix) => {
|
|
985
1043
|
const lines = text.split(/\r?\n/);
|
|
986
1044
|
const firstLine = lines.shift();
|
|
@@ -993,6 +1051,13 @@ window.__supervisor__ = (() => {
|
|
|
993
1051
|
}
|
|
994
1052
|
return result;
|
|
995
1053
|
};
|
|
1054
|
+
const escapeHtml = string => {
|
|
1055
|
+
return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1056
|
+
};
|
|
1057
|
+
const link = ({
|
|
1058
|
+
href,
|
|
1059
|
+
text = href
|
|
1060
|
+
}) => "<a href=\"".concat(href, "\">").concat(text, "</a>");
|
|
996
1061
|
if (customElements && !customElements.get(JSENV_ERROR_OVERLAY_TAGNAME)) {
|
|
997
1062
|
customElements.define(JSENV_ERROR_OVERLAY_TAGNAME, JsenvErrorOverlay);
|
|
998
1063
|
}
|
|
@@ -1000,21 +1065,8 @@ window.__supervisor__ = (() => {
|
|
|
1000
1065
|
}
|
|
1001
1066
|
supervisor.createException = createException;
|
|
1002
1067
|
supervisor.reportException = exception => {
|
|
1003
|
-
const {
|
|
1004
|
-
theme,
|
|
1005
|
-
title,
|
|
1006
|
-
text,
|
|
1007
|
-
tip,
|
|
1008
|
-
errorDetailsPromise
|
|
1009
|
-
} = formatError(exception);
|
|
1010
1068
|
if (errorOverlay) {
|
|
1011
|
-
const removeErrorOverlay = displayJsenvErrorOverlay(
|
|
1012
|
-
theme,
|
|
1013
|
-
title,
|
|
1014
|
-
text,
|
|
1015
|
-
tip,
|
|
1016
|
-
errorDetailsPromise
|
|
1017
|
-
});
|
|
1069
|
+
const removeErrorOverlay = displayJsenvErrorOverlay(exception);
|
|
1018
1070
|
if (window.__reloader__) {
|
|
1019
1071
|
const onchange = window.__reloader__.status.onchange;
|
|
1020
1072
|
window.__reloader__.status.onchange = () => {
|
|
@@ -1027,8 +1079,8 @@ window.__supervisor__ = (() => {
|
|
|
1027
1079
|
}
|
|
1028
1080
|
if (errorNotification) {
|
|
1029
1081
|
displayErrorNotification({
|
|
1030
|
-
title,
|
|
1031
|
-
text
|
|
1082
|
+
title: "An error occured",
|
|
1083
|
+
text: "todo"
|
|
1032
1084
|
});
|
|
1033
1085
|
}
|
|
1034
1086
|
return exception;
|
|
@@ -1055,6 +1107,7 @@ window.__supervisor__ = (() => {
|
|
|
1055
1107
|
// when error is reported within a worker error is null
|
|
1056
1108
|
// but there is a message property on errorEvent
|
|
1057
1109
|
reportedBy: "window_error_event",
|
|
1110
|
+
message,
|
|
1058
1111
|
url: filename,
|
|
1059
1112
|
line: lineno,
|
|
1060
1113
|
column: colno
|
|
@@ -1097,7 +1150,7 @@ window.__supervisor__ = (() => {
|
|
|
1097
1150
|
resolve({
|
|
1098
1151
|
detectedBy: "window_error_event",
|
|
1099
1152
|
failed: true,
|
|
1100
|
-
|
|
1153
|
+
errorEvent
|
|
1101
1154
|
});
|
|
1102
1155
|
}
|
|
1103
1156
|
};
|
|
@@ -1110,7 +1163,7 @@ window.__supervisor__ = (() => {
|
|
|
1110
1163
|
resolve({
|
|
1111
1164
|
detectedBy: "script_error_event",
|
|
1112
1165
|
failed: true,
|
|
1113
|
-
|
|
1166
|
+
errorEvent
|
|
1114
1167
|
});
|
|
1115
1168
|
});
|
|
1116
1169
|
script.addEventListener("load", () => {
|