From 3048c6f96117790e7ec162cb97feeca1b18e9775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Sat, 14 Sep 2019 08:57:37 +0200 Subject: [PATCH 1/4] [REF] component: introduce fiber part of #293 --- src/component/component.ts | 75 ++++++--- src/component/directive.ts | 15 +- src/qweb/base_directives.ts | 2 +- src/qweb/qweb.ts | 10 +- src/store/connected_component.ts | 7 +- src/tags.ts | 2 - tests/__snapshots__/animations.test.ts.snap | 8 +- .../__snapshots__/component.test.ts.snap | 158 +++++++++--------- .../props_validation.test.ts.snap | 4 +- tests/component/component.test.ts | 12 +- tests/component/props_validation.test.ts | 2 +- tests/helpers.ts | 6 +- tests/qweb/__snapshots__/qweb.test.ts.snap | 22 +-- tests/qweb/qweb.test.ts | 4 +- .../__snapshots__/RouteComponent.test.ts.snap | 4 +- tests/store/connected_component.test.ts | 16 +- 16 files changed, 190 insertions(+), 157 deletions(-) diff --git a/src/component/component.ts b/src/component/component.ts index af3417f3..8e99d2b8 100644 --- a/src/component/component.ts +++ b/src/component/component.ts @@ -33,6 +33,19 @@ export interface Env { [key: string]: any; } +export interface Fiber { + force: boolean; + rootFiber: Fiber | null; + isCancelled: boolean; + scope: any; + vars: any; +// component: Component; +// promises: any[]; +// vnode?: VNode; +// handlers?: any; +// mountedHandlers?: any; +} + /** * This is mostly an internal detail of implementation. The Meta interface is * useful to typecheck and describe the internal keys used by Owl to manage the @@ -279,8 +292,9 @@ export class Component { if (__owl__.isMounted) { return; } + const fiber = this.__createRootFiber(false); if (!__owl__.vnode) { - const vnode = await this.__prepare(); + const vnode = await this.__prepareAndRender(fiber); if (__owl__.isDestroyed) { // component was destroyed before we get here... return; @@ -288,7 +302,7 @@ export class Component { this.__patch(vnode); } else if (renderBeforeRemount) { const patchQueue = []; - await this.__render(false, patchQueue, undefined, undefined); + await this.__render(fiber, patchQueue); this.__applyPatchQueue(patchQueue); } target.appendChild(this.el!); @@ -323,10 +337,11 @@ export class Component { if (!__owl__.isMounted) { return; } + const fiber = this.__createRootFiber(force); const patchQueue = []; const renderId = ++__owl__.renderId; - await this.__render(force, patchQueue, undefined, undefined); + await this.__render(fiber, patchQueue); if (__owl__.isMounted && renderId === __owl__.renderId) { // we only update the vnode and the actual DOM if no other rendering @@ -335,6 +350,25 @@ export class Component { } } + __createRootFiber(force): Fiber { + const fiber: Fiber = { + force, + scope: undefined, + vars: undefined, + rootFiber: null, + isCancelled: false + }; + fiber.rootFiber = fiber; + return fiber; + } + + __createSubFiber(parent: Fiber, scope, vars): Fiber { + const fiber = Object.create(parent); + fiber.scope = scope; + fiber.vars = vars; + return fiber; + } + /** * Destroy the component. This operation is quite complex: * - it recursively destroy all children @@ -476,12 +510,12 @@ export class Component { */ async __updateProps( nextProps: Props, - forceUpdate: boolean = false, + parentFiber: Fiber, patchQueue?: any[], scope?: any, vars?: any ): Promise { - const shouldUpdate = forceUpdate || this.shouldUpdate(nextProps); + const shouldUpdate = parentFiber.force || this.shouldUpdate(nextProps); if (shouldUpdate) { const defaultProps = (this.constructor).defaultProps; if (defaultProps) { @@ -489,7 +523,8 @@ export class Component { } await this.willUpdateProps(nextProps); this.props = nextProps; - await this.__render(forceUpdate, patchQueue, scope, vars); + const fiber = this.__createSubFiber(parentFiber, scope, vars); + await this.__render(fiber, patchQueue); } } @@ -503,14 +538,20 @@ export class Component { __owl__.vnode = patch(target, vnode); } - __prepare(scope?: Object, vars?: any): Promise { + /** + * The __prepare method is only called by the t-component directive, when a + * subcomponent is created. It gets its scope and vars, if any, from the + * parent template. + */ + __prepare(parentFiber: Fiber, scope: any, vars: any): Promise { const __owl__ = this.__owl__; + const fiber = this.__createSubFiber(parentFiber, scope, vars); __owl__.renderProps = this.props; - __owl__.renderPromise = this.__prepareAndRender(scope, vars); + __owl__.renderPromise = this.__prepareAndRender(fiber); return __owl__.renderPromise; } - async __prepareAndRender(scope?: Object, vars?: any): Promise { + async __prepareAndRender(fiber: Fiber): Promise { try { await this.willStart(); } catch (e) { @@ -545,16 +586,10 @@ export class Component { } __owl__.render = qweb.render.bind(qweb, p._template); this.__observeState(); - - return this.__render(false, [], scope, vars); + return this.__render(fiber, []); } - __render( - force: boolean = false, - patchQueue: any[] = [], - scope?: Object, - vars?: any - ): Promise { + __render(fiber: Fiber, patchQueue: any[] = []): Promise { const __owl__ = this.__owl__; const promises: Promise[] = []; const patch: any[] = [this]; @@ -568,10 +603,8 @@ export class Component { promises, handlers: __owl__.boundHandlers, mountedHandlers: __owl__.mountedHandlers, - forceUpdate: force, - patchQueue, - scope, - vars + fiber: fiber, + patchQueue }); } catch (e) { vnode = __owl__.vnode || h("div"); diff --git a/src/component/directive.ts b/src/component/directive.ts index 6115370f..47d21af0 100644 --- a/src/component/directive.ts +++ b/src/component/directive.ts @@ -441,14 +441,15 @@ QWeb.addDirective({ } } - let scopeVars = ""; + let scopeVars; if (hasSlots) { - scopeVars += ctx.scopeVars.length ? `Object.assign({}, scope)` : varDefs.length ? `{}` : ""; - if (varDefs.length) { - scopeVars += `, {${varDefs.join(",")}}`; - } + 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(${scopeVars});`); + ctx.addLine(`def${defID} = w${componentID}.__prepare(extra.fiber, ${scopeVars});`); // hack: specify empty remove hook to prevent the node from being removed from the DOM let registerCode = `c${ctx.parentNode}[_${dummyID}_index]=pvnode;`; if (shouldProxy) { @@ -472,7 +473,7 @@ QWeb.addDirective({ ctx.addLine(`utils.validateProps(w${componentID}.constructor, props${componentID})`); } ctx.addLine( - `def${defID} = def${defID} || w${componentID}.__updateProps(props${componentID}, extra.forceUpdate, ${patchQueueCode}${scopeVars && + `def${defID} = def${defID} || w${componentID}.__updateProps(props${componentID}, extra.fiber, ${patchQueueCode}${scopeVars && ", " + scopeVars});` ); let keepAliveCode = ""; diff --git a/src/qweb/base_directives.ts b/src/qweb/base_directives.ts index 92965d25..e49f8a2f 100644 --- a/src/qweb/base_directives.ts +++ b/src/qweb/base_directives.ts @@ -244,7 +244,7 @@ QWeb.addDirective({ varCode = `{${content}}`; } ctx.addLine( - `this.recursiveFns['${subTemplateName}'].call(this, context, Object.assign({}, extra, {parentNode: c${ctx.parentNode}, vars: ${varCode}, scope}));` + `this.recursiveFns['${subTemplateName}'].call(this, context, Object.assign({}, extra, {parentNode: c${ctx.parentNode}, fiber: {vars: ${varCode}, scope}}));` ); return true; } diff --git a/src/qweb/qweb.ts b/src/qweb/qweb.ts index 21a7e391..7f80795a 100644 --- a/src/qweb/qweb.ts +++ b/src/qweb/qweb.ts @@ -244,7 +244,7 @@ export class QWeb extends EventBus { this._processTemplate(elem); const template = { elem, - fn: function (this: QWeb, context, extra) { + fn: function(this: QWeb, context, extra) { const compiledFunction = this._compile(name, elem); template.fn = compiledFunction; return compiledFunction.call(this, context, extra); @@ -312,8 +312,8 @@ export class QWeb extends EventBus { * to render a full component tree, since this is an asynchronous operation. * This method can only render templates without components. */ - renderToString(name: string, context: EvalContext = {}): string { - const vnode = this.render(name, context); + renderToString(name: string, context: EvalContext = {}, extra?: any): string { + const vnode = this.render(name, context, extra); if (vnode.sel === undefined) { return vnode.text!; } @@ -357,12 +357,12 @@ export class QWeb extends EventBus { for (let v in parentContext.variables) { let variable = parentContext.variables[v]; if (variable.id) { - ctx.addLine(`let ${variable.id} = extra.vars.${variable.id}`); + ctx.addLine(`let ${variable.id} = extra.fiber.vars.${variable.id}`); } } } if (parentContext) { - ctx.addLine(" Object.assign(context, extra.scope);"); + ctx.addLine(" Object.assign(context, extra.fiber.scope);"); } this._compileNode(elem, ctx); diff --git a/src/store/connected_component.ts b/src/store/connected_component.ts index 347c297b..20a7c9fc 100644 --- a/src/store/connected_component.ts +++ b/src/store/connected_component.ts @@ -1,4 +1,4 @@ -import { Component, Env } from "../component/component"; +import { Component, Env, Fiber } from "../component/component"; //------------------------------------------------------------------------------ // Connect function @@ -47,8 +47,7 @@ export class ConnectedComponent extends Component * Need to do this here so 'deep' can be overrided by subcomponent easily */ async __prepareAndRender( - scope?: Object, - vars?: any + fiber: Fiber ): ReturnType["__prepareAndRender"]> { const store = this.getStore(this.env); const ownProps = this.props || {}; @@ -62,7 +61,7 @@ export class ConnectedComponent extends Component prevStoreProps: this.storeProps }); (this.__owl__ as any).rev = observer.rev; - return super.__prepareAndRender(scope, vars); + return super.__prepareAndRender(fiber); } /** * We do not use the mounted hook here for a subtle reason: we want the diff --git a/src/tags.ts b/src/tags.ts index 3e5d2352..95675b56 100644 --- a/src/tags.ts +++ b/src/tags.ts @@ -10,8 +10,6 @@ import { QWeb } from "./qweb/index"; * The plan is to add a few other tags such as css, globalcss. */ - - /** * XML tag helper for defining templates. With this, one can simply define * an inline template with just the template xml: diff --git a/tests/__snapshots__/animations.test.ts.snap b/tests/__snapshots__/animations.test.ts.snap index b4add252..9b0c41c3 100644 --- a/tests/__snapshots__/animations.test.ts.snap +++ b/tests/__snapshots__/animations.test.ts.snap @@ -31,13 +31,13 @@ exports[`animations t-transition combined with component 1`] = ` if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;utils.transitionInsert(vn, 'chimay');},remove() {},destroy(vn) {let finalize = () => { w4.destroy(); }; utils.transitionRemove(vn, 'chimay', finalize);}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -77,13 +77,13 @@ exports[`animations t-transition combined with t-component and t-if 1`] = ` if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;utils.transitionInsert(vn, 'chimay');},remove() {},destroy(vn) {let finalize = () => { w4.destroy(); }; utils.transitionRemove(vn, 'chimay', finalize);}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap index 3bd31515..ec4e4440 100644 --- a/tests/component/__snapshots__/component.test.ts.snap +++ b/tests/component/__snapshots__/component.test.ts.snap @@ -44,10 +44,10 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = ` if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')} w8 = new W8(parent, props8); parent.__owl__.cmap[8] = w8.__owl__.id; - def7 = w8.__prepare(); + def7 = w8.__prepare(extra.fiber, undefined, undefined); def7 = def7.then(vnode=>{if (w8.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 8, hook: {insert(vn) {let nvn=w8.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w8.destroy();}}});c5[_6_index]=pvnode;w8.__owl__.pvnode = pvnode;}); } else { - def7 = def7 || w8.__updateProps(props8, extra.forceUpdate, extra.patchQueue); + def7 = def7 || w8.__updateProps(props8, extra.fiber, extra.patchQueue, undefined, undefined); def7 = def7.then(()=>{if (w8.__owl__.isDestroyed) {return};let pvnode=w8.__owl__.pvnode;c5[_6_index]=pvnode;}); } extra.promises.push(def7); @@ -72,10 +72,10 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = ` if (!W11) {throw new Error('Cannot find the definition of component \\"' + componentKey11 + '\\"')} w11 = new W11(parent, props11); parent.__owl__.cmap[11] = w11.__owl__.id; - def10 = w11.__prepare(); + def10 = w11.__prepare(extra.fiber, undefined, undefined); def10 = def10.then(vnode=>{if (w11.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 11, hook: {insert(vn) {let nvn=w11.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w11.destroy();}}});c5[_9_index]=pvnode;w11.__owl__.pvnode = pvnode;}); } else { - def10 = def10 || w11.__updateProps(props11, extra.forceUpdate, patchQueue11); + def10 = def10 || w11.__updateProps(props11, extra.fiber, patchQueue11, undefined, undefined); def10 = def10.then(()=>{if (w11.__owl__.isDestroyed) {return};let pvnode=w11.__owl__.pvnode;c5[_9_index]=pvnode;}); } def10.then(w11.__applyPatchQueue.bind(w11, patchQueue11)); @@ -128,10 +128,10 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = ` if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')} w8 = new W8(parent, props8); parent.__owl__.cmap[8] = w8.__owl__.id; - def7 = w8.__prepare(); + def7 = w8.__prepare(extra.fiber, undefined, undefined); def7 = def7.then(vnode=>{if (w8.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 8, hook: {insert(vn) {let nvn=w8.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w8.destroy();}}});c5[_6_index]=pvnode;w8.__owl__.pvnode = pvnode;}); } else { - def7 = def7 || w8.__updateProps(props8, extra.forceUpdate, patchQueue8); + def7 = def7 || w8.__updateProps(props8, extra.fiber, patchQueue8, undefined, undefined); def7 = def7.then(()=>{if (w8.__owl__.isDestroyed) {return};let pvnode=w8.__owl__.pvnode;c5[_6_index]=pvnode;}); } def7.then(w8.__applyPatchQueue.bind(w8, patchQueue8)); @@ -155,10 +155,10 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = ` if (!W11) {throw new Error('Cannot find the definition of component \\"' + componentKey11 + '\\"')} w11 = new W11(parent, props11); parent.__owl__.cmap[11] = w11.__owl__.id; - def10 = w11.__prepare(); + def10 = w11.__prepare(extra.fiber, undefined, undefined); def10 = def10.then(vnode=>{if (w11.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 11, hook: {insert(vn) {let nvn=w11.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w11.destroy();}}});c5[_9_index]=pvnode;w11.__owl__.pvnode = pvnode;}); } else { - def10 = def10 || w11.__updateProps(props11, extra.forceUpdate, extra.patchQueue); + def10 = def10 || w11.__updateProps(props11, extra.fiber, extra.patchQueue, undefined, undefined); def10 = def10.then(()=>{if (w11.__owl__.isDestroyed) {return};let pvnode=w11.__owl__.pvnode;c5[_9_index]=pvnode;}); } extra.promises.push(def10); @@ -210,10 +210,10 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')} w8 = new W8(parent, props8); parent.__owl__.cmap[8] = w8.__owl__.id; - def7 = w8.__prepare(); + def7 = w8.__prepare(extra.fiber, undefined, undefined); def7 = def7.then(vnode=>{if (w8.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 8, hook: {insert(vn) {let nvn=w8.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w8.destroy();}}});c5[_6_index]=pvnode;w8.__owl__.pvnode = pvnode;}); } else { - def7 = def7 || w8.__updateProps(props8, extra.forceUpdate, extra.patchQueue); + def7 = def7 || w8.__updateProps(props8, extra.fiber, extra.patchQueue, undefined, undefined); def7 = def7.then(()=>{if (w8.__owl__.isDestroyed) {return};let pvnode=w8.__owl__.pvnode;c5[_6_index]=pvnode;}); } extra.promises.push(def7); @@ -238,10 +238,10 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render if (!W11) {throw new Error('Cannot find the definition of component \\"' + componentKey11 + '\\"')} w11 = new W11(parent, props11); parent.__owl__.cmap[11] = w11.__owl__.id; - def10 = w11.__prepare(); + def10 = w11.__prepare(extra.fiber, undefined, undefined); def10 = def10.then(vnode=>{if (w11.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 11, hook: {insert(vn) {let nvn=w11.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w11.destroy();}}});c5[_9_index]=pvnode;w11.__owl__.pvnode = pvnode;}); } else { - def10 = def10 || w11.__updateProps(props11, extra.forceUpdate, patchQueue11); + def10 = def10 || w11.__updateProps(props11, extra.fiber, patchQueue11, undefined, undefined); def10 = def10.then(()=>{if (w11.__owl__.isDestroyed) {return};let pvnode=w11.__owl__.pvnode;c5[_9_index]=pvnode;}); } def10.then(w11.__applyPatchQueue.bind(w11, patchQueue11)); @@ -281,10 +281,10 @@ exports[`class and style attributes with t-component dynamic t-att-style is prop if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.style = _5;}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};w4.el.style=_5;let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -326,10 +326,10 @@ exports[`class and style attributes with t-component t-att-class is properly add if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;context.refs[ref5] = w4;},remove() {},destroy(vn) {w4.destroy();delete context.refs[ref5];}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } w4.__owl__.classObj=_6; @@ -386,10 +386,10 @@ exports[`class and style attributes with t-component t-att-class is properly add if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;context.refs[ref5] = w4;},remove() {},destroy(vn) {w4.destroy();delete context.refs[ref5];}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } w4.__owl__.classObj=_6; @@ -444,10 +444,10 @@ exports[`class and style attributes with t-component t-att-class is properly add if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } w4.__owl__.classObj=_5; @@ -488,10 +488,10 @@ exports[`composition sub components dom state with t-keepalive is preserved 1`] if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.unmount();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, w4.__owl__.isMounted ? extra.patchQueue : []); + def3 = def3 || w4.__updateProps(props4, extra.fiber, w4.__owl__.isMounted ? extra.patchQueue : [], undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w4.el,vn.elm);vn.elm=w4.el;w4.__remount();};c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -548,10 +548,10 @@ exports[`composition sub components with some state rendered in a loop 1`] = ` if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')} w7 = new W7(parent, props7); parent.__owl__.cmap[templateId9] = w7.__owl__.id; - def6 = w7.__prepare(); + def6 = w7.__prepare(extra.fiber, undefined, undefined); def6 = def6.then(vnode=>{if (w7.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId9, hook: {insert(vn) {let nvn=w7.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w7.destroy();}}});c1[_5_index]=pvnode;w7.__owl__.pvnode = pvnode;}); } else { - def6 = def6 || w7.__updateProps(props7, extra.forceUpdate, extra.patchQueue); + def6 = def6 || w7.__updateProps(props7, extra.fiber, extra.patchQueue, undefined, undefined); def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c1[_5_index]=pvnode;}); } extra.promises.push(def6); @@ -591,10 +591,10 @@ exports[`composition t-component with dynamic value 1`] = ` if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -633,10 +633,10 @@ exports[`composition t-component with dynamic value 2 1`] = ` if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -675,10 +675,10 @@ exports[`dynamic t-props basic use 1`] = ` if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -718,10 +718,10 @@ exports[`lifecycle hooks willPatch/patched hook with t-keepalive 1`] = ` if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.unmount();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, w4.__owl__.isMounted ? extra.patchQueue : []); + def3 = def3 || w4.__updateProps(props4, extra.fiber, w4.__owl__.isMounted ? extra.patchQueue : [], undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w4.el,vn.elm);vn.elm=w4.el;w4.__remount();};c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -761,10 +761,10 @@ exports[`other directives with t-component t-on with handler bound to argument 1 if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, 3));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -803,10 +803,10 @@ exports[`other directives with t-component t-on with handler bound to empty obje if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -845,10 +845,10 @@ exports[`other directives with t-component t-on with handler bound to empty obje if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -887,10 +887,10 @@ exports[`other directives with t-component t-on with handler bound to object 1`] if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {val:3}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -929,10 +929,10 @@ exports[`other directives with t-component t-on with prevent and self modifiers if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {e.preventDefault();if (e.target !== vn.elm) {return}owner['onEv'].call(owner, e);});}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -971,10 +971,10 @@ exports[`other directives with t-component t-on with self and prevent modifiers if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if (e.target !== vn.elm) {return}e.preventDefault();owner['onEv'].call(owner, e);});}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1013,10 +1013,10 @@ exports[`other directives with t-component t-on with self modifier 1`] = ` if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', owner['onEv1'].bind(owner));vn.elm.addEventListener('ev-2', function (e) {if (e.target !== vn.elm) {return}owner['onEv2'].call(owner, e);});}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1055,10 +1055,10 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', function (e) {e.stopPropagation();owner['onEv1'].call(owner, e);});vn.elm.addEventListener('ev-2', function (e) {e.preventDefault();owner['onEv2'].call(owner, e);});vn.elm.addEventListener('ev-3', function (e) {e.stopPropagation();e.preventDefault();owner['onEv3'].call(owner, e);});}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1099,10 +1099,10 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = ` if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[templateId6] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId6, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1159,10 +1159,10 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')} w7 = new W7(parent, props7); parent.__owl__.cmap[templateId9] = w7.__owl__.id; - def6 = w7.__prepare(); + def6 = w7.__prepare(extra.fiber, undefined, undefined); def6 = def6.then(vnode=>{if (w7.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, arg10));}};let pvnode=h(vnode.sel, {key: templateId9, hook: {insert(vn) {let nvn=w7.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w7.destroy();}}});c1[_5_index]=pvnode;w7.__owl__.pvnode = pvnode;}); } else { - def6 = def6 || w7.__updateProps(props7, extra.forceUpdate, extra.patchQueue); + def6 = def6 || w7.__updateProps(props7, extra.fiber, extra.patchQueue, undefined, undefined); def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c1[_5_index]=pvnode;}); } extra.promises.push(def6); @@ -1384,10 +1384,10 @@ exports[`t-slot directive can define and call slots 1`] = ` w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; w4.__owl__.slotId = 1; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, {}, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, {}, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1426,7 +1426,7 @@ exports[`t-slot directive can define and call slots 3`] = ` ) { var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); let c2 = [], p2 = {key:2}; var vn2 = h('span', p2, c2); c1.push(vn2); @@ -1439,7 +1439,7 @@ exports[`t-slot directive can define and call slots 4`] = ` ) { var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); let c2 = [], p2 = {key:2}; var vn2 = h('span', p2, c2); c1.push(vn2); @@ -1452,7 +1452,7 @@ exports[`t-slot directive content is the default slot 1`] = ` ) { var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); let c2 = [], p2 = {key:2}; var vn2 = h('span', p2, c2); c1.push(vn2); @@ -1465,7 +1465,7 @@ exports[`t-slot directive default slot work with text nodes 1`] = ` ) { var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); c1.push({text: \`sts rocks\`}); }" `; @@ -1475,7 +1475,7 @@ exports[`t-slot directive multiple roots are allowed in a default slot 1`] = ` ) { var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); let c2 = [], p2 = {key:2}; var vn2 = h('span', p2, c2); c1.push(vn2); @@ -1492,7 +1492,7 @@ exports[`t-slot directive multiple roots are allowed in a named slot 1`] = ` ) { var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); let c2 = [], p2 = {key:2}; var vn2 = h('span', p2, c2); c1.push(vn2); @@ -1510,7 +1510,7 @@ exports[`t-slot directive refs are properly bound in slots 1`] = ` let owner = context; var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); let c2 = [], p2 = {key:2,on:{}}; var vn2 = h('button', p2, c2); c1.push(vn2); @@ -1535,7 +1535,7 @@ exports[`t-slot directive slots are rendered with proper context 1`] = ` let owner = context; var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); let c2 = [], p2 = {key:2,on:{}}; var vn2 = h('button', p2, c2); c1.push(vn2); @@ -1626,10 +1626,10 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = ` w9 = new W9(parent, props9); parent.__owl__.cmap[templateId10] = w9.__owl__.id; w9.__owl__.slotId = 1; - def8 = w9.__prepare(Object.assign({}, scope)); + def8 = w9.__prepare(extra.fiber, Object.assign({}, scope), undefined); def8 = def8.then(vnode=>{if (w9.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId10, hook: {insert(vn) {let nvn=w9.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w9.destroy();}}});c6[_7_index]=pvnode;w9.__owl__.pvnode = pvnode;}); } else { - def8 = def8 || w9.__updateProps(props9, extra.forceUpdate, extra.patchQueue, Object.assign({}, scope)); + def8 = def8 || w9.__updateProps(props9, extra.fiber, extra.patchQueue, Object.assign({}, scope), undefined); def8 = def8.then(()=>{if (w9.__owl__.isDestroyed) {return};let pvnode=w9.__owl__.pvnode;c6[_7_index]=pvnode;}); } extra.promises.push(def8); @@ -1643,7 +1643,7 @@ exports[`t-slot directive slots are rendered with proper context, part 2 3`] = ` ) { var h = this.h; let c6 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); c6.push({text: \`User \`}); var _7 = context['user'].name; if (_7 || _7 === 0) { @@ -1731,10 +1731,10 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` w10 = new W10(parent, props10); parent.__owl__.cmap[templateId11] = w10.__owl__.id; w10.__owl__.slotId = 1; - def9 = w10.__prepare(Object.assign({}, scope), {_7}); + def9 = w10.__prepare(extra.fiber, Object.assign({}, scope), {_7}); def9 = def9.then(vnode=>{if (w10.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId11, hook: {insert(vn) {let nvn=w10.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w10.destroy();}}});c6[_8_index]=pvnode;w10.__owl__.pvnode = pvnode;}); } else { - def9 = def9 || w10.__updateProps(props10, extra.forceUpdate, extra.patchQueue, Object.assign({}, scope), {_7}); + def9 = def9 || w10.__updateProps(props10, extra.fiber, extra.patchQueue, Object.assign({}, scope), {_7}); def9 = def9.then(()=>{if (w10.__owl__.isDestroyed) {return};let pvnode=w10.__owl__.pvnode;c6[_8_index]=pvnode;}); } extra.promises.push(def9); @@ -1748,8 +1748,8 @@ exports[`t-slot directive slots are rendered with proper context, part 3 3`] = ` ) { var h = this.h; let c6 = extra.parentNode; - let _7 = extra.vars._7 - Object.assign(context, extra.scope); + let _7 = extra.fiber.vars._7 + Object.assign(context, extra.fiber.scope); if (_7 || _7 === 0) { c6.push({text: _7}); } @@ -1789,10 +1789,10 @@ exports[`t-slot directive slots are rendered with proper context, part 4 1`] = ` w5 = new W5(parent, props5); parent.__owl__.cmap[5] = w5.__owl__.id; w5.__owl__.slotId = 1; - def4 = w5.__prepare({}, {_2}); + def4 = w5.__prepare(extra.fiber, {}, {_2}); def4 = def4.then(vnode=>{if (w5.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 5, hook: {insert(vn) {let nvn=w5.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w5.destroy();}}});c1[_3_index]=pvnode;w5.__owl__.pvnode = pvnode;}); } else { - def4 = def4 || w5.__updateProps(props5, extra.forceUpdate, extra.patchQueue, {}, {_2}); + def4 = def4 || w5.__updateProps(props5, extra.fiber, extra.patchQueue, {}, {_2}); def4 = def4.then(()=>{if (w5.__owl__.isDestroyed) {return};let pvnode=w5.__owl__.pvnode;c1[_3_index]=pvnode;}); } extra.promises.push(def4); @@ -1805,8 +1805,8 @@ exports[`t-slot directive slots are rendered with proper context, part 4 2`] = ` ) { var h = this.h; let c1 = extra.parentNode; - let _2 = extra.vars._2 - Object.assign(context, extra.scope); + let _2 = extra.fiber.vars._2 + Object.assign(context, extra.fiber.scope); if (_2 || _2 === 0) { c1.push({text: _2}); } @@ -1842,10 +1842,10 @@ exports[`top level sub widgets basic use 1`] = ` if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[3] = w3.__owl__.id; - def2 = w3.__prepare(); + def2 = w3.__prepare(extra.fiber, undefined, undefined); def2 = def2.then(vnode=>{if (w3.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 3, hook: {insert(vn) {let nvn=w3.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}});utils.defineProxy(vn4, pvnode);w3.__owl__.pvnode = pvnode;}); } else { - def2 = def2 || w3.__updateProps(props3, extra.forceUpdate, extra.patchQueue); + def2 = def2 || w3.__updateProps(props3, extra.fiber, extra.patchQueue, undefined, undefined); def2 = def2.then(()=>{if (w3.__owl__.isDestroyed) {return};let pvnode=w3.__owl__.pvnode;utils.defineProxy(vn4, pvnode);}); } extra.promises.push(def2); @@ -1883,10 +1883,10 @@ exports[`top level sub widgets can select a sub widget 1`] = ` if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[3] = w3.__owl__.id; - def2 = w3.__prepare(); + def2 = w3.__prepare(extra.fiber, undefined, undefined); def2 = def2.then(vnode=>{if (w3.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 3, hook: {insert(vn) {let nvn=w3.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}});utils.defineProxy(vn4, pvnode);w3.__owl__.pvnode = pvnode;}); } else { - def2 = def2 || w3.__updateProps(props3, extra.forceUpdate, extra.patchQueue); + def2 = def2 || w3.__updateProps(props3, extra.fiber, extra.patchQueue, undefined, undefined); def2 = def2.then(()=>{if (w3.__owl__.isDestroyed) {return};let pvnode=w3.__owl__.pvnode;utils.defineProxy(vn4, pvnode);}); } extra.promises.push(def2); @@ -1912,10 +1912,10 @@ exports[`top level sub widgets can select a sub widget 1`] = ` if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')} w7 = new W7(parent, props7); parent.__owl__.cmap[7] = w7.__owl__.id; - def6 = w7.__prepare(); + def6 = w7.__prepare(extra.fiber, undefined, undefined); def6 = def6.then(vnode=>{if (w7.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 7, hook: {insert(vn) {let nvn=w7.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w7.destroy();}}});utils.defineProxy(vn8, pvnode);w7.__owl__.pvnode = pvnode;}); } else { - def6 = def6 || w7.__updateProps(props7, extra.forceUpdate, extra.patchQueue); + def6 = def6 || w7.__updateProps(props7, extra.fiber, extra.patchQueue, undefined, undefined); def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;utils.defineProxy(vn8, pvnode);}); } extra.promises.push(def6); diff --git a/tests/component/__snapshots__/props_validation.test.ts.snap b/tests/component/__snapshots__/props_validation.test.ts.snap index 0c9382aa..9fa88d51 100644 --- a/tests/component/__snapshots__/props_validation.test.ts.snap +++ b/tests/component/__snapshots__/props_validation.test.ts.snap @@ -36,11 +36,11 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] = utils.validateProps(W4, props4) w4 = new W4(parent, props4); parent.__owl__.cmap[4] = w4.__owl__.id; - def3 = w4.__prepare(); + def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { utils.validateProps(w4.constructor, props4) - def3 = def3 || w4.__updateProps(props4, extra.forceUpdate, extra.patchQueue); + def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index 1077929a..7b0eeb26 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -137,9 +137,9 @@ describe("basic widget properties", () => { async willStart() { this.state.drinks++; } - async __render() { + async __render(a,b) { renderCalls++; - return super.__render(); + return super.__render(a,b); } } const widget = new TestW(env); @@ -2779,9 +2779,9 @@ describe("updating environment", () => { test("updating widget env does not render widget (if not mounted)", async () => { let n = 0; class TestWidget extends Widget { - __render() { + __render(a,b) { n++; - return super.__render(); + return super.__render(a,b); } } @@ -4185,9 +4185,9 @@ describe("unmounting and remounting", () => { `; state = { n: 2 }; - __render(a, b, c, d) { + __render(a, b) { steps.push("render"); - return super.__render(a, b, c, d); + return super.__render(a, b); } willPatch() { steps.push("willPatch"); diff --git a/tests/component/props_validation.test.ts b/tests/component/props_validation.test.ts index 718e494a..c1160469 100644 --- a/tests/component/props_validation.test.ts +++ b/tests/component/props_validation.test.ts @@ -334,7 +334,7 @@ describe("default props", () => { const w = new TestWidget(env, { p: 1 }); await w.mount(fixture); expect(fixture.innerHTML).toMatchSnapshot(); - await w.__updateProps({}); + await w.__updateProps({}, {force: false}); await w.render(); expect(w.props.p).toBe(4); expect(fixture.innerHTML).toMatchSnapshot(); diff --git a/tests/helpers.ts b/tests/helpers.ts index 0896ec4d..f9712bf0 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -99,10 +99,10 @@ export function renderToDOM( * Note that the result of renderToString is guaranteed to be the same as the * one from QWeb. */ -export function renderToString(qweb: QWeb, t: string, context: EvalContext = {}): string { - const node = renderToDOM(qweb, t, context); +export function renderToString(qweb: QWeb, t: string, context: EvalContext = {}, extra?: any): string { + const node = renderToDOM(qweb, t, context, extra); const result = node instanceof Text ? node.textContent! : node.outerHTML; - if (result !== qweb.renderToString(t, context)) { + if (result !== qweb.renderToString(t, context, extra)) { throw new Error("HTML string returned by renderToString helper does not match QWeb render"); } return result; diff --git a/tests/qweb/__snapshots__/qweb.test.ts.snap b/tests/qweb/__snapshots__/qweb.test.ts.snap index 008b210d..a2544eb6 100644 --- a/tests/qweb/__snapshots__/qweb.test.ts.snap +++ b/tests/qweb/__snapshots__/qweb.test.ts.snap @@ -884,7 +884,7 @@ exports[`t-call (template calling recursive template, part 1 1`] = ` c1.push(vn2); c2.push({text: \`hey\`}); if (false) { - this.recursiveFns['__3'].call(this, context, Object.assign({}, extra, {parentNode: c1, vars: {}, scope})); + this.recursiveFns['__3'].call(this, context, Object.assign({}, extra, {parentNode: c1, fiber: {vars: {}, scope}})); } return vn1; }" @@ -896,7 +896,7 @@ exports[`t-call (template calling recursive template, part 1 2`] = ` let owner = context; var h = this.h; let c1 = extra.parentNode; - Object.assign(context, extra.scope); + Object.assign(context, extra.fiber.scope); let c2 = [], p2 = {key:2}; var vn2 = h('div', p2, c2); c1.push(vn2); @@ -905,7 +905,7 @@ exports[`t-call (template calling recursive template, part 1 2`] = ` c2.push(vn3); c3.push({text: \`hey\`}); if (false) { - this.recursiveFns['__3'].call(this, context, Object.assign({}, extra, {parentNode: c2, vars: {}, scope})); + this.recursiveFns['__3'].call(this, context, Object.assign({}, extra, {parentNode: c2, fiber: {vars: {}, scope}})); } }" `; @@ -951,7 +951,7 @@ exports[`t-call (template calling recursive template, part 2 1`] = ` scope.subtree = context.subtree; context.subtree_value = _8[i]; scope.subtree_value = context.subtree_value; - this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c3, vars: {_v0: context['subtree']}, scope})); + this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c3, fiber: {vars: {_v0: context['subtree']}, scope}})); } } return vn1; @@ -966,8 +966,8 @@ exports[`t-call (template calling recursive template, part 2 2`] = ` const scope = Object.create(null); var h = this.h; let c3 = extra.parentNode; - let _v0 = extra.vars._v0 - Object.assign(context, extra.scope); + let _v0 = extra.fiber.vars._v0 + Object.assign(context, extra.fiber.scope); let c4 = [], p4 = {key:4}; var vn4 = h('div', p4, c4); c3.push(vn4); @@ -997,7 +997,7 @@ exports[`t-call (template calling recursive template, part 2 2`] = ` scope.subtree = context.subtree; context.subtree_value = _9[i]; scope.subtree_value = context.subtree_value; - this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c4, vars: {_v0: context['subtree']}, scope})); + this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c4, fiber: {vars: {_v0: context['subtree']}, scope}})); } }" `; @@ -1043,7 +1043,7 @@ exports[`t-call (template calling recursive template, part 3 1`] = ` scope.subtree = context.subtree; context.subtree_value = _8[i]; scope.subtree_value = context.subtree_value; - this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c3, vars: {_v0: context['subtree']}, scope})); + this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c3, fiber: {vars: {_v0: context['subtree']}, scope}})); } } return vn1; @@ -1058,8 +1058,8 @@ exports[`t-call (template calling recursive template, part 3 2`] = ` const scope = Object.create(null); var h = this.h; let c3 = extra.parentNode; - let _v0 = extra.vars._v0 - Object.assign(context, extra.scope); + let _v0 = extra.fiber.vars._v0 + Object.assign(context, extra.fiber.scope); let c4 = [], p4 = {key:4}; var vn4 = h('div', p4, c4); c3.push(vn4); @@ -1089,7 +1089,7 @@ exports[`t-call (template calling recursive template, part 3 2`] = ` scope.subtree = context.subtree; context.subtree_value = _9[i]; scope.subtree_value = context.subtree_value; - this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c4, vars: {_v0: context['subtree']}, scope})); + this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c4, fiber: {vars: {_v0: context['subtree']}, scope}})); } }" `; diff --git a/tests/qweb/qweb.test.ts b/tests/qweb/qweb.test.ts index 604a33ed..b704a780 100644 --- a/tests/qweb/qweb.test.ts +++ b/tests/qweb/qweb.test.ts @@ -637,7 +637,7 @@ describe("t-call (template calling", () => { `); const root = { val: "a", children: [{ val: "b" }, { val: "c" }] }; const expected = "

