From 921ced7c9030b4bfdc54bcd07ab929aa706ead46 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();
+ });
});