diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index b8c7e593..260bb289 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -4015,6 +4015,10 @@ getJasmineRequireObj().pp = function(j$) { } else { this.emitScalar(value.toString()); } + } catch (e) { + if (this.ppNestLevel_ > 1 || !(e instanceof MaxCharsReachedError)) { + throw e; + } } finally { this.ppNestLevel_--; } @@ -4194,22 +4198,31 @@ getJasmineRequireObj().pp = function(j$) { }; StringPrettyPrinter.prototype.append = function(value) { - if (this.length < j$.MAX_PRETTY_PRINT_CHARS) { - value = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length); - this.length += value.length; - this.stringParts.push(value); + var result = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length); + this.length += result.value.length; + this.stringParts.push(result.value); + + if (result.truncated) { + throw new MaxCharsReachedError(); } }; function truncate(s, maxlen) { if (s.length <= maxlen) { - return s; + return { value: s, truncated: false }; } - s = s.substring(0, maxlen - 4); - return s + ' ...'; + s = s.substring(0, maxlen - 4) + ' ...'; + return { value: s, truncated: true }; } + function MaxCharsReachedError() { + this.message = 'Exceeded ' + j$.MAX_PRETTY_PRINT_CHARS + + ' characters while pretty-printing a value'; + } + + MaxCharsReachedError.prototype = new Error(); + function keys(obj, isArray) { var allKeys = Object.keys ? Object.keys(obj) : (function(o) { diff --git a/spec/core/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index 745a5619..65578260 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -131,19 +131,39 @@ describe("jasmineUnderTest.pp", function () { } }); - it("should truncate outputs that are too long", function() { + function withMaxChars(maxChars, fn) { var originalMaxChars = jasmineUnderTest.MAX_PRETTY_PRINT_CHARS; + + try { + jasmineUnderTest.MAX_PRETTY_PRINT_CHARS = maxChars; + fn(); + } finally { + jasmineUnderTest.MAX_PRETTY_PRINT_CHARS = originalMaxChars; + } + } + + it("should truncate outputs that are too long", function() { var big = [ { a: 1, b: "a long string" }, {} ]; - try { - jasmineUnderTest.MAX_PRETTY_PRINT_CHARS = 34; + withMaxChars(34, function() { expect(jasmineUnderTest.pp(big)).toEqual("[ Object({ a: 1, b: 'a long st ..."); - } finally { - jasmineUnderTest.MAX_PRETTY_PRINT_CHARS = originalMaxChars; - } + }); + }); + + it("should not serialize more objects after hitting MAX_PRETTY_PRINT_CHARS", function() { + var a = { jasmineToString: function() { return 'object a'; } }, + b = { jasmineToString: function() { return 'object b'; } }, + c = { jasmineToString: jasmine.createSpy('c jasmineToString').and.returnValue('') }, + d = { jasmineToString: jasmine.createSpy('d jasmineToString').and.returnValue('') }; + + withMaxChars(30, function() { + jasmineUnderTest.pp([{a: a, b: b, c: c}, d]); + expect(c.jasmineToString).not.toHaveBeenCalled(); + expect(d.jasmineToString).not.toHaveBeenCalled(); + }); }); it("should print 'null' as the constructor of an object with its own constructor property", function() { diff --git a/src/core/PrettyPrinter.js b/src/core/PrettyPrinter.js index 04f85078..0685fa24 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -57,6 +57,10 @@ getJasmineRequireObj().pp = function(j$) { } else { this.emitScalar(value.toString()); } + } catch (e) { + if (this.ppNestLevel_ > 1 || !(e instanceof MaxCharsReachedError)) { + throw e; + } } finally { this.ppNestLevel_--; } @@ -236,22 +240,31 @@ getJasmineRequireObj().pp = function(j$) { }; StringPrettyPrinter.prototype.append = function(value) { - if (this.length < j$.MAX_PRETTY_PRINT_CHARS) { - value = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length); - this.length += value.length; - this.stringParts.push(value); + var result = truncate(value, j$.MAX_PRETTY_PRINT_CHARS - this.length); + this.length += result.value.length; + this.stringParts.push(result.value); + + if (result.truncated) { + throw new MaxCharsReachedError(); } }; function truncate(s, maxlen) { if (s.length <= maxlen) { - return s; + return { value: s, truncated: false }; } - s = s.substring(0, maxlen - 4); - return s + ' ...'; + s = s.substring(0, maxlen - 4) + ' ...'; + return { value: s, truncated: true }; } + function MaxCharsReachedError() { + this.message = 'Exceeded ' + j$.MAX_PRETTY_PRINT_CHARS + + ' characters while pretty-printing a value'; + } + + MaxCharsReachedError.prototype = new Error(); + function keys(obj, isArray) { var allKeys = Object.keys ? Object.keys(obj) : (function(o) {