Skip to content

Commit 79a3e37

Browse files
jasnellMylesBorins
authored andcommitted
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: #12678 Ref: #12675 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Daijiro Wachi <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Tobias Nießen <[email protected]>
1 parent 5c18651 commit 79a3e37

File tree

4 files changed

+194
-0
lines changed

4 files changed

+194
-0
lines changed

‎doc/api/console.md‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,76 @@ console.assert(false, 'this message will print, but no error thrown');
155155
console.log('this will also print');
156156
```
157157

158+
### console.clear()
159+
<!-- YAML
160+
added: REPLACEME
161+
-->
162+
163+
When `stdout` is a TTY, calling `console.clear()` will attempt to clear the
164+
TTY. When `stdout` is not a TTY, this method does nothing.
165+
166+
*Note*: The specific operation of `console.clear()` can vary across operating
167+
systems and terminal types. For most Linux operating systems, `console.clear()`
168+
operates similarly to the `clear` shell command. On Windows, `console.clear()`
169+
will clear only the output in the current terminal viewport for the Node.js
170+
binary.
171+
172+
### console.count([label])
173+
<!-- YAML
174+
added: REPLACEME
175+
-->
176+
177+
*`label`{string} The display label for the counter. Defaults to `'default'`.
178+
179+
Maintains an internal counter specific to `label` and outputs to `stdout` the
180+
number of times `console.count()` has been called with the given `label`.
181+
182+
<!-- eslint-skip -->
183+
```js
184+
>console.count()
185+
default:1
186+
undefined
187+
>console.count('default')
188+
default:2
189+
undefined
190+
>console.count('abc')
191+
abc:1
192+
undefined
193+
>console.count('xyz')
194+
xyz:1
195+
undefined
196+
>console.count('abc')
197+
abc:2
198+
undefined
199+
>console.count()
200+
default:3
201+
undefined
202+
>
203+
```
204+
205+
### console.countReset([label = 'default'])
206+
<!-- YAML
207+
added: REPLACEME
208+
-->
209+
210+
*`label`{string} The display label for the counter. Defaults to `'default'`.
211+
212+
Resets the internal counter specific to `label`.
213+
214+
<!-- eslint-skip -->
215+
```js
216+
>console.count('abc');
217+
abc:1
218+
undefined
219+
>console.countReset('abc');
220+
undefined
221+
>console.count('abc');
222+
abc:1
223+
undefined
224+
>
225+
```
226+
<!-- eslint-enable -->
227+
158228
### console.dir(obj[, options])
159229
<!-- YAML
160230
added: v0.1.101

‎lib/console.js‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
constutil=require('util');
4+
constkCounts=Symbol('counts');
45

56
functionConsole(stdout,stderr){
67
if(!(thisinstanceofConsole)){
@@ -27,6 +28,8 @@ function Console(stdout, stderr){
2728
prop.value=newMap();
2829
Object.defineProperty(this,'_times',prop);
2930

31+
this[kCounts]=newMap();
32+
3033
// bind the prototype functions to this Console instance
3134
varkeys=Object.keys(Console.prototype);
3235
for(varv=0;v<keys.length;v++){
@@ -96,6 +99,42 @@ Console.prototype.assert = function(expression, ...args){
9699
}
97100
};
98101

102+
// Defined by: https://console.spec.whatwg.org/#clear
103+
Console.prototype.clear=functionclear(){
104+
// It only makes sense to clear if _stdout is a TTY.
105+
// Otherwise, do nothing.
106+
if(this._stdout.isTTY){
107+
// The require is here intentionally to avoid readline being
108+
// required too early when console is first loaded.
109+
const{ cursorTo, clearScreenDown }=require('readline');
110+
cursorTo(this._stdout,0,0);
111+
clearScreenDown(this._stdout);
112+
}
113+
};
114+
115+
// Defined by: https://console.spec.whatwg.org/#count
116+
Console.prototype.count=functioncount(label='default'){
117+
// Ensures that label is a string, and only things that can be
118+
// coerced to strings. e.g. Symbol is not allowed
119+
label=`${label}`;
120+
constcounts=this[kCounts];
121+
letcount=counts.get(label);
122+
if(count===undefined)
123+
count=1;
124+
else
125+
count++;
126+
counts.set(label,count);
127+
this.log(`${label}: ${count}`);
128+
};
129+
130+
// Not yet defined by the https://console.spec.whatwg.org, but
131+
// proposed to be added and currently implemented by Edge. Having
132+
// the ability to reset counters is important to help prevent
133+
// the counter from being a memory leak.
134+
Console.prototype.countReset=functioncountReset(label='default'){
135+
constcounts=this[kCounts];
136+
counts.delete(`${label}`);
137+
};
99138

100139
module.exports=newConsole(process.stdout,process.stderr);
101140
module.exports.Console=Console;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
3+
require('../common');
4+
constassert=require('assert');
5+
6+
conststdoutWrite=process.stdout.write;
7+
8+
// The sequence for moving the cursor to 0,0 and clearing screen down
9+
constcheck='\u001b[1;1H\u001b[0J';
10+
11+
functiondoTest(isTTY,check){
12+
letbuf='';
13+
process.stdout.isTTY=isTTY;
14+
process.stdout.write=(string)=>buf+=string;
15+
console.clear();
16+
process.stdout.write=stdoutWrite;
17+
assert.strictEqual(buf,check);
18+
}
19+
20+
// Fake TTY
21+
doTest(true,check);
22+
doTest(false,'');
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
'use strict';
2+
3+
require('../common');
4+
constassert=require('assert');
5+
6+
conststdoutWrite=process.stdout.write;
7+
8+
letbuf='';
9+
10+
process.stdout.write=(string)=>buf=string;
11+
12+
console.count();
13+
assert.strictEqual(buf,'default: 1\n');
14+
15+
// 'default' and undefined are equivalent
16+
console.count('default');
17+
assert.strictEqual(buf,'default: 2\n');
18+
19+
console.count('a');
20+
assert.strictEqual(buf,'a: 1\n');
21+
22+
console.count('b');
23+
assert.strictEqual(buf,'b: 1\n');
24+
25+
console.count('a');
26+
assert.strictEqual(buf,'a: 2\n');
27+
28+
console.count();
29+
assert.strictEqual(buf,'default: 3\n');
30+
31+
console.count({});
32+
assert.strictEqual(buf,'[object Object]: 1\n');
33+
34+
console.count(1);
35+
assert.strictEqual(buf,'1: 1\n');
36+
37+
console.count(null);
38+
assert.strictEqual(buf,'null: 1\n');
39+
40+
console.count('null');
41+
assert.strictEqual(buf,'null: 2\n');
42+
43+
console.countReset();
44+
console.count();
45+
assert.strictEqual(buf,'default: 1\n');
46+
47+
console.countReset('a');
48+
console.count('a');
49+
assert.strictEqual(buf,'a: 1\n');
50+
51+
// countReset('a') only reset the a counter
52+
console.count();
53+
assert.strictEqual(buf,'default: 2\n');
54+
55+
process.stdout.write=stdoutWrite;
56+
57+
// Symbol labels do not work
58+
assert.throws(
59+
()=>console.count(Symbol('test')),
60+
/^TypeError:CannotconvertaSymbolvaluetoastring$/);
61+
assert.throws(
62+
()=>console.countReset(Symbol('test')),
63+
/^TypeError:CannotconvertaSymbolvaluetoastring$/);

0 commit comments

Comments
(0)