8000 lib: print to stdout/stderr directly instead of using console · nodejs/node@c2a03d5 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit c2a03d5

Browse files
joyeecheungtargos
authored andcommitted
lib: print to stdout/stderr directly instead of using console
This patch adds an internal function that prints to stdout or stderr by directly writing to the known file descriptor, and uses it internally in common cases to avoid the overhead of the console implementation. PR-URL: #27320 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 76af4f0 commit c2a03d5

File tree

6 files changed

+103
-35
lines changed

6 files changed

+103
-35
lines changed

lib/fs.js

+2-18
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ const {
7474
validateOffsetLengthRead,
7575
validateOffsetLengthWrite,
7676
validatePath,
77-
warnOnNonPortableTemplate
77+
warnOnNonPortableTemplate,
78+
handleErrorFromBinding
7879
} = require('internal/fs/utils');
7980
const {
8081
CHAR_FORWARD_SLASH,
@@ -117,23 +118,6 @@ function showTruncateDeprecation() {
117118
}
118119
}
119120

120-
function handleErrorFromBinding(ctx) {
121-
if (ctx.errno !== undefined) { // libuv error numbers
122-
const err = uvException(ctx);
123-
// eslint-disable-next-line no-restricted-syntax
124-
Error.captureStackTrace(err, handleErrorFromBinding);
125-
throw err;
126-
}
127-
if (ctx.error !== undefined) { // Errors created in C++ land.
128-
// TODO(joyeecheung): currently, ctx.error are encoding errors
129-
// usually caused by memory problems. We need to figure out proper error
130-
// code(s) for this.
131-
// eslint-disable-next-line no-restricted-syntax
132-
Error.captureStackTrace(ctx.error, handleErrorFromBinding);
133-
throw ctx.error;
134-
}
135-
}
136-
137121
function maybeCallback(cb) {
138122
if (typeof cb === 'function')
139123
return cb;

lib/internal/fs/utils.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ const {
1212
ERR_INVALID_OPT_VALUE_ENCODING,
1313
ERR_OUT_OF_RANGE
1414
},
15-
hideStackFrames
15+
hideStackFrames,
16+
uvException
1617
} = require('internal/errors');
1718
const {
1819
isUint8Array,
@@ -444,7 +445,26 @@ function warnOnNonPortableTemplate(template) {
444445
}
445446
}
446447

