on master help sign in
port to std futures and async/await
957fec4ldesgoui
crates/js-api/src/lib.rs+9−6
@@ -116,7 +116,6 @@ impl Render for GreetingViaJs {
116#![deny(missing_docs, missing_debug_implementations)]
116#![deny(missing_docs, missing_debug_implementations)]
117
117
118use dodrio::{builder, bumpalo, Node, Render, RenderContext};
118use dodrio::{builder, bumpalo, Node, Render, RenderContext};
119−use futures::prelude::*;
120use js_sys::{Object, Promise, Reflect};
119use js_sys::{Object, Promise, Reflect};
121use wasm_bindgen::prelude::*;
120use wasm_bindgen::prelude::*;
122use wasm_bindgen::JsCast;
121use wasm_bindgen::JsCast;
@@ -185,12 +184,16 @@ impl VdomWeak {
185 /// Schedule re-rendering of the virtual DOM. A promise is returned that is
184 /// Schedule re-rendering of the virtual DOM. A promise is returned that is
186 /// resolved after the rendering has happened.
185 /// resolved after the rendering has happened.
187 pub fn render(&self) -> Promise {
186 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 {
190 let msg = e.to_string();
191 let msg = e.to_string();
191− js_sys::Error::new(&msg).into()
192+ Err(js_sys::Error::new(&msg).into())
192− }),
193+ } else {
194+ Ok(JsValue::null())
195+ }
193− )
196+ })
194 }
197 }
195}
198}
196
199
src/vdom.rs+66−70
@@ -6,11 +6,11 @@ use crate::events::EventsRegistry;
6use crate::node::{Node, NodeKey};
6use crate::node::{Node, NodeKey};
7use crate::RenderContext;
7use crate::RenderContext;
8use bumpalo::Bump;
8use bumpalo::Bump;
9−use futures::future::Future;
10use fxhash::FxHashMap;
9use fxhash::FxHashMap;
11use std::cell::Cell;
10use std::cell::Cell;
12use std::cell::RefCell;
11use std::cell::RefCell;
13use std::fmt;
12use std::fmt;
13+use std::future::Future;
14use std::mem;
14use std::mem;
15use std::mem::ManuallyDrop;
15use std::mem::ManuallyDrop;
16use std::rc::{Rc, Weak};
16use std::rc::{Rc, Weak};
@@ -371,25 +371,20 @@ impl VdomWeak {
371 /// Replace the root rendering component with the new `root`.
371 /// Replace the root rendering component with the new `root`.
372 ///
372 ///
373 /// Returns a future that resolves to the *old* root component.
373 /// Returns a future that resolves to the *old* root component.
374− pub fn set_component(
374+ pub async fn set_component(
375 self,
375 self,
376 root: Box<dyn RootRender>,
376 root: Box<dyn RootRender>,
377− ) -> impl Future<Item = Box<dyn RootRender + 'static>, Error = VdomDroppedError> {
377+ ) -> Result<Box<dyn RootRender + 'static>, VdomDroppedError> {
378− futures::future::ok(self.inner.upgrade())
379− .and_then(|inner| inner.ok_or(()))
380− .map_err(|_| VdomDroppedError {})
378+ let inner = self.inner.upgrade().ok_or(VdomDroppedError {})?;
381− .and_then(|inner| {
379+
382− let promise = js_sys::Promise::resolve(&JsValue::null());
383− JsFuture::from(promise)
384− .map_err(|_| VdomDroppedError {})
385− .and_then(move |_| {
386− let old = {
380+ let old = {
387− let mut exclusive = inner.exclusive.borrow_mut();
381+ let mut exclusive = inner.exclusive.borrow_mut();
388− mem::replace(&mut *exclusive.component.as_mut().unwrap_throw(), root)
382+ mem::replace(&mut *exclusive.component.as_mut().unwrap_throw(), root)
389− };
383+ };
384+
390− VdomWeak::new(&inner).render().map(|_| old)
385+ VdomWeak::new(&inner).render().await?;
391− })
386+
392− })
387+ Ok(old)
393 }
388 }
394
389
395 /// Execute `f` with a reference to this virtual DOM's root rendering
390 /// Execute `f` with a reference to this virtual DOM's root rendering
@@ -397,24 +392,15 @@ impl VdomWeak {
397 ///
392 ///
398 /// To ensure exclusive access to the root rendering component, the
393 /// To ensure exclusive access to the root rendering component, the
399 /// invocation takes place on a new tick of the micro-task queue.
394 /// 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>
401 where
396 where
402 F: 'static + FnOnce(&mut dyn RootRender) -> T,
397 F: 'static + FnOnce(&mut dyn RootRender) -> T,
403 {
398 {
404− futures::future::ok(self.inner.upgrade())
405− .and_then(|inner| inner.ok_or(()))
406− .map_err(|_| VdomDroppedError {})
399+ let inner = self.inner.upgrade().ok_or(VdomDroppedError {})?;
407− .and_then(|inner| {
400+
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();
401+ let mut exclusive = inner.exclusive.borrow_mut();
402+
415− f(exclusive.component_raw_mut())
403+ Ok(f(exclusive.component_raw_mut()))
416− })
417− })
418 }
404 }
419
405
420 /// Schedule a render to occur during the next animation frame.
406 /// Schedule a render to occur during the next animation frame.
@@ -423,7 +409,12 @@ impl VdomWeak {
423 /// `render` instead.
409 /// `render` instead.
424 pub fn schedule_render(&self) {
410 pub fn schedule_render(&self) {
425 debug!("VdomWeak::schedule_render");
411 debug!("VdomWeak::schedule_render");
412+
413+ let future = self.render();
414+
426− wasm_bindgen_futures::spawn_local(self.render().map_err(|_| ()));
415+ wasm_bindgen_futures::spawn_local(async move {
416+ let _ = future.await;
417+ });
427 }
418 }
428
419
429 /// Schedule a render to occur during the next animation frame and return a
420 /// Schedule a render to occur during the next animation frame and return a
@@ -431,41 +422,46 @@ impl VdomWeak {
431 ///
422 ///
432 /// If you don't want to do more things after the render completes, then use
423 /// If you don't want to do more things after the render completes, then use
433 /// `schedule_render` instead of `render`.
424 /// `schedule_render` instead of `render`.
434− pub fn render(&self) -> impl Future<Item = (), Error = VdomDroppedError> {
425+ pub fn render(&self) -> impl Future<Output = Result<(), VdomDroppedError>> {
435− futures::future::ok(self.inner.upgrade())
426+ let inner = self.inner.upgrade();
436− .and_then(|inner| inner.ok_or(()))
427+
428+ async move {
437− .map_err(|_| VdomDroppedError {})
429+ let inner = inner.ok_or(VdomDroppedError {})?;
438− .and_then(|inner| {
430+
439− let promise = inner.shared.render_scheduled.take().unwrap_or_else(|| {
431+ let promise = inner.shared.render_scheduled.take().unwrap_or_else(|| {
440− js_sys::Promise::new(&mut |resolve, reject| {
432+ js_sys::Promise::new(&mut |resolve, reject| {
441− let vdom = VdomWeak {
433+ let vdom = VdomWeak {
442− inner: Rc::downgrade(&inner),
434+ inner: Rc::downgrade(&inner),
443− };
435+ };
436+
444− with_animation_frame(move || match vdom.inner.upgrade() {
437+ with_animation_frame(move || match vdom.inner.upgrade() {
445− None => {
438+ None => {
446− warn!("VdomWeak::render: vdom unmounted before we could render");
439+ warn!("VdomWeak::render: vdom unmounted before we could render");
447− let r = reject.call0(&JsValue::null());
440+ let r = reject.call0(&JsValue::null());
448− debug_assert!(r.is_ok());
441+ debug_assert!(r.is_ok());
449− }
442+ }
450− Some(inner) => {
443+ Some(inner) => {
451− let mut exclusive = inner.exclusive.borrow_mut();
444+ let mut exclusive = inner.exclusive.borrow_mut();
452− exclusive.render();
445+ exclusive.render();
453−
446+
454− // We did the render, so take the promise away
447+ // We did the render, so take the promise away
455− // and let future `render` calls request new
448+ // and let future `render` calls request new
456− // animation frames.
449+ // animation frames.
457− let _ = inner.shared.render_scheduled.take();
450+ let _ = inner.shared.render_scheduled.take();
458−
451+
459− let r = resolve.call0(&JsValue::null());
452+ let r = resolve.call0(&JsValue::null());
460− debug_assert!(r.is_ok());
453+ debug_assert!(r.is_ok());
461− }
454+ }
462− });
455+ });
463− })
456+ })
464− });
457+ });
458+
465− inner.shared.render_scheduled.set(Some(promise.clone()));
459+ inner.shared.render_scheduled.set(Some(promise.clone()));
460+
466− JsFuture::from(promise)
461+ JsFuture::from(promise)
462+ .await
467− .map(|_| ())
463+ .map(drop)
468− .map_err(|_| VdomDroppedError {})
464+ .map_err(|_| VdomDroppedError {})
469− })
465+ }
470 }
466 }
471}
467}