From e3a013ae99decb7a5efad5bce35aa492ae32d6d1 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Sun, 4 Mar 2012 16:27:16 -0800 Subject: [PATCH] Allow users to set the pretty-printer's recursion depth Currently, jasmine's pretty printer traverses objects to 40 levels of nesting. If an object is more deeply nested than that, an exception is thrown. I find that after a few levels of nesting, the output becomes difficult to read. The process of serializing such deep objects also sometimes crashes the browser or causes a 'slow script' warning. This commit exposes a 'MAX_PRETTY_PRINT_DEPTH' option. It also causes the pretty printer to skip over parts of an object that are nested to deeply by simply printing out 'Object' or 'Array', rather than throwing an exception. --- spec/core/PrettyPrintSpec.js | 22 ++++++++++++++++++++++ src/core/PrettyPrinter.js | 14 ++++++++++---- src/core/base.js | 5 +++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/spec/core/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index 6d1cfc08..14d0d3e0 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -40,6 +40,28 @@ describe("jasmine.pp", function () { expect(jasmine.pp(instance)).toEqual("{ bar : 'my own bar' }"); }); + it("should not recurse objects and arrays more deeply than jasmine.MAX_PRETTY_PRINT_DEPTH", function() { + var originalMaxDepth = jasmine.MAX_PRETTY_PRINT_DEPTH; + var nestedObject = { level1: { level2: { level3: { level4: "leaf" } } } }; + var nestedArray = [1, [2, [3, [4, "leaf"]]]]; + + try { + jasmine.MAX_PRETTY_PRINT_DEPTH = 2; + expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : Object } }"); + expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, Array ] ]"); + + jasmine.MAX_PRETTY_PRINT_DEPTH = 3; + expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : Object } } }"); + expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, Array ] ] ]"); + + jasmine.MAX_PRETTY_PRINT_DEPTH = 4; + expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : { level4 : 'leaf' } } } }"); + expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, [ 4, 'leaf' ] ] ] ]"); + } finally { + jasmine.MAX_PRETTY_PRINT_DEPTH = originalMaxDepth; + } + }); + it("should stringify RegExp objects properly", function() { expect(jasmine.pp(/x|y|z/)).toEqual("/x|y|z/"); }); diff --git a/src/core/PrettyPrinter.js b/src/core/PrettyPrinter.js index 74fa4e7a..f276cea3 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -11,10 +11,6 @@ jasmine.PrettyPrinter = function() { * @param value */ jasmine.PrettyPrinter.prototype.format = function(value) { - if (this.ppNestLevel_ > 40) { - throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); - } - this.ppNestLevel_++; try { if (value === jasmine.undefined) { @@ -85,6 +81,11 @@ jasmine.StringPrettyPrinter.prototype.emitString = function(value) { }; jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { + this.append("Array"); + return; + } + this.append('[ '); for (var i = 0; i < array.length; i++) { if (i > 0) { @@ -96,6 +97,11 @@ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { }; jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { + this.append("Object"); + return; + } + var self = this; this.append('{ '); var first = true; diff --git a/src/core/base.js b/src/core/base.js index 51761ba2..af8d3ea0 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -34,6 +34,11 @@ jasmine.VERBOSE = false; */ jasmine.DEFAULT_UPDATE_INTERVAL = 250; +/** + * Maximum levels of nesting that will be included when an object is pretty-printed + */ +jasmine.MAX_PRETTY_PRINT_DEPTH = 40; + /** * Default timeout interval in milliseconds for waitsFor() blocks. */