Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823// Derived from Node.js v24.16.0 (MIT; Copyright Node.js contributors, and Joyent, Inc. and// other Node contributors). See LICENSE-node.// util.inspect and util.format, following Node's lib/internal/util/inspect.js// algorithm (compact=3 line joining, array grouping, circular refs, error stacks)// over the subset of value kinds JavaScript can observe without engine internals.// Promise state and Proxy targets are not observable from JS: a Promise prints as// `Promise { <unknown> }` and a Proxy prints as its target would.
export const customInspect: unique symbol = Symbol.for("nodejs.util.inspect.custom") as never;
export interface InspectOptions { showHidden?: boolean; depth?: number | null; colors?: boolean; customInspect?: boolean; showProxy?: boolean; maxArrayLength?: number | null; maxStringLength?: number | null; breakLength?: number; compact?: boolean | number; sorted?: boolean | ((a: string, b: string) => number); getters?: boolean | "get" | "set"; numericSeparator?: boolean; stylize?: (text: string, style: string) => string;}
interface Ctx { showHidden: boolean; depth: number; colors: boolean; customInspect: boolean; maxArrayLength: number; maxStringLength: number; breakLength: number; compact: boolean | number; sorted: boolean | ((a: string, b: string) => number); getters: boolean | "get" | "set"; numericSeparator: boolean; stylize: (text: string, style: string) => string; seen: unknown[]; circular: Map<unknown, number> | undefined; indentationLvl: number; currentDepth: number; userOptions: InspectOptions;}
export const defaultOptions = { showHidden: false, depth: 2, colors: false, customInspect: true, showProxy: false, maxArrayLength: 100, maxStringLength: 10000, breakLength: 80, compact: 3, sorted: false, getters: false, numericSeparator: false,} satisfies InspectOptions;
/** inspect.colors: Node's SGR open/close pairs, its aliases non-enumerable as in Node. */const COLORS: Record<string, [number, number]> = { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23], underline: [4, 24], blink: [5, 25], inverse: [7, 27], hidden: [8, 28], strikethrough: [9, 29], doubleunderline: [21, 24], black: [30, 39], red: [31, 39], green: [32, 39], yellow: [33, 39], blue: [34, 39], magenta: [35, 39], cyan: [36, 39], white: [37, 39], bgBlack: [40, 49], bgRed: [41, 49], bgGreen: [42, 49], bgYellow: [43, 49], bgBlue: [44, 49], bgMagenta: [45, 49], bgCyan: [46, 49], bgWhite: [47, 49], framed: [51, 54], overlined: [53, 55], gray: [90, 39], redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39], blueBright: [94, 39], magentaBright: [95, 39], cyanBright: [96, 39], whiteBright: [97, 39], bgGray: [100, 49], bgRedBright: [101, 49], bgGreenBright: [102, 49], bgYellowBright: [103, 49], bgBlueBright: [104, 49], bgMagentaBright: [105, 49], bgCyanBright: [106, 49], bgWhiteBright: [107, 49],};for (const [alias, name] of [ ["grey", "gray"], ["blackBright", "gray"], ["bgGrey", "bgGray"], ["bgBlackBright", "bgGray"], ["faint", "dim"], ["crossedout", "strikethrough"], ["strikeThrough", "strikethrough"], ["crossedOut", "strikethrough"], ["conceal", "hidden"], ["swapColors", "inverse"], ["swapcolors", "inverse"], ["doubleUnderline", "doubleunderline"],] as const) { Object.defineProperty(COLORS, alias, { get: () => COLORS[name], set(value) { Object.defineProperty(COLORS, alias, { value, configurable: true, enumerable: true, writable: true }); }, configurable: true, enumerable: false, });}const STYLES: Record<string, string> = { special: "cyan", number: "yellow", bigint: "yellow", boolean: "yellow", undefined: "grey", null: "bold", string: "green", symbol: "green", date: "magenta", regexp: "red", module: "underline",};
function stylizeWithColor(text: string, style: string): string { const color = COLORS[STYLES[style] ?? ""]; return color ? `\u001b[${color[0]}m${text}\u001b[${color[1]}m` : text;}const stylizeNoColor = (text: string): string => text;
const ANSI = /[\u001B\u009B][[\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\d/#&.:=?%@~_]+)*|[a-zA-Z\d]+(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~]))/g;export function stripVTControlCharacters(str: string): string { return str.replace(ANSI, "");}const visibleLength = (ctx: Ctx, s: string): number => (ctx.colors ? stripVTControlCharacters(s).length : s.length);
export function inspect(value: unknown, opts?: InspectOptions | boolean, ...legacy: unknown[]): string { let user: InspectOptions = {}; if (typeof opts === "boolean") { user = { showHidden: opts }; if (legacy[0] !== undefined) user.depth = legacy[0] as number | null; if (legacy[1] !== undefined) user.colors = legacy[1] as boolean; } else if (opts) { user = opts; } const merged = { ...inspect.defaultOptions, ...user }; const ctx: Ctx = { showHidden: Boolean(merged.showHidden), depth: merged.depth === null ? Infinity : merged.depth, colors: Boolean(merged.colors), customInspect: merged.customInspect !== false, maxArrayLength: merged.maxArrayLength === null ? Infinity : merged.maxArrayLength, maxStringLength: merged.maxStringLength === null ? Infinity : merged.maxStringLength, breakLength: merged.breakLength, compact: merged.compact, sorted: merged.sorted, getters: merged.getters, numericSeparator: Boolean(merged.numericSeparator), stylize: user.stylize ?? (merged.colors ? stylizeWithColor : stylizeNoColor), seen: [], circular: undefined, indentationLvl: 0, currentDepth: 0, userOptions: user, }; return formatValue(ctx, value, 0);}inspect.custom = customInspect;inspect.defaultOptions = { ...defaultOptions } as typeof defaultOptions;inspect.colors = COLORS;inspect.styles = STYLES;
// ---- strings ----
const META: string[] = [];for (let i = 0; i < 32; i++) META[i] = `\\x${i.toString(16).toUpperCase().padStart(2, "0")}`;Object.assign(META, { 8: "\\b", 9: "\\t", 10: "\\n", 12: "\\f", 13: "\\r" });for (let i = 0x7f; i <= 0x9f; i++) META[i] = `\\x${i.toString(16).toUpperCase()}`;
/** Node's quote choice: single quotes, else double, else backticks, escaping the one used. */function strEscape(str: string): string { let quote = "'"; if (str.includes("'")) { if (!str.includes('"')) quote = '"'; else if (!str.includes("`") && !str.includes("${")) quote = "`"; } let out = ""; for (let i = 0; i < str.length; i++) { const c = str.charCodeAt(i); if (str[i] === quote && quote === "'") out += "\\'"; else if (c === 92) out += "\\\\"; else if (c < 32 || (c >= 0x7f && c <= 0x9f)) out += META[c]; else if (c >= 0xd800 && c <= 0xdfff) { const next = str.charCodeAt(i + 1); if (c <= 0xdbff && next >= 0xdc00 && next <= 0xdfff) { out += str[i]! + str[i + 1]!; i++; } else { out += `\\u${c.toString(16).toUpperCase()}`; } } else out += str[i]; } return quote + out + quote;}
function formatNumber(fn: Ctx["stylize"], n: number, separator: boolean): string { if (Object.is(n, -0)) return fn("-0", "number"); if (!separator || !Number.isFinite(n)) return fn(`${n}`, "number"); const [int, frac] = String(n).split("."); const grouped = int!.replace(/\B(?=(\d{3})+(?!\d))/g, "_"); return fn(frac === undefined ? grouped : `${grouped}.${frac.replace(/(\d{3})(?=\d)/g, "$1_")}`, "number");}
function formatBigInt(fn: Ctx["stylize"], n: bigint, separator: boolean): string { const s = separator ? String(n).replace(/\B(?=(\d{3})+(?!\d))/g, "_") : String(n); return fn(`${s}n`, "bigint");}
function formatPrimitive(ctx: Ctx, value: unknown): string { const fn = ctx.stylize; if (typeof value === "string") { let trailer = ""; let str = value; if (str.length > ctx.maxStringLength) { const remaining = str.length - ctx.maxStringLength; str = str.slice(0, ctx.maxStringLength); trailer = `... ${remaining} more character${remaining > 1 ? "s" : ""}`; } if (ctx.compact !== true && str.length > 16 && str.length > ctx.breakLength - ctx.indentationLvl - 4) { return str.split(/(?<=\n)/).map((line) => fn(strEscape(line), "string")) .join(` +\n${" ".repeat(ctx.indentationLvl + 2)}`) + trailer; } return fn(strEscape(str), "string") + trailer; } if (typeof value === "number") return formatNumber(fn, value, ctx.numericSeparator); if (typeof value === "bigint") return formatBigInt(fn, value, ctx.numericSeparator); if (typeof value === "boolean") return fn(`${value}`, "boolean"); if (value === undefined) return fn("undefined", "undefined"); return fn(String(value), "symbol");}
// ---- objects ----
const tagOf = (v: unknown): string => Object.prototype.toString.call(v).slice(8, -1);
function getConstructorName(obj: object): string | null { let o: object | null = obj; while (o !== null) { const d = Object.getOwnPropertyDescriptor(o, "constructor"); if (d && typeof d.value === "function" && d.value.name !== "") { try { if (obj instanceof d.value) return d.value.name as string; } catch { /* a throwing Symbol.hasInstance: keep walking */ } } o = Object.getPrototypeOf(o); } return null;}
function getPrefix(constructor: string | null, tag: string, fallback: string, size = ""): string { if (constructor === null) { if (tag !== "" && fallback !== tag) return `[${fallback}${size}: null prototype] [${tag}] `; return `[${fallback}${size}: null prototype] `; } if (tag !== "" && constructor !== tag) return `${constructor}${size} [${tag}] `; return `${constructor}${size} `;}
function getKeys(value: object, showHidden: boolean): Array<string | symbol> { const keys: Array<string | symbol> = showHidden ? Object.getOwnPropertyNames(value) : Object.keys(value); const symbols = Object.getOwnPropertySymbols(value); for (const s of symbols) if (showHidden || Object.prototype.propertyIsEnumerable.call(value, s)) keys.push(s); return keys;}
const isIndex = (k: string): boolean => /^(?:0|[1-9]\d*)$/.test(k) && Number(k) < 2 ** 32 - 1;
function getNonIndexKeys(value: object, showHidden: boolean): Array<string | symbol> { return getKeys(value, showHidden).filter((k) => typeof k === "symbol" || !isIndex(k));}
function isError(v: unknown): v is Error { return v instanceof Error || tagOf(v) === "Error";}
const BUILTIN_CTORS = new Set(Object.getOwnPropertyNames(globalThis).filter( (n) => /^[A-Z]/.test(n) && typeof (globalThis as Record<string, unknown>)[n] === "function",));
/** True unless the object (or a user-defined class in its chain) overrides toString. */function hasBuiltInToString(value: object): boolean { if (typeof (value as { toString?: unknown }).toString !== "function") return true; if (Object.hasOwn(value, "toString")) return false; let pointer: object | null = value; do { pointer = Object.getPrototypeOf(pointer); } while (pointer !== null && !Object.hasOwn(pointer, "toString")); if (pointer === null) return true; const d = Object.getOwnPropertyDescriptor(pointer, "constructor"); return d !== undefined && typeof d.value === "function" && BUILTIN_CTORS.has(d.value.name);}
function formatValue(ctx: Ctx, value: unknown, recurseTimes: number): string { if (typeof value !== "object" && typeof value !== "function") return formatPrimitive(ctx, value); if (value === null) return ctx.stylize("null", "null"); if (ctx.customInspect) { const custom = (value as Record<symbol, unknown>)[customInspect]; const ctor = (value as { constructor?: { prototype?: unknown } }).constructor; if (typeof custom === "function" && custom !== inspect && !(ctor && ctor.prototype === value)) { const depth = ctx.depth - recurseTimes; const options = { ...inspect.defaultOptions, ...ctx.userOptions, depth, stylize: ctx.stylize }; const ret = custom.call(value, depth, options, inspect); if (ret !== value) { if (typeof ret !== "string") return formatValue(ctx, ret, recurseTimes); return ret.replaceAll("\n", `\n${" ".repeat(ctx.indentationLvl)}`); } } } if (ctx.seen.includes(value)) { ctx.circular ??= new Map(); let index = ctx.circular.get(value); if (index === undefined) { index = ctx.circular.size + 1; ctx.circular.set(value, index); } return ctx.stylize(`[Circular *${index}]`, "special"); } return formatRaw(ctx, value, recurseTimes);}
const OBJECT = 0;const ARRAY_LIKE = 1;type Formatter = (ctx: Ctx, value: any, recurseTimes: number) => string[];const noEntries: Formatter = () => [];
function formatRaw(ctx: Ctx, value: object, recurseTimes: number): string { const constructor = getConstructorName(value); let tag = (value as Record<symbol, unknown>)[Symbol.toStringTag]; if (typeof tag !== "string" || (tag !== "" && Object.prototype.propertyIsEnumerable.call(value, Symbol.toStringTag))) tag = ""; const t = tag as string; let keys: Array<string | symbol>; let base = ""; let formatter: Formatter = noEntries; let braces: [string, string]; let extrasType = OBJECT; let iterable = true;
if (Array.isArray(value)) { const prefix = constructor !== "Array" || t !== "" ? getPrefix(constructor, t, "Array", `(${value.length})`) : ""; keys = getNonIndexKeys(value, ctx.showHidden); braces = [`${prefix}[`, "]"]; if (value.length === 0 && keys.length === 0) return `${braces[0]}]`; extrasType = ARRAY_LIKE; formatter = formatArray; } else if (value instanceof Set) { const prefix = getPrefix(constructor, t, "Set", `(${value.size})`); keys = getKeys(value, ctx.showHidden); formatter = formatSet; if (value.size === 0 && keys.length === 0) return `${prefix}{}`; braces = [`${prefix}{`, "}"]; } else if (value instanceof Map) { const prefix = getPrefix(constructor, t, "Map", `(${value.size})`); keys = getKeys(value, ctx.showHidden); formatter = formatMap; if (value.size === 0 && keys.length === 0) return `${prefix}{}`; braces = [`${prefix}{`, "}"]; } else if (ArrayBuffer.isView(value) && !(value instanceof DataView)) { const ta = value as unknown as ArrayLike<number | bigint>; keys = getNonIndexKeys(value, ctx.showHidden); const prefix = getPrefix(constructor, t, tagOf(value), `(${ta.length})`); braces = [`${prefix}[`, "]"]; if (ta.length === 0 && keys.length === 0 && !ctx.showHidden) return `${braces[0]}]`; formatter = formatTypedArray; extrasType = ARRAY_LIKE; } else { iterable = false; }
if (!iterable) { keys = getKeys(value, ctx.showHidden); braces = ["{", "}"]; if (typeof value === "function") { base = getFunctionBase(value, constructor, t); if (keys.length === 0) return ctx.stylize(base, "special"); } else if (constructor === "Object") { if (tagOf(value) === "Arguments") braces[0] = "[Arguments] ["; else if (t !== "") braces[0] = `${getPrefix(constructor, t, "Object")}{`; if (keys.length === 0) return `${braces[0]}}`; if (braces[0] === "[Arguments] [") { extrasType = ARRAY_LIKE; braces[1] = "]"; formatter = formatArray; keys = getNonIndexKeys(value, ctx.showHidden); } } else if (value instanceof RegExp) { base = RegExp.prototype.toString.call(value); const prefix = getPrefix(constructor, t, "RegExp"); if (prefix !== "RegExp ") base = `${prefix}${base}`; if (keys.length === 0 || recurseTimes > ctx.depth) return ctx.stylize(base, "regexp"); } else if (value instanceof Date) { base = Number.isNaN(value.getTime()) ? Date.prototype.toString.call(value) : value.toISOString(); const prefix = getPrefix(constructor, t, "Date"); if (prefix !== "Date ") base = `${prefix}${base}`; if (keys.length === 0) return ctx.stylize(base, "date"); } else if (isError(value)) { base = formatError(value, constructor, t, ctx, keys); if (keys.length === 0) return base; } else if (value instanceof ArrayBuffer) { keys.unshift("byteLength"); const bytes = new Uint8Array(value); const prefix = getPrefix(constructor, t, "ArrayBuffer"); braces[0] = `${prefix}{`; formatter = () => [`[Uint8Contents]: <${hexBytes(bytes, ctx.maxArrayLength)}>`]; if (keys.length === 1) keys = ["byteLength"]; } else if (tagOf(value) === "Promise") { braces[0] = `${getPrefix(constructor, t, "Promise")}{`; formatter = (c) => [c.stylize("<unknown>", "special")]; } else if (value instanceof WeakSet || value instanceof WeakMap) { const kind = value instanceof WeakSet ? "WeakSet" : "WeakMap"; braces[0] = `${getPrefix(constructor, t, kind)}{`; formatter = (c) => [c.stylize("<items unknown>", "special")]; } else if (isBoxed(value)) { if (value instanceof String) keys = keys.filter((k) => typeof k === "symbol" || !isIndex(k)); base = boxedBase(ctx, value, constructor, t); if (keys.length === 0) return base; } else { if (keys.length === 0) return `${getPrefix(constructor, t, "Object")}{}`; braces[0] = `${getPrefix(constructor, t, "Object")}{`; } }
if (recurseTimes > ctx.depth) { let name = getPrefix(constructor, t, "Object").slice(0, -1); if (constructor !== null) name = `[${name}]`; return ctx.stylize(name, "special"); } recurseTimes += 1; ctx.seen.push(value); ctx.currentDepth = recurseTimes; const output = formatter(ctx, value, recurseTimes); for (const key of keys!) output.push(formatProperty(ctx, value, recurseTimes, key, extrasType)); if (ctx.circular !== undefined) { const index = ctx.circular.get(value); if (index !== undefined) { const reference = ctx.stylize(`<ref *${index}>`, "special"); if (ctx.compact !== true) base = base === "" ? reference : `${reference} ${base}`; else braces![0] = `${reference} ${braces![0]}`; } } ctx.seen.pop(); if (ctx.sorted) { const cmp = ctx.sorted === true ? undefined : ctx.sorted; if (extrasType === OBJECT) output.sort(cmp); } return reduceToSingleString(ctx, output, base, braces!, extrasType, recurseTimes, value);}
function hexBytes(bytes: Uint8Array, max: number): string { const shown = Array.from(bytes.subarray(0, Math.min(max, bytes.length)), (b) => b.toString(16).padStart(2, "0")).join(" "); const remaining = bytes.length - Math.min(max, bytes.length); return remaining > 0 ? `${shown} ... ${remaining} more byte${remaining > 1 ? "s" : ""}` : shown;}
function isBoxed(v: object): boolean { return v instanceof Number || v instanceof String || v instanceof Boolean || (typeof BigInt === "function" && tagOf(v) === "BigInt") || tagOf(v) === "Symbol";}
function boxedBase(ctx: Ctx, value: object, constructor: string | null, tag: string): string { let type: string; let shown: string; if (value instanceof Number) { type = "Number"; shown = formatNumber(stylizeNoColor, value.valueOf(), false); } else if (value instanceof String) { type = "String"; shown = strEscape(value.valueOf()); } else if (value instanceof Boolean) { type = "Boolean"; shown = String(value.valueOf()); } else if (tagOf(value) === "BigInt") { type = "BigInt"; shown = `${(value as { valueOf(): bigint }).valueOf()}n`; } else { type = "Symbol"; shown = String((value as { valueOf(): symbol }).valueOf()); } let base = `[${type}`; if (type !== constructor) base += constructor === null ? " (null prototype)" : ` (${constructor})`; base += `: ${shown}]`; if (tag !== "" && tag !== constructor) base += ` [${tag}]`; return ctx.stylize(base, type.toLowerCase() === "string" ? "string" : type.toLowerCase());}
function getFunctionBase(fn: Function, constructor: string | null, tag: string): string { const source = Function.prototype.toString.call(fn); if (source.startsWith("class") && source.endsWith("}")) { const body = source.slice(5, -1); const brace = body.indexOf("{"); if (brace !== -1 && !body.slice(0, brace).includes("(")) { const name = (Object.hasOwn(fn, "name") && fn.name) || "(anonymous)"; let base = `class ${name}`; if (constructor !== "Function" && constructor !== null) base += ` [${constructor}]`; if (tag !== "" && constructor !== tag) base += ` [${tag}]`; if (constructor !== null) { const superName = (Object.getPrototypeOf(fn) as Function | null)?.name; if (superName) base += ` extends ${superName}`; } else { base += " extends [null prototype]"; } return `[${base}]`; } } let type = "Function"; const kind = tagOf(fn); if (kind === "GeneratorFunction" || kind === "AsyncGeneratorFunction") type = `Generator${type}`; if (kind === "AsyncFunction" || kind === "AsyncGeneratorFunction") type = `Async${type}`; let base = `[${type}`; if (constructor === null) base += " (null prototype)"; base += fn.name === "" ? " (anonymous)" : `: ${fn.name}`; base += "]"; if (constructor !== type && constructor !== null) base += ` ${constructor}`; if (tag !== "" && constructor !== tag) base += ` [${tag}]`; return base;}
function formatError(err: Error, constructor: string | null, tag: string, ctx: Ctx, keys: Array<string | symbol>): string { const name = err.name != null ? String(err.name) : "Error"; let stack = err.stack ? String(err.stack) : Error.prototype.toString.call(err); if (!ctx.showHidden && keys.length !== 0) { for (const prop of ["name", "message", "stack"] as const) { const i = keys.indexOf(prop); if (i !== -1 && (typeof err[prop] !== "string" || stack.includes(err[prop] as string))) keys.splice(i, 1); } } if ("cause" in err && !keys.includes("cause")) keys.push("cause"); if (Array.isArray((err as { errors?: unknown }).errors) && !keys.includes("errors")) keys.push("errors"); stack = improveStack(stack, constructor, name, tag); let pos = (err.message && stack.indexOf(err.message)) || -1; if (pos !== -1) pos += err.message.length; const stackStart = stack.indexOf("\n at", pos); if (stackStart === -1) stack = `[${stack}]`; if (ctx.indentationLvl !== 0) stack = stack.replaceAll("\n", `\n${" ".repeat(ctx.indentationLvl)}`); return stack;}
function improveStack(stack: string, constructor: string | null, name: string, tag: string): string { let len = name.length; if (constructor === null || (name.endsWith("Error") && stack.startsWith(name) && (stack.length === len || stack[len] === ":" || stack[len] === "\n"))) { let fallback = "Error"; if (constructor === null) { const start = /^([A-Z][a-z_ A-Z0-9[\]()-]+)(?::|\n\s+at)/.exec(stack) ?? /^([a-z_A-Z0-9-]*Error)$/.exec(stack); fallback = start?.[1] ?? ""; len = fallback.length; fallback ||= "Error"; } const prefix = getPrefix(constructor, tag, fallback).slice(0, -1); if (name !== prefix) { if (prefix.includes(name)) stack = len === 0 ? `${prefix}: ${stack}` : `${prefix}${stack.slice(len)}`; else stack = `${prefix} [${name}]${stack.slice(len)}`; } } return stack;}
function formatArray(ctx: Ctx, value: ArrayLike<unknown>, recurseTimes: number): string[] { const len = Math.min(Math.max(0, ctx.maxArrayLength), value.length); const output: string[] = []; let holes = 0; const flushHoles = (): void => { if (holes > 0) output.push(ctx.stylize(`<${holes} empty item${holes > 1 ? "s" : ""}>`, "undefined")); holes = 0; }; for (let i = 0; i < len; i++) { if (!Object.hasOwn(value, i)) { holes++; continue; } flushHoles(); output.push(formatProperty(ctx, value as object, recurseTimes, String(i), ARRAY_LIKE)); } flushHoles(); const remaining = value.length - len; if (remaining > 0) output.push(`... ${remaining} more item${remaining > 1 ? "s" : ""}`); return output;}
function formatTypedArray(ctx: Ctx, value: ArrayLike<number | bigint>, _recurseTimes: number): string[] { const max = Math.min(Math.max(0, ctx.maxArrayLength), value.length); const output: string[] = []; for (let i = 0; i < max; i++) { const v = value[i]!; output.push(typeof v === "bigint" ? formatBigInt(ctx.stylize, v, ctx.numericSeparator) : formatNumber(ctx.stylize, v, ctx.numericSeparator)); } const remaining = value.length - max; if (remaining > 0) output.push(`... ${remaining} more item${remaining > 1 ? "s" : ""}`); return output;}
function formatSet(ctx: Ctx, value: Set<unknown>, recurseTimes: number): string[] { const output: string[] = []; ctx.indentationLvl += 2; for (const v of value) output.push(formatValue(ctx, v, recurseTimes)); ctx.indentationLvl -= 2; return output;}
function formatMap(ctx: Ctx, value: Map<unknown, unknown>, recurseTimes: number): string[] { const output: string[] = []; ctx.indentationLvl += 2; for (const [k, v] of value) output.push(`${formatValue(ctx, k, recurseTimes)} => ${formatValue(ctx, v, recurseTimes)}`); ctx.indentationLvl -= 2; return output;}
const KEY_PLAIN = /^[a-zA-Z_][a-zA-Z_0-9]*$/;
function formatProperty(ctx: Ctx, value: object, recurseTimes: number, key: string | symbol, type: number): string { let str: string; const desc = Object.getOwnPropertyDescriptor(value, key) ?? { value: (value as Record<string | symbol, unknown>)[key], enumerable: false }; if (desc.value !== undefined) { const diff = ctx.compact !== true || type !== OBJECT ? 2 : 3; ctx.indentationLvl += diff; str = formatValue(ctx, desc.value, recurseTimes); ctx.indentationLvl -= diff; } else if (desc.get !== undefined) { const label = desc.set !== undefined ? "Getter/Setter" : "Getter"; if (ctx.getters && (ctx.getters === true || (ctx.getters === "get" && desc.set === undefined) || (ctx.getters === "set" && desc.set !== undefined))) { try { const got = desc.get.call(value); ctx.indentationLvl += 2; str = `${ctx.stylize(`[${label}:`, "special")} ${formatValue(ctx, got, recurseTimes)}${ctx.stylize("]", "special")}`; ctx.indentationLvl -= 2; } catch (e) { str = ctx.stylize(`[${label}: <Inspection threw (${(e as Error).message})>]`, "special"); } } else { str = ctx.stylize(`[${label}]`, "special"); } } else if (desc.set !== undefined) { str = ctx.stylize("[Setter]", "special"); } else { str = ctx.stylize("undefined", "undefined"); } if (type === ARRAY_LIKE && typeof key === "string" && isIndex(key)) return str; let name: string; if (typeof key === "symbol") name = ctx.stylize(String(key), "symbol"); else if (key === "__proto__") name = "['__proto__']"; else if (desc.enumerable === false) name = `[${key}]`; else if (KEY_PLAIN.test(key)) name = ctx.stylize(key, "name"); else name = ctx.stylize(strEscape(key), "string"); return `${name}: ${str}`;}
function isBelowBreakLength(ctx: Ctx, output: string[], start: number, base: string): boolean { let total = output.length + start; if (total + output.length > ctx.breakLength) return false; for (const entry of output) { total += visibleLength(ctx, entry); if (total > ctx.breakLength) return false; } return base === "" || !base.includes("\n");}
function reduceToSingleString( ctx: Ctx, output: string[], base: string, braces: [string, string], extrasType: number, recurseTimes: number, value: unknown,): string { if (ctx.compact !== true) { if (typeof ctx.compact === "number" && ctx.compact >= 1) { const entries = output.length; if (extrasType === ARRAY_LIKE && entries > 6) output = groupArrayElements(ctx, output, value as ArrayLike<unknown>); if (ctx.currentDepth - recurseTimes < ctx.compact && entries === output.length) { const start = output.length + ctx.indentationLvl + braces[0].length + base.length + 10; if (isBelowBreakLength(ctx, output, start, base)) { const joined = output.join(", "); if (!joined.includes("\n")) return `${base ? `${base} ` : ""}${braces[0]} ${joined} ${braces[1]}`; } } } const indentation = `\n${" ".repeat(ctx.indentationLvl)}`; return `${base ? `${base} ` : ""}${braces[0]}${indentation} ${output.join(`,${indentation} `)}${indentation}${braces[1]}`; } if (isBelowBreakLength(ctx, output, 0, base)) { return `${braces[0]}${base ? ` ${base}` : ""} ${output.join(", ")} ${braces[1]}`; } const indentation = `\n${" ".repeat(ctx.indentationLvl)}`; const ln = base === "" && braces[0].length === 1 ? " " : `${base ? ` ${base}` : ""}\n${indentation} `; return `${braces[0]}${ln}${output.join(`,\n${indentation} `)} ${braces[1]}`;}
/** Node's column layout for arrays of more than six short entries. */function groupArrayElements(ctx: Ctx, output: string[], value: ArrayLike<unknown> | undefined): string[] { let totalLength = 0; let maxLength = 0; let outputLength = output.length; if (value && ctx.maxArrayLength < value.length) outputLength--; // the "... more items" entry const separatorSpace = 2; const dataLen: number[] = new Array(outputLength); for (let i = 0; i < outputLength; i++) { const len = visibleLength(ctx, output[i]!); dataLen[i] = len; totalLength += len + separatorSpace; if (maxLength < len) maxLength = len; } const actualMax = maxLength + separatorSpace; if (actualMax * 3 + ctx.indentationLvl < ctx.breakLength && (totalLength / actualMax > 5 || maxLength <= 6)) { const averageBias = Math.sqrt(actualMax - totalLength / output.length); const biasedMax = Math.max(actualMax - 3 - averageBias, 1); const columns = Math.min( Math.round(Math.sqrt(2.5 * biasedMax * outputLength) / biasedMax), Math.floor((ctx.breakLength - ctx.indentationLvl) / actualMax), (ctx.compact as number) * 4, 15, ); if (columns <= 1) return output; const tmp: string[] = []; const maxLineLength: number[] = []; for (let i = 0; i < columns; i++) { let lineLength = 0; for (let j = i; j < output.length; j += columns) if (dataLen[j]! > lineLength) lineLength = dataLen[j]!; maxLineLength.push(lineLength + separatorSpace); } let padStart = true; if (value !== undefined) { for (let i = 0; i < output.length; i++) { const v = value[i]; if (typeof v !== "number" && typeof v !== "bigint") { padStart = false; break; } } } for (let i = 0; i < outputLength; i += columns) { const max = Math.min(i + columns, outputLength); let str = ""; let j = i; for (; j < max - 1; j++) { const padding = maxLineLength[j - i]! + output[j]!.length - dataLen[j]!; str += padStart ? `${output[j]}, `.padStart(padding, " ") : `${output[j]}, `.padEnd(padding, " "); } if (padStart) { const padding = maxLineLength[j - i]! + output[j]!.length - dataLen[j]! - separatorSpace; str += output[j]!.padStart(padding, " "); } else { str += output[j]; } tmp.push(str); } if (value && ctx.maxArrayLength < value.length) tmp.push(output[outputLength]!); return tmp; } return output;}
// ---- format ----
function tryStringify(v: unknown): string { try { return JSON.stringify(v); } catch (e) { if ((e as Error).message.includes("circular")) return "[Circular]"; throw e; }}
export function formatWithOptions(inspectOptions: InspectOptions, ...args: unknown[]): string { const first = args[0]; let a = 0; let str = ""; let join = ""; if (typeof first === "string") { if (args.length === 1) return first; let lastPos = 0; let tempStr = ""; for (let i = 0; i < first.length - 1; i++) { if (first.charCodeAt(i) !== 37) continue; // '%' const next = first.charCodeAt(++i); if (a + 1 !== args.length) { switch (next) { case 115: { // s const arg = args[++a]; if (typeof arg === "number") tempStr = formatNumber(stylizeNoColor, arg, false); else if (typeof arg === "bigint") tempStr = formatBigInt(stylizeNoColor, arg, false); else if (typeof arg !== "object" || arg === null || !hasBuiltInToString(arg)) tempStr = String(arg); else tempStr = inspect(arg, { ...inspectOptions, depth: 0, colors: false, compact: 3 }); break; } case 106: // j tempStr = tryStringify(args[++a]); break; case 100: { // d const n = args[++a]; if (typeof n === "bigint") tempStr = formatBigInt(stylizeNoColor, n, false); else if (typeof n === "symbol") tempStr = "NaN"; else tempStr = formatNumber(stylizeNoColor, Number(n), false); break; } case 79: // O tempStr = inspect(args[++a], inspectOptions); break; case 111: // o tempStr = inspect(args[++a], { ...inspectOptions, showHidden: true, showProxy: true, depth: 4 }); break; case 105: { // i const n = args[++a]; if (typeof n === "bigint") tempStr = formatBigInt(stylizeNoColor, n, false); else if (typeof n === "symbol") tempStr = "NaN"; else tempStr = formatNumber(stylizeNoColor, Number.parseInt(n as string), false); break; } case 102: { // f const n = args[++a]; tempStr = typeof n === "symbol" ? "NaN" : formatNumber(stylizeNoColor, Number.parseFloat(n as string), false); break; } case 99: // c a += 1; tempStr = ""; break; case 37: // % str += first.slice(lastPos, i); lastPos = i + 1; continue; default: continue; } if (lastPos !== i - 1) str += first.slice(lastPos, i - 1); str += tempStr; lastPos = i + 1; } else if (next === 37) { str += first.slice(lastPos, i); lastPos = i + 1; } } if (lastPos !== 0) { a++; join = " "; if (lastPos < first.length) str += first.slice(lastPos); } } while (a < args.length) { const value = args[a]; str += join; str += typeof value !== "string" ? inspect(value, inspectOptions) : value; join = " "; a++; } return str;}
export function format(...args: unknown[]): string { return formatWithOptions({}, ...args);}