Skip to content

Commit f3c397c

Browse files
committed
console: implement timeLog method
Refs: whatwg/console#138 PR-URL: #21312 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Weijia Wang <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 47b10e3 commit f3c397c

File tree

3 files changed

+73
-15
lines changed

3 files changed

+73
-15
lines changed

doc/api/console.md

+19
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,25 @@ console.timeEnd('100-elements');
413413
// prints 100-elements: 225.438ms
414414
```
415415

416+
### console.timeLog([label][, ...data])
417+
<!-- YAML
418+
added: REPLACEME
419+
-->
420+
* `label` {string} **Default:** `'default'`
421+
* `...data` {any}
422+
423+
For a timer that was previously started by calling [`console.time()`][], prints
424+
the elapsed time and other `data` arguments to `stdout`:
425+
426+
```js
427+
console.time('process');
428+
const value = expensiveProcess1(); // Returns 42
429+
console.timeLog('process', value);
430+
// Prints "process: 365.227ms 42".
431+
doExpensiveProcess2(value);
432+
console.timeEnd('process');
433+
```
434+
416435
### console.trace([message][, ...args])
417436
<!-- YAML
418437
added: v0.1.104

lib/console.js

+22-6
Original file line numberDiff line numberDiff line change
@@ -231,18 +231,34 @@ Console.prototype.time = function time(label = 'default') {
231231
};
232232

233233
Console.prototype.timeEnd = function timeEnd(label = 'default') {
234+
const hasWarned = timeLogImpl(this, 'timeEnd', label);
235+
if (!hasWarned) {
236+
this._times.delete(label);
237+
}
238+
};
239+
240+
Console.prototype.timeLog = function timeLog(label, ...data) {
241+
timeLogImpl(this, 'timeLog', label, data);
242+
};
243+
244+
// Returns true if label was not found
245+
function timeLogImpl(self, name, label = 'default', data) {
234246
// Coerces everything other than Symbol to a string
235247
label = `${label}`;
236-
const time = this._times.get(label);
248+
const time = self._times.get(label);
237249
if (!time) {
238-
process.emitWarning(`No such label '${label}' for console.timeEnd()`);
239-
return;
250+
process.emitWarning(`No such label '${label}' for console.${name}()`);
251+
return true;
240252
}
241253
const duration = process.hrtime(time);
242254
const ms = duration[0] * 1000 + duration[1] / 1e6;
243-
this.log('%s: %sms', label, ms.toFixed(3));
244-
this._times.delete(label);
245-
};
255+
if (data === undefined) {
256+
self.log('%s: %sms', label, ms.toFixed(3));
257+
} else {
258+
self.log('%s: %sms', label, ms.toFixed(3), ...data);
259+
}
260+
return false;
261+
}
246262

247263
Console.prototype.trace = function trace(...args) {
248264
const err = {

test/parallel/test-console.js

+32-9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
'use strict';
2323
const common = require('../common');
2424
const assert = require('assert');
25+
const util = require('util');
2526

2627
assert.ok(process.stdout.writable);
2728
assert.ok(process.stderr.writable);
@@ -30,11 +31,17 @@ if (common.isMainThread) {
3031
assert.strictEqual(typeof process.stdout.fd, 'number');
3132
assert.strictEqual(typeof process.stderr.fd, 'number');
3233
}
33-
process.once('warning', common.mustCall((warning) => {
34-
assert(/no such label/.test(warning.message));
35-
}));
3634

37-
console.timeEnd('no such label');
35+
common.expectWarning(
36+
'Warning',
37+
[
38+
['No such label \'nolabel\' for console.timeEnd()', common.noWarnCode],
39+
['No such label \'nolabel\' for console.timeLog()', common.noWarnCode]
40+
]
41+
);
42+
43+
console.timeEnd('nolabel');
44+
console.timeLog('nolabel');
3845

3946
console.time('label');
4047
console.timeEnd('label');
@@ -47,8 +54,8 @@ assert.throws(() => console.timeEnd(Symbol('test')),
4754
TypeError);
4855

4956

50-
// an Object with a custom .inspect() function
51-
const custom_inspect = { foo: 'bar', inspect: () => 'inspect' };
57+
// An Object with a custom inspect function.
58+
const custom_inspect = { foo: 'bar', [util.inspect.custom]: () => 'inspect' };
5259

5360
const strings = [];
5461
const errStrings = [];
@@ -139,6 +146,12 @@ console.timeEnd();
139146
console.time(NaN);
140147
console.timeEnd(NaN);
141148

149+
console.time('log1');
150+
console.timeLog('log1');
151+
console.timeLog('log1', 'test');
152+
console.timeLog('log1', {}, [1, 2, 3]);
153+
console.timeEnd('log1');
154+
142155
console.assert(false, '%s should', 'console.assert', 'not throw');
143156
assert.strictEqual(errStrings[errStrings.length - 1],
144157
'Assertion failed: console.assert should not throw\n');
@@ -179,9 +192,11 @@ for (const expected of expectedStrings) {
179192
}
180193

181194
assert.strictEqual(strings.shift(),
182-
"{ foo: 'bar', inspect: [Function: inspect] }\n");
195+
"{ foo: 'bar',\n [Symbol(util.inspect.custom)]: " +
196+
'[Function: [util.inspect.custom]] }\n');
183197
assert.strictEqual(strings.shift(),
184-
"{ foo: 'bar', inspect: [Function: inspect] }\n");
198+
"{ foo: 'bar',\n [Symbol(util.inspect.custom)]: " +
199+
'[Function: [util.inspect.custom]] }\n');
185200
assert.ok(strings.shift().includes('foo: [Object]'));
186201
assert.strictEqual(strings.shift().includes('baz'), false);
187202
assert.strictEqual(strings.shift(), 'inspect inspect\n');
@@ -202,6 +217,14 @@ assert.ok(/^default: \d+\.\d{3}ms$/.test(strings.shift().trim()));
202217
assert.ok(/^default: \d+\.\d{3}ms$/.test(strings.shift().trim()));
203218
assert.ok(/^NaN: \d+\.\d{3}ms$/.test(strings.shift().trim()));
204219

220+
assert.ok(/^log1: \d+\.\d{3}ms$/.test(strings.shift().trim()));
221+
assert.ok(/^log1: \d+\.\d{3}ms test$/.test(strings.shift().trim()));
222+
assert.ok(/^log1: \d+\.\d{3}ms {} \[ 1, 2, 3 ]$/.test(strings.shift().trim()));
223+
assert.ok(/^log1: \d+\.\d{3}ms$/.test(strings.shift().trim()));
224+
225+
// Make sure that we checked all strings
226+
assert.strictEqual(strings.length, 0);
227+
205228
assert.strictEqual(errStrings.shift().split('\n').shift(),
206229
'Trace: This is a {"formatted":"trace"} 10 foo');
207230

@@ -212,6 +235,6 @@ common.hijackStderr(common.mustCall(function(data) {
212235

213236
// stderr.write will catch sync error, so use `process.nextTick` here
214237
process.nextTick(function() {
215-
assert.strictEqual(data.includes('no such label'), true);
238+
assert.strictEqual(data.includes('nolabel'), true);
216239
});
217240
}));

0 commit comments

Comments
 (0)