| 'use strict'; |
| |
| const { |
| ObjectCreate, |
| ObjectDefineProperty, |
| RegExp, |
| RegExpPrototypeExec, |
| SafeArrayIterator, |
| StringPrototypeToLowerCase, |
| StringPrototypeToUpperCase, |
| } = primordials; |
| |
| const { inspect, format, formatWithOptions } = require('internal/util/inspect'); |
| |
| // `debugImpls` and `testEnabled` are deliberately not initialized so any call |
| // to `debuglog()` before `initializeDebugEnv()` is called will throw. |
| let debugImpls; |
| let testEnabled; |
| |
| |
| // `debugEnv` is initial value of process.env.NODE_DEBUG |
| function initializeDebugEnv(debugEnv) { |
| debugImpls = ObjectCreate(null); |
| if (debugEnv) { |
| // This is run before any user code, it's OK not to use primordials. |
| debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&') |
| .replaceAll('*', '.*') |
| .replaceAll(',', '$|^'); |
| const debugEnvRegex = new RegExp(`^${debugEnv}$`, 'i'); |
| testEnabled = (str) => RegExpPrototypeExec(debugEnvRegex, str) !== null; |
| } else { |
| testEnabled = () => false; |
| } |
| } |
| |
| // 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 \'' + StringPrototypeToLowerCase(set) + '\' can expose sensitive ' + |
| 'data (such as passwords, tokens and authentication headers) ' + |
| 'in the resulting log.'); |
| } |
| } |
| |
| const noop = () => {}; |
| |
| function debuglogImpl(enabled, set) { |
| if (debugImpls[set] === undefined) { |
| if (enabled) { |
| const pid = process.pid; |
| emitWarningIfNeeded(set); |
| debugImpls[set] = function debug(...args) { |
| const colors = process.stderr.hasColors && process.stderr.hasColors(); |
| const msg = formatWithOptions({ colors }, ...args); |
| const coloredPID = inspect(pid, { colors }); |
| process.stderr.write(format('%s %s: %s\n', set, coloredPID, msg)); |
| }; |
| } else { |
| debugImpls[set] = noop; |
| } |
| } |
| return debugImpls[set]; |
| } |
| |
| // debuglogImpl depends on process.pid and process.env.NODE_DEBUG, |
| // so it needs to be called lazily in top scopes of internal modules |
| // that may be loaded before these run time states are allowed to |
| // be accessed. |
| function debuglog(set, cb) { |
| function init() { |
| set = StringPrototypeToUpperCase(set); |
| enabled = testEnabled(set); |
| } |
| let debug = (...args) => { |
| init(); |
| // Only invokes debuglogImpl() when the debug function is |
| // called for the first time. |
| debug = debuglogImpl(enabled, set); |
| if (typeof cb === 'function') |
| cb(debug); |
| switch (args.length) { |
| case 1: return debug(args[0]); |
| case 2: return debug(args[0], args[1]); |
| default: return debug(...new SafeArrayIterator(args)); |
| } |
| }; |
| let enabled; |
| let test = () => { |
| init(); |
| test = () => enabled; |
| return enabled; |
| }; |
| const logger = (...args) => { |
| switch (args.length) { |
| case 1: return debug(args[0]); |
| case 2: return debug(args[0], args[1]); |
| default: return debug(...new SafeArrayIterator(args)); |
| } |
| }; |
| ObjectDefineProperty(logger, 'enabled', { |
| __proto__: null, |
| get() { |
| return test(); |
| }, |
| configurable: true, |
| enumerable: true |
| }); |
| return logger; |
| } |
| |
| module.exports = { |
| debuglog, |
| initializeDebugEnv |
| }; |