util: don't throw on circular %j input to format()
authorBen Noordhuis <info@bnoordhuis.nl>
Mon, 29 Jul 2013 19:00:33 +0000 (21:00 +0200)
committerBen Noordhuis <info@bnoordhuis.nl>
Mon, 29 Jul 2013 19:59:15 +0000 (21:59 +0200)
Don't throw an exception when the argument to %j is an object that
contains circular references, it's not helpful. Catch the exception
and return the string '[Circular]'.

doc/api/util.markdown
lib/util.js
test/simple/test-util-format.js

index a1bfdb0..88ef5ea 100644 (file)
@@ -53,7 +53,8 @@ argument. Supported placeholders are:
 
 * `%s` - String.
 * `%d` - Number (both integer and float).
-* `%j` - JSON.
+* `%j` - JSON.  Replaced with the string `'[Circular]'` if the argument
+         contains circular references.
 * `%%` - single percent sign (`'%'`). This does not consume an argument.
 
 If the placeholder does not have a corresponding argument, the placeholder is
index 993e363..23de9df 100644 (file)
@@ -38,7 +38,12 @@ exports.format = function(f) {
     switch (x) {
       case '%s': return String(args[i++]);
       case '%d': return Number(args[i++]);
-      case '%j': return JSON.stringify(args[i++]);
+      case '%j':
+        try {
+          return JSON.stringify(args[i++]);
+        } catch (_) {
+          return '[Circular]';
+        }
       default:
         return x;
     }
index b559220..ee96744 100644 (file)
@@ -60,3 +60,9 @@ assert.equal(util.format('%s:%s', 'foo', 'bar'), 'foo:bar');
 assert.equal(util.format('%s:%s', 'foo', 'bar', 'baz'), 'foo:bar baz');
 assert.equal(util.format('%%%s%%', 'hi'), '%hi%');
 assert.equal(util.format('%%%s%%%%', 'hi'), '%hi%%');
+
+(function() {
+  var o = {};
+  o.o = o;
+  assert.equal(util.format('%j', o), '[Circular]');
+})();