mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 64bad25762 | |||
| 7ab34c5ca5 | |||
| 669fd622ec |
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@odoo/owl",
|
||||
"version": "2.0.0-beta-21",
|
||||
"version": "2.0.0-beta-22",
|
||||
"description": "Odoo Web Library (OWL)",
|
||||
"main": "dist/owl.cjs.js",
|
||||
"module": "dist/owl.es.js",
|
||||
|
||||
@@ -214,6 +214,14 @@ class CodeTarget {
|
||||
result.push(`}`);
|
||||
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"];
|
||||
@@ -365,19 +373,15 @@ export class CodeGenerator {
|
||||
|
||||
insertBlock(expression: string, block: BlockDescription, ctx: Context): void {
|
||||
let blockExpr = block.generateExpr(expression);
|
||||
const tKeyExpr = ctx.tKeyExpr;
|
||||
if (block.parentVar) {
|
||||
let keyArg = `key${this.target.loopLevel}`;
|
||||
if (tKeyExpr) {
|
||||
keyArg = `${tKeyExpr} + ${keyArg}`;
|
||||
}
|
||||
let key = this.target.currentKey(ctx);
|
||||
this.helpers.add("withKey");
|
||||
this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${keyArg});`);
|
||||
this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${key});`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tKeyExpr) {
|
||||
blockExpr = `toggler(${tKeyExpr}, ${blockExpr})`;
|
||||
if (ctx.tKeyExpr) {
|
||||
blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
|
||||
}
|
||||
|
||||
if (block.isRoot && !ctx.preventRoot) {
|
||||
@@ -424,78 +428,66 @@ export class CodeGenerator {
|
||||
.join("");
|
||||
}
|
||||
|
||||
compileAST(ast: AST, ctx: Context) {
|
||||
/**
|
||||
* @returns the newly created block name, if any
|
||||
*/
|
||||
compileAST(ast: AST, ctx: Context): string | null {
|
||||
switch (ast.type) {
|
||||
case ASTType.Comment:
|
||||
this.compileComment(ast, ctx);
|
||||
break;
|
||||
return this.compileComment(ast, ctx);
|
||||
case ASTType.Text:
|
||||
this.compileText(ast, ctx);
|
||||
break;
|
||||
return this.compileText(ast, ctx);
|
||||
case ASTType.DomNode:
|
||||
this.compileTDomNode(ast, ctx);
|
||||
break;
|
||||
return this.compileTDomNode(ast, ctx);
|
||||
case ASTType.TEsc:
|
||||
this.compileTEsc(ast, ctx);
|
||||
break;
|
||||
return this.compileTEsc(ast, ctx);
|
||||
case ASTType.TOut:
|
||||
this.compileTOut(ast, ctx);
|
||||
break;
|
||||
return this.compileTOut(ast, ctx);
|
||||
case ASTType.TIf:
|
||||
this.compileTIf(ast, ctx);
|
||||
break;
|
||||
return this.compileTIf(ast, ctx);
|
||||
case ASTType.TForEach:
|
||||
this.compileTForeach(ast, ctx);
|
||||
break;
|
||||
return this.compileTForeach(ast, ctx);
|
||||
case ASTType.TKey:
|
||||
this.compileTKey(ast, ctx);
|
||||
break;
|
||||
return this.compileTKey(ast, ctx);
|
||||
case ASTType.Multi:
|
||||
this.compileMulti(ast, ctx);
|
||||
break;
|
||||
return this.compileMulti(ast, ctx);
|
||||
case ASTType.TCall:
|
||||
this.compileTCall(ast, ctx);
|
||||
break;
|
||||
return this.compileTCall(ast, ctx);
|
||||
case ASTType.TCallBlock:
|
||||
this.compileTCallBlock(ast, ctx);
|
||||
break;
|
||||
return this.compileTCallBlock(ast, ctx);
|
||||
case ASTType.TSet:
|
||||
this.compileTSet(ast, ctx);
|
||||
break;
|
||||
return this.compileTSet(ast, ctx);
|
||||
case ASTType.TComponent:
|
||||
this.compileComponent(ast, ctx);
|
||||
break;
|
||||
return this.compileComponent(ast, ctx);
|
||||
case ASTType.TDebug:
|
||||
this.compileDebug(ast, ctx);
|
||||
break;
|
||||
return this.compileDebug(ast, ctx);
|
||||
case ASTType.TLog:
|
||||
this.compileLog(ast, ctx);
|
||||
break;
|
||||
return this.compileLog(ast, ctx);
|
||||
case ASTType.TSlot:
|
||||
this.compileTSlot(ast, ctx);
|
||||
break;
|
||||
return this.compileTSlot(ast, ctx);
|
||||
case ASTType.TTranslation:
|
||||
this.compileTTranslation(ast, ctx);
|
||||
break;
|
||||
return this.compileTTranslation(ast, ctx);
|
||||
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;`);
|
||||
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)});`);
|
||||
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;
|
||||
const isNewBlock = !block || forceNewBlock;
|
||||
if (isNewBlock) {
|
||||
@@ -508,9 +500,10 @@ export class CodeGenerator {
|
||||
const text = xmlDoc.createComment(ast.value);
|
||||
block!.insert(text);
|
||||
}
|
||||
return block!.varName;
|
||||
}
|
||||
|
||||
compileText(ast: ASTText, ctx: Context) {
|
||||
compileText(ast: ASTText, ctx: Context): string {
|
||||
let { block, forceNewBlock } = ctx;
|
||||
|
||||
let value = ast.value;
|
||||
@@ -529,6 +522,7 @@ export class CodeGenerator {
|
||||
const createFn = ast.type === ASTType.Text ? xmlDoc.createTextNode : xmlDoc.createComment;
|
||||
block.insert(createFn.call(xmlDoc, value));
|
||||
}
|
||||
return block.varName;
|
||||
}
|
||||
|
||||
generateHandlerCode(rawEvent: string, handler: string): string {
|
||||
@@ -548,7 +542,7 @@ export class CodeGenerator {
|
||||
return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
|
||||
}
|
||||
|
||||
compileTDomNode(ast: ASTDomNode, ctx: Context) {
|
||||
compileTDomNode(ast: ASTDomNode, ctx: Context): string {
|
||||
let { block, forceNewBlock } = ctx;
|
||||
const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
|
||||
let codeIdx = this.target.code.length;
|
||||
@@ -735,9 +729,10 @@ export class CodeGenerator {
|
||||
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 expr: string;
|
||||
if (ast.expr === "0") {
|
||||
@@ -758,9 +753,10 @@ export class CodeGenerator {
|
||||
const text = xmlDoc.createElement(`block-text-${idx}`);
|
||||
block.insert(text);
|
||||
}
|
||||
return block.varName;
|
||||
}
|
||||
|
||||
compileTOut(ast: ASTTOut, ctx: Context) {
|
||||
compileTOut(ast: ASTTOut, ctx: Context): string {
|
||||
let { block } = ctx;
|
||||
if (block) {
|
||||
this.insertAnchor(block);
|
||||
@@ -782,6 +778,7 @@ export class CodeGenerator {
|
||||
blockStr = `safeOutput(${compileExpr(ast.expr)})`;
|
||||
}
|
||||
this.insertBlock(blockStr, block, ctx);
|
||||
return block.varName;
|
||||
}
|
||||
|
||||
compileTIfBranch(content: AST, block: BlockDescription, ctx: Context) {
|
||||
@@ -795,7 +792,7 @@ export class CodeGenerator {
|
||||
this.target.indentLevel--;
|
||||
}
|
||||
|
||||
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode) {
|
||||
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode): string {
|
||||
let { block, forceNewBlock } = ctx;
|
||||
const codeIdx = this.target.code.length;
|
||||
const isNewBlock = !block || (block.type !== "multi" && forceNewBlock);
|
||||
@@ -838,9 +835,10 @@ export class CodeGenerator {
|
||||
const args = block!.children.map((c) => c.varName).join(", ");
|
||||
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
||||
}
|
||||
return block.varName;
|
||||
}
|
||||
|
||||
compileTForeach(ast: ASTTForEach, ctx: Context) {
|
||||
compileTForeach(ast: ASTTForEach, ctx: Context): string {
|
||||
let { block } = ctx;
|
||||
if (block) {
|
||||
this.insertAnchor(block);
|
||||
@@ -918,9 +916,10 @@ export class CodeGenerator {
|
||||
this.addLine(`ctx = ctx.__proto__;`);
|
||||
}
|
||||
this.insertBlock("l", block, ctx);
|
||||
return block.varName;
|
||||
}
|
||||
|
||||
compileTKey(ast: ASTTKey, ctx: Context) {
|
||||
compileTKey(ast: ASTTKey, ctx: Context): string | null {
|
||||
const tKeyExpr = generateId("tKey_");
|
||||
this.define(tKeyExpr, compileExpr(ast.expr));
|
||||
ctx = createContext(ctx, {
|
||||
@@ -928,20 +927,22 @@ export class CodeGenerator {
|
||||
block: ctx.block,
|
||||
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;
|
||||
const isNewBlock = !block || forceNewBlock;
|
||||
let codeIdx = this.target.code.length;
|
||||
if (isNewBlock) {
|
||||
const n = ast.content.filter((c) => c.type !== ASTType.TSet).length;
|
||||
let result: string | null = null;
|
||||
if (n <= 1) {
|
||||
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);
|
||||
}
|
||||
@@ -981,9 +982,10 @@ export class CodeGenerator {
|
||||
const args = block!.children.map((c) => c.varName).join(", ");
|
||||
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 ctxVar = ctx.ctxVar || "ctx";
|
||||
if (ast.context) {
|
||||
@@ -994,12 +996,11 @@ export class CodeGenerator {
|
||||
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
||||
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
||||
this.helpers.add("isBoundary");
|
||||
const nextId = BlockDescription.nextBlockId;
|
||||
const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
|
||||
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
|
||||
if (nextId !== BlockDescription.nextBlockId) {
|
||||
const bl = this.compileMulti({ type: ASTType.Multi, content: ast.body }, subCtx);
|
||||
if (bl) {
|
||||
this.helpers.add("zero");
|
||||
this.addLine(`${ctxVar}[zero] = b${nextId};`);
|
||||
this.addLine(`${ctxVar}[zero] = ${bl};`);
|
||||
}
|
||||
}
|
||||
const isDynamic = INTERP_REGEXP.test(ast.name);
|
||||
@@ -1033,9 +1034,10 @@ export class CodeGenerator {
|
||||
if (ast.body && !ctx.isLast) {
|
||||
this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
|
||||
}
|
||||
return block.varName;
|
||||
}
|
||||
|
||||
compileTCallBlock(ast: ASTTCallBlock, ctx: Context) {
|
||||
compileTCallBlock(ast: ASTTCallBlock, ctx: Context): string {
|
||||
let { block, forceNewBlock } = ctx;
|
||||
if (block) {
|
||||
if (!forceNewBlock) {
|
||||
@@ -1044,9 +1046,10 @@ export class CodeGenerator {
|
||||
}
|
||||
block = this.createBlock(block, "multi", ctx);
|
||||
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.helpers.add("isBoundary").add("withDefault");
|
||||
const expr = ast.value ? compileExpr(ast.value || "") : "null";
|
||||
@@ -1054,7 +1057,8 @@ export class CodeGenerator {
|
||||
this.helpers.add("LazyValue");
|
||||
const bodyAst: AST = { type: ASTType.Multi, content: ast.body };
|
||||
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;
|
||||
this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
|
||||
} else {
|
||||
@@ -1071,6 +1075,7 @@ export class CodeGenerator {
|
||||
this.helpers.add("setContextValue");
|
||||
this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
generateComponentKey() {
|
||||
@@ -1122,7 +1127,7 @@ export class CodeGenerator {
|
||||
return propString;
|
||||
}
|
||||
|
||||
compileComponent(ast: ASTComponent, ctx: Context) {
|
||||
compileComponent(ast: ASTComponent, ctx: Context): string {
|
||||
let { block } = ctx;
|
||||
// props
|
||||
const hasSlotsProp = "slots" in (ast.props || {});
|
||||
@@ -1222,6 +1227,7 @@ export class CodeGenerator {
|
||||
|
||||
block = this.createBlock(block, "multi", ctx);
|
||||
this.insertBlock(blockExpr, block, ctx);
|
||||
return block.varName;
|
||||
}
|
||||
|
||||
wrapWithEventCatcher(expr: string, on: EventHandlers): string {
|
||||
@@ -1240,7 +1246,7 @@ export class CodeGenerator {
|
||||
return `${name}(${expr}, [${handlers.join(",")}])`;
|
||||
}
|
||||
|
||||
compileTSlot(ast: ASTSlot, ctx: Context) {
|
||||
compileTSlot(ast: ASTSlot, ctx: Context): string {
|
||||
this.helpers.add("callSlot");
|
||||
let { block } = ctx;
|
||||
let blockString: string;
|
||||
@@ -1289,14 +1295,16 @@ export class CodeGenerator {
|
||||
}
|
||||
block = this.createBlock(block, "multi", ctx);
|
||||
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) {
|
||||
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")) {
|
||||
this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
|
||||
}
|
||||
@@ -1323,5 +1331,6 @@ export class CodeGenerator {
|
||||
}
|
||||
block = this.createBlock(block, "multi", ctx);
|
||||
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
||||
return block.varName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,15 +111,18 @@ class LazyValue {
|
||||
ctx: any;
|
||||
component: 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.ctx = capture(ctx);
|
||||
this.component = component;
|
||||
this.node = node;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
@@ -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`] = `
|
||||
"function anonymous(app, bdom, helpers
|
||||
) {
|
||||
|
||||
@@ -126,7 +126,7 @@ exports[`t-esc t-esc is escaped 1`] = `
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
ctx[\`var\`] = new LazyValue(value1, ctx, this, node);
|
||||
ctx[\`var\`] = new LazyValue(value1, ctx, this, node, key);
|
||||
let txt1 = ctx['var'];
|
||||
return block1([txt1]);
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ exports[`t-out t-out bdom 1`] = `
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
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']);
|
||||
return block1([], [b3]);
|
||||
}
|
||||
@@ -310,7 +310,7 @@ exports[`t-out t-out switch markup on bdom 1`] = `
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
let b3,b5;
|
||||
ctx[\`bdom\`] = new LazyValue(value1, ctx, this, node);
|
||||
ctx[\`bdom\`] = new LazyValue(value1, ctx, this, node, key);
|
||||
if (ctx['hasBdom']) {
|
||||
const b4 = safeOutput(ctx['bdom']);
|
||||
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 = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
ctx[\`value\`] = new LazyValue(value1, ctx, this, node);
|
||||
ctx[\`value\`] = new LazyValue(value1, ctx, this, node, key);
|
||||
return text(ctx['value']);
|
||||
}
|
||||
}"
|
||||
@@ -142,7 +142,7 @@ exports[`t-set set from body lookup 1`] = `
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
ctx[\`stuff\`] = new LazyValue(value1, ctx, this, node);
|
||||
ctx[\`stuff\`] = new LazyValue(value1, ctx, this, node, key);
|
||||
let txt1 = ctx['stuff'];
|
||||
return block1([txt1]);
|
||||
}
|
||||
@@ -206,7 +206,7 @@ exports[`t-set t-set body is evaluated immediately 1`] = `
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
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');
|
||||
const b3 = safeOutput(ctx['v2']);
|
||||
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 = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
ctx[\`setvar\`] = new LazyValue(value1, ctx, this, node);
|
||||
ctx[\`setvar\`] = new LazyValue(value1, ctx, this, node, key);
|
||||
let txt1 = ctx['setvar'];
|
||||
return block1([txt1]);
|
||||
}
|
||||
@@ -497,7 +497,7 @@ exports[`t-set t-set with t-value (falsy) and body 1`] = `
|
||||
ctx[isBoundary] = 1
|
||||
setContextValue(ctx, \\"v3\\", false);
|
||||
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, \\"v3\\", true);
|
||||
const b3 = safeOutput(ctx['v2']);
|
||||
@@ -525,7 +525,7 @@ exports[`t-set t-set with t-value (truthy) and body 1`] = `
|
||||
ctx[isBoundary] = 1
|
||||
setContextValue(ctx, \\"v3\\", 'Truthy');
|
||||
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, \\"v3\\", false);
|
||||
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 = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
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'];
|
||||
return block1([txt1]);
|
||||
}
|
||||
|
||||
@@ -479,4 +479,21 @@ describe("t-call (template calling)", () => {
|
||||
"<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>");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
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);
|
||||
return block1([], [b3]);
|
||||
}
|
||||
|
||||
@@ -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 = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
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 b4 = safeOutput(ctx['v']);
|
||||
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 = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
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 b6 = safeOutput(ctx['v']);
|
||||
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 = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
ctx[isBoundary] = 1
|
||||
ctx[\`v\`] = new LazyValue(value1, ctx, this, node);
|
||||
ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
|
||||
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 = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
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']);
|
||||
return block1([], [b3]);
|
||||
}
|
||||
@@ -377,7 +377,7 @@ exports[`t-set t-set with something in body 1`] = `
|
||||
return function template(ctx, node, key = \\"\\") {
|
||||
ctx = Object.create(ctx);
|
||||
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']);
|
||||
return block1([], [b3]);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user