Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: explicitly initialize debuglog during bootstrap #26468

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,15 @@ Readable.ReadableState = ReadableState;
const EE = require('events');
const Stream = require('stream');
const { Buffer } = require('buffer');
const util = require('util');
const debug = util.debuglog('stream');

let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('stream');
}
debuglog(...args);
}

const BufferList = require('internal/streams/buffer_list');
const destroyImpl = require('internal/streams/destroy');
const { getHighWaterMark } = require('internal/streams/state');
Expand Down
7 changes: 7 additions & 0 deletions lib/internal/bootstrap/pre_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ let traceEventsAsyncHook;
function prepareMainThreadExecution() {
setupTraceCategoryState();

setupDebugEnv();

// Only main thread receives signals.
setupSignalHandlers();

Expand Down Expand Up @@ -52,6 +54,10 @@ function initializeReport() {
});
}

function setupDebugEnv() {
require('internal/util/debuglog').initializeDebugEnv(process.env.NODE_DEBUG);
}

function setupSignalHandlers() {
const {
createSignalHandlers
Expand Down Expand Up @@ -231,6 +237,7 @@ function loadPreloadModules() {
}

module.exports = {
setupDebugEnv,
prepareMainThreadExecution,
initializeDeprecations,
initializeESMLoader,
Expand Down
6 changes: 6 additions & 0 deletions lib/internal/main/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

// `node inspect ...` or `node debug ...`

const {
prepareMainThreadExecution
} = require('internal/bootstrap/pre_execution');

prepareMainThreadExecution();

if (process.argv[1] === 'debug') {
process.emitWarning(
'`node debug` is deprecated. Please use `node inspect` instead.',
Expand Down
6 changes: 6 additions & 0 deletions lib/internal/main/print_bash_completion.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
'use strict';
const { options, aliases } = require('internal/options');

const {
prepareMainThreadExecution
} = require('internal/bootstrap/pre_execution');

function print(stream) {
const all_opts = [...options.keys(), ...aliases.keys()];

Expand All @@ -18,6 +22,8 @@ function print(stream) {
complete -F _node_complete node node_g`);
}

prepareMainThreadExecution();

markBootstrapComplete();

print(process.stdout);
6 changes: 6 additions & 0 deletions lib/internal/main/print_help.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
const { types } = internalBinding('options');
const hasCrypto = Boolean(process.versions.openssl);

const {
prepareMainThreadExecution
} = require('internal/bootstrap/pre_execution');

const typeLookup = [];
for (const key of Object.keys(types))
typeLookup[types[key]] = key;
Expand Down Expand Up @@ -171,6 +175,8 @@ function print(stream) {
stream.write('\nDocumentation can be found at https://nodejs.org/\n');
}

prepareMainThreadExecution();

markBootstrapComplete();

print(process.stdout);
5 changes: 5 additions & 0 deletions lib/internal/main/prof_process.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
'use strict';

const {
prepareMainThreadExecution
} = require('internal/bootstrap/pre_execution');

prepareMainThreadExecution();
markBootstrapComplete();
require('internal/v8_prof_processor');
4 changes: 4 additions & 0 deletions lib/internal/main/worker_thread.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// message port.

const {
setupDebugEnv,
initializeDeprecations,
initializeESMLoader,
initializeFrozenIntrinsics,
Expand Down Expand Up @@ -37,6 +38,9 @@ const {
} = require('internal/process/execution');

const publicWorker = require('worker_threads');

setupDebugEnv();

const debug = require('util').debuglog('worker');

debug(`[${threadId}] is setting up worker child environment`);
Expand Down
8 changes: 7 additions & 1 deletion lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,13 @@ Object.defineProperty(Module, 'wrapper', {
}
});

const debug = util.debuglog('module');
let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('module');
}
debuglog(...args);
}

Module._debug = util.deprecate(debug, 'Module._debug is deprecated.',
'DEP0077');
Expand Down
54 changes: 54 additions & 0 deletions lib/internal/util/debuglog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict';

const { format } = require('internal/util/inspect');

// `debugs` is deliberately initialized to undefined so any call to
// debuglog() before initializeDebugEnv() is called will throw.
let debugs;

let debugEnvRegex = /^$/;

// `debugEnv` is initial value of process.env.NODE_DEBUG
function initializeDebugEnv(debugEnv) {
debugs = {};
if (debugEnv) {
debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
.replace(/\*/g, '.*')
.replace(/,/g, '$|^')
.toUpperCase();
debugEnvRegex = new RegExp(`^${debugEnv}$`, 'i');
}
}

// Emits warning when user sets
// NODE_DEBUG=http or NODE_DEBUG=http2.
function emitWarningIfNeeded(set) {
if ('HTTP' === set || 'HTTP2' === set) {
process.emitWarning('Setting the NODE_DEBUG environment variable ' +
'to \'' + set.toLowerCase() + '\' can expose sensitive ' +
'data (such as passwords, tokens and authentication headers) ' +
'in the resulting log.');
}
}

function debuglog(set) {
set = set.toUpperCase();
BridgeAR marked this conversation as resolved.
Show resolved Hide resolved
if (!debugs[set]) {
if (debugEnvRegex.test(set)) {
const pid = process.pid;
BridgeAR marked this conversation as resolved.
Show resolved Hide resolved
emitWarningIfNeeded(set);
debugs[set] = function debug(...args) {
const msg = format(...args);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function debug() {};
}
}
return debugs[set];
}

module.exports = {
debuglog,
initializeDebugEnv
};
133 changes: 132 additions & 1 deletion lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -1363,8 +1363,139 @@ function reduceToSingleString(ctx, output, base, braces, combine = false) {
return `${braces[0]}${ln}${join(output, `,\n${indentation} `)} ${braces[1]}`;
}

const emptyOptions = {};
function format(...args) {
return formatWithOptions(emptyOptions, ...args);
}


let CIRCULAR_ERROR_MESSAGE;
function tryStringify(arg) {
try {
return JSON.stringify(arg);
} catch (err) {
// Populate the circular error message lazily
if (!CIRCULAR_ERROR_MESSAGE) {
try {
const a = {}; a.a = a; JSON.stringify(a);
} catch (err) {
CIRCULAR_ERROR_MESSAGE = err.message;
}
}
if (err.name === 'TypeError' && err.message === CIRCULAR_ERROR_MESSAGE)
return '[Circular]';
throw err;
}
}

function formatWithOptions(inspectOptions, ...args) {
const first = args[0];
let a = 0;
let str = '';
let join = '';

if (typeof first === 'string') {
if (args.length === 1) {
return first;
}
let tempStr;
let lastPos = 0;

for (var i = 0; i < first.length - 1; i++) {
if (first.charCodeAt(i) === 37) { // '%'
const nextChar = first.charCodeAt(++i);
if (a + 1 !== args.length) {
switch (nextChar) {
case 115: // 's'
tempStr = String(args[++a]);
break;
case 106: // 'j'
tempStr = tryStringify(args[++a]);
break;
case 100: // 'd'
const tempNum = args[++a];
// eslint-disable-next-line valid-typeof
if (typeof tempNum === 'bigint') {
tempStr = `${tempNum}n`;
} else if (typeof tempNum === 'symbol') {
tempStr = 'NaN';
} else {
tempStr = `${Number(tempNum)}`;
}
break;
case 79: // 'O'
tempStr = inspect(args[++a], inspectOptions);
break;
case 111: // 'o'
{
tempStr = inspect(args[++a], {
...inspectOptions,
showHidden: true,
showProxy: true,
depth: 4
});
break;
}
case 105: // 'i'
const tempInteger = args[++a];
// eslint-disable-next-line valid-typeof
if (typeof tempInteger === 'bigint') {
tempStr = `${tempInteger}n`;
} else if (typeof tempInteger === 'symbol') {
tempStr = 'NaN';
} else {
tempStr = `${parseInt(tempInteger)}`;
}
break;
case 102: // 'f'
const tempFloat = args[++a];
if (typeof tempFloat === 'symbol') {
tempStr = 'NaN';
} else {
tempStr = `${parseFloat(tempFloat)}`;
}
break;
case 37: // '%'
str += first.slice(lastPos, i);
lastPos = i + 1;
continue;
default: // Any other character is not a correct placeholder
continue;
}
if (lastPos !== i - 1) {
str += first.slice(lastPos, i - 1);
}
str += tempStr;
lastPos = i + 1;
} else if (nextChar === 37) {
str += first.slice(lastPos, i);
lastPos = i + 1;
}
}
}
if (lastPos !== 0) {
a++;
join = ' ';
if (lastPos < first.length) {
str += first.slice(lastPos);
}
}
}

while (a < args.length) {
const value = args[a];
str += join;
str += typeof value !== 'string' ? inspect(value, inspectOptions) : value;
join = ' ';
a++;
}
return str;
}

module.exports = {
inspect,
formatProperty,
kObjectType
kObjectType,
format,
formatWithOptions
};
10 changes: 8 additions & 2 deletions lib/internal/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const util = require('util');

const {
ERR_WORKER_PATH,
ERR_WORKER_UNSERIALIZABLE_ERROR,
Expand Down Expand Up @@ -45,7 +45,13 @@ const kOnCouldNotSerializeErr = Symbol('kOnCouldNotSerializeErr');
const kOnErrorMessage = Symbol('kOnErrorMessage');
const kParentSideStdio = Symbol('kParentSideStdio');

const debug = util.debuglog('worker');
let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('worker');
}
debuglog(...args);
}

class Worker extends EventEmitter {
constructor(filename, options = {}) {
Expand Down
9 changes: 8 additions & 1 deletion lib/internal/worker/io.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ const { threadId } = internalBinding('worker');
const { Readable, Writable } = require('stream');
const EventEmitter = require('events');
const util = require('util');
const debug = util.debuglog('worker');

let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('worker');
}
debuglog(...args);
}

const kIncrementsPortRef = Symbol('kIncrementsPortRef');
const kName = Symbol('kName');
Expand Down
10 changes: 9 additions & 1 deletion lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,15 @@ const {
const internalUtil = require('internal/util');
const util = require('util');
const { ERR_INVALID_CALLBACK } = require('internal/errors').codes;
const debug = util.debuglog('timer');

let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('timer');
}
debuglog(...args);
}

const {
destroyHooksExist,
// The needed emit*() functions.
Expand Down
Loading