diff --git a/src/qweb/base_directives.ts b/src/qweb/base_directives.ts index 9ac3fe46..6031e524 100644 --- a/src/qweb/base_directives.ts +++ b/src/qweb/base_directives.ts @@ -234,10 +234,12 @@ QWeb.addDirective({ // Step 2: compile target template in sub templates // ------------------------------------------------ - if (!qweb.subTemplates[subTemplate]) { - qweb.subTemplates[subTemplate] = true; + let subId = qweb.subTemplates[subTemplate]; + if (!subId) { + subId = QWeb.nextId++; + qweb.subTemplates[subTemplate] = subId; const subTemplateFn = qweb._compile(subTemplate, nodeTemplate.elem, ctx, true); - qweb.subTemplates[subTemplate] = subTemplateFn; + QWeb.subTemplates[subId] = subTemplateFn; } // Step 3: compile t-call body if necessary @@ -275,12 +277,16 @@ QWeb.addDirective({ const parentNode = ctx.parentNode ? `c${ctx.parentNode}` : "result"; const extra = `Object.assign({}, extra, {parentNode: ${parentNode}, parent: ${parentComponent}, key: ${key}})`; if (ctx.parentNode) { - ctx.addLine(`this.subTemplates['${subTemplate}'].call(this, ${callingScope}, ${extra});`); + ctx.addLine( + `this.constructor.subTemplates['${subId}'].call(this, ${callingScope}, ${extra});` + ); } else { // this is a t-call with no parentnode, we need to extract the result ctx.rootContext.shouldDefineResult = true; ctx.addLine(`result = []`); - ctx.addLine(`this.subTemplates['${subTemplate}'].call(this, ${callingScope}, ${extra});`); + ctx.addLine( + `this.constructor.subTemplates['${subId}'].call(this, ${callingScope}, ${extra});` + ); ctx.addLine(`result = result[0]`); } diff --git a/src/qweb/qweb.ts b/src/qweb/qweb.ts index a3e94cfd..618807ec 100644 --- a/src/qweb/qweb.ts +++ b/src/qweb/qweb.ts @@ -212,10 +212,12 @@ export class QWeb extends EventBus { static slots = {}; static nextSlotId = 1; - // recursiveTemplates contains sub templates called with t-call, but which - // ends up in recursive situations. This is very similar to the slot situation, - // as in we need to propagate the scope. - subTemplates = {}; + // subTemplates are stored in two objects: a (local) mapping from a name to an + // id, and a (global) mapping from an id to the compiled function. This is + // necessary to ensure that global templates can be called with more than one + // QWeb instance. + subTemplates: {[key: string]: number} = {}; + static subTemplates: {[id: number]: Function} = {}; isUpdating: boolean = false; translateFn?: QWebConfig["translateFn"]; diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap index 6ea5f6d3..918198d0 100644 --- a/tests/component/__snapshots__/component.test.ts.snap +++ b/tests/component/__snapshots__/component.test.ts.snap @@ -1253,7 +1253,7 @@ exports[`other directives with t-component t-set can't alter from within callee if (scope.iter != null) { c2.push({text: scope.iter}); } - this.subTemplates['ChildWidget'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['2'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); let c5 = [], p5 = {key:5}; let vn5 = h('p', p5, c5); c1.push(vn5); @@ -1289,7 +1289,7 @@ exports[`other directives with t-component t-set can't alter in t-call body 1`] utils.getScope(scope, 'iter').iter = 'inCall'; scope[utils.zero] = c__0; } - this.subTemplates['ChildWidget'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__5__'})); + this.constructor.subTemplates['2'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__5__'})); scope = _origScope4; } let c6 = [], p6 = {key:6}; @@ -1410,7 +1410,7 @@ exports[`random stuff/miscellaneous can inject values in tagged templates 1`] = let h = this.h; let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); - this.subTemplates['__template__1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['3'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); return vn1; }" `; diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index 96df72a2..d3dafbc6 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -3825,7 +3825,9 @@ describe("t-call", () => { expect(fixture.innerHTML).toBe("

lucas

"); fixture.querySelector("p")!.click(); - expect(env.qweb.subTemplates["sub"].toString()).toMatchSnapshot(); + const subId = env.qweb.subTemplates["sub"]; + const subFn = QWeb.subTemplates[subId] as any; + expect(subFn.toString()).toMatchSnapshot(); }); test("parent is set within t-call", async () => { @@ -3847,7 +3849,10 @@ describe("t-call", () => { expect(fixture.innerHTML).toBe("
lucas
"); expect(child.__owl__.parent).toBe(parent); - expect(env.qweb.subTemplates["sub"].toString()).toMatchSnapshot(); + const subId = env.qweb.subTemplates["sub"]; + const subFn = QWeb.subTemplates[subId] as any; + + expect(subFn.toString()).toMatchSnapshot(); }); test("t-call in t-foreach and children component", async () => { @@ -3889,7 +3894,9 @@ describe("t-call", () => { expect(fixture.innerHTML).toBe("lucas"); expect(child.__owl__.parent).toBe(parent); - expect(env.qweb.subTemplates["sub"].toString()).toMatchSnapshot(); + const subId = env.qweb.subTemplates["sub"]; + const subFn = QWeb.subTemplates[subId] as any; + expect(subFn.toString()).toMatchSnapshot(); }); test("handlers with arguments are properly bound through a t-call", async () => { @@ -3905,7 +3912,9 @@ describe("t-call", () => { } const parent = new Parent(); await parent.mount(fixture); - expect(env.qweb.subTemplates["sub"].toString()).toMatchSnapshot(); + const subId = env.qweb.subTemplates["sub"]; + const subFn = QWeb.subTemplates[subId] as any; + expect(subFn.toString()).toMatchSnapshot(); fixture.querySelector("p")!.click(); }); diff --git a/tests/qweb/__snapshots__/qweb.test.ts.snap b/tests/qweb/__snapshots__/qweb.test.ts.snap index b56c3230..abdc10ce 100644 --- a/tests/qweb/__snapshots__/qweb.test.ts.snap +++ b/tests/qweb/__snapshots__/qweb.test.ts.snap @@ -749,7 +749,7 @@ exports[`loading templates can load a few templates from a xml string 1`] = ` let h = this.h; let c1 = [], p1 = {key:1}; let vn1 = h('ul', p1, c1); - this.subTemplates['items'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); return vn1; }" `; @@ -803,23 +803,23 @@ exports[`misc global 1`] = ` scope[utils.zero] = c__0; } let k14 = \`__14__\${key1}__\`; - this.subTemplates['_callee-uses-foo'].call(this, scope, Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k14})); + this.constructor.subTemplates['2'].call(this, scope, Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k14})); scope = _origScope13; } let k15 = \`__15__\${key1}__\`; - this.subTemplates['_callee-uses-foo'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k15})); + this.constructor.subTemplates['2'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k15})); utils.getScope(scope, 'foo').foo = 'bbb'; let k16 = \`__16__\${key1}__\`; - this.subTemplates['_callee-uses-foo'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k16})); + this.constructor.subTemplates['2'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k16})); scope[utils.zero] = c__0; } let k17 = \`__17__\${key1}__\`; - this.subTemplates['_callee-asc'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: k17})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: k17})); scope = _origScope10; } } scope = _origScope5; - this.subTemplates['_callee-asc-toto'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__20__'})); + this.constructor.subTemplates['3'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__20__'})); return vn1; }" `; @@ -1108,25 +1108,11 @@ exports[`t-call (template calling basic caller 1`] = ` let h = this.h; let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); - this.subTemplates['_basic-callee'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); return vn1; }" `; -exports[`t-call (template calling basic caller 2`] = ` -"function anonymous(context, extra -) { - // Template name: \\"_basic-callee\\" - let h = this.h; - let c1 = extra.parentNode; - let key0 = extra.key || \\"\\"; - let c2 = [], p2 = {key:\`\${key0}_2\`}; - let vn2 = h('span', p2, c2); - c1.push(vn2); - c2.push({text: \`ok\`}); -}" -`; - exports[`t-call (template calling basic caller, no parent node 1`] = ` "function anonymous(context, extra ) { @@ -1136,26 +1122,12 @@ exports[`t-call (template calling basic caller, no parent node 1`] = ` let result; let h = this.h; result = [] - this.subTemplates['_basic-callee'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context), key: '__3__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context), key: '__3__'})); result = result[0] return result; }" `; -exports[`t-call (template calling basic caller, no parent node 2`] = ` -"function anonymous(context, extra -) { - // Template name: \\"_basic-callee\\" - let h = this.h; - let c1 = extra.parentNode; - let key0 = extra.key || \\"\\"; - let c2 = [], p2 = {key:\`\${key0}_2\`}; - let vn2 = h('div', p2, c2); - c1.push(vn2); - c2.push({text: \`ok\`}); -}" -`; - exports[`t-call (template calling call with several sub nodes on same line 1`] = ` "function anonymous(context, extra ) { @@ -1182,28 +1154,14 @@ exports[`t-call (template calling call with several sub nodes on same line 1`] = c5.push({text: \`yay\`}); scope[utils.zero] = c__0; } - this.subTemplates['SubTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__6__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__6__'})); scope = _origScope3; } return vn1; }" `; -exports[`t-call (template calling call with several sub nodes on same line 2`] = ` -"function anonymous(context, extra -) { - // Template name: \\"SubTemplate\\" - let utils = this.constructor.utils; - let scope = Object.create(context); - let h = this.h; - let c1 = extra.parentNode; - let key0 = extra.key || \\"\\"; - let c2 = [], p2 = {key:\`\${key0}_2\`}; - let vn2 = h('div', p2, c2); - c1.push(vn2); - c2.push(...scope[utils.zero]); -}" -`; +exports[`t-call (template calling call with several sub nodes on same line 2`] = `"1"`; exports[`t-call (template calling cascading t-call t-raw='0' 1`] = ` "function anonymous(context, extra @@ -1231,7 +1189,7 @@ exports[`t-call (template calling cascading t-call t-raw='0' 1`] = ` c14.push({text: \`yay\`}); scope[utils.zero] = c__0; } - this.subTemplates['SubTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__15__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__15__'})); scope = _origScope12; } return vn1; @@ -1248,7 +1206,7 @@ exports[`t-call (template calling inherit context 1`] = ` let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); scope.foo = 1; - this.subTemplates['_callee-uses-foo'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__2__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__2__'})); return vn1; }" `; @@ -1267,7 +1225,7 @@ exports[`t-call (template calling recursive template, part 1 1`] = ` c1.push(vn2); c2.push({text: \`hey\`}); if (false) { - this.subTemplates['recursive'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__6__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__6__'})); } return vn1; }" @@ -1291,7 +1249,7 @@ exports[`t-call (template calling recursive template, part 1 2`] = ` c4.push({text: \`hey\`}); if (false) { let k5 = \`__5__\${key0}__\`; - this.subTemplates['recursive'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c3, parent: utils.getComponent(context), key: k5})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c3, parent: utils.getComponent(context), key: k5})); } }" `; @@ -1314,7 +1272,7 @@ exports[`t-call (template calling recursive template, part 2 1`] = ` utils.getScope(scope, 'node').node = scope['root']; scope[utils.zero] = c__0; } - this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__12__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__12__'})); scope = _origScope11; } return vn1; @@ -1367,7 +1325,7 @@ exports[`t-call (template calling recursive template, part 2 2`] = ` scope[utils.zero] = c__0; } let k10 = \`__10__\${key0}__\${key1}__\`; - this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c2, parent: utils.getComponent(context), key: k10})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c2, parent: utils.getComponent(context), key: k10})); scope = _origScope9; } } @@ -1393,7 +1351,7 @@ exports[`t-call (template calling recursive template, part 3 1`] = ` utils.getScope(scope, 'node').node = scope['root']; scope[utils.zero] = c__0; } - this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__12__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__12__'})); scope = _origScope11; } return vn1; @@ -1446,7 +1404,7 @@ exports[`t-call (template calling recursive template, part 3 2`] = ` scope[utils.zero] = c__0; } let k10 = \`__10__\${key0}__\${key1}__\`; - this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c2, parent: utils.getComponent(context), key: k10})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c2, parent: utils.getComponent(context), key: k10})); scope = _origScope9; } } @@ -1473,7 +1431,7 @@ exports[`t-call (template calling recursive template, part 4: with t-set recursi utils.getScope(scope, 'node').node = scope['root']; scope[utils.zero] = c__0; } - this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__12__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__12__'})); scope = _origScope11; } return vn1; @@ -1531,7 +1489,7 @@ exports[`t-call (template calling recursive template, part 4: with t-set recursi scope[utils.zero] = c__0; } let k10 = \`__10__\${key0}__\${key1}__\`; - this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c2, parent: utils.getComponent(context), key: k10})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c2, parent: utils.getComponent(context), key: k10})); scope = _origScope9; } } @@ -1557,7 +1515,7 @@ exports[`t-call (template calling scoped parameters 1`] = ` utils.getScope(scope, 'foo').foo = 42; scope[utils.zero] = c__0; } - this.subTemplates['_basic-callee'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); scope = _origScope2; } if (scope.foo != null) { @@ -1577,26 +1535,12 @@ exports[`t-call (template calling t-call with t-if 1`] = ` let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); if (scope['flag']) { - this.subTemplates['sub'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); } return vn1; }" `; -exports[`t-call (template calling t-call with t-if 2`] = ` -"function anonymous(context, extra -) { - // Template name: \\"sub\\" - let h = this.h; - let c1 = extra.parentNode; - let key0 = extra.key || \\"\\"; - let c2 = [], p2 = {key:\`\${key0}_2\`}; - let vn2 = h('span', p2, c2); - c1.push(vn2); - c2.push({text: \`ok\`}); -}" -`; - exports[`t-call (template calling t-call with t-set inside and outside 1`] = ` "function anonymous(context, extra ) { @@ -1634,7 +1578,7 @@ exports[`t-call (template calling t-call with t-set inside and outside 1`] = ` scope[utils.zero] = c__0; } let k9 = \`__9__\${key1}__\`; - this.subTemplates['sub'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: k9})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: k9})); scope = _origScope8; } } @@ -1653,7 +1597,7 @@ exports[`t-call (template calling t-call with t-set inside and outside. 2 1`] = let c1 = [], p1 = {key:1}; let vn1 = h('p', p1, c1); scope.w = 'fromwrapper'; - this.subTemplates['main'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__11__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__11__'})); return vn1; }" `; @@ -1669,7 +1613,7 @@ exports[`t-call (template calling t-call, conditional and t-set in t-call body 1 let vn1 = h('div', p1, c1); scope.v1 = 'elif'; if (scope.v1==='if') { - this.subTemplates['callee1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); } else if (scope.v1==='elif') { { @@ -1681,7 +1625,7 @@ exports[`t-call (template calling t-call, conditional and t-set in t-call body 1 utils.getScope(scope, 'v').v = 'success'; scope[utils.zero] = c__0; } - this.subTemplates['callee2'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__7__'})); + this.constructor.subTemplates['2'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__7__'})); scope = _origScope6; } } @@ -1698,7 +1642,35 @@ exports[`t-call (template calling t-call, global templates 1`] = ` let h = this.h; let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); - this.subTemplates['john'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); + return vn1; +}" +`; + +exports[`t-call (template calling two different QWeb instances, and shared templates 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"main\\" + let utils = this.constructor.utils; + let scope = Object.create(context); + let h = this.h; + let c1 = [], p1 = {key:1}; + let vn1 = h('div', p1, c1); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); + return vn1; +}" +`; + +exports[`t-call (template calling two different QWeb instances, and shared templates 2`] = ` +"function anonymous(context, extra +) { + // Template name: \\"main\\" + let utils = this.constructor.utils; + let scope = Object.create(context); + let h = this.h; + let c1 = [], p1 = {key:1}; + let vn1 = h('div', p1, c1); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__3__'})); return vn1; }" `; @@ -1721,7 +1693,7 @@ exports[`t-call (template calling with unused body 1`] = ` scope[utils.zero] = c__0; } result = [] - this.subTemplates['_basic-callee'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context), key: '__4__'})); result = result[0] scope = _origScope3; } @@ -1747,7 +1719,7 @@ exports[`t-call (template calling with unused setbody 1`] = ` scope[utils.zero] = c__0; } result = [] - this.subTemplates['_basic-callee'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context), key: '__4__'})); result = result[0] scope = _origScope3; } @@ -1773,7 +1745,7 @@ exports[`t-call (template calling with used body 1`] = ` scope[utils.zero] = c__0; } result = [] - this.subTemplates['_callee-printsbody'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context), key: '__4__'})); result = result[0] scope = _origScope3; } @@ -1799,7 +1771,7 @@ exports[`t-call (template calling with used set body 1`] = ` utils.getScope(scope, 'foo').foo = 'ok'; scope[utils.zero] = c__0; } - this.subTemplates['_callee-uses-foo'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); scope = _origScope3; } return vn1; @@ -1949,7 +1921,7 @@ exports[`t-esc t-esc inside t-call, with t-set outside 1`] = ` let c2 = new utils.VDomArray(); c2.push({text: \`Hi\`}); scope.v = c2 - this.subTemplates['sub'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__5__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__5__'})); return vn1; }" `; @@ -2018,7 +1990,7 @@ exports[`t-esc t-esc=0 is escaped 1`] = ` c4.push({text: \`escaped\`}); scope[utils.zero] = c__0; } - this.subTemplates['test'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__5__'})); + this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__5__'})); scope = _origScope3; } return vn1; @@ -2814,7 +2786,7 @@ exports[`t-on t-on with t-call 1`] = ` let h = this.h; let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); - this.subTemplates['sub'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); return vn1; }" `; @@ -2828,7 +2800,7 @@ exports[`t-on t-on, with arguments and t-call 1`] = ` let h = this.h; let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); - this.subTemplates['sub'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); + this.constructor.subTemplates['1'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__4__'})); return vn1; }" `; diff --git a/tests/qweb/qweb.test.ts b/tests/qweb/qweb.test.ts index 4036633a..c8919e29 100644 --- a/tests/qweb/qweb.test.ts +++ b/tests/qweb/qweb.test.ts @@ -747,7 +747,7 @@ describe("t-call (template calling", () => { qweb.addTemplate("caller", '
'); const expected = "
ok
"; expect(renderToString(qweb, "caller")).toBe(expected); - expect(qweb.subTemplates["_basic-callee"].toString()).toMatchSnapshot(); + expect(qweb.subTemplates["_basic-callee"]).toBeTruthy(); }); test("basic caller, no parent node", () => { @@ -755,7 +755,7 @@ describe("t-call (template calling", () => { qweb.addTemplate("caller", ''); const expected = "
ok
"; expect(renderToString(qweb, "caller")).toBe(expected); - expect(qweb.subTemplates["_basic-callee"].toString()).toMatchSnapshot(); + expect(qweb.subTemplates["_basic-callee"]).toBeTruthy(); }); test("t-call with t-if", () => { @@ -763,7 +763,7 @@ describe("t-call (template calling", () => { qweb.addTemplate("caller", '
'); const expected = "
ok
"; expect(renderToString(qweb, "caller", { flag: true })).toBe(expected); - expect(qweb.subTemplates["sub"].toString()).toMatchSnapshot(); + expect(qweb.subTemplates["sub"]).toBeTruthy(); }); test("t-call not allowed on a non t node", () => { @@ -898,7 +898,8 @@ describe("t-call (template calling", () => { `); const expected = "
hey
"; expect(renderToString(qweb, "recursive")).toBe(expected); - const recursiveFn = Object.values(qweb.subTemplates)[0] as any; + const subId = qweb.subTemplates["recursive"]; + const recursiveFn = QWeb.subTemplates[subId] as any; expect(recursiveFn.toString()).toMatchSnapshot(); }); @@ -926,7 +927,8 @@ describe("t-call (template calling", () => { expect(renderToString(qweb, "Parent", { root }, { fiber: { vars: {}, scope: {} } })).toBe( expected ); - const recursiveFn = Object.values(qweb.subTemplates)[0] as any; + const subId = qweb.subTemplates["nodeTemplate"]; + const recursiveFn = QWeb.subTemplates[subId] as any; expect(recursiveFn.toString()).toMatchSnapshot(); }); @@ -953,7 +955,8 @@ describe("t-call (template calling", () => { const expected = "

a

b

d

c

"; expect(renderToString(qweb, "Parent", { root }, { fiber: {} })).toBe(expected); - const recursiveFn = Object.values(qweb.subTemplates)[0] as any; + const subId = qweb.subTemplates["nodeTemplate"]; + const recursiveFn = QWeb.subTemplates[subId] as any; expect(recursiveFn.toString()).toMatchSnapshot(); }); @@ -985,7 +988,8 @@ describe("t-call (template calling", () => { const expected = "

a 2

b 3

c 4

d 5

"; expect(renderToString(qweb, "Parent", { root })).toBe(expected); - const recursiveFn = Object.values(qweb.subTemplates)[0] as any; + const subId = qweb.subTemplates["nodeTemplate"]; + const recursiveFn = QWeb.subTemplates[subId] as any; expect(recursiveFn.toString()).toMatchSnapshot(); }); @@ -1057,6 +1061,17 @@ describe("t-call (template calling", () => { const context = { list: [{ val: 1 }, { val: 2 }, { val: 3 }] }; expect(trim(renderToString(qweb, "wrapper", context))).toBe(expected); }); + + test("two different QWeb instances, and shared templates", () => { + QWeb.registerTemplate("sub", `ok`); + QWeb.registerTemplate("main", `
`); + + const qweb1 = new QWeb(); + const qweb2 = new QWeb(); + + expect(renderToString(qweb1, "main")).toBe("
ok
"); + expect(renderToString(qweb2, "main")).toBe("
ok
"); + }); }); describe("foreach", () => {