Skip to content

Commit d49661b

Browse files
dbkapluntrivikr
authored andcommittedMar 26, 2018
console: don't swallow call stack exceeded errors
Fixes test/parallel/test-console-no-swallow-stack-exceeded.js PR-URL: #19423 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent cde98ce commit d49661b

File tree

3 files changed

+45
-12
lines changed

3 files changed

+45
-12
lines changed
 

‎lib/console.js

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@
2121

2222
'use strict';
2323

24-
const { ERR_CONSOLE_WRITABLE_STREAM } = require('internal/errors').codes;
24+
const {
25+
isStackOverflowError,
26+
codes: { ERR_CONSOLE_WRITABLE_STREAM },
27+
} = require('internal/errors');
2528
const util = require('util');
2629
const kCounts = Symbol('counts');
2730

2831
// Track amount of indentation required via `console.group()`.
2932
const kGroupIndent = Symbol('groupIndent');
3033

31-
let MAX_STACK_MESSAGE;
32-
3334
function Console(stdout, stderr, ignoreErrors = true) {
3435
if (!(this instanceof Console)) {
3536
return new Console(stdout, stderr, ignoreErrors);
@@ -113,17 +114,9 @@ function write(ignoreErrors, stream, string, errorhandler, groupIndent) {
113114

114115
stream.write(string, errorhandler);
115116
} catch (e) {
116-
if (MAX_STACK_MESSAGE === undefined) {
117-
try {
118-
// eslint-disable-next-line no-unused-vars
119-
function a() { a(); }
120-
} catch (err) {
121-
MAX_STACK_MESSAGE = err.message;
122-
}
123-
}
124117
// console is a debugging utility, so it swallowing errors is not desirable
125118
// even in edge cases such as low stack space.
126-
if (e.message === MAX_STACK_MESSAGE && e.name === 'RangeError')
119+
if (isStackOverflowError(e))
127120
throw e;
128121
// Sorry, there's no proper way to pass along the error here.
129122
} finally {

‎lib/internal/errors.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,11 +569,33 @@ function dnsException(err, syscall, hostname) {
569569
return ex;
570570
}
571571

572+
let MAX_STACK_MESSAGE;
573+
/**
574+
* Returns true if `err` is a `RangeError` with an engine-specific message.
575+
* "Maximum call stack size exceeded" in V8.
576+
*
577+
* @param {Error} err
578+
* @returns {boolean}
579+
*/
580+
function isStackOverflowError(err) {
581+
if (MAX_STACK_MESSAGE === undefined) {
582+
try {
583+
function overflowStack() { overflowStack(); }
584+
overflowStack();
585+
} catch (err) {
586+
MAX_STACK_MESSAGE = err.message;
587+
}
588+
}
589+
590+
return err.name === 'RangeError' && err.message === MAX_STACK_MESSAGE;
591+
}
592+
572593
module.exports = exports = {
573594
dnsException,
574595
errnoException,
575596
exceptionWithHostPort,
576597
uvException,
598+
isStackOverflowError,
577599
message,
578600
AssertionError,
579601
SystemError,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
const common = require('../common');
3+
const { Console } = require('console');
4+
const { Writable } = require('stream');
5+
6+
for (const method of ['dir', 'log', 'warn']) {
7+
common.expectsError(() => {
8+
const out = new Writable({
9+
write: common.mustCall(function write(...args) {
10+
// Exceeds call stack.
11+
return write(...args);
12+
}),
13+
});
14+
const c = new Console(out, out, true);
15+
16+
c[method]('Hello, world!');
17+
}, { name: 'RangeError' });
18+
}

0 commit comments

Comments
 (0)