[IMP] portal: portal as a Directive

Before this commit, portal was a Component, now is a directive.
This commit also clean some unused code, and fix an issue on the clean
optimization when a portal is found in a condition or a loop.
This commit is contained in:
Jorge Pinna Puissant
2022-01-11 10:47:50 +01:00
committed by Aaron Bohy
parent c221721d7f
commit 90167c5436
11 changed files with 558 additions and 252 deletions
+37 -12
View File
@@ -19,6 +19,7 @@ import {
ASTTSet,
ASTTranslation,
ASTType,
ASTTPortal,
} from "./parser";
type BlockType = "block" | "text" | "multi" | "list" | "html" | "comment";
@@ -64,13 +65,15 @@ class BlockDescription {
type: BlockType;
parentVar: string = "";
id: number;
deepRemove: boolean;
constructor(target: CodeTarget, type: BlockType) {
constructor(target: CodeTarget, type: BlockType, deepRemove: boolean = false) {
this.id = BlockDescription.nextBlockId++;
this.varName = "b" + this.id;
this.blockName = "block" + this.id;
this.target = target;
this.type = type;
this.deepRemove = deepRemove;
}
insertData(str: string, prefix: string = "d"): number {
@@ -99,7 +102,7 @@ class BlockDescription {
}
return `${this.blockName}(${params})`;
} else if (this.type === "list") {
return `list(c_block${this.id})`;
return `list(c_block${this.id}${this.deepRemove ? ", true" : ""})`;
}
return expr;
}
@@ -250,6 +253,8 @@ export class CodeGenerator {
mainCode.push(`const ${id} = getTemplate(${template});`);
}
const deepRemove = "deepRemove" in this.ast ? this.ast.deepRemove : false;
// define all blocks
if (this.blocks.length) {
mainCode.push(``);
@@ -259,9 +264,15 @@ export class CodeGenerator {
if (block.dynamicTagName) {
xmlString = xmlString.replace(/^<\w+/, `<\${tag || '${block.dom.nodeName}'}`);
xmlString = xmlString.replace(/\w+>$/, `\${tag || '${block.dom.nodeName}'}>`);
mainCode.push(`let ${block.blockName} = tag => createBlock(\`${xmlString}\`);`);
mainCode.push(
`let ${block.blockName} = tag => createBlock(\`${xmlString}\`${
deepRemove ? ", true" : ""
});`
);
} else {
mainCode.push(`let ${block.blockName} = createBlock(\`${xmlString}\`);`);
mainCode.push(
`let ${block.blockName} = createBlock(\`${xmlString}\`${deepRemove ? ", true" : ""});`
);
}
}
}
@@ -317,10 +328,11 @@ export class CodeGenerator {
createBlock(
parentBlock: BlockDescription | null,
type: BlockType,
ctx: Context
ctx: Context,
deepRemove: boolean = false
): BlockDescription {
const hasRoot = this.target.hasRoot;
const block = new BlockDescription(this.target, type);
const block = new BlockDescription(this.target, type, deepRemove);
if (!hasRoot && !ctx.preventRoot) {
this.target.hasRoot = true;
block.isRoot = true;
@@ -445,6 +457,8 @@ export class CodeGenerator {
case ASTType.TTranslation:
this.compileTTranslation(ast, ctx);
break;
case ASTType.TPortal:
this.compileTPortal(ast, ctx);
}
}
@@ -704,7 +718,7 @@ export class CodeGenerator {
if (ast.body) {
const nextId = BlockDescription.nextBlockId;
const subCtx: Context = createContext(ctx);
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
this.compileAST({ type: ASTType.Multi, content: ast.body, deepRemove: false }, subCtx);
this.helpers.add("withDefault");
expr = `withDefault(${expr}, b${nextId})`;
}
@@ -765,7 +779,7 @@ export class CodeGenerator {
// note: this part is duplicated from end of compilemulti:
const args = block!.children.map((c) => c.varName).join(", ");
this.insertBlock(`multi([${args}])`, block!, ctx)!;
this.insertBlock(`multi([${args}]${ast.deepRemove ? ", true" : ""})`, block!, ctx)!;
}
}
@@ -774,7 +788,7 @@ export class CodeGenerator {
if (block) {
this.insertAnchor(block);
}
block = this.createBlock(block, "list", ctx);
block = this.createBlock(block, "list", ctx, ast.deepRemove);
this.target.loopLevel++;
const loopVar = `i${this.target.loopLevel}`;
this.addLine(`ctx = Object.create(ctx);`);
@@ -909,7 +923,7 @@ export class CodeGenerator {
}
const args = block!.children.map((c) => c.varName).join(", ");
this.insertBlock(`multi([${args}])`, block!, ctx)!;
this.insertBlock(`multi([${args}]${ast.deepRemove ? ", true" : ""})`, block!, ctx)!;
}
}
@@ -921,7 +935,7 @@ export class CodeGenerator {
this.helpers.add("isBoundary");
const nextId = BlockDescription.nextBlockId;
const subCtx: Context = createContext(ctx, { preventRoot: true });
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
this.compileAST({ type: ASTType.Multi, content: ast.body, deepRemove: false }, subCtx);
if (nextId !== BlockDescription.nextBlockId) {
this.helpers.add("zero");
this.addLine(`ctx[zero] = b${nextId};`);
@@ -976,7 +990,7 @@ export class CodeGenerator {
const expr = ast.value ? compileExpr(ast.value || "") : "null";
if (ast.body) {
this.helpers.add("LazyValue");
const bodyAst: AST = { type: ASTType.Multi, content: ast.body };
const bodyAst: AST = { type: ASTType.Multi, content: ast.body, deepRemove: false };
const name = this.compileInNewTarget("value", bodyAst, ctx);
let value = `new LazyValue(${name}, ctx, node)`;
value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
@@ -1162,4 +1176,15 @@ export class CodeGenerator {
this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
}
}
compileTPortal(ast: ASTTPortal, ctx: Context) {
this.helpers.add("callPortal");
let { block } = ctx;
const name = this.compileInNewTarget("portalContent", ast.content, ctx);
const blockString = `callPortal(ctx, node, key, ${ast.target}, ${name})`;
if (block) {
this.insertAnchor(block);
}
block = this.createBlock(block, "multi", ctx);
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
}
}