js_arc/
lib.rs

1//! This is a Send + Sync abstraction for JsValue.
2//!
3//! It makes it possible to wrap a JsValue in an Arc and use it with other wrapped JsValues. It also supports async closures and covers some trait operations. **It accomplishes this by keeping JsValues on one thread and sending closures from other threads to be executed on it**.
4//!
5//!
6//! This is how to create a wrapped value
7//!```
8//!let js_v = JsArc::new(|| "Hello World!".into()).await;
9//!
10//!js_v.with_self(|js_value| {
11//!    web_sys::console::log_1(&js_value);
12//!    js_value
13//!})
14//!.await;
15//!```
16//! After creating values, they can still be changed
17//!```
18//!let js_v = JsArc::new(|| 2.into()).await;
19//!js_v.with_self(|one| one + &5.into()).await;
20//!
21//!// Outputs 7
22//!js_v.with_self(|js_v| {
23//!    web_sys::console::log_1(&js_v);
24//!    js_v
25//!})
26//!.await;
27//! ```
28//!
29//!
30//! This demonstrates creating two JsValues and using them with each other
31//! ```
32//!let one = JsArc::new(|| 1.into()).await;
33//!let two = JsArc::new(|| 2.into()).await;
34//!
35//!let three = one
36//!    .with_other(&two, |one, two| {
37//!        let add_result: JsValue = &one + &two;
38//!
39//!        (one, two, add_result)
40//!    })
41//!    .await;
42//!
43//!three
44//!    .with_self(|three| {
45//!        web_sys::console::log_1(&three);
46//!
47//!        three
48//!    })
49//!    .await;
50//!```
51//!   
52//!It also works with async closures
53//!   
54//!```
55//!let js_v = JsArc::new(|| "Hello World!".into()).await;
56//!
57//!js_v.with_self_async(|hello| async move {
58//!    web_sys::console::log_1(&"Waiting 5 second then printing value".into());
59//!    async_std::task::sleep(Duration::from_secs(5)).await;
60//!    web_sys::console::log_1(&hello);
61//!
62//!    hello
63//!})
64//!.await;
65//!```
66//!    
67//!And async closures with two JsValues
68//!    
69//!```
70//!let five = three
71//!    .with_other_async(&two, |three, two| async {
72//!        web_sys::console::log_1(&"Waiting 1 second then adding values".into());
73//!        async_std::task::sleep(Duration::from_secs(1)).await;
74//!        let add_result: JsValue = &three + &two;
75//!
76//!        (three, two, add_result)
77//!    })
78//!    .await;
79//!
80//!five.with_self(|five| {
81//!    web_sys::console::log_1(&five);
82//!
83//!    five
84//!})
85//!.await;
86//!```
87//!And many JsValues
88//!```
89//!let v0 = JsArc::new(|| 0.into()).await;
90//!let v1 = JsArc::new(|| 1.into()).await;
91//!let v2 = JsArc::new(|| 2.into()).await;
92//!let v3 = JsArc::new(|| 3.into()).await;
93//!let v4 = JsArc::new(|| 4.into()).await;
94//!
95//!let ten = v0
96//!    .with_many(vec![&v1, &v2, &v3, &v4], |mut all| {
97//!        let [v0, v1, v2, v3, v4] = &all[..] else {
98//!            unreachable!("Not possible");
99//!        };
100//!
101//!        let result = v0 + v1 + v2 + v3 + v4;
102//!
103//!        all.push(result);
104//!        all
105//!    })
106//!    .await; 
107//!```
108//!The purpose for writing it was to simplify use of JsValues across different threads.
109//!    
110//!```
111//!// It works inside Arc so it can be used on different threads. JsValue does not support Send + Sync by itself.
112//!let value_in_arc: Arc<JsArc> = Arc::new(three);
113//!let str: Arc<JsArc> = JsArc::new(|| "hello!".into()).await.arc();
114//!```
115//! And it also supports some trait operations: Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Shl, Shr, Sub
116//!```
117//!let three = (&one + &two).await;
118//!let ten = (&(&three * &three).await + &one).await;
119//!let seven = (&ten - &three).await;
120//!
121//!seven
122//!    .with_self(|seven| {
123//!        web_sys::console::log_1(&seven);
124//!
125//!        seven
126//!    })
127//!    .await;
128//!```
129//! # Warning
130//! <div class="warning">This is not tested. The syntax of this abstraction compiles, but it has not been tested with actual multithreading. Rust WASM does not support threading by default in the 2021 edition. In this untested state it can be used to pass trait restriction requirements for Send + Sync. There was not unsafe code used in writing this and the implmentation should be correct for a threading environment.
131//! </div>
132
133use std::{
134    collections::HashMap,
135    ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Shl, Shr, Sub},
136    pin::Pin,
137    sync::{Arc, Mutex},
138};
139
140use async_channel::{unbounded, Receiver, Sender};
141
142use once_cell::sync::Lazy;
143use std::future::Future;
144
145use wasm_bindgen::JsValue;
146use wasm_bindgen_futures::{js_sys::Object, wasm_bindgen};
147trait ExecuteOnJs: Send + Sync {
148    fn execute(&self, v: JsValue) -> JsValue;
149}
150
151impl<T: Fn(JsValue) -> JsValue + Send + Sync> ExecuteOnJs for T {
152    fn execute(&self, v: JsValue) -> JsValue {
153        (&self)(v)
154    }
155}
156
157trait ExecuteOnMultiple: Send + Sync {
158    fn execute(&self, v: JsValue, v2: JsValue) -> (JsValue, JsValue, JsValue);
159}
160
161impl<T: Fn(JsValue, JsValue) -> (JsValue, JsValue, JsValue) + Send + Sync> ExecuteOnMultiple for T {
162    fn execute(&self, v: JsValue, v2: JsValue) -> (JsValue, JsValue, JsValue) {
163        (&self)(v, v2)
164    }
165}
166
167trait ExecuteOnMany: Send + Sync {
168    fn execute(&self, v: Vec<JsValue>) -> Vec<JsValue>;
169}
170
171impl<T: Fn(Vec<JsValue>) -> Vec<JsValue> + Send + Sync> ExecuteOnMany for T {
172    fn execute(&self, v: Vec<JsValue>) -> Vec<JsValue> {
173        (&self)(v)
174    }
175}
176
177trait ExecuteOnManyAsync: Send + Sync + 'static {
178    fn execute(&self, v: Vec<JsValue>) -> Pin<Box<dyn Future<Output = Vec<JsValue>>>>;
179}
180
181impl<
182        FUT: Future<Output = Vec<JsValue>> + 'static,
183        T: Fn(Vec<JsValue>) -> FUT + Send + Sync + 'static,
184    > ExecuteOnManyAsync for T
185{
186    fn execute(&self, v: Vec<JsValue>) -> Pin<Box<dyn Future<Output = Vec<JsValue>>>> {
187        Box::pin((&self)(v))
188    }
189}
190
191trait ExecuteOnJsAsync: Send + Sync + 'static {
192    fn execute(&self, v: JsValue) -> Pin<Box<dyn Future<Output = JsValue>>>;
193}
194
195impl<R: Future<Output = JsValue> + 'static, F: Fn(JsValue) -> R + Send + Sync + 'static>
196    ExecuteOnJsAsync for F
197{
198    fn execute(&self, v: JsValue) -> Pin<Box<dyn Future<Output = JsValue>>> {
199        Box::pin((&self)(v))
200    }
201}
202
203trait ExecuteOnMultipleAsync: Send + Sync + 'static {
204    fn execute(
205        &self,
206        v1: JsValue,
207        v2: JsValue,
208    ) -> Pin<Box<dyn Future<Output = (JsValue, JsValue, JsValue)>>>;
209}
210
211impl<
212        R: Future<Output = (JsValue, JsValue, JsValue)> + 'static,
213        F: Fn(JsValue, JsValue) -> R + Send + Sync + 'static,
214    > ExecuteOnMultipleAsync for F
215{
216    fn execute(
217        &self,
218        v1: JsValue,
219        v2: JsValue,
220    ) -> Pin<Box<dyn Future<Output = (JsValue, JsValue, JsValue)>>> {
221        Box::pin((&self)(v1, v2))
222    }
223}
224
225/// This handle provides access to the running JsArcServer which maintains the storage for all JsValues
226/// that are being managed by JsArc values.
227///
228/// If the value of it is None, it hasn't been initialized yet.
229static JS_ARC_HANDLE: Lazy<Mutex<Option<Arc<async_channel::Sender<ServerCommands>>>>> =
230    Lazy::new(|| Mutex::new(None));
231
232enum ServerCommands {
233    // function, result_id
234    Initialize(Box<dyn ExecuteOnJs>, Sender<usize>),
235    InitializeAsync(Box<dyn ExecuteOnJsAsync>, Sender<usize>),
236    // id, function, notify when done executing
237    Use(usize, Box<dyn ExecuteOnJs>, Sender<()>),
238    UseAsync(usize, Box<dyn ExecuteOnJsAsync>, Sender<()>),
239    // id1, id2, function, result_id
240    UseTwo(usize, usize, Box<dyn ExecuteOnMultiple>, Sender<usize>),
241    UseTwoAsync(usize, usize, Box<dyn ExecuteOnMultipleAsync>, Sender<usize>),
242    // id of self, id for each item in vec, closure, result_id for new value
243    UseMany(usize, Vec<usize>, Box<dyn ExecuteOnMany>, Sender<usize>),
244    UseManyAsync(
245        usize,
246        Vec<usize>,
247        Box<dyn ExecuteOnManyAsync>,
248        Sender<usize>,
249    ),
250
251    // Remove value with id from memory
252    Deallocate(usize),
253    // The id maps to a complete handle that is used to notify the creating client that the future is processed
254    AsyncExecutionComplete(usize),
255}
256
257struct ExecutionResult<IDS, SENDBACKTYPE, SAVERESULT> {
258    // The send back type is what should be sent to the JsArc abstraction
259    js_arc_notifier: Sender<SENDBACKTYPE>,
260    // These are the ids in memory that correspond to JsValues. These need to be used to save the `result`
261    save_location_ids: IDS,
262    // This is the resulting JsValues after values from memory or used or created.
263    result: SAVERESULT,
264}
265
266enum FinishAsyncContainer {
267    // newly issued id, send back the new id for the JsArc, the JsValue that needs to be saved at the newly issued id
268    AfterCreateSendId(Receiver<ExecutionResult<usize, usize, JsValue>>),
269    // locations in memory that correspond to the js values. The newly issued id that the abstraction needs, the values to save to memory in the 1 fields memory locations
270    AfterMultiSaveCreateSendId(
271        Receiver<ExecutionResult<(usize, usize, usize), usize, (JsValue, JsValue, JsValue)>>,
272    ),
273    AfterManySaveCreateSendId(Receiver<ExecutionResult<Vec<usize>, usize, Vec<JsValue>>>),
274    // save the JsValue at the usize location, send the JsArc a complete signal when done
275    AfterUseSaveResultAndNotify(Receiver<ExecutionResult<usize, (), JsValue>>),
276}
277
278struct JsArcServer {
279    storage: HashMap<usize, JsValue>,
280    issued: usize,
281    // This is for async tasks to use while they're being processed. This id
282    // is for async_issued, not for issued.
283    temp_async_storage: HashMap<usize, FinishAsyncContainer>,
284    async_issued: usize,
285    handle: async_channel::Receiver<ServerCommands>,
286}
287
288impl JsArcServer {
289    fn claim_id(&mut self) -> usize {
290        let id = self.issued;
291        self.issued += 1;
292        id
293    }
294
295    fn claim_async_id(&mut self) -> usize {
296        let id = self.async_issued;
297        self.async_issued += 1;
298        id
299    }
300
301    async fn run(&mut self) {
302        while let Ok(next_cmd) = self.handle.recv().await {
303            match next_cmd {
304                ServerCommands::Initialize(create_closure, after_create_sender) => {
305                    let undefined: JsValue = Object::new().into();
306
307                    let id = self.claim_id();
308
309                    let initial = create_closure.execute(undefined);
310                    self.storage.insert(id, initial);
311
312                    let _ = after_create_sender.send(id).await;
313                }
314                ServerCommands::InitializeAsync(create_closure, after_create_sender) => {
315                    let undefined: JsValue = Object::new().into();
316
317                    let id = self.claim_id();
318                    let async_id = self.claim_async_id();
319
320                    let (s, r) = unbounded();
321
322                    self.temp_async_storage
323                        .insert(async_id, FinishAsyncContainer::AfterCreateSendId(r));
324
325                    // The goal is to not block receiving messages while async messages are processing. As an example,
326                    // the executing async function could timeout for 10 minutes. If this waited 10 minutes,
327                    // to handle the next sent server command, it really wouldn't be working as expected.
328                    wasm_bindgen_futures::spawn_local(async move {
329                        let initial = create_closure.execute(undefined).await;
330
331                        let result = ExecutionResult {
332                            js_arc_notifier: after_create_sender,
333                            save_location_ids: id,
334                            result: initial,
335                        };
336
337                        let _ = s.send(result).await;
338
339                        let client = JsArcClient::new();
340
341                        let _ = client
342                            .handle
343                            .send(ServerCommands::AsyncExecutionComplete(async_id))
344                            .await;
345                    });
346                }
347                ServerCommands::Use(id, use_value_closure, after_notify) => {
348                    let from_storage: JsValue = self.storage.get(&id).unwrap().clone();
349
350                    let after_use: JsValue = use_value_closure.execute(from_storage);
351                    self.storage.insert(id, after_use);
352
353                    let _ = after_notify.send(()).await;
354                }
355
356                // This is an almost word for word copy of the above, I just found it difficult to restructure
357                ServerCommands::UseAsync(id, use_value_closure, after_notify) => {
358                    let from_storage: JsValue = self.storage.get(&id).unwrap().clone();
359                    let async_id = self.claim_async_id();
360
361                    let (s, r) = unbounded();
362
363                    self.temp_async_storage.insert(
364                        async_id,
365                        FinishAsyncContainer::AfterUseSaveResultAndNotify(r),
366                    );
367
368                    // The goal is to not block receiving messages while async messages are processing. As an example,
369                    // the executing async function could timeout for 10 minutes. If this waited 10 minutes,
370                    // to handle the next sent server command, it really wouldn't be working as expected.
371                    wasm_bindgen_futures::spawn_local(async move {
372                        let result_after_use = use_value_closure.execute(from_storage).await;
373
374                        let result = ExecutionResult {
375                            js_arc_notifier: after_notify,
376                            save_location_ids: id,
377                            result: result_after_use,
378                        };
379
380                        let _ = s.send(result).await;
381
382                        let client = JsArcClient::new();
383
384                        let _ = client
385                            .handle
386                            .send(ServerCommands::AsyncExecutionComplete(async_id))
387                            .await;
388                    });
389                }
390                ServerCommands::Deallocate(id) => {
391                    self.storage.remove(&id);
392                }
393                ServerCommands::UseTwo(id1, id2, with_two_closure, result_id_sender) => {
394                    let from_storage_one: JsValue = self.storage.get(&id1).unwrap().clone();
395                    let from_storage_two: JsValue = self.storage.get(&id2).unwrap().clone();
396
397                    let (after_one, after_two, result) =
398                        with_two_closure.execute(from_storage_one, from_storage_two);
399
400                    self.storage.insert(id1, after_one);
401                    self.storage.insert(id2, after_two);
402                    self.storage.insert(self.issued, result);
403
404                    let result_id = self.claim_id();
405
406                    let _ = result_id_sender.send(result_id).await;
407                }
408
409                // This is an almost word for word copy of the above, I just found it difficult to restructure
410                ServerCommands::UseTwoAsync(id1, id2, with_two_closure, result_id_sender) => {
411                    let from_storage_one: JsValue = self.storage.get(&id1).unwrap().clone();
412                    let from_storage_two: JsValue = self.storage.get(&id2).unwrap().clone();
413
414                    let async_id = self.claim_async_id();
415                    let id = self.claim_id();
416
417                    let (s, r) = unbounded();
418
419                    self.temp_async_storage.insert(
420                        async_id,
421                        FinishAsyncContainer::AfterMultiSaveCreateSendId(r),
422                    );
423
424                    // The goal is to not block receiving messages while async messages are processing. As an example,
425                    // the executing async function could timeout for 10 minutes. If this waited 10 minutes,
426                    // to handle the next sent server command, it really wouldn't be working as expected.
427                    wasm_bindgen_futures::spawn_local(async move {
428                        let save = (id1, id2, id);
429                        let after = with_two_closure
430                            .execute(from_storage_one, from_storage_two)
431                            .await;
432
433                        let result = ExecutionResult {
434                            js_arc_notifier: result_id_sender,
435                            save_location_ids: save,
436                            result: after,
437                        };
438
439                        let _ = s.send(result).await;
440
441                        let client = JsArcClient::new();
442
443                        let _ = client
444                            .handle
445                            .send(ServerCommands::AsyncExecutionComplete(async_id))
446                            .await;
447                    });
448                }
449
450                ServerCommands::UseMany(id, mut other_ids, to_execute, extra_save_value) => {
451                    other_ids.insert(0, id);
452                    let mut all_ids = other_ids;
453
454                    let from_memory: Vec<JsValue> = all_ids
455                        .iter()
456                        .map(|v| self.storage.get(v).unwrap().clone())
457                        .collect();
458
459                    let after = to_execute.execute(from_memory);
460
461                    let last = self.claim_id();
462                    all_ids.push(last);
463
464                    all_ids
465                        .iter()
466                        .zip(after)
467                        .map(|(k, v)| {
468                            self.storage.insert(*k, v);
469                        })
470                        .count();
471
472                    let _ = extra_save_value.send(last).await;
473                }
474                ServerCommands::UseManyAsync(id, mut other_ids, to_execute, extra_save_value) => {
475                    let store_async_id = self.claim_async_id();
476                    let new_id = self.claim_id();
477
478                    other_ids.insert(0, id);
479                    let mut all_ids = other_ids;
480
481                    let from_memory: Vec<JsValue> = all_ids
482                        .iter()
483                        .map(|v| self.storage.get(v).unwrap().clone())
484                        .collect();
485
486                    all_ids.push(new_id);
487
488                    let (s, r) = unbounded();
489
490                    self.temp_async_storage.insert(
491                        store_async_id,
492                        FinishAsyncContainer::AfterManySaveCreateSendId(r),
493                    );
494
495                    wasm_bindgen_futures::spawn_local(async move {
496                        let save = all_ids;
497                        let after = to_execute.execute(from_memory).await;
498
499                        let result = ExecutionResult {
500                            js_arc_notifier: extra_save_value,
501                            save_location_ids: save,
502                            result: after,
503                        };
504
505                        let _ = s.send(result).await;
506
507                        let client = JsArcClient::new();
508
509                        let _ = client
510                            .handle
511                            .send(ServerCommands::AsyncExecutionComplete(store_async_id))
512                            .await;
513                    });
514                    // );
515                }
516                ServerCommands::AsyncExecutionComplete(async_id) => {
517                    let result = self
518                        .temp_async_storage
519                        .remove(&async_id)
520                        .expect("I don't know how it was removed, this should never happen");
521
522                    match result {
523                        FinishAsyncContainer::AfterCreateSendId(recv) => {
524                            let result = recv.recv().await.expect("This should never fail");
525
526                            let ExecutionResult {
527                                js_arc_notifier,
528                                save_location_ids: id,
529                                result,
530                            } = result;
531
532                            self.storage.insert(id, result);
533
534                            let _ = js_arc_notifier.send(id).await;
535                        }
536                        FinishAsyncContainer::AfterUseSaveResultAndNotify(recv) => {
537                            let result = recv.recv().await.expect("This should never fail");
538
539                            let ExecutionResult {
540                                js_arc_notifier,
541                                save_location_ids: id,
542                                result,
543                            } = result;
544
545                            self.storage.insert(id, result);
546
547                            let _ = js_arc_notifier.send(()).await;
548                        }
549                        FinishAsyncContainer::AfterMultiSaveCreateSendId(recv) => {
550                            let result = recv.recv().await.expect("This should never fail");
551
552                            let ExecutionResult {
553                                js_arc_notifier,
554                                save_location_ids: (id1, id2, newly_issued_id),
555                                result: (after_one, after_two, result),
556                            } = result;
557
558                            self.storage.insert(id1, after_one);
559                            self.storage.insert(id2, after_two);
560                            self.storage.insert(newly_issued_id, result);
561
562                            let _ = js_arc_notifier.send(newly_issued_id).await;
563                        }
564                        FinishAsyncContainer::AfterManySaveCreateSendId(recv) => {
565                            let result = recv.recv().await.expect("This should never fail");
566
567                            let ExecutionResult {
568                                js_arc_notifier,
569                                save_location_ids,
570                                result,
571                            } = result;
572
573                            let last_copy = *save_location_ids.last().unwrap();
574
575                            save_location_ids
576                                .into_iter()
577                                .zip(result.into_iter())
578                                .for_each(|(k, v)| {
579                                    self.storage.insert(k, v);
580                                });
581
582                            let _ = js_arc_notifier.send(last_copy).await;
583                        }
584                    }
585                }
586            }
587        }
588    }
589}
590
591#[derive(Clone)]
592struct JsArcClient {
593    handle: Arc<async_channel::Sender<ServerCommands>>,
594}
595
596impl JsArcClient {
597    fn new() -> JsArcClient {
598        if let Ok(mut locked) = JS_ARC_HANDLE.lock() {
599            let handle: &mut Option<Arc<Sender<ServerCommands>>> = &mut locked;
600
601            if handle.is_none() {
602                let (s, r) = async_channel::unbounded::<ServerCommands>();
603
604                let server = JsArcServer {
605                    storage: HashMap::new(),
606                    issued: 0,
607                    handle: r,
608                    temp_async_storage: HashMap::new(),
609                    async_issued: 0,
610                };
611
612                *handle = Some(Arc::new(s));
613
614                wasm_bindgen_futures::spawn_local(async move {
615                    let mut server = server;
616
617                    server.run().await;
618                });
619            }
620
621            if let Some(initalized_handle) = handle {
622                let borrowed_handle: &mut Arc<_> = initalized_handle;
623
624                let copy = borrowed_handle.clone();
625
626                let client = JsArcClient { handle: copy };
627
628                return client;
629            }
630        }
631
632        panic!("It should not be possible to panic. It's possible there's a problem with the Mutex implementation used in the environment.");
633    }
634}
635
636pub struct JsArc {
637    client: JsArcClient,
638    issue_id: usize,
639}
640
641impl JsArc {
642    /// Creates a wrapped JsValue from an initialization closure.
643    ///```
644    ///let js_value = JsArc::new(|| "Hello World!".into()).await;
645    ///```
646    pub async fn new<F: Fn() -> JsValue + Send + Sync + 'static>(
647        initialization_closure: F,
648    ) -> JsArc {
649        let initalize_fn = move |_| initialization_closure();
650        let client = JsArcClient::new();
651
652        let (s, r) = unbounded();
653
654        let _ = client
655            .handle
656            .send(ServerCommands::Initialize(Box::new(initalize_fn), s))
657            .await;
658
659        let id = r.recv().await.unwrap();
660
661        JsArc {
662            client,
663            issue_id: id,
664        }
665    }
666
667    /// Creates a wrapped JsValue from an async initialization closure.
668    ///```
669    ///#[wasm_bindgen]
670    ///extern "C" {
671    ///    #[wasm_bindgen]
672    ///    pub type HelloWorldModule;
673    ///
674    ///    #[wasm_bindgen(method, js_name = "helloWorld")]
675    ///    pub fn hello_world(this: &HelloWorldModule);
676    ///
677    ///}
678    ///
679    ///pub async fn load_dynamic_hello_world() -> HelloWorldModule {
680    ///    let module_as_str = r#"export function helloWorld() { console.log("Hello World!"); }"#;
681    ///
682    ///    let from_data = Array::new();
683    ///    from_data.push(&module_as_str.into());
684    ///
685    ///    let mut type_set: BlobPropertyBag = BlobPropertyBag::new();
686    ///    type_set.type_("application/javascript");
687    ///
688    ///    let blob = Blob::new_with_str_sequence_and_options(&from_data, &type_set).unwrap();
689    ///    let module_address = web_sys::Url::create_object_url_with_blob(&blob).unwrap();
690    ///
691    ///    let module_promise: Promise = js_sys::eval(&format!(r#"import ("{}")"#, module_address))
692    ///        .unwrap()
693    ///        .into();
694    ///
695    ///    let module = JsFuture::from(module_promise).await.unwrap();
696    ///
697    ///    let as_hello_world: HelloWorldModule = module.into();
698    ///    as_hello_world.hello_world();
699    ///
700    ///    as_hello_world
701    ///}
702    ///
703    ///let module = JsArc::new_async(|| async { load_dynamic_hello_world().await.into() }).await;
704    ///```
705    pub async fn new_async<
706        K: Future<Output = JsValue> + 'static,
707        F: Fn() -> K + Send + Sync + 'static,
708    >(
709        initialization_closure: F,
710    ) -> JsArc {
711        let initalize_fn = move |_| {
712            let generation = initialization_closure();
713
714            async { generation.await }
715        };
716
717        let client = JsArcClient::new();
718
719        let (s, r) = unbounded();
720
721        let _ = client
722            .handle
723            .send(ServerCommands::InitializeAsync(Box::new(initalize_fn), s))
724            .await;
725
726        let id = r.recv().await.unwrap();
727
728        JsArc {
729            client,
730            issue_id: id,
731        }
732    }
733
734    /// Wraps in an Arc. The impl is the following
735    ///```
736    ///Arc::new(self)
737    ///```
738    pub fn arc(self) -> Arc<Self> {
739        Arc::new(self)
740    }
741
742    /// Provides the ability to use and modify the JsValue abstracted by the wrapped JsValue
743    /// ```
744    ///let js_v = JsArc::new(|| "Hello World!".into()).await;
745    ///
746    ///js_v.with_self(|js_value| {
747    ///    web_sys::console::log_1(&js_value);
748    ///    js_value
749    ///})
750    ///.await;
751    ///```
752    /// The value returned from the closure is the value saved for the abstraction.
753    ///
754    /// The following outputs 7
755    /// ```
756    ///let js_v = JsArc::new(|| 2.into()).await;
757    ///js_v.with_self(|one| one + &5.into()).await;
758    ///js_v.with_self(|js_v| {
759    ///    web_sys::console::log_1(&js_v);
760    ///    js_v
761    ///})
762    ///.await;
763    ///```
764    pub async fn with_self<F: Fn(JsValue) -> JsValue + Send + Sync + 'static>(
765        &self,
766        usage_closure: F,
767    ) {
768        let id = self.issue_id.clone();
769        let client = self.client.clone();
770
771        let (s, r) = unbounded();
772
773        let _ = client
774            .handle
775            .send(ServerCommands::Use(id, Box::new(usage_closure), s))
776            .await;
777
778        let _ = r.recv().await;
779    }
780
781    /// Provides the ability to asynchronously use and modify the JsValue abstracted by the wrapped JsValue
782    ///```
783    ///js_value
784    ///    .with_self_async(|hello| async move {
785    ///        web_sys::console::log_1(&"Waiting 5 second then printing value".into());
786    ///        async_std::task::sleep(Duration::from_secs(5)).await;
787    ///        web_sys::console::log_1(&hello);
788    ///
789    ///        hello
790    ///    })
791    ///    .await;
792    ///```
793    pub async fn with_self_async<
794        R: Future<Output = JsValue> + 'static,
795        F: Fn(JsValue) -> R + Send + Sync + 'static,
796    >(
797        &self,
798        v: F,
799    ) {
800        let id = self.issue_id.clone();
801        let client = self.client.clone();
802
803        let (s, r) = unbounded();
804
805        let _ = client
806            .handle
807            .send(ServerCommands::UseAsync(id, Box::new(v), s))
808            .await;
809
810        let _ = r.recv().await;
811    }
812
813    /// Provides the ability to use and modify two JsValues at once while also creating a new abstracted JsValue for a third value
814    ///```
815    ///let one = JsArc::new(|| 1.into()).await;
816    ///let two = JsArc::new(|| 2.into()).await;
817    ///
818    ///let three = one
819    ///    .with_other(&two, |one, two| {
820    ///        let add_result: JsValue = &one + &two;
821    ///
822    ///        (one, two, add_result)
823    ///    })
824    ///    .await;
825    ///    
826    ///three
827    ///    .with_self(|three| {
828    ///        web_sys::console::log_1(&three);
829    ///
830    ///        three
831    ///    })
832    ///    .await;
833    ///```
834    pub async fn with_other<
835        F: Fn(JsValue, JsValue) -> (JsValue, JsValue, JsValue) + Send + Sync + 'static,
836    >(
837        &self,
838        other: &Self,
839        v: F,
840    ) -> JsArc {
841        let id1 = self.issue_id.clone();
842        let id2 = other.issue_id.clone();
843        let client = self.client.clone();
844
845        let (s, r) = unbounded();
846
847        let _ = client
848            .handle
849            .send(ServerCommands::UseTwo(id1, id2, Box::new(v), s))
850            .await;
851
852        let result = JsArc {
853            client: client.clone(),
854            issue_id: r.recv().await.unwrap(),
855        };
856
857        result
858    }
859
860    /// Provides the ability to asynchronously use and modify two JsValues at once while also creating a new abstracted JsValue for a third value
861    ///```
862    ///let five = three
863    ///    .with_other_async(&two, |three, two| async {
864    ///        web_sys::console::log_1(&"Waiting 1 second then adding values".into());
865    ///        async_std::task::sleep(Duration::from_secs(1)).await;
866    ///        let add_result: JsValue = &three + &two;
867    ///
868    ///        (three, two, add_result)
869    ///    })
870    ///    .await;
871    ///
872    ///five.with_self(|five| {
873    ///    web_sys::console::log_1(&five);
874    ///
875    ///    five
876    ///})
877    ///.await;
878    ///```
879    pub async fn with_other_async<
880        R: Future<Output = (JsValue, JsValue, JsValue)> + 'static,
881        F: Fn(JsValue, JsValue) -> R + Send + Sync + 'static,
882    >(
883        &self,
884        other: &Self,
885        v: F,
886    ) -> JsArc {
887        let id1 = self.issue_id.clone();
888        let id2 = other.issue_id.clone();
889        let client = self.client.clone();
890
891        let (s, r) = unbounded();
892
893        let _ = client
894            .handle
895            .send(ServerCommands::UseTwoAsync(id1, id2, Box::new(v), s))
896            .await;
897
898        let result = JsArc {
899            client: client.clone(),
900            issue_id: r.recv().await.unwrap(),
901        };
902
903        result
904    }
905
906    /// Places the &self value in the front of the Vec, then calls the defined closure. It expects
907    /// to end with an extra value at the end of the Vec.
908    ///```
909    ///let v0 = JsArc::new(|| 0.into()).await;
910    ///let v1 = JsArc::new(|| 1.into()).await;
911    ///let v2 = JsArc::new(|| 2.into()).await;
912    ///let v3 = JsArc::new(|| 3.into()).await;
913    ///let v4 = JsArc::new(|| 4.into()).await;
914    ///
915    ///let ten = v0
916    ///    .with_many(vec![&v1, &v2, &v3, &v4], |mut all| {
917    ///        let [v0, v1, v2, v3, v4] = &all[..] else {
918    ///            unreachable!("Not possible");
919    ///        };
920    ///
921    ///        let result = v0 + v1 + v2 + v3 + v4;
922    ///
923    ///        all.push(result);
924    ///        all
925    ///    })
926    ///    .await;
927    ///```  
928    pub async fn with_many<F: Fn(Vec<JsValue>) -> Vec<JsValue> + Send + Sync + 'static>(
929        &self,
930        others: Vec<&Self>,
931        closure_all_returns_all_and_extra: F,
932    ) -> JsArc {
933        let id1 = self.issue_id.clone();
934        let others: Vec<usize> = others.iter().map(|v| v.issue_id.clone()).collect();
935
936        let client = self.client.clone();
937
938        let (s, r) = unbounded();
939
940        let _ = client
941            .handle
942            .send(ServerCommands::UseMany(
943                id1,
944                others,
945                Box::new(closure_all_returns_all_and_extra),
946                s,
947            ))
948            .await;
949
950        let result = JsArc {
951            client: client.clone(),
952            issue_id: r.recv().await.unwrap(),
953        };
954
955        result
956    }
957
958    /// Places the &self value in the front of the Vec, then calls the defined closure. It expects
959    /// to end with an extra value at the end of the Vec.
960    ///```
961    ///    let v0 = JsArc::new(|| 0.into()).await;
962    ///    let v1 = JsArc::new(|| 1.into()).await;
963    ///    let v2 = JsArc::new(|| 2.into()).await;
964    ///    let v3 = JsArc::new(|| 3.into()).await;
965    ///    let v4 = JsArc::new(|| 4.into()).await;
966    ///
967    ///    let twenty = v0
968    ///        .with_many_async(vec![&v1, &v2, &v3, &v4], |mut all| async {
969    ///            let [v0, v1, v2, v3, v4] = &all[..] else {
970    ///                unreachable!("Not possible");
971    ///            };
972    ///
973    ///            let result = (v0 + v1 + v2 + v3 + v4) * v2;
974    ///
975    ///            web_sys::console::log_1(&"Waiting 1 second before continuing".into());
976    ///            async_std::task::sleep(Duration::from_secs(1)).await;
977    ///
978    ///            all.push(result);
979    ///            all
980    ///        })
981    ///        .await;
982    ///
983    ///    twenty
984    ///        .with_self(|result| {
985    ///            web_sys::console::log_1(&result);
986    ///
987    ///            result
988    ///        })
989    ///        .await;    
990    ///```
991    pub async fn with_many_async<
992        FUT: Future<Output = Vec<JsValue>> + 'static,
993        F: Fn(Vec<JsValue>) -> FUT + Send + Sync + 'static,
994    >(
995        &self,
996        others: Vec<&Self>,
997        closure_all_returns_all_and_extra: F,
998    ) -> JsArc {
999        let id1 = self.issue_id.clone();
1000        let others: Vec<usize> = others.iter().map(|v| v.issue_id.clone()).collect();
1001
1002        let client = self.client.clone();
1003
1004        let (s, r) = unbounded();
1005
1006        let _ = client
1007            .handle
1008            .send(ServerCommands::UseManyAsync(
1009                id1,
1010                others,
1011                Box::new(closure_all_returns_all_and_extra),
1012                s,
1013            ))
1014            .await;
1015
1016        let result = JsArc {
1017            client: client.clone(),
1018            issue_id: r.recv().await.unwrap(),
1019        };
1020
1021        result
1022    }
1023}
1024
1025impl Drop for JsArc {
1026    fn drop(&mut self) {
1027        let drop_id = self.issue_id.clone();
1028        let handle_copy = self.client.handle.clone();
1029
1030        wasm_bindgen_futures::spawn_local(async move {
1031            let _ = handle_copy.send(ServerCommands::Deallocate(drop_id)).await;
1032        });
1033    }
1034}
1035
1036pub struct JsArcFutureWrap {
1037    inner: Option<Pin<Box<dyn Future<Output = JsArc>>>>,
1038}
1039
1040impl Future for JsArcFutureWrap {
1041    type Output = JsArc;
1042
1043    fn poll(
1044        mut self: Pin<&mut Self>,
1045        cx: &mut std::task::Context<'_>,
1046    ) -> std::task::Poll<Self::Output> {
1047        let Some(mut fut) = self.inner.take() else {
1048            unreachable!("Not possible");
1049        };
1050
1051        let state = Future::poll(fut.as_mut(), cx);
1052
1053        self.inner = Some(fut);
1054
1055        state
1056    }
1057}
1058
1059pub struct JsArcFutureWrapLifetime<'a> {
1060    inner: Option<Pin<Box<dyn Future<Output = JsArc> + 'a>>>,
1061    // other: PhantomData<&'a A>,
1062}
1063
1064impl<'a> Future for JsArcFutureWrapLifetime<'a> {
1065    type Output = JsArc;
1066
1067    fn poll(
1068        mut self: Pin<&mut Self>,
1069        cx: &mut std::task::Context<'_>,
1070    ) -> std::task::Poll<Self::Output> {
1071        let Some(mut fut) = self.inner.take() else {
1072            unreachable!("Not possible");
1073        };
1074
1075        let state = Future::poll(fut.as_mut(), cx);
1076
1077        self.inner = Some(fut);
1078
1079        state
1080    }
1081}
1082
1083impl Add for JsArc {
1084    type Output = JsArcFutureWrap;
1085
1086    fn add(self, rhs: Self) -> Self::Output {
1087        let out = async move {
1088            self.with_other(&rhs, |l, r| {
1089                let result = &l + &r;
1090                (l, r, result)
1091            })
1092            .await
1093        };
1094
1095        let result = JsArcFutureWrap {
1096            inner: Some(Box::pin(out)),
1097        };
1098
1099        result
1100    }
1101}
1102
1103impl BitAnd for JsArc {
1104    type Output = JsArcFutureWrap;
1105
1106    fn bitand(self, rhs: Self) -> Self::Output {
1107        let out = async move {
1108            self.with_other(&rhs, |l, r| {
1109                let result = &l & &r;
1110                (l, r, result)
1111            })
1112            .await
1113        };
1114
1115        let result = JsArcFutureWrap {
1116            inner: Some(Box::pin(out)),
1117        };
1118
1119        result
1120    }
1121}
1122
1123impl BitOr for JsArc {
1124    type Output = JsArcFutureWrap;
1125
1126    fn bitor(self, rhs: Self) -> Self::Output {
1127        let out = async move {
1128            self.with_other(&rhs, |l, r| {
1129                let result = &l | &r;
1130                (l, r, result)
1131            })
1132            .await
1133        };
1134
1135        let result = JsArcFutureWrap {
1136            inner: Some(Box::pin(out)),
1137        };
1138
1139        result
1140    }
1141}
1142
1143impl BitXor for JsArc {
1144    type Output = JsArcFutureWrap;
1145
1146    fn bitxor(self, rhs: Self) -> Self::Output {
1147        let out = async move {
1148            self.with_other(&rhs, |l, r| {
1149                let result = &l ^ &r;
1150                (l, r, result)
1151            })
1152            .await
1153        };
1154
1155        let result = JsArcFutureWrap {
1156            inner: Some(Box::pin(out)),
1157        };
1158
1159        result
1160    }
1161}
1162
1163impl Div for JsArc {
1164    type Output = JsArcFutureWrap;
1165
1166    fn div(self, rhs: Self) -> Self::Output {
1167        let out = async move {
1168            self.with_other(&rhs, |l, r| {
1169                let result = &l / &r;
1170                (l, r, result)
1171            })
1172            .await
1173        };
1174
1175        let result = JsArcFutureWrap {
1176            inner: Some(Box::pin(out)),
1177        };
1178
1179        result
1180    }
1181}
1182
1183impl Mul for JsArc {
1184    type Output = JsArcFutureWrap;
1185
1186    fn mul(self, rhs: Self) -> Self::Output {
1187        let out = async move {
1188            self.with_other(&rhs, |l, r| {
1189                let result = &l * &r;
1190
1191                (l, r, result)
1192            })
1193            .await
1194        };
1195
1196        let result = JsArcFutureWrap {
1197            inner: Some(Box::pin(out)),
1198        };
1199
1200        result
1201    }
1202}
1203
1204impl Neg for JsArc {
1205    type Output = JsArcFutureWrap;
1206
1207    fn neg(self) -> Self::Output {
1208        let out = async move {
1209            let new = self
1210                .with_other(&JsArc::new(|| "undefined".into()).await, |l, _| {
1211                    let copy = l.clone();
1212                    let r: JsValue = (-copy).into();
1213
1214                    (l, r.clone(), r)
1215                })
1216                .await;
1217
1218            new
1219        };
1220
1221        let result = JsArcFutureWrap {
1222            inner: Some(Box::pin(out)),
1223        };
1224
1225        result
1226    }
1227}
1228
1229impl Not for JsArc {
1230    type Output = JsArcFutureWrap;
1231
1232    fn not(self) -> Self::Output {
1233        let out = async move {
1234            let new = self
1235                .with_other(&JsArc::new(|| "undefined".into()).await, |l, _| {
1236                    let copy = l.clone();
1237                    let r: JsValue = (!copy).into();
1238
1239                    (l, r.clone(), r)
1240                })
1241                .await;
1242
1243            new
1244        };
1245
1246        let result = JsArcFutureWrap {
1247            inner: Some(Box::pin(out)),
1248        };
1249
1250        result
1251    }
1252}
1253
1254impl Shl for JsArc {
1255    type Output = JsArcFutureWrap;
1256
1257    fn shl(self, rhs: Self) -> Self::Output {
1258        let out = async move {
1259            self.with_other(&rhs, |l, r| {
1260                let result = &l << &r;
1261
1262                (l, r, result)
1263            })
1264            .await
1265        };
1266
1267        let result = JsArcFutureWrap {
1268            inner: Some(Box::pin(out)),
1269        };
1270
1271        result
1272    }
1273}
1274
1275impl Shr for JsArc {
1276    type Output = JsArcFutureWrap;
1277
1278    fn shr(self, rhs: Self) -> Self::Output {
1279        let out = async move {
1280            self.with_other(&rhs, |l, r| {
1281                let result = &l >> &r;
1282
1283                (l, r, result)
1284            })
1285            .await
1286        };
1287
1288        let result = JsArcFutureWrap {
1289            inner: Some(Box::pin(out)),
1290        };
1291
1292        result
1293    }
1294}
1295
1296impl Sub for JsArc {
1297    type Output = JsArcFutureWrap;
1298
1299    fn sub(self, rhs: Self) -> Self::Output {
1300        let out = async move {
1301            self.with_other(&rhs, |l, r| {
1302                let result = &l - &r;
1303
1304                (l, r, result)
1305            })
1306            .await
1307        };
1308
1309        let result = JsArcFutureWrap {
1310            inner: Some(Box::pin(out)),
1311        };
1312
1313        result
1314    }
1315}
1316
1317impl<'a> Add for &'a JsArc {
1318    type Output = JsArcFutureWrapLifetime<'a>;
1319
1320    fn add(self, rhs: Self) -> Self::Output {
1321        let out = self.with_other(&rhs, |l, r| {
1322            let result = &l + &r;
1323
1324            (l, r, result)
1325        });
1326
1327        let result = JsArcFutureWrapLifetime {
1328            inner: Some(Box::pin(out)),
1329        };
1330
1331        result
1332    }
1333}
1334
1335impl<'a> BitAnd for &'a JsArc {
1336    type Output = JsArcFutureWrapLifetime<'a>;
1337
1338    fn bitand(self, rhs: Self) -> Self::Output {
1339        let out = self.with_other(&rhs, |l, r| {
1340            let result = &l & &r;
1341
1342            (l, r, result)
1343        });
1344
1345        let result = JsArcFutureWrapLifetime {
1346            inner: Some(Box::pin(out)),
1347        };
1348
1349        result
1350    }
1351}
1352
1353impl<'a> BitOr for &'a JsArc {
1354    type Output = JsArcFutureWrapLifetime<'a>;
1355
1356    fn bitor(self, rhs: Self) -> Self::Output {
1357        let out = self.with_other(&rhs, |l, r| {
1358            let result = &l | &r;
1359
1360            (l, r, result)
1361        });
1362
1363        let result = JsArcFutureWrapLifetime {
1364            inner: Some(Box::pin(out)),
1365        };
1366
1367        result
1368    }
1369}
1370
1371impl<'a> BitXor for &'a JsArc {
1372    type Output = JsArcFutureWrapLifetime<'a>;
1373
1374    fn bitxor(self, rhs: Self) -> Self::Output {
1375        let out = self.with_other(&rhs, |l, r| {
1376            let result = &l ^ &r;
1377
1378            (l, r, result)
1379        });
1380
1381        let result = JsArcFutureWrapLifetime {
1382            inner: Some(Box::pin(out)),
1383        };
1384
1385        result
1386    }
1387}
1388
1389impl<'a> Div for &'a JsArc {
1390    type Output = JsArcFutureWrapLifetime<'a>;
1391
1392    fn div(self, rhs: Self) -> Self::Output {
1393        let out = self.with_other(&rhs, |l, r| {
1394            let result = &l / &r;
1395
1396            (l, r, result)
1397        });
1398
1399        let result = JsArcFutureWrapLifetime {
1400            inner: Some(Box::pin(out)),
1401        };
1402
1403        result
1404    }
1405}
1406
1407impl<'a> Mul for &'a JsArc {
1408    type Output = JsArcFutureWrapLifetime<'a>;
1409
1410    fn mul(self, rhs: Self) -> Self::Output {
1411        let out = self.with_other(&rhs, |l, r| {
1412            let result = &l * &r;
1413
1414            (l, r, result)
1415        });
1416
1417        let result = JsArcFutureWrapLifetime {
1418            inner: Some(Box::pin(out)),
1419        };
1420
1421        result
1422    }
1423}
1424
1425impl<'a> Neg for &'a JsArc {
1426    type Output = JsArcFutureWrapLifetime<'a>;
1427
1428    fn neg(self) -> Self::Output {
1429        let out = async move {
1430            let new = self
1431                .with_other(&JsArc::new(|| "undefined".into()).await, |l, _| {
1432                    let copy = l.clone();
1433                    let r: JsValue = (-copy).into();
1434
1435                    (l, r.clone(), r)
1436                })
1437                .await;
1438
1439            new
1440        };
1441
1442        let result = JsArcFutureWrapLifetime {
1443            inner: Some(Box::pin(out)),
1444        };
1445
1446        result
1447    }
1448}
1449
1450impl<'a> Not for &'a JsArc {
1451    type Output = JsArcFutureWrapLifetime<'a>;
1452
1453    fn not(self) -> Self::Output {
1454        let out = async move {
1455            let new = self
1456                .with_other(&JsArc::new(|| "undefined".into()).await, |l, _| {
1457                    let copy = l.clone();
1458                    let r: JsValue = (!copy).into();
1459
1460                    (l, r.clone(), r)
1461                })
1462                .await;
1463
1464            new
1465        };
1466
1467        let result = JsArcFutureWrapLifetime {
1468            inner: Some(Box::pin(out)),
1469        };
1470
1471        result
1472    }
1473}
1474
1475impl<'a> Shl for &'a JsArc {
1476    type Output = JsArcFutureWrapLifetime<'a>;
1477
1478    fn shl(self, rhs: Self) -> Self::Output {
1479        let out = self.with_other(&rhs, |l, r| {
1480            let result = &l << &r;
1481
1482            (l, r, result)
1483        });
1484
1485        let result = JsArcFutureWrapLifetime {
1486            inner: Some(Box::pin(out)),
1487        };
1488
1489        result
1490    }
1491}
1492
1493impl<'a> Shr for &'a JsArc {
1494    type Output = JsArcFutureWrapLifetime<'a>;
1495
1496    fn shr(self, rhs: Self) -> Self::Output {
1497        let out = self.with_other(&rhs, |l, r| {
1498            let result = &l >> &r;
1499
1500            (l, r, result)
1501        });
1502
1503        let result = JsArcFutureWrapLifetime {
1504            inner: Some(Box::pin(out)),
1505        };
1506
1507        result
1508    }
1509}
1510
1511impl<'a> Sub for &'a JsArc {
1512    type Output = JsArcFutureWrapLifetime<'a>;
1513
1514    fn sub(self, rhs: Self) -> Self::Output {
1515        let out = self.with_other(&rhs, |l, r| {
1516            let result = &l - &r;
1517
1518            (l, r, result)
1519        });
1520
1521        let result = JsArcFutureWrapLifetime {
1522            inner: Some(Box::pin(out)),
1523        };
1524
1525        result
1526    }
1527}