nodejs / nodejs/node

`util.inspect()` ignores `breakLength: Infinity` when `depth: Infinity` is also set in some cases

Aperta
#60,475 4 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

confirmed-bug util
Lingua principale
JavaScript
Stelle
122k
Fork
37.3k
Merge medio
4g 2h
PR unite (30g)
283

Descrizione

Version

v25.1.0

Platform
- Windows: Microsoft Windows NT 10.0.26200.0 x64
- macOS: Darwin MacBook-Pro.local 24.6.0 Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:51 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T8112 arm64
- Linux: Linux myhost 6.8.0-45-generic #45-Ubuntu SMP PREEMPT_DYNAMIC x86_64 GNU/Linux
Subsystem

util

What steps will reproduce the bug?

When util.inspect() is called with both breakLength: Infinity and depth: Infinity, the output unexpectedly contains line breaks in Node.js v25.x.

In contrast:

  • Using only breakLength: Infinity (with default depth) works correctly and produces a single-line output.
  • The issue appears only when depth is explicitly set to Infinity.

This behavior did not occur in Node.js v24.x, so it appears to be a regression.

A minimal reproducible example is provided below.

$ nvm use 24
Now using node v24.11.0 (npm v11.6.1)
$ node
Welcome to Node.js v24.11.0.
Type ".help" for more information.
> const util = require("node:util")
undefined
> util.inspect(util, { breakLength: Infinity })
"{ _errnoException: [Function: _errnoException], _exceptionWithHostPort: [Function: _exceptionWithHostPort], _extend: [Function: deprecated], callbackify: [Function: callbackify], debug: [Function: debuglog], debuglog: [Function: debuglog], deprecate: [Function: deprecate], format: [Function: format], styleText: [Function: styleText], formatWithOptions: [Function: formatWithOptions], getCallSites: [Function: getCallSites], getSystemErrorMap: [Function: getSystemErrorMap], getSystemErrorName: [Function: getSystemErrorName], getSystemErrorMessage: [Function: getSystemErrorMessage], inherits: [Function: inherits], inspect: [Function: inspect] { custom: Symbol(nodejs.util.inspect.custom), colors: [Object: null prototype] { reset: [Array], bold: [Array], dim: [Array], italic: [Array], underline: [Array], blink: [Array], inverse: [Array], hidden: [Array], strikethrough: [Array], doubleunderline: [Array], black: [Array], red: [Array], green: [Array], yellow: [Array], blue: [Array], magenta: [Array], cyan: [Array], white: [Array], bgBlack: [Array], bgRed: [Array], bgGreen: [Array], bgYellow: [Array], bgBlue: [Array], bgMagenta: [Array], bgCyan: [Array], bgWhite: [Array], framed: [Array], overlined: [Array], gray: [Array], redBright: [Array], greenBright: [Array], yellowBright: [Array], blueBright: [Array], magentaBright: [Array], cyanBright: [Array], whiteBright: [Array], bgGray: [Array], bgRedBright: [Array], bgGreenBright: [Array], bgYellowBright: [Array], bgBlueBright: [Array], bgMagentaBright: [Array], bgCyanBright: [Array], bgWhiteBright: [Array] }, styles: [Object: null prototype] { special: 'cyan', number: 'yellow', bigint: 'yellow', boolean: 'yellow', undefined: 'grey', null: 'bold', string: 'green', symbol: 'green', date: 'magenta', regexp: 'red', module: 'underline' }, replDefaults: [Getter/Setter] }, isArray: [Function: deprecated], isDeepStrictEqual: [Function: isDeepStrictEqual], promisify: [Function: promisify] { custom: Symbol(nodejs.util.promisify.custom) }, stripVTControlCharacters: [Function: stripVTControlCharacters], toUSVString: [Function: toUSVString], transferableAbortSignal: [Getter], transferableAbortController: [Getter], aborted: [Getter], types: { isArgumentsObject: [Function (anonymous)], isArrayBuffer: [Function (anonymous)], isAsyncFunction: [Function (anonymous)], isBigIntObject: [Function (anonymous)], isBooleanObject: [Function (anonymous)], isDataView: [Function (anonymous)], isDate: [Function (anonymous)], isExternal: [Function (anonymous)], isGeneratorFunction: [Function (anonymous)], isGeneratorObject: [Function (anonymous)], isMap: [Function (anonymous)], isMapIterator: [Function (anonymous)], isModuleNamespaceObject: [Function (anonymous)], isNativeError: [Function (anonymous)], isNumberObject: [Function (anonymous)], isPromise: [Function (anonymous)], isProxy: [Function (anonymous)], isRegExp: [Function (anonymous)], isSet: [Function (anonymous)], isSetIterator: [Function (anonymous)], isSharedArrayBuffer: [Function (anonymous)], isStringObject: [Function (anonymous)], isSymbolObject: [Function (anonymous)], isWeakMap: [Function (anonymous)], isWeakSet: [Function (anonymous)], isAnyArrayBuffer: [Function (anonymous)], isBoxedPrimitive: [Function (anonymous)], isArrayBufferView: [Function: isView], isTypedArray: [Function: isTypedArray], isUint8Array: [Function: isUint8Array], isUint8ClampedArray: [Function: isUint8ClampedArray], isUint16Array: [Function: isUint16Array], isUint32Array: [Function: isUint32Array], isInt8Array: [Function: isInt8Array], isInt16Array: [Function: isInt16Array], isInt32Array: [Function: isInt32Array], isFloat16Array: [Function: isFloat16Array], isFloat32Array: [Function: isFloat32Array], isFloat64Array: [Function: isFloat64Array], isBigInt64Array: [Function: isBigInt64Array], isBigUint64Array: [Function: isBigUint64Array], isKeyObject: [Function: value], isCryptoKey: [Function: value] }, parseEnv: [Function: parseEnv], parseArgs: [Function: parseArgs], TextDecoder: [class TextDecoder], TextEncoder: [class TextEncoder], MIMEType: [class MIMEType], MIMEParams: [class MIMEParams], diff: [Function: diff], setTraceSigInt: [Function: setTraceSigInt] }"
> util.inspect(util, { breakLength: Infinity, depth: Infinity })
"{ _errnoException: [Function: _errnoException], _exceptionWithHostPort: [Function: _exceptionWithHostPort], _extend: [Function: deprecated], callbackify: [Function: callbackify], debug: [Function: debuglog], debuglog: [Function: debuglog], deprecate: [Function: deprecate], format: [Function: format], styleText: [Function: styleText], formatWithOptions: [Function: formatWithOptions], getCallSites: [Function: getCallSites], getSystemErrorMap: [Function: getSystemErrorMap], getSystemErrorName: [Function: getSystemErrorName], getSystemErrorMessage: [Function: getSystemErrorMessage], inherits: [Function: inherits], inspect: [Function: inspect] { custom: Symbol(nodejs.util.inspect.custom), colors: [Object: null prototype] { 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 ] }, styles: [Object: null prototype] { special: 'cyan', number: 'yellow', bigint: 'yellow', boolean: 'yellow', undefined: 'grey', null: 'bold', string: 'green', symbol: 'green', date: 'magenta', regexp: 'red', module: 'underline' }, replDefaults: [Getter/Setter] }, isArray: [Function: deprecated], isDeepStrictEqual: [Function: isDeepStrictEqual], promisify: [Function: promisify] { custom: Symbol(nodejs.util.promisify.custom) }, stripVTControlCharacters: [Function: stripVTControlCharacters], toUSVString: [Function: toUSVString], transferableAbortSignal: [Getter], transferableAbortController: [Getter], aborted: [Getter], types: { isArgumentsObject: [Function (anonymous)], isArrayBuffer: [Function (anonymous)], isAsyncFunction: [Function (anonymous)], isBigIntObject: [Function (anonymous)], isBooleanObject: [Function (anonymous)], isDataView: [Function (anonymous)], isDate: [Function (anonymous)], isExternal: [Function (anonymous)], isGeneratorFunction: [Function (anonymous)], isGeneratorObject: [Function (anonymous)], isMap: [Function (anonymous)], isMapIterator: [Function (anonymous)], isModuleNamespaceObject: [Function (anonymous)], isNativeError: [Function (anonymous)], isNumberObject: [Function (anonymous)], isPromise: [Function (anonymous)], isProxy: [Function (anonymous)], isRegExp: [Function (anonymous)], isSet: [Function (anonymous)], isSetIterator: [Function (anonymous)], isSharedArrayBuffer: [Function (anonymous)], isStringObject: [Function (anonymous)], isSymbolObject: [Function (anonymous)], isWeakMap: [Function (anonymous)], isWeakSet: [Function (anonymous)], isAnyArrayBuffer: [Function (anonymous)], isBoxedPrimitive: [Function (anonymous)], isArrayBufferView: [Function: isView], isTypedArray: [Function: isTypedArray], isUint8Array: [Function: isUint8Array], isUint8ClampedArray: [Function: isUint8ClampedArray], isUint16Array: [Function: isUint16Array], isUint32Array: [Function: isUint32Array], isInt8Array: [Function: isInt8Array], isInt16Array: [Function: isInt16Array], isInt32Array: [Function: isInt32Array], isFloat16Array: [Function: isFloat16Array], isFloat32Array: [Function: isFloat32Array], isFloat64Array: [Function: isFloat64Array], isBigInt64Array: [Function: isBigInt64Array], isBigUint64Array: [Function: isBigUint64Array], isKeyObject: [Function: value], isCryptoKey: [Function: value] }, parseEnv: [Function: parseEnv], parseArgs: [Function: parseArgs], TextDecoder: [class TextDecoder], TextEncoder: [class TextEncoder], MIMEType: [class MIMEType], MIMEParams: [class MIMEParams], diff: [Function: diff], setTraceSigInt: [Function: setTraceSigInt] }"
>
$ nvm use 25
Now using node v25.1.0 (npm v11.6.2)
$ node
Welcome to Node.js v25.1.0.
Type ".help" for more information.
> const util = require("node:util")
undefined
> util.inspect(util, { breakLength: Infinity })
"{ _errnoException: [Function: _errnoException], _exceptionWithHostPort: [Function: _exceptionWithHostPort], _extend: [Function: deprecated], callbackify: [Function: callbackify], debug: [Function: debuglog], debuglog: [Function: debuglog], deprecate: [Function: deprecate], format: [Function: format], styleText: [Function: styleText], formatWithOptions: [Function: formatWithOptions], getCallSites: [Function: getCallSites], getSystemErrorMap: [Function: getSystemErrorMap], getSystemErrorName: [Function: getSystemErrorName], getSystemErrorMessage: [Function: getSystemErrorMessage], inherits: [Function: inherits], inspect: [Function: inspect] { custom: Symbol(nodejs.util.inspect.custom), colors: [Object: null prototype] { reset: [Array], bold: [Array], dim: [Array], italic: [Array], underline: [Array], blink: [Array], inverse: [Array], hidden: [Array], strikethrough: [Array], doubleunderline: [Array], black: [Array], red: [Array], green: [Array], yellow: [Array], blue: [Array], magenta: [Array], cyan: [Array], white: [Array], bgBlack: [Array], bgRed: [Array], bgGreen: [Array], bgYellow: [Array], bgBlue: [Array], bgMagenta: [Array], bgCyan: [Array], bgWhite: [Array], framed: [Array], overlined: [Array], gray: [Array], redBright: [Array], greenBright: [Array], yellowBright: [Array], blueBright: [Array], magentaBright: [Array], cyanBright: [Array], whiteBright: [Array], bgGray: [Array], bgRedBright: [Array], bgGreenBright: [Array], bgYellowBright: [Array], bgBlueBright: [Array], bgMagentaBright: [Array], bgCyanBright: [Array], bgWhiteBright: [Array] }, styles: [Object: null prototype] { special: 'cyan', number: 'yellow', bigint: 'yellow', boolean: 'yellow', undefined: 'grey', null: 'bold', string: 'green', symbol: 'green', date: 'magenta', regexp: [Function], module: 'underline' }, replDefaults: [Getter/Setter] }, isArray: [Function: deprecated], isDeepStrictEqual: [Function: isDeepStrictEqual], promisify: [Function: promisify] { custom: Symbol(nodejs.util.promisify.custom) }, stripVTControlCharacters: [Function: stripVTControlCharacters], toUSVString: [Function: toUSVString], transferableAbortSignal: [Getter], transferableAbortController: [Getter], aborted: [Getter], types: { isArgumentsObject: [Function (anonymous)], isArrayBuffer: [Function (anonymous)], isAsyncFunction: [Function (anonymous)], isBigIntObject: [Function (anonymous)], isBooleanObject: [Function (anonymous)], isDataView: [Function (anonymous)], isDate: [Function (anonymous)], isExternal: [Function (anonymous)], isGeneratorFunction: [Function (anonymous)], isGeneratorObject: [Function (anonymous)], isMap: [Function (anonymous)], isMapIterator: [Function (anonymous)], isModuleNamespaceObject: [Function (anonymous)], isNativeError: [Function (anonymous)], isNumberObject: [Function (anonymous)], isPromise: [Function (anonymous)], isProxy: [Function (anonymous)], isRegExp: [Function (anonymous)], isSet: [Function (anonymous)], isSetIterator: [Function (anonymous)], isSharedArrayBuffer: [Function (anonymous)], isStringObject: [Function (anonymous)], isSymbolObject: [Function (anonymous)], isWeakMap: [Function (anonymous)], isWeakSet: [Function (anonymous)], isAnyArrayBuffer: [Function (anonymous)], isBoxedPrimitive: [Function (anonymous)], isArrayBufferView: [Function: isView], isTypedArray: [Function: isTypedArray], isUint8Array: [Function: isUint8Array], isUint8ClampedArray: [Function: isUint8ClampedArray], isUint16Array: [Function: isUint16Array], isUint32Array: [Function: isUint32Array], isInt8Array: [Function: isInt8Array], isInt16Array: [Function: isInt16Array], isInt32Array: [Function: isInt32Array], isFloat16Array: [Function: isFloat16Array], isFloat32Array: [Function: isFloat32Array], isFloat64Array: [Function: isFloat64Array], isBigInt64Array: [Function: isBigInt64Array], isBigUint64Array: [Function: isBigUint64Array], isKeyObject: [Function: value], isCryptoKey: [Function: value] }, parseEnv: [Function: parseEnv], parseArgs: [Function: parseArgs], TextDecoder: [class TextDecoder], TextEncoder: [class TextEncoder], MIMEType: [class MIMEType], MIMEParams: [class MIMEParams], diff: [Function: diff], setTraceSigInt: [Function: setTraceSigInt] }"
> util.inspect(util, { breakLength: Infinity, depth: Infinity })
'{\n' +
  '  _errnoException: [Function: _errnoException],\n' +
  '  _exceptionWithHostPort: [Function: _exceptionWithHostPort],\n' +
  '  _extend: [Function: deprecated],\n' +
  '  callbackify: [Function: callbackify],\n' +
  '  debug: [Function: debuglog],\n' +
  '  debuglog: [Function: debuglog],\n' +
  '  deprecate: [Function: deprecate],\n' +
  '  format: [Function: format],\n' +
  '  styleText: [Function: styleText],\n' +
  '  formatWithOptions: [Function: formatWithOptions],\n' +
  '  getCallSites: [Function: getCallSites],\n' +
  '  getSystemErrorMap: [Function: getSystemErrorMap],\n' +
  '  getSystemErrorName: [Function: getSystemErrorName],\n' +
  '  getSystemErrorMessage: [Function: getSystemErrorMessage],\n' +
  '  inherits: [Function: inherits],\n' +
  '  inspect: [Function: inspect] {\n' +
  '    custom: Symbol(nodejs.util.inspect.custom),\n' +
  '    colors: [Object: null prototype] { 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 ] },\n' +
  "    styles: [Object: null prototype] { special: 'cyan', number: 'yellow', bigint: 'yellow', boolean: 'yellow', undefined: 'grey', null: 'bold', string: 'green', symbol: 'green', date: 'magenta', regexp: [Function: highlightRegExp] { colors: [ 'green', 'red', 'yellow', 'cyan', 'magenta' ] }, module: 'underline' },\n" +
  '    replDefaults: [Getter/Setter]\n' +
  '  },\n' +
  '  isArray: [Function: deprecated],\n' +
  '  isDeepStrictEqual: [Function: isDeepStrictEqual],\n' +
  '  promisify: [Function: promisify] { custom: Symbol(nodejs.util.promisify.custom) },\n' +
  '  stripVTControlCharacters: [Function: stripVTControlCharacters],\n' +
  '  toUSVString: [Function: toUSVString],\n' +
  '  transferableAbortSignal: [Getter],\n' +
  '  transferableAbortController: [Getter],\n' +
  '  aborted: [Getter],\n' +
  '  types: { isArgumentsObject: [Function (anonymous)], isArrayBuffer: [Function (anonymous)], isAsyncFunction: [Function (anonymous)], isBigIntObject: [Function (anonymous)], isBooleanObject: [Function (anonymous)], isDataView: [Function (anonymous)], isDate: [Function (anonymous)], isExternal: [Function (anonymous)], isGeneratorFunction: [Function (anonymous)], isGeneratorObject: [Function (anonymous)], isMap: [Function (anonymous)], isMapIterator: [Function (anonymous)], isModuleNamespaceObject: [Function (anonymous)], isNativeError: [Function (anonymous)], isNumberObject: [Function (anonymous)], isPromise: [Function (anonymous)], isProxy: [Function (anonymous)], isRegExp: [Function (anonymous)], isSet: [Function (anonymous)], isSetIterator: [Function (anonymous)], isSharedArrayBuffer: [Function (anonymous)], isStringObject: [Function (anonymous)], isSymbolObject: [Function (anonymous)], isWeakMap: [Function (anonymous)], isWeakSet: [Function (anonymous)], isAnyArrayBuffer: [Function (anonymous)], isBoxedPrimitive: [Function (anonymous)], isArrayBufferView: [Function: isView], isTypedArray: [Function: isTypedArray], isUint8Array: [Function: isUint8Array], isUint8ClampedArray: [Function: isUint8ClampedArray], isUint16Array: [Function: isUint16Array], isUint32Array: [Function: isUint32Array], isInt8Array: [Function: isInt8Array], isInt16Array: [Function: isInt16Array], isInt32Array: [Function: isInt32Array], isFloat16Array: [Function: isFloat16Array], isFloat32Array: [Function: isFloat32Array], isFloat64Array: [Function: isFloat64Array], isBigInt64Array: [Function: isBigInt64Array], isBigUint64Array: [Function: isBigUint64Array], isKeyObject: [Function: value], isCryptoKey: [Function: value] },\n' +
  '  parseEnv: [Function: parseEnv],\n' +
  '  parseArgs: [Function: parseArgs],\n' +
  '  TextDecoder: [class TextDecoder],\n' +
  '  TextEncoder: [class TextEncoder],\n' +
  '  MIMEType: [class MIMEType],\n' +
  '  MIMEParams: [class MIMEParams],\n' +
  '  diff: [Function: diff],\n' +
  '  setTraceSigInt: [Function: setTraceSigInt]\n' +
  '}'
How often does it reproduce? Is there a required condition?

Always reproducible when both breakLength and depth are set to Infinity.

What is the expected behavior? Why is that the expected behavior?

According to the Node.js documentation:

breakLength <integer>
The length at which input values are split across multiple lines.
Set to Infinity to format the input as a single line (in combination with compact set to true or any number >= 1).
Default: 80.

Therefore, when breakLength is set to Infinity, the output should always be rendered as a single line, regardless of object depth or size.

What do you see instead?

The output contains multiple lines with indentation, even though breakLength is set to Infinity.

This happens only when depth is also set to Infinity.

Additional information

No response

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia riproducendo l’esempio minimo di util.inspect() su Node.js v24 e v25, sia con breakLength: Infinity sia con depth: Infinity. Analizza l’implementazione di util.inspect() e la copertura esistente per queste opzioni; il lavoro è completo quando le opzioni combinate producono l’output atteso su una singola riga senza introdurre regressioni negli altri casi descritti.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
javascript, nodejs
Ambito
backend
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.