From 21737d33fa86611649a22fc04337c924943b3a61 Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Thu, 2 Jan 2020 14:01:45 +0100 Subject: [PATCH] [FIX] qweb: variables set outside foreach must be altered by inloop t-tset In a template, have t-set t-value outside a t-foreach in the t-foreach, alter that variable by resetting it (as for a incrementation variable) Before this commit, when printing the variable when the loop had finished its value was the one set in the first place After this commit, the value becomes the one altered by the loop iterations closes #598 --- src/qweb/base_directives.ts | 9 +- src/qweb/compilation_context.ts | 10 +- src/qweb/qweb.ts | 17 +- .../__snapshots__/component.test.ts.snap | 251 +++++++++++++++++- .../__snapshots__/slots.test.ts.snap | 6 +- tests/component/component.test.ts | 232 ++++++++++++++++ tests/qweb/__snapshots__/qweb.test.ts.snap | 61 ++--- 7 files changed, 542 insertions(+), 44 deletions(-) diff --git a/src/qweb/base_directives.ts b/src/qweb/base_directives.ts index a91fa1e4..c13f75b5 100644 --- a/src/qweb/base_directives.ts +++ b/src/qweb/base_directives.ts @@ -128,7 +128,12 @@ QWeb.addDirective({ qwebvar.expr = `scope.${variable}`; if (value) { const formattedValue = ctx.formatExpression(value); - ctx.addLine(`${qwebvar.expr} = ${formattedValue};`); + let scopeExpr = `scope`; + if (ctx.protectedScopeNumber) { + ctx.rootContext.shouldDefineUtils = true; + scopeExpr = `utils.getScope(scope, '${variable}')`; + } + ctx.addLine(`${scopeExpr}.${variable} = ${formattedValue};`); qwebvar.value = formattedValue; } @@ -313,7 +318,7 @@ QWeb.addDirective({ ctx.addLine(`_${valuesID} = Object.values(_${arrayID});`); ctx.closeIf(); ctx.addLine(`let _length${keysID} = _${keysID}.length;`); - let varsID = ctx.startProtectScope(); + let varsID = ctx.startProtectScope(true); const loopVar = `i${ctx.loopNumber}`; ctx.addLine(`for (let ${loopVar} = 0; ${loopVar} < _length${keysID}; ${loopVar}++) {`); ctx.indent(); diff --git a/src/qweb/compilation_context.ts b/src/qweb/compilation_context.ts index 0abceb5e..625a3f71 100644 --- a/src/qweb/compilation_context.ts +++ b/src/qweb/compilation_context.ts @@ -17,6 +17,7 @@ export class CompilationContext { rootContext: CompilationContext; shouldDefineParent: boolean = false; shouldDefineScope: boolean = false; + protectedScopeNumber: number = 0; shouldDefineQWeb: boolean = false; shouldDefineUtils: boolean = false; shouldDefineRefs: boolean = false; @@ -173,14 +174,17 @@ export class CompilationContext { let r = s.replace(/\{\{.*?\}\}/g, s => "${" + this.formatExpression(s.slice(2, -2)) + "}"); return "`" + r + "`"; } - startProtectScope(): number { + startProtectScope(codeBlock?: boolean): number { const protectID = this.generateID(); + this.rootContext.protectedScopeNumber++; this.rootContext.shouldDefineScope = true; + const scopeExpr = codeBlock ? `Object.create(scope);` : `Object.assign(Object.create(context), scope);`; this.addLine(`let _origScope${protectID} = scope;`); - this.addLine(`scope = Object.assign(Object.create(context), scope);`); + this.addLine(`scope = ${scopeExpr}`); return protectID; } stopProtectScope(protectID: number) { + this.rootContext.protectedScopeNumber--; this.addLine(`scope = _origScope${protectID};`); } -} +} \ No newline at end of file diff --git a/src/qweb/qweb.ts b/src/qweb/qweb.ts index f95d1c58..ec32ef81 100644 --- a/src/qweb/qweb.ts +++ b/src/qweb/qweb.ts @@ -86,6 +86,10 @@ interface Utils { [key: string]: any; } +function isComponent(obj) { + return obj && obj.hasOwnProperty("__owl__"); +} + const UTILS: Utils = { zero: Symbol("zero"), toObj(expr) { @@ -122,10 +126,21 @@ const UTILS: Utils = { .join(""); }, getComponent(obj) { - while (obj && !obj.hasOwnProperty("__owl__")) { + while (obj && !isComponent(obj)) { obj = obj.__proto__; } return obj; + }, + getScope(obj, property: string) { + const obj0 = obj; + while (obj && !obj.hasOwnProperty(property)) { + const newObj = obj.__proto__; + if (!newObj || isComponent(newObj)) { + return obj0; + } + obj = newObj; + } + return obj; } }; diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap index be30c7c3..d78d0b70 100644 --- a/tests/component/__snapshots__/component.test.ts.snap +++ b/tests/component/__snapshots__/component.test.ts.snap @@ -58,7 +58,7 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.section_first = i1 === 0 scope.section_last = i1 === _length3 - 1 @@ -75,7 +75,7 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for } let _length7 = _7.length; let _origScope9 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i2 = 0; i2 < _length7; i2++) { scope.blip_first = i2 === 0 scope.blip_last = i2 === _length7 - 1 @@ -432,7 +432,7 @@ exports[`composition sub components with some state rendered in a loop 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.number_first = i1 === 0 scope.number_last = i1 === _length3 - 1 @@ -587,6 +587,58 @@ exports[`dynamic t-props basic use 1`] = ` }" `; +exports[`other directives with t-component slot setted value (with t-set) not accessible with t-esc 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"__template__2\\" + let utils = this.constructor.utils; + let QWeb = this.constructor; + let parent = context; + let scope = Object.create(context); + let h = this.h; + let c1 = [], p1 = {key:1}; + let vn1 = h('div', p1, c1); + scope.iter = 'source'; + let c2 = [], p2 = {key:2}; + let vn2 = h('p', p2, c2); + c1.push(vn2); + if (scope.iter != null) { + c2.push({text: scope.iter}); + } + // Component 'ChildWidget' + let w3 = '__4__' in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap['__4__']] : false; + let props3 = {}; + if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { + w3.destroy(); + w3 = false; + } + if (w3) { + w3.__updateProps(props3, extra.fiber, Object.assign(Object.create(context), scope)); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { + let componentKey3 = \`ChildWidget\`; + let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['ChildWidget']; + if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} + w3 = new W3(parent, props3); + parent.__owl__.cmap['__4__'] = w3.__owl__.id; + w3.__owl__.slotId = 1; + let fiber = w3.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: '__4__', hook: {remove() {},destroy(vn) {w3.destroy();}}}); + c1.push(pvnode); + w3.__owl__.pvnode = pvnode; + } + w3.__owl__.parentLastFiberId = extra.fiber.id; + let c5 = [], p5 = {key:5}; + let vn5 = h('p', p5, c5); + c1.push(vn5); + if (scope.iter != null) { + c5.push({text: scope.iter}); + } + return vn1; +}" +`; + exports[`other directives with t-component t-on with getter as handler 1`] = ` "function anonymous(context, extra ) { @@ -1017,6 +1069,195 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie }" `; +exports[`other directives with t-component t-set can't alter component 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"__template__1\\" + let scope = Object.create(context); + let h = this.h; + let c1 = [], p1 = {key:1}; + let vn1 = h('div', p1, c1); + let c2 = [], p2 = {key:2}; + let vn2 = h('p', p2, c2); + c1.push(vn2); + let _3 = scope['iter']; + if (_3 != null) { + c2.push({text: _3}); + } + scope.iter = 5; + let c4 = [], p4 = {key:4}; + let vn4 = h('p', p4, c4); + c1.push(vn4); + if (scope.iter != null) { + c4.push({text: scope.iter}); + } + return vn1; +}" +`; + +exports[`other directives with t-component t-set can't alter from within callee 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"__template__1\\" + 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); + scope.iter = 'source'; + let c2 = [], p2 = {key:2}; + let vn2 = h('p', p2, c2); + c1.push(vn2); + 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)})); + let c4 = [], p4 = {key:4}; + let vn4 = h('p', p4, c4); + c1.push(vn4); + if (scope.iter != null) { + c4.push({text: scope.iter}); + } + return vn1; +}" +`; + +exports[`other directives with t-component t-set can't alter in t-call body 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"__template__1\\" + 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); + scope.iter = 'source'; + let c2 = [], p2 = {key:2}; + let vn2 = h('p', p2, c2); + c1.push(vn2); + if (scope.iter != null) { + c2.push({text: scope.iter}); + } + { + let _origScope4 = scope; + scope = Object.assign(Object.create(context), scope); + { + let c__0 = []; + 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)})); + scope = _origScope4; + } + let c5 = [], p5 = {key:5}; + let vn5 = h('p', p5, c5); + c1.push(vn5); + if (scope.iter != null) { + c5.push({text: scope.iter}); + } + return vn1; +}" +`; + +exports[`other directives with t-component t-set not altered by child widget 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"__template__2\\" + let utils = this.constructor.utils; + let QWeb = this.constructor; + let parent = context; + let scope = Object.create(context); + let h = this.h; + let c1 = [], p1 = {key:1}; + let vn1 = h('div', p1, c1); + scope.iter = 'source'; + let c2 = [], p2 = {key:2}; + let vn2 = h('p', p2, c2); + c1.push(vn2); + if (scope.iter != null) { + c2.push({text: scope.iter}); + } + // Component 'ChildWidget' + let w3 = '__4__' in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap['__4__']] : false; + let props3 = {}; + if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { + w3.destroy(); + w3 = false; + } + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { + let componentKey3 = \`ChildWidget\`; + let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['ChildWidget']; + if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} + w3 = new W3(parent, props3); + parent.__owl__.cmap['__4__'] = w3.__owl__.id; + let fiber = w3.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: '__4__', hook: {remove() {},destroy(vn) {w3.destroy();}}}); + c1.push(pvnode); + w3.__owl__.pvnode = pvnode; + } + w3.__owl__.parentLastFiberId = extra.fiber.id; + let c5 = [], p5 = {key:5}; + let vn5 = h('p', p5, c5); + c1.push(vn5); + if (scope.iter != null) { + c5.push({text: scope.iter}); + } + return vn1; +}" +`; + +exports[`other directives with t-component t-set outside modified in t-foreach 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"__template__1\\" + 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); + scope.iter = 0; + let _2 = scope['state'].values; + if (!_2) { throw new Error('QWeb error: Invalid loop expression')} + let _3 = _4 = _2; + if (!(_2 instanceof Array)) { + _3 = Object.keys(_2); + _4 = Object.values(_2); + } + let _length3 = _3.length; + let _origScope5 = scope; + scope = Object.create(scope); + for (let i1 = 0; i1 < _length3; i1++) { + scope.val_first = i1 === 0 + scope.val_last = i1 === _length3 - 1 + scope.val_index = i1 + scope.val = _3[i1] + scope.val_value = _4[i1] + let key1 = scope['val']; + let c6 = [], p6 = {key:\`\${key1}_6\`}; + let vn6 = h('p', p6, c6); + c1.push(vn6); + c6.push({text: \`InLoop: \`}); + if (scope.iter != null) { + c6.push({text: scope.iter}); + } + utils.getScope(scope, 'iter').iter = scope.iter+1; + } + scope = _origScope5; + let c7 = [], p7 = {key:7}; + let vn7 = h('p', p7, c7); + c1.push(vn7); + c7.push({text: \`EndLoop: \`}); + if (scope.iter != null) { + c7.push({text: scope.iter}); + } + return vn1; +}" +`; + exports[`random stuff/miscellaneous can inject values in tagged templates 1`] = ` "function anonymous(context, extra ) { @@ -1093,7 +1334,7 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.item_first = i1 === 0 scope.item_last = i1 === _length3 - 1 @@ -1342,7 +1583,7 @@ exports[`t-model directive in a t-foreach 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.thing_first = i1 === 0 scope.thing_last = i1 === _length3 - 1 diff --git a/tests/component/__snapshots__/slots.test.ts.snap b/tests/component/__snapshots__/slots.test.ts.snap index fe1edc2c..e020d99b 100644 --- a/tests/component/__snapshots__/slots.test.ts.snap +++ b/tests/component/__snapshots__/slots.test.ts.snap @@ -263,7 +263,7 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = ` } let _length4 = _4.length; let _origScope6 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length4; i1++) { scope.user_first = i1 === 0 scope.user_last = i1 === _length4 - 1 @@ -360,7 +360,7 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` } let _length4 = _4.length; let _origScope6 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length4; i1++) { scope.user_first = i1 === 0 scope.user_last = i1 === _length4 - 1 @@ -371,7 +371,7 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` let c7 = [], p7 = {key:\`\${key1}_7\`}; let vn7 = h('li', p7, c7); c2.push(vn7); - scope.userdescr = 'User '+scope['user'].name; + utils.getScope(scope, 'userdescr').userdescr = 'User '+scope['user'].name; // Component 'Link' let k9 = \`__9__\${key1}__\`; let w8 = k9 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k9]] : false; diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index 52ca2a67..c7d2b960 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -2670,6 +2670,238 @@ describe("other directives with t-component", () => { await nextTick(); // wait for changes triggered in mounted to be applied expect(fixture.innerHTML).toBe("
B0B1
"); }); + + test("t-set outside modified in t-foreach", async () => { + class SomeWidget extends Component { + static template = xml` +
+ + +

