44 ArrayPrototypeIndexOf,
55 ArrayPrototypePush,
66 ArrayPrototypeSplice,
7+ SafeFinalizationRegistry,
78 ObjectGetPrototypeOf,
89 ObjectSetPrototypeOf,
910 Promise,
@@ -28,14 +29,29 @@ const { triggerUncaughtException } = internalBinding('errors');
2829
2930const { WeakReference } = internalBinding ( 'util' ) ;
3031
31- function decRef ( channel ) {
32- if ( channels . get ( channel . name ) . decRef ( ) === 0 ) {
33- channels . delete ( channel . name ) ;
32+ // Can't delete when weakref count reaches 0 as it could increment again.
33+ // Only GC can be used as a valid time to clean up the channels map.
34+ class WeakRefMap extends SafeMap {
35+ #finalizers = new SafeFinalizationRegistry ( ( key ) => {
36+ this . delete ( key ) ;
37+ } ) ;
38+
39+ set ( key , value ) {
40+ this . #finalizers. register ( value , key ) ;
41+ return super . set ( key , new WeakReference ( value ) ) ;
3442 }
35- }
3643
37- function incRef ( channel ) {
38- channels . get ( channel . name ) . incRef ( ) ;
44+ get ( key ) {
45+ return super . get ( key ) ?. get ( ) ;
46+ }
47+
48+ incRef ( key ) {
49+ return super . get ( key ) ?. incRef ( ) ;
50+ }
51+
52+ decRef ( key ) {
53+ return super . get ( key ) ?. decRef ( ) ;
54+ }
3955}
4056
4157function markActive ( channel ) {
@@ -80,7 +96,7 @@ class ActiveChannel {
8096 subscribe ( subscription ) {
8197 validateFunction ( subscription , 'subscription' ) ;
8298 ArrayPrototypePush ( this . _subscribers , subscription ) ;
83- incRef ( this ) ;
99+ channels . incRef ( this . name ) ;
84100 }
85101
86102 unsubscribe ( subscription ) {
@@ -89,15 +105,15 @@ class ActiveChannel {
89105
90106 ArrayPrototypeSplice ( this . _subscribers , index , 1 ) ;
91107
92- decRef ( this ) ;
108+ channels . decRef ( this . name ) ;
93109 maybeMarkInactive ( this ) ;
94110
95111 return true ;
96112 }
97113
98114 bindStore ( store , transform ) {
99115 const replacing = this . _stores . has ( store ) ;
100- if ( ! replacing ) incRef ( this ) ;
116+ if ( ! replacing ) channels . incRef ( this . name ) ;
101117 this . _stores . set ( store , transform ) ;
102118 }
103119
@@ -108,7 +124,7 @@ class ActiveChannel {
108124
109125 this . _stores . delete ( store ) ;
110126
111- decRef ( this ) ;
127+ channels . decRef ( this . name ) ;
112128 maybeMarkInactive ( this ) ;
113129
114130 return true ;
@@ -153,7 +169,7 @@ class Channel {
153169 this . _stores = undefined ;
154170 this . name = name ;
155171
156- channels . set ( name , new WeakReference ( this ) ) ;
172+ channels . set ( name , this ) ;
157173 }
158174
159175 static [ SymbolHasInstance ] ( instance ) {
@@ -191,12 +207,10 @@ class Channel {
191207 }
192208}
193209
194- const channels = new SafeMap ( ) ;
210+ const channels = new WeakRefMap ( ) ;
195211
196212function channel ( name ) {
197- let channel ;
198- const ref = channels . get ( name ) ;
199- if ( ref ) channel = ref . get ( ) ;
213+ const channel = channels . get ( name ) ;
200214 if ( channel ) return channel ;
201215
202216 if ( typeof name !== 'string' && typeof name !== 'symbol' ) {
@@ -215,12 +229,8 @@ function unsubscribe(name, subscription) {
215229}
216230
217231function hasSubscribers ( name ) {
218- let channel ;
219- const ref = channels . get ( name ) ;
220- if ( ref ) channel = ref . get ( ) ;
221- if ( ! channel ) {
222- return false ;
223- }
232+ const channel = channels . get ( name ) ;
233+ if ( ! channel ) return false ;
224234
225235 return channel . hasSubscribers ;
226236}
0 commit comments