@@ -53,6 +53,9 @@ const kClearEntry = Symbol('clear-entry');
5353const  kGetEntries  =  Symbol ( 'get-entries' ) ; 
5454const  kIndex  =  Symbol ( 'index' ) ; 
5555const  kMarks  =  Symbol ( 'marks' ) ; 
56+ const  kCount  =  Symbol ( 'count' ) ; 
57+ const  kMaxCount  =  Symbol ( 'max-count' ) ; 
58+ const  kDefaultMaxCount  =  150 ; 
5659
5760observerCounts [ NODE_PERFORMANCE_ENTRY_TYPE_MARK ]  =  1 ; 
5861observerCounts [ NODE_PERFORMANCE_ENTRY_TYPE_MEASURE ]  =  1 ; 
@@ -250,20 +253,32 @@ const nodeTiming = new PerformanceNodeTiming();
250253// Maintains a list of entries as a linked list stored in insertion order. 
251254class  PerformanceObserverEntryList  { 
252255  constructor ( )  { 
253-     Object . defineProperty ( this ,  kEntries ,  { 
254-       writable : true , 
255-       enumerable : false , 
256-       value : { } 
256+     Object . defineProperties ( this ,  { 
257+       [ kEntries ] : { 
258+         writable : true , 
259+         enumerable : false , 
260+         value : { } 
261+       } , 
262+       [ kCount ] : { 
263+         writable : true , 
264+         enumerable : false , 
265+         value : 0 
266+       } 
257267    } ) ; 
258268    L . init ( this [ kEntries ] ) ; 
259269  } 
260270
261271  [ kInsertEntry ] ( entry )  { 
262272    const  item  =  {  entry } ; 
263273    L . append ( this [ kEntries ] ,  item ) ; 
274+     this [ kCount ] ++ ; 
264275    this [ kIndexEntry ] ( item ) ; 
265276  } 
266277
278+   get  length ( )  { 
279+     return  this [ kCount ] ; 
280+   } 
281+ 
267282  [ kIndexEntry ] ( entry )  { 
268283    // Default implementation does nothing 
269284  } 
@@ -384,9 +399,22 @@ class Performance extends PerformanceObserverEntryList {
384399    this [ kIndex ]  =  { 
385400      [ kMarks ] : new  Set ( ) 
386401    } ; 
402+     this [ kMaxCount ]  =  kDefaultMaxCount ; 
387403    this [ kInsertEntry ] ( nodeTiming ) ; 
388404  } 
389405
406+   set  maxEntries ( val )  { 
407+     if  ( typeof  val  !==  'number'  ||  val  >>>  0  !==  val )  { 
408+       const  errors  =  lazyErrors ( ) ; 
409+       throw  new  errors . TypeError ( 'ERR_INVALID_ARG_TYPE' ,  'val' ,  'number' ) ; 
410+     } 
411+     this [ kMaxCount ]  =  Math . max ( 1 ,  val  >>>  0 ) ; 
412+   } 
413+ 
414+   get  maxEntries ( )  { 
415+     return  this [ kMaxCount ] ; 
416+   } 
417+ 
390418  [ kIndexEntry ] ( item )  { 
391419    const  index  =  this [ kIndex ] ; 
392420    const  type  =  item . entry . entryType ; 
@@ -397,6 +425,17 @@ class Performance extends PerformanceObserverEntryList {
397425    } 
398426    const  entry  =  item . entry ; 
399427    L . append ( items ,  {  entry,  item } ) ; 
428+     const  count  =  this [ kCount ] ; 
429+     if  ( count  >  this [ kMaxCount ] )  { 
430+       const  text  =  count  ===  1  ? 'is 1 entry'  : `are ${ count }  ; 
431+       process . emitWarning ( 'Possible perf_hooks memory leak detected. '  + 
432+                           `There ${ text }   + 
433+                           'Performance Timeline. Use the clear methods '  + 
434+                           'to remove entries that are no longer needed or '  + 
435+                           'set performance.maxEntries equal to a higher '  + 
436+                           'value (currently the maxEntries is '  + 
437+                           `${ this [ kMaxCount ] }  ) ; 
438+     } 
400439  } 
401440
402441  [ kClearEntry ] ( type ,  name )  { 
@@ -411,10 +450,12 @@ class Performance extends PerformanceObserverEntryList {
411450        if  ( entry . name  ===  `${ name }  )  { 
412451          L . remove ( item ) ;  // remove from the index 
413452          L . remove ( item . item ) ;  // remove from the master 
453+           this [ kCount ] -- ; 
414454        } 
415455      }  else  { 
416456        L . remove ( item ) ;  // remove from the index 
417457        L . remove ( item . item ) ;  // remove from the master 
458+         this [ kCount ] -- ; 
418459      } 
419460      item  =  next ; 
420461    } 
0 commit comments