Rsx children scope placing

This commit is contained in:
2026-01-30 23:13:05 +01:00
parent 74e33fa4c2
commit e31c17ba41
4 changed files with 46 additions and 12 deletions
+5 -1
View File
@@ -17,5 +17,9 @@ fn App(cx: &Arc<Context>) -> View {
#[component] #[component]
fn MyComponent(cx: &Arc<Context>, children: &Rsx) -> View { fn MyComponent(cx: &Arc<Context>, children: &Rsx) -> View {
children.view(&cx) rsx! {
"Simple"
@{children}
}
.view(&cx)
} }
+8
View File
@@ -118,6 +118,10 @@ fn emit_node_scope(node: &RsxNode) -> TokenStream {
} }
} }
} }
RsxNode::Expr(expr) => quote! {
r.child(#expr);
},
} }
} }
@@ -169,5 +173,9 @@ fn emit_node(node: &RsxNode) -> TokenStream {
RsxNode::If { .. } => panic!("Invalid if statement"), RsxNode::If { .. } => panic!("Invalid if statement"),
RsxNode::For { .. } => panic!("Invalid for loop"), RsxNode::For { .. } => panic!("Invalid for loop"),
RsxNode::Expr(expr) => quote! {
r.child(#expr);
},
} }
} }
+13 -7
View File
@@ -27,7 +27,7 @@ pub struct RsxProp {
pub enum RsxNode { pub enum RsxNode {
Text(LitStr), Text(LitStr),
/// Component with optional props and children: `Path { prop: expr, "child", ... }` or bare `Path`. Expr(Expr),
Component { Component {
path: Path, path: Path,
props: Vec<RsxProp>, props: Vec<RsxProp>,
@@ -82,6 +82,18 @@ fn parse_deps(input: ParseStream) -> Result<Vec<Dep>> {
impl Parse for RsxNode { impl Parse for RsxNode {
fn parse(input: ParseStream) -> Result<Self> { fn parse(input: ParseStream) -> Result<Self> {
// --- @{ expr } ---
if input.peek(Token![@]) {
input.parse::<Token![@]>()?;
let content;
braced!(content in input);
let expr: Expr = content.parse()?;
return Ok(RsxNode::Expr(expr));
}
// --- existing code ---
if input.peek(Token![!]) { if input.peek(Token![!]) {
input.parse::<Token![!]>()?; input.parse::<Token![!]>()?;
let mount: Ident = input.parse()?; let mount: Ident = input.parse()?;
@@ -93,10 +105,8 @@ impl Parse for RsxNode {
if input.peek(Token![if]) { if input.peek(Token![if]) {
input.parse::<Token![if]>()?; input.parse::<Token![if]>()?;
let cond: Expr = input.parse()?; let cond: Expr = input.parse()?;
let content; let content;
braced!(content in input); braced!(content in input);
let children = parse_children(&content)?; let children = parse_children(&content)?;
return Ok(RsxNode::If { return Ok(RsxNode::If {
deps, deps,
@@ -107,14 +117,11 @@ impl Parse for RsxNode {
if input.peek(Token![for]) { if input.peek(Token![for]) {
input.parse::<Token![for]>()?; input.parse::<Token![for]>()?;
// Parse a possibly multi-pattern (e.g. with `|`) for the `for` binding.
let pat: Pat = Pat::parse_multi(input)?; let pat: Pat = Pat::parse_multi(input)?;
input.parse::<Token![in]>()?; input.parse::<Token![in]>()?;
let expr: Expr = input.parse()?; let expr: Expr = input.parse()?;
let content; let content;
braced!(content in input); braced!(content in input);
let children = parse_children(&content)?; let children = parse_children(&content)?;
return Ok(RsxNode::For { return Ok(RsxNode::For {
deps, deps,
@@ -128,7 +135,6 @@ impl Parse for RsxNode {
return Ok(RsxNode::Text(input.parse()?)); return Ok(RsxNode::Text(input.parse()?));
} }
// Component: Path or Path { props, children }
parse_component_invocation(input) parse_component_invocation(input)
} }
} }
+20 -4
View File
@@ -6,15 +6,21 @@ use crate::{
View, View,
}; };
pub trait ToRsx {
fn to_rsx(&self) -> Rsx;
}
#[derive(Clone)]
pub enum RsxScope { pub enum RsxScope {
Static(Box<dyn Fn(&Arc<Scope>) + Send + Sync>), Static(Arc<dyn Fn(&Arc<Scope>) + Send + Sync>),
Dynamic( Dynamic(
Arc<dyn Fn(&Arc<Scope>) + Send + Sync>, Arc<dyn Fn(&Arc<Scope>) + Send + Sync>,
Vec<Box<dyn HookDependency>>, Vec<Arc<dyn HookDependency>>,
), ),
Child(Rsx), Child(Rsx),
} }
#[derive(Clone)]
pub struct Rsx(Vec<RsxScope>); pub struct Rsx(Vec<RsxScope>);
impl Rsx { impl Rsx {
@@ -23,18 +29,22 @@ impl Rsx {
} }
pub fn static_scope<F: Fn(&Arc<Scope>) + Send + Sync + 'static>(&mut self, scope: F) { pub fn static_scope<F: Fn(&Arc<Scope>) + Send + Sync + 'static>(&mut self, scope: F) {
self.0.push(RsxScope::Static(Box::new(scope))); self.0.push(RsxScope::Static(Arc::new(scope)));
} }
pub fn dynamic_scope<F: Fn(&Arc<Scope>) + Send + Sync + 'static>( pub fn dynamic_scope<F: Fn(&Arc<Scope>) + Send + Sync + 'static>(
&mut self, &mut self,
drawer: F, drawer: F,
dependencies: Vec<Box<dyn HookDependency>>, dependencies: Vec<Arc<dyn HookDependency>>,
) { ) {
self.0 self.0
.push(RsxScope::Dynamic(Arc::new(drawer), dependencies)); .push(RsxScope::Dynamic(Arc::new(drawer), dependencies));
} }
pub fn child<R: ToRsx>(&mut self, child: R) {
self.0.push(RsxScope::Child(child.to_rsx()));
}
pub fn generate_children(&self, context: &Arc<Context>) { pub fn generate_children(&self, context: &Arc<Context>) {
let executor = context.get_executor(); let executor = context.get_executor();
@@ -69,3 +79,9 @@ impl Rsx {
}) })
} }
} }
impl ToRsx for &Rsx {
fn to_rsx(&self) -> Rsx {
Rsx(self.0.clone())
}
}