px_wsdom_core/interaction/
await.rs

1use core::{
2    fmt::Write,
3    future::{Future, IntoFuture},
4    task::Poll,
5};
6
7use alloc::{borrow::ToOwned, string::String};
8
9use crate::{
10    js_types::JsValue,
11    link::RetrievalState,
12    protocol::{DEL, ERR, GET, REP, SET},
13    Browser,
14};
15
16pub struct Await {
17    browser: Browser,
18    ret_id: u64,
19    cell_id: u64,
20}
21
22impl Future for Await {
23    type Output = JsValue;
24
25    fn poll(
26        self: core::pin::Pin<&mut Self>,
27        cx: &mut core::task::Context<'_>,
28    ) -> core::task::Poll<Self::Output> {
29        let this = self.get_mut();
30        let mut link = this.browser.0.lock();
31        let ret_id = this.ret_id;
32        match link.retrievals.entry(ret_id) {
33           hashbrown::hash_map::Entry::Occupied(mut occ) => {
34                let state = occ.get_mut();
35
36                let new_waker = cx.waker();
37                if !state.waker.will_wake(new_waker) {
38                    state.waker = new_waker.to_owned();
39                }
40
41                if state.times != 0 {
42                    let val_id = link.get_new_id();
43                    let cell_id = this.cell_id;
44                    writeln!(
45                        link.raw_commands_buf(),
46                        "{{var v = {GET}({cell_id}).$);(v.r?{ERR}:{SET})({val_id}, v.e), {DEL}({cell_id})}}}};"
47                    )
48                    .unwrap();
49                    link.wake_outgoing_lazy();
50                    Poll::Ready(JsValue {
51                        browser: this.browser.clone(),
52                        id: val_id,
53                    })
54                } else {
55                    Poll::Pending
56                }
57            }
58            hashbrown::hash_map::Entry::Vacant(vac) => {
59                vac.insert(RetrievalState {
60                    waker: cx.waker().to_owned(),
61                    last_value: String::new(),
62                    times: 0,
63                });
64                Poll::Pending
65            }
66        }
67    }
68}
69impl IntoFuture for JsValue {
70    type Output = JsValue;
71
72    type IntoFuture = Await;
73
74    fn into_future(self) -> Self::IntoFuture {
75        let mut link = self.browser.0.lock();
76        let ret_id = link.get_new_id();
77        let cell_id = link.get_new_id();
78        let id = self.id;
79        writeln!(
80            link.raw_commands_buf(),
81            "{SET}({cell_id},{{}}); try{{Promise.prototype.then.call({GET}({id}),function(e) {{{GET}({cell_id}).$ = {{e,r:0}}; {REP}({ret_id}, 0) }},function(e) {{{GET}({cell_id}).$ = {{e,r:1}}; {REP}({ret_id}, 0) }}))}}catch($){{{GET}({cell_id}).$ = {{e:e,r:1}}; {REP}({ret_id}, 0)}};"
82        )
83        .unwrap();
84        link.wake_outgoing_lazy();
85        return Await {
86            browser: self.browser.clone(),
87            ret_id,
88            cell_id,
89        };
90    }
91}