1use crate::imp::{core::*, impl_future::*, prelude::*};
2use serde_json::value::Value;
3use std::{fmt::Debug, future::Future, pin::Pin, sync::TryLockError, task::Waker};
4
5pub(crate) fn upgrade<T>(w: &Weak<T>) -> Result<Arc<T>, Error> {
6 w.upgrade().ok_or(Error::ObjectNotFound)
7}
8
9pub(crate) fn weak_and_then<T, U, F>(w: &Weak<T>, f: F) -> Weak<U>
10where
11 F: FnOnce(Arc<T>) -> Weak<U>
12{
13 let rc = match w.upgrade() {
14 None => return Weak::new(),
15 Some(rc) => rc
16 };
17 f(rc)
18}
19
20#[derive(Debug)]
21pub(crate) struct ChannelOwner {
22 pub(crate) ctx: Weak<Mutex<Context>>,
23 pub(crate) parent: Option<RemoteWeak>,
24 pub(crate) typ: Str<ObjectType>,
25 pub(crate) guid: Str<Guid>,
26 pub(crate) initializer: Value,
27 children: Mutex<Vec<RemoteWeak>>
28}
29
30impl ChannelOwner {
31 pub(crate) fn new(
32 ctx: Weak<Mutex<Context>>,
33 parent: RemoteWeak,
34 typ: Str<ObjectType>,
35 guid: Str<Guid>,
36 initializer: Value
37 ) -> Self {
38 Self {
39 ctx,
40 parent: Some(parent),
41 typ,
42 guid,
43 initializer,
44 children: Mutex::new(Vec::new())
45 }
46 }
47
48 pub(crate) fn new_root() -> Self {
49 Self {
50 ctx: Weak::new(),
51 parent: None,
52 typ: Str::validate("".into()).unwrap(),
53 guid: Str::validate("".into()).unwrap(),
54 initializer: Value::default(),
55 children: Mutex::default()
56 }
57 }
58
59 pub(crate) fn create_request(&self, method: Str<Method>) -> RequestBody {
60 RequestBody::new(self.guid.clone(), method)
61 }
62
63 pub(crate) async fn send_message(
64 &self,
65 r: RequestBody
66 ) -> Result<WaitData<WaitMessageResult>, Error> {
67 let wait = WaitData::new();
68 let r = r.set_wait(&wait);
69 let ctx = upgrade(&self.ctx)?;
70 ctx.lock().unwrap().send_message(r)?;
71 Ok(wait)
72 }
73
74 pub(crate) fn children(&self) -> Vec<RemoteWeak> { self.children.lock().unwrap().to_vec() }
75
76 pub(crate) fn push_child(&self, c: RemoteWeak) {
77 let children = &mut self.children.lock().unwrap();
78 children.push(c);
79 }
80}
81
82#[derive(Debug)]
83pub(crate) struct DummyObject {
84 channel: ChannelOwner
85}
86
87impl DummyObject {
88 pub(crate) fn new(channel: ChannelOwner) -> Self { DummyObject { channel } }
89}
90
91impl RemoteObject for DummyObject {
92 fn channel(&self) -> &ChannelOwner { &self.channel }
93 fn channel_mut(&mut self) -> &mut ChannelOwner { &mut self.channel }
94}
95
96#[derive(Debug)]
97pub(crate) struct RootObject {
98 channel: ChannelOwner
99}
100
101impl RootObject {
102 pub(crate) fn new() -> Self {
103 Self {
104 channel: ChannelOwner::new_root()
105 }
106 }
107}
108
109impl Default for RootObject {
110 fn default() -> Self { Self::new() }
111}
112
113impl RemoteObject for RootObject {
114 fn channel(&self) -> &ChannelOwner { &self.channel }
115 fn channel_mut(&mut self) -> &mut ChannelOwner { &mut self.channel }
116}
117
118pub(crate) trait RemoteObject: Debug {
119 fn channel(&self) -> &ChannelOwner;
120 fn channel_mut(&mut self) -> &mut ChannelOwner;
121
122 fn guid(&self) -> &S<Guid> { &self.channel().guid }
123 fn context(&self) -> Result<Arc<Mutex<Context>>, Error> { upgrade(&self.channel().ctx) }
124
125 fn handle_event(
126 &self,
127 _ctx: &Context,
128 _method: Str<Method>,
129 _params: Map<String, Value>
130 ) -> Result<(), Error> {
131 Ok(())
132 }
133}
134
135mod remote_enum {
136 use super::{DummyObject as Dummy, RootObject as Root, *};
137 use crate::imp::{
138 artifact::Artifact, binding_call::BindingCall, browser::Browser,
139 browser_context::BrowserContext, browser_type::BrowserType,
140 console_message::ConsoleMessage, dialog::Dialog, element_handle::ElementHandle,
141 frame::Frame, js_handle::JsHandle, page::Page, playwright::Playwright, request::Request,
142 response::Response, route::Route, selectors::Selectors, stream::Stream,
143 websocket::WebSocket, worker::Worker
144 };
145
146 macro_rules! upgrade {
147 ($($t:ident),*) => {
148 pub(crate) fn upgrade(&self) -> Option<RemoteArc> {
149 match self {
150 $(
151 Self::$t(x) => x.upgrade().map(RemoteArc::$t)
152 ),*
153 }
154 }
155 }
156 }
157
158 macro_rules! downgrade {
159 ($($t:ident),*) => {
160 pub(crate) fn downgrade(&self) -> RemoteWeak {
161 match self {
162 $(
163 Self::$t(x) => RemoteWeak::$t(Arc::downgrade(x))
164 ),*
165 }
166 }
167 }
168 }
169
170 macro_rules! handle_event {
171 ($($t:ident),*) => {
172 pub(crate) fn handle_event(
173 &self, ctx: &Context, method: Str<Method>, params: Map<String, Value>
174 ) -> Result<(), Error> {
175 match self {
176 $(
177 Self::$t(x) => x.handle_event(ctx, method, params)
178 ),*
179 }
180 }
181 }
182 }
183
184 macro_rules! channel {
185 ($($t:ident),*) => {
186 pub(crate) fn channel(&self) -> &ChannelOwner {
187 match self {
188 $(
189 Self::$t(x) => x.channel()
190 ),*
191 }
192 }
193 }
194 }
195
196 macro_rules! remote_enum {
197 ($($t:ident),*) => {
198 #[derive(Debug, Clone)]
199 pub(crate) enum RemoteArc {
200 $($t(Arc<$t>)),*
201 }
202
203 #[derive(Debug, Clone)]
204 pub(crate) enum RemoteWeak {
205 $($t(Weak<$t>)),*
206 }
207
208 impl RemoteWeak {
209 upgrade!{$($t),*}
210 }
211
212 impl RemoteArc {
213 downgrade!{$($t),*}
214 handle_event!{$($t),*}
215 channel!{$($t),*}
216 }
217 }
218 }
219
220 remote_enum! {
221 Dummy,
222 Root,
223 Artifact,
227 BindingCall,
228 Browser,
229 BrowserContext,
230 BrowserType,
231 ConsoleMessage,
233 Dialog,
234 ElementHandle,
237 Frame,
238 JsHandle,
239 Page,
240 Playwright,
241 Request,
242 Response,
243 Route,
244 Stream,
245 Selectors,
246 WebSocket,
247 Worker
248 }
249
250 impl RemoteArc {
251 pub(crate) fn try_new(
252 typ: &S<ObjectType>,
253 ctx: &Context,
254 c: ChannelOwner
255 ) -> Result<RemoteArc, Error> {
256 let r = match typ.as_str() {
257 "Artifact" => RemoteArc::Artifact(Arc::new(Artifact::try_new(c)?)),
258 "BindingCall" => RemoteArc::BindingCall(Arc::new(BindingCall::new(c))),
259 "Browser" => RemoteArc::Browser(Arc::new(Browser::try_new(c)?)),
260 "BrowserContext" => {
261 RemoteArc::BrowserContext(Arc::new(BrowserContext::try_new(c)?))
262 }
263 "BrowserType" => RemoteArc::BrowserType(Arc::new(BrowserType::try_new(c)?)),
264 "ConsoleMessage" => {
265 RemoteArc::ConsoleMessage(Arc::new(ConsoleMessage::try_new(ctx, c)?))
266 }
267 "Dialog" => RemoteArc::Dialog(Arc::new(Dialog::new(c))),
268 "ElementHandle" => RemoteArc::ElementHandle(Arc::new(ElementHandle::new(c))),
269 "Frame" => RemoteArc::Frame(Arc::new(Frame::try_new(ctx, c)?)),
270 "JSHandle" => RemoteArc::JsHandle(Arc::new(JsHandle::try_new(c)?)),
271 "Page" => RemoteArc::Page(Arc::new(Page::try_new(ctx, c)?)),
272 "Playwright" => RemoteArc::Playwright(Arc::new(Playwright::try_new(ctx, c)?)),
273 "Request" => RemoteArc::Request(Request::try_new(ctx, c)?),
274 "Response" => RemoteArc::Response(Arc::new(Response::try_new(ctx, c)?)),
275 "Route" => RemoteArc::Route(Arc::new(Route::try_new(ctx, c)?)),
276 "Stream" => RemoteArc::Stream(Arc::new(Stream::new(c))),
277 "Selectors" => RemoteArc::Selectors(Arc::new(Selectors::new(c))),
278 "WebSocket" => RemoteArc::WebSocket(Arc::new(WebSocket::try_new(c)?)),
279 "Worker" => RemoteArc::Worker(Arc::new(Worker::try_new(c)?)),
280 _ => RemoteArc::Dummy(Arc::new(DummyObject::new(c)))
281 };
282 Ok(r)
283 }
284 }
285}
286
287pub(crate) use remote_enum::{RemoteArc, RemoteWeak};
288
289pub(crate) struct RequestBody {
290 pub(crate) guid: Str<Guid>,
291 pub(crate) method: Str<Method>,
292 pub(crate) params: Map<String, Value>,
293 pub(crate) place: WaitPlaces<WaitMessageResult>
294}
295
296impl RequestBody {
297 pub(crate) fn new(guid: Str<Guid>, method: Str<Method>) -> RequestBody {
298 RequestBody {
299 guid,
300 method,
301 params: Map::default(),
302 place: WaitPlaces::new_empty()
303 }
304 }
305
306 pub(crate) fn set_params(mut self, params: Map<String, Value>) -> Self {
312 self.params = params;
313 self
314 }
315
316 pub(crate) fn set_args<T: Serialize>(self, body: T) -> Result<Self, Error> {
317 let v = serde_json::value::to_value(body).map_err(Error::Serde)?;
318 let p = match v {
319 Value::Object(m) => m,
320 _ => return Err(Error::NotObject)
321 };
322 Ok(self.set_params(p))
323 }
324
325 pub(crate) fn set_wait(mut self, wait: &WaitData<WaitMessageResult>) -> Self {
326 self.place = wait.place();
327 self
328 }
329
330 }
335
336pub(crate) type WaitMessageResult = Result<Result<Arc<Value>, Arc<ErrorMessage>>, Arc<Error>>;
337
338#[derive(Debug, Clone)]
339pub(crate) struct WaitPlaces<T> {
340 pub(crate) value: Wm<Option<T>>,
341 pub(crate) waker: Wm<Option<Waker>>
342}
343
344pub(crate) struct WaitData<T> {
345 place: Arc<Mutex<Option<T>>>,
346 waker: Arc<Mutex<Option<Waker>>>
347}
348
349impl<T> WaitPlaces<T> {
350 pub(crate) fn new_empty() -> Self {
351 Self {
352 value: Weak::new(),
353 waker: Weak::new()
354 }
355 }
356}
357
358impl<T> WaitData<T> {
359 pub(crate) fn new() -> Self {
360 let place = Arc::new(Mutex::new(None));
361 let waker = Arc::new(Mutex::new(None));
362 Self { place, waker }
363 }
364
365 pub(crate) fn place(&self) -> WaitPlaces<T> {
366 let wp = Arc::downgrade(&self.place);
367 let ww = Arc::downgrade(&self.waker);
368 WaitPlaces {
369 value: wp,
370 waker: ww
371 }
372 }
373}
374
375impl<T> Future for WaitData<T>
376where
377 T: Clone
378{
379 type Output = T;
380
381 fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
382 let this = self.get_mut();
383 log::trace!("poll WaitData");
384 macro_rules! pending {
385 () => {{
386 cx.waker().wake_by_ref();
387 return Poll::Pending;
388 }};
389 }
390 {
391 let x = match this.place.try_lock() {
392 Ok(x) => x,
393 Err(TryLockError::WouldBlock) => pending!(),
394 Err(e) => Err(e).unwrap()
395 };
396 if let Some(x) = &*x {
397 return Poll::Ready(x.clone());
398 }
399 }
400 {
401 let mut x = match this.waker.try_lock() {
402 Ok(x) => x,
403 Err(TryLockError::WouldBlock) => pending!(),
404 Err(e) => Err(e).unwrap()
405 };
406 if x.is_none() {
407 *x = Some(cx.waker().clone());
408 }
409 }
410 Poll::Pending
411 }
412}