diff --git a/crates/macro/src/html_tree/html_tag/mod.rs b/crates/macro/src/html_tree/html_tag/mod.rs
index 98a9aa053f4..6db099320ac 100644
--- a/crates/macro/src/html_tree/html_tag/mod.rs
+++ b/crates/macro/src/html_tree/html_tag/mod.rs
@@ -149,7 +149,10 @@ impl ToTokens for HtmlTag {
#vtag.node_ref = #node_ref;
}
});
- let listeners = listeners.iter().map(|(name, callback)| {
+ let listeners = listeners.iter().map(|listener| {
+ let name = &listener.label.name;
+ let callback = &listener.value;
+
quote_spanned! {name.span()=> {
::yew::html::#name::Wrapper::new(
<::yew::virtual_dom::vtag::VTag<_> as ::yew::virtual_dom::Transformer<_, _, _>>::transform(
diff --git a/crates/macro/src/html_tree/html_tag/tag_attributes.rs b/crates/macro/src/html_tree/html_tag/tag_attributes.rs
index 5a6dbb3e933..543b29c693b 100644
--- a/crates/macro/src/html_tree/html_tag/tag_attributes.rs
+++ b/crates/macro/src/html_tree/html_tag/tag_attributes.rs
@@ -1,15 +1,14 @@
use crate::html_tree::HtmlProp as TagAttribute;
use crate::PeekValue;
use lazy_static::lazy_static;
-use proc_macro2::TokenStream;
-use quote::{quote, quote_spanned, ToTokens};
-use std::collections::HashMap;
+use std::collections::HashSet;
+use std::iter::FromIterator;
use syn::parse::{Parse, ParseStream, Result as ParseResult};
-use syn::{Expr, ExprClosure, ExprTuple, Ident, Pat};
+use syn::{Expr, ExprTuple};
pub struct TagAttributes {
pub attributes: Vec,
- pub listeners: Vec<(Ident, TokenStream)>,
+ pub listeners: Vec,
pub classes: Option,
pub value: Option,
pub kind: Option,
@@ -25,75 +24,67 @@ pub enum ClassesForm {
Single(Expr),
}
-pub struct TagListener {
- name: Ident,
- handler: Expr,
- event_name: String,
-}
-
lazy_static! {
- static ref LISTENER_MAP: HashMap<&'static str, &'static str> = {
- let mut m = HashMap::new();
- m.insert("onclick", "ClickEvent");
- m.insert("ondoubleclick", "DoubleClickEvent");
- m.insert("onkeypress", "KeyPressEvent");
- m.insert("onkeydown", "KeyDownEvent");
- m.insert("onkeyup", "KeyUpEvent");
- m.insert("onmousedown", "MouseDownEvent");
- m.insert("onmousemove", "MouseMoveEvent");
- m.insert("onmouseout", "MouseOutEvent");
- m.insert("onmouseenter", "MouseEnterEvent");
- m.insert("onmouseleave", "MouseLeaveEvent");
- m.insert("onmousewheel", "MouseWheelEvent");
- m.insert("onmouseover", "MouseOverEvent");
- m.insert("onmouseup", "MouseUpEvent");
- m.insert("ontouchcancel", "TouchCancel");
- m.insert("ontouchend", "TouchEnd");
- m.insert("ontouchenter", "TouchEnter");
- m.insert("ontouchmove", "TouchMove");
- m.insert("ontouchstart", "TouchStart");
- m.insert("ongotpointercapture", "GotPointerCaptureEvent");
- m.insert("onlostpointercapture", "LostPointerCaptureEvent");
- m.insert("onpointercancel", "PointerCancelEvent");
- m.insert("onpointerdown", "PointerDownEvent");
- m.insert("onpointerenter", "PointerEnterEvent");
- m.insert("onpointerleave", "PointerLeaveEvent");
- m.insert("onpointermove", "PointerMoveEvent");
- m.insert("onpointerout", "PointerOutEvent");
- m.insert("onpointerover", "PointerOverEvent");
- m.insert("onpointerup", "PointerUpEvent");
- m.insert("onscroll", "ScrollEvent");
- m.insert("onblur", "BlurEvent");
- m.insert("onfocus", "FocusEvent");
- m.insert("onsubmit", "SubmitEvent");
- m.insert("oninput", "InputData");
- m.insert("onchange", "ChangeData");
- m.insert("ondrag", "DragEvent");
- m.insert("ondragstart", "DragStartEvent");
- m.insert("ondragend", "DragEndEvent");
- m.insert("ondragenter", "DragEnterEvent");
- m.insert("ondragleave", "DragLeaveEvent");
- m.insert("ondragover", "DragOverEvent");
- m.insert("ondragexit", "DragExitEvent");
- m.insert("ondrop", "DragDropEvent");
- m.insert("oncontextmenu", "ContextMenuEvent");
- m
+ static ref LISTENER_SET: HashSet<&'static str> = {
+ HashSet::from_iter(
+ vec![
+ "onclick",
+ "ondoubleclick",
+ "onkeypress",
+ "onkeydown",
+ "onkeyup",
+ "onmousedown",
+ "onmousemove",
+ "onmouseout",
+ "onmouseenter",
+ "onmouseleave",
+ "onmousewheel",
+ "onmouseover",
+ "onmouseup",
+ "ontouchcancel",
+ "ontouchend",
+ "ontouchenter",
+ "ontouchmove",
+ "ontouchstart",
+ "ongotpointercapture",
+ "onlostpointercapture",
+ "onpointercancel",
+ "onpointerdown",
+ "onpointerenter",
+ "onpointerleave",
+ "onpointermove",
+ "onpointerout",
+ "onpointerover",
+ "onpointerup",
+ "onscroll",
+ "onblur",
+ "onfocus",
+ "onsubmit",
+ "oninput",
+ "onchange",
+ "ondrag",
+ "ondragstart",
+ "ondragend",
+ "ondragenter",
+ "ondragleave",
+ "ondragover",
+ "ondragexit",
+ "ondrop",
+ "oncontextmenu",
+ ]
+ .into_iter(),
+ )
};
}
impl TagAttributes {
- fn drain_listeners(attrs: &mut Vec) -> Vec {
+ fn drain_listeners(attrs: &mut Vec) -> Vec {
let mut i = 0;
let mut drained = Vec::new();
while i < attrs.len() {
let name_str = attrs[i].label.to_string();
- if let Some(event_type) = LISTENER_MAP.get(&name_str.as_str()) {
- let TagAttribute { label, value } = attrs.remove(i);
- drained.push(TagListener {
- name: label.name,
- handler: value,
- event_name: event_type.to_owned().to_string(),
- });
+ if LISTENER_SET.contains(&name_str.as_str()) {
+ drained.push(attrs.remove(i));
} else {
i += 1;
}
@@ -119,54 +110,6 @@ impl TagAttributes {
expr => ClassesForm::Single(expr),
}
}
-
- fn map_listener(listener: TagListener) -> ParseResult<(Ident, TokenStream)> {
- let TagListener {
- name,
- event_name,
- handler,
- } = listener;
-
- let callback: TokenStream = match handler {
- Expr::Closure(closure) => {
- let ExprClosure {
- inputs,
- body,
- or1_token,
- or2_token,
- ..
- } = closure;
-
- let or_span = quote! {#or1_token#or2_token};
- if inputs.len() != 1 {
- return Err(syn::Error::new_spanned(
- or_span,
- "there must be one closure argument",
- ));
- }
-
- let var = match inputs.first().unwrap() {
- Pat::Ident(pat) => Ok(pat.into_token_stream()),
- Pat::Wild(pat) => Ok(pat.into_token_stream()),
- _ => Err(syn::Error::new_spanned(or_span, "invalid closure argument")),
- }?;
- let callback =
- Ident::new(&format!("__yew_{}_callback", name.to_string()), name.span());
- let segment = syn::PathSegment {
- ident: Ident::new(&event_name, name.span()),
- arguments: syn::PathArguments::None,
- };
-
- quote_spanned! {name.span()=> {
- let #callback = move | #var: ::yew::events::#segment | #body;
- #callback
- }}
- }
- callback => callback.into_token_stream(),
- };
-
- Ok((name, callback))
- }
}
impl Parse for TagAttributes {
@@ -178,7 +121,7 @@ impl Parse for TagAttributes {
let mut listeners = Vec::new();
for listener in TagAttributes::drain_listeners(&mut attributes) {
- listeners.push(TagAttributes::map_listener(listener)?);
+ listeners.push(listener);
}
// Multiple listener attributes are allowed, but no others
diff --git a/tests/macro/html-tag-fail.rs b/tests/macro/html-tag-fail.rs
index 2a8bda43215..8a8ebd1d6d1 100644
--- a/tests/macro/html-tag-fail.rs
+++ b/tests/macro/html-tag-fail.rs
@@ -30,9 +30,7 @@ fn compile_fail() {
html! { };
html! { };
- html! { };
- html! { };
- html! { };
+ html! { };
html! { };
diff --git a/tests/macro/html-tag-fail.stderr b/tests/macro/html-tag-fail.stderr
index 147ec3cb66d..969579cd8bd 100644
--- a/tests/macro/html-tag-fail.stderr
+++ b/tests/macro/html-tag-fail.stderr
@@ -102,28 +102,10 @@ error: only one `class` attribute allowed
23 | html! { };
| ^^^^^
-error: there must be one closure argument
- --> $DIR/html-tag-fail.rs:33:28
- |
-33 | html! { };
- | ^^
-
-error: there must be one closure argument
- --> $DIR/html-tag-fail.rs:34:28
- |
-34 | html! { };
- | ^^^^^^
-
-error: invalid closure argument
- --> $DIR/html-tag-fail.rs:35:28
- |
-35 | html! { };
- | ^^^^^^^^^^^
-
error: only one `ref` attribute allowed
- --> $DIR/html-tag-fail.rs:40:27
+ --> $DIR/html-tag-fail.rs:38:27
|
-40 | html! { };
+38 | html! { };
| ^^^
error[E0308]: mismatched types
@@ -193,13 +175,22 @@ error[E0308]: mismatched types
= note: expected type `yew::callback::Callback`
found type `{integer}`
+error[E0308]: mismatched types
+ --> $DIR/html-tag-fail.rs:33:20
+ |
+33 | html! { };
+ | ^^^^^^^ expected struct `stdweb::webapi::events::mouse::ClickEvent`, found struct `std::string::String`
+ |
+ = note: expected type `yew::callback::Callback`
+ found type `yew::callback::Callback`
+
error[E0599]: no method named `to_string` found for type `NotToString` in the current scope
- --> $DIR/html-tag-fail.rs:37:27
+ --> $DIR/html-tag-fail.rs:35:27
|
3 | struct NotToString;
| ------------------- method `to_string` not found for this
...
-37 | html! { };
+35 | html! { };
| ^^^^^^^^^^^ method not found in `NotToString`
|
= note: the method `to_string` exists but the following trait bounds were not satisfied:
@@ -209,9 +200,9 @@ error[E0599]: no method named `to_string` found for type `NotToString` in the cu
candidate #1: `std::string::ToString`
error[E0308]: mismatched types
- --> $DIR/html-tag-fail.rs:39:24
+ --> $DIR/html-tag-fail.rs:37:24
|
-39 | html! { };
+37 | html! { };
| ^^ expected struct `yew::html::NodeRef`, found ()
|
= note: expected type `yew::html::NodeRef`
diff --git a/tests/macro/html-tag-pass.rs b/tests/macro/html-tag-pass.rs
index f660b5f96f9..76ccdd3cf05 100644
--- a/tests/macro/html-tag-pass.rs
+++ b/tests/macro/html-tag-pass.rs
@@ -37,7 +37,6 @@ pass_helper! {
-