@@ -5,12 +5,12 @@ use std::rc::Rc;
55
66use dodrio::{
77 bumpalo::{self, Bump},
8− Attribute, Node, NodeKey, Render, RenderContext,
8+ Attribute, Listener, Node, NodeKey, Render, RenderContext, RootRender, VdomWeak,
99};
1010use nock::{
1111 cue::cue_bytes,
1212 interpreter::{generate_interpreter_context, slam},
13− noun::Noun,
13+ noun::{cell, Noun},
1414};
1515use wasm_bindgen::prelude::*;
1616use wasm_bindgen_futures::JsFuture;
@@ -26,19 +26,25 @@ extern "C" {
2626
2727struct WockApp {
2828 nock: Rc<Noun>,
29+ model: Rc<Noun>,
2930}
3031
3132impl<'a> Render<'a> for WockApp {
3233 fn render(&self, cx: &mut dodrio::RenderContext<'a>) -> dodrio::Node<'a> {
3334 let mut ctx = generate_interpreter_context();
3435
35− let sail = slam(&mut ctx, &self.nock, &Rc::new(Noun::from_u32(0))).unwrap();
36+ let sail = slam(
37+ &mut ctx,
38+ &self.nock,
39+ &cell(&Rc::new(Noun::from_bytes(b"view")), &self.model),
40+ )
41+ .unwrap();
3642
37− render_sail(cx, &sail)
43+ render_sail(cx, sail)
3844 }
3945}
4046
41−fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: &Rc<Noun>) -> Node<'a> {
47+fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: Rc<Noun>) -> Node<'a> {
4248 let (marx, marl) = manx.as_cell().unwrap();
4349 let (mane, mart) = marx.as_cell().unwrap();
4450
@@ -53,21 +59,51 @@ fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: &Rc<Noun>) -> Node<'a> {
5359 } else {
5460 let mut children = bumpalo::collections::Vec::new_in(&ctx.bump);
5561 marl.list_iter()
56− .map(|child| render_sail(ctx, child))
62+ .map(|child| render_sail(ctx, child.clone()))
5763 .collect_into(&mut children);
5864
5965 let mut attributes = bumpalo::collections::Vec::new_in(ctx.bump);
60− mart.list_iter()
61− .map(|attr| {
62− let (name, value) = attr.as_cell().unwrap();
63− Attribute {
66+ let mut listeners = bumpalo::collections::Vec::new_in(ctx.bump);
67+
68+ mart.list_iter().for_each(|attr| {
69+ let (name, value) = attr.as_cell().unwrap();
70+ match &*name.as_bytes().unwrap() {
71+ b"on-click" => listeners.push(Listener {
72+ event: "click",
73+ callback: {
74+ let value = value.clone();
75+ ctx.bump.alloc(
76+ move |root: &mut dyn RootRender,
77+ vdom: VdomWeak,
78+ _event: web_sys::Event| {
79+ let mut ctx = generate_interpreter_context();
80+ let sig = ctx.nouns.sig.clone();
81+
82+ let app = root.unwrap_mut::<WockApp>();
83+
84+ let new_model = slam(
85+ &mut ctx,
86+ &app.nock,
87+ &cell(
88+ &Rc::new(Noun::from_bytes(b"move")),
89+ &cell(&app.model, &cell(&value, &sig)),
90+ ),
91+ )
92+ .unwrap();
93+
94+ app.model = new_model;
95+
96+ vdom.schedule_render();
97+ },
98+ )
99+ },
100+ }),
101+ _ => attributes.push(Attribute {
64102 name: cord_to_bump_str(ctx.bump, name),
65− value: cord_to_bump_str(ctx.bump, value),
66− }
67− })
68− .collect_into(&mut attributes);
69−
70− let listeners = bumpalo::collections::Vec::new_in(ctx.bump);
103+ value: tape_to_bump_str(ctx.bump, value),
104+ }),
105+ };
106+ });
71107
72108 Node::element(
73109 &ctx.bump,
@@ -106,7 +142,16 @@ pub async fn main(path: &str) {
106142 let document = gloo::utils::document();
107143 let output_el: Element = document.get_element_by_id("output").unwrap();
108144
109− dodrio::Vdom::new(&output_el, WockApp { nock }).forget();
145+ let mut ctx = generate_interpreter_context();
146+
147+ let model = slam(
148+ &mut ctx,
149+ &nock,
150+ &cell(&Rc::new(Noun::from_bytes(b"init")), &Rc::new(Noun::SIG)),
151+ )
152+ .unwrap();
153+
154+ dodrio::Vdom::new(&output_el, WockApp { nock, model }).forget();
110155}
111156
112157pub async fn load_nock(path: &str) -> Rc<Noun> {