Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 748d4f6

Browse filesBrowse files
BridgeARaduh95
authored andcommitted
util: mark special properties when inspecting them
This makes sure special properties (such as a byteLength, buffer, and more) are marked that they are not regular properties. They are mostly getters, that just seemed even more of a breaking change. Thus, they just use square brackets for now. On top of that, it makes inspecting detached DataViews robust. Inspecting those failed so far. PR-URL: #60131 Reviewed-By: Jordan Harband <ljharb@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent 34e4c8c commit 748d4f6
Copy full SHA for 748d4f6

File tree

Expand file treeCollapse file tree

3 files changed

+103
-79
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+103
-79
lines changed
Open diff view settings
Collapse file

‎lib/internal/util/inspect.js‎

Copy file name to clipboardExpand all lines: lib/internal/util/inspect.js
+41-28Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ const {
111111
StringPrototypeSplit,
112112
StringPrototypeStartsWith,
113113
StringPrototypeToLowerCase,
114-
StringPrototypeTrim,
115114
StringPrototypeValueOf,
116115
SymbolIterator,
117116
SymbolPrototypeToString,
@@ -972,6 +971,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
972971
const filter = ctx.showHidden ? ALL_PROPERTIES : ONLY_ENUMERABLE;
973972

974973
let extrasType = kObjectType;
974+
let extraKeys;
975975

976976
// Iterators and the rest are split to reduce checks.
977977
// We have to check all values in case the constructor is set to null.
@@ -1027,6 +1027,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
10271027
// bound function is required to reconstruct missing information.
10281028
formatter = FunctionPrototypeBind(formatTypedArray, null, bound, size);
10291029
extrasType = kArrayExtrasType;
1030+
1031+
if (ctx.showHidden) {
1032+
extraKeys = ['BYTES_PER_ELEMENT', 'length', 'byteLength', 'byteOffset', 'buffer'];
1033+
typedArray = true;
1034+
}
10301035
} else if (isMapIterator(value)) {
10311036
keys = getKeys(value, ctx.showHidden);
10321037
braces = getIteratorBraces('Map', tag);
@@ -1095,14 +1100,14 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
10951100
formatter = formatArrayBuffer;
10961101
} else if (keys.length === 0 && protoProps === undefined) {
10971102
return prefix +
1098-
`{ byteLength: ${formatNumber(ctx.stylize, value.byteLength, false)} }`;
1103+
`{ [byteLength]: ${formatNumber(ctx.stylize, value.byteLength, false)} }`;
10991104
}
11001105
braces[0] = `${prefix}{`;
1101-
ArrayPrototypeUnshift(keys, 'byteLength');
1106+
extraKeys = ['byteLength'];
11021107
} else if (isDataView(value)) {
11031108
braces[0] = `${getPrefix(constructor, tag, 'DataView')}{`;
11041109
// .buffer goes last, it's not a primitive like the others.
1105-
ArrayPrototypeUnshift(keys, 'byteLength', 'byteOffset', 'buffer');
1110+
extraKeys = ['byteLength', 'byteOffset', 'buffer'];
11061111
} else if (isPromise(value)) {
11071112
braces[0] = `${getPrefix(constructor, tag, 'Promise')}{`;
11081113
formatter = formatPromise;
@@ -1152,6 +1157,18 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
11521157
const indentationLvl = ctx.indentationLvl;
11531158
try {
11541159
output = formatter(ctx, value, recurseTimes);
1160+
if (extraKeys !== undefined) {
1161+
for (i = 0; i < extraKeys.length; i++) {
1162+
let formatted;
1163+
try {
1164+
formatted = formatExtraProperties(ctx, value, recurseTimes, extraKeys[i], typedArray);
1165+
} catch {
1166+
const tempValue = { [extraKeys[i]]: value.buffer[extraKeys[i]] };
1167+
formatted = formatExtraProperties(ctx, tempValue, recurseTimes, extraKeys[i], typedArray);
1168+
}
1169+
ArrayPrototypePush(output, formatted);
1170+
}
1171+
}
11551172
for (i = 0; i < keys.length; i++) {
11561173
ArrayPrototypePush(
11571174
output,
@@ -2011,11 +2028,15 @@ function formatArrayBuffer(ctx, value) {
20112028
}
20122029
if (hexSlice === undefined)
20132030
hexSlice = uncurryThis(require('buffer').Buffer.prototype.hexSlice);
2014-
let str = StringPrototypeTrim(RegExpPrototypeSymbolReplace(
2015-
/(.{2})/g,
2016-
hexSlice(buffer, 0, MathMin(ctx.maxArrayLength, buffer.length)),
2017-
'$1 ',
2018-
));
2031+
const rawString = hexSlice(buffer, 0, MathMin(ctx.maxArrayLength, buffer.length));
2032+
let str = '';
2033+
let i = 0;
2034+
for (; i < rawString.length - 2; i += 2) {
2035+
str += `${rawString[i]}${rawString[i + 1]} `;
2036+
}
2037+
if (rawString.length > 0) {
2038+
str += `${rawString[i]}${rawString[i + 1]}`;
2039+
}
20192040
const remaining = buffer.length - ctx.maxArrayLength;
20202041
if (remaining > 0)
20212042
str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
@@ -2042,7 +2063,7 @@ function formatArray(ctx, value, recurseTimes) {
20422063
return output;
20432064
}
20442065

2045-
function formatTypedArray(value, length, ctx, ignored, recurseTimes) {
2066+
function formatTypedArray(value, length, ctx) {
20462067
const maxLength = MathMin(MathMax(0, ctx.maxArrayLength), length);
20472068
const remaining = value.length - maxLength;
20482069
const output = new Array(maxLength);
@@ -2055,22 +2076,6 @@ function formatTypedArray(value, length, ctx, ignored, recurseTimes) {
20552076
if (remaining > 0) {
20562077
output[maxLength] = remainingText(remaining);
20572078
}
2058-
if (ctx.showHidden) {
2059-
// .buffer goes last, it's not a primitive like the others.
2060-
// All besides `BYTES_PER_ELEMENT` are actually getters.
2061-
ctx.indentationLvl += 2;
2062-
for (const key of [
2063-
'BYTES_PER_ELEMENT',
2064-
'length',
2065-
'byteLength',
2066-
'byteOffset',
2067-
'buffer',
2068-
]) {
2069-
const str = formatValue(ctx, value[key], recurseTimes, true);
2070-
ArrayPrototypePush(output, `[${key}]: ${str}`);
2071-
}
2072-
ctx.indentationLvl -= 2;
2073-
}
20742079
return output;
20752080
}
20762081

@@ -2218,12 +2223,20 @@ function formatPromise(ctx, value, recurseTimes) {
22182223
return output;
22192224
}
22202225

2226+
function formatExtraProperties(ctx, value, recurseTimes, key, typedArray) {
2227+
ctx.indentationLvl += 2;
2228+
const str = formatValue(ctx, value[key], recurseTimes, typedArray);
2229+
ctx.indentationLvl -= 2;
2230+
2231+
// These entries are mainly getters. Should they be formatted like getters?
2232+
return ctx.stylize(`[${key}]: ${str}`, 'string');
2233+
}
2234+
22212235
function formatProperty(ctx, value, recurseTimes, key, type, desc,
22222236
original = value) {
22232237
let name, str;
22242238
let extra = ' ';
2225-
desc ||= ObjectGetOwnPropertyDescriptor(value, key) ||
2226-
{ value: value[key], enumerable: true };
2239+
desc ??= ObjectGetOwnPropertyDescriptor(value, key);
22272240
if (desc.value !== undefined) {
22282241
const diff = (ctx.compact !== true || type !== kObjectType) ? 2 : 3;
22292242
ctx.indentationLvl += diff;
Collapse file

‎test/parallel/test-util-format.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-util-format.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ assert.strictEqual(
588588

589589
assert.strictEqual(
590590
util.format(new SharedArrayBuffer(4)),
591-
'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
591+
'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, [byteLength]: 4 }'
592592
);
593593

594594
assert.strictEqual(
Collapse file

‎test/parallel/test-util-inspect.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-util-inspect.js
+61-50Lines changed: 61 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -172,56 +172,67 @@ assert.doesNotMatch(
172172
const dv = new DataView(ab, 1, 2);
173173
assert.strictEqual(
174174
util.inspect(ab, showHidden),
175-
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }'
175+
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, [byteLength]: 4 }'
176176
);
177177
assert.strictEqual(util.inspect(new DataView(ab, 1, 2), showHidden),
178178
'DataView {\n' +
179-
' byteLength: 2,\n' +
180-
' byteOffset: 1,\n' +
181-
' buffer: ArrayBuffer {' +
182-
' [Uint8Contents]: <01 02 03 04>, byteLength: 4 }\n}');
179+
' [byteLength]: 2,\n' +
180+
' [byteOffset]: 1,\n' +
181+
' [buffer]: ArrayBuffer {' +
182+
' [Uint8Contents]: <01 02 03 04>, [byteLength]: 4 }\n}');
183183
assert.strictEqual(
184184
util.inspect(ab, showHidden),
185-
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }'
185+
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, [byteLength]: 4 }'
186186
);
187187
assert.strictEqual(util.inspect(dv, showHidden),
188188
'DataView {\n' +
189-
' byteLength: 2,\n' +
190-
' byteOffset: 1,\n' +
191-
' buffer: ArrayBuffer { [Uint8Contents]: ' +
192-
'<01 02 03 04>, byteLength: 4 }\n}');
189+
' [byteLength]: 2,\n' +
190+
' [byteOffset]: 1,\n' +
191+
' [buffer]: ArrayBuffer { [Uint8Contents]: ' +
192+
'<01 02 03 04>, [byteLength]: 4 }\n}');
193193
ab.x = 42;
194194
dv.y = 1337;
195195
assert.strictEqual(util.inspect(ab, showHidden),
196196
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, ' +
197-
'byteLength: 4, x: 42 }');
198-
assert.strictEqual(util.inspect(dv, showHidden),
197+
'[byteLength]: 4, x: 42 }');
198+
assert.strictEqual(util.inspect(dv, { showHidden, breakLength: 82 }),
199199
'DataView {\n' +
200-
' byteLength: 2,\n' +
201-
' byteOffset: 1,\n' +
202-
' buffer: ArrayBuffer { [Uint8Contents]: <01 02 03 04>,' +
203-
' byteLength: 4, x: 42 },\n' +
200+
' [byteLength]: 2,\n' +
201+
' [byteOffset]: 1,\n' +
202+
' [buffer]: ArrayBuffer { [Uint8Contents]: <01 02 03 04>,' +
203+
' [byteLength]: 4, x: 42 },\n' +
204204
' y: 1337\n}');
205205
}
206206

207207
{
208208
const ab = new ArrayBuffer(42);
209+
const dv = new DataView(ab);
210+
209211
assert.strictEqual(ab.byteLength, 42);
210212
new MessageChannel().port1.postMessage(ab, [ ab ]);
211213
assert.strictEqual(ab.byteLength, 0);
212214
assert.strictEqual(util.inspect(ab),
213-
'ArrayBuffer { (detached), byteLength: 0 }');
215+
'ArrayBuffer { (detached), [byteLength]: 0 }');
216+
217+
assert.strictEqual(
218+
util.inspect(dv),
219+
'DataView {\n' +
220+
' [byteLength]: 0,\n' +
221+
' [byteOffset]: undefined,\n' +
222+
' [buffer]: ArrayBuffer { (detached), [byteLength]: 0 }\n' +
223+
' }',
224+
);
214225
}
215226

216227
// Truncate output for ArrayBuffers using plural or singular bytes
217228
{
218229
const ab = new ArrayBuffer(3);
219-
assert.strictEqual(util.inspect(ab, { showHidden: true, maxArrayLength: 2 }),
230+
assert.strictEqual(util.inspect(ab, { showHidden: true, maxArrayLength: 2, breakLength: 82 }),
220231
'ArrayBuffer { [Uint8Contents]' +
221-
': <00 00 ... 1 more byte>, byteLength: 3 }');
222-
assert.strictEqual(util.inspect(ab, { showHidden: true, maxArrayLength: 1 }),
232+
': <00 00 ... 1 more byte>, [byteLength]: 3 }');
233+
assert.strictEqual(util.inspect(ab, { showHidden: true, maxArrayLength: 1, breakLength: 82 }),
223234
'ArrayBuffer { [Uint8Contents]' +
224-
': <00 ... 2 more bytes>, byteLength: 3 }');
235+
': <00 ... 2 more bytes>, [byteLength]: 3 }');
225236
}
226237

227238
// Now do the same checks but from a different context.
@@ -231,35 +242,35 @@ assert.doesNotMatch(
231242
const dv = vm.runInNewContext('new DataView(ab, 1, 2)', { ab });
232243
assert.strictEqual(
233244
util.inspect(ab, showHidden),
234-
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
245+
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, [byteLength]: 4 }'
235246
);
236247
assert.strictEqual(util.inspect(new DataView(ab, 1, 2), showHidden),
237248
'DataView {\n' +
238-
' byteLength: 2,\n' +
239-
' byteOffset: 1,\n' +
240-
' buffer: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
241-
' byteLength: 4 }\n}');
249+
' [byteLength]: 2,\n' +
250+
' [byteOffset]: 1,\n' +
251+
' [buffer]: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
252+
' [byteLength]: 4 }\n}');
242253
assert.strictEqual(
243254
util.inspect(ab, showHidden),
244-
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
255+
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, [byteLength]: 4 }'
245256
);
246257
assert.strictEqual(util.inspect(dv, showHidden),
247258
'DataView {\n' +
248-
' byteLength: 2,\n' +
249-
' byteOffset: 1,\n' +
250-
' buffer: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
251-
' byteLength: 4 }\n}');
259+
' [byteLength]: 2,\n' +
260+
' [byteOffset]: 1,\n' +
261+
' [buffer]: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
262+
' [byteLength]: 4 }\n}');
252263
ab.x = 42;
253264
dv.y = 1337;
254265
assert.strictEqual(util.inspect(ab, showHidden),
255266
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, ' +
256-
'byteLength: 4, x: 42 }');
257-
assert.strictEqual(util.inspect(dv, showHidden),
267+
'[byteLength]: 4, x: 42 }');
268+
assert.strictEqual(util.inspect(dv, { showHidden, breakLength: 82 }),
258269
'DataView {\n' +
259-
' byteLength: 2,\n' +
260-
' byteOffset: 1,\n' +
261-
' buffer: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
262-
' byteLength: 4, x: 42 },\n' +
270+
' [byteLength]: 2,\n' +
271+
' [byteOffset]: 1,\n' +
272+
' [buffer]: ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
273+
' [byteLength]: 4, x: 42 },\n' +
263274
' y: 1337\n}');
264275
}
265276

