Pretty-Printing Variables, Objects, and Functions in JavaScriptCore
By default, the string output of JSValue
in JavaScriptCore printing (e.g. via my console.log
) will produce a mere [object Object]
. That’s not very helpful.
It’s simple to pretty-print objects (if they are merely data-containers) via JSON:
const obj = {a: 123, b: 456};
JSON.stringify(obj, null, 4 /* spacing level */);
// => {
// a: 123,
// b: 456
// }
This won’t print functions at all, though.
Any function in JavaScript can be converted to string and printed directly, so it’s simple to get to that point:
function addTwo(x) {
return x + 2;
}
addTwo // ⚠ No call, just reference the function
// => function addTwo(x) {
// return x + 2;
// }
During my research I found an old JavaScript dump
function from 2005 that traverses objects and prints the key-value pairs manually. With more modern ECMAScript 6 capabilities, we can use the following to print an object similar-ish to JSON, but including functions:
function dump(obj, level = 0) {
if (typeof obj === 'object' && obj !== null) {
const indent = " ".repeat(level + 1);
const entries = Object.entries(obj).map(([key, value]) => {
let entry = `${indent}"${key}": `;
if (typeof value === 'object' && value !== null) {
entry += dump(value, level + 1).trim();
} else if (typeof value === 'string') {
entry += `"${value}"`;
} else {
entry += `${value}`;
}
return entry;
});
const joinedEntries = entries.join(",\n");
const levelPadding = " ".repeat(level);
return `{\n${joinedEntries}\n${levelPadding}}`;
} else {
return `${obj} (${typeof obj})`;
}
}
Usage:
const obj = {
f: (x) => x + 4,
a: 123,
b: { ba: 555, bb: "hello"}
};
dump(obj);
// => {
// 'f': (x) => x + 4,
// 'a': 123,
// 'b': {
// 'ba': 555,
// 'bb': "hello"
// }
// }
This produces a string representation that itself is valid JavaScript when evaluated:
eval(`(${dump(obj)})`).f(1); // => 5
There’s probably a node package that does this and much more, but it’s enough for me to inspect JavaScriptCore objects from inside JavaScriptCore via a REPL in my app.