InLoop:

+ + +

EndLoop:

+
`; + + state = useState({values: ['a', 'b']}); + } + const widget = new SomeWidget(); + await widget.mount(fixture); + + expect(fixture.innerHTML).toBe("

InLoop: 0

InLoop: 1

EndLoop: 2

"); + expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot(); + }); + + test("t-set outside modified in t-if", async () => { + class SomeWidget extends Component { + static template = xml` +
+ + + + + + + + + + + +

+
`; + + state = {flag: 'if'}; + } + const widget = new SomeWidget(); + await widget.mount(fixture); + + expect(fixture.innerHTML).toBe("

2

"); + widget.state.flag = 'elif'; + await widget.render(); + expect(fixture.innerHTML).toBe("

3

"); + widget.state.flag = 'false'; + await widget.render(); + expect(fixture.innerHTML).toBe("

4

"); + }); + + test("t-set in t-if", async () => { + // Weird that code block within 'if' leaks outside of it + // Python does the same + class SomeWidget extends Component { + static template = xml` +
+ + + + + + + + + + +

+
`; + + state = {flag: 'if'}; + } + const widget = new SomeWidget(); + await widget.mount(fixture); + + expect(fixture.innerHTML).toBe("

2

"); + widget.state.flag = 'elif'; + await widget.render(); + expect(fixture.innerHTML).toBe("

3

"); + widget.state.flag = 'false'; + await widget.render(); + expect(fixture.innerHTML).toBe("

4

"); + }); + + test("t-set can't alter component", async () => { + class SomeWidget extends Component { + static template = xml` +
+

