diff --git a/src/qweb/expression_parser.ts b/src/qweb/expression_parser.ts index 32a7a966..f0d8952d 100644 --- a/src/qweb/expression_parser.ts +++ b/src/qweb/expression_parser.ts @@ -81,7 +81,7 @@ const STATIC_TOKEN_MAP: { [key: string]: TKind } = { // note that the space after typeof is relevant. It makes sure that the formatted // expression has a space after typeof -const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;".split(","); +const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ".split(","); type Tokenizer = (expr: string) => Token | false; diff --git a/tests/qweb/qweb_expressions.test.ts b/tests/qweb/qweb_expressions.test.ts index 9c6f8b6a..e713511c 100644 --- a/tests/qweb/qweb_expressions.test.ts +++ b/tests/qweb/qweb_expressions.test.ts @@ -56,6 +56,12 @@ describe("tokenizer", () => { { type: "OPERATOR", value: "..." }, { type: "VALUE", value: "1" } ]); + + expect(tokenize("a in b")).toEqual([ + { type: "SYMBOL", value: "a" }, + { type: "OPERATOR", value: "in " }, + { type: "SYMBOL", value: "b" } + ]); }); test("strings", () => { @@ -134,6 +140,7 @@ describe("expression evaluation", () => { expect(compileExpr("color === 'black'", {})).toBe("scope['color']==='black'"); expect(compileExpr("'li_'+item", {})).toBe("'li_'+scope['item']"); expect(compileExpr("state.val > 1", {})).toBe("scope['state'].val>1"); + expect(compileExpr("a in b", {})).toBe("scope['a']in scope['b']"); }); test("boolean operations", () => {