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

Add timed sections #485

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 33 additions & 4 deletions src/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.hrtime = hrtimeInit();
exports.storage = 'undefined' != typeof chrome
&& 'undefined' != typeof chrome.storage
? chrome.storage.local
Expand Down Expand Up @@ -80,20 +81,28 @@ exports.formatters.j = function(v) {
* @api public
*/

function formatArgs(args) {
function formatArgs(args, section) {
var useColors = this.useColors;

args[0] = (useColors ? '%c' : '')
+ this.namespace
+ (useColors ? ' %c' : ' ')
+ (section ? (section.title + (useColors ? ' %c' : ' ')) : '')
+ args[0]
+ (useColors ? '%c ' : ' ')
+ '+' + exports.humanize(this.diff);
+ '+' + exports.humanize(this.diff)
+ (section && section.complete ? ('%c (delta ' + (useColors ? '%c+' : '+') + exports.humanize(section.deltaTime) + (useColors ? '%c)' : ')')) : '');

if (!useColors) return;

var c = 'color: ' + this.color;
args.splice(1, 0, c, 'color: inherit')
var inherit = 'color: inherit';

if (section) {
args.splice(1, 0, c, inherit + '; font-weight: bold', 'font-weight: normal');
} else {
args.splice(1, 0, c, inherit);
}

// the final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
Expand All @@ -110,7 +119,11 @@ function formatArgs(args) {
}
});

args.splice(lastC, 0, c);
if (section && section.complete) {
args.splice(lastC - 2, 0, c, inherit, c, inherit);
} else {
args.splice(lastC, 0, c);
}
}

/**
Expand Down Expand Up @@ -166,6 +179,22 @@ function load() {
return r;
}

/**
* Browser implementation of hrtime().
*
* Follows the spec outlined in debug.begin() (see debug.js).
*
* If the browser has support for `window.performance.now()`,
* then it is used. Otherwise, it falls back to `Date.now()`.
*/
function hrtimeInit() {
var nowfn = window && window.performance && window.performance.now ? window.performance.now.bind(window.performance) : Date.now;
return function (prev) {
var now = nowfn();
return prev ? (now - prev) : now;
};
}

/**
* Enable namespaces listed in `localStorage.debug` initially.
*/
Expand Down
162 changes: 133 additions & 29 deletions src/debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ exports.instances = [];
/**
* The currently active debug mode names, and names to skip.
*/

exports.names = [];
exports.skips = [];

Expand All @@ -31,7 +30,15 @@ exports.skips = [];
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
*/

exports.formatters = {};
exports.formatters = {
s: String,
i: function (v) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseInt(v, 10)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const o = { valueOf: () => 1234 };

parseInt(o, 10); //-> NaN
Number(o); //-> 1234

v = Number(v);
return v - (v % 1);
},
d: Number,
f: Number
};

/**
* Select a color.
Expand All @@ -51,6 +58,39 @@ function selectColor(namespace) {
return exports.colors[Math.abs(hash) % exports.colors.length];
}

/**
* Formats a sequence of arguments.
* @api private
*/

function formatInlineArgs(dbg, args) {
args[0] = exports.coerce(args[0]);

if ('string' !== typeof args[0]) {
// anything else let's inspect with %O
args.unshift('%O');
}

var index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = exports.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(dbg, val);

// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});

return args;
}

