GeezerVison is showing github.com — util: inspect ArrayBuffers contents as well · nodejs/node@901d3d0
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file 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 number | Diff line number | Diff line change |
|---|
@@ -375,6 +375,9 @@ stream.write('With ES6'); | 375 | 375 | <!-- YAML | 376 | 376 | added: v0.3.0 | 377 | 377 | changes: | | 378 | + - version: REPLACEME | | 379 | + pr-url: https://github.com/nodejs/node/pull/25006 | | 380 | + description: ArrayBuffers now also show their binary contents. | 378 | 381 | - version: v11.5.0 | 379 | 382 | pr-url: https://github.com/nodejs/node/pull/24852 | 380 | 383 | description: The `getters` option is supported now. | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/util/inspect.js +21-5Lines changed: 21 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -89,6 +89,7 @@ const setValues = uncurryThis(Set.prototype.values); | 89 | 89 | const mapEntries = uncurryThis(Map.prototype.entries); | 90 | 90 | const dateGetTime = uncurryThis(Date.prototype.getTime); | 91 | 91 | const hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty); | | 92 | +let hexSlice; | 92 | 93 |
| 93 | 94 | const inspectDefaultOptions = Object.seal({ | 94 | 95 | showHidden: false, | @@ -494,7 +495,7 @@ function noPrototypeIterator(ctx, value, recurseTimes) { | 494 | 495 | // Note: using `formatValue` directly requires the indentation level to be | 495 | 496 | // corrected by setting `ctx.indentationLvL += diff` and then to decrease the | 496 | 497 | // value afterwards again. | 497 | | -function formatValue(ctx, value, recurseTimes) { | | 498 | +function formatValue(ctx, value, recurseTimes, typedArray) { | 498 | 499 | // Primitive types cannot have properties. | 499 | 500 | if (typeof value !== 'object' && typeof value !== 'function') { | 500 | 501 | return formatPrimitive(ctx.stylize, value, ctx); | @@ -542,10 +543,10 @@ function formatValue(ctx, value, recurseTimes) { | 542 | 543 | if (ctx.seen.indexOf(value) !== -1) | 543 | 544 | return ctx.stylize('[Circular]', 'special'); | 544 | 545 |
| 545 | | - return formatRaw(ctx, value, recurseTimes); | | 546 | + return formatRaw(ctx, value, recurseTimes, typedArray); | 546 | 547 | } | 547 | 548 |
| 548 | | -function formatRaw(ctx, value, recurseTimes) { | | 549 | +function formatRaw(ctx, value, recurseTimes, typedArray) { | 549 | 550 | let keys; | 550 | 551 |
| 551 | 552 | const constructor = getConstructorName(value, ctx); | @@ -678,9 +679,12 @@ function formatRaw(ctx, value, recurseTimes) { | 678 | 679 | const arrayType = isArrayBuffer(value) ? 'ArrayBuffer' : | 679 | 680 | 'SharedArrayBuffer'; | 680 | 681 | const prefix = getPrefix(constructor, tag, arrayType); | 681 | | - if (keys.length === 0) | | 682 | + if (typedArray === undefined) { | | 683 | + formatter = formatArrayBuffer; | | 684 | + } else if (keys.length === 0) { | 682 | 685 | return prefix + | 683 | 686 | `{ byteLength: ${formatNumber(ctx.stylize, value.byteLength)} }`; | | 687 | + } | 684 | 688 | braces[0] = `${prefix}{`; | 685 | 689 | keys.unshift('byteLength'); | 686 | 690 | } else if (isDataView(value)) { | @@ -941,6 +945,18 @@ function formatSpecialArray(ctx, value, recurseTimes, maxLength, output, i) { | 941 | 945 | return output; | 942 | 946 | } | 943 | 947 |
| | 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 | + | 944 | 960 | function formatArray(ctx, value, recurseTimes) { | 945 | 961 | const valLen = value.length; | 946 | 962 | const len = Math.min(Math.max(0, ctx.maxArrayLength), valLen); | @@ -981,7 +997,7 @@ function formatTypedArray(ctx, value, recurseTimes) { | 981 | 997 | 'byteOffset', | 982 | 998 | 'buffer' | 983 | 999 | ]) { | 984 | | - const str = formatValue(ctx, value[key], recurseTimes); | | 1000 | + const str = formatValue(ctx, value[key], recurseTimes, true); | 985 | 1001 | output.push(`[${key}]: ${str}`); | 986 | 1002 | } | 987 | 1003 | ctx.indentationLvl -= 2; | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-util-format-shared-arraybuffer.js -6Lines changed: 0 additions & 6 deletions Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-util-format.js +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -308,3 +308,8 @@ Object.setPrototypeOf(BadCustomError.prototype, Error.prototype); | 308 | 308 | Object.setPrototypeOf(BadCustomError, Error); | 309 | 309 | assert.strictEqual(util.format(new BadCustomError('foo')), | 310 | 310 | '[BadCustomError: foo]'); | | 311 | + | | 312 | +assert.strictEqual( | | 313 | + util.format(new SharedArrayBuffer(4)), | | 314 | + 'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }' | | 315 | +); |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-util-inspect.js +36-19Lines changed: 36 additions & 19 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -115,70 +115,86 @@ assert(!/Object/.test( | 115 | 115 | util.inspect({ a: { a: { a: { a: {} } } } }, undefined, null, true) | 116 | 116 | )); | 117 | 117 |
| 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; | 120 | 121 | const dv = new DataView(ab, 1, 2); | 121 | 122 | assert.strictEqual( | 122 | 123 | util.inspect(ab, showHidden), | 123 | | - 'ArrayBuffer { byteLength: 4 }' | | 124 | + 'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }' | 124 | 125 | ); | 125 | 126 | assert.strictEqual(util.inspect(new DataView(ab, 1, 2), showHidden), | 126 | 127 | 'DataView {\n' + | 127 | 128 | ' byteLength: 2,\n' + | 128 | 129 | ' byteOffset: 1,\n' + | 129 | | - ' buffer: ArrayBuffer { byteLength: 4 } }'); | | 130 | + ' buffer:\n' + | | 131 | + ' ArrayBuffer { [Uint8Contents]: ' + | | 132 | + '<01 02 03 04>, byteLength: 4 } }'); | 130 | 133 | assert.strictEqual( | 131 | 134 | util.inspect(ab, showHidden), | 132 | | - 'ArrayBuffer { byteLength: 4 }' | | 135 | + 'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, byteLength: 4 }' | 133 | 136 | ); | 134 | 137 | assert.strictEqual(util.inspect(dv, showHidden), | 135 | 138 | 'DataView {\n' + | 136 | 139 | ' byteLength: 2,\n' + | 137 | 140 | ' byteOffset: 1,\n' + | 138 | | - ' buffer: ArrayBuffer { byteLength: 4 } }'); | | 141 | + ' buffer:\n' + | | 142 | + ' ArrayBuffer { [Uint8Contents]: ' + | | 143 | + '<01 02 03 04>, byteLength: 4 } }'); | 139 | 144 | ab.x = 42; | 140 | 145 | dv.y = 1337; | 141 | 146 | assert.strictEqual(util.inspect(ab, showHidden), | 142 | | - 'ArrayBuffer { byteLength: 4, x: 42 }'); | | 147 | + 'ArrayBuffer { [Uint8Contents]: <01 02 03 04>, ' + | | 148 | + 'byteLength: 4, x: 42 }'); | 143 | 149 | assert.strictEqual(util.inspect(dv, showHidden), | 144 | 150 | 'DataView {\n' + | 145 | 151 | ' byteLength: 2,\n' + | 146 | 152 | ' 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' + | 148 | 156 | ' y: 1337 }'); | 149 | 157 | } | 150 | 158 |
| 151 | 159 | // Now do the same checks but from a different context. | 152 | | -for (const showHidden of [true, false]) { | | 160 | +{ | | 161 | + const showHidden = false; | 153 | 162 | const ab = vm.runInNewContext('new ArrayBuffer(4)'); | 154 | 163 | const dv = vm.runInNewContext('new DataView(ab, 1, 2)', { ab }); | 155 | 164 | assert.strictEqual( | 156 | 165 | util.inspect(ab, showHidden), | 157 | | - 'ArrayBuffer { byteLength: 4 }' | | 166 | + 'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }' | 158 | 167 | ); | 159 | 168 | assert.strictEqual(util.inspect(new DataView(ab, 1, 2), showHidden), | 160 | 169 | 'DataView {\n' + | 161 | 170 | ' byteLength: 2,\n' + | 162 | 171 | ' byteOffset: 1,\n' + | 163 | | - ' buffer: ArrayBuffer { byteLength: 4 } }'); | | 172 | + ' buffer:\n' + | | 173 | + ' ArrayBuffer { [Uint8Contents]: <00 00 00 00>, ' + | | 174 | + 'byteLength: 4 } }'); | 164 | 175 | assert.strictEqual( | 165 | 176 | util.inspect(ab, showHidden), | 166 | | - 'ArrayBuffer { byteLength: 4 }' | | 177 | + 'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }' | 167 | 178 | ); | 168 | 179 | assert.strictEqual(util.inspect(dv, showHidden), | 169 | 180 | 'DataView {\n' + | 170 | 181 | ' byteLength: 2,\n' + | 171 | 182 | ' byteOffset: 1,\n' + | 172 | | - ' buffer: ArrayBuffer { byteLength: 4 } }'); | | 183 | + ' buffer:\n' + | | 184 | + ' ArrayBuffer { [Uint8Contents]: <00 00 00 00>, ' + | | 185 | + 'byteLength: 4 } }'); | 173 | 186 | ab.x = 42; | 174 | 187 | dv.y = 1337; | 175 | 188 | assert.strictEqual(util.inspect(ab, showHidden), | 176 | | - 'ArrayBuffer { byteLength: 4, x: 42 }'); | | 189 | + 'ArrayBuffer { [Uint8Contents]: <00 00 00 00>, ' + | | 190 | + 'byteLength: 4, x: 42 }'); | 177 | 191 | assert.strictEqual(util.inspect(dv, showHidden), | 178 | 192 | 'DataView {\n' + | 179 | 193 | ' byteLength: 2,\n' + | 180 | 194 | ' 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' + | 182 | 198 | ' y: 1337 }'); | 183 | 199 | } | 184 | 200 |
| @@ -1639,13 +1655,14 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'"); | 1639 | 1655 | [new Float64Array(2), '[Float64Array: null prototype] [ 0, 0 ]'], | 1640 | 1656 | [new BigInt64Array(2), '[BigInt64Array: null prototype] [ 0n, 0n ]'], | 1641 | 1657 | [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 }'], | 1644 | 1661 | [new DataView(new ArrayBuffer(16)), | 1645 | 1662 | '[DataView: null prototype] {\n byteLength: undefined,\n ' + | 1646 | | - 'byteOffset: undefined,\n buffer: undefined }'], | | 1663 | + 'byteOffset: undefined,\n buffer: undefined }'], | 1647 | 1664 | [new SharedArrayBuffer(2), '[SharedArrayBuffer: null prototype] ' + | 1648 | | - '{ byteLength: undefined }'], | | 1665 | + '{ [Uint8Contents]: <00 00>, byteLength: undefined }'], | 1649 | 1666 | [/foobar/, '[RegExp: null prototype] /foobar/'] | 1650 | 1667 | ].forEach(([value, expected]) => { | 1651 | 1668 | assert.strictEqual( | |
|