[FIX] runtime: properly support t-foreach on strings

Previously, support for iterables was added to t-foreach. The idea was
that anything that you can spread or on which you can use for..of would
be supported. Due to an implementation mistakes, strings, which are
iterable were not supported because we checked that the typeof the
iterable was 'object'.

To fix this, we coerce the iterable to an object and check whether that
coerced value has a Symbol.iterator property, which is what happens
behind the scenes when using for..of or spreading a primitive.

Closes: odoo/owl#1503
This commit is contained in:
Samuel Degueldre
2023-08-09 07:38:10 +02:00
committed by Bruno Boi
parent 4b23f51974
commit 610ed02373
3 changed files with 42 additions and 7 deletions
@@ -256,6 +256,34 @@ exports[`t-foreach iterate, position 1`] = `
}"
`;
exports[`t-foreach iterate, string param 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { prepareList, withKey } = helpers;
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block1, v_block1, l_block1, c_block1] = prepareList('abc');;
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`item\`] = k_block1[i1];
ctx[\`item_index\`] = i1;
ctx[\`item_value\`] = v_block1[i1];
const key1 = ctx['item_index'];
const b3 = text(\` [\`);
const b4 = text(ctx['item_index']);
const b5 = text(\`: \`);
const b6 = text(ctx['item']);
const b7 = text(\` \`);
const b8 = text(ctx['item_value']);
const b9 = text(\`] \`);
c_block1[i1] = withKey(multi([b3, b4, b5, b6, b7, b8, b9]), key1);
}
return list(c_block1);
}
}"
`;
exports[`t-foreach simple iteration (in a node) 1`] = `
"function anonymous(app, bdom, helpers
) {
+9
View File
@@ -131,6 +131,15 @@ describe("t-foreach", () => {
expect(renderToString(template, context)).toBe(expected);
});
test("iterate, string param", () => {
const template = `
<t t-foreach="'abc'" t-as="item" t-key="item_index">
[<t t-esc="item_index"/>: <t t-esc="item"/> <t t-esc="item_value"/>]
</t>`;
const expected = ` [0: a a] [1: b b] [2: c c] `;
expect(renderToString(template)).toBe(expected);
});
test("iterate, iterable param", () => {
const template = `
<t t-foreach="map.values()" t-as="item" t-key="item_index">