The case for console.hex()

What was a major annoyance during the development and especially the debugging of my WebBluetooth demos has now turned into a real proposal to extend the console API in the developer tools for all browsers. It is still early, so this may never really happen, but so far the response has been fantastic.

But first a bit of background. Almost 25 years ago I created my first website and I’ve been active with web development ever since. When JavaScript became popular there weren’t any developer tools yet. Debugging was just a seemingly endless number of alerts(), especially when debugging complicated loops. When Firebug first launch I was so happy and it completely changed the way we now develop web applications. But even now we often just skip the debugger and go back to the old style of debugging. But nowadays we don’t use alerts anymore, we log data to the console.

Traditionally we’ve had a lot of higher-level data types in the browser. From Numbers to Strings and from Arrays to Objects. And a lot of very specific objects like DOM nodes and even functions. The current developer tools are experts in dealing with these datatypes. If you log an array to the console, you can go over each of the elements and dive deep into nested objects.

But there is one area where the console is seriously lacking: binary data. And lately we’ve been seeing more and more specifications that handle binary data. We’ve got Blobs, ArrayBuffers and TypedArrays. And what happens when you log these data types to the console?

Logging a Blob to the console is pretty much useless. You can see that it is a Blob and the length, but the contents is invisible.

Logging an ArrayBuffer is almost just as bad. We know that it is an ArrayBuffer and again the the length, but the contents is completely invisible.

Logging a TypedArray is probably the best. We get the actual type of the TypedArray, in this case an Uint8Array, we get the length and also the content. But the content is pretty much a dump of numbers without any formatting or context. Especially with larger TypedArrays it is so hard to actually get a proper sense of the content of the TypedArray that we might as well consider it invisible.

But ever since the days of Microsoft DOS there has been way to represent binary data in a format that is both structured and easy to read. Using three major columns with from left to right: the position in the data, 16 octets of data printed as a hexadecimal number and finally the ASCII representation of each octet. A hex dump.

So last weekend I’ve spend a few hours trying to create a simple helper function that I can include in my projects to log a hex dump to the console. Building a hex dump in JavaScript is not that difficult and looking at NPM there are a lot of different options you can choose from. But the challenge on my part was to create a hex dump in a ‘one-liner’. And it turns out that is actually possible.

console.hex = (d) => console.log((Object(d).buffer instanceof ArrayBuffer ? new Uint8Array(d.buffer) : 
typeof d === 'string' ? (new TextEncoder('utf-8')).encode(d) : 
new Uint8ClampedArray(d)).reduce((p, c, i, a) => p + (i % 16 === 0 ? i.toString(16).padStart(6, 0) + '  ' : ' ') + 
c.toString(16).padStart(2, 0) + (i === a.length - 1 || i % 16 === 15 ? 
' '.repeat((15 - i % 16) * 3) + Array.from(a).splice(i - i % 16, 16).reduce((r, v) => 
r + (v > 31 && v < 127 || v > 159 ? String.fromCharCode(v) : '.'), '  ') + '\n' : ''), ''));

Yeah, that is pretty much crazy. But, what happens when we then use our newly defined console.hex()?

That certainly looks a whole lot better. We have a good sense of how long the data is and we can actually see there is an URL in there. They are actually commands for an ESC/POS receipt printer and tells it to print a barcode and a QR code. Mission succeeded. Although there is probably a lot to improve – it doesn’t support Blobs just yet – I just need to include this small piece of code in all my projects and…

But what if this was actually available by default in the developer tools? What if this was actually part of the standard? That would be absolutely brilliant. And why not? It would certainly make the life of everybody that deals with binary data in the browser so much easier.

So I’ve opened up an issue at the WhatWG:
https://github.com/whatwg/console/issues/121

And bugs for every major browser:

Let’s make this thing happen!