From b31b71f3a076bfc4278daad442203a9c51c6e676 Mon Sep 17 00:00:00 2001 From: Pascal Date: Wed, 9 Sep 2026 09:08:27 +0200 Subject: [PATCH] jinja: treat a null left operand of in as a plain lookup (#28620) Templates that default an optional variable to none and then test its membership in a map hit an error, while the same expression is a normal lookup returning false in Jinja. The undefined counterpart of this case was already handled just above. --- common/jinja/runtime.cpp | 6 ++++++ tests/test-jinja.cpp | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/common/jinja/runtime.cpp b/common/jinja/runtime.cpp index b029925293..49354c7c9c 100644 --- a/common/jinja/runtime.cpp +++ b/common/jinja/runtime.cpp @@ -167,6 +167,12 @@ value binary_expression::execute_impl(context & ctx) { } throw std::runtime_error("Cannot perform operation " + op.value + " on undefined values"); } else if (is_val(left_val) || is_val(right_val)) { + if (!is_val(right_val) && (op.value == "in" || op.value == "not in")) { + // case: none in {'low': 1} + // A null left operand is looked up like any other value. + bool member = test_is_in(); + return mk_val(op.value == "in" ? member : !member); + } if (op.value == "+" || op.value == "~") { value res = mk_val(); if (workaround_concat_null_with_str(res)) { diff --git a/tests/test-jinja.cpp b/tests/test-jinja.cpp index 974a3f9dd8..ab551d7b38 100644 --- a/tests/test-jinja.cpp +++ b/tests/test-jinja.cpp @@ -374,6 +374,24 @@ static void test_expressions(testing & t) { "42" ); + test_template(t, "none in object", + "{{ x in {'low': 1, 'high': 2} }}", + {{"x", nullptr}}, + "False" + ); + + test_template(t, "none not in object", + "{{ x not in {'low': 1, 'high': 2} }}", + {{"x", nullptr}}, + "True" + ); + + test_template(t, "none in array", + "{{ x in [1, none, 3] }}", + {{"x", nullptr}}, + "True" + ); + test_template(t, "dot notation", "{{ user.name }}", {{"user", {{"name", "Bob"}}}},