Skip to content

Commit da8075a

Browse files
committed
Add Error.cause and stack to the error output
1 parent 5bc12b3 commit da8075a

File tree

3 files changed

+95
-16
lines changed

3 files changed

+95
-16
lines changed

content/JavaScript/error.jsdoc

+52-7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ Same as %%#new_Error_String|**new Error(message)**%%.
2323
Spec:
2424
http://www.ecma-international.org/ecma-262/5.1/#sec-15.11.1.1
2525

26+
----
27+
Error(message : String, options : Object) : Error
28+
29+
Same as %%#new_Error_String_Object|**new Error(message, options)**%%.
30+
31+
Spec:
32+
https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-error-constructor
33+
2634
----
2735
new Error(message : String) : Error
2836

@@ -37,7 +45,7 @@ var divide = function(x, y) {
3745
};
3846

3947
try {
40-
console.log(divide(10, 0));
48+
console.log(divide(10, 0));
4149
}
4250
catch (error) {
4351
console.log(error.name);
@@ -49,21 +57,42 @@ Spec:
4957
http://www.ecma-international.org/ecma-262/5.1/#sec-15.11.2.1
5058

5159
----
52-
prototype.name : String
60+
new Error(message : String, options : { cause : Error }) : Error
5361

54-
The type of error.
62+
Creates a new **Error** with the specified **message** that describes the error and
63+
original **cause** of the error.
5564

5665
<example>
66+
var validateNumber = function(x) {
67+
if (typeof x !== 'number') {
68+
throw Error(x + ' is not a number');
69+
}
70+
return x;
71+
};
72+
73+
var multiply = function(x, y) {
74+
try {
75+
return validateNumber(x) * validateNumber(y);
76+
}
77+
catch(e) {
78+
throw Error('Unable to multiply', { cause: e });
79+
}
80+
};
81+
5782
try {
58-
foo;
83+
console.log(multiply(3, 'abc'));
5984
}
6085
catch (error) {
61-
console.log(error.name);
86+
console.log(error);
87+
console.log('Cause:', error.cause);
6288
}
6389
</example>
6490

6591
Spec:
66-
http://www.ecma-international.org/ecma-262/5.1/#sec-15.11.4.2
92+
https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-error-constructor
93+
94+
Version:
95+
ECMAScript 2022
6796

6897
----
6998
prototype.message : String
@@ -72,7 +101,7 @@ A human readable message that describes the error.
72101

73102
<example>
74103
try {
75-
foo;
104+
foo;
76105
}
77106
catch (error) {
78107
console.log(error.message);
@@ -82,3 +111,19 @@ catch (error) {
82111
Spec:
83112
http://www.ecma-international.org/ecma-262/5.1/#sec-15.11.4.3
84113

114+
----
115+
prototype.name : String
116+
117+
The type of error.
118+
119+
<example>
120+
try {
121+
foo;
122+
}
123+
catch (error) {
124+
console.log(error.name);
125+
}
126+
</example>
127+
128+
Spec:
129+
http://www.ecma-international.org/ecma-262/5.1/#sec-15.11.4.2

static/styles.css

+2-1
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ h1.declaration {
397397
padding: 0.5em;
398398
font-family: Menlo, consolas, monospace;
399399
font-size: 0.8em;
400+
white-space: pre;
400401
box-shadow: 2px 2px 5px -1px rgba(102, 92, 48, 0.8); }
401402

402403
.errormessage {
@@ -600,6 +601,6 @@ div.popup {
600601
.members-collapsed .member-body {
601602
display: none; }
602603

603-
.ecmascript2019, .ecmascript2020, .ecmascript2021 {
604+
.ecmascript2020, .ecmascript2021, .ecmascript2022 {
604605
background: #FFE780;
605606
color: #413500; }

templates/javascripture.ejs

+41-8
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,39 @@ var escapeHTML = function(s) {
474474
});
475475
}
476476

477+
var getErrorMessage = function(error, fromUnhandledRejection) {
478+
var message = fromUnhandledRejection ? 'Promise rejected: ' : '';
479+
480+
if (error.stack) {
481+
// Replace blob url with 'example'
482+
var stack = error.stack.replace(/blob:https?:\/\/.*?\/[^:]*/g, 'example')
483+
484+
// FireFox/Safari style error
485+
if (/@/.test(stack)) {
486+
// Strip asyncFunctionResume added by Safari
487+
console.log('here', JSON.stringify(stack));
488+
stack = stack.replace(/\s*asyncFunctionResume.*\n.*/g, '');
489+
// Indent
490+
stack = stack.replace(/^/gm, ' ');
491+
// Prepend name/message
492+
message += error.name + ': ' + error.message + '\n' + stack;
493+
}
494+
else {
495+
message += stack;
496+
}
497+
}
498+
else if (error.name) {
499+
message += error.name + ': ' + error.message;
500+
}
501+
else {
502+
message += String(error);
503+
}
504+
if (error.cause) {
505+
message += '\nCaused by: ' + getErrorMessage(error.cause);
506+
}
507+
return message;
508+
}
509+
477510
var lastRun;
478511
var recordRun = function(prop) {
479512
if (!init && lastRun !== prop) {
@@ -576,15 +609,15 @@ var executeExample = function(example, prop) {
576609
}
577610
};
578611

579-
iframe.contentWindow.javascriptureReportError = function(error) {
580-
errormessage.innerHTML = escapeHTML(error);
612+
iframe.contentWindow.javascriptureReportError = function(error, fromUnhandledRejection) {
613+
errormessage.innerHTML = getErrorMessage(error, fromUnhandledRejection);
581614
errormessage.style.display = 'block';
582615
};
583616

584617
doc.writeln('<!DOCTYPE html>');
585618
doc.writeln('<script>');
586-
doc.writeln('window.onerror=function(err) { javascriptureReportError(err); };');
587-
doc.writeln('window.onunhandledrejection=function(evt) { javascriptureReportError("Promise rejected: " + evt.reason); evt.preventDefault(); };');
619+
doc.writeln('window.onerror=function(msg, file, line, column, err) { javascriptureReportError(err || msg); };');
620+
doc.writeln('window.onunhandledrejection=function(evt) { javascriptureReportError(evt.reason, true); evt.preventDefault(); };');
588621
doc.writeln('</script>');
589622

590623
var scriptBody;
@@ -666,15 +699,15 @@ var executeHTMLExample = function(example, prop) {
666699

667700
errormessage.style.display = 'none';
668701

669-
iframe.contentWindow.javascriptureReportError = function(error) {
670-
errormessage.innerHTML = escapeHTML(error);
702+
iframe.contentWindow.javascriptureReportError = function(error, fromUnhandledRejection) {
703+
errormessage.innerHTML = getErrorMessage(error, fromUnhandledRejection);
671704
errormessage.style.display = 'block';
672705
};
673706

674707
doc.writeln('<!DOCTYPE html>');
675708
doc.writeln('<script>');
676-
doc.writeln('window.onerror=function(err) { javascriptureReportError(err); };');
677-
doc.writeln('window.onunhandledrejection=function(evt) { javascriptureReportError("Promise rejected: " + evt.reason); evt.preventDefault(); };');
709+
doc.writeln('window.onerror=function(msg, file, line, column, err) { javascriptureReportError(err || msg); };');
710+
doc.writeln('window.onunhandledrejection=function(evt) { javascriptureReportError(evt.reason, true); evt.preventDefault(); };');
678711
doc.writeln('</script>');
679712
doc.writeln(code.value);
680713
doc.close();

0 commit comments

Comments
 (0)