From cdf6471234d3ba6d0647321081d0ee741640d466 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sun, 12 Aug 2018 22:27:45 +0200 Subject: [PATCH] util: fix sparse array inspection For very special sparse arrays it was possible that util.inspect visualized the entries not in the intended way. PR-URL: https://github.com/nodejs/node/pull/22283 Reviewed-By: James M Snell Reviewed-By: Trivikram Kamat --- lib/util.js | 40 ++++++++++++++---------------- test/parallel/test-util-inspect.js | 13 ++++++++++ 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/util.js b/lib/util.js index b427895ebd5c44..d36225a800f5be 100644 --- a/lib/util.js +++ b/lib/util.js @@ -843,33 +843,29 @@ function formatNamespaceObject(ctx, value, recurseTimes, keys) { function formatSpecialArray(ctx, value, recurseTimes, keys, maxLength, valLen) { const output = []; const keyLen = keys.length; - let visibleLength = 0; let i = 0; - if (keyLen !== 0 && numberRegExp.test(keys[0])) { - for (const key of keys) { - if (visibleLength === maxLength) + for (const key of keys) { + if (output.length === maxLength) + break; + const index = +key; + // Arrays can only have up to 2^32 - 1 entries + if (index > 2 ** 32 - 2) + break; + if (`${i}` !== key) { + if (!numberRegExp.test(key)) break; - const index = +key; - // Arrays can only have up to 2^32 - 1 entries - if (index > 2 ** 32 - 2) + const emptyItems = index - i; + const ending = emptyItems > 1 ? 's' : ''; + const message = `<${emptyItems} empty item${ending}>`; + output.push(ctx.stylize(message, 'undefined')); + i = index; + if (output.length === maxLength) break; - if (i !== index) { - if (!numberRegExp.test(key)) - break; - const emptyItems = index - i; - const ending = emptyItems > 1 ? 's' : ''; - const message = `<${emptyItems} empty item${ending}>`; - output.push(ctx.stylize(message, 'undefined')); - i = index; - if (++visibleLength === maxLength) - break; - } - output.push(formatProperty(ctx, value, recurseTimes, key, 1)); - visibleLength++; - i++; } + output.push(formatProperty(ctx, value, recurseTimes, key, 1)); + i++; } - if (i < valLen && visibleLength !== maxLength) { + if (i < valLen && output.length !== maxLength) { const len = valLen - i; const ending = len > 1 ? 's' : ''; const message = `<${len} empty item${ending}>`; diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 183fbb16e39c9e..1e390f648bff42 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -345,6 +345,19 @@ assert.strictEqual( "[ <2 empty items>, '00': 1, '01': 2 ]"); assert.strictEqual(util.inspect(arr2, { showHidden: true }), "[ <2 empty items>, [length]: 2, '00': 1, '01': 2 ]"); + delete arr2['00']; + arr2[0] = 0; + assert.strictEqual(util.inspect(arr2), + "[ 0, <1 empty item>, '01': 2 ]"); + assert.strictEqual(util.inspect(arr2, { showHidden: true }), + "[ 0, <1 empty item>, [length]: 2, '01': 2 ]"); + delete arr2['01']; + arr2[2 ** 32 - 2] = 'max'; + arr2[2 ** 32 - 1] = 'too far'; + assert.strictEqual( + util.inspect(arr2), + "[ 0, <4294967293 empty items>, 'max', '4294967295': 'too far' ]" + ); const arr3 = []; arr3[-1] = -1;