Skip to content

fix: reconstruct current_path when base template defers before blocks#1321

Draft
jasmith-hs wants to merge 2 commits into
masterfrom
jasmith/fix-current-path-reconstruction-when-base-defers-v1
Draft

fix: reconstruct current_path when base template defers before blocks#1321
jasmith-hs wants to merge 2 commits into
masterfrom
jasmith/fix-current-path-reconstruction-when-base-defers-v1

Conversation

@jasmith-hs

Copy link
Copy Markdown
Contributor

Description

PR description authored by Claude Code.

Base templates that extends and set a deferred variable before their block
definitions were losing the current_path reference across eager passes. The eager
first pass emitted output without {% set current_path = '...' %}, so the second pass
had no base-template path to resolve relative includes against, breaking path-dependent
tags in any such base template.

The path setter was only written when resolveBlockStubs() added deferred tokens
(deferred content inside block bodies), not when the base template itself deferred
tokens before its blocks.

This PR contains two commits:

  • reconstruct current_path when base template defers before blocks — widens the
    path-setter condition so it also fires when the base template defers before its blocks.
  • only reconstruct current_path when an extends actually deferred — fixes a
    regression from the first commit. preserveBlocks was unsound outside the extends
    loop: numDeferredTokensBefore starts at 0 and is only advanced inside the
    while (!extendParentRoots.isEmpty()) loop, so a template with no extend parents
    never entered the loop and preserveBlocks collapsed to deferredTokens.size() > 0.
    Any deferred template (for, import, set, include, ...) then injected a spurious
    {% set current_path = null %}. The fix gates preserveBlocks on an extends having
    actually been processed, so the path setter only fires in the intended
    base-template-defers-before-blocks case.

BRAVE

Backwards Compatibility

  • The no-extends path now falls back to the original resolveBlockStubs growth check, restoring pre-first-commit behavior.
  • Only the extends + defer-before-blocks case changes: it now correctly emits the current_path setter.

Rollout and Rollback Plan

  • Library change; rolls out with the next jinjava release. Revert the PR to roll back.

Automated Testing

  • Added itDefersSetInBaseBeforeBlock / itDefersSetInBaseBeforeBlockSecondPass covering the base-defers-before-block case.
  • Full suite green: 2130 run, 0 failures (was 279 failures after the first commit alone).

Verification

  • Confirmed the spurious {% set current_path = null %} no longer appears in the previously-failing eager tag tests (EagerForTag, EagerImportTag, EagerSetTag, EagerIncludeTag, EagerFromTag, etc.).

Expect Dependencies to Fail

  • None expected.
REVIEWERS: Please review both the code changes and the answers above, and validate that they match the expectations for BRAVE

jasmith-hs and others added 2 commits June 26, 2026 11:43
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 <noreply@anthropic.com>
The prior commit widened the path-setter condition to fire whenever
preserveBlocks was true. But preserveBlocks was unsound outside the
extends loop: numDeferredTokensBefore is initialized to 0 and only
advanced inside the `while (!extendParentRoots.isEmpty())` loop, so when
a template had no extend parents the loop never ran and preserveBlocks
collapsed to `deferredTokens.size() > 0`. Any deferred template (for,
import, set, include, ...) then injected a spurious
`{% set current_path = null %}`, breaking 279 tests.

Gate preserveBlocks on an extends having actually been processed
(processedExtendRoots) so the path setter only fires in the
base-template-defers-before-blocks case it was meant for. The
no-extends path falls back to the original resolveBlockStubs growth
check, restoring prior behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jasmith-hs jasmith-hs self-assigned this Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant