5151
5252
5353class Channel (AsyncIOEventEmitter ):
54- def __init__ (self , connection : "Connection" , guid : str ) -> None :
54+ def __init__ (self , connection : "Connection" , object : "ChannelOwner" ) -> None :
5555 super ().__init__ ()
56- self ._connection : Connection = connection
57- self ._guid = guid
58- self ._object : Optional [ ChannelOwner ] = None
56+ self ._connection = connection
57+ self ._guid = object . _guid
58+ self ._object = object
5959
6060 async def send (self , method : str , params : Dict = None ) -> Any :
6161 return await self ._connection .wrap_api_call (
@@ -71,7 +71,7 @@ def send_no_reply(self, method: str, params: Dict = None) -> None:
7171 # No reply messages are used to e.g. waitForEventInfo(after).
7272 self ._connection .wrap_api_call_sync (
7373 lambda : self ._connection ._send_message_to_server (
74- self ._guid , method , {} if params is None else params , True
74+ self ._object , method , {} if params is None else params , True
7575 )
7676 )
7777
@@ -80,7 +80,9 @@ async def inner_send(
8080 ) -> Any :
8181 if params is None :
8282 params = {}
83- callback = self ._connection ._send_message_to_server (self ._guid , method , params )
83+ callback = self ._connection ._send_message_to_server (
84+ self ._object , method , params
85+ )
8486 if self ._connection ._error :
8587 error = self ._connection ._error
8688 self ._connection ._error = None
@@ -121,33 +123,34 @@ def __init__(
121123 self ._loop : asyncio .AbstractEventLoop = parent ._loop
122124 self ._dispatcher_fiber : Any = parent ._dispatcher_fiber
123125 self ._type = type
124- self ._guid = guid
126+ self ._guid : str = guid
125127 self ._connection : Connection = (
126128 parent ._connection if isinstance (parent , ChannelOwner ) else parent
127129 )
128130 self ._parent : Optional [ChannelOwner ] = (
129131 parent if isinstance (parent , ChannelOwner ) else None
130132 )
131133 self ._objects : Dict [str , "ChannelOwner" ] = {}
132- self ._channel : Channel = Channel (self ._connection , guid )
133- self ._channel ._object = self
134+ self ._channel : Channel = Channel (self ._connection , self )
134135 self ._initializer = initializer
136+ self ._was_collected = False
135137
136138 self ._connection ._objects [guid ] = self
137139 if self ._parent :
138140 self ._parent ._objects [guid ] = self
139141
140142 self ._event_to_subscription_mapping : Dict [str , str ] = {}
141143
142- def _dispose (self ) -> None :
144+ def _dispose (self , reason : Optional [ str ] ) -> None :
143145 # Clean up from parent and connection.
144146 if self ._parent :
145147 del self ._parent ._objects [self ._guid ]
146148 del self ._connection ._objects [self ._guid ]
149+ self ._was_collected = reason == "gc"
147150
148151 # Dispose all children.
149152 for object in list (self ._objects .values ()):
150- object ._dispose ()
153+ object ._dispose (reason )
151154 self ._objects .clear ()
152155
153156 def _adopt (self , child : "ChannelOwner" ) -> None :
@@ -308,10 +311,14 @@ def set_in_tracing(self, is_tracing: bool) -> None:
308311 self ._tracing_count -= 1
309312
310313 def _send_message_to_server (
311- self , guid : str , method : str , params : Dict , no_reply : bool = False
314+ self , object : ChannelOwner , method : str , params : Dict , no_reply : bool = False
312315 ) -> ProtocolCallback :
313316 if self ._closed_error_message :
314317 raise Error (self ._closed_error_message )
318+ if object ._was_collected :
319+ raise Error (
320+ "The object has been collected to prevent unbounded heap growth."
321+ )
315322 self ._last_id += 1
316323 id = self ._last_id
317324 callback = ProtocolCallback (self ._loop )
@@ -335,7 +342,7 @@ def _send_message_to_server(
335342 )
336343 message = {
337344 "id" : id ,
338- "guid" : guid ,
345+ "guid" : object . _guid ,
339346 "method" : method ,
340347 "params" : self ._replace_channels_with_guids (params ),
341348 "metadata" : {
@@ -345,7 +352,7 @@ def _send_message_to_server(
345352 "internal" : not stack_trace_information ["apiName" ],
346353 },
347354 }
348- if self ._tracing_count > 0 and frames and guid != "localUtils" :
355+ if self ._tracing_count > 0 and frames and object . _guid != "localUtils" :
349356 self .local_utils .add_stack_to_tracing_no_reply (id , frames )
350357
351358 self ._transport .send (message )
@@ -401,7 +408,8 @@ def dispatch(self, msg: ParsedMessagePayload) -> None:
401408 return
402409
403410 if method == "__dispose__" :
404- self ._objects [guid ]._dispose ()
411+ assert isinstance (params , dict )
412+ self ._objects [guid ]._dispose (cast (Optional [str ], params .get ("reason" )))
405413 return
406414 object = self ._objects [guid ]
407415 should_replace_guids_with_channels = "jsonPipe@" not in guid
0 commit comments