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