/**
* Create a debugger with the given `namespace`.
*
Expand All @@ -63,7 +103,7 @@ function createDebug(namespace) {

var prevTime;

function debug() {
function debugHandle(rawArgs, section) {
// disabled?
if (!debug.enabled) return;

Expand All @@ -78,49 +118,113 @@ function createDebug(namespace) {
prevTime = curr;

// turn the `arguments` into a proper Array
var args = new Array(arguments.length);
var args = new Array(rawArgs.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}

args[0] = exports.coerce(args[0]);

if ('string' !== typeof args[0]) {
// anything else let's inspect with %O
args.unshift('%O');
args[i] = rawArgs[i];
}

// apply any `formatters` transformations
var index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = exports.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(self, val);

// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
formatInlineArgs(self, args);

// apply env-specific formatting (colors, etc.)
exports.formatArgs.call(self, args);
exports.formatArgs.call(self, args, section);

var logFn = debug.log || exports.log || console.log.bind(console);
logFn.apply(self, args);
}

function debug() {
debugHandle(arguments);
}

debug.namespace = namespace;
debug.enabled = exports.enabled(namespace);
debug.useColors = exports.useColors();
debug.color = selectColor(namespace);
debug.destroy = destroy;

debug.begin = function () {
// hrtime() can return whatever it wants with no arguments;
// however, it must return a float when called with a second parameter;
// that float must be the delta time in milliseconds.
var args = arguments;
var beginTime = exports.hrtime();
var ended = false;

var mark = function (title, extraArgs) {
if (ended) {
return;
}

section.title = title;
section.deltaTime = exports.hrtime(beginTime);
if (extraArgs.length) {
var leftArgs = formatInlineArgs(debug, [].slice.call(args));
var newArgs;
if (extraArgs.length > 0) {
var rightArgs = formatInlineArgs(debug, [].slice.call(extraArgs));
newArgs = leftArgs.concat(['::']).concat(rightArgs)
} else {
newArgs = leftArgs;
}
debugHandle(newArgs, section);
} else {
debugHandle(args, section);
}
return section;
}

var section = {
title: '[begin]',
end: function () {
try {
return mark('[end]', arguments);
} finally {
ended = true;
}
},
mark: function () {
return mark('[mark]', arguments);
}
};

debugHandle(args, section);
section.complete = true;

return section;
};

debug.time = function () {
var args = [].slice.call(arguments);
if (args.length < 2) {
throw new Error('debug.time() takes at least a debug string and a function');
}

var fn = args.pop();
if (typeof fn !== 'function') {
throw new Error('the last argument to debug.time() must be a function');
}

var isPromise = false;
var section = debug.begin.apply(debug, args);
try {
var result = fn(section);

if (typeof Promise === 'function' && result instanceof Promise) { // eslint-disable-line no-undef
isPromise = true;
result.then(function () {
section.end();
});
}

return result;
} finally {
if (!isPromise) {
section.end();
}
}
};

// env-specific initialization logic for debug instances
if ('function' === typeof exports.init) {
exports.init(debug);
Expand Down
29 changes: 26 additions & 3 deletions src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.hrtime = hrtime;

/**
* Colors.
Expand Down Expand Up @@ -101,17 +102,22 @@ exports.formatters.O = function(v) {
* @api public
*/

function formatArgs(args) {
function formatArgs(args, section) {
var name = this.namespace;
var useColors = this.useColors;

if (useColors) {
var c = this.color;
var colorCode = '\u001b[3' + (c < 8 ? c : '8;5;' + c);
var prefix = ' ' + colorCode + ';1m' + name + ' ' + '\u001b[0m';
var prefix = ' ' + colorCode + ';1m' + name + '\u001b[0m ';
var sectionPrefix = section ? ('\u001b[1m' + section.title + '\u001b[0m ') : '';

args[0] = prefix + args[0].split('\n').join('\n' + prefix);
args[0] = prefix + sectionPrefix + args[0].split('\n').join('\n' + prefix);
args.push(colorCode + 'm+' + exports.humanize(this.diff) + '\u001b[0m');

if (section && section.complete) {
args.push('(delta ' + colorCode + 'm+' + exports.humanize(section.deltaTime) + '\u001b[0m)');
}
} else {
args[0] = new Date().toISOString()
+ ' ' + name + ' ' + args[0];
Expand Down Expand Up @@ -170,6 +176,23 @@ function init (debug) {
}
}

/**
* Wrapper around Node's process.hrtime().
*
* As per the spec defined by debug.begin() (see debug.js),
* this function returns normally when there is no argument,
* but returns a delta float in the event that there is.
*/

function hrtime(prev) {
if (prev) {
var delta = process.hrtime(prev);
return (delta[0] * 1000) + (delta[1] / 1e6);
}

return process.hrtime();
}

/**
* Enable namespaces listed in `process.env.DEBUG` initially.
*/
Expand Down