Skip to content

Commit 2adf606

Browse files
committed
[FIX] blockdom: fix t-set-slot causing context capture with xml
This is a commit message.
1 parent 70101e4 commit 2adf606

File tree

4 files changed

+58
-11
lines changed

4 files changed

+58
-11
lines changed

src/compiler/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { BDom } from "../runtime/blockdom";
33
import { CodeGenerator, Config } from "./code_generator";
44
import { parse } from "./parser";
55
import { OwlError } from "../common/owl_error";
6+
import { parseXML } from "../common/utils";
67

78
export type Template = (context: any, vnode: any, key?: string) => BDom;
89

@@ -16,13 +17,13 @@ export function compile(
1617
options: CompileOptions = {}
1718
): TemplateFunction {
1819
// parsing
20+
if (typeof template === "string") {
21+
template = parseXML(`<t>${template}</t>`).firstChild as Element;
22+
}
1923
const ast = parse(template);
2024

2125
// some work
22-
const hasSafeContext =
23-
template instanceof Node
24-
? !(template instanceof Element) || template.querySelector("[t-set], [t-call]") === null
25-
: !template.includes("t-set") && !template.includes("t-call");
26+
const hasSafeContext = template.querySelector("[t-set], [t-call]") === null;
2627

2728
// code generation
2829
const codeGenerator = new CodeGenerator(ast, { ...options, hasSafeContext });

src/compiler/parser.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { OwlError } from "../common/owl_error";
2-
import { parseXML } from "../common/utils";
32

43
// -----------------------------------------------------------------------------
54
// AST Type definition
@@ -198,11 +197,7 @@ export type AST =
198197
// -----------------------------------------------------------------------------
199198
const cache: WeakMap<Element, AST> = new WeakMap();
200199

201-
export function parse(xml: string | Element): AST {
202-
if (typeof xml === "string") {
203-
const elem = parseXML(`<t>${xml}</t>`).firstChild as Element;
204-
return _parse(elem);
205-
}
200+
export function parse(xml: Element): AST {
206201
let ast = cache.get(xml);
207202
if (!ast) {
208203
// we clone here the xml to prevent modifying it in place

tests/components/__snapshots__/slots.test.ts.snap

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2875,6 +2875,35 @@ exports[`slots t-set t-value in a slot 2`] = `
28752875
}"
28762876
`;
28772877

2878+
exports[`slots t-set-slot doesn't cause context to be captured 1`] = `
2879+
"function anonymous(app, bdom, helpers
2880+
) {
2881+
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
2882+
let { markRaw } = helpers;
2883+
const comp1 = app.createComponent(\`Child\`, true, true, false, []);
2884+
2885+
function slot1(ctx, node, key = \\"\\") {
2886+
return text(ctx['someVal']);
2887+
}
2888+
2889+
return function template(ctx, node, key = \\"\\") {
2890+
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}})}, key + \`__1\`, node, this, null);
2891+
}
2892+
}"
2893+
`;
2894+
2895+
exports[`slots t-set-slot doesn't cause context to be captured 2`] = `
2896+
"function anonymous(app, bdom, helpers
2897+
) {
2898+
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
2899+
let { callSlot } = helpers;
2900+
2901+
return function template(ctx, node, key = \\"\\") {
2902+
return callSlot(ctx, node, key, 'default', false, {});
2903+
}
2904+
}"
2905+
`;
2906+
28782907
exports[`slots t-set-slot=default has priority over rest of the content 1`] = `
28792908
"function anonymous(app, bdom, helpers
28802909
) {

tests/components/slots.test.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
1+
import { App, Component, mount, onMounted, onRendered, useState, xml } from "../../src/index";
22
import { children, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
33

44
snapshotEverything();
@@ -62,6 +62,28 @@ describe("slots", () => {
6262
expect(fixture.innerHTML).toBe("some other text");
6363
});
6464

65+
test.only("t-set-slot doesn't cause context to be captured", async () => {
66+
class Child extends Component {
67+
static template = xml`<t t-slot="default"/>`;
68+
}
69+
70+
class Parent extends Component {
71+
static template = xml`<Child>
72+
<t t-set-slot="default"><t t-esc="someVal"/></t>
73+
</Child>`;
74+
static components = { Child };
75+
someVal = "some text";
76+
setup() {
77+
onRendered(() => {
78+
this.someVal = "some other text";
79+
});
80+
}
81+
}
82+
await mount(Parent, fixture);
83+
84+
expect(fixture.textContent).toBe("some other text");
85+
});
86+
6587
test("simple slot with slot scope", async () => {
6688
let child: any;
6789
class Child extends Component {

0 commit comments

Comments
 (0)