@gjsify/util 0.3.21 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts DELETED
@@ -1,747 +0,0 @@
1
- // Reference: Node.js lib/util.js
2
- // Reimplemented for GJS
3
-
4
- import type { InspectOptions } from 'node:util';
5
-
6
- import * as types from './types.js';
7
- import { getSystemErrorName, getSystemErrorMap } from './errors.js';
8
-
9
- export { types };
10
- export { getSystemErrorName, getSystemErrorMap };
11
-
12
- // ---- inspect ----
13
-
14
- const kCustomInspect = Symbol.for('nodejs.util.inspect.custom');
15
-
16
- function inspectValue(value: unknown, opts: InspectOptions, depth: number): string {
17
- if (value === null) return opts.colors ? '\x1b[1mnull\x1b[22m' : 'null';
18
- if (value === undefined) return opts.colors ? '\x1b[90mundefined\x1b[39m' : 'undefined';
19
-
20
- const maxDepth = opts.depth ?? 2;
21
-
22
- if (typeof value === 'string') {
23
- const escaped = value.replace(/\\/g, '\\\\');
24
- // Smart quoting: use double quotes if string contains single quote but no double quote
25
- if (value.includes("'") && !value.includes('"')) {
26
- const dq = escaped.replace(/"/g, '\\"');
27
- return opts.colors ? `\x1b[32m"${dq}"\x1b[39m` : `"${dq}"`;
28
- }
29
- const sq = escaped.replace(/'/g, "\\'");
30
- return opts.colors ? `\x1b[32m'${sq}'\x1b[39m` : `'${sq}'`;
31
- }
32
- if (typeof value === 'number') {
33
- return opts.colors ? `\x1b[33m${value}\x1b[39m` : String(value);
34
- }
35
- if (typeof value === 'bigint') {
36
- return opts.colors ? `\x1b[33m${value}n\x1b[39m` : `${value}n`;
37
- }
38
- if (typeof value === 'boolean') {
39
- return opts.colors ? `\x1b[33m${value}\x1b[39m` : String(value);
40
- }
41
- if (typeof value === 'symbol') {
42
- return opts.colors ? `\x1b[32m${value.toString()}\x1b[39m` : value.toString();
43
- }
44
- if (typeof value === 'function') {
45
- const name = value.name ? `: ${value.name}` : '';
46
- return opts.colors ? `\x1b[36m[Function${name}]\x1b[39m` : `[Function${name}]`;
47
- }
48
-
49
- // Custom inspect
50
- if (value !== null && typeof value === 'object' && kCustomInspect in (value as Record<symbol, unknown>)) {
51
- const custom = (value as Record<symbol, unknown>)[kCustomInspect];
52
- if (typeof custom === 'function') {
53
- const result = custom.call(value, depth, opts);
54
- if (typeof result === 'string') return result;
55
- return inspectValue(result, opts, depth);
56
- }
57
- }
58
-
59
- if (value instanceof Date) {
60
- return value.toISOString();
61
- }
62
- if (value instanceof RegExp) {
63
- return opts.colors ? `\x1b[31m${value.toString()}\x1b[39m` : value.toString();
64
- }
65
- if (value instanceof Error) {
66
- return value.stack || value.toString();
67
- }
68
-
69
- if (depth > maxDepth) {
70
- return Array.isArray(value) ? '[Array]' : '[Object]';
71
- }
72
-
73
- if (Array.isArray(value)) {
74
- return inspectArray(value, opts, depth);
75
- }
76
-
77
- if (value instanceof Map) {
78
- const entries = [...value.entries()].map(([k, v]) =>
79
- `${inspectValue(k, opts, depth + 1)} => ${inspectValue(v, opts, depth + 1)}`
80
- );
81
- return `Map(${value.size}) { ${entries.join(', ')} }`;
82
- }
83
-
84
- if (value instanceof Set) {
85
- const entries = [...value].map(v => inspectValue(v, opts, depth + 1));
86
- return `Set(${value.size}) { ${entries.join(', ')} }`;
87
- }
88
-
89
- if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
90
- const name = value.constructor?.name || 'TypedArray';
91
- const arr = Array.from(value as Uint8Array);
92
- return `${name}(${arr.length}) [ ${arr.join(', ')} ]`;
93
- }
94
-
95
- return inspectObject(value as Record<string, unknown>, opts, depth);
96
- }
97
-
98
- function inspectArray(arr: unknown[], opts: InspectOptions, depth: number): string {
99
- const maxLen = opts.maxArrayLength ?? 100;
100
- const len = Math.min(arr.length, maxLen);
101
- const items: string[] = [];
102
- for (let i = 0; i < len; i++) {
103
- items.push(inspectValue(arr[i], opts, depth + 1));
104
- }
105
- if (arr.length > maxLen) {
106
- items.push(`... ${arr.length - maxLen} more items`);
107
- }
108
-
109
- // Show hidden properties like [length] when showHidden is true
110
- if (opts.showHidden) {
111
- items.push(`[length]: ${arr.length}`);
112
- }
113
-
114
- const breakLength = opts.breakLength ?? 72;
115
- const compact = opts.compact ?? 3;
116
-
117
- // Compact grouping: when array has more elements than compact threshold,
118
- // use grouped multiline format (multiple items per line)
119
- if (typeof compact === 'number' && compact > 0 && arr.length > compact) {
120
- const indent = ' ';
121
- const indentLen = indent.length;
122
- // Calculate max item length (strip ANSI for measurement)
123
- const stripAnsi = (s: string) => s.replace(/\x1b\[[0-9;]*m/g, '');
124
- const maxItemLen = Math.max(...items.map(item => stripAnsi(item).length));
125
- const biasedMax = Math.max(maxItemLen - 2, 1);
126
- const numItems = items.length;
127
- const approxCharHeights = 2.5;
128
- const columns = Math.min(
129
- Math.round(Math.sqrt(approxCharHeights * biasedMax * numItems) / biasedMax),
130
- Math.floor((breakLength - indentLen) / biasedMax),
131
- Math.floor((2.5 + numItems - 1) / 2),
132
- 15
133
- );
134
- if (columns > 1) {
135
- const rows: string[] = [];
136
- for (let i = 0; i < numItems; i += columns) {
137
- rows.push(indent + items.slice(i, Math.min(i + columns, numItems)).join(', '));
138
- }
139
- return `[\n${rows.join(',\n')}\n]`;
140
- }
141
- }
142
-
143
- const singleLine = `[ ${items.join(', ')} ]`;
144
- if (singleLine.length <= breakLength) return singleLine;
145
-
146
- return `[\n${items.map(i => ' ' + i).join(',\n')}\n]`;
147
- }
148
-
149
- function inspectObject(obj: Record<string, unknown>, opts: InspectOptions, depth: number): string {
150
- const keys = opts.showHidden
151
- ? Object.getOwnPropertyNames(obj)
152
- : Object.keys(obj);
153
-
154
- if (opts.sorted) keys.sort();
155
-
156
- if (keys.length === 0) {
157
- const tag = Object.prototype.toString.call(obj);
158
- if (tag !== '[object Object]') return tag;
159
- return '{}';
160
- }
161
-
162
- const items = keys.map(key => {
163
- const val = inspectValue(obj[key], opts, depth + 1);
164
- return `${key}: ${val}`;
165
- });
166
-
167
- const breakLength = opts.breakLength ?? 72;
168
- const singleLine = `{ ${items.join(', ')} }`;
169
- if (singleLine.length <= breakLength) return singleLine;
170
-
171
- return `{\n${items.map(i => ' ' + i).join(',\n')}\n}`;
172
- }
173
-
174
- export function inspect(value: unknown, opts?: boolean | InspectOptions): string {
175
- const options: InspectOptions = typeof opts === 'boolean'
176
- ? { showHidden: opts }
177
- : { ...opts };
178
-
179
- if (options.colors === undefined) options.colors = false;
180
- return inspectValue(value, options, 0);
181
- }
182
-
183
- inspect.custom = kCustomInspect;
184
- inspect.defaultOptions = {
185
- showHidden: false,
186
- depth: 2,
187
- colors: false,
188
- maxArrayLength: 100,
189
- maxStringLength: 10000,
190
- breakLength: 72,
191
- compact: 3,
192
- sorted: false,
193
- };
194
-
195
- /** ANSI color code pairs [open, close] for terminal coloring. */
196
- inspect.colors = {
197
- reset: [0, 0],
198
- bold: [1, 22],
199
- dim: [2, 22],
200
- italic: [3, 23],
201
- underline: [4, 24],
202
- blink: [5, 25],
203
- inverse: [7, 27],
204
- hidden: [8, 28],
205
- strikethrough: [9, 29],
206
- doubleunderline: [21, 24],
207
- black: [30, 39],
208
- red: [31, 39],
209
- green: [32, 39],
210
- yellow: [33, 39],
211
- blue: [34, 39],
212
- magenta: [35, 39],
213
- cyan: [36, 39],
214
- white: [37, 39],
215
- bgBlack: [40, 49],
216
- bgRed: [41, 49],
217
- bgGreen: [42, 49],
218
- bgYellow: [43, 49],
219
- bgBlue: [44, 49],
220
- bgMagenta: [45, 49],
221
- bgCyan: [46, 49],
222
- bgWhite: [47, 49],
223
- framed: [51, 54],
224
- overlined: [53, 55],
225
- gray: [90, 39],
226
- grey: [90, 39],
227
- redBright: [91, 39],
228
- greenBright: [92, 39],
229
- yellowBright: [93, 39],
230
- blueBright: [94, 39],
231
- magentaBright: [95, 39],
232
- cyanBright: [96, 39],
233
- whiteBright: [97, 39],
234
- bgBlackBright: [100, 49],
235
- bgRedBright: [101, 49],
236
- bgGreenBright: [102, 49],
237
- bgYellowBright: [103, 49],
238
- bgBlueBright: [104, 49],
239
- bgMagentaBright: [105, 49],
240
- bgCyanBright: [106, 49],
241
- bgWhiteBright: [107, 49],
242
- } as Record<string, [number, number]>;
243
-
244
- /** Maps type names to color names for util.inspect output styling. */
245
- inspect.styles = {
246
- special: 'cyan',
247
- number: 'yellow',
248
- bigint: 'yellow',
249
- boolean: 'yellow',
250
- undefined: 'grey',
251
- null: 'bold',
252
- string: 'green',
253
- symbol: 'green',
254
- date: 'magenta',
255
- regexp: 'red',
256
- module: 'underline',
257
- } as Record<string, string>;
258
-
259
- // ---- format ----
260
-
261
- export function format(fmt: string, ...args: unknown[]): string {
262
- // format() with no args returns ''
263
- if (fmt === undefined && args.length === 0) return '';
264
-
265
- if (typeof fmt !== 'string') {
266
- if (args.length === 0) return inspect(fmt);
267
- const parts = [inspect(fmt)];
268
- for (const arg of args) parts.push(inspect(arg));
269
- return parts.join(' ');
270
- }
271
-
272
- let i = 0;
273
- let result = '';
274
- let lastIdx = 0;
275
-
276
- for (let p = 0; p < fmt.length - 1; p++) {
277
- if (fmt[p] !== '%') continue;
278
-
279
- if (p > lastIdx) result += fmt.slice(lastIdx, p);
280
-
281
- const next = fmt[p + 1];
282
-
283
- // %% always produces literal % (no arg consumed)
284
- if (next === '%') {
285
- result += '%';
286
- lastIdx = p + 2;
287
- p++;
288
- continue;
289
- }
290
-
291
- if (i >= args.length) {
292
- result += '%' + next;
293
- lastIdx = p + 2;
294
- p++;
295
- continue;
296
- }
297
-
298
- const arg = args[i];
299
- switch (next) {
300
- case 's': {
301
- if (typeof arg === 'bigint') {
302
- result += `${arg}n`;
303
- } else if (typeof arg === 'symbol') {
304
- result += arg.toString();
305
- } else if (typeof arg === 'number' && Object.is(arg, -0)) {
306
- result += '-0';
307
- } else if (typeof arg === 'object' && arg !== null) {
308
- // Objects with custom toString use it, others get inspect
309
- const proto = Object.getPrototypeOf(arg);
310
- if (proto === null || (typeof arg.toString === 'function' && arg.toString !== Object.prototype.toString && arg.toString !== Array.prototype.toString)) {
311
- try {
312
- const str = arg.toString();
313
- if (typeof str === 'string' && str !== '[object Object]') {
314
- result += str;
315
- } else {
316
- result += inspect(arg, { depth: 0 });
317
- }
318
- } catch {
319
- result += inspect(arg, { depth: 0 });
320
- }
321
- } else {
322
- result += inspect(arg, { depth: 0 });
323
- }
324
- } else {
325
- result += String(arg);
326
- }
327
- i++;
328
- break;
329
- }
330
- case 'd': {
331
- if (typeof arg === 'bigint') {
332
- result += `${arg}n`;
333
- } else if (typeof arg === 'symbol') {
334
- result += 'NaN';
335
- } else {
336
- const n = Number(arg);
337
- result += Object.is(n, -0) ? '-0' : String(n);
338
- }
339
- i++;
340
- break;
341
- }
342
- case 'i': {
343
- if (typeof arg === 'bigint') {
344
- result += `${arg}n`;
345
- } else if (typeof arg === 'symbol') {
346
- result += 'NaN';
347
- } else {
348
- const n = Number(arg);
349
- if (!isFinite(n)) {
350
- // Node.js: parseInt('Infinity') → NaN, parseInt('-Infinity') → NaN
351
- result += 'NaN';
352
- } else {
353
- const truncated = Math.trunc(n);
354
- result += Object.is(truncated, -0) ? '-0' : String(truncated);
355
- }
356
- }
357
- i++;
358
- break;
359
- }
360
- case 'f': {
361
- if (typeof arg === 'bigint') {
362
- result += Number(arg).toString();
363
- } else if (typeof arg === 'symbol') {
364
- result += 'NaN';
365
- } else {
366
- const n = parseFloat(String(arg));
367
- result += Object.is(n, -0) ? '-0' : String(n);
368
- }
369
- i++;
370
- break;
371
- }
372
- case 'j':
373
- try {
374
- result += JSON.stringify(args[i++]);
375
- } catch {
376
- result += '[Circular]';
377
- }
378
- break;
379
- case 'o':
380
- result += inspect(args[i++], { showHidden: true, depth: 4 });
381
- break;
382
- case 'O':
383
- result += inspect(args[i++], { depth: 4 });
384
- break;
385
- default:
386
- result += '%' + next;
387
- break;
388
- }
389
- lastIdx = p + 2;
390
- p++;
391
- }
392
-
393
- if (lastIdx < fmt.length) {
394
- result += fmt.slice(lastIdx);
395
- }
396
-
397
- // Append remaining args (strings passed as-is, objects inspected)
398
- for (; i < args.length; i++) {
399
- const arg = args[i];
400
- if (typeof arg === 'string') {
401
- result += ' ' + arg;
402
- } else {
403
- result += ' ' + inspect(arg);
404
- }
405
- }
406
-
407
- return result;
408
- }
409
-
410
- export function formatWithOptions(inspectOptions: InspectOptions, fmt: string, ...args: unknown[]): string {
411
- // Apply inspect options to embedded inspect calls — simplified implementation
412
- return format(fmt, ...args);
413
- }
414
-
415
- // ---- styleText / stripVTControlCharacters (Node 21+ / 16.11+) ----
416
-
417
- // Matches all ANSI escape code sequences. Same regex used by Node — sourced
418
- // from Sindre Sorhus's chalk/ansi-regex (MIT). Kept module-local; the only
419
- // consumer is stripVTControlCharacters and its callers.
420
- const ANSI_REGEX = new RegExp(
421
- '[\\u001B\\u009B][[\\]()#;?]*' +
422
- '(?:(?:(?:(?:;[-a-zA-Z\\d\\/\\#&.:=?%@~_]+)*' +
423
- '|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/\\#&.:=?%@~_]*)*)?' +
424
- '(?:\\u0007|\\u001B\\u005C|\\u009C))' +
425
- '|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?' +
426
- '[\\dA-PR-TZcf-nq-uy=><~]))',
427
- 'g',
428
- );
429
-
430
- export function stripVTControlCharacters(str: string): string {
431
- if (typeof str !== 'string') {
432
- throw new TypeError('The "str" argument must be of type string. Received ' + typeof str);
433
- }
434
- // Short-circuit: ESC () or CSI (›) introducer must be present.
435
- if (str.indexOf('') === -1 && str.indexOf('›') === -1) return str;
436
- return str.replace(ANSI_REGEX, '');
437
- }
438
-
439
- interface StyleTextOptions {
440
- validateStream?: boolean;
441
- stream?: { isTTY?: boolean };
442
- }
443
-
444
- /**
445
- * Apply ANSI styling to text, using the format names from `inspect.colors`.
446
- * Per Node's spec, when `validateStream` is true (default) and the target
447
- * stream is not a TTY, return the unstyled text. We use `process.stdout` as
448
- * the default stream — the same as Node.
449
- */
450
- export function styleText(
451
- format: string | string[],
452
- text: string,
453
- options?: StyleTextOptions,
454
- ): string {
455
- if (typeof text !== 'string') {
456
- throw new TypeError('The "text" argument must be of type string. Received ' + typeof text);
457
- }
458
- const validateStream = options?.validateStream ?? true;
459
- if (validateStream) {
460
- const stream = options?.stream ?? (globalThis as { process?: { stdout?: { isTTY?: boolean } } }).process?.stdout;
461
- if (!stream?.isTTY) return text;
462
- }
463
-
464
- const formats = Array.isArray(format) ? format : [format];
465
- let openCodes = '';
466
- let closeCodes = '';
467
- for (const key of formats) {
468
- if (key === 'none') continue;
469
- const style = inspect.colors[key];
470
- if (style === undefined) {
471
- throw new TypeError(`The "format" argument must be one of: ${Object.keys(inspect.colors).join(', ')}. Received '${key}'`);
472
- }
473
- openCodes += `[${style[0]}m`;
474
- closeCodes = `[${style[1]}m` + closeCodes;
475
- }
476
- return `${openCodes}${text}${closeCodes}`;
477
- }
478
-
479
- // ---- promisify / callbackify ----
480
-
481
- const kCustomPromisify = Symbol.for('nodejs.util.promisify.custom');
482
-
483
- export function promisify<T extends (...args: unknown[]) => void>(fn: T): (...args: unknown[]) => Promise<unknown> {
484
- if (typeof fn !== 'function') {
485
- throw new TypeError('The "original" argument must be of type Function');
486
- }
487
-
488
- // Check for custom promisify
489
- const custom = (fn as unknown as Record<symbol, unknown>)[kCustomPromisify];
490
- if (typeof custom === 'function') return custom as (...args: unknown[]) => Promise<unknown>;
491
-
492
- function promisified(this: unknown, ...args: unknown[]): Promise<unknown> {
493
- return new Promise((resolve, reject) => {
494
- fn.call(this, ...args, (err: Error | null, ...values: unknown[]) => {
495
- if (err) {
496
- reject(err);
497
- } else if (values.length <= 1) {
498
- resolve(values[0]);
499
- } else {
500
- resolve(values);
501
- }
502
- });
503
- });
504
- }
505
-
506
- Object.setPrototypeOf(promisified, Object.getPrototypeOf(fn));
507
- Object.defineProperty(promisified, kCustomPromisify, { value: promisified });
508
- return promisified;
509
- }
510
-
511
- promisify.custom = kCustomPromisify;
512
-
513
- export function callbackify<T>(fn: () => Promise<T>): (callback: (err: Error | null, result?: T) => void) => void;
514
- export function callbackify<T>(fn: (...args: unknown[]) => Promise<T>): (...args: unknown[]) => void;
515
- export function callbackify(fn: (...args: unknown[]) => Promise<unknown>): (...args: unknown[]) => void {
516
- if (typeof fn !== 'function') {
517
- throw new TypeError('The "original" argument must be of type Function');
518
- }
519
-
520
- return function (this: unknown, ...args: unknown[]) {
521
- const callback = args.pop();
522
- if (typeof callback !== 'function') {
523
- throw new TypeError('The last argument must be of type Function');
524
- }
525
- fn.apply(this, args).then(
526
- (result: unknown) => Promise.resolve().then(() => callback(null, result)),
527
- (err: Error) => Promise.resolve().then(() => callback(err || new Error()))
528
- );
529
- };
530
- }
531
-
532
- // ---- deprecate ----
533
-
534
- export function deprecate<T extends (...args: unknown[]) => unknown>(fn: T, msg: string, code?: string): T {
535
- let warned = false;
536
- function deprecated(this: unknown, ...args: unknown[]): unknown {
537
- if (!warned) {
538
- warned = true;
539
- const warning = code ? `[${code}] ${msg}` : msg;
540
- console.warn(`DeprecationWarning: ${warning}`);
541
- }
542
- return fn.apply(this, args);
543
- }
544
- Object.setPrototypeOf(deprecated, fn);
545
- return deprecated as unknown as T;
546
- }
547
-
548
- // ---- debuglog ----
549
-
550
- export function debuglog(section: string): (...args: unknown[]) => void {
551
- let debug: ((...args: unknown[]) => void) | undefined;
552
-
553
- return (...args: unknown[]) => {
554
- if (debug === undefined) {
555
- const nodeDebug = typeof globalThis.process?.env?.NODE_DEBUG === 'string'
556
- ? globalThis.process.env.NODE_DEBUG
557
- : '';
558
- const regex = new RegExp(`\\b${section}\\b`, 'i');
559
- if (regex.test(nodeDebug)) {
560
- const pid = typeof globalThis.process?.pid === 'number' ? globalThis.process.pid : 0;
561
- debug = (...a: unknown[]) => {
562
- console.error(`${section.toUpperCase()} ${pid}:`, ...a);
563
- };
564
- } else {
565
- debug = () => {};
566
- }
567
- }
568
- debug(...args);
569
- };
570
- }
571
-
572
- // ---- inherits ----
573
-
574
- export function inherits(ctor: Function, superCtor: Function): void {
575
- if (ctor === undefined || ctor === null) {
576
- const err = new TypeError('The "ctor" argument must be of type Function. Received ' + String(ctor));
577
- (err as any).code = 'ERR_INVALID_ARG_TYPE';
578
- throw err;
579
- }
580
- if (superCtor === undefined || superCtor === null) {
581
- const err = new TypeError('The "superCtor" argument must be of type Function. Received ' + String(superCtor));
582
- (err as any).code = 'ERR_INVALID_ARG_TYPE';
583
- throw err;
584
- }
585
- if (superCtor.prototype === undefined) {
586
- const err = new TypeError('The "superCtor.prototype" property must not be undefined');
587
- (err as any).code = 'ERR_INVALID_ARG_TYPE';
588
- throw err;
589
- }
590
- Object.defineProperty(ctor, 'super_', { value: superCtor, writable: true, configurable: true });
591
- Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
592
- }
593
-
594
- // ---- Legacy type checking (deprecated but still used) ----
595
-
596
- export function isBoolean(value: unknown): value is boolean {
597
- return typeof value === 'boolean';
598
- }
599
-
600
- export function isNull(value: unknown): value is null {
601
- return value === null;
602
- }
603
-
604
- export function isNullOrUndefined(value: unknown): value is null | undefined {
605
- return value == null;
606
- }
607
-
608
- export function isNumber(value: unknown): value is number {
609
- return typeof value === 'number';
610
- }
611
-
612
- export function isString(value: unknown): value is string {
613
- return typeof value === 'string';
614
- }
615
-
616
- export function isSymbol(value: unknown): value is symbol {
617
- return typeof value === 'symbol';
618
- }
619
-
620
- export function isUndefined(value: unknown): value is undefined {
621
- return value === undefined;
622
- }
623
-
624
- export function isObject(value: unknown): value is object {
625
- return value !== null && typeof value === 'object';
626
- }
627
-
628
- export function isError(value: unknown): value is Error {
629
- return value instanceof Error;
630
- }
631
-
632
- export function isFunction(value: unknown): value is Function {
633
- return typeof value === 'function';
634
- }
635
-
636
- export function isRegExp(value: unknown): value is RegExp {
637
- return value instanceof RegExp;
638
- }
639
-
640
- export function isArray(value: unknown): value is unknown[] {
641
- return Array.isArray(value);
642
- }
643
-
644
- export function isPrimitive(value: unknown): boolean {
645
- return value === null || (typeof value !== 'object' && typeof value !== 'function');
646
- }
647
-
648
- export function isDate(value: unknown): value is Date {
649
- return value instanceof Date;
650
- }
651
-
652
- export function isBuffer(value: unknown): boolean {
653
- return value instanceof Uint8Array && (value as unknown as { constructor?: { name?: string } }).constructor?.name === 'Buffer';
654
- }
655
-
656
- // ---- Re-export globals ----
657
-
658
- export const TextDecoder = globalThis.TextDecoder;
659
- export const TextEncoder = globalThis.TextEncoder;
660
-
661
- // ---- isDeepStrictEqual ----
662
-
663
- export function isDeepStrictEqual(a: unknown, b: unknown): boolean {
664
- if (Object.is(a, b)) return true;
665
- if (typeof a !== typeof b) return false;
666
- if (a === null || b === null) return false;
667
- if (typeof a !== 'object') return false;
668
-
669
- const aObj = a as Record<string, unknown>;
670
- const bObj = b as Record<string, unknown>;
671
-
672
- if (Array.isArray(aObj) && Array.isArray(bObj)) {
673
- if (aObj.length !== bObj.length) return false;
674
- for (let i = 0; i < aObj.length; i++) {
675
- if (!isDeepStrictEqual(aObj[i], bObj[i])) return false;
676
- }
677
- return true;
678
- }
679
-
680
- if (Array.isArray(aObj) !== Array.isArray(bObj)) return false;
681
-
682
- if (aObj instanceof Date && bObj instanceof Date) {
683
- return aObj.getTime() === bObj.getTime();
684
- }
685
-
686
- if (aObj instanceof RegExp && bObj instanceof RegExp) {
687
- return aObj.source === bObj.source && aObj.flags === bObj.flags;
688
- }
689
-
690
- const aKeys = Object.keys(aObj);
691
- const bKeys = Object.keys(bObj);
692
- if (aKeys.length !== bKeys.length) return false;
693
-
694
- for (const key of aKeys) {
695
- if (!Object.prototype.hasOwnProperty.call(bObj, key)) return false;
696
- if (!isDeepStrictEqual(aObj[key], bObj[key])) return false;
697
- }
698
-
699
- return true;
700
- }
701
-
702
- // ---- toUSVString ----
703
-
704
- export function toUSVString(string: string): string {
705
- if (typeof (string as unknown as { toWellFormed?: () => string }).toWellFormed === 'function') {
706
- return (string as unknown as { toWellFormed: () => string }).toWellFormed();
707
- }
708
- // Fallback
709
- return string.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, '\uFFFD');
710
- }
711
-
712
- // ---- Default export ----
713
-
714
- export default {
715
- format,
716
- formatWithOptions,
717
- styleText,
718
- stripVTControlCharacters,
719
- inspect,
720
- promisify,
721
- callbackify,
722
- deprecate,
723
- debuglog,
724
- inherits,
725
- types,
726
- isBoolean,
727
- isNull,
728
- isNullOrUndefined,
729
- isNumber,
730
- isString,
731
- isSymbol,
732
- isUndefined,
733
- isObject,
734
- isError,
735
- isFunction,
736
- isRegExp,
737
- isArray,
738
- isPrimitive,
739
- isDate,
740
- isBuffer,
741
- isDeepStrictEqual,
742
- toUSVString,
743
- TextDecoder: globalThis.TextDecoder,
744
- TextEncoder: globalThis.TextEncoder,
745
- getSystemErrorName,
746
- getSystemErrorMap,
747
- };