[REF] qweb: improve variable handling

This commit is contained in:
Géry Debongnie
2019-06-04 14:23:26 +02:00
parent d1094f647a
commit 438b21df3f
4 changed files with 88 additions and 83 deletions
+15 -7
View File
@@ -518,7 +518,8 @@ export class QWeb {
// dynamic attributes
if (name.startsWith("t-att-")) {
let attName = name.slice(6);
let formattedValue = ctx.formatExpression(ctx.getValue(value!));
const v = ctx.getValue(value);
let formattedValue = v.id || ctx.formatExpression(v);
if (
formattedValue[0] === "{" &&
formattedValue[formattedValue.length - 1] === "}"
@@ -623,11 +624,21 @@ export class QWeb {
//------------------------------------------------------------------------------
// Compilation Context
//------------------------------------------------------------------------------
export interface QWebExprVar {
id: string;
expr: string;
}
export interface QWebXMLVar {
xml: NodeList;
}
export type QWebVar = QWebExprVar | QWebXMLVar;
export class Context {
nextID: number = 1;
code: string[] = [];
variables: { [key: string]: any } = {};
definedVariables: { [key: string]: string } = {};
variables: { [key: string]: QWebVar } = {};
escaping: boolean = false;
parentNode: number | null = null;
rootNode: number | null = null;
@@ -744,14 +755,11 @@ export class Context {
} else if (c.match(/\W/) && invar.length) {
// TODO: Should check for possible spaces before dot
if (chars[invarPos - 1] !== "." && RESERVED_WORDS.indexOf(invar) < 0) {
if (!(invar in this.definedVariables)) {
invar =
WORD_REPLACEMENT[invar] ||
(invar in this.variables &&
this.formatExpression(this.variables[invar])) ||
(this.variables[invar] && (<any>this.variables[invar]).id) ||
"context['" + invar + "']";
}
}
r += invar;
invar = "";
} else if (invar.length) {
+30 -27
View File
@@ -1,4 +1,4 @@
import { Context, QWeb, UTILS } from "./qweb_core";
import { Context, QWeb, UTILS, QWebExprVar } from "./qweb_core";
/**
* Owl QWeb Directives
@@ -14,7 +14,6 @@ import { Context, QWeb, UTILS } from "./qweb_core";
* - t-log
*/
//------------------------------------------------------------------------------
// t-esc and t-raw
//------------------------------------------------------------------------------
@@ -30,11 +29,18 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Context) {
return;
}
if (value.xml instanceof NodeList) {
for (let node of Array.from(value.xml)) {
qweb._compileNode(<ChildNode>node, ctx);
}
return;
}
let exprID: string;
if (typeof value === "string") {
let exprID = value;
if (!(value in ctx.definedVariables)) {
exprID = `_${ctx.generateID()}`;
ctx.addLine(`var ${exprID} = ${ctx.formatExpression(value)};`);
} else {
exprID = value.id;
}
ctx.addIf(`${exprID} || ${exprID} === 0`);
if (!ctx.parentNode) {
@@ -58,14 +64,8 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Context) {
ctx.addElse();
qweb._compileChildren(node, ctx);
}
ctx.closeIf();
return;
}
if (value instanceof NodeList) {
for (let node of Array.from(value)) {
qweb._compileNode(<ChildNode>node, ctx);
}
}
}
QWeb.addDirective({
@@ -109,15 +109,21 @@ QWeb.addDirective({
if (value) {
const formattedValue = ctx.formatExpression(value);
if (ctx.variables.hasOwnProperty(variable)) {
ctx.addLine(`${ctx.variables[variable]} = ${formattedValue}`);
ctx.addLine(
`${(<QWebExprVar>ctx.variables[variable]).id} = ${formattedValue}`
);
} else {
const varName = `_${ctx.generateID()}`;
ctx.addLine(`var ${varName} = ${formattedValue};`);
ctx.definedVariables[varName] = formattedValue;
ctx.variables[variable] = varName;
ctx.variables[variable] = {
id: varName,
expr: formattedValue
};
}
} else {
ctx.variables[variable] = node.childNodes;
ctx.variables[variable] = {
xml: node.childNodes
};
}
return true;
}
@@ -189,30 +195,27 @@ QWeb.addDirective({
tempCtx.nextID = ctx.rootContext.nextID;
qweb._compileNode(nodeCopy, tempCtx);
const vars = Object.assign({}, ctx.variables, tempCtx.variables);
var definedVariables = Object.assign(
{},
ctx.definedVariables,
tempCtx.definedVariables
);
ctx.rootContext.nextID = tempCtx.nextID;
// open new scope, if necessary
const hasNewVariables = Object.keys(definedVariables).length > 0;
const hasNewVariables = Object.keys(tempCtx.variables).length > 0;
if (hasNewVariables) {
ctx.addLine("{");
ctx.indent();
}
// add new variables, if any
for (let key in definedVariables) {
ctx.addLine(`let ${key} = ${definedVariables[key]}`);
for (let key in tempCtx.variables) {
const v = tempCtx.variables[key];
if ((<QWebExprVar>v).expr) {
ctx.addLine(`let ${(<QWebExprVar>v).id} = ${(<QWebExprVar>v).expr};`);
}
// todo: handle XML variables...
}
}
// compile sub template
const subCtx = ctx
.subContext("caller", nodeCopy)
.subContext("variables", Object.create(vars))
.subContext("definedVariables", Object.create(definedVariables));
.subContext("variables", Object.create(vars));
qweb._compileNode(nodeTemplate.elem, subCtx);
+5 -11
View File
@@ -585,13 +585,13 @@ exports[`misc global 1`] = `
c5.push({text: _6});
}
{
let _11 = 'bbb'
let _11 = 'bbb';
var _13 = 'agüero';
let c14 = [], p14 = {key:14,attrs:{\\"falló\\": _13},on:{}};
var vn14 = h('Año', p14, c14);
c1.push(vn14);
{
let _15 = 'aaa'
let _15 = 'aaa';
let c16 = [], p16 = {key:16,on:{}};
var vn16 = h('span', p16, c16);
c14.push(vn16);
@@ -611,8 +611,6 @@ exports[`misc global 1`] = `
c17.push({text: \`foo default\`});
}
var _19 = 'bbb';
{
let _19 = 'bbb'
let c20 = [], p20 = {key:20,on:{}};
var vn20 = h('span', p20, c20);
c14.push(vn20);
@@ -623,7 +621,6 @@ exports[`misc global 1`] = `
}
}
}
}
let c21 = [], p21 = {key:21,on:{}};
var vn21 = h('div', p21, c21);
c1.push(vn21);
@@ -756,12 +753,9 @@ exports[`t-call (template calling inherit context 1`] = `
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
var _2 = 1;
{
let _2 = 1
if (_2 || _2 === 0) {
c1.push({text: _2});
}
}
return vn1;
}"
`;
@@ -773,7 +767,7 @@ exports[`t-call (template calling scoped parameters 1`] = `
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
{
let _2 = 42
let _2 = 42;
c1.push({text: \`ok\`});
}
var _3 = context['foo'];
@@ -800,7 +794,7 @@ exports[`t-call (template calling with unused setbody 1`] = `
) {
var h = this.utils.h;
{
let _1 = 3
let _1 = 3;
let c2 = [], p2 = {key:2};
var vn2 = h('div', p2, c2);
c2.push({text: \`ok\`});
@@ -827,7 +821,7 @@ exports[`t-call (template calling with used set body 1`] = `
let c1 = [], p1 = {key:1};
var vn1 = h('span', p1, c1);
{
let _2 = 'ok'
let _2 = 'ok';
if (_2 || _2 === 0) {
c1.push({text: _2});
}