From 3c38bbc076a510bf3ebe6ecfbf98cdebb8fe8951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 24 Oct 2019 21:20:52 +0200 Subject: [PATCH] [REF] component: large cleanup of concurrency branch We remove here old comments, add some tests and documentation, and in general, make sure the state of the code is in a good shape part of #330 --- src/component/component.ts | 66 ++- src/component/directive.ts | 125 ++--- src/component/fiber.ts | 54 ++- src/component/scheduler.ts | 55 ++- src/context.ts | 9 +- src/qweb/base_directives.ts | 4 +- src/store.ts | 4 +- tests/__snapshots__/animations.test.ts.snap | 30 +- .../__snapshots__/component.test.ts.snap | 455 ++++++++---------- .../props_validation.test.ts.snap | 17 +- tests/component/component.test.ts | 97 +++- tests/component/props_validation.test.ts | 7 +- tests/helpers.ts | 34 +- .../route_component.test.ts.snap | 15 +- 14 files changed, 530 insertions(+), 442 deletions(-) diff --git a/src/component/component.ts b/src/component/component.ts index f08ad7ff..99e5a2e8 100644 --- a/src/component/component.ts +++ b/src/component/component.ts @@ -1,10 +1,10 @@ import { Observer } from "../core/observer"; import { CompiledTemplate, QWeb } from "../qweb/index"; import { h, patch, VNode } from "../vdom/index"; -import { Fiber } from "./fiber"; -import { scheduler } from "./scheduler"; import "./directive"; +import { Fiber } from "./fiber"; import "./props_validation"; +import { Scheduler } from "./scheduler"; /** * Owl Component System @@ -20,6 +20,8 @@ import "./props_validation"; //------------------------------------------------------------------------------ // Types/helpers //------------------------------------------------------------------------------ +const raf = window.requestAnimationFrame.bind(window); +export const scheduler = new Scheduler(raf); /** * An Env (environment) is an object that will be (mostly) shared between all @@ -62,7 +64,7 @@ interface Internal { boundHandlers: { [key: number]: any }; observer: Observer | null; - render: CompiledTemplate; + renderFn: CompiledTemplate; mountedCB: Function | null; willUnmountCB: Function | null; willPatchCB: Function | null; @@ -179,7 +181,7 @@ export class Component { willStartCB: null, willUpdatePropsCB: null, observer: null, - render: qweb.render.bind(qweb, this.__getTemplate(qweb)), + renderFn: qweb.render.bind(qweb, this.__getTemplate(qweb)), classObj: null, refs: null }; @@ -280,41 +282,31 @@ export class Component { if (__owl__.isMounted) { return Promise.resolve(); } - const fiber = new Fiber(null, this, this.props, undefined, undefined, false); - if (!__owl__.vnode) { - this.__prepareAndRender(fiber); - return new Promise(resolve => { - scheduler.addFiber(fiber, () => { - if (!__owl__.isDestroyed) { - this.__patch(fiber.vnode); - target.appendChild(this.el!); - if (document.body.contains(target)) { - this.__callMounted(); - } - } - resolve(); - }); - }); - } else if (renderBeforeRemount) { - this.__render(fiber); - return new Promise(resolve => { - scheduler.addFiber(fiber, () => { - if (!__owl__.isDestroyed) { - this.__patch(fiber.vnode); - target.appendChild(this.el!); - if (document.body.contains(target)) { - this.__callMounted(); - } - } - resolve(); - }); - }); - } else { + if (__owl__.vnode && !renderBeforeRemount) { target.appendChild(this.el!); if (document.body.contains(target)) { this.__callMounted(); } + return; } + const fiber = new Fiber(null, this, this.props, undefined, undefined, false); + if (!__owl__.vnode) { + this.__prepareAndRender(fiber); + } else { + this.__render(fiber); + } + return new Promise(resolve => { + scheduler.addFiber(fiber, () => { + if (!__owl__.isDestroyed) { + this.__patch(fiber.vnode); + target.appendChild(this.el!); + if (document.body.contains(target)) { + this.__callMounted(); + } + } + resolve(); + }); + }); } /** @@ -350,7 +342,7 @@ export class Component { return new Promise(resolve => { scheduler.addFiber(fiber.root, () => { if (__owl__.isMounted && fiber === fiber.root) { - fiber.__applyPatchQueue(); + fiber.patchComponents(); } resolve(); }); @@ -588,7 +580,7 @@ export class Component { } let vnode; try { - vnode = __owl__.render!(this, { + vnode = __owl__.renderFn!(this, { handlers: __owl__.boundHandlers, fiber: fiber }); @@ -674,7 +666,7 @@ Fiber.prototype.handleError = function(error) { * If there are no such component, we destroy everything. This is better than * being in a corrupted state. */ -export function errorHandler(error: Error, fiber: Fiber) { +function errorHandler(error: Error, fiber: Fiber) { let canCatch = false; let component = fiber.component; let qweb = component.env.qweb; diff --git a/src/component/directive.ts b/src/component/directive.ts index e4667fd3..4c3b3959 100644 --- a/src/component/directive.ts +++ b/src/component/directive.ts @@ -240,7 +240,6 @@ QWeb.addDirective({ // want to evaluate it only once) ctx.addLine(`let key${keyID} = 'key' + ${key};`); } - ctx.addLine(`let def${defID};`); let locationExpr = `\`__${ctx.generateID()}__`; for (let i = 0; i < ctx.loopNumber - 1; i++) { @@ -376,7 +375,69 @@ QWeb.addDirective({ ctx.addLine(`w${componentID} = false;`); ctx.closeIf(); - ctx.addIf(`!w${componentID}`); + let registerCode = ""; + if (shouldProxy) { + registerCode = `utils.defineProxy(vn${ctx.rootNode}, pvnode);`; + } + + // SLOTS + const varDefs: string[] = []; + const hasSlots = node.childNodes.length; + if (hasSlots) { + ctx.rootContext.shouldTrackScope = true; + for (let v of Object.values(ctx.variables)) { + if (v["id"]) { + varDefs.push(v["id"]); + } + } + } + + let scopeVars; + if (hasSlots) { + let scope = ctx.scopeVars.length ? `Object.assign({}, scope)` : `{}`; + let vars = varDefs.length ? `{${varDefs.join(",")}}` : "undefined"; + scopeVars = `${scope}, ${vars}`; + } else { + scopeVars = "undefined, undefined"; + } + + ctx.addIf(`w${componentID}`); + + // need to update component + let patchQueueCode = keepAlive ? `fiber${componentID}` : "extra.fiber"; + if (keepAlive) { + // if we have t-keepalive="1", the component could be unmounted, but then + // we __updateProps is called. This is ok, but we do not want to call + // the willPatch/patched hooks of the component in this case, so we + // disable the patch queue + patchQueueCode = `w${componentID}.__owl__.isMounted ? extra.fiber : fiber${componentID}`; + } + if (QWeb.dev) { + ctx.addLine(`utils.validateProps(w${componentID}.constructor, props${componentID})`); + } + let styleCode = ""; + if (tattStyle) { + styleCode = `.then(()=>{if (w${componentID}.__owl__.isDestroyed) {return};w${componentID}.el.style=${tattStyle};});`; + } + ctx.addLine( + `w${componentID}.__updateProps(props${componentID}, ${patchQueueCode}${scopeVars && + ", " + scopeVars}, sibling)${styleCode};` + ); + ctx.addLine(`let pvnode = w${componentID}.__owl__.pvnode;`); + let keepAliveCode = ""; + if (keepAlive) { + keepAliveCode = `pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w${componentID}.el,vn.elm);vn.elm=w${componentID}.el;w${componentID}.__remount();};`; + ctx.addLine(keepAliveCode); + } + if (registerCode) { + ctx.addLine(registerCode); + } + if (ctx.parentNode) { + ctx.addLine(`c${ctx.parentNode}.push(pvnode);`); + } + + ctx.addElse(); + // new component let dynamicFallback = ""; if (!value.match(INTERP_REGEXP)) { @@ -395,17 +456,7 @@ QWeb.addDirective({ ctx.addLine(`w${componentID} = new W${componentID}(parent, props${componentID});`); ctx.addLine(`parent.__owl__.cmap[${templateId}] = w${componentID}.__owl__.id;`); - // SLOTS - const varDefs: string[] = []; - const hasSlots = node.childNodes.length; if (hasSlots) { - ctx.rootContext.shouldTrackScope = true; - for (let v of Object.values(ctx.variables)) { - if (v["id"]) { - varDefs.push(v["id"]); - } - } - const clone = node.cloneNode(true); const slotNodes = clone.querySelectorAll("[t-set]"); const slotId = QWeb.nextSlotId++; @@ -430,20 +481,8 @@ QWeb.addDirective({ } } - let scopeVars; - if (hasSlots) { - let scope = ctx.scopeVars.length ? `Object.assign({}, scope)` : `{}`; - let vars = varDefs.length ? `{${varDefs.join(",")}}` : "undefined"; - scopeVars = `${scope}, ${vars}`; - } else { - scopeVars = "undefined, undefined"; - } - ctx.addLine(`def${defID} = w${componentID}.__prepare(extra.fiber, ${scopeVars}, sibling);`); + ctx.addLine(`let def${defID} = w${componentID}.__prepare(extra.fiber, ${scopeVars}, sibling);`); // hack: specify empty remove hook to prevent the node from being removed from the DOM - let registerCode = ""; - if (shouldProxy) { - registerCode = `utils.defineProxy(vn${ctx.rootNode}, pvnode);`; - } ctx.addLine( `let pvnode = h('dummy', {key: ${templateId}, hook: {insert(vn) { let nvn=w${componentID}.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;${refExpr}${transitionsInsertCode}},remove() {},destroy(vn) {${finalizeComponentCode}}}});` ); @@ -459,47 +498,13 @@ QWeb.addDirective({ } ctx.addLine(`w${componentID}.__owl__.pvnode = pvnode;`); - ctx.addElse(); - // need to update component - let patchQueueCode = keepAlive ? `fiber${componentID}` : "extra.fiber"; - if (keepAlive) { - // if we have t-keepalive="1", the component could be unmounted, but then - // we __updateProps is called. This is ok, but we do not want to call - // the willPatch/patched hooks of the component in this case, so we - // disable the patch queue - patchQueueCode = `w${componentID}.__owl__.isMounted ? extra.fiber : fiber${componentID}`; - } - if (QWeb.dev) { - ctx.addLine(`utils.validateProps(w${componentID}.constructor, props${componentID})`); - } - ctx.addLine( - `def${defID} = def${defID} || w${componentID}.__updateProps(props${componentID}, ${patchQueueCode}${scopeVars && - ", " + scopeVars}, sibling);` - ); - ctx.addLine(`let pvnode = w${componentID}.__owl__.pvnode;`); - let keepAliveCode = ""; - if (keepAlive) { - keepAliveCode = `pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w${componentID}.el,vn.elm);vn.elm=w${componentID}.el;w${componentID}.__remount();};`; - ctx.addLine(keepAliveCode); - } - if (registerCode) { - ctx.addLine(registerCode); - } - if (ctx.parentNode) { - ctx.addLine(`c${ctx.parentNode}.push(pvnode);`); - } - if (tattStyle) { - ctx.addLine( - `def${defID} = def${defID}.then(()=>{if (w${componentID}.__owl__.isDestroyed) {return};w${componentID}.el.style=${tattStyle};});` - ); - } ctx.closeIf(); if (classObj) { ctx.addLine(`w${componentID}.__owl__.classObj=${classObj};`); } - ctx.addLine(`sibling = w${componentID}.__owl__.currentFiber;`); + ctx.addLine(`sibling = w${componentID}.__owl__.currentFiber || sibling;`); return true; } diff --git a/src/component/fiber.ts b/src/component/fiber.ts index 17435e28..157e3b00 100644 --- a/src/component/fiber.ts +++ b/src/component/fiber.ts @@ -1,17 +1,46 @@ import { VNode } from "../vdom/index"; import { Component } from "./component"; + /** + * Owl Fiber Class + * * Fibers are small abstractions designed to contain all the internal state - * associated to a "rendering work unit", relative to a specific component. + * associated with a "rendering work unit", relative to a specific component. * * A rendering will cause the creation of a fiber for each impacted components. + * + * Fibers capture all that necessary information, which is critical to owl + * asynchronous rendering pipeline. Fibers can be cancelled, can be in different + * states and in general determine the state of the rendering. */ + export class Fiber { + // The force attribute determines if a rendering should bypass the `shouldUpdate` + // method potentially implemented by a component. It is usually set to false. force: boolean; + + // isCancelled means that the rendering corresponding to this fiber and its + // children is cancelled. No extra work should be done. isCancelled: boolean = false; + + // the fibers corresponding to component updates (updateProps) need to call + // the willPatch and patched hooks from the corresponding component. However, + // fibers corresponding to a new component do not need to do that. So, the + // shouldPatch hook is the boolean that we check whenever we need to apply + // a patch. shouldPatch: boolean = true; + + // isRendered is the last state of a fiber. If true, this means that it has + // been rendered and is inert (so, it should not be taken into account when + // counting the number of active fibers). isRendered: boolean = false; + // the counter number is a critical information. It is only necessary for a + // root fiber. For that fiber, this number counts the number of active sub + // fibers. When that number reaches 0, the fiber can be applied by the + // scheduler. + counter: number = 0; + scope: any; vars: any; props: any; @@ -24,8 +53,6 @@ export class Fiber { sibling: Fiber | null = null; parent: Fiber | null = null; - counter: number = 0; - constructor(parent: Fiber | null, component: Component, props, scope, vars, force) { this.force = force; this.scope = scope; @@ -38,7 +65,7 @@ export class Fiber { let oldFiber = component.__owl__.currentFiber; if (oldFiber && !oldFiber.isCancelled) { - this.__remapFiber(oldFiber); + this._remapFiber(oldFiber); } this.root.counter++; @@ -46,7 +73,13 @@ export class Fiber { component.__owl__.currentFiber = this; } - __remapFiber(oldFiber: Fiber) { + /** + * In some cases, a rendering initiated at some component can detect that it + * should be part of a larger rendering initiated somewhere up the component + * tree. In that case, it needs to cancel the previous rendering and + * remap itself as a part of the current parent rendering. + */ + _remapFiber(oldFiber: Fiber) { oldFiber.cancel(); if (oldFiber === oldFiber.root) { oldFiber.root.counter++; @@ -75,7 +108,7 @@ export class Fiber { * This function has been taken from * https://medium.com/react-in-depth/the-how-and-why-on-reacts-usage-of-linked-list-in-fiber-67f1014d0eb7 */ - __walk(doWork: (f: Fiber) => Fiber | null) { + _walk(doWork: (f: Fiber) => Fiber | null) { let root = this; let current: Fiber = this; while (true) { @@ -103,7 +136,7 @@ export class Fiber { * 2) Call '__patch' on the component of each patch * 3) Call 'patched' on the component of each patch, in reverse order */ - __applyPatchQueue() { + patchComponents() { const patchQueue: Fiber[] = []; const doWork: (Fiber) => Fiber | null = function(f) { if (f.shouldPatch) { @@ -111,7 +144,7 @@ export class Fiber { } return f.child; }; - this.__walk(doWork); + this._walk(doWork); let component: Component = this.component; this.shouldPatch = false; const patchLen = patchQueue.length; @@ -149,8 +182,11 @@ export class Fiber { this.shouldPatch = true; } + /** + * Cancel a fiber and all its children. + */ cancel() { - this.__walk(f => { + this._walk(f => { if (!f.isRendered) { f.root.counter--; } diff --git a/src/component/scheduler.ts b/src/component/scheduler.ts index 40e0f150..23c5f8fe 100644 --- a/src/component/scheduler.ts +++ b/src/component/scheduler.ts @@ -1,14 +1,29 @@ import { Fiber } from "./fiber"; -// scheduler +/** + * Owl Scheduler Class + * + * The scheduler is the part of Owl that will effectively apply a rendering + * whenever a fiber is ready. + * + * Briefly, it can be used to register root fibers. Whenever there is an + * active root fiber, it will poll continuously each animation frame (so, about + * once every 16ms) and whenever a root fiber is ready, it will apply it. + */ + interface Task { fiber: Fiber; callback: () => void; } -export const scheduler = { - tasks: [] as Task[], - isRunning: false, +export class Scheduler { + tasks: Task[] = []; + isRunning: boolean = false; + requestAnimationFrame: typeof window.requestAnimationFrame; + + constructor(requestAnimationFrame) { + this.requestAnimationFrame = requestAnimationFrame; + } addFiber(fiber, callback) { this.tasks.push({ fiber, callback }); @@ -16,7 +31,12 @@ export const scheduler = { return; } this.scheduleTasks(); - }, + } + + /** + * Process all current tasks. This only applies to the fibers that are ready. + * Other tasks are left unchanged. + */ flush() { let tasks = this.tasks; this.tasks = []; @@ -31,20 +51,17 @@ export const scheduler = { return true; }); this.tasks = tasks.concat(this.tasks); - }, - processTasks() { - this.flush(); - if (this.tasks.length > 0) { - this.scheduleTasks(); - } else { - this.isRunning = false; - } - }, + } scheduleTasks() { this.isRunning = true; - this.requestAnimationFrame(() => this.processTasks()); - }, - - requestAnimationFrame: requestAnimationFrame.bind(window) -}; + this.requestAnimationFrame(() => { + this.flush(); + if (this.tasks.length > 0) { + this.scheduleTasks(); + } else { + this.isRunning = false; + } + }); + } +} diff --git a/src/context.ts b/src/context.ts index 36f8f7f0..3748735b 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,5 +1,4 @@ -import { Component } from "./component/component"; -import { scheduler } from "./component/scheduler"; +import { Component, scheduler } from "./component/component"; import { EventBus } from "./core/event_bus"; import { Observer } from "./core/observer"; import { onWillUnmount } from "./hooks"; @@ -70,7 +69,7 @@ export function useContext(ctx: Context): any { return useContextWithCB(ctx, component, component.render.bind(component)); } -export function useContextWithCB(ctx: Context, component, method): any { +export function useContextWithCB(ctx: Context, component: Component, method): any { const __owl__ = component.__owl__; const id = __owl__.id; const mapping = ctx.mapping; @@ -78,8 +77,8 @@ export function useContextWithCB(ctx: Context, component, method): any { return ctx.state; } mapping[id] = 0; - const renderFn = __owl__.render; - __owl__.render = function(comp, params) { + const renderFn = __owl__.renderFn; + __owl__.renderFn = function(comp, params) { mapping[id] = ctx.id; return renderFn(comp, params); }; diff --git a/src/qweb/base_directives.ts b/src/qweb/base_directives.ts index 44265006..667461f6 100644 --- a/src/qweb/base_directives.ts +++ b/src/qweb/base_directives.ts @@ -133,7 +133,7 @@ QWeb.addDirective({ priority: 20, atNodeEncounter({ node, ctx }): boolean { let cond = ctx.getValue(node.getAttribute("t-if")!); - ctx.addIf(typeof cond === 'string' ? ctx.formatExpression(cond) : cond.id); + ctx.addIf(typeof cond === "string" ? ctx.formatExpression(cond) : cond.id); return false; }, finalize({ ctx }) { @@ -146,7 +146,7 @@ QWeb.addDirective({ priority: 30, atNodeEncounter({ node, ctx }): boolean { let cond = ctx.getValue(node.getAttribute("t-elif")!); - ctx.addLine(`else if (${typeof cond === 'string' ? ctx.formatExpression(cond) : cond.id}) {`); + ctx.addLine(`else if (${typeof cond === "string" ? ctx.formatExpression(cond) : cond.id}) {`); ctx.indent(); return false; }, diff --git a/src/store.ts b/src/store.ts index 33cfcc97..484cefdf 100644 --- a/src/store.ts +++ b/src/store.ts @@ -104,11 +104,11 @@ export function useStore(selector, options: SelectorOptions = {}): any { return true; } return false; - }) + }); useContextWithCB(store, component, function(): Promise | void { let shouldRender = false; - updateFunctions.forEach(function (updateFn) { + updateFunctions.forEach(function(updateFn) { shouldRender = updateFn() || shouldRender; }); if (shouldRender) { diff --git a/tests/__snapshots__/animations.test.ts.snap b/tests/__snapshots__/animations.test.ts.snap index d3382645..29883063 100644 --- a/tests/__snapshots__/animations.test.ts.snap +++ b/tests/__snapshots__/animations.test.ts.snap @@ -12,7 +12,6 @@ exports[`animations t-transition combined with component 1`] = ` let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -20,13 +19,17 @@ exports[`animations t-transition combined with component 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;utils.transitionInsert(vn, 'chimay');},remove() {},destroy(vn) {let finalize = () => { w3.destroy(); }; @@ -35,12 +38,8 @@ exports[`animations t-transition combined with component 1`] = ` def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -58,7 +57,6 @@ exports[`animations t-transition combined with t-component and t-if 1`] = ` var vn1 = h('div', p1, c1); if (context['state'].display) { //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -66,13 +64,17 @@ exports[`animations t-transition combined with t-component and t-if 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;utils.transitionInsert(vn, 'chimay');},remove() {},destroy(vn) {let finalize = () => { w3.destroy(); }; @@ -81,12 +83,8 @@ exports[`animations t-transition combined with t-component and t-if 1`] = ` def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; } return vn1; }" diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap index 1d106281..4760ba62 100644 --- a/tests/component/__snapshots__/component.test.ts.snap +++ b/tests/component/__snapshots__/component.test.ts.snap @@ -41,7 +41,6 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for context.blip = _6[i2]; context.blip_value = _7[i2]; //COMPONENT - let def8; let templateId9 = \`__10__\${i1}__\${i2}__\`; let w9 = templateId9 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId9]] : false; let props9 = {blip:context['blip']}; @@ -49,24 +48,24 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for w9.destroy(); w9 = false; } - if (!w9) { + if (w9) { + w9.__updateProps(props9, extra.fiber, undefined, undefined, sibling); + let pvnode = w9.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey9 = \`Child\`; let W9 = context.constructor.components[componentKey9] || QWeb.components[componentKey9]|| context['Child']; if (!W9) {throw new Error('Cannot find the definition of component \\"' + componentKey9 + '\\"')} w9 = new W9(parent, props9); parent.__owl__.cmap[templateId9] = w9.__owl__.id; - def8 = w9.__prepare(extra.fiber, undefined, undefined, sibling); + let def8 = w9.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId9, hook: {insert(vn) { let nvn=w9.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w9.destroy();}}}); const fiber = w9.__owl__.currentFiber; def8.then(function () {if (w9.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w9.__owl__.pvnode = pvnode; - } else { - def8 = def8 || w9.__updateProps(props9, extra.fiber, undefined, undefined, sibling); - let pvnode = w9.__owl__.pvnode; - c1.push(pvnode); } - sibling = w9.__owl__.currentFiber; + sibling = w9.__owl__.currentFiber || sibling; } } return vn1; @@ -85,7 +84,6 @@ exports[`class and style attributes with t-component dynamic t-att-style is prop let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; const _5 = context['state'].style; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; @@ -94,25 +92,24 @@ exports[`class and style attributes with t-component dynamic t-att-style is prop w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling).then(()=>{if (w3.__owl__.isDestroyed) {return};w3.el.style=_5;});; + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.style = _5;}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); - def2 = def2.then(()=>{if (w3.__owl__.isDestroyed) {return};w3.el.style=_5;}); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -130,7 +127,6 @@ exports[`class and style attributes with t-component t-att-class is properly add let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; const ref5 = \`child\`; let _6 = {'a':true}; @@ -141,25 +137,25 @@ exports[`class and style attributes with t-component t-att-class is properly add w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;context.__owl__.refs[ref5] = w3;},remove() {},destroy(vn) {w3.destroy();delete context.__owl__.refs[ref5];}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } w3.__owl__.classObj=_6; - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -191,7 +187,6 @@ exports[`class and style attributes with t-component t-att-class is properly add let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; const ref5 = \`child\`; let _6 = {'a':true}; @@ -202,25 +197,25 @@ exports[`class and style attributes with t-component t-att-class is properly add w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;context.__owl__.refs[ref5] = w3;},remove() {},destroy(vn) {w3.destroy();delete context.__owl__.refs[ref5];}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } w3.__owl__.classObj=_6; - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -252,7 +247,6 @@ exports[`composition sub components dom state with t-keepalive is preserved 1`] var vn1 = h('div', p1, c1); if (context['state'].ok) { //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; const fiber3 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); @@ -261,25 +255,25 @@ exports[`composition sub components dom state with t-keepalive is preserved 1`] w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, w3.__owl__.isMounted ? extra.fiber : fiber3, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w3.el,vn.elm);vn.elm=w3.el;w3.__remount();}; + c1.push(pvnode); + } else { let componentKey3 = \`InputWidget\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['InputWidget']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.unmount();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, w3.__owl__.isMounted ? extra.fiber : fiber3, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w3.el,vn.elm);vn.elm=w3.el;w3.__remount();}; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; } return vn1; }" @@ -313,7 +307,6 @@ exports[`composition sub components with some state rendered in a loop 1`] = ` context.number_value = _4[i1]; //COMPONENT let key7 = 'key' + context['number']; - let def5; let templateId6 = \`__8__\` + key7; let w6 = templateId6 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId6]] : false; let props6 = {}; @@ -321,24 +314,24 @@ exports[`composition sub components with some state rendered in a loop 1`] = ` w6.destroy(); w6 = false; } - if (!w6) { + if (w6) { + w6.__updateProps(props6, extra.fiber, undefined, undefined, sibling); + let pvnode = w6.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey6 = \`ChildWidget\`; let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| context['ChildWidget']; if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} w6 = new W6(parent, props6); parent.__owl__.cmap[templateId6] = w6.__owl__.id; - def5 = w6.__prepare(extra.fiber, undefined, undefined, sibling); + let def5 = w6.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId6, hook: {insert(vn) { let nvn=w6.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w6.destroy();}}}); const fiber = w6.__owl__.currentFiber; def5.then(function () {if (w6.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w6.__owl__.pvnode = pvnode; - } else { - def5 = def5 || w6.__updateProps(props6, extra.fiber, undefined, undefined, sibling); - let pvnode = w6.__owl__.pvnode; - c1.push(pvnode); } - sibling = w6.__owl__.currentFiber; + sibling = w6.__owl__.currentFiber || sibling; } return vn1; }" @@ -356,7 +349,6 @@ exports[`composition t-component with dynamic value 1`] = ` let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -364,24 +356,24 @@ exports[`composition t-component with dynamic value 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = (context['state'].widget); let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -398,7 +390,6 @@ exports[`composition t-component with dynamic value 2 1`] = ` let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -406,24 +397,24 @@ exports[`composition t-component with dynamic value 2 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Widget\${context['state'].widget}\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -440,7 +431,6 @@ exports[`dynamic t-props basic use 1`] = ` let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = Object.assign({}, context['some'].obj); @@ -448,24 +438,24 @@ exports[`dynamic t-props basic use 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -483,7 +473,6 @@ exports[`lifecycle hooks willPatch/patched hook with t-keepalive 1`] = ` var vn1 = h('div', p1, c1); if (context['state'].flag) { //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; const fiber3 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); @@ -492,25 +481,25 @@ exports[`lifecycle hooks willPatch/patched hook with t-keepalive 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, w3.__owl__.isMounted ? extra.fiber : fiber3, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w3.el,vn.elm);vn.elm=w3.el;w3.__remount();}; + c1.push(pvnode); + } else { let componentKey3 = \`ChildWidget\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['ChildWidget']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.unmount();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, w3.__owl__.isMounted ? extra.fiber : fiber3, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w3.el,vn.elm);vn.elm=w3.el;w3.__remount();}; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; } return vn1; }" @@ -532,7 +521,6 @@ exports[`other directives with t-component t-on with getter as handler 1`] = ` c1.push({text: _2}); } //COMPONENT - let def3; let templateId4 = \`__5__\`; let w4 = templateId4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId4]] : false; let props4 = {}; @@ -540,24 +528,24 @@ exports[`other directives with t-component t-on with getter as handler 1`] = ` w4.destroy(); w4 = false; } - if (!w4) { + if (w4) { + w4.__updateProps(props4, extra.fiber, undefined, undefined, sibling); + let pvnode = w4.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey4 = \`Child\`; let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| context['Child']; if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[templateId4] = w4.__owl__.id; - def3 = w4.__prepare(extra.fiber, undefined, undefined, sibling); + let def3 = w4.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId4, hook: {insert(vn) { let nvn=w4.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}}); const fiber = w4.__owl__.currentFiber; def3.then(function () {if (w4.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['handler'];if (fn) { fn.call(owner, e); } else { owner.handler; }});}};}); c1.push(pvnode); w4.__owl__.pvnode = pvnode; - } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined, sibling); - let pvnode = w4.__owl__.pvnode; - c1.push(pvnode); } - sibling = w4.__owl__.currentFiber; + sibling = w4.__owl__.currentFiber || sibling; return vn1; }" `; @@ -574,7 +562,6 @@ exports[`other directives with t-component t-on with handler bound to argument 1 let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -582,24 +569,24 @@ exports[`other directives with t-component t-on with handler bound to argument 1 w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, 3, e); } else { owner.onEv; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -616,7 +603,6 @@ exports[`other directives with t-component t-on with handler bound to empty obje let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -624,24 +610,24 @@ exports[`other directives with t-component t-on with handler bound to empty obje w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, {}, e); } else { owner.onEv; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -658,7 +644,6 @@ exports[`other directives with t-component t-on with handler bound to empty obje let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -666,24 +651,24 @@ exports[`other directives with t-component t-on with handler bound to empty obje w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, {}, e); } else { owner.onEv; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -700,7 +685,6 @@ exports[`other directives with t-component t-on with handler bound to object 1`] let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -708,24 +692,24 @@ exports[`other directives with t-component t-on with handler bound to object 1`] w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, {val:3}, e); } else { owner.onEv; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -746,7 +730,6 @@ exports[`other directives with t-component t-on with inline statement 1`] = ` c1.push({text: _2}); } //COMPONENT - let def3; let templateId4 = \`__5__\`; let w4 = templateId4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId4]] : false; let props4 = {}; @@ -754,24 +737,24 @@ exports[`other directives with t-component t-on with inline statement 1`] = ` w4.destroy(); w4 = false; } - if (!w4) { + if (w4) { + w4.__updateProps(props4, extra.fiber, undefined, undefined, sibling); + let pvnode = w4.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey4 = \`Child\`; let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| context['Child']; if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[templateId4] = w4.__owl__.id; - def3 = w4.__prepare(extra.fiber, undefined, undefined, sibling); + let def3 = w4.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId4, hook: {insert(vn) { let nvn=w4.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}}); const fiber = w4.__owl__.currentFiber; def3.then(function () {if (w4.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['state.counter++'];if (fn) { fn.call(owner, e); } else { owner.state.counter++; }});}};}); c1.push(pvnode); w4.__owl__.pvnode = pvnode; - } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined, sibling); - let pvnode = w4.__owl__.pvnode; - c1.push(pvnode); } - sibling = w4.__owl__.currentFiber; + sibling = w4.__owl__.currentFiber || sibling; return vn1; }" `; @@ -788,7 +771,6 @@ exports[`other directives with t-component t-on with no handler (only modifiers) let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -796,24 +778,24 @@ exports[`other directives with t-component t-on with no handler (only modifiers) w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`ComponentA\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['ComponentA']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -830,7 +812,6 @@ exports[`other directives with t-component t-on with prevent and self modifiers let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -838,24 +819,24 @@ exports[`other directives with t-component t-on with prevent and self modifiers w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {e.preventDefault();if (e.target !== vn.elm) {return}const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -872,7 +853,6 @@ exports[`other directives with t-component t-on with self and prevent modifiers let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -880,24 +860,24 @@ exports[`other directives with t-component t-on with self and prevent modifiers w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if (e.target !== vn.elm) {return}e.preventDefault();const fn = owner['onEv'];if (fn) { fn.call(owner, e); } else { owner.onEv; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -914,7 +894,6 @@ exports[`other directives with t-component t-on with self modifier 1`] = ` let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -922,24 +901,24 @@ exports[`other directives with t-component t-on with self modifier 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', function (e) {const fn = owner['onEv1'];if (fn) { fn.call(owner, e); } else { owner.onEv1; }});vn.elm.addEventListener('ev-2', function (e) {if (e.target !== vn.elm) {return}const fn = owner['onEv2'];if (fn) { fn.call(owner, e); } else { owner.onEv2; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -956,7 +935,6 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -964,24 +942,24 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', function (e) {e.stopPropagation();const fn = owner['onEv1'];if (fn) { fn.call(owner, e); } else { owner.onEv1; }});vn.elm.addEventListener('ev-2', function (e) {e.preventDefault();const fn = owner['onEv2'];if (fn) { fn.call(owner, e); } else { owner.onEv2; }});vn.elm.addEventListener('ev-3', function (e) {e.stopPropagation();e.preventDefault();const fn = owner['onEv3'];if (fn) { fn.call(owner, e); } else { owner.onEv3; }});}};}); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -1017,7 +995,6 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = ` var vn1 = h('div', p1, c1); //COMPONENT let key4 = 'key' + 'somestring'; - let def2; let templateId3 = \`__5__\` + key4; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {flag:context['state'].flag}; @@ -1025,24 +1002,24 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -1075,7 +1052,6 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument context.item_value = _4[i1]; //COMPONENT let key7 = 'key' + context['item']; - let def5; let templateId6 = \`__8__\` + key7; let arg9 = context['item']; let w6 = templateId6 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId6]] : false; @@ -1084,24 +1060,24 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument w6.destroy(); w6 = false; } - if (!w6) { + if (w6) { + w6.__updateProps(props6, extra.fiber, undefined, undefined, sibling); + let pvnode = w6.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey6 = \`Child\`; let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| context['Child']; if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} w6 = new W6(parent, props6); parent.__owl__.cmap[templateId6] = w6.__owl__.id; - def5 = w6.__prepare(extra.fiber, undefined, undefined, sibling); + let def5 = w6.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId6, hook: {insert(vn) { let nvn=w6.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w6.destroy();}}}); const fiber = w6.__owl__.currentFiber; def5.then(function () {if (w6.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {const fn = owner['onEv'];if (fn) { fn.call(owner, arg9, e); } else { owner.onEv; }});}};}); c1.push(pvnode); w6.__owl__.pvnode = pvnode; - } else { - def5 = def5 || w6.__updateProps(props6, extra.fiber, undefined, undefined, sibling); - let pvnode = w6.__owl__.pvnode; - c1.push(pvnode); } - sibling = w6.__owl__.currentFiber; + sibling = w6.__owl__.currentFiber || sibling; } return vn1; }" @@ -1324,7 +1300,6 @@ exports[`t-slot directive can define and call slots 1`] = ` let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {}; @@ -1332,25 +1307,25 @@ exports[`t-slot directive can define and call slots 1`] = ` w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + w3.__updateProps(props3, extra.fiber, {}, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Dialog\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Dialog']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; w3.__owl__.slotId = 1; - def2 = w3.__prepare(extra.fiber, {}, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, {}, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, {}, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; @@ -1571,7 +1546,6 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = ` var vn6 = h('li', p6, c6); c2.push(vn6); //COMPONENT - let def7; let templateId8 = \`__9__\` + nodeKey6; let w8 = templateId8 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId8]] : false; let props8 = {to:'/user/'+context['user'].id}; @@ -1579,25 +1553,25 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = ` w8.destroy(); w8 = false; } - if (!w8) { + if (w8) { + w8.__updateProps(props8, extra.fiber, Object.assign({}, scope), undefined, sibling); + let pvnode = w8.__owl__.pvnode; + c6.push(pvnode); + } else { let componentKey8 = \`Link\`; let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8]|| context['Link']; if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')} w8 = new W8(parent, props8); parent.__owl__.cmap[templateId8] = w8.__owl__.id; w8.__owl__.slotId = 1; - def7 = w8.__prepare(extra.fiber, Object.assign({}, scope), undefined, sibling); + let def7 = w8.__prepare(extra.fiber, Object.assign({}, scope), undefined, sibling); let pvnode = h('dummy', {key: templateId8, hook: {insert(vn) { let nvn=w8.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w8.destroy();}}}); const fiber = w8.__owl__.currentFiber; def7.then(function () {if (w8.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c6.push(pvnode); w8.__owl__.pvnode = pvnode; - } else { - def7 = def7 || w8.__updateProps(props8, extra.fiber, Object.assign({}, scope), undefined, sibling); - let pvnode = w8.__owl__.pvnode; - c6.push(pvnode); } - sibling = w8.__owl__.currentFiber; + sibling = w8.__owl__.currentFiber || sibling; } return vn1; }" @@ -1676,7 +1650,6 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` c2.push(vn6); var _7 = 'User '+context['user'].name; //COMPONENT - let def8; let templateId9 = \`__10__\` + nodeKey6; let w9 = templateId9 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId9]] : false; let props9 = {to:'/user/'+context['user'].id}; @@ -1684,25 +1657,25 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` w9.destroy(); w9 = false; } - if (!w9) { + if (w9) { + w9.__updateProps(props9, extra.fiber, Object.assign({}, scope), {_7}, sibling); + let pvnode = w9.__owl__.pvnode; + c6.push(pvnode); + } else { let componentKey9 = \`Link\`; let W9 = context.constructor.components[componentKey9] || QWeb.components[componentKey9]|| context['Link']; if (!W9) {throw new Error('Cannot find the definition of component \\"' + componentKey9 + '\\"')} w9 = new W9(parent, props9); parent.__owl__.cmap[templateId9] = w9.__owl__.id; w9.__owl__.slotId = 1; - def8 = w9.__prepare(extra.fiber, Object.assign({}, scope), {_7}, sibling); + let def8 = w9.__prepare(extra.fiber, Object.assign({}, scope), {_7}, sibling); let pvnode = h('dummy', {key: templateId9, hook: {insert(vn) { let nvn=w9.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w9.destroy();}}}); const fiber = w9.__owl__.currentFiber; def8.then(function () {if (w9.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c6.push(pvnode); w9.__owl__.pvnode = pvnode; - } else { - def8 = def8 || w9.__updateProps(props9, extra.fiber, Object.assign({}, scope), {_7}, sibling); - let pvnode = w9.__owl__.pvnode; - c6.push(pvnode); } - sibling = w9.__owl__.currentFiber; + sibling = w9.__owl__.currentFiber || sibling; } return vn1; }" @@ -1735,7 +1708,6 @@ exports[`t-slot directive slots are rendered with proper context, part 4 1`] = ` var vn1 = h('div', p1, c1); var _2 = 'User '+context['state'].user.name; //COMPONENT - let def3; let templateId4 = \`__5__\`; let w4 = templateId4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId4]] : false; let props4 = {to:'/user/'+context['state'].user.id}; @@ -1743,25 +1715,25 @@ exports[`t-slot directive slots are rendered with proper context, part 4 1`] = ` w4.destroy(); w4 = false; } - if (!w4) { + if (w4) { + w4.__updateProps(props4, extra.fiber, {}, {_2}, sibling); + let pvnode = w4.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey4 = \`Link\`; let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| context['Link']; if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[templateId4] = w4.__owl__.id; w4.__owl__.slotId = 1; - def3 = w4.__prepare(extra.fiber, {}, {_2}, sibling); + let def3 = w4.__prepare(extra.fiber, {}, {_2}, sibling); let pvnode = h('dummy', {key: templateId4, hook: {insert(vn) { let nvn=w4.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}}); const fiber = w4.__owl__.currentFiber; def3.then(function () {if (w4.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w4.__owl__.pvnode = pvnode; - } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, {}, {_2}, sibling); - let pvnode = w4.__owl__.pvnode; - c1.push(pvnode); } - sibling = w4.__owl__.currentFiber; + sibling = w4.__owl__.currentFiber || sibling; return vn1; }" `; @@ -1810,7 +1782,6 @@ exports[`top level sub widgets basic use 1`] = ` let result; var h = this.h; //COMPONENT - let def1; let templateId2 = \`__3__\`; let w2 = templateId2 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId2]] : false; let vn4 = {}; @@ -1820,24 +1791,24 @@ exports[`top level sub widgets basic use 1`] = ` w2.destroy(); w2 = false; } - if (!w2) { + if (w2) { + w2.__updateProps(props2, extra.fiber, undefined, undefined, sibling); + let pvnode = w2.__owl__.pvnode; + utils.defineProxy(vn4, pvnode); + } else { let componentKey2 = \`Child\`; let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| context['Child']; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap[templateId2] = w2.__owl__.id; - def1 = w2.__prepare(extra.fiber, undefined, undefined, sibling); + let def1 = w2.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId2, hook: {insert(vn) { let nvn=w2.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w2.destroy();}}}); const fiber = w2.__owl__.currentFiber; def1.then(function () {if (w2.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); utils.defineProxy(vn4, pvnode); w2.__owl__.pvnode = pvnode; - } else { - def1 = def1 || w2.__updateProps(props2, extra.fiber, undefined, undefined, sibling); - let pvnode = w2.__owl__.pvnode; - utils.defineProxy(vn4, pvnode); } - sibling = w2.__owl__.currentFiber; + sibling = w2.__owl__.currentFiber || sibling; return result; }" `; @@ -1854,7 +1825,6 @@ exports[`top level sub widgets can select a sub widget 1`] = ` var h = this.h; if (context['env'].flag) { //COMPONENT - let def1; let templateId2 = \`__3__\`; let w2 = templateId2 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId2]] : false; let vn4 = {}; @@ -1864,28 +1834,27 @@ exports[`top level sub widgets can select a sub widget 1`] = ` w2.destroy(); w2 = false; } - if (!w2) { + if (w2) { + w2.__updateProps(props2, extra.fiber, undefined, undefined, sibling); + let pvnode = w2.__owl__.pvnode; + utils.defineProxy(vn4, pvnode); + } else { let componentKey2 = \`Child\`; let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| context['Child']; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap[templateId2] = w2.__owl__.id; - def1 = w2.__prepare(extra.fiber, undefined, undefined, sibling); + let def1 = w2.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId2, hook: {insert(vn) { let nvn=w2.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w2.destroy();}}}); const fiber = w2.__owl__.currentFiber; def1.then(function () {if (w2.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); utils.defineProxy(vn4, pvnode); w2.__owl__.pvnode = pvnode; - } else { - def1 = def1 || w2.__updateProps(props2, extra.fiber, undefined, undefined, sibling); - let pvnode = w2.__owl__.pvnode; - utils.defineProxy(vn4, pvnode); } - sibling = w2.__owl__.currentFiber; + sibling = w2.__owl__.currentFiber || sibling; } if (!context['env'].flag) { //COMPONENT - let def5; let templateId6 = \`__7__\`; let w6 = templateId6 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId6]] : false; let vn8 = {}; @@ -1895,24 +1864,24 @@ exports[`top level sub widgets can select a sub widget 1`] = ` w6.destroy(); w6 = false; } - if (!w6) { + if (w6) { + w6.__updateProps(props6, extra.fiber, undefined, undefined, sibling); + let pvnode = w6.__owl__.pvnode; + utils.defineProxy(vn8, pvnode); + } else { let componentKey6 = \`OtherChild\`; let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| context['OtherChild']; if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} w6 = new W6(parent, props6); parent.__owl__.cmap[templateId6] = w6.__owl__.id; - def5 = w6.__prepare(extra.fiber, undefined, undefined, sibling); + let def5 = w6.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId6, hook: {insert(vn) { let nvn=w6.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w6.destroy();}}}); const fiber = w6.__owl__.currentFiber; def5.then(function () {if (w6.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); utils.defineProxy(vn8, pvnode); w6.__owl__.pvnode = pvnode; - } else { - def5 = def5 || w6.__updateProps(props6, extra.fiber, undefined, undefined, sibling); - let pvnode = w6.__owl__.pvnode; - utils.defineProxy(vn8, pvnode); } - sibling = w6.__owl__.currentFiber; + sibling = w6.__owl__.currentFiber || sibling; } return result; }" diff --git a/tests/component/__snapshots__/props_validation.test.ts.snap b/tests/component/__snapshots__/props_validation.test.ts.snap index e56fac8e..779a6193 100644 --- a/tests/component/__snapshots__/props_validation.test.ts.snap +++ b/tests/component/__snapshots__/props_validation.test.ts.snap @@ -12,7 +12,6 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] = let c1 = [], p1 = {key:1}; var vn1 = h('div', p1, c1); //COMPONENT - let def2; let templateId3 = \`__4__\`; let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false; let props3 = {message:1}; @@ -20,25 +19,25 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] = w3.destroy(); w3 = false; } - if (!w3) { + if (w3) { + utils.validateProps(w3.constructor, props3) + w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); + let pvnode = w3.__owl__.pvnode; + c1.push(pvnode); + } else { let componentKey3 = \`Child\`; let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['Child']; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[templateId3] = w3.__owl__.id; - def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); + let def2 = w3.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId3, hook: {insert(vn) { let nvn=w3.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}}); const fiber = w3.__owl__.currentFiber; def2.then(function () {if (w3.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); c1.push(pvnode); w3.__owl__.pvnode = pvnode; - } else { - utils.validateProps(w3.constructor, props3) - def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined, sibling); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); } - sibling = w3.__owl__.currentFiber; + sibling = w3.__owl__.currentFiber || sibling; return vn1; }" `; diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index f8da6bfd..ded73e3c 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -193,6 +193,23 @@ describe("basic widget properties", () => { expect(steps).toEqual(["__render", "mounted"]); }); + test("render method wait until rendering is done", async () => { + class TestW extends Component { + static template = xml`
`; + state = { drinks: 1 }; + } + const widget = new TestW(env); + await widget.mount(fixture); + expect(fixture.innerHTML).toBe("
1
"); + + widget.state.drinks = 2; + + const renderPromise = widget.render(); + expect(fixture.innerHTML).toBe("
1
"); + await renderPromise; + expect(fixture.innerHTML).toBe("
2
"); + }); + test("keeps a reference to env", async () => { const widget = new Widget(env); expect(widget.env).toBe(env); @@ -1553,6 +1570,44 @@ describe("composition", () => { expect(fixture.innerHTML).toBe("
world
"); expect(env.qweb.templates.ParentWidget.fn.toString()).toMatchSnapshot(); }); + + test("sub components, loops, and shouldUpdate", async () => { + class ChildWidget extends Component { + static template = xml``; + shouldUpdate(nextProps) { + if (nextProps.val === 12) { + return false; + } + return true; + } + } + + class Parent extends Component { + static template = xml` +
+ + + +
`; + state = useState({ + records: [{ id: 1, val: 1 }, { id: 2, val: 2 }, { id: 3, val: 3 }] + }); + static components = { ChildWidget }; + } + const parent = new Parent(env); + await parent.mount(fixture); + expect(normalize(fixture.innerHTML)).toBe( + "
123
" + ); + + parent.state.records[0].val = 11; + parent.state.records[1].val = 12; + parent.state.records[2].val = 13; + await nextTick(); + expect(normalize(fixture.innerHTML)).toBe( + "
11213
" + ); + }); }); describe("props evaluation ", () => { @@ -2707,7 +2762,7 @@ describe("async rendering", () => { return defs[index++]; } patched() { - steps.push('patched'); + steps.push("patched"); } } @@ -2730,7 +2785,45 @@ describe("async rendering", () => { defs[1].resolve(); await nextTick(); expect(fixture.innerHTML).toBe("
3
"); - expect(steps).toEqual(['patched']); + expect(steps).toEqual(["patched"]); + }); + + test("update a sub-component twice in the same frame, 2", async () => { + const steps: string[] = []; + class ChildA extends Component { + static template = xml``; + patched() { + steps.push("patched"); + } + val() { + steps.push("render"); + return this.props.val; + } + } + + class Parent extends Component { + static template = xml`
`; + static components = { ChildA }; + state = useState({ valA: 1 }); + } + const parent = new Parent(env); + await parent.mount(fixture); + expect(fixture.innerHTML).toBe("
1
"); + parent.state.valA = 2; + await nextMicroTick(); + expect(steps).toEqual(["render"]); + await nextMicroTick(); + expect(steps).toEqual(["render", "render"]); + expect(fixture.innerHTML).toBe("
1
"); + parent.state.valA = 3; + await nextMicroTick(); + expect(steps).toEqual(["render", "render"]); + await nextMicroTick(); + expect(steps).toEqual(["render", "render", "render"]); + expect(fixture.innerHTML).toBe("
1
"); + await nextTick(); + expect(fixture.innerHTML).toBe("
3
"); + expect(steps).toEqual(["render", "render", "render", "patched"]); }); test("components in a node in a t-foreach ", async () => { diff --git a/tests/component/props_validation.test.ts b/tests/component/props_validation.test.ts index 5ec33a88..63994bfe 100644 --- a/tests/component/props_validation.test.ts +++ b/tests/component/props_validation.test.ts @@ -363,13 +363,12 @@ describe("default props", () => { } class App extends Widget { - static template = xml`
`; - static components = { TestWidget }; + static template = xml`
`; + static components = { TestWidget }; } const w = new App(env, {}); await w.mount(fixture); - expect(fixture.innerHTML).toBe('
heyhey
') + expect(fixture.innerHTML).toBe("
heyhey
"); }); - }); diff --git a/tests/helpers.ts b/tests/helpers.ts index f845f73d..d9ddf407 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -1,19 +1,15 @@ -import { Env } from "../src/component/component"; +import { Env, scheduler } from "../src/component/component"; import { EvalContext, QWeb } from "../src/qweb/qweb"; import { patch } from "../src/vdom"; import "../src/qweb/base_directives"; import "../src/qweb/extensions"; import "../src/component/directive"; -// modifies scheduler to make it easier to test components -// let current; -// scheduler.requestAnimationFrame = function(callback: FrameRequestCallback) { -// if (current) { -// throw new Error("should not schedule 2 callbacks!"); -// } -// current = callback; -// return 1; -// }; +// modifies scheduler to make it faster to test components +scheduler.requestAnimationFrame = function(callback: FrameRequestCallback) { + setTimeout(callback, 1); + return 1; +}; // Some static cleanup let nextSlotId; @@ -22,7 +18,6 @@ let nextId; let TEMPLATES; beforeEach(() => { - // current = null; nextSlotId = QWeb.nextSlotId; slots = Object.assign({}, QWeb.slots); nextId = QWeb.nextId; @@ -30,7 +25,6 @@ beforeEach(() => { }); afterEach(() => { - // current = null; QWeb.nextSlotId = nextSlotId; QWeb.slots = slots; QWeb.nextId = nextId; @@ -41,22 +35,10 @@ afterEach(() => { export function nextMicroTick(): Promise { return Promise.resolve(); } -// export async function nextTick(): Promise { -// await Promise.resolve(); -// let max = 1000; -// while (current && max > 0) { -// const cb = current; -// console.warn('next'); -// current = null; -// cb(); -// max--; -// await Promise.resolve(); -// } -// } export async function nextTick(): Promise { - return new Promise(function (resolve) { - setTimeout(() => requestAnimationFrame(() => resolve())); + return new Promise(function(resolve) { + setTimeout(() => scheduler.requestAnimationFrame(() => resolve())); }); } diff --git a/tests/router/__snapshots__/route_component.test.ts.snap b/tests/router/__snapshots__/route_component.test.ts.snap index 0f7f7d55..46f3e4c9 100644 --- a/tests/router/__snapshots__/route_component.test.ts.snap +++ b/tests/router/__snapshots__/route_component.test.ts.snap @@ -13,7 +13,6 @@ exports[`RouteComponent can render simple cases 1`] = ` if (context['routeComponent']) { //COMPONENT let key3 = 'key' + context['env'].router.currentRouteName; - let def1; let templateId2 = \`__4__\` + key3; let w2 = templateId2 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId2]] : false; let vn5 = {}; @@ -23,24 +22,24 @@ exports[`RouteComponent can render simple cases 1`] = ` w2.destroy(); w2 = false; } - if (!w2) { + if (w2) { + w2.__updateProps(props2, extra.fiber, undefined, undefined, sibling); + let pvnode = w2.__owl__.pvnode; + utils.defineProxy(vn5, pvnode); + } else { let componentKey2 = \`routeComponent\`; let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| context['routeComponent']; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap[templateId2] = w2.__owl__.id; - def1 = w2.__prepare(extra.fiber, undefined, undefined, sibling); + let def1 = w2.__prepare(extra.fiber, undefined, undefined, sibling); let pvnode = h('dummy', {key: templateId2, hook: {insert(vn) { let nvn=w2.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w2.destroy();}}}); const fiber = w2.__owl__.currentFiber; def1.then(function () {if (w2.__owl__.isDestroyed) {return;} const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); utils.defineProxy(vn5, pvnode); w2.__owl__.pvnode = pvnode; - } else { - def1 = def1 || w2.__updateProps(props2, extra.fiber, undefined, undefined, sibling); - let pvnode = w2.__owl__.pvnode; - utils.defineProxy(vn5, pvnode); } - sibling = w2.__owl__.currentFiber; + sibling = w2.__owl__.currentFiber || sibling; } return result; }"