From 508c867fa8c1284e24772de00f7f23f2b352453a Mon Sep 17 00:00:00 2001 From: jasmith-hs Date: Fri, 26 Jun 2026 11:43:40 -0400 Subject: [PATCH] fix: reconstruct current_path when base template defers before blocks When a base template defers a variable before its block definitions, the eager first pass produced output without {% set current_path = '...' %}, leaving the second pass without a base-template path reference. This would break relative path resolution for any base template using includes or other path-dependent tags. The pathSetter was only written when resolveBlockStubs() added deferred tokens (deferred content inside block bodies). It was not written when the base template itself produced deferred tokens before its blocks (preserveBlocks = true). Fix: also set pathSetter when preserveBlocks is true. Co-Authored-By: Claude Sonnet 4.6 --- .../jinjava/interpret/JinjavaInterpreter.java | 4 +++- .../lib/tag/eager/EagerExtendsTagTest.java | 15 +++++++++++++++ .../base-with-deferred-before-block.html | 4 ++++ ...t-in-base-before-block.expected.expected.jinja | 4 ++++ ...defers-set-in-base-before-block.expected.jinja | 6 ++++++ .../defers-set-in-base-before-block.jinja | 4 ++++ 6 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/tags/eager/extendstag/base-with-deferred-before-block.html create mode 100644 src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.expected.expected.jinja create mode 100644 src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.expected.jinja create mode 100644 src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.jinja diff --git a/src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java b/src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java index 4034ee43c..0e6f90533 100644 --- a/src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java +++ b/src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java @@ -513,7 +513,9 @@ private String render(Node root, boolean processExtendRoots, long renderLimit) { ); } } - if (context.getDeferredTokens().size() > numDeferredTokensBefore) { + if ( + preserveBlocks || context.getDeferredTokens().size() > numDeferredTokensBefore + ) { pathSetter.setValue( EagerReconstructionUtils.buildBlockOrInlineSetTag( RelativePathResolver.CURRENT_PATH_CONTEXT_KEY, diff --git a/src/test/java/com/hubspot/jinjava/lib/tag/eager/EagerExtendsTagTest.java b/src/test/java/com/hubspot/jinjava/lib/tag/eager/EagerExtendsTagTest.java index 93d6c4916..f9a38ce13 100644 --- a/src/test/java/com/hubspot/jinjava/lib/tag/eager/EagerExtendsTagTest.java +++ b/src/test/java/com/hubspot/jinjava/lib/tag/eager/EagerExtendsTagTest.java @@ -124,6 +124,21 @@ public void itReconstructsDeferredOutsideBlockSecondPass() { ); } + @Test + public void itDefersSetInBaseBeforeBlock() { + expectedTemplateInterpreter.assertExpectedOutputNonIdempotent( + "defers-set-in-base-before-block" + ); + } + + @Test + public void itDefersSetInBaseBeforeBlockSecondPass() { + context.put("deferred", "Resolved now"); + expectedTemplateInterpreter.assertExpectedOutput( + "defers-set-in-base-before-block.expected" + ); + } + @Test public void itThrowsWhenDeferredExtendsTag() { interpreter.render( diff --git a/src/test/resources/tags/eager/extendstag/base-with-deferred-before-block.html b/src/test/resources/tags/eager/extendstag/base-with-deferred-before-block.html new file mode 100644 index 000000000..a95db89f1 --- /dev/null +++ b/src/test/resources/tags/eager/extendstag/base-with-deferred-before-block.html @@ -0,0 +1,4 @@ +{% set foo = deferred %} +{{ foo }} +{% block body %} +{% endblock body %} diff --git a/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.expected.expected.jinja b/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.expected.expected.jinja new file mode 100644 index 000000000..03c953931 --- /dev/null +++ b/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.expected.expected.jinja @@ -0,0 +1,4 @@ + +Resolved now + +Hi diff --git a/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.expected.jinja b/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.expected.jinja new file mode 100644 index 000000000..bb5f90f14 --- /dev/null +++ b/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.expected.jinja @@ -0,0 +1,6 @@ +{% set current_path = '../eager/extendstag/base-with-deferred-before-block.html' %}\ +{% set foo = deferred %} +{{ foo }} +{% block body %} +Hi +{% endblock body %} diff --git a/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.jinja b/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.jinja new file mode 100644 index 000000000..795d43e39 --- /dev/null +++ b/src/test/resources/tags/eager/extendstag/defers-set-in-base-before-block.jinja @@ -0,0 +1,4 @@ +{% extends "../eager/extendstag/base-with-deferred-before-block.html" %} +{% block body %} +Hi +{% endblock body %}