From a9f29c4caad4f32d06be1ec4780572825781cd9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Wed, 9 Feb 2022 09:28:24 +0100 Subject: [PATCH] [FIX] refs in recursive templates now work properly --- src/blockdom/block_compiler.ts | 13 ++++----- tests/blockdom/block_refs.test.ts | 13 +++++++++ .../__snapshots__/refs.test.ts.snap | 20 ++++++++++++++ tests/components/refs.test.ts | 27 +++++++++++++++++-- 4 files changed, 65 insertions(+), 8 deletions(-) diff --git a/src/blockdom/block_compiler.ts b/src/blockdom/block_compiler.ts index 226cd003..de128960 100644 --- a/src/blockdom/block_compiler.ts +++ b/src/blockdom/block_compiler.ts @@ -299,7 +299,7 @@ interface BlockCtx { locations: IndexedLocation[]; children: Child[]; cbRefs: number[]; - refList: (() => void)[]; + refList: (() => void)[][]; } function buildContext(tree: IntermediateTree, ctx?: BlockCtx, fromIdx?: number): BlockCtx { @@ -409,8 +409,7 @@ function updateCtx(ctx: BlockCtx, tree: IntermediateTree) { break; } case "ref": - const index = ctx.refList.push(NO_OP) - 1; - ctx.cbRefs.push(info.idx); + const index = ctx.cbRefs.push(info.idx) - 1; ctx.locations.push({ idx: info.idx, refIdx: info.refIdx!, @@ -430,10 +429,12 @@ function buildBlock(template: HTMLElement, ctx: BlockCtx): BlockType { if (ctx.cbRefs.length) { const cbRefs = ctx.cbRefs; const refList = ctx.refList; + let cbRefsNumber = cbRefs.length; B = class extends B { mount(parent: HTMLElement, afterNode: Node | null) { + refList.push(new Array(cbRefsNumber)); super.mount(parent, afterNode); - for (let cbRef of refList) { + for (let cbRef of refList.pop()!) { cbRef(); } } @@ -620,8 +621,8 @@ function setText(this: Text, value: any) { characterDataSetData.call(this, toText(value)); } -function makeRefSetter(index: number, refs: (() => void)[]): Setter { +function makeRefSetter(index: number, refs: (() => void)[][]): Setter { return function setRef(this: HTMLElement, fn: any) { - refs[index] = () => fn(this); + refs[refs.length - 1][index] = () => fn(this); }; } diff --git a/tests/blockdom/block_refs.test.ts b/tests/blockdom/block_refs.test.ts index 3f60f607..1e880c69 100644 --- a/tests/blockdom/block_refs.test.ts +++ b/tests/blockdom/block_refs.test.ts @@ -1,4 +1,5 @@ import { createBlock, mount, patch, remove } from "../../src/blockdom"; +import { logStep } from "../helpers"; import { makeTestFixture } from "./helpers"; //------------------------------------------------------------------------------ @@ -55,3 +56,15 @@ test("is in dom when callback is called", async () => { mount(tree, fixture); }); + +test("callback ref in callback ref with same block", async () => { + const block = createBlock('

'); + let refFn = (el: HTMLParagraphElement) => logStep(el.outerHTML); + + const child = block([refFn, "child"], []); + const parent = block([refFn, "parent"], [child]); + mount(parent, fixture); + + expect(fixture.innerHTML).toBe("

parent

child

"); + expect(["

child

", "

parent

child

"]).toBeLogged(); +}); diff --git a/tests/components/__snapshots__/refs.test.ts.snap b/tests/components/__snapshots__/refs.test.ts.snap index 09ae5139..d3fbe34d 100644 --- a/tests/components/__snapshots__/refs.test.ts.snap +++ b/tests/components/__snapshots__/refs.test.ts.snap @@ -38,6 +38,26 @@ exports[`refs can use 2 refs with same name in a t-if/t-else situation 1`] = ` }" `; +exports[`refs refs and recursive templates 1`] = ` +"function anonymous(bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component, comment } = bdom; + + let block1 = createBlock(\`

\`); + + return function template(ctx, node, key = \\"\\") { + const refs = ctx.__owl__.refs; + const ref1 = (el) => refs[\`root\`] = el; + let b2; + let txt1 = ctx['props'].tree.value; + if (ctx['props'].tree.child) { + b2 = component(\`Test\`, {tree: ctx['props'].tree.child}, key + \`__1\`, node, ctx); + } + return block1([ref1, txt1], [b2]); + } +}" +`; + exports[`refs refs are properly bound in slots 1`] = ` "function anonymous(bdom, helpers ) { diff --git a/tests/components/refs.test.ts b/tests/components/refs.test.ts index 99432e2a..f5cb3e1f 100644 --- a/tests/components/refs.test.ts +++ b/tests/components/refs.test.ts @@ -1,5 +1,5 @@ -import { Component, mount, useRef, useState } from "../../src/index"; -import { makeTestFixture, nextTick, snapshotEverything } from "../helpers"; +import { Component, mount, onMounted, useRef, useState } from "../../src/index"; +import { logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import { xml } from "../../src/index"; snapshotEverything(); @@ -100,4 +100,27 @@ describe("refs", () => { expect(console.warn).toBeCalledTimes(1); console.warn = consoleWarn; }); + + test("refs and recursive templates", async () => { + class Test extends Component { + static components = {}; + static template = xml` +

+ + +

`; + root = useRef("root"); + + setup() { + onMounted(() => logStep(this.root.el!.outerHTML)); + } + } + Test.components = { Test }; + + const tree = { value: "a", child: { value: "b", child: null } }; + + await mount(Test, fixture, { props: { tree } }); + expect(fixture.innerHTML).toBe("

a

b

"); + expect(["

b

", "

a

b

"]).toBeLogged(); + }); });