console: don't swallow call stack exceeded errors
Fixes test/parallel/test-console-no-swallow-stack-exceeded.js PR-URL: https://github.com/nodejs/node/pull/19423 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
parent
cde98ce147
commit
d49661bb80
@ -21,15 +21,16 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { ERR_CONSOLE_WRITABLE_STREAM } = require('internal/errors').codes;
|
const {
|
||||||
|
isStackOverflowError,
|
||||||
|
codes: { ERR_CONSOLE_WRITABLE_STREAM },
|
||||||
|
} = require('internal/errors');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const kCounts = Symbol('counts');
|
const kCounts = Symbol('counts');
|
||||||
|
|
||||||
// Track amount of indentation required via `console.group()`.
|
// Track amount of indentation required via `console.group()`.
|
||||||
const kGroupIndent = Symbol('groupIndent');
|
const kGroupIndent = Symbol('groupIndent');
|
||||||
|
|
||||||
let MAX_STACK_MESSAGE;
|
|
||||||
|
|
||||||
function Console(stdout, stderr, ignoreErrors = true) {
|
function Console(stdout, stderr, ignoreErrors = true) {
|
||||||
if (!(this instanceof Console)) {
|
if (!(this instanceof Console)) {
|
||||||
return new Console(stdout, stderr, ignoreErrors);
|
return new Console(stdout, stderr, ignoreErrors);
|
||||||
@ -113,17 +114,9 @@ function write(ignoreErrors, stream, string, errorhandler, groupIndent) {
|
|||||||
|
|
||||||
stream.write(string, errorhandler);
|
stream.write(string, errorhandler);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (MAX_STACK_MESSAGE === undefined) {
|
|
||||||
try {
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
function a() { a(); }
|
|
||||||
} catch (err) {
|
|
||||||
MAX_STACK_MESSAGE = err.message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// console is a debugging utility, so it swallowing errors is not desirable
|
// console is a debugging utility, so it swallowing errors is not desirable
|
||||||
// even in edge cases such as low stack space.
|
// even in edge cases such as low stack space.
|
||||||
if (e.message === MAX_STACK_MESSAGE && e.name === 'RangeError')
|
if (isStackOverflowError(e))
|
||||||
throw e;
|
throw e;
|
||||||
// Sorry, there's no proper way to pass along the error here.
|
// Sorry, there's no proper way to pass along the error here.
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -569,11 +569,33 @@ function dnsException(err, syscall, hostname) {
|
|||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let MAX_STACK_MESSAGE;
|
||||||
|
/**
|
||||||
|
* Returns true if `err` is a `RangeError` with an engine-specific message.
|
||||||
|
* "Maximum call stack size exceeded" in V8.
|
||||||
|
*
|
||||||
|
* @param {Error} err
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isStackOverflowError(err) {
|
||||||
|
if (MAX_STACK_MESSAGE === undefined) {
|
||||||
|
try {
|
||||||
|
function overflowStack() { overflowStack(); }
|
||||||
|
overflowStack();
|
||||||
|
} catch (err) {
|
||||||
|
MAX_STACK_MESSAGE = err.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err.name === 'RangeError' && err.message === MAX_STACK_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = exports = {
|
module.exports = exports = {
|
||||||
dnsException,
|
dnsException,
|
||||||
errnoException,
|
errnoException,
|
||||||
exceptionWithHostPort,
|
exceptionWithHostPort,
|
||||||
uvException,
|
uvException,
|
||||||
|
isStackOverflowError,
|
||||||
message,
|
message,
|
||||||
AssertionError,
|
AssertionError,
|
||||||
SystemError,
|
SystemError,
|
||||||
|
18
test/parallel/test-console-no-swallow-stack-overflow.js
Normal file
18
test/parallel/test-console-no-swallow-stack-overflow.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
const { Console } = require('console');
|
||||||
|
const { Writable } = require('stream');
|
||||||
|
|
||||||
|
for (const method of ['dir', 'log', 'warn']) {
|
||||||
|
common.expectsError(() => {
|
||||||
|
const out = new Writable({
|
||||||
|
write: common.mustCall(function write(...args) {
|
||||||
|
// Exceeds call stack.
|
||||||
|
return write(...args);
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const c = new Console(out, out, true);
|
||||||
|
|
||||||
|
c[method]('Hello, world!');
|
||||||
|
}, { name: 'RangeError' });
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user