Browse Source

console: add console.count() and console.clear()

Both are simple utility functions defined by the WHATWG
console spec (https://console.spec.whatwg.org/).

PR-URL: https://github.com/nodejs/node/pull/12678
Ref: https://github.com/nodejs/node/issues/12675
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
v6
James M Snell 8 years ago
parent
commit
cc43c8fb54
  1. 70
      doc/api/console.md
  2. 39
      lib/console.js
  3. 22
      test/parallel/test-console-clear.js
  4. 63
      test/parallel/test-console-count.js

70
doc/api/console.md

@ -167,6 +167,76 @@ console.assert(false, 'this message will print, but no error thrown');
console.log('this will also print');
```
### console.clear()
<!-- YAML
added: REPLACEME
-->
When `stdout` is a TTY, calling `console.clear()` will attempt to clear the
TTY. When `stdout` is not a TTY, this method does nothing.
*Note*: The specific operation of `console.clear()` can vary across operating
systems and terminal types. For most Linux operating systems, `console.clear()`
operates similarly to the `clear` shell command. On Windows, `console.clear()`
will clear only the output in the current terminal viewport for the Node.js
binary.
### console.count([label])
<!-- YAML
added: REPLACEME
-->
* `label` {string} The display label for the counter. Defaults to `'default'`.
Maintains an internal counter specific to `label` and outputs to `stdout` the
number of times `console.count()` has been called with the given `label`.
<!-- eslint-skip -->
```js
> console.count()
default: 1
undefined
> console.count('default')
default: 2
undefined
> console.count('abc')
abc: 1
undefined
> console.count('xyz')
xyz: 1
undefined
> console.count('abc')
abc: 2
undefined
> console.count()
default: 3
undefined
>
```
### console.countReset([label = 'default'])
<!-- YAML
added: REPLACEME
-->
* `label` {string} The display label for the counter. Defaults to `'default'`.
Resets the internal counter specific to `label`.
<!-- eslint-skip -->
```js
> console.count('abc');
abc: 1
undefined
> console.countReset('abc');
undefined
> console.count('abc');
abc: 1
undefined
>
```
<!-- eslint-enable -->
### console.dir(obj[, options])
<!-- YAML
added: v0.1.101

39
lib/console.js

@ -23,6 +23,7 @@
const errors = require('internal/errors');
const util = require('util');
const kCounts = Symbol('counts');
function Console(stdout, stderr, ignoreErrors = true) {
if (!(this instanceof Console)) {
@ -55,6 +56,8 @@ function Console(stdout, stderr, ignoreErrors = true) {
prop.value = createWriteErrorHandler(stderr);
Object.defineProperty(this, '_stderrErrorHandler', prop);
this[kCounts] = new Map();
// bind the prototype functions to this Console instance
var keys = Object.keys(Console.prototype);
for (var v = 0; v < keys.length; v++) {
@ -166,6 +169,42 @@ Console.prototype.assert = function assert(expression, ...args) {
}
};
// Defined by: https://console.spec.whatwg.org/#clear
Console.prototype.clear = function clear() {
// It only makes sense to clear if _stdout is a TTY.
// Otherwise, do nothing.
if (this._stdout.isTTY) {
// The require is here intentionally to avoid readline being
// required too early when console is first loaded.
const { cursorTo, clearScreenDown } = require('readline');
cursorTo(this._stdout, 0, 0);
clearScreenDown(this._stdout);
}
};
// Defined by: https://console.spec.whatwg.org/#count
Console.prototype.count = function count(label = 'default') {
// Ensures that label is a string, and only things that can be
// coerced to strings. e.g. Symbol is not allowed
label = `${label}`;
const counts = this[kCounts];
let count = counts.get(label);
if (count === undefined)
count = 1;
else
count++;
counts.set(label, count);
this.log(`${label}: ${count}`);
};
// Not yet defined by the https://console.spec.whatwg.org, but
// proposed to be added and currently implemented by Edge. Having
// the ability to reset counters is important to help prevent
// the counter from being a memory leak.
Console.prototype.countReset = function countReset(label = 'default') {
const counts = this[kCounts];
counts.delete(`${label}`);
};
module.exports = new Console(process.stdout, process.stderr);
module.exports.Console = Console;

22
test/parallel/test-console-clear.js

@ -0,0 +1,22 @@
'use strict';
require('../common');
const assert = require('assert');
const stdoutWrite = process.stdout.write;
// The sequence for moving the cursor to 0,0 and clearing screen down
const check = '\u001b[1;1H\u001b[0J';
function doTest(isTTY, check) {
let buf = '';
process.stdout.isTTY = isTTY;
process.stdout.write = (string) => buf += string;
console.clear();
process.stdout.write = stdoutWrite;
assert.strictEqual(buf, check);
}
// Fake TTY
doTest(true, check);
doTest(false, '');

63
test/parallel/test-console-count.js

@ -0,0 +1,63 @@
'use strict';
require('../common');
const assert = require('assert');
const stdoutWrite = process.stdout.write;
let buf = '';
process.stdout.write = (string) => buf = string;
console.count();
assert.strictEqual(buf, 'default: 1\n');
// 'default' and undefined are equivalent
console.count('default');
assert.strictEqual(buf, 'default: 2\n');
console.count('a');
assert.strictEqual(buf, 'a: 1\n');
console.count('b');
assert.strictEqual(buf, 'b: 1\n');
console.count('a');
assert.strictEqual(buf, 'a: 2\n');
console.count();
assert.strictEqual(buf, 'default: 3\n');
console.count({});
assert.strictEqual(buf, '[object Object]: 1\n');
console.count(1);
assert.strictEqual(buf, '1: 1\n');
console.count(null);
assert.strictEqual(buf, 'null: 1\n');
console.count('null');
assert.strictEqual(buf, 'null: 2\n');
console.countReset();
console.count();
assert.strictEqual(buf, 'default: 1\n');
console.countReset('a');
console.count('a');
assert.strictEqual(buf, 'a: 1\n');
// countReset('a') only reset the a counter
console.count();
assert.strictEqual(buf, 'default: 2\n');
process.stdout.write = stdoutWrite;
// Symbol labels do not work
assert.throws(
() => console.count(Symbol('test')),
/^TypeError: Cannot convert a Symbol value to a string$/);
assert.throws(
() => console.countReset(Symbol('test')),
/^TypeError: Cannot convert a Symbol value to a string$/);
Loading…
Cancel
Save