mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] qweb: t-set directive
This commit reintroduces some tests for the t-set directive and make
them pass. For that, it was necessary to adapt the qweb compiler in
order to get the following behaviors:
A t-set can affect parent contexts (up to the first parent tagged as
boundary) when the key changed is found in one of the parent contexts.
Some context are marked as boundaries in such a way that
- rendering contexts (e.g. components) cannot be modified via a t-set.
- a t-set in a t-call body or in a called template can never change a
context above the t-call context.
Code prettification has been done.
Snapshots have been modified.
This commit is contained in:
committed by
Aaron Bohy
parent
10df0b5f4a
commit
0f2192604c
@@ -274,7 +274,7 @@ export class QWebCompiler {
|
||||
// define blocks and utility functions
|
||||
this.addLine(`let { text, createBlock, list, multi, html, toggler, component } = bdom;`);
|
||||
this.addLine(
|
||||
`let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, shallowEqual } = helpers;`
|
||||
`let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue } = helpers;`
|
||||
);
|
||||
if (this.shouldDefineAssign) {
|
||||
this.addLine(`let assign = Object.assign;`);
|
||||
@@ -308,6 +308,7 @@ export class QWebCompiler {
|
||||
}
|
||||
if (this.shouldProtectScope) {
|
||||
this.addLine(` ctx = Object.create(ctx);`);
|
||||
this.addLine(` ctx[isBoundary] = 1`);
|
||||
}
|
||||
if (this.target.hasCache) {
|
||||
this.addLine(` let cache = ctx.cache || {};`);
|
||||
@@ -815,9 +816,9 @@ export class QWebCompiler {
|
||||
|
||||
compileTCall(ast: ASTTCall, ctx: Context) {
|
||||
let { block, forceNewBlock } = ctx;
|
||||
// this.hasTCall = true;
|
||||
if (ast.body) {
|
||||
this.addLine(`ctx = Object.create(ctx);`);
|
||||
this.addLine(`ctx[isBoundary] = 1;`);
|
||||
const nextId = BlockDescription.nextBlockId;
|
||||
const subCtx: Context = createContext(ctx, { preventRoot: true });
|
||||
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
|
||||
@@ -883,7 +884,7 @@ export class QWebCompiler {
|
||||
} else {
|
||||
value = expr;
|
||||
}
|
||||
this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
|
||||
this.addLine(`setContextValue(ctx, "${ast.name}", ${value});`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,10 @@
|
||||
// Misc types, constants and helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const RESERVED_WORDS = "true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,eval,void,Math,RegExp,Array,Object,Date".split(
|
||||
","
|
||||
);
|
||||
const RESERVED_WORDS =
|
||||
"true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,eval,void,Math,RegExp,Array,Object,Date".split(
|
||||
","
|
||||
);
|
||||
|
||||
const WORD_REPLACEMENT: { [key: string]: string } = Object.assign(Object.create(null), {
|
||||
and: "&&",
|
||||
|
||||
@@ -65,16 +65,34 @@ function prepareList(collection: any): [any[], any[], number, any[]] {
|
||||
const n = values.length;
|
||||
return [keys, values, n, new Array(n)];
|
||||
}
|
||||
|
||||
const isBoundary = Symbol("isBoundary");
|
||||
|
||||
function setContextValue(ctx: { [key: string]: any }, key: string, value: any): void {
|
||||
const ctx0 = ctx;
|
||||
while (!ctx.hasOwnProperty(key) && !ctx.hasOwnProperty(isBoundary)) {
|
||||
const newCtx = ctx.__proto__;
|
||||
if (!newCtx) {
|
||||
ctx = ctx0;
|
||||
break;
|
||||
}
|
||||
ctx = newCtx;
|
||||
}
|
||||
ctx[key] = value;
|
||||
}
|
||||
|
||||
export const UTILS = {
|
||||
// elem,
|
||||
// setText,
|
||||
withDefault,
|
||||
zero: Symbol("zero"),
|
||||
isBoundary,
|
||||
callSlot,
|
||||
capture,
|
||||
// toClassObj,
|
||||
withKey,
|
||||
prepareList,
|
||||
setContextValue,
|
||||
shallowEqual,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user