1+ import { resolve , isRejected , isNever } from '../../src/main'
2+ import { Future } from '../../src/Promise'
3+ import Action from '../../src/Action'
4+
5+ const knownNames = [ 'Handle' , 'Action' ,
6+ 'Then' , 'Chain' , 'Map' , 'Delay' ,
7+ 'Future' , 'Fulfilled' , 'Rejected' ,
8+ 'Settle' , 'Merge' , 'Any' , 'Race' ]
9+ const DELAY_TIME = 5
10+
11+ export default function getCounts ( exec , report , targets = knownNames , withResult = false ) {
12+ function asyncReport ( x ) {
13+ timeoutCount ++
14+ setTimeout ( ( ) => {
15+ res . push ( report ( x , 'result after' , collect ( [ result ] , targets , seenBefore ) ) )
16+ if ( globals . size > + withResult ) res . push ( report ( x , 'globals after' , collect ( globals , targets , seenBefore ) ) )
17+ if ( -- timeoutCount == 0 ) promise . _fulfill ( res )
18+ } , 2 ) // after the TaskQueue is drained
19+ }
20+ function monitoredTimeout ( log , fn , captures = [ ] ) {
21+ for ( let c of captures )
22+ globals . add ( c )
23+ timeoutCount ++
24+ setTimeout ( ( ) => {
25+ for ( let c of captures )
26+ globals . delete ( c )
27+ if ( captures . length ) res . push ( report ( log , 'captures from timeout' , collect ( captures , targets , seenBefore ) ) )
28+ res . push ( report ( log , 'result before' , collect ( [ result ] , targets , seenBefore ) ) )
29+ if ( globals . size > + withResult ) res . push ( report ( log , 'globals before' , collect ( globals , targets , seenBefore ) ) )
30+ fn ( )
31+ asyncReport ( log )
32+ if ( -- timeoutCount == 0 ) promise . _fulfill ( res )
33+ } , DELAY_TIME )
34+ }
35+ function monitoredDelay ( x , id ) {
36+ const p = resolve ( x )
37+ if ( isRejected ( p ) || isNever ( p ) ) {
38+ return p
39+ } else {
40+ var promise = new Future ( )
41+ p . _runAction ( new Delay ( promise , id ) )
42+ return promise
43+ }
44+ }
45+ class Delay extends Action {
46+ constructor ( promise , id ) {
47+ super ( promise )
48+ this . id = id
49+ }
50+
51+ fulfilled ( p ) {
52+ monitoredTimeout ( this . id || p . value , ( ) => this . promise . _become ( p ) , [ this . promise , p ] )
53+ }
54+ }
55+
56+ const promise = new Future
57+ var timeoutCount = 0
58+ const res = [ ]
59+ const seenBefore = new WeakSet
60+ const globals = new Set
61+ const result = exec ( monitoredDelay , monitoredTimeout ) ;
62+ if ( withResult ) {
63+ globals . add ( result )
64+ }
65+ asyncReport ( 0 ) // 'init'
66+ return promise
67+ }
68+
69+ export function collect ( sources , targets = knownNames , seenBefore = new WeakSet ) {
70+ var counts = { }
71+ for ( let name of targets ) {
72+ counts [ name + 's' ] = 0
73+ counts [ 'new' + name + 's' ] = 0
74+ }
75+ var seen = new WeakSet ( [ ] )
76+ function test ( o ) {
77+ if ( seen . has ( o ) ) {
78+ return
79+ } else {
80+ seen . add ( o )
81+ }
82+
83+ const name = o . constructor . name
84+ if ( targets . includes ( name ) ) {
85+ counts [ name + 's' ] ++
86+ if ( ! seenBefore . has ( o ) ) {
87+ counts [ 'new' + name + 's' ] ++
88+ }
89+ } else {
90+ console . log ( 'unknown kind:' , o )
91+ }
92+ seenBefore . add ( o )
93+
94+ for ( let property in o ) {
95+ let value = o [ property ]
96+ if ( value && typeof value == 'object' ) { // ignore function objects
97+ test ( value )
98+ }
99+ }
100+ }
101+ for ( let source of sources ) {
102+ test ( source )
103+ }
104+ return counts
105+ }
106+ export function formatResults ( counts ) {
107+ var x = [ ]
108+ for ( let name in counts ) {
109+ if ( counts [ name ] == 0 ) continue
110+ if ( / ^ n e w / . test ( name ) ) continue
111+ let r = name + ': ' + counts [ name ]
112+ if ( counts [ 'new' + name ] > 0 )
113+ r += ' (+' + counts [ 'new' + name ] + ')'
114+ x . push ( r )
115+ }
116+ return x . join ( ', ' )
117+ }
118+
119+ export function sumResults ( counts ) {
120+ var c = 0 ;
121+ for ( let name in counts )
122+ if ( ! / ^ n e w / . test ( name ) )
123+ c += counts [ name ]
124+ return c
125+ }
0 commit comments