@@ -286,7 +297,7 @@ assert.doesNotMatch(
286297
` [length]: ${length},\n` +
287298
` [byteLength]: ${byteLength},\n` +
288299
' [byteOffset]: 0,\n' +
289-
` [buffer]: ArrayBuffer { byteLength: ${byteLength} }\n]`);
300+
` [buffer]: ArrayBuffer { [byteLength]: ${byteLength} }\n]`);
290301
assert.strictEqual(
291302
util.inspect(array, false),
292303
`${constructor.name}(${length}) [ 65, 97 ]`
@@ -320,7 +331,7 @@ assert.doesNotMatch(
320331
` [length]: ${length},\n` +
321332
` [byteLength]: ${byteLength},\n` +
322333
' [byteOffset]: 0,\n' +
323-
` [buffer]: ArrayBuffer { byteLength: ${byteLength} }\n]`);
334+
` [buffer]: ArrayBuffer { [byteLength]: ${byteLength} }\n]`);
324335
assert.strictEqual(
325336
util.inspect(array, false),
326337
`${constructor.name}(${length}) [ 65, 97 ]`
@@ -1837,7 +1848,7 @@ util.inspect(process);
18371848
' [byteLength]: 0,',
18381849
' [byteOffset]: 0,',
18391850
' [buffer]: ArrayBuffer {',
1840-
' byteLength: 0,',
1851+
' [byteLength]: 0,',
18411852
' foo: true',
18421853
' }',
18431854
' ],',
@@ -1855,7 +1866,7 @@ util.inspect(process);
18551866
' [byteLength]: 0,',
18561867
' [byteOffset]: 0,',
18571868
' [buffer]: ArrayBuffer {',
1858-
' byteLength: 0,',
1869+
' [byteLength]: 0,',
18591870
' foo: true',
18601871
' }',
18611872
' ],',
@@ -1885,7 +1896,7 @@ util.inspect(process);
18851896
' [length]: 0,',
18861897
' [byteLength]: 0,',
18871898
' [byteOffset]: 0,',
1888-
' [buffer]: ArrayBuffer { byteLength: 0, foo: true }',
1899+
' [buffer]: ArrayBuffer { [byteLength]: 0, foo: true }',
18891900
' ],',
18901901
' [Set Iterator] {',
18911902
' [ 1, 2, [length]: 2 ],',
@@ -1896,7 +1907,7 @@ util.inspect(process);
18961907
' [length]: 0,',
18971908
' [byteLength]: 0,',
18981909
' [byteOffset]: 0,',
1899-
' [buffer]: ArrayBuffer { byteLength: 0, foo: true }',
1910+
' [buffer]: ArrayBuffer { [byteLength]: 0, foo: true }',
19001911
' ],',
19011912
' [Circular *1],',
19021913
" [Symbol(Symbol.toStringTag)]: 'Map Iterator'",
@@ -1924,7 +1935,7 @@ util.inspect(process);
19241935
' [byteLength]: 0,',
19251936
' [byteOffset]: 0,',
19261937
' [buffer]: ArrayBuffer {',
1927-
' byteLength: 0,',
1938+
' [byteLength]: 0,',
19281939
' foo: true } ],',
19291940
' [Set Iterator] {',
19301941
' [ 1,',
@@ -1938,7 +1949,7 @@ util.inspect(process);
19381949
' [byteLength]: 0,',
19391950
' [byteOffset]: 0,',
19401951
' [buffer]: ArrayBuffer {',
1941-
' byteLength: 0,',
1952+
' [byteLength]: 0,',
19421953
' foo: true } ],',
19431954
' [Circular *1],',
19441955
' [Symbol(Symbol.toStringTag)]:',
@@ -2244,12 +2255,12 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");
22442255
[new BigUint64Array(2), '[BigUint64Array(2): null prototype] [ 0n, 0n ]'],
22452256
[new ArrayBuffer(16), '[ArrayBuffer: null prototype] {\n' +
22462257
' [Uint8Contents]: <00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>,\n' +
2247-
' byteLength: undefined\n}'],
2258+
' [byteLength]: undefined\n}'],
22482259
[new DataView(new ArrayBuffer(16)),
2249-
'[DataView: null prototype] {\n byteLength: undefined,\n ' +
2250-
'byteOffset: undefined,\n buffer: undefined\n}'],
2260+
'[DataView: null prototype] {\n [byteLength]: undefined,\n ' +
2261+
'[byteOffset]: undefined,\n [buffer]: undefined\n}'],
22512262
[new SharedArrayBuffer(2), '[SharedArrayBuffer: null prototype] ' +
2252-
'{\n [Uint8Contents]: <00 00>,\n byteLength: undefined\n}'],
2263+
'{\n [Uint8Contents]: <00 00>,\n [byteLength]: undefined\n}'],
22532264
[/foobar/, '[RegExp: null prototype] /foobar/'],
22542265
[new Date('Sun, 14 Feb 2010 11:48:40 GMT'),
22552266
'[Date: null prototype] 2010-02-14T11:48:40.000Z'],
@@ -3632,7 +3643,7 @@ assert.strictEqual(
36323643
assert.strictEqual(
36333644
util.inspect(o),
36343645
'{\n' +
3635-
' arrayBuffer: ArrayBuffer { [Uint8Contents]: <>, byteLength: 0 },\n' +
3646+
' arrayBuffer: ArrayBuffer { [Uint8Contents]: <>, [byteLength]: 0 },\n' +
36363647
' buffer: <Buffer 48 65 6c 6c 6f>,\n' +
36373648
' typedArray: TypedArray(5) [Uint8Array] [ 72, 101, 108, 108, 111 ],\n' +
36383649
' array: [],\n' +

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.