+ +

+
`; + + iter = 1; + } + const widget = new SomeWidget(); + await widget.mount(fixture); + + expect(fixture.innerHTML).toBe("

1

5

"); + expect(widget.iter).toBe(1); + expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot(); + }); + + test("t-set can't alter from within callee", async () => { + env.qweb.addTemplate("ChildWidget", `
`); + class SomeWidget extends Component { + static template = xml` +
+ +

+ +

+
`; + } + const widget = new SomeWidget(); + await widget.mount(fixture); + + expect(fixture.innerHTML).toBe("

source

sourcecalled

source

"); + expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot(); + }); + + test("t-set can't alter in t-call body", async () => { + env.qweb.addTemplate("ChildWidget", `
`); + class SomeWidget extends Component { + static template = xml` +
+ +

+ + + +

+
`; + } + const widget = new SomeWidget(); + await widget.mount(fixture); + + expect(fixture.innerHTML).toBe("

source

inCallcalled

source

"); + expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot(); + }); + + test("slot setted value (with t-set) not accessible with t-esc", async () => { + class ChildWidget extends Component { + static template = xml`
`; + } + class SomeWidget extends Component { + static components = { ChildWidget }; + static template = xml` +
+ +

+ + + +

+
`; + } + const widget = new SomeWidget(); + await widget.mount(fixture); + + expect(fixture.innerHTML).toBe("

source

called

source

"); + expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot(); + }); + + test("t-set not altered by child widget", async () => { + let child; + class ChildWidget extends Component { + static template = xml`
`; + iter = 'child'; + constructor() { + super(...arguments); + child = this; + } + } + class SomeWidget extends Component { + static components = { ChildWidget }; + static template = xml` +
+ +

