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.