mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] slots: prevent crash when using same slot in different locations
Before this commit, a crash could occur when a component with no props is defined in a slot, and that slot is conditionally displayed in multiple locations. The reason for that is that the key provided to the callSlot function was identical, so from the perspective of the component function, it was not possible to make the difference between a component located in either places. With this commit, we make sure that a unique key is used when a slot is reused in a template (or if it is dynamic, because in that case, we have no idea at compile time if it will be unique or not) closes #1246
This commit is contained in:
committed by
Sam Degueldre
parent
9cb74d619b
commit
3883cec079
@@ -232,6 +232,7 @@ export class CodeGenerator {
|
||||
translatableAttributes: string[] = TRANSLATABLE_ATTRS;
|
||||
ast: AST;
|
||||
staticDefs: { id: string; expr: string }[] = [];
|
||||
slotNames: Set<String> = new Set();
|
||||
helpers: Set<string> = new Set();
|
||||
|
||||
constructor(ast: AST, options: CodeGenOptions) {
|
||||
@@ -1245,28 +1246,37 @@ export class CodeGenerator {
|
||||
let blockString: string;
|
||||
let slotName;
|
||||
let dynamic = false;
|
||||
let isMultiple = false;
|
||||
if (ast.name.match(INTERP_REGEXP)) {
|
||||
dynamic = true;
|
||||
isMultiple = true;
|
||||
slotName = interpolate(ast.name);
|
||||
} else {
|
||||
slotName = "'" + ast.name + "'";
|
||||
isMultiple = isMultiple || this.slotNames.has(ast.name);
|
||||
this.slotNames.add(ast.name);
|
||||
}
|
||||
const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
|
||||
if (ast.attrs) {
|
||||
delete ast.attrs["t-props"];
|
||||
}
|
||||
let key = this.target.loopLevel ? `key${this.target.loopLevel}` : "key";
|
||||
if (isMultiple) {
|
||||
key = `${key} + \`${this.generateComponentKey()}\``;
|
||||
}
|
||||
|
||||
const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
|
||||
const scope = this.getPropString(props, dynProps);
|
||||
if (ast.defaultContent) {
|
||||
const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
|
||||
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope}, ${name})`;
|
||||
blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name})`;
|
||||
} else {
|
||||
if (dynamic) {
|
||||
let name = generateId("slot");
|
||||
this.define(name, slotName);
|
||||
blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}, ${dynamic}, ${scope}))`;
|
||||
blockString = `toggler(${name}, callSlot(ctx, node, ${key}, ${name}, ${dynamic}, ${scope}))`;
|
||||
} else {
|
||||
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope})`;
|
||||
blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope})`;
|
||||
}
|
||||
}
|
||||
// event handling
|
||||
|
||||
Reference in New Issue
Block a user