diff --git a/src/compiler/inline_expressions.ts b/src/compiler/inline_expressions.ts index 5cde7949..e4df91ac 100644 --- a/src/compiler/inline_expressions.ts +++ b/src/compiler/inline_expressions.ts @@ -85,8 +85,10 @@ const STATIC_TOKEN_MAP: { [key: string]: TKind } = Object.assign(Object.create(n }); // note that the space after typeof is relevant. It makes sure that the formatted -// expression has a space after typeof -const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ".split(","); +// expression has a space after typeof. Currently we don't support delete and void +const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ".split( + "," +); type Tokenizer = (expr: string) => Token | false; @@ -344,9 +346,12 @@ export function compileExprToArray(expr: string): Token[] { return tokens; } +// Leading spaces are trimmed during tokenization, so they need to be added back for some values +const paddedValues = new Map([["in ", " in "]]); + export function compileExpr(expr: string): string { return compileExprToArray(expr) - .map((t) => t.value) + .map((t) => paddedValues.get(t.value) || t.value) .join(""); } diff --git a/tests/compiler/inline_expressions.test.ts b/tests/compiler/inline_expressions.test.ts index ae6fe234..06f71c8a 100644 --- a/tests/compiler/inline_expressions.test.ts +++ b/tests/compiler/inline_expressions.test.ts @@ -135,7 +135,7 @@ describe("expression evaluation", () => { expect(compileExpr("color === 'black'")).toBe("ctx['color']==='black'"); expect(compileExpr("'li_'+item")).toBe("'li_'+ctx['item']"); expect(compileExpr("state.val > 1")).toBe("ctx['state'].val>1"); - expect(compileExpr("a in b")).toBe("ctx['a']in ctx['b']"); + expect(compileExpr("a in b")).toBe("ctx['a'] in ctx['b']"); }); test("boolean operations", () => { @@ -215,4 +215,10 @@ describe("expression evaluation", () => { expect(compileExpr("[a, {b, c},d]")).toBe("[ctx['a'],{b:ctx['b'],c:ctx['c']},ctx['d']]"); expect(compileExpr("{a:[b, {c, d: e}]}")).toBe("{a:[ctx['b'],{c:ctx['c'],d:ctx['e']}]}"); }); + + test("preserving spaces where needed for text operators", () => { + expect(compileExpr("new Date()")).toBe("new Date()"); + expect(compileExpr("a.c in b")).toBe("ctx['a'].c in ctx['b']"); + expect(compileExpr("typeof val")).toBe("typeof ctx['val']"); + }); });