diff --git a/examples/async/src/lib.rs b/examples/async/src/lib.rs index 8d1f486..f0b6f02 100644 --- a/examples/async/src/lib.rs +++ b/examples/async/src/lib.rs @@ -49,7 +49,7 @@ struct User { impl User { async fn fetch(user: &str) -> Result { let user = fetch_github(&format!("https://api.github.com/users/{}", user)).await?; - Ok(serde_json::from_str::(&user).unwrap_throw()) + Ok(serde_json::from_str::(&user).unwrap()) } } diff --git a/examples/async/src/util.rs b/examples/async/src/util.rs index 1ea1dff..d1ec2f3 100644 --- a/examples/async/src/util.rs +++ b/examples/async/src/util.rs @@ -112,7 +112,7 @@ pub async fn fetch_github(url: &str) -> Result { headers.set("Accept", "application/vnd.github.v3+json")?; let future = window() - .unwrap_throw() + .unwrap() .fetch_with_str_and_init( url, RequestInit::new() @@ -131,7 +131,7 @@ pub async fn fetch_github(url: &str) -> Result { let value = JsFuture::from(response.text()?) .await? .as_string() - .unwrap_throw(); + .unwrap(); Ok(value) } diff --git a/examples/todomvc/src/app.rs b/examples/todomvc/src/app.rs index 0675707..d4f86f9 100644 --- a/examples/todomvc/src/app.rs +++ b/examples/todomvc/src/app.rs @@ -21,7 +21,7 @@ pub enum Route { impl Route { // This could use more advanced URL parsing, but it isn't needed pub fn from_url(url: &str) -> Self { - let url = Url::new(&url).unwrap_throw(); + let url = Url::new(&url).unwrap(); match url.hash().as_str() { "#/active" => Route::Active, "#/completed" => Route::Completed, @@ -72,7 +72,7 @@ impl App { pub fn deserialize() -> Arc { local_storage() .get_item("todos-rust-dominator") - .unwrap_throw() + .unwrap() .and_then(|state_json| { serde_json::from_str(state_json.as_str()).ok() }) @@ -80,11 +80,11 @@ impl App { } pub fn serialize(&self) { - let state_json = serde_json::to_string(self).unwrap_throw(); + let state_json = serde_json::to_string(self).unwrap(); local_storage() .set_item("todos-rust-dominator", state_json.as_str()) - .unwrap_throw(); + .unwrap(); } pub fn route(&self) -> impl Signal { diff --git a/examples/todomvc/src/todo.rs b/examples/todomvc/src/todo.rs index 91a51d9..b1628f4 100644 --- a/examples/todomvc/src/todo.rs +++ b/examples/todomvc/src/todo.rs @@ -126,7 +126,7 @@ impl Todo { .event(clone!(todo => move |event: events::KeyDown| { match event.key().as_str() { "Enter" => { - element.blur().unwrap_throw(); + element.blur().unwrap(); }, "Escape" => { todo.cancel_editing(); diff --git a/examples/todomvc/src/util.rs b/examples/todomvc/src/util.rs index 1b2bd27..d59bb20 100644 --- a/examples/todomvc/src/util.rs +++ b/examples/todomvc/src/util.rs @@ -3,7 +3,7 @@ use web_sys::{window, Storage}; pub fn local_storage() -> Storage { - window().unwrap_throw().local_storage().unwrap_throw().unwrap_throw() + window().unwrap().local_storage().unwrap().unwrap() } #[inline] diff --git a/src/animation.rs b/src/animation.rs index 8c339f8..171c9c2 100644 --- a/src/animation.rs +++ b/src/animation.rs @@ -1,23 +1,22 @@ -use std::fmt; -use std::rc::Rc; use std::cell::RefCell; +use std::fmt; use std::pin::Pin; -use std::sync::{Arc, Weak, Mutex}; -use std::task::{Poll, Waker, Context}; +use std::rc::Rc; +use std::sync::{Arc, Mutex, Weak}; +use std::task::{Context, Poll, Waker}; -use futures_util::future::{ready, FutureExt}; -use futures_signals::CancelableFutureHandle; -use futures_signals::signal::{Signal, SignalExt, WaitFor, MutableSignal, Mutable}; -use futures_signals::signal_vec::{SignalVec, VecDiff}; use discard::DiscardOnDrop; +use futures_signals::signal::{Mutable, MutableSignal, Signal, SignalExt, WaitFor}; +use futures_signals::signal_vec::{SignalVec, VecDiff}; +use futures_signals::CancelableFutureHandle; +use futures_util::future::{ready, FutureExt}; use pin_project::pin_project; -use wasm_bindgen::{JsCast, UnwrapThrowExt}; use wasm_bindgen::closure::Closure; +use wasm_bindgen::JsCast; use web_sys::window; use crate::operations::spawn_future; - struct RafState { id: i32, closure: Closure, @@ -30,14 +29,17 @@ struct Raf { } impl Raf { - fn new(mut callback: F) -> Self where F: FnMut(f64) + 'static { + fn new(mut callback: F) -> Self + where + F: FnMut(f64) + 'static, + { let state: Rc>> = Rc::new(RefCell::new(None)); fn schedule(callback: &Closure) -> i32 { window() - .unwrap_throw() + .unwrap() .request_animation_frame(callback.as_ref().unchecked_ref()) - .unwrap_throw() + .unwrap() } let closure = { @@ -46,7 +48,7 @@ impl Raf { Closure::wrap(Box::new(move |time| { { let mut state = state.borrow_mut(); - let state = state.as_mut().unwrap_throw(); + let state = state.as_mut().unwrap(); state.id = schedule(&state.closure); } @@ -56,7 +58,7 @@ impl Raf { *state.borrow_mut() = Some(RafState { id: schedule(&closure), - closure + closure, }); Self { state } @@ -66,16 +68,12 @@ impl Raf { impl Drop for Raf { fn drop(&mut self) { // The take is necessary in order to prevent an Rc leak - let state = self.state.borrow_mut().take().unwrap_throw(); + let state = self.state.borrow_mut().take().unwrap(); - window() - .unwrap_throw() - .cancel_animation_frame(state.id) - .unwrap_throw(); + window().unwrap().cancel_animation_frame(state.id).unwrap(); } } - struct TimestampsManager { raf: Option, // TODO make this more efficient @@ -91,7 +89,6 @@ impl TimestampsManager { } } - #[derive(Debug)] struct TimestampsState { changed: bool, @@ -128,12 +125,11 @@ impl Signal for Timestamps { // TODO implement Poll::Ready(None) fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - let mut lock = self.state.lock().unwrap_throw(); + let mut lock = self.state.lock().unwrap(); if lock.changed { lock.changed = false; Poll::Ready(Some(lock.value)) - } else { lock.waker = Some(cx.waker().clone()); Poll::Pending @@ -141,7 +137,6 @@ impl Signal for Timestamps { } } - // TODO somehow share this safely between threads ? thread_local! { static TIMESTAMPS_MANAGER: Rc> = Rc::new(RefCell::new(TimestampsManager::new())); @@ -164,7 +159,7 @@ pub fn timestamps() -> Timestamps { lock.states.retain(|state| { if let Some(state) = state.upgrade() { - let mut lock = state.lock().unwrap_throw(); + let mut lock = state.lock().unwrap(); lock.changed = true; lock.value = Some(time); @@ -175,7 +170,6 @@ pub fn timestamps() -> Timestamps { } true - } else { false } @@ -194,13 +188,13 @@ pub fn timestamps() -> Timestamps { }) } - pub trait AnimatedSignalVec: SignalVec { type Animation; fn animated_map(self, duration: f64, f: F) -> AnimatedMap - where F: FnMut(Self::Item, Self::Animation) -> A, - Self: Sized; + where + F: FnMut(Self::Item, Self::Animation) -> A, + Self: Sized; } impl AnimatedSignalVec for S { @@ -208,7 +202,9 @@ impl AnimatedSignalVec for S { #[inline] fn animated_map(self, duration: f64, f: F) -> AnimatedMap - where F: FnMut(Self::Item, Self::Animation) -> A { + where + F: FnMut(Self::Item, Self::Animation) -> A, + { AnimatedMap { duration: duration, animations: vec![], @@ -218,7 +214,6 @@ impl AnimatedSignalVec for S { } } - #[derive(Debug)] pub struct AnimatedMapBroadcaster(MutableAnimation); @@ -230,7 +225,6 @@ impl AnimatedMapBroadcaster { } } - #[derive(Debug)] struct AnimatedMapState { animation: MutableAnimation, @@ -249,9 +243,10 @@ pub struct AnimatedMap { } impl AnimatedMap - where S: SignalVec, - F: FnMut(S::Item, AnimatedMapBroadcaster) -> A { - +where + S: SignalVec, + F: FnMut(S::Item, AnimatedMapBroadcaster) -> A, +{ fn animated_state(duration: f64) -> AnimatedMapState { let state = AnimatedMapState { animation: MutableAnimation::new(duration), @@ -263,27 +258,35 @@ impl AnimatedMap state } - fn remove_index(animations: &mut Vec, index: usize) -> Poll>> { + fn remove_index( + animations: &mut Vec, + index: usize, + ) -> Poll>> { if index == (animations.len() - 1) { animations.pop(); Poll::Ready(Some(VecDiff::Pop {})) - } else { animations.remove(index); Poll::Ready(Some(VecDiff::RemoveAt { index })) } } - fn should_remove(animations: &mut Vec, cx: &mut Context, index: usize) -> bool { + fn should_remove( + animations: &mut Vec, + cx: &mut Context, + index: usize, + ) -> bool { let state = &mut animations[index]; state.animation.animate_to(Percentage::new_unchecked(0.0)); - let mut future = state.animation.signal().wait_for(Percentage::new_unchecked(0.0)); + let mut future = state + .animation + .signal() + .wait_for(Percentage::new_unchecked(0.0)); if future.poll_unpin(cx).is_ready() { true - } else { state.removing = Some(future); false @@ -298,12 +301,10 @@ impl AnimatedMap if state.removing.is_none() { if seen == parent_index { true - } else { seen += 1; false } - } else { false } @@ -312,120 +313,160 @@ impl AnimatedMap #[inline] fn find_last_index(animations: &Vec) -> Option { - animations.iter().rposition(|state| state.removing.is_none()) + animations + .iter() + .rposition(|state| state.removing.is_none()) } } impl SignalVec for AnimatedMap - where S: SignalVec, - F: FnMut(S::Item, AnimatedMapBroadcaster) -> A { +where + S: SignalVec, + F: FnMut(S::Item, AnimatedMapBroadcaster) -> A, +{ type Item = A; // TODO this can probably be implemented more efficiently - fn poll_vec_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll>> { + fn poll_vec_change( + self: Pin<&mut Self>, + cx: &mut Context, + ) -> Poll>> { let mut is_done = true; - let AnimatedMapProj { mut animations, mut signal, callback, duration, .. } = self.project(); + let AnimatedMapProj { + mut animations, + mut signal, + callback, + duration, + .. + } = self.project(); // TODO is this loop correct ? - while let Some(result) = signal.as_mut().as_pin_mut().map(|signal| signal.poll_vec_change(cx)) { + while let Some(result) = signal + .as_mut() + .as_pin_mut() + .map(|signal| signal.poll_vec_change(cx)) + { match result { - Poll::Ready(Some(change)) => return match change { - // TODO maybe it should play remove / insert animations for this ? - VecDiff::Replace { values } => { - *animations = Vec::with_capacity(values.len()); - - Poll::Ready(Some(VecDiff::Replace { - values: values.into_iter().map(|value| { - let state = AnimatedMapState { - animation: MutableAnimation::new_with_initial(*duration, Percentage::new_unchecked(1.0)), - removing: None, - }; - - let value = callback(value, AnimatedMapBroadcaster(state.animation.raw_clone())); - - animations.push(state); - - value - }).collect() - })) - }, - - VecDiff::InsertAt { index, value } => { - let index = Self::find_index(&animations, index).unwrap_or_else(|| animations.len()); - let state = Self::animated_state(*duration); - let value = callback(value, AnimatedMapBroadcaster(state.animation.raw_clone())); - animations.insert(index, state); - Poll::Ready(Some(VecDiff::InsertAt { index, value })) - }, - - VecDiff::Push { value } => { - let state = Self::animated_state(*duration); - let value = callback(value, AnimatedMapBroadcaster(state.animation.raw_clone())); - animations.push(state); - Poll::Ready(Some(VecDiff::Push { value })) - }, - - VecDiff::UpdateAt { index, value } => { - let index = Self::find_index(&animations, index).unwrap_throw(); - let state = { - let state = &animations[index]; - AnimatedMapBroadcaster(state.animation.raw_clone()) - }; - let value = callback(value, state); - Poll::Ready(Some(VecDiff::UpdateAt { index, value })) - }, - - // TODO test this - // TODO should this be treated as a removal + insertion ? - VecDiff::Move { old_index, new_index } => { - let old_index = Self::find_index(&animations, old_index).unwrap_throw(); - - let state = animations.remove(old_index); - - let new_index = Self::find_index(&animations, new_index).unwrap_or_else(|| animations.len()); - - animations.insert(new_index, state); - - Poll::Ready(Some(VecDiff::Move { old_index, new_index })) - }, - - VecDiff::RemoveAt { index } => { - let index = Self::find_index(&animations, index).unwrap_throw(); - - if Self::should_remove(&mut animations, cx, index) { - Self::remove_index(&mut animations, index) + Poll::Ready(Some(change)) => { + return match change { + // TODO maybe it should play remove / insert animations for this ? + VecDiff::Replace { values } => { + *animations = Vec::with_capacity(values.len()); + + Poll::Ready(Some(VecDiff::Replace { + values: values + .into_iter() + .map(|value| { + let state = AnimatedMapState { + animation: MutableAnimation::new_with_initial( + *duration, + Percentage::new_unchecked(1.0), + ), + removing: None, + }; + + let value = callback( + value, + AnimatedMapBroadcaster(state.animation.raw_clone()), + ); + + animations.push(state); + + value + }) + .collect(), + })) + } - } else { - continue; + VecDiff::InsertAt { index, value } => { + let index = Self::find_index(&animations, index) + .unwrap_or_else(|| animations.len()); + let state = Self::animated_state(*duration); + let value = callback( + value, + AnimatedMapBroadcaster(state.animation.raw_clone()), + ); + animations.insert(index, state); + Poll::Ready(Some(VecDiff::InsertAt { index, value })) } - }, - VecDiff::Pop {} => { - let index = Self::find_last_index(&animations).unwrap_throw(); + VecDiff::Push { value } => { + let state = Self::animated_state(*duration); + let value = callback( + value, + AnimatedMapBroadcaster(state.animation.raw_clone()), + ); + animations.push(state); + Poll::Ready(Some(VecDiff::Push { value })) + } - if Self::should_remove(&mut animations, cx, index) { - Self::remove_index(&mut animations, index) + VecDiff::UpdateAt { index, value } => { + let index = Self::find_index(&animations, index).unwrap(); + let state = { + let state = &animations[index]; + AnimatedMapBroadcaster(state.animation.raw_clone()) + }; + let value = callback(value, state); + Poll::Ready(Some(VecDiff::UpdateAt { index, value })) + } - } else { - continue; + // TODO test this + // TODO should this be treated as a removal + insertion ? + VecDiff::Move { + old_index, + new_index, + } => { + let old_index = Self::find_index(&animations, old_index).unwrap(); + + let state = animations.remove(old_index); + + let new_index = Self::find_index(&animations, new_index) + .unwrap_or_else(|| animations.len()); + + animations.insert(new_index, state); + + Poll::Ready(Some(VecDiff::Move { + old_index, + new_index, + })) + } + + VecDiff::RemoveAt { index } => { + let index = Self::find_index(&animations, index).unwrap(); + + if Self::should_remove(&mut animations, cx, index) { + Self::remove_index(&mut animations, index) + } else { + continue; + } + } + + VecDiff::Pop {} => { + let index = Self::find_last_index(&animations).unwrap(); + + if Self::should_remove(&mut animations, cx, index) { + Self::remove_index(&mut animations, index) + } else { + continue; + } } - }, - - // TODO maybe it should play remove animation for this ? - VecDiff::Clear {} => { - animations.clear(); - Poll::Ready(Some(VecDiff::Clear {})) - }, - }, + + // TODO maybe it should play remove animation for this ? + VecDiff::Clear {} => { + animations.clear(); + Poll::Ready(Some(VecDiff::Clear {})) + } + } + } Poll::Ready(None) => { signal.set(None); break; - }, + } Poll::Pending => { is_done = false; break; - }, + } } } @@ -437,27 +478,24 @@ impl SignalVec for AnimatedMap if let Some(ref mut future) = state.removing { is_removing = true; future.poll_unpin(cx).is_ready() - } else { false } }); match index { - Some(index) => { - Self::remove_index(&mut animations, index) - }, - None => if is_done && !is_removing { - Poll::Ready(None) - - } else { - Poll::Pending - }, + Some(index) => Self::remove_index(&mut animations, index), + None => { + if is_done && !is_removing { + Poll::Ready(None) + } else { + Poll::Pending + } + } } } } - #[derive(Debug, Clone, Copy, PartialEq)] pub struct Percentage(f64); @@ -477,12 +515,18 @@ impl Percentage { } #[inline] - pub fn map(self, f: F) -> Self where F: FnOnce(f64) -> f64 { + pub fn map(self, f: F) -> Self + where + F: FnOnce(f64) -> f64, + { Self::new(f(self.0)) } #[inline] - pub fn map_unchecked(self, f: F) -> Self where F: FnOnce(f64) -> f64 { + pub fn map_unchecked(self, f: F) -> Self + where + F: FnOnce(f64) -> f64, + { Self::new_unchecked(f(self.0)) } @@ -506,7 +550,6 @@ impl Percentage { pub fn none_if(self, percentage: f64) -> Option { if self.0 == percentage { None - } else { Some(self) } @@ -518,7 +561,6 @@ fn range_inclusive(percentage: f64, low: f64, high: f64) -> f64 { low + (percentage * (high - low)) } - /*pub struct MutableTimestamps { callback: Arc, animating: Mutex>>, @@ -533,12 +575,12 @@ impl MutableTimestamps where F: FnMut(f64) { } pub fn stop(&self) { - let mut lock = self.animating.lock().unwrap_throw(); + let mut lock = self.animating.lock().unwrap(); *lock = None; } pub fn start(&self) { - let mut lock = self.animating.lock().unwrap_throw(); + let mut lock = self.animating.lock().unwrap(); if let None = animating { let callback = self.callback.clone(); @@ -550,7 +592,6 @@ impl MutableTimestamps where F: FnMut(f64) { } }*/ - pub fn timestamps_absolute_difference() -> impl Signal> { let mut starting_time = None; @@ -562,13 +603,14 @@ pub fn timestamps_absolute_difference() -> impl Signal> { }) } - pub fn timestamps_difference() -> impl Signal> { let mut previous_time = None; timestamps().map(move |current_time| { let diff = current_time.map(|current_time| { - previous_time.map(|previous_time| current_time - previous_time).unwrap_or(0.0) + previous_time + .map(|previous_time| current_time - previous_time) + .unwrap_or(0.0) }); previous_time = current_time; @@ -577,32 +619,31 @@ pub fn timestamps_difference() -> impl Signal> { }) } - pub struct OnTimestampDiff(DiscardOnDrop); impl OnTimestampDiff { - pub fn new(mut callback: F) -> Self where F: FnMut(f64) + 'static { - OnTimestampDiff(spawn_future( - timestamps_absolute_difference() - .for_each(move |diff| { - if let Some(diff) = diff { - callback(diff); - } + pub fn new(mut callback: F) -> Self + where + F: FnMut(f64) + 'static, + { + OnTimestampDiff(spawn_future(timestamps_absolute_difference().for_each( + move |diff| { + if let Some(diff) = diff { + callback(diff); + } - ready(()) - }) - )) + ready(()) + }, + ))) } } impl fmt::Debug for OnTimestampDiff { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_tuple("OnTimestampDiff") - .finish() + fmt.debug_tuple("OnTimestampDiff").finish() } } - #[derive(Debug)] pub struct MutableAnimationSignal(MutableSignal); @@ -615,7 +656,6 @@ impl Signal for MutableAnimationSignal { } } - // TODO verify that this is Sync and Send struct MutableAnimationState { playing: bool, @@ -639,7 +679,7 @@ pub struct MutableAnimation { impl fmt::Debug for MutableAnimation { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let state = self.inner.state.lock().unwrap_throw(); + let state = self.inner.state.lock().unwrap(); fmt.debug_struct("MutableAnimation") .field("playing", &state.playing) @@ -697,27 +737,27 @@ impl MutableAnimation { let state = self.raw_clone(); - lock._animating = Some(OnTimestampDiff::new(move |diff| { - let diff = diff / duration; - - // TODO test the performance of set_neq - if diff >= 1.0 { - { - let mut lock = state.inner.state.lock().unwrap_throw(); - Self::stop_animating(&mut lock); + lock._animating = + Some(OnTimestampDiff::new(move |diff| { + let diff = diff / duration; + + // TODO test the performance of set_neq + if diff >= 1.0 { + { + let mut lock = state.inner.state.lock().unwrap(); + Self::stop_animating(&mut lock); + } + state.inner.value.set_neq(Percentage::new_unchecked(end)); + } else { + state.inner.value.set_neq(Percentage::new_unchecked( + range_inclusive(diff, start, end), + )); } - state.inner.value.set_neq(Percentage::new_unchecked(end)); - - } else { - state.inner.value.set_neq(Percentage::new_unchecked(range_inclusive(diff, start, end))); - } - })); - + })); } else { Self::stop_animating(lock); self.inner.value.set_neq(Percentage::new_unchecked(end)); } - } else { // TODO is this necessary ? Self::stop_animating(lock); @@ -728,7 +768,7 @@ impl MutableAnimation { pub fn set_duration(&self, duration: f64) { debug_assert!(duration >= 0.0); - let mut lock = self.inner.state.lock().unwrap_throw(); + let mut lock = self.inner.state.lock().unwrap(); if lock.duration != duration { lock.duration = duration; @@ -738,7 +778,7 @@ impl MutableAnimation { #[inline] pub fn pause(&self) { - let mut lock = self.inner.state.lock().unwrap_throw(); + let mut lock = self.inner.state.lock().unwrap(); if lock.playing { lock.playing = false; @@ -748,7 +788,7 @@ impl MutableAnimation { #[inline] pub fn play(&self) { - let mut lock = self.inner.state.lock().unwrap_throw(); + let mut lock = self.inner.state.lock().unwrap(); if !lock.playing { lock.playing = true; @@ -756,7 +796,11 @@ impl MutableAnimation { } } - fn _jump_to(mut lock: &mut MutableAnimationState, mutable: &Mutable, end: Percentage) { + fn _jump_to( + mut lock: &mut MutableAnimationState, + mutable: &Mutable, + end: Percentage, + ) { Self::stop_animating(&mut lock); lock.end = end; @@ -765,18 +809,17 @@ impl MutableAnimation { } pub fn jump_to(&self, end: Percentage) { - let mut lock = self.inner.state.lock().unwrap_throw(); + let mut lock = self.inner.state.lock().unwrap(); Self::_jump_to(&mut lock, &self.inner.value, end); } pub fn animate_to(&self, end: Percentage) { - let mut lock = self.inner.state.lock().unwrap_throw(); + let mut lock = self.inner.state.lock().unwrap(); if lock.end != end { if lock.duration <= 0.0 { Self::_jump_to(&mut lock, &self.inner.value, end); - } else { lock.end = end; self.start_animating(&mut lock); @@ -795,7 +838,6 @@ impl MutableAnimation { } } - pub mod easing { use super::Percentage; @@ -811,22 +853,26 @@ pub mod easing { } #[inline] - pub fn out(p: Percentage, f: F) -> Percentage where F: FnOnce(Percentage) -> Percentage { + pub fn out(p: Percentage, f: F) -> Percentage + where + F: FnOnce(Percentage) -> Percentage, + { f(p.invert()).invert() } - pub fn in_out(p: Percentage, f: F) -> Percentage where F: FnOnce(Percentage) -> Percentage { + pub fn in_out(p: Percentage, f: F) -> Percentage + where + F: FnOnce(Percentage) -> Percentage, + { p.map_unchecked(|p| { if p <= 0.5 { f(Percentage::new_unchecked(p * 2.0)).into_f64() / 2.0 - } else { 1.0 - (f(Percentage::new_unchecked((1.0 - p) * 2.0)).into_f64() / 2.0) } }) } - /*pub struct Point { pub x: f64, pub y: f64, @@ -860,7 +906,6 @@ pub mod easing { (3.0 * a * p * p) + (2.0 * b * p) + c }*/ - const EPSILON: f64 = 1e-6; pub struct CubicBezier { @@ -888,7 +933,14 @@ pub mod easing { let by = 3.0 * (y2 - y1) - cy; let ay = 1.0 - cy - by; - Self { ax, bx, cx, ay, by, cy } + Self { + ax, + bx, + cx, + ay, + by, + cy, + } } /*fn values(p: f64) -> (f64, f64, f64, f64) { @@ -908,10 +960,8 @@ pub mod easing { p.map_unchecked(|p| { if p == 0.0 { 0.0 - } else if p == 1.0 { 1.0 - } else { self.y(self.get_t_for_x(p)) } @@ -988,7 +1038,6 @@ pub mod easing { if x > 0.0 { end = t; - } else { start = t; } @@ -1073,7 +1122,6 @@ pub mod easing { } } - /*cubic_bezier(t, Percentage::new(1.0), Percentage::new(0.0), diff --git a/src/bindings.rs b/src/bindings.rs index 4d50635..1d69e7d 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -7,14 +7,14 @@ use web_sys::{HtmlElement, Element, Node, Window, History, Document, Text, Comme // TODO move this into wasm-bindgen or gloo or something // TODO maybe use Object for obj ? pub(crate) fn set_property(obj: &JsValue, name: &str, value: &JsValue) { - Reflect::set(obj, &JsValue::from(name), value).unwrap_throw(); + Reflect::set(obj, &JsValue::from(name), value).unwrap(); } thread_local! { - static WINDOW: Window = web_sys::window().unwrap_throw(); - static DOCUMENT: Document = WINDOW.with(|w| w.document().unwrap_throw()); - static HISTORY: History = WINDOW.with(|w| w.history().unwrap_throw()); + static WINDOW: Window = web_sys::window().unwrap(); + static DOCUMENT: Document = WINDOW.with(|w| w.document().unwrap()); + static HISTORY: History = WINDOW.with(|w| w.history().unwrap()); } pub(crate) fn window_event_target() -> EventTarget { @@ -23,7 +23,7 @@ pub(crate) fn window_event_target() -> EventTarget { } pub(crate) fn body() -> HtmlElement { - DOCUMENT.with(|d| d.body().unwrap_throw()) + DOCUMENT.with(|d| d.body().unwrap()) } pub(crate) fn ready_state() -> String { @@ -31,12 +31,12 @@ pub(crate) fn ready_state() -> String { } pub(crate) fn current_url() -> String { - WINDOW.with(|w| w.location().href().unwrap_throw()) + WINDOW.with(|w| w.location().href().unwrap()) } pub(crate) fn go_to_url(url: &str) { HISTORY.with(|h| { - h.push_state_with_url(&JsValue::NULL, "", Some(url)).unwrap_throw(); + h.push_state_with_url(&JsValue::NULL, "", Some(url)).unwrap(); }); } @@ -44,34 +44,34 @@ pub(crate) fn create_stylesheet() -> CssStyleSheet { DOCUMENT.with(|document| { // TODO use createElementNS ? // TODO use dyn_into ? - let e: HtmlStyleElement = document.create_element("style").unwrap_throw().unchecked_into(); + let e: HtmlStyleElement = document.create_element("style").unwrap().unchecked_into(); e.set_type("text/css"); - append_child(&document.head().unwrap_throw(), &e); + append_child(&document.head().unwrap(), &e); // TODO use dyn_into ? - e.sheet().unwrap_throw().unchecked_into() + e.sheet().unwrap().unchecked_into() }) } pub(crate) fn make_style_rule(sheet: &CssStyleSheet, selector: &str) -> Result { - let rules = sheet.css_rules().unwrap_throw(); + let rules = sheet.css_rules().unwrap(); let length = rules.length(); // TODO don't return u32 ? sheet.insert_rule_with_index(&format!("{}{{}}", selector), length)?; // TODO use dyn_into ? - Ok(rules.get(length).unwrap_throw().unchecked_into()) + Ok(rules.get(length).unwrap().unchecked_into()) } pub(crate) fn get_element_by_id(id: &str) -> Element { - DOCUMENT.with(|d| d.get_element_by_id(id).unwrap_throw()) + DOCUMENT.with(|d| d.get_element_by_id(id).unwrap()) } pub(crate) fn create_element(name: &str) -> Element { - DOCUMENT.with(|d| d.create_element(name).unwrap_throw()) + DOCUMENT.with(|d| d.create_element(name).unwrap()) } pub(crate) fn create_element_ns(namespace: &str, name: &str) -> Element { - DOCUMENT.with(|d| d.create_element_ns(Some(namespace), name).unwrap_throw()) + DOCUMENT.with(|d| d.create_element_ns(Some(namespace), name).unwrap()) } pub(crate) fn create_text_node(value: &str) -> Text { @@ -95,67 +95,67 @@ pub(crate) fn create_empty_node() -> Node { // TODO check that the attribute *actually* was changed pub(crate) fn set_attribute(elem: &Element, key: &str, value: &str) { - elem.set_attribute(key, value).unwrap_throw(); + elem.set_attribute(key, value).unwrap(); } pub(crate) fn set_attribute_ns(elem: &Element, namespace: &str, key: &str, value: &str) { - elem.set_attribute_ns(Some(namespace), key, value).unwrap_throw(); + elem.set_attribute_ns(Some(namespace), key, value).unwrap(); } pub(crate) fn remove_attribute(elem: &Element, key: &str) { - elem.remove_attribute(key).unwrap_throw(); + elem.remove_attribute(key).unwrap(); } pub(crate) fn remove_attribute_ns(elem: &Element, namespace: &str, key: &str) { - elem.remove_attribute_ns(Some(namespace), key).unwrap_throw(); + elem.remove_attribute_ns(Some(namespace), key).unwrap(); } pub(crate) fn add_class(classes: &DomTokenList, value: &str) { - classes.add_1(value).unwrap_throw(); + classes.add_1(value).unwrap(); } pub(crate) fn remove_class(classes: &DomTokenList, value: &str) { - classes.remove_1(value).unwrap_throw(); + classes.remove_1(value).unwrap(); } pub(crate) fn get_style(style: &CssStyleDeclaration, name: &str) -> String { - style.get_property_value(name).unwrap_throw() + style.get_property_value(name).unwrap() } pub(crate) fn remove_style(style: &CssStyleDeclaration, name: &str) { // TODO don't return String ? - style.remove_property(name).unwrap_throw(); + style.remove_property(name).unwrap(); } pub(crate) fn set_style(style: &CssStyleDeclaration, name: &str, value: &str, important: bool) { let priority = if important { intern("important") } else { intern("") }; - style.set_property_with_priority(name, value, priority).unwrap_throw(); + style.set_property_with_priority(name, value, priority).unwrap(); } pub(crate) fn insert_child_before(parent: &Node, child: &Node, other: &Node) { // TODO don't return Node ? - parent.insert_before(child, Some(other)).unwrap_throw(); + parent.insert_before(child, Some(other)).unwrap(); } pub(crate) fn replace_child(parent: &Node, child: &Node, other: &Node) { // TODO don't return Node ? - parent.replace_child(child, other).unwrap_throw(); + parent.replace_child(child, other).unwrap(); } pub(crate) fn append_child(parent: &Node, child: &Node) { // TODO don't return Node ? - parent.append_child(child).unwrap_throw(); + parent.append_child(child).unwrap(); } pub(crate) fn remove_child(parent: &Node, child: &Node) { // TODO don't return Node ? - parent.remove_child(child).unwrap_throw(); + parent.remove_child(child).unwrap(); } pub(crate) fn focus(elem: &HtmlElement) { - elem.focus().unwrap_throw(); + elem.focus().unwrap(); } pub(crate) fn blur(elem: &HtmlElement) { - elem.blur().unwrap_throw(); + elem.blur().unwrap(); } diff --git a/src/dom.rs b/src/dom.rs index 1cad472..8efcec7 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -1,38 +1,45 @@ -use std::pin::Pin; use std::borrow::BorrowMut; use std::convert::AsRef; use std::future::Future; +use std::pin::Pin; use std::task::{Context, Poll}; -use once_cell::sync::Lazy; -use futures_signals::signal::{Signal, not}; +use discard::{Discard, DiscardOnDrop}; +use futures_channel::oneshot; +use futures_signals::signal::{not, Signal}; use futures_signals::signal_vec::SignalVec; use futures_util::FutureExt; -use futures_channel::oneshot; -use discard::{Discard, DiscardOnDrop}; -use wasm_bindgen::{JsValue, UnwrapThrowExt, JsCast, intern}; -use web_sys::{HtmlElement, Node, EventTarget, Element, CssStyleSheet, CssStyleDeclaration, ShadowRoot, ShadowRootMode, ShadowRootInit, Text}; +use once_cell::sync::Lazy; +use wasm_bindgen::{intern, JsCast, JsValue}; +use web_sys::{ + CssStyleDeclaration, CssStyleSheet, Element, EventTarget, HtmlElement, Node, ShadowRoot, + ShadowRootInit, ShadowRootMode, Text, +}; use crate::bindings; use crate::callbacks::Callbacks; -use crate::traits::*; use crate::operations; use crate::operations::{for_each, spawn_future}; -use crate::utils::{EventListener, on, ValueDiscard, FnDiscard}; - +use crate::traits::*; +use crate::utils::{on, EventListener, FnDiscard, ValueDiscard}; -pub struct RefFn where B: ?Sized, C: Fn(&A) -> &B { +pub struct RefFn +where + B: ?Sized, + C: Fn(&A) -> &B, +{ value: A, callback: C, } -impl RefFn where B: ?Sized, C: Fn(&A) -> &B { +impl RefFn +where + B: ?Sized, + C: Fn(&A) -> &B, +{ #[inline] pub fn new(value: A, callback: C) -> Self { - Self { - value, - callback, - } + Self { value, callback } } #[inline] @@ -69,31 +76,28 @@ impl RefFn where B: ?Sized, C: Fn(&A) -> &B { } }*/ - // https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS#Valid%20Namespace%20URIs const SVG_NAMESPACE: &str = "http://www.w3.org/2000/svg"; // 32-bit signed int pub const HIGHEST_ZINDEX: &str = "2147483647"; - -static HIDDEN_CLASS: Lazy = Lazy::new(|| class! { - .style_important("display", "none") +static HIDDEN_CLASS: Lazy = Lazy::new(|| { + class! { + .style_important("display", "none") + } }); - // TODO should return HtmlBodyElement ? pub fn body() -> HtmlElement { bindings::body() } - pub fn get_id(id: &str) -> Element { // TODO intern ? bindings::get_element_by_id(id) } - pub struct DomHandle { parent: Node, dom: Dom, @@ -122,7 +126,6 @@ pub fn append_dom(parent: &Node, mut dom: Dom) -> DomHandle { } } - // TODO use must_use ? enum IsWindowLoaded { Initial {}, @@ -143,27 +146,28 @@ impl Signal for IsWindowLoaded { if is_ready { Poll::Ready(Some(true)) - } else { let (sender, receiver) = oneshot::channel(); *self = IsWindowLoaded::Pending { receiver, - _event: EventListener::once(&bindings::window_event_target(), "load", move |_| { - // TODO test this - sender.send(Some(true)).unwrap_throw(); - }), + _event: EventListener::once( + &bindings::window_event_target(), + "load", + move |_| { + // TODO test this + sender.send(Some(true)).unwrap(); + }, + ), }; Poll::Ready(Some(false)) } - }, - IsWindowLoaded::Pending { ref mut receiver, .. } => { - receiver.poll_unpin(cx).map(|x| x.unwrap_throw()) - }, - IsWindowLoaded::Done {} => { - Poll::Ready(None) - }, + } + IsWindowLoaded::Pending { + ref mut receiver, .. + } => receiver.poll_unpin(cx).map(|x| x.unwrap()), + IsWindowLoaded::Done {} => Poll::Ready(None), }; if let Poll::Ready(Some(true)) = result { @@ -180,18 +184,17 @@ pub fn is_window_loaded() -> impl Signal { IsWindowLoaded::Initial {} } - // TODO should this intern ? #[inline] pub fn text(value: &str) -> Dom { Dom::new(bindings::create_text_node(value).into()) } - fn make_text_signal(callbacks: &mut Callbacks, value: B) -> Text - where A: AsStr, - B: Signal + 'static { - +where + A: AsStr, + B: Signal + 'static, +{ let element = bindings::create_text_node(intern("")); { @@ -210,9 +213,10 @@ fn make_text_signal(callbacks: &mut Callbacks, value: B) -> Text // TODO should this inline ? pub fn text_signal(value: B) -> Dom - where A: AsStr, - B: Signal + 'static { - +where + A: AsStr, + B: Signal + 'static, +{ let mut callbacks = Callbacks::new(); let element = make_text_signal(&mut callbacks, value); @@ -223,7 +227,6 @@ pub fn text_signal(value: B) -> Dom } } - // TODO better warning message for must_use #[must_use] #[derive(Debug)] @@ -246,12 +249,16 @@ impl Dom { Self::new(bindings::create_empty_node()) } - #[deprecated(since = "0.5.15", note = "Store the data explicitly in a component struct instead")] + #[deprecated( + since = "0.5.15", + note = "Store the data explicitly in a component struct instead" + )] #[inline] pub fn with_state(mut state: A, initializer: F) -> Dom - where A: 'static, - F: FnOnce(&mut A) -> Dom { - + where + A: 'static, + F: FnOnce(&mut A) -> Dom, + { let mut dom = initializer(&mut state); dom.callbacks.after_remove(ValueDiscard::new(state)); @@ -260,27 +267,34 @@ impl Dom { } } - #[inline] -fn create_element(name: &str) -> A where A: JsCast { +fn create_element(name: &str) -> A +where + A: JsCast, +{ // TODO use unchecked_into in release mode ? - bindings::create_element(intern(name)).dyn_into().unwrap_throw() + bindings::create_element(intern(name)).dyn_into().unwrap() } #[inline] -fn create_element_ns(name: &str, namespace: &str) -> A where A: JsCast { +fn create_element_ns(name: &str, namespace: &str) -> A +where + A: JsCast, +{ // TODO use unchecked_into in release mode ? - bindings::create_element_ns(intern(namespace), intern(name)).dyn_into().unwrap_throw() + bindings::create_element_ns(intern(namespace), intern(name)) + .dyn_into() + .unwrap() } - // TODO should this inline ? fn set_option(element: A, callbacks: &mut Callbacks, value: D, mut f: F) - where A: 'static, - C: OptionStr, - D: Signal + 'static, - F: FnMut(&A, Option) + 'static { - +where + A: 'static, + C: OptionStr, + D: Signal + 'static, + F: FnMut(&A, Option) + 'static, +{ let mut is_set = false; callbacks.after_remove(for_each(value, move |value| { @@ -288,10 +302,8 @@ fn set_option(element: A, callbacks: &mut Callbacks, value: D, mu if value.is_some() { is_set = true; - } else if is_set { is_set = false; - } else { return; } @@ -302,13 +314,21 @@ fn set_option(element: A, callbacks: &mut Callbacks, value: D, mu // TODO should this inline ? fn set_style(style: &CssStyleDeclaration, name: &A, value: B, important: bool) - where A: MultiStr, - B: MultiStr { - +where + A: MultiStr, + B: MultiStr, +{ let mut names = vec![]; let mut values = vec![]; - fn try_set_style(style: &CssStyleDeclaration, names: &mut Vec, values: &mut Vec, name: &str, value: &str, important: bool) -> Option<()> { + fn try_set_style( + style: &CssStyleDeclaration, + names: &mut Vec, + values: &mut Vec, + name: &str, + value: &str, + important: bool, + ) -> Option<()> { assert!(value != ""); // TODO handle browser prefixes ? @@ -320,7 +340,6 @@ fn set_style(style: &CssStyleDeclaration, name: &A, value: B, important: b if is_changed { Some(()) - } else { names.push(String::from(name)); values.push(String::from(value)); @@ -340,57 +359,71 @@ fn set_style(style: &CssStyleDeclaration, name: &A, value: B, important: b if let None = okay { if cfg!(debug_assertions) { // TODO maybe make this configurable - panic!("style is incorrect:\n names: {}\n values: {}", names.join(", "), values.join(", ")); + panic!( + "style is incorrect:\n names: {}\n values: {}", + names.join(", "), + values.join(", ") + ); } } } // TODO should this inline ? -fn set_style_signal(style: CssStyleDeclaration, callbacks: &mut Callbacks, name: A, value: D, important: bool) - where A: MultiStr + 'static, - B: MultiStr, - C: OptionStr, - D: Signal + 'static { - +fn set_style_signal( + style: CssStyleDeclaration, + callbacks: &mut Callbacks, + name: A, + value: D, + important: bool, +) where + A: MultiStr + 'static, + B: MultiStr, + C: OptionStr, + D: Signal + 'static, +{ set_option(style, callbacks, value, move |style, value| { match value { Some(value) => { // TODO should this intern or not ? set_style(style, &name, value, important); - }, + } None => { name.each(|name| { // TODO handle browser prefixes ? bindings::remove_style(style, intern(name)); }); - }, + } } }); } // TODO should this inline ? -fn set_style_unchecked_signal(style: CssStyleDeclaration, callbacks: &mut Callbacks, name: A, value: D, important: bool) - where A: AsStr + 'static, - B: AsStr, - C: OptionStr, - D: Signal + 'static { - - set_option(style, callbacks, value, move |style, value| { - match value { - Some(value) => { - name.with_str(|name| { - let name: &str = intern(name); - - value.with_str(|value| { - bindings::set_style(style, name, value, important); - }); - }); - }, - None => { - name.with_str(|name| { - bindings::remove_style(style, intern(name)); +fn set_style_unchecked_signal( + style: CssStyleDeclaration, + callbacks: &mut Callbacks, + name: A, + value: D, + important: bool, +) where + A: AsStr + 'static, + B: AsStr, + C: OptionStr, + D: Signal + 'static, +{ + set_option(style, callbacks, value, move |style, value| match value { + Some(value) => { + name.with_str(|name| { + let name: &str = intern(name); + + value.with_str(|value| { + bindings::set_style(style, name, value, important); }); - }, + }); + } + None => { + name.with_str(|name| { + bindings::remove_style(style, intern(name)); + }); } }); } @@ -398,7 +431,12 @@ fn set_style_unchecked_signal(style: CssStyleDeclaration, callbacks: // TODO check that the property *actually* was changed ? // TODO maybe use AsRef ? // TODO should this inline ? -fn set_property(element: &A, name: &B, value: C) where A: AsRef, B: MultiStr, C: Into { +fn set_property(element: &A, name: &B, value: C) +where + A: AsRef, + B: MultiStr, + C: Into, +{ let element = element.as_ref(); let value = value.into(); @@ -407,7 +445,6 @@ fn set_property(element: &A, name: &B, value: C) where A: AsRef { @@ -458,7 +494,10 @@ pub struct DomBuilder { callbacks: Callbacks, } -impl DomBuilder where A: JsCast { +impl DomBuilder +where + A: JsCast, +{ #[inline] pub fn new_html(name: &str) -> Self { Self::new(create_element(name)) @@ -474,8 +513,12 @@ impl DomBuilder { #[inline] #[doc(hidden)] pub fn __internal_transfer_callbacks(mut self, mut shadow: DomBuilder) -> Self { - self.callbacks.after_insert.append(&mut shadow.callbacks.after_insert); - self.callbacks.after_remove.append(&mut shadow.callbacks.after_remove); + self.callbacks + .after_insert + .append(&mut shadow.callbacks.after_insert); + self.callbacks + .after_remove + .append(&mut shadow.callbacks.after_remove); self } @@ -488,61 +531,89 @@ impl DomBuilder { } #[inline] - fn _event(callbacks: &mut Callbacks, element: &EventTarget, options: &EventOptions, listener: F) - where T: StaticEvent, - F: FnMut(T) + 'static { + fn _event( + callbacks: &mut Callbacks, + element: &EventTarget, + options: &EventOptions, + listener: F, + ) where + T: StaticEvent, + F: FnMut(T) + 'static, + { callbacks.after_remove(on(element, options, listener)); } // TODO add this to the StylesheetBuilder and ClassBuilder too #[inline] pub fn global_event_with_options(mut self, options: &EventOptions, listener: F) -> Self - where T: StaticEvent, - F: FnMut(T) + 'static { - Self::_event(&mut self.callbacks, &bindings::window_event_target(), options, listener); + where + T: StaticEvent, + F: FnMut(T) + 'static, + { + Self::_event( + &mut self.callbacks, + &bindings::window_event_target(), + options, + listener, + ); self } // TODO add this to the StylesheetBuilder and ClassBuilder too #[inline] pub fn global_event(self, listener: F) -> Self - where T: StaticEvent, - F: FnMut(T) + 'static { + where + T: StaticEvent, + F: FnMut(T) + 'static, + { self.global_event_with_options(&T::default_options(false), listener) } #[deprecated(since = "0.5.21", note = "Use global_event_with_options instead")] #[inline] pub fn global_event_preventable(self, listener: F) -> Self - where T: StaticEvent, - F: FnMut(T) + 'static { + where + T: StaticEvent, + F: FnMut(T) + 'static, + { self.global_event_with_options(&T::default_options(true), listener) } #[inline] - pub fn future(mut self, future: F) -> Self where F: Future + 'static { - self.callbacks.after_remove(DiscardOnDrop::leak(spawn_future(future))); + pub fn future(mut self, future: F) -> Self + where + F: Future + 'static, + { + self.callbacks + .after_remove(DiscardOnDrop::leak(spawn_future(future))); self } - #[inline] - pub fn apply(self, f: F) -> Self where F: FnOnce(Self) -> Self { + pub fn apply(self, f: F) -> Self + where + F: FnOnce(Self) -> Self, + { f(self) } #[inline] - pub fn apply_if(self, test: bool, f: F) -> Self where F: FnOnce(Self) -> Self { + pub fn apply_if(self, test: bool, f: F) -> Self + where + F: FnOnce(Self) -> Self, + { if test { f(self) - } else { self } } } -impl DomBuilder where A: Clone { +impl DomBuilder +where + A: Clone, +{ #[inline] #[doc(hidden)] pub fn __internal_element(&self) -> A { @@ -551,37 +622,56 @@ impl DomBuilder where A: Clone { #[deprecated(since = "0.5.1", note = "Use the with_node macro instead")] #[inline] - pub fn with_element(self, f: F) -> B where F: FnOnce(Self, A) -> B { + pub fn with_element(self, f: F) -> B + where + F: FnOnce(Self, A) -> B, + { let element = self.element.clone(); f(self, element) } #[deprecated(since = "0.5.20", note = "Use the with_node macro instead")] #[inline] - pub fn before_inserted(self, f: F) -> Self where F: FnOnce(A) { + pub fn before_inserted(self, f: F) -> Self + where + F: FnOnce(A), + { let element = self.element.clone(); f(element); self } } -impl DomBuilder where A: Clone + 'static { +impl DomBuilder +where + A: Clone + 'static, +{ #[inline] - pub fn after_inserted(mut self, f: F) -> Self where F: FnOnce(A) + 'static { + pub fn after_inserted(mut self, f: F) -> Self + where + F: FnOnce(A) + 'static, + { let element = self.element.clone(); self.callbacks.after_insert(move |_| f(element)); self } #[inline] - pub fn after_removed(mut self, f: F) -> Self where F: FnOnce(A) + 'static { + pub fn after_removed(mut self, f: F) -> Self + where + F: FnOnce(A) + 'static, + { let element = self.element.clone(); - self.callbacks.after_remove(FnDiscard::new(move || f(element))); + self.callbacks + .after_remove(FnDiscard::new(move || f(element))); self } } -impl DomBuilder where A: Into { +impl DomBuilder +where + A: Into, +{ #[inline] pub fn into_dom(self) -> Dom { Dom { @@ -591,27 +681,42 @@ impl DomBuilder where A: Into { } } -impl DomBuilder where A: AsRef { +impl DomBuilder +where + A: AsRef, +{ #[inline] - pub fn prop(self, name: B, value: C) -> Self where B: MultiStr, C: Into { + pub fn prop(self, name: B, value: C) -> Self + where + B: MultiStr, + C: Into, + { set_property(&self.element, &name, value); self } #[deprecated(since = "0.5.24", note = "Use the `prop` method instead")] #[inline] - pub fn property(self, name: B, value: C) -> Self where B: MultiStr, C: Into { + pub fn property(self, name: B, value: C) -> Self + where + B: MultiStr, + C: Into, + { self.prop(name, value) } } -impl DomBuilder where A: AsRef { +impl DomBuilder +where + A: AsRef, +{ // TODO should this inline ? fn set_property_signal(&mut self, name: B, value: D) - where B: MultiStr + 'static, - C: Into, - D: Signal + 'static { - + where + B: MultiStr + 'static, + C: Into, + D: Signal + 'static, + { let element = self.element.as_ref().clone(); self.callbacks.after_remove(for_each(value, move |value| { @@ -621,10 +726,11 @@ impl DomBuilder where A: AsRef { #[inline] pub fn prop_signal(mut self, name: B, value: D) -> Self - where B: MultiStr + 'static, - C: Into, - D: Signal + 'static { - + where + B: MultiStr + 'static, + C: Into, + D: Signal + 'static, + { self.set_property_signal(name, value); self } @@ -632,40 +738,58 @@ impl DomBuilder where A: AsRef { #[deprecated(since = "0.5.24", note = "Use the `prop_signal` method instead")] #[inline] pub fn property_signal(self, name: B, value: D) -> Self - where B: MultiStr + 'static, - C: Into, - D: Signal + 'static { - + where + B: MultiStr + 'static, + C: Into, + D: Signal + 'static, + { self.prop_signal(name, value) } } -impl DomBuilder where A: AsRef { +impl DomBuilder +where + A: AsRef, +{ #[inline] pub fn event_with_options(mut self, options: &EventOptions, listener: F) -> Self - where T: StaticEvent, - F: FnMut(T) + 'static { - Self::_event(&mut self.callbacks, &self.element.as_ref(), options, listener); + where + T: StaticEvent, + F: FnMut(T) + 'static, + { + Self::_event( + &mut self.callbacks, + &self.element.as_ref(), + options, + listener, + ); self } #[inline] pub fn event(self, listener: F) -> Self - where T: StaticEvent, - F: FnMut(T) + 'static { + where + T: StaticEvent, + F: FnMut(T) + 'static, + { self.event_with_options(&T::default_options(false), listener) } #[deprecated(since = "0.5.21", note = "Use event_with_options instead")] #[inline] pub fn event_preventable(self, listener: F) -> Self - where T: StaticEvent, - F: FnMut(T) + 'static { + where + T: StaticEvent, + F: FnMut(T) + 'static, + { self.event_with_options(&T::default_options(true), listener) } } -impl DomBuilder where A: AsRef { +impl DomBuilder +where + A: AsRef, +{ #[inline] pub fn text(self, value: &str) -> Self { // TODO should this intern ? @@ -675,9 +799,10 @@ impl DomBuilder where A: AsRef { #[inline] pub fn text_signal(mut self, value: C) -> Self - where B: AsStr, - C: Signal + 'static { - + where + B: AsStr, + C: Signal + 'static, + { let element = make_text_signal(&mut self.callbacks, value); bindings::append_child(self.element.as_ref(), &element); self @@ -685,14 +810,19 @@ impl DomBuilder where A: AsRef { #[inline] pub fn child>(mut self, mut child: B) -> Self { - operations::insert_children_one(self.element.as_ref(), &mut self.callbacks, child.borrow_mut()); + operations::insert_children_one( + self.element.as_ref(), + &mut self.callbacks, + child.borrow_mut(), + ); self } #[inline] pub fn child_signal(mut self, child: B) -> Self - where B: Signal> + 'static { - + where + B: Signal> + 'static, + { operations::insert_child_signal(self.element.as_ref().clone(), &mut self.callbacks, child); self } @@ -706,23 +836,38 @@ impl DomBuilder where A: AsRef { #[inline] pub fn children_signal_vec(mut self, children: B) -> Self - where B: SignalVec + 'static { - - operations::insert_children_signal_vec(self.element.as_ref().clone(), &mut self.callbacks, children); + where + B: SignalVec + 'static, + { + operations::insert_children_signal_vec( + self.element.as_ref().clone(), + &mut self.callbacks, + children, + ); self } } -impl DomBuilder where A: AsRef { +impl DomBuilder +where + A: AsRef, +{ #[inline] #[doc(hidden)] pub fn __internal_shadow_root(&self, mode: ShadowRootMode) -> DomBuilder { - let shadow = self.element.as_ref().attach_shadow(&ShadowRootInit::new(mode)).unwrap_throw(); + let shadow = self + .element + .as_ref() + .attach_shadow(&ShadowRootInit::new(mode)) + .unwrap(); DomBuilder::new(shadow) } #[inline] - pub fn attr(self, name: B, value: &str) -> Self where B: MultiStr { + pub fn attr(self, name: B, value: &str) -> Self + where + B: MultiStr, + { let element = self.element.as_ref(); name.each(|name| { @@ -734,12 +879,18 @@ impl DomBuilder where A: AsRef { #[deprecated(since = "0.5.24", note = "Use the `attr` method instead")] #[inline] - pub fn attribute(self, name: B, value: &str) -> Self where B: MultiStr { + pub fn attribute(self, name: B, value: &str) -> Self + where + B: MultiStr, + { self.attr(name, value) } #[inline] - pub fn attr_ns(self, namespace: &str, name: B, value: &str) -> Self where B: MultiStr { + pub fn attr_ns(self, namespace: &str, name: B, value: &str) -> Self + where + B: MultiStr, + { let element = self.element.as_ref(); let namespace: &str = intern(namespace); @@ -752,12 +903,18 @@ impl DomBuilder where A: AsRef { #[deprecated(since = "0.5.24", note = "Use the `attr_ns` method instead")] #[inline] - pub fn attribute_namespace(self, namespace: &str, name: B, value: &str) -> Self where B: MultiStr { + pub fn attribute_namespace(self, namespace: &str, name: B, value: &str) -> Self + where + B: MultiStr, + { self.attr_ns(namespace, name, value) } #[inline] - pub fn class(self, name: B) -> Self where B: MultiStr { + pub fn class(self, name: B) -> Self + where + B: MultiStr, + { let classes = self.element.as_ref().class_list(); name.each(|name| { @@ -773,46 +930,53 @@ impl DomBuilder where A: AsRef { if value { // TODO remove the class somehow ? self - } else { self.class(&*HIDDEN_CLASS) } } } -impl DomBuilder where A: AsRef { +impl DomBuilder +where + A: AsRef, +{ // TODO should this inline ? fn set_attribute_signal(&mut self, name: B, value: E) - where B: MultiStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - - set_option(self.element.as_ref().clone(), &mut self.callbacks, value, move |element, value| { - match value { + where + B: MultiStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { + set_option( + self.element.as_ref().clone(), + &mut self.callbacks, + value, + move |element, value| match value { Some(value) => { value.with_str(|value| { name.each(|name| { bindings::set_attribute(element, intern(name), &value); }); }); - }, + } None => { name.each(|name| { bindings::remove_attribute(element, intern(name)); }); - }, - } - }); + } + }, + ); } #[inline] pub fn attr_signal(mut self, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - + where + B: MultiStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { self.set_attribute_signal(name, value); self } @@ -820,51 +984,63 @@ impl DomBuilder where A: AsRef { #[deprecated(since = "0.5.24", note = "Use the `attr_signal` method instead")] #[inline] pub fn attribute_signal(self, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - + where + B: MultiStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { self.attr_signal(name, value) } - // TODO should this inline ? fn set_attribute_namespace_signal(&mut self, namespace: &str, name: B, value: E) - where B: MultiStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - + where + B: MultiStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { // TODO avoid this to_owned by using Into> let namespace: String = intern(namespace).to_owned(); - set_option(self.element.as_ref().clone(), &mut self.callbacks, value, move |element, value| { - match value { - Some(value) => { - value.with_str(|value| { + set_option( + self.element.as_ref().clone(), + &mut self.callbacks, + value, + move |element, value| { + match value { + Some(value) => { + value.with_str(|value| { + name.each(|name| { + // TODO should this intern the value ? + bindings::set_attribute_ns( + element, + &namespace, + intern(name), + &value, + ); + }); + }); + } + None => { name.each(|name| { - // TODO should this intern the value ? - bindings::set_attribute_ns(element, &namespace, intern(name), &value); + bindings::remove_attribute_ns(element, &namespace, intern(name)); }); - }); - }, - None => { - name.each(|name| { - bindings::remove_attribute_ns(element, &namespace, intern(name)); - }); - }, - } - }); + } + } + }, + ); } #[inline] pub fn attr_ns_signal(mut self, namespace: &str, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - + where + B: MultiStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { self.set_attribute_namespace_signal(namespace, name, value); self } @@ -872,20 +1048,21 @@ impl DomBuilder where A: AsRef { #[deprecated(since = "0.5.24", note = "Use the `attr_ns_signal` method instead")] #[inline] pub fn attribute_namespace_signal(self, namespace: &str, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - + where + B: MultiStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { self.attr_ns_signal(namespace, name, value) } - // TODO should this inline ? fn set_class_signal(&mut self, name: B, value: C) - where B: MultiStr + 'static, - C: Signal + 'static { - + where + B: MultiStr + 'static, + C: Signal + 'static, + { let element = self.element.as_ref().class_list(); let mut is_set = false; @@ -899,7 +1076,6 @@ impl DomBuilder where A: AsRef { bindings::add_class(&element, intern(name)); }); } - } else { if is_set { is_set = false; @@ -914,26 +1090,30 @@ impl DomBuilder where A: AsRef { #[inline] pub fn class_signal(mut self, name: B, value: C) -> Self - where B: MultiStr + 'static, - C: Signal + 'static { - + where + B: MultiStr + 'static, + C: Signal + 'static, + { self.set_class_signal(name, value); self } // TODO make this more efficient ? #[inline] - pub fn visible_signal(self, value: B) -> Self where B: Signal + 'static { + pub fn visible_signal(self, value: B) -> Self + where + B: Signal + 'static, + { self.class_signal(&*HIDDEN_CLASS, not(value)) } - // TODO use OptionStr ? // TODO should this inline ? fn set_scroll_signal(&mut self, signal: B, mut f: F) - where B: Signal> + 'static, - F: FnMut(&Element, i32) + 'static { - + where + B: Signal> + 'static, + F: FnMut(&Element, i32) + 'static, + { let element: Element = self.element.as_ref().clone(); // This needs to use `after_insert` because scrolling an element before it is in the DOM has no effect @@ -948,7 +1128,10 @@ impl DomBuilder where A: AsRef { // TODO rename to scroll_x_signal ? #[inline] - pub fn scroll_left_signal(mut self, signal: B) -> Self where B: Signal> + 'static { + pub fn scroll_left_signal(mut self, signal: B) -> Self + where + B: Signal> + 'static, + { // TODO bindings function for this ? self.set_scroll_signal(signal, Element::set_scroll_left); self @@ -956,34 +1139,46 @@ impl DomBuilder where A: AsRef { // TODO rename to scroll_y_signal ? #[inline] - pub fn scroll_top_signal(mut self, signal: B) -> Self where B: Signal> + 'static { + pub fn scroll_top_signal(mut self, signal: B) -> Self + where + B: Signal> + 'static, + { // TODO bindings function for this ? self.set_scroll_signal(signal, Element::set_scroll_top); self } } -impl DomBuilder where A: AsRef { +impl DomBuilder +where + A: AsRef, +{ #[inline] pub fn style(self, name: B, value: C) -> Self - where B: MultiStr, - C: MultiStr { + where + B: MultiStr, + C: MultiStr, + { set_style(&self.element.as_ref().style(), &name, value, false); self } #[inline] pub fn style_important(self, name: B, value: C) -> Self - where B: MultiStr, - C: MultiStr { + where + B: MultiStr, + C: MultiStr, + { set_style(&self.element.as_ref().style(), &name, value, true); self } #[inline] pub fn style_unchecked(self, name: B, value: C) -> Self - where B: AsStr, - C: AsStr { + where + B: AsStr, + C: AsStr, + { name.with_str(|name| { value.with_str(|value| { bindings::set_style(&self.element.as_ref().style(), intern(name), value, false); @@ -993,41 +1188,64 @@ impl DomBuilder where A: AsRef { } } -impl DomBuilder where A: AsRef { +impl DomBuilder +where + A: AsRef, +{ #[inline] pub fn style_signal(mut self, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: MultiStr, - D: OptionStr, - E: Signal + 'static { - - set_style_signal(self.element.as_ref().style(), &mut self.callbacks, name, value, false); + where + B: MultiStr + 'static, + C: MultiStr, + D: OptionStr, + E: Signal + 'static, + { + set_style_signal( + self.element.as_ref().style(), + &mut self.callbacks, + name, + value, + false, + ); self } #[inline] pub fn style_important_signal(mut self, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: MultiStr, - D: OptionStr, - E: Signal + 'static { - - set_style_signal(self.element.as_ref().style(), &mut self.callbacks, name, value, true); + where + B: MultiStr + 'static, + C: MultiStr, + D: OptionStr, + E: Signal + 'static, + { + set_style_signal( + self.element.as_ref().style(), + &mut self.callbacks, + name, + value, + true, + ); self } #[inline] pub fn style_unchecked_signal(mut self, name: B, value: E) -> Self - where B: AsStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - - set_style_unchecked_signal(self.element.as_ref().style(), &mut self.callbacks, name, value, false); + where + B: AsStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { + set_style_unchecked_signal( + self.element.as_ref().style(), + &mut self.callbacks, + name, + value, + false, + ); self } - // TODO remove the `value` argument ? #[inline] pub fn focused(mut self, value: bool) -> Self { @@ -1038,7 +1256,6 @@ impl DomBuilder where A: AsRef { // TODO avoid updating if the focused state hasn't changed ? if value { bindings::focus(&element); - } else { bindings::blur(&element); } @@ -1047,11 +1264,11 @@ impl DomBuilder where A: AsRef { self } - // TODO should this inline ? fn set_focused_signal(&mut self, value: B) - where B: Signal + 'static { - + where + B: Signal + 'static, + { let element = self.element.as_ref().clone(); // This needs to use `after_insert` because calling `.focus()` on an element before it is in the DOM has no effect @@ -1061,7 +1278,6 @@ impl DomBuilder where A: AsRef { // TODO avoid updating if the focused state hasn't changed ? if value { bindings::focus(&element); - } else { bindings::blur(&element); } @@ -1071,14 +1287,14 @@ impl DomBuilder where A: AsRef { #[inline] pub fn focused_signal(mut self, value: B) -> Self - where B: Signal + 'static { - + where + B: Signal + 'static, + { self.set_focused_signal(value); self } } - // TODO better warning message for must_use #[must_use] pub struct StylesheetBuilder { @@ -1091,18 +1307,24 @@ impl StylesheetBuilder { // TODO should this inline ? #[doc(hidden)] #[inline] - pub fn __internal_new(selector: A) -> Self where A: MultiStr { + pub fn __internal_new(selector: A) -> Self + where + A: MultiStr, + { // TODO can this be made faster ? // TODO somehow share this safely between threads ? thread_local! { static STYLESHEET: CssStyleSheet = bindings::create_stylesheet(); } - fn try_make(stylesheet: &CssStyleSheet, selector: &str, selectors: &mut Vec) -> Option { + fn try_make( + stylesheet: &CssStyleSheet, + selector: &str, + selectors: &mut Vec, + ) -> Option { // TODO maybe intern the selector ? if let Ok(declaration) = bindings::make_style_rule(stylesheet, selector) { Some(declaration.style()) - } else { selectors.push(String::from(selector)); None @@ -1112,13 +1334,10 @@ impl StylesheetBuilder { let element = STYLESHEET.with(move |stylesheet| { let mut selectors = vec![]; - let okay = selector.find_map(|selector| { - try_make(stylesheet, selector, &mut selectors) - }); + let okay = selector.find_map(|selector| try_make(stylesheet, selector, &mut selectors)); if let Some(okay) = okay { okay - } else { // TODO maybe make this configurable panic!("selectors are incorrect:\n {}", selectors.join("\n ")); @@ -1133,24 +1352,30 @@ impl StylesheetBuilder { #[inline] pub fn style(self, name: B, value: C) -> Self - where B: MultiStr, - C: MultiStr { + where + B: MultiStr, + C: MultiStr, + { set_style(&self.element, &name, value, false); self } #[inline] pub fn style_important(self, name: B, value: C) -> Self - where B: MultiStr, - C: MultiStr { + where + B: MultiStr, + C: MultiStr, + { set_style(&self.element, &name, value, true); self } #[inline] pub fn style_unchecked(self, name: B, value: C) -> Self - where B: AsStr, - C: AsStr { + where + B: AsStr, + C: AsStr, + { name.with_str(|name| { value.with_str(|value| { bindings::set_style(&self.element, intern(name), value, false); @@ -1161,34 +1386,49 @@ impl StylesheetBuilder { #[inline] pub fn style_signal(mut self, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: MultiStr, - D: OptionStr, - E: Signal + 'static { - - set_style_signal(self.element.clone(), &mut self.callbacks, name, value, false); + where + B: MultiStr + 'static, + C: MultiStr, + D: OptionStr, + E: Signal + 'static, + { + set_style_signal( + self.element.clone(), + &mut self.callbacks, + name, + value, + false, + ); self } #[inline] pub fn style_important_signal(mut self, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: MultiStr, - D: OptionStr, - E: Signal + 'static { - + where + B: MultiStr + 'static, + C: MultiStr, + D: OptionStr, + E: Signal + 'static, + { set_style_signal(self.element.clone(), &mut self.callbacks, name, value, true); self } #[inline] pub fn style_unchecked_signal(mut self, name: B, value: E) -> Self - where B: AsStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - - set_style_unchecked_signal(self.element.clone(), &mut self.callbacks, name, value, false); + where + B: AsStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { + set_style_unchecked_signal( + self.element.clone(), + &mut self.callbacks, + name, + value, + false, + ); self } @@ -1203,7 +1443,6 @@ impl StylesheetBuilder { } } - // TODO better warning message for must_use #[must_use] pub struct ClassBuilder { @@ -1232,57 +1471,66 @@ impl ClassBuilder { #[inline] pub fn style(mut self, name: B, value: C) -> Self - where B: MultiStr, - C: MultiStr { + where + B: MultiStr, + C: MultiStr, + { self.stylesheet = self.stylesheet.style(name, value); self } #[inline] pub fn style_important(mut self, name: B, value: C) -> Self - where B: MultiStr, - C: MultiStr { + where + B: MultiStr, + C: MultiStr, + { self.stylesheet = self.stylesheet.style_important(name, value); self } #[inline] pub fn style_unchecked(mut self, name: B, value: C) -> Self - where B: AsStr, - C: AsStr { + where + B: AsStr, + C: AsStr, + { self.stylesheet = self.stylesheet.style_unchecked(name, value); self } #[inline] pub fn style_signal(mut self, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: MultiStr, - D: OptionStr, - E: Signal + 'static { - + where + B: MultiStr + 'static, + C: MultiStr, + D: OptionStr, + E: Signal + 'static, + { self.stylesheet = self.stylesheet.style_signal(name, value); self } #[inline] pub fn style_important_signal(mut self, name: B, value: E) -> Self - where B: MultiStr + 'static, - C: MultiStr, - D: OptionStr, - E: Signal + 'static { - + where + B: MultiStr + 'static, + C: MultiStr, + D: OptionStr, + E: Signal + 'static, + { self.stylesheet = self.stylesheet.style_important_signal(name, value); self } #[inline] pub fn style_unchecked_signal(mut self, name: B, value: E) -> Self - where B: AsStr + 'static, - C: AsStr, - D: OptionStr, - E: Signal + 'static { - + where + B: AsStr + 'static, + C: AsStr, + D: OptionStr, + E: Signal + 'static, + { self.stylesheet = self.stylesheet.style_unchecked_signal(name, value); self } @@ -1296,17 +1544,14 @@ impl ClassBuilder { } } - #[doc(hidden)] pub mod __internal { - use std::sync::atomic::{AtomicU32, Ordering}; use crate::traits::MultiStr; - + use std::sync::atomic::{AtomicU32, Ordering}; pub use web_sys::HtmlElement; pub use web_sys::SvgElement; - pub fn make_class_id() -> String { // TODO replace this with a global counter in JavaScript ? // TODO can this be made more efficient ? @@ -1320,34 +1565,43 @@ pub mod __internal { format!("__class_{}__", id) } - pub struct Pseudo<'a, A> { class_name: &'a str, pseudos: A, } - impl<'a, A> Pseudo<'a, A> where A: MultiStr { + impl<'a, A> Pseudo<'a, A> + where + A: MultiStr, + { #[inline] pub fn new(class_name: &'a str, pseudos: A) -> Self { - Self { class_name, pseudos } + Self { + class_name, + pseudos, + } } } - impl<'a, A> MultiStr for Pseudo<'a, A> where A: MultiStr { + impl<'a, A> MultiStr for Pseudo<'a, A> + where + A: MultiStr, + { #[inline] - fn find_map(&self, mut f: F) -> Option where F: FnMut(&str) -> Option { - self.pseudos.find_map(|x| { - f(&format!(".{}{}", self.class_name, x)) - }) + fn find_map(&self, mut f: F) -> Option + where + F: FnMut(&str) -> Option, + { + self.pseudos + .find_map(|x| f(&format!(".{}{}", self.class_name, x))) } } } - #[cfg(test)] mod tests { - use super::{DomBuilder, text_signal, RefFn}; - use crate::{html, shadow_root, ShadowRootMode, with_cfg}; + use super::{text_signal, DomBuilder, RefFn}; + use crate::{html, shadow_root, with_cfg, ShadowRootMode}; use futures_signals::signal::{always, SignalExt}; use once_cell::sync::Lazy; use web_sys::HtmlElement; @@ -1365,22 +1619,21 @@ mod tests { #[test] fn children_mut() { - let _a: DomBuilder = DomBuilder::new_html("div") - .children(&mut [ - DomBuilder::::new_html("div").into_dom(), - DomBuilder::::new_html("div").into_dom(), - DomBuilder::::new_html("div").into_dom(), - ]); + let _a: DomBuilder = DomBuilder::new_html("div").children(&mut [ + DomBuilder::::new_html("div").into_dom(), + DomBuilder::::new_html("div").into_dom(), + DomBuilder::::new_html("div").into_dom(), + ]); } #[test] fn children_value() { let v: Vec = vec![]; - let _a: DomBuilder = DomBuilder::new_html("div") - .children(v.iter().map(|_| { - DomBuilder::::new_html("div").into_dom() - })); + let _a: DomBuilder = DomBuilder::new_html("div").children( + v.iter() + .map(|_| DomBuilder::::new_html("div").into_dom()), + ); } #[test] @@ -1404,15 +1657,12 @@ mod tests { .prop("foo", "hi") .prop("foo", 5) .prop(["foo", "-webkit-foo", "-ms-foo"], "hi") - .prop_signal("foo", always("hi")) .prop_signal("foo", always(5)) .prop_signal("foo", always(Some("hi"))) - .prop_signal(["foo", "-webkit-foo", "-ms-foo"], always("hi")) .prop_signal(["foo", "-webkit-foo", "-ms-foo"], always(5)) - .prop_signal(["foo", "-webkit-foo", "-ms-foo"], always(Some("hi"))) - ; + .prop_signal(["foo", "-webkit-foo", "-ms-foo"], always(Some("hi"))); } #[test] @@ -1420,13 +1670,10 @@ mod tests { let _a: DomBuilder = DomBuilder::new_html("div") .attr("foo", "hi") .attr(["foo", "-webkit-foo", "-ms-foo"], "hi") - .attr_signal("foo", always("hi")) .attr_signal("foo", always(Some("hi"))) - .attr_signal(["foo", "-webkit-foo", "-ms-foo"], always("hi")) - .attr_signal(["foo", "-webkit-foo", "-ms-foo"], always(Some("hi"))) - ; + .attr_signal(["foo", "-webkit-foo", "-ms-foo"], always(Some("hi"))); } #[test] @@ -1434,10 +1681,8 @@ mod tests { let _a: DomBuilder = DomBuilder::new_html("div") .class("foo") .class(["foo", "-webkit-foo", "-ms-foo"]) - .class_signal("foo", always(true)) - .class_signal(["foo", "-webkit-foo", "-ms-foo"], always(true)) - ; + .class_signal(["foo", "-webkit-foo", "-ms-foo"], always(true)); } #[test] @@ -1447,38 +1692,49 @@ mod tests { let _a: DomBuilder = DomBuilder::new_html("div") .style_signal("foo", always("bar")) .style_signal("foo", always("bar".to_owned())) - .style_signal("foo", always("bar".to_owned()).map(|x| RefFn::new(x, |x| x.as_str()))) - + .style_signal( + "foo", + always("bar".to_owned()).map(|x| RefFn::new(x, |x| x.as_str())), + ) .style("foo".to_owned(), "bar".to_owned()) .style_signal("foo".to_owned(), always("bar".to_owned())) - .style(&"foo".to_owned(), &"bar".to_owned()) //.style(Box::new("foo".to_owned()), Box::new("bar".to_owned())) //.style_signal(Box::new("foo".to_owned()), always(Box::new("bar".to_owned()))) - .style_signal(&*FOO, always(&*FOO)) - //.style(vec!["-moz-foo", "-webkit-foo", "foo"].as_slice(), vec!["bar"].as_slice()) - .style_signal(RefFn::new(vec!["-moz-foo", "-webkit-foo", "foo"], |x| x.as_slice()), always(RefFn::new(vec!["bar"], |x| x.as_slice()))) - + .style_signal( + RefFn::new(vec!["-moz-foo", "-webkit-foo", "foo"], |x| x.as_slice()), + always(RefFn::new(vec!["bar"], |x| x.as_slice())), + ) .style_signal(["-moz-foo", "-webkit-foo", "foo"], always("bar")) .style_signal(["-moz-foo", "-webkit-foo", "foo"], always("bar".to_owned())) - .style_signal(["-moz-foo", "-webkit-foo", "foo"], always("bar".to_owned()).map(|x| RefFn::new(x, |x| x.as_str()))) - + .style_signal( + ["-moz-foo", "-webkit-foo", "foo"], + always("bar".to_owned()).map(|x| RefFn::new(x, |x| x.as_str())), + ) .style_signal(["-moz-foo", "-webkit-foo", "foo"], always(["bar", "qux"])) - .style_signal(["-moz-foo", "-webkit-foo", "foo"], always(["bar".to_owned(), "qux".to_owned()])) - + .style_signal( + ["-moz-foo", "-webkit-foo", "foo"], + always(["bar".to_owned(), "qux".to_owned()]), + ) //.style_signal(["-moz-foo", "-webkit-foo", "foo"], always(AsSlice::new(["foo", "bar"]))) //.style_signal(["-moz-foo", "-webkit-foo", "foo"], always(("bar".to_owned(), "qux".to_owned())).map(|x| RefFn::new(x, |x| AsSlice::new([x.0.as_str(), x.1.as_str()])))) - .style_signal("foo", always(Some("bar"))) .style_signal("foo", always(Some("bar".to_owned()))) - .style_signal("foo", always("bar".to_owned()).map(|x| Some(RefFn::new(x, |x| x.as_str())))) - + .style_signal( + "foo", + always("bar".to_owned()).map(|x| Some(RefFn::new(x, |x| x.as_str()))), + ) .style_signal(["-moz-foo", "-webkit-foo", "foo"], always(Some("bar"))) - .style_signal(["-moz-foo", "-webkit-foo", "foo"], always(Some("bar".to_owned()))) - .style_signal(["-moz-foo", "-webkit-foo", "foo"], always("bar".to_owned()).map(|x| Some(RefFn::new(x, |x| x.as_str())))) - ; + .style_signal( + ["-moz-foo", "-webkit-foo", "foo"], + always(Some("bar".to_owned())), + ) + .style_signal( + ["-moz-foo", "-webkit-foo", "foo"], + always("bar".to_owned()).map(|x| Some(RefFn::new(x, |x| x.as_str()))), + ); } #[test] diff --git a/src/operations.rs b/src/operations.rs index df6fd8a..e73caf9 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -9,7 +9,6 @@ use futures_signals::{cancelable_future, CancelableFutureHandle}; use futures_signals::signal::{Signal, SignalExt}; use futures_signals::signal_vec::{VecDiff, SignalVec, SignalVecExt}; use web_sys::Node; -use wasm_bindgen::UnwrapThrowExt; use wasm_bindgen_futures::spawn_local; use crate::bindings; @@ -290,7 +289,7 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb }, VecDiff::Pop {} => { - let dom = self.children.pop().unwrap_throw(); + let dom = self.children.pop().unwrap(); bindings::remove_child(&self.element, &dom.element); diff --git a/src/utils.rs b/src/utils.rs index 5c7a367..6dd3cab 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,23 +1,28 @@ use std::borrow::Cow; use std::mem::ManuallyDrop; -use wasm_bindgen::{UnwrapThrowExt, intern}; use discard::Discard; -use web_sys::{EventTarget, Event}; +use wasm_bindgen::intern; +use web_sys::{Event, EventTarget}; use crate::dom::EventOptions; use crate::traits::StaticEvent; - pub(crate) struct EventListener(Option); // TODO should these inline ? impl EventListener { #[inline] - pub(crate) fn new(elem: &EventTarget, name: N, options: &EventOptions, callback: F) -> Self - where N: Into>, - F: FnMut(&Event) + 'static { - + pub(crate) fn new( + elem: &EventTarget, + name: N, + options: &EventOptions, + callback: F, + ) -> Self + where + N: Into>, + F: FnMut(&Event) + 'static, + { // TODO get rid of this by fixing web-sys code generation intern("capture"); intern("once"); @@ -36,9 +41,10 @@ impl EventListener { #[inline] pub(crate) fn once(elem: &EventTarget, name: N, callback: F) -> Self - where N: Into>, - F: FnOnce(&Event) + 'static { - + where + N: Into>, + F: FnOnce(&Event) + 'static, + { // TODO get rid of this by fixing web-sys code generation intern("capture"); intern("once"); @@ -53,7 +59,8 @@ impl EventListener { EventOptions { bubbles: false, preventable: false, - }.into_gloo(), + } + .into_gloo(), callback, ))) } @@ -73,21 +80,25 @@ impl Discard for EventListener { #[inline] fn discard(mut self) { // Drops the listener which cleans it up - let _ = self.0.take().unwrap_throw(); + let _ = self.0.take().unwrap(); } } - #[inline] -pub(crate) fn on(element: &EventTarget, options: &EventOptions, mut callback: F) -> EventListener - where E: StaticEvent, - F: FnMut(E) + 'static { +pub(crate) fn on( + element: &EventTarget, + options: &EventOptions, + mut callback: F, +) -> EventListener +where + E: StaticEvent, + F: FnMut(E) + 'static, +{ EventListener::new(element, E::EVENT_TYPE, options, move |e| { callback(E::unchecked_from_event(e.clone())); }) } - // TODO move this into the discard crate // TODO verify that this is correct and doesn't leak memory or cause memory safety pub(crate) struct ValueDiscard(ManuallyDrop); @@ -107,19 +118,24 @@ impl Discard for ValueDiscard { } } - // TODO move this into the discard crate // TODO replace this with an impl for FnOnce() ? pub(crate) struct FnDiscard(A); -impl FnDiscard where A: FnOnce() { +impl FnDiscard +where + A: FnOnce(), +{ #[inline] pub(crate) fn new(f: A) -> Self { FnDiscard(f) } } -impl Discard for FnDiscard where A: FnOnce() { +impl Discard for FnDiscard +where + A: FnOnce(), +{ #[inline] fn discard(self) { self.0();