Skip to content

Commit 2e48257

Browse files
author
SparshGarg999
committed
util: allow styleText text param to accept non-string scalars
Allow util.styleText() to accept umber, �oolean, and �igint`nvalues for the ext parameter, automatically coercing them to string via String(text). Previously, passing anything other than a string would throw ERR_INVALID_ARG_TYPE. This forced callers to wrap every non-string value manually: util.styleText('red', String(count)) // before util.styleText('red', count) // after The coercion is applied before the fast path so there is no extra branching cost for the common string case. Values that cannot be meaningfully stringified (null, undefined, Symbol, Function, Object) still throw ERR_INVALID_ARG_TYPE as before. Fixes: #63841 Signed-off-by: SparshGarg999 <sparshgarg999@gmail.com>
1 parent a4821c8 commit 2e48257

3 files changed

Lines changed: 43 additions & 5 deletions

File tree

doc/api/util.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2574,7 +2574,9 @@ changes:
25742574
* `format` {string | Array} A text format or an Array
25752575
of text formats defined in `util.inspect.colors`, or a hex color in `#RGB`
25762576
or `#RRGGBB` form.
2577-
* `text` {string} The text to be formatted.
2577+
* `text` {string|number|boolean|bigint} The text to be formatted.
2578+
Non-string scalar values (`number`, `boolean`, `bigint`) are coerced
2579+
to a string internally via `String(text)`.
25782580
* `options` {Object}
25792581
* `validateStream` {boolean} When true, `stream` is checked to see if it can handle colors. **Default:** `true`.
25802582
* `stream` {Stream} A stream that will be validated if it can be colored. **Default:** `process.stdout`.

lib/util.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ function rgbToAnsi24Bit(r, g, b) {
237237

238238
/**
239239
* @param {string | string[]} format
240-
* @param {string} text
240+
* @param {string | number | boolean | bigint} text
241241
* @param {object} [options]
242242
* @param {boolean} [options.validateStream] - Whether to validate the stream.
243243
* @param {Stream} [options.stream] - The stream used for validation.
@@ -246,6 +246,14 @@ function rgbToAnsi24Bit(r, g, b) {
246246
function styleText(format, text, options) {
247247
const validateStream = options?.validateStream ?? true;
248248

249+
// Coerce scalar values (number, boolean, bigint) to string.
250+
// This avoids requiring callers to manually cast values like
251+
// `String(count)` before passing them to styleText.
252+
const textType = typeof text;
253+
if (textType === 'number' || textType === 'boolean' || textType === 'bigint') {
254+
text = String(text);
255+
}
256+
249257
// Fast path: single format string with validateStream=false
250258
if (!validateStream && typeof format === 'string' && typeof text === 'string') {
251259
const cache = getStyleCache();
@@ -268,7 +276,9 @@ function styleText(format, text, options) {
268276
}
269277
}
270278

271-
validateString(text, 'text');
279+
if (textType !== 'number' && textType !== 'boolean' && textType !== 'bigint') {
280+
validateString(text, 'text');
281+
}
272282
if (options !== undefined) {
273283
validateObject(options, 'options');
274284
}

test/parallel/test-util-styletext.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,39 @@ const noChange = 'test';
2323
}, {
2424
code: 'ERR_INVALID_ARG_VALUE',
2525
}, invalidOption);
26+
});
27+
28+
// Non-string scalars for `text` should NOT throw — they are coerced internally.
29+
[
30+
null,
31+
undefined,
32+
Symbol(),
33+
() => {},
34+
{},
35+
].forEach((invalidText) => {
2636
assert.throws(() => {
27-
util.styleText('red', invalidOption);
37+
util.styleText('red', invalidText);
2838
}, {
2939
code: 'ERR_INVALID_ARG_TYPE'
30-
}, invalidOption);
40+
}, invalidText);
3141
});
3242

43+
// Scalar values are coerced to string (number, boolean, bigint).
44+
assert.strictEqual(
45+
util.styleText('red', 42, { validateStream: false }),
46+
'\u001b[31m42\u001b[39m',
47+
);
48+
49+
assert.strictEqual(
50+
util.styleText('red', true, { validateStream: false }),
51+
'\u001b[31mtrue\u001b[39m',
52+
);
53+
54+
assert.strictEqual(
55+
util.styleText('red', 3n, { validateStream: false }),
56+
'\u001b[31m3\u001b[39m',
57+
);
58+
3359
assert.throws(() => {
3460
util.styleText('invalid', 'text');
3561
}, {

0 commit comments

Comments
 (0)