a

b

c

"; - expect(renderToString(qweb, "Parent", { root })).toBe(expected); + expect(renderToString(qweb, "Parent", { root }, {fiber: {vars: {}, scope: {}}})).toBe(expected); const recursiveFn = Object.values(qweb.recursiveFns)[0]; expect(recursiveFn.toString()).toMatchSnapshot(); }); @@ -664,7 +664,7 @@ describe("t-call (template calling", () => { const root = { val: "a", children: [{ val: "b", children: [{ val: "d" }] }, { val: "c" }] }; const expected = "

a

b

d

c

"; - expect(renderToString(qweb, "Parent", { root })).toBe(expected); + expect(renderToString(qweb, "Parent", { root }, {fiber: {}})).toBe(expected); const recursiveFn = Object.values(qweb.recursiveFns)[0]; expect(recursiveFn.toString()).toMatchSnapshot(); }); diff --git a/tests/router/__snapshots__/RouteComponent.test.ts.snap b/tests/router/__snapshots__/RouteComponent.test.ts.snap index 85497b2e..374ad3b0 100644 --- a/tests/router/__snapshots__/RouteComponent.test.ts.snap +++ b/tests/router/__snapshots__/RouteComponent.test.ts.snap @@ -46,10 +46,10 @@ exports[`RouteComponent can render simple cases 1`] = ` if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} w6 = new W6(parent, props6); parent.__owl__.cmap[templateId7] = w6.__owl__.id; - def5 = w6.__prepare(); + def5 = w6.__prepare(extra.fiber, undefined, undefined); def5 = def5.then(vnode=>{if (w6.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId7, hook: {insert(vn) {let nvn=w6.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w6.destroy();}}});utils.defineProxy(vn8, pvnode);w6.__owl__.pvnode = pvnode;}); } else { - def5 = def5 || w6.__updateProps(props6, extra.forceUpdate, extra.patchQueue); + def5 = def5 || w6.__updateProps(props6, extra.fiber, extra.patchQueue, undefined, undefined); def5 = def5.then(()=>{if (w6.__owl__.isDestroyed) {return};let pvnode=w6.__owl__.pvnode;utils.defineProxy(vn8, pvnode);}); } extra.promises.push(def5); diff --git a/tests/store/connected_component.test.ts b/tests/store/connected_component.test.ts index 0bf28dc9..04182b9d 100644 --- a/tests/store/connected_component.test.ts +++ b/tests/store/connected_component.test.ts @@ -698,9 +698,9 @@ describe("connecting a component to store", () => { editTodo() { this.env.store.dispatch("editTodo"); } - __render(...args) { + __render(f,p) { renderCount++; - return super.__render(...args); + return super.__render(f,p); } } class TodoApp extends ConnectedComponent { @@ -776,9 +776,9 @@ describe("connecting a component to store", () => { removeTodo() { this.env.store.dispatch("removeTodo"); } - __render(...args) { + __render(f,p) { renderCount++; - return super.__render(...args); + return super.__render(f,p); } } @@ -910,11 +910,12 @@ describe("connected components and default values", () => { await app.mount(fixture); expect(fixture.innerHTML).toBe("
Hello, John
"); - await app.__updateProps({ initialRecipient: "James" }, true); + const fiber = { force: true, scope: undefined, vars: undefined } + await app.__updateProps({ initialRecipient: "James" }, fiber); await app.render(); expect(fixture.innerHTML).toBe("
Hello, James
"); - await app.__updateProps({ initialRecipient: undefined }, true); + await app.__updateProps({ initialRecipient: undefined }, fiber); await app.render(); expect(fixture.innerHTML).toBe("
Hello, John
"); }); @@ -997,7 +998,8 @@ describe("connected components and default values", () => { "
100Message100
101Message101
" ); - await app.__updateProps({ threadId: 2 }, true); + const fiber = { force: true, scope: undefined, vars: undefined } + await app.__updateProps({ threadId: 2 }, fiber); await app.render(); expect(fixture.innerHTML).toBe("
200Message200
"); From 01eb338e693a02c558e3e7298c18d62706c1e5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 19 Sep 2019 11:42:00 +0200 Subject: [PATCH 2/4] [REF] component: move patchqueue management to fiber part of #293 --- src/component/component.ts | 77 ++++++++++-------- src/component/directive.ts | 14 ++-- src/store/connected_component.ts | 4 +- tests/__snapshots__/animations.test.ts.snap | 4 +- .../__snapshots__/component.test.ts.snap | 80 ++++++++++--------- .../props_validation.test.ts.snap | 2 +- tests/component/component.test.ts | 24 +++--- tests/component/props_validation.test.ts | 3 +- tests/helpers.ts | 7 +- tests/qweb/qweb.test.ts | 9 ++- .../__snapshots__/RouteComponent.test.ts.snap | 2 +- tests/store/connected_component.test.ts | 12 +-- 12 files changed, 130 insertions(+), 108 deletions(-) diff --git a/src/component/component.ts b/src/component/component.ts index 8e99d2b8..a1974d6e 100644 --- a/src/component/component.ts +++ b/src/component/component.ts @@ -39,11 +39,13 @@ export interface Fiber { isCancelled: boolean; scope: any; vars: any; -// component: Component; -// promises: any[]; -// vnode?: VNode; -// handlers?: any; -// mountedHandlers?: any; + patchQueue: Fiber[]; + component: Component; + // promises: any[]; + vnode: VNode | null; + willPatchResult: any; + // handlers?: any; + // mountedHandlers?: any; } /** @@ -301,9 +303,9 @@ export class Component { } this.__patch(vnode); } else if (renderBeforeRemount) { - const patchQueue = []; - await this.__render(fiber, patchQueue); - this.__applyPatchQueue(patchQueue); + fiber.patchQueue.push(fiber); + await this.__render(fiber); + this.__applyPatchQueue(fiber); } target.appendChild(this.el!); @@ -338,15 +340,15 @@ export class Component { return; } const fiber = this.__createRootFiber(force); - const patchQueue = []; + fiber.patchQueue.push(fiber); const renderId = ++__owl__.renderId; - await this.__render(fiber, patchQueue); + await this.__render(fiber); if (__owl__.isMounted && renderId === __owl__.renderId) { // we only update the vnode and the actual DOM if no other rendering // occurred between now and when the render method was initially called. - this.__applyPatchQueue(patchQueue); + this.__applyPatchQueue(fiber); } } @@ -356,7 +358,11 @@ export class Component { scope: undefined, vars: undefined, rootFiber: null, - isCancelled: false + isCancelled: false, + component: this, + vnode: null, + patchQueue: [], + willPatchResult: null }; fiber.rootFiber = fiber; return fiber; @@ -366,6 +372,9 @@ export class Component { const fiber = Object.create(parent); fiber.scope = scope; fiber.vars = vars; + fiber.component = this; + fiber.vnode = null; + fiber.willPatchResult = null; return fiber; } @@ -511,7 +520,6 @@ export class Component { async __updateProps( nextProps: Props, parentFiber: Fiber, - patchQueue?: any[], scope?: any, vars?: any ): Promise { @@ -524,7 +532,9 @@ export class Component { await this.willUpdateProps(nextProps); this.props = nextProps; const fiber = this.__createSubFiber(parentFiber, scope, vars); - await this.__render(fiber, patchQueue); + fiber.patchQueue.push(fiber); + + await this.__render(fiber); } } @@ -546,6 +556,7 @@ export class Component { __prepare(parentFiber: Fiber, scope: any, vars: any): Promise { const __owl__ = this.__owl__; const fiber = this.__createSubFiber(parentFiber, scope, vars); + __owl__.renderProps = this.props; __owl__.renderPromise = this.__prepareAndRender(fiber); return __owl__.renderPromise; @@ -586,14 +597,12 @@ export class Component { } __owl__.render = qweb.render.bind(qweb, p._template); this.__observeState(); - return this.__render(fiber, []); + return this.__render(fiber); } - __render(fiber: Fiber, patchQueue: any[] = []): Promise { + __render(fiber: Fiber): Promise { const __owl__ = this.__owl__; const promises: Promise[] = []; - const patch: any[] = [this]; - patchQueue.push(patch); if (__owl__.observer) { __owl__.observer.allowMutations = false; } @@ -603,14 +612,13 @@ export class Component { promises, handlers: __owl__.boundHandlers, mountedHandlers: __owl__.mountedHandlers, - fiber: fiber, - patchQueue + fiber: fiber }); } catch (e) { vnode = __owl__.vnode || h("div"); errorHandler(e, this); } - patch.push(vnode); + fiber.vnode = vnode; if (__owl__.observer) { __owl__.observer.allowMutations = true; } @@ -688,29 +696,30 @@ export class Component { } /** - * Apply the given patch queue. A patch is a pair [c, vn], where c is a - * Component instance and vn a VNode. + * Apply the given patch queue from a fiber. * 1) Call 'willPatch' on the component of each patch * 2) Call '__patch' on the component of each patch - * 3) Call 'patched' on the component of each patch, in inverse order + * 3) Call 'patched' on the component of each patch, in reverse order */ - __applyPatchQueue(patchQueue: any[]) { - let component = this; + __applyPatchQueue(fiber: Fiber) { + const patchQueue = fiber.patchQueue; + let component: Component = this; try { const patchLen = patchQueue.length; for (let i = 0; i < patchLen; i++) { - const patch = patchQueue[i]; - component = patch[0]; - patch.push(patch[0].willPatch()); + const fiber = patchQueue[i]; + component = fiber.component; + fiber.willPatchResult = component.willPatch(); } for (let i = 0; i < patchLen; i++) { - const patch = patchQueue[i]; - patch[0].__patch(patch[1]); + const fiber = patchQueue[i]; + component = fiber.component; + component.__patch(fiber.vnode); } for (let i = patchLen - 1; i >= 0; i--) { - const patch = patchQueue[i]; - component = patch[0]; - patch[0].patched(patch[2]); + const fiber = patchQueue[i]; + component = fiber.component; + component.patched(fiber.willPatchResult); } } catch (e) { errorHandler(e, component); diff --git a/src/component/directive.ts b/src/component/directive.ts index 47d21af0..f1ae503c 100644 --- a/src/component/directive.ts +++ b/src/component/directive.ts @@ -356,8 +356,12 @@ QWeb.addDirective({ ctx.addLine(`let _${dummyID}_index = c${ctx.parentNode}.length;`); } let shouldProxy = false; + if (async || keepAlive) { + ctx.addLine( + `const fiber${componentID} = Object.assign(Object.create(extra.fiber), {patchQueue: []});` + ); + } if (async) { - ctx.addLine(`const patchQueue${componentID} = [];`); ctx.addLine( `c${ctx.parentNode}.push(w${componentID} && w${componentID}.__owl__.pvnode || null);` ); @@ -461,19 +465,19 @@ QWeb.addDirective({ ctx.addElse(); // need to update component - let patchQueueCode = async ? `patchQueue${componentID}` : "extra.patchQueue"; + let patchQueueCode = async || 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 ? ${patchQueueCode} : []`; + 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}, extra.fiber, ${patchQueueCode}${scopeVars && + `def${defID} = def${defID} || w${componentID}.__updateProps(props${componentID}, ${patchQueueCode}${scopeVars && ", " + scopeVars});` ); let keepAliveCode = ""; @@ -493,7 +497,7 @@ QWeb.addDirective({ if (async) { ctx.addLine( - `def${defID}.then(w${componentID}.__applyPatchQueue.bind(w${componentID}, patchQueue${componentID}));` + `def${defID}.then(w${componentID}.__applyPatchQueue.bind(w${componentID}, fiber${componentID}));` ); } else { ctx.addLine(`extra.promises.push(def${defID});`); diff --git a/src/store/connected_component.ts b/src/store/connected_component.ts index 20a7c9fc..3d6b6f02 100644 --- a/src/store/connected_component.ts +++ b/src/store/connected_component.ts @@ -106,9 +106,9 @@ export class ConnectedComponent extends Component return (this.__owl__ as any).renderPromise; } - async __updateProps(nextProps: P, f, p, s, v) { + async __updateProps(nextProps: P, f, s, v) { this.__updateStoreProps(nextProps); - return super.__updateProps(nextProps, f, p, s, v); + return super.__updateProps(nextProps, f, s, v); } __updateStoreProps(nextProps): boolean { diff --git a/tests/__snapshots__/animations.test.ts.snap b/tests/__snapshots__/animations.test.ts.snap index 9b0c41c3..2503d3aa 100644 --- a/tests/__snapshots__/animations.test.ts.snap +++ b/tests/__snapshots__/animations.test.ts.snap @@ -37,7 +37,7 @@ exports[`animations t-transition combined with component 1`] = ` }; utils.transitionRemove(vn, 'chimay', finalize);}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -83,7 +83,7 @@ exports[`animations t-transition combined with t-component and t-if 1`] = ` }; utils.transitionRemove(vn, 'chimay', finalize);}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap index ec4e4440..a26579ba 100644 --- a/tests/component/__snapshots__/component.test.ts.snap +++ b/tests/component/__snapshots__/component.test.ts.snap @@ -47,7 +47,7 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = ` def7 = w8.__prepare(extra.fiber, undefined, undefined); def7 = def7.then(vnode=>{if (w8.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 8, hook: {insert(vn) {let nvn=w8.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w8.destroy();}}});c5[_6_index]=pvnode;w8.__owl__.pvnode = pvnode;}); } else { - def7 = def7 || w8.__updateProps(props8, extra.fiber, extra.patchQueue, undefined, undefined); + def7 = def7 || w8.__updateProps(props8, extra.fiber, undefined, undefined); def7 = def7.then(()=>{if (w8.__owl__.isDestroyed) {return};let pvnode=w8.__owl__.pvnode;c5[_6_index]=pvnode;}); } extra.promises.push(def7); @@ -55,7 +55,7 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = ` let def10; let w11 = 11 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[11]] : false; let _9_index = c5.length; - const patchQueue11 = []; + const fiber11 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c5.push(w11 && w11.__owl__.pvnode || null); let props11 = {val:context['state'].val}; if (w11 && w11.__owl__.renderPromise && !w11.__owl__.vnode) { @@ -75,10 +75,10 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = ` def10 = w11.__prepare(extra.fiber, undefined, undefined); def10 = def10.then(vnode=>{if (w11.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 11, hook: {insert(vn) {let nvn=w11.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w11.destroy();}}});c5[_9_index]=pvnode;w11.__owl__.pvnode = pvnode;}); } else { - def10 = def10 || w11.__updateProps(props11, extra.fiber, patchQueue11, undefined, undefined); + def10 = def10 || w11.__updateProps(props11, fiber11, undefined, undefined); def10 = def10.then(()=>{if (w11.__owl__.isDestroyed) {return};let pvnode=w11.__owl__.pvnode;c5[_9_index]=pvnode;}); } - def10.then(w11.__applyPatchQueue.bind(w11, patchQueue11)); + def10.then(w11.__applyPatchQueue.bind(w11, fiber11)); return vn1; }" `; @@ -111,7 +111,7 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = ` let def7; let w8 = 8 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[8]] : false; let _6_index = c5.length; - const patchQueue8 = []; + const fiber8 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c5.push(w8 && w8.__owl__.pvnode || null); let props8 = {val:context['state'].val}; if (w8 && w8.__owl__.renderPromise && !w8.__owl__.vnode) { @@ -131,10 +131,10 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = ` def7 = w8.__prepare(extra.fiber, undefined, undefined); def7 = def7.then(vnode=>{if (w8.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 8, hook: {insert(vn) {let nvn=w8.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w8.destroy();}}});c5[_6_index]=pvnode;w8.__owl__.pvnode = pvnode;}); } else { - def7 = def7 || w8.__updateProps(props8, extra.fiber, patchQueue8, undefined, undefined); + def7 = def7 || w8.__updateProps(props8, fiber8, undefined, undefined); def7 = def7.then(()=>{if (w8.__owl__.isDestroyed) {return};let pvnode=w8.__owl__.pvnode;c5[_6_index]=pvnode;}); } - def7.then(w8.__applyPatchQueue.bind(w8, patchQueue8)); + def7.then(w8.__applyPatchQueue.bind(w8, fiber8)); //COMPONENT let def10; let w11 = 11 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[11]] : false; @@ -158,7 +158,7 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = ` def10 = w11.__prepare(extra.fiber, undefined, undefined); def10 = def10.then(vnode=>{if (w11.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 11, hook: {insert(vn) {let nvn=w11.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w11.destroy();}}});c5[_9_index]=pvnode;w11.__owl__.pvnode = pvnode;}); } else { - def10 = def10 || w11.__updateProps(props11, extra.fiber, extra.patchQueue, undefined, undefined); + def10 = def10 || w11.__updateProps(props11, extra.fiber, undefined, undefined); def10 = def10.then(()=>{if (w11.__owl__.isDestroyed) {return};let pvnode=w11.__owl__.pvnode;c5[_9_index]=pvnode;}); } extra.promises.push(def10); @@ -213,7 +213,7 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render def7 = w8.__prepare(extra.fiber, undefined, undefined); def7 = def7.then(vnode=>{if (w8.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 8, hook: {insert(vn) {let nvn=w8.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w8.destroy();}}});c5[_6_index]=pvnode;w8.__owl__.pvnode = pvnode;}); } else { - def7 = def7 || w8.__updateProps(props8, extra.fiber, extra.patchQueue, undefined, undefined); + def7 = def7 || w8.__updateProps(props8, extra.fiber, undefined, undefined); def7 = def7.then(()=>{if (w8.__owl__.isDestroyed) {return};let pvnode=w8.__owl__.pvnode;c5[_6_index]=pvnode;}); } extra.promises.push(def7); @@ -221,7 +221,7 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render let def10; let w11 = 11 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[11]] : false; let _9_index = c5.length; - const patchQueue11 = []; + const fiber11 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c5.push(w11 && w11.__owl__.pvnode || null); let props11 = {val:context['state'].val}; if (w11 && w11.__owl__.renderPromise && !w11.__owl__.vnode) { @@ -241,10 +241,10 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render def10 = w11.__prepare(extra.fiber, undefined, undefined); def10 = def10.then(vnode=>{if (w11.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 11, hook: {insert(vn) {let nvn=w11.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w11.destroy();}}});c5[_9_index]=pvnode;w11.__owl__.pvnode = pvnode;}); } else { - def10 = def10 || w11.__updateProps(props11, extra.fiber, patchQueue11, undefined, undefined); + def10 = def10 || w11.__updateProps(props11, fiber11, undefined, undefined); def10 = def10.then(()=>{if (w11.__owl__.isDestroyed) {return};let pvnode=w11.__owl__.pvnode;c5[_9_index]=pvnode;}); } - def10.then(w11.__applyPatchQueue.bind(w11, patchQueue11)); + def10.then(w11.__applyPatchQueue.bind(w11, fiber11)); return vn1; }" `; @@ -284,7 +284,7 @@ exports[`class and style attributes with t-component dynamic t-att-style is prop def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.style = _5;}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};w4.el.style=_5;let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -329,7 +329,7 @@ exports[`class and style attributes with t-component t-att-class is properly add def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;context.refs[ref5] = w4;},remove() {},destroy(vn) {w4.destroy();delete context.refs[ref5];}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } w4.__owl__.classObj=_6; @@ -389,7 +389,7 @@ exports[`class and style attributes with t-component t-att-class is properly add def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;context.refs[ref5] = w4;},remove() {},destroy(vn) {w4.destroy();delete context.refs[ref5];}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } w4.__owl__.classObj=_6; @@ -447,7 +447,7 @@ exports[`class and style attributes with t-component t-att-class is properly add def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } w4.__owl__.classObj=_5; @@ -472,6 +472,7 @@ exports[`composition sub components dom state with t-keepalive is preserved 1`] let def3; let w4 = 4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[4]] : false; let _2_index = c1.length; + const fiber4 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c1.push(null); let props4 = {}; if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { @@ -491,7 +492,7 @@ exports[`composition sub components dom state with t-keepalive is preserved 1`] def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.unmount();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, w4.__owl__.isMounted ? extra.patchQueue : [], undefined, undefined); + def3 = def3 || w4.__updateProps(props4, w4.__owl__.isMounted ? extra.fiber : fiber4, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w4.el,vn.elm);vn.elm=w4.el;w4.__remount();};c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -551,7 +552,7 @@ exports[`composition sub components with some state rendered in a loop 1`] = ` def6 = w7.__prepare(extra.fiber, undefined, undefined); def6 = def6.then(vnode=>{if (w7.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId9, hook: {insert(vn) {let nvn=w7.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w7.destroy();}}});c1[_5_index]=pvnode;w7.__owl__.pvnode = pvnode;}); } else { - def6 = def6 || w7.__updateProps(props7, extra.fiber, extra.patchQueue, undefined, undefined); + def6 = def6 || w7.__updateProps(props7, extra.fiber, undefined, undefined); def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c1[_5_index]=pvnode;}); } extra.promises.push(def6); @@ -594,7 +595,7 @@ exports[`composition t-component with dynamic value 1`] = ` def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -636,7 +637,7 @@ exports[`composition t-component with dynamic value 2 1`] = ` def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -678,7 +679,7 @@ exports[`dynamic t-props basic use 1`] = ` def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -702,6 +703,7 @@ exports[`lifecycle hooks willPatch/patched hook with t-keepalive 1`] = ` let def3; let w4 = 4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[4]] : false; let _2_index = c1.length; + const fiber4 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c1.push(null); let props4 = {v:context['state'].n}; if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { @@ -721,7 +723,7 @@ exports[`lifecycle hooks willPatch/patched hook with t-keepalive 1`] = ` def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.unmount();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, w4.__owl__.isMounted ? extra.patchQueue : [], undefined, undefined); + def3 = def3 || w4.__updateProps(props4, w4.__owl__.isMounted ? extra.fiber : fiber4, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w4.el,vn.elm);vn.elm=w4.el;w4.__remount();};c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -764,7 +766,7 @@ exports[`other directives with t-component t-on with handler bound to argument 1 def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, 3));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -806,7 +808,7 @@ exports[`other directives with t-component t-on with handler bound to empty obje def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -848,7 +850,7 @@ exports[`other directives with t-component t-on with handler bound to empty obje def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -890,7 +892,7 @@ exports[`other directives with t-component t-on with handler bound to object 1`] def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, {val:3}));}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -932,7 +934,7 @@ exports[`other directives with t-component t-on with prevent and self modifiers def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {e.preventDefault();if (e.target !== vn.elm) {return}owner['onEv'].call(owner, e);});}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -974,7 +976,7 @@ exports[`other directives with t-component t-on with self and prevent modifiers def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if (e.target !== vn.elm) {return}e.preventDefault();owner['onEv'].call(owner, e);});}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1016,7 +1018,7 @@ exports[`other directives with t-component t-on with self modifier 1`] = ` def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', owner['onEv1'].bind(owner));vn.elm.addEventListener('ev-2', function (e) {if (e.target !== vn.elm) {return}owner['onEv2'].call(owner, e);});}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1058,7 +1060,7 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev-1', function (e) {e.stopPropagation();owner['onEv1'].call(owner, e);});vn.elm.addEventListener('ev-2', function (e) {e.preventDefault();owner['onEv2'].call(owner, e);});vn.elm.addEventListener('ev-3', function (e) {e.stopPropagation();e.preventDefault();owner['onEv3'].call(owner, e);});}};let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1102,7 +1104,7 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = ` def3 = w4.__prepare(extra.fiber, undefined, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId6, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1162,7 +1164,7 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument def6 = w7.__prepare(extra.fiber, undefined, undefined); def6 = def6.then(vnode=>{if (w7.__owl__.isDestroyed){return}vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', owner['onEv'].bind(owner, arg10));}};let pvnode=h(vnode.sel, {key: templateId9, hook: {insert(vn) {let nvn=w7.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w7.destroy();}}});c1[_5_index]=pvnode;w7.__owl__.pvnode = pvnode;}); } else { - def6 = def6 || w7.__updateProps(props7, extra.fiber, extra.patchQueue, undefined, undefined); + def6 = def6 || w7.__updateProps(props7, extra.fiber, undefined, undefined); def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c1[_5_index]=pvnode;}); } extra.promises.push(def6); @@ -1387,7 +1389,7 @@ exports[`t-slot directive can define and call slots 1`] = ` def3 = w4.__prepare(extra.fiber, {}, undefined); def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, {}, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, {}, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); @@ -1629,7 +1631,7 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = ` def8 = w9.__prepare(extra.fiber, Object.assign({}, scope), undefined); def8 = def8.then(vnode=>{if (w9.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId10, hook: {insert(vn) {let nvn=w9.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w9.destroy();}}});c6[_7_index]=pvnode;w9.__owl__.pvnode = pvnode;}); } else { - def8 = def8 || w9.__updateProps(props9, extra.fiber, extra.patchQueue, Object.assign({}, scope), undefined); + def8 = def8 || w9.__updateProps(props9, extra.fiber, Object.assign({}, scope), undefined); def8 = def8.then(()=>{if (w9.__owl__.isDestroyed) {return};let pvnode=w9.__owl__.pvnode;c6[_7_index]=pvnode;}); } extra.promises.push(def8); @@ -1734,7 +1736,7 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` def9 = w10.__prepare(extra.fiber, Object.assign({}, scope), {_7}); def9 = def9.then(vnode=>{if (w10.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId11, hook: {insert(vn) {let nvn=w10.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w10.destroy();}}});c6[_8_index]=pvnode;w10.__owl__.pvnode = pvnode;}); } else { - def9 = def9 || w10.__updateProps(props10, extra.fiber, extra.patchQueue, Object.assign({}, scope), {_7}); + def9 = def9 || w10.__updateProps(props10, extra.fiber, Object.assign({}, scope), {_7}); def9 = def9.then(()=>{if (w10.__owl__.isDestroyed) {return};let pvnode=w10.__owl__.pvnode;c6[_8_index]=pvnode;}); } extra.promises.push(def9); @@ -1792,7 +1794,7 @@ exports[`t-slot directive slots are rendered with proper context, part 4 1`] = ` def4 = w5.__prepare(extra.fiber, {}, {_2}); def4 = def4.then(vnode=>{if (w5.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 5, hook: {insert(vn) {let nvn=w5.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w5.destroy();}}});c1[_3_index]=pvnode;w5.__owl__.pvnode = pvnode;}); } else { - def4 = def4 || w5.__updateProps(props5, extra.fiber, extra.patchQueue, {}, {_2}); + def4 = def4 || w5.__updateProps(props5, extra.fiber, {}, {_2}); def4 = def4.then(()=>{if (w5.__owl__.isDestroyed) {return};let pvnode=w5.__owl__.pvnode;c1[_3_index]=pvnode;}); } extra.promises.push(def4); @@ -1845,7 +1847,7 @@ exports[`top level sub widgets basic use 1`] = ` def2 = w3.__prepare(extra.fiber, undefined, undefined); def2 = def2.then(vnode=>{if (w3.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 3, hook: {insert(vn) {let nvn=w3.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}});utils.defineProxy(vn4, pvnode);w3.__owl__.pvnode = pvnode;}); } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, extra.patchQueue, undefined, undefined); + def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined); def2 = def2.then(()=>{if (w3.__owl__.isDestroyed) {return};let pvnode=w3.__owl__.pvnode;utils.defineProxy(vn4, pvnode);}); } extra.promises.push(def2); @@ -1886,7 +1888,7 @@ exports[`top level sub widgets can select a sub widget 1`] = ` def2 = w3.__prepare(extra.fiber, undefined, undefined); def2 = def2.then(vnode=>{if (w3.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 3, hook: {insert(vn) {let nvn=w3.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}});utils.defineProxy(vn4, pvnode);w3.__owl__.pvnode = pvnode;}); } else { - def2 = def2 || w3.__updateProps(props3, extra.fiber, extra.patchQueue, undefined, undefined); + def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined); def2 = def2.then(()=>{if (w3.__owl__.isDestroyed) {return};let pvnode=w3.__owl__.pvnode;utils.defineProxy(vn4, pvnode);}); } extra.promises.push(def2); @@ -1915,7 +1917,7 @@ exports[`top level sub widgets can select a sub widget 1`] = ` def6 = w7.__prepare(extra.fiber, undefined, undefined); def6 = def6.then(vnode=>{if (w7.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 7, hook: {insert(vn) {let nvn=w7.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w7.destroy();}}});utils.defineProxy(vn8, pvnode);w7.__owl__.pvnode = pvnode;}); } else { - def6 = def6 || w7.__updateProps(props7, extra.fiber, extra.patchQueue, undefined, undefined); + def6 = def6 || w7.__updateProps(props7, extra.fiber, undefined, undefined); def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;utils.defineProxy(vn8, pvnode);}); } extra.promises.push(def6); diff --git a/tests/component/__snapshots__/props_validation.test.ts.snap b/tests/component/__snapshots__/props_validation.test.ts.snap index 9fa88d51..c2227ac2 100644 --- a/tests/component/__snapshots__/props_validation.test.ts.snap +++ b/tests/component/__snapshots__/props_validation.test.ts.snap @@ -40,7 +40,7 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] = def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;}); } else { utils.validateProps(w4.constructor, props4) - def3 = def3 || w4.__updateProps(props4, extra.fiber, extra.patchQueue, undefined, undefined); + def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined); def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;}); } extra.promises.push(def3); diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index 7b0eeb26..8ab8f355 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -137,9 +137,9 @@ describe("basic widget properties", () => { async willStart() { this.state.drinks++; } - async __render(a,b) { + async __render(f) { renderCalls++; - return super.__render(a,b); + return super.__render(f); } } const widget = new TestW(env); @@ -251,7 +251,7 @@ describe("lifecycle hooks", () => { } class ParentWidget extends Widget { - static template = xml`
` + static template = xml`
`; static components = { ChildWidget }; mounted() { steps.push("parent:mounted"); @@ -2143,9 +2143,9 @@ describe("random stuff/miscellaneous", () => { async willStart() { steps.push(`${this.name}:willStart`); } - __render(f, p) { + __render(f) { steps.push(`${this.name}:render`); - return super.__render(f, p); + return super.__render(f); } __patch(vnode) { steps.push(`${this.name}:__patch`); @@ -2487,8 +2487,8 @@ describe("async rendering", () => { // __render) def = makeDeferred(); } - async __render(f, p) { - const result = await super.__render(f, p); + async __render(f) { + const result = await super.__render(f); await def; return result; } @@ -2779,9 +2779,9 @@ describe("updating environment", () => { test("updating widget env does not render widget (if not mounted)", async () => { let n = 0; class TestWidget extends Widget { - __render(a,b) { + __render(f) { n++; - return super.__render(a,b); + return super.__render(f); } } @@ -3719,7 +3719,7 @@ describe("environment and plugins", () => { test("plugin works as expected", async () => { somePlugin(env); class App extends Widget { - static template=xml` + static template = xml`
Red Blue @@ -4185,9 +4185,9 @@ describe("unmounting and remounting", () => { `; state = { n: 2 }; - __render(a, b) { + __render(f) { steps.push("render"); - return super.__render(a, b); + return super.__render(f); } willPatch() { steps.push("willPatch"); diff --git a/tests/component/props_validation.test.ts b/tests/component/props_validation.test.ts index c1160469..543dac83 100644 --- a/tests/component/props_validation.test.ts +++ b/tests/component/props_validation.test.ts @@ -334,7 +334,8 @@ describe("default props", () => { const w = new TestWidget(env, { p: 1 }); await w.mount(fixture); expect(fixture.innerHTML).toMatchSnapshot(); - await w.__updateProps({}, {force: false}); + const fiber = w.__createRootFiber(false); + await w.__updateProps({}, fiber); await w.render(); expect(w.props.p).toBe(4); expect(fixture.innerHTML).toMatchSnapshot(); diff --git a/tests/helpers.ts b/tests/helpers.ts index f9712bf0..9d2870ae 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -99,7 +99,12 @@ export function renderToDOM( * Note that the result of renderToString is guaranteed to be the same as the * one from QWeb. */ -export function renderToString(qweb: QWeb, t: string, context: EvalContext = {}, extra?: any): string { +export function renderToString( + qweb: QWeb, + t: string, + context: EvalContext = {}, + extra?: any +): string { const node = renderToDOM(qweb, t, context, extra); const result = node instanceof Text ? node.textContent! : node.outerHTML; if (result !== qweb.renderToString(t, context, extra)) { diff --git a/tests/qweb/qweb.test.ts b/tests/qweb/qweb.test.ts index b704a780..c24a6193 100644 --- a/tests/qweb/qweb.test.ts +++ b/tests/qweb/qweb.test.ts @@ -637,7 +637,9 @@ describe("t-call (template calling", () => { `); const root = { val: "a", children: [{ val: "b" }, { val: "c" }] }; const expected = "

a

b

c

"; - expect(renderToString(qweb, "Parent", { root }, {fiber: {vars: {}, scope: {}}})).toBe(expected); + expect(renderToString(qweb, "Parent", { root }, { fiber: { vars: {}, scope: {} } })).toBe( + expected + ); const recursiveFn = Object.values(qweb.recursiveFns)[0]; expect(recursiveFn.toString()).toMatchSnapshot(); }); @@ -664,18 +666,17 @@ describe("t-call (template calling", () => { const root = { val: "a", children: [{ val: "b", children: [{ val: "d" }] }, { val: "c" }] }; const expected = "

a

b

d

c

"; - expect(renderToString(qweb, "Parent", { root }, {fiber: {}})).toBe(expected); + expect(renderToString(qweb, "Parent", { root }, { fiber: {} })).toBe(expected); const recursiveFn = Object.values(qweb.recursiveFns)[0]; expect(recursiveFn.toString()).toMatchSnapshot(); }); test("t-call, global templates", () => { - QWeb.registerTemplate('abcd', '
') + QWeb.registerTemplate("abcd", '
'); qweb.addTemplate("john", `desk`); const expected = "
desk
"; expect(trim(renderToString(qweb, "abcd"))).toBe(expected); }); - }); describe("foreach", () => { diff --git a/tests/router/__snapshots__/RouteComponent.test.ts.snap b/tests/router/__snapshots__/RouteComponent.test.ts.snap index 374ad3b0..601c0413 100644 --- a/tests/router/__snapshots__/RouteComponent.test.ts.snap +++ b/tests/router/__snapshots__/RouteComponent.test.ts.snap @@ -49,7 +49,7 @@ exports[`RouteComponent can render simple cases 1`] = ` def5 = w6.__prepare(extra.fiber, undefined, undefined); def5 = def5.then(vnode=>{if (w6.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId7, hook: {insert(vn) {let nvn=w6.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w6.destroy();}}});utils.defineProxy(vn8, pvnode);w6.__owl__.pvnode = pvnode;}); } else { - def5 = def5 || w6.__updateProps(props6, extra.fiber, extra.patchQueue, undefined, undefined); + def5 = def5 || w6.__updateProps(props6, extra.fiber, undefined, undefined); def5 = def5.then(()=>{if (w6.__owl__.isDestroyed) {return};let pvnode=w6.__owl__.pvnode;utils.defineProxy(vn8, pvnode);}); } extra.promises.push(def5); diff --git a/tests/store/connected_component.test.ts b/tests/store/connected_component.test.ts index 04182b9d..69cd247b 100644 --- a/tests/store/connected_component.test.ts +++ b/tests/store/connected_component.test.ts @@ -698,9 +698,9 @@ describe("connecting a component to store", () => { editTodo() { this.env.store.dispatch("editTodo"); } - __render(f,p) { + __render(f) { renderCount++; - return super.__render(f,p); + return super.__render(f); } } class TodoApp extends ConnectedComponent { @@ -776,9 +776,9 @@ describe("connecting a component to store", () => { removeTodo() { this.env.store.dispatch("removeTodo"); } - __render(f,p) { + __render(f) { renderCount++; - return super.__render(f,p); + return super.__render(f); } } @@ -910,7 +910,7 @@ describe("connected components and default values", () => { await app.mount(fixture); expect(fixture.innerHTML).toBe("
Hello, John
"); - const fiber = { force: true, scope: undefined, vars: undefined } + const fiber = app.__createRootFiber(true); await app.__updateProps({ initialRecipient: "James" }, fiber); await app.render(); expect(fixture.innerHTML).toBe("
Hello, James
"); @@ -998,7 +998,7 @@ describe("connected components and default values", () => { "
100Message100
101Message101
" ); - const fiber = { force: true, scope: undefined, vars: undefined } + const fiber = app.__createRootFiber(true); await app.__updateProps({ threadId: 2 }, fiber); await app.render(); expect(fixture.innerHTML).toBe("
200Message200
"); From 7a49b9d94e5cf4fc64756b79d3d60186b715f222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 19 Sep 2019 15:14:04 +0200 Subject: [PATCH 3/4] [REF] component: move render props and promise to fiber part of #293 --- src/component/component.ts | 71 ++++--- src/component/directive.ts | 8 +- tests/__snapshots__/animations.test.ts.snap | 12 +- .../__snapshots__/component.test.ts.snap | 198 +++++++++--------- .../props_validation.test.ts.snap | 6 +- .../__snapshots__/RouteComponent.test.ts.snap | 6 +- 6 files changed, 153 insertions(+), 148 deletions(-) diff --git a/src/component/component.ts b/src/component/component.ts index a1974d6e..41160eb7 100644 --- a/src/component/component.ts +++ b/src/component/component.ts @@ -33,17 +33,24 @@ export interface Env { [key: string]: any; } -export interface Fiber { +/** + * Fibers are small abstractions designed to contain all the internal state + * associated to a "rendering work unit", relative to a specific component. + * + * A rendering will cause the creation of a fiber for each impacted components. + */ +export interface Fiber { force: boolean; - rootFiber: Fiber | null; + rootFiber: Fiber | null; isCancelled: boolean; scope: any; vars: any; - patchQueue: Fiber[]; + patchQueue: Fiber[]; component: Component; - // promises: any[]; vnode: VNode | null; willPatchResult: any; + props: Props; + promise: Promise | null; // handlers?: any; // mountedHandlers?: any; } @@ -70,13 +77,7 @@ interface Internal { // the component instance back whenever the template is rerendered. cmap: { [key: number]: number }; - renderId: number; - - // the renderProps and renderPromise keys are only useful for the "prepare" - // step of the lifecycle of a component. Once a component has been rendered - // and patched, it is no longer useful. - renderProps: Props | null; - renderPromise: Promise | null; + currentFiber: Fiber | null; boundHandlers: { [key: number]: any }; observer: Observer | null; @@ -184,9 +185,7 @@ export class Component { parent: p, children: {}, cmap: {}, - renderId: 1, - renderPromise: null, - renderProps: props || null, + currentFiber: null, boundHandlers: {}, mountedHandlers: {}, observer: null, @@ -296,7 +295,8 @@ export class Component { } const fiber = this.__createRootFiber(false); if (!__owl__.vnode) { - const vnode = await this.__prepareAndRender(fiber); + fiber.promise = this.__prepareAndRender(fiber); + const vnode = await fiber.promise; if (__owl__.isDestroyed) { // component was destroyed before we get here... return; @@ -304,7 +304,8 @@ export class Component { this.__patch(vnode); } else if (renderBeforeRemount) { fiber.patchQueue.push(fiber); - await this.__render(fiber); + fiber.promise = this.__render(fiber); + await fiber.promise; this.__applyPatchQueue(fiber); } target.appendChild(this.el!); @@ -341,19 +342,18 @@ export class Component { } const fiber = this.__createRootFiber(force); fiber.patchQueue.push(fiber); + fiber.promise = this.__render(fiber); + await fiber.promise; - const renderId = ++__owl__.renderId; - await this.__render(fiber); - - if (__owl__.isMounted && renderId === __owl__.renderId) { + if (__owl__.isMounted && fiber === __owl__.currentFiber) { // we only update the vnode and the actual DOM if no other rendering // occurred between now and when the render method was initially called. this.__applyPatchQueue(fiber); } } - __createRootFiber(force): Fiber { - const fiber: Fiber = { + __createRootFiber(force): Fiber { + const fiber: Fiber = { force, scope: undefined, vars: undefined, @@ -362,19 +362,25 @@ export class Component { component: this, vnode: null, patchQueue: [], - willPatchResult: null + willPatchResult: null, + props: this.props, + promise: null }; fiber.rootFiber = fiber; + this.__owl__.currentFiber = fiber; return fiber; } - __createSubFiber(parent: Fiber, scope, vars): Fiber { + __createSubFiber(parent: Fiber, scope, vars): Fiber { const fiber = Object.create(parent); fiber.scope = scope; fiber.vars = vars; fiber.component = this; fiber.vnode = null; fiber.willPatchResult = null; + this.__owl__.currentFiber = fiber; + fiber.props = this.props; + fiber.promise = null; return fiber; } @@ -519,7 +525,7 @@ export class Component { */ async __updateProps( nextProps: Props, - parentFiber: Fiber, + parentFiber: Fiber, scope?: any, vars?: any ): Promise { @@ -553,16 +559,13 @@ export class Component { * subcomponent is created. It gets its scope and vars, if any, from the * parent template. */ - __prepare(parentFiber: Fiber, scope: any, vars: any): Promise { - const __owl__ = this.__owl__; + __prepare(parentFiber: Fiber, scope: any, vars: any): Promise { const fiber = this.__createSubFiber(parentFiber, scope, vars); - - __owl__.renderProps = this.props; - __owl__.renderPromise = this.__prepareAndRender(fiber); - return __owl__.renderPromise; + fiber.promise = this.__prepareAndRender(fiber); + return fiber.promise; } - async __prepareAndRender(fiber: Fiber): Promise { + async __prepareAndRender(fiber: Fiber): Promise { try { await this.willStart(); } catch (e) { @@ -600,7 +603,7 @@ export class Component { return this.__render(fiber); } - __render(fiber: Fiber): Promise { + __render(fiber: Fiber): Promise { const __owl__ = this.__owl__; const promises: Promise[] = []; if (__owl__.observer) { @@ -701,7 +704,7 @@ export class Component { * 2) Call '__patch' on the component of each patch * 3) Call 'patched' on the component of each patch, in reverse order */ - __applyPatchQueue(fiber: Fiber) { + __applyPatchQueue(fiber: Fiber) { const patchQueue = fiber.patchQueue; let component: Component = this; try { diff --git a/src/component/directive.ts b/src/component/directive.ts index f1ae503c..948008f7 100644 --- a/src/component/directive.ts +++ b/src/component/directive.ts @@ -384,10 +384,12 @@ QWeb.addDirective({ ctx.addLine(`let props${componentID} = {${propStr}};`); } ctx.addIf( - `w${componentID} && w${componentID}.__owl__.renderPromise && !w${componentID}.__owl__.vnode` + `w${componentID} && w${componentID}.__owl__.currentFiber && !w${componentID}.__owl__.vnode` ); - ctx.addIf(`utils.shallowEqual(props${componentID}, w${componentID}.__owl__.renderProps)`); - ctx.addLine(`def${defID} = w${componentID}.__owl__.renderPromise;`); + ctx.addIf( + `utils.shallowEqual(props${componentID}, w${componentID}.__owl__.currentFiber.props)` + ); + ctx.addLine(`def${defID} = w${componentID}.__owl__.currentFiber.promise;`); ctx.addElse(); ctx.addLine(`w${componentID}.destroy();`); ctx.addLine(`w${componentID} = false;`); diff --git a/tests/__snapshots__/animations.test.ts.snap b/tests/__snapshots__/animations.test.ts.snap index 2503d3aa..c9f40872 100644 --- a/tests/__snapshots__/animations.test.ts.snap +++ b/tests/__snapshots__/animations.test.ts.snap @@ -17,9 +17,9 @@ exports[`animations t-transition combined with component 1`] = ` let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -63,9 +63,9 @@ exports[`animations t-transition combined with t-component and t-if 1`] = ` let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap index a26579ba..3e6dc975 100644 --- a/tests/component/__snapshots__/component.test.ts.snap +++ b/tests/component/__snapshots__/component.test.ts.snap @@ -30,9 +30,9 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = ` let _6_index = c5.length; c5.push(null); let props8 = {val:context['state'].val}; - if (w8 && w8.__owl__.renderPromise && !w8.__owl__.vnode) { - if (utils.shallowEqual(props8, w8.__owl__.renderProps)) { - def7 = w8.__owl__.renderPromise; + if (w8 && w8.__owl__.currentFiber && !w8.__owl__.vnode) { + if (utils.shallowEqual(props8, w8.__owl__.currentFiber.props)) { + def7 = w8.__owl__.currentFiber.promise; } else { w8.destroy(); w8 = false; @@ -58,9 +58,9 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = ` const fiber11 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c5.push(w11 && w11.__owl__.pvnode || null); let props11 = {val:context['state'].val}; - if (w11 && w11.__owl__.renderPromise && !w11.__owl__.vnode) { - if (utils.shallowEqual(props11, w11.__owl__.renderProps)) { - def10 = w11.__owl__.renderPromise; + if (w11 && w11.__owl__.currentFiber && !w11.__owl__.vnode) { + if (utils.shallowEqual(props11, w11.__owl__.currentFiber.props)) { + def10 = w11.__owl__.currentFiber.promise; } else { w11.destroy(); w11 = false; @@ -114,9 +114,9 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = ` const fiber8 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c5.push(w8 && w8.__owl__.pvnode || null); let props8 = {val:context['state'].val}; - if (w8 && w8.__owl__.renderPromise && !w8.__owl__.vnode) { - if (utils.shallowEqual(props8, w8.__owl__.renderProps)) { - def7 = w8.__owl__.renderPromise; + if (w8 && w8.__owl__.currentFiber && !w8.__owl__.vnode) { + if (utils.shallowEqual(props8, w8.__owl__.currentFiber.props)) { + def7 = w8.__owl__.currentFiber.promise; } else { w8.destroy(); w8 = false; @@ -141,9 +141,9 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = ` let _9_index = c5.length; c5.push(null); let props11 = {val:context['state'].val}; - if (w11 && w11.__owl__.renderPromise && !w11.__owl__.vnode) { - if (utils.shallowEqual(props11, w11.__owl__.renderProps)) { - def10 = w11.__owl__.renderPromise; + if (w11 && w11.__owl__.currentFiber && !w11.__owl__.vnode) { + if (utils.shallowEqual(props11, w11.__owl__.currentFiber.props)) { + def10 = w11.__owl__.currentFiber.promise; } else { w11.destroy(); w11 = false; @@ -196,9 +196,9 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render let _6_index = c5.length; c5.push(null); let props8 = {val:context['state'].val}; - if (w8 && w8.__owl__.renderPromise && !w8.__owl__.vnode) { - if (utils.shallowEqual(props8, w8.__owl__.renderProps)) { - def7 = w8.__owl__.renderPromise; + if (w8 && w8.__owl__.currentFiber && !w8.__owl__.vnode) { + if (utils.shallowEqual(props8, w8.__owl__.currentFiber.props)) { + def7 = w8.__owl__.currentFiber.promise; } else { w8.destroy(); w8 = false; @@ -224,9 +224,9 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render const fiber11 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c5.push(w11 && w11.__owl__.pvnode || null); let props11 = {val:context['state'].val}; - if (w11 && w11.__owl__.renderPromise && !w11.__owl__.vnode) { - if (utils.shallowEqual(props11, w11.__owl__.renderProps)) { - def10 = w11.__owl__.renderPromise; + if (w11 && w11.__owl__.currentFiber && !w11.__owl__.vnode) { + if (utils.shallowEqual(props11, w11.__owl__.currentFiber.props)) { + def10 = w11.__owl__.currentFiber.promise; } else { w11.destroy(); w11 = false; @@ -267,9 +267,9 @@ exports[`class and style attributes with t-component dynamic t-att-style is prop let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -312,9 +312,9 @@ exports[`class and style attributes with t-component t-att-class is properly add let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -372,9 +372,9 @@ exports[`class and style attributes with t-component t-att-class is properly add let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -430,9 +430,9 @@ exports[`class and style attributes with t-component t-att-class is properly add let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -475,9 +475,9 @@ exports[`composition sub components dom state with t-keepalive is preserved 1`] const fiber4 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -535,9 +535,9 @@ exports[`composition sub components with some state rendered in a loop 1`] = ` let _5_index = c1.length; c1.push(null); let props7 = {}; - if (w7 && w7.__owl__.renderPromise && !w7.__owl__.vnode) { - if (utils.shallowEqual(props7, w7.__owl__.renderProps)) { - def6 = w7.__owl__.renderPromise; + if (w7 && w7.__owl__.currentFiber && !w7.__owl__.vnode) { + if (utils.shallowEqual(props7, w7.__owl__.currentFiber.props)) { + def6 = w7.__owl__.currentFiber.promise; } else { w7.destroy(); w7 = false; @@ -578,9 +578,9 @@ exports[`composition t-component with dynamic value 1`] = ` let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -620,9 +620,9 @@ exports[`composition t-component with dynamic value 2 1`] = ` let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -662,9 +662,9 @@ exports[`dynamic t-props basic use 1`] = ` let _2_index = c1.length; c1.push(null); let props4 = Object.assign({}, context['some'].obj); - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -706,9 +706,9 @@ exports[`lifecycle hooks willPatch/patched hook with t-keepalive 1`] = ` const fiber4 = Object.assign(Object.create(extra.fiber), {patchQueue: []}); c1.push(null); let props4 = {v:context['state'].n}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -749,9 +749,9 @@ exports[`other directives with t-component t-on with handler bound to argument 1 let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -791,9 +791,9 @@ exports[`other directives with t-component t-on with handler bound to empty obje let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -833,9 +833,9 @@ exports[`other directives with t-component t-on with handler bound to empty obje let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -875,9 +875,9 @@ exports[`other directives with t-component t-on with handler bound to object 1`] let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -917,9 +917,9 @@ exports[`other directives with t-component t-on with prevent and self modifiers let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -959,9 +959,9 @@ exports[`other directives with t-component t-on with self and prevent modifiers let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -1001,9 +1001,9 @@ exports[`other directives with t-component t-on with self modifier 1`] = ` let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -1043,9 +1043,9 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -1087,9 +1087,9 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = ` let _2_index = c1.length; c1.push(null); let props4 = {flag:context['state'].flag}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -1147,9 +1147,9 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument let _5_index = c1.length; c1.push(null); let props7 = {}; - if (w7 && w7.__owl__.renderPromise && !w7.__owl__.vnode) { - if (utils.shallowEqual(props7, w7.__owl__.renderProps)) { - def6 = w7.__owl__.renderPromise; + if (w7 && w7.__owl__.currentFiber && !w7.__owl__.vnode) { + if (utils.shallowEqual(props7, w7.__owl__.currentFiber.props)) { + def6 = w7.__owl__.currentFiber.promise; } else { w7.destroy(); w7 = false; @@ -1371,9 +1371,9 @@ exports[`t-slot directive can define and call slots 1`] = ` let _2_index = c1.length; c1.push(null); let props4 = {}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; @@ -1613,9 +1613,9 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = ` let _7_index = c6.length; c6.push(null); let props9 = {to:'/user/'+context['user'].id}; - if (w9 && w9.__owl__.renderPromise && !w9.__owl__.vnode) { - if (utils.shallowEqual(props9, w9.__owl__.renderProps)) { - def8 = w9.__owl__.renderPromise; + if (w9 && w9.__owl__.currentFiber && !w9.__owl__.vnode) { + if (utils.shallowEqual(props9, w9.__owl__.currentFiber.props)) { + def8 = w9.__owl__.currentFiber.promise; } else { w9.destroy(); w9 = false; @@ -1718,9 +1718,9 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` let _8_index = c6.length; c6.push(null); let props10 = {to:'/user/'+context['user'].id}; - if (w10 && w10.__owl__.renderPromise && !w10.__owl__.vnode) { - if (utils.shallowEqual(props10, w10.__owl__.renderProps)) { - def9 = w10.__owl__.renderPromise; + if (w10 && w10.__owl__.currentFiber && !w10.__owl__.vnode) { + if (utils.shallowEqual(props10, w10.__owl__.currentFiber.props)) { + def9 = w10.__owl__.currentFiber.promise; } else { w10.destroy(); w10 = false; @@ -1776,9 +1776,9 @@ exports[`t-slot directive slots are rendered with proper context, part 4 1`] = ` let _3_index = c1.length; c1.push(null); let props5 = {to:'/user/'+context['state'].user.id}; - if (w5 && w5.__owl__.renderPromise && !w5.__owl__.vnode) { - if (utils.shallowEqual(props5, w5.__owl__.renderProps)) { - def4 = w5.__owl__.renderPromise; + if (w5 && w5.__owl__.currentFiber && !w5.__owl__.vnode) { + if (utils.shallowEqual(props5, w5.__owl__.currentFiber.props)) { + def4 = w5.__owl__.currentFiber.promise; } else { w5.destroy(); w5 = false; @@ -1830,9 +1830,9 @@ exports[`top level sub widgets basic use 1`] = ` let vn4 = {}; result = vn4; let props3 = {p:1}; - if (w3 && w3.__owl__.renderPromise && !w3.__owl__.vnode) { - if (utils.shallowEqual(props3, w3.__owl__.renderProps)) { - def2 = w3.__owl__.renderPromise; + if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { + if (utils.shallowEqual(props3, w3.__owl__.currentFiber.props)) { + def2 = w3.__owl__.currentFiber.promise; } else { w3.destroy(); w3 = false; @@ -1871,9 +1871,9 @@ exports[`top level sub widgets can select a sub widget 1`] = ` let vn4 = {}; result = vn4; let props3 = {}; - if (w3 && w3.__owl__.renderPromise && !w3.__owl__.vnode) { - if (utils.shallowEqual(props3, w3.__owl__.renderProps)) { - def2 = w3.__owl__.renderPromise; + if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { + if (utils.shallowEqual(props3, w3.__owl__.currentFiber.props)) { + def2 = w3.__owl__.currentFiber.promise; } else { w3.destroy(); w3 = false; @@ -1900,9 +1900,9 @@ exports[`top level sub widgets can select a sub widget 1`] = ` let vn8 = {}; result = vn8; let props7 = {}; - if (w7 && w7.__owl__.renderPromise && !w7.__owl__.vnode) { - if (utils.shallowEqual(props7, w7.__owl__.renderProps)) { - def6 = w7.__owl__.renderPromise; + if (w7 && w7.__owl__.currentFiber && !w7.__owl__.vnode) { + if (utils.shallowEqual(props7, w7.__owl__.currentFiber.props)) { + def6 = w7.__owl__.currentFiber.promise; } else { w7.destroy(); w7 = false; diff --git a/tests/component/__snapshots__/props_validation.test.ts.snap b/tests/component/__snapshots__/props_validation.test.ts.snap index c2227ac2..3ccffd98 100644 --- a/tests/component/__snapshots__/props_validation.test.ts.snap +++ b/tests/component/__snapshots__/props_validation.test.ts.snap @@ -21,9 +21,9 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] = let _2_index = c1.length; c1.push(null); let props4 = {message:1}; - if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) { - if (utils.shallowEqual(props4, w4.__owl__.renderProps)) { - def3 = w4.__owl__.renderPromise; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + if (utils.shallowEqual(props4, w4.__owl__.currentFiber.props)) { + def3 = w4.__owl__.currentFiber.promise; } else { w4.destroy(); w4 = false; diff --git a/tests/router/__snapshots__/RouteComponent.test.ts.snap b/tests/router/__snapshots__/RouteComponent.test.ts.snap index 601c0413..9d8097f3 100644 --- a/tests/router/__snapshots__/RouteComponent.test.ts.snap +++ b/tests/router/__snapshots__/RouteComponent.test.ts.snap @@ -32,9 +32,9 @@ exports[`RouteComponent can render simple cases 1`] = ` let vn8 = {}; result = vn8; let props6 = Object.assign({}, context['env'].router.currentParams); - if (w6 && w6.__owl__.renderPromise && !w6.__owl__.vnode) { - if (utils.shallowEqual(props6, w6.__owl__.renderProps)) { - def5 = w6.__owl__.renderPromise; + if (w6 && w6.__owl__.currentFiber && !w6.__owl__.vnode) { + if (utils.shallowEqual(props6, w6.__owl__.currentFiber.props)) { + def5 = w6.__owl__.currentFiber.promise; } else { w6.destroy(); w6 = false; From caa63628dc667e1205e89471b30eb3ea023180a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Fri, 20 Sep 2019 11:08:16 +0200 Subject: [PATCH 4/4] [REF] component: refactor fiber creation methods --- src/component/component.ts | 31 +++++++----------------- src/store/connected_component.ts | 5 ++-- tests/component/props_validation.test.ts | 2 +- tests/store/connected_component.test.ts | 4 +-- 4 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/component/component.ts b/src/component/component.ts index 41160eb7..6b40e63d 100644 --- a/src/component/component.ts +++ b/src/component/component.ts @@ -293,7 +293,7 @@ export class Component { if (__owl__.isMounted) { return; } - const fiber = this.__createRootFiber(false); + const fiber = this.__createFiber(false, undefined, undefined, undefined); if (!__owl__.vnode) { fiber.promise = this.__prepareAndRender(fiber); const vnode = await fiber.promise; @@ -340,7 +340,7 @@ export class Component { if (!__owl__.isMounted) { return; } - const fiber = this.__createRootFiber(force); + const fiber = this.__createFiber(force, undefined, undefined, undefined); fiber.patchQueue.push(fiber); fiber.promise = this.__render(fiber); await fiber.promise; @@ -352,38 +352,25 @@ export class Component { } } - __createRootFiber(force): Fiber { + __createFiber(force, scope, vars, parent?: Fiber): Fiber { const fiber: Fiber = { force, - scope: undefined, - vars: undefined, + scope, + vars, rootFiber: null, isCancelled: false, component: this, vnode: null, - patchQueue: [], + patchQueue: parent ? parent.patchQueue : [], willPatchResult: null, props: this.props, promise: null }; - fiber.rootFiber = fiber; + fiber.rootFiber = parent || fiber; this.__owl__.currentFiber = fiber; return fiber; } - __createSubFiber(parent: Fiber, scope, vars): Fiber { - const fiber = Object.create(parent); - fiber.scope = scope; - fiber.vars = vars; - fiber.component = this; - fiber.vnode = null; - fiber.willPatchResult = null; - this.__owl__.currentFiber = fiber; - fiber.props = this.props; - fiber.promise = null; - return fiber; - } - /** * Destroy the component. This operation is quite complex: * - it recursively destroy all children @@ -537,7 +524,7 @@ export class Component { } await this.willUpdateProps(nextProps); this.props = nextProps; - const fiber = this.__createSubFiber(parentFiber, scope, vars); + const fiber = this.__createFiber(parentFiber.force, scope, vars, parentFiber); fiber.patchQueue.push(fiber); await this.__render(fiber); @@ -560,7 +547,7 @@ export class Component { * parent template. */ __prepare(parentFiber: Fiber, scope: any, vars: any): Promise { - const fiber = this.__createSubFiber(parentFiber, scope, vars); + const fiber = this.__createFiber(parentFiber.force, scope, vars, parentFiber); fiber.promise = this.__prepareAndRender(fiber); return fiber.promise; } diff --git a/src/store/connected_component.ts b/src/store/connected_component.ts index 3d6b6f02..7ed46430 100644 --- a/src/store/connected_component.ts +++ b/src/store/connected_component.ts @@ -1,4 +1,5 @@ import { Component, Env, Fiber } from "../component/component"; +import { VNode } from "../vdom/index"; //------------------------------------------------------------------------------ // Connect function @@ -46,9 +47,7 @@ export class ConnectedComponent extends Component /** * Need to do this here so 'deep' can be overrided by subcomponent easily */ - async __prepareAndRender( - fiber: Fiber - ): ReturnType["__prepareAndRender"]> { + async __prepareAndRender(fiber: Fiber

): Promise { const store = this.getStore(this.env); const ownProps = this.props || {}; this.storeProps = (this.constructor).mapStoreToProps(store.state, ownProps, store.getters); diff --git a/tests/component/props_validation.test.ts b/tests/component/props_validation.test.ts index 543dac83..3bfeefc5 100644 --- a/tests/component/props_validation.test.ts +++ b/tests/component/props_validation.test.ts @@ -334,7 +334,7 @@ describe("default props", () => { const w = new TestWidget(env, { p: 1 }); await w.mount(fixture); expect(fixture.innerHTML).toMatchSnapshot(); - const fiber = w.__createRootFiber(false); + const fiber = w.__createFiber(false, undefined, undefined, undefined); await w.__updateProps({}, fiber); await w.render(); expect(w.props.p).toBe(4); diff --git a/tests/store/connected_component.test.ts b/tests/store/connected_component.test.ts index 69cd247b..78754e83 100644 --- a/tests/store/connected_component.test.ts +++ b/tests/store/connected_component.test.ts @@ -910,7 +910,7 @@ describe("connected components and default values", () => { await app.mount(fixture); expect(fixture.innerHTML).toBe("

Hello, John
"); - const fiber = app.__createRootFiber(true); + const fiber = app.__createFiber(true, undefined, undefined, undefined); await app.__updateProps({ initialRecipient: "James" }, fiber); await app.render(); expect(fixture.innerHTML).toBe("
Hello, James
"); @@ -998,7 +998,7 @@ describe("connected components and default values", () => { "
100Message100
101Message101
" ); - const fiber = app.__createRootFiber(true); + const fiber = app.__createFiber(true, undefined, undefined, undefined); await app.__updateProps({ threadId: 2 }, fiber); await app.render(); expect(fixture.innerHTML).toBe("
200Message200
");