Compare commits

...

5 Commits

Author SHA1 Message Date
Géry Debongnie 1253b3922b [IMP] hooks: add useRoots hook
closes #1260
2022-09-24 16:35:33 +02:00
Géry Debongnie d5ed25cd19 [FIX] props validation: does not crash with t-call-context
The code for props validation assumed that the rendering context was a
component.  This was actually true when it was written, but is no longer
true since t-call-context was introduced.

Because of that, it would crash when trying to access the internals of
the component, such as the static components object.

The fix is simple: instead of passing the context to the props
validation code, which can now be anything, we pass the component node,
which is guaranteed to give a reference to the component (and also to
the app).  This also make the code slightly simpler.

closes #1261
2022-09-24 08:34:22 +02:00
Géry Debongnie c4f0f17b9b [FIX] blockdom: prevent side effects at block compilation
When creating the template node for a block, we create htmlelements and
set their (static) attributes.  But this can have side effects. For
example, setting the src attribute for an img element will trigger a
request to fetch the image.

We avoid that issue by simply setting the html element template node
inside a <template/> element.

Note that I don't really see how to test this fix in jest: we don't have
a real browser, and no real way to check for this side effect.

closes #1257
2022-09-21 13:59:13 +02:00
Florent Dardenne - dafl@odoo d27455e9f2 [IMP] doc: explicit useEffect first parameter
The `useEffect` has two parameters:
* The `effect` function
* The `computeDependencies` function

The `effect` function always take as parameters the result
 of the `computeDependencies` function.

Expliciting this allows to better understand the `useEffect`
behaviour and the following example in the doc:

