Skip to content

Commit b1696fc

Browse files
authored
chore: align selectors handling with upstream (microsoft#1176)
1 parent 0ffc788 commit b1696fc

File tree

5 files changed

+50
-13
lines changed

5 files changed

+50
-13
lines changed

playwright/_impl/_browser_type.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ async def connect(
206206
if not timeout_future.done():
207207
timeout_future.cancel()
208208
playwright: "Playwright" = next(iter(done)).result()
209+
playwright._set_selectors(self._playwright.selectors)
209210
self._connection._child_ws_connections.append(connection)
210211
pre_launched_browser = playwright._initializer.get("preLaunchedBrowser")
211212
assert pre_launched_browser
@@ -219,6 +220,7 @@ def handle_transport_close() -> None:
219220
page._on_close()
220221
context._on_close()
221222
browser._on_close()
223+
connection.cleanup()
222224

223225
transport.once("close", handle_transport_close)
224226

playwright/_impl/_connection.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union
2020

2121
from greenlet import greenlet
22-
from pyee import AsyncIOEventEmitter
22+
from pyee import AsyncIOEventEmitter, EventEmitter
2323

2424
from playwright._impl._helper import ParsedMessagePayload, parse_error
2525
from playwright._impl._transport import Transport
@@ -141,14 +141,15 @@ async def initialize(self) -> "Playwright":
141141
)
142142

143143

144-
class Connection:
144+
class Connection(EventEmitter):
145145
def __init__(
146146
self,
147147
dispatcher_fiber: Any,
148148
object_factory: Callable[[ChannelOwner, str, str, Dict], ChannelOwner],
149149
transport: Transport,
150150
loop: asyncio.AbstractEventLoop,
151151
) -> None:
152+
super().__init__()
152153
self._dispatcher_fiber = dispatcher_fiber
153154
self._transport = transport
154155
self._transport.on_message = lambda msg: self.dispatch(msg)
@@ -195,6 +196,7 @@ async def stop_async(self) -> None:
195196
def cleanup(self) -> None:
196197
for ws_connection in self._child_ws_connections:
197198
ws_connection._transport.dispose()
199+
self.emit("close")
198200

199201
def call_on_object_with_known_name(
200202
self, guid: str, callback: Callable[[ChannelOwner], None]

playwright/_impl/_object_factory.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from playwright._impl._network import Request, Response, Route, WebSocket
3131
from playwright._impl._page import BindingCall, Page, Worker
3232
from playwright._impl._playwright import Playwright
33-
from playwright._impl._selectors import Selectors
33+
from playwright._impl._selectors import SelectorsOwner
3434
from playwright._impl._stream import Stream
3535
from playwright._impl._tracing import Tracing
3636

@@ -90,5 +90,5 @@ def create_remote_object(
9090
if type == "Worker":
9191
return Worker(parent, type, guid, initializer)
9292
if type == "Selectors":
93-
return Selectors(parent, type, guid, initializer)
93+
return SelectorsOwner(parent, type, guid, initializer)
9494
return DummyObject(parent, type, guid, initializer)

playwright/_impl/_playwright.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from playwright._impl._connection import ChannelOwner, from_channel
1919
from playwright._impl._fetch import APIRequest
2020
from playwright._impl._local_utils import LocalUtils
21-
from playwright._impl._selectors import Selectors
21+
from playwright._impl._selectors import Selectors, SelectorsOwner
2222

2323

2424
class Playwright(ChannelOwner):
@@ -40,7 +40,14 @@ def __init__(
4040
self.firefox._playwright = self
4141
self.webkit = from_channel(initializer["webkit"])
4242
self.webkit._playwright = self
43-
self.selectors = from_channel(initializer["selectors"])
43+
44+
self.selectors = Selectors(self._loop)
45+
selectors_owner: SelectorsOwner = from_channel(initializer["selectors"])
46+
self.selectors._add_channel(selectors_owner)
47+
48+
self._connection.on(
49+
"close", lambda: self.selectors._remove_channel(selectors_owner)
50+
)
4451
self.devices = {}
4552
self.devices = {
4653
device["name"]: parse_device_descriptor(device["descriptor"])
@@ -57,6 +64,12 @@ def __getitem__(self, value: str) -> "BrowserType":
5764
return self.webkit
5865
raise ValueError("Invalid browser " + value)
5966

67+
def _set_selectors(self, selectors: SelectorsOwner) -> None:
68+
selectors_owner = from_channel(self._initializer["selectors"])
69+
self.selectors._remove_channel(selectors_owner)
70+
self.selectors = selectors
71+
self.selectors._add_channel(selectors_owner)
72+
6073
def stop(self) -> None:
6174
pass
6275

playwright/_impl/_selectors.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import asyncio
1516
from pathlib import Path
16-
from typing import Any, Dict, Union
17+
from typing import Any, Dict, List, Set, Union
1718

1819
from playwright._impl._api_types import Error
1920
from playwright._impl._connection import ChannelOwner
2021
from playwright._impl._helper import async_readfile
2122

2223

23-
class Selectors(ChannelOwner):
24-
def __init__(
25-
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
26-
) -> None:
27-
super().__init__(parent, type, guid, initializer)
24+
class Selectors:
25+
def __init__(self, loop: asyncio.AbstractEventLoop) -> None:
26+
self._loop = loop
27+
self._channels: Set[SelectorsOwner] = set()
28+
self._registrations: List[Dict] = []
2829

2930
async def register(
3031
self,
@@ -40,4 +41,23 @@ async def register(
4041
params: Dict[str, Any] = dict(name=name, source=script)
4142
if contentScript:
4243
params["contentScript"] = True
43-
await self._channel.send("register", params)
44+
for channel in self._channels:
45+
await channel._channel.send("register", params)
46+
self._registrations.append(params)
47+
48+
def _add_channel(self, channel: "SelectorsOwner") -> None:
49+
self._channels.add(channel)
50+
for params in self._registrations:
51+
# This should not fail except for connection closure, but just in case we catch.
52+
channel._channel.send_no_reply("register", params)
53+
54+
def _remove_channel(self, channel: "SelectorsOwner") -> None:
55+
if channel in self._channels:
56+
self._channels.remove(channel)
57+
58+
59+
class SelectorsOwner(ChannelOwner):
60+
def __init__(
61+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
62+
) -> None:
63+
super().__init__(parent, type, guid, initializer)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy