From 9d1fc5ab0bc9373ba146bf36a89528ddb84ae3a2 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 9 May 2023 10:11:07 +0200 Subject: [PATCH 1/3] chore: do not continue with no_reply messages --- playwright/_impl/_connection.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/playwright/_impl/_connection.py b/playwright/_impl/_connection.py index 10a3fe6b3..7d9c09dc1 100644 --- a/playwright/_impl/_connection.py +++ b/playwright/_impl/_connection.py @@ -70,7 +70,7 @@ async def send_return_as_dict(self, method: str, params: Dict = None) -> Any: def send_no_reply(self, method: str, params: Dict = None) -> None: self._connection.wrap_api_call_sync( lambda: self._connection._send_message_to_server( - self._guid, method, {} if params is None else params + self._guid, method, {} if params is None else params, True ) ) @@ -178,6 +178,7 @@ def remove_listener(self, event: str, f: Any) -> None: class ProtocolCallback: def __init__(self, loop: asyncio.AbstractEventLoop) -> None: self.stack_trace: traceback.StackSummary + self.no_reply: bool self.future = loop.create_future() # The outer task can get cancelled by the user, this forwards the cancellation to the inner task. current_task = asyncio.current_task() @@ -305,7 +306,7 @@ def set_in_tracing(self, is_tracing: bool) -> None: self._tracing_count -= 1 def _send_message_to_server( - self, guid: str, method: str, params: Dict + self, guid: str, method: str, params: Dict, no_reply: bool = False ) -> ProtocolCallback: if self._closed_error_message: raise Error(self._closed_error_message) @@ -317,6 +318,7 @@ def _send_message_to_server( traceback.StackSummary, getattr(task, "__pw_stack_trace__", traceback.extract_stack()), ) + callback.no_reply = no_reply self._callbacks[id] = callback stack_trace_information = cast(ParsedStackTrace, self._api_zone.get()) frames = stack_trace_information.get("frames", []) @@ -357,6 +359,8 @@ def dispatch(self, msg: ParsedMessagePayload) -> None: callback = self._callbacks.pop(id) if callback.future.cancelled(): return + if callback.no_reply: + return error = msg.get("error") if error: parsed_error = parse_error(error["error"]) # type: ignore From dd7a6f013e653c93ee03b3b0d2331c830b847229 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 9 May 2023 21:30:56 +0200 Subject: [PATCH 2/3] review feedback --- playwright/_impl/_connection.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/playwright/_impl/_connection.py b/playwright/_impl/_connection.py index 7d9c09dc1..338dd0713 100644 --- a/playwright/_impl/_connection.py +++ b/playwright/_impl/_connection.py @@ -68,6 +68,8 @@ async def send_return_as_dict(self, method: str, params: Dict = None) -> Any: ) def send_no_reply(self, method: str, params: Dict = None) -> None: + # No reply messages are used to e.g. waitForEventInfo(after) which returns exceptions on page close. + # To prevent 'Future exception was never retrieved' we just ignore such messages. self._connection.wrap_api_call_sync( lambda: self._connection._send_message_to_server( self._guid, method, {} if params is None else params, True @@ -359,6 +361,8 @@ def dispatch(self, msg: ParsedMessagePayload) -> None: callback = self._callbacks.pop(id) if callback.future.cancelled(): return + # No reply messages are used to e.g. waitForEventInfo(after) which returns exceptions on page close. + # To prevent 'Future exception was never retrieved' we just ignore such messages. if callback.no_reply: return error = msg.get("error") From 4506332b0f4969b106b6504ed58df93240db9fb1 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 9 May 2023 21:32:58 +0200 Subject: [PATCH 3/3] nit --- playwright/_impl/_connection.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/playwright/_impl/_connection.py b/playwright/_impl/_connection.py index 338dd0713..a0762f339 100644 --- a/playwright/_impl/_connection.py +++ b/playwright/_impl/_connection.py @@ -68,8 +68,7 @@ async def send_return_as_dict(self, method: str, params: Dict = None) -> Any: ) def send_no_reply(self, method: str, params: Dict = None) -> None: - # No reply messages are used to e.g. waitForEventInfo(after) which returns exceptions on page close. - # To prevent 'Future exception was never retrieved' we just ignore such messages. + # No reply messages are used to e.g. waitForEventInfo(after). self._connection.wrap_api_call_sync( lambda: self._connection._send_message_to_server( self._guid, method, {} if params is None else params, True