```
useEffect(
    (el) => el && el.focus(),
    () => [ref.el]
  );
```
2022-09-09 20:24:56 +02:00
Géry Debongnie 6ef38676c4 [DOC] doc: fix broken link and update roadmap 2022-09-09 09:45:05 +02:00
28 changed files with 482 additions and 115 deletions
+6 -1
View File
@@ -261,7 +261,12 @@ This comes from the fact that Owl 2 supports fragments (arbitrary content).
Migration: if one need a reference to the root htmlelement of a template, it is Migration: if one need a reference to the root htmlelement of a template, it is
suggested to simply add a `ref` on it, and access the reference as needed. suggested to simply add a `ref` on it, and access the reference as needed.
Documentation: [Refs](doc/reference/refs.md) Another way to get access to a root node or html element is the hook `useRoots`
Documentation:
- [Refs](doc/reference/refs.md)
- [useRoots](doc/reference/hooks.md#useroots)
### 10. style/class on components are now regular props ### 10. style/class on components are now regular props
+1 -1
View File
@@ -124,5 +124,5 @@ npm install @odoo/owl
If you want to use a simple `<script>` tag, the last release can be downloaded here: If you want to use a simple `<script>` tag, the last release can be downloaded here:
- [owl-1.4.10](https://github.com/odoo/owl/releases/tag/v1.4.10) - [owl](https://github.com/odoo/owl/releases/latest)
+1
View File
@@ -38,6 +38,7 @@ Other hooks:
- [`useRef`](reference/hooks.md#useref): get an object representing a reference (`t-ref`) - [`useRef`](reference/hooks.md#useref): get an object representing a reference (`t-ref`)
- [`useChildSubEnv`](reference/hooks.md#usesubenv-and-usechildsubenv): extend the current env with additional information (for child components) - [`useChildSubEnv`](reference/hooks.md#usesubenv-and-usechildsubenv): extend the current env with additional information (for child components)
- [`useSubEnv`](reference/hooks.md#usesubenv-and-usechildsubenv): extend the current env with additional information (for current component and child components) - [`useSubEnv`](reference/hooks.md#usesubenv-and-usechildsubenv): extend the current env with additional information (for current component and child components)
- [`useRoots`](reference/hooks.md#useroots): returns an object that provides access to all root nodes or htmlelements
Utility/helpers: Utility/helpers:
+39 -1
View File
@@ -13,6 +13,7 @@
- [`useComponent`](#usecomponent) - [`useComponent`](#usecomponent)
- [`useEnv`](#useenv) - [`useEnv`](#useenv)
- [`useEffect`](#useeffect) - [`useEffect`](#useeffect)
- [`useRoots`](#useroots)
- [Example: Mouse Position](#example-mouse-position) - [Example: Mouse Position](#example-mouse-position)
## Overview ## Overview
@@ -234,7 +235,8 @@ are defined by a function instead of just the dependencies.
The `useEffect` hook takes two function: the effect function and the dependency The `useEffect` hook takes two function: the effect function and the dependency
function. The effect function perform some task and return (optionally) a cleanup function. The effect function perform some task and return (optionally) a cleanup
function. The dependency function returns a list of dependencies. If any of these function. The dependency function returns a list of dependencies, these dependencies
are passed as parameters in the effect function . If any of these
dependencies changes, then the current effect will be cleaned up and reexecuted. dependencies changes, then the current effect will be cleaned up and reexecuted.
Here is an example without any dependencies: Here is an example without any dependencies:
@@ -287,6 +289,42 @@ class SomeComponent extends Component {
} }
``` ```
### `useRoots`
`useRoots` is an alternative way to get a reference to the root notes or elements
of a component. It may be useful in some cases where `useRef` cannot be applied,
such as a higher order component, or a component with only text as content.
The return value of `useRoots` is an object with the following key/values:
- `node`: getter that evaluates to the first node of the component content (or null)
- `elem`: getter that evaluates to the first HTMLElement of the component content (or null)
- `nodes`: iterator that returns all content nodes
- `elems`: iterator that returns all HTMLElement nodes
```js
class Child extends Component {
static template = xml`<p>some content</p>`;
}
class Parent extends Component {
static template = xml`<Child/>`;
static components = { Child };
setup() {
this.roots = useRoots();
console.log(this.roots.elem); // null
onMounted(() => {
console.log(this.roots.elem); // log the `p` element from the child
for (let elem of this.roots.elems) {
console.log(elem); // log the `p` element from the child
}
});
}
}
```
## Example: mouse position ## Example: mouse position
Here is the classical example of a non trivial hook to track the mouse position. Here is the classical example of a non trivial hook to track the mouse position.
+4 -23
View File
@@ -1,28 +1,9 @@
# 🦉 OWL Roadmap 🦉 # 🦉 OWL Roadmap 🦉
- Current version: 1.4.10 - Current version: 2.X
- Status: stable - Status: stable
This roadmap is only an attempt at predicting Owl's future. Everything may Owl is currently stable. No (large) improvements is expected in the near future.
change!
### 1.x
- add chrome and firefox devtools,
- fix every bugs,
- improve documentation,
- small backward compatible improvements.
### 2.x (2020? 2021? 2022?)
- stop support for `t-set` directive to define the content of a slot
Maybe:
- reimplement vdom to use *block* system, like Vue 3, which should make Owl
much faster
- refactor `QWeb` to use an intermediate representation (some kind of AST) to
allow additional optimisations.
Note that we intend to keep maintaining owl, and as such, improvements and/or
breaking changes may require a version bump in the future.
+1 -1
View File
@@ -1188,7 +1188,7 @@ export class CodeGenerator {
} }
if (this.dev) { if (this.dev) {
this.addLine(`helpers.validateProps(${expr}, ${propVar!}, ctx);`); this.addLine(`helpers.validateProps(${expr}, ${propVar!}, node);`);
} }
if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) { if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
+1 -1
View File
@@ -66,7 +66,7 @@ export class App<
mount(target: HTMLElement, options?: MountOptions): Promise<Component<P, E> & InstanceType<T>> { mount(target: HTMLElement, options?: MountOptions): Promise<Component<P, E> & InstanceType<T>> {
App.validateTarget(target); App.validateTarget(target);
if (this.dev) { if (this.dev) {
validateProps(this.Root, this.props, { __owl__: { app: this } }); validateProps(this.Root, this.props, { app: this });
} }
const node = this.makeNode(this.Root, this.props); const node = this.makeNode(this.Root, this.props);
const prom = this.mountNode(node, target, options); const prom = this.mountNode(node, target, options);
+15
View File
@@ -157,6 +157,15 @@ function buildTree(
: document.createElement(tagName); : document.createElement(tagName);
} }
if (el instanceof Element) { if (el instanceof Element) {
if (!domParentTree) {
// some html elements may have side effects when setting their attributes.
// For example, setting the src attribute of an <img/> will trigger a
// request to get the corresponding image. This is something that we
// don't want at compile time. We avoid that by putting the content of
// the block in a <template/> element
const fragment = document.createElement("template").content;
fragment.appendChild(el);
}
for (let i = 0; i < attrs.length; i++) { for (let i = 0; i < attrs.length; i++) {
const attrName = attrs[i].name; const attrName = attrs[i].name;
const attrValue = attrs[i].value; const attrValue = attrs[i].value;
@@ -508,6 +517,12 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
return this.el!; return this.el!;
} }
*nodes() {
if (this.el) {
yield this.el;
}
}
moveBefore(other: Block | null, afterNode: Node | null) { moveBefore(other: Block | null, afterNode: Node | null) {
const target = other ? other.el! : afterNode; const target = other ? other.el! : afterNode;
nodeInsertBefore.call(this.parentEl, this.el!, target); nodeInsertBefore.call(this.parentEl, this.el!, target);
+6 -6
View File
@@ -12,7 +12,6 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher {
child: VNode; child: VNode;
handlerData: any[]; handlerData: any[];
handlerFns: any[] = []; handlerFns: any[] = [];
parentEl?: HTMLElement | undefined; parentEl?: HTMLElement | undefined;
afterNode: Text | null = null; afterNode: Text | null = null;
@@ -44,13 +43,10 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher {
const self = this; const self = this;
handler[idx] = function (ev: any) { handler[idx] = function (ev: any) {
const target = ev.target; const target = ev.target;
let currentNode: any = self.child.firstNode(); for (let node of self.nodes()) {
const afterNode = self.afterNode; if (node.contains(target)) {
while (currentNode !== afterNode) {
if (currentNode.contains(target)) {
return origFn.call(this, ev); return origFn.call(this, ev);
} }
currentNode = currentNode.nextSibling;
} }
}; };
} }
@@ -90,6 +86,10 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher {
return this.child.firstNode(); return this.child.firstNode();
} }
nodes(): Generator<Node> {
return this.child.nodes();
}
toString(): string { toString(): string {
return this.child.toString(); return this.child.toString();
} }
+6
View File
@@ -78,6 +78,12 @@ class VHtml {
return this.content[0]!; return this.content[0]!;
} }
*nodes() {
for (let elem of this.content) {
yield elem;
}
}
toString() { toString() {
return this.html; return this.html;
} }
+2
View File
@@ -16,6 +16,8 @@ export interface VNode<T = any> {
remove(): void; remove(): void;
firstNode(): Node | undefined; firstNode(): Node | undefined;
nodes(): Generator<Node>;
el?: undefined | HTMLElement | Text; el?: undefined | HTMLElement | Text;
parentEl?: undefined | HTMLElement; parentEl?: undefined | HTMLElement;
isOnlyChild?: boolean | undefined; isOnlyChild?: boolean | undefined;
+6
View File
@@ -221,6 +221,12 @@ class VList {
return child ? child.firstNode() : undefined; return child ? child.firstNode() : undefined;
} }
*nodes() {
for (let child of this.children) {
yield* child.nodes();
}
}
toString(): string { toString(): string {
return this.children.map((c) => c!.toString()).join(""); return this.children.map((c) => c!.toString()).join("");
} }
+8
View File
@@ -124,6 +124,14 @@ export class VMulti {
return child ? child.firstNode() : this.anchors![0]; return child ? child.firstNode() : this.anchors![0];
} }
*nodes() {
for (let child of this.children) {
if (child) {
yield* child.nodes();
}
}
}
toString(): string { toString(): string {
return this.children.map((c) => (c ? c!.toString() : "")).join(""); return this.children.map((c) => (c ? c!.toString() : "")).join("");
} }
+6
View File
@@ -38,6 +38,12 @@ abstract class VSimpleNode {
return this.el!; return this.el!;
} }
*nodes(): Generator<Node> {
if (this.el) {
yield this.el;
}
}
toString() { toString() {
return this.text; return this.text;
} }
+4
View File
@@ -55,6 +55,10 @@ class VToggler {
return this.child.firstNode(); return this.child.firstNode();
} }
nodes() {
return this.child.nodes();
}
toString(): string { toString(): string {
return this.child.toString(); return this.child.toString();
} }
+6
View File
@@ -296,6 +296,12 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
return bdom ? bdom.firstNode() : undefined; return bdom ? bdom.firstNode() : undefined;
} }
*nodes(): Generator<Node> {
if (this.bdom) {
yield* this.bdom.nodes();
}
}
mount(parent: HTMLElement, anchor: ChildNode) { mount(parent: HTMLElement, anchor: ChildNode) {
const bdom = this.fiber!.bdom!; const bdom = this.fiber!.bdom!;
this.bdom = bdom; this.bdom = bdom;
+36
View File
@@ -127,3 +127,39 @@ export function useExternalListener(
onMounted(() => target.addEventListener(eventName, boundHandler, eventParams)); onMounted(() => target.addEventListener(eventName, boundHandler, eventParams));
onWillUnmount(() => target.removeEventListener(eventName, boundHandler, eventParams)); onWillUnmount(() => target.removeEventListener(eventName, boundHandler, eventParams));
} }
// -----------------------------------------------------------------------------
// useRoots
// -----------------------------------------------------------------------------
interface DomRangeObj {
node: Node | null;
elem: HTMLElement | null;
elems: Iterable<HTMLElement>;
nodes: Iterable<Node>;
}
export function useRoots(): DomRangeObj {
const cnode = getCurrent();
function* _elems(): Generator<HTMLElement> {
for (let node of cnode.nodes()) {
if (node.nodeType === 1) {
yield node as HTMLElement;
}
}
}
return {
get node() {
return cnode.nodes().next().value || null;
},
get elem() {
return _elems().next().value || null;
},
get nodes() {
return cnode.nodes();
},
get elems() {
return _elems();
},
};
}
+9 -1
View File
@@ -40,7 +40,15 @@ export type { ComponentConstructor } from "./component";
export { useComponent, useState } from "./component_node"; export { useComponent, useState } from "./component_node";
export { status } from "./status"; export { status } from "./status";
export { reactive, markRaw, toRaw } from "./reactivity"; export { reactive, markRaw, toRaw } from "./reactivity";
export { useEffect, useEnv, useExternalListener, useRef, useChildSubEnv, useSubEnv } from "./hooks"; export {
useEffect,
useEnv,
useExternalListener,
useRef,
useChildSubEnv,
useSubEnv,
useRoots,
} from "./hooks";
export { EventBus, whenReady, loadFile, markup } from "./utils"; export { EventBus, whenReady, loadFile, markup } from "./utils";
export { export {
onWillStart, onWillStart,
+3 -3
View File
@@ -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. * visit recursively the props and all the children to check if they are valid.
* This is why it is only done in 'dev' mode. * This is why it is only done in 'dev' mode.
*/ */
export function validateProps<P>(name: string | ComponentConstructor<P>, props: P, parent?: any) { export function validateProps<P>(name: string | ComponentConstructor<P>, props: P, node?: any) {
const ComponentClass = const ComponentClass =
typeof name !== "string" typeof name !== "string"
? name ? name
: (parent.constructor.components[name] as ComponentConstructor<P> | undefined); : (node.component.constructor.components[name] as ComponentConstructor<P> | undefined);
if (!ComponentClass) { if (!ComponentClass) {
// this is an error, wrong component. We silently return here instead so the // this is an error, wrong component. We silently return here instead so the
@@ -221,7 +221,7 @@ export function validateProps<P>(name: string | ComponentConstructor<P>, props:
const schema = ComponentClass.props; const schema = ComponentClass.props;
if (!schema) { if (!schema) {
if (parent.__owl__.app.warnIfNoStaticProps) { if (node.app.warnIfNoStaticProps) {
console.warn(`Component '${ComponentClass.name}' does not have a static props description`); console.warn(`Component '${ComponentClass.name}' does not have a static props description`);
} }
return; return;
@@ -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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SomeMispelledComponent\`, props1, ctx); helpers.validateProps(\`SomeMispelledComponent\`, props1, node);
return comp1(props1, key + \`__1\`, node, this, null); return comp1(props1, key + \`__1\`, node, this, null);
} }
}" }"
@@ -405,3 +405,69 @@ exports[`hooks useSubEnv supports arbitrary descriptor 2`] = `
} }
}" }"
`; `;
exports[`useRoots hook return a list of nodes and elems 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<span>hey</span>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`useRoots hook return a list of nodes and elems 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block3 = createBlock(\`<span>hey</span>\`);
let block5 = createBlock(\`<p>bla</p>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = text(\` some text \`);
const b3 = block3();
const b4 = text(\` coucou \`);
const b5 = block5();
return multi([b2, b3, b4, b5]);
}
}"
`;
exports[`useRoots hook useRoots and lifecycle 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<span>hey</span>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`useRoots hook useRoots is up to date 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block2 = createBlock(\`<span>hey</span>\`);
let block5 = createBlock(\`<p>paragraph</p>\`);
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (ctx['state'].flag) {
b2 = block2();
} else {
const b4 = text(\` coucou \`);
const b5 = block5();
b3 = multi([b4, b5]);
}
return multi([b2, b3]);
}
}"
`;
@@ -704,7 +704,7 @@ exports[`lifecycle hooks timeout in onWillUpdateProps emits a warning 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {prop: ctx['state'].prop}; const props1 = {prop: ctx['state'].prop};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, node);
return comp1(props1, key + \`__1\`, node, this, null); return comp1(props1, key + \`__1\`, node, this, null);
} }
}" }"
@@ -8,7 +8,7 @@ exports[`default props a default prop cannot be defined on a mandatory prop 1`]
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, node);
return comp1(props1, key + \`__1\`, node, this, null); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -61,7 +61,7 @@ exports[`default props can set default values 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['state'].p}; const props1 = {p: ctx['state'].p};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -121,7 +121,7 @@ exports[`props validation can specify that additional props are allowed (array)
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {message: 'm',otherProp: 'o'}; const props1 = {message: 'm',otherProp: 'o'};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, node);
return comp1(props1, key + \`__1\`, node, this, null); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {message: 'm',otherProp: 'o'}; const props1 = {message: 'm',otherProp: 'o'};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, node);
return comp1(props1, key + \`__1\`, node, this, null); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -207,7 +207,7 @@ exports[`props validation can validate a prop with multiple types 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -237,7 +237,7 @@ exports[`props validation can validate a prop with multiple types 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); 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 = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -455,7 +455,7 @@ exports[`props validation can validate an object with simple shape 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -485,7 +485,7 @@ exports[`props validation can validate an object with simple shape 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -502,7 +502,7 @@ exports[`props validation can validate an object with simple shape 4`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -519,7 +519,7 @@ exports[`props validation can validate an object with simple shape 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -536,7 +536,7 @@ exports[`props validation can validate an optional props 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -566,7 +566,7 @@ exports[`props validation can validate an optional props 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -596,7 +596,7 @@ exports[`props validation can validate an optional props 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -613,7 +613,7 @@ exports[`props validation can validate recursively complicated prop def 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -643,7 +643,7 @@ exports[`props validation can validate recursively complicated prop def 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -673,7 +673,7 @@ exports[`props validation can validate recursively complicated prop def 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -690,7 +690,7 @@ exports[`props validation default values are applied before validating props at
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['state'].p}; const props1 = {p: ctx['state'].p};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -721,7 +721,7 @@ exports[`props validation missing required boolean prop causes an error 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -738,7 +738,7 @@ exports[`props validation mix of optional and mandatory 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -755,7 +755,7 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] =
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {message: 1}; const props1 = {message: 1};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -786,7 +786,7 @@ exports[`props validation props are validated whenever component is updated 1`]
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['state'].p}; const props1 = {p: ctx['state'].p};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -817,7 +817,7 @@ exports[`props validation props: list of strings 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -834,7 +834,7 @@ exports[`props validation validate simple types 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -851,7 +851,7 @@ exports[`props validation validate simple types 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -881,7 +881,7 @@ exports[`props validation validate simple types 4`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -898,7 +898,7 @@ exports[`props validation validate simple types 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -915,7 +915,7 @@ exports[`props validation validate simple types 6`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -945,7 +945,7 @@ exports[`props validation validate simple types 8`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -962,7 +962,7 @@ exports[`props validation validate simple types 9`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -979,7 +979,7 @@ exports[`props validation validate simple types 10`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1009,7 +1009,7 @@ exports[`props validation validate simple types 12`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1026,7 +1026,7 @@ exports[`props validation validate simple types 13`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1043,7 +1043,7 @@ exports[`props validation validate simple types 14`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1073,7 +1073,7 @@ exports[`props validation validate simple types 16`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1090,7 +1090,7 @@ exports[`props validation validate simple types 17`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1107,7 +1107,7 @@ exports[`props validation validate simple types 18`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1137,7 +1137,7 @@ exports[`props validation validate simple types 20`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1154,7 +1154,7 @@ exports[`props validation validate simple types 21`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1171,7 +1171,7 @@ exports[`props validation validate simple types 22`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1201,7 +1201,7 @@ exports[`props validation validate simple types 24`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1218,7 +1218,7 @@ exports[`props validation validate simple types, alternate form 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1235,7 +1235,7 @@ exports[`props validation validate simple types, alternate form 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1265,7 +1265,7 @@ exports[`props validation validate simple types, alternate form 4`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1282,7 +1282,7 @@ exports[`props validation validate simple types, alternate form 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1299,7 +1299,7 @@ exports[`props validation validate simple types, alternate form 6`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1329,7 +1329,7 @@ exports[`props validation validate simple types, alternate form 8`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1346,7 +1346,7 @@ exports[`props validation validate simple types, alternate form 9`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1363,7 +1363,7 @@ exports[`props validation validate simple types, alternate form 10`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1393,7 +1393,7 @@ exports[`props validation validate simple types, alternate form 12`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1410,7 +1410,7 @@ exports[`props validation validate simple types, alternate form 13`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1427,7 +1427,7 @@ exports[`props validation validate simple types, alternate form 14`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1457,7 +1457,7 @@ exports[`props validation validate simple types, alternate form 16`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1474,7 +1474,7 @@ exports[`props validation validate simple types, alternate form 17`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1491,7 +1491,7 @@ exports[`props validation validate simple types, alternate form 18`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1521,7 +1521,7 @@ exports[`props validation validate simple types, alternate form 20`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1538,7 +1538,7 @@ exports[`props validation validate simple types, alternate form 21`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1555,7 +1555,7 @@ exports[`props validation validate simple types, alternate form 22`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1585,7 +1585,7 @@ exports[`props validation validate simple types, alternate form 24`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1602,7 +1602,7 @@ exports[`props validation validation is only done in dev mode 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
@@ -444,6 +444,51 @@ exports[`t-call t-call with t-call-context and subcomponent 3`] = `
}" }"
`; `;
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const callTemplate_1 = app.getTemplate(\`someTemplate\`);
return function template(ctx, node, key = \\"\\") {
let ctx1 = ctx['subctx'];
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Child\`, true, false, false, false);
const comp2 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") {
const props1 = {name: ctx['aab']};
helpers.validateProps(\`Child\`, props1, node);
const b2 = comp1(props1, key + \`__1\`, node, this, null);
const props2 = {name: ctx['lpe']};
helpers.validateProps(\`Child\`, props2, node);
const b3 = comp2(props2, key + \`__2\`, node, this, null);
return multi([b2, b3]);
}
}"
`;
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`child\`);
const b3 = text(ctx['props'].name);
return multi([b2, b3]);
}
}"
`;
exports[`t-call t-call with t-call-context, simple use 1`] = ` exports[`t-call t-call with t-call-context, simple use 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -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}\`)} if (keys1.has(key1)) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
keys1.add(key1); keys1.add(key1);
const props1 = {}; const props1 = {};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, node);
c_block1[i1] = withKey(comp1(props1, key + \`__1__\${key1}\`, node, this, null), key1); c_block1[i1] = withKey(comp1(props1, key + \`__1__\${key1}\`, node, this, null), key1);
} }
return list(c_block1); return list(c_block1);
+109 -1
View File
@@ -19,6 +19,7 @@ import {
xml, xml,
OwlError, OwlError,
} from "../../src/index"; } from "../../src/index";
import { useRoots } from "../../src/runtime/hooks";
import { import {
elem, elem,
logStep, logStep,
@@ -518,7 +519,7 @@ describe("hooks", () => {
}); });
test("dependencies prevent effects from rerunning when unchanged", async () => { test("dependencies prevent effects from rerunning when unchanged", async () => {
let steps = []; let steps: string[] = [];
class MyComponent extends Component { class MyComponent extends Component {
state = useState({ state = useState({
a: 0, a: 0,
@@ -673,3 +674,110 @@ describe("hooks", () => {
}); });
}); });
}); });
describe("useRoots hook", () => {
test("return a list of nodes and elems", async () => {
class MyComponent extends Component {
static template = xml`<span>hey</span>`;
roots: any;
setup() {
this.roots = useRoots();
}
}
const comp = await mount(MyComponent, fixture);
expect(comp.roots.node).toBeInstanceOf(HTMLSpanElement);
expect(comp.roots.elem).toBeInstanceOf(HTMLSpanElement);
expect([...comp.roots.nodes].map((n: any) => n.tagName)).toEqual(["SPAN"]);
expect([...comp.roots.elems].map((n: any) => n.tagName)).toEqual(["SPAN"]);
});
test("return a list of nodes and elems", async () => {
class MyComponent extends Component {
static template = xml`
some text
<span>hey</span>
coucou
<p>bla</p>`;
roots: any;
setup() {
this.roots = useRoots();
}
}
const comp = await mount(MyComponent, fixture);
expect(comp.roots.node).toBeInstanceOf(Text);
expect(comp.roots.elem).toBeInstanceOf(HTMLSpanElement);
expect([...comp.roots.elems].map((n: any) => n.tagName)).toEqual(["SPAN", "P"]);
expect([...comp.roots.nodes].map((n: any) => n.nodeType)).toEqual([3, 1, 3, 1]);
});
test("useRoots and lifecycle", async () => {
expect.assertions(13);
class MyComponent extends Component {
static template = xml`<span>hey</span>`;
roots: any;
setup() {
this.roots = useRoots();
expect(this.roots.elem).toBe(null);
expect(this.roots.node).toBe(null);
expect([...this.roots.nodes]).toEqual([]);
expect([...this.roots.elems]).toEqual([]);
onWillStart(() => {
expect(this.roots.elem).toBe(null);
expect(this.roots.node).toBe(null);
expect([...this.roots.nodes]).toEqual([]);
expect([...this.roots.elems]).toEqual([]);
});
onMounted(() => {
expect(this.roots.elem).toBeInstanceOf(HTMLSpanElement);
expect(this.roots.node).toBeInstanceOf(HTMLSpanElement);
expect([...this.roots.elems].map((n: any) => n.tagName)).toEqual(["SPAN"]);
expect([...this.roots.nodes].map((n: any) => n.nodeType)).toEqual([1]);
});
}
}
const comp = await mount(MyComponent, fixture);
comp.__owl__.app.destroy();
});
test("useRoots is up to date", async () => {
class MyComponent extends Component {
static template = xml`
<t t-if="state.flag">
<span>hey</span>
</t>
<t t-else="">
coucou
<p>paragraph</p>
</t>`;
roots: any;
state: any;
setup() {
this.roots = useRoots();
this.state = useState({ flag: true });
onMounted(() => {
expect(this.roots.elem).toBeInstanceOf(HTMLSpanElement);
expect(this.roots.node).toBeInstanceOf(HTMLSpanElement);
expect([...this.roots.elems].map((n: any) => n.tagName)).toEqual(["SPAN"]);
expect([...this.roots.nodes].map((n: any) => n.nodeType)).toEqual([1]);
});
}
}
const comp = await mount(MyComponent, fixture);
comp.state.flag = false;
await nextTick();
expect(comp.roots.node.nodeType).toBe(3); // text node
expect(comp.roots.node.textContent).toBe(" coucou "); // text node
expect(comp.roots.elem).toBeInstanceOf(HTMLParagraphElement);
});
});
+28
View File
@@ -287,4 +287,32 @@ describe("t-call", () => {
}); });
expect(fixture.innerHTML).toBe("childaaronchildlucas"); expect(fixture.innerHTML).toBe("childaaronchildlucas");
}); });
test("t-call with t-call-context and subcomponent, in dev mode", async () => {
class Child extends Component {
static template = xml`child<t t-esc="props.name"/>`;
static props = ["name"];
}
class Root extends Component {
static template = xml`
<t t-call="someTemplate" t-call-context="subctx"/>`;
static components = { Child };
subctx = { aab: "aaron", lpe: "lucas" };
}
await mount(Root, fixture, {
dev: true,
templates: `
<templates>
<t t-name="someTemplate">
<Child name="aab"/>
<Child name="lpe"/>
</t>
</templates>`,
});
expect(fixture.innerHTML).toBe("childaaronchildlucas");
});
}); });
+1 -3
View File
@@ -72,10 +72,8 @@ async function startRelease() {
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
log(`Step 3/${STEPS}: updating package.json, readme.md and roadmap.md...`); log(`Step 3/${STEPS}: updating package.json...`);
await replaceInFile("./package.json", current, next); await replaceInFile("./package.json", current, next);
await replaceInFile("./README.md", current, next);
await replaceInFile("./roadmap.md", current, next);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
log(`Step 4/${STEPS}: creating git commit...`); log(`Step 4/${STEPS}: creating git commit...`);