Skip to content
File

Blob: src/workerd/api/node/tests/util-nodejs-test.js

javascript6002 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4//
5// Adapted from Node.js. Copyright Joyent, Inc. and other Node contributors.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a
8// copy of this software and associated documentation files (the
9// "Software"), to deal in the Software without restriction, including
10// without limitation the rights to use, copy, modify, merge, publish,
11// distribute, sublicense, and/or sell copies of the Software, and to permit
12// persons to whom the Software is furnished to do so, subject to the
13// following conditions:
14//
15// The above copyright notice and this permission notice shall be included
16// in all copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
21// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24// USE OR OTHER DEALINGS IN THE SOFTWARE.
25 
26import assert from 'node:assert';
27import { mock } from 'node:test';
28import util, {
29 inspect,
30 callbackify,
31 inherits,
32 promisify,
33 stripVTControlCharacters,
34 styleText,
35 parseEnv,
36} from 'node:util';
37 
38const remainingMustCallErrors = new Set();
39function commonMustCall(f) {
40 const error = new Error('Expected function to be called');
41 remainingMustCallErrors.add(error);
42 return function (...args) {
43 remainingMustCallErrors.delete(error);
44 return f.call(this, ...args);
45 };
46}
47function assertCalledMustCalls() {
48 try {
49 for (const error of remainingMustCallErrors) throw error;
50 } finally {
51 remainingMustCallErrors.clear();
52 }
53}
54 
55function invalidArgTypeHelper(input) {
56 if (input == null) {
57 return ` Received ${input}`;
58 }
59 if (typeof input === 'function') {
60 return ` Received function ${input.name}`;
61 }
62 if (typeof input === 'object') {
63 if (input.constructor?.name) {
64 return ` Received an instance of ${input.constructor.name}`;
65 }
66 return ` Received ${inspect(input, { depth: -1 })}`;
67 }
68 
69 let inspected = inspect(input, { colors: false });
70 if (inspected.length > 28) {
71 inspected = `${inspected.slice(inspected, 0, 25)}...`;
72 }
73 
74 return ` Received type ${typeof input} (${inspected})`;
75}
76 
77export const utilInspect = {
78 // test-util-inspect.js
79 test(ctrl, env, ctx) {
80 assert.strictEqual(util.inspect(1), '1');
81 assert.strictEqual(util.inspect(false), 'false');
82 assert.strictEqual(util.inspect(''), "''");
83 assert.strictEqual(util.inspect('hello'), "'hello'");
84 assert.strictEqual(
85 util.inspect(function abc() {}),
86 '[Function: abc]'
87 );
88 assert.strictEqual(
89 util.inspect(() => {}),
90 '[Function (anonymous)]'
91 );
92 assert.strictEqual(
93 util.inspect(async function () {}),
94 '[AsyncFunction (anonymous)]'
95 );
96 assert.strictEqual(
97 util.inspect(async () => {}),
98 '[AsyncFunction (anonymous)]'
99 );
100 
101 // Special function inspection.
102 {
103 const fn = (() => function* () {})();
104 assert.strictEqual(util.inspect(fn), '[GeneratorFunction (anonymous)]');
105 assert.strictEqual(
106 util.inspect(async function* abc() {}),
107 '[AsyncGeneratorFunction: abc]'
108 );
109 Object.setPrototypeOf(
110 fn,
111 Object.getPrototypeOf(async () => {})
112 );
113 assert.strictEqual(
114 util.inspect(fn),
115 '[GeneratorFunction (anonymous)] AsyncFunction'
116 );
117 Object.defineProperty(fn, 'name', { value: 5, configurable: true });
118 assert.strictEqual(
119 util.inspect(fn),
120 '[GeneratorFunction: 5] AsyncFunction'
121 );
122 Object.defineProperty(fn, Symbol.toStringTag, {
123 value: 'Foobar',
124 configurable: true,
125 });
126 assert.strictEqual(
127 util.inspect({ ['5']: fn }),
128 "{ '5': [GeneratorFunction: 5] AsyncFunction [Foobar] }"
129 );
130 Object.defineProperty(fn, 'name', { value: '5', configurable: true });
131 Object.setPrototypeOf(fn, null);
132 assert.strictEqual(
133 util.inspect(fn),
134 '[GeneratorFunction (null prototype): 5] [Foobar]'
135 );
136 assert.strictEqual(
137 util.inspect({ ['5']: fn }),
138 "{ '5': [GeneratorFunction (null prototype): 5] [Foobar] }"
139 );
140 }
141 
142 assert.strictEqual(util.inspect(undefined), 'undefined');
143 assert.strictEqual(util.inspect(null), 'null');
144 assert.strictEqual(util.inspect(/foo(bar\n)?/gi), '/foo(bar\\n)?/gi');
145 assert.strictEqual(
146 util.inspect(new Date('Sun, 14 Feb 2010 11:48:40 GMT')),
147 new Date('2010-02-14T12:48:40+01:00').toISOString()
148 );
149 assert.strictEqual(util.inspect(new Date('')), new Date('').toString());
150 assert.strictEqual(util.inspect('\n\x01'), "'\\n\\x01'");
151 assert.strictEqual(
152 util.inspect(`${Array(75).fill(1)}'\n\x1d\n\x03\x85\x7f\x7e\x9f\xa0`),
153 // eslint-disable-next-line no-irregular-whitespace
154 `"${Array(75).fill(1)}'\\n" +\n '\\x1D\\n' +\n '\\x03\\x85\\x7F~\\x9F '`
155 );
156 assert.strictEqual(util.inspect([]), '[]');
157 assert.strictEqual(util.inspect({ __proto__: [] }), 'Array {}');
158 assert.strictEqual(util.inspect([1, 2]), '[ 1, 2 ]');
159 assert.strictEqual(util.inspect([1, [2, 3]]), '[ 1, [ 2, 3 ] ]');
160 assert.strictEqual(util.inspect({}), '{}');
161 assert.strictEqual(util.inspect({ a: 1 }), '{ a: 1 }');
162 assert.strictEqual(
163 util.inspect({ a: function () {} }),
164 '{ a: [Function: a] }'
165 );
166 assert.strictEqual(util.inspect({ a: () => {} }), '{ a: [Function: a] }');
167 assert.strictEqual(
168 util.inspect({ a: async function abc() {} }),
169 '{ a: [AsyncFunction: abc] }'
170 );
171 assert.strictEqual(
172 util.inspect({ a: async () => {} }),
173 '{ a: [AsyncFunction: a] }'
174 );
175 assert.strictEqual(
176 util.inspect({ a: function* () {} }),
177 '{ a: [GeneratorFunction: a] }'
178 );
179 assert.strictEqual(util.inspect({ a: 1, b: 2 }), '{ a: 1, b: 2 }');
180 assert.strictEqual(util.inspect({ a: {} }), '{ a: {} }');
181 assert.strictEqual(util.inspect({ a: { b: 2 } }), '{ a: { b: 2 } }');
182 assert.strictEqual(
183 util.inspect({ a: { b: { c: { d: 2 } } } }),
184 '{ a: { b: { c: [Object] } } }'
185 );
186 assert.strictEqual(
187 util.inspect({ a: { b: { c: { d: 2 } } } }, false, null),
188 '{\n a: { b: { c: { d: 2 } } }\n}'
189 );
190 assert.strictEqual(
191 util.inspect([1, 2, 3], true),
192 '[ 1, 2, 3, [length]: 3 ]'
193 );
194 assert.strictEqual(
195 util.inspect({ a: { b: { c: 2 } } }, false, 0),
196 '{ a: [Object] }'
197 );
198 assert.strictEqual(
199 util.inspect({ a: { b: { c: 2 } } }, false, 1),
200 '{ a: { b: [Object] } }'
201 );
202 assert.strictEqual(
203 util.inspect({ a: { b: ['c'] } }, false, 1),
204 '{ a: { b: [Array] } }'
205 );
206 assert.strictEqual(util.inspect(new Uint8Array(0)), 'Uint8Array(0) []');
207 assert(
208 inspect(new Uint8Array(0), { showHidden: true }).includes('[buffer]')
209 );
210 assert.strictEqual(
211 util.inspect(
212 Object.create(
213 {},
214 { visible: { value: 1, enumerable: true }, hidden: { value: 2 } }
215 )
216 ),
217 '{ visible: 1 }'
218 );
219 assert.strictEqual(
220 util.inspect(
221 Object.assign(new String('hello'), { [Symbol('foo')]: 123 }),
222 { showHidden: true }
223 ),
224 "[String: 'hello'] { [length]: 5, Symbol(foo): 123 }"
225 );
226 
227 {
228 const regexp = /regexp/;
229 regexp.aprop = 42;
230 assert.strictEqual(
231 util.inspect({ a: regexp }, false, 0),
232 '{ a: /regexp/ }'
233 );
234 }
235 
236 assert.match(
237 util.inspect({ a: { a: { a: { a: {} } } } }, undefined, undefined, true),
238 /Object/
239 );
240 assert.doesNotMatch(
241 util.inspect({ a: { a: { a: { a: {} } } } }, undefined, null, true),
242 /Object/
243 );
244 
245 {
246 const showHidden = true;
247 const ab = new Uint8Array([1, 2, 3, 4]).buffer;
248 const dv = new DataView(ab, 1, 2);
249 assert.strictEqual(
250 util.inspect(ab, showHidden),
251 'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }'
252 );
253 assert.strictEqual(
254 util.inspect(new DataView(ab, 1, 2), showHidden),
255 'DataView {\n' +
256 ' byteLength: 2,\n' +
257 ' byteOffset: 1,\n' +
258 ' buffer: ArrayBuffer {' +
259 ' [Uint8Contents]: <01 02 03 04>, byteLength: 4 }\n}'
260 );
261 assert.strictEqual(
262 util.inspect(ab, showHidden),
263 'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }'
264 );
265 assert.strictEqual(
266 util.inspect(dv, showHidden),
267 'DataView {\n' +
268 ' byteLength: 2,\n' +
269 ' byteOffset: 1,\n' +
270 ' buffer: ArrayBuffer { [Uint8Contents]: ' +
271 '<01 02 03 04>, byteLength: 4 }\n}'
272 );
273 ab.x = 42;
274 dv.y = 1337;
275 assert.strictEqual(
276 util.inspect(ab, showHidden),
277 'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, ' +
278 'byteLength: 4, x: 42 }'
279 );
280 assert.strictEqual(
281 util.inspect(dv, showHidden),
282 'DataView {\n' +
283 ' byteLength: 2,\n' +
284 ' byteOffset: 1,\n' +
285 ' buffer: ArrayBuffer { [Uint8Contents]: <01 02 03 04>,' +
286 ' byteLength: 4, x: 42 },\n' +
287 ' y: 1337\n}'
288 );
289 }
290 
291 {
292 const ab = new ArrayBuffer(42);
293 assert.strictEqual(ab.byteLength, 42);
294 structuredClone(ab, { transfer: [ab] });
295 assert.strictEqual(ab.byteLength, 0);
296 assert.strictEqual(
297 util.inspect(ab),
298 'ArrayBuffer { (detached), byteLength: 0 }'
299 );
300 }
301 
302 // Truncate output for ArrayBuffers using plural or singular bytes
303 {
304 const ab = new ArrayBuffer(3);
305 assert.strictEqual(
306 util.inspect(ab, { showHidden: true, maxArrayLength: 2 }),
307 'ArrayBuffer { [Uint8Contents]' +
308 ': <00 00 ... 1 more byte>, byteLength: 3 }'
309 );
310 assert.strictEqual(
311 util.inspect(ab, { showHidden: true, maxArrayLength: 1 }),
312 'ArrayBuffer { [Uint8Contents]' +
313 ': <00 ... 2 more bytes>, byteLength: 3 }'
314 );
315 }
316 
317 [
318 Float16Array,
319 Float32Array,
320 Float64Array,
321 Int16Array,
322 Int32Array,
323 Int8Array,
324 Uint16Array,
325 Uint32Array,
326 Uint8Array,
327 Uint8ClampedArray,
328 ].forEach((constructor) => {
329 const length = 2;
330 const byteLength = length * constructor.BYTES_PER_ELEMENT;
331 const array = new constructor(new ArrayBuffer(byteLength), 0, length);
332 array[0] = 65;
333 array[1] = 97;
334 assert.strictEqual(
335 util.inspect(array, { showHidden: true }),
336 `${constructor.name}(${length}) [\n` +
337 ' 65,\n' +
338 ' 97,\n' +
339 ` [BYTES_PER_ELEMENT]: ${constructor.BYTES_PER_ELEMENT},\n` +
340 ` [length]: ${length},\n` +
341 ` [byteLength]: ${byteLength},\n` +
342 ' [byteOffset]: 0,\n' +
343 ` [buffer]: ArrayBuffer { byteLength: ${byteLength} }\n]`
344 );
345 assert.strictEqual(
346 util.inspect(array, false),
347 `${constructor.name}(${length}) [ 65, 97 ]`
348 );
349 });
350 
351 {
352 const brokenLength = new Float32Array(2);
353 Object.defineProperty(brokenLength, 'length', { value: -1 });
354 assert.strictEqual(inspect(brokenLength), 'Float32Array(2) [ 0n, 0n ]');
355 }
356 
357 assert.strictEqual(
358 util.inspect(
359 Object.create(
360 {},
361 {
362 visible: { value: 1, enumerable: true },
363 hidden: { value: 2 },
364 }
365 ),
366 { showHidden: true }
367 ),
368 '{ visible: 1, [hidden]: 2 }'
369 );
370 // Objects without prototype.
371 assert.strictEqual(
372 util.inspect(
373 Object.create(null, {
374 name: { value: 'Tim', enumerable: true },
375 hidden: { value: 'secret' },
376 }),
377 { showHidden: true }
378 ),
379 "[Object: null prototype] { name: 'Tim', [hidden]: 'secret' }"
380 );
381 
382 assert.strictEqual(
383 util.inspect(
384 Object.create(null, {
385 name: { value: 'Tim', enumerable: true },
386 hidden: { value: 'secret' },
387 })
388 ),
389 "[Object: null prototype] { name: 'Tim' }"
390 );
391 
392 // Dynamic properties.
393 {
394 assert.strictEqual(
395 util.inspect({
396 get readonly() {
397 return 1;
398 },
399 }),
400 '{ readonly: [Getter] }'
401 );
402 
403 assert.strictEqual(
404 util.inspect({
405 get readwrite() {
406 return 1;
407 },
408 set readwrite(val) {},
409 }),
410 '{ readwrite: [Getter/Setter] }'
411 );
412 
413 assert.strictEqual(
414 util.inspect({ set writeonly(val) {} }),
415 '{ writeonly: [Setter] }'
416 );
417 
418 const value = {};
419 value.a = value;
420 assert.strictEqual(util.inspect(value), '<ref *1> { a: [Circular *1] }');
421 const getterFn = {
422 get one() {
423 return null;
424 },
425 };
426 assert.strictEqual(
427 util.inspect(getterFn, { getters: true }),
428 '{ one: [Getter: null] }'
429 );
430 }
431 
432 // Array with dynamic properties.
433 {
434 const value = [1, 2, 3];
435 Object.defineProperty(value, 'growingLength', {
436 enumerable: true,
437 get: function () {
438 this.push(true);
439 return this.length;
440 },
441 });
442 Object.defineProperty(value, '-1', {
443 enumerable: true,
444 value: -1,
445 });
446 assert.strictEqual(
447 util.inspect(value),
448 "[ 1, 2, 3, growingLength: [Getter], '-1': -1 ]"
449 );
450 }
451 
452 // Array with inherited number properties.
453 {
454 class CustomArray extends Array {}
455 CustomArray.prototype[5] = 'foo';
456 CustomArray.prototype[49] = 'bar';
457 CustomArray.prototype.foo = true;
458 const arr = new CustomArray(50);
459 arr[49] = 'I win';
460 assert.strictEqual(
461 util.inspect(arr),
462 "CustomArray(50) [ <49 empty items>, 'I win' ]"
463 );
464 assert.strictEqual(
465 util.inspect(arr, { showHidden: true }),
466 'CustomArray(50) [\n' +
467 ' <49 empty items>,\n' +
468 " 'I win',\n" +
469 ' [length]: 50,\n' +
470 " '5': 'foo',\n" +
471 ' foo: true\n' +
472 ']'
473 );
474 }
475 
476 // Array with extra properties.
477 {
478 const arr = [1, 2, 3, ,]; // eslint-disable-line no-sparse-arrays
479 arr.foo = 'bar';
480 assert.strictEqual(
481 util.inspect(arr),
482 "[ 1, 2, 3, <1 empty item>, foo: 'bar' ]"
483 );
484 
485 const arr2 = [];
486 assert.strictEqual(
487 util.inspect([], { showHidden: true }),
488 '[ [length]: 0 ]'
489 );
490 arr2['00'] = 1;
491 assert.strictEqual(util.inspect(arr2), "[ '00': 1 ]");
492 assert.strictEqual(
493 util.inspect(arr2, { showHidden: true }),
494 "[ [length]: 0, '00': 1 ]"
495 );
496 arr2[1] = 0;
497 assert.strictEqual(util.inspect(arr2), "[ <1 empty item>, 0, '00': 1 ]");
498 assert.strictEqual(
499 util.inspect(arr2, { showHidden: true }),
500 "[ <1 empty item>, 0, [length]: 2, '00': 1 ]"
501 );
502 delete arr2[1];
503 assert.strictEqual(util.inspect(arr2), "[ <2 empty items>, '00': 1 ]");
504 assert.strictEqual(
505 util.inspect(arr2, { showHidden: true }),
506 "[ <2 empty items>, [length]: 2, '00': 1 ]"
507 );
508 arr2['01'] = 2;
509 assert.strictEqual(
510 util.inspect(arr2),
511 "[ <2 empty items>, '00': 1, '01': 2 ]"
512 );
513 assert.strictEqual(
514 util.inspect(arr2, { showHidden: true }),
515 "[ <2 empty items>, [length]: 2, '00': 1, '01': 2 ]"
516 );
517 delete arr2['00'];
518 arr2[0] = 0;
519 assert.strictEqual(util.inspect(arr2), "[ 0, <1 empty item>, '01': 2 ]");
520 assert.strictEqual(
521 util.inspect(arr2, { showHidden: true }),
522 "[ 0, <1 empty item>, [length]: 2, '01': 2 ]"
523 );
524 delete arr2['01'];
525 arr2[2 ** 32 - 2] = 'max';
526 arr2[2 ** 32 - 1] = 'too far';
527 assert.strictEqual(
528 util.inspect(arr2),
529 "[ 0, <4294967293 empty items>, 'max', '4294967295': 'too far' ]"
530 );
531 
532 const arr3 = [];
533 arr3[-1] = -1;
534 assert.strictEqual(util.inspect(arr3), "[ '-1': -1 ]");
535 }
536 
537 // Indices out of bounds.
538 {
539 const arr = [];
540 arr[2 ** 32] = true; // Not a valid array index.
541 assert.strictEqual(util.inspect(arr), "[ '4294967296': true ]");
542 arr[0] = true;
543 arr[10] = true;
544 assert.strictEqual(
545 util.inspect(arr),
546 "[ true, <9 empty items>, true, '4294967296': true ]"
547 );
548 arr[2 ** 32 - 2] = true;
549 arr[2 ** 32 - 1] = true;
550 arr[2 ** 32 + 1] = true;
551 delete arr[0];
552 delete arr[10];
553 assert.strictEqual(
554 util.inspect(arr),
555 [
556 '[',
557 '<4294967294 empty items>,',
558 'true,',
559 "'4294967296': true,",
560 "'4294967295': true,",
561 "'4294967297': true\n]",
562 ].join('\n ')
563 );
564 }
565 
566 // Function with properties.
567 {
568 const value = () => {};
569 value.aprop = 42;
570 assert.strictEqual(
571 util.inspect(value),
572 '[Function: value] { aprop: 42 }'
573 );
574 }
575 
576 // Anonymous function with properties.
577 {
578 const value = (() => function () {})();
579 value.aprop = 42;
580 assert.strictEqual(
581 util.inspect(value),
582 '[Function (anonymous)] { aprop: 42 }'
583 );
584 }
585 
586 // Regular expressions with properties.
587 {
588 const value = /123/gi;
589 value.aprop = 42;
590 assert.strictEqual(util.inspect(value), '/123/gi { aprop: 42 }');
591 }
592 
593 // Dates with properties.
594 {
595 const value = new Date('Sun, 14 Feb 2010 11:48:40 GMT');
596 value.aprop = 42;
597 assert.strictEqual(
598 util.inspect(value),
599 '2010-02-14T11:48:40.000Z { aprop: 42 }'
600 );
601 }
602 
603 // Test positive/negative zero.
604 assert.strictEqual(util.inspect(0), '0');
605 assert.strictEqual(util.inspect(-0), '-0');
606 // Edge case from check.
607 assert.strictEqual(util.inspect(-5e-324), '-5e-324');
608 
609 // Test for sparse array.
610 {
611 const a = ['foo', 'bar', 'baz'];
612 assert.strictEqual(util.inspect(a), "[ 'foo', 'bar', 'baz' ]");
613 delete a[1];
614 assert.strictEqual(util.inspect(a), "[ 'foo', <1 empty item>, 'baz' ]");
615 assert.strictEqual(
616 util.inspect(a, true),
617 "[ 'foo', <1 empty item>, 'baz', [length]: 3 ]"
618 );
619 assert.strictEqual(util.inspect(new Array(5)), '[ <5 empty items> ]');
620 a[3] = 'bar';
621 a[100] = 'qux';
622 assert.strictEqual(
623 util.inspect(a, { breakLength: Infinity }),
624 "[ 'foo', <1 empty item>, 'baz', 'bar', <96 empty items>, 'qux' ]"
625 );
626 delete a[3];
627 assert.strictEqual(
628 util.inspect(a, { maxArrayLength: 4 }),
629 "[ 'foo', <1 empty item>, 'baz', <97 empty items>, ... 1 more item ]"
630 );
631 // test 4 special case
632 assert.strictEqual(
633 util.inspect(a, {
634 maxArrayLength: 2,
635 }),
636 "[ 'foo', <1 empty item>, ... 99 more items ]"
637 );
638 }
639 
640 // Test for property descriptors.
641 {
642 const getter = Object.create(null, {
643 a: {
644 get: function () {
645 return 'aaa';
646 },
647 },
648 });
649 const setter = Object.create(null, {
650 b: {
651 set: function () {},
652 },
653 });
654 const getterAndSetter = Object.create(null, {
655 c: {
656 get: function () {
657 return 'ccc';
658 },
659 set: function () {},
660 },
661 });
662 assert.strictEqual(
663 util.inspect(getter, true),
664 '[Object: null prototype] { [a]: [Getter] }'
665 );
666 assert.strictEqual(
667 util.inspect(setter, true),
668 '[Object: null prototype] { [b]: [Setter] }'
669 );
670 assert.strictEqual(
671 util.inspect(getterAndSetter, true),
672 '[Object: null prototype] { [c]: [Getter/Setter] }'
673 );
674 }
675 
676 // Exceptions should print the error message, not '{}'.
677 {
678 [
679 new Error(),
680 new Error('FAIL'),
681 new TypeError('FAIL'),
682 new SyntaxError('FAIL'),
683 ].forEach((err) => {
684 assert.strictEqual(util.inspect(err), err.stack);
685 });
686 assert.throws(
687 () => undef(), // eslint-disable-line no-undef
688 (e) => {
689 assert.strictEqual(util.inspect(e), e.stack);
690 return true;
691 }
692 );
693 
694 const ex = util.inspect(new Error('FAIL'), true);
695 assert(ex.includes('Error: FAIL'));
696 assert(ex.includes('[stack]'));
697 assert(ex.includes('[message]'));
698 }
699 
700 {
701 const falsyCause1 = new Error('', { cause: false });
702 delete falsyCause1.stack;
703 const falsyCause2 = new Error(undefined, { cause: null });
704 falsyCause2.stack = '';
705 const undefinedCause = new Error('', { cause: undefined });
706 undefinedCause.stack = '';
707 
708 assert.strictEqual(
709 util.inspect(falsyCause1),
710 '[Error] { [cause]: false }'
711 );
712 assert.strictEqual(
713 util.inspect(falsyCause2),
714 '[Error] { [cause]: null }'
715 );
716 assert.strictEqual(
717 util.inspect(undefinedCause),
718 '[Error] { [cause]: undefined }'
719 );
720 }
721 
722 {
723 const tmp = Error.stackTraceLimit;
724 Error.stackTraceLimit = 0;
725 const err = new Error('foo');
726 const err2 = new Error('foo\nbar');
727 assert.strictEqual(util.inspect(err, { compact: true }), '[Error: foo]');
728 assert(err.stack);
729 delete err.stack;
730 assert(!err.stack);
731 assert.strictEqual(util.inspect(err, { compact: true }), '[Error: foo]');
732 assert.strictEqual(
733 util.inspect(err2, { compact: true }),
734 '[Error: foo\nbar]'
735 );
736 
737 err.bar = true;
738 err2.bar = true;
739 
740 assert.strictEqual(
741 util.inspect(err, { compact: true }),
742 '{ [Error: foo] bar: true }'
743 );
744 assert.strictEqual(
745 util.inspect(err2, { compact: true }),
746 '{ [Error: foo\nbar]\n bar: true }'
747 );
748 assert.strictEqual(
749 util.inspect(err, { compact: true, breakLength: 5 }),
750 '{ [Error: foo]\n bar: true }'
751 );
752 assert.strictEqual(
753 util.inspect(err, { compact: true, breakLength: 1 }),
754 '{ [Error: foo]\n bar:\n true }'
755 );
756 assert.strictEqual(
757 util.inspect(err2, { compact: true, breakLength: 5 }),
758 '{ [Error: foo\nbar]\n bar: true }'
759 );
760 assert.strictEqual(
761 util.inspect(err, { compact: false }),
762 '[Error: foo] {\n bar: true\n}'
763 );
764 assert.strictEqual(
765 util.inspect(err2, { compact: false }),
766 '[Error: foo\nbar] {\n bar: true\n}'
767 );
768 
769 Error.stackTraceLimit = tmp;
770 }
771 
772 // Prevent enumerable error properties from being printed.
773 {
774 let err = new Error('foobar');
775 err.message = 'foobar';
776 let out = util.inspect(err).split('\n');
777 assert.strictEqual(out[0], 'Error: foobar');
778 assert(out[1].startsWith(' at '));
779 // Reset the error, the stack is otherwise not recreated.
780 err = new Error();
781 err.message = 'foobar';
782 out = util.inspect(err).split('\n');
783 assert.strictEqual(out[0], 'Error');
784 assert(out[1].startsWith(' at '));
785 assert.strictEqual(out[out.length - 2], " message: 'foobar'");
786 assert.strictEqual(out[out.length - 1], '}');
787 // Reset the error, the stack is otherwise not recreated.
788 err = new Error('foobar');
789 err.name = 'Unique';
790 Object.defineProperty(err, 'stack', {
791 value: err.stack,
792 enumerable: true,
793 });
794 out = util.inspect(err).split('\n');
795 assert.strictEqual(out[0], 'Unique: foobar');
796 assert(out[1].startsWith(' at '));
797 err.name = 'Baz';
798 out = util.inspect(err).split('\n');
799 assert.strictEqual(out[0], 'Unique: foobar');
800 assert.strictEqual(out[out.length - 2], " name: 'Baz'");
801 assert.strictEqual(out[out.length - 1], '}');
802 }
803 
804 // Doesn't capture stack trace.
805 {
806 function BadCustomError(msg) {
807 Error.call(this);
808 Object.defineProperty(this, 'message', {
809 value: msg,
810 enumerable: false,
811 });
812 Object.defineProperty(this, 'name', {
813 value: 'BadCustomError',
814 enumerable: false,
815 });
816 }
817 Object.setPrototypeOf(BadCustomError.prototype, Error.prototype);
818 Object.setPrototypeOf(BadCustomError, Error);
819 assert.strictEqual(
820 util.inspect(new BadCustomError('foo')),
821 '[BadCustomError: foo]'
822 );
823 }
824 
825 // Tampered error stack or name property (different type than string).
826 // Note: Symbols are not supported by `Error#toString()` which is called by
827 // accessing the `stack` property.
828 [
829 [404, '404 [RangeError]: foo', '[404]'],
830 [0, '0 [RangeError]: foo', '[RangeError: foo]'],
831 [0n, '0 [RangeError]: foo', '[RangeError: foo]'],
832 [null, 'null: foo', '[RangeError: foo]'],
833 [undefined, 'RangeError: foo', '[RangeError: foo]'],
834 [false, 'false [RangeError]: foo', '[RangeError: foo]'],
835 ['', 'foo', '[RangeError: foo]'],
836 [[1, 2, 3], '1,2,3 [RangeError]: foo', '[[\n 1,\n 2,\n 3\n]]'],
837 ].forEach(([value, outputStart, stack]) => {
838 let err = new RangeError('foo');
839 err.name = value;
840 assert(
841 util.inspect(err).startsWith(outputStart),
842 util.format(
843 'The name set to %o did not result in the expected output "%s"',
844 value,
845 outputStart
846 )
847 );
848 
849 err = new RangeError('foo');
850 err.stack = value;
851 assert.strictEqual(util.inspect(err), stack);
852 });
853 
854 // https://github.com/nodejs/node-v0.x-archive/issues/1941
855 assert.strictEqual(util.inspect({ __proto__: Date.prototype }), 'Date {}');
856 
857 // https://github.com/nodejs/node-v0.x-archive/issues/1944
858 {
859 const d = new Date();
860 d.toUTCString = null;
861 util.inspect(d);
862 }
863 
864 // Should not throw.
865 {
866 const d = new Date();
867 d.toISOString = null;
868 util.inspect(d);
869 }
870 
871 // Should not throw.
872 {
873 const r = /regexp/;
874 r.toString = null;
875 util.inspect(r);
876 }
877 
878 // See https://github.com/nodejs/node-v0.x-archive/issues/2225
879 {
880 const x = { [util.inspect.custom]: util.inspect };
881 assert(
882 util
883 .inspect(x)
884 .includes(
885 'Symbol(nodejs.util.inspect.custom): [Function: inspect] {\n'
886 )
887 );
888 }
889 
890 // `util.inspect` should display the escaped value of a key.
891 {
892 const w = {
893 '\\': 1,
894 '\\\\': 2,
895 '\\\\\\': 3,
896 '\\\\\\\\': 4,
897 '\n': 5,
898 '\r': 6,
899 };
900 
901 const y = ['a', 'b', 'c'];
902 y['\\\\'] = 'd';
903 y['\n'] = 'e';
904 y['\r'] = 'f';
905 
906 assert.strictEqual(
907 util.inspect(w),
908 "{ '\\\\': 1, '\\\\\\\\': 2, '\\\\\\\\\\\\': 3, " +
909 "'\\\\\\\\\\\\\\\\': 4, '\\n': 5, '\\r': 6 }"
910 );
911 assert.strictEqual(
912 util.inspect(y),
913 "[ 'a', 'b', 'c', '\\\\\\\\': 'd', " + "'\\n': 'e', '\\r': 'f' ]"
914 );
915 }
916 
917 // Escape unpaired surrogate pairs.
918 {
919 const edgeChar = String.fromCharCode(0xd799);
920 
921 for (let charCode = 0xd800; charCode < 0xdfff; charCode++) {
922 const surrogate = String.fromCharCode(charCode);
923 
924 assert.strictEqual(
925 util.inspect(surrogate),
926 `'\\u${charCode.toString(16)}'`
927 );
928 assert.strictEqual(
929 util.inspect(`${'a'.repeat(200)}${surrogate}`),
930 `'${'a'.repeat(200)}\\u${charCode.toString(16)}'`
931 );
932 assert.strictEqual(
933 util.inspect(`${surrogate}${'a'.repeat(200)}`),
934 `'\\u${charCode.toString(16)}${'a'.repeat(200)}'`
935 );
936 if (charCode < 0xdc00) {
937 const highSurrogate = surrogate;
938 const lowSurrogate = String.fromCharCode(charCode + 1024);
939 assert(
940 !util
941 .inspect(`${edgeChar}${highSurrogate}${lowSurrogate}${edgeChar}`)
942 .includes('\\u')
943 );
944 assert.strictEqual(
945 (
946 util
947 .inspect(`${highSurrogate}${highSurrogate}${lowSurrogate}`)
948 .match(/\\u/g) ?? []
949 ).length,
950 1
951 );
952 } else {
953 assert.strictEqual(
954 util.inspect(`${edgeChar}${surrogate}${edgeChar}`),
955 `'${edgeChar}\\u${charCode.toString(16)}${edgeChar}'`
956 );
957 }
958 }
959 }
960 
961 // Test util.inspect.styles and util.inspect.colors.
962 {
963 function testColorStyle(style, input) {
964 const colorName = util.inspect.styles[style];
965 let color = ['', ''];
966 if (util.inspect.colors[colorName])
967 color = util.inspect.colors[colorName];
968 
969 const withoutColor = util.inspect(input, false, 0, false);
970 const withColor = util.inspect(input, false, 0, true);
971 const expect = `\u001b[${color[0]}m${withoutColor}\u001b[${color[1]}m`;
972 assert.strictEqual(
973 withColor,
974 expect,
975 `util.inspect color for style ${style}`
976 );
977 }
978 
979 testColorStyle('special', function () {});
980 testColorStyle('number', 123.456);
981 testColorStyle('boolean', true);
982 testColorStyle('undefined', undefined);
983 testColorStyle('null', null);
984 testColorStyle('string', 'test string');
985 testColorStyle('date', new Date());
986 testColorStyle('regexp', /regexp/);
987 }
988 
989 // An object with "hasOwnProperty" overwritten should not throw.
990 util.inspect({ hasOwnProperty: null });
991 
992 // New API, accepts an "options" object.
993 {
994 const subject = { foo: 'bar', hello: 31, a: { b: { c: { d: 0 } } } };
995 Object.defineProperty(subject, 'hidden', {
996 enumerable: false,
997 value: null,
998 });
999 
1000 assert.strictEqual(
1001 util.inspect(subject, { showHidden: false }).includes('hidden'),
1002 false
1003 );
1004 assert.strictEqual(
1005 util.inspect(subject, { showHidden: true }).includes('hidden'),
1006 true
1007 );
1008 assert.strictEqual(
1009 util.inspect(subject, { colors: false }).includes('\u001b[32m'),
1010 false
1011 );
1012 assert.strictEqual(
1013 util.inspect(subject, { colors: true }).includes('\u001b[32m'),
1014 true
1015 );
1016 assert.strictEqual(
1017 util.inspect(subject, { depth: 2 }).includes('c: [Object]'),
1018 true
1019 );
1020 assert.strictEqual(
1021 util.inspect(subject, { depth: 0 }).includes('a: [Object]'),
1022 true
1023 );
1024 assert.strictEqual(
1025 util.inspect(subject, { depth: null }).includes('{ d: 0 }'),
1026 true
1027 );
1028 assert.strictEqual(
1029 util.inspect(subject, { depth: undefined }).includes('{ d: 0 }'),
1030 true
1031 );
1032 }
1033 
1034 {
1035 // "customInspect" option can enable/disable calling [util.inspect.custom]().
1036 const subject = { [util.inspect.custom]: () => 123 };
1037 
1038 assert.strictEqual(
1039 util.inspect(subject, { customInspect: true }).includes('123'),
1040 true
1041 );
1042 assert.strictEqual(
1043 util.inspect(subject, { customInspect: true }).includes('inspect'),
1044 false
1045 );
1046 assert.strictEqual(
1047 util.inspect(subject, { customInspect: false }).includes('123'),
1048 false
1049 );
1050 assert.strictEqual(
1051 util.inspect(subject, { customInspect: false }).includes('inspect'),
1052 true
1053 );
1054 
1055 // A custom [util.inspect.custom]() should be able to return other Objects.
1056 subject[util.inspect.custom] = () => ({ foo: 'bar' });
1057 
1058 assert.strictEqual(util.inspect(subject), "{ foo: 'bar' }");
1059 
1060 subject[util.inspect.custom] = commonMustCall((depth, opts, inspect) => {
1061 const clone = { ...opts };
1062 // This might change at some point but for now we keep the stylize function.
1063 // The function should either be documented or an alternative should be
1064 // implemented.
1065 assert.strictEqual(typeof opts.stylize, 'function');
1066 assert.strictEqual(opts.seen, undefined);
1067 assert.strictEqual(opts.budget, undefined);
1068 assert.strictEqual(opts.indentationLvl, undefined);
1069 assert.strictEqual(opts.showHidden, false);
1070 assert.strictEqual(inspect, util.inspect);
1071 assert.deepStrictEqual(
1072 new Set(Object.keys(inspect.defaultOptions).concat(['stylize'])),
1073 new Set(Object.keys(opts))
1074 );
1075 opts.showHidden = true;
1076 return {
1077 [inspect.custom]: commonMustCall((depth, opts2) => {
1078 assert.deepStrictEqual(clone, opts2);
1079 }),
1080 };
1081 });
1082 
1083 util.inspect(subject);
1084 
1085 // util.inspect.custom is a shared symbol which can be accessed as
1086 // Symbol.for("nodejs.util.inspect.custom").
1087 const inspect = Symbol.for('nodejs.util.inspect.custom');
1088 
1089 subject[inspect] = () => ({ baz: 'quux' });
1090 
1091 assert.strictEqual(util.inspect(subject), "{ baz: 'quux' }");
1092 
1093 subject[inspect] = (depth, opts) => {
1094 assert.strictEqual(opts.customInspectOptions, true);
1095 assert.strictEqual(opts.seen, null);
1096 return {};
1097 };
1098 
1099 util.inspect(subject, { customInspectOptions: true, seen: null });
1100 }
1101 
1102 {
1103 const subject = {
1104 [util.inspect.custom]: commonMustCall((depth, opts) => {
1105 assert.strictEqual(depth, null);
1106 assert.strictEqual(opts.compact, true);
1107 }),
1108 };
1109 util.inspect(subject, { depth: null, compact: true });
1110 }
1111 
1112 {
1113 // Returning `this` from a custom inspection function works.
1114 const subject = {
1115 a: 123,
1116 [util.inspect.custom]() {
1117 return this;
1118 },
1119 };
1120 const UIC = 'nodejs.util.inspect.custom';
1121 assert.strictEqual(
1122 util.inspect(subject),
1123 `{\n a: 123,\n Symbol(${UIC}): [Function: [${UIC}]]\n}`
1124 );
1125 }
1126 
1127 // Verify that it's possible to use the stylize function to manipulate input.
1128 assert.strictEqual(
1129 util.inspect([1, 2, 3], {
1130 stylize() {
1131 return 'x';
1132 },
1133 }),
1134 '[ x, x, x ]'
1135 );
1136 
1137 // Using `util.inspect` with "colors" option should produce as many lines as
1138 // without it.
1139 {
1140 function testLines(input) {
1141 const countLines = (str) => (str.match(/\n/g) || []).length;
1142 const withoutColor = util.inspect(input);
1143 const withColor = util.inspect(input, { colors: true });
1144 assert.strictEqual(countLines(withoutColor), countLines(withColor));
1145 }
1146 
1147 const bigArray = Array.from({ length: 100 }, (_value, index) => index);
1148 
1149 testLines([1, 2, 3, 4, 5, 6, 7]);
1150 testLines(bigArray);
1151 testLines({ foo: 'bar', baz: 35, b: { a: 35 } });
1152 testLines({
1153 a: { a: 3, b: 1, c: 1, d: 1, e: 1, f: 1, g: 1, h: 1 },
1154 b: 1,
1155 });
1156 testLines({
1157 foo: 'bar',
1158 baz: 35,
1159 b: { a: 35 },
1160 veryLongKey: 'very long value',
1161 evenLongerKey: ['with even longer value in array'],
1162 });
1163 }
1164 
1165 // Test boxed primitives output the correct values.
1166 assert.strictEqual(util.inspect(new String('test')), "[String: 'test']");
1167 assert.strictEqual(
1168 util.inspect(new String('test'), { colors: true }),
1169 "\u001b[32m[String: 'test']\u001b[39m"
1170 );
1171 assert.strictEqual(
1172 util.inspect(Object(Symbol('test'))),
1173 '[Symbol: Symbol(test)]'
1174 );
1175 assert.strictEqual(util.inspect(new Boolean(false)), '[Boolean: false]');
1176 assert.strictEqual(
1177 util.inspect(Object.setPrototypeOf(new Boolean(true), null)),
1178 '[Boolean (null prototype): true]'
1179 );
1180 assert.strictEqual(util.inspect(new Number(0)), '[Number: 0]');
1181 assert.strictEqual(
1182 util.inspect(
1183 Object.defineProperty(
1184 Object.setPrototypeOf(new Number(-0), Array.prototype),
1185 Symbol.toStringTag,
1186 { value: 'Foobar' }
1187 )
1188 ),
1189 '[Number (Array): -0] [Foobar]'
1190 );
1191 assert.strictEqual(util.inspect(new Number(-1.1)), '[Number: -1.1]');
1192 assert.strictEqual(util.inspect(new Number(13.37)), '[Number: 13.37]');
1193 
1194 // Test boxed primitives with own properties.
1195 {
1196 const str = new String('baz');
1197 str.foo = 'bar';
1198 assert.strictEqual(util.inspect(str), "[String: 'baz'] { foo: 'bar' }");
1199 
1200 const bool = new Boolean(true);
1201 bool.foo = 'bar';
1202 assert.strictEqual(util.inspect(bool), "[Boolean: true] { foo: 'bar' }");
1203 
1204 const num = new Number(13.37);
1205 num.foo = 'bar';
1206 assert.strictEqual(util.inspect(num), "[Number: 13.37] { foo: 'bar' }");
1207 
1208 const sym = Object(Symbol('foo'));
1209 sym.foo = 'bar';
1210 assert.strictEqual(
1211 util.inspect(sym),
1212 "[Symbol: Symbol(foo)] { foo: 'bar' }"
1213 );
1214 
1215 const big = Object(BigInt(55));
1216 big.foo = 'bar';
1217 assert.strictEqual(util.inspect(big), "[BigInt: 55n] { foo: 'bar' }");
1218 }
1219 
1220 // Test es6 Symbol.
1221 if (typeof Symbol !== 'undefined') {
1222 assert.strictEqual(util.inspect(Symbol()), 'Symbol()');
1223 assert.strictEqual(util.inspect(Symbol(123)), 'Symbol(123)');
1224 assert.strictEqual(util.inspect(Symbol('hi')), 'Symbol(hi)');
1225 assert.strictEqual(util.inspect([Symbol()]), '[ Symbol() ]');
1226 assert.strictEqual(util.inspect({ foo: Symbol() }), '{ foo: Symbol() }');
1227 
1228 const options = { showHidden: true };
1229 let subject = {};
1230 
1231 subject[Symbol('sym\nbol')] = 42;
1232 
1233 assert.strictEqual(util.inspect(subject), '{ Symbol(sym\\nbol): 42 }');
1234 assert.strictEqual(
1235 util.inspect(subject, options),
1236 '{ Symbol(sym\\nbol): 42 }'
1237 );
1238 
1239 Object.defineProperty(subject, Symbol(), {
1240 enumerable: false,
1241 value: 'non-enum',
1242 });
1243 assert.strictEqual(util.inspect(subject), '{ Symbol(sym\\nbol): 42 }');
1244 assert.strictEqual(
1245 util.inspect(subject, options),
1246 "{ Symbol(sym\\nbol): 42, [Symbol()]: 'non-enum' }"
1247 );
1248 
1249 subject = [1, 2, 3];
1250 subject[Symbol('symbol')] = 42;
1251 
1252 assert.strictEqual(
1253 util.inspect(subject),
1254 '[ 1, 2, 3, Symbol(symbol): 42 ]'
1255 );
1256 }
1257 
1258 // Test Set.
1259 {
1260 assert.strictEqual(util.inspect(new Set()), 'Set(0) {}');
1261 assert.strictEqual(
1262 util.inspect(new Set([1, 2, 3])),
1263 'Set(3) { 1, 2, 3 }'
1264 );
1265 assert.strictEqual(
1266 util.inspect(new Set([1, 2, 3]), { maxArrayLength: 1 }),
1267 'Set(3) { 1, ... 2 more items }'
1268 );
1269 const set = new Set(['foo']);
1270 set.bar = 42;
1271 assert.strictEqual(
1272 util.inspect(set, { showHidden: true }),
1273 "Set(1) { 'foo', bar: 42 }"
1274 );
1275 }
1276 
1277 // Test circular Set.
1278 {
1279 const set = new Set();
1280 set.add(set);
1281 assert.strictEqual(
1282 util.inspect(set),
1283 '<ref *1> Set(1) { [Circular *1] }'
1284 );
1285 }
1286 
1287 // Test Map.
1288 {
1289 assert.strictEqual(util.inspect(new Map()), 'Map(0) {}');
1290 assert.strictEqual(
1291 util.inspect(
1292 new Map([
1293 [1, 'a'],
1294 [2, 'b'],
1295 [3, 'c'],
1296 ])
1297 ),
1298 "Map(3) { 1 => 'a', 2 => 'b', 3 => 'c' }"
1299 );
1300 assert.strictEqual(
1301 util.inspect(
1302 new Map([
1303 [1, 'a'],
1304 [2, 'b'],
1305 [3, 'c'],
1306 ]),
1307 { maxArrayLength: 1 }
1308 ),
1309 "Map(3) { 1 => 'a', ... 2 more items }"
1310 );
1311 const map = new Map([['foo', null]]);
1312 map.bar = 42;
1313 assert.strictEqual(
1314 util.inspect(map, true),
1315 "Map(1) { 'foo' => null, bar: 42 }"
1316 );
1317 }
1318 
1319 // Test circular Map.
1320 {
1321 const map = new Map();
1322 map.set(map, 'map');
1323 assert.strictEqual(
1324 inspect(map),
1325 "<ref *1> Map(1) { [Circular *1] => 'map' }"
1326 );
1327 map.set(map, map);
1328 assert.strictEqual(
1329 inspect(map),
1330 '<ref *1> Map(1) { [Circular *1] => [Circular *1] }'
1331 );
1332 map.delete(map);
1333 map.set('map', map);
1334 assert.strictEqual(
1335 inspect(map),
1336 "<ref *1> Map(1) { 'map' => [Circular *1] }"
1337 );
1338 }
1339 
1340 // Test multiple circular references.
1341 {
1342 const obj = {};
1343 obj.a = [obj];
1344 obj.b = {};
1345 obj.b.inner = obj.b;
1346 obj.b.obj = obj;
1347 
1348 assert.strictEqual(
1349 inspect(obj),
1350 '<ref *1> {\n' +
1351 ' a: [ [Circular *1] ],\n' +
1352 ' b: <ref *2> { inner: [Circular *2], obj: [Circular *1] }\n' +
1353 '}'
1354 );
1355 }
1356 
1357 // Test Promise.
1358 {
1359 const resolved = Promise.resolve(3);
1360 assert.strictEqual(util.inspect(resolved), 'Promise { 3 }');
1361 
1362 const rejected = Promise.reject(3);
1363 assert.strictEqual(util.inspect(rejected), 'Promise { <rejected> 3 }');
1364 // Squelch UnhandledPromiseRejection.
1365 rejected.catch(() => {});
1366 
1367 const pending = new Promise(() => {});
1368 assert.strictEqual(util.inspect(pending), 'Promise { <pending> }');
1369 
1370 const promiseWithProperty = Promise.resolve('foo');
1371 promiseWithProperty.bar = 42;
1372 assert.strictEqual(
1373 util.inspect(promiseWithProperty),
1374 "Promise { 'foo', bar: 42 }"
1375 );
1376 }
1377 
1378 // Make sure it doesn't choke on polyfills. Unlike Set/Map, there is no standard
1379 // interface to synchronously inspect a Promise, so our techniques only work on
1380 // a bonafide native Promise.
1381 {
1382 const oldPromise = Promise;
1383 globalThis.Promise = function () {
1384 this.bar = 42;
1385 };
1386 assert.strictEqual(util.inspect(new Promise()), '{ bar: 42 }');
1387 globalThis.Promise = oldPromise;
1388 }
1389 
1390 // Test Map iterators.
1391 {
1392 const map = new Map([['foo', 'bar']]);
1393 assert.strictEqual(util.inspect(map.keys()), "[Map Iterator] { 'foo' }");
1394 const mapValues = map.values();
1395 Object.defineProperty(mapValues, Symbol.toStringTag, { value: 'Foo' });
1396 assert.strictEqual(
1397 util.inspect(mapValues),
1398 "[Foo] [Map Iterator] { 'bar' }"
1399 );
1400 map.set('A', 'B!');
1401 assert.strictEqual(
1402 util.inspect(map.entries(), { maxArrayLength: 1 }),
1403 "[Map Entries] { [ 'foo', 'bar' ], ... 1 more item }"
1404 );
1405 // Make sure the iterator doesn't get consumed.
1406 const keys = map.keys();
1407 assert.strictEqual(util.inspect(keys), "[Map Iterator] { 'foo', 'A' }");
1408 assert.strictEqual(util.inspect(keys), "[Map Iterator] { 'foo', 'A' }");
1409 keys.extra = true;
1410 assert.strictEqual(
1411 util.inspect(keys, { maxArrayLength: 0 }),
1412 '[Map Iterator] { ... 2 more items, extra: true }'
1413 );
1414 }
1415 
1416 // Test Set iterators.
1417 {
1418 const aSet = new Set([1]);
1419 assert.strictEqual(
1420 util.inspect(aSet.entries(), { compact: false }),
1421 '[Set Entries] {\n [\n 1,\n 1\n ]\n}'
1422 );
1423 aSet.add(3);
1424 assert.strictEqual(util.inspect(aSet.keys()), '[Set Iterator] { 1, 3 }');
1425 assert.strictEqual(
1426 util.inspect(aSet.values()),
1427 '[Set Iterator] { 1, 3 }'
1428 );
1429 const setEntries = aSet.entries();
1430 Object.defineProperty(setEntries, Symbol.toStringTag, { value: 'Foo' });
1431 assert.strictEqual(
1432 util.inspect(setEntries),
1433 '[Foo] [Set Entries] { [ 1, 1 ], [ 3, 3 ] }'
1434 );
1435 // Make sure the iterator doesn't get consumed.
1436 const keys = aSet.keys();
1437 Object.defineProperty(keys, Symbol.toStringTag, { value: null });
1438 assert.strictEqual(util.inspect(keys), '[Set Iterator] { 1, 3 }');
1439 assert.strictEqual(util.inspect(keys), '[Set Iterator] { 1, 3 }');
1440 keys.extra = true;
1441 assert.strictEqual(
1442 util.inspect(keys, { maxArrayLength: 1 }),
1443 '[Set Iterator] { 1, ... 1 more item, extra: true }'
1444 );
1445 }
1446 
1447 // Minimal inspection should still return as much information as possible about
1448 // the constructor and Symbol.toStringTag.
1449 {
1450 class Foo {
1451 get [Symbol.toStringTag]() {
1452 return 'ABC';
1453 }
1454 }
1455 const a = new Foo();
1456 assert.strictEqual(inspect(a, { depth: -1 }), 'Foo [ABC] {}');
1457 a.foo = true;
1458 assert.strictEqual(inspect(a, { depth: -1 }), '[Foo [ABC]]');
1459 Object.defineProperty(a, Symbol.toStringTag, {
1460 value: 'Foo',
1461 configurable: true,
1462 writable: true,
1463 });
1464 assert.strictEqual(inspect(a, { depth: -1 }), '[Foo]');
1465 // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
1466 delete a[Symbol.toStringTag];
1467 Object.setPrototypeOf(a, null);
1468 assert.strictEqual(inspect(a, { depth: -1 }), '[Foo: null prototype]');
1469 delete a.foo;
1470 assert.strictEqual(inspect(a, { depth: -1 }), '[Foo: null prototype] {}');
1471 Object.defineProperty(a, Symbol.toStringTag, {
1472 value: 'ABC',
1473 configurable: true,
1474 });
1475 assert.strictEqual(
1476 inspect(a, { depth: -1 }),
1477 '[Foo: null prototype] [ABC] {}'
1478 );
1479 Object.defineProperty(a, Symbol.toStringTag, {
1480 value: 'Foo',
1481 configurable: true,
1482 });
1483 assert.strictEqual(
1484 inspect(a, { depth: -1 }),
1485 '[Object: null prototype] [Foo] {}'
1486 );
1487 }
1488 
1489 // Test alignment of items in container.
1490 // Assumes that the first numeric character is the start of an item.
1491 {
1492 function checkAlignment(container, start, lineX, end) {
1493 const lines = util.inspect(container).split('\n');
1494 lines.forEach((line, i) => {
1495 if (i === 0) {
1496 assert.strictEqual(line, start);
1497 } else if (i === lines.length - 1) {
1498 assert.strictEqual(line, end);
1499 } else {
1500 let expected = lineX.replace('X', i - 1);
1501 if (i !== lines.length - 2) expected += ',';
1502 assert.strictEqual(line, expected);
1503 }
1504 });
1505 }
1506 
1507 const bigArray = [];
1508 for (let i = 0; i < 100; i++) {
1509 bigArray.push(i);
1510 }
1511 
1512 const obj = {};
1513 bigArray.forEach((prop) => {
1514 obj[prop] = null;
1515 });
1516 
1517 checkAlignment(obj, '{', " 'X': null", '}');
1518 checkAlignment(new Set(bigArray), 'Set(100) {', ' X', '}');
1519 checkAlignment(
1520 new Map(bigArray.map((number) => [number, null])),
1521 'Map(100) {',
1522 ' X => null',
1523 '}'
1524 );
1525 }
1526 
1527 // Test display of constructors.
1528 {
1529 class ObjectSubclass {}
1530 class ArraySubclass extends Array {}
1531 class SetSubclass extends Set {}
1532 class MapSubclass extends Map {}
1533 class PromiseSubclass extends Promise {}
1534 class SymbolNameClass {
1535 static name = Symbol('name');
1536 }
1537 
1538 const x = new ObjectSubclass();
1539 x.foo = 42;
1540 assert.strictEqual(util.inspect(x), 'ObjectSubclass { foo: 42 }');
1541 assert.strictEqual(
1542 util.inspect(new ArraySubclass(1, 2, 3)),
1543 'ArraySubclass(3) [ 1, 2, 3 ]'
1544 );
1545 assert.strictEqual(
1546 util.inspect(new SetSubclass([1, 2, 3])),
1547 'SetSubclass(3) [Set] { 1, 2, 3 }'
1548 );
1549 assert.strictEqual(
1550 util.inspect(new MapSubclass([['foo', 42]])),
1551 "MapSubclass(1) [Map] { 'foo' => 42 }"
1552 );
1553 assert.strictEqual(
1554 util.inspect(new PromiseSubclass(() => {})),
1555 'PromiseSubclass [Promise] { <pending> }'
1556 );
1557 assert.strictEqual(
1558 util.inspect(new SymbolNameClass()),
1559 'Symbol(name) {}'
1560 );
1561 assert.strictEqual(
1562 util.inspect(
1563 { a: { b: new ArraySubclass([1, [2], 3]) } },
1564 { depth: 1 }
1565 ),
1566 '{ a: { b: [ArraySubclass] } }'
1567 );
1568 assert.strictEqual(
1569 util.inspect(Object.setPrototypeOf(x, null)),
1570 '[ObjectSubclass: null prototype] { foo: 42 }'
1571 );
1572 }
1573 
1574 // Empty and circular before depth.
1575 {
1576 const arr = [[[[]]]];
1577 assert.strictEqual(util.inspect(arr), '[ [ [ [] ] ] ]');
1578 arr[0][0][0][0] = [];
1579 assert.strictEqual(util.inspect(arr), '[ [ [ [Array] ] ] ]');
1580 arr[0][0][0] = {};
1581 assert.strictEqual(util.inspect(arr), '[ [ [ {} ] ] ]');
1582 arr[0][0][0] = { a: 2 };
1583 assert.strictEqual(util.inspect(arr), '[ [ [ [Object] ] ] ]');
1584 arr[0][0][0] = arr;
1585 assert.strictEqual(
1586 util.inspect(arr),
1587 '<ref *1> [ [ [ [Circular *1] ] ] ]'
1588 );
1589 arr[0][0][0] = arr[0][0];
1590 assert.strictEqual(
1591 util.inspect(arr),
1592 '[ [ <ref *1> [ [Circular *1] ] ] ]'
1593 );
1594 }
1595 
1596 // Corner cases.
1597 {
1598 const x = { constructor: 42 };
1599 assert.strictEqual(util.inspect(x), '{ constructor: 42 }');
1600 }
1601 
1602 {
1603 const x = {};
1604 Object.defineProperty(x, 'constructor', {
1605 get: function () {
1606 throw new Error('should not access constructor');
1607 },
1608 enumerable: true,
1609 });
1610 assert.strictEqual(util.inspect(x), '{ constructor: [Getter] }');
1611 }
1612 
1613 {
1614 const x = new (function () {})();
1615 assert.strictEqual(util.inspect(x), '{}');
1616 }
1617 
1618 {
1619 const x = { __proto__: null };
1620 assert.strictEqual(util.inspect(x), '[Object: null prototype] {}');
1621 }
1622 
1623 {
1624 const x = [];
1625 x[''] = 1;
1626 assert.strictEqual(util.inspect(x), "[ '': 1 ]");
1627 }
1628 
1629 // The following maxArrayLength tests were introduced after v6.0.0 was released.
1630 // Do not backport to v5/v4 unless all of
1631 // https://github.com/nodejs/node/pull/6334 is backported.
1632 {
1633 const x = Array.from({ length: 101 });
1634 assert(util.inspect(x).endsWith('1 more item\n]'));
1635 assert(
1636 !util.inspect(x, { maxArrayLength: 101 }).endsWith('1 more item\n]')
1637 );
1638 assert.strictEqual(
1639 util.inspect(x, { maxArrayLength: -1 }),
1640 '[ ... 101 more items ]'
1641 );
1642 assert.strictEqual(
1643 util.inspect(x, { maxArrayLength: 0 }),
1644 '[ ... 101 more items ]'
1645 );
1646 }
1647 
1648 {
1649 const x = Array.from({ length: 101 });
1650 assert.strictEqual(
1651 util.inspect(x, { maxArrayLength: 0 }),
1652 '[ ... 101 more items ]'
1653 );
1654 assert(
1655 !util.inspect(x, { maxArrayLength: null }).endsWith('1 more item\n]')
1656 );
1657 assert(
1658 !util.inspect(x, { maxArrayLength: Infinity }).endsWith('1 more item ]')
1659 );
1660 }
1661 
1662 {
1663 const x = new Uint8Array(101);
1664 assert(util.inspect(x).endsWith('1 more item\n]'));
1665 assert(!util.inspect(x, { maxArrayLength: 101 }).includes('1 more item'));
1666 assert.strictEqual(
1667 util.inspect(x, { maxArrayLength: 0 }),
1668 'Uint8Array(101) [ ... 101 more items ]'
1669 );
1670 assert(
1671 !util.inspect(x, { maxArrayLength: null }).includes('1 more item')
1672 );
1673 assert(
1674 util.inspect(x, { maxArrayLength: Infinity }).endsWith(' 0, 0\n]')
1675 );
1676 }
1677 
1678 {
1679 const obj = { foo: 'abc', bar: 'xyz' };
1680 const oneLine = util.inspect(obj, { breakLength: Infinity });
1681 // Subtract four for the object's two curly braces and two spaces of padding.
1682 // Add one more to satisfy the strictly greater than condition in the code.
1683 const breakpoint = oneLine.length - 5;
1684 const twoLines = util.inspect(obj, { breakLength: breakpoint });
1685 
1686 assert.strictEqual(oneLine, "{ foo: 'abc', bar: 'xyz' }");
1687 assert.strictEqual(
1688 util.inspect(obj, { breakLength: breakpoint + 1 }),
1689 twoLines
1690 );
1691 assert.strictEqual(twoLines, "{\n foo: 'abc',\n bar: 'xyz'\n}");
1692 }
1693 
1694 // util.inspect.defaultOptions tests.
1695 {
1696 const arr = Array.from({ length: 101 });
1697 const obj = { a: { a: { a: { a: 1 } } } };
1698 
1699 const oldOptions = { ...util.inspect.defaultOptions };
1700 
1701 // Set single option through property assignment.
1702 util.inspect.defaultOptions.maxArrayLength = null;
1703 assert.doesNotMatch(util.inspect(arr), /1 more item/);
1704 util.inspect.defaultOptions.maxArrayLength = oldOptions.maxArrayLength;
1705 assert.match(util.inspect(arr), /1 more item/);
1706 util.inspect.defaultOptions.depth = null;
1707 assert.doesNotMatch(util.inspect(obj), /Object/);
1708 util.inspect.defaultOptions.depth = oldOptions.depth;
1709 assert.match(util.inspect(obj), /Object/);
1710 assert.strictEqual(
1711 JSON.stringify(util.inspect.defaultOptions),
1712 JSON.stringify(oldOptions)
1713 );
1714 
1715 // Set multiple options through object assignment.
1716 util.inspect.defaultOptions = { maxArrayLength: null, depth: 2 };
1717 assert.doesNotMatch(util.inspect(arr), /1 more item/);
1718 assert.match(util.inspect(obj), /Object/);
1719 util.inspect.defaultOptions = oldOptions;
1720 assert.match(util.inspect(arr), /1 more item/);
1721 assert.match(util.inspect(obj), /Object/);
1722 assert.strictEqual(
1723 JSON.stringify(util.inspect.defaultOptions),
1724 JSON.stringify(oldOptions)
1725 );
1726 
1727 assert.throws(
1728 () => {
1729 util.inspect.defaultOptions = null;
1730 },
1731 {
1732 code: 'ERR_INVALID_ARG_TYPE',
1733 name: 'TypeError',
1734 message:
1735 'The "options" argument must be of type object. ' + 'Received null',
1736 }
1737 );
1738 
1739 assert.throws(
1740 () => {
1741 util.inspect.defaultOptions = 'bad';
1742 },
1743 {
1744 code: 'ERR_INVALID_ARG_TYPE',
1745 name: 'TypeError',
1746 message:
1747 'The "options" argument must be of type object. ' +
1748 "Received type string ('bad')",
1749 }
1750 );
1751 }
1752 
1753 // Setting custom inspect property to a non-function should do nothing.
1754 {
1755 const obj = { [util.inspect.custom]: 'fhqwhgads' };
1756 assert.strictEqual(
1757 util.inspect(obj),
1758 "{ Symbol(nodejs.util.inspect.custom): 'fhqwhgads' }"
1759 );
1760 }
1761 
1762 {
1763 // @@toStringTag
1764 const obj = { [Symbol.toStringTag]: 'a' };
1765 assert.strictEqual(
1766 util.inspect(obj),
1767 "{ Symbol(Symbol.toStringTag): 'a' }"
1768 );
1769 Object.defineProperty(obj, Symbol.toStringTag, {
1770 value: 'a',
1771 enumerable: false,
1772 });
1773 assert.strictEqual(util.inspect(obj), 'Object [a] {}');
1774 assert.strictEqual(
1775 util.inspect(obj, { showHidden: true }),
1776 "{ [Symbol(Symbol.toStringTag)]: 'a' }"
1777 );
1778 
1779 class Foo {
1780 constructor() {
1781 this.foo = 'bar';
1782 }
1783 
1784 get [Symbol.toStringTag]() {
1785 return this.foo;
1786 }
1787 }
1788 
1789 assert.strictEqual(
1790 util.inspect(
1791 Object.create(null, { [Symbol.toStringTag]: { value: 'foo' } })
1792 ),
1793 '[Object: null prototype] [foo] {}'
1794 );
1795 
1796 assert.strictEqual(util.inspect(new Foo()), "Foo [bar] { foo: 'bar' }");
1797 
1798 assert.strictEqual(
1799 util.inspect(new (class extends Foo {})()),
1800 "Foo [bar] { foo: 'bar' }"
1801 );
1802 
1803 assert.strictEqual(
1804 util.inspect(
1805 Object.create(
1806 { __proto__: Foo.prototype },
1807 {
1808 foo: { value: 'bar', enumerable: true },
1809 }
1810 )
1811 ),
1812 "Foo [bar] { foo: 'bar' }"
1813 );
1814 
1815 class ThrowingClass {
1816 get [Symbol.toStringTag]() {
1817 throw new Error('toStringTag error');
1818 }
1819 }
1820 
1821 assert.throws(
1822 () => util.inspect(new ThrowingClass()),
1823 /toStringTag error/
1824 );
1825 
1826 class NotStringClass {
1827 get [Symbol.toStringTag]() {
1828 return null;
1829 }
1830 }
1831 
1832 assert.strictEqual(
1833 util.inspect(new NotStringClass()),
1834 'NotStringClass {}'
1835 );
1836 }
1837 
1838 {
1839 const o = {
1840 a: [
1841 1,
1842 2,
1843 [
1844 [
1845 'Lorem ipsum dolor\nsit amet,\tconsectetur adipiscing elit, sed do ' +
1846 'eiusmod tempor incididunt ut labore et dolore magna aliqua.',
1847 'test',
1848 'foo',
1849 ],
1850 ],
1851 4,
1852 ],
1853 b: new Map([
1854 ['za', 1],
1855 ['zb', 'test'],
1856 ]),
1857 };
1858 
1859 let out = util.inspect(o, { compact: true, depth: 5, breakLength: 80 });
1860 let expect = [
1861 '{ a:',
1862 ' [ 1,',
1863 ' 2,',
1864 " [ [ 'Lorem ipsum dolor\\nsit amet,\\tconsectetur adipiscing elit, " +
1865 "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',",
1866 " 'test',",
1867 " 'foo' ] ],",
1868 ' 4 ],',
1869 " b: Map(2) { 'za' => 1, 'zb' => 'test' } }",
1870 ].join('\n');
1871 assert.strictEqual(out, expect);
1872 
1873 out = util.inspect(o, { compact: false, depth: 5, breakLength: 60 });
1874 expect = [
1875 '{',
1876 ' a: [',
1877 ' 1,',
1878 ' 2,',
1879 ' [',
1880 ' [',
1881 " 'Lorem ipsum dolor\\n' +",
1882 " 'sit amet,\\tconsectetur adipiscing elit, sed do eiusmod " +
1883 "tempor incididunt ut labore et dolore magna aliqua.',",
1884 " 'test',",
1885 " 'foo'",
1886 ' ]',
1887 ' ],',
1888 ' 4',
1889 ' ],',
1890 ' b: Map(2) {',
1891 " 'za' => 1,",
1892 " 'zb' => 'test'",
1893 ' }',
1894 '}',
1895 ].join('\n');
1896 assert.strictEqual(out, expect);
1897 
1898 out = util.inspect(o.a[2][0][0], { compact: false, breakLength: 30 });
1899 expect = [
1900 "'Lorem ipsum dolor\\n' +",
1901 " 'sit amet,\\tconsectetur adipiscing elit, sed do eiusmod tempor " +
1902 "incididunt ut labore et dolore magna aliqua.'",
1903 ].join('\n');
1904 assert.strictEqual(out, expect);
1905 
1906 out = util.inspect('12345678901234567890123456789012345678901234567890', {
1907 compact: false,
1908 breakLength: 3,
1909 });
1910 expect = "'12345678901234567890123456789012345678901234567890'";
1911 assert.strictEqual(out, expect);
1912 
1913 out = util.inspect(
1914 '12 45 78 01 34 67 90 23 56 89 123456789012345678901234567890',
1915 { compact: false, breakLength: 3 }
1916 );
1917 expect = [
1918 "'12 45 78 01 34 67 90 23 56 89 123456789012345678901234567890'",
1919 ].join('\n');
1920 assert.strictEqual(out, expect);
1921 
1922 o.a = () => {};
1923 o.b = new Number(3);
1924 out = util.inspect(o, { compact: false, breakLength: 3 });
1925 expect = [
1926 '{',
1927 ' a: [Function (anonymous)],',
1928 ' b: [Number: 3]',
1929 '}',
1930 ].join('\n');
1931 assert.strictEqual(out, expect);
1932 
1933 out = util.inspect(o, {
1934 compact: false,
1935 breakLength: 3,
1936 showHidden: true,
1937 });
1938 expect = [
1939 '{',
1940 ' a: [Function (anonymous)] {',
1941 ' [length]: 0,',
1942 " [name]: ''",
1943 ' },',
1944 ' b: [Number: 3]',
1945 '}',
1946 ].join('\n');
1947 assert.strictEqual(out, expect);
1948 
1949 o[util.inspect.custom] = () => 42;
1950 out = util.inspect(o, { compact: false, breakLength: 3 });
1951 expect = '42';
1952 assert.strictEqual(out, expect);
1953 
1954 o[util.inspect.custom] = () => '12 45 78 01 34 67 90 23';
1955 out = util.inspect(o, { compact: false, breakLength: 3 });
1956 expect = '12 45 78 01 34 67 90 23';
1957 assert.strictEqual(out, expect);
1958 
1959 o[util.inspect.custom] = () => ({ a: '12 45 78 01 34 67 90 23' });
1960 out = util.inspect(o, { compact: false, breakLength: 3 });
1961 expect = "{\n a: '12 45 78 01 34 67 90 23'\n}";
1962 assert.strictEqual(out, expect);
1963 }
1964 
1965 // Check compact indentation.
1966 {
1967 const typed = new Uint8Array();
1968 typed.buffer.foo = true;
1969 const set = new Set([[1, 2]]);
1970 const promise = Promise.resolve([[1, set]]);
1971 const map = new Map([[promise, typed]]);
1972 map.set(set.values(), map.values());
1973 
1974 let out = util.inspect(map, {
1975 compact: false,
1976 showHidden: true,
1977 depth: 9,
1978 });
1979 let expected = [
1980 'Map(2) {',
1981 ' Promise {',
1982 ' [',
1983 ' [',
1984 ' 1,',
1985 ' Set(1) {',
1986 ' [',
1987 ' 1,',
1988 ' 2,',
1989 ' [length]: 2',
1990 ' ]',
1991 ' },',
1992 ' [length]: 2',
1993 ' ],',
1994 ' [length]: 1',
1995 ' ]',
1996 ' } => Uint8Array(0) [',
1997 ' [BYTES_PER_ELEMENT]: 1,',
1998 ' [length]: 0,',
1999 ' [byteLength]: 0,',
2000 ' [byteOffset]: 0,',
2001 ' [buffer]: ArrayBuffer {',
2002 ' byteLength: 0,',
2003 ' foo: true',
2004 ' }',
2005 ' ],',
2006 ' [Set Iterator] {',
2007 ' [',
2008 ' 1,',
2009 ' 2,',
2010 ' [length]: 2',
2011 ' ],',
2012 " [Symbol(Symbol.toStringTag)]: 'Set Iterator'",
2013 ' } => <ref *1> [Map Iterator] {',
2014 ' Uint8Array(0) [',
2015 ' [BYTES_PER_ELEMENT]: 1,',
2016 ' [length]: 0,',
2017 ' [byteLength]: 0,',
2018 ' [byteOffset]: 0,',
2019 ' [buffer]: ArrayBuffer {',
2020 ' byteLength: 0,',
2021 ' foo: true',
2022 ' }',
2023 ' ],',
2024 ' [Circular *1],',
2025 " [Symbol(Symbol.toStringTag)]: 'Map Iterator'",
2026 ' }',
2027 '}',
2028 ].join('\n');
2029 
2030 assert.strict.equal(out, expected);
2031 
2032 out = util.inspect(map, { compact: 2, showHidden: true, depth: 9 });
2033 
2034 expected = [
2035 'Map(2) {',
2036 ' Promise {',
2037 ' [',
2038 ' [',
2039 ' 1,',
2040 ' Set(1) { [ 1, 2, [length]: 2 ] },',
2041 ' [length]: 2',
2042 ' ],',
2043 ' [length]: 1',
2044 ' ]',
2045 ' } => Uint8Array(0) [',
2046 ' [BYTES_PER_ELEMENT]: 1,',
2047 ' [length]: 0,',
2048 ' [byteLength]: 0,',
2049 ' [byteOffset]: 0,',
2050 ' [buffer]: ArrayBuffer { byteLength: 0, foo: true }',
2051 ' ],',
2052 ' [Set Iterator] {',
2053 ' [ 1, 2, [length]: 2 ],',
2054 " [Symbol(Symbol.toStringTag)]: 'Set Iterator'",
2055 ' } => <ref *1> [Map Iterator] {',
2056 ' Uint8Array(0) [',
2057 ' [BYTES_PER_ELEMENT]: 1,',
2058 ' [length]: 0,',
2059 ' [byteLength]: 0,',
2060 ' [byteOffset]: 0,',
2061 ' [buffer]: ArrayBuffer { byteLength: 0, foo: true }',
2062 ' ],',
2063 ' [Circular *1],',
2064 " [Symbol(Symbol.toStringTag)]: 'Map Iterator'",
2065 ' }',
2066 '}',
2067 ].join('\n');
2068 
2069 assert.strict.equal(out, expected);
2070 
2071 out = util.inspect(map, {
2072 showHidden: true,
2073 depth: 9,
2074 breakLength: 4,
2075 compact: true,
2076 });
2077 expected = [
2078 'Map(2) {',
2079 ' Promise {',
2080 ' [ [ 1,',
2081 ' Set(1) {',
2082 ' [ 1,',
2083 ' 2,',
2084 ' [length]: 2 ] },',
2085 ' [length]: 2 ],',
2086 ' [length]: 1 ] } => Uint8Array(0) [',
2087 ' [BYTES_PER_ELEMENT]: 1,',
2088 ' [length]: 0,',
2089 ' [byteLength]: 0,',
2090 ' [byteOffset]: 0,',
2091 ' [buffer]: ArrayBuffer {',
2092 ' byteLength: 0,',
2093 ' foo: true } ],',
2094 ' [Set Iterator] {',
2095 ' [ 1,',
2096 ' 2,',
2097 ' [length]: 2 ],',
2098 ' [Symbol(Symbol.toStringTag)]:',
2099 " 'Set Iterator' } => <ref *1> [Map Iterator] {",
2100 ' Uint8Array(0) [',
2101 ' [BYTES_PER_ELEMENT]: 1,',
2102 ' [length]: 0,',
2103 ' [byteLength]: 0,',
2104 ' [byteOffset]: 0,',
2105 ' [buffer]: ArrayBuffer {',
2106 ' byteLength: 0,',
2107 ' foo: true } ],',
2108 ' [Circular *1],',
2109 ' [Symbol(Symbol.toStringTag)]:',
2110 " 'Map Iterator' } }",
2111 ].join('\n');
2112 
2113 assert.strict.equal(out, expected);
2114 }
2115 
2116 {
2117 // Test WeakMap && WeakSet
2118 const obj = {};
2119 const arr = [];
2120 const weakMap = new WeakMap([
2121 [obj, arr],
2122 [arr, obj],
2123 ]);
2124 let out = util.inspect(weakMap, { showHidden: true });
2125 let expect = 'WeakMap { [ [length]: 0 ] => {}, {} => [ [length]: 0 ] }';
2126 assert.strictEqual(out, expect);
2127 
2128 out = util.inspect(weakMap);
2129 expect = 'WeakMap { <items unknown> }';
2130 assert.strictEqual(out, expect);
2131 
2132 out = util.inspect(weakMap, { maxArrayLength: 0, showHidden: true });
2133 expect = 'WeakMap { ... 2 more items }';
2134 assert.strictEqual(out, expect);
2135 
2136 weakMap.extra = true;
2137 out = util.inspect(weakMap, { maxArrayLength: 1, showHidden: true });
2138 // It is not possible to determine the output reliable.
2139 expect =
2140 'WeakMap { [ [length]: 0 ] => {}, ... 1 more item, extra: true }';
2141 let expectAlt =
2142 'WeakMap { {} => [ [length]: 0 ], ... 1 more item, ' + 'extra: true }';
2143 assert(
2144 out === expect || out === expectAlt,
2145 `Found: "${out}"\nrather than: "${expect}"\nor: "${expectAlt}"`
2146 );
2147 
2148 // Test WeakSet
2149 arr.push(1);
2150 const weakSet = new WeakSet([obj, arr]);
2151 out = util.inspect(weakSet, { showHidden: true });
2152 expect = 'WeakSet { [ 1, [length]: 1 ], {} }';
2153 assert.strictEqual(out, expect);
2154 
2155 out = util.inspect(weakSet);
2156 expect = 'WeakSet { <items unknown> }';
2157 assert.strictEqual(out, expect);
2158 
2159 out = util.inspect(weakSet, { maxArrayLength: -2, showHidden: true });
2160 expect = 'WeakSet { ... 2 more items }';
2161 assert.strictEqual(out, expect);
2162 
2163 weakSet.extra = true;
2164 out = util.inspect(weakSet, { maxArrayLength: 1, showHidden: true });
2165 // It is not possible to determine the output reliable.
2166 expect = 'WeakSet { {}, ... 1 more item, extra: true }';
2167 expectAlt =
2168 'WeakSet { [ 1, [length]: 1 ], ... 1 more item, extra: true }';
2169 assert(
2170 out === expect || out === expectAlt,
2171 `Found: "${out}"\nrather than: "${expect}"\nor: "${expectAlt}"`
2172 );
2173 // Keep references to the WeakMap entries, otherwise they could be GC'ed too
2174 // early.
2175 assert(obj && arr);
2176 }
2177 
2178 {
2179 // Test argument objects.
2180 const args = (function () {
2181 return arguments;
2182 })('a');
2183 assert.strictEqual(util.inspect(args), "[Arguments] { '0': 'a' }");
2184 }
2185 
2186 {
2187 // Test that a long linked list can be inspected without throwing an error.
2188 const list = {};
2189 let head = list;
2190 // A linked list of length 100k should be inspectable in some way, even though
2191 // the real cutoff value is much lower than 100k.
2192 for (let i = 0; i < 100000; i++) head = head.next = {};
2193 assert.strictEqual(
2194 util.inspect(list),
2195 '{ next: { next: { next: [Object] } } }'
2196 );
2197 const longList = util.inspect(list, { depth: Infinity });
2198 const match = longList.match(/next/g);
2199 assert(match.length > 500 && match.length < 10000);
2200 assert(
2201 longList.includes(
2202 '[Object: Inspection interrupted ' +
2203 'prematurely. Maximum call stack size exceeded.]'
2204 )
2205 );
2206 }
2207 
2208 // Do not escape single quotes if no double quote or backtick is present.
2209 assert.strictEqual(util.inspect("'"), '"\'"');
2210 assert.strictEqual(util.inspect('"\''), '`"\'`');
2211 assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");
2212 
2213 // Errors should visualize as much information as possible.
2214 // If the name is not included in the stack, visualize it as well.
2215 [
2216 [class Foo extends TypeError {}, 'test'],
2217 [class Foo extends TypeError {}, undefined],
2218 [class BarError extends Error {}, 'test'],
2219 [
2220 class BazError extends Error {
2221 get name() {
2222 return 'BazError';
2223 }
2224 },
2225 undefined,
2226 ],
2227 ].forEach(([Class, message], i) => {
2228 console.log('Test %i', i);
2229 const foo = new Class(message);
2230 const name = foo.name;
2231 const extra = Class.name.includes('Error') ? '' : ` [${foo.name}]`;
2232 assert(
2233 util
2234 .inspect(foo)
2235 .startsWith(
2236 `${Class.name}${extra}${message ? `: ${message}` : '\n'}`
2237 ),
2238 util.inspect(foo)
2239 );
2240 Object.defineProperty(foo, Symbol.toStringTag, {
2241 value: 'WOW',
2242 writable: true,
2243 configurable: true,
2244 });
2245 const stack = foo.stack;
2246 foo.stack = 'This is a stack';
2247 assert.strictEqual(util.inspect(foo), '[This is a stack]');
2248 foo.stack = stack;
2249 assert(
2250 util
2251 .inspect(foo)
2252 .startsWith(
2253 `${Class.name} [WOW]${extra}${message ? `: ${message}` : '\n'}`
2254 ),
2255 util.inspect(foo)
2256 );
2257 Object.setPrototypeOf(foo, null);
2258 assert(
2259 util
2260 .inspect(foo)
2261 .startsWith(
2262 `[${name}: null prototype] [WOW]${message ? `: ${message}` : '\n'}`
2263 ),
2264 util.inspect(foo)
2265 );
2266 foo.bar = true;
2267 // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
2268 delete foo[Symbol.toStringTag];
2269 assert(
2270 util
2271 .inspect(foo)
2272 .startsWith(
2273 `[${name}: null prototype]${message ? `: ${message}` : '\n'}`
2274 ),
2275 util.inspect(foo)
2276 );
2277 foo.stack = 'This is a stack';
2278 assert.strictEqual(
2279 util.inspect(foo),
2280 '[[Error: null prototype]: This is a stack] { bar: true }'
2281 );
2282 foo.stack = stack.split('\n')[0];
2283 assert.strictEqual(
2284 util.inspect(foo),
2285 `[[${name}: null prototype]${message ? `: ${message}` : ''}] { bar: true }`
2286 );
2287 });
2288 
2289 // Verify that classes are properly inspected.
2290 [
2291 // The whitespace is intentional.
2292 [class {}, '[class (anonymous)]'],
2293 [
2294 class extends Error {
2295 log() {}
2296 },
2297 '[class (anonymous) extends Error]',
2298 ],
2299 [
2300 class A {
2301 constructor(a) {
2302 this.a = a;
2303 }
2304 log() {
2305 return this.a;
2306 }
2307 },
2308 '[class A]',
2309 ],
2310 [
2311 class // Random { // comments /* */ are part of the toString() result
2312 äß /**/
2313 extends /*{*/ TypeError {},
2314 '[class äß extends TypeError]',
2315 ],
2316 /* The whitespace and new line is intended! */
2317 // Foobar !!!
2318 [
2319 class X extends /****/ Error {
2320 // More comments
2321 },
2322 '[class X extends Error]',
2323 ],
2324 ].forEach(([clazz, string]) => {
2325 const inspected = util.inspect(clazz);
2326 assert.strictEqual(inspected, string);
2327 Object.defineProperty(clazz, Symbol.toStringTag, {
2328 value: 'Woohoo',
2329 });
2330 const parts = inspected.slice(0, -1).split(' ');
2331 const [, name, ...rest] = parts;
2332 rest.unshift('[Woohoo]');
2333 if (rest.length) {
2334 rest[rest.length - 1] += ']';
2335 }
2336 assert.strictEqual(
2337 util.inspect(clazz),
2338 ['[class', name, ...rest].join(' ')
2339 );
2340 if (rest.length) {
2341 rest[rest.length - 1] = rest[rest.length - 1].slice(0, -1);
2342 rest.length = 1;
2343 }
2344 Object.setPrototypeOf(clazz, Map.prototype);
2345 assert.strictEqual(
2346 util.inspect(clazz),
2347 ['[class', name, '[Map]', ...rest].join(' ') + ']'
2348 );
2349 Object.setPrototypeOf(clazz, null);
2350 assert.strictEqual(
2351 util.inspect(clazz),
2352 ['[class', name, ...rest, 'extends [null prototype]]'].join(' ')
2353 );
2354 Object.defineProperty(clazz, 'name', { value: 'Foo' });
2355 const res = ['[class', 'Foo', ...rest, 'extends [null prototype]]'].join(
2356 ' '
2357 );
2358 assert.strictEqual(util.inspect(clazz), res);
2359 clazz.foo = true;
2360 assert.strictEqual(util.inspect(clazz), `${res} { foo: true }`);
2361 });
2362 
2363 // "class" properties should not be detected as "class".
2364 {
2365 let obj = { class() {} };
2366 assert.strictEqual(util.inspect(obj), '{ class: [Function: class] }');
2367 obj = { class: () => {} };
2368 assert.strictEqual(util.inspect(obj), '{ class: [Function: class] }');
2369 obj = { ['class Foo {}']() {} };
2370 assert.strictEqual(
2371 util.inspect(obj),
2372 "{ 'class Foo {}': [Function: class Foo {}] }"
2373 );
2374 function Foo() {}
2375 Object.defineProperty(Foo, 'toString', { value: () => 'class Foo {}' });
2376 assert.strictEqual(util.inspect(Foo), '[Function: Foo]');
2377 function fn() {}
2378 Object.defineProperty(fn, 'name', { value: 'class Foo {}' });
2379 assert.strictEqual(util.inspect(fn), '[Function: class Foo {}]');
2380 }
2381 
2382 // Verify that throwing in valueOf and toString still produces nice results.
2383 [
2384 [new String(55), "[String: '55']"],
2385 [new Boolean(true), '[Boolean: true]'],
2386 [new Number(55), '[Number: 55]'],
2387 [Object(BigInt(55)), '[BigInt: 55n]'],
2388 [Object(Symbol('foo')), '[Symbol: Symbol(foo)]'],
2389 [function () {}, '[Function (anonymous)]'],
2390 [() => {}, '[Function (anonymous)]'],
2391 [[1, 2], '[ 1, 2 ]'],
2392 // eslint-disable-next-line no-sparse-arrays
2393 [[, , 5, , , ,], '[ <2 empty items>, 5, <3 empty items> ]'],
2394 [{ a: 5 }, '{ a: 5 }'],
2395 [new Set([1, 2]), 'Set(2) { 1, 2 }'],
2396 [new Map([[1, 2]]), 'Map(1) { 1 => 2 }'],
2397 [new Set([1, 2]).entries(), '[Set Entries] { [ 1, 1 ], [ 2, 2 ] }'],
2398 [new Map([[1, 2]]).keys(), '[Map Iterator] { 1 }'],
2399 [new Date(2000), '1970-01-01T00:00:02.000Z'],
2400 [new Uint8Array(2), 'Uint8Array(2) [ 0, 0 ]'],
2401 [
2402 new Promise((resolve) => setTimeout(resolve, 10)),
2403 'Promise { <pending> }',
2404 ],
2405 [new WeakSet(), 'WeakSet { <items unknown> }'],
2406 [new WeakMap(), 'WeakMap { <items unknown> }'],
2407 [/foobar/g, '/foobar/g'],
2408 ].forEach(([value, expected]) => {
2409 Object.defineProperty(value, 'valueOf', {
2410 get() {
2411 throw new Error('valueOf');
2412 },
2413 });
2414 Object.defineProperty(value, 'toString', {
2415 get() {
2416 throw new Error('toString');
2417 },
2418 });
2419 assert.strictEqual(util.inspect(value), expected);
2420 value.foo = 'bar';
2421 assert.notStrictEqual(util.inspect(value), expected);
2422 delete value.foo;
2423 value[Symbol('foo')] = 'yeah';
2424 assert.notStrictEqual(util.inspect(value), expected);
2425 });
2426 
2427 // Verify that having no prototype still produces nice results.
2428 [
2429 [[1, 3, 4], '[Array(3): null prototype] [ 1, 3, 4 ]'],
2430 [new Set([1, 2]), '[Set(2): null prototype] { 1, 2 }'],
2431 [new Map([[1, 2]]), '[Map(1): null prototype] { 1 => 2 }'],
2432 [
2433 new Promise((resolve) => setTimeout(resolve, 10)),
2434 '[Promise: null prototype] { <pending> }',
2435 ],
2436 [new WeakSet(), '[WeakSet: null prototype] { <items unknown> }'],
2437 [new WeakMap(), '[WeakMap: null prototype] { <items unknown> }'],
2438 [new Uint8Array(2), '[Uint8Array(2): null prototype] [ 0, 0 ]'],
2439 [new Uint16Array(2), '[Uint16Array(2): null prototype] [ 0, 0 ]'],
2440 [new Uint32Array(2), '[Uint32Array(2): null prototype] [ 0, 0 ]'],
2441 [new Int8Array(2), '[Int8Array(2): null prototype] [ 0, 0 ]'],
2442 [new Int16Array(2), '[Int16Array(2): null prototype] [ 0, 0 ]'],
2443 [new Int32Array(2), '[Int32Array(2): null prototype] [ 0, 0 ]'],
2444 [new Float16Array(2), '[Float16Array(2): null prototype] [ 0, 0 ]'],
2445 [new Float32Array(2), '[Float32Array(2): null prototype] [ 0, 0 ]'],
2446 [new Float64Array(2), '[Float64Array(2): null prototype] [ 0, 0 ]'],
2447 [new BigInt64Array(2), '[BigInt64Array(2): null prototype] [ 0n, 0n ]'],
2448 [new BigUint64Array(2), '[BigUint64Array(2): null prototype] [ 0n, 0n ]'],
2449 [
2450 new ArrayBuffer(16),
2451 '[ArrayBuffer: null prototype] {\n' +
2452 ' [Uint8Contents]: <00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>,\n' +
2453 ' byteLength: undefined\n}',
2454 ],
2455 [
2456 new DataView(new ArrayBuffer(16)),
2457 '[DataView: null prototype] {\n byteLength: undefined,\n ' +
2458 'byteOffset: undefined,\n buffer: undefined\n}',
2459 ],
2460 [
2461 new SharedArrayBuffer(2),
2462 '[SharedArrayBuffer: null prototype] ' +
2463 '{\n [Uint8Contents]: <00 00>,\n byteLength: undefined\n}',
2464 ],
2465 [/foobar/, '[RegExp: null prototype] /foobar/'],
2466 [
2467 new Date('Sun, 14 Feb 2010 11:48:40 GMT'),
2468 '[Date: null prototype] 2010-02-14T11:48:40.000Z',
2469 ],
2470 ].forEach(([value, expected]) => {
2471 assert.strictEqual(
2472 util.inspect(Object.setPrototypeOf(value, null)),
2473 expected
2474 );
2475 value.foo = 'bar';
2476 assert.notStrictEqual(util.inspect(value), expected);
2477 delete value.foo;
2478 value[Symbol('foo')] = 'yeah';
2479 assert.notStrictEqual(util.inspect(value), expected);
2480 });
2481 
2482 // Verify that subclasses with and without prototype produce nice results.
2483 [
2484 [RegExp, ['foobar', 'g'], '/foobar/g'],
2485 [WeakSet, [[{}]], '{ <items unknown> }'],
2486 [WeakMap, [[[{}, {}]]], '{ <items unknown> }'],
2487 [
2488 BigInt64Array,
2489 [10],
2490 '[\n 0n, 0n, 0n, 0n, 0n,\n 0n, 0n, 0n, 0n, 0n\n]',
2491 ],
2492 [Date, ['Sun, 14 Feb 2010 11:48:40 GMT'], '2010-02-14T11:48:40.000Z'],
2493 [Date, ['invalid_date'], 'Invalid Date'],
2494 ].forEach(([base, input, rawExpected]) => {
2495 class Foo extends base {}
2496 const value = new Foo(...input);
2497 const symbol = value[Symbol.toStringTag];
2498 const size = base.name.includes('Array') ? `(${input[0]})` : '';
2499 const expected = `Foo${size} ${symbol ? `[${symbol}] ` : ''}${rawExpected}`;
2500 const expectedWithoutProto = `[${base.name}${size}: null prototype] ${rawExpected}`;
2501 assert.strictEqual(util.inspect(value), expected);
2502 value.foo = 'bar';
2503 assert.notStrictEqual(util.inspect(value), expected);
2504 delete value.foo;
2505 assert.strictEqual(
2506 util.inspect(Object.setPrototypeOf(value, null)),
2507 expectedWithoutProto
2508 );
2509 value.foo = 'bar';
2510 let res = util.inspect(value);
2511 assert.notStrictEqual(res, expectedWithoutProto);
2512 assert.match(res, /foo: 'bar'/);
2513 delete value.foo;
2514 value[Symbol('foo')] = 'yeah';
2515 res = util.inspect(value);
2516 assert.notStrictEqual(res, expectedWithoutProto);
2517 assert.match(res, /Symbol\(foo\): 'yeah'/);
2518 });
2519 
2520 assert.strictEqual(inspect(1n), '1n');
2521 assert.strictEqual(inspect(Object(-1n)), '[BigInt: -1n]');
2522 assert.strictEqual(inspect(Object(13n)), '[BigInt: 13n]');
2523 assert.strictEqual(
2524 inspect(new BigInt64Array([0n])),
2525 'BigInt64Array(1) [ 0n ]'
2526 );
2527 assert.strictEqual(
2528 inspect(new BigUint64Array([0n])),
2529 'BigUint64Array(1) [ 0n ]'
2530 );
2531 
2532 // Verify non-enumerable keys get escaped.
2533 {
2534 const obj = {};
2535 Object.defineProperty(obj, 'Non\nenumerable\tkey', { value: true });
2536 assert.strictEqual(
2537 util.inspect(obj, { showHidden: true }),
2538 "{ ['Non\\nenumerable\\tkey']: true }"
2539 );
2540 }
2541 
2542 // Check for special colors.
2543 {
2544 const special = inspect.colors[inspect.styles.special];
2545 const string = inspect.colors[inspect.styles.string];
2546 
2547 assert.strictEqual(
2548 inspect(new WeakSet(), { colors: true }),
2549 `WeakSet { \u001b[${special[0]}m<items unknown>\u001b[${special[1]}m }`
2550 );
2551 assert.strictEqual(
2552 inspect(new WeakMap(), { colors: true }),
2553 `WeakMap { \u001b[${special[0]}m<items unknown>\u001b[${special[1]}m }`
2554 );
2555 assert.strictEqual(
2556 inspect(new Promise(() => {}), { colors: true }),
2557 `Promise { \u001b[${special[0]}m<pending>\u001b[${special[1]}m }`
2558 );
2559 
2560 const rejection = Promise.reject('Oh no!');
2561 assert.strictEqual(
2562 inspect(rejection, { colors: true }),
2563 `Promise { \u001b[${special[0]}m<rejected>\u001b[${special[1]}m ` +
2564 `\u001b[${string[0]}m'Oh no!'\u001b[${string[1]}m }`
2565 );
2566 rejection.catch(() => {});
2567 
2568 // Verify that aliases do not show up as key while checking `inspect.colors`.
2569 const colors = Object.keys(inspect.colors);
2570 const aliases = Object.getOwnPropertyNames(inspect.colors).filter(
2571 (c) => !colors.includes(c)
2572 );
2573 assert(!colors.includes('grey'));
2574 assert(colors.includes('gray'));
2575 // Verify that all aliases are correctly mapped.
2576 for (const alias of aliases) {
2577 assert(Array.isArray(inspect.colors[alias]));
2578 }
2579 // Check consistent naming.
2580 [
2581 'black',
2582 'red',
2583 'green',
2584 'yellow',
2585 'blue',
2586 'magenta',
2587 'cyan',
2588 'white',
2589 ].forEach((color, i) => {
2590 assert.deepStrictEqual(inspect.colors[color], [30 + i, 39]);
2591 assert.deepStrictEqual(inspect.colors[`${color}Bright`], [90 + i, 39]);
2592 const bgColor = `bg${color[0].toUpperCase()}${color.slice(1)}`;
2593 assert.deepStrictEqual(inspect.colors[bgColor], [40 + i, 49]);
2594 assert.deepStrictEqual(inspect.colors[`${bgColor}Bright`], [
2595 100 + i,
2596 49,
2597 ]);
2598 });
2599 
2600 // Unknown colors are handled gracefully:
2601 const stringStyle = inspect.styles.string;
2602 inspect.styles.string = 'UNKNOWN';
2603 assert.strictEqual(inspect('foobar', { colors: true }), "'foobar'");
2604 inspect.styles.string = stringStyle;
2605 }
2606 
2607 assert.strictEqual(
2608 inspect([1, 3, 2], { sorted: true }),
2609 inspect([1, 3, 2])
2610 );
2611 assert.strictEqual(
2612 inspect({ c: 3, a: 1, b: 2 }, { sorted: true }),
2613 '{ a: 1, b: 2, c: 3 }'
2614 );
2615 assert.strictEqual(
2616 inspect(
2617 { a200: 4, a100: 1, a102: 3, a101: 2 },
2618 {
2619 sorted(a, b) {
2620 return b.localeCompare(a);
2621 },
2622 }
2623 ),
2624 '{ a200: 4, a102: 3, a101: 2, a100: 1 }'
2625 );
2626 
2627 // Non-indices array properties are sorted as well.
2628 {
2629 const arr = [3, 2, 1];
2630 arr.b = 2;
2631 arr.c = 3;
2632 arr.a = 1;
2633 arr[Symbol('b')] = true;
2634 arr[Symbol('a')] = false;
2635 assert.strictEqual(
2636 inspect(arr, { sorted: true }),
2637 '[ 3, 2, 1, Symbol(a): false, Symbol(b): true, a: 1, b: 2, c: 3 ]'
2638 );
2639 }
2640 
2641 // Manipulate the prototype in weird ways.
2642 {
2643 let obj = { a: true };
2644 let value = (function () {
2645 return function () {};
2646 })();
2647 Object.setPrototypeOf(value, null);
2648 Object.setPrototypeOf(obj, value);
2649 assert.strictEqual(
2650 util.inspect(obj),
2651 'Object <[Function (null prototype) (anonymous)]> { a: true }'
2652 );
2653 assert.strictEqual(
2654 util.inspect(obj, { colors: true }),
2655 'Object <\u001b[36m[Function (null prototype) (anonymous)]\u001b[39m> ' +
2656 '{ a: \u001b[33mtrue\u001b[39m }'
2657 );
2658 
2659 obj = { a: true };
2660 value = [];
2661 Object.setPrototypeOf(value, null);
2662 Object.setPrototypeOf(obj, value);
2663 assert.strictEqual(
2664 util.inspect(obj),
2665 'Object <[Array(0): null prototype] []> { a: true }'
2666 );
2667 
2668 function StorageObject() {}
2669 StorageObject.prototype = { __proto__: null };
2670 assert.strictEqual(
2671 util.inspect(new StorageObject()),
2672 'StorageObject <[Object: null prototype] {}> {}'
2673 );
2674 
2675 obj = [1, 2, 3];
2676 Object.setPrototypeOf(obj, Number.prototype);
2677 assert.strictEqual(inspect(obj), "Number { '0': 1, '1': 2, '2': 3 }");
2678 
2679 Object.setPrototypeOf(obj, { __proto__: null });
2680 assert.strictEqual(
2681 inspect(obj),
2682 "Array <[Object: null prototype] {}> { '0': 1, '1': 2, '2': 3 }"
2683 );
2684 
2685 StorageObject.prototype = { __proto__: null };
2686 Object.setPrototypeOf(StorageObject.prototype, { __proto__: null });
2687 Object.setPrototypeOf(Object.getPrototypeOf(StorageObject.prototype), {
2688 __proto__: null,
2689 });
2690 assert.strictEqual(
2691 util.inspect(new StorageObject()),
2692 'StorageObject <Object <Object <[Object: null prototype] {}>>> {}'
2693 );
2694 assert.strictEqual(
2695 util.inspect(new StorageObject(), { depth: 1 }),
2696 'StorageObject <Object <Object <Complex prototype>>> {}'
2697 );
2698 }
2699 
2700 // Check that the fallback always works.
2701 {
2702 const obj = new Set([1, 2]);
2703 const iterator = obj[Symbol.iterator];
2704 Object.setPrototypeOf(obj, null);
2705 Object.defineProperty(obj, Symbol.iterator, {
2706 value: iterator,
2707 configurable: true,
2708 });
2709 assert.strictEqual(
2710 util.inspect(obj),
2711 '[Set(2): null prototype] { 1, 2 }'
2712 );
2713 Object.defineProperty(obj, Symbol.iterator, {
2714 value: true,
2715 configurable: true,
2716 });
2717 Object.defineProperty(obj, 'size', {
2718 value: NaN,
2719 configurable: true,
2720 enumerable: true,
2721 });
2722 assert.strictEqual(
2723 util.inspect(obj),
2724 '[Set(2): null prototype] { 1, 2, size: NaN }'
2725 );
2726 }
2727 
2728 // Check the getter option.
2729 {
2730 let foo = 1;
2731 const get = {
2732 get foo() {
2733 return foo;
2734 },
2735 };
2736 const getset = {
2737 get foo() {
2738 return foo;
2739 },
2740 set foo(val) {
2741 foo = val;
2742 },
2743 get inc() {
2744 return ++foo;
2745 },
2746 };
2747 const thrower = {
2748 get foo() {
2749 throw new Error('Oops');
2750 },
2751 };
2752 assert.strictEqual(
2753 inspect(get, { getters: true, colors: true }),
2754 '{ foo: \u001b[36m[Getter:\u001b[39m ' +
2755 '\u001b[33m1\u001b[39m\u001b[36m]\u001b[39m }'
2756 );
2757 assert.strictEqual(
2758 inspect(thrower, { getters: true }),
2759 '{ foo: [Getter: <Inspection threw (Oops)>] }'
2760 );
2761 assert.strictEqual(
2762 inspect(getset, { getters: true }),
2763 '{ foo: [Getter/Setter: 1], inc: [Getter: 2] }'
2764 );
2765 assert.strictEqual(
2766 inspect(getset, { getters: 'get' }),
2767 '{ foo: [Getter/Setter], inc: [Getter: 3] }'
2768 );
2769 assert.strictEqual(
2770 inspect(getset, { getters: 'set' }),
2771 '{ foo: [Getter/Setter: 3], inc: [Getter] }'
2772 );
2773 getset.foo = new Set([[{ a: true }, 2, {}], 'foobar', { x: 1 }]);
2774 assert.strictEqual(
2775 inspect(getset, { getters: true }),
2776 '{\n foo: [Getter/Setter] Set(3) { [ [Object], 2, {} ], ' +
2777 "'foobar', { x: 1 } },\n inc: [Getter: NaN]\n}"
2778 );
2779 }
2780 
2781 // Check compact number mode.
2782 {
2783 let obj = {
2784 a: {
2785 b: {
2786 x: 5,
2787 c: {
2788 x: '10000000000000000 00000000000000000 '.repeat(1e1),
2789 d: 2,
2790 e: 3,
2791 },
2792 },
2793 },
2794 b: [1, 2, [1, 2, { a: 1, b: 2, c: 3 }]],
2795 c: ['foo', 4, 444444],
2796 d: Array.from({ length: 101 }, (_e, i) => {
2797 return i % 2 === 0 ? i * i : i;
2798 }),
2799 e: Array.from({ length: 6 }, () => 'foobar'),
2800 f: Array.from({ length: 9 }, () => 'foobar'),
2801 g: Array.from({ length: 21 }, () => 'foobar baz'),
2802 h: [100].concat(Array.from({ length: 9 }, (_e, n) => n)),
2803 long: Array.from(
2804 { length: 9 },
2805 () => 'This text is too long for grouping!'
2806 ),
2807 };
2808 
2809 let out = util.inspect(obj, { compact: 3, depth: 10, breakLength: 60 });
2810 let expected = [
2811 '{',
2812 ' a: {',
2813 ' b: {',
2814 ' x: 5,',
2815 ' c: {',
2816 " x: '10000000000000000 00000000000000000 10000000000000000 " +
2817 '00000000000000000 10000000000000000 00000000000000000 ' +
2818 '10000000000000000 00000000000000000 10000000000000000 ' +
2819 '00000000000000000 10000000000000000 00000000000000000 ' +
2820 '10000000000000000 00000000000000000 10000000000000000 ' +
2821 '00000000000000000 10000000000000000 00000000000000000 ' +
2822 "10000000000000000 00000000000000000 ',",
2823 ' d: 2,',
2824 ' e: 3',
2825 ' }',
2826 ' }',
2827 ' },',
2828 ' b: [ 1, 2, [ 1, 2, { a: 1, b: 2, c: 3 } ] ],',
2829 " c: [ 'foo', 4, 444444 ],",
2830 ' d: [',
2831 ' 0, 1, 4, 3, 16, 5, 36, 7, 64,',
2832 ' 9, 100, 11, 144, 13, 196, 15, 256, 17,',
2833 ' 324, 19, 400, 21, 484, 23, 576, 25, 676,',
2834 ' 27, 784, 29, 900, 31, 1024, 33, 1156, 35,',
2835 ' 1296, 37, 1444, 39, 1600, 41, 1764, 43, 1936,',
2836 ' 45, 2116, 47, 2304, 49, 2500, 51, 2704, 53,',
2837 ' 2916, 55, 3136, 57, 3364, 59, 3600, 61, 3844,',
2838 ' 63, 4096, 65, 4356, 67, 4624, 69, 4900, 71,',
2839 ' 5184, 73, 5476, 75, 5776, 77, 6084, 79, 6400,',
2840 ' 81, 6724, 83, 7056, 85, 7396, 87, 7744, 89,',
2841 ' 8100, 91, 8464, 93, 8836, 95, 9216, 97, 9604,',
2842 ' 99,',
2843 ' ... 1 more item',
2844 ' ],',
2845 ' e: [',
2846 " 'foobar',",
2847 " 'foobar',",
2848 " 'foobar',",
2849 " 'foobar',",
2850 " 'foobar',",
2851 " 'foobar'",
2852 ' ],',
2853 ' f: [',
2854 " 'foobar', 'foobar',",
2855 " 'foobar', 'foobar',",
2856 " 'foobar', 'foobar',",
2857 " 'foobar', 'foobar',",
2858 " 'foobar'",
2859 ' ],',
2860 ' g: [',
2861 " 'foobar baz', 'foobar baz',",
2862 " 'foobar baz', 'foobar baz',",
2863 " 'foobar baz', 'foobar baz',",
2864 " 'foobar baz', 'foobar baz',",
2865 " 'foobar baz', 'foobar baz',",
2866 " 'foobar baz', 'foobar baz',",
2867 " 'foobar baz', 'foobar baz',",
2868 " 'foobar baz', 'foobar baz',",
2869 " 'foobar baz', 'foobar baz',",
2870 " 'foobar baz', 'foobar baz',",
2871 " 'foobar baz'",
2872 ' ],',
2873 ' h: [',
2874 ' 100, 0, 1, 2, 3,',
2875 ' 4, 5, 6, 7, 8',
2876 ' ],',
2877 ' long: [',
2878 " 'This text is too long for grouping!',",
2879 " 'This text is too long for grouping!',",
2880 " 'This text is too long for grouping!',",
2881 " 'This text is too long for grouping!',",
2882 " 'This text is too long for grouping!',",
2883 " 'This text is too long for grouping!',",
2884 " 'This text is too long for grouping!',",
2885 " 'This text is too long for grouping!',",
2886 " 'This text is too long for grouping!'",
2887 ' ]',
2888 '}',
2889 ].join('\n');
2890 
2891 assert.strictEqual(out, expected);
2892 
2893 obj = [
2894 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2895 1, 1, 123456789,
2896 ];
2897 
2898 out = util.inspect(obj, { compact: 3 });
2899 
2900 expected = [
2901 '[',
2902 ' 1, 1, 1, 1,',
2903 ' 1, 1, 1, 1,',
2904 ' 1, 1, 1, 1,',
2905 ' 1, 1, 1, 1,',
2906 ' 1, 1, 1, 1,',
2907 ' 1, 1, 1, 1,',
2908 ' 1, 1, 123456789',
2909 ']',
2910 ].join('\n');
2911 
2912 assert.strictEqual(out, expected);
2913 
2914 // Unicode support. あ has a length of one and a width of two.
2915 obj = [
2916 '123',
2917 '123',
2918 '123',
2919 '123',
2920 'あああ',
2921 '123',
2922 '123',
2923 '123',
2924 '123',
2925 'あああ',
2926 ];
2927 
2928 out = util.inspect(obj, { compact: 3 });
2929 
2930 expected = [
2931 '[',
2932 " '123', '123',",
2933 " '123', '123',",
2934 " 'あああ', '123',",
2935 " '123', '123',",
2936 " '123', 'あああ'",
2937 ']',
2938 ].join('\n');
2939 
2940 assert.strictEqual(out, expected);
2941 
2942 // Array grouping should prevent lining up outer elements on a single line.
2943 obj = [[[1, 2, 3, 4, 5, 6, 7, 8, 9]]];
2944 
2945 out = util.inspect(obj, { compact: 3 });
2946 
2947 expected = [
2948 '[',
2949 ' [',
2950 ' [',
2951 ' 1, 2, 3, 4, 5,',
2952 ' 6, 7, 8, 9',
2953 ' ]',
2954 ' ]',
2955 ']',
2956 ].join('\n');
2957 
2958 assert.strictEqual(out, expected);
2959 
2960 // Verify that array grouping and line consolidation does not happen together.
2961 obj = {
2962 a: {
2963 b: {
2964 x: 5,
2965 c: {
2966 d: 2,
2967 e: 3,
2968 },
2969 },
2970 },
2971 b: Array.from({ length: 9 }, (e, n) => {
2972 return n % 2 === 0 ? 'foobar' : 'baz';
2973 }),
2974 };
2975 
2976 out = util.inspect(obj, {
2977 compact: 1,
2978 breakLength: Infinity,
2979 colors: true,
2980 });
2981 
2982 expected = [
2983 '{',
2984 ' a: {',
2985 ' b: { x: \u001b[33m5\u001b[39m, c: \u001b[36m[Object]\u001b[39m }',
2986 ' },',
2987 ' b: [',
2988 " \u001b[32m'foobar'\u001b[39m, \u001b[32m'baz'\u001b[39m,",
2989 " \u001b[32m'foobar'\u001b[39m, \u001b[32m'baz'\u001b[39m,",
2990 " \u001b[32m'foobar'\u001b[39m, \u001b[32m'baz'\u001b[39m,",
2991 " \u001b[32m'foobar'\u001b[39m, \u001b[32m'baz'\u001b[39m,",
2992 " \u001b[32m'foobar'\u001b[39m",
2993 ' ]',
2994 '}',
2995 ].join('\n');
2996 
2997 assert.strictEqual(out, expected);
2998 
2999 obj = Array.from({ length: 60 }, (_e, i) => i);
3000 out = util.inspect(obj, {
3001 compact: 1,
3002 breakLength: Infinity,
3003 colors: true,
3004 });
3005 
3006 expected = [
3007 '[',
3008 ' \u001b[33m0\u001b[39m, \u001b[33m1\u001b[39m, \u001b[33m2\u001b[39m, \u001b[33m3\u001b[39m,',
3009 ' \u001b[33m4\u001b[39m, \u001b[33m5\u001b[39m, \u001b[33m6\u001b[39m, \u001b[33m7\u001b[39m,',
3010 ' \u001b[33m8\u001b[39m, \u001b[33m9\u001b[39m, \u001b[33m10\u001b[39m, \u001b[33m11\u001b[39m,',
3011 ' \u001b[33m12\u001b[39m, \u001b[33m13\u001b[39m, \u001b[33m14\u001b[39m, \u001b[33m15\u001b[39m,',
3012 ' \u001b[33m16\u001b[39m, \u001b[33m17\u001b[39m, \u001b[33m18\u001b[39m, \u001b[33m19\u001b[39m,',
3013 ' \u001b[33m20\u001b[39m, \u001b[33m21\u001b[39m, \u001b[33m22\u001b[39m, \u001b[33m23\u001b[39m,',
3014 ' \u001b[33m24\u001b[39m, \u001b[33m25\u001b[39m, \u001b[33m26\u001b[39m, \u001b[33m27\u001b[39m,',
3015 ' \u001b[33m28\u001b[39m, \u001b[33m29\u001b[39m, \u001b[33m30\u001b[39m, \u001b[33m31\u001b[39m,',
3016 ' \u001b[33m32\u001b[39m, \u001b[33m33\u001b[39m, \u001b[33m34\u001b[39m, \u001b[33m35\u001b[39m,',
3017 ' \u001b[33m36\u001b[39m, \u001b[33m37\u001b[39m, \u001b[33m38\u001b[39m, \u001b[33m39\u001b[39m,',
3018 ' \u001b[33m40\u001b[39m, \u001b[33m41\u001b[39m, \u001b[33m42\u001b[39m, \u001b[33m43\u001b[39m,',
3019 ' \u001b[33m44\u001b[39m, \u001b[33m45\u001b[39m, \u001b[33m46\u001b[39m, \u001b[33m47\u001b[39m,',
3020 ' \u001b[33m48\u001b[39m, \u001b[33m49\u001b[39m, \u001b[33m50\u001b[39m, \u001b[33m51\u001b[39m,',
3021 ' \u001b[33m52\u001b[39m, \u001b[33m53\u001b[39m, \u001b[33m54\u001b[39m, \u001b[33m55\u001b[39m,',
3022 ' \u001b[33m56\u001b[39m, \u001b[33m57\u001b[39m, \u001b[33m58\u001b[39m, \u001b[33m59\u001b[39m',
3023 ']',
3024 ].join('\n');
3025 
3026 assert.strictEqual(out, expected);
3027 
3028 out = util.inspect([1, 2, 3, 4], { compact: 1, colors: true });
3029 expected =
3030 '[ \u001b[33m1\u001b[39m, \u001b[33m2\u001b[39m, ' +
3031 '\u001b[33m3\u001b[39m, \u001b[33m4\u001b[39m ]';
3032 
3033 assert.strictEqual(out, expected);
3034 
3035 obj = [
3036 'Object',
3037 'Function',
3038 'Array',
3039 'Number',
3040 'parseFloat',
3041 'parseInt',
3042 'Infinity',
3043 'NaN',
3044 'undefined',
3045 'Boolean',
3046 'String',
3047 'Symbol',
3048 'Date',
3049 'Promise',
3050 'RegExp',
3051 'Error',
3052 'EvalError',
3053 'RangeError',
3054 'ReferenceError',
3055 'SyntaxError',
3056 'TypeError',
3057 'URIError',
3058 'JSON',
3059 'Math',
3060 'console',
3061 'Intl',
3062 'ArrayBuffer',
3063 'Uint8Array',
3064 'Int8Array',
3065 'Uint16Array',
3066 'Int16Array',
3067 'Uint32Array',
3068 'Int32Array',
3069 'Float32Array',
3070 'Float64Array',
3071 'Uint8ClampedArray',
3072 'BigUint64Array',
3073 'BigInt64Array',
3074 'DataView',
3075 'Map',
3076 'BigInt',
3077 'Set',
3078 'WeakMap',
3079 'WeakSet',
3080 'Proxy',
3081 'Reflect',
3082 'decodeURI',
3083 'decodeURIComponent',
3084 'encodeURI',
3085 'encodeURIComponent',
3086 'escape',
3087 'unescape',
3088 'eval',
3089 'isFinite',
3090 'isNaN',
3091 'SharedArrayBuffer',
3092 'Atomics',
3093 'globalThis',
3094 'WebAssembly',
3095 'global',
3096 'process',
3097 'Buffer',
3098 'URL',
3099 'URLSearchParams',
3100 'TextEncoder',
3101 'TextDecoder',
3102 'clearInterval',
3103 'clearTimeout',
3104 'setInterval',
3105 'setTimeout',
3106 'queueMicrotask',
3107 'clearImmediate',
3108 'setImmediate',
3109 'module',
3110 'require',
3111 'assert',
3112 'async_hooks',
3113 'buffer',
3114 'child_process',
3115 'cluster',
3116 'crypto',
3117 'dgram',
3118 'dns',
3119 'domain',
3120 'events',
3121 'fs',
3122 'http',
3123 'http2',
3124 'https',
3125 'inspector',
3126 'net',
3127 'os',
3128 'path',
3129 'perf_hooks',
3130 'punycode',
3131 'querystring',
3132 'readline',
3133 'repl',
3134 'stream',
3135 'string_decoder',
3136 'tls',
3137 'trace_events',
3138 'tty',
3139 'url',
3140 'v8',
3141 'vm',
3142 'worker_threads',
3143 'zlib',
3144 '_',
3145 '_error',
3146 'util',
3147 ];
3148 
3149 out = util.inspect(obj, {
3150 compact: 3,
3151 breakLength: 80,
3152 maxArrayLength: 250,
3153 });
3154 expected = [
3155 '[',
3156 " 'Object', 'Function', 'Array',",
3157 " 'Number', 'parseFloat', 'parseInt',",
3158 " 'Infinity', 'NaN', 'undefined',",
3159 " 'Boolean', 'String', 'Symbol',",
3160 " 'Date', 'Promise', 'RegExp',",
3161 " 'Error', 'EvalError', 'RangeError',",
3162 " 'ReferenceError', 'SyntaxError', 'TypeError',",
3163 " 'URIError', 'JSON', 'Math',",
3164 " 'console', 'Intl', 'ArrayBuffer',",
3165 " 'Uint8Array', 'Int8Array', 'Uint16Array',",
3166 " 'Int16Array', 'Uint32Array', 'Int32Array',",
3167 " 'Float32Array', 'Float64Array', 'Uint8ClampedArray',",
3168 " 'BigUint64Array', 'BigInt64Array', 'DataView',",
3169 " 'Map', 'BigInt', 'Set',",
3170 " 'WeakMap', 'WeakSet', 'Proxy',",
3171 " 'Reflect', 'decodeURI', 'decodeURIComponent',",
3172 " 'encodeURI', 'encodeURIComponent', 'escape',",
3173 " 'unescape', 'eval', 'isFinite',",
3174 " 'isNaN', 'SharedArrayBuffer', 'Atomics',",
3175 " 'globalThis', 'WebAssembly', 'global',",
3176 " 'process', 'Buffer', 'URL',",
3177 " 'URLSearchParams', 'TextEncoder', 'TextDecoder',",
3178 " 'clearInterval', 'clearTimeout', 'setInterval',",
3179 " 'setTimeout', 'queueMicrotask', 'clearImmediate',",
3180 " 'setImmediate', 'module', 'require',",
3181 " 'assert', 'async_hooks', 'buffer',",
3182 " 'child_process', 'cluster', 'crypto',",
3183 " 'dgram', 'dns', 'domain',",
3184 " 'events', 'fs', 'http',",
3185 " 'http2', 'https', 'inspector',",
3186 " 'net', 'os', 'path',",
3187 " 'perf_hooks', 'punycode', 'querystring',",
3188 " 'readline', 'repl', 'stream',",
3189 " 'string_decoder', 'tls', 'trace_events',",
3190 " 'tty', 'url', 'v8',",
3191 " 'vm', 'worker_threads', 'zlib',",
3192 " '_', '_error', 'util'",
3193 ']',
3194 ].join('\n');
3195 
3196 assert.strictEqual(out, expected);
3197 }
3198 
3199 {
3200 // Cross platform checks.
3201 const err = new Error('foo');
3202 util
3203 .inspect(err, { colors: true })
3204 .split('\n')
3205 .forEach((line, i) => {
3206 assert(i < 2 || line.startsWith('\u001b[90m'));
3207 });
3208 }
3209 
3210 // Inspect prototype properties.
3211 {
3212 class Foo extends Map {
3213 prop = false;
3214 prop2 = true;
3215 get abc() {
3216 return true;
3217 }
3218 get def() {
3219 return false;
3220 }
3221 set def(v) {}
3222 get xyz() {
3223 return 'Should be ignored';
3224 }
3225 func(a) {}
3226 [util.inspect.custom]() {
3227 return this;
3228 }
3229 }
3230 
3231 class Bar extends Foo {
3232 abc = true;
3233 prop = true;
3234 get xyz() {
3235 return 'YES!';
3236 }
3237 [util.inspect.custom]() {
3238 return this;
3239 }
3240 }
3241 
3242 const bar = new Bar();
3243 
3244 assert.strictEqual(
3245 inspect(bar),
3246 'Bar(0) [Map] { prop: true, prop2: true, abc: true }'
3247 );
3248 assert.strictEqual(
3249 inspect(bar, { showHidden: true, getters: true, colors: false }),
3250 'Bar(0) [Map] {\n' +
3251 ' prop: true,\n' +
3252 ' prop2: true,\n' +
3253 ' abc: true,\n' +
3254 " [xyz]: [Getter: 'YES!'],\n" +
3255 ' [def]: [Getter/Setter: false]\n' +
3256 '}'
3257 );
3258 assert.strictEqual(
3259 inspect(bar, { showHidden: true, getters: false, colors: true }),
3260 'Bar(0) [Map] {\n' +
3261 ' prop: \x1B[33mtrue\x1B[39m,\n' +
3262 ' prop2: \x1B[33mtrue\x1B[39m,\n' +
3263 ' abc: \x1B[33mtrue\x1B[39m,\n' +
3264 ' \x1B[2m[xyz]: \x1B[36m[Getter]\x1B[39m\x1B[22m,\n' +
3265 ' \x1B[2m[def]: \x1B[36m[Getter/Setter]\x1B[39m\x1B[22m\n' +
3266 '}'
3267 );
3268 
3269 const obj = { __proto__: { abc: true, def: 5, toString() {} } };
3270 assert.strictEqual(
3271 inspect(obj, { showHidden: true, colors: true }),
3272 '{ \x1B[2mabc: \x1B[33mtrue\x1B[39m\x1B[22m, ' +
3273 '\x1B[2mdef: \x1B[33m5\x1B[39m\x1B[22m }'
3274 );
3275 
3276 assert.strictEqual(
3277 inspect(Object.getPrototypeOf(bar), {
3278 showHidden: true,
3279 getters: true,
3280 }),
3281 '<ref *1> Foo [Map] {\n' +
3282 ' [constructor]: [class Bar extends Foo] {\n' +
3283 ' [length]: 0,\n' +
3284 " [name]: 'Bar',\n" +
3285 ' [prototype]: [Circular *1],\n' +
3286 ' [Symbol(Symbol.species)]: [Getter: <Inspection threw ' +
3287 "(Symbol.prototype.toString requires that 'this' be a Symbol)>]\n" +
3288 ' },\n' +
3289 " [xyz]: [Getter: 'YES!'],\n" +
3290 ' [Symbol(nodejs.util.inspect.custom)]: ' +
3291 '[Function: [nodejs.util.inspect.custom]] {\n' +
3292 ' [length]: 0,\n' +
3293 " [name]: '[nodejs.util.inspect.custom]'\n" +
3294 ' },\n' +
3295 ' [abc]: [Getter: true],\n' +
3296 ' [def]: [Getter/Setter: false]\n' +
3297 ' }'
3298 );
3299 
3300 assert.strictEqual(inspect(Object.getPrototypeOf(bar)), 'Foo [Map] {}');
3301 
3302 assert.strictEqual(inspect(Object.getPrototypeOf(new Foo())), 'Map {}');
3303 }
3304 
3305 // Check that prototypes with a null prototype are inspectable.
3306 // Regression test for https://github.com/nodejs/node/issues/35730
3307 {
3308 function Func() {}
3309 Func.prototype = null;
3310 const object = {};
3311 object.constructor = Func;
3312 
3313 assert.strictEqual(
3314 util.inspect(object),
3315 '{ constructor: [Function: Func] }'
3316 );
3317 }
3318 
3319 // Test changing util.inspect.colors colors and aliases.
3320 {
3321 const colors = util.inspect.colors;
3322 
3323 const originalValue = colors.gray;
3324 
3325 // "grey" is reference-equal alias of "gray".
3326 assert.strictEqual(colors.grey, colors.gray);
3327 
3328 // Assigning one should assign the other. This tests that the alias setter
3329 // function keeps things reference-equal.
3330 colors.gray = [0, 0];
3331 assert.deepStrictEqual(colors.gray, [0, 0]);
3332 assert.strictEqual(colors.grey, colors.gray);
3333 
3334 colors.grey = [1, 1];
3335 assert.deepStrictEqual(colors.grey, [1, 1]);
3336 assert.strictEqual(colors.grey, colors.gray);
3337 
3338 // Restore original value to avoid side effects in other tests.
3339 colors.gray = originalValue;
3340 assert.deepStrictEqual(colors.gray, originalValue);
3341 assert.strictEqual(colors.grey, colors.gray);
3342 }
3343 
3344 // Truncate output for Primitives with 1 character left
3345 {
3346 assert.strictEqual(
3347 util.inspect('bl', { maxStringLength: 1 }),
3348 "'b'... 1 more character"
3349 );
3350 }
3351 
3352 {
3353 const x = 'a'.repeat(1e6);
3354 assert(util.inspect(x).endsWith('... 990000 more characters'));
3355 assert.strictEqual(
3356 util.inspect(x, { maxStringLength: 4 }),
3357 "'aaaa'... 999996 more characters"
3358 );
3359 assert.match(util.inspect(x, { maxStringLength: null }), /a'$/);
3360 }
3361 
3362 {
3363 // Confirm that own constructor value displays correctly.
3364 
3365 function Fhqwhgads() {}
3366 
3367 const sterrance = new Fhqwhgads();
3368 sterrance.constructor = Fhqwhgads;
3369 
3370 assert.strictEqual(
3371 util.inspect(sterrance, { showHidden: true }),
3372 'Fhqwhgads {\n' +
3373 ' constructor: <ref *1> [Function: Fhqwhgads] {\n' +
3374 ' [length]: 0,\n' +
3375 " [name]: 'Fhqwhgads',\n" +
3376 ' [prototype]: { [constructor]: [Circular *1] }\n' +
3377 ' }\n' +
3378 '}'
3379 );
3380 }
3381 
3382 // TODO(soon): figure out why we're generating `Iterator [Generator]` instead of `Object [Generator]`
3383 {
3384 // Confirm null prototype of generator prototype displays as expected.
3385 
3386 function getProtoOfProto() {
3387 return Object.getPrototypeOf(Object.getPrototypeOf(function* () {}));
3388 }
3389 
3390 function* generator() {}
3391 
3392 const generatorPrototype = Object.getPrototypeOf(generator);
3393 const originalProtoOfProto = Object.getPrototypeOf(generatorPrototype);
3394 assert.strictEqual(getProtoOfProto(), originalProtoOfProto);
3395 Object.setPrototypeOf(generatorPrototype, null);
3396 assert.notStrictEqual(getProtoOfProto, originalProtoOfProto);
3397 
3398 // This is the actual test. The other assertions in this block are about
3399 // making sure the test is set up correctly and isn't polluting other tests.
3400 const expected1 =
3401 '[GeneratorFunction: generator] {\n' +
3402 ' [length]: 0,\n' +
3403 " [name]: 'generator',\n" +
3404 " [prototype]: Object [Generator] { [Symbol(Symbol.toStringTag)]: 'Generator' },\n" +
3405 " [Symbol(Symbol.toStringTag)]: 'GeneratorFunction'\n" +
3406 '}';
3407 const expected2 = // TODO: Remove this once updated to new V8.
3408 '[GeneratorFunction: generator] {\n' +
3409 ' [length]: 0,\n' +
3410 " [name]: 'generator',\n" +
3411 " [prototype]: Iterator [Generator] { [Symbol(Symbol.toStringTag)]: 'Generator' },\n" +
3412 " [Symbol(Symbol.toStringTag)]: 'GeneratorFunction'\n" +
3413 '}';
3414 const actual = util.inspect(generator, { showHidden: true });
3415 assert.ok(actual == expected1 || actual == expected2);
3416 
3417 // Reset so we don't pollute other tests
3418 Object.setPrototypeOf(generatorPrototype, originalProtoOfProto);
3419 assert.strictEqual(getProtoOfProto(), originalProtoOfProto);
3420 }
3421 
3422 {
3423 // Test for when breakLength results in a single column.
3424 const obj = Array.from(
3425 { length: 9 },
3426 () => 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf'
3427 );
3428 assert.strictEqual(
3429 util.inspect(obj, { breakLength: 256 }),
3430 '[\n' +
3431 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf',\n" +
3432 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf',\n" +
3433 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf',\n" +
3434 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf',\n" +
3435 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf',\n" +
3436 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf',\n" +
3437 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf',\n" +
3438 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf',\n" +
3439 " 'fhqwhgadshgnsdhjsdbkhsdabkfabkveybvf'\n" +
3440 ']'
3441 );
3442 }
3443 
3444 {
3445 assert.strictEqual(
3446 util.inspect({ ['__proto__']: { a: 1 } }),
3447 "{ ['__proto__']: { a: 1 } }"
3448 );
3449 }
3450 
3451 {
3452 const { numericSeparator } = util.inspect.defaultOptions;
3453 util.inspect.defaultOptions.numericSeparator = true;
3454 
3455 assert.strictEqual(
3456 // eslint-disable-next-line no-loss-of-precision
3457 util.inspect(1234567891234567891234),
3458 '1.234567891234568e+21'
3459 );
3460 assert.strictEqual(
3461 util.inspect(123456789.12345678),
3462 '123_456_789.123_456_78'
3463 );
3464 
3465 assert.strictEqual(util.inspect(10_000_000), '10_000_000');
3466 assert.strictEqual(util.inspect(1_000_000), '1_000_000');
3467 assert.strictEqual(util.inspect(100_000), '100_000');
3468 assert.strictEqual(util.inspect(99_999.9), '99_999.9');
3469 assert.strictEqual(util.inspect(9_999), '9_999');
3470 assert.strictEqual(util.inspect(999), '999');
3471 assert.strictEqual(util.inspect(NaN), 'NaN');
3472 assert.strictEqual(util.inspect(Infinity), 'Infinity');
3473 assert.strictEqual(util.inspect(-Infinity), '-Infinity');
3474 
3475 assert.strictEqual(
3476 util.inspect(new Float64Array([100_000_000])),
3477 'Float64Array(1) [ 100_000_000 ]'
3478 );
3479 assert.strictEqual(
3480 util.inspect(new BigInt64Array([9_100_000_100n])),
3481 'BigInt64Array(1) [ 9_100_000_100n ]'
3482 );
3483 
3484 assert.strictEqual(util.inspect(123456789), '123_456_789');
3485 assert.strictEqual(util.inspect(123456789n), '123_456_789n');
3486 
3487 util.inspect.defaultOptions.numericSeparator = numericSeparator;
3488 
3489 assert.strictEqual(
3490 util.inspect(123456789.12345678, { numericSeparator: true }),
3491 '123_456_789.123_456_78'
3492 );
3493 
3494 assert.strictEqual(
3495 util.inspect(-123456789.12345678, { numericSeparator: true }),
3496 '-123_456_789.123_456_78'
3497 );
3498 }
3499 
3500 // Regression test for https://github.com/nodejs/node/issues/41244
3501 {
3502 assert.strictEqual(
3503 util.inspect({
3504 get [Symbol.iterator]() {
3505 throw new Error();
3506 },
3507 }),
3508 '{ Symbol(Symbol.iterator): [Getter] }'
3509 );
3510 }
3511 
3512 {
3513 const sym = Symbol('bar()');
3514 const o = {
3515 foo: 0,
3516 'Symbol(foo)': 0,
3517 [Symbol('foo')]: 0,
3518 [Symbol('foo()')]: 0,
3519 [sym]: 0,
3520 };
3521 Object.defineProperty(o, sym, { enumerable: false });
3522 
3523 assert.strictEqual(
3524 util.inspect(o, { showHidden: true }),
3525 '{\n' +
3526 ' foo: 0,\n' +
3527 " 'Symbol(foo)': 0,\n" +
3528 ' Symbol(foo): 0,\n' +
3529 ' Symbol(foo()): 0,\n' +
3530 ' [Symbol(bar())]: 0\n' +
3531 '}'
3532 );
3533 }
3534 
3535 {
3536 const o = {};
3537 const { prototype: BuiltinPrototype } = Object;
3538 const desc = Reflect.getOwnPropertyDescriptor(
3539 BuiltinPrototype,
3540 'constructor'
3541 );
3542 Object.defineProperty(BuiltinPrototype, 'constructor', {
3543 get: () => BuiltinPrototype,
3544 configurable: true,
3545 });
3546 assert.strictEqual(util.inspect(o), '{}');
3547 Object.defineProperty(BuiltinPrototype, 'constructor', desc);
3548 }
3549 
3550 {
3551 const o = { f() {} };
3552 const { prototype: BuiltinPrototype } = Function;
3553 const desc = Reflect.getOwnPropertyDescriptor(
3554 BuiltinPrototype,
3555 'constructor'
3556 );
3557 Object.defineProperty(BuiltinPrototype, 'constructor', {
3558 get: () => BuiltinPrototype,
3559 configurable: true,
3560 });
3561 assert.strictEqual(util.inspect(o), '{ f: [Function: f] }');
3562 Object.defineProperty(BuiltinPrototype, 'constructor', desc);
3563 }
3564 {
3565 const prototypes = [
3566 Array.prototype,
3567 ArrayBuffer.prototype,
3568 Buffer.prototype,
3569 Function.prototype,
3570 Map.prototype,
3571 Object.prototype,
3572 Reflect.getPrototypeOf(Uint8Array.prototype),
3573 Set.prototype,
3574 Uint8Array.prototype,
3575 ];
3576 const descriptors = new Map();
3577 const buffer = Buffer.from('Hello');
3578 const o = {
3579 arrayBuffer: new ArrayBuffer(),
3580 buffer,
3581 typedArray: Uint8Array.from(buffer),
3582 array: [],
3583 func() {},
3584 set: new Set([1]),
3585 map: new Map(),
3586 };
3587 for (const BuiltinPrototype of prototypes) {
3588 descriptors.set(
3589 BuiltinPrototype,
3590 Reflect.getOwnPropertyDescriptor(BuiltinPrototype, 'constructor')
3591 );
3592 Object.defineProperty(BuiltinPrototype, 'constructor', {
3593 get: () => BuiltinPrototype,
3594 configurable: true,
3595 });
3596 }
3597 assert.strictEqual(
3598 util.inspect(o),
3599 '{\n' +
3600 ' arrayBuffer: ArrayBuffer { [Uint8Contents]: <>, byteLength: 0 },\n' +
3601 ' buffer: <Buffer 48 65 6c 6c 6f>,\n' +
3602 ' typedArray: TypedArray(5) [Uint8Array] [ 72, 101, 108, 108, 111 ],\n' +
3603 ' array: [],\n' +
3604 ' func: [Function: func],\n' +
3605 ' set: Set(1) { 1 },\n' +
3606 ' map: Map(0) {}\n' +
3607 '}'
3608 );
3609 for (const [BuiltinPrototype, desc] of descriptors) {
3610 Object.defineProperty(BuiltinPrototype, 'constructor', desc);
3611 }
3612 }
3613 
3614 {
3615 function f() {}
3616 Object.defineProperty(f, 'name', { value: Symbol('f') });
3617 
3618 assert.strictEqual(util.inspect(f), '[Function: Symbol(f)]');
3619 }
3620 
3621 {
3622 const error = new EvalError();
3623 const re = /a/g;
3624 error.name = re;
3625 assert.strictEqual(error.name, re);
3626 assert.strictEqual(
3627 util.inspect(error),
3628 `${re} [EvalError]
3629${error.stack.split('\n').slice(1).join('\n')}`
3630 );
3631 }
3632 
3633 {
3634 const error = new Error();
3635 error.stack = [Symbol('foo')];
3636 
3637 assert.strictEqual(inspect(error), '[[\n Symbol(foo)\n]]');
3638 }
3639 
3640 assertCalledMustCalls();
3641 },
3642};
3643 
3644export const utilInspectProxy = {
3645 // test-util-inspect-proxy.js
3646 test(ctrl, env, ctx) {
3647 const opts = { showProxy: true };
3648 
3649 let proxyObj;
3650 let called = false;
3651 const target = {
3652 [util.inspect.custom](depth, { showProxy }) {
3653 if (showProxy === false) {
3654 called = true;
3655 if (proxyObj !== this) {
3656 throw new Error('Failed');
3657 }
3658 }
3659 return [1, 2, 3];
3660 },
3661 };
3662 const handler = {
3663 getPrototypeOf() {
3664 throw new Error('getPrototypeOf');
3665 },
3666 setPrototypeOf() {
3667 throw new Error('setPrototypeOf');
3668 },
3669 isExtensible() {
3670 throw new Error('isExtensible');
3671 },
3672 preventExtensions() {
3673 throw new Error('preventExtensions');
3674 },
3675 getOwnPropertyDescriptor() {
3676 throw new Error('getOwnPropertyDescriptor');
3677 },
3678 defineProperty() {
3679 throw new Error('defineProperty');
3680 },
3681 has() {
3682 throw new Error('has');
3683 },
3684 get() {
3685 throw new Error('get');
3686 },
3687 set() {
3688 throw new Error('set');
3689 },
3690 deleteProperty() {
3691 throw new Error('deleteProperty');
3692 },
3693 ownKeys() {
3694 throw new Error('ownKeys');
3695 },
3696 apply() {
3697 throw new Error('apply');
3698 },
3699 construct() {
3700 throw new Error('construct');
3701 },
3702 };
3703 proxyObj = new Proxy(target, handler);
3704 
3705 // Inspecting the proxy should not actually walk its properties
3706 util.inspect(proxyObj, opts);
3707 
3708 // Make sure inspecting object does not trigger any proxy traps.
3709 util.format('%s', proxyObj);
3710 // %i%f%d use Symbol.toPrimitive to convert the value to a string.
3711 // %j uses JSON.stringify, accessing the value's toJSON and toString method.
3712 util.format('%s%o%O%c', proxyObj, proxyObj, proxyObj, proxyObj);
3713 const nestedFormatProxy = new Proxy(new Proxy({}, handler), {});
3714 util.format(
3715 '%s%o%O%c',
3716 nestedFormatProxy,
3717 nestedFormatProxy,
3718 nestedFormatProxy,
3719 nestedFormatProxy
3720 );
3721 
3722 const r = Proxy.revocable({}, {});
3723 r.revoke();
3724 
3725 assert.strictEqual(util.inspect(r.proxy), '<Revoked Proxy>');
3726 assert.strictEqual(
3727 util.inspect(r, { showProxy: true }),
3728 '{ proxy: <Revoked Proxy>, revoke: [Function (anonymous)] }'
3729 );
3730 
3731 assert.strictEqual(util.format('%s', r.proxy), '<Revoked Proxy>');
3732 
3733 assert.strictEqual(
3734 util.inspect(proxyObj, opts),
3735 'Proxy [\n' +
3736 ' [ 1, 2, 3 ],\n' +
3737 ' {\n' +
3738 ' getPrototypeOf: [Function: getPrototypeOf],\n' +
3739 ' setPrototypeOf: [Function: setPrototypeOf],\n' +
3740 ' isExtensible: [Function: isExtensible],\n' +
3741 ' preventExtensions: [Function: preventExtensions],\n' +
3742 ' getOwnPropertyDescriptor: [Function: getOwnPropertyDescriptor],\n' +
3743 ' defineProperty: [Function: defineProperty],\n' +
3744 ' has: [Function: has],\n' +
3745 ' get: [Function: get],\n' +
3746 ' set: [Function: set],\n' +
3747 ' deleteProperty: [Function: deleteProperty],\n' +
3748 ' ownKeys: [Function: ownKeys],\n' +
3749 ' apply: [Function: apply],\n' +
3750 ' construct: [Function: construct]\n' +
3751 ' }\n' +
3752 ']'
3753 );
3754 
3755 // Inspecting a proxy without the showProxy option set to true should not
3756 // trigger any proxy handlers.
3757 assert.strictEqual(util.inspect(proxyObj), '[ 1, 2, 3 ]');
3758 assert(called);
3759 
3760 // Yo dawg, I heard you liked Proxy so I put a Proxy
3761 // inside your Proxy that proxies your Proxy's Proxy.
3762 const proxy1 = new Proxy({}, {});
3763 const proxy2 = new Proxy(proxy1, {});
3764 const proxy3 = new Proxy(proxy2, proxy1);
3765 const proxy4 = new Proxy(proxy1, proxy2);
3766 const proxy5 = new Proxy(proxy3, proxy4);
3767 const proxy6 = new Proxy(proxy5, proxy5);
3768 const expected0 = 'Proxy({})';
3769 const expected1 = 'Proxy [ {}, {} ]';
3770 const expected2 = 'Proxy [ Proxy [ {}, {} ], {} ]';
3771 const expected3 =
3772 'Proxy [ Proxy [ Proxy [ {}, {} ], {} ], Proxy [ {}, {} ] ]';
3773 const expected4 =
3774 'Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [ {}, {} ], {} ] ]';
3775 const expected5 =
3776 'Proxy [\n ' +
3777 'Proxy [ Proxy [ Proxy [Array], {} ], Proxy [ {}, {} ] ],\n' +
3778 ' Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [Array], {} ] ]' +
3779 '\n]';
3780 const expected6 =
3781 'Proxy [\n' +
3782 ' Proxy [\n' +
3783 ' Proxy [ Proxy [Array], Proxy [Array] ],\n' +
3784 ' Proxy [ Proxy [Array], Proxy [Array] ]\n' +
3785 ' ],\n' +
3786 ' Proxy [\n' +
3787 ' Proxy [ Proxy [Array], Proxy [Array] ],\n' +
3788 ' Proxy [ Proxy [Array], Proxy [Array] ]\n' +
3789 ' ]\n' +
3790 ']';
3791 const expected2NoShowProxy = 'Proxy(Proxy({}))';
3792 const expected3NoShowProxy = 'Proxy(Proxy(Proxy({})))';
3793 const expected4NoShowProxy = 'Proxy(Proxy(Proxy(Proxy({}))))';
3794 const expected5NoShowProxy = 'Proxy(Proxy(Proxy(Proxy(Proxy({})))))';
3795 assert.strictEqual(
3796 util.inspect(proxy1, { showProxy: 1, depth: null }),
3797 expected1
3798 );
3799 assert.strictEqual(util.inspect(proxy2, opts), expected2);
3800 assert.strictEqual(util.inspect(proxy3, opts), expected3);
3801 assert.strictEqual(util.inspect(proxy4, opts), expected4);
3802 assert.strictEqual(util.inspect(proxy5, opts), expected5);
3803 assert.strictEqual(util.inspect(proxy6, opts), expected6);
3804 assert.strictEqual(util.inspect(proxy1), expected0);
3805 assert.strictEqual(util.inspect(proxy2), expected2NoShowProxy);
3806 assert.strictEqual(util.inspect(proxy3), expected3NoShowProxy);
3807 assert.strictEqual(util.inspect(proxy4), expected2NoShowProxy);
3808 assert.strictEqual(util.inspect(proxy5), expected4NoShowProxy);
3809 assert.strictEqual(util.inspect(proxy6), expected5NoShowProxy);
3810 
3811 // Just for fun, let's create a Proxy using Arrays.
3812 const proxy7 = new Proxy([], []);
3813 const expected7 = 'Proxy [ [], [] ]';
3814 assert.strictEqual(util.inspect(proxy7, opts), expected7);
3815 assert.strictEqual(util.inspect(proxy7), 'Proxy([])');
3816 
3817 // Now we're just getting silly, right?
3818 const proxy8 = new Proxy(Date, []);
3819 const proxy9 = new Proxy(Date, String);
3820 const expected8 = 'Proxy [ [Function: Date], [] ]';
3821 const expected9 = 'Proxy [ [Function: Date], [Function: String] ]';
3822 assert.strictEqual(util.inspect(proxy8, opts), expected8);
3823 assert.strictEqual(util.inspect(proxy9, opts), expected9);
3824 assert.strictEqual(util.inspect(proxy8), 'Proxy([Function: Date])');
3825 assert.strictEqual(util.inspect(proxy9), 'Proxy([Function: Date])');
3826 
3827 const proxy10 = new Proxy(() => {}, {});
3828 const proxy11 = new Proxy(() => {}, {
3829 get() {
3830 return proxy11;
3831 },
3832 apply() {
3833 return proxy11;
3834 },
3835 });
3836 const expected10 = 'Proxy([Function (anonymous)])';
3837 const expected11 = 'Proxy([Function (anonymous)])';
3838 assert.strictEqual(util.inspect(proxy10), expected10);
3839 assert.strictEqual(util.inspect(proxy11), expected11);
3840 
3841 const proxy12 = new Proxy([1, 2, 3], proxy5);
3842 assert.strictEqual(
3843 util.inspect(proxy12, { colors: true, breakLength: 1 }),
3844 '\x1B[36mProxy(\x1B[39m' +
3845 '[\n \x1B[33m1\x1B[39m,\n \x1B[33m2\x1B[39m,\n \x1B[33m3\x1B[39m\n]\x1B[36m' +
3846 ')\x1B[39m'
3847 );
3848 assert.strictEqual(util.format('%s', proxy12), 'Proxy([ 1, 2, 3 ])');
3849 
3850 {
3851 // Nested proxies should not trigger any proxy handlers.
3852 const nestedProxy = new Proxy(new Proxy(new Proxy({}, handler), {}), {});
3853 
3854 assert.strictEqual(
3855 util.inspect(nestedProxy, { showProxy: true }),
3856 'Proxy [ Proxy [ Proxy [ {}, [Object] ], {} ], {} ]'
3857 );
3858 assert.strictEqual(
3859 util.inspect(nestedProxy, { showProxy: false }),
3860 expected3NoShowProxy
3861 );
3862 }
3863 
3864 {
3865 // Nested revoked proxies should work as expected as well as custom
3866 // inspection functions.
3867 const revocable = Proxy.revocable({}, handler);
3868 revocable.revoke();
3869 const nestedProxy = new Proxy(revocable.proxy, {});
3870 
3871 assert.strictEqual(
3872 util.inspect(nestedProxy, { showProxy: true }),
3873 'Proxy [ <Revoked Proxy>, {} ]'
3874 );
3875 assert.strictEqual(
3876 util.inspect(nestedProxy, { showProxy: false }),
3877 'Proxy(<Revoked Proxy>)'
3878 );
3879 }
3880 },
3881};
3882 
3883export const utilInspectGettersAccessingThis = {
3884 // test-util-inspect-getters-accessing-this.js
3885 test(ctrl, env, ctx) {
3886 {
3887 class X {
3888 constructor() {
3889 this._y = 123;
3890 }
3891 
3892 get y() {
3893 return this._y;
3894 }
3895 }
3896 
3897 const result = inspect(new X(), {
3898 getters: true,
3899 showHidden: true,
3900 });
3901 
3902 assert.strictEqual(result, 'X { _y: 123, [y]: [Getter: 123] }');
3903 }
3904 
3905 // Regression test for https://github.com/nodejs/node/issues/37054
3906 {
3907 class A {
3908 constructor(B) {
3909 this.B = B;
3910 }
3911 get b() {
3912 return this.B;
3913 }
3914 }
3915 
3916 class B {
3917 constructor() {
3918 this.A = new A(this);
3919 }
3920 get a() {
3921 return this.A;
3922 }
3923 }
3924 
3925 const result = inspect(new B(), {
3926 depth: 1,
3927 getters: true,
3928 showHidden: true,
3929 });
3930 
3931 assert.strictEqual(
3932 result,
3933 '<ref *1> B {\n' +
3934 ' A: A { B: [Circular *1], [b]: [Getter] [Circular *1] },\n' +
3935 ' [a]: [Getter] A { B: [Circular *1], [b]: [Getter] [Circular *1] }\n' +
3936 '}'
3937 );
3938 }
3939 },
3940};
3941 
3942export const utilFormat = {
3943 // test-util-format.js
3944 async test(ctrl, env, ctx) {
3945 const symbol = Symbol('foo');
3946 
3947 assert.strictEqual(util.format(), '');
3948 assert.strictEqual(util.format(''), '');
3949 assert.strictEqual(util.format([]), '[]');
3950 assert.strictEqual(util.format([0]), '[ 0 ]');
3951 assert.strictEqual(util.format({}), '{}');
3952 assert.strictEqual(util.format({ foo: 42 }), '{ foo: 42 }');
3953 assert.strictEqual(util.format(null), 'null');
3954 assert.strictEqual(util.format(true), 'true');
3955 assert.strictEqual(util.format(false), 'false');
3956 assert.strictEqual(util.format('test'), 'test');
3957 
3958 // CHECKME this is for console.log() compatibility - but is it *right*?
3959 assert.strictEqual(util.format('foo', 'bar', 'baz'), 'foo bar baz');
3960 
3961 // ES6 Symbol handling
3962 assert.strictEqual(util.format(symbol), 'Symbol(foo)');
3963 assert.strictEqual(util.format('foo', symbol), 'foo Symbol(foo)');
3964 assert.strictEqual(util.format('%s', symbol), 'Symbol(foo)');
3965 assert.strictEqual(util.format('%j', symbol), 'undefined');
3966 
3967 // Number format specifier
3968 assert.strictEqual(util.format('%d'), '%d');
3969 assert.strictEqual(util.format('%d', 42.0), '42');
3970 assert.strictEqual(util.format('%d', 42), '42');
3971 assert.strictEqual(util.format('%d', '42'), '42');
3972 assert.strictEqual(util.format('%d', '42.0'), '42');
3973 assert.strictEqual(util.format('%d', 1.5), '1.5');
3974 assert.strictEqual(util.format('%d', -0.5), '-0.5');
3975 assert.strictEqual(util.format('%d', -0.0), '-0');
3976 assert.strictEqual(util.format('%d', ''), '0');
3977 assert.strictEqual(util.format('%d', ' -0.000'), '-0');
3978 assert.strictEqual(util.format('%d', Symbol()), 'NaN');
3979 assert.strictEqual(util.format('%d', Infinity), 'Infinity');
3980 assert.strictEqual(util.format('%d', -Infinity), '-Infinity');
3981 assert.strictEqual(util.format('%d %d', 42, 43), '42 43');
3982 assert.strictEqual(util.format('%d %d', 42), '42 %d');
3983 assert.strictEqual(
3984 util.format('%d', 1180591620717411303424),
3985 '1.1805916207174113e+21'
3986 );
3987 assert.strictEqual(
3988 util.format('%d', 1180591620717411303424n),
3989 '1180591620717411303424n'
3990 );
3991 assert.strictEqual(
3992 util.format('%d %d', 1180591620717411303424n, 12345678901234567890123n),
3993 '1180591620717411303424n 12345678901234567890123n'
3994 );
3995 
3996 {
3997 const { numericSeparator } = util.inspect.defaultOptions;
3998 util.inspect.defaultOptions.numericSeparator = true;
3999 
4000 assert.strictEqual(
4001 util.format('%d', 1180591620717411303424),
4002 '1.1805916207174113e+21'
4003 );
4004 
4005 assert.strictEqual(
4006 util.format(
4007 '%d %s %i',
4008 // eslint-disable-next-line no-loss-of-precision
4009 118059162071741130342,
4010 // eslint-disable-next-line no-loss-of-precision
4011 118059162071741130342,
4012 123_123_123
4013 ),
4014 '118_059_162_071_741_140_000 118_059_162_071_741_140_000 123_123_123'
4015 );
4016 
4017 assert.strictEqual(
4018 util.format(
4019 '%d %s',
4020 1_180_591_620_717_411_303_424n,
4021 12_345_678_901_234_567_890_123n
4022 ),
4023 '1_180_591_620_717_411_303_424n 12_345_678_901_234_567_890_123n'
4024 );
4025 
4026 assert.strictEqual(
4027 util.format('%i', 1_180_591_620_717_411_303_424n),
4028 '1_180_591_620_717_411_303_424n'
4029 );
4030 
4031 util.inspect.defaultOptions.numericSeparator = numericSeparator;
4032 }
4033 // Integer format specifier
4034 assert.strictEqual(util.format('%i'), '%i');
4035 assert.strictEqual(util.format('%i', 42.0), '42');
4036 assert.strictEqual(util.format('%i', 42), '42');
4037 assert.strictEqual(util.format('%i', '42'), '42');
4038 assert.strictEqual(util.format('%i', '42.0'), '42');
4039 assert.strictEqual(util.format('%i', 1.5), '1');
4040 assert.strictEqual(util.format('%i', -0.5), '-0');
4041 assert.strictEqual(util.format('%i', ''), 'NaN');
4042 assert.strictEqual(util.format('%i', Infinity), 'NaN');
4043 assert.strictEqual(util.format('%i', -Infinity), 'NaN');
4044 assert.strictEqual(util.format('%i', Symbol()), 'NaN');
4045 assert.strictEqual(util.format('%i %i', 42, 43), '42 43');
4046 assert.strictEqual(util.format('%i %i', 42), '42 %i');
4047 assert.strictEqual(util.format('%i', 1180591620717411303424), '1');
4048 assert.strictEqual(
4049 util.format('%i', 1180591620717411303424n),
4050 '1180591620717411303424n'
4051 );
4052 assert.strictEqual(
4053 util.format('%i %i', 1180591620717411303424n, 12345678901234567890123n),
4054 '1180591620717411303424n 12345678901234567890123n'
4055 );
4056 
4057 assert.strictEqual(
4058 util.format('%d %i', 1180591620717411303424n, 12345678901234567890123n),
4059 '1180591620717411303424n 12345678901234567890123n'
4060 );
4061 
4062 assert.strictEqual(
4063 util.format('%i %d', 1180591620717411303424n, 12345678901234567890123n),
4064 '1180591620717411303424n 12345678901234567890123n'
4065 );
4066 
4067 assert.strictEqual(
4068 util.formatWithOptions(
4069 { numericSeparator: true },
4070 '%i %d',
4071 1180591620717411303424n,
4072 12345678901234567890123n
4073 ),
4074 '1_180_591_620_717_411_303_424n 12_345_678_901_234_567_890_123n'
4075 );
4076 
4077 // Float format specifier
4078 assert.strictEqual(util.format('%f'), '%f');
4079 assert.strictEqual(util.format('%f', 42.0), '42');
4080 assert.strictEqual(util.format('%f', 42), '42');
4081 assert.strictEqual(util.format('%f', '42'), '42');
4082 assert.strictEqual(util.format('%f', '-0.0'), '-0');
4083 assert.strictEqual(util.format('%f', '42.0'), '42');
4084 assert.strictEqual(util.format('%f', 1.5), '1.5');
4085 assert.strictEqual(util.format('%f', -0.5), '-0.5');
4086 assert.strictEqual(util.format('%f', Math.PI), '3.141592653589793');
4087 assert.strictEqual(util.format('%f', ''), 'NaN');
4088 assert.strictEqual(util.format('%f', Symbol('foo')), 'NaN');
4089 assert.strictEqual(util.format('%f', 5n), '5');
4090 assert.strictEqual(util.format('%f', Infinity), 'Infinity');
4091 assert.strictEqual(util.format('%f', -Infinity), '-Infinity');
4092 assert.strictEqual(util.format('%f %f', 42, 43), '42 43');
4093 assert.strictEqual(util.format('%f %f', 42), '42 %f');
4094 
4095 // String format specifier
4096 assert.strictEqual(util.format('%s'), '%s');
4097 assert.strictEqual(util.format('%s', undefined), 'undefined');
4098 assert.strictEqual(util.format('%s', null), 'null');
4099 assert.strictEqual(util.format('%s', 'foo'), 'foo');
4100 assert.strictEqual(util.format('%s', 42), '42');
4101 assert.strictEqual(util.format('%s', '42'), '42');
4102 assert.strictEqual(util.format('%s', -0), '-0');
4103 assert.strictEqual(util.format('%s', '-0.0'), '-0.0');
4104 assert.strictEqual(util.format('%s %s', 42, 43), '42 43');
4105 assert.strictEqual(util.format('%s %s', 42), '42 %s');
4106 assert.strictEqual(util.format('%s', 42n), '42n');
4107 assert.strictEqual(util.format('%s', Symbol('foo')), 'Symbol(foo)');
4108 assert.strictEqual(util.format('%s', true), 'true');
4109 assert.strictEqual(util.format('%s', { a: [1, 2, 3] }), '{ a: [Array] }');
4110 assert.strictEqual(
4111 util.format('%s', {
4112 toString() {
4113 return 'Foo';
4114 },
4115 }),
4116 'Foo'
4117 );
4118 assert.strictEqual(util.format('%s', { toString: 5 }), '{ toString: 5 }');
4119 assert.strictEqual(
4120 util.format('%s', () => 5),
4121 '() => 5'
4122 );
4123 assert.strictEqual(util.format('%s', Infinity), 'Infinity');
4124 assert.strictEqual(util.format('%s', -Infinity), '-Infinity');
4125 
4126 // String format specifier including `toString` properties on the prototype.
4127 {
4128 class Foo {
4129 toString() {
4130 return 'Bar';
4131 }
4132 }
4133 assert.strictEqual(util.format('%s', new Foo()), 'Bar');
4134 assert.strictEqual(
4135 util.format('%s', Object.setPrototypeOf(new Foo(), null)),
4136 '[Foo: null prototype] {}'
4137 );
4138 globalThis.Foo = Foo;
4139 assert.strictEqual(util.format('%s', new Foo()), 'Bar');
4140 delete globalThis.Foo;
4141 class Bar {
4142 abc = true;
4143 }
4144 assert.strictEqual(util.format('%s', new Bar()), 'Bar { abc: true }');
4145 class Foobar extends Array {
4146 aaa = true;
4147 }
4148 assert.strictEqual(
4149 util.format('%s', new Foobar(5)),
4150 'Foobar(5) [ <5 empty items>, aaa: true ]'
4151 );
4152 
4153 // Subclassing:
4154 class B extends Foo {}
4155 
4156 function C() {}
4157 C.prototype.toString = function () {
4158 return 'Custom';
4159 };
4160 
4161 function D() {
4162 C.call(this);
4163 }
4164 D.prototype = { __proto__: C.prototype };
4165 
4166 assert.strictEqual(util.format('%s', new B()), 'Bar');
4167 assert.strictEqual(util.format('%s', new C()), 'Custom');
4168 assert.strictEqual(util.format('%s', new D()), 'Custom');
4169 
4170 D.prototype.constructor = D;
4171 assert.strictEqual(util.format('%s', new D()), 'Custom');
4172 
4173 D.prototype.constructor = null;
4174 assert.strictEqual(util.format('%s', new D()), 'Custom');
4175 
4176 D.prototype.constructor = { name: 'Foobar' };
4177 assert.strictEqual(util.format('%s', new D()), 'Custom');
4178 
4179 Object.defineProperty(D.prototype, 'constructor', {
4180 get() {
4181 throw new Error();
4182 },
4183 configurable: true,
4184 });
4185 assert.strictEqual(util.format('%s', new D()), 'Custom');
4186 
4187 assert.strictEqual(
4188 util.format('%s', { __proto__: null }),
4189 '[Object: null prototype] {}'
4190 );
4191 }
4192 
4193 // JSON format specifier
4194 assert.strictEqual(util.format('%j'), '%j');
4195 assert.strictEqual(util.format('%j', 42), '42');
4196 assert.strictEqual(util.format('%j', '42'), '"42"');
4197 assert.strictEqual(util.format('%j %j', 42, 43), '42 43');
4198 assert.strictEqual(util.format('%j %j', 42), '42 %j');
4199 
4200 // Object format specifier
4201 const obj = {
4202 foo: 'bar',
4203 foobar: 1,
4204 func: function () {},
4205 };
4206 const nestedObj = {
4207 foo: 'bar',
4208 foobar: {
4209 foo: 'bar',
4210 func: function () {},
4211 },
4212 };
4213 const nestedObj2 = {
4214 foo: 'bar',
4215 foobar: 1,
4216 func: [{ a: function () {} }],
4217 };
4218 assert.strictEqual(util.format('%o'), '%o');
4219 assert.strictEqual(util.format('%o', 42), '42');
4220 assert.strictEqual(util.format('%o', 'foo'), "'foo'");
4221 assert.strictEqual(
4222 util.format('%o', obj),
4223 '{\n' +
4224 " foo: 'bar',\n" +
4225 ' foobar: 1,\n' +
4226 ' func: <ref *1> [Function: func] {\n' +
4227 ' [length]: 0,\n' +
4228 " [name]: 'func',\n" +
4229 ' [prototype]: { [constructor]: [Circular *1] }\n' +
4230 ' }\n' +
4231 '}'
4232 );
4233 assert.strictEqual(
4234 util.format('%o', nestedObj2),
4235 '{\n' +
4236 " foo: 'bar',\n" +
4237 ' foobar: 1,\n' +
4238 ' func: [\n' +
4239 ' {\n' +
4240 ' a: <ref *1> [Function: a] {\n' +
4241 ' [length]: 0,\n' +
4242 " [name]: 'a',\n" +
4243 ' [prototype]: { [constructor]: [Circular *1] }\n' +
4244 ' }\n' +
4245 ' },\n' +
4246 ' [length]: 1\n' +
4247 ' ]\n' +
4248 '}'
4249 );
4250 assert.strictEqual(
4251 util.format('%o', nestedObj),
4252 '{\n' +
4253 " foo: 'bar',\n" +
4254 ' foobar: {\n' +
4255 " foo: 'bar',\n" +
4256 ' func: <ref *1> [Function: func] {\n' +
4257 ' [length]: 0,\n' +
4258 " [name]: 'func',\n" +
4259 ' [prototype]: { [constructor]: [Circular *1] }\n' +
4260 ' }\n' +
4261 ' }\n' +
4262 '}'
4263 );
4264 assert.strictEqual(
4265 util.format('%o %o', obj, obj),
4266 '{\n' +
4267 " foo: 'bar',\n" +
4268 ' foobar: 1,\n' +
4269 ' func: <ref *1> [Function: func] {\n' +
4270 ' [length]: 0,\n' +
4271 " [name]: 'func',\n" +
4272 ' [prototype]: { [constructor]: [Circular *1] }\n' +
4273 ' }\n' +
4274 '} {\n' +
4275 " foo: 'bar',\n" +
4276 ' foobar: 1,\n' +
4277 ' func: <ref *1> [Function: func] {\n' +
4278 ' [length]: 0,\n' +
4279 " [name]: 'func',\n" +
4280 ' [prototype]: { [constructor]: [Circular *1] }\n' +
4281 ' }\n' +
4282 '}'
4283 );
4284 assert.strictEqual(
4285 util.format('%o %o', obj),
4286 '{\n' +
4287 " foo: 'bar',\n" +
4288 ' foobar: 1,\n' +
4289 ' func: <ref *1> [Function: func] {\n' +
4290 ' [length]: 0,\n' +
4291 " [name]: 'func',\n" +
4292 ' [prototype]: { [constructor]: [Circular *1] }\n' +
4293 ' }\n' +
4294 '} %o'
4295 );
4296 
4297 assert.strictEqual(util.format('%O'), '%O');
4298 assert.strictEqual(util.format('%O', 42), '42');
4299 assert.strictEqual(util.format('%O', 'foo'), "'foo'");
4300 assert.strictEqual(
4301 util.format('%O', obj),
4302 "{ foo: 'bar', foobar: 1, func: [Function: func] }"
4303 );
4304 assert.strictEqual(
4305 util.format('%O', nestedObj),
4306 "{ foo: 'bar', foobar: { foo: 'bar', func: [Function: func] } }"
4307 );
4308 assert.strictEqual(
4309 util.format('%O %O', obj, obj),
4310 "{ foo: 'bar', foobar: 1, func: [Function: func] } " +
4311 "{ foo: 'bar', foobar: 1, func: [Function: func] }"
4312 );
4313 assert.strictEqual(
4314 util.format('%O %O', obj),
4315 "{ foo: 'bar', foobar: 1, func: [Function: func] } %O"
4316 );
4317 
4318 // Various format specifiers
4319 assert.strictEqual(util.format('%%s%s', 'foo'), '%sfoo');
4320 assert.strictEqual(util.format('%s:%s'), '%s:%s');
4321 assert.strictEqual(util.format('%s:%s', undefined), 'undefined:%s');
4322 assert.strictEqual(util.format('%s:%s', 'foo'), 'foo:%s');
4323 assert.strictEqual(util.format('%s:%i', 'foo'), 'foo:%i');
4324 assert.strictEqual(util.format('%s:%f', 'foo'), 'foo:%f');
4325 assert.strictEqual(util.format('%s:%s', 'foo', 'bar'), 'foo:bar');
4326 assert.strictEqual(
4327 util.format('%s:%s', 'foo', 'bar', 'baz'),
4328 'foo:bar baz'
4329 );
4330 assert.strictEqual(util.format('%%%s%%', 'hi'), '%hi%');
4331 assert.strictEqual(util.format('%%%s%%%%', 'hi'), '%hi%%');
4332 assert.strictEqual(util.format('%sbc%%def', 'a'), 'abc%def');
4333 assert.strictEqual(util.format('%d:%d', 12, 30), '12:30');
4334 assert.strictEqual(util.format('%d:%d', 12), '12:%d');
4335 assert.strictEqual(util.format('%d:%d'), '%d:%d');
4336 assert.strictEqual(util.format('%i:%i', 12, 30), '12:30');
4337 assert.strictEqual(util.format('%i:%i', 12), '12:%i');
4338 assert.strictEqual(util.format('%i:%i'), '%i:%i');
4339 assert.strictEqual(util.format('%f:%f', 12, 30), '12:30');
4340 assert.strictEqual(util.format('%f:%f', 12), '12:%f');
4341 assert.strictEqual(util.format('%f:%f'), '%f:%f');
4342 assert.strictEqual(util.format('o: %j, a: %j', {}, []), 'o: {}, a: []');
4343 assert.strictEqual(util.format('o: %j, a: %j', {}), 'o: {}, a: %j');
4344 assert.strictEqual(util.format('o: %j, a: %j'), 'o: %j, a: %j');
4345 assert.strictEqual(util.format('o: %o, a: %O', {}, []), 'o: {}, a: []');
4346 assert.strictEqual(util.format('o: %o, a: %o', {}), 'o: {}, a: %o');
4347 assert.strictEqual(util.format('o: %O, a: %O'), 'o: %O, a: %O');
4348 
4349 // Invalid format specifiers
4350 assert.strictEqual(util.format('a% b', 'x'), 'a% b x');
4351 assert.strictEqual(
4352 util.format('percent: %d%, fraction: %d', 10, 0.1),
4353 'percent: 10%, fraction: 0.1'
4354 );
4355 assert.strictEqual(util.format('abc%', 1), 'abc% 1');
4356 
4357 // Additional arguments after format specifiers
4358 assert.strictEqual(util.format('%i', 1, 'number'), '1 number');
4359 assert.strictEqual(
4360 util.format('%i', 1, () => {}),
4361 '1 [Function (anonymous)]'
4362 );
4363 
4364 // %c from https://console.spec.whatwg.org/
4365 assert.strictEqual(util.format('%c'), '%c');
4366 assert.strictEqual(util.format('%cab'), '%cab');
4367 assert.strictEqual(util.format('%cab', 'color: blue'), 'ab');
4368 assert.strictEqual(util.format('%cab', 'color: blue', 'c'), 'ab c');
4369 
4370 {
4371 const o = {};
4372 o.o = o;
4373 assert.strictEqual(util.format('%j', o), '[Circular]');
4374 }
4375 
4376 {
4377 const o = {
4378 toJSON() {
4379 throw new Error('Not a circular object but still not serializable');
4380 },
4381 };
4382 assert.throws(
4383 () => util.format('%j', o),
4384 /^Error: Not a circular object but still not serializable$/
4385 );
4386 }
4387 
4388 // Errors
4389 const err = new Error('foo');
4390 assert.strictEqual(util.format(err), err.stack);
4391 class CustomError extends Error {
4392 constructor(msg) {
4393 super();
4394 Object.defineProperty(this, 'message', {
4395 value: msg,
4396 enumerable: false,
4397 });
4398 Object.defineProperty(this, 'name', {
4399 value: 'CustomError',
4400 enumerable: false,
4401 });
4402 Error.captureStackTrace(this, CustomError);
4403 }
4404 }
4405 const customError = new CustomError('bar');
4406 assert.strictEqual(util.format(customError), customError.stack);
4407 // Doesn't capture stack trace
4408 function BadCustomError(msg) {
4409 Error.call(this);
4410 Object.defineProperty(this, 'message', { value: msg, enumerable: false });
4411 Object.defineProperty(this, 'name', {
4412 value: 'BadCustomError',
4413 enumerable: false,
4414 });
4415 }
4416 Object.setPrototypeOf(BadCustomError.prototype, Error.prototype);
4417 Object.setPrototypeOf(BadCustomError, Error);
4418 assert.strictEqual(
4419 util.format(new BadCustomError('foo')),
4420 '[BadCustomError: foo]'
4421 );
4422 
4423 // The format of arguments should not depend on type of the first argument
4424 assert.strictEqual(util.format('1', '1'), '1 1');
4425 assert.strictEqual(util.format(1, '1'), '1 1');
4426 assert.strictEqual(util.format('1', 1), '1 1');
4427 assert.strictEqual(util.format(1, -0), '1 -0');
4428 assert.strictEqual(
4429 util.format('1', () => {}),
4430 '1 [Function (anonymous)]'
4431 );
4432 assert.strictEqual(
4433 util.format(1, () => {}),
4434 '1 [Function (anonymous)]'
4435 );
4436 assert.strictEqual(util.format('1', "'"), "1 '");
4437 assert.strictEqual(util.format(1, "'"), "1 '");
4438 assert.strictEqual(util.format('1', 'number'), '1 number');
4439 assert.strictEqual(util.format(1, 'number'), '1 number');
4440 assert.strictEqual(util.format(5n), '5n');
4441 assert.strictEqual(util.format(5n, 5n), '5n 5n');
4442 
4443 // Check `formatWithOptions`.
4444 assert.strictEqual(
4445 util.formatWithOptions(
4446 { colors: true },
4447 true,
4448 undefined,
4449 Symbol(),
4450 1,
4451 5n,
4452 null,
4453 'foobar'
4454 ),
4455 '\u001b[33mtrue\u001b[39m ' +
4456 '\u001b[90mundefined\u001b[39m ' +
4457 '\u001b[32mSymbol()\u001b[39m ' +
4458 '\u001b[33m1\u001b[39m ' +
4459 '\u001b[33m5n\u001b[39m ' +
4460 '\u001b[1mnull\u001b[22m ' +
4461 'foobar'
4462 );
4463 
4464 assert.strictEqual(
4465 util.format(new SharedArrayBuffer(4)),
4466 'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
4467 );
4468 
4469 assert.strictEqual(
4470 util.formatWithOptions({ colors: true, compact: 3 }, '%s', [
4471 1,
4472 { a: true },
4473 ]),
4474 '[ 1, [Object] ]'
4475 );
4476 
4477 [undefined, null, false, 5n, 5, 'test', Symbol()].forEach(
4478 (invalidOptions) => {
4479 assert.throws(
4480 () => {
4481 util.formatWithOptions(invalidOptions, { a: true });
4482 },
4483 {
4484 code: 'ERR_INVALID_ARG_TYPE',
4485 message: /"inspectOptions".+object/,
4486 }
4487 );
4488 }
4489 );
4490 },
4491};
4492 
4493export const utilInspectError = {
4494 // message/util_inspect_error.js
4495 async test(ctrl, env, ctx) {
4496 const err = new Error('foo\nbar');
4497 
4498 assert.match(
4499 util.inspect({ err, nested: { err } }, { compact: true }),
4500 // eslint-disable-next-line no-regex-spaces
4501 /{ err: Error: foo\n bar\n at .+,\n nested: { err: Error: foo\n bar\n at .+ } }/s
4502 );
4503 assert.match(
4504 util.inspect({ err, nested: { err } }, { compact: false }),
4505 // eslint-disable-next-line no-regex-spaces
4506 /{\n err: Error: foo\n bar\n at .+,\n nested: {\n err: Error: foo\n bar\n at .+\n }\n}/s
4507 );
4508 
4509 err.foo = 'bar';
4510 assert.match(
4511 util.inspect(err, { compact: true, breakLength: 5 }),
4512 // eslint-disable-next-line no-regex-spaces
4513 /{ Error: foo\nbar\n at .+\n foo: 'bar' }/
4514 );
4515 },
4516};
4517 
4518export const logTest = {
4519 test() {
4520 const original = console.log;
4521 console.log = mock.fn();
4522 
4523 util.log('test');
4524 
4525 assert.strictEqual(console.log.mock.callCount(), 1);
4526 const args = console.log.mock.calls[0].arguments;
4527 assert.strictEqual(args.length, 3);
4528 assert.strictEqual(args[0], '%s - %s');
4529 // skipping the check on args[1] since it'll be a timestamp that changes
4530 assert.strictEqual(args[2], 'test');
4531 
4532 console.log = original;
4533 },
4534};
4535 
4536export const aborted = {
4537 async test() {
4538 const signal = AbortSignal.timeout(10);
4539 await util.aborted(signal, {});
4540 
4541 await assert.rejects(util.aborted({}, {}), {
4542 message:
4543 'The "signal" argument must be an instance of AbortSignal. ' +
4544 'Received an instance of Object',
4545 });
4546 },
4547};
4548 
4549export const debuglog = {
4550 test() {
4551 const original = console.log;
4552 console.log = mock.fn();
4553 
4554 util.debuglog('test')('hello');
4555 
4556 assert.strictEqual(console.log.mock.callCount(), 1);
4557 const args = console.log.mock.calls[0].arguments;
4558 assert.strictEqual(args.length, 1);
4559 assert.strictEqual(args[0], 'TEST: hello\n');
4560 
4561 console.log = original;
4562 },
4563};
4564 
4565export const getCallSitesTest = {
4566 test() {
4567 const callSites = util.getCallSites();
4568 assert.strictEqual(callSites.length, 1);
4569 const [stack] = callSites;
4570 assert.strictEqual(stack.functionName, 'test');
4571 assert.strictEqual(stack.scriptName, 'worker');
4572 assert.strictEqual(typeof stack.lineNumber, 'number');
4573 assert.strictEqual(typeof stack.columnNumber, 'number');
4574 assert.strictEqual(typeof stack.column, 'number');
4575 
4576 // We leave this implementation for compat reasons.
4577 // Node.js originally introduced the API with the name `getCallSite()` as an experimental
4578 // API but then renamed it to `getCallSites()` soon after. We had already implemented the
4579 // API with the original name in a release. To avoid the possibility of breaking, we export
4580 // the function using both names.
4581 assert.strictEqual(typeof util.getCallSite, 'function');
4582 },
4583};
4584 
4585export const isDeepStrictEqual = {
4586 // https://github.com/nodejs/node/blob/2be863be08ff9f16eae6bb907388c354c55c3bfc/test/parallel/test-util-isDeepStrictEqual.js
4587 test() {
4588 function utilIsDeepStrict(a, b) {
4589 assert.strictEqual(util.isDeepStrictEqual(a, b), true);
4590 assert.strictEqual(util.isDeepStrictEqual(b, a), true);
4591 }
4592 
4593 function notUtilIsDeepStrict(a, b) {
4594 assert.strictEqual(util.isDeepStrictEqual(a, b), false);
4595 assert.strictEqual(util.isDeepStrictEqual(b, a), false);
4596 }
4597 
4598 // Handle boxed primitives
4599 {
4600 const boxedString = new String('test');
4601 const boxedSymbol = Object(Symbol());
4602 notUtilIsDeepStrict(new Boolean(true), Object(false));
4603 notUtilIsDeepStrict(Object(true), new Number(1));
4604 notUtilIsDeepStrict(new Number(2), new Number(1));
4605 notUtilIsDeepStrict(boxedSymbol, Object(Symbol()));
4606 notUtilIsDeepStrict(boxedSymbol, {});
4607 utilIsDeepStrict(boxedSymbol, boxedSymbol);
4608 utilIsDeepStrict(Object(true), Object(true));
4609 utilIsDeepStrict(Object(2), Object(2));
4610 utilIsDeepStrict(boxedString, Object('test'));
4611 boxedString.slow = true;
4612 notUtilIsDeepStrict(boxedString, Object('test'));
4613 boxedSymbol.slow = true;
4614 notUtilIsDeepStrict(boxedSymbol, {});
4615 utilIsDeepStrict(Object(BigInt(1)), Object(BigInt(1)));
4616 notUtilIsDeepStrict(Object(BigInt(1)), Object(BigInt(2)));
4617 
4618 const booleanish = new Boolean(true);
4619 Object.defineProperty(booleanish, Symbol.toStringTag, {
4620 value: 'String',
4621 });
4622 Object.setPrototypeOf(booleanish, String.prototype);
4623 notUtilIsDeepStrict(booleanish, new String('true'));
4624 
4625 const numberish = new Number(42);
4626 Object.defineProperty(numberish, Symbol.toStringTag, { value: 'String' });
4627 Object.setPrototypeOf(numberish, String.prototype);
4628 notUtilIsDeepStrict(numberish, new String('42'));
4629 
4630 const stringish = new String('0');
4631 Object.defineProperty(stringish, Symbol.toStringTag, { value: 'Number' });
4632 Object.setPrototypeOf(stringish, Number.prototype);
4633 notUtilIsDeepStrict(stringish, new Number(0));
4634 
4635 const bigintish = new Object(BigInt(42));
4636 Object.defineProperty(bigintish, Symbol.toStringTag, { value: 'String' });
4637 Object.setPrototypeOf(bigintish, String.prototype);
4638 notUtilIsDeepStrict(bigintish, new String('42'));
4639 
4640 const symbolish = new Object(Symbol('fhqwhgads'));
4641 Object.defineProperty(symbolish, Symbol.toStringTag, { value: 'String' });
4642 Object.setPrototypeOf(symbolish, String.prototype);
4643 notUtilIsDeepStrict(symbolish, new String('fhqwhgads'));
4644 }
4645 
4646 // Handle symbols (enumerable only)
4647 {
4648 const symbol1 = Symbol();
4649 const obj1 = { [symbol1]: 1 };
4650 const obj2 = { [symbol1]: 1 };
4651 const obj3 = { [Symbol()]: 1 };
4652 const obj4 = {};
4653 // Add a non enumerable symbol as well. It is going to be ignored!
4654 Object.defineProperty(obj2, Symbol(), { value: 1 });
4655 Object.defineProperty(obj4, symbol1, { value: 1 });
4656 notUtilIsDeepStrict(obj1, obj3);
4657 utilIsDeepStrict(obj1, obj2);
4658 notUtilIsDeepStrict(obj1, obj4);
4659 // TypedArrays have a fast path. Test for this as well.
4660 const a = new Uint8Array(4);
4661 const b = new Uint8Array(4);
4662 a[symbol1] = true;
4663 b[symbol1] = false;
4664 notUtilIsDeepStrict(a, b);
4665 b[symbol1] = true;
4666 utilIsDeepStrict(a, b);
4667 // The same as TypedArrays is valid for boxed primitives
4668 const boxedStringA = new String('test');
4669 const boxedStringB = new String('test');
4670 boxedStringA[symbol1] = true;
4671 notUtilIsDeepStrict(boxedStringA, boxedStringB);
4672 boxedStringA[symbol1] = true;
4673 utilIsDeepStrict(a, b);
4674 }
4675 },
4676};
4677 
4678export const isArray = {
4679 test() {
4680 assert.ok(util.isArray([]));
4681 assert.ok(!util.isArray('hello world'));
4682 },
4683};
4684 
4685export const makeSureUtilTypesIsExported = {
4686 async test() {
4687 const types = await import('node:util/types');
4688 assert.ok(types, 'node:util/types is not exported');
4689 assert.ok(types.isTypedArray);
4690 assert.ok(types.default.isTypedArray);
4691 },
4692};
4693 
4694export const testTypes = {
4695 async test() {
4696 const {
4697 isCryptoKey,
4698 isKeyObject,
4699 isAsyncFunction,
4700 isGeneratorFunction,
4701 isGeneratorObject,
4702 isAnyArrayBuffer,
4703 isArrayBuffer,
4704 isArgumentsObject,
4705 isBoxedPrimitive,
4706 isDataView,
4707 isMap,
4708 isMapIterator,
4709 isModuleNamespaceObject,
4710 isNativeError,
4711 isPromise,
4712 isProxy,
4713 isSet,
4714 isSetIterator,
4715 isSharedArrayBuffer,
4716 isWeakMap,
4717 isWeakSet,
4718 isRegExp,
4719 isDate,
4720 isStringObject,
4721 isSymbolObject,
4722 isNumberObject,
4723 isBooleanObject,
4724 isBigIntObject,
4725 isArrayBufferView,
4726 isBigInt64Array,
4727 isBigUint64Array,
4728 isFloat16Array,
4729 isFloat32Array,
4730 isFloat64Array,
4731 isInt8Array,
4732 isInt16Array,
4733 isInt32Array,
4734 isTypedArray,
4735 isUint8Array,
4736 isUint8ClampedArray,
4737 isUint16Array,
4738 isUint32Array,
4739 isExternal,
4740 } = await import('node:util/types');
4741 
4742 {
4743 const key = await crypto.subtle.importKey(
4744 'raw',
4745 new Uint8Array(3),
4746 {
4747 name: 'HMAC',
4748 hash: 'SHA-256',
4749 },
4750 false,
4751 ['sign']
4752 );
4753 assert.ok(isCryptoKey(key));
4754 assert.ok(!isCryptoKey(1));
4755 }
4756 
4757 {
4758 const { createSecretKey } = await import('node:crypto');
4759 const key = createSecretKey('hello', 'utf8');
4760 assert.ok(isKeyObject(key));
4761 assert.ok(!isKeyObject(1));
4762 }
4763 
4764 {
4765 const foo = async () => {};
4766 assert.ok(isAsyncFunction(foo));
4767 assert.ok(!isAsyncFunction(1));
4768 }
4769 
4770 {
4771 function* foo() {}
4772 assert.ok(isGeneratorFunction(foo));
4773 assert.ok(!isGeneratorFunction(1));
4774 }
4775 
4776 {
4777 function* foo() {}
4778 const gen = foo();
4779 assert.ok(isGeneratorObject(gen));
4780 assert.ok(!isGeneratorObject(1));
4781 }
4782 
4783 {
4784 assert.ok(isAnyArrayBuffer(new ArrayBuffer(0)));
4785 assert.ok(isAnyArrayBuffer(new SharedArrayBuffer(0)));
4786 assert.ok(!isAnyArrayBuffer(1));
4787 }
4788 
4789 {
4790 assert.ok(isArrayBuffer(new ArrayBuffer(0)));
4791 assert.ok(!isArrayBuffer(new SharedArrayBuffer(0)));
4792 assert.ok(!isArrayBuffer(1));
4793 }
4794 
4795 {
4796 (function () {
4797 assert.ok(isArgumentsObject(arguments));
4798 assert.ok(!isArgumentsObject(1));
4799 })();
4800 }
4801 
4802 {
4803 assert.ok(isBoxedPrimitive(new String('')));
4804 assert.ok(!isBoxedPrimitive(1));
4805 }
4806 
4807 {
4808 assert.ok(isDataView(new DataView(new ArrayBuffer(1))));
4809 assert.ok(!isDataView(1));
4810 }
4811 
4812 {
4813 assert.ok(isMap(new Map()));
4814 assert.ok(!isMap(1));
4815 }
4816 
4817 {
4818 const map = new Map();
4819 assert.ok(isMapIterator(map.values()));
4820 assert.ok(!isMapIterator(1));
4821 }
4822 
4823 {
4824 const mod = await import('node:net');
4825 assert.ok(isModuleNamespaceObject(mod));
4826 assert.ok(!isModuleNamespaceObject(1));
4827 }
4828 
4829 {
4830 assert.ok(isNativeError(new Error()));
4831 assert.ok(!isNativeError(1));
4832 }
4833 
4834 {
4835 assert.ok(isPromise(Promise.resolve()));
4836 assert.ok(!isPromise(1));
4837 }
4838 
4839 {
4840 assert.ok(isProxy(new Proxy({}, {})));
4841 assert.ok(!isProxy(1));
4842 }
4843 
4844 {
4845 assert.ok(isSet(new Set()));
4846 assert.ok(!isSet(1));
4847 }
4848 
4849 {
4850 const set = new Set();
4851 assert.ok(isSetIterator(set.values()));
4852 assert.ok(!isSetIterator(1));
4853 }
4854 
4855 {
4856 assert.ok(isSharedArrayBuffer(new SharedArrayBuffer(0)));
4857 assert.ok(!isSharedArrayBuffer(new ArrayBuffer(0)));
4858 assert.ok(!isSharedArrayBuffer(1));
4859 }
4860 
4861 {
4862 assert.ok(isWeakMap(new WeakMap()));
4863 assert.ok(!isWeakMap(1));
4864 }
4865 
4866 {
4867 assert.ok(isWeakSet(new WeakSet()));
4868 assert.ok(!isWeakSet(1));
4869 }
4870 
4871 {
4872 assert.ok(isRegExp(/abc/));
4873 assert.ok(!isRegExp(1));
4874 }
4875 
4876 {
4877 assert.ok(isDate(new Date()));
4878 assert.ok(!isDate(1));
4879 }
4880 
4881 {
4882 assert.ok(isStringObject(new String('')));
4883 assert.ok(!isStringObject(''));
4884 }
4885 
4886 {
4887 assert.ok(isSymbolObject(Object(Symbol('test'))));
4888 assert.ok(!isSymbolObject(1));
4889 }
4890 
4891 {
4892 assert.ok(isNumberObject(new Number(1)));
4893 assert.ok(!isNumberObject(1));
4894 }
4895 
4896 {
4897 assert.ok(isBooleanObject(new Boolean()));
4898 assert.ok(!isBooleanObject(1));
4899 }
4900 
4901 {
4902 assert.ok(isBigIntObject(Object(1n)));
4903 assert.ok(!isBigIntObject(1));
4904 }
4905 
4906 {
4907 assert.ok(isArrayBufferView(new Uint8Array(0)));
4908 assert.ok(isArrayBufferView(new DataView(new ArrayBuffer(0))));
4909 assert.ok(!isArrayBufferView(1));
4910 }
4911 
4912 {
4913 assert.ok(isBigInt64Array(new BigInt64Array(0)));
4914 assert.ok(!isBigInt64Array(1));
4915 }
4916 
4917 {
4918 assert.ok(isBigUint64Array(new BigUint64Array(0)));
4919 assert.ok(!isBigUint64Array(1));
4920 }
4921 
4922 {
4923 assert.ok(isFloat16Array(new Float16Array(0)));
4924 assert.ok(!isFloat16Array(1));
4925 }
4926 
4927 {
4928 assert.ok(isFloat32Array(new Float32Array(0)));
4929 assert.ok(!isFloat32Array(1));
4930 }
4931 
4932 {
4933 assert.ok(isFloat64Array(new Float64Array(0)));
4934 assert.ok(!isFloat64Array(1));
4935 }
4936 
4937 {
4938 assert.ok(isInt8Array(new Int8Array(0)));
4939 assert.ok(!isInt8Array(1));
4940 }
4941 
4942 {
4943 assert.ok(isInt16Array(new Int16Array(0)));
4944 assert.ok(!isInt16Array(1));
4945 }
4946 
4947 {
4948 assert.ok(isInt32Array(new Int32Array(0)));
4949 assert.ok(!isInt32Array(1));
4950 }
4951 
4952 {
4953 assert.ok(isTypedArray(new Uint8Array(0)));
4954 assert.ok(!isTypedArray(new DataView(new ArrayBuffer(0))));
4955 assert.ok(!isTypedArray(1));
4956 }
4957 
4958 {
4959 assert.ok(isUint8Array(new Uint8Array(0)));
4960 assert.ok(!isUint8Array(1));
4961 }
4962 
4963 {
4964 assert.ok(isUint8ClampedArray(new Uint8ClampedArray(0)));
4965 assert.ok(!isUint8ClampedArray(new Uint8Array(0)));
4966 assert.ok(!isUint8ClampedArray(1));
4967 }
4968 
4969 {
4970 assert.ok(isUint16Array(new Uint16Array(0)));
4971 assert.ok(!isUint16Array(1));
4972 }
4973 
4974 {
4975 assert.ok(isUint32Array(new Uint32Array(0)));
4976 assert.ok(!isUint32Array(1));
4977 }
4978 
4979 {
4980 // We don't really expose any externals in any existing APIS
4981 // where this would be useful, but hey, let's test it anyway.
4982 assert.ok(!isExternal({}));
4983 }
4984 },
4985};
4986 
4987// https://github.com/nodejs/node/blob/2be863be08ff9f16eae6bb907388c354c55c3bfc/test/parallel/test-util-inspect-getters-accessing-this.js
4988export const testInspectGetters = {
4989 async test() {
4990 // This test ensures that util.inspect logs getters
4991 // which access this.
4992 {
4993 class X {
4994 constructor() {
4995 this._y = 123;
4996 }
4997 
4998 get y() {
4999 return this._y;
5000 }
5001 }
5002 
5003 const result = inspect(new X(), {
5004 getters: true,
5005 showHidden: true,
5006 });
5007 
5008 assert.strictEqual(result, 'X { _y: 123, [y]: [Getter: 123] }');
5009 }
5010 
5011 // Regression test for https://github.com/nodejs/node/issues/37054
5012 {
5013 class A {
5014 constructor(B) {
5015 this.B = B;
5016 }
5017 get b() {
5018 return this.B;
5019 }
5020 }
5021 
5022 class B {
5023 constructor() {
5024 this.A = new A(this);
5025 }
5026 get a() {
5027 return this.A;
5028 }
5029 }
5030 
5031 const result = inspect(new B(), {
5032 depth: 1,
5033 getters: true,
5034 showHidden: true,
5035 });
5036 
5037 assert.strictEqual(
5038 result,
5039 '<ref *1> B {\n' +
5040 ' A: A { B: [Circular *1], [b]: [Getter] [Circular *1] },\n' +
5041 ' [a]: [Getter] A { B: [Circular *1], [b]: [Getter] [Circular *1] }\n' +
5042 '}'
5043 );
5044 }
5045 },
5046};
5047 
5048// https://github.com/nodejs/node/blob/2be863be08ff9f16eae6bb907388c354c55c3bfc/test/parallel/test-util-callbackify.js
5049export const testCallbackify = {
5050 async test() {
5051 const values = [
5052 'hello world',
5053 null,
5054 undefined,
5055 false,
5056 0,
5057 {},
5058 { key: 'value' },
5059 Symbol('I am a symbol'),
5060 function ok() {},
5061 ['array', 'with', 4, 'values'],
5062 new Error('boo'),
5063 ];
5064 
5065 {
5066 // Test that the resolution value is passed as second argument to callback
5067 for (const value of values) {
5068 // Test and `async function`
5069 async function asyncFn() {
5070 return value;
5071 }
5072 
5073 const cbAsyncFn = callbackify(asyncFn);
5074 cbAsyncFn(
5075 commonMustCall(function (err, ret) {
5076 assert.ifError(err);
5077 assert.strictEqual(ret, value);
5078 })
5079 );
5080 
5081 // Test Promise factory
5082 function promiseFn() {
5083 return Promise.resolve(value);
5084 }
5085 
5086 const cbPromiseFn = callbackify(promiseFn);
5087 cbPromiseFn(
5088 commonMustCall(function (err, ret) {
5089 assert.ifError(err);
5090 assert.strictEqual(ret, value);
5091 })
5092 );
5093 
5094 // Test Thenable
5095 function thenableFn() {
5096 return {
5097 then(onRes, onRej) {
5098 onRes(value);
5099 },
5100 };
5101 }
5102 
5103 const cbThenableFn = callbackify(thenableFn);
5104 cbThenableFn(
5105 commonMustCall(function (err, ret) {
5106 assert.ifError(err);
5107 assert.strictEqual(ret, value);
5108 })
5109 );
5110 }
5111 }
5112 
5113 {
5114 // Test that rejection reason is passed as first argument to callback
5115 for (const value of values) {
5116 // Test an `async function`
5117 async function asyncFn() {
5118 return Promise.reject(value);
5119 }
5120 
5121 const cbAsyncFn = callbackify(asyncFn);
5122 assert.strictEqual(cbAsyncFn.length, 1);
5123 assert.strictEqual(cbAsyncFn.name, 'asyncFnCallbackified');
5124 cbAsyncFn(
5125 commonMustCall((err, ret) => {
5126 assert.strictEqual(ret, undefined);
5127 if (err instanceof Error) {
5128 if ('reason' in err) {
5129 assert(!value);
5130 assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
5131 assert.strictEqual(err.reason, value);
5132 } else {
5133 assert.strictEqual(String(value).endsWith(err.message), true);
5134 }
5135 } else {
5136 assert.strictEqual(err, value);
5137 }
5138 })
5139 );
5140 
5141 // Test a Promise factory
5142 function promiseFn() {
5143 return Promise.reject(value);
5144 }
5145 const obj = {};
5146 Object.defineProperty(promiseFn, 'name', {
5147 value: obj,
5148 writable: false,
5149 enumerable: false,
5150 configurable: true,
5151 });
5152 
5153 const cbPromiseFn = callbackify(promiseFn);
5154 assert.strictEqual(promiseFn.name, obj);
5155 cbPromiseFn(
5156 commonMustCall((err, ret) => {
5157 assert.strictEqual(ret, undefined);
5158 if (err instanceof Error) {
5159 if ('reason' in err) {
5160 assert(!value);
5161 assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
5162 assert.strictEqual(err.reason, value);
5163 } else {
5164 assert.strictEqual(String(value).endsWith(err.message), true);
5165 }
5166 } else {
5167 assert.strictEqual(err, value);
5168 }
5169 })
5170 );
5171 
5172 // Test Thenable
5173 function thenableFn() {
5174 return {
5175 then(onRes, onRej) {
5176 onRej(value);
5177 },
5178 };
5179 }
5180 
5181 const cbThenableFn = callbackify(thenableFn);
5182 cbThenableFn(
5183 commonMustCall((err, ret) => {
5184 assert.strictEqual(ret, undefined);
5185 if (err instanceof Error) {
5186 if ('reason' in err) {
5187 assert(!value);
5188 assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
5189 assert.strictEqual(err.reason, value);
5190 } else {
5191 assert.strictEqual(String(value).endsWith(err.message), true);
5192 }
5193 } else {
5194 assert.strictEqual(err, value);
5195 }
5196 })
5197 );
5198 }
5199 }
5200 
5201 await new Promise((resolve) => queueMicrotask(resolve));
5202 
5203 {
5204 // Test that arguments passed to callbackified function are passed to original
5205 for (const value of values) {
5206 async function asyncFn(arg) {
5207 assert.strictEqual(arg, value);
5208 return arg;
5209 }
5210 
5211 const cbAsyncFn = callbackify(asyncFn);
5212 assert.strictEqual(cbAsyncFn.length, 2);
5213 assert.notStrictEqual(
5214 Object.getPrototypeOf(cbAsyncFn),
5215 Object.getPrototypeOf(asyncFn)
5216 );
5217 assert.strictEqual(
5218 Object.getPrototypeOf(cbAsyncFn),
5219 Function.prototype
5220 );
5221 cbAsyncFn(
5222 value,
5223 commonMustCall(function (err, ret) {
5224 assert.ifError(err);
5225 assert.strictEqual(ret, value);
5226 })
5227 );
5228 
5229 function promiseFn(arg) {
5230 assert.strictEqual(arg, value);
5231 return Promise.resolve(arg);
5232 }
5233 const obj = {};
5234 Object.defineProperty(promiseFn, 'length', {
5235 value: obj,
5236 writable: false,
5237 enumerable: false,
5238 configurable: true,
5239 });
5240 
5241 const cbPromiseFn = callbackify(promiseFn);
5242 assert.strictEqual(promiseFn.length, obj);
5243 cbPromiseFn(
5244 value,
5245 commonMustCall(function (err, ret) {
5246 assert.ifError(err);
5247 assert.strictEqual(ret, value);
5248 })
5249 );
5250 }
5251 }
5252 
5253 {
5254 // Test that `this` binding is the same for callbackified and original
5255 for (const value of values) {
5256 const iAmThis = {
5257 fn(arg) {
5258 assert.strictEqual(this, iAmThis);
5259 return Promise.resolve(arg);
5260 },
5261 };
5262 iAmThis.cbFn = callbackify(iAmThis.fn);
5263 iAmThis.cbFn(
5264 value,
5265 commonMustCall(function (err, ret) {
5266 assert.ifError(err);
5267 assert.strictEqual(ret, value);
5268 assert.strictEqual(this, iAmThis);
5269 })
5270 );
5271 
5272 const iAmThat = {
5273 async fn(arg) {
5274 assert.strictEqual(this, iAmThat);
5275 return arg;
5276 },
5277 };
5278 iAmThat.cbFn = callbackify(iAmThat.fn);
5279 iAmThat.cbFn(
5280 value,
5281 commonMustCall(function (err, ret) {
5282 assert.ifError(err);
5283 assert.strictEqual(ret, value);
5284 assert.strictEqual(this, iAmThat);
5285 })
5286 );
5287 }
5288 }
5289 
5290 {
5291 // Verify that non-function inputs throw.
5292 ['foo', null, undefined, false, 0, {}, Symbol(), []].forEach((value) => {
5293 assert.throws(
5294 () => {
5295 callbackify(value);
5296 },
5297 {
5298 code: 'ERR_INVALID_ARG_TYPE',
5299 name: 'TypeError',
5300 message:
5301 'The "original" argument must be of type function.' +
5302 invalidArgTypeHelper(value),
5303 }
5304 );
5305 });
5306 }
5307 
5308 {
5309 async function asyncFn() {
5310 return 42;
5311 }
5312 
5313 const cb = callbackify(asyncFn);
5314 const args = [];
5315 
5316 // Verify that the last argument to the callbackified function is a function.
5317 ['foo', null, undefined, false, 0, {}, Symbol(), []].forEach((value) => {
5318 args.push(value);
5319 assert.throws(
5320 () => {
5321 cb(...args);
5322 },
5323 {
5324 code: 'ERR_INVALID_ARG_TYPE',
5325 name: 'TypeError',
5326 message:
5327 'The last argument must be of type function.' +
5328 invalidArgTypeHelper(value),
5329 }
5330 );
5331 });
5332 }
5333 
5334 {
5335 // Test Promise factory
5336 function promiseFn(value) {
5337 return Promise.reject(value);
5338 }
5339 
5340 const cbPromiseFn = callbackify(promiseFn);
5341 
5342 cbPromiseFn(null, (err) => {
5343 assert.strictEqual(
5344 err.message,
5345 'Promise was rejected with falsy value'
5346 );
5347 assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
5348 assert.strictEqual(err.reason, null);
5349 // const stack = err.stack.split(/[\r\n]+/);
5350 // assert.match(stack[1], /at process\.processTicksAndRejections/);
5351 });
5352 }
5353 
5354 await new Promise((resolve) => queueMicrotask(resolve));
5355 
5356 assertCalledMustCalls();
5357 },
5358};
5359 
5360// https://github.com/nodejs/node/blob/2be863be08ff9f16eae6bb907388c354c55c3bfc/test/parallel/test-util-inherits.js
5361export const testInherits = {
5362 async test() {
5363 // Super constructor
5364 function A() {
5365 this._a = 'a';
5366 }
5367 A.prototype.a = function () {
5368 return this._a;
5369 };
5370 
5371 // One level of inheritance
5372 function B(value) {
5373 A.call(this);
5374 this._b = value;
5375 }
5376 inherits(B, A);
5377 B.prototype.b = function () {
5378 return this._b;
5379 };
5380 
5381 assert.deepStrictEqual(Object.getOwnPropertyDescriptor(B, 'super_'), {
5382 value: A,
5383 enumerable: false,
5384 configurable: true,
5385 writable: true,
5386 });
5387 
5388 const b = new B('b');
5389 assert.strictEqual(b.a(), 'a');
5390 assert.strictEqual(b.b(), 'b');
5391 assert.strictEqual(b.constructor, B);
5392 
5393 // Two levels of inheritance
5394 function C() {
5395 B.call(this, 'b');
5396 this._c = 'c';
5397 }
5398 inherits(C, B);
5399 C.prototype.c = function () {
5400 return this._c;
5401 };
5402 C.prototype.getValue = function () {
5403 return this.a() + this.b() + this.c();
5404 };
5405 
5406 assert.strictEqual(C.super_, B);
5407 
5408 const c = new C();
5409 assert.strictEqual(c.getValue(), 'abc');
5410 assert.strictEqual(c.constructor, C);
5411 
5412 // Inherits can be called after setting prototype properties
5413 function D() {
5414 C.call(this);
5415 this._d = 'd';
5416 }
5417 
5418 D.prototype.d = function () {
5419 return this._d;
5420 };
5421 inherits(D, C);
5422 
5423 assert.strictEqual(D.super_, C);
5424 
5425 const d = new D();
5426 assert.strictEqual(d.c(), 'c');
5427 assert.strictEqual(d.d(), 'd');
5428 assert.strictEqual(d.constructor, D);
5429 
5430 // ES6 classes can inherit from a constructor function
5431 class E {
5432 constructor() {
5433 D.call(this);
5434 this._e = 'e';
5435 }
5436 e() {
5437 return this._e;
5438 }
5439 }
5440 inherits(E, D);
5441 
5442 assert.strictEqual(E.super_, D);
5443 
5444 const e = new E();
5445 assert.strictEqual(e.getValue(), 'abc');
5446 assert.strictEqual(e.d(), 'd');
5447 assert.strictEqual(e.e(), 'e');
5448 assert.strictEqual(e.constructor, E);
5449 
5450 // Should throw with invalid arguments
5451 assert.throws(
5452 () => {
5453 inherits(A, {});
5454 },
5455 {
5456 code: 'ERR_INVALID_ARG_TYPE',
5457 name: 'TypeError',
5458 message:
5459 'The "superCtor.prototype" property must be of type object. ' +
5460 'Received undefined',
5461 }
5462 );
5463 
5464 assert.throws(
5465 () => {
5466 inherits(A, null);
5467 },
5468 {
5469 code: 'ERR_INVALID_ARG_TYPE',
5470 name: 'TypeError',
5471 message:
5472 'The "superCtor" argument must be of type function. ' +
5473 'Received null',
5474 }
5475 );
5476 
5477 assert.throws(
5478 () => {
5479 inherits(null, A);
5480 },
5481 {
5482 code: 'ERR_INVALID_ARG_TYPE',
5483 name: 'TypeError',
5484 message: 'The "ctor" argument must be of type function. Received null',
5485 }
5486 );
5487 },
5488};
5489 
5490// https://github.com/nodejs/node/blob/2be863be08ff9f16eae6bb907388c354c55c3bfc/test/parallel/test-util-promisify.js
5491export const testPromisify = {
5492 async test() {
5493 // TODO(soon): Enable once fs supported
5494 // const stat = promisify(fs.stat);
5495 
5496 // {
5497 // const promise = stat(__filename);
5498 // assert(promise instanceof Promise);
5499 // promise.then(mustCall((value) => {
5500 // assert.deepStrictEqual(value, fs.statSync(__filename));
5501 // }));
5502 // }
5503 
5504 // {
5505 // const promise = stat('/dontexist');
5506 // promise.catch(mustCall((error) => {
5507 // assert(error.message.includes('ENOENT: no such file or directory, stat'));
5508 // }));
5509 // }
5510 
5511 {
5512 function fn() {}
5513 
5514 function promisifedFn() {}
5515 fn[promisify.custom] = promisifedFn;
5516 assert.strictEqual(promisify(fn), promisifedFn);
5517 assert.strictEqual(promisify(promisify(fn)), promisifedFn);
5518 }
5519 
5520 {
5521 function fn() {}
5522 
5523 function promisifiedFn() {}
5524 
5525 // util.promisify.custom is a shared symbol which can be accessed
5526 // as `Symbol.for("nodejs.util.promisify.custom")`.
5527 const kCustomPromisifiedSymbol = Symbol.for(
5528 'nodejs.util.promisify.custom'
5529 );
5530 fn[kCustomPromisifiedSymbol] = promisifiedFn;
5531 
5532 assert.strictEqual(kCustomPromisifiedSymbol, promisify.custom);
5533 assert.strictEqual(promisify(fn), promisifiedFn);
5534 assert.strictEqual(promisify(promisify(fn)), promisifiedFn);
5535 }
5536 
5537 {
5538 function fn() {}
5539 fn[promisify.custom] = 42;
5540 assert.throws(() => promisify(fn), {
5541 code: 'ERR_INVALID_ARG_TYPE',
5542 name: 'TypeError',
5543 });
5544 }
5545 
5546 // TODO(soon): customPromisifyArgs unsupported
5547 // {
5548 // const firstValue = 5;
5549 // const secondValue = 17;
5550 
5551 // function fn(callback) {
5552 // callback(null, firstValue, secondValue);
5553 // }
5554 
5555 // fn[customPromisifyArgs] = ['first', 'second'];
5556 
5557 // promisify(fn)().then(mustCall((obj) => {
5558 // assert.deepStrictEqual(obj, { first: firstValue, second: secondValue });
5559 // }));
5560 // }
5561 
5562 // vm unsupported
5563 // {
5564 // const fn = vm.runInNewContext('(function() {})');
5565 // assert.notStrictEqual(Object.getPrototypeOf(promisify(fn)),
5566 // Function.prototype);
5567 // }
5568 
5569 {
5570 function fn(callback) {
5571 callback(null, 'foo', 'bar');
5572 }
5573 promisify(fn)().then(
5574 commonMustCall((value) => {
5575 assert.strictEqual(value, 'foo');
5576 })
5577 );
5578 }
5579 
5580 {
5581 function fn(callback) {
5582 callback(null);
5583 }
5584 promisify(fn)().then(
5585 commonMustCall((value) => {
5586 assert.strictEqual(value, undefined);
5587 })
5588 );
5589 }
5590 
5591 {
5592 function fn(callback) {
5593 callback();
5594 }
5595 promisify(fn)().then(
5596 commonMustCall((value) => {
5597 assert.strictEqual(value, undefined);
5598 })
5599 );
5600 }
5601 
5602 {
5603 function fn(err, val, callback) {
5604 callback(err, val);
5605 }
5606 promisify(fn)(null, 42).then(
5607 commonMustCall((value) => {
5608 assert.strictEqual(value, 42);
5609 })
5610 );
5611 }
5612 
5613 {
5614 function fn(err, val, callback) {
5615 callback(err, val);
5616 }
5617 promisify(fn)(new Error('oops'), null).catch(
5618 commonMustCall((err) => {
5619 assert.strictEqual(err.message, 'oops');
5620 })
5621 );
5622 }
5623 
5624 {
5625 function fn(err, val, callback) {
5626 callback(err, val);
5627 }
5628 
5629 (async () => {
5630 const value = await promisify(fn)(null, 42);
5631 assert.strictEqual(value, 42);
5632 })().then(commonMustCall());
5633 }
5634 
5635 {
5636 const o = {};
5637 const fn = promisify(function (cb) {
5638 cb(null, this === o);
5639 });
5640 
5641 o.fn = fn;
5642 
5643 o.fn().then(commonMustCall((val) => assert(val)));
5644 }
5645 
5646 {
5647 const err = new Error(
5648 'Should not have called the callback with the error.'
5649 );
5650 const stack = err.stack;
5651 
5652 const fn = promisify(function (cb) {
5653 cb(null);
5654 cb(err);
5655 });
5656 
5657 (async () => {
5658 await fn();
5659 await Promise.resolve();
5660 return assert.strictEqual(stack, err.stack);
5661 })().then(commonMustCall());
5662 }
5663 
5664 {
5665 function c() {}
5666 const a = promisify(function () {});
5667 const b = promisify(a);
5668 assert.notStrictEqual(c, a);
5669 assert.strictEqual(a, b);
5670 }
5671 
5672 {
5673 let errToThrow;
5674 const thrower = promisify(function (a, b, c, cb) {
5675 errToThrow = new Error();
5676 throw errToThrow;
5677 });
5678 thrower(1, 2, 3)
5679 .then(assert.fail)
5680 .then(assert.fail, (e) => assert.strictEqual(e, errToThrow));
5681 }
5682 
5683 {
5684 const err = new Error();
5685 
5686 const a = promisify((cb) => cb(err))();
5687 const b = promisify(() => {
5688 throw err;
5689 })();
5690 
5691 await Promise.all([
5692 a.then(assert.fail, function (e) {
5693 assert.strictEqual(err, e);
5694 }),
5695 b.then(assert.fail, function (e) {
5696 assert.strictEqual(err, e);
5697 }),
5698 ]);
5699 }
5700 
5701 [undefined, null, true, 0, 'str', {}, [], Symbol()].forEach((input) => {
5702 assert.throws(() => promisify(input), {
5703 code: 'ERR_INVALID_ARG_TYPE',
5704 name: 'TypeError',
5705 message:
5706 'The "original" argument must be of type function.' +
5707 invalidArgTypeHelper(input),
5708 });
5709 });
5710 },
5711};
5712 
5713// https://github.com/nodejs/node/blob/2be863be08ff9f16eae6bb907388c354c55c3bfc/test/parallel/test-util-stripvtcontrolcharacters.js
5714export const testStripVtControlCharacters = {
5715 async test() {
5716 // Ref: https://github.com/chalk/ansi-regex/blob/main/test.js
5717 const tests = [
5718 // [before, expected]
5719 [
5720 '\u001B[0m\u001B[4m\u001B[42m\u001B[31mfoo\u001B[39m\u001B[49m\u001B[24mfoo\u001B[0m',
5721 'foofoo',
5722 ], // Basic ANSI
5723 ['\u001B[0;33;49;3;9;4mbar\u001B[0m', 'bar'], // Advanced colors
5724 ['foo\u001B[0gbar', 'foobar'], // Clear tabs
5725 ['foo\u001B[Kbar', 'foobar'], // Clear line
5726 ['foo\u001B[2Jbar', 'foobar'], // Clear screen
5727 ];
5728 
5729 for (const ST of ['\u0007', '\u001B\u005C', '\u009C']) {
5730 tests.push(
5731 [`\u001B]8;;mailto:no-replay@mail.com${ST}mail\u001B]8;;${ST}`, 'mail'],
5732 [
5733 `\u001B]8;k=v;https://example-a.com/?a_b=1&c=2#tit%20le${ST}click\u001B]8;;${ST}`,
5734 'click',
5735 ]
5736 );
5737 }
5738 
5739 for (const [before, expected] of tests) {
5740 assert.strictEqual(stripVTControlCharacters(before), expected);
5741 }
5742 },
5743};
5744 
5745export const testStyleText = {
5746 async test() {
5747 const styled = '\u001b[31mtest\u001b[39m';
5748 const _noChange = 'test';
5749 
5750 [undefined, null, false, 5n, 5, Symbol(), () => {}, {}].forEach(
5751 (invalidOption) => {
5752 assert.throws(
5753 () => {
5754 styleText(invalidOption, 'test');
5755 },
5756 {
5757 code: 'ERR_INVALID_ARG_VALUE',
5758 }
5759 );
5760 assert.throws(
5761 () => {
5762 styleText('red', invalidOption);
5763 },
5764 {
5765 code: 'ERR_INVALID_ARG_TYPE',
5766 }
5767 );
5768 }
5769 );
5770 
5771 assert.throws(
5772 () => {
5773 styleText('invalid', 'text');
5774 },
5775 {
5776 code: 'ERR_INVALID_ARG_VALUE',
5777 }
5778 );
5779 
5780 assert.strictEqual(
5781 styleText('red', 'test', { validateStream: false }),
5782 '\u001b[31mtest\u001b[39m'
5783 );
5784 
5785 assert.strictEqual(
5786 styleText(['bold', 'red'], 'test', { validateStream: false }),
5787 '\u001b[1m\u001b[31mtest\u001b[39m\u001b[22m'
5788 );
5789 
5790 assert.strictEqual(
5791 styleText(['bold', 'red'], 'test', { validateStream: false }),
5792 styleText('bold', styleText('red', 'test', { validateStream: false }), {
5793 validateStream: false,
5794 })
5795 );
5796 
5797 assert.throws(
5798 () => {
5799 styleText(['invalid'], 'text');
5800 },
5801 {
5802 code: 'ERR_INVALID_ARG_VALUE',
5803 }
5804 );
5805 
5806 assert.throws(
5807 () => {
5808 styleText('red', 'text', { stream: {} });
5809 },
5810 {
5811 code: 'ERR_INVALID_ARG_TYPE',
5812 }
5813 );
5814 
5815 // does not throw
5816 styleText('red', 'text', { stream: {}, validateStream: false });
5817 
5818 assert.strictEqual(
5819 styleText('red', 'test', { validateStream: false }),
5820 styled
5821 );
5822 
5823 assert.strictEqual(styleText('none', 'test'), 'test');
5824 },
5825};
5826 
5827const validContent = `BASIC=basic
5828
5829# COMMENTS=work
5830#BASIC=basic2
5831#BASIC=basic3
5832
5833# previous line intentionally left blank
5834AFTER_LINE=after_line
5835A="B=C"
5836B=C=D
5837EMPTY=
5838EMPTY_SINGLE_QUOTES=''
5839EMPTY_DOUBLE_QUOTES=""
5840EMPTY_BACKTICKS=\`\`
5841SINGLE_QUOTES='single_quotes'
5842SINGLE_QUOTES_SPACED=' single quotes '
5843DOUBLE_QUOTES="double_quotes"
5844DOUBLE_QUOTES_SPACED=" double quotes "
5845DOUBLE_QUOTES_INSIDE_SINGLE='double "quotes" work inside single quotes'
5846DOUBLE_QUOTES_WITH_NO_SPACE_BRACKET="{ port: $MONGOLAB_PORT}"
5847SINGLE_QUOTES_INSIDE_DOUBLE="single 'quotes' work inside double quotes"
5848BACKTICKS_INSIDE_SINGLE='\`backticks\` work inside single quotes'
5849BACKTICKS_INSIDE_DOUBLE="\`backticks\` work inside double quotes"
5850BACKTICKS=\`backticks\`
5851BACKTICKS_SPACED=\` backticks \`
5852DOUBLE_QUOTES_INSIDE_BACKTICKS=\`double "quotes" work inside backticks\`
5853SINGLE_QUOTES_INSIDE_BACKTICKS=\`single 'quotes' work inside backticks\`
5854DOUBLE_AND_SINGLE_QUOTES_INSIDE_BACKTICKS=\`double "quotes" and single 'quotes' work inside backticks\`
5855EXPAND_NEWLINES="expand\\nnew\\nlines"
5856DONT_EXPAND_UNQUOTED=dontexpand\\nnewlines
5857DONT_EXPAND_SQUOTED='dontexpand\\nnewlines'
5858# COMMENTS=work
5859INLINE_COMMENTS=inline comments # work #very #well
5860INLINE_COMMENTS_SINGLE_QUOTES='inline comments outside of #singlequotes' # work
5861INLINE_COMMENTS_DOUBLE_QUOTES="inline comments outside of #doublequotes" # work
5862INLINE_COMMENTS_BACKTICKS=\`inline comments outside of #backticks\` # work
5863INLINE_COMMENTS_SPACE=inline comments start with a#number sign. no space required.
5864EQUAL_SIGNS=equals==
5865RETAIN_INNER_QUOTES={"foo": "bar"}
5866RETAIN_INNER_QUOTES_AS_STRING='{"foo": "bar"}'
5867RETAIN_INNER_QUOTES_AS_BACKTICKS=\`{"foo": "bar's"}\`
5868TRIM_SPACE_FROM_UNQUOTED= some spaced out string
5869SPACE_BEFORE_DOUBLE_QUOTES= "space before double quotes"
5870EMAIL=therealnerdybeast@example.tld
5871 SPACED_KEY = parsed
5872EDGE_CASE_INLINE_COMMENTS="VALUE1" # or "VALUE2" or "VALUE3"
5873
5874MULTI_DOUBLE_QUOTED="THIS
5875IS
5876A
5877MULTILINE
5878STRING"
5879
5880MULTI_SINGLE_QUOTED='THIS
5881IS
5882A
5883MULTILINE
5884STRING'
5885
5886MULTI_BACKTICKED=\`THIS
5887IS
5888A
5889"MULTILINE'S"
5890STRING\`
5891export EXPORT_EXAMPLE = ignore export
5892
5893MULTI_NOT_VALID_QUOTE="
5894MULTI_NOT_VALID=THIS
5895IS NOT MULTILINE`;
5896 
5897export const testParseEnv = {
5898 async test() {
5899 {
5900 assert.deepStrictEqual(parseEnv(validContent), {
5901 A: 'B=C',
5902 B: 'C=D',
5903 AFTER_LINE: 'after_line',
5904 BACKTICKS: 'backticks',
5905 BACKTICKS_INSIDE_DOUBLE: '`backticks` work inside double quotes',
5906 BACKTICKS_INSIDE_SINGLE: '`backticks` work inside single quotes',
5907 BACKTICKS_SPACED: ' backticks ',
5908 BASIC: 'basic',
5909 DONT_EXPAND_SQUOTED: 'dontexpand\\nnewlines',
5910 DONT_EXPAND_UNQUOTED: 'dontexpand\\nnewlines',
5911 DOUBLE_AND_SINGLE_QUOTES_INSIDE_BACKTICKS:
5912 'double "quotes" and single \'quotes\' work inside backticks',
5913 DOUBLE_QUOTES: 'double_quotes',
5914 DOUBLE_QUOTES_INSIDE_BACKTICKS: 'double "quotes" work inside backticks',
5915 DOUBLE_QUOTES_INSIDE_SINGLE:
5916 'double "quotes" work inside single quotes',
5917 DOUBLE_QUOTES_SPACED: ' double quotes ',
5918 DOUBLE_QUOTES_WITH_NO_SPACE_BRACKET: '{ port: $MONGOLAB_PORT}',
5919 EDGE_CASE_INLINE_COMMENTS: 'VALUE1',
5920 EMAIL: 'therealnerdybeast@example.tld',
5921 EMPTY: '',
5922 EMPTY_BACKTICKS: '',
5923 EMPTY_DOUBLE_QUOTES: '',
5924 EMPTY_SINGLE_QUOTES: '',
5925 EQUAL_SIGNS: 'equals==',
5926 EXPORT_EXAMPLE: 'ignore export',
5927 EXPAND_NEWLINES: 'expand\nnew\nlines',
5928 INLINE_COMMENTS: 'inline comments',
5929 INLINE_COMMENTS_BACKTICKS: 'inline comments outside of #backticks',
5930 INLINE_COMMENTS_DOUBLE_QUOTES:
5931 'inline comments outside of #doublequotes',
5932 INLINE_COMMENTS_SINGLE_QUOTES:
5933 'inline comments outside of #singlequotes',
5934 INLINE_COMMENTS_SPACE: 'inline comments start with a',
5935 MULTI_BACKTICKED: 'THIS\nIS\nA\n"MULTILINE\'S"\nSTRING',
5936 MULTI_DOUBLE_QUOTED: 'THIS\nIS\nA\nMULTILINE\nSTRING',
5937 MULTI_NOT_VALID: 'THIS',
5938 MULTI_NOT_VALID_QUOTE: '"',
5939 MULTI_SINGLE_QUOTED: 'THIS\nIS\nA\nMULTILINE\nSTRING',
5940 RETAIN_INNER_QUOTES: '{"foo": "bar"}',
5941 RETAIN_INNER_QUOTES_AS_BACKTICKS: '{"foo": "bar\'s"}',
5942 RETAIN_INNER_QUOTES_AS_STRING: '{"foo": "bar"}',
5943 SINGLE_QUOTES: 'single_quotes',
5944 SINGLE_QUOTES_INSIDE_BACKTICKS: "single 'quotes' work inside backticks",
5945 SINGLE_QUOTES_INSIDE_DOUBLE:
5946 "single 'quotes' work inside double quotes",
5947 SINGLE_QUOTES_SPACED: ' single quotes ',
5948 SPACED_KEY: 'parsed',
5949 SPACE_BEFORE_DOUBLE_QUOTES: 'space before double quotes',
5950 TRIM_SPACE_FROM_UNQUOTED: 'some spaced out string',
5951 });
5952 }
5953 
5954 assert.deepStrictEqual(parseEnv(''), {});
5955 assert.deepStrictEqual(parseEnv('FOO=bar\nFOO=baz\n'), { FOO: 'baz' });
5956 
5957 // Test for invalid input.
5958 assert.throws(
5959 () => {
5960 for (const value of [null, undefined, {}, []]) {
5961 parseEnv(value);
5962 }
5963 },
5964 {
5965 code: 'ERR_INVALID_ARG_TYPE',
5966 }
5967 );
5968 },
5969};
5970 
5971export const testNotImplemented = {
5972 async test() {
5973 for (const method of ['_errnoException', '_exceptionWithHostPort']) {
5974 assert.throws(() => util[method](), {
5975 code: 'ERR_METHOD_NOT_IMPLEMENTED',
5976 });
5977 }
5978 },
5979};
5980 
5981export const testEndOfLife = {
5982 async test() {
5983 assert.strictEqual(typeof util.isArray, 'function');
5984 assert.strictEqual(typeof util.isBoolean, 'function');
5985 assert.strictEqual(typeof util.isBuffer, 'function');
5986 assert.strictEqual(typeof util.isDate, 'function');
5987 assert.strictEqual(typeof util.isError, 'function');
5988 assert.strictEqual(typeof util.isFunction, 'function');
5989 assert.strictEqual(typeof util.isNull, 'function');
5990 assert.strictEqual(typeof util.isNullOrUndefined, 'function');
5991 assert.strictEqual(typeof util.isNumber, 'function');
5992 assert.strictEqual(typeof util.isObject, 'function');
5993 assert.strictEqual(typeof util.isPrimitive, 'function');
5994 assert.strictEqual(typeof util.isRegExp, 'function');
5995 assert.strictEqual(typeof util.isString, 'function');
5996 assert.strictEqual(typeof util.isSymbol, 'function');
5997 assert.strictEqual(typeof util.isUndefined, 'function');
5998 
5999 assert.strictEqual(util.isBuffer(true), false);
6000 },
6001};