51
51
52
52
53
53
class Channel (AsyncIOEventEmitter ):
54
- def __init__ (self , connection : "Connection" , guid : str ) -> None :
54
+ def __init__ (self , connection : "Connection" , object : "ChannelOwner" ) -> None :
55
55
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
59
59
60
60
async def send (self , method : str , params : Dict = None ) -> Any :
61
61
return await self ._connection .wrap_api_call (
@@ -71,7 +71,7 @@ def send_no_reply(self, method: str, params: Dict = None) -> None:
71
71
# No reply messages are used to e.g. waitForEventInfo(after).
72
72
self ._connection .wrap_api_call_sync (
73
73
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
75
75
)
76
76
)
77
77
@@ -80,7 +80,9 @@ async def inner_send(
80
80
) -> Any :
81
81
if params is None :
82
82
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
+ )
84
86
if self ._connection ._error :
85
87
error = self ._connection ._error
86
88
self ._connection ._error = None
@@ -121,33 +123,34 @@ def __init__(
121
123
self ._loop : asyncio .AbstractEventLoop = parent ._loop
122
124
self ._dispatcher_fiber : Any = parent ._dispatcher_fiber
123
125
self ._type = type
124
- self ._guid = guid
126
+ self ._guid : str = guid
125
127
self ._connection : Connection = (
126
128
parent ._connection if isinstance (parent , ChannelOwner ) else parent
127
129
)
128
130
self ._parent : Optional [ChannelOwner ] = (
129
131
parent if isinstance (parent , ChannelOwner ) else None
130
132
)
131
133
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 )
134
135
self ._initializer = initializer
136
+ self ._was_collected = False
135
137
136
138
self ._connection ._objects [guid ] = self
137
139
if self ._parent :
138
140
self ._parent ._objects [guid ] = self
139
141
140
142
self ._event_to_subscription_mapping : Dict [str , str ] = {}
141
143
142
- def _dispose (self ) -> None :
144
+ def _dispose (self , reason : Optional [ str ] ) -> None :
143
145
# Clean up from parent and connection.
144
146
if self ._parent :
145
147
del self ._parent ._objects [self ._guid ]
146
148
del self ._connection ._objects [self ._guid ]
149
+ self ._was_collected = reason == "gc"
147
150
148
151
# Dispose all children.
149
152
for object in list (self ._objects .values ()):
150
- object ._dispose ()
153
+ object ._dispose (reason )
151
154
self ._objects .clear ()
152
155
153
156
def _adopt (self , child : "ChannelOwner" ) -> None :
@@ -308,10 +311,14 @@ def set_in_tracing(self, is_tracing: bool) -> None:
308
311
self ._tracing_count -= 1
309
312
310
313
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
312
315
) -> ProtocolCallback :
313
316
if self ._closed_error_message :
314
317
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
+ )
315
322
self ._last_id += 1
316
323
id = self ._last_id
317
324
callback = ProtocolCallback (self ._loop )
@@ -335,7 +342,7 @@ def _send_message_to_server(
335
342
)
336
343
message = {
337
344
"id" : id ,
338
- "guid" : guid ,
345
+ "guid" : object . _guid ,
339
346
"method" : method ,
340
347
"params" : self ._replace_channels_with_guids (params ),
341
348
"metadata" : {
@@ -345,7 +352,7 @@ def _send_message_to_server(
345
352
"internal" : not stack_trace_information ["apiName" ],
346
353
},
347
354
}
348
- if self ._tracing_count > 0 and frames and guid != "localUtils" :
355
+ if self ._tracing_count > 0 and frames and object . _guid != "localUtils" :
349
356
self .local_utils .add_stack_to_tracing_no_reply (id , frames )
350
357
351
358
self ._transport .send (message )
@@ -401,7 +408,8 @@ def dispatch(self, msg: ParsedMessagePayload) -> None:
401
408
return
402
409
403
410
if method == "__dispose__" :
404
- self ._objects [guid ]._dispose ()
411
+ assert isinstance (params , dict )
412
+ self ._objects [guid ]._dispose (cast (Optional [str ], params .get ("reason" )))
405
413
return
406
414
object = self ._objects [guid ]
407
415
should_replace_guids_with_channels = "jsonPipe@" not in guid
0 commit comments