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;