Fix sorting of DeferredLazyReference values that are prefixed before deferred block of code (such as an if tag block) #1193
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Found that there's a bug with how #894 is supposed to work now.
We are checking for
instanceof LazyReference
, when we should be checking forinstanceof DeferredLazyReference
here, as that is how the values are always stored on the context.There wasn't a corresponding test for this behaviour, as the logic in
jinjava/src/main/java/com/hubspot/jinjava/util/EagerReconstructionUtils.java
Line 790 in ec179b8
But that is for when the deferral happens on the same scope level. Since we need to make sure we reconstruct the value on the correct scope. When it's on a higher-level scope, we wait before reconstructing, and that reconstruction happens at the
EagerExecutionResult#getPrefixToPreserveState()
in theif
tag when determining thePrefixToPreserveState
for itself and its children. We need to make sure the{% set %}
tags that prefix the{% if %}
tag are ordered properly, and that is done here by having theDeferredLazyReference
values come after any direct values (additionally sorting if there's recursion among the lazy references too)To elaborate on why we need to wait until we're on the right scope level, we wouldn't want to have a reconstructed result like:
Because then
foo
andbar
wouldn't exist if the if block doesn't get entered, which is wrong. That whole logic isn't changed in this PR, this PR just makes it so that the prefix before the{% if deferred %}
is{% set foo = ['a', 1] %}{% set bar = foo %}
instead of{% set bar = foo %}{% set foo = ['a', 1] %}