From d917af4614ef99ab8ea5f114ad0ddace1875f218 Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Wed, 18 May 2022 16:06:52 +0200 Subject: [PATCH] [IMP] compiler: add better support for "in" and "new" operators Previously, the support for the "in" operator was iffy, and "new" was not supported at all, "in" would fail when checking if a nested property was in something else, as the leading space would be stripped, and "new" would fail because the following space would be stripped. This commit fixes that by preserving the significant whitespace where necessary. --- src/compiler/inline_expressions.ts | 11 ++++++++--- tests/compiler/inline_expressions.test.ts | 8 +++++++- 2 files changed, 15 insertions(+), 4 deletions(-) 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']"); + }); });