448+
// This handles errors following the convention of the fs binding.
449+
function handleErrorFromBinding(ctx) {
450+
if (ctx.errno !== undefined) { // libuv error numbers
451+
const err = uvException(ctx);
452+
// eslint-disable-next-line no-restricted-syntax
453+
Error.captureStackTrace(err, handleErrorFromBinding);
454+
throw err;
455+
}
456+
if (ctx.error !== undefined) { // Errors created in C++ land.
457+
// TODO(joyeecheung): currently, ctx.error are encoding errors
458+
// usually caused by memory problems. We need to figure out proper error
459+
// code(s) for this.
460+
// eslint-disable-next-line no-restricted-syntax
461+
Error.captureStackTrace(ctx.error, handleErrorFromBinding);
462+
throw ctx.error;
463+
}
464+
}
465+
447466
module.exports = {
467+
handleErrorFromBinding,
448468
assertEncoding,
449469
copyObject,
450470
Dirent,

lib/internal/main/repl.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const {
1111
evalScript
1212
} = require('internal/process/execution');
1313

14-
const console = require('internal/console/global');
14+
const { print, kStderr, kStdout } = require('internal/util/print');
1515

1616
const { getOptionValue } = require('internal/options');
1717

@@ -21,14 +21,12 @@ markBootstrapComplete();
2121

2222
// --input-type flag not supported in REPL
2323
if (getOptionValue('--input-type')) {
24-
// If we can't write to stderr, we'd like to make this a noop,
25-
// so use console.error.
26-
console.error('Cannot specify --input-type for REPL');
24+
print(kStderr, 'Cannot specify --input-type for REPL');
2725
process.exit(1);
2826
}
2927

30-
console.log(`Welcome to Node.js ${process.version}.\n` +
31-
'Type ".help" for more information.');
28+
print(kStdout, `Welcome to Node.js ${process.version}.\n` +
29+
'Type ".help" for more information.');
3230

3331
const cliRepl = require('internal/repl');
3432
cliRepl.createInternalRepl(process.env, (err, repl) => {

lib/internal/process/execution.js

+8-10
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,22 @@ function tryGetCwd() {
3535
}
3636
}
3737

38-
function evalModule(source, print) {
39-
const { log, error } = require('internal/console/global');
38+
function evalModule(source, printResult) {
4039
const { decorateErrorStack } = require('internal/util');
4140
const asyncESM = require('internal/process/esm_loader');
41+
const { kStdout, kStderr, print } = require('internal/util/print');
4242
asyncESM.loaderPromise.then(async (loader) => {
4343
const { result } = await loader.eval(source);
44-
if (print) {
45-
log(result);
46-
}
44+
if (printResult) { print(kStdout, result); }
4745
})
4846
.catch((e) => {
4947
decorateErrorStack(e);
50-
error(e);
48+
print(kStderr, e);
5149
process.exit(1);
5250
});
5351
}
5452

55-
function evalScript(name, body, breakFirstLine, print) {
53+
function evalScript(name, body, breakFirstLine, printResult) {
5654
const CJSModule = require('internal/modules/cjs/loader');
5755
const { kVmBreakFirstLineSymbol } = require('internal/util');
5856

@@ -77,9 +75,9 @@ function evalScript(name, body, breakFirstLine, print) {
7775
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine}
7876
});\n`;
7977
const result = module._compile(script, `${name}-wrapper`);
80-
if (print) {
81-
const { log } = require('internal/console/global');
82-
log(result);
78+
if (printResult) {
79+
const { kStdout, print } = require('internal/util/print');
80+
print(kStdout, result);
8381
}
8482
}
8583

lib/internal/util/print.js

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'use strict';
2+
3+
// This implements a light-weight printer that writes to stdout/stderr
4+
// directly to avoid the overhead in the console abstraction.
5+
6+
const { formatWithOptions } = require('internal/util/inspect');
7+
const { writeString } = internalBinding('fs');
8+
const { handleErrorFromBinding } = require('internal/fs/utils');
9+
const { guessHandleType } = internalBinding('util');
10+
const { log } = require('internal/console/global');
11+
12+
const kStdout = 1;
13+
const kStderr = 2;
14+
const handleType = [undefined, undefined, undefined];
15+
function getFdType(fd) {
16+
if (handleType[fd] === undefined) {
17+
handleType[fd] = guessHandleType(fd);
18+
}
19+
return handleType[fd];
20+
}
21+
22+
function formatAndWrite(fd, obj, ignoreErrors, colors = false) {
23+
const str = `${formatWithOptions({ colors }, obj)}\n`;
24+
const ctx = {};
25+
writeString(fd, str, null, undefined, undefined, ctx);
26+
if (!ignoreErrors) {
27+
handleErrorFromBinding(ctx);
28+
}
29+
}
30+
31+
let colors;
32+
function getColors() {
33+
if (colors === undefined) {
34+
colors = require('internal/tty').getColorDepth() > 2;
35+
}
36+
return colors;
37+
}
38+
39+
// TODO(joyeecheung): replace more internal process._rawDebug()
40+
// and console.log() usage with this if possible.
41+
function print(fd, obj, ignoreErrors = true) {
42+
switch (getFdType(fd)) {
43+
case 'TTY':
44+
formatAndWrite(fd, obj, ignoreErrors, getColors());
45+
break;
46+
case 'FILE':
47+
formatAndWrite(fd, obj, ignoreErrors);
48+
break;
49+
case 'PIPE':
50+
case 'TCP':
51+
// Fallback to console.log to handle IPC.
52+
if (process.channel && process.channel.fd === fd) {
53+
log(obj);
54+
} else {
55+
formatAndWrite(fd, obj, ignoreErrors);
56+
}
57+
break;
58+
default:
59+
log(obj);
60+
}
61+
}
62+
63+
module.exports = {
64+
print,
65+
kStderr,
66+
kStdout
67+
};

node.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
'lib/internal/url.js',
185185
'lib/internal/util.js',
186186
'lib/internal/util/comparisons.js',
187+
'lib/internal/util/print.js',
187188
'lib/internal/util/debuglog.js',
188189
'lib/internal/util/inspect.js',
189190
'lib/internal/util/inspector.js',

0 commit comments

Comments
 (0)
0