File tree Expand file tree Collapse file tree 2 files changed +57
-16
lines changed
Expand file tree Collapse file tree 2 files changed +57
-16
lines changed Original file line number Diff line number Diff line change @@ -118,6 +118,50 @@ describe("logger", () => {
118118 } ) ;
119119 } ) ;
120120
121+ it ( "should not detect duplicate object as circular" , ( ) => {
122+ const obj : any = { a : "foo" } ;
123+ const entry : logger . LogEntry = {
124+ severity : "ERROR" ,
125+ message : "testing circular" ,
126+ a : obj ,
127+ b : obj ,
128+ } ;
129+ logger . write ( entry ) ;
130+ expectStderr ( {
131+ severity : "ERROR" ,
132+ message : "testing circular" ,
133+ a : { a : "foo" } ,
134+ b : { a : "foo" } ,
135+ } ) ;
136+ } ) ;
137+
138+ it ( "should not detect duplicate object in array as circular" , ( ) => {
139+ const obj : any = { a : "foo" } ;
140+ const arr : any = [
141+ { a : obj , b : obj } ,
142+ { a : obj , b : obj } ,
143+ ] ;
144+ const entry : logger . LogEntry = {
145+ severity : "ERROR" ,
146+ message : "testing circular" ,
147+ a : arr ,
148+ b : arr ,
149+ } ;
150+ logger . write ( entry ) ;
151+ expectStderr ( {
152+ severity : "ERROR" ,
153+ message : "testing circular" ,
154+ a : [
155+ { a : { a : "foo" } , b : { a : "foo" } } ,
156+ { a : { a : "foo" } , b : { a : "foo" } } ,
157+ ] ,
158+ b : [
159+ { a : { a : "foo" } , b : { a : "foo" } } ,
160+ { a : { a : "foo" } , b : { a : "foo" } } ,
161+ ] ,
162+ } ) ;
163+ } ) ;
164+
121165 it ( "should not break on objects that override toJSON" , ( ) => {
122166 const obj : any = { a : new Date ( "August 26, 1994 12:24:00Z" ) } ;
123167
Original file line number Diff line number Diff line change @@ -56,28 +56,25 @@ function removeCircular(obj: any, refs: any[] = []): any {
5656 if ( typeof obj !== "object" || ! obj ) {
5757 return obj ;
5858 }
59- // If the object defines its own toJSON, prefer that .
60- if ( obj . toJSON ) {
59+ // If the object defines its own toJSON method, use it .
60+ if ( obj . toJSON && typeof obj . toJSON === "function" ) {
6161 return obj . toJSON ( ) ;
6262 }
63- if ( refs . includes ( obj ) ) {
63+ // Only check for circularity among ancestors in the recursion stack.
64+ if ( refs . indexOf ( obj ) !== - 1 ) {
6465 return "[Circular]" ;
65- } else {
66- refs . push ( obj ) ;
6766 }
68- let returnObj : any ;
69- if ( Array . isArray ( obj ) ) {
70- returnObj = new Array ( obj . length ) ;
71- } else {
72- returnObj = { } ;
73- }
74- for ( const k in obj ) {
75- if ( refs . includes ( obj [ k ] ) ) {
76- returnObj [ k ] = "[Circular]" ;
77- } else {
78- returnObj [ k ] = removeCircular ( obj [ k ] , refs ) ;
67+ // Add the current object to the recursion stack.
68+ refs . push ( obj ) ;
69+
70+ let returnObj : any = Array . isArray ( obj ) ? [ ] : { } ;
71+ for ( const key in obj ) {
72+ if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) {
73+ returnObj [ key ] = removeCircular ( obj [ key ] , refs ) ;
7974 }
8075 }
76+ // Remove the current object from the stack once its properties are processed.
77+ refs . pop ( ) ;
8178 return returnObj ;
8279}
8380
You can’t perform that action at this time.
0 commit comments