diff --git a/src/compiler/code_generator.ts b/src/compiler/code_generator.ts index 6d41f67a..10e35666 100644 --- a/src/compiler/code_generator.ts +++ b/src/compiler/code_generator.ts @@ -1188,7 +1188,7 @@ export class CodeGenerator { } if (this.dev) { - this.addLine(`helpers.validateProps(${expr}, ${propVar!}, node);`); + this.addLine(`helpers.validateProps(${expr}, ${propVar!}, this);`); } if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) { diff --git a/src/runtime/app.ts b/src/runtime/app.ts index f548088f..736f221d 100644 --- a/src/runtime/app.ts +++ b/src/runtime/app.ts @@ -66,7 +66,7 @@ export class App< mount(target: HTMLElement, options?: MountOptions): Promise & InstanceType> { App.validateTarget(target); if (this.dev) { - validateProps(this.Root, this.props, { app: this }); + validateProps(this.Root, this.props, { __owl__: { app: this } }); } const node = this.makeNode(this.Root, this.props); const prom = this.mountNode(node, target, options); diff --git a/src/runtime/template_helpers.ts b/src/runtime/template_helpers.ts index cf7a9181..b87e6b1e 100644 --- a/src/runtime/template_helpers.ts +++ b/src/runtime/template_helpers.ts @@ -207,11 +207,11 @@ function multiRefSetter(refs: RefMap, name: string): RefSetter { * visit recursively the props and all the children to check if they are valid. * This is why it is only done in 'dev' mode. */ -export function validateProps

(name: string | ComponentConstructor

, props: P, node?: any) { +export function validateProps

(name: string | ComponentConstructor

, props: P, comp?: any) { const ComponentClass = typeof name !== "string" ? name - : (node.component.constructor.components[name] as ComponentConstructor

| undefined); + : (comp.constructor.components[name] as ComponentConstructor

| undefined); if (!ComponentClass) { // this is an error, wrong component. We silently return here instead so the @@ -221,7 +221,7 @@ export function validateProps

(name: string | ComponentConstructor

, props: const schema = ComponentClass.props; if (!schema) { - if (node.app.warnIfNoStaticProps) { + if (comp.__owl__.app.warnIfNoStaticProps) { console.warn(`Component '${ComponentClass.name}' does not have a static props description`); } return; diff --git a/tests/components/__snapshots__/error_handling.test.ts.snap b/tests/components/__snapshots__/error_handling.test.ts.snap index 9e48ca71..92fc7779 100644 --- a/tests/components/__snapshots__/error_handling.test.ts.snap +++ b/tests/components/__snapshots__/error_handling.test.ts.snap @@ -20,7 +20,7 @@ exports[`basics display a nice error if it cannot find component (in dev mode) 1 return function template(ctx, node, key = \\"\\") { const props1 = {}; - helpers.validateProps(\`SomeMispelledComponent\`, props1, node); + helpers.validateProps(\`SomeMispelledComponent\`, props1, this); return comp1(props1, key + \`__1\`, node, this, null); } }" diff --git a/tests/components/__snapshots__/lifecycle.test.ts.snap b/tests/components/__snapshots__/lifecycle.test.ts.snap index 8068056b..285e939d 100644 --- a/tests/components/__snapshots__/lifecycle.test.ts.snap +++ b/tests/components/__snapshots__/lifecycle.test.ts.snap @@ -704,7 +704,7 @@ exports[`lifecycle hooks timeout in onWillUpdateProps emits a warning 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {prop: ctx['state'].prop}; - helpers.validateProps(\`Child\`, props1, node); + helpers.validateProps(\`Child\`, props1, this); return comp1(props1, key + \`__1\`, node, this, null); } }" diff --git a/tests/components/__snapshots__/props_validation.test.ts.snap b/tests/components/__snapshots__/props_validation.test.ts.snap index 37654493..9ae2f135 100644 --- a/tests/components/__snapshots__/props_validation.test.ts.snap +++ b/tests/components/__snapshots__/props_validation.test.ts.snap @@ -8,7 +8,7 @@ exports[`default props a default prop cannot be defined on a mandatory prop 1`] return function template(ctx, node, key = \\"\\") { const props1 = {}; - helpers.validateProps(\`Child\`, props1, node); + helpers.validateProps(\`Child\`, props1, this); return comp1(props1, key + \`__1\`, node, this, null); } }" @@ -24,7 +24,7 @@ exports[`default props can set default boolean values 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -61,7 +61,7 @@ exports[`default props can set default values 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -92,7 +92,7 @@ exports[`default props default values are also set whenever component is updated return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['state'].p}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -121,7 +121,7 @@ exports[`props validation can specify that additional props are allowed (array) return function template(ctx, node, key = \\"\\") { const props1 = {message: 'm',otherProp: 'o'}; - helpers.validateProps(\`Child\`, props1, node); + helpers.validateProps(\`Child\`, props1, this); return comp1(props1, key + \`__1\`, node, this, null); } }" @@ -148,7 +148,7 @@ exports[`props validation can specify that additional props are allowed (object) return function template(ctx, node, key = \\"\\") { const props1 = {message: 'm',otherProp: 'o'}; - helpers.validateProps(\`Child\`, props1, node); + helpers.validateProps(\`Child\`, props1, this); return comp1(props1, key + \`__1\`, node, this, null); } }" @@ -177,7 +177,7 @@ exports[`props validation can validate a prop with multiple types 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -207,7 +207,7 @@ exports[`props validation can validate a prop with multiple types 3`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -237,7 +237,7 @@ exports[`props validation can validate a prop with multiple types 5`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -254,7 +254,7 @@ exports[`props validation can validate an array with given primitive type 1`] = return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -284,7 +284,7 @@ exports[`props validation can validate an array with given primitive type 3`] = return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -314,7 +314,7 @@ exports[`props validation can validate an array with given primitive type 5`] = return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -331,7 +331,7 @@ exports[`props validation can validate an array with given primitive type 6`] = return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -348,7 +348,7 @@ exports[`props validation can validate an array with multiple sub element types return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -378,7 +378,7 @@ exports[`props validation can validate an array with multiple sub element types return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -408,7 +408,7 @@ exports[`props validation can validate an array with multiple sub element types return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -438,7 +438,7 @@ exports[`props validation can validate an array with multiple sub element types return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -455,7 +455,7 @@ exports[`props validation can validate an object with simple shape 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -485,7 +485,7 @@ exports[`props validation can validate an object with simple shape 3`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -502,7 +502,7 @@ exports[`props validation can validate an object with simple shape 4`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -519,7 +519,7 @@ exports[`props validation can validate an object with simple shape 5`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -536,7 +536,7 @@ exports[`props validation can validate an optional props 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -566,7 +566,7 @@ exports[`props validation can validate an optional props 3`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -596,7 +596,7 @@ exports[`props validation can validate an optional props 5`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -613,7 +613,7 @@ exports[`props validation can validate recursively complicated prop def 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -643,7 +643,7 @@ exports[`props validation can validate recursively complicated prop def 3`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -673,13 +673,47 @@ exports[`props validation can validate recursively complicated prop def 5`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } }" `; +exports[`props validation can validate through slots 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { markRaw } = helpers; + const comp1 = app.createComponent(\`Child\`, true, false, false, true); + const comp2 = app.createComponent(\`Wrapper\`, true, true, false, true); + + function slot1(ctx, node, key = \\"\\") { + const props1 = {}; + helpers.validateProps(\`Child\`, props1, this); + return comp1(props1, key + \`__1\`, node, this, null); + } + + return function template(ctx, node, key = \\"\\") { + const props2 = {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}; + helpers.validateProps(\`Wrapper\`, props2, this); + return comp2(props2, key + \`__2\`, node, this, null); + } +}" +`; + +exports[`props validation can validate through slots 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { callSlot } = helpers; + + return function template(ctx, node, key = \\"\\") { + return callSlot(ctx, node, key, 'default', false, {}); + } +}" +`; + exports[`props validation default values are applied before validating props at update 1`] = ` "function anonymous(app, bdom, helpers ) { @@ -690,7 +724,7 @@ exports[`props validation default values are applied before validating props at return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['state'].p}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -721,7 +755,7 @@ exports[`props validation missing required boolean prop causes an error 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -738,7 +772,7 @@ exports[`props validation mix of optional and mandatory 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {}; - helpers.validateProps(\`Child\`, props1, node); + helpers.validateProps(\`Child\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -755,7 +789,7 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] = return function template(ctx, node, key = \\"\\") { const props1 = {message: 1}; - helpers.validateProps(\`Child\`, props1, node); + helpers.validateProps(\`Child\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -786,7 +820,7 @@ exports[`props validation props are validated whenever component is updated 1`] return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['state'].p}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -817,7 +851,7 @@ exports[`props validation props: list of strings 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -834,7 +868,7 @@ exports[`props validation validate simple types 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -851,7 +885,7 @@ exports[`props validation validate simple types 2`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -881,7 +915,7 @@ exports[`props validation validate simple types 4`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -898,7 +932,7 @@ exports[`props validation validate simple types 5`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -915,7 +949,7 @@ exports[`props validation validate simple types 6`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -945,7 +979,7 @@ exports[`props validation validate simple types 8`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -962,7 +996,7 @@ exports[`props validation validate simple types 9`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -979,7 +1013,7 @@ exports[`props validation validate simple types 10`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1009,7 +1043,7 @@ exports[`props validation validate simple types 12`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1026,7 +1060,7 @@ exports[`props validation validate simple types 13`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1043,7 +1077,7 @@ exports[`props validation validate simple types 14`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1073,7 +1107,7 @@ exports[`props validation validate simple types 16`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1090,7 +1124,7 @@ exports[`props validation validate simple types 17`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1107,7 +1141,7 @@ exports[`props validation validate simple types 18`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1137,7 +1171,7 @@ exports[`props validation validate simple types 20`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1154,7 +1188,7 @@ exports[`props validation validate simple types 21`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1171,7 +1205,7 @@ exports[`props validation validate simple types 22`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1201,7 +1235,7 @@ exports[`props validation validate simple types 24`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1218,7 +1252,7 @@ exports[`props validation validate simple types, alternate form 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1235,7 +1269,7 @@ exports[`props validation validate simple types, alternate form 2`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1265,7 +1299,7 @@ exports[`props validation validate simple types, alternate form 4`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1282,7 +1316,7 @@ exports[`props validation validate simple types, alternate form 5`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1299,7 +1333,7 @@ exports[`props validation validate simple types, alternate form 6`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1329,7 +1363,7 @@ exports[`props validation validate simple types, alternate form 8`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1346,7 +1380,7 @@ exports[`props validation validate simple types, alternate form 9`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1363,7 +1397,7 @@ exports[`props validation validate simple types, alternate form 10`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1393,7 +1427,7 @@ exports[`props validation validate simple types, alternate form 12`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1410,7 +1444,7 @@ exports[`props validation validate simple types, alternate form 13`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1427,7 +1461,7 @@ exports[`props validation validate simple types, alternate form 14`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1457,7 +1491,7 @@ exports[`props validation validate simple types, alternate form 16`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1474,7 +1508,7 @@ exports[`props validation validate simple types, alternate form 17`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1491,7 +1525,7 @@ exports[`props validation validate simple types, alternate form 18`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1521,7 +1555,7 @@ exports[`props validation validate simple types, alternate form 20`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1538,7 +1572,7 @@ exports[`props validation validate simple types, alternate form 21`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1555,7 +1589,7 @@ exports[`props validation validate simple types, alternate form 22`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1585,7 +1619,7 @@ exports[`props validation validate simple types, alternate form 24`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {p: ctx['p']}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } @@ -1602,7 +1636,7 @@ exports[`props validation validation is only done in dev mode 1`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {}; - helpers.validateProps(\`SubComp\`, props1, node); + helpers.validateProps(\`SubComp\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); return block1([], [b2]); } diff --git a/tests/components/__snapshots__/t_call.test.ts.snap b/tests/components/__snapshots__/t_call.test.ts.snap index 7dc6078f..9debc214 100644 --- a/tests/components/__snapshots__/t_call.test.ts.snap +++ b/tests/components/__snapshots__/t_call.test.ts.snap @@ -466,10 +466,10 @@ exports[`t-call t-call with t-call-context and subcomponent, in dev mode 2`] = ` return function template(ctx, node, key = \\"\\") { const props1 = {name: ctx['aab']}; - helpers.validateProps(\`Child\`, props1, node); + helpers.validateProps(\`Child\`, props1, this); const b2 = comp1(props1, key + \`__1\`, node, this, null); const props2 = {name: ctx['lpe']}; - helpers.validateProps(\`Child\`, props2, node); + helpers.validateProps(\`Child\`, props2, this); const b3 = comp2(props2, key + \`__2\`, node, this, null); return multi([b2, b3]); } diff --git a/tests/components/__snapshots__/t_foreach.test.ts.snap b/tests/components/__snapshots__/t_foreach.test.ts.snap index 9e8ef827..34c3f1df 100644 --- a/tests/components/__snapshots__/t_foreach.test.ts.snap +++ b/tests/components/__snapshots__/t_foreach.test.ts.snap @@ -56,7 +56,7 @@ exports[`list of components crash on duplicate key in dev mode 1`] = ` if (keys1.has(key1)) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)} keys1.add(key1); const props1 = {}; - helpers.validateProps(\`Child\`, props1, node); + helpers.validateProps(\`Child\`, props1, this); c_block1[i1] = withKey(comp1(props1, key + \`__1__\${key1}\`, node, this, null), key1); } return list(c_block1); diff --git a/tests/components/props_validation.test.ts b/tests/components/props_validation.test.ts index 12f6a894..55327611 100644 --- a/tests/components/props_validation.test.ts +++ b/tests/components/props_validation.test.ts @@ -780,6 +780,32 @@ describe("props validation", () => { // we just check that it doesn't throw await expect(mount(Parent, fixture, { dev: true })).resolves.toEqual(expect.anything()); }); + + test("can validate through slots", async () => { + class Child extends Component { + static props = ["message"]; + static template = xml`

hey
`; + } + + class Wrapper extends Component { + static template = xml``; + } + + class Parent extends Component { + static components = { Child, Wrapper }; + static template = xml``; + } + + const app = new App(Parent, { test: true }); + let error: OwlError | undefined; + const mountProm = app.mount(fixture).catch((e: Error) => (error = e)); + await expect(nextAppError(app)).resolves.toThrow( + "Invalid props for component 'Child': 'message' is missing" + ); + await mountProm; + expect(error!).toBeDefined(); + expect(error!.message).toBe("Invalid props for component 'Child': 'message' is missing"); + }); }); //------------------------------------------------------------------------------