All files / lib/internal/util debuglog.js

100% Statements 106/106
100% Branches 20/20
90.91% Functions 10/11
100% Lines 106/106

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 10719x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 5081x 5081x 5081x 45x 45x 45x 45x 45x 45x 5081x 5081x 19x 19x 19x 33x 33x 3x 3x 3x 3x 3x 33x 19x 19x 19x 18846x 18846x 12489x 33x 33x 33x 138x 138x 138x 138x 33x 12461x 12456x 12456x 12489x 18846x 18846x 19x 19x 19x 19x 19x 51254x 51254x 18884x 18884x 18884x 51254x 18846x 18846x 18846x 18846x 18846x 18846x 18846x 51254x 51254x 51254x 38x 38x 38x 51254x 51254x 51254x 51254x 38x 51254x 51254x 51254x 51254x 51254x 51254x 19x 19x 19x 19x 19x  
'use strict';
 
const {
  FunctionPrototype,
  FunctionPrototypeBind,
  ObjectCreate,
  ObjectDefineProperty,
  RegExp,
  RegExpPrototypeTest,
  SafeArrayIterator,
  StringPrototypeToLowerCase,
  StringPrototypeToUpperCase,
} = primordials;
 
const { inspect, format, formatWithOptions } = require('internal/util/inspect');
 
// `debugs` is deliberately initialized to undefined so any call to
// debuglog() before initializeDebugEnv() is called will throw.
let debugImpls;
 
let debugEnvRegex = /^$/;
let testEnabled;
 
// `debugEnv` is initial value of process.env.NODE_DEBUG
function initializeDebugEnv(debugEnv) {
  debugImpls = ObjectCreate(null);
  if (debugEnv) {
    debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
      .replace(/\*/g, '.*')
      .replace(/,/g, '$|^')
      .toUpperCase();
    debugEnvRegex = new RegExp(`^${debugEnv}$`, 'i');
  }
  testEnabled = FunctionPrototypeBind(RegExpPrototypeTest, null, debugEnvRegex);
}
 
// 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 = FunctionPrototype;
 
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);
    debug(...new SafeArrayIterator(args));
  };
  let enabled;
  let test = () => {
    init();
    test = () => enabled;
    return enabled;
  };
  const logger = (...args) => debug(...new SafeArrayIterator(args));
  ObjectDefineProperty(logger, 'enabled', {
    get() {
      return test();
    },
    configurable: true,
    enumerable: true
  });
  return logger;
}
 
module.exports = {
  debuglog,
  initializeDebugEnv
};