diff --git a/Foundation/CPArray/_CPArray.j b/Foundation/CPArray/_CPArray.j index 98759ea44..5ecb8a6cb 100755 --- a/Foundation/CPArray/_CPArray.j +++ b/Foundation/CPArray/_CPArray.j @@ -37,6 +37,8 @@ CPBinarySearchingFirstEqual = 1 << 8; CPBinarySearchingLastEqual = 1 << 9; CPBinarySearchingInsertionIndex = 1 << 10; +var CPArrayMaxDescriptionRecursion = 10; + var concat = Array.prototype.concat, join = Array.prototype.join, push = Array.prototype.push; @@ -874,6 +876,11 @@ var concat = Array.prototype.concat, Returns a human readable description of this array and it's elements. */ - (CPString)description +{ + return [self _descriptionWithMaximumDepth:CPArrayMaxDescriptionRecursion]; +} + +- (CPString)_descriptionWithMaximumDepth:(int)maximumDepth { var index = 0, count = [self count], @@ -887,7 +894,7 @@ var concat = Array.prototype.concat, var object = [self objectAtIndex:index]; // NOTE: replace(/^/mg, " ") inserts 4 spaces at the beginning of every line - description += CPDescriptionOfObject(object).replace(/^/mg, " "); + description += CPDescriptionOfObject(object, maximumDepth).replace(/^/mg, " "); if (index < count - 1) description += ",\n"; diff --git a/Foundation/CPDictionary.j b/Foundation/CPDictionary.j index 3ee48a7bd..330935b9c 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -27,7 +27,9 @@ @import "CPObject.j" //FIXME: After release of 0.9.7 remove below variable -var CPDictionaryShowNilDeprecationMessage = YES; +var CPDictionaryShowNilDeprecationMessage = YES, + + CPDictionaryMaxDescriptionRecursion = 10; /* @ignore */ @implementation _CPDictionaryValueEnumerator : CPEnumerator @@ -733,7 +735,7 @@ var CPDictionaryShowNilDeprecationMessage = YES; var key = keys[index], value = self.valueForKey(key); - string += " @\"" + key + "\": " + CPDescriptionOfObject(value).split("\n").join("\n ") + (index + 1 < count ? "," : "") + "\n"; + string += " @\"" + key + "\": " + CPDescriptionOfObject(value, CPDictionaryMaxDescriptionRecursion).split("\n").join("\n ") + (index + 1 < count ? "," : "") + "\n"; } return string + "}"; diff --git a/Foundation/CPObject.j b/Foundation/CPObject.j index 613f1e457..bc84e9ce8 100644 --- a/Foundation/CPObject.j +++ b/Foundation/CPObject.j @@ -536,7 +536,7 @@ CPLog(@"Got some class: %@", inst); @end -function CPDescriptionOfObject(anObject) +function CPDescriptionOfObject(anObject, maximumRecursionDepth) { if (anObject === nil) return "nil"; @@ -547,11 +547,17 @@ function CPDescriptionOfObject(anObject) if (anObject === window) return "window"; + if (maximumRecursionDepth === 0) + return "..."; + if (anObject.isa) { if ([anObject isKindOfClass:CPString]) return '@"' + [anObject description] + '"'; + if ([anObject respondsToSelector:@selector(_descriptionWithMaximumDepth:)]) + return [anObject _descriptionWithMaximumDepth:maximumRecursionDepth !== undefined ? maximumRecursionDepth - 1 : maximumRecursionDepth]; + return [anObject description]; } @@ -584,7 +590,10 @@ function CPDescriptionOfObject(anObject) if (i === 0) desc += "\n"; - desc += " " + properties[i] + ": " + CPDescriptionOfObject(anObject[properties[i]]).split("\n").join("\n "); + var value = anObject[properties[i]], + valueDescription = CPDescriptionOfObject(value, maximumRecursionDepth !== undefined ? maximumRecursionDepth - 1 : maximumRecursionDepth).split("\n").join("\n "); + + desc += " " + properties[i] + ": " + valueDescription; if (i < properties.length - 1) desc += ",\n"; diff --git a/Tests/Foundation/CPArrayTest.j b/Tests/Foundation/CPArrayTest.j index d15aa52cb..d3d1bb3b8 100644 --- a/Tests/Foundation/CPArrayTest.j +++ b/Tests/Foundation/CPArrayTest.j @@ -641,6 +641,15 @@ [self assertTrue:d.indexOf("(5, 6)") !== -1 message:"Can't find '(5, 6)' in description of array " + d]; } +- (void)testRecursiveJSObjectDescription +{ + var a = []; + + a.push(a); + + [self assert:'@[\n @[\n @[\n @[\n @[\n @[\n @[\n @[\n @[\n @[\n @[\n ...\n ]\n ]\n ]\n ]\n ]\n ]\n ]\n ]\n ]\n ]\n]' equals:[a description]]; +} + - (void)testSortUsingDescriptorsWithDifferentSelectors { var a = [CPDictionary dictionaryWithJSObject:{"a": "AB", "b": "ba"}], diff --git a/Tests/Foundation/CPDictionaryTest.j b/Tests/Foundation/CPDictionaryTest.j index bd1447fd2..f14dce9b0 100644 --- a/Tests/Foundation/CPDictionaryTest.j +++ b/Tests/Foundation/CPDictionaryTest.j @@ -408,6 +408,15 @@ [self assert:'@{\n @"Key": window\n}' equals:[dict description]]; } +- (void)testRecursiveJSObjectDescription +{ + var a = {}; + + a['a'] = a; + + [self assert:'@{\n @"a": {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: {\n a: ...\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n}' equals:[@{ 'a': a } description]]; +} + - (void)testInitWithObjectsAndKeys { var dict = [[CPDictionary alloc] initWithObjectsAndKeys:@"Value1", @"Key1", nil, @"Key2", @"Value3", @"Key3"];