diff --git a/lua/u/renderer.lua b/lua/u/renderer.lua index 181f02c..4e002b2 100644 --- a/lua/u/renderer.lua +++ b/lua/u/renderer.lua @@ -86,7 +86,7 @@ M.Renderer = Renderer --- component?: (fun(component: u.renderer.FnComponent, tag: u.renderer.Tag): any), --- unknown?: fun(tag: any): any --- } -function Renderer.tree_match(tree, visitors)-- {{{ +function Renderer.tree_match(tree, visitors) -- {{{ local function is_tag(x) return type(x) == 'table' and x.kind == 'tag' end local function is_tag_arr(x) return type(x) == 'table' and not is_tag(x) end @@ -108,7 +108,7 @@ function Renderer.tree_match(tree, visitors)-- {{{ else return visitors.unknown and visitors.unknown(tree) or error 'unknown value: not a tag' end -end-- }}} +end -- }}} --- @private --- @param tree u.renderer.Tree @@ -788,15 +788,15 @@ function Renderer:mount(tree) -- {{{ or nil if old_tree_kind == new_tree_kind then self.component_tree.ctx_by_node[old_tree] = nil end - --- @param new_tree u.renderer.Tree --- @param ctx u.renderer.FnComponentContext --- @param rendered_component u.renderer.Tree - local function update_ctx_and_recurse(new_tree, ctx, rendered_component) + local function update_ctx_and_recurse(ctx, rendered_component) self.component_tree.ctx_by_node[new_tree] = ctx -- The rendered component could have other components in its tree: -- recurse and simplify: - local new_tree_simplified = H2.visit_tree(ctx.prev_tree, rendered_component) - ctx.prev_tree = new_tree_simplified + local new_tree_simplified = + M.h('text', ctx.props, H2.visit_tree(ctx.prev_tree, rendered_component)) + ctx.prev_tree = rendered_component return new_tree_simplified end @@ -804,13 +804,13 @@ function Renderer:mount(tree) -- {{{ old_ctx.phase = 'update' old_ctx.props = new_tag.attributes old_ctx.children = new_tag.children - return update_ctx_and_recurse(new_tree, old_ctx, NewC(old_ctx)) + return update_ctx_and_recurse(old_ctx, NewC(old_ctx)) else local state = tracker.create_signal(nil) --- @type u.renderer.FnComponentContext local ctx = { - phase = old_tree and 'update' or 'mount', + phase = 'mount', props = new_tag.attributes, children = new_tag.children, state = state --[[@as any]], @@ -822,7 +822,7 @@ function Renderer:mount(tree) -- {{{ -- first-renders to initialize the state without firing a -- re-render: ctx.unsubscribe = state:subscribe(render) - return update_ctx_and_recurse(new_tree, ctx, rendered) + return update_ctx_and_recurse(ctx, rendered) end end, }) @@ -836,29 +836,33 @@ function Renderer:mount(tree) -- {{{ --- @param new_arr u.renderer.Node[] --- @return u.renderer.Node[] function H2.visit_array(old_arr, new_arr) - --- @type u.renderer.Node[] - local old_to_unmount = {} --- @type table local old_by_key = {} - for _, old in ipairs(old_arr or {}) do - local key = Renderer.tree_match(old, { - tag = function(t) return t.attributes.key end, - component = function(_, t) return t.attributes.key end, + + --- @param tree u.renderer.Tree + --- @param idx integer + local function get_or_set_key(tree, idx) + return Renderer.tree_match(tree, { + tag = function(t) + if not t.attributes.key then t.attributes.key = idx end + return t.attributes.key + end, + component = function(_, t) + if not t.attributes.key then t.attributes.key = idx end + return t.attributes.key + end, }) - if not key then - table.insert(old_to_unmount, old) - else - old_by_key[key] = old - end + end + + for idx, old in ipairs(old_arr or {}) do + local key = get_or_set_key(old, idx) + if key then old_by_key[key] = old end end --- @type u.renderer.Node[] local resulting_nodes = {} - for _, new in ipairs(new_arr) do - local key = Renderer.tree_match(new, { - tag = function(t) return t.attributes.key end, - component = function(_, t) return t.attributes.key end, - }) + for idx, new in ipairs(new_arr) do + local key = get_or_set_key(new, idx) local old = nil if key then old = old_by_key[key] @@ -867,10 +871,8 @@ function Renderer:mount(tree) -- {{{ table.insert(resulting_nodes, H2.visit_tree(old, new)) end + -- Unmount whatever is left in the "old" map: for _, n in pairs(old_by_key) do - table.insert(old_to_unmount, n) - end - for _, n in pairs(old_to_unmount) do H2.unmount(n) end