From 92a0739e357da01e524f4cafeabeaf9656d623d5 Mon Sep 17 00:00:00 2001 From: mnobile Date: Fri, 10 Apr 2026 15:48:05 -0700 Subject: [PATCH 1/2] Fix NPE when calling macros inside ternary with variable condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `else` keyword in Python-style ternaries (`x if cond else y`) is registered with `Symbol.COLON`, causing `nonliteral()` to greedily interpret `var else resolve_url(...)` as the namespace-prefixed function `var:resolve_url`. This made `AstMacroFunction.eval()` fail to find the macro by name, falling through to `super.eval()` with a null base → NPE. The fix adds an image check (`getImage().equals(":")`) so the parser only enters namespace-prefix logic for a literal colon token, not `else`. Co-Authored-By: Claude Opus 4.6 --- .../com/hubspot/jinjava/el/ext/ExtendedParser.java | 2 +- .../com/hubspot/jinjava/lib/tag/MacroTagTest.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/hubspot/jinjava/el/ext/ExtendedParser.java b/src/main/java/com/hubspot/jinjava/el/ext/ExtendedParser.java index 54726af70..6bf8132fb 100644 --- a/src/main/java/com/hubspot/jinjava/el/ext/ExtendedParser.java +++ b/src/main/java/com/hubspot/jinjava/el/ext/ExtendedParser.java @@ -281,7 +281,7 @@ protected AstNode nonliteral() throws ScanException, ParseException { switch (getToken().getSymbol()) { case IDENTIFIER: String name = consumeToken().getImage(); - if (getToken().getSymbol() == COLON) { + if (getToken().getSymbol() == COLON && getToken().getImage().equals(":")) { Symbol lookahead = lookahead(0).getSymbol(); if ( isPossibleExpTest(lookahead) && diff --git a/src/test/java/com/hubspot/jinjava/lib/tag/MacroTagTest.java b/src/test/java/com/hubspot/jinjava/lib/tag/MacroTagTest.java index de95f36d4..394553406 100644 --- a/src/test/java/com/hubspot/jinjava/lib/tag/MacroTagTest.java +++ b/src/test/java/com/hubspot/jinjava/lib/tag/MacroTagTest.java @@ -373,6 +373,19 @@ public void itCorrectlyScopesNestedMacroTags() { } } + @Test + public void itCallsMacroInTernaryWithVariableCondition() { + String template = + "{% macro greet(name) %}Hello {{ name }}{% endmacro %}" + + "{{ greet('world') if myVar else greet('nobody') }}"; + + context.put("myVar", true); + assertThat(jinjava.render(template, context).trim()).isEqualTo("Hello world"); + + context.put("myVar", false); + assertThat(jinjava.render(template, context).trim()).isEqualTo("Hello nobody"); + } + private Node snippet(String jinja) { return new TreeParser(interpreter, jinja).buildTree().getChildren().getFirst(); } From d57126e33ab64a45b55ed805920101a5cb48e1a0 Mon Sep 17 00:00:00 2001 From: mnobile Date: Fri, 10 Apr 2026 16:23:20 -0700 Subject: [PATCH 2/2] Add test for macro in standard ternary (? :) syntax Addresses review feedback to ensure the `?`/`:` ternary also works correctly with macro calls and variable conditions. Co-Authored-By: Claude Opus 4.6 --- .../com/hubspot/jinjava/lib/tag/MacroTagTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/java/com/hubspot/jinjava/lib/tag/MacroTagTest.java b/src/test/java/com/hubspot/jinjava/lib/tag/MacroTagTest.java index 394553406..0d669f5ca 100644 --- a/src/test/java/com/hubspot/jinjava/lib/tag/MacroTagTest.java +++ b/src/test/java/com/hubspot/jinjava/lib/tag/MacroTagTest.java @@ -386,6 +386,19 @@ public void itCallsMacroInTernaryWithVariableCondition() { assertThat(jinjava.render(template, context).trim()).isEqualTo("Hello nobody"); } + @Test + public void itCallsMacroInStandardTernaryWithVariableCondition() { + String template = + "{% macro greet(name) %}Hello {{ name }}{% endmacro %}" + + "{{ myVar ? greet('world') : greet('nobody') }}"; + + context.put("myVar", true); + assertThat(jinjava.render(template, context).trim()).isEqualTo("Hello world"); + + context.put("myVar", false); + assertThat(jinjava.render(template, context).trim()).isEqualTo("Hello nobody"); + } + private Node snippet(String jinja) { return new TreeParser(interpreter, jinja).buildTree().getChildren().getFirst(); }