fix autofmt: don't panic when writing blocks out without a srcfile (#2854)
* fix: don't panic when writing blocks out * also fix serialization for hotreload * fix windows line endings
This commit is contained in:
1 parent
b47a6cf83e
commit
4963aa3118
9 files changed
+142
-46
No files matched your search
@@ -93,7 +93,7 @@ pub fn try_fmt_file(
|
|||||||
writer.out.indent_level = writer
|
writer.out.indent_level = writer
|
||||||
.out
|
.out
|
||||||
.indent
|
.indent
|
||||||
.count_indents(writer.src[rsx_start.line - 1]);
|
.count_indents(writer.src.get(rsx_start.line - 1).unwrap_or(&""));
|
||||||
|
|
||||||
// TESTME
|
// TESTME
|
||||||
// Writing *should* not fail but it's possible that it does
|
// Writing *should* not fail but it's possible that it does
|
||||||
|
|||||||
@@ -607,7 +607,11 @@ impl<'a> Writer<'a> {
|
|||||||
|
|
||||||
let mut comments = VecDeque::new();
|
let mut comments = VecDeque::new();
|
||||||
|
|
||||||
for (id, line) in self.src[..line_start].iter().enumerate().rev() {
|
let Some(lines) = self.src.get(..line_start) else {
|
||||||
|
return comments;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (id, line) in lines.iter().enumerate().rev() {
|
||||||
if line.trim().starts_with("//") || line.is_empty() && id != 0 {
|
if line.trim().starts_with("//") || line.is_empty() && id != 0 {
|
||||||
if id != 0 {
|
if id != 0 {
|
||||||
comments.push_front(id);
|
comments.push_front(id);
|
||||||
@@ -621,7 +625,11 @@ impl<'a> Writer<'a> {
|
|||||||
}
|
}
|
||||||
fn apply_comments(&mut self, mut comments: VecDeque<usize>) -> Result {
|
fn apply_comments(&mut self, mut comments: VecDeque<usize>) -> Result {
|
||||||
while let Some(comment_line) = comments.pop_front() {
|
while let Some(comment_line) = comments.pop_front() {
|
||||||
let line = &self.src[comment_line].trim();
|
let Some(line) = self.src.get(comment_line) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let line = &line.trim();
|
||||||
|
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
self.out.new_line()?;
|
self.out.new_line()?;
|
||||||
@@ -690,13 +698,15 @@ impl<'a> Writer<'a> {
|
|||||||
|
|
||||||
for attr in attributes {
|
for attr in attributes {
|
||||||
if self.current_span_is_primary(attr.span().start()) {
|
if self.current_span_is_primary(attr.span().start()) {
|
||||||
'line: for line in self.src[..attr.span().start().line - 1].iter().rev() {
|
if let Some(lines) = self.src.get(..attr.span().start().line - 1) {
|
||||||
match (line.trim().starts_with("//"), line.is_empty()) {
|
'line: for line in lines.iter().rev() {
|
||||||
(true, _) => return 100000,
|
match (line.trim().starts_with("//"), line.is_empty()) {
|
||||||
(_, true) => continue 'line,
|
(true, _) => return 100000,
|
||||||
_ => break 'line,
|
(_, true) => continue 'line,
|
||||||
|
_ => break 'line,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let name_len = match &attr.name {
|
let name_len = match &attr.name {
|
||||||
@@ -738,7 +748,9 @@ impl<'a> Writer<'a> {
|
|||||||
writeln!(self.out)?;
|
writeln!(self.out)?;
|
||||||
|
|
||||||
for idx in start.line..end.line {
|
for idx in start.line..end.line {
|
||||||
let line = &self.src[idx];
|
let Some(line) = self.src.get(idx) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if line.trim().starts_with("//") {
|
if line.trim().starts_with("//") {
|
||||||
for _ in 0..self.out.indent_level + 1 {
|
for _ in 0..self.out.indent_level + 1 {
|
||||||
write!(self.out, " ")?
|
write!(self.out, " ")?
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
use dioxus_rsx::CallBody;
|
||||||
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
|
|
||||||
|
/// Ensure we can write RSX blocks without a source file
|
||||||
|
///
|
||||||
|
/// Useful in code generation use cases where we still want formatted code.
|
||||||
|
#[test]
|
||||||
|
fn write_block_out() {
|
||||||
|
let src = include_str!("./srcless/basic_expr.rsx");
|
||||||
|
|
||||||
|
let tokens: TokenStream2 = syn::parse_str(src).unwrap();
|
||||||
|
let parsed: CallBody = syn::parse2(tokens).unwrap();
|
||||||
|
|
||||||
|
let block = dioxus_autofmt::write_block_out(&parsed).unwrap();
|
||||||
|
|
||||||
|
// normalize line endings for windows tests to pass
|
||||||
|
pretty_assertions::assert_eq!(
|
||||||
|
block.trim().lines().collect::<Vec<_>>().join("\n"),
|
||||||
|
src.trim().lines().collect::<Vec<_>>().join("\n")
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
div {
|
||||||
|
"hi"
|
||||||
|
{children}
|
||||||
|
}
|
||||||
|
Fragment {
|
||||||
|
Fragment {
|
||||||
|
Fragment {
|
||||||
|
Fragment {
|
||||||
|
Fragment {
|
||||||
|
div { "Finally have a real node!" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div { class, "hello world" }
|
||||||
|
h1 { class, "hello world" }
|
||||||
|
h1 { class, {children} }
|
||||||
|
h1 { class, id, {children} }
|
||||||
|
h1 { class,
|
||||||
|
"hello world"
|
||||||
|
{children}
|
||||||
|
}
|
||||||
|
h1 { id,
|
||||||
|
"hello world"
|
||||||
|
{children}
|
||||||
|
}
|
||||||
|
Other { class, children }
|
||||||
|
Other { class,
|
||||||
|
"hello world"
|
||||||
|
{children}
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
class: "asdasd",
|
||||||
|
onclick: move |_| {
|
||||||
|
let a = 10;
|
||||||
|
let b = 40;
|
||||||
|
let c = 50;
|
||||||
|
},
|
||||||
|
"hi"
|
||||||
|
}
|
||||||
|
div { class: "asd", "Jon" }
|
||||||
@@ -10,7 +10,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct HotreloadedLiteral {
|
pub struct HotreloadedLiteral {
|
||||||
@@ -19,7 +18,6 @@ pub struct HotreloadedLiteral {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum HotReloadLiteral {
|
pub enum HotReloadLiteral {
|
||||||
@@ -71,7 +69,6 @@ impl Hash for HotReloadLiteral {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
pub struct FmtedSegments {
|
pub struct FmtedSegments {
|
||||||
@@ -98,6 +95,8 @@ impl FmtedSegments {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StaticStr = &'static str;
|
||||||
|
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
@@ -107,7 +106,7 @@ pub enum FmtSegment {
|
|||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
serde(deserialize_with = "deserialize_string_leaky")
|
serde(deserialize_with = "deserialize_string_leaky")
|
||||||
)]
|
)]
|
||||||
value: &'static str,
|
value: StaticStr,
|
||||||
},
|
},
|
||||||
Dynamic {
|
Dynamic {
|
||||||
id: usize,
|
id: usize,
|
||||||
@@ -313,16 +312,16 @@ impl DynamicValuePool {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
pub struct HotReloadTemplateWithLocation {
|
pub struct HotReloadTemplateWithLocation {
|
||||||
pub location: String,
|
pub location: String,
|
||||||
pub template: HotReloadedTemplate,
|
pub template: HotReloadedTemplate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StaticTemplateArray = &'static [TemplateNode];
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
pub struct HotReloadedTemplate {
|
pub struct HotReloadedTemplate {
|
||||||
pub key: Option<FmtedSegments>,
|
pub key: Option<FmtedSegments>,
|
||||||
pub dynamic_nodes: Vec<HotReloadDynamicNode>,
|
pub dynamic_nodes: Vec<HotReloadDynamicNode>,
|
||||||
@@ -332,7 +331,7 @@ pub struct HotReloadedTemplate {
|
|||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
serde(deserialize_with = "crate::nodes::deserialize_leaky")
|
serde(deserialize_with = "crate::nodes::deserialize_leaky")
|
||||||
)]
|
)]
|
||||||
pub roots: &'static [TemplateNode],
|
pub roots: StaticTemplateArray,
|
||||||
/// The template that is computed from the hot reload roots
|
/// The template that is computed from the hot reload roots
|
||||||
template: Template,
|
template: Template,
|
||||||
}
|
}
|
||||||
@@ -425,7 +424,6 @@ impl HotReloadedTemplate {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, PartialEq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
pub enum HotReloadDynamicNode {
|
pub enum HotReloadDynamicNode {
|
||||||
Dynamic(usize),
|
Dynamic(usize),
|
||||||
Formatted(FmtedSegments),
|
Formatted(FmtedSegments),
|
||||||
@@ -434,7 +432,6 @@ pub enum HotReloadDynamicNode {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, PartialEq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
pub enum HotReloadDynamicAttribute {
|
pub enum HotReloadDynamicAttribute {
|
||||||
Dynamic(usize),
|
Dynamic(usize),
|
||||||
Named(NamedAttribute),
|
Named(NamedAttribute),
|
||||||
@@ -449,13 +446,13 @@ pub struct NamedAttribute {
|
|||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
serde(deserialize_with = "crate::nodes::deserialize_string_leaky")
|
serde(deserialize_with = "crate::nodes::deserialize_string_leaky")
|
||||||
)]
|
)]
|
||||||
name: &'static str,
|
name: StaticStr,
|
||||||
/// The namespace of this attribute. Does not exist in the HTML spec
|
/// The namespace of this attribute. Does not exist in the HTML spec
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
serde(deserialize_with = "crate::nodes::deserialize_option_leaky")
|
serde(deserialize_with = "crate::nodes::deserialize_option_leaky")
|
||||||
)]
|
)]
|
||||||
namespace: Option<&'static str>,
|
namespace: Option<StaticStr>,
|
||||||
|
|
||||||
value: HotReloadAttributeValue,
|
value: HotReloadAttributeValue,
|
||||||
}
|
}
|
||||||
@@ -477,7 +474,6 @@ impl NamedAttribute {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, PartialEq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
pub enum HotReloadAttributeValue {
|
pub enum HotReloadAttributeValue {
|
||||||
Literal(HotReloadLiteral),
|
Literal(HotReloadLiteral),
|
||||||
Dynamic(usize),
|
Dynamic(usize),
|
||||||
|
|||||||
+45
-18
@@ -288,6 +288,11 @@ impl VNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StaticStr = &'static str;
|
||||||
|
type StaticPathArray = &'static [&'static [u8]];
|
||||||
|
type StaticTemplateArray = &'static [TemplateNode];
|
||||||
|
type StaticTemplateAttributeArray = &'static [TemplateAttribute];
|
||||||
|
|
||||||
/// A static layout of a UI tree that describes a set of dynamic and static nodes.
|
/// A static layout of a UI tree that describes a set of dynamic and static nodes.
|
||||||
///
|
///
|
||||||
/// This is the core innovation in Dioxus. Most UIs are made of static nodes, yet participate in diffing like any
|
/// This is the core innovation in Dioxus. Most UIs are made of static nodes, yet participate in diffing like any
|
||||||
@@ -297,14 +302,13 @@ impl VNode {
|
|||||||
/// For this to work properly, the [`Template::name`] *must* be unique across your entire project. This can be done via variety of
|
/// For this to work properly, the [`Template::name`] *must* be unique across your entire project. This can be done via variety of
|
||||||
/// ways, with the suggested approach being the unique code location (file, line, col, etc).
|
/// ways, with the suggested approach being the unique code location (file, line, col, etc).
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "serialize", serde(bound(deserialize = "'de: 'static")))]
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, Eq, PartialOrd, Ord)]
|
||||||
pub struct Template {
|
pub struct Template {
|
||||||
/// The list of template nodes that make up the template
|
/// The list of template nodes that make up the template
|
||||||
///
|
///
|
||||||
/// Unlike react, calls to `rsx!` can have multiple roots. This list supports that paradigm.
|
/// Unlike react, calls to `rsx!` can have multiple roots. This list supports that paradigm.
|
||||||
#[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
|
#[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
|
||||||
pub roots: &'static [TemplateNode],
|
pub roots: StaticTemplateArray,
|
||||||
|
|
||||||
/// The paths of each node relative to the root of the template.
|
/// The paths of each node relative to the root of the template.
|
||||||
///
|
///
|
||||||
@@ -314,7 +318,7 @@ pub struct Template {
|
|||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
serde(deserialize_with = "deserialize_bytes_leaky")
|
serde(deserialize_with = "deserialize_bytes_leaky")
|
||||||
)]
|
)]
|
||||||
pub node_paths: &'static [&'static [u8]],
|
pub node_paths: StaticPathArray,
|
||||||
|
|
||||||
/// The paths of each dynamic attribute relative to the root of the template
|
/// The paths of each dynamic attribute relative to the root of the template
|
||||||
///
|
///
|
||||||
@@ -322,9 +326,9 @@ pub struct Template {
|
|||||||
/// topmost element, not the `roots` field.
|
/// topmost element, not the `roots` field.
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
serde(deserialize_with = "deserialize_bytes_leaky")
|
serde(deserialize_with = "deserialize_bytes_leaky", bound = "")
|
||||||
)]
|
)]
|
||||||
pub attr_paths: &'static [&'static [u8]],
|
pub attr_paths: StaticPathArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::hash::Hash for Template {
|
impl std::hash::Hash for Template {
|
||||||
@@ -344,7 +348,9 @@ impl PartialEq for Template {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
pub(crate) fn deserialize_string_leaky<'a, 'de, D>(deserializer: D) -> Result<&'a str, D::Error>
|
pub(crate) fn deserialize_string_leaky<'a, 'de, D>(
|
||||||
|
deserializer: D,
|
||||||
|
) -> Result<&'static str, D::Error>
|
||||||
where
|
where
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
@@ -355,7 +361,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
fn deserialize_bytes_leaky<'a, 'de, D>(deserializer: D) -> Result<&'a [&'a [u8]], D::Error>
|
fn deserialize_bytes_leaky<'a, 'de, D>(
|
||||||
|
deserializer: D,
|
||||||
|
) -> Result<&'static [&'static [u8]], D::Error>
|
||||||
where
|
where
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
@@ -370,7 +378,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
pub(crate) fn deserialize_leaky<'a, 'de, T, D>(deserializer: D) -> Result<&'a [T], D::Error>
|
pub(crate) fn deserialize_leaky<'a, 'de, T, D>(deserializer: D) -> Result<&'static [T], D::Error>
|
||||||
where
|
where
|
||||||
T: serde::Deserialize<'de>,
|
T: serde::Deserialize<'de>,
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
@@ -421,7 +429,11 @@ pub enum TemplateNode {
|
|||||||
/// The name of the element
|
/// The name of the element
|
||||||
///
|
///
|
||||||
/// IE for a div, it would be the string "div"
|
/// IE for a div, it would be the string "div"
|
||||||
tag: &'static str,
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
serde(deserialize_with = "deserialize_string_leaky")
|
||||||
|
)]
|
||||||
|
tag: StaticStr,
|
||||||
|
|
||||||
/// The namespace of the element
|
/// The namespace of the element
|
||||||
///
|
///
|
||||||
@@ -431,17 +443,20 @@ pub enum TemplateNode {
|
|||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
serde(deserialize_with = "deserialize_option_leaky")
|
serde(deserialize_with = "deserialize_option_leaky")
|
||||||
)]
|
)]
|
||||||
namespace: Option<&'static str>,
|
namespace: Option<StaticStr>,
|
||||||
|
|
||||||
/// A list of possibly dynamic attributes for this element
|
/// A list of possibly dynamic attributes for this element
|
||||||
///
|
///
|
||||||
/// An attribute on a DOM node, such as `id="my-thing"` or `href="https://example.com"`.
|
/// An attribute on a DOM node, such as `id="my-thing"` or `href="https://example.com"`.
|
||||||
#[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
|
#[cfg_attr(
|
||||||
attrs: &'static [TemplateAttribute],
|
feature = "serialize",
|
||||||
|
serde(deserialize_with = "deserialize_leaky", bound = "")
|
||||||
|
)]
|
||||||
|
attrs: StaticTemplateAttributeArray,
|
||||||
|
|
||||||
/// A list of template nodes that define another set of template nodes
|
/// A list of template nodes that define another set of template nodes
|
||||||
#[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
|
#[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
|
||||||
children: &'static [TemplateNode],
|
children: StaticTemplateArray,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// This template node is just a piece of static text
|
/// This template node is just a piece of static text
|
||||||
@@ -449,9 +464,9 @@ pub enum TemplateNode {
|
|||||||
/// The actual text
|
/// The actual text
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serialize",
|
feature = "serialize",
|
||||||
serde(deserialize_with = "deserialize_string_leaky")
|
serde(deserialize_with = "deserialize_string_leaky", bound = "")
|
||||||
)]
|
)]
|
||||||
text: &'static str,
|
text: StaticStr,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// This template node is unknown, and needs to be created at runtime.
|
/// This template node is unknown, and needs to be created at runtime.
|
||||||
@@ -652,15 +667,27 @@ pub enum TemplateAttribute {
|
|||||||
/// The name of this attribute.
|
/// The name of this attribute.
|
||||||
///
|
///
|
||||||
/// For example, the `href` attribute in `href="https://example.com"`, would have the name "href"
|
/// For example, the `href` attribute in `href="https://example.com"`, would have the name "href"
|
||||||
name: &'static str,
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
serde(deserialize_with = "deserialize_string_leaky", bound = "")
|
||||||
|
)]
|
||||||
|
name: StaticStr,
|
||||||
|
|
||||||
/// The value of this attribute, known at compile time
|
/// The value of this attribute, known at compile time
|
||||||
///
|
///
|
||||||
/// Currently this only accepts &str, so values, even if they're known at compile time, are not known
|
/// Currently this only accepts &str, so values, even if they're known at compile time, are not known
|
||||||
value: &'static str,
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
serde(deserialize_with = "deserialize_string_leaky", bound = "")
|
||||||
|
)]
|
||||||
|
value: StaticStr,
|
||||||
|
|
||||||
/// The namespace of this attribute. Does not exist in the HTML spec
|
/// The namespace of this attribute. Does not exist in the HTML spec
|
||||||
namespace: Option<&'static str>,
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
serde(deserialize_with = "deserialize_option_leaky", bound = "")
|
||||||
|
)]
|
||||||
|
namespace: Option<StaticStr>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The attribute in this position is actually determined dynamically at runtime
|
/// The attribute in this position is actually determined dynamically at runtime
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ pub use ws_receiver::*;
|
|||||||
|
|
||||||
/// A message the hot reloading server sends to the client
|
/// A message the hot reloading server sends to the client
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
#[serde(bound(deserialize = "'de: 'static"))]
|
|
||||||
pub enum DevserverMsg {
|
pub enum DevserverMsg {
|
||||||
/// Attempt a hotreload
|
/// Attempt a hotreload
|
||||||
/// This includes all the templates/literals/assets/binary patches that have changed in one shot
|
/// This includes all the templates/literals/assets/binary patches that have changed in one shot
|
||||||
@@ -47,7 +46,6 @@ pub enum ClientMsg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
#[serde(bound(deserialize = "'de: 'static"))]
|
|
||||||
pub struct HotReloadMsg {
|
pub struct HotReloadMsg {
|
||||||
pub templates: Vec<HotReloadTemplateWithLocation>,
|
pub templates: Vec<HotReloadTemplateWithLocation>,
|
||||||
pub assets: Vec<PathBuf>,
|
pub assets: Vec<PathBuf>,
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ impl NativeReceiver {
|
|||||||
match res {
|
match res {
|
||||||
Ok(res) => match res {
|
Ok(res) => match res {
|
||||||
Message::Text(text) => {
|
Message::Text(text) => {
|
||||||
let leaked: &'static str = Box::leak(text.into_boxed_str());
|
// let leaked: &'static str = Box::leak(text.into_boxed_str());
|
||||||
let msg = serde_json::from_str::<DevserverMsg>(leaked);
|
let msg = serde_json::from_str::<DevserverMsg>(&text);
|
||||||
if let Ok(msg) = msg {
|
if let Ok(msg) = msg {
|
||||||
return Some(Ok(msg));
|
return Some(Ok(msg));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ fn make_ws(tx: UnboundedSender<HotReloadMsg>, poll_interval: i32, reload: bool)
|
|||||||
|
|
||||||
// The devserver messages have some &'static strs in them, so we need to leak the source string
|
// The devserver messages have some &'static strs in them, so we need to leak the source string
|
||||||
let string: String = text.into();
|
let string: String = text.into();
|
||||||
let leaked: &'static str = Box::leak(Box::new(string));
|
// let leaked: &'static str = Box::leak(Box::new(string));
|
||||||
|
|
||||||
match serde_json::from_str::<DevserverMsg>(leaked) {
|
match serde_json::from_str::<DevserverMsg>(&string) {
|
||||||
Ok(DevserverMsg::HotReload(hr)) => _ = tx_.unbounded_send(hr),
|
Ok(DevserverMsg::HotReload(hr)) => _ = tx_.unbounded_send(hr),
|
||||||
|
|
||||||
// todo: we want to throw a screen here that shows the user that the devserver has disconnected
|
// todo: we want to throw a screen here that shows the user that the devserver has disconnected
|
||||||
|
|||||||
Reference in new issue
Block a user