Skip to content

Commit 23695ab

Browse files
authored
Merge pull request #1120 from HubSpot/aliased-macro-modification
Explicitly defer node when attempting deferring an aliased modification in an imported macro function
2 parents 1963975 + 47405e7 commit 23695ab

7 files changed

Lines changed: 41 additions & 6 deletions

File tree

src/main/java/com/hubspot/jinjava/lib/tag/eager/EagerSetTagStrategy.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.hubspot.jinjava.lib.tag.eager;
22

33
import com.google.common.annotations.Beta;
4+
import com.hubspot.jinjava.interpret.DeferredValueException;
45
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
56
import com.hubspot.jinjava.lib.tag.SetTag;
67
import com.hubspot.jinjava.lib.tag.eager.importing.AliasedEagerImportingStrategy;
@@ -166,6 +167,11 @@ public static String getSuffixToPreserveState(
166167
!AliasedEagerImportingStrategy.isTemporaryImportAlias(variables) &&
167168
!interpreter.getContext().getMetaContextVariables().contains(variables)
168169
) {
170+
if (!interpreter.getContext().containsKey(maybeTemporaryImportAlias.get())) {
171+
throw new DeferredValueException(
172+
"Cannot modify temporary import alias outside of import tag"
173+
);
174+
}
169175
String updateString = getUpdateString(variables);
170176

171177
// Don't need to render because the temporary import alias's value is always deferred, and rendering will do nothing

src/main/java/com/hubspot/jinjava/lib/tag/eager/importing/AliasedEagerImportingStrategy.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,17 @@ public void integrateChild(JinjavaInterpreter child) {
115115
childBindings.remove(temporaryImportAlias);
116116
importingData.getOriginalInterpreter().getContext().remove(temporaryImportAlias);
117117
// Remove meta keys
118-
childBindings.remove(Context.GLOBAL_MACROS_SCOPE_KEY);
119-
childBindings.remove(Context.IMPORT_RESOURCE_ALIAS_KEY);
120-
mapForCurrentContextAlias.putAll(childBindings);
118+
childBindings
119+
.entrySet()
120+
.stream()
121+
.filter(
122+
entry ->
123+
!(
124+
entry.getKey().equals(Context.GLOBAL_MACROS_SCOPE_KEY) ||
125+
entry.getKey().equals(Context.IMPORT_RESOURCE_ALIAS_KEY)
126+
)
127+
)
128+
.forEach(entry -> mapForCurrentContextAlias.put(entry.getKey(), entry.getValue()));
121129
}
122130

123131
@Override

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,4 +1499,14 @@ public void itAllowsVariableSharingAliasName() {
14991499
"allows-variable-sharing-alias-name"
15001500
);
15011501
}
1502+
1503+
@Test
1504+
public void itFailsOnModificationInAliasedMacro() {
1505+
String input = expectedTemplateInterpreter.getFixtureTemplate(
1506+
"fails-on-modification-in-aliased-macro"
1507+
);
1508+
interpreter.render(input);
1509+
// We don't support this
1510+
assertThat(interpreter.getContext().getDeferredNodes()).isNotEmpty();
1511+
}
15021512
}

src/test/java/com/hubspot/jinjava/lib/tag/eager/EagerImportTagTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ public void itDefersTripleLayer() {
344344
context.put("b_val", "b");
345345
context.put("c_val", "c");
346346
String result = interpreter.render(
347-
"{% import 'import-tree-c.jinja' as c %}{{ c|dictsort(false, 'key') }}"
347+
"{% import 'import-tree-c.jinja' as c %}{{ c.b|dictsort(false, 'key') }}{{ c.foo_b }}{{ c.import_resource_path }}"
348348
);
349349
assertThat(interpreter.render("{{ c.b.a.foo_a }}")).isEqualTo("{{ c.b.a.foo_a }}");
350350
assertThat(interpreter.render("{{ c.b.foo_b }}")).isEqualTo("{{ c.b.foo_b }}");
@@ -355,7 +355,7 @@ public void itDefersTripleLayer() {
355355
assertThat(interpreter.render(result).trim())
356356
.isEqualTo(
357357
interpreter.render(
358-
"{% import 'import-tree-c.jinja' as c %}{{ c|dictsort(false, 'key') }}"
358+
"{% import 'import-tree-c.jinja' as c %}{{ c.b|dictsort(false, 'key') }}{{ c.foo_b }}{{ c.import_resource_path }}"
359359
)
360360
);
361361
}

src/test/resources/eager/allows-variable-sharing-alias-name.expected.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
{% set bar = deferred %}{% do __temp_import_alias_854547461__.update({'bar': bar}) %}
33

44
{% set filters = {} %}{% do __temp_import_alias_854547461__.update({'filters': filters}) %}{% do filters.update(deferred) %}
5-
{% do __temp_import_alias_854547461__.update({'bar': bar,'import_resource_path': 'filters.jinja','filters': filters,'foo': 123}) %}{% endfor %}{% set filters = __temp_import_alias_854547461__ %}{% set current_path = '' %}{% enddo %}
5+
{% do __temp_import_alias_854547461__.update({'bar': bar,'foo': 123,'import_resource_path': 'filters.jinja','filters': filters}) %}{% endfor %}{% set filters = __temp_import_alias_854547461__ %}{% set current_path = '' %}{% enddo %}
66

77
{{ filters }}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{% import 'eager/settings.jinja' as shared %}
2+
3+
{% if deferred %}
4+
{{ shared.load_settings() }}
5+
{% endif %}
6+
{{ shared.settings }}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{% set settings = {} %}
2+
3+
{% macro load_settings() %}
4+
{% do settings.put('foo', 'bar') %}
5+
{% endmacro %}

0 commit comments

Comments
 (0)