debug.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /**
  2. * This is the common logic for both the Node.js and web browser
  3. * implementations of `debug()`.
  4. *
  5. * Expose `debug()` as the module.
  6. */
  7. exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
  8. exports.coerce = coerce;
  9. exports.disable = disable;
  10. exports.enable = enable;
  11. exports.enabled = enabled;
  12. exports.humanize = require('ms');
  13. /**
  14. * Active `debug` instances.
  15. */
  16. exports.instances = [];
  17. /**
  18. * The currently active debug mode names, and names to skip.
  19. */
  20. exports.names = [];
  21. exports.skips = [];
  22. /**
  23. * Map of special "%n" handling functions, for the debug "format" argument.
  24. *
  25. * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
  26. */
  27. exports.formatters = {};
  28. /**
  29. * Select a color.
  30. * @param {String} namespace
  31. * @return {Number}
  32. * @api private
  33. */
  34. function selectColor(namespace) {
  35. var hash = 0, i;
  36. for (i in namespace) {
  37. hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
  38. hash |= 0; // Convert to 32bit integer
  39. }
  40. return exports.colors[Math.abs(hash) % exports.colors.length];
  41. }
  42. /**
  43. * Create a debugger with the given `namespace`.
  44. *
  45. * @param {String} namespace
  46. * @return {Function}
  47. * @api public
  48. */
  49. function createDebug(namespace) {
  50. var prevTime;
  51. function debug() {
  52. // disabled?
  53. if (!debug.enabled) return;
  54. var self = debug;
  55. // set `diff` timestamp
  56. var curr = +new Date();
  57. var ms = curr - (prevTime || curr);
  58. self.diff = ms;
  59. self.prev = prevTime;
  60. self.curr = curr;
  61. prevTime = curr;
  62. // turn the `arguments` into a proper Array
  63. var args = new Array(arguments.length);
  64. for (var i = 0; i < args.length; i++) {
  65. args[i] = arguments[i];
  66. }
  67. args[0] = exports.coerce(args[0]);
  68. if ('string' !== typeof args[0]) {
  69. // anything else let's inspect with %O
  70. args.unshift('%O');
  71. }
  72. // apply any `formatters` transformations
  73. var index = 0;
  74. args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
  75. // if we encounter an escaped % then don't increase the array index
  76. if (match === '%%') return match;
  77. index++;
  78. var formatter = exports.formatters[format];
  79. if ('function' === typeof formatter) {
  80. var val = args[index];
  81. match = formatter.call(self, val);
  82. // now we need to remove `args[index]` since it's inlined in the `format`
  83. args.splice(index, 1);
  84. index--;
  85. }
  86. return match;
  87. });
  88. // apply env-specific formatting (colors, etc.)
  89. exports.formatArgs.call(self, args);
  90. var logFn = debug.log || exports.log || console.log.bind(console);
  91. logFn.apply(self, args);
  92. }
  93. debug.namespace = namespace;
  94. debug.enabled = exports.enabled(namespace);
  95. debug.useColors = exports.useColors();
  96. debug.color = selectColor(namespace);
  97. debug.destroy = destroy;
  98. // env-specific initialization logic for debug instances
  99. if ('function' === typeof exports.init) {
  100. exports.init(debug);
  101. }
  102. exports.instances.push(debug);
  103. return debug;
  104. }
  105. function destroy () {
  106. var index = exports.instances.indexOf(this);
  107. if (index !== -1) {
  108. exports.instances.splice(index, 1);
  109. return true;
  110. } else {
  111. return false;
  112. }
  113. }
  114. /**
  115. * Enables a debug mode by namespaces. This can include modes
  116. * separated by a colon and wildcards.
  117. *
  118. * @param {String} namespaces
  119. * @api public
  120. */
  121. function enable(namespaces) {
  122. exports.save(namespaces);
  123. exports.names = [];
  124. exports.skips = [];
  125. var i;
  126. var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
  127. var len = split.length;
  128. for (i = 0; i < len; i++) {
  129. if (!split[i]) continue; // ignore empty strings
  130. namespaces = split[i].replace(/\*/g, '.*?');
  131. if (namespaces[0] === '-') {
  132. exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
  133. } else {
  134. exports.names.push(new RegExp('^' + namespaces + '$'));
  135. }
  136. }
  137. for (i = 0; i < exports.instances.length; i++) {
  138. var instance = exports.instances[i];
  139. instance.enabled = exports.enabled(instance.namespace);
  140. }
  141. }
  142. /**
  143. * Disable debug output.
  144. *
  145. * @api public
  146. */
  147. function disable() {
  148. exports.enable('');
  149. }
  150. /**
  151. * Returns true if the given mode name is enabled, false otherwise.
  152. *
  153. * @param {String} name
  154. * @return {Boolean}
  155. * @api public
  156. */
  157. function enabled(name) {
  158. if (name[name.length - 1] === '*') {
  159. return true;
  160. }
  161. var i, len;
  162. for (i = 0, len = exports.skips.length; i < len; i++) {
  163. if (exports.skips[i].test(name)) {
  164. return false;
  165. }
  166. }
  167. for (i = 0, len = exports.names.length; i < len; i++) {
  168. if (exports.names[i].test(name)) {
  169. return true;
  170. }
  171. }
  172. return false;
  173. }
  174. /**
  175. * Coerce `val`.
  176. *
  177. * @param {Mixed} val
  178. * @return {Mixed}
  179. * @api private
  180. */
  181. function coerce(val) {
  182. if (val instanceof Error) return val.stack || val.message;
  183. return val;
  184. }