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 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 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}