mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b2cfefd008 | |||
| 30d6994836 | |||
| ba1a270c93 | |||
| d546244fc3 | |||
| a1f22829c1 | |||
| 64bad25762 | |||
| 7ab34c5ca5 | |||
| 669fd622ec | |||
| ab72cdddde | |||
| 17fb33475c | |||
| ab29b896eb | |||
| d5ed25cd19 | |||
| c4f0f17b9b | |||
| d27455e9f2 | |||
| 6ef38676c4 | |||
| b51756f356 | |||
| cfdf7caa50 | |||
| a5a6a592c1 | |||
| d0d7482b0f | |||
| 8fe4c0c76e | |||
| c1afaeb92a | |||
| 3883cec079 |
@@ -124,5 +124,5 @@ npm install @odoo/owl
|
|||||||
|
|
||||||
If you want to use a simple `<script>` tag, the last release can be downloaded here:
|
If you want to use a simple `<script>` tag, the last release can be downloaded here:
|
||||||
|
|
||||||
- [owl-1.4.10](https://github.com/odoo/owl/releases/tag/v1.4.10)
|
- [owl](https://github.com/odoo/owl/releases/latest)
|
||||||
|
|
||||||
|
|||||||
@@ -770,10 +770,11 @@ For reference, here is the final code:
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>OWL Todo App</title>
|
<title>OWL Todo App</title>
|
||||||
<link rel="stylesheet" href="app.css" />
|
<link rel="stylesheet" href="app.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
<script src="owl.js"></script>
|
<script src="owl.js"></script>
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
</head>
|
</body>
|
||||||
<body></body>
|
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -234,7 +234,8 @@ are defined by a function instead of just the dependencies.
|
|||||||
|
|
||||||
The `useEffect` hook takes two function: the effect function and the dependency
|
The `useEffect` hook takes two function: the effect function and the dependency
|
||||||
function. The effect function perform some task and return (optionally) a cleanup
|
function. The effect function perform some task and return (optionally) a cleanup
|
||||||
function. The dependency function returns a list of dependencies. If any of these
|
function. The dependency function returns a list of dependencies, these dependencies
|
||||||
|
are passed as parameters in the effect function . If any of these
|
||||||
dependencies changes, then the current effect will be cleaned up and reexecuted.
|
dependencies changes, then the current effect will be cleaned up and reexecuted.
|
||||||
|
|
||||||
Here is an example without any dependencies:
|
Here is an example without any dependencies:
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odoo/owl",
|
"name": "@odoo/owl",
|
||||||
"version": "2.0.0-beta-17",
|
"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",
|
||||||
|
|||||||
+4
-23
@@ -1,28 +1,9 @@
|
|||||||
# 🦉 OWL Roadmap 🦉
|
# 🦉 OWL Roadmap 🦉
|
||||||
|
|
||||||
- Current version: 1.4.10
|
- Current version: 2.X
|
||||||
- Status: stable
|
- Status: stable
|
||||||
|
|
||||||
This roadmap is only an attempt at predicting Owl's future. Everything may
|
Owl is currently stable. No (large) improvements is expected in the near future.
|
||||||
change!
|
|
||||||
|
|
||||||
|
|
||||||
### 1.x
|
|
||||||
|
|
||||||
- add chrome and firefox devtools,
|
|
||||||
- fix every bugs,
|
|
||||||
- improve documentation,
|
|
||||||
- small backward compatible improvements.
|
|
||||||
|
|
||||||
### 2.x (2020? 2021? 2022?)
|
|
||||||
|
|
||||||
- stop support for `t-set` directive to define the content of a slot
|
|
||||||
|
|
||||||
Maybe:
|
|
||||||
|
|
||||||
- reimplement vdom to use *block* system, like Vue 3, which should make Owl
|
|
||||||
much faster
|
|
||||||
- refactor `QWeb` to use an intermediate representation (some kind of AST) to
|
|
||||||
allow additional optimisations.
|
|
||||||
|
|
||||||
|
|
||||||
|
Note that we intend to keep maintaining owl, and as such, improvements and/or
|
||||||
|
breaking changes may require a version bump in the future.
|
||||||
|
|||||||
@@ -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"];
|
||||||
@@ -232,6 +240,7 @@ export class CodeGenerator {
|
|||||||
translatableAttributes: string[] = TRANSLATABLE_ATTRS;
|
translatableAttributes: string[] = TRANSLATABLE_ATTRS;
|
||||||
ast: AST;
|
ast: AST;
|
||||||
staticDefs: { id: string; expr: string }[] = [];
|
staticDefs: { id: string; expr: string }[] = [];
|
||||||
|
slotNames: Set<String> = new Set();
|
||||||
helpers: Set<string> = new Set();
|
helpers: Set<string> = new Set();
|
||||||
|
|
||||||
constructor(ast: AST, options: CodeGenOptions) {
|
constructor(ast: AST, options: CodeGenOptions) {
|
||||||
@@ -364,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) {
|
||||||
@@ -423,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) {
|
||||||
@@ -507,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;
|
||||||
@@ -528,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 {
|
||||||
@@ -547,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;
|
||||||
@@ -734,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") {
|
||||||
@@ -757,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);
|
||||||
@@ -781,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) {
|
||||||
@@ -794,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);
|
||||||
@@ -837,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);
|
||||||
@@ -878,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) {
|
||||||
@@ -917,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, {
|
||||||
@@ -927,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);
|
||||||
}
|
}
|
||||||
@@ -980,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) {
|
||||||
@@ -993,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);
|
||||||
@@ -1032,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) {
|
||||||
@@ -1043,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";
|
||||||
@@ -1053,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 {
|
||||||
@@ -1070,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() {
|
||||||
@@ -1121,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 || {});
|
||||||
@@ -1187,7 +1193,7 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.dev) {
|
if (this.dev) {
|
||||||
this.addLine(`helpers.validateProps(${expr}, ${propVar!}, ctx);`);
|
this.addLine(`helpers.validateProps(${expr}, ${propVar!}, this);`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
|
if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
|
||||||
@@ -1221,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 {
|
||||||
@@ -1239,34 +1246,43 @@ 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;
|
||||||
let slotName;
|
let slotName;
|
||||||
let dynamic = false;
|
let dynamic = false;
|
||||||
|
let isMultiple = false;
|
||||||
if (ast.name.match(INTERP_REGEXP)) {
|
if (ast.name.match(INTERP_REGEXP)) {
|
||||||
dynamic = true;
|
dynamic = true;
|
||||||
|
isMultiple = true;
|
||||||
slotName = interpolate(ast.name);
|
slotName = interpolate(ast.name);
|
||||||
} else {
|
} else {
|
||||||
slotName = "'" + ast.name + "'";
|
slotName = "'" + ast.name + "'";
|
||||||
|
isMultiple = isMultiple || this.slotNames.has(ast.name);
|
||||||
|
this.slotNames.add(ast.name);
|
||||||
}
|
}
|
||||||
const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
|
const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
|
||||||
if (ast.attrs) {
|
if (ast.attrs) {
|
||||||
delete ast.attrs["t-props"];
|
delete ast.attrs["t-props"];
|
||||||
}
|
}
|
||||||
|
let key = this.target.loopLevel ? `key${this.target.loopLevel}` : "key";
|
||||||
|
if (isMultiple) {
|
||||||
|
key = `${key} + \`${this.generateComponentKey()}\``;
|
||||||
|
}
|
||||||
|
|
||||||
const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
|
const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
|
||||||
const scope = this.getPropString(props, dynProps);
|
const scope = this.getPropString(props, dynProps);
|
||||||
if (ast.defaultContent) {
|
if (ast.defaultContent) {
|
||||||
const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
|
const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
|
||||||
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope}, ${name})`;
|
blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name})`;
|
||||||
} else {
|
} else {
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
let name = generateId("slot");
|
let name = generateId("slot");
|
||||||
this.define(name, slotName);
|
this.define(name, slotName);
|
||||||
blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}, ${dynamic}, ${scope}))`;
|
blockString = `toggler(${name}, callSlot(ctx, node, ${key}, ${name}, ${dynamic}, ${scope}))`;
|
||||||
} else {
|
} else {
|
||||||
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope})`;
|
blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// event handling
|
// event handling
|
||||||
@@ -1279,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` });
|
||||||
}
|
}
|
||||||
@@ -1313,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 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -6,6 +6,7 @@ import { Scheduler } from "./scheduler";
|
|||||||
import { validateProps } from "./template_helpers";
|
import { validateProps } from "./template_helpers";
|
||||||
import { TemplateSet, TemplateSetConfig } from "./template_set";
|
import { TemplateSet, TemplateSetConfig } from "./template_set";
|
||||||
import { validateTarget } from "./utils";
|
import { validateTarget } from "./utils";
|
||||||
|
import { handleError } from "./error_handling";
|
||||||
|
|
||||||
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
|
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
|
||||||
|
|
||||||
@@ -94,9 +95,7 @@ export class App<
|
|||||||
nodeErrorHandlers.set(node, handlers);
|
nodeErrorHandlers.set(node, handlers);
|
||||||
}
|
}
|
||||||
handlers.unshift((e) => {
|
handlers.unshift((e) => {
|
||||||
if (isResolved) {
|
if (!isResolved) {
|
||||||
console.error(e);
|
|
||||||
} else {
|
|
||||||
reject(e);
|
reject(e);
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -169,6 +168,10 @@ export class App<
|
|||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleError(...args: Parameters<typeof handleError>) {
|
||||||
|
return handleError(...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function mount<
|
export async function mount<
|
||||||
|
|||||||
@@ -157,6 +157,15 @@ function buildTree(
|
|||||||
: document.createElement(tagName);
|
: document.createElement(tagName);
|
||||||
}
|
}
|
||||||
if (el instanceof Element) {
|
if (el instanceof Element) {
|
||||||
|
if (!domParentTree) {
|
||||||
|
// some html elements may have side effects when setting their attributes.
|
||||||
|
// For example, setting the src attribute of an <img/> will trigger a
|
||||||
|
// request to get the corresponding image. This is something that we
|
||||||
|
// don't want at compile time. We avoid that by putting the content of
|
||||||
|
// the block in a <template/> element
|
||||||
|
const fragment = document.createElement("template").content;
|
||||||
|
fragment.appendChild(el);
|
||||||
|
}
|
||||||
for (let i = 0; i < attrs.length; i++) {
|
for (let i = 0; i < attrs.length; i++) {
|
||||||
const attrName = attrs[i].name;
|
const attrName = attrs[i].name;
|
||||||
const attrValue = attrs[i].value;
|
const attrValue = attrs[i].value;
|
||||||
@@ -508,9 +517,12 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
|
|||||||
return this.el!;
|
return this.el!;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveBefore(other: Block | 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: Block | null, afterNode: Node | null) {
|
||||||
|
nodeInsertBefore.call(this.parentEl, this.el!, other ? other.el! : afterNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
|
|||||||
@@ -56,8 +56,17 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ function createElementHandler(evName: string, capture: boolean = false): EventHa
|
|||||||
}
|
}
|
||||||
|
|
||||||
function listener(ev: Event) {
|
function listener(ev: Event) {
|
||||||
const currentTarget = ev.currentTarget;
|
const currentTarget = ev.currentTarget as HTMLElement;
|
||||||
if (!currentTarget || !document.contains(currentTarget as HTMLElement)) return;
|
if (!currentTarget || !currentTarget.ownerDocument.contains(currentTarget)) return;
|
||||||
const data = (currentTarget as any)[eventKey];
|
const data = (currentTarget as any)[eventKey];
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
config.mainEventHandler(data, ev, currentTarget);
|
config.mainEventHandler(data, ev, currentTarget);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ 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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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() {}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { App, Env } from "./app";
|
import type { App, Env } from "./app";
|
||||||
import { BDom, VNode } from "./blockdom";
|
import { BDom, VNode } from "./blockdom";
|
||||||
import { Component, ComponentConstructor, Props } from "./component";
|
import { Component, ComponentConstructor, Props } from "./component";
|
||||||
import { fibersInError, handleError, OwlError } from "./error_handling";
|
import { fibersInError, OwlError } from "./error_handling";
|
||||||
import { Fiber, makeChildFiber, makeRootFiber, MountFiber, MountOptions } from "./fibers";
|
import { Fiber, makeChildFiber, makeRootFiber, MountFiber, MountOptions } from "./fibers";
|
||||||
import {
|
import {
|
||||||
clearReactivesForCallback,
|
clearReactivesForCallback,
|
||||||
@@ -141,7 +141,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
|
|||||||
try {
|
try {
|
||||||
await Promise.all(this.willStart.map((f) => f.call(component)));
|
await Promise.all(this.willStart.map((f) => f.call(component)));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ node: this, error: e });
|
this.app.handleError({ node: this, error: e });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.status === STATUS.NEW && this.fiber === fiber) {
|
if (this.status === STATUS.NEW && this.fiber === fiber) {
|
||||||
@@ -219,7 +219,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
|
|||||||
cb.call(component);
|
cb.call(component);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ error: e, node: this });
|
this.app.handleError({ error: e, node: this });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.status = STATUS.DESTROYED;
|
this.status = STATUS.DESTROYED;
|
||||||
@@ -306,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() {
|
||||||
|
|||||||
@@ -71,5 +71,6 @@ export function handleError(params: ErrorParams) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { BDom, mount } from "./blockdom";
|
import { BDom, mount } from "./blockdom";
|
||||||
import type { ComponentNode } from "./component_node";
|
import type { ComponentNode } from "./component_node";
|
||||||
import { fibersInError, handleError, OwlError } from "./error_handling";
|
import { fibersInError, OwlError } from "./error_handling";
|
||||||
import { STATUS } from "./status";
|
import { STATUS } from "./status";
|
||||||
|
|
||||||
export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber {
|
export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber {
|
||||||
@@ -130,7 +130,7 @@ export class Fiber {
|
|||||||
(this.bdom as any) = true;
|
(this.bdom as any) = true;
|
||||||
this.bdom = node.renderFn();
|
this.bdom = node.renderFn();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ node, error: e });
|
node.app.handleError({ node, error: e });
|
||||||
}
|
}
|
||||||
root.setCounter(root.counter - 1);
|
root.setCounter(root.counter - 1);
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ export class RootFiber extends Fiber {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.locked = false;
|
this.locked = false;
|
||||||
handleError({ fiber: current || this, error: e });
|
node.app.handleError({ fiber: current || this, error: e });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ export class MountFiber extends RootFiber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ fiber: current as Fiber, error: e });
|
this.node.app.handleError({ fiber: current as Fiber, error: e });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+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, parent?: 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
|
||||||
: (parent.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 (parent.__owl__.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, ctx);
|
helpers.validateProps(\`SomeMispelledComponent\`, props1, this);
|
||||||
return comp1(props1, key + \`__1\`, node, this, null);
|
return comp1(props1, key + \`__1\`, node, this, null);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|||||||
@@ -58,6 +58,20 @@ exports[`event handling handler receive the event as argument 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`event handling handler works when app is mounted in an iframe 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<span block-handler-0=\\"click\\">click me</span>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let hdlr1 = [ctx['inc'], ctx];
|
||||||
|
return block1([hdlr1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`event handling input blur event is not called if component is destroyed 1`] = `
|
exports[`event handling input blur event is not called if component is destroyed 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -704,7 +704,7 @@ exports[`lifecycle hooks timeout in onWillUpdateProps emits a warning 1`] = `
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const props1 = {prop: ctx['state'].prop};
|
const props1 = {prop: ctx['state'].prop};
|
||||||
helpers.validateProps(\`Child\`, props1, ctx);
|
helpers.validateProps(\`Child\`, props1, 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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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, ctx);
|
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]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -604,6 +604,64 @@ exports[`slots default slot work with text nodes 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`slots dynamic slot in multiple locations 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { capture, markRaw } = helpers;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
const comp2 = app.createComponent(\`Slotter\`, true, true, false, false);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\`hello \`);
|
||||||
|
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const ctx1 = capture(ctx);
|
||||||
|
return comp2({location: ctx['state'].location,slots: markRaw({'coffee': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots dynamic slot in multiple locations 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { callSlot } = helpers;
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<p><block-child-0/></p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let b2,b4;
|
||||||
|
if (ctx['props'].location===1) {
|
||||||
|
const slot1 = ('coffee');
|
||||||
|
const b3 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {}));
|
||||||
|
b2 = block2([], [b3]);
|
||||||
|
}
|
||||||
|
if (ctx['props'].location===2) {
|
||||||
|
const slot2 = ('coffee');
|
||||||
|
b4 = toggler(slot2, callSlot(ctx, node, key + \`__2\`, slot2, true, {}));
|
||||||
|
}
|
||||||
|
return multi([b2, b4]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots dynamic slot in multiple locations 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div>child</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`slots dynamic t-slot call 1`] = `
|
exports[`slots dynamic t-slot call 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -645,7 +703,7 @@ exports[`slots dynamic t-slot call 2`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
let hdlr1 = [ctx['toggle'], ctx];
|
let hdlr1 = [ctx['toggle'], ctx];
|
||||||
const slot1 = (ctx['current'].slot);
|
const slot1 = (ctx['current'].slot);
|
||||||
const b2 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {}));
|
const b2 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {}));
|
||||||
return block1([hdlr1], [b2]);
|
return block1([hdlr1], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -695,7 +753,7 @@ exports[`slots dynamic t-slot call with default 2`] = `
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
let hdlr1 = [ctx['toggle'], ctx];
|
let hdlr1 = [ctx['toggle'], ctx];
|
||||||
const b3 = callSlot(ctx, node, key, (ctx['current'].slot), true, {}, defaultContent1);
|
const b3 = callSlot(ctx, node, key + \`__1\`, (ctx['current'].slot), true, {}, defaultContent1);
|
||||||
return block1([hdlr1], [b3]);
|
return block1([hdlr1], [b3]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -726,7 +784,7 @@ exports[`slots fun: two calls to the same slot 2`] = `
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = callSlot(ctx, node, key, 'default', false, {});
|
const b2 = callSlot(ctx, node, key, 'default', false, {});
|
||||||
const b3 = callSlot(ctx, node, key, 'default', false, {});
|
const b3 = callSlot(ctx, node, key + \`__1\`, 'default', false, {});
|
||||||
return multi([b2, b3]);
|
return multi([b2, b3]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -1527,7 +1585,7 @@ exports[`slots simple dynamic slot with slot scope 2`] = `
|
|||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const slot1 = ('slotName');
|
const slot1 = ('slotName');
|
||||||
const b2 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {bool: ctx['state'].bool}));
|
const b2 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {bool: ctx['state'].bool}));
|
||||||
return block1([], [b2]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -1854,7 +1912,7 @@ exports[`slots slot content has different key from other content -- dynamic slot
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = comp1({parent: 'SlotDisplay'}, key + \`__1\`, node, this, null);
|
const b2 = comp1({parent: 'SlotDisplay'}, key + \`__1\`, node, this, null);
|
||||||
const slot1 = (ctx['slotName']);
|
const slot1 = (ctx['slotName']);
|
||||||
const b3 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {}));
|
const b3 = toggler(slot1, callSlot(ctx, node, key + \`__2\`, slot1, true, {}));
|
||||||
return multi([b2, b3]);
|
return multi([b2, b3]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -1995,6 +2053,118 @@ exports[`slots slot content is bound to caller 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in multiple locations 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { markRaw } = helpers;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
const comp2 = app.createComponent(\`Slotter\`, true, true, false, false);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\` hello \`);
|
||||||
|
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return comp2({location: ctx['state'].location,slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in multiple locations 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { callSlot } = helpers;
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<p><block-child-0/></p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let b2,b4;
|
||||||
|
if (ctx['props'].location===1) {
|
||||||
|
const b3 = callSlot(ctx, node, key, 'default', false, {});
|
||||||
|
b2 = block2([], [b3]);
|
||||||
|
}
|
||||||
|
if (ctx['props'].location===2) {
|
||||||
|
b4 = callSlot(ctx, node, key + \`__1\`, 'default', false, {});
|
||||||
|
}
|
||||||
|
return multi([b2, b4]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in multiple locations 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div>child</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in t-foreach locations 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { markRaw } = helpers;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
|
||||||
|
const comp2 = app.createComponent(\`Slotter\`, true, true, false, false);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\` hello \`);
|
||||||
|
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return comp2({list: ctx['state'].list,slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in t-foreach locations 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, callSlot, withKey } = helpers;
|
||||||
|
|
||||||
|
let block2 = createBlock(\`<p><block-text-0/><block-child-0/></p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['props'].list);;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`elem\`] = v_block1[i1];
|
||||||
|
ctx[\`elem_index\`] = i1;
|
||||||
|
const key1 = ctx['elem_index'];
|
||||||
|
let txt1 = ctx['elem'];
|
||||||
|
const b3 = callSlot(ctx, node, key1, 'default', false, {});
|
||||||
|
c_block1[i1] = withKey(block2([txt1], [b3]), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots slot in t-foreach locations 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div>child</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`slots slot preserves properly parented relationship 1`] = `
|
exports[`slots slot preserves properly parented relationship 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -2665,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
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -444,6 +444,51 @@ exports[`t-call t-call with t-call-context and subcomponent 3`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`someTemplate\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let ctx1 = ctx['subctx'];
|
||||||
|
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, false);
|
||||||
|
const comp2 = app.createComponent(\`Child\`, true, false, false, false);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const props1 = {name: ctx['aab']};
|
||||||
|
helpers.validateProps(\`Child\`, props1, this);
|
||||||
|
const b2 = comp1(props1, key + \`__1\`, node, this, null);
|
||||||
|
const props2 = {name: ctx['lpe']};
|
||||||
|
helpers.validateProps(\`Child\`, props2, this);
|
||||||
|
const b3 = comp2(props2, key + \`__2\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\`child\`);
|
||||||
|
const b3 = text(ctx['props'].name);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-call t-call with t-call-context, simple use 1`] = `
|
exports[`t-call t-call with t-call-context, simple use 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -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, ctx);
|
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]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import { App, Component, mount, status, toRaw, useState, xml } from "../../src";
|
import { App, Component, mount, status, toRaw, useState, xml } from "../../src";
|
||||||
import { elem, makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
|
import {
|
||||||
|
elem,
|
||||||
|
makeTestFixture,
|
||||||
|
nextAppError,
|
||||||
|
nextTick,
|
||||||
|
snapshotEverything,
|
||||||
|
useLogLifecycle,
|
||||||
|
} from "../helpers";
|
||||||
import { markup } from "../../src/runtime/utils";
|
import { markup } from "../../src/runtime/utils";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
@@ -208,14 +215,14 @@ describe("basics", () => {
|
|||||||
static template = xml`<div/>`;
|
static template = xml`<div/>`;
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
const prom = mount(Test, fixture);
|
const app = new App(Test);
|
||||||
|
const prom = app.mount(fixture);
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
fixture.remove();
|
fixture.remove();
|
||||||
try {
|
prom.catch((e: Error) => (error = e));
|
||||||
await prom;
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
} catch (e) {
|
"Cannot mount a component on a detached dom node"
|
||||||
error = e as Error;
|
);
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Cannot mount a component on a detached dom node");
|
expect(error!.message).toBe("Cannot mount a component on a detached dom node");
|
||||||
expect(console.warn).toBeCalledTimes(1);
|
expect(console.warn).toBeCalledTimes(1);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, mount, onWillDestroy } from "../../src";
|
import { App, Component, mount, onWillDestroy } from "../../src";
|
||||||
import {
|
import {
|
||||||
onError,
|
onError,
|
||||||
onMounted,
|
onMounted,
|
||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
nextMicroTick,
|
nextMicroTick,
|
||||||
snapshotEverything,
|
snapshotEverything,
|
||||||
useLogLifecycle,
|
useLogLifecycle,
|
||||||
|
nextAppError,
|
||||||
} from "../helpers";
|
} from "../helpers";
|
||||||
import { OwlError } from "../../src/runtime/error_handling";
|
import { OwlError } from "../../src/runtime/error_handling";
|
||||||
|
|
||||||
@@ -59,9 +60,10 @@ describe("basics", () => {
|
|||||||
parent.state.flag = true;
|
parent.state.flag = true;
|
||||||
|
|
||||||
parent.render();
|
parent.render();
|
||||||
await nextTick();
|
await expect(nextAppError(parent.__owl__.app)).resolves.toThrow(
|
||||||
|
"An error occured in the owl lifecycle"
|
||||||
|
);
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
expect(mockConsoleError).toBeCalledTimes(1);
|
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,12 +73,13 @@ describe("basics", () => {
|
|||||||
static template = xml`<SomeMispelledComponent />`;
|
static template = xml`<SomeMispelledComponent />`;
|
||||||
static components = { SomeComponent };
|
static components = { SomeComponent };
|
||||||
}
|
}
|
||||||
|
const app = new App(Parent);
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(Parent, fixture);
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
} catch (e) {
|
'Cannot find the definition of component "SomeMispelledComponent"'
|
||||||
error = e as Error;
|
);
|
||||||
}
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
|
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
|
||||||
expect(console.error).toBeCalledTimes(0);
|
expect(console.error).toBeCalledTimes(0);
|
||||||
@@ -90,12 +93,13 @@ describe("basics", () => {
|
|||||||
static template = xml`<SomeMispelledComponent />`;
|
static template = xml`<SomeMispelledComponent />`;
|
||||||
static components = { SomeComponent };
|
static components = { SomeComponent };
|
||||||
}
|
}
|
||||||
|
const app = new App(Parent, { test: true });
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(Parent, fixture, { test: true });
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
} catch (e) {
|
'Cannot find the definition of component "SomeMispelledComponent"'
|
||||||
error = e as Error;
|
);
|
||||||
}
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
|
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
|
||||||
expect(console.error).toBeCalledTimes(0);
|
expect(console.error).toBeCalledTimes(0);
|
||||||
@@ -109,13 +113,13 @@ describe("basics", () => {
|
|||||||
static template = xml`<SomeComponent />`;
|
static template = xml`<SomeComponent />`;
|
||||||
static components = { SomeComponent: notAComponentConstructor };
|
static components = { SomeComponent: notAComponentConstructor };
|
||||||
}
|
}
|
||||||
|
const app = new App(Parent as typeof Component);
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
// @ts-expect-error
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
await mount(Parent, fixture);
|
'"SomeComponent" is not a Component. It must inherit from the Component class'
|
||||||
} catch (e) {
|
);
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
'"SomeComponent" is not a Component. It must inherit from the Component class'
|
'"SomeComponent" is not a Component. It must inherit from the Component class'
|
||||||
@@ -156,16 +160,15 @@ describe("basics", () => {
|
|||||||
describe("errors and promises", () => {
|
describe("errors and promises", () => {
|
||||||
test("a rendering error will reject the mount promise", async () => {
|
test("a rendering error will reject the mount promise", async () => {
|
||||||
// we do not catch error in willPatch anymore
|
// we do not catch error in willPatch anymore
|
||||||
class App extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div><t t-esc="this.will.crash"/></div>`;
|
static template = xml`<div><t t-esc="this.will.crash"/></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const app = new App(Root);
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(App, fixture);
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as OwlError;
|
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
const regexp =
|
const regexp =
|
||||||
@@ -176,7 +179,7 @@ describe("errors and promises", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("an error in mounted call will reject the mount promise", async () => {
|
test("an error in mounted call will reject the mount promise", async () => {
|
||||||
class App extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div>abc</div>`;
|
static template = xml`<div>abc</div>`;
|
||||||
setup() {
|
setup() {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -185,12 +188,11 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const app = new App(Root);
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(App, fixture);
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as OwlError;
|
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
expect(error!.cause.message).toBe("boom");
|
expect(error!.cause.message).toBe("boom");
|
||||||
@@ -200,7 +202,7 @@ describe("errors and promises", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("an error in onMounted callback will have the component's setup in its stack trace", async () => {
|
test("an error in onMounted callback will have the component's setup in its stack trace", async () => {
|
||||||
class App extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div>abc</div>`;
|
static template = xml`<div>abc</div>`;
|
||||||
setup() {
|
setup() {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -209,14 +211,13 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: Error;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(App, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.stack).toContain("App.setup");
|
expect(error!.stack).toContain("Root.setup");
|
||||||
expect(error!.stack).toContain("error_handling.test.ts");
|
expect(error!.stack).toContain("error_handling.test.ts");
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
expect(mockConsoleError).toBeCalledTimes(0);
|
expect(mockConsoleError).toBeCalledTimes(0);
|
||||||
@@ -224,7 +225,7 @@ describe("errors and promises", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("errors in onWillRender/onRender aren't wrapped more than once", async () => {
|
test("errors in onWillRender/onRender aren't wrapped more than once", async () => {
|
||||||
class App extends Component {
|
class Root extends Component {
|
||||||
static template = xml`<div>abc</div>`;
|
static template = xml`<div>abc</div>`;
|
||||||
setup() {
|
setup() {
|
||||||
onWillRender(() => {
|
onWillRender(() => {
|
||||||
@@ -236,12 +237,11 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: Error;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(App, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillRender");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`The following error occurred in onWillRender: "boom in onWillRender"`
|
`The following error occurred in onWillRender: "boom in onWillRender"`
|
||||||
@@ -278,12 +278,11 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: any;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
|
||||||
error = e;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`The following error occurred in onWillStart: "boom in onWillStart"`
|
`The following error occurred in onWillStart: "boom in onWillStart"`
|
||||||
@@ -342,17 +341,16 @@ describe("errors and promises", () => {
|
|||||||
class Child extends Component {
|
class Child extends Component {
|
||||||
static template = xml`<div><t t-esc="this.will.crash"/></div>`;
|
static template = xml`<div><t t-esc="this.will.crash"/></div>`;
|
||||||
}
|
}
|
||||||
class App extends Component {
|
class Parent extends Component {
|
||||||
static template = xml`<div><Child/></div>`;
|
static template = xml`<div><Child/></div>`;
|
||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const app = new App(Parent);
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(App, fixture);
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as OwlError;
|
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
const regexp =
|
const regexp =
|
||||||
@@ -394,12 +392,11 @@ describe("errors and promises", () => {
|
|||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const app = new App(Parent);
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(Parent, fixture);
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as OwlError;
|
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
const regexp =
|
const regexp =
|
||||||
@@ -425,13 +422,12 @@ describe("errors and promises", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const app = new App(Example, { test: true });
|
||||||
await mount(Example, fixture, { test: true });
|
let error: OwlError;
|
||||||
} catch (e) {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
expect((e as Error).message).toBe(
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
|
||||||
`The following error occurred in onMounted: "Error in mounted"`
|
await mountProm;
|
||||||
);
|
expect(error!.message).toBe(`The following error occurred in onMounted: "Error in mounted"`);
|
||||||
}
|
|
||||||
// 1 additional error is logged because the destruction of the app causes
|
// 1 additional error is logged because the destruction of the app causes
|
||||||
// the onWillUnmount hook to be called and to fail
|
// the onWillUnmount hook to be called and to fail
|
||||||
expect(mockConsoleError).toBeCalledTimes(1);
|
expect(mockConsoleError).toBeCalledTimes(1);
|
||||||
@@ -448,9 +444,10 @@ describe("errors and promises", () => {
|
|||||||
|
|
||||||
root.state = "boom";
|
root.state = "boom";
|
||||||
root.render();
|
root.render();
|
||||||
await nextTick();
|
await expect(nextAppError(root.__owl__.app)).resolves.toThrow(
|
||||||
|
"error occured in the owl lifecycle"
|
||||||
|
);
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
expect(mockConsoleError).toBeCalledTimes(1);
|
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -500,13 +497,12 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: Error;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const crashProm = expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
|
||||||
} catch (error) {
|
await app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
e = error as Error;
|
await crashProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`The following error occurred in onWillStart: "No active component (a hook function should only be called in 'setup')"`
|
`The following error occurred in onWillStart: "No active component (a hook function should only be called in 'setup')"`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -523,14 +519,13 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(`The following error occurred in onMounted: "test error"`);
|
||||||
expect(e!.message).toBe(`The following error occurred in onMounted: "test error"`);
|
expect(error!.cause).toBe(err);
|
||||||
expect(e!.cause).toBe(err);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Errors in owl lifecycle are wrapped in dev mode: async hook", async () => {
|
test("Errors in owl lifecycle are wrapped in dev mode: async hook", async () => {
|
||||||
@@ -546,14 +541,13 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(`The following error occurred in onWillStart: "test error"`);
|
||||||
expect(e!.message).toBe(`The following error occurred in onWillStart: "test error"`);
|
expect(error!.cause).toBe(err);
|
||||||
expect(e!.cause).toBe(err);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Errors in owl lifecycle are wrapped outside dev mode: sync hook", async () => {
|
test("Errors in owl lifecycle are wrapped outside dev mode: sync hook", async () => {
|
||||||
@@ -568,16 +562,15 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root);
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
||||||
);
|
);
|
||||||
expect(e!.cause).toBe(err);
|
expect(error!.cause).toBe(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Errors in owl lifecycle are wrapped out of dev mode: async hook", async () => {
|
test("Errors in owl lifecycle are wrapped out of dev mode: async hook", async () => {
|
||||||
@@ -593,16 +586,15 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root);
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
||||||
);
|
);
|
||||||
expect(e!.cause).toBe(err);
|
expect(error!.cause).toBe(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Thrown values that are not errors are wrapped in dev mode", async () => {
|
test("Thrown values that are not errors are wrapped in dev mode", async () => {
|
||||||
@@ -616,16 +608,15 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root, { test: true });
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture, { test: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("not an Error was thrown in onMounted");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`Something that is not an Error was thrown in onMounted (see this Error's "cause" property)`
|
`Something that is not an Error was thrown in onMounted (see this Error's "cause" property)`
|
||||||
);
|
);
|
||||||
expect(e!.cause).toBe("This is not an error");
|
expect(error!.cause).toBe("This is not an error");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Thrown values that are not errors are wrapped outside dev mode", async () => {
|
test("Thrown values that are not errors are wrapped outside dev mode", async () => {
|
||||||
@@ -639,16 +630,15 @@ describe("can catch errors", () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e: OwlError;
|
const app = new App(Root);
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(Root, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (error) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
e = error as OwlError;
|
await mountProm;
|
||||||
}
|
expect(error!.message).toBe(
|
||||||
expect(e!.message).toBe(
|
|
||||||
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
`An error occured in the owl lifecycle (see this Error's "cause" property)`
|
||||||
);
|
);
|
||||||
expect(e!.cause).toBe("This is not an error");
|
expect(error!.cause).toBe("This is not an error");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can catch an error in the initial call of a component render function (parent mounted)", async () => {
|
test("can catch an error in the initial call of a component render function (parent mounted)", async () => {
|
||||||
|
|||||||
@@ -171,4 +171,22 @@ describe("event handling", () => {
|
|||||||
// input is removed when component is destroyed => nothing should happen
|
// input is removed when component is destroyed => nothing should happen
|
||||||
expect([]).toBeLogged();
|
expect([]).toBeLogged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("handler works when app is mounted in an iframe", async () => {
|
||||||
|
let clickCount = 0;
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`<span t-on-click="inc">click me</span>`;
|
||||||
|
inc() {
|
||||||
|
clickCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const iframe = document.createElement("iframe");
|
||||||
|
fixture.appendChild(iframe);
|
||||||
|
const iframeDoc = iframe.contentDocument!;
|
||||||
|
await mount(Parent, iframeDoc.body);
|
||||||
|
expect(clickCount).toBe(0);
|
||||||
|
iframeDoc.querySelector("span")!.click();
|
||||||
|
expect(clickCount).toBe(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,8 +17,16 @@ import {
|
|||||||
useChildSubEnv,
|
useChildSubEnv,
|
||||||
useSubEnv,
|
useSubEnv,
|
||||||
xml,
|
xml,
|
||||||
|
OwlError,
|
||||||
} from "../../src/index";
|
} from "../../src/index";
|
||||||
import { elem, logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import {
|
||||||
|
elem,
|
||||||
|
logStep,
|
||||||
|
makeTestFixture,
|
||||||
|
nextAppError,
|
||||||
|
nextTick,
|
||||||
|
snapshotEverything,
|
||||||
|
} from "../helpers";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
|
|
||||||
@@ -650,11 +658,12 @@ describe("hooks", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
let error: OwlError;
|
||||||
await mount(MyComponent, fixture);
|
const app = new App(MyComponent);
|
||||||
} catch (e: any) {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
expect(e.cause.message).toBe("Intentional error");
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
}
|
await mountProm;
|
||||||
|
expect(error!.cause.message).toBe("Intentional error");
|
||||||
// no console.error because the error has been caught in this test
|
// no console.error because the error has been caught in this test
|
||||||
expect(console.error).toHaveBeenCalledTimes(0);
|
expect(console.error).toHaveBeenCalledTimes(0);
|
||||||
console.error = originalconsoleError;
|
console.error = originalconsoleError;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
import { Component, onError, xml, mount } from "../../src";
|
import { Component, onError, xml, mount, OwlError } from "../../src";
|
||||||
import { DEV_MSG } from "../../src/runtime/app";
|
import { App, DEV_MSG } from "../../src/runtime/app";
|
||||||
import { validateProps } from "../../src/runtime/template_helpers";
|
import { validateProps } from "../../src/runtime/template_helpers";
|
||||||
import { Schema } from "../../src/runtime/validation";
|
import { Schema } from "../../src/runtime/validation";
|
||||||
|
|
||||||
@@ -48,13 +48,14 @@ describe("props validation", () => {
|
|||||||
static components = { SubComp };
|
static components = { SubComp };
|
||||||
static template = xml`<div><SubComp /></div>`;
|
static template = xml`<div><SubComp /></div>`;
|
||||||
}
|
}
|
||||||
let error: Error | undefined;
|
|
||||||
|
|
||||||
try {
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
let error: OwlError | undefined;
|
||||||
} catch (e) {
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
error = e as Error;
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
}
|
"Invalid props for component 'SubComp': 'message' is missing"
|
||||||
|
);
|
||||||
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
|
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
|
||||||
error = undefined;
|
error = undefined;
|
||||||
@@ -77,12 +78,13 @@ describe("props validation", () => {
|
|||||||
static template = xml`<div><SubComp /></div>`;
|
static template = xml`<div><SubComp /></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: Error;
|
const app = new App(Parent, { test: true });
|
||||||
try {
|
let error: OwlError | undefined;
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
error = e as Error;
|
"Invalid props for component 'SubComp': 'message' is missing"
|
||||||
}
|
);
|
||||||
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
|
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
|
||||||
});
|
});
|
||||||
@@ -126,14 +128,12 @@ describe("props validation", () => {
|
|||||||
};
|
};
|
||||||
(Parent as any).components = { SubComp };
|
(Parent as any).components = { SubComp };
|
||||||
|
|
||||||
let error: Error | undefined;
|
|
||||||
props = {};
|
props = {};
|
||||||
|
let app = new App(Parent, { test: true });
|
||||||
try {
|
let error: OwlError | undefined;
|
||||||
await mount(Parent, fixture, { dev: true });
|
let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
|
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
|
||||||
@@ -147,11 +147,10 @@ describe("props validation", () => {
|
|||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
props = { p: test.ko };
|
props = { p: test.ko };
|
||||||
try {
|
app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
|
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
|
||||||
@@ -181,13 +180,12 @@ describe("props validation", () => {
|
|||||||
static template = xml`<div>hey</div>`;
|
static template = xml`<div>hey</div>`;
|
||||||
};
|
};
|
||||||
(Parent as any).components = { SubComp };
|
(Parent as any).components = { SubComp };
|
||||||
let error: Error | undefined;
|
|
||||||
props = {};
|
props = {};
|
||||||
try {
|
let app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
let error: OwlError | undefined;
|
||||||
} catch (e) {
|
let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
error = e as Error;
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
|
||||||
}
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
|
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
|
||||||
@@ -201,11 +199,10 @@ describe("props validation", () => {
|
|||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
props = { p: test.ko };
|
props = { p: test.ko };
|
||||||
try {
|
app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
|
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
|
||||||
@@ -227,26 +224,25 @@ describe("props validation", () => {
|
|||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
let props: { p?: any };
|
let props: { p?: any };
|
||||||
|
props = { p: "string" };
|
||||||
try {
|
try {
|
||||||
props = { p: "string" };
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
await mount(Parent, fixture, { dev: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
|
props = { p: true };
|
||||||
try {
|
try {
|
||||||
props = { p: true };
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
await mount(Parent, fixture, { dev: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: 1 };
|
||||||
props = { p: 1 };
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' is not a string or boolean"
|
"Invalid props for component 'SubComp': 'p' is not a string or boolean"
|
||||||
@@ -267,26 +263,25 @@ describe("props validation", () => {
|
|||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
let props: { p?: any };
|
let props: { p?: any };
|
||||||
|
props = { p: "key" };
|
||||||
try {
|
try {
|
||||||
props = { p: "key" };
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
await mount(Parent, fixture, { dev: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
|
props = {};
|
||||||
try {
|
try {
|
||||||
props = {};
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
await mount(Parent, fixture, { dev: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: 1 };
|
||||||
props = { p: 1 };
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is not a string");
|
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is not a string");
|
||||||
});
|
});
|
||||||
@@ -319,20 +314,18 @@ describe("props validation", () => {
|
|||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: [1] };
|
||||||
props = { p: [1] };
|
let app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
error = undefined;
|
error = undefined;
|
||||||
try {
|
app = new App(Parent, { test: true });
|
||||||
props = { p: ["string", 1] };
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
await mount(Parent, fixture, { dev: true });
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
} catch (e) {
|
await mountProm;
|
||||||
error = e as Error;
|
expect(error!).toBeDefined();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can validate an array with multiple sub element types", async () => {
|
test("can validate an array with multiple sub element types", async () => {
|
||||||
@@ -370,12 +363,11 @@ describe("props validation", () => {
|
|||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: [true, 1] };
|
||||||
props = { p: [true, 1] };
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p[1]' is not a string or boolean"
|
"Invalid props for component 'SubComp': 'p[1]' is not a string or boolean"
|
||||||
@@ -405,33 +397,30 @@ describe("props validation", () => {
|
|||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: { id: 1, url: "url", extra: true } };
|
||||||
props = { p: { id: 1, url: "url", extra: true } };
|
let app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' has not the correct shape (unknown key 'extra')"
|
"Invalid props for component 'SubComp': 'p' has not the correct shape (unknown key 'extra')"
|
||||||
);
|
);
|
||||||
try {
|
props = { p: { id: "1", url: "url" } };
|
||||||
props = { p: { id: "1", url: "url" } };
|
app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' has not the correct shape ('id' is not a number)"
|
"Invalid props for component 'SubComp': 'p' has not the correct shape ('id' is not a number)"
|
||||||
);
|
);
|
||||||
error = undefined;
|
error = undefined;
|
||||||
try {
|
props = { p: { id: 1 } };
|
||||||
props = { p: { id: 1 } };
|
app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is missing (should be a string))"
|
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is missing (should be a string))"
|
||||||
@@ -474,12 +463,11 @@ describe("props validation", () => {
|
|||||||
error = e as Error;
|
error = e as Error;
|
||||||
}
|
}
|
||||||
expect(error!).toBeUndefined();
|
expect(error!).toBeUndefined();
|
||||||
try {
|
props = { p: { id: 1, url: [12, true] } };
|
||||||
props = { p: { id: 1, url: [12, true] } };
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is not a boolean or list of numbers)"
|
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is not a boolean or list of numbers)"
|
||||||
@@ -686,11 +674,10 @@ describe("props validation", () => {
|
|||||||
static components = { SubComp };
|
static components = { SubComp };
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is missing");
|
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is missing");
|
||||||
});
|
});
|
||||||
@@ -754,11 +741,10 @@ describe("props validation", () => {
|
|||||||
static template = xml`<div><Child/></div>`;
|
static template = xml`<div><Child/></div>`;
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'Child'");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"Invalid props for component 'Child': 'mandatory' is missing (should be a number)"
|
"Invalid props for component 'Child': 'mandatory' is missing (should be a number)"
|
||||||
@@ -794,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");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -859,11 +871,12 @@ describe("default props", () => {
|
|||||||
static template = xml`<Child/>`;
|
static template = xml`<Child/>`;
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent, { test: true });
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
error = e as Error;
|
"default value cannot be defined for a mandatory prop"
|
||||||
}
|
);
|
||||||
|
await mountProm;
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(
|
expect(error!.message).toBe(
|
||||||
"A default value cannot be defined for a mandatory prop (name: 'mandatory', component: Child)"
|
"A default value cannot be defined for a mandatory prop (name: 'mandatory', component: Child)"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, mount, onMounted, useRef, useState } from "../../src/index";
|
import { App, Component, mount, onMounted, useRef, useState } from "../../src/index";
|
||||||
import { logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { logStep, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
import { xml } from "../../src/index";
|
import { xml } from "../../src/index";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
@@ -94,9 +94,14 @@ describe("refs", () => {
|
|||||||
ref = useRef("coucou");
|
ref = useRef("coucou");
|
||||||
}
|
}
|
||||||
|
|
||||||
await expect(async () => {
|
const app = new App(Test, { test: true });
|
||||||
await mount(Test, fixture);
|
const mountProm = expect(app.mount(fixture)).rejects.toThrowError(
|
||||||
}).rejects.toThrowError("Cannot have 2 elements with same ref name at the same time");
|
"Cannot have 2 elements with same ref name at the same time"
|
||||||
|
);
|
||||||
|
await expect(nextAppError(app)).resolves.toThrow(
|
||||||
|
"Cannot have 2 elements with same ref name at the same time"
|
||||||
|
);
|
||||||
|
await mountProm;
|
||||||
expect(console.warn).toBeCalledTimes(1);
|
expect(console.warn).toBeCalledTimes(1);
|
||||||
console.warn = consoleWarn;
|
console.warn = consoleWarn;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
|
import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
|
||||||
import { children, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { children, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
let originalconsoleWarn = console.warn;
|
let originalconsoleWarn = console.warn;
|
||||||
@@ -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 {
|
||||||
@@ -204,13 +221,12 @@ describe("slots", () => {
|
|||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = null;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(Parent, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
error = e;
|
await mountProm;
|
||||||
}
|
expect(error!).not.toBeNull();
|
||||||
expect(error).not.toBeNull();
|
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1819,4 +1835,102 @@ describe("slots", () => {
|
|||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<button>inc</button>[B][C][A][sub1] [sub2334]");
|
expect(fixture.innerHTML).toBe("<button>inc</button>[B][C][A][sub1] [sub2334]");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("slot in multiple locations", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<div>child</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Slotter extends Component {
|
||||||
|
static components = { Child };
|
||||||
|
static template = xml`
|
||||||
|
<t t-if="props.location === 1">
|
||||||
|
<p><t t-slot="default"/></p>
|
||||||
|
</t>
|
||||||
|
<t t-if="props.location === 2">
|
||||||
|
<t t-slot="default"/>
|
||||||
|
</t>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static components = { Child, Slotter };
|
||||||
|
static template = xml`
|
||||||
|
<Slotter location="state.location">
|
||||||
|
hello <Child/>
|
||||||
|
</Slotter>`;
|
||||||
|
state = useState({ location: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<p> hello <div>child</div></p>");
|
||||||
|
parent.state.location = 2;
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe(" hello <div>child</div>");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("dynamic slot in multiple locations", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<div>child</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Slotter extends Component {
|
||||||
|
static components = { Child };
|
||||||
|
static template = xml`
|
||||||
|
<t t-if="props.location === 1">
|
||||||
|
<p><t t-slot="{{'coffee'}}"/></p>
|
||||||
|
</t>
|
||||||
|
<t t-if="props.location === 2">
|
||||||
|
<t t-slot="{{'coffee'}}"/>
|
||||||
|
</t>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static components = { Child, Slotter };
|
||||||
|
static template = xml`
|
||||||
|
<Slotter location="state.location">
|
||||||
|
<t t-set-slot="coffee">hello <Child/></t>
|
||||||
|
</Slotter>`;
|
||||||
|
state = useState({ location: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<p>hello <div>child</div></p>");
|
||||||
|
parent.state.location = 2;
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe("hello <div>child</div>");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("slot in t-foreach locations", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<div>child</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Slotter extends Component {
|
||||||
|
static components = { Child };
|
||||||
|
static template = xml`
|
||||||
|
<t t-foreach="props.list" t-as="elem" t-key="elem_index">
|
||||||
|
<p><t t-esc="elem"/><t t-slot="default"/></p>
|
||||||
|
</t>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Component {
|
||||||
|
static components = { Child, Slotter };
|
||||||
|
static template = xml`
|
||||||
|
<Slotter list="state.list">
|
||||||
|
hello <Child/>
|
||||||
|
</Slotter>`;
|
||||||
|
state = useState({ list: [1] });
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = await mount(Parent, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<p>1 hello <div>child</div></p>");
|
||||||
|
parent.state.list.push(2);
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe(
|
||||||
|
"<p>1 hello <div>child</div></p><p>2 hello <div>child</div></p>"
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { OwlError } from "../../src/runtime/error_handling";
|
import { OwlError } from "../../src/runtime/error_handling";
|
||||||
import { Component, mount, onMounted, useState, xml } from "../../src";
|
import { App, Component, mount, onMounted, useState, xml } from "../../src";
|
||||||
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
@@ -343,16 +343,15 @@ describe("style and class handling", () => {
|
|||||||
class Child extends Component {
|
class Child extends Component {
|
||||||
static template = xml`<div t-att-class="props.class" t-esc="this.will.crash"/>`;
|
static template = xml`<div t-att-class="props.class" t-esc="this.will.crash"/>`;
|
||||||
}
|
}
|
||||||
class ParentWidget extends Component {
|
class Parent extends Component {
|
||||||
static template = xml`<Child class="'a'"/>`;
|
static template = xml`<Child class="'a'"/>`;
|
||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(ParentWidget, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
error = e as OwlError;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
const regexp =
|
const regexp =
|
||||||
|
|||||||
@@ -287,4 +287,32 @@ describe("t-call", () => {
|
|||||||
});
|
});
|
||||||
expect(fixture.innerHTML).toBe("childaaronchildlucas");
|
expect(fixture.innerHTML).toBe("childaaronchildlucas");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-call with t-call-context and subcomponent, in dev mode", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`child<t t-esc="props.name"/>`;
|
||||||
|
static props = ["name"];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Root extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-call="someTemplate" t-call-context="subctx"/>`;
|
||||||
|
|
||||||
|
static components = { Child };
|
||||||
|
|
||||||
|
subctx = { aab: "aaron", lpe: "lucas" };
|
||||||
|
}
|
||||||
|
|
||||||
|
await mount(Root, fixture, {
|
||||||
|
dev: true,
|
||||||
|
templates: `
|
||||||
|
<templates>
|
||||||
|
<t t-name="someTemplate">
|
||||||
|
<Child name="aab"/>
|
||||||
|
<Child name="lpe"/>
|
||||||
|
</t>
|
||||||
|
</templates>`,
|
||||||
|
});
|
||||||
|
expect(fixture.innerHTML).toBe("childaaronchildlucas");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { Component, mount, onMounted, useState, xml } from "../../src/index";
|
import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
|
||||||
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
|
import {
|
||||||
|
makeTestFixture,
|
||||||
|
nextAppError,
|
||||||
|
nextTick,
|
||||||
|
snapshotEverything,
|
||||||
|
useLogLifecycle,
|
||||||
|
} from "../helpers";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
|
|
||||||
@@ -315,10 +321,73 @@ describe("list of components", () => {
|
|||||||
`;
|
`;
|
||||||
static components = { Child };
|
static components = { Child };
|
||||||
}
|
}
|
||||||
await expect(async () => {
|
|
||||||
await mount(Parent, fixture, { dev: true });
|
const app = new App(Parent, { test: true });
|
||||||
}).rejects.toThrowError("Got duplicate key in t-foreach: child");
|
const mountProm = expect(app.mount(fixture)).rejects.toThrow(
|
||||||
|
"Got duplicate key in t-foreach: child"
|
||||||
|
);
|
||||||
|
await expect(nextAppError(app)).resolves.toThrow("Got duplicate key in t-foreach: child");
|
||||||
|
await mountProm;
|
||||||
console.info = consoleInfo;
|
console.info = consoleInfo;
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -261,6 +261,20 @@ expect.extend({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export function nextAppError(app: any) {
|
||||||
|
const { handleError } = app;
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
app.handleError = (...args: Parameters<typeof handleError>) => {
|
||||||
|
try {
|
||||||
|
handleError.call(app, ...args);
|
||||||
|
} catch (e: any) {
|
||||||
|
app.handleError = handleError;
|
||||||
|
resolve(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace jest {
|
namespace jest {
|
||||||
interface Matchers<R> {
|
interface Matchers<R> {
|
||||||
|
|||||||
@@ -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
|
||||||
) {
|
) {
|
||||||
|
|||||||
+56
-17
@@ -12,7 +12,7 @@ import {
|
|||||||
} from "../../src";
|
} from "../../src";
|
||||||
import { xml } from "../../src/";
|
import { xml } from "../../src/";
|
||||||
import { DEV_MSG } from "../../src/runtime/app";
|
import { DEV_MSG } from "../../src/runtime/app";
|
||||||
import { elem, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { elem, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
let originalconsoleWarn = console.warn;
|
let originalconsoleWarn = console.warn;
|
||||||
@@ -269,15 +269,14 @@ describe("Portal", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(Parent, fixture);
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("invalid portal target");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe("invalid portal target");
|
expect(error!.message).toBe("invalid portal target");
|
||||||
expect(fixture.innerHTML).toBe(`<div></div>`);
|
expect(fixture.innerHTML).toBe(``);
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(1);
|
expect(mockConsoleWarn).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -875,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", () => {
|
||||||
@@ -960,11 +1001,10 @@ describe("Portal: Props validation", () => {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
let error: OwlError;
|
let error: OwlError;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
|
||||||
error = e as OwlError;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.cause).toBeDefined();
|
expect(error!.cause).toBeDefined();
|
||||||
expect(error!.cause.message).toBe(`' ' is not a valid selector`);
|
expect(error!.cause.message).toBe(`' ' is not a valid selector`);
|
||||||
@@ -980,11 +1020,10 @@ describe("Portal: Props validation", () => {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
let error: Error;
|
let error: Error;
|
||||||
try {
|
const app = new App(Parent);
|
||||||
await mount(Parent, fixture, { dev: true });
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
} catch (e) {
|
await expect(nextAppError(app)).resolves.toThrow("invalid portal target");
|
||||||
error = e as Error;
|
await mountProm;
|
||||||
}
|
|
||||||
expect(error!).toBeDefined();
|
expect(error!).toBeDefined();
|
||||||
expect(error!.message).toBe(`invalid portal target`);
|
expect(error!.message).toBe(`invalid portal target`);
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-3
@@ -72,10 +72,8 @@ async function startRelease() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
log(`Step 3/${STEPS}: updating package.json, readme.md and roadmap.md...`);
|
log(`Step 3/${STEPS}: updating package.json...`);
|
||||||
await replaceInFile("./package.json", current, next);
|
await replaceInFile("./package.json", current, next);
|
||||||
await replaceInFile("./README.md", current, next);
|
|
||||||
await replaceInFile("./roadmap.md", current, next);
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
log(`Step 4/${STEPS}: creating git commit...`);
|
log(`Step 4/${STEPS}: creating git commit...`);
|
||||||
|
|||||||
Reference in New Issue
Block a user