• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const {
4  FunctionPrototypeBind,
5  ObjectCreate,
6  ObjectDefineProperty,
7  RegExp,
8  RegExpPrototypeTest,
9  SafeArrayIterator,
10  StringPrototypeToUpperCase
11} = primordials;
12
13const { inspect, format, formatWithOptions } = require('internal/util/inspect');
14
15// `debugs` is deliberately initialized to undefined so any call to
16// debuglog() before initializeDebugEnv() is called will throw.
17let debugImpls;
18
19let debugEnvRegex = /^$/;
20let testEnabled;
21
22// `debugEnv` is initial value of process.env.NODE_DEBUG
23function initializeDebugEnv(debugEnv) {
24  debugImpls = ObjectCreate(null);
25  if (debugEnv) {
26    debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
27      .replace(/\*/g, '.*')
28      .replace(/,/g, '$|^')
29      .toUpperCase();
30    debugEnvRegex = new RegExp(`^${debugEnv}$`, 'i');
31  }
32  testEnabled = FunctionPrototypeBind(RegExpPrototypeTest, null, debugEnvRegex);
33}
34
35// Emits warning when user sets
36// NODE_DEBUG=http or NODE_DEBUG=http2.
37function emitWarningIfNeeded(set) {
38  if ('HTTP' === set || 'HTTP2' === set) {
39    process.emitWarning('Setting the NODE_DEBUG environment variable ' +
40      'to \'' + set.toLowerCase() + '\' can expose sensitive ' +
41      'data (such as passwords, tokens and authentication headers) ' +
42      'in the resulting log.');
43  }
44}
45
46function noop() {}
47
48function debuglogImpl(enabled, set) {
49  if (debugImpls[set] === undefined) {
50    if (enabled) {
51      const pid = process.pid;
52      emitWarningIfNeeded(set);
53      debugImpls[set] = function debug(...args) {
54        const colors = process.stderr.hasColors && process.stderr.hasColors();
55        const msg = formatWithOptions({ colors }, ...args);
56        const coloredPID = inspect(pid, { colors });
57        process.stderr.write(format('%s %s: %s\n', set, coloredPID, msg));
58      };
59    } else {
60      debugImpls[set] = noop;
61    }
62  }
63  return debugImpls[set];
64}
65
66// debuglogImpl depends on process.pid and process.env.NODE_DEBUG,
67// so it needs to be called lazily in top scopes of internal modules
68// that may be loaded before these run time states are allowed to
69// be accessed.
70function debuglog(set, cb) {
71  function init() {
72    set = StringPrototypeToUpperCase(set);
73    enabled = testEnabled(set);
74  }
75  let debug = (...args) => {
76    init();
77    // Only invokes debuglogImpl() when the debug function is
78    // called for the first time.
79    debug = debuglogImpl(enabled, set);
80    if (typeof cb === 'function')
81      cb(debug);
82    debug(...new SafeArrayIterator(args));
83  };
84  let enabled;
85  let test = () => {
86    init();
87    test = () => enabled;
88    return enabled;
89  };
90  const logger = (...args) => debug(...new SafeArrayIterator(args));
91  ObjectDefineProperty(logger, 'enabled', {
92    get() {
93      return test();
94    },
95    configurable: true,
96    enumerable: true
97  });
98  return logger;
99}
100
101module.exports = {
102  debuglog,
103  initializeDebugEnv
104};
105