on master help sign in
port to std futures and async/await
commit957fec48a238bb88d673cd655a6f204b4abaefdd authorldesgoui <ldesgoui@ldesgoui.xyz> dateSat 30 Nov 2019, 03:45 (7 years ago) parentedb74a7
2 files changed+75−76
crates/js-api/src/lib.rs+9−6 src/vdom.rs+66−70
crates/js-api/src/lib.rs+9−6
@@ -116,7 +116,6 @@ impl Render for GreetingViaJs {
116116#![deny(missing_docs, missing_debug_implementations)]
117117
118118use dodrio::{builder, bumpalo, Node, Render, RenderContext};
119−use futures::prelude::*;
120119use js_sys::{Object, Promise, Reflect};
121120use wasm_bindgen::prelude::*;
122121use wasm_bindgen::JsCast;
@@ -185,12 +184,16 @@ impl VdomWeak {
185184 /// Schedule re-rendering of the virtual DOM. A promise is returned that is
186185 /// resolved after the rendering has happened.
187186 pub fn render(&self) -> Promise {
188− wasm_bindgen_futures::future_to_promise(
189− self.inner.render().map(|_| JsValue::null()).map_err(|e| {
187+ let future = self.inner.render();
188+
189+ wasm_bindgen_futures::future_to_promise(async move {
190+ if let Err(e) = future.await {
190191 let msg = e.to_string();
191− js_sys::Error::new(&msg).into()
192− }),
193− )
192+ Err(js_sys::Error::new(&msg).into())
193+ } else {
194+ Ok(JsValue::null())
195+ }
196+ })
194197 }
195198}
196199
src/vdom.rs+66−70
@@ -6,11 +6,11 @@ use crate::events::EventsRegistry;
66use crate::node::{Node, NodeKey};
77use crate::RenderContext;
88use bumpalo::Bump;
9−use futures::future::Future;
109use fxhash::FxHashMap;
1110use std::cell::Cell;
1211use std::cell::RefCell;
1312use std::fmt;
13+use std::future::Future;
1414use std::mem;
1515use std::mem::ManuallyDrop;
1616use std::rc::{Rc, Weak};
@@ -371,25 +371,20 @@ impl VdomWeak {
371371 /// Replace the root rendering component with the new `root`.
372372 ///
373373 /// Returns a future that resolves to the *old* root component.
374− pub fn set_component(
374+ pub async fn set_component(
375375 self,
376376 root: Box<dyn RootRender>,
377− ) -> impl Future<Item = Box<dyn RootRender + 'static>, Error = VdomDroppedError> {
378− futures::future::ok(self.inner.upgrade())
379− .and_then(|inner| inner.ok_or(()))
380− .map_err(|_| VdomDroppedError {})
381− .and_then(|inner| {
382− let promise = js_sys::Promise::resolve(&JsValue::null());
383− JsFuture::from(promise)
384− .map_err(|_| VdomDroppedError {})
385− .and_then(move |_| {
386− let old = {
387− let mut exclusive = inner.exclusive.borrow_mut();
388− mem::replace(&mut *exclusive.component.as_mut().unwrap_throw(), root)
389− };
390− VdomWeak::new(&inner).render().map(|_| old)
391− })
392− })
377+ ) -> Result<Box<dyn RootRender + 'static>, VdomDroppedError> {
378+ let inner = self.inner.upgrade().ok_or(VdomDroppedError {})?;
379+
380+ let old = {
381+ let mut exclusive = inner.exclusive.borrow_mut();
382+ mem::replace(&mut *exclusive.component.as_mut().unwrap_throw(), root)
383+ };
384+
385+ VdomWeak::new(&inner).render().await?;
386+
387+ Ok(old)
393388 }
394389
395390 /// Execute `f` with a reference to this virtual DOM's root rendering
@@ -397,24 +392,15 @@ impl VdomWeak {
397392 ///
398393 /// To ensure exclusive access to the root rendering component, the
399394 /// invocation takes place on a new tick of the micro-task queue.
400− pub fn with_component<F, T>(&self, f: F) -> impl Future<Item = T, Error = VdomDroppedError>
395+ pub async fn with_component<F, T>(&self, f: F) -> Result<T, VdomDroppedError>
401396 where
402397 F: 'static + FnOnce(&mut dyn RootRender) -> T,
403398 {
404− futures::future::ok(self.inner.upgrade())
405− .and_then(|inner| inner.ok_or(()))
406− .map_err(|_| VdomDroppedError {})
407− .and_then(|inner| {
408− let mut f = Some(f);
409− let promise = js_sys::Promise::resolve(&JsValue::null());
410− JsFuture::from(promise)
411− .map_err(|_| VdomDroppedError {})
412− .map(move |_| {
413− let f = f.take().unwrap_throw();
414− let mut exclusive = inner.exclusive.borrow_mut();
415− f(exclusive.component_raw_mut())
416− })
417− })
399+ let inner = self.inner.upgrade().ok_or(VdomDroppedError {})?;
400+
401+ let mut exclusive = inner.exclusive.borrow_mut();
402+
403+ Ok(f(exclusive.component_raw_mut()))
418404 }
419405
420406 /// Schedule a render to occur during the next animation frame.
@@ -423,7 +409,12 @@ impl VdomWeak {
423409 /// `render` instead.
424410 pub fn schedule_render(&self) {
425411 debug!("VdomWeak::schedule_render");
426− wasm_bindgen_futures::spawn_local(self.render().map_err(|_| ()));
412+
413+ let future = self.render();
414+
415+ wasm_bindgen_futures::spawn_local(async move {
416+ let _ = future.await;
417+ });
427418 }
428419
429420 /// Schedule a render to occur during the next animation frame and return a
@@ -431,41 +422,46 @@ impl VdomWeak {
431422 ///
432423 /// If you don't want to do more things after the render completes, then use
433424 /// `schedule_render` instead of `render`.
434− pub fn render(&self) -> impl Future<Item = (), Error = VdomDroppedError> {
435− futures::future::ok(self.inner.upgrade())
436− .and_then(|inner| inner.ok_or(()))
437− .map_err(|_| VdomDroppedError {})
438− .and_then(|inner| {
439− let promise = inner.shared.render_scheduled.take().unwrap_or_else(|| {
440− js_sys::Promise::new(&mut |resolve, reject| {
441− let vdom = VdomWeak {
442− inner: Rc::downgrade(&inner),
443− };
444− with_animation_frame(move || match vdom.inner.upgrade() {
445− None => {
446− warn!("VdomWeak::render: vdom unmounted before we could render");
447− let r = reject.call0(&JsValue::null());
448− debug_assert!(r.is_ok());
449− }
450− Some(inner) => {
451− let mut exclusive = inner.exclusive.borrow_mut();
452− exclusive.render();
453−
454− // We did the render, so take the promise away
455− // and let future `render` calls request new
456− // animation frames.
457− let _ = inner.shared.render_scheduled.take();
458−
459− let r = resolve.call0(&JsValue::null());
460− debug_assert!(r.is_ok());
461− }
462− });
463− })
464− });
465− inner.shared.render_scheduled.set(Some(promise.clone()));
466− JsFuture::from(promise)
467− .map(|_| ())
468− .map_err(|_| VdomDroppedError {})
469− })
425+ pub fn render(&self) -> impl Future<Output = Result<(), VdomDroppedError>> {
426+ let inner = self.inner.upgrade();
427+
428+ async move {
429+ let inner = inner.ok_or(VdomDroppedError {})?;
430+
431+ let promise = inner.shared.render_scheduled.take().unwrap_or_else(|| {
432+ js_sys::Promise::new(&mut |resolve, reject| {
433+ let vdom = VdomWeak {
434+ inner: Rc::downgrade(&inner),
435+ };
436+
437+ with_animation_frame(move || match vdom.inner.upgrade() {
438+ None => {
439+ warn!("VdomWeak::render: vdom unmounted before we could render");
440+ let r = reject.call0(&JsValue::null());
441+ debug_assert!(r.is_ok());
442+ }
443+ Some(inner) => {
444+ let mut exclusive = inner.exclusive.borrow_mut();
445+ exclusive.render();
446+
447+ // We did the render, so take the promise away
448+ // and let future `render` calls request new
449+ // animation frames.
450+ let _ = inner.shared.render_scheduled.take();
451+
452+ let r = resolve.call0(&JsValue::null());
453+ debug_assert!(r.is_ok());
454+ }
455+ });
456+ })
457+ });
458+
459+ inner.shared.render_scheduled.set(Some(promise.clone()));
460+
461+ JsFuture::from(promise)
462+ .await
463+ .map(drop)
464+ .map_err(|_| VdomDroppedError {})
465+ }
470466 }
471467}