summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/fs.js20
-rw-r--r--lib/internal/fs/utils.js22
-rw-r--r--lib/internal/main/repl.js10
-rw-r--r--lib/internal/process/execution.js18
-rw-r--r--lib/internal/util/print.js67
-rw-r--r--node.gyp1
6 files changed, 103 insertions, 35 deletions
diff --git a/lib/fs.js b/lib/fs.js
index 38c13613cb..9effb93acb 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -74,7 +74,8 @@ const {
validateOffsetLengthRead,
validateOffsetLengthWrite,
validatePath,
- warnOnNonPortableTemplate
+ warnOnNonPortableTemplate,
+ handleErrorFromBinding
} = require('internal/fs/utils');
const {
CHAR_FORWARD_SLASH,
@@ -117,23 +118,6 @@ function showTruncateDeprecation() {
}
}
-function handleErrorFromBinding(ctx) {
- if (ctx.errno !== undefined) { // libuv error numbers
- const err = uvException(ctx);
- // eslint-disable-next-line no-restricted-syntax
- Error.captureStackTrace(err, handleErrorFromBinding);
- throw err;
- }
- if (ctx.error !== undefined) { // Errors created in C++ land.
- // TODO(joyeecheung): currently, ctx.error are encoding errors
- // usually caused by memory problems. We need to figure out proper error
- // code(s) for this.
- // eslint-disable-next-line no-restricted-syntax
- Error.captureStackTrace(ctx.error, handleErrorFromBinding);
- throw ctx.error;
- }
-}
-
function maybeCallback(cb) {
if (typeof cb === 'function')
return cb;
diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js
index ca8328f553..dde78654e0 100644
--- a/lib/internal/fs/utils.js
+++ b/lib/internal/fs/utils.js
@@ -12,7 +12,8 @@ const {
ERR_INVALID_OPT_VALUE_ENCODING,
ERR_OUT_OF_RANGE
},
- hideStackFrames
+ hideStackFrames,
+ uvException
} = require('internal/errors');
const {
isUint8Array,
@@ -444,7 +445,26 @@ function warnOnNonPortableTemplate(template) {
}
}
+// This handles errors following the convention of the fs binding.
+function handleErrorFromBinding(ctx) {
+ if (ctx.errno !== undefined) { // libuv error numbers
+ const err = uvException(ctx);
+ // eslint-disable-next-line no-restricted-syntax
+ Error.captureStackTrace(err, handleErrorFromBinding);
+ throw err;
+ }
+ if (ctx.error !== undefined) { // Errors created in C++ land.
+ // TODO(joyeecheung): currently, ctx.error are encoding errors
+ // usually caused by memory problems. We need to figure out proper error
+ // code(s) for this.
+ // eslint-disable-next-line no-restricted-syntax
+ Error.captureStackTrace(ctx.error, handleErrorFromBinding);
+ throw ctx.error;
+ }
+}
+
module.exports = {
+ handleErrorFromBinding,
assertEncoding,
copyObject,
Dirent,
diff --git a/lib/internal/main/repl.js b/lib/internal/main/repl.js
index 980893f9c3..58afb2be98 100644
--- a/lib/internal/main/repl.js
+++ b/lib/internal/main/repl.js
@@ -11,7 +11,7 @@ const {
evalScript
} = require('internal/process/execution');
-const console = require('internal/console/global');
+const { print, kStderr, kStdout } = require('internal/util/print');
const { getOptionValue } = require('internal/options');
@@ -21,14 +21,12 @@ markBootstrapComplete();
// --input-type flag not supported in REPL
if (getOptionValue('--input-type')) {
- // If we can't write to stderr, we'd like to make this a noop,
- // so use console.error.
- console.error('Cannot specify --input-type for REPL');
+ print(kStderr, 'Cannot specify --input-type for REPL');
process.exit(1);
}
-console.log(`Welcome to Node.js ${process.version}.\n` +
- 'Type ".help" for more information.');
+print(kStdout, `Welcome to Node.js ${process.version}.\n` +
+ 'Type ".help" for more information.');
const cliRepl = require('internal/repl');
cliRepl.createInternalRepl(process.env, (err, repl) => {
diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js
index addd450ed3..93855ddbfc 100644
--- a/lib/internal/process/execution.js
+++ b/lib/internal/process/execution.js
@@ -35,26 +35,24 @@ function tryGetCwd() {
}
}
-function evalModule(source, print) {
- const { log, error } = require('internal/console/global');
+function evalModule(source, printResult) {
const { decorateErrorStack } = require('internal/util');
const asyncESM = require('internal/process/esm_loader');
+ const { kStdout, kStderr, print } = require('internal/util/print');
asyncESM.loaderPromise.then(async (loader) => {
const { result } = await loader.eval(source);
- if (print) {
- log(result);
- }
+ if (printResult) { print(kStdout, result); }
})
.catch((e) => {
decorateErrorStack(e);
- error(e);
+ print(kStderr, e);
process.exit(1);
});
// Handle any nextTicks added in the first tick of the program.
process._tickCallback();
}
-function evalScript(name, body, breakFirstLine, print) {
+function evalScript(name, body, breakFirstLine, printResult) {
const CJSModule = require('internal/modules/cjs/loader');
const { kVmBreakFirstLineSymbol } = require('internal/util');
@@ -79,9 +77,9 @@ function evalScript(name, body, breakFirstLine, print) {
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine}
});\n`;
const result = module._compile(script, `${name}-wrapper`);
- if (print) {
- const { log } = require('internal/console/global');
- log(result);
+ if (printResult) {
+ const { kStdout, print } = require('internal/util/print');
+ print(kStdout, result);
}
// Handle any nextTicks added in the first tick of the program.
process._tickCallback();
diff --git a/lib/internal/util/print.js b/lib/internal/util/print.js
new file mode 100644
index 0000000000..4c9327502e
--- /dev/null
+++ b/lib/internal/util/print.js
@@ -0,0 +1,67 @@
+'use strict';
+
+// This implements a light-weight printer that writes to stdout/stderr
+// directly to avoid the overhead in the console abstraction.
+
+const { formatWithOptions } = require('internal/util/inspect');
+const { writeString } = internalBinding('fs');
+const { handleErrorFromBinding } = require('internal/fs/utils');
+const { guessHandleType } = internalBinding('util');
+const { log } = require('internal/console/global');
+
+const kStdout = 1;
+const kStderr = 2;
+const handleType = [undefined, undefined, undefined];
+function getFdType(fd) {
+ if (handleType[fd] === undefined) {
+ handleType[fd] = guessHandleType(fd);
+ }
+ return handleType[fd];
+}
+
+function formatAndWrite(fd, obj, ignoreErrors, colors = false) {
+ const str = `${formatWithOptions({ colors }, obj)}\n`;
+ const ctx = {};
+ writeString(fd, str, null, undefined, undefined, ctx);
+ if (!ignoreErrors) {
+ handleErrorFromBinding(ctx);
+ }
+}
+
+let colors;
+function getColors() {
+ if (colors === undefined) {
+ colors = require('internal/tty').getColorDepth() > 2;
+ }
+ return colors;
+}
+
+// TODO(joyeecheung): replace more internal process._rawDebug()
+// and console.log() usage with this if possible.
+function print(fd, obj, ignoreErrors = true) {
+ switch (getFdType(fd)) {
+ case 'TTY':
+ formatAndWrite(fd, obj, ignoreErrors, getColors());
+ break;
+ case 'FILE':
+ formatAndWrite(fd, obj, ignoreErrors);
+ break;
+ case 'PIPE':
+ case 'TCP':
+ // Fallback to console.log to handle IPC.
+ if (process.channel && process.channel.fd === fd) {
+ log(obj);
+ } else {
+ formatAndWrite(fd, obj, ignoreErrors);
+ }
+ break;
+ default:
+ log(obj);
+ }
+}
+
+module.exports = {
+ print,
+ kStderr,
+ kStdout
+};
diff --git a/node.gyp b/node.gyp
index 53bd954afb..3cf47ffc25 100644
--- a/node.gyp
+++ b/node.gyp
@@ -184,6 +184,7 @@
'lib/internal/url.js',
'lib/internal/util.js',
'lib/internal/util/comparisons.js',
+ 'lib/internal/util/print.js',
'lib/internal/util/debuglog.js',
'lib/internal/util/inspect.js',
'lib/internal/util/inspector.js',