[FIX] qweb/component: refactoring of scoping/variables/slots

This commit is a significant refactoring of the internal of QWeb. It
simplifies the way variables/scoping and slots interact together.  The
main idea is that we use a simple scope object instead of a
context/var/scope object.

This commit also implement the actual correct QWeb semantic for the
t-call directive with a sub body.  Before, we simply extracted the
variables from the body and injected them at the top of the sub
template.  We now simply compile the body before the sub template.

This is a joint work with Lucas (lpe).

closes #541
closes #544
closes #545

closes #557
closes #556
This commit is contained in:
Géry Debongnie
2019-12-07 22:56:00 +01:00
parent b890e7ceae
commit ce9c2f8613
18 changed files with 1625 additions and 1279 deletions
+5 -5
View File
@@ -5,17 +5,17 @@ exports[`Link component can render simple cases 1`] = `
) {
// Template name: \\"__template__1\\"
let utils = this.constructor.utils;
let owner = context;
let scope = Object.create(context);
var h = this.h;
let _5 = utils.toObj({'router-link-active':context['isActive']});
var _6 = context['href'];
let _5 = utils.toObj({'router-link-active':scope['isActive']});
var _6 = scope['href'];
let c7 = [], p7 = {key:7,attrs:{href: _6},class:_5,on:{}};
var vn7 = h('a', p7, c7);
extra.handlers['click' + 7] = extra.handlers['click' + 7] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['navigate'];if (fn) { fn.call(owner, e); } else { context.navigate; }};
extra.handlers['click' + 7] = extra.handlers['click' + 7] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['navigate'];if (fn) { fn.call(context, e); } else { context.navigate; }};
p7.on['click'] = extra.handlers['click' + 7];
const slot8 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
if (slot8) {
slot8.call(this, context.__owl__.parent, Object.assign({}, extra, {parentNode: c7, parent: extra.parent || owner, vars: extra.fiber.vars}));
slot8.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c7, parent: extra.parent || context}));
}
return vn7;
}"
@@ -7,32 +7,32 @@ exports[`RouteComponent can render simple cases 1`] = `
let utils = this.constructor.utils;
let QWeb = this.constructor;
let parent = context;
let owner = context;
let scope = Object.create(context);
let result;
var h = this.h;
if (context['routeComponent']) {
const nodeKey5 = context['env'].router.currentRouteName;
if (scope['routeComponent']) {
const nodeKey5 = scope['env'].router.currentRouteName;
//COMPONENT
let k7 = \`__8__\` + nodeKey5;
let w6 = k7 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k7]] : false;
let vn9 = {};
result = vn9;
let props6 = Object.assign({}, context['env'].router.currentParams);
let props6 = Object.assign({}, scope['env'].router.currentParams);
if (w6 && w6.__owl__.currentFiber && !w6.__owl__.vnode) {
w6.destroy();
w6 = false;
}
if (w6) {
w6.__updateProps(props6, extra.fiber, undefined, undefined);
w6.__updateProps(props6, extra.fiber, undefined);
let pvnode = w6.__owl__.pvnode;
utils.defineProxy(vn9, pvnode);
} else {
let componentKey6 = \`routeComponent\`;
let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| context['routeComponent'];
let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| scope['routeComponent'];
if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')}
w6 = new W6(parent, props6);
parent.__owl__.cmap[k7] = w6.__owl__.id;
let fiber = w6.__prepare(extra.fiber, undefined, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
let fiber = w6.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
let pvnode = h('dummy', {key: k7, hook: {remove() {},destroy(vn) {w6.destroy();}}});
utils.defineProxy(vn9, pvnode);
w6.__owl__.pvnode = pvnode;