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 901d3d0

Browse filesBrowse files
BridgeARaddaleax
authored andcommitted
util: inspect ArrayBuffers contents as well
Inspecting an ArrayBuffer now also shows their binary contents. PR-URL: #25006 Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 4794cf6 commit 901d3d0
Copy full SHA for 901d3d0

File tree

Expand file treeCollapse file tree

5 files changed

+65
-30
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

5 files changed

+65
-30
lines changed
Open diff view settings
Collapse file

‎doc/api/util.md‎

Copy file name to clipboardExpand all lines: doc/api/util.md
+3Lines changed: 3 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,9 @@ stream.write('With ES6');
375375
<!-- YAML
376376
added: v0.3.0
377377
changes:
378+
- version: REPLACEME
379+
pr-url: https://github.com/nodejs/node/pull/25006
380+
description: ArrayBuffers now also show their binary contents.
378381
- version: v11.5.0
379382
pr-url: https://github.com/nodejs/node/pull/24852
380383
description: The `getters` option is supported now.
Collapse file

‎lib/internal/util/inspect.js‎

Copy file name to clipboardExpand all lines: lib/internal/util/inspect.js
+21-5Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const setValues = uncurryThis(Set.prototype.values);
8989
const mapEntries = uncurryThis(Map.prototype.entries);
9090
const dateGetTime = uncurryThis(Date.prototype.getTime);
9191
const hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
92+
let hexSlice;
9293

