playwright/imp/
worker.rs

1use crate::imp::{
2    browser_context::BrowserContext, core::*, js_handle::JsHandle, page::Page, prelude::*
3};
4
5#[derive(Debug)]
6pub(crate) struct Worker {
7    channel: ChannelOwner,
8    url: String,
9    var: Mutex<Variable>,
10    tx: Mutex<Option<broadcast::Sender<Evt>>>
11}
12
13#[derive(Debug, Default)]
14pub(crate) struct Variable {
15    page: Option<Weak<Page>>,
16    browser_context: Option<Weak<BrowserContext>>
17}
18
19impl Worker {
20    pub(crate) fn try_new(channel: ChannelOwner) -> Result<Self, Error> {
21        let Initializer { url } = serde_json::from_value(channel.initializer.clone())?;
22        Ok(Self {
23            channel,
24            url,
25            var: Mutex::default(),
26            tx: Mutex::default()
27        })
28    }
29
30    pub(crate) fn url(&self) -> &str { &self.url }
31
32    pub(crate) async fn eval<U>(&self, expression: &str) -> ArcResult<U>
33    where
34        U: DeserializeOwned
35    {
36        self.evaluate::<(), U>(expression, None).await
37    }
38
39    pub(crate) async fn evaluate<T, U>(&self, expression: &str, arg: Option<T>) -> ArcResult<U>
40    where
41        T: Serialize,
42        U: DeserializeOwned
43    {
44        #[derive(Serialize)]
45        #[serde(rename_all = "camelCase")]
46        struct Args<'a> {
47            expression: &'a str,
48            arg: Value
49        }
50        let arg = ser::to_value(&arg).map_err(Error::SerializationPwJson)?;
51        let args = Args { expression, arg };
52        let v = send_message!(self, "evaluateExpression", args);
53        let first = first(&v).ok_or(Error::ObjectNotFound)?;
54        Ok(de::from_value(first).map_err(Error::DeserializationPwJson)?)
55    }
56
57    pub(crate) async fn eval_handle(&self, expression: &str) -> ArcResult<Weak<JsHandle>> {
58        self.evaluate_handle::<()>(expression, None).await
59    }
60
61    pub(crate) async fn evaluate_handle<T>(
62        &self,
63        expression: &str,
64        arg: Option<T>
65    ) -> ArcResult<Weak<JsHandle>>
66    where
67        T: Serialize
68    {
69        #[derive(Serialize)]
70        #[serde(rename_all = "camelCase")]
71        struct Args<'a> {
72            expression: &'a str,
73            arg: Value
74        }
75        let arg = ser::to_value(&arg).map_err(Error::SerializationPwJson)?;
76        let args = Args { expression, arg };
77        let v = send_message!(self, "evaluateExpressionHandle", args);
78        let guid = only_guid(&v)?;
79        let h = get_object!(self.context()?.lock().unwrap(), guid, JsHandle)?;
80        Ok(h)
81    }
82}
83
84impl Worker {
85    pub(crate) fn set_page(&self, page: Weak<Page>) { self.var.lock().unwrap().page = Some(page); }
86
87    // pub(crate) fn set_browser_context(&self, browser_context: Weak<BrowserContext>) {
88    //    self.var.lock().unwrap().browser_context = Some(browser_context);
89    //}
90
91    fn on_close(&self, ctx: &Context) -> Result<(), Error> {
92        let this = get_object!(ctx, self.guid(), Worker)?;
93        let var = self.var.lock().unwrap();
94        if let Some(page) = var.page.as_ref().and_then(Weak::upgrade) {
95            page.remove_worker(&this);
96        }
97        // var.context.remove_service_worker(&this)
98        self.emit_event(Evt::Close);
99        Ok(())
100    }
101}
102
103impl RemoteObject for Worker {
104    fn channel(&self) -> &ChannelOwner { &self.channel }
105    fn channel_mut(&mut self) -> &mut ChannelOwner { &mut self.channel }
106
107    fn handle_event(
108        &self,
109        ctx: &Context,
110        method: Str<Method>,
111        _params: Map<String, Value>
112    ) -> Result<(), Error> {
113        if method.as_str() == "close" {
114            self.on_close(ctx)?;
115        }
116        Ok(())
117    }
118}
119
120#[derive(Debug, Deserialize)]
121#[serde(rename_all = "camelCase")]
122struct Initializer {
123    url: String
124}
125
126#[derive(Debug, Clone)]
127pub(crate) enum Evt {
128    Close
129}
130
131#[derive(Debug, Clone, Copy, PartialEq)]
132pub enum EventType {
133    Close
134}
135
136impl IsEvent for Evt {
137    type EventType = EventType;
138
139    fn event_type(&self) -> Self::EventType {
140        match self {
141            Self::Close => EventType::Close
142        }
143    }
144}
145
146impl EventEmitter for Worker {
147    type Event = Evt;
148    fn tx(&self) -> Option<broadcast::Sender<Self::Event>> { self.tx.lock().unwrap().clone() }
149    fn set_tx(&self, tx: broadcast::Sender<Self::Event>) { *self.tx.lock().unwrap() = Some(tx); }
150}