mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1253b3922b | |||
| d5ed25cd19 | |||
| c4f0f17b9b | |||
| d27455e9f2 | |||
| 6ef38676c4 | |||
| b51756f356 | |||
| cfdf7caa50 | |||
| a5a6a592c1 | |||
| d0d7482b0f | |||
| 8fe4c0c76e | |||
| c1afaeb92a | |||
| 3883cec079 |
+6
-1
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -770,10 +770,11 @@ For reference, here is the final code:
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>OWL Todo App</title>
|
<title>OWL Todo App</title>
|
||||||
<link rel="stylesheet" href="app.css" />
|
<link rel="stylesheet" href="app.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
<script src="owl.js"></script>
|
<script src="owl.js"></script>
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
</head>
|
</body>
|
||||||
<body></body>
|
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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.
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odoo/owl",
|
"name": "@odoo/owl",
|
||||||
"version": "2.0.0-beta-17",
|
"version": "2.0.0-beta-20",
|
||||||
"description": "Odoo Web Library (OWL)",
|
"description": "Odoo Web Library (OWL)",
|
||||||
"main": "dist/owl.cjs.js",
|
"main": "dist/owl.cjs.js",
|
||||||
"module": "dist/owl.es.js",
|
"module": "dist/owl.es.js",
|
||||||
|
|||||||
+4
-23
@@ -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.
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ export class CodeGenerator {
|
|||||||
translatableAttributes: string[] = TRANSLATABLE_ATTRS;
|
translatableAttributes: string[] = TRANSLATABLE_ATTRS;
|
||||||
ast: AST;
|
ast: AST;
|
||||||
staticDefs: { id: string; expr: string }[] = [];
|
staticDefs: { id: string; expr: string }[] = [];
|
||||||
|
slotNames: Set<String> = new Set();
|
||||||
helpers: Set<string> = new Set();
|
helpers: Set<string> = new Set();
|
||||||
|
|
||||||
constructor(ast: AST, options: CodeGenOptions) {
|
constructor(ast: AST, options: CodeGenOptions) {
|
||||||
@@ -1187,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)) {
|
||||||
@@ -1245,28 +1246,37 @@ export class CodeGenerator {
|
|||||||
let blockString: string;
|
let blockString: string;
|
||||||
let slotName;
|
let slotName;
|
||||||
let dynamic = false;
|
let dynamic = false;
|
||||||
|
let isMultiple = false;
|
||||||
if (ast.name.match(INTERP_REGEXP)) {
|
if (ast.name.match(INTERP_REGEXP)) {
|
||||||
dynamic = true;
|
dynamic = true;
|
||||||
|
isMultiple = true;
|
||||||
slotName = interpolate(ast.name);
|
slotName = interpolate(ast.name);
|
||||||
} else {
|
} else {
|
||||||
slotName = "'" + ast.name + "'";
|
slotName = "'" + ast.name + "'";
|
||||||
|
isMultiple = isMultiple || this.slotNames.has(ast.name);
|
||||||
|
this.slotNames.add(ast.name);
|
||||||
}
|
}
|
||||||
const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
|
const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
|
||||||
if (ast.attrs) {
|
if (ast.attrs) {
|
||||||
delete ast.attrs["t-props"];
|
delete ast.attrs["t-props"];
|
||||||
}
|
}
|
||||||
|
let key = this.target.loopLevel ? `key${this.target.loopLevel}` : "key";
|
||||||
|
if (isMultiple) {
|
||||||
|
key = `${key} + \`${this.generateComponentKey()}\``;
|
||||||
|
}
|
||||||
|
|
||||||
const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
|
const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
|
||||||
const scope = this.getPropString(props, dynProps);
|
const scope = this.getPropString(props, dynProps);
|
||||||
if (ast.defaultContent) {
|
if (ast.defaultContent) {
|
||||||
const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
|
const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
|
||||||
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope}, ${name})`;
|
blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name})`;
|
||||||
} else {
|
} else {
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
let name = generateId("slot");
|
let name = generateId("slot");
|
||||||
this.define(name, slotName);
|
this.define(name, slotName);
|
||||||
blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}, ${dynamic}, ${scope}))`;
|
blockString = `toggler(${name}, callSlot(ctx, node, ${key}, ${name}, ${dynamic}, ${scope}))`;
|
||||||
} else {
|
} else {
|
||||||
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope})`;
|
blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// event handling
|
// event handling
|
||||||
|
|||||||
+7
-4
@@ -6,6 +6,7 @@ import { Scheduler } from "./scheduler";
|
|||||||
import { validateProps } from "./template_helpers";
|
import { validateProps } from "./template_helpers";
|
||||||
import { TemplateSet, TemplateSetConfig } from "./template_set";
|
import { TemplateSet, TemplateSetConfig } from "./template_set";
|
||||||
import { validateTarget } from "./utils";
|
import { validateTarget } from "./utils";
|
||||||
|
import { handleError } from "./error_handling";
|
||||||
|
|
||||||
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
|
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
|
||||||
|
|
||||||
@@ -65,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);
|
||||||
@@ -94,9 +95,7 @@ export class App<
|
|||||||
nodeErrorHandlers.set(node, handlers);
|
nodeErrorHandlers.set(node, handlers);
|
||||||
}
|
}
|
||||||
handlers.unshift((e) => {
|
handlers.unshift((e) => {
|
||||||
if (isResolved) {
|
if (!isResolved) {
|
||||||
console.error(e);
|
|
||||||
} else {
|
|
||||||
reject(e);
|
reject(e);
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -169,6 +168,10 @@ export class App<
|
|||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleError(...args: Parameters<typeof handleError>) {
|
||||||
|
return handleError(...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function mount<
|
export async function mount<
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ function createElementHandler(evName: string, capture: boolean = false): EventHa
|
|||||||
}
|
}
|
||||||
|
|
||||||
function listener(ev: Event) {
|
function listener(ev: Event) {
|
||||||
const currentTarget = ev.currentTarget;
|
const currentTarget = ev.currentTarget as HTMLElement;
|
||||||
if (!currentTarget || !document.contains(currentTarget as HTMLElement)) return;
|
if (!currentTarget || !currentTarget.ownerDocument.contains(currentTarget)) return;
|
||||||
const data = (currentTarget as any)[eventKey];
|
const data = (currentTarget as any)[eventKey];
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
config.mainEventHandler(data, ev, currentTarget);
|
config.mainEventHandler(data, ev, currentTarget);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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("");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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("");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { App, Env } from "./app";
|
import type { App, Env } from "./app";
|
||||||
import { BDom, VNode } from "./blockdom";
|
import { BDom, VNode } from "./blockdom";
|
||||||
import { Component, ComponentConstructor, Props } from "./component";
|
import { Component, ComponentConstructor, Props } from "./component";
|
||||||
import { fibersInError, handleError, OwlError } from "./error_handling";
|
import { fibersInError, OwlError } from "./error_handling";
|
||||||
import { Fiber, makeChildFiber, makeRootFiber, MountFiber, MountOptions } from "./fibers";
|
import { Fiber, makeChildFiber, makeRootFiber, MountFiber, MountOptions } from "./fibers";
|
||||||
import {
|
import {
|
||||||
clearReactivesForCallback,
|
clearReactivesForCallback,
|
||||||
@@ -141,7 +141,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
|
|||||||
try {
|
try {
|
||||||
await Promise.all(this.willStart.map((f) => f.call(component)));
|
await Promise.all(this.willStart.map((f) => f.call(component)));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ node: this, error: e });
|
this.app.handleError({ node: this, error: e });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.status === STATUS.NEW && this.fiber === fiber) {
|
if (this.status === STATUS.NEW && this.fiber === fiber) {
|
||||||
@@ -219,7 +219,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
|
|||||||
cb.call(component);
|
cb.call(component);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ error: e, node: this });
|
this.app.handleError({ error: e, node: this });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.status = STATUS.DESTROYED;
|
this.status = STATUS.DESTROYED;
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -71,5 +71,6 @@ export function handleError(params: ErrorParams) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { BDom, mount } from "./blockdom";
|
import { BDom, mount } from "./blockdom";
|
||||||
import type { ComponentNode } from "./component_node";
|
import type { ComponentNode } from "./component_node";
|
||||||
import { fibersInError, handleError, OwlError } from "./error_handling";
|
import { fibersInError, OwlError } from "./error_handling";
|
||||||
import { STATUS } from "./status";
|
import { STATUS } from "./status";
|
||||||
|
|
||||||
export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber {
|
export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber {
|
||||||
@@ -130,7 +130,7 @@ export class Fiber {
|
|||||||
(this.bdom as any) = true;
|
(this.bdom as any) = true;
|
||||||
this.bdom = node.renderFn();
|
this.bdom = node.renderFn();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ node, error: e });
|
node.app.handleError({ node, error: e });
|
||||||
}
|
}
|
||||||
root.setCounter(root.counter - 1);
|
root.setCounter(root.counter - 1);
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ export class RootFiber extends Fiber {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.locked = false;
|
this.locked = false;
|
||||||
handleError({ fiber: current || this, error: e });
|
node.app.handleError({ fiber: current || this, error: e });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ export class MountFiber extends RootFiber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ fiber: current as Fiber, error: e });
|
this.node.app.handleError({ fiber: current as Fiber, error: e });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|||||||
@@ -58,6 +58,20 @@ exports[`event handling handler receive the event as argument 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`event handling handler works when app is mounted in an iframe 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<span block-handler-0=\\"click\\">click me</span>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let hdlr1 = [ctx['inc'], ctx];
|
||||||
|
return block1([hdlr1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`event handling input blur event is not called if component is destroyed 1`] = `
|
exports[`event handling input blur event is not called if component is destroyed 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -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]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -604,6 +604,64 @@ exports[`slots default slot work with text nodes 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`slots dynamic slot in multiple locations 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { capture, markRaw } = helpers;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
const comp2 = app.createComponent(\`Slotter\`, true, true, false, false);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\`hello \`);
|
||||||
|
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const ctx1 = capture(ctx);
|
||||||
|
return comp2({location: ctx['state'].location,slots: markRaw({'coffee': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots dynamic slot in multiple locations 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { callSlot } = helpers;
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<p><block-child-0/></p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let b2,b4;
|
||||||
|
if (ctx['props'].location===1) {
|
||||||
|
const slot1 = ('coffee');
|
||||||
|
const b3 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {}));
|
||||||
|
b2 = block2([], [b3]);
|
||||||
|
}
|
||||||
|
if (ctx['props'].location===2) {
|
||||||
|
const slot2 = ('coffee');
|
||||||
|
b4 = toggler(slot2, callSlot(ctx, node, key + \`__2\`, slot2, true, {}));
|
||||||
|
}
|
||||||
|
return multi([b2, b4]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots dynamic slot in multiple locations 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div>child</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`slots dynamic t-slot call 1`] = `
|
exports[`slots dynamic t-slot call 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -645,7 +703,7 @@ exports[`slots dynamic t-slot call 2`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
let hdlr1 = [ctx['toggle'], ctx];
|
let hdlr1 = [ctx['toggle'], ctx];
|
||||||
const slot1 = (ctx['current'].slot);
|
const slot1 = (ctx['current'].slot);
|
||||||
const b2 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {}));
|
const b2 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {}));
|
||||||
return block1([hdlr1], [b2]);
|
return block1([hdlr1], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -695,7 +753,7 @@ exports[`slots dynamic t-slot call with default 2`] = `
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
let hdlr1 = [ctx['toggle'], ctx];
|
let hdlr1 = [ctx['toggle'], ctx];
|
||||||
const b3 = callSlot(ctx, node, key, (ctx['current'].slot), true, {}, defaultContent1);
|
const b3 = callSlot(ctx, node, key + \`__1\`, (ctx['current'].slot), true, {}, defaultContent1);
|
||||||
return block1([hdlr1], [b3]);
|
return block1([hdlr1], [b3]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -726,7 +784,7 @@ exports[`slots fun: two calls to the same slot 2`] = `
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = callSlot(ctx, node, key, 'default', false, {});
|
const b2 = callSlot(ctx, node, key, 'default', false, {});
|
||||||
const b3 = callSlot(ctx, node, key, 'default', false, {});
|
const b3 = callSlot(ctx, node, key + \`__1\`, 'default', false, {});
|
||||||
return multi([b2, b3]);
|
return multi([b2, b3]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -1527,7 +1585,7 @@ exports[`slots simple dynamic slot with slot scope 2`] = `
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const slot1 = ('slotName');
|
const slot1 = ('slotName');
|
||||||
const b2 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {bool: ctx['state'].bool}));
|
const b2 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {bool: ctx['state'].bool}));
|
||||||
return block1([], [b2]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -1854,7 +1912,7 @@ exports[`slots slot content has different key from other content -- dynamic slot
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = comp1({parent: 'SlotDisplay'}, key + \`__1\`, node, this, null);
|
const b2 = comp1({parent: 'SlotDisplay'}, key + \`__1\`, node, this, null);
|
||||||
const slot1 = (ctx['slotName']);
|
const slot1 = (ctx['slotName']);
|
||||||
const b3 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {}));
|
const b3 = toggler(slot1, callSlot(ctx, node, key + \`__2\`, slot1, true, {}));
|
||||||
return multi([b2, b3]);
|
return multi([b2, b3]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -1995,6 +2053,118 @@ exports[`slots slot content is bound to caller 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in multiple locations 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(\`Slotter\`, true, true, false, false);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\` hello \`);
|
||||||
|
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return comp2({location: ctx['state'].location,slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in multiple locations 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { callSlot } = helpers;
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<p><block-child-0/></p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let b2,b4;
|
||||||
|
if (ctx['props'].location===1) {
|
||||||
|
const b3 = callSlot(ctx, node, key, 'default', false, {});
|
||||||
|
b2 = block2([], [b3]);
|
||||||
|
}
|
||||||
|
if (ctx['props'].location===2) {
|
||||||
|
b4 = callSlot(ctx, node, key + \`__1\`, 'default', false, {});
|
||||||
|
}
|
||||||
|
return multi([b2, b4]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in multiple locations 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div>child</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in t-foreach locations 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(\`Slotter\`, true, true, false, false);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\` hello \`);
|
||||||
|
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return comp2({list: ctx['state'].list,slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in t-foreach locations 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, callSlot, withKey } = helpers;
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<p><block-text-0/><block-child-0/></p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['props'].list);;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`elem\`] = v_block1[i1];
|
||||||
|
ctx[\`elem_index\`] = i1;
|
||||||
|
const key1 = ctx['elem_index'];
|
||||||
|
let txt1 = ctx['elem'];
|
||||||
|
const b3 = callSlot(ctx, node, key1, 'default', false, {});
|
||||||
|
c_block1[i1] = withKey(block2([txt1], [b3]), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in t-foreach locations 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div>child</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`slots slot preserves properly parented relationship 1`] = `
|
exports[`slots slot preserves properly parented relationship 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import { App, Component, mount, status, toRaw, useState, xml } from "../../src";
|
import { App, Component, mount, status, toRaw, useState, xml } from "../../src";
|
||||||
import { elem, makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
|
import {
|
||||||
|
elem,
|
||||||
|
makeTestFixture,
|
||||||
|
nextAppError,
|
||||||
|
nextTick,
|
||||||
|
snapshotEverything,
|
||||||
|
useLogLifecycle,
|
||||||
|
} from "../helpers";
|
||||||
import { markup } from "../../src/runtime/utils";
|
import { markup } from "../../src/runtime/utils";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
@@ -208,14 +215,14 @@ describe("basics", () => {
|
|||||||
static template = xml`<div/>`;
|
static template = xml`<div/>`;
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
const prom = mount(Test, fixture);
|
const app = new App(Test);
|
||||||
|
const prom = app.mount(fixture);
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
fixture.remove();
|
fixture.remove();
|
||||||
try {
|
prom.catch((e: Error) => (error = e));
|
||||||
await prom;
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
} catch (e) {
|
"Cannot mount a component on a detached dom node"
|
||||||
error = e as Error;
|
);
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Cannot mount a component on a detached dom node");
|
expect(error!.message).toBe("Cannot mount a component on a detached dom node");
|
||||||
expect(console.warn).toBeCalledTimes(1);
|
expect(console.warn).toBeCalledTimes(1);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, mount, onWillDestroy } from "../../src";
|
import { App, Component, mount, onWillDestroy } from "../../src";
|
||||||
import {
|
import {
|
||||||
onError,
|
onError,
|
||||||
onMounted,
|
onMounted,
|
||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
nextMicroTick,
|
nextMicroTick,
|
||||||
snapshotEverything,
|
snapshotEverything,
|
||||||
useLogLifecycle,
|
useLogLifecycle,
|
||||||
|
nextAppError,
|
||||||
} from "../helpers";
|
} from "../helpers";
|
||||||
import { OwlError } from "../../src/runtime/error_handling";
|
import { OwlError } from "../../src/runtime/error_handling";
|
||||||
|
|
||||||
@@ -59,9 +60,10 @@ describe("basics", () => {
|
|||||||
parent.state.flag = true;
|
parent.state.flag = true;
|
||||||
|
|
||||||
parent.render();
|
parent.render();
|
||||||
await nextTick();
|
await expect(nextAppError(parent.__owl__.app)).resolves.toThrow(
|
||||||
|
"An error occured in the owl lifecycle"
|
||||||
|
);
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
expect(mockConsoleError).toBeCalledTimes(1);
|
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,12 +73,13 @@ describe("basics", () => {
|
|||||||
static template = xml`<SomeMispelledComponent />`;
|
static template = xml`<SomeMispelledComponent />`;
|
||||||
static components = { SomeComponent };
|
static components = { SomeComponent };
|
||||||
}
|
}
|
||||||
|
const app = new App(Parent);
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(Parent, fixture);
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
} catch (e) {
|
'Cannot find the definition of component "SomeMispelledComponent"'
|
||||||
error = e as Error;
|
);
|
||||||
}
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
|
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
|
||||||
expect(console.error).toBeCalledTimes(0);
|
expect(console.error).toBeCalledTimes(0);
|
||||||
@@ -90,12 +93,13 @@ describe("basics", () => {
|
|||||||
static template = xml`<SomeMispelledComponent />`;
|
static template = xml`<SomeMispelledComponent />`;
|
||||||
static components = { SomeComponent };
|
static components = { SomeComponent };
|
||||||
}
|
}
|
||||||
|
const app = new App(Parent, { test: true });
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(Parent, fixture, { test: true });
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
} catch (e) {
|
'Cannot find the definition of component "SomeMispelledComponent"'
|
||||||
error = e as Error;
|
);
|
||||||
}
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
|
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
|
||||||
expect(console.error).toBeCalledTimes(0);
|
expect(console.error).toBeCalledTimes(0);
|
||||||
@@ -109,13 +113,13 @@ describe("basics", () => {
|
|||||||
static template = xml`<SomeComponent />`;
|
static template = xml`<SomeComponent />`;
|
||||||
static components = { SomeComponent: notAComponentConstructor };
|
static components = { SomeComponent: notAComponentConstructor };
|
||||||
}
|
}
|
||||||
|
const app = new App(Parent as typeof Component);
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
// @ts-expect-error
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
await mount(Parent, fixture);
|
'"SomeComponent" is not a Component. It must inherit from the Component class'
|
||||||
} catch (e) {
|
);
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
'"SomeComponent" is not a Component. It must inherit from the Component class'
|
'"SomeComponent" is not a Component. It must inherit from the Component class'
|
||||||
@@ -156,16 +160,15 @@ describe("basics", () => {
|
|||||||
describe("errors and promises", () => {
|
describe("errors and promises", () => {
|
||||||
test("a rendering error will reject the mount promise", async () => {
|
test("a rendering error will reject the mount promise", async () => {
|
||||||
// we do not catch error in willPatch anymore
|
// we do not catch error in willPatch anymore
|
||||||
class App extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div><t t-esc="this.will.crash"/></div>`;
|
static template = xml`<div><t t-esc="this.will.crash"/></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const app = new App(Root);
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(App, fixture);
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as OwlError;
|
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
const regexp =
|
const regexp =
|
||||||
@@ -176,7 +179,7 @@ describe("errors and promises", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("an error in mounted call will reject the mount promise", async () => {
|
test("an error in mounted call will reject the mount promise", async () => {
|
||||||
class App extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div>abc</div>`;
|
static template = xml`<div>abc</div>`;
|
||||||
setup() {
|
setup() {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -185,12 +188,11 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const app = new App(Root);
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(App, fixture);
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as OwlError;
|
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
expect(error!.cause.message).toBe("boom");
|
expect(error!.cause.message).toBe("boom");
|
||||||
@@ -200,7 +202,7 @@ describe("errors and promises", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("an error in onMounted callback will have the component's setup in its stack trace", async () => {
|
test("an error in onMounted callback will have the component's setup in its stack trace", async () => {
|
||||||
class App extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div>abc</div>`;
|
static template = xml`<div>abc</div>`;
|
||||||
setup() {
|
setup() {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -209,14 +211,13 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: Error;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(App, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.stack).toContain("App.setup");
|
expect(error!.stack).toContain("Root.setup");
|
||||||
expect(error!.stack).toContain("error_handling.test.ts");
|
expect(error!.stack).toContain("error_handling.test.ts");
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
expect(mockConsoleError).toBeCalledTimes(0);
|
expect(mockConsoleError).toBeCalledTimes(0);
|
||||||
@@ -224,7 +225,7 @@ describe("errors and promises", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("errors in onWillRender/onRender aren't wrapped more than once", async () => {
|
test("errors in onWillRender/onRender aren't wrapped more than once", async () => {
|
||||||
class App extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div>abc</div>`;
|
static template = xml`<div>abc</div>`;
|
||||||
setup() {
|
setup() {
|
||||||
onWillRender(() => {
|
onWillRender(() => {
|
||||||
@@ -236,12 +237,11 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: Error;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(App, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillRender");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`The following error occurred in onWillRender: "boom in onWillRender"`
|
`The following error occurred in onWillRender: "boom in onWillRender"`
|
||||||
@@ -278,12 +278,11 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: any;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
|
||||||
error = e;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`The following error occurred in onWillStart: "boom in onWillStart"`
|
`The following error occurred in onWillStart: "boom in onWillStart"`
|
||||||
@@ -342,17 +341,16 @@ describe("errors and promises", () => {
|
|||||||
class Child extends Component {
|
class Child extends Component {
|
||||||
static template = xml`<div><t t-esc="this.will.crash"/></div>`;
|
static template = xml`<div><t t-esc="this.will.crash"/></div>`;
|
||||||
}
|
}
|
||||||
class App extends Component {
|
class Parent extends Component {
|
||||||
static template = xml`<div><Child/></div>`;
|
static template = xml`<div><Child/></div>`;
|
||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const app = new App(Parent);
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(App, fixture);
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as OwlError;
|
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
const regexp =
|
const regexp =
|
||||||
@@ -394,12 +392,11 @@ describe("errors and promises", () => {
|
|||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const app = new App(Parent);
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(Parent, fixture);
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as OwlError;
|
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
const regexp =
|
const regexp =
|
||||||
@@ -425,13 +422,12 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const app = new App(Example, { test: true });
|
||||||
await mount(Example, fixture, { test: true });
|
let error: OwlError;
|
||||||
} catch (e) {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
expect((e as Error).message).toBe(
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
|
||||||
`The following error occurred in onMounted: "Error in mounted"`
|
await mountProm;
|
||||||
);
|
expect(error!.message).toBe(`The following error occurred in onMounted: "Error in mounted"`);
|
||||||
}
|
|
||||||
// 1 additional error is logged because the destruction of the app causes
|
// 1 additional error is logged because the destruction of the app causes
|
||||||
// the onWillUnmount hook to be called and to fail
|
// the onWillUnmount hook to be called and to fail
|
||||||
expect(mockConsoleError).toBeCalledTimes(1);
|
expect(mockConsoleError).toBeCalledTimes(1);
|
||||||
@@ -448,9 +444,10 @@ describe("errors and promises", () => {
|
|||||||
|
|
||||||
root.state = "boom";
|
root.state = "boom";
|
||||||
root.render();
|
root.render();
|
||||||
await nextTick();
|
await expect(nextAppError(root.__owl__.app)).resolves.toThrow(
|
||||||
|
"error occured in the owl lifecycle"
|
||||||
|
);
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
expect(mockConsoleError).toBeCalledTimes(1);
|
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -500,13 +497,12 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: Error;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const crashProm = expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
|
||||||
} catch (error) {
|
await app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
e = error as Error;
|
await crashProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`The following error occurred in onWillStart: "No active component (a hook function should only be called in 'setup')"`
|
`The following error occurred in onWillStart: "No active component (a hook function should only be called in 'setup')"`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -523,14 +519,13 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(`The following error occurred in onMounted: "test error"`);
|
||||||
expect(e!.message).toBe(`The following error occurred in onMounted: "test error"`);
|
expect(error!.cause).toBe(err);
|
||||||
expect(e!.cause).toBe(err);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Errors in owl lifecycle are wrapped in dev mode: async hook", async () => {
|
test("Errors in owl lifecycle are wrapped in dev mode: async hook", async () => {
|
||||||
@@ -546,14 +541,13 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(`The following error occurred in onWillStart: "test error"`);
|
||||||
expect(e!.message).toBe(`The following error occurred in onWillStart: "test error"`);
|
expect(error!.cause).toBe(err);
|
||||||
expect(e!.cause).toBe(err);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Errors in owl lifecycle are wrapped outside dev mode: sync hook", async () => {
|
test("Errors in owl lifecycle are wrapped outside dev mode: sync hook", async () => {
|
||||||
@@ -568,16 +562,15 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root);
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
||||||
);
|
);
|
||||||
expect(e!.cause).toBe(err);
|
expect(error!.cause).toBe(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Errors in owl lifecycle are wrapped out of dev mode: async hook", async () => {
|
test("Errors in owl lifecycle are wrapped out of dev mode: async hook", async () => {
|
||||||
@@ -593,16 +586,15 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root);
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
||||||
);
|
);
|
||||||
expect(e!.cause).toBe(err);
|
expect(error!.cause).toBe(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Thrown values that are not errors are wrapped in dev mode", async () => {
|
test("Thrown values that are not errors are wrapped in dev mode", async () => {
|
||||||
@@ -616,16 +608,15 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("not an Error was thrown in onMounted");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`Something that is not an Error was thrown in onMounted (see this Error's "cause" property)`
|
`Something that is not an Error was thrown in onMounted (see this Error's "cause" property)`
|
||||||
);
|
);
|
||||||
expect(e!.cause).toBe("This is not an error");
|
expect(error!.cause).toBe("This is not an error");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Thrown values that are not errors are wrapped outside dev mode", async () => {
|
test("Thrown values that are not errors are wrapped outside dev mode", async () => {
|
||||||
@@ -639,16 +630,15 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root);
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
||||||
);
|
);
|
||||||
expect(e!.cause).toBe("This is not an error");
|
expect(error!.cause).toBe("This is not an error");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can catch an error in the initial call of a component render function (parent mounted)", async () => {
|
test("can catch an error in the initial call of a component render function (parent mounted)", async () => {
|
||||||
|
|||||||
@@ -171,4 +171,22 @@ describe("event handling", () => {
|
|||||||
// input is removed when component is destroyed => nothing should happen
|
// input is removed when component is destroyed => nothing should happen
|
||||||
expect([]).toBeLogged();
|
expect([]).toBeLogged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("handler works when app is mounted in an iframe", async () => {
|
||||||
|
let clickCount = 0;
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`<span t-on-click="inc">click me</span>`;
|
||||||
|
inc() {
|
||||||
|
clickCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const iframe = document.createElement("iframe");
|
||||||
|
fixture.appendChild(iframe);
|
||||||
|
const iframeDoc = iframe.contentDocument!;
|
||||||
|
await mount(Parent, iframeDoc.body);
|
||||||
|
expect(clickCount).toBe(0);
|
||||||
|
iframeDoc.querySelector("span")!.click();
|
||||||
|
expect(clickCount).toBe(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,8 +17,17 @@ import {
|
|||||||
useChildSubEnv,
|
useChildSubEnv,
|
||||||
useSubEnv,
|
useSubEnv,
|
||||||
xml,
|
xml,
|
||||||
|
OwlError,
|
||||||
} from "../../src/index";
|
} from "../../src/index";
|
||||||
import { elem, logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { useRoots } from "../../src/runtime/hooks";
|
||||||
|
import {
|
||||||
|
elem,
|
||||||
|
logStep,
|
||||||
|
makeTestFixture,
|
||||||
|
nextAppError,
|
||||||
|
nextTick,
|
||||||
|
snapshotEverything,
|
||||||
|
} from "../helpers";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
|
|
||||||
@@ -510,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,
|
||||||
@@ -650,11 +659,12 @@ describe("hooks", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(MyComponent, fixture);
|
const app = new App(MyComponent);
|
||||||
} catch (e: any) {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
expect(e.cause.message).toBe("Intentional error");
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
}
|
await mountProm;
|
||||||
|
expect(error!.cause.message).toBe("Intentional error");
|
||||||
// no console.error because the error has been caught in this test
|
// no console.error because the error has been caught in this test
|
||||||
expect(console.error).toHaveBeenCalledTimes(0);
|
expect(console.error).toHaveBeenCalledTimes(0);
|
||||||
console.error = originalconsoleError;
|
console.error = originalconsoleError;
|
||||||
@@ -664,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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
import { Component, onError, xml, mount } from "../../src";
|
import { Component, onError, xml, mount, OwlError } from "../../src";
|
||||||
import { DEV_MSG } from "../../src/runtime/app";
|
import { App, DEV_MSG } from "../../src/runtime/app";
|
||||||
import { validateProps } from "../../src/runtime/template_helpers";
|
import { validateProps } from "../../src/runtime/template_helpers";
|
||||||
import { Schema } from "../../src/runtime/validation";
|
import { Schema } from "../../src/runtime/validation";
|
||||||
|
|
||||||
@@ -48,13 +48,14 @@ describe("props validation", () => {
|
|||||||
static components = { SubComp };
|
static components = { SubComp };
|
||||||
static template = xml`<div><SubComp /></div>`;
|
static template = xml`<div><SubComp /></div>`;
|
||||||
}
|
}
|
||||||
let error: Error | undefined;
|
|
||||||
|
|
||||||
try {
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
let error: OwlError | undefined;
|
||||||
} catch (e) {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
error = e as Error;
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
}
|
"Invalid props for component 'SubComp': 'message' is missing"
|
||||||
|
);
|
||||||
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
|
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
|
||||||
error = undefined;
|
error = undefined;
|
||||||
@@ -77,12 +78,13 @@ describe("props validation", () => {
|
|||||||
static template = xml`<div><SubComp /></div>`;
|
static template = xml`<div><SubComp /></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: Error;
|
const app = new App(Parent, { test: true });
|
||||||
try {
|
let error: OwlError | undefined;
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
error = e as Error;
|
"Invalid props for component 'SubComp': 'message' is missing"
|
||||||
}
|
);
|
||||||
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
|
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
|
||||||
});
|
});
|
||||||
@@ -126,14 +128,12 @@ describe("props validation", () => {
|
|||||||
};
|
};
|
||||||
(Parent as any).components = { SubComp };
|
(Parent as any).components = { SubComp };
|
||||||
|
|
||||||
let error: Error | undefined;
|
|
||||||
props = {};
|
props = {};
|
||||||
|
let app = new App(Parent, { test: true });
|
||||||
try {
|
let error: OwlError | undefined;
|
||||||
await mount(Parent, fixture, { dev: true });
|
let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
|
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
|
||||||
@@ -147,11 +147,10 @@ describe("props validation", () => {
|
|||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
props = { p: test.ko };
|
props = { p: test.ko };
|
||||||
try {
|
app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
|
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
|
||||||
@@ -181,13 +180,12 @@ describe("props validation", () => {
|
|||||||
static template = xml`<div>hey</div>`;
|
static template = xml`<div>hey</div>`;
|
||||||
};
|
};
|
||||||
(Parent as any).components = { SubComp };
|
(Parent as any).components = { SubComp };
|
||||||
let error: Error | undefined;
|
|
||||||
props = {};
|
props = {};
|
||||||
try {
|
let app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
let error: OwlError | undefined;
|
||||||
} catch (e) {
|
let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
error = e as Error;
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
|
||||||
}
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
|
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
|
||||||
@@ -201,11 +199,10 @@ describe("props validation", () => {
|
|||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
props = { p: test.ko };
|
props = { p: test.ko };
|
||||||
try {
|
app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
|
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
|
||||||
@@ -227,26 +224,25 @@ describe("props validation", () => {
|
|||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
let props: { p?: any };
|
let props: { p?: any };
|
||||||
|
props = { p: "string" };
|
||||||
try {
|
try {
|
||||||
props = { p: "string" };
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
await mount(Parent, fixture, { dev: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
|
props = { p: true };
|
||||||
try {
|
try {
|
||||||
props = { p: true };
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
await mount(Parent, fixture, { dev: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: 1 };
|
||||||
props = { p: 1 };
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' is not a string or boolean"
|
"Invalid props for component 'SubComp': 'p' is not a string or boolean"
|
||||||
@@ -267,26 +263,25 @@ describe("props validation", () => {
|
|||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
let props: { p?: any };
|
let props: { p?: any };
|
||||||
|
props = { p: "key" };
|
||||||
try {
|
try {
|
||||||
props = { p: "key" };
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
await mount(Parent, fixture, { dev: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
|
props = {};
|
||||||
try {
|
try {
|
||||||
props = {};
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
await mount(Parent, fixture, { dev: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: 1 };
|
||||||
props = { p: 1 };
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is not a string");
|
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is not a string");
|
||||||
});
|
});
|
||||||
@@ -319,20 +314,18 @@ describe("props validation", () => {
|
|||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: [1] };
|
||||||
props = { p: [1] };
|
let app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
error = undefined;
|
error = undefined;
|
||||||
try {
|
app = new App(Parent, { test: true });
|
||||||
props = { p: ["string", 1] };
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(Parent, fixture, { dev: true });
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as Error;
|
expect(error!).toBeDefined();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can validate an array with multiple sub element types", async () => {
|
test("can validate an array with multiple sub element types", async () => {
|
||||||
@@ -370,12 +363,11 @@ describe("props validation", () => {
|
|||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: [true, 1] };
|
||||||
props = { p: [true, 1] };
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p[1]' is not a string or boolean"
|
"Invalid props for component 'SubComp': 'p[1]' is not a string or boolean"
|
||||||
@@ -405,33 +397,30 @@ describe("props validation", () => {
|
|||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: { id: 1, url: "url", extra: true } };
|
||||||
props = { p: { id: 1, url: "url", extra: true } };
|
let app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' has not the correct shape (unknown key 'extra')"
|
"Invalid props for component 'SubComp': 'p' has not the correct shape (unknown key 'extra')"
|
||||||
);
|
);
|
||||||
try {
|
props = { p: { id: "1", url: "url" } };
|
||||||
props = { p: { id: "1", url: "url" } };
|
app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' has not the correct shape ('id' is not a number)"
|
"Invalid props for component 'SubComp': 'p' has not the correct shape ('id' is not a number)"
|
||||||
);
|
);
|
||||||
error = undefined;
|
error = undefined;
|
||||||
try {
|
props = { p: { id: 1 } };
|
||||||
props = { p: { id: 1 } };
|
app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is missing (should be a string))"
|
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is missing (should be a string))"
|
||||||
@@ -474,12 +463,11 @@ describe("props validation", () => {
|
|||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: { id: 1, url: [12, true] } };
|
||||||
props = { p: { id: 1, url: [12, true] } };
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is not a boolean or list of numbers)"
|
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is not a boolean or list of numbers)"
|
||||||
@@ -686,11 +674,10 @@ describe("props validation", () => {
|
|||||||
static components = { SubComp };
|
static components = { SubComp };
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is missing");
|
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is missing");
|
||||||
});
|
});
|
||||||
@@ -754,11 +741,10 @@ describe("props validation", () => {
|
|||||||
static template = xml`<div><Child/></div>`;
|
static template = xml`<div><Child/></div>`;
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'Child'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'Child': 'mandatory' is missing (should be a number)"
|
"Invalid props for component 'Child': 'mandatory' is missing (should be a number)"
|
||||||
@@ -859,11 +845,12 @@ describe("default props", () => {
|
|||||||
static template = xml`<Child/>`;
|
static template = xml`<Child/>`;
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
error = e as Error;
|
"default value cannot be defined for a mandatory prop"
|
||||||
}
|
);
|
||||||
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"A default value cannot be defined for a mandatory prop (name: 'mandatory', component: Child)"
|
"A default value cannot be defined for a mandatory prop (name: 'mandatory', component: Child)"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, mount, onMounted, useRef, useState } from "../../src/index";
|
import { App, Component, mount, onMounted, useRef, useState } from "../../src/index";
|
||||||
import { logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { logStep, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
import { xml } from "../../src/index";
|
import { xml } from "../../src/index";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
@@ -94,9 +94,14 @@ describe("refs", () => {
|
|||||||
ref = useRef("coucou");
|
ref = useRef("coucou");
|
||||||
}
|
}
|
||||||
|
|
||||||
await expect(async () => {
|
const app = new App(Test, { test: true });
|
||||||
await mount(Test, fixture);
|
const mountProm = expect(app.mount(fixture)).rejects.toThrowError(
|
||||||
}).rejects.toThrowError("Cannot have 2 elements with same ref name at the same time");
|
"Cannot have 2 elements with same ref name at the same time"
|
||||||
|
);
|
||||||
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
|
"Cannot have 2 elements with same ref name at the same time"
|
||||||
|
);
|
||||||
|
await mountProm;
|
||||||
expect(console.warn).toBeCalledTimes(1);
|
expect(console.warn).toBeCalledTimes(1);
|
||||||
console.warn = consoleWarn;
|
console.warn = consoleWarn;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
|
import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
|
||||||
import { children, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { children, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
let originalconsoleWarn = console.warn;
|
let originalconsoleWarn = console.warn;
|
||||||
@@ -204,13 +204,12 @@ describe("slots", () => {
|
|||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = null;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(Parent, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
error = e;
|
await mountProm;
|
||||||
}
|
expect(error!).not.toBeNull();
|
||||||
expect(error).not.toBeNull();
|
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1819,4 +1818,102 @@ describe("slots", () => {
|
|||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<button>inc</button>[B][C][A][sub1] [sub2334]");
|
expect(fixture.innerHTML).toBe("<button>inc</button>[B][C][A][sub1] [sub2334]");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("slot in multiple locations", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<div>child</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Slotter extends Component {
|
||||||
|
static components = { Child };
|
||||||
|
static template = xml`
|
||||||
|
<t t-if="props.location === 1">
|
||||||
|
<p><t t-slot="default"/></p>
|
||||||
|
</t>
|
||||||
|
<t t-if="props.location === 2">
|
||||||
|
<t t-slot="default"/>
|
||||||
|
</t>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static components = { Child, Slotter };
|
||||||
|
static template = xml`
|
||||||
|
<Slotter location="state.location">
|
||||||
|
hello <Child/>
|
||||||
|
</Slotter>`;
|
||||||
|
state = useState({ location: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<p> hello <div>child</div></p>");
|
||||||
|
parent.state.location = 2;
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe(" hello <div>child</div>");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("dynamic slot in multiple locations", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<div>child</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Slotter extends Component {
|
||||||
|
static components = { Child };
|
||||||
|
static template = xml`
|
||||||
|
<t t-if="props.location === 1">
|
||||||
|
<p><t t-slot="{{'coffee'}}"/></p>
|
||||||
|
</t>
|
||||||
|
<t t-if="props.location === 2">
|
||||||
|
<t t-slot="{{'coffee'}}"/>
|
||||||
|
</t>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static components = { Child, Slotter };
|
||||||
|
static template = xml`
|
||||||
|
<Slotter location="state.location">
|
||||||
|
<t t-set-slot="coffee">hello <Child/></t>
|
||||||
|
</Slotter>`;
|
||||||
|
state = useState({ location: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<p>hello <div>child</div></p>");
|
||||||
|
parent.state.location = 2;
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe("hello <div>child</div>");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("slot in t-foreach locations", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<div>child</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Slotter extends Component {
|
||||||
|
static components = { Child };
|
||||||
|
static template = xml`
|
||||||
|
<t t-foreach="props.list" t-as="elem" t-key="elem_index">
|
||||||
|
<p><t t-esc="elem"/><t t-slot="default"/></p>
|
||||||
|
</t>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static components = { Child, Slotter };
|
||||||
|
static template = xml`
|
||||||
|
<Slotter list="state.list">
|
||||||
|
hello <Child/>
|
||||||
|
</Slotter>`;
|
||||||
|
state = useState({ list: [1] });
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<p>1 hello <div>child</div></p>");
|
||||||
|
parent.state.list.push(2);
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe(
|
||||||
|
"<p>1 hello <div>child</div></p><p>2 hello <div>child</div></p>"
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { OwlError } from "../../src/runtime/error_handling";
|
import { OwlError } from "../../src/runtime/error_handling";
|
||||||
import { Component, mount, onMounted, useState, xml } from "../../src";
|
import { App, Component, mount, onMounted, useState, xml } from "../../src";
|
||||||
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
@@ -343,16 +343,15 @@ describe("style and class handling", () => {
|
|||||||
class Child extends Component {
|
class Child extends Component {
|
||||||
static template = xml`<div t-att-class="props.class" t-esc="this.will.crash"/>`;
|
static template = xml`<div t-att-class="props.class" t-esc="this.will.crash"/>`;
|
||||||
}
|
}
|
||||||
class ParentWidget extends Component {
|
class Parent extends Component {
|
||||||
static template = xml`<Child class="'a'"/>`;
|
static template = xml`<Child class="'a'"/>`;
|
||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(ParentWidget, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
error = e as OwlError;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
const regexp =
|
const regexp =
|
||||||
|
|||||||
@@ -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,5 +1,11 @@
|
|||||||
import { Component, mount, onMounted, useState, xml } from "../../src/index";
|
import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
|
||||||
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
|
import {
|
||||||
|
makeTestFixture,
|
||||||
|
nextAppError,
|
||||||
|
nextTick,
|
||||||
|
snapshotEverything,
|
||||||
|
useLogLifecycle,
|
||||||
|
} from "../helpers";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
|
|
||||||
@@ -315,9 +321,13 @@ describe("list of components", () => {
|
|||||||
`;
|
`;
|
||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
await expect(async () => {
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
const app = new App(Parent, { test: true });
|
||||||
}).rejects.toThrowError("Got duplicate key in t-foreach: child");
|
const mountProm = expect(app.mount(fixture)).rejects.toThrow(
|
||||||
|
"Got duplicate key in t-foreach: child"
|
||||||
|
);
|
||||||
|
await expect(nextAppError(app)).resolves.toThrow("Got duplicate key in t-foreach: child");
|
||||||
|
await mountProm;
|
||||||
console.info = consoleInfo;
|
console.info = consoleInfo;
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -261,6 +261,20 @@ expect.extend({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export function nextAppError(app: any) {
|
||||||
|
const { handleError } = app;
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
app.handleError = (...args: Parameters<typeof handleError>) => {
|
||||||
|
try {
|
||||||
|
handleError.call(app, ...args);
|
||||||
|
} catch (e: any) {
|
||||||
|
app.handleError = handleError;
|
||||||
|
resolve(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace jest {
|
namespace jest {
|
||||||
interface Matchers<R> {
|
interface Matchers<R> {
|
||||||
|
|||||||
+13
-16
@@ -12,7 +12,7 @@ import {
|
|||||||
} from "../../src";
|
} from "../../src";
|
||||||
import { xml } from "../../src/";
|
import { xml } from "../../src/";
|
||||||
import { DEV_MSG } from "../../src/runtime/app";
|
import { DEV_MSG } from "../../src/runtime/app";
|
||||||
import { elem, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { elem, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
let originalconsoleWarn = console.warn;
|
let originalconsoleWarn = console.warn;
|
||||||
@@ -269,11 +269,10 @@ describe("Portal", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(Parent, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("invalid portal target");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("invalid portal target");
|
expect(error!.message).toBe("invalid portal target");
|
||||||
@@ -960,11 +959,10 @@ describe("Portal: Props validation", () => {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
error = e as OwlError;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
expect(error!.cause.message).toBe(`' ' is not a valid selector`);
|
expect(error!.cause.message).toBe(`' ' is not a valid selector`);
|
||||||
@@ -980,11 +978,10 @@ describe("Portal: Props validation", () => {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("invalid portal target");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(`invalid portal target`);
|
expect(error!.message).toBe(`invalid portal target`);
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-3
@@ -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...`);
|
||||||
|
|||||||
Reference in New Issue
Block a user