Skip to content

Commit

Permalink
web_sys cfg conversion (#862)
Browse files Browse the repository at this point in the history
* Use `cfg-if` and `cfg-match` and some polish.

* Mistakes were made.

* Missed line during rebasing.

* Mistakes were undone.

* Remove global.

* Remove part of `global!`.
  • Loading branch information
daxpedda authored and jstarry committed Jan 15, 2020
1 parent 8bb9d88 commit 3b3fa96
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 247 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ travis-ci = { repository = "yewstack/yew" }
[dependencies]
anymap = "0.12"
bincode = { version = "~1.2.1", optional = true }
cfg-if = "0.1"
cfg-match = "0.2"
console_error_panic_hook = { version = "0.1", optional = true }
failure = "0.1"
gloo = { version = "0.2", optional = true }
Expand Down
12 changes: 8 additions & 4 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@

use crate::html::{Component, NodeRef, Scope};
use crate::utils::document;
#[cfg(feature = "std_web")]
use stdweb::web::{Element, INode, IParentNode};
#[cfg(feature = "web_sys")]
use web_sys::Element;
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::web::{Element, INode, IParentNode};
} else if #[cfg(feature = "web_sys")] {
use web_sys::Element;
}
}

/// An application instance.
#[derive(Debug)]
Expand Down
9 changes: 5 additions & 4 deletions src/components/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use crate::callback::Callback;
use crate::html::{ChangeData, Component, ComponentLink, Html, ShouldRender};
use crate::macros::{html, Properties};
use cfg_match::cfg_match;

/// `Select` component.
#[derive(Debug)]
Expand Down Expand Up @@ -122,10 +123,10 @@ where
self.link.callback(|event| match event {
ChangeData::Select(elem) => {
let value = elem.selected_index();
#[cfg(feature = "std_web")]
let value = value.map(|x| x as usize);
#[cfg(feature = "web_sys")]
let value = Some(value as usize);
let value = cfg_match! {
feature = "std_web" => value.map(|x| x as usize),
feature = "web_sys" => Some(value as usize),
};
Msg::Selected(value)
}
_ => {
Expand Down
31 changes: 15 additions & 16 deletions src/html/listener/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ macro_rules! impl_action {
($($action:ident(name: $name:literal, event: $type:ident) -> $ret:ty => $convert:expr)*) => {$(
/// An abstract implementation of a listener.
pub mod $action {
use cfg_if::cfg_if;
use cfg_match::cfg_match;
use crate::callback::Callback;
#[allow(unused_imports)]
use crate::html::listener::*;
use crate::virtual_dom::Listener;
#[cfg(feature = "std_web")]
use stdweb::web::{
event::{$type, IEvent},
Element, IEventTarget,
};
#[cfg(feature = "web_sys")]
use ::{
gloo::events::EventListener,
wasm_bindgen::JsValue,
web_sys::{$type as WebSysType, Element, EventTarget},
};
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::web::event::{$type, IEvent};
use stdweb::web::{Element, IEventTarget};
} else if #[cfg(feature = "web_sys")] {
use gloo::events::EventListener;
use wasm_bindgen::JsValue;
use web_sys::{$type as WebSysType, Element, EventTarget};
}
}

/// A wrapper for a callback which attaches event listeners to elements.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -55,12 +56,10 @@ macro_rules! impl_action {
let event: WebSysType = JsValue::from(event).into();
callback.emit($convert(&this, event));
};
#[cfg(feature = "std_web")]
{
EventListener(Some(element.add_event_listener(listener)))
cfg_match! {
feature = "std_web" => EventListener(Some(element.add_event_listener(listener))),
feature = "web_sys" => EventListener::new(&EventTarget::from(element.clone()), $name, listener),
}
#[cfg(feature = "web_sys")]
EventListener::new(&EventTarget::from(element.clone()), $name, listener)
}
}
}
Expand Down
126 changes: 65 additions & 61 deletions src/html/listener/mod.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
#[macro_use]
mod macros;
#[cfg(feature = "std_web")]
mod listener_stdweb;
#[cfg(feature = "web_sys")]
mod listener_web_sys;

#[cfg(feature = "std_web")]
pub use listener_stdweb::*;
#[cfg(feature = "web_sys")]
pub use listener_web_sys::*;
#[cfg(feature = "std_web")]
use stdweb::{
js,
unstable::TryInto,
web::{
html_element::{InputElement, SelectElement, TextAreaElement},
Element, EventListenerHandle, FileList, IElement, INode,
},
};
#[cfg(feature = "web_sys")]
use ::{
wasm_bindgen::JsCast,
web_sys::{
Element, FileList, HtmlInputElement as InputElement, HtmlSelectElement as SelectElement,
HtmlTextAreaElement as TextAreaElement,
},
};
use cfg_if::cfg_if;
use cfg_match::cfg_match;

cfg_if! {
if #[cfg(feature = "std_web")] {
mod listener_stdweb;

use stdweb::js;
use stdweb::unstable::{TryFrom, TryInto};
use stdweb::web::html_element::{InputElement, SelectElement, TextAreaElement};
use stdweb::web::{Element, EventListenerHandle, FileList, IElement, INode};

pub use listener_stdweb::*;
} else if #[cfg(feature = "web_sys")] {
mod listener_web_sys;

use wasm_bindgen::JsCast;
use web_sys::{
Element, FileList, HtmlInputElement as InputElement, HtmlSelectElement as SelectElement,
HtmlTextAreaElement as TextAreaElement,
};

pub use listener_web_sys::*;
}
}

