mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 545d40b211 | |||
| 2c244aa31a | |||
| ba1a270c93 | |||
| d546244fc3 | |||
| a1f22829c1 | |||
| 64bad25762 | |||
| 7ab34c5ca5 | |||
| 669fd622ec | |||
| ab72cdddde | |||
| 17fb33475c | |||
| ab29b896eb |
+1
-6
@@ -261,12 +261,7 @@ 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.
|
||||||
|
|
||||||
Another way to get access to a root node or html element is the hook `useRoots`
|
Documentation: [Refs](doc/reference/refs.md)
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ 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:
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
- [`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
|
||||||
@@ -289,42 +288,6 @@ 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-20",
|
"version": "2.0.0",
|
||||||
"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",
|
||||||
|
|||||||
@@ -214,6 +214,14 @@ class CodeTarget {
|
|||||||
result.push(`}`);
|
result.push(`}`);
|
||||||
return result.join("\n ");
|
return result.join("\n ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentKey(ctx: Context) {
|
||||||
|
let key = this.loopLevel ? `key${this.loopLevel}` : "key";
|
||||||
|
if (ctx.tKeyExpr) {
|
||||||
|
key = `${ctx.tKeyExpr} + ${key}`;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"];
|
const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"];
|
||||||
@@ -365,19 +373,15 @@ export class CodeGenerator {
|
|||||||
|
|
||||||
insertBlock(expression: string, block: BlockDescription, ctx: Context): void {
|
insertBlock(expression: string, block: BlockDescription, ctx: Context): void {
|
||||||
let blockExpr = block.generateExpr(expression);
|
let blockExpr = block.generateExpr(expression);
|
||||||
const tKeyExpr = ctx.tKeyExpr;
|
|
||||||
if (block.parentVar) {
|
if (block.parentVar) {
|
||||||
let keyArg = `key${this.target.loopLevel}`;
|
let key = this.target.currentKey(ctx);
|
||||||
if (tKeyExpr) {
|
|
||||||
keyArg = `${tKeyExpr} + ${keyArg}`;
|
|
||||||
}
|
|
||||||
this.helpers.add("withKey");
|
this.helpers.add("withKey");
|
||||||
this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${keyArg});`);
|
this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${key});`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tKeyExpr) {
|
if (ctx.tKeyExpr) {
|
||||||
blockExpr = `toggler(${tKeyExpr}, ${blockExpr})`;
|
blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block.isRoot && !ctx.preventRoot) {
|
if (block.isRoot && !ctx.preventRoot) {
|
||||||
@@ -424,78 +428,66 @@ export class CodeGenerator {
|
|||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
compileAST(ast: AST, ctx: Context) {
|
/**
|
||||||
|
* @returns the newly created block name, if any
|
||||||
|
*/
|
||||||
|
compileAST(ast: AST, ctx: Context): string | null {
|
||||||
switch (ast.type) {
|
switch (ast.type) {
|
||||||
case ASTType.Comment:
|
case ASTType.Comment:
|
||||||
this.compileComment(ast, ctx);
|
return this.compileComment(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.Text:
|
case ASTType.Text:
|
||||||
this.compileText(ast, ctx);
|
return this.compileText(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.DomNode:
|
case ASTType.DomNode:
|
||||||
this.compileTDomNode(ast, ctx);
|
return this.compileTDomNode(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TEsc:
|
case ASTType.TEsc:
|
||||||
this.compileTEsc(ast, ctx);
|
return this.compileTEsc(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TOut:
|
case ASTType.TOut:
|
||||||
this.compileTOut(ast, ctx);
|
return this.compileTOut(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TIf:
|
case ASTType.TIf:
|
||||||
this.compileTIf(ast, ctx);
|
return this.compileTIf(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TForEach:
|
case ASTType.TForEach:
|
||||||
this.compileTForeach(ast, ctx);
|
return this.compileTForeach(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TKey:
|
case ASTType.TKey:
|
||||||
this.compileTKey(ast, ctx);
|
return this.compileTKey(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.Multi:
|
case ASTType.Multi:
|
||||||
this.compileMulti(ast, ctx);
|
return this.compileMulti(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TCall:
|
case ASTType.TCall:
|
||||||
this.compileTCall(ast, ctx);
|
return this.compileTCall(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TCallBlock:
|
case ASTType.TCallBlock:
|
||||||
this.compileTCallBlock(ast, ctx);
|
return this.compileTCallBlock(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TSet:
|
case ASTType.TSet:
|
||||||
this.compileTSet(ast, ctx);
|
return this.compileTSet(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TComponent:
|
case ASTType.TComponent:
|
||||||
this.compileComponent(ast, ctx);
|
return this.compileComponent(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TDebug:
|
case ASTType.TDebug:
|
||||||
this.compileDebug(ast, ctx);
|
return this.compileDebug(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TLog:
|
case ASTType.TLog:
|
||||||
this.compileLog(ast, ctx);
|
return this.compileLog(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TSlot:
|
case ASTType.TSlot:
|
||||||
this.compileTSlot(ast, ctx);
|
return this.compileTSlot(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TTranslation:
|
case ASTType.TTranslation:
|
||||||
this.compileTTranslation(ast, ctx);
|
return this.compileTTranslation(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TPortal:
|
case ASTType.TPortal:
|
||||||
this.compileTPortal(ast, ctx);
|
return this.compileTPortal(ast, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileDebug(ast: ASTDebug, ctx: Context) {
|
compileDebug(ast: ASTDebug, ctx: Context): string | null {
|
||||||
this.addLine(`debugger;`);
|
this.addLine(`debugger;`);
|
||||||
if (ast.content) {
|
if (ast.content) {
|
||||||
this.compileAST(ast.content, ctx);
|
return this.compileAST(ast.content, ctx);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileLog(ast: ASTLog, ctx: Context) {
|
compileLog(ast: ASTLog, ctx: Context): string | null {
|
||||||
this.addLine(`console.log(${compileExpr(ast.expr)});`);
|
this.addLine(`console.log(${compileExpr(ast.expr)});`);
|
||||||
if (ast.content) {
|
if (ast.content) {
|
||||||
this.compileAST(ast.content, ctx);
|
return this.compileAST(ast.content, ctx);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
compileComment(ast: ASTComment, ctx: Context) {
|
compileComment(ast: ASTComment, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
const isNewBlock = !block || forceNewBlock;
|
const isNewBlock = !block || forceNewBlock;
|
||||||
if (isNewBlock) {
|
if (isNewBlock) {
|
||||||
@@ -508,9 +500,10 @@ export class CodeGenerator {
|
|||||||
const text = xmlDoc.createComment(ast.value);
|
const text = xmlDoc.createComment(ast.value);
|
||||||
block!.insert(text);
|
block!.insert(text);
|
||||||
}
|
}
|
||||||
|
return block!.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileText(ast: ASTText, ctx: Context) {
|
compileText(ast: ASTText, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
|
|
||||||
let value = ast.value;
|
let value = ast.value;
|
||||||
@@ -529,6 +522,7 @@ export class CodeGenerator {
|
|||||||
const createFn = ast.type === ASTType.Text ? xmlDoc.createTextNode : xmlDoc.createComment;
|
const createFn = ast.type === ASTType.Text ? xmlDoc.createTextNode : xmlDoc.createComment;
|
||||||
block.insert(createFn.call(xmlDoc, value));
|
block.insert(createFn.call(xmlDoc, value));
|
||||||
}
|
}
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateHandlerCode(rawEvent: string, handler: string): string {
|
generateHandlerCode(rawEvent: string, handler: string): string {
|
||||||
@@ -548,7 +542,7 @@ export class CodeGenerator {
|
|||||||
return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
|
return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTDomNode(ast: ASTDomNode, ctx: Context) {
|
compileTDomNode(ast: ASTDomNode, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
|
const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
|
||||||
let codeIdx = this.target.code.length;
|
let codeIdx = this.target.code.length;
|
||||||
@@ -735,9 +729,10 @@ export class CodeGenerator {
|
|||||||
this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return block!.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTEsc(ast: ASTTEsc, ctx: Context) {
|
compileTEsc(ast: ASTTEsc, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
let expr: string;
|
let expr: string;
|
||||||
if (ast.expr === "0") {
|
if (ast.expr === "0") {
|
||||||
@@ -758,9 +753,10 @@ export class CodeGenerator {
|
|||||||
const text = xmlDoc.createElement(`block-text-${idx}`);
|
const text = xmlDoc.createElement(`block-text-${idx}`);
|
||||||
block.insert(text);
|
block.insert(text);
|
||||||
}
|
}
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTOut(ast: ASTTOut, ctx: Context) {
|
compileTOut(ast: ASTTOut, ctx: Context): string {
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
if (block) {
|
if (block) {
|
||||||
this.insertAnchor(block);
|
this.insertAnchor(block);
|
||||||
@@ -782,6 +778,7 @@ export class CodeGenerator {
|
|||||||
blockStr = `safeOutput(${compileExpr(ast.expr)})`;
|
blockStr = `safeOutput(${compileExpr(ast.expr)})`;
|
||||||
}
|
}
|
||||||
this.insertBlock(blockStr, block, ctx);
|
this.insertBlock(blockStr, block, ctx);
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTIfBranch(content: AST, block: BlockDescription, ctx: Context) {
|
compileTIfBranch(content: AST, block: BlockDescription, ctx: Context) {
|
||||||
@@ -795,7 +792,7 @@ export class CodeGenerator {
|
|||||||
this.target.indentLevel--;
|
this.target.indentLevel--;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode) {
|
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
const codeIdx = this.target.code.length;
|
const codeIdx = this.target.code.length;
|
||||||
const isNewBlock = !block || (block.type !== "multi" && forceNewBlock);
|
const isNewBlock = !block || (block.type !== "multi" && forceNewBlock);
|
||||||
@@ -838,9 +835,10 @@ export class CodeGenerator {
|
|||||||
const args = block!.children.map((c) => c.varName).join(", ");
|
const args = block!.children.map((c) => c.varName).join(", ");
|
||||||
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
||||||
}
|
}
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTForeach(ast: ASTTForEach, ctx: Context) {
|
compileTForeach(ast: ASTTForEach, ctx: Context): string {
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
if (block) {
|
if (block) {
|
||||||
this.insertAnchor(block);
|
this.insertAnchor(block);
|
||||||
@@ -879,9 +877,9 @@ export class CodeGenerator {
|
|||||||
// Throw error on duplicate keys in dev mode
|
// Throw error on duplicate keys in dev mode
|
||||||
this.helpers.add("OwlError");
|
this.helpers.add("OwlError");
|
||||||
this.addLine(
|
this.addLine(
|
||||||
`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`
|
`if (keys${block.id}.has(String(key${this.target.loopLevel}))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`
|
||||||
);
|
);
|
||||||
this.addLine(`keys${block.id}.add(key${this.target.loopLevel});`);
|
this.addLine(`keys${block.id}.add(String(key${this.target.loopLevel}));`);
|
||||||
}
|
}
|
||||||
let id: string;
|
let id: string;
|
||||||
if (ast.memo) {
|
if (ast.memo) {
|
||||||
@@ -918,9 +916,10 @@ export class CodeGenerator {
|
|||||||
this.addLine(`ctx = ctx.__proto__;`);
|
this.addLine(`ctx = ctx.__proto__;`);
|
||||||
}
|
}
|
||||||
this.insertBlock("l", block, ctx);
|
this.insertBlock("l", block, ctx);
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTKey(ast: ASTTKey, ctx: Context) {
|
compileTKey(ast: ASTTKey, ctx: Context): string | null {
|
||||||
const tKeyExpr = generateId("tKey_");
|
const tKeyExpr = generateId("tKey_");
|
||||||
this.define(tKeyExpr, compileExpr(ast.expr));
|
this.define(tKeyExpr, compileExpr(ast.expr));
|
||||||
ctx = createContext(ctx, {
|
ctx = createContext(ctx, {
|
||||||
@@ -928,20 +927,22 @@ export class CodeGenerator {
|
|||||||
block: ctx.block,
|
block: ctx.block,
|
||||||
index: ctx.index,
|
index: ctx.index,
|
||||||
});
|
});
|
||||||
this.compileAST(ast.content, ctx);
|
return this.compileAST(ast.content, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileMulti(ast: ASTMulti, ctx: Context) {
|
compileMulti(ast: ASTMulti, ctx: Context): string | null {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
const isNewBlock = !block || forceNewBlock;
|
const isNewBlock = !block || forceNewBlock;
|
||||||
let codeIdx = this.target.code.length;
|
let codeIdx = this.target.code.length;
|
||||||
if (isNewBlock) {
|
if (isNewBlock) {
|
||||||
const n = ast.content.filter((c) => c.type !== ASTType.TSet).length;
|
const n = ast.content.filter((c) => c.type !== ASTType.TSet).length;
|
||||||
|
let result: string | null = null;
|
||||||
if (n <= 1) {
|
if (n <= 1) {
|
||||||
for (let child of ast.content) {
|
for (let child of ast.content) {
|
||||||
this.compileAST(child, ctx);
|
const blockName = this.compileAST(child, ctx);
|
||||||
|
result = result || blockName;
|
||||||
}
|
}
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
}
|
}
|
||||||
@@ -981,9 +982,10 @@ export class CodeGenerator {
|
|||||||
const args = block!.children.map((c) => c.varName).join(", ");
|
const args = block!.children.map((c) => c.varName).join(", ");
|
||||||
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
||||||
}
|
}
|
||||||
|
return block!.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTCall(ast: ASTTCall, ctx: Context) {
|
compileTCall(ast: ASTTCall, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
let ctxVar = ctx.ctxVar || "ctx";
|
let ctxVar = ctx.ctxVar || "ctx";
|
||||||
if (ast.context) {
|
if (ast.context) {
|
||||||
@@ -994,12 +996,11 @@ export class CodeGenerator {
|
|||||||
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
||||||
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
||||||
this.helpers.add("isBoundary");
|
this.helpers.add("isBoundary");
|
||||||
const nextId = BlockDescription.nextBlockId;
|
|
||||||
const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
|
const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
|
||||||
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
|
const bl = this.compileMulti({ type: ASTType.Multi, content: ast.body }, subCtx);
|
||||||
if (nextId !== BlockDescription.nextBlockId) {
|
if (bl) {
|
||||||
this.helpers.add("zero");
|
this.helpers.add("zero");
|
||||||
this.addLine(`${ctxVar}[zero] = b${nextId};`);
|
this.addLine(`${ctxVar}[zero] = ${bl};`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isDynamic = INTERP_REGEXP.test(ast.name);
|
const isDynamic = INTERP_REGEXP.test(ast.name);
|
||||||
@@ -1033,9 +1034,10 @@ export class CodeGenerator {
|
|||||||
if (ast.body && !ctx.isLast) {
|
if (ast.body && !ctx.isLast) {
|
||||||
this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
|
this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
|
||||||
}
|
}
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTCallBlock(ast: ASTTCallBlock, ctx: Context) {
|
compileTCallBlock(ast: ASTTCallBlock, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
if (block) {
|
if (block) {
|
||||||
if (!forceNewBlock) {
|
if (!forceNewBlock) {
|
||||||
@@ -1044,9 +1046,10 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(compileExpr(ast.name), block, { ...ctx, forceNewBlock: !block });
|
this.insertBlock(compileExpr(ast.name), block, { ...ctx, forceNewBlock: !block });
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTSet(ast: ASTTSet, ctx: Context) {
|
compileTSet(ast: ASTTSet, ctx: Context): null {
|
||||||
this.target.shouldProtectScope = true;
|
this.target.shouldProtectScope = true;
|
||||||
this.helpers.add("isBoundary").add("withDefault");
|
this.helpers.add("isBoundary").add("withDefault");
|
||||||
const expr = ast.value ? compileExpr(ast.value || "") : "null";
|
const expr = ast.value ? compileExpr(ast.value || "") : "null";
|
||||||
@@ -1054,7 +1057,8 @@ export class CodeGenerator {
|
|||||||
this.helpers.add("LazyValue");
|
this.helpers.add("LazyValue");
|
||||||
const bodyAst: AST = { type: ASTType.Multi, content: ast.body };
|
const bodyAst: AST = { type: ASTType.Multi, content: ast.body };
|
||||||
const name = this.compileInNewTarget("value", bodyAst, ctx);
|
const name = this.compileInNewTarget("value", bodyAst, ctx);
|
||||||
let value = `new LazyValue(${name}, ctx, this, node)`;
|
let key = this.target.currentKey(ctx);
|
||||||
|
let value = `new LazyValue(${name}, ctx, this, node, ${key})`;
|
||||||
value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
|
value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
|
||||||
this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
|
this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
|
||||||
} else {
|
} else {
|
||||||
@@ -1071,6 +1075,7 @@ export class CodeGenerator {
|
|||||||
this.helpers.add("setContextValue");
|
this.helpers.add("setContextValue");
|
||||||
this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
|
this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateComponentKey() {
|
generateComponentKey() {
|
||||||
@@ -1122,7 +1127,7 @@ export class CodeGenerator {
|
|||||||
return propString;
|
return propString;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileComponent(ast: ASTComponent, ctx: Context) {
|
compileComponent(ast: ASTComponent, ctx: Context): string {
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
// props
|
// props
|
||||||
const hasSlotsProp = "slots" in (ast.props || {});
|
const hasSlotsProp = "slots" in (ast.props || {});
|
||||||
@@ -1188,7 +1193,7 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.dev) {
|
if (this.dev) {
|
||||||
this.addLine(`helpers.validateProps(${expr}, ${propVar!}, node);`);
|
this.addLine(`helpers.validateProps(${expr}, ${propVar!}, this);`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
|
if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
|
||||||
@@ -1222,6 +1227,7 @@ export class CodeGenerator {
|
|||||||
|
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(blockExpr, block, ctx);
|
this.insertBlock(blockExpr, block, ctx);
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapWithEventCatcher(expr: string, on: EventHandlers): string {
|
wrapWithEventCatcher(expr: string, on: EventHandlers): string {
|
||||||
@@ -1240,7 +1246,7 @@ export class CodeGenerator {
|
|||||||
return `${name}(${expr}, [${handlers.join(",")}])`;
|
return `${name}(${expr}, [${handlers.join(",")}])`;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTSlot(ast: ASTSlot, ctx: Context) {
|
compileTSlot(ast: ASTSlot, ctx: Context): string {
|
||||||
this.helpers.add("callSlot");
|
this.helpers.add("callSlot");
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
let blockString: string;
|
let blockString: string;
|
||||||
@@ -1289,14 +1295,16 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTTranslation(ast: ASTTranslation, ctx: Context) {
|
compileTTranslation(ast: ASTTranslation, ctx: Context): string | null {
|
||||||
if (ast.content) {
|
if (ast.content) {
|
||||||
this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
|
return this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
compileTPortal(ast: ASTTPortal, ctx: Context) {
|
compileTPortal(ast: ASTTPortal, ctx: Context): string {
|
||||||
if (!this.staticDefs.find((d) => d.id === "Portal")) {
|
if (!this.staticDefs.find((d) => d.id === "Portal")) {
|
||||||
this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
|
this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
|
||||||
}
|
}
|
||||||
@@ -1323,5 +1331,6 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -781,8 +781,9 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
|
|
||||||
// default slot
|
// default slot
|
||||||
const defaultContent = parseChildNodes(clone, ctx);
|
const defaultContent = parseChildNodes(clone, ctx);
|
||||||
if (defaultContent) {
|
slots = slots || {};
|
||||||
slots = slots || {};
|
// t-set-slot="default" has priority over content
|
||||||
|
if (defaultContent && !slots.default) {
|
||||||
slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
|
slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -66,7 +66,7 @@ export class App<
|
|||||||
mount(target: HTMLElement, options?: MountOptions): Promise<Component<P, E> & InstanceType<T>> {
|
mount(target: HTMLElement, options?: MountOptions): Promise<Component<P, E> & InstanceType<T>> {
|
||||||
App.validateTarget(target);
|
App.validateTarget(target);
|
||||||
if (this.dev) {
|
if (this.dev) {
|
||||||
validateProps(this.Root, this.props, { app: this });
|
validateProps(this.Root, this.props, { __owl__: { 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);
|
||||||
|
|||||||
@@ -517,15 +517,12 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
|
|||||||
return this.el!;
|
return this.el!;
|
||||||
}
|
}
|
||||||
|
|
||||||
*nodes() {
|
moveBeforeDOMNode(node: Node | null) {
|
||||||
if (this.el) {
|
nodeInsertBefore.call(this.parentEl, this.el!, node);
|
||||||
yield this.el;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: Block | null, afterNode: Node | null) {
|
moveBeforeVNode(other: Block | null, afterNode: Node | null) {
|
||||||
const target = other ? other.el! : afterNode;
|
nodeInsertBefore.call(this.parentEl, this.el!, other ? other.el! : afterNode);
|
||||||
nodeInsertBefore.call(this.parentEl, this.el!, target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ 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;
|
||||||
|
|
||||||
@@ -43,17 +44,29 @@ 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;
|
||||||
for (let node of self.nodes()) {
|
let currentNode: any = self.child.firstNode();
|
||||||
if (node.contains(target)) {
|
const afterNode = self.afterNode;
|
||||||
|
while (currentNode !== afterNode) {
|
||||||
|
if (currentNode.contains(target)) {
|
||||||
return origFn.call(this, ev);
|
return origFn.call(this, ev);
|
||||||
}
|
}
|
||||||
|
currentNode = currentNode.nextSibling;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: VCatcher | null, afterNode: Node | null) {
|
moveBeforeDOMNode(node: Node | null) {
|
||||||
this.child.moveBefore(other ? other.child : null, afterNode);
|
this.child.moveBeforeDOMNode(node);
|
||||||
|
this.parentEl!.insertBefore(this.afterNode!, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveBeforeVNode(other: VCatcher | null, afterNode: Node | null) {
|
||||||
|
if (other) {
|
||||||
|
// check this with @ged-odoo for use in foreach
|
||||||
|
afterNode = other.firstNode() || afterNode;
|
||||||
|
}
|
||||||
|
this.child.moveBeforeVNode(other ? other.child : null, afterNode);
|
||||||
this.parentEl!.insertBefore(this.afterNode!, afterNode);
|
this.parentEl!.insertBefore(this.afterNode!, afterNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,10 +99,6 @@ 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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,14 +29,18 @@ class VHtml {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: VHtml | null, afterNode: Node | null) {
|
moveBeforeDOMNode(node: Node | null) {
|
||||||
const target = other ? other.content[0] : afterNode;
|
|
||||||
const parent = this.parentEl;
|
const parent = this.parentEl;
|
||||||
for (let elem of this.content) {
|
for (let elem of this.content) {
|
||||||
nodeInsertBefore.call(parent, elem, target);
|
nodeInsertBefore.call(parent, elem, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moveBeforeVNode(other: VHtml | null, afterNode: Node | null) {
|
||||||
|
const target = other ? other.content[0] : afterNode;
|
||||||
|
this.moveBeforeDOMNode(target);
|
||||||
|
}
|
||||||
|
|
||||||
patch(other: VHtml) {
|
patch(other: VHtml) {
|
||||||
if (this === other) {
|
if (this === other) {
|
||||||
return;
|
return;
|
||||||
@@ -78,12 +82,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,13 @@ export { createCatcher } from "./event_catcher";
|
|||||||
|
|
||||||
export interface VNode<T = any> {
|
export interface VNode<T = any> {
|
||||||
mount(parent: HTMLElement, afterNode: Node | null): void;
|
mount(parent: HTMLElement, afterNode: Node | null): void;
|
||||||
moveBefore(other: T | null, afterNode: Node | null): void;
|
moveBeforeDOMNode(node: Node | null): void;
|
||||||
|
moveBeforeVNode(other: T | null, afterNode: Node | null): void;
|
||||||
patch(other: T, withBeforeRemove: boolean): void;
|
patch(other: T, withBeforeRemove: boolean): void;
|
||||||
beforeRemove(): void;
|
beforeRemove(): void;
|
||||||
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;
|
||||||
|
|||||||
@@ -38,14 +38,22 @@ class VList {
|
|||||||
this.parentEl = parent;
|
this.parentEl = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: VList | null, afterNode: Node | null) {
|
moveBeforeDOMNode(node: Node | null) {
|
||||||
|
const children = this.children;
|
||||||
|
for (let i = 0, l = children.length; i < l; i++) {
|
||||||
|
children[i].moveBeforeDOMNode(node);
|
||||||
|
}
|
||||||
|
this.parentEl!.insertBefore(this.anchor!, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveBeforeVNode(other: VList | null, afterNode: Node | null) {
|
||||||
if (other) {
|
if (other) {
|
||||||
const next = other!.children[0];
|
const next = other!.children[0];
|
||||||
afterNode = (next ? next.firstNode() : other!.anchor) || null;
|
afterNode = (next ? next.firstNode() : other!.anchor) || null;
|
||||||
}
|
}
|
||||||
const children = this.children;
|
const children = this.children;
|
||||||
for (let i = 0, l = children.length; i < l; i++) {
|
for (let i = 0, l = children.length; i < l; i++) {
|
||||||
children[i].moveBefore(null, afterNode);
|
children[i].moveBeforeVNode(null, afterNode);
|
||||||
}
|
}
|
||||||
this.parentEl!.insertBefore(this.anchor!, afterNode);
|
this.parentEl!.insertBefore(this.anchor!, afterNode);
|
||||||
}
|
}
|
||||||
@@ -66,7 +74,7 @@ class VList {
|
|||||||
patch: cPatch,
|
patch: cPatch,
|
||||||
remove: cRemove,
|
remove: cRemove,
|
||||||
beforeRemove,
|
beforeRemove,
|
||||||
moveBefore: cMoveBefore,
|
moveBeforeVNode: cMoveBefore,
|
||||||
firstNode: cFirstNode,
|
firstNode: cFirstNode,
|
||||||
} = proto;
|
} = proto;
|
||||||
|
|
||||||
@@ -221,12 +229,6 @@ 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("");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,22 @@ export class VMulti {
|
|||||||
this.parentEl = parent;
|
this.parentEl = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: VMulti | null, afterNode: Node | null) {
|
moveBeforeDOMNode(node: Node | null) {
|
||||||
|
const children = this.children;
|
||||||
|
const parent = this.parentEl;
|
||||||
|
const anchors = this.anchors;
|
||||||
|
for (let i = 0, l = children.length; i < l; i++) {
|
||||||
|
let child = children[i];
|
||||||
|
if (child) {
|
||||||
|
child.moveBeforeDOMNode(node);
|
||||||
|
} else {
|
||||||
|
const anchor = anchors![i];
|
||||||
|
nodeInsertBefore.call(parent, anchor, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
moveBeforeVNode(other: VMulti | null, afterNode: Node | null) {
|
||||||
if (other) {
|
if (other) {
|
||||||
const next = other!.children[0];
|
const next = other!.children[0];
|
||||||
afterNode = (next ? next.firstNode() : other!.anchors![0]) || null;
|
afterNode = (next ? next.firstNode() : other!.anchors![0]) || null;
|
||||||
@@ -49,7 +64,7 @@ export class VMulti {
|
|||||||
for (let i = 0, l = children.length; i < l; i++) {
|
for (let i = 0, l = children.length; i < l; i++) {
|
||||||
let child = children[i];
|
let child = children[i];
|
||||||
if (child) {
|
if (child) {
|
||||||
child.moveBefore(null, afterNode);
|
child.moveBeforeVNode(null, afterNode);
|
||||||
} else {
|
} else {
|
||||||
const anchor = anchors![i];
|
const anchor = anchors![i];
|
||||||
nodeInsertBefore.call(parent, anchor, afterNode);
|
nodeInsertBefore.call(parent, anchor, afterNode);
|
||||||
@@ -124,14 +139,6 @@ 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("");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,12 @@ abstract class VSimpleNode {
|
|||||||
this.el = node;
|
this.el = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: VText | null, afterNode: Node | null) {
|
moveBeforeDOMNode(node: Node | null) {
|
||||||
const target = other ? other.el! : afterNode;
|
nodeInsertBefore.call(this.parentEl, this.el!, node);
|
||||||
nodeInsertBefore.call(this.parentEl, this.el!, target);
|
}
|
||||||
|
|
||||||
|
moveBeforeVNode(other: VText | null, afterNode: Node | null) {
|
||||||
|
nodeInsertBefore.call(this.parentEl, this.el!, other ? other.el! : afterNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeRemove() {}
|
beforeRemove() {}
|
||||||
@@ -38,12 +41,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,12 @@ class VToggler {
|
|||||||
this.child.mount(parent, afterNode);
|
this.child.mount(parent, afterNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: VToggler | null, afterNode: Node | null) {
|
moveBeforeDOMNode(node: Node | null) {
|
||||||
this.child.moveBefore(other ? other.child : null, afterNode);
|
this.child.moveBeforeDOMNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveBeforeVNode(other: VToggler | null, afterNode: Node | null) {
|
||||||
|
this.moveBeforeDOMNode((other && other.firstNode()) || afterNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
patch(other: VToggler, withBeforeRemove: boolean) {
|
patch(other: VToggler, withBeforeRemove: boolean) {
|
||||||
@@ -55,10 +59,6 @@ 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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,12 +296,6 @@ 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;
|
||||||
@@ -312,8 +306,12 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
|
|||||||
this.fiber = null;
|
this.fiber = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: ComponentNode | null, afterNode: Node | null) {
|
moveBeforeDOMNode(node: Node | null): void {
|
||||||
this.bdom!.moveBefore(other ? other.bdom : null, afterNode);
|
this.bdom!.moveBeforeDOMNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveBeforeVNode(other: ComponentNode<P, E> | null, afterNode: Node | null) {
|
||||||
|
this.bdom!.moveBeforeVNode(other ? other.bdom : null, afterNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
patch() {
|
patch() {
|
||||||
|
|||||||
@@ -127,39 +127,3 @@ 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,15 +40,7 @@ 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 {
|
export { useEffect, useEnv, useExternalListener, useRef, useChildSubEnv, useSubEnv } from "./hooks";
|
||||||
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,
|
||||||
|
|||||||
+36
-35
@@ -1,4 +1,4 @@
|
|||||||
import { onWillUnmount } from "./lifecycle_hooks";
|
import { onMounted, onWillUnmount } from "./lifecycle_hooks";
|
||||||
import { BDom, text, VNode } from "./blockdom";
|
import { BDom, text, VNode } from "./blockdom";
|
||||||
import { Component } from "./component";
|
import { Component } from "./component";
|
||||||
import { OwlError } from "./error_handling";
|
import { OwlError } from "./error_handling";
|
||||||
@@ -6,60 +6,51 @@ import { OwlError } from "./error_handling";
|
|||||||
const VText: any = text("").constructor;
|
const VText: any = text("").constructor;
|
||||||
|
|
||||||
class VPortal extends VText implements Partial<VNode<VPortal>> {
|
class VPortal extends VText implements Partial<VNode<VPortal>> {
|
||||||
// selector: string;
|
content: BDom | null;
|
||||||
realBDom: BDom | null;
|
selector: string;
|
||||||
target: HTMLElement | null = null;
|
target: HTMLElement | null = null;
|
||||||
|
|
||||||
constructor(selector: string, realBDom: BDom) {
|
constructor(selector: string, content: BDom) {
|
||||||
super("");
|
super("");
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.realBDom = realBDom;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
mount(parent: HTMLElement, anchor: ChildNode) {
|
mount(parent: HTMLElement, anchor: ChildNode) {
|
||||||
super.mount(parent, anchor);
|
super.mount(parent, anchor);
|
||||||
this.target = document.querySelector(this.selector) as any;
|
this.target = document.querySelector(this.selector) as any;
|
||||||
if (!this.target) {
|
if (this.target) {
|
||||||
let el: any = this.el;
|
this.content!.mount(this.target!, null);
|
||||||
while (el && el.parentElement instanceof HTMLElement) {
|
|
||||||
el = el.parentElement;
|
|
||||||
}
|
|
||||||
this.target = el && el.querySelector(this.selector);
|
|
||||||
if (!this.target) {
|
|
||||||
throw new OwlError("invalid portal target");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.realBDom!.mount(this.target!, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeRemove() {
|
beforeRemove() {
|
||||||
this.realBDom!.beforeRemove();
|
// this.target not being null means content is mounted
|
||||||
}
|
if (this.target) {
|
||||||
remove() {
|
this.content!.beforeRemove();
|
||||||
if (this.realBDom) {
|
this.content!.remove();
|
||||||
super.remove();
|
|
||||||
this.realBDom!.remove();
|
|
||||||
this.realBDom = null;
|
|
||||||
}
|
}
|
||||||
|
this.content = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
patch(other: VPortal) {
|
patch(other: VPortal) {
|
||||||
super.patch(other);
|
super.patch(other);
|
||||||
if (this.realBDom) {
|
if (this.content) {
|
||||||
this.realBDom.patch(other.realBDom!, true);
|
this.content.patch(other.content!, true);
|
||||||
} else {
|
} else {
|
||||||
this.realBDom = other.realBDom;
|
this.content = other.content;
|
||||||
this.realBDom!.mount(this.target!, null);
|
this.content!.mount(this.target!, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <t t-slot="default"/>
|
* kind of similar to <t t-slot="default"/>, but it wraps it around a VPortal
|
||||||
*/
|
*/
|
||||||
export function portalTemplate(app: any, bdom: any, helpers: any) {
|
export function portalTemplate(app: any, bdom: any, helpers: any) {
|
||||||
let { callSlot } = helpers;
|
let { callSlot } = helpers;
|
||||||
return function template(ctx: any, node: any, key = "") {
|
return function template(ctx: any, node: any, key = ""): any {
|
||||||
return callSlot(ctx, node, key, "default", false, null);
|
return new VPortal(ctx.props.target, callSlot(ctx, node, key, "default", false, null));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,13 +64,23 @@ export class Portal extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const node = this.__owl__;
|
const node: any = this.__owl__;
|
||||||
const renderFn = node.renderFn;
|
|
||||||
node.renderFn = () => new VPortal(this.props.target, renderFn());
|
onMounted(() => {
|
||||||
onWillUnmount(() => {
|
const portal: VPortal = node.bdom;
|
||||||
if (node.bdom) {
|
if (!portal.target) {
|
||||||
node.bdom.remove();
|
portal.target = document.querySelector(this.props.target);
|
||||||
|
if (portal.target) {
|
||||||
|
portal.content!.mount(portal.target, null);
|
||||||
|
} else {
|
||||||
|
throw new OwlError("invalid portal target");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onWillUnmount(() => {
|
||||||
|
const portal: VPortal = node.bdom;
|
||||||
|
portal.beforeRemove();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,15 +111,18 @@ class LazyValue {
|
|||||||
ctx: any;
|
ctx: any;
|
||||||
component: any;
|
component: any;
|
||||||
node: any;
|
node: any;
|
||||||
constructor(fn: any, ctx: any, component: any, node: any) {
|
key: any;
|
||||||
|
|
||||||
|
constructor(fn: any, ctx: any, component: any, node: any, key: any) {
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
this.ctx = capture(ctx);
|
this.ctx = capture(ctx);
|
||||||
this.component = component;
|
this.component = component;
|
||||||
this.node = node;
|
this.node = node;
|
||||||
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluate(): any {
|
evaluate(): any {
|
||||||
return this.fn.call(this.component, this.ctx, this.node);
|
return this.fn.call(this.component, this.ctx, this.node, this.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
@@ -207,11 +210,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, node?: any) {
|
export function validateProps<P>(name: string | ComponentConstructor<P>, props: P, comp?: any) {
|
||||||
const ComponentClass =
|
const ComponentClass =
|
||||||
typeof name !== "string"
|
typeof name !== "string"
|
||||||
? name
|
? name
|
||||||
: (node.component.constructor.components[name] as ComponentConstructor<P> | undefined);
|
: (comp.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 +224,7 @@ export function validateProps<P>(name: string | ComponentConstructor<P>, props:
|
|||||||
|
|
||||||
const schema = ComponentClass.props;
|
const schema = ComponentClass.props;
|
||||||
if (!schema) {
|
if (!schema) {
|
||||||
if (node.app.warnIfNoStaticProps) {
|
if (comp.__owl__.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;
|
||||||
|
|||||||
@@ -334,6 +334,57 @@ exports[`t-call (template calling) inherit context 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) nested t-calls with magic variable 0 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, zero } = helpers;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`grandchild\`);
|
||||||
|
const callTemplate_2 = app.getTemplate(\`child\`);
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<p>Some content...</p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1;
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1;
|
||||||
|
const b1 = block1();
|
||||||
|
ctx[zero] = b1;
|
||||||
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
|
ctx = ctx.__proto__;
|
||||||
|
ctx[zero] = b2;
|
||||||
|
return callTemplate_2.call(this, ctx, node, key + \`__2\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) nested t-calls with magic variable 0 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { zero } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\`grandchild\`);
|
||||||
|
const b3 = ctx[zero];
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) nested t-calls with magic variable 0 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { zero } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return ctx[zero];
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-call (template calling) recursive template, part 1 1`] = `
|
exports[`t-call (template calling) recursive template, part 1 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ exports[`t-esc t-esc is escaped 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`var\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`var\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
let txt1 = ctx['var'];
|
let txt1 = ctx['var'];
|
||||||
return block1([txt1]);
|
return block1([txt1]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ exports[`t-out t-out bdom 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`var\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`var\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
const b3 = safeOutput(ctx['var']);
|
const b3 = safeOutput(ctx['var']);
|
||||||
return block1([], [b3]);
|
return block1([], [b3]);
|
||||||
}
|
}
|
||||||
@@ -310,7 +310,7 @@ exports[`t-out t-out switch markup on bdom 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
let b3,b5;
|
let b3,b5;
|
||||||
ctx[\`bdom\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`bdom\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
if (ctx['hasBdom']) {
|
if (ctx['hasBdom']) {
|
||||||
const b4 = safeOutput(ctx['bdom']);
|
const b4 = safeOutput(ctx['bdom']);
|
||||||
b3 = block3([], [b4]);
|
b3 = block3([], [b4]);
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ exports[`t-set set from body literal (with t-if/t-else 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`value\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`value\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
return text(ctx['value']);
|
return text(ctx['value']);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -142,7 +142,7 @@ exports[`t-set set from body lookup 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`stuff\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`stuff\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
let txt1 = ctx['stuff'];
|
let txt1 = ctx['stuff'];
|
||||||
return block1([txt1]);
|
return block1([txt1]);
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ exports[`t-set t-set body is evaluated immediately 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
setContextValue(ctx, \\"v1\\", 'before');
|
setContextValue(ctx, \\"v1\\", 'before');
|
||||||
ctx[\`v2\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`v2\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
setContextValue(ctx, \\"v1\\", 'after');
|
setContextValue(ctx, \\"v1\\", 'after');
|
||||||
const b3 = safeOutput(ctx['v2']);
|
const b3 = safeOutput(ctx['v2']);
|
||||||
return block1([], [b3]);
|
return block1([], [b3]);
|
||||||
@@ -471,7 +471,7 @@ exports[`t-set t-set with content and sub t-esc 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`setvar\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`setvar\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
let txt1 = ctx['setvar'];
|
let txt1 = ctx['setvar'];
|
||||||
return block1([txt1]);
|
return block1([txt1]);
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,7 @@ exports[`t-set t-set with t-value (falsy) and body 1`] = `
|
|||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
setContextValue(ctx, \\"v3\\", false);
|
setContextValue(ctx, \\"v3\\", false);
|
||||||
setContextValue(ctx, \\"v1\\", 'before');
|
setContextValue(ctx, \\"v1\\", 'before');
|
||||||
ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, this, node));
|
ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, this, node, key));
|
||||||
setContextValue(ctx, \\"v1\\", 'after');
|
setContextValue(ctx, \\"v1\\", 'after');
|
||||||
setContextValue(ctx, \\"v3\\", true);
|
setContextValue(ctx, \\"v3\\", true);
|
||||||
const b3 = safeOutput(ctx['v2']);
|
const b3 = safeOutput(ctx['v2']);
|
||||||
@@ -525,7 +525,7 @@ exports[`t-set t-set with t-value (truthy) and body 1`] = `
|
|||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
setContextValue(ctx, \\"v3\\", 'Truthy');
|
setContextValue(ctx, \\"v3\\", 'Truthy');
|
||||||
setContextValue(ctx, \\"v1\\", 'before');
|
setContextValue(ctx, \\"v1\\", 'before');
|
||||||
ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, this, node));
|
ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, this, node, key));
|
||||||
setContextValue(ctx, \\"v1\\", 'after');
|
setContextValue(ctx, \\"v1\\", 'after');
|
||||||
setContextValue(ctx, \\"v3\\", false);
|
setContextValue(ctx, \\"v3\\", false);
|
||||||
const b3 = safeOutput(ctx['v2']);
|
const b3 = safeOutput(ctx['v2']);
|
||||||
@@ -638,7 +638,7 @@ exports[`t-set value priority (with non text body 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`value\`] = withDefault(1, new LazyValue(value1, ctx, this, node));
|
ctx[\`value\`] = withDefault(1, new LazyValue(value1, ctx, this, node, key));
|
||||||
let txt1 = ctx['value'];
|
let txt1 = ctx['value'];
|
||||||
return block1([txt1]);
|
return block1([txt1]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -479,4 +479,21 @@ describe("t-call (template calling)", () => {
|
|||||||
"<span>123lucas</span>"
|
"<span>123lucas</span>"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("nested t-calls with magic variable 0", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
context.addTemplate("grandchild", `grandchild<t t-out="0"/>`);
|
||||||
|
context.addTemplate("child", `<t t-out="0"/>`);
|
||||||
|
context.addTemplate(
|
||||||
|
"main",
|
||||||
|
`
|
||||||
|
<t t-call="child">
|
||||||
|
<t t-call="grandchild">
|
||||||
|
<p>Some content...</p>
|
||||||
|
</t>
|
||||||
|
</t>`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(context.renderToString("main")).toBe("grandchild<p>Some content...</p>");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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, node);
|
helpers.validateProps(\`SomeMispelledComponent\`, props1, this);
|
||||||
return comp1(props1, key + \`__1\`, node, this, null);
|
return comp1(props1, key + \`__1\`, node, this, null);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|||||||
@@ -405,69 +405,3 @@ 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, node);
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
return comp1(props1, key + \`__1\`, node, this, null);
|
return comp1(props1, key + \`__1\`, node, this, null);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ exports[`basics t-set with a body expression can be passed in props, and then t-
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`abc\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`abc\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
const b3 = comp1({val: ctx['abc']}, key + \`__1\`, node, this, null);
|
const b3 = comp1({val: ctx['abc']}, key + \`__1\`, node, this, null);
|
||||||
return block1([], [b3]);
|
return block1([], [b3]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, node);
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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,13 +673,47 @@ 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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
||||||
return block1([], [b2]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`props validation can validate through slots 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { markRaw } = helpers;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
const comp2 = app.createComponent(\`Wrapper\`, true, true, false, true);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
const props1 = {};
|
||||||
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
|
return comp1(props1, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const props2 = {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})};
|
||||||
|
helpers.validateProps(\`Wrapper\`, props2, this);
|
||||||
|
return comp2(props2, key + \`__2\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`props validation can validate through slots 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { callSlot } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return callSlot(ctx, node, key, 'default', false, {});
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`props validation default values are applied before validating props at update 1`] = `
|
exports[`props validation default values are applied before validating props at update 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -690,7 +724,7 @@ exports[`props validation default values are applied before validating props at
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const props1 = {p: ctx['state'].p};
|
const props1 = {p: ctx['state'].p};
|
||||||
helpers.validateProps(\`SubComp\`, props1, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
||||||
return block1([], [b2]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
@@ -721,7 +755,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +772,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, node);
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
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 +789,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, node);
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
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 +820,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +851,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +868,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +885,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +915,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +932,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +949,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +979,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +996,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1013,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1043,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1060,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1077,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1107,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1124,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1141,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1171,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1188,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1205,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1235,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1252,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1269,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1299,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1316,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1333,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1363,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1380,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1397,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1427,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1444,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1461,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1491,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1508,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1525,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1555,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1572,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1589,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1619,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
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 +1636,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, node);
|
helpers.validateProps(\`SubComp\`, props1, this);
|
||||||
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
||||||
return block1([], [b2]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2835,6 +2835,36 @@ exports[`slots t-set t-value in a slot 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`slots t-set-slot=default has priority over rest of the content 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, true, false, true);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`some other text\`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const ctx1 = capture(ctx);
|
||||||
|
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots t-set-slot=default has priority over rest of the content 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { callSlot } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return callSlot(ctx, node, key, 'default', false, {});
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`slots t-slot in recursive templates 1`] = `
|
exports[`slots t-slot in recursive templates 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -466,10 +466,10 @@ exports[`t-call t-call with t-call-context and subcomponent, in dev mode 2`] = `
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const props1 = {name: ctx['aab']};
|
const props1 = {name: ctx['aab']};
|
||||||
helpers.validateProps(\`Child\`, props1, node);
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
||||||
const props2 = {name: ctx['lpe']};
|
const props2 = {name: ctx['lpe']};
|
||||||
helpers.validateProps(\`Child\`, props2, node);
|
helpers.validateProps(\`Child\`, props2, this);
|
||||||
const b3 = comp2(props2, key + \`__2\`, node, this, null);
|
const b3 = comp2(props2, key + \`__2\`, node, this, null);
|
||||||
return multi([b2, b3]);
|
return multi([b2, b3]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ exports[`list of components crash on duplicate key in dev mode 1`] = `
|
|||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`item\`] = v_block1[i1];
|
ctx[\`item\`] = v_block1[i1];
|
||||||
const key1 = 'child';
|
const key1 = 'child';
|
||||||
if (keys1.has(key1)) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
|
if (keys1.has(String(key1))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
|
||||||
keys1.add(key1);
|
keys1.add(String(key1));
|
||||||
const props1 = {};
|
const props1 = {};
|
||||||
helpers.validateProps(\`Child\`, props1, node);
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
c_block1[i1] = withKey(comp1(props1, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block1[i1] = withKey(comp1(props1, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
}
|
}
|
||||||
return list(c_block1);
|
return list(c_block1);
|
||||||
@@ -75,6 +75,42 @@ exports[`list of components crash on duplicate key in dev mode 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`list of components crash when using object as keys that serialize to the same string 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, OwlError, withKey } = helpers;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([{},{}]);;
|
||||||
|
const keys1 = new Set();
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`item\`] = v_block1[i1];
|
||||||
|
const key1 = ctx['item'];
|
||||||
|
if (keys1.has(String(key1))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
|
||||||
|
keys1.add(String(key1));
|
||||||
|
const props1 = {};
|
||||||
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
|
c_block1[i1] = withKey(comp1(props1, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`list of components crash when using object as keys that serialize to the same string 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`list of components list of sub components inside other nodes 1`] = `
|
exports[`list of components list of sub components inside other nodes 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -113,6 +149,58 @@ exports[`list of components list of sub components inside other nodes 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`list of components order is correct when slots are not of same type 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, true, false, true);
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<div>A</div>\`);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
let b2;
|
||||||
|
if (!ctx['state'].active) {
|
||||||
|
b2 = block2();
|
||||||
|
}
|
||||||
|
return multi([b2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function slot2(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`B\`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function slot3(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`C\`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const ctx1 = capture(ctx);
|
||||||
|
return comp1({slots: markRaw({'a': {__render: slot1, __ctx: ctx1, active: !ctx['state'].active}, 'b': {__render: slot2, __ctx: ctx1, active: true}, 'c': {__render: slot3, __ctx: ctx1, active: ctx['state'].active}})}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`list of components order is correct when slots are not of same type 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, callSlot, withKey } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['slotNames']);;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`slotName\`] = v_block1[i1];
|
||||||
|
const key1 = ctx['slotName'];
|
||||||
|
const slot1 = (ctx['slotName']);
|
||||||
|
c_block1[i1] = withKey(toggler(slot1, callSlot(ctx, node, key1 + \`__1__\${key1}\`, slot1, true, {})), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`list of components reconciliation alg works for t-foreach in t-foreach 1`] = `
|
exports[`list of components reconciliation alg works for t-foreach in t-foreach 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`components in t-out simple list 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, isBoundary, withDefault, LazyValue, safeOutput, withKey } = helpers;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
|
||||||
|
function value1(ctx, node, key = \\"\\") {
|
||||||
|
return comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1,2]);;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`n\`] = v_block1[i1];
|
||||||
|
const key1 = ctx['n'];
|
||||||
|
ctx[\`blabla\`] = new LazyValue(value1, ctx, this, node, key1);
|
||||||
|
c_block1[i1] = withKey(safeOutput(ctx['blabla']), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`components in t-out simple list 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`child\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
@@ -59,7 +59,7 @@ exports[`t-set slots with a t-set with a component in body 1`] = `
|
|||||||
function slot1(ctx, node, key = \\"\\") {
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`v\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
const b3 = text(\` in slot \`);
|
const b3 = text(\` in slot \`);
|
||||||
const b4 = safeOutput(ctx['v']);
|
const b4 = safeOutput(ctx['v']);
|
||||||
return multi([b3, b4]);
|
return multi([b3, b4]);
|
||||||
@@ -114,7 +114,7 @@ exports[`t-set slots with an t-set with a component in body 1`] = `
|
|||||||
function slot1(ctx, node, key = \\"\\") {
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`v\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
const b5 = text(\` tea \`);
|
const b5 = text(\` tea \`);
|
||||||
const b6 = safeOutput(ctx['v']);
|
const b6 = safeOutput(ctx['v']);
|
||||||
return multi([b5, b6]);
|
return multi([b5, b6]);
|
||||||
@@ -169,7 +169,7 @@ exports[`t-set slots with an unused t-set with a component in body 1`] = `
|
|||||||
function slot1(ctx, node, key = \\"\\") {
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`v\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
return text(\` in slot \`);
|
return text(\` in slot \`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ exports[`t-set t-set with a component in body 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`v\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
const b3 = safeOutput(ctx['v']);
|
const b3 = safeOutput(ctx['v']);
|
||||||
return block1([], [b3]);
|
return block1([], [b3]);
|
||||||
}
|
}
|
||||||
@@ -377,7 +377,7 @@ exports[`t-set t-set with something in body 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1
|
ctx[isBoundary] = 1
|
||||||
ctx[\`v\`] = new LazyValue(value1, ctx, this, node);
|
ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
const b3 = safeOutput(ctx['v']);
|
const b3 = safeOutput(ctx['v']);
|
||||||
return block1([], [b3]);
|
return block1([], [b3]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import {
|
|||||||
xml,
|
xml,
|
||||||
OwlError,
|
OwlError,
|
||||||
} from "../../src/index";
|
} from "../../src/index";
|
||||||
import { useRoots } from "../../src/runtime/hooks";
|
|
||||||
import {
|
import {
|
||||||
elem,
|
elem,
|
||||||
logStep,
|
logStep,
|
||||||
@@ -519,7 +518,7 @@ describe("hooks", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("dependencies prevent effects from rerunning when unchanged", async () => {
|
test("dependencies prevent effects from rerunning when unchanged", async () => {
|
||||||
let steps: string[] = [];
|
let steps = [];
|
||||||
class MyComponent extends Component {
|
class MyComponent extends Component {
|
||||||
state = useState({
|
state = useState({
|
||||||
a: 0,
|
a: 0,
|
||||||
@@ -674,110 +673,3 @@ 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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -780,6 +780,32 @@ describe("props validation", () => {
|
|||||||
// we just check that it doesn't throw
|
// we just check that it doesn't throw
|
||||||
await expect(mount(Parent, fixture, { dev: true })).resolves.toEqual(expect.anything());
|
await expect(mount(Parent, fixture, { dev: true })).resolves.toEqual(expect.anything());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("can validate through slots", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static props = ["message"];
|
||||||
|
static template = xml`<div>hey</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Wrapper extends Component {
|
||||||
|
static template = xml`<t t-slot="default"/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static components = { Child, Wrapper };
|
||||||
|
static template = xml`<Wrapper><Child /></Wrapper>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = new App(Parent, { test: true });
|
||||||
|
let error: OwlError | undefined;
|
||||||
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
|
"Invalid props for component 'Child': 'message' is missing"
|
||||||
|
);
|
||||||
|
await mountProm;
|
||||||
|
expect(error!).toBeDefined();
|
||||||
|
expect(error!.message).toBe("Invalid props for component 'Child': 'message' is missing");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -45,6 +45,23 @@ describe("slots", () => {
|
|||||||
expect(fixture.innerHTML).toBe("some text");
|
expect(fixture.innerHTML).toBe("some text");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-set-slot=default has priority over rest of the content", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<t t-slot="default"/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`<Child>
|
||||||
|
some text
|
||||||
|
<t t-set-slot="default">some other text</t>
|
||||||
|
</Child>`;
|
||||||
|
static components = { Child };
|
||||||
|
}
|
||||||
|
await mount(Parent, fixture);
|
||||||
|
|
||||||
|
expect(fixture.innerHTML).toBe("some other text");
|
||||||
|
});
|
||||||
|
|
||||||
test("simple slot with slot scope", async () => {
|
test("simple slot with slot scope", async () => {
|
||||||
let child: any;
|
let child: any;
|
||||||
class Child extends Component {
|
class Child extends Component {
|
||||||
|
|||||||
@@ -331,4 +331,63 @@ describe("list of components", () => {
|
|||||||
console.info = consoleInfo;
|
console.info = consoleInfo;
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("crash when using object as keys that serialize to the same string", async () => {
|
||||||
|
const consoleInfo = console.info;
|
||||||
|
console.info = jest.fn();
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml``;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-foreach="[{}, {}]" t-as="item" t-key="item">
|
||||||
|
<Child/>
|
||||||
|
</t>
|
||||||
|
`;
|
||||||
|
static components = { Child };
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = new App(Parent, { test: true });
|
||||||
|
const mountProm = expect(app.mount(fixture)).rejects.toThrow(
|
||||||
|
"Got duplicate key in t-foreach: [object Object]"
|
||||||
|
);
|
||||||
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
|
"Got duplicate key in t-foreach: [object Object]"
|
||||||
|
);
|
||||||
|
await mountProm;
|
||||||
|
console.info = consoleInfo;
|
||||||
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("order is correct when slots are not of same type", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-slot="{{ slotName }}" t-foreach="slotNames" t-as="slotName" t-key="slotName"/>
|
||||||
|
`;
|
||||||
|
get slotNames() {
|
||||||
|
return Object.entries(this.props.slots)
|
||||||
|
.filter((entry: any) => entry[1].active)
|
||||||
|
.map((entry) => entry[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<Child>
|
||||||
|
<t t-set-slot="a" active="!state.active"><div t-if="!state.active">A</div></t>
|
||||||
|
<t t-set-slot="b" active="true">B</t>
|
||||||
|
<t t-set-slot="c" active="state.active">C</t>
|
||||||
|
</Child>
|
||||||
|
`;
|
||||||
|
static components = { Child };
|
||||||
|
state = useState({ active: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = await mount(Parent, fixture);
|
||||||
|
expect(fixture.textContent).toBe("AB");
|
||||||
|
parent.state.active = true;
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.textContent).toBe("BC");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { Component, mount, xml } from "../../src/index";
|
||||||
|
import { makeTestFixture, snapshotEverything } from "../helpers";
|
||||||
|
|
||||||
|
snapshotEverything();
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// t-out
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe("components in t-out", () => {
|
||||||
|
let fixture: HTMLElement;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = makeTestFixture();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("simple list", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`child`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-foreach="[1,2]" t-as="n" t-key="n">
|
||||||
|
<t t-set="blabla">
|
||||||
|
<Child />
|
||||||
|
</t>
|
||||||
|
<t t-out="blabla"/>
|
||||||
|
</t>`;
|
||||||
|
static components = { Child };
|
||||||
|
}
|
||||||
|
|
||||||
|
await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("childchild");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -155,6 +155,44 @@ exports[`Portal Add and remove portals with t-foreach inside div 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Portal Child and Portal 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
|
||||||
|
let block3 = createBlock(\`<div class=\\"portal\\"/>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
const b3 = block3();
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Portal Child and Portal 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const Portal = app.Portal;
|
||||||
|
const comp1 = app.createComponent(null, false, true, false, false);
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<span>child</span>\`);
|
||||||
|
let block3 = createBlock(\`<span>portal</span>\`);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
return block3();
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = block2();
|
||||||
|
const b4 = comp1({target: '.portal',slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal);
|
||||||
|
return multi([b2, b4]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Portal Portal composed with t-slot 1`] = `
|
exports[`Portal Portal composed with t-slot 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -515,6 +553,44 @@ exports[`Portal lifecycle hooks of portal sub component are properly called 2`]
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Portal portal and Child 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<div class=\\"portal\\"/>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = block2();
|
||||||
|
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Portal portal and Child 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const Portal = app.Portal;
|
||||||
|
const comp1 = app.createComponent(null, false, true, false, false);
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<span>child</span>\`);
|
||||||
|
let block3 = createBlock(\`<span>portal</span>\`);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
return block3();
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = block2();
|
||||||
|
const b4 = comp1({target: '.portal',slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal);
|
||||||
|
return multi([b2, b4]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Portal portal could have dynamically no content 1`] = `
|
exports[`Portal portal could have dynamically no content 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ describe("Portal", () => {
|
|||||||
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("invalid portal target");
|
expect(error!.message).toBe("invalid portal target");
|
||||||
expect(fixture.innerHTML).toBe(`<div></div>`);
|
expect(fixture.innerHTML).toBe(``);
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -874,6 +874,48 @@ describe("Portal", () => {
|
|||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe('<div id="outside"></div><div></div>');
|
expect(fixture.innerHTML).toBe('<div id="outside"></div><div></div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Child and Portal", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<span>child</span>
|
||||||
|
<t t-portal="'.portal'"><span>portal</span></t>`;
|
||||||
|
}
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t>
|
||||||
|
<Child/>
|
||||||
|
<div class="portal"></div>
|
||||||
|
</t>`;
|
||||||
|
|
||||||
|
static components = { Child };
|
||||||
|
}
|
||||||
|
await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe(
|
||||||
|
'<span>child</span><div class="portal"><span>portal</span></div>'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("portal and Child", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<span>child</span>
|
||||||
|
<t t-portal="'.portal'"><span>portal</span></t>`;
|
||||||
|
}
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t>
|
||||||
|
<div class="portal"></div>
|
||||||
|
<Child/>
|
||||||
|
</t>`;
|
||||||
|
|
||||||
|
static components = { Child };
|
||||||
|
}
|
||||||
|
await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe(
|
||||||
|
'<div class="portal"><span>portal</span></div><span>child</span>'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Portal: UI/UX", () => {
|
describe("Portal: UI/UX", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user