From e646eb697ebbd457fe5c32a54990a6a277bcf879 Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Tue, 18 May 2021 09:04:37 +0200 Subject: [PATCH] [FIX] qweb: fix order of lookup in t-component directive Previously, the order of resolution was: - components defined on the class of the current component - components defined on the QWeb instance - the current instance's context This is unnatural because it doesn't go from most specific to least, as the current instance's context is the most specific. This is also fragile, as adding components to the QWeb instance can break unrelated components. This commit fixes that by making the lookup start with the current component's context instead --- src/component/directive.ts | 7 +- tests/__snapshots__/animations.test.ts.snap | 6 +- .../__snapshots__/class_style.test.ts.snap | 6 +- .../__snapshots__/component.test.ts.snap | 66 +++++++++---------- .../props_validation.test.ts.snap | 2 +- .../__snapshots__/slots.test.ts.snap | 10 +-- tests/component/component.test.ts | 17 +++++ .../route_component.test.ts.snap | 2 +- 8 files changed, 65 insertions(+), 51 deletions(-) diff --git a/src/component/directive.ts b/src/component/directive.ts index ff4c28ac..3712dc0b 100644 --- a/src/component/directive.ts +++ b/src/component/directive.ts @@ -378,14 +378,11 @@ QWeb.addDirective({ ctx.addElse(); // new component - let dynamicFallback = ""; - if (!value.match(INTERP_REGEXP)) { - dynamicFallback = `|| ${ctx.formatExpression(value)}`; - } + const contextualValue = value.match(INTERP_REGEXP) ? "false" : ctx.formatExpression(value); const interpValue = ctx.interpolate(value); ctx.addLine(`let componentKey${componentID} = ${interpValue};`); ctx.addLine( - `let W${componentID} = context.constructor.components[componentKey${componentID}] || QWeb.components[componentKey${componentID}]${dynamicFallback};` + `let W${componentID} = ${contextualValue} || context.constructor.components[componentKey${componentID}] || QWeb.components[componentKey${componentID}];` ); // maybe only do this in dev mode... diff --git a/tests/__snapshots__/animations.test.ts.snap b/tests/__snapshots__/animations.test.ts.snap index 821a1eff..d054297f 100644 --- a/tests/__snapshots__/animations.test.ts.snap +++ b/tests/__snapshots__/animations.test.ts.snap @@ -24,7 +24,7 @@ exports[`animations t-transition combined with component 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); const __patch2 = w2.__patch; @@ -69,7 +69,7 @@ exports[`animations t-transition combined with t-component and t-if 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); const __patch2 = w2.__patch; @@ -115,7 +115,7 @@ exports[`animations t-transition combined with t-component, remove and re-add be c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); const __patch2 = w2.__patch; diff --git a/tests/component/__snapshots__/class_style.test.ts.snap b/tests/component/__snapshots__/class_style.test.ts.snap index 7aa53646..32797b72 100644 --- a/tests/component/__snapshots__/class_style.test.ts.snap +++ b/tests/component/__snapshots__/class_style.test.ts.snap @@ -25,7 +25,7 @@ exports[`class and style attributes with t-component dynamic t-att-style is prop c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -67,7 +67,7 @@ exports[`class and style attributes with t-component t-att-class is properly add c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -125,7 +125,7 @@ exports[`class and style attributes with t-component t-att-class is properly add c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap index a78b1ced..8884483d 100644 --- a/tests/component/__snapshots__/component.test.ts.snap +++ b/tests/component/__snapshots__/component.test.ts.snap @@ -24,7 +24,7 @@ exports[`basic widget properties can handle empty props 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -97,7 +97,7 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for c1.push(pvnode); } else { let componentKey10 = \`Child\`; - let W10 = context.constructor.components[componentKey10] || QWeb.components[componentKey10]|| scope['Child']; + let W10 = scope['Child'] || context.constructor.components[componentKey10] || QWeb.components[componentKey10]; if (!W10) {throw new Error('Cannot find the definition of component \\"' + componentKey10 + '\\"')} w10 = new W10(parent, props10); parent.__owl__.cmap[k11] = w10.__owl__.id; @@ -145,7 +145,7 @@ exports[`basic widget properties same t-keys in two different places 1`] = ` c2.push(pvnode); } else { let componentKey3 = \`Child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; + let W3 = scope['Child'] || context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[k4] = w3.__owl__.id; @@ -175,7 +175,7 @@ exports[`basic widget properties same t-keys in two different places 1`] = ` c5.push(pvnode); } else { let componentKey6 = \`Child\`; - let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| scope['Child']; + let W6 = scope['Child'] || context.constructor.components[componentKey6] || QWeb.components[componentKey6]; if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} w6 = new W6(parent, props6); parent.__owl__.cmap[k7] = w6.__owl__.id; @@ -218,7 +218,7 @@ exports[`basic widget properties t-key on a component with t-if, and a sibling c c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap[k3] = w2.__owl__.id; @@ -243,7 +243,7 @@ exports[`basic widget properties t-key on a component with t-if, and a sibling c c1.push(pvnode); } else { let componentKey4 = \`Child\`; - let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| scope['Child']; + let W4 = scope['Child'] || context.constructor.components[componentKey4] || QWeb.components[componentKey4]; if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap['__5__'] = w4.__owl__.id; @@ -301,7 +301,7 @@ exports[`composition sub components with some state rendered in a loop 1`] = ` c1.push(pvnode); } else { let componentKey6 = \`ChildWidget\`; - let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| scope['ChildWidget']; + let W6 = scope['ChildWidget'] || context.constructor.components[componentKey6] || QWeb.components[componentKey6]; if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} w6 = new W6(parent, props6); parent.__owl__.cmap[k7] = w6.__owl__.id; @@ -342,7 +342,7 @@ exports[`composition t-component with dynamic value 1`] = ` c1.push(pvnode); } else { let componentKey2 = (scope['state'].widget); - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]; + let W2 = false || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -380,7 +380,7 @@ exports[`composition t-component with dynamic value 2 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Widget\${scope['state'].widget}\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]; + let W2 = false || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -440,7 +440,7 @@ exports[`composition t-ref on a node, and t-on-click 2`] = ` c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -478,7 +478,7 @@ exports[`dynamic t-props basic use 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -523,7 +523,7 @@ exports[`other directives with t-component slot setted value (with t-set) not ac c1.push(pvnode); } else { let componentKey3 = \`ChildWidget\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['ChildWidget']; + let W3 = scope['ChildWidget'] || context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap['__4__'] = w3.__owl__.id; @@ -766,7 +766,7 @@ exports[`other directives with t-component t-on with .capture modifier 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -808,7 +808,7 @@ exports[`other directives with t-component t-on with getter as handler 1`] = ` c1.push(pvnode); } else { let componentKey3 = \`Child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; + let W3 = scope['Child'] || context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap['__4__'] = w3.__owl__.id; @@ -847,7 +847,7 @@ exports[`other directives with t-component t-on with handler bound to argument 1 c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -886,7 +886,7 @@ exports[`other directives with t-component t-on with handler bound to empty obje c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -925,7 +925,7 @@ exports[`other directives with t-component t-on with handler bound to empty obje c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -964,7 +964,7 @@ exports[`other directives with t-component t-on with handler bound to object 1`] c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -1007,7 +1007,7 @@ exports[`other directives with t-component t-on with inline statement 1`] = ` c1.push(pvnode); } else { let componentKey3 = \`Child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; + let W3 = scope['Child'] || context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap['__4__'] = w3.__owl__.id; @@ -1045,7 +1045,7 @@ exports[`other directives with t-component t-on with no handler (only modifiers) c1.push(pvnode); } else { let componentKey2 = \`ComponentA\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['ComponentA']; + let W2 = scope['ComponentA'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -1083,7 +1083,7 @@ exports[`other directives with t-component t-on with prevent and self modifiers c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -1121,7 +1121,7 @@ exports[`other directives with t-component t-on with self and prevent modifiers c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -1159,7 +1159,7 @@ exports[`other directives with t-component t-on with self modifier 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -1197,7 +1197,7 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -1337,7 +1337,7 @@ exports[`other directives with t-component t-set not altered by child widget 1`] c1.push(pvnode); } else { let componentKey3 = \`ChildWidget\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['ChildWidget']; + let W3 = scope['ChildWidget'] || context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap['__4__'] = w3.__owl__.id; @@ -1432,7 +1432,7 @@ exports[`props evaluation t-set with a body expression can be used as textual p c1.push(pvnode); } else { let componentKey3 = \`Child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; + let W3 = scope['Child'] || context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap['__4__'] = w3.__owl__.id; @@ -1491,7 +1491,7 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + let W2 = scope['child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap[k3] = w2.__owl__.id; @@ -1551,7 +1551,7 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument c1.push(pvnode); } else { let componentKey6 = \`Child\`; - let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| scope['Child']; + let W6 = scope['Child'] || context.constructor.components[componentKey6] || QWeb.components[componentKey6]; if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} w6 = new W6(parent, props6); parent.__owl__.cmap[k7] = w6.__owl__.id; @@ -1629,7 +1629,7 @@ exports[`t-call parent is set within t-call 1`] = ` c2.push(pvnode); } else { let componentKey3 = \`Child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; + let W3 = scope['Child'] || context.constructor.components[componentKey3] || QWeb.components[componentKey3]; if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} w3 = new W3(parent, props3); parent.__owl__.cmap[k4] = w3.__owl__.id; @@ -1667,7 +1667,7 @@ exports[`t-call parent is set within t-call with no parentNode 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap[k3] = w2.__owl__.id; @@ -2062,7 +2062,7 @@ exports[`top level sub widgets basic use 1`] = ` utils.defineProxy(vn3, pvnode); } else { let componentKey1 = \`Child\`; - let W1 = context.constructor.components[componentKey1] || QWeb.components[componentKey1]|| scope['Child']; + let W1 = scope['Child'] || context.constructor.components[componentKey1] || QWeb.components[componentKey1]; if (!W1) {throw new Error('Cannot find the definition of component \\"' + componentKey1 + '\\"')} w1 = new W1(parent, props1); parent.__owl__.cmap['__2__'] = w1.__owl__.id; @@ -2102,7 +2102,7 @@ exports[`top level sub widgets can select a sub widget 1`] = ` utils.defineProxy(vn3, pvnode); } else { let componentKey1 = \`Child\`; - let W1 = context.constructor.components[componentKey1] || QWeb.components[componentKey1]|| scope['Child']; + let W1 = scope['Child'] || context.constructor.components[componentKey1] || QWeb.components[componentKey1]; if (!W1) {throw new Error('Cannot find the definition of component \\"' + componentKey1 + '\\"')} w1 = new W1(parent, props1); parent.__owl__.cmap['__2__'] = w1.__owl__.id; @@ -2129,7 +2129,7 @@ exports[`top level sub widgets can select a sub widget 1`] = ` utils.defineProxy(vn6, pvnode); } else { let componentKey4 = \`OtherChild\`; - let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| scope['OtherChild']; + let W4 = scope['OtherChild'] || context.constructor.components[componentKey4] || QWeb.components[componentKey4]; if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap['__5__'] = w4.__owl__.id; diff --git a/tests/component/__snapshots__/props_validation.test.ts.snap b/tests/component/__snapshots__/props_validation.test.ts.snap index 27fb75d9..9e590f0e 100644 --- a/tests/component/__snapshots__/props_validation.test.ts.snap +++ b/tests/component/__snapshots__/props_validation.test.ts.snap @@ -24,7 +24,7 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] = c1.push(pvnode); } else { let componentKey2 = \`Child\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + let W2 = scope['Child'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; diff --git a/tests/component/__snapshots__/slots.test.ts.snap b/tests/component/__snapshots__/slots.test.ts.snap index 0ab51d8a..458ddf89 100644 --- a/tests/component/__snapshots__/slots.test.ts.snap +++ b/tests/component/__snapshots__/slots.test.ts.snap @@ -24,7 +24,7 @@ exports[`t-slot directive can define and call slots 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Dialog\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Dialog']; + let W2 = scope['Dialog'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -114,7 +114,7 @@ exports[`t-slot directive can define and call slots using old t-set keyword 1`] c1.push(pvnode); } else { let componentKey2 = \`Dialog\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Dialog']; + let W2 = scope['Dialog'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; @@ -397,7 +397,7 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = ` c7.push(pvnode); } else { let componentKey8 = \`Link\`; - let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8]|| scope['Link']; + let W8 = scope['Link'] || context.constructor.components[componentKey8] || QWeb.components[componentKey8]; if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')} w8 = new W8(parent, props8); parent.__owl__.cmap[k9] = w8.__owl__.id; @@ -495,7 +495,7 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` c7.push(pvnode); } else { let componentKey8 = \`Link\`; - let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8]|| scope['Link']; + let W8 = scope['Link'] || context.constructor.components[componentKey8] || QWeb.components[componentKey8]; if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')} w8 = new W8(parent, props8); parent.__owl__.cmap[k9] = w8.__owl__.id; @@ -551,7 +551,7 @@ exports[`t-slot directive slots are rendered with proper context, part 4 1`] = ` c1.push(pvnode); } else { let componentKey2 = \`Link\`; - let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Link']; + let W2 = scope['Link'] || context.constructor.components[componentKey2] || QWeb.components[componentKey2]; if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} w2 = new W2(parent, props2); parent.__owl__.cmap['__3__'] = w2.__owl__.id; diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index e493ee20..053b0e21 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -1242,6 +1242,23 @@ describe("composition", () => { delete QWeb.components["WidgetB"]; }); + test("don't fallback to global/component's registry if widget defined in the instance's context", async () => { + QWeb.registerComponent("WidgetB", WidgetB); // should not use this widget + env.qweb.addTemplate("ParentWidget", `
`); + env.qweb.addTemplate("ComponentWidgetB", `Belgium`); // should not use this widget either + env.qweb.addTemplate("InstanceWidgetB", `Chocolate`); // should use this + class ComponentWidgetB extends Component {} + class InstanceWidgetB extends Component {} + class ParentWidget extends Component { + static components = { WidgetB: ComponentWidgetB }; + WidgetB = InstanceWidgetB; + } + const widget = new ParentWidget(); + await widget.mount(fixture); + expect(fixture.innerHTML).toBe("
Chocolate
"); + delete QWeb.components["WidgetB"]; + }); + test("can define components in template without t-component", async () => { env.qweb.addTemplates(` diff --git a/tests/router/__snapshots__/route_component.test.ts.snap b/tests/router/__snapshots__/route_component.test.ts.snap index b4a33c9a..a166319b 100644 --- a/tests/router/__snapshots__/route_component.test.ts.snap +++ b/tests/router/__snapshots__/route_component.test.ts.snap @@ -29,7 +29,7 @@ exports[`RouteComponent can render simple cases 1`] = ` utils.defineProxy(vn6, pvnode); } else { let componentKey4 = \`routeComponent\`; - let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| scope['routeComponent']; + let W4 = scope['routeComponent'] || context.constructor.components[componentKey4] || QWeb.components[componentKey4]; if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} w4 = new W4(parent, props4); parent.__owl__.cmap[k5] = w4.__owl__.id;