Skip to content

Commit a1af87c

Browse files
authored
Merge pull request #1315 from HubSpot/jasmith_hubspot/backport-1312-2.8.x
fix: Backport block tag preservation fix to 2.8.x (#1312)
2 parents ccec95b + 6f50b2d commit a1af87c

19 files changed

Lines changed: 362 additions & 8 deletions

File tree

src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ private String render(Node root, boolean processExtendRoots, long renderLimit) {
429429
output.addNode(pathSetter);
430430
Optional<String> basePath = context.getCurrentPathStack().peek();
431431
StringBuilder ignoredOutput = new StringBuilder();
432+
boolean preserveBlocks = false;
432433
// render all extend parents, keeping the last as the root output
433434
if (processExtendRoots) {
434435
Set<String> extendPaths = new HashSet<>();
@@ -497,10 +498,23 @@ private String render(Node root, boolean processExtendRoots, long renderLimit) {
497498
basePath = Optional.of(currentPath);
498499
}
499500
}
501+
preserveBlocks = (context.getDeferredTokens().size() > numDeferredTokensBefore);
500502
}
501503

502504
int numDeferredTokensBefore = context.getDeferredTokens().size();
503505
resolveBlockStubs(output);
506+
if (preserveBlocks) {
507+
for (BlockPlaceholderOutputNode blockPlaceholder : output.getBlocks()) {
508+
blockPlaceholder.resolve(
509+
EagerReconstructionUtils.wrapInTag(
510+
blockPlaceholder.getValue(),
511+
"block %s".formatted(blockPlaceholder.getBlockName()),
512+
this,
513+
false
514+
)
515+
);
516+
}
517+
}
504518
if (context.getDeferredTokens().size() > numDeferredTokensBefore) {
505519
pathSetter.setValue(
506520
EagerReconstructionUtils.buildBlockOrInlineSetTag(

src/test/java/com/hubspot/jinjava/EagerTest.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,4 +1754,65 @@ public void itHandlesDeferredValueInRenderFilter() {
17541754
"handles-deferred-value-in-render-filter/test"
17551755
);
17561756
}
1757+
1758+
@Test
1759+
public void itHandlesDeferredUsedInMultipleBlockLevels() {
1760+
expectedTemplateInterpreter.assertExpectedOutputNonIdempotent(
1761+
"handles-deferred-used-in-multiple-block-levels/test"
1762+
);
1763+
}
1764+
1765+
@Test
1766+
public void itHandlesDeferredUsedInMultipleBlockLevelsSecondPass() {
1767+
localContext.put("deferred", "resolved");
1768+
expectedTemplateInterpreter.assertExpectedOutput(
1769+
"handles-deferred-used-in-multiple-block-levels/test.expected"
1770+
);
1771+
expectedTemplateInterpreter.assertExpectedNonEagerOutput(
1772+
"handles-deferred-used-in-multiple-block-levels/test.expected"
1773+
);
1774+
}
1775+
1776+
@Test
1777+
public void itDoesNotDeferBlockWhenOnlyMiddleDefers() {
1778+
expectedTemplateInterpreter.assertExpectedOutputNonIdempotent(
1779+
"does-not-defer-block-when-only-middle-defers/test"
1780+
);
1781+
}
1782+
1783+
@Test
1784+
public void itDoesNotDeferBlockWhenOnlyMiddleDefersSecondPass() {
1785+
localContext.put("deferred", "resolved");
1786+
expectedTemplateInterpreter.assertExpectedOutput(
1787+
"does-not-defer-block-when-only-middle-defers/test.expected"
1788+
);
1789+
expectedTemplateInterpreter.assertExpectedNonEagerOutput(
1790+
"does-not-defer-block-when-only-middle-defers/test.expected"
1791+
);
1792+
}
1793+
1794+
@Test
1795+
public void itPreservesBlocksForReconstructionOrder() {
1796+
expectedTemplateInterpreter.assertExpectedOutputNonIdempotent(
1797+
"preserves-blocks-for-reconstruction-order/test"
1798+
);
1799+
}
1800+
1801+
@Test
1802+
public void itPreservesBlocksForReconstructionOrderSecondPhase() {
1803+
localContext.put("deferred", "resolved");
1804+
String twoPhaseOutput = expectedTemplateInterpreter.assertExpectedOutput(
1805+
"preserves-blocks-for-reconstruction-order/test.expected"
1806+
);
1807+
expectedTemplateInterpreter.assertExpectedNonEagerOutput(
1808+
"preserves-blocks-for-reconstruction-order/test.expected"
1809+
);
1810+
// Sanity check
1811+
assertThat(twoPhaseOutput)
1812+
.isEqualToIgnoringWhitespace(
1813+
expectedTemplateInterpreter.renderTemplate(
1814+
"preserves-blocks-for-reconstruction-order/test"
1815+
)
1816+
);
1817+
}
17571818
}

src/test/java/com/hubspot/jinjava/ExpectedTemplateInterpreter.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ private ExpectedTemplateInterpreter(
4949
}
5050

5151
public String assertExpectedOutput(String name) {
52-
String template = getFixtureTemplate(name);
53-
String output = JinjavaInterpreter.getCurrent().render(template);
52+
String output = renderTemplate(name);
5453
assertThat(JinjavaInterpreter.getCurrent().getContext().getDeferredNodes())
5554
.as("Ensure no deferred nodes were created")
5655
.isEmpty();
@@ -60,9 +59,13 @@ public String assertExpectedOutput(String name) {
6059
return output;
6160
}
6261

63-
public String assertExpectedOutputNonIdempotent(String name) {
62+
public String renderTemplate(String name) {
6463
String template = getFixtureTemplate(name);
65-
String output = JinjavaInterpreter.getCurrent().render(template);
64+
return JinjavaInterpreter.getCurrent().render(template);
65+
}
66+
67+
public String assertExpectedOutputNonIdempotent(String name) {
68+
String output = renderTemplate(name);
6669
assertThat(JinjavaInterpreter.getCurrent().getContext().getDeferredNodes())
6770
.as("Ensure no deferred nodes were created")
6871
.isEmpty();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{% set tracker_base = '1_base' %}
2+
3+
4+
-----Pre-First-----
5+
{% block first -%}
6+
{%- endblock %}
7+
-----Post-First-----
8+
-----Pre-Second-----
9+
{% block second -%}
10+
{%- endblock %}
11+
-----Post-Second-----
12+
We aren't deferring tracker base.{# This message WILL show up in final output #}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{% extends '../../eager/does-not-defer-block-when-only-middle-defers/base.jinja' %}
2+
{% set tracker_middle = '2_middle' %}
3+
{% block first %}
4+
I WON'T SHOW UP
5+
{% endblock %}
6+
7+
{% block second %}
8+
tracker_base is '1_base': {{ tracker_base }}? {{ tracker_base == '1_base' }}
9+
tracker_middle is 'resolved': {{ tracker_middle }}? {{ tracker_middle == 'resolved' }}
10+
tracker_test is 'resolved': {{ tracker_test }}? {{ tracker_test == 'resolved' }}
11+
{% endblock %}
12+
Deferring tracker middle.{# This message will not show up in final output #}
13+
{% set tracker_middle = deferred %}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-----Pre-First-----
2+
3+
tracker_base is '1_base': 1_base? true
4+
tracker_middle is 'resolved': resolved? true
5+
tracker_test is 'resolved': resolved? true
6+
7+
-----Post-First-----
8+
-----Pre-Second-----
9+
10+
tracker_base is '1_base': 1_base? true
11+
tracker_middle is 'resolved': resolved? true
12+
tracker_test is 'resolved': resolved? true
13+
14+
-----Post-Second-----
15+
We aren't deferring tracker base.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{# Start Label: ignored_output_from_extends #}{% do %}
2+
3+
4+
5+
Deferring tracker test.
6+
{% set tracker_test = deferred %}
7+
8+
9+
10+
11+
12+
Deferring tracker middle.
13+
{% set tracker_middle = deferred %}
14+
{% enddo %}\
15+
{# End Label: ignored_output_from_extends #}{% set current_path = 'eager/does-not-defer-block-when-only-middle-defers/base.jinja' %}
16+
17+
18+
-----Pre-First-----
19+
{% set __temp_meta_current_path_1008935144__,current_path = current_path,'eager/does-not-defer-block-when-only-middle-defers/test.jinja' %}
20+
tracker_base is '1_base': 1_base? true
21+
tracker_middle is 'resolved': {{ tracker_middle }}\
22+
? {{ tracker_middle == 'resolved' }}
23+
tracker_test is 'resolved': {{ tracker_test }}\
24+
? {{ tracker_test == 'resolved' }}
25+
{% set current_path,__temp_meta_current_path_1008935144__ = __temp_meta_current_path_1008935144__,null %}
26+
-----Post-First-----
27+
-----Pre-Second-----
28+
{% set __temp_meta_current_path_245328778__,current_path = current_path,'eager/does-not-defer-block-when-only-middle-defers/middle.jinja' %}
29+
tracker_base is '1_base': 1_base? true
30+
tracker_middle is 'resolved': {{ tracker_middle }}\
31+
? {{ tracker_middle == 'resolved' }}
32+
tracker_test is 'resolved': {{ tracker_test }}\
33+
? {{ tracker_test == 'resolved' }}
34+
{% set current_path,__temp_meta_current_path_245328778__ = __temp_meta_current_path_245328778__,null %}
35+
-----Post-Second-----
36+
We aren't deferring tracker base.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{% extends '../../eager/does-not-defer-block-when-only-middle-defers/middle.jinja' %}
2+
3+
{% set tracker_test = '3_test' %}
4+
{% block first %}
5+
tracker_base is '1_base': {{ tracker_base }}? {{ tracker_base == '1_base' }}
6+
tracker_middle is 'resolved': {{ tracker_middle }}? {{ tracker_middle == 'resolved' }}
7+
tracker_test is 'resolved': {{ tracker_test }}? {{ tracker_test == 'resolved' }}
8+
{% endblock %}
9+
Deferring tracker test.{# This message will not show up in final output #}
10+
{% set tracker_test = deferred %}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{% set tracker_base = '1_base' %}
2+
3+
tracker_base is '1_base': {{ tracker_base }}? {{ tracker_base == '1_base' }}
4+
tracker_middle is 'resolved': {{ tracker_middle }}? {{ tracker_middle == 'resolved' }}
5+
tracker_test is 'resolved': {{ tracker_test }}? {{ tracker_test == 'resolved' }}
6+
-----Pre-First-----
7+
{% block first -%}
8+
tracker_base is 'resolved': {{ tracker_base }}? {{ tracker_base == 'resolved' }}
9+
tracker_middle is 'resolved': {{ tracker_middle }}? {{ tracker_middle == 'resolved' }}
10+
tracker_test is 'resolved': {{ tracker_test }}? {{ tracker_test == 'resolved' }}
11+
{%- endblock %}
12+
-----Post-First-----
13+
tracker_base is '1_base': {{ tracker_base }}? {{ tracker_base == '1_base' }}
14+
tracker_middle is 'resolved': {{ tracker_middle }}? {{ tracker_middle == 'resolved' }}
15+
tracker_test is 'resolved': {{ tracker_test }}? {{ tracker_test == 'resolved' }}
16+
-----Pre-Second-----
17+
{% block second -%}
18+
tracker_base is 'resolved': {{ tracker_base }}? {{ tracker_base == 'resolved' }}
19+
tracker_middle is 'resolved': {{ tracker_middle }}? {{ tracker_middle == 'resolved' }}
20+
tracker_test is 'resolved': {{ tracker_test }}? {{ tracker_test == 'resolved' }}
21+
{%- endblock %}
22+
-----Post-Second-----
23+
Deferring tracker base.{# This message WILL show up in final output #}
24+
{% set tracker_base = deferred %}
25+
tracker_base is 'resolved': {{ tracker_base }}? {{ tracker_base == 'resolved' }}
26+
tracker_middle is 'resolved': {{ tracker_middle }}? {{ tracker_middle == 'resolved' }}
27+
tracker_test is 'resolved': {{ tracker_test }}? {{ tracker_test == 'resolved' }}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{% extends '../../eager/handles-deferred-used-in-multiple-block-levels/base.jinja' %}
2+
{% set tracker_middle = '2_middle' %}
3+
{% block first %}
4+
I WON'T SHOW UP
5+
{% endblock %}
6+
7+
{% block second %}
8+
tracker_base is 'resolved': {{ tracker_base }}? {{ tracker_base == 'resolved' }}
9+
tracker_middle is 'resolved': {{ tracker_middle }}? {{ tracker_middle == 'resolved' }}
10+
tracker_test is 'resolved': {{ tracker_test }}? {{ tracker_test == 'resolved' }}
11+
{% endblock %}
12+
Deferring tracker middle.{# This message will not show up in final output #}
13+
{% set tracker_middle = deferred %}

0 commit comments

Comments
 (0)