9394
const inspectDefaultOptions = Object.seal({
9495
showHidden: false,
@@ -494,7 +495,7 @@ function noPrototypeIterator(ctx, value, recurseTimes) {
494495
// Note: using `formatValue` directly requires the indentation level to be
495496
// corrected by setting `ctx.indentationLvL += diff` and then to decrease the
496497
// value afterwards again.
497-
function formatValue(ctx, value, recurseTimes) {
498+
function formatValue(ctx, value, recurseTimes, typedArray) {
498499
// Primitive types cannot have properties.
499500
if (typeof value !== 'object' && typeof value !== 'function') {
500501
return formatPrimitive(ctx.stylize, value, ctx);
@@ -542,10 +543,10 @@ function formatValue(ctx, value, recurseTimes) {
542543
if (ctx.seen.indexOf(value) !== -1)
543544
return ctx.stylize('[Circular]', 'special');
544545

545-
return formatRaw(ctx, value, recurseTimes);
546+
return formatRaw(ctx, value, recurseTimes, typedArray);
546547
}
547548

548-
function formatRaw(ctx, value, recurseTimes) {
549+
function formatRaw(ctx, value, recurseTimes, typedArray) {
549550
let keys;
550551

551552
const constructor = getConstructorName(value, ctx);
@@ -678,9 +679,12 @@ function formatRaw(ctx, value, recurseTimes) {
678679
const arrayType = isArrayBuffer(value) ? 'ArrayBuffer' :
679680
'SharedArrayBuffer';
680681
const prefix = getPrefix(constructor, tag, arrayType);
681-
if (keys.length === 0)
682+
if (typedArray === undefined) {
683+
formatter = formatArrayBuffer;
684+
} else if (keys.length === 0) {
682685
return prefix +
683686
`{ byteLength: ${formatNumber(ctx.stylize, value.byteLength)} }`;
687+
}
684688
braces[0] = `${prefix}{`;
685689
keys.unshift('byteLength');
686690
} else if (isDataView(value)) {
@@ -941,6 +945,18 @@ function formatSpecialArray(ctx, value, recurseTimes, maxLength, output, i) {
941945
return output;
942946
}
943947

948+
function formatArrayBuffer(ctx, value) {
949+
const buffer = new Uint8Array(value);
950+
if (hexSlice === undefined)
951+
hexSlice = uncurryThis(require('buffer').Buffer.prototype.hexSlice);
952+
let str = hexSlice(buffer, 0, Math.min(ctx.maxArrayLength, buffer.length))
953+
.replace(/(.{2})/g, '$1 ').trim();
954+
const remaining = buffer.length - ctx.maxArrayLength;
955+
if (remaining > 0)
956+
str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
957+
return [`${ctx.stylize('[Uint8Contents]', 'special')}: <${str}>`];
958+
}
959+
944960
function formatArray(ctx, value, recurseTimes) {
945961
const valLen = value.length;
946962
const len = Math.min(Math.max(0, ctx.maxArrayLength), valLen);
@@ -981,7 +997,7 @@ function formatTypedArray(ctx, value, recurseTimes) {
981997
'byteOffset',
982998
'buffer'
983999
]) {
984-
const str = formatValue(ctx, value[key], recurseTimes);
1000+
const str = formatValue(ctx, value[key], recurseTimes, true);
9851001
output.push(`[${key}]: ${str}`);
9861002
}
9871003
ctx.indentationLvl -= 2;
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-util-format-shared-arraybuffer.js
-6Lines changed: 0 additions & 6 deletions
This file was deleted.
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-util-format.js
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,8 @@ Object.setPrototypeOf(BadCustomError.prototype, Error.prototype);
308308
Object.setPrototypeOf(BadCustomError, Error);
309309
assert.strictEqual(util.format(new BadCustomError('foo')),
310310
'[BadCustomError: foo]');
311+
312+
assert.strictEqual(
313+
util.format(new SharedArrayBuffer(4)),
314+
'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
315+
);
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-util-inspect.js
+36-19Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -115,70 +115,86 @@ assert(!/Object/.test(
115115
util.inspect({ a: { a: { a: { a: {} } } } }, undefined, null, true)
116116
));
117117

118-
for (const showHidden of [true, false]) {
119-
const ab = new ArrayBuffer(4);
118+
{
119+
const showHidden = true;
120+
const ab = new Uint8Array([1, 2, 3, 4]).buffer;
120121
const dv = new DataView(ab, 1, 2);
121122
assert.strictEqual(
122123
util.inspect(ab, showHidden),
123-
'ArrayBuffer { byteLength: 4 }'
124+
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }'
124125
);
125126
assert.strictEqual(util.inspect(new DataView(ab, 1, 2), showHidden),
126127
'DataView {\n' +
127128
' byteLength: 2,\n' +
128129
' byteOffset: 1,\n' +
129-
' buffer: ArrayBuffer { byteLength: 4 } }');
130+
' buffer:\n' +
131+
' ArrayBuffer { [Uint8Contents]: ' +
132+
'<01 02 03 04>, byteLength: 4 } }');
130133
assert.strictEqual(
131134
util.inspect(ab, showHidden),
132-
'ArrayBuffer { byteLength: 4 }'
135+
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }'
133136
);
134137
assert.strictEqual(util.inspect(dv, showHidden),
135138
'DataView {\n' +
136139
' byteLength: 2,\n' +
137140
' byteOffset: 1,\n' +
138-
' buffer: ArrayBuffer { byteLength: 4 } }');
141+
' buffer:\n' +
142+
' ArrayBuffer { [Uint8Contents]: ' +
143+
'<01 02 03 04>, byteLength: 4 } }');
139144
ab.x = 42;
140145
dv.y = 1337;
141146
assert.strictEqual(util.inspect(ab, showHidden),
142-
'ArrayBuffer { byteLength: 4, x: 42 }');
147+
'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, ' +
148+
'byteLength: 4, x: 42 }');
143149
assert.strictEqual(util.inspect(dv, showHidden),
144150
'DataView {\n' +
145151
' byteLength: 2,\n' +
146152
' byteOffset: 1,\n' +
147-
' buffer: ArrayBuffer { byteLength: 4, x: 42 },\n' +
153+
' buffer:\n' +
154+
' ArrayBuffer { [Uint8Contents]: <01 02 03 04>, ' +
155+
'byteLength: 4, x: 42 },\n' +
148156
' y: 1337 }');
149157
}
150158

151159
// Now do the same checks but from a different context.
152-
for (const showHidden of [true, false]) {
160+
{
161+
const showHidden = false;
153162
const ab = vm.runInNewContext('new ArrayBuffer(4)');
154163
const dv = vm.runInNewContext('new DataView(ab, 1, 2)', { ab });
155164
assert.strictEqual(
156165
util.inspect(ab, showHidden),
157-
'ArrayBuffer { byteLength: 4 }'
166+
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
158167
);
159168
assert.strictEqual(util.inspect(new DataView(ab, 1, 2), showHidden),
160169
'DataView {\n' +
161170
' byteLength: 2,\n' +
162171
' byteOffset: 1,\n' +
163-
' buffer: ArrayBuffer { byteLength: 4 } }');
172+
' buffer:\n' +
173+
' ArrayBuffer { [Uint8Contents]: <00 00 00 00>, ' +
174+
'byteLength: 4 } }');
164175
assert.strictEqual(
165176
util.inspect(ab, showHidden),
166-
'ArrayBuffer { byteLength: 4 }'
177+
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
167178
);
168179
assert.strictEqual(util.inspect(dv, showHidden),
169180
'DataView {\n' +
170181
' byteLength: 2,\n' +
171182
' byteOffset: 1,\n' +
172-
' buffer: ArrayBuffer { byteLength: 4 } }');
183+
' buffer:\n' +
184+
' ArrayBuffer { [Uint8Contents]: <00 00 00 00>, ' +
185+
'byteLength: 4 } }');
173186
ab.x = 42;
174187
dv.y = 1337;
175188
assert.strictEqual(util.inspect(ab, showHidden),
176-
'ArrayBuffer { byteLength: 4, x: 42 }');
189+
'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, ' +
190+
'byteLength: 4, x: 42 }');
177191
assert.strictEqual(util.inspect(dv, showHidden),
178192
'DataView {\n' +
179193
' byteLength: 2,\n' +
180194
' byteOffset: 1,\n' +
181-
' buffer: ArrayBuffer { byteLength: 4, x: 42 },\n' +
195+
' buffer:\n' +
196+
' ArrayBuffer { [Uint8Contents]: <00 00 00 00>,' +
197+
' byteLength: 4, x: 42 },\n' +
182198
' y: 1337 }');
183199
}
184200

@@ -1639,13 +1655,14 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");
16391655
[new Float64Array(2), '[Float64Array: null prototype] [ 0, 0 ]'],
16401656
[new BigInt64Array(2), '[BigInt64Array: null prototype] [ 0n, 0n ]'],
16411657
[new BigUint64Array(2), '[BigUint64Array: null prototype] [ 0n, 0n ]'],
1642-
[new ArrayBuffer(16), '[ArrayBuffer: null prototype] ' +
1643-
'{ byteLength: undefined }'],
1658+
[new ArrayBuffer(16), '[ArrayBuffer: null prototype] {\n' +
1659+
' [Uint8Contents]: <00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>,\n' +
1660+
' byteLength: undefined }'],
16441661
[new DataView(new ArrayBuffer(16)),
16451662
'[DataView: null prototype] {\n byteLength: undefined,\n ' +
1646-
'byteOffset: undefined,\n buffer: undefined }'],
1663+
'byteOffset: undefined,\n buffer: undefined }'],
16471664
[new SharedArrayBuffer(2), '[SharedArrayBuffer: null prototype] ' +
1648-
'{ byteLength: undefined }'],
1665+
'{ [Uint8Contents]: <00 00>, byteLength: undefined }'],
16491666
[/foobar/, '[RegExp: null prototype] /foobar/']
16501667
].forEach(([value, expected]) => {
16511668
assert.strictEqual(

0 commit comments

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