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
");