mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[REF] qweb: improve variable handling
This commit is contained in:
+18
-10
@@ -518,7 +518,8 @@ export class QWeb {
|
|||||||
// dynamic attributes
|
// dynamic attributes
|
||||||
if (name.startsWith("t-att-")) {
|
if (name.startsWith("t-att-")) {
|
||||||
let attName = name.slice(6);
|
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 (
|
if (
|
||||||
formattedValue[0] === "{" &&
|
formattedValue[0] === "{" &&
|
||||||
formattedValue[formattedValue.length - 1] === "}"
|
formattedValue[formattedValue.length - 1] === "}"
|
||||||
@@ -623,11 +624,21 @@ export class QWeb {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Compilation Context
|
// Compilation Context
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
export interface QWebExprVar {
|
||||||
|
id: string;
|
||||||
|
expr: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QWebXMLVar {
|
||||||
|
xml: NodeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type QWebVar = QWebExprVar | QWebXMLVar;
|
||||||
|
|
||||||
export class Context {
|
export class Context {
|
||||||
nextID: number = 1;
|
nextID: number = 1;
|
||||||
code: string[] = [];
|
code: string[] = [];
|
||||||
variables: { [key: string]: any } = {};
|
variables: { [key: string]: QWebVar } = {};
|
||||||
definedVariables: { [key: string]: string } = {};
|
|
||||||
escaping: boolean = false;
|
escaping: boolean = false;
|
||||||
parentNode: number | null = null;
|
parentNode: number | null = null;
|
||||||
rootNode: number | null = null;
|
rootNode: number | null = null;
|
||||||
@@ -744,13 +755,10 @@ export class Context {
|
|||||||
} else if (c.match(/\W/) && invar.length) {
|
} else if (c.match(/\W/) && invar.length) {
|
||||||
// TODO: Should check for possible spaces before dot
|
// TODO: Should check for possible spaces before dot
|
||||||
if (chars[invarPos - 1] !== "." && RESERVED_WORDS.indexOf(invar) < 0) {
|
if (chars[invarPos - 1] !== "." && RESERVED_WORDS.indexOf(invar) < 0) {
|
||||||
if (!(invar in this.definedVariables)) {
|
invar =
|
||||||
invar =
|
WORD_REPLACEMENT[invar] ||
|
||||||
WORD_REPLACEMENT[invar] ||
|
(this.variables[invar] && (<any>this.variables[invar]).id) ||
|
||||||
(invar in this.variables &&
|
"context['" + invar + "']";
|
||||||
this.formatExpression(this.variables[invar])) ||
|
|
||||||
"context['" + invar + "']";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
r += invar;
|
r += invar;
|
||||||
invar = "";
|
invar = "";
|
||||||
|
|||||||
+55
-52
@@ -1,4 +1,4 @@
|
|||||||
import { Context, QWeb, UTILS } from "./qweb_core";
|
import { Context, QWeb, UTILS, QWebExprVar } from "./qweb_core";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Owl QWeb Directives
|
* Owl QWeb Directives
|
||||||
@@ -14,7 +14,6 @@ import { Context, QWeb, UTILS } from "./qweb_core";
|
|||||||
* - t-log
|
* - t-log
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// t-esc and t-raw
|
// t-esc and t-raw
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -30,42 +29,43 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof value === "string") {
|
if (value.xml instanceof NodeList) {
|
||||||
let exprID = value;
|
for (let node of Array.from(value.xml)) {
|
||||||
if (!(value in ctx.definedVariables)) {
|
|
||||||
exprID = `_${ctx.generateID()}`;
|
|
||||||
ctx.addLine(`var ${exprID} = ${ctx.formatExpression(value)};`);
|
|
||||||
}
|
|
||||||
ctx.addIf(`${exprID} || ${exprID} === 0`);
|
|
||||||
if (!ctx.parentNode) {
|
|
||||||
throw new Error("Should not have a text node without a parent");
|
|
||||||
}
|
|
||||||
if (ctx.escaping) {
|
|
||||||
ctx.addLine(`c${ctx.parentNode}.push({text: ${exprID}});`);
|
|
||||||
} else {
|
|
||||||
let fragID = ctx.generateID();
|
|
||||||
ctx.addLine(`var frag${fragID} = this.utils.getFragment(${exprID})`);
|
|
||||||
let tempNodeID = ctx.generateID();
|
|
||||||
ctx.addLine(`var p${tempNodeID} = {hook: {`);
|
|
||||||
ctx.addLine(
|
|
||||||
` insert: n => n.elm.parentNode.replaceChild(frag${fragID}, n.elm),`
|
|
||||||
);
|
|
||||||
ctx.addLine(`}};`);
|
|
||||||
ctx.addLine(`var vn${tempNodeID} = h('div', p${tempNodeID})`);
|
|
||||||
ctx.addLine(`c${ctx.parentNode}.push(vn${tempNodeID});`);
|
|
||||||
}
|
|
||||||
if (node.childNodes.length) {
|
|
||||||
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._compileNode(<ChildNode>node, ctx);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
let exprID: string;
|
||||||
|
if (typeof value === "string") {
|
||||||
|
exprID = `_${ctx.generateID()}`;
|
||||||
|
ctx.addLine(`var ${exprID} = ${ctx.formatExpression(value)};`);
|
||||||
|
} else {
|
||||||
|
exprID = value.id;
|
||||||
|
}
|
||||||
|
ctx.addIf(`${exprID} || ${exprID} === 0`);
|
||||||
|
if (!ctx.parentNode) {
|
||||||
|
throw new Error("Should not have a text node without a parent");
|
||||||
|
}
|
||||||
|
if (ctx.escaping) {
|
||||||
|
ctx.addLine(`c${ctx.parentNode}.push({text: ${exprID}});`);
|
||||||
|
} else {
|
||||||
|
let fragID = ctx.generateID();
|
||||||
|
ctx.addLine(`var frag${fragID} = this.utils.getFragment(${exprID})`);
|
||||||
|
let tempNodeID = ctx.generateID();
|
||||||
|
ctx.addLine(`var p${tempNodeID} = {hook: {`);
|
||||||
|
ctx.addLine(
|
||||||
|
` insert: n => n.elm.parentNode.replaceChild(frag${fragID}, n.elm),`
|
||||||
|
);
|
||||||
|
ctx.addLine(`}};`);
|
||||||
|
ctx.addLine(`var vn${tempNodeID} = h('div', p${tempNodeID})`);
|
||||||
|
ctx.addLine(`c${ctx.parentNode}.push(vn${tempNodeID});`);
|
||||||
|
}
|
||||||
|
if (node.childNodes.length) {
|
||||||
|
ctx.addElse();
|
||||||
|
qweb._compileChildren(node, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.closeIf();
|
||||||
}
|
}
|
||||||
|
|
||||||
QWeb.addDirective({
|
QWeb.addDirective({
|
||||||
@@ -109,15 +109,21 @@ QWeb.addDirective({
|
|||||||
if (value) {
|
if (value) {
|
||||||
const formattedValue = ctx.formatExpression(value);
|
const formattedValue = ctx.formatExpression(value);
|
||||||
if (ctx.variables.hasOwnProperty(variable)) {
|
if (ctx.variables.hasOwnProperty(variable)) {
|
||||||
ctx.addLine(`${ctx.variables[variable]} = ${formattedValue}`);
|
ctx.addLine(
|
||||||
|
`${(<QWebExprVar>ctx.variables[variable]).id} = ${formattedValue}`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
const varName = `_${ctx.generateID()}`;
|
const varName = `_${ctx.generateID()}`;
|
||||||
ctx.addLine(`var ${varName} = ${formattedValue};`);
|
ctx.addLine(`var ${varName} = ${formattedValue};`);
|
||||||
ctx.definedVariables[varName] = formattedValue;
|
ctx.variables[variable] = {
|
||||||
ctx.variables[variable] = varName;
|
id: varName,
|
||||||
|
expr: formattedValue
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.variables[variable] = node.childNodes;
|
ctx.variables[variable] = {
|
||||||
|
xml: node.childNodes
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -189,30 +195,27 @@ QWeb.addDirective({
|
|||||||
tempCtx.nextID = ctx.rootContext.nextID;
|
tempCtx.nextID = ctx.rootContext.nextID;
|
||||||
qweb._compileNode(nodeCopy, tempCtx);
|
qweb._compileNode(nodeCopy, tempCtx);
|
||||||
const vars = Object.assign({}, ctx.variables, tempCtx.variables);
|
const vars = Object.assign({}, ctx.variables, tempCtx.variables);
|
||||||
var definedVariables = Object.assign(
|
|
||||||
{},
|
|
||||||
ctx.definedVariables,
|
|
||||||
tempCtx.definedVariables
|
|
||||||
);
|
|
||||||
ctx.rootContext.nextID = tempCtx.nextID;
|
ctx.rootContext.nextID = tempCtx.nextID;
|
||||||
|
|
||||||
// open new scope, if necessary
|
// open new scope, if necessary
|
||||||
const hasNewVariables = Object.keys(definedVariables).length > 0;
|
const hasNewVariables = Object.keys(tempCtx.variables).length > 0;
|
||||||
if (hasNewVariables) {
|
if (hasNewVariables) {
|
||||||
ctx.addLine("{");
|
ctx.addLine("{");
|
||||||
ctx.indent();
|
ctx.indent();
|
||||||
}
|
// add new variables, if any
|
||||||
|
for (let key in tempCtx.variables) {
|
||||||
// add new variables, if any
|
const v = tempCtx.variables[key];
|
||||||
for (let key in definedVariables) {
|
if ((<QWebExprVar>v).expr) {
|
||||||
ctx.addLine(`let ${key} = ${definedVariables[key]}`);
|
ctx.addLine(`let ${(<QWebExprVar>v).id} = ${(<QWebExprVar>v).expr};`);
|
||||||
|
}
|
||||||
|
// todo: handle XML variables...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile sub template
|
// compile sub template
|
||||||
const subCtx = ctx
|
const subCtx = ctx
|
||||||
.subContext("caller", nodeCopy)
|
.subContext("caller", nodeCopy)
|
||||||
.subContext("variables", Object.create(vars))
|
.subContext("variables", Object.create(vars));
|
||||||
.subContext("definedVariables", Object.create(definedVariables));
|
|
||||||
|
|
||||||
qweb._compileNode(nodeTemplate.elem, subCtx);
|
qweb._compileNode(nodeTemplate.elem, subCtx);
|
||||||
|
|
||||||
|
|||||||
@@ -585,13 +585,13 @@ exports[`misc global 1`] = `
|
|||||||
c5.push({text: _6});
|
c5.push({text: _6});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let _11 = 'bbb'
|
let _11 = 'bbb';
|
||||||
var _13 = 'agüero';
|
var _13 = 'agüero';
|
||||||
let c14 = [], p14 = {key:14,attrs:{\\"falló\\": _13},on:{}};
|
let c14 = [], p14 = {key:14,attrs:{\\"falló\\": _13},on:{}};
|
||||||
var vn14 = h('Año', p14, c14);
|
var vn14 = h('Año', p14, c14);
|
||||||
c1.push(vn14);
|
c1.push(vn14);
|
||||||
{
|
{
|
||||||
let _15 = 'aaa'
|
let _15 = 'aaa';
|
||||||
let c16 = [], p16 = {key:16,on:{}};
|
let c16 = [], p16 = {key:16,on:{}};
|
||||||
var vn16 = h('span', p16, c16);
|
var vn16 = h('span', p16, c16);
|
||||||
c14.push(vn16);
|
c14.push(vn16);
|
||||||
@@ -611,16 +611,13 @@ exports[`misc global 1`] = `
|
|||||||
c17.push({text: \`foo default\`});
|
c17.push({text: \`foo default\`});
|
||||||
}
|
}
|
||||||
var _19 = 'bbb';
|
var _19 = 'bbb';
|
||||||
{
|
let c20 = [], p20 = {key:20,on:{}};
|
||||||
let _19 = 'bbb'
|
var vn20 = h('span', p20, c20);
|
||||||
let c20 = [], p20 = {key:20,on:{}};
|
c14.push(vn20);
|
||||||
var vn20 = h('span', p20, c20);
|
if (_19 || _19 === 0) {
|
||||||
c14.push(vn20);
|
c20.push({text: _19});
|
||||||
if (_19 || _19 === 0) {
|
} else {
|
||||||
c20.push({text: _19});
|
c20.push({text: \`foo default\`});
|
||||||
} else {
|
|
||||||
c20.push({text: \`foo default\`});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -756,11 +753,8 @@ exports[`t-call (template calling inherit context 1`] = `
|
|||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
var _2 = 1;
|
var _2 = 1;
|
||||||
{
|
if (_2 || _2 === 0) {
|
||||||
let _2 = 1
|
c1.push({text: _2});
|
||||||
if (_2 || _2 === 0) {
|
|
||||||
c1.push({text: _2});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return vn1;
|
return vn1;
|
||||||
}"
|
}"
|
||||||
@@ -773,7 +767,7 @@ exports[`t-call (template calling scoped parameters 1`] = `
|
|||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
{
|
{
|
||||||
let _2 = 42
|
let _2 = 42;
|
||||||
c1.push({text: \`ok\`});
|
c1.push({text: \`ok\`});
|
||||||
}
|
}
|
||||||
var _3 = context['foo'];
|
var _3 = context['foo'];
|
||||||
@@ -800,7 +794,7 @@ exports[`t-call (template calling with unused setbody 1`] = `
|
|||||||
) {
|
) {
|
||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
{
|
{
|
||||||
let _1 = 3
|
let _1 = 3;
|
||||||
let c2 = [], p2 = {key:2};
|
let c2 = [], p2 = {key:2};
|
||||||
var vn2 = h('div', p2, c2);
|
var vn2 = h('div', p2, c2);
|
||||||
c2.push({text: \`ok\`});
|
c2.push({text: \`ok\`});
|
||||||
@@ -827,7 +821,7 @@ exports[`t-call (template calling with used set body 1`] = `
|
|||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('span', p1, c1);
|
var vn1 = h('span', p1, c1);
|
||||||
{
|
{
|
||||||
let _2 = 'ok'
|
let _2 = 'ok';
|
||||||
if (_2 || _2 === 0) {
|
if (_2 || _2 === 0) {
|
||||||
c1.push({text: _2});
|
c1.push({text: _2});
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -184,7 +184,7 @@ describe("t-set", () => {
|
|||||||
test("t-set and t-if", () => {
|
test("t-set and t-if", () => {
|
||||||
qweb.addTemplate(
|
qweb.addTemplate(
|
||||||
"test",
|
"test",
|
||||||
`<div >
|
`<div>
|
||||||
<t t-set="v" t-value="value"/>
|
<t t-set="v" t-value="value"/>
|
||||||
<t t-if="v === 'ok'">grimbergen</t>
|
<t t-if="v === 'ok'">grimbergen</t>
|
||||||
</div>`
|
</div>`
|
||||||
|
|||||||
Reference in New Issue
Block a user