+ +

+
`; + } + const widget = new SomeWidget(); + await widget.mount(fixture); + + expect(fixture.innerHTML).toBe("

source

childcalled

source

"); + expect(child.iter).toBe('child'); + expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot(); + }); + + test("t-set outside modified in t-foreach increment-after operator", async () => { + class SomeWidget extends Component { + static template = xml` +
+ + +

InLoop:

+ + +

EndLoop:

+
`; + + state = useState({values: ['a', 'b']}); + } + const widget = new SomeWidget(); + await widget.mount(fixture); + expect(fixture.innerHTML).toBe("

InLoop: 0

InLoop: 1

EndLoop: 0

"); + }); + + test("t-set outside modified in t-foreach increment-before operator", async () => { + class SomeWidget extends Component { + static template = xml` +
+ + +

InLoop:

+ + +

EndLoop:

+
`; + + state = useState({values: ['a', 'b']}); + } + const widget = new SomeWidget(); + await widget.mount(fixture); + expect(fixture.innerHTML).toBe("

InLoop: 0

InLoop: 1

EndLoop: 1

"); + }); }); describe("random stuff/miscellaneous", () => { diff --git a/tests/qweb/__snapshots__/qweb.test.ts.snap b/tests/qweb/__snapshots__/qweb.test.ts.snap index 4026a6f1..7e37322e 100644 --- a/tests/qweb/__snapshots__/qweb.test.ts.snap +++ b/tests/qweb/__snapshots__/qweb.test.ts.snap @@ -421,7 +421,7 @@ exports[`foreach does not pollute the rendering context 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.item_first = i1 === 0 scope.item_last = i1 === _length3 - 1 @@ -456,7 +456,7 @@ exports[`foreach iterate on items (on a element node) 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.item_first = i1 === 0 scope.item_last = i1 === _length3 - 1 @@ -494,7 +494,7 @@ exports[`foreach iterate on items 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.item_first = i1 === 0 scope.item_last = i1 === _length3 - 1 @@ -541,7 +541,7 @@ exports[`foreach iterate, dict param 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.item_first = i1 === 0 scope.item_last = i1 === _length3 - 1 @@ -588,7 +588,7 @@ exports[`foreach iterate, position 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.elem_first = i1 === 0 scope.elem_last = i1 === _length3 - 1 @@ -632,7 +632,7 @@ exports[`foreach t-foreach in t-forach 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.number_first = i1 === 0 scope.number_last = i1 === _length3 - 1 @@ -649,7 +649,7 @@ exports[`foreach t-foreach in t-forach 1`] = ` } let _length7 = _7.length; let _origScope9 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i2 = 0; i2 < _length7; i2++) { scope.letter_first = i2 === 0 scope.letter_last = i2 === _length7 - 1 @@ -692,7 +692,7 @@ exports[`foreach warn if no key in some case 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.item_first = i1 === 0 scope.item_last = i1 === _length3 - 1 @@ -757,7 +757,7 @@ exports[`misc global 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.value_first = i1 === 0 scope.value_last = i1 === _length3 - 1 @@ -782,7 +782,7 @@ exports[`misc global 1`] = ` scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.foo = 'aaa'; + utils.getScope(scope, 'foo').foo = 'aaa'; scope[utils.zero] = c__0; } let k14 = \`__14__\${key1}__\`; @@ -791,7 +791,7 @@ exports[`misc global 1`] = ` } 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})); - scope.foo = 'bbb'; + 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})); scope[utils.zero] = c__0; @@ -1241,7 +1241,7 @@ exports[`t-call (template calling recursive template, part 2 1`] = ` scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.node = scope['root']; + 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__'})); @@ -1279,7 +1279,7 @@ exports[`t-call (template calling recursive template, part 2 2`] = ` } let _length6 = _6.length; let _origScope8 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length6; i1++) { scope.subtree_first = i1 === 0 scope.subtree_last = i1 === _length6 - 1 @@ -1292,7 +1292,7 @@ exports[`t-call (template calling recursive template, part 2 2`] = ` scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.node = scope['subtree']; + utils.getScope(scope, 'node').node = scope['subtree']; scope[utils.zero] = c__0; } let k10 = \`__10__\${key0}__\${key1}__\`; @@ -1318,7 +1318,7 @@ exports[`t-call (template calling recursive template, part 3 1`] = ` scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.node = scope['root']; + 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__'})); @@ -1356,7 +1356,7 @@ exports[`t-call (template calling recursive template, part 3 2`] = ` } let _length6 = _6.length; let _origScope8 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length6; i1++) { scope.subtree_first = i1 === 0 scope.subtree_last = i1 === _length6 - 1 @@ -1369,7 +1369,7 @@ exports[`t-call (template calling recursive template, part 3 2`] = ` scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.node = scope['subtree']; + utils.getScope(scope, 'node').node = scope['subtree']; scope[utils.zero] = c__0; } let k10 = \`__10__\${key0}__\${key1}__\`; @@ -1395,7 +1395,7 @@ exports[`t-call (template calling scoped parameters 1`] = ` scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.foo = 42; + 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__'})); @@ -1456,7 +1456,7 @@ exports[`t-call (template calling t-call with t-set inside and outside 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.v_first = i1 === 0 scope.v_last = i1 === _length3 - 1 @@ -1464,13 +1464,13 @@ exports[`t-call (template calling t-call with t-set inside and outside 1`] = ` scope.v = _3[i1] scope.v_value = _4[i1] let key1 = i1; - scope.val = scope['v'].val; + utils.getScope(scope, 'val').val = scope['v'].val; { let _origScope8 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.val3 = scope.val*3; + utils.getScope(scope, 'val3').val3 = scope.val*3; scope[utils.zero] = c__0; } let k9 = \`__9__\${key1}__\`; @@ -1517,7 +1517,7 @@ exports[`t-call (template calling t-call, conditional and t-set in t-call body 1 scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.v = 'success'; + 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__'})); @@ -1580,7 +1580,7 @@ exports[`t-call (template calling with unused setbody 1`] = ` scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.qux = 3; + utils.getScope(scope, 'qux').qux = 3; scope[utils.zero] = c__0; } result = [] @@ -1631,7 +1631,7 @@ exports[`t-call (template calling with used set body 1`] = ` scope = Object.assign(Object.create(context), scope); { let c__0 = []; - scope.foo = 'ok'; + 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__'})); @@ -2156,7 +2156,7 @@ exports[`t-key t-key directive in a list 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.beer_first = i1 === 0 scope.beer_last = i1 === _length3 - 1 @@ -2260,7 +2260,7 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.action_first = i1 === 0 scope.action_last = i1 === _length3 - 1 @@ -2517,7 +2517,7 @@ exports[`t-on t-on with prevent modifier in t-foreach 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.project_first = i1 === 0 scope.project_last = i1 === _length3 - 1 @@ -2763,7 +2763,7 @@ exports[`t-ref refs in a loop 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.item_first = i1 === 0 scope.item_last = i1 === _length3 - 1 @@ -2990,6 +2990,7 @@ exports[`t-set t-set should reuse variable if possible 1`] = ` "function anonymous(context, extra ) { // Template name: \\"test\\" + let utils = this.constructor.utils; let scope = Object.create(context); let h = this.h; let c1 = [], p1 = {key:1}; @@ -3004,7 +3005,7 @@ exports[`t-set t-set should reuse variable if possible 1`] = ` } let _length3 = _3.length; let _origScope5 = scope; - scope = Object.assign(Object.create(context), scope); + scope = Object.create(scope); for (let i1 = 0; i1 < _length3; i1++) { scope.elem_first = i1 === 0 scope.elem_last = i1 === _length3 - 1 @@ -3022,7 +3023,7 @@ exports[`t-set t-set should reuse variable if possible 1`] = ` if (scope.v != null) { c7.push({text: scope.v}); } - scope.v = scope['elem']; + utils.getScope(scope, 'v').v = scope['elem']; } scope = _origScope5; return vn1;