/// A type representing data from `oninput` event.
#[derive(Debug)]
Expand Down Expand Up @@ -60,22 +60,26 @@ fn oninput_handler(this: &Element) -> InputData {
// practice though any element with `contenteditable=true` may generate such events,
// therefore here we fall back to just returning the text content of the node.
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event.
#[cfg(feature = "std_web")]
let (v1, v2) = (
this.clone()
.try_into()
.map(|input: InputElement| input.raw_value())
.ok(),
this.clone()
.try_into()
.map(|input: TextAreaElement| input.value())
.ok(),
);
#[cfg(feature = "web_sys")]
let (v1, v2) = (
this.dyn_ref().map(|input: &InputElement| input.value()),
this.dyn_ref().map(|input: &TextAreaElement| input.value()),
);
let (v1, v2) = cfg_match! {
feature = "std_web" => ({
(
this.clone()
.try_into()
.map(|input: InputElement| input.raw_value())
.ok(),
this.clone()
.try_into()
.map(|input: TextAreaElement| input.value())
.ok(),
)
}),
feature = "web_sys" => ({
(
this.dyn_ref().map(|input: &InputElement| input.value()),
this.dyn_ref().map(|input: &TextAreaElement| input.value()),
)
}),
};
let v3 = this.text_content();
let value = v1.or(v2).or(v3)
.expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener");
Expand All @@ -85,39 +89,39 @@ fn oninput_handler(this: &Element) -> InputData {
fn onchange_handler(this: &Element) -> ChangeData {
match this.node_name().as_ref() {
"INPUT" => {
#[cfg(feature = "std_web")]
let input: InputElement = this.clone().try_into().unwrap();
#[cfg(feature = "web_sys")]
let input: &InputElement = this.dyn_ref().unwrap();
let input = cfg_match! {
feature = "std_web" => InputElement::try_from(this.clone()).unwrap(),
feature = "web_sys" => this.dyn_ref::<InputElement>().unwrap(),
};
let is_file = input
.get_attribute("type")
.map(|value| value.eq_ignore_ascii_case("file"))
.unwrap_or(false);
if is_file {
#[cfg(feature = "std_web")]
let files: FileList = js!( return @{input}.files; ).try_into().unwrap();
#[cfg(feature = "web_sys")]
let files: FileList = input.files().unwrap();
let files: FileList = cfg_match! {
feature = "std_web" => js!( return @{input}.files; ).try_into().unwrap(),
feature = "web_sys" => input.files().unwrap(),
};
ChangeData::Files(files)
} else {
#[cfg(feature = "std_web")]
return ChangeData::Value(input.raw_value());
#[cfg(feature = "web_sys")]
ChangeData::Value(input.value())
cfg_match! {
feature = "std_web" => ChangeData::Value(input.raw_value()),
feature = "web_sys" => ChangeData::Value(input.value()),
}
}
}
"TEXTAREA" => {
#[cfg(feature = "std_web")]
let tae: TextAreaElement = this.clone().try_into().unwrap();
#[cfg(feature = "web_sys")]
let tae: &TextAreaElement = this.dyn_ref().unwrap();
let tae = cfg_match! {
feature = "std_web" => TextAreaElement::try_from(this.clone()).unwrap(),
feature = "web_sys" => this.dyn_ref::<TextAreaElement>().unwrap(),
};
ChangeData::Value(tae.value())
}
"SELECT" => {
#[cfg(feature = "std_web")]
let se: SelectElement = this.clone().try_into().unwrap();
#[cfg(feature = "web_sys")]
let se = this.dyn_ref::<SelectElement>().unwrap().clone();
let se = cfg_match! {
feature = "std_web" => SelectElement::try_from(this.clone()).unwrap(),
feature = "web_sys" => this.dyn_ref::<SelectElement>().unwrap().clone(),
};
ChangeData::Select(se)
}
_ => {
Expand Down
23 changes: 14 additions & 9 deletions src/html/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@ pub use scope::{Scope, ScopeHolder};

use crate::callback::Callback;
use crate::virtual_dom::{VChild, VList, VNode};
use cfg_if::cfg_if;
use cfg_match::cfg_match;
use std::any::TypeId;
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
#[cfg(feature = "std_web")]
use stdweb::{unstable::TryFrom, web::Node};
#[cfg(feature = "web_sys")]
use ::{wasm_bindgen::JsValue, web_sys::Node};
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::unstable::TryFrom;
use stdweb::web::Node;
} else if #[cfg(feature = "web_sys")] {
use wasm_bindgen::JsValue;
use web_sys::Node;
}
}

/// This type indicates that component should be rendered again.
pub type ShouldRender = bool;
Expand Down Expand Up @@ -324,12 +331,10 @@ impl NodeRef {
&self,
) -> Option<INTO> {
let node = self.get();
#[cfg(feature = "std_web")]
{
node.and_then(|node| INTO::try_from(node).ok())
cfg_match! {
feature = "std_web" => node.and_then(|node| INTO::try_from(node).ok()),
feature = "web_sys" => node.map(Into::into).map(INTO::from),
}
#[cfg(feature = "web_sys")]
node.map(Into::into).map(INTO::from)
}

/// Place a Node in a reference for later use
Expand Down
12 changes: 8 additions & 4 deletions src/html/scope.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use super::*;
use crate::scheduler::{scheduler, Runnable, Shared};
use crate::virtual_dom::{VDiff, VNode};
use cfg_if::cfg_if;
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
#[cfg(feature = "std_web")]
use stdweb::web::Element;
#[cfg(feature = "web_sys")]
use web_sys::Element;
cfg_if! {
if #[cfg(feature = "std_web")] {
use stdweb::web::Element;
} else if #[cfg(feature = "web_sys")] {
use web_sys::Element;
}
}

/// Updates for a `Component` instance. Used by scope sender.
pub(crate) enum ComponentUpdate<COMP: Component> {
Expand Down
47 changes: 27 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,32 +99,39 @@ pub mod services;

/// The module that contains all events available in the framework.
pub mod events {
use cfg_if::cfg_if;

pub use crate::html::{ChangeData, InputData};

#[cfg(feature = "std_web")]
pub use stdweb::web::event::{
BlurEvent, ClickEvent, ContextMenuEvent, DoubleClickEvent, DragDropEvent, DragEndEvent,
DragEnterEvent, DragEvent, DragExitEvent, DragLeaveEvent, DragOverEvent, DragStartEvent,
FocusEvent, GotPointerCaptureEvent, IKeyboardEvent, IMouseEvent, IPointerEvent,
KeyDownEvent, KeyPressEvent, KeyUpEvent, LostPointerCaptureEvent, MouseDownEvent,
MouseEnterEvent, MouseLeaveEvent, MouseMoveEvent, MouseOutEvent, MouseOverEvent,
MouseUpEvent, MouseWheelEvent, PointerCancelEvent, PointerDownEvent, PointerEnterEvent,
PointerLeaveEvent, PointerMoveEvent, PointerOutEvent, PointerOverEvent, PointerUpEvent,
ScrollEvent, SubmitEvent, TouchCancel, TouchEnd, TouchEnter, TouchMove, TouchStart,
};
#[cfg(feature = "web_sys")]
pub use web_sys::{
DragEvent, Event, FocusEvent, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent, UiEvent,
WheelEvent,
};
cfg_if! {
if #[cfg(feature = "std_web")] {
pub use stdweb::web::event::{
BlurEvent, ClickEvent, ContextMenuEvent, DoubleClickEvent, DragDropEvent, DragEndEvent,
DragEnterEvent, DragEvent, DragExitEvent, DragLeaveEvent, DragOverEvent, DragStartEvent,
FocusEvent, GotPointerCaptureEvent, IKeyboardEvent, IMouseEvent, IPointerEvent,
KeyDownEvent, KeyPressEvent, KeyUpEvent, LostPointerCaptureEvent, MouseDownEvent,
MouseEnterEvent, MouseLeaveEvent, MouseMoveEvent, MouseOutEvent, MouseOverEvent,
MouseUpEvent, MouseWheelEvent, PointerCancelEvent, PointerDownEvent, PointerEnterEvent,
PointerLeaveEvent, PointerMoveEvent, PointerOutEvent, PointerOverEvent, PointerUpEvent,
ScrollEvent, SubmitEvent, TouchCancel, TouchEnd, TouchEnter, TouchMove, TouchStart,
};
} else if #[cfg(feature = "web_sys")] {
pub use web_sys::{
DragEvent, Event, FocusEvent, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent, UiEvent,
WheelEvent,
};
}
}
}

use cfg_match::cfg_match;

/// Initializes yew framework. It should be called first.
pub fn initialize() {
#[cfg(feature = "std_web")]
stdweb::initialize();
#[cfg(feature = "web_sys")]
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
cfg_match! {
feature = "std_web" => stdweb::initialize(),
feature = "web_sys" => std::panic::set_hook(Box::new(console_error_panic_hook::hook)),
};
}

/// Starts event loop.
Expand Down
Loading

0 comments on commit 3b3fa96

Please sign in to comment.