[REF] qweb: t-foreach: remove integer support for t-value

Handling it complexifies the compiled code, and it is not really
useful (the same result can be achieved with t-foreach="Array(n)")

Part of #128
This commit is contained in:
Aaron Bohy
2019-06-07 14:10:59 +02:00
committed by Géry Debongnie
parent b14d069ee7
commit 49baf0de6e
6 changed files with 75 additions and 127 deletions
+3 -4
View File
@@ -392,9 +392,8 @@ Like conditions, `t-foreach` applies to the element bearing the directives at
is equivalent to the previous example.
`t-foreach` can iterate on an array (the current item will be the current value),
an object (the current item will be the current key) or an integer (equivalent
to iterating on an array between 0 inclusive and the provided integer exclusive).
`t-foreach` can iterate on an array (the current item will be the current value)
or an object (the current item will be the current key).
In addition to the name passed via t-as, `t-foreach` provides a few other
variables for various data points (note: `$as` will be replaced by the name
@@ -418,7 +417,7 @@ into the global context.
<t t-set="existing_variable" t-value="False"/>
<!-- existing_variable now False -->
<p t-foreach="[1, 2, 3]" t-as="i">
<p t-foreach="Array(3)" t-as="i">
<t t-set="existing_variable" t-value="True"/>
<t t-set="new_variable" t-value="True"/>
<!-- existing_variable and new_variable now True -->
+6 -10
View File
@@ -243,18 +243,14 @@ QWeb.addDirective({
ctx.addLine(
`if (!_${arrayID}) { throw new Error('QWeb error: Invalid loop expression')}`
);
ctx.addLine(
`if (typeof _${arrayID} === 'number') { _${arrayID} = Array.from(Array(_${arrayID}).keys())}`
);
let keysID = ctx.generateID();
ctx.addLine(
`var _${keysID} = _${arrayID} instanceof Array ? _${arrayID} : Object.keys(_${arrayID});`
);
ctx.addLine(`var _length${keysID} = _${keysID}.length;`);
let valuesID = ctx.generateID();
ctx.addLine(
`var _${valuesID} = _${arrayID} instanceof Array ? _${arrayID} : Object.values(_${arrayID});`
);
ctx.addLine(`var _${keysID} = _${valuesID} = _${arrayID};`);
ctx.addIf(`!(_${arrayID} instanceof Array)`);
ctx.addLine(`_${keysID} = Object.keys(_${arrayID});`);
ctx.addLine(`_${valuesID} = Object.values(_${arrayID});`);
ctx.closeIf();
ctx.addLine(`var _length${keysID} = _${keysID}.length;`);
ctx.addLine(`for (let i = 0; i < _length${keysID}; i++) {`);
ctx.indent();
ctx.addLine(`context.${name}_first = i === 0;`);
+5 -3
View File
@@ -98,10 +98,12 @@ exports[`composition sub widgets with some state rendered in a loop 1`] = `
var vn1 = h('div', p1, c1);
var _2 = context['state'].numbers;
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.number_first = i === 0;
context.number_last = i === _length3 - 1;
+55 -73
View File
@@ -317,10 +317,12 @@ exports[`foreach does not pollute the rendering context 1`] = `
var vn1 = h('div', p1, c1);
var _2 = [1];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.item_first = i === 0;
context.item_last = i === _length3 - 1;
@@ -345,10 +347,12 @@ exports[`foreach iterate on items (on a element node) 1`] = `
var vn1 = h('div', p1, c1);
var _2 = [1, 2];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.item_first = i === 0;
context.item_last = i === _length3 - 1;
@@ -376,10 +380,12 @@ exports[`foreach iterate on items 1`] = `
var vn1 = h('div', p1, c1);
var _2 = [3, 2, 1];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.item_first = i === 0;
context.item_last = i === _length3 - 1;
@@ -416,50 +422,12 @@ exports[`foreach iterate, dict param 1`] = `
var vn1 = h('div', p1, c1);
var _2 = context['value'];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.item_first = i === 0;
context.item_last = i === _length3 - 1;
context.item_index = i;
context.item = _3[i];
context.item_value = _4[i];
c1.push({text: \` [\`});
var _5 = context['item_index'];
if (_5 || _5 === 0) {
c1.push({text: _5});
}
c1.push({text: \`: \`});
var _6 = context['item'];
if (_6 || _6 === 0) {
c1.push({text: _6});
}
c1.push({text: \` \`});
var _7 = context['item_value'];
if (_7 || _7 === 0) {
c1.push({text: _7});
}
c1.push({text: \`] \`});
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
return vn1;
}"
`;
exports[`foreach iterate, integer param 1`] = `
"function anonymous(context,extra
) {
context = Object.create(context);
var h = this.utils.h;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
var _2 = 3;
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.item_first = i === 0;
context.item_last = i === _length3 - 1;
@@ -494,12 +462,14 @@ exports[`foreach iterate, position 1`] = `
var h = this.utils.h;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
var _2 = 5;
var _2 = Array(5);
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.elem_first = i === 0;
context.elem_last = i === _length3 - 1;
@@ -533,10 +503,12 @@ exports[`foreach warn if no key in some case 1`] = `
var vn1 = h('div', p1, c1);
var _2 = [1, 2];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.item_first = i === 0;
context.item_last = i === _length3 - 1;
@@ -593,10 +565,12 @@ exports[`misc global 1`] = `
var vn1 = h('div', p1, c1);
var _2 = [4,5,6];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.value_first = i === 0;
context.value_last = i === _length3 - 1;
@@ -1102,10 +1076,12 @@ exports[`t-key t-key directive in a list 1`] = `
var vn1 = h('ul', p1, c1);
var _2 = context['beers'];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.beer_first = i === 0;
context.beer_last = i === _length3 - 1;
@@ -1201,10 +1177,12 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = `
var vn1 = h('ul', p1, c1);
var _2 = ['someval'];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.action_first = i === 0;
context.action_last = i === _length3 - 1;
@@ -1528,10 +1506,12 @@ exports[`t-ref refs in a loop 1`] = `
var vn1 = h('div', p1, c1);
var _2 = context['items'];
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _2 === 'number') { _2 = Array.from(Array(_2).keys())}
var _3 = _2 instanceof Array ? _2 : Object.keys(_2);
var _3 = _4 = _2;
if (!(_2 instanceof Array)) {
_3 = Object.keys(_2);
_4 = Object.values(_2);
}
var _length3 = _3.length;
var _4 = _2 instanceof Array ? _2 : Object.values(_2);
for (let i = 0; i < _length3; i++) {
context.item_first = i === 0;
context.item_last = i === _length3 - 1;
@@ -1686,10 +1666,12 @@ exports[`t-set t-set should reuse variable if possible 1`] = `
var _2 = 1;
var _3 = context['list'];
if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
if (typeof _3 === 'number') { _3 = Array.from(Array(_3).keys())}
var _4 = _3 instanceof Array ? _3 : Object.keys(_3);
var _4 = _5 = _3;
if (!(_3 instanceof Array)) {
_4 = Object.keys(_3);
_5 = Object.values(_3);
}
var _length4 = _4.length;
var _5 = _3 instanceof Array ? _3 : Object.values(_3);
for (let i = 0; i < _length4; i++) {
context.elem_first = i === 0;
context.elem_last = i === _length4 - 1;
+5 -24
View File
@@ -1151,8 +1151,7 @@ describe("composition", () => {
<t t-if="state.ok"><t t-widget="ChildWidget" t-ref="child" t-keepalive="1"/></t>
</div>
<span t-name="ChildWidget">Hello</span>
</templates>`
);
</templates>`);
class ParentWidget extends Widget {
state = { ok: true };
widgets = { ChildWidget };
@@ -1162,19 +1161,19 @@ describe("composition", () => {
await widget.mount(fixture);
let child = children(widget)[0];
expect(fixture.innerHTML).toBe('<div><span>Hello</span></div>');
expect(fixture.innerHTML).toBe("<div><span>Hello</span></div>");
expect(widget.refs.child).toEqual(child);
widget.state.ok = false;
await nextTick();
expect(fixture.innerHTML).toBe('<div></div>');
expect(fixture.innerHTML).toBe("<div></div>");
expect(widget.refs.child).toEqual(child);
widget.state.ok = true;
await nextTick();
expect(fixture.innerHTML).toBe('<div><span>Hello</span></div>');
expect(fixture.innerHTML).toBe("<div><span>Hello</span></div>");
expect(widget.refs.child).toEqual(child);
});
@@ -1849,7 +1848,7 @@ describe("random stuff/miscellaneous", () => {
// directive as a key
env.qweb.addTemplate(
"Test",
`<div><t t-foreach="2">txt</t><t t-widget="widget"/></div>`
`<div><t t-foreach="Array(2)">txt</t><t t-widget="widget"/></div>`
);
class Test extends Widget {
widgets = { widget: Widget };
@@ -2499,24 +2498,6 @@ describe("widget and observable state", () => {
);
}
});
test("widget can add observed keys to its state", async () => {
env.qweb.addTemplate(
"TestWidget",
`<div><t t-esc="state.a"/><t t-esc="state.b"/></div>`
);
class TestWidget extends Widget {
state: any = { a: 1 };
}
const widget = new TestWidget(env);
await widget.mount(fixture);
expect(fixture.innerHTML).toBe("<div>1</div>");
widget.set(widget.state, "b", 2);
await nextTick();
expect(fixture.innerHTML).toBe("<div>12</div>");
});
});
describe("t-mounted directive", () => {
+1 -13
View File
@@ -657,7 +657,7 @@ describe("foreach", () => {
"test",
`
<div>
<t t-foreach="5" t-as="elem">
<t t-foreach="Array(5)" t-as="elem">
-<t t-if="elem_first"> first</t><t t-if="elem_last"> last</t> (<t t-esc="elem_index"/>)
</t>
</div>`
@@ -667,18 +667,6 @@ describe("foreach", () => {
expect(result).toBe(expected);
});
test("iterate, integer param", () => {
qweb.addTemplate(
"test",
`<div><t t-foreach="3" t-as="item">
[<t t-esc="item_index"/>: <t t-esc="item"/> <t t-esc="item_value"/>]
</t></div>`
);
const result = trim(renderToString(qweb, "test"));
const expected = `<div>[0:00][1:11][2:22]</div>`;
expect(result).toBe(expected);
});
test("iterate, dict param", () => {
qweb.addTemplate(
"test",