Skip to content

Commit ec179b8

Browse files
committed
Use different approach which separates metaContextVariables from overriddenMetaContextVariables.
This makes it so that metaContextVariables never have values get removed from them so that running prepareContext can multiple times without issue
1 parent d49c704 commit ec179b8

16 files changed

Lines changed: 82 additions & 89 deletions

src/main/java/com/hubspot/jinjava/el/ext/eager/EvalResultHolder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ static String reconstructNode(
136136
.getELResolver()
137137
.getValue(context, null, ExtendedParser.INTERPRETER)
138138
).getContext()
139-
.getMetaContextVariables()
139+
.getComputedMetaContextVariables()
140140
.contains(name)
141141
) {
142142
return name;

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

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.common.collect.HashMultimap;
2121
import com.google.common.collect.ImmutableSet;
2222
import com.google.common.collect.SetMultimap;
23+
import com.google.common.collect.Sets;
2324
import com.hubspot.jinjava.lib.Importable;
2425
import com.hubspot.jinjava.lib.expression.DefaultExpressionStrategy;
2526
import com.hubspot.jinjava.lib.expression.ExpressionStrategy;
@@ -34,6 +35,7 @@
3435
import com.hubspot.jinjava.lib.tag.Tag;
3536
import com.hubspot.jinjava.lib.tag.TagLibrary;
3637
import com.hubspot.jinjava.lib.tag.eager.DeferredToken;
38+
import com.hubspot.jinjava.mode.EagerExecutionMode;
3739
import com.hubspot.jinjava.tree.Node;
3840
import com.hubspot.jinjava.util.DeferredValueUtils;
3941
import com.hubspot.jinjava.util.ScopeMap;
@@ -115,9 +117,9 @@ public enum Library {
115117
private boolean throwInterpreterErrors = false;
116118
private boolean partialMacroEvaluation = false;
117119
private boolean unwrapRawOverride = false;
118-
private boolean preparedByExecutionMode = false;
119120
private DynamicVariableResolver dynamicVariableResolver = null;
120121
private final Set<String> metaContextVariables; // These variable names aren't tracked in eager execution
122+
private final Set<String> overriddenNonMetaContextVariables;
121123
private Node currentNode;
122124

123125
public Context() {
@@ -210,6 +212,8 @@ public Context(
210212
new FunctionLibrary(parent == null, disabled.get(Library.FUNCTION));
211213
this.metaContextVariables =
212214
parent == null ? new HashSet<>() : parent.metaContextVariables;
215+
this.overriddenNonMetaContextVariables =
216+
parent == null ? new HashSet<>() : parent.overriddenNonMetaContextVariables;
213217
if (parent != null) {
214218
this.expressionStrategy = parent.expressionStrategy;
215219
this.partialMacroEvaluation = parent.partialMacroEvaluation;
@@ -218,7 +222,6 @@ public Context(
218222
this.deferredExecutionMode = parent.deferredExecutionMode;
219223
this.deferLargeObjects = parent.deferLargeObjects;
220224
this.throwInterpreterErrors = parent.throwInterpreterErrors;
221-
this.preparedByExecutionMode = parent.preparedByExecutionMode;
222225
}
223226
}
224227

@@ -350,10 +353,37 @@ public void addResolvedFunction(String function) {
350353
}
351354
}
352355

356+
@Deprecated
357+
@Beta
353358
public Set<String> getMetaContextVariables() {
354359
return metaContextVariables;
355360
}
356361

362+
@Beta
363+
public Set<String> getComputedMetaContextVariables() {
364+
return Sets.difference(metaContextVariables, overriddenNonMetaContextVariables);
365+
}
366+
367+
@Beta
368+
public void addMetaContextVariables(Collection<String> variables) {
369+
metaContextVariables.addAll(variables);
370+
}
371+
372+
@Beta
373+
public void addNonMetaContextVariables(Collection<String> variables) {
374+
overriddenNonMetaContextVariables.addAll(
375+
variables
376+
.stream()
377+
.filter(var -> !EagerExecutionMode.STATIC_META_CONTEXT_VARIABLES.contains(var))
378+
.collect(Collectors.toList())
379+
);
380+
}
381+
382+
@Beta
383+
public void removeNonMetaContextVariables(Collection<String> variables) {
384+
overriddenNonMetaContextVariables.removeAll(variables);
385+
}
386+
357387
public void handleDeferredNode(Node node) {
358388
if (
359389
JinjavaInterpreter
@@ -827,12 +857,4 @@ public void setCurrentNode(final Node currentNode) {
827857
public boolean isInForLoop() {
828858
return get(ForTag.LOOP) != null;
829859
}
830-
831-
boolean isPreparedByExecutionMode() {
832-
return preparedByExecutionMode;
833-
}
834-
835-
void setPreparedByExecutionMode(boolean preparedByExecutionMode) {
836-
this.preparedByExecutionMode = preparedByExecutionMode;
837-
}
838860
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,7 @@ public JinjavaInterpreter(
111111
this.context = context;
112112
this.config = renderConfig;
113113
this.application = application;
114-
if (!this.context.isPreparedByExecutionMode()) {
115-
this.config.getExecutionMode().prepareContext(this.context);
116-
this.context.setPreparedByExecutionMode(true);
117-
}
114+
this.config.getExecutionMode().prepareContext(this.context);
118115

119116
switch (config.getRandomNumberGeneratorStrategy()) {
120117
case THREAD_LOCAL:

src/main/java/com/hubspot/jinjava/lib/tag/ForTag.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import com.hubspot.jinjava.tree.Node;
3838
import com.hubspot.jinjava.tree.TagNode;
3939
import com.hubspot.jinjava.tree.parse.TagToken;
40-
import com.hubspot.jinjava.util.EagerReconstructionUtils;
4140
import com.hubspot.jinjava.util.ForLoop;
4241
import com.hubspot.jinjava.util.HelperStringTokenizer;
4342
import com.hubspot.jinjava.util.LengthLimitingStringBuilder;
@@ -48,7 +47,6 @@
4847
import java.util.List;
4948
import java.util.Map.Entry;
5049
import java.util.Optional;
51-
import java.util.Set;
5250
import java.util.regex.Matcher;
5351
import java.util.regex.Pattern;
5452
import org.apache.commons.lang3.tuple.Pair;
@@ -165,11 +163,7 @@ public String renderForCollection(
165163
) {
166164
ForLoop loop = ObjectIterator.getLoop(collection);
167165

168-
Set<String> removedMetaContextVariables =
169-
EagerReconstructionUtils.removeMetaContextVariables(
170-
loopVars.stream(),
171-
interpreter.getContext()
172-
);
166+
interpreter.getContext().addNonMetaContextVariables(loopVars);
173167
try (InterpreterScopeClosable c = interpreter.enterScope()) {
174168
if (interpreter.isValidationMode() && !loop.hasNext()) {
175169
loop = ObjectIterator.getLoop(new DummyObject());
@@ -298,10 +292,7 @@ public String renderForCollection(
298292
}
299293
return checkLoopVariable(interpreter, buff);
300294
} finally {
301-
interpreter
302-
.getContext()
303-
.getMetaContextVariables()
304-
.addAll(removedMetaContextVariables);
295+
interpreter.getContext().removeNonMetaContextVariables(loopVars);
305296
}
306297
}
307298

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ private static Collection<String> markDeferredWordsAndFindSources(
378378
}
379379
return !(val instanceof DeferredValue);
380380
})
381-
.filter(prop -> !context.getMetaContextVariables().contains(prop))
381+
.filter(prop -> !context.getComputedMetaContextVariables().contains(prop))
382382
.filter(prop -> {
383383
DeferredValue deferredValue = convertToDeferredValue(context, prop);
384384
context.put(prop, deferredValue);

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,7 @@ private EagerExecutionResult runLoopOnce(
185185
List<String> loopVars = getTag()
186186
.getLoopVarsAndExpression((TagToken) tagNode.getMaster())
187187
.getLeft();
188-
Set<String> removedMetaContextVariables =
189-
EagerReconstructionUtils.removeMetaContextVariables(
190-
loopVars.stream(),
191-
interpreter.getContext()
192-
);
188+
interpreter.getContext().addNonMetaContextVariables(loopVars);
193189
loopVars.forEach(var ->
194190
interpreter.getContext().put(var, DeferredValue.instance())
195191
);
@@ -198,10 +194,7 @@ private EagerExecutionResult runLoopOnce(
198194
renderChildren(tagNode, eagerInterpreter)
199195
);
200196
} finally {
201-
interpreter
202-
.getContext()
203-
.getMetaContextVariables()
204-
.addAll(removedMetaContextVariables);
197+
interpreter.getContext().removeNonMetaContextVariables(loopVars);
205198
if (clearDeferredWords) {
206199
interpreter
207200
.getContext()

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ public String run(TagNode tagNode, JinjavaInterpreter interpreter) {
4040
variables = new String[] { var };
4141
expression = tagNode.getHelpers();
4242
}
43-
44-
EagerReconstructionUtils.removeMetaContextVariables(
45-
Arrays.stream(variables).map(String::trim),
46-
interpreter.getContext()
47-
);
43+
interpreter
44+
.getContext()
45+
.addNonMetaContextVariables(
46+
Arrays.stream(variables).map(String::trim).collect(Collectors.toList())
47+
);
4848

4949
EagerExecutionResult eagerExecutionResult = getEagerExecutionResult(
5050
tagNode,
@@ -167,7 +167,7 @@ public static String getSuffixToPreserveState(
167167
if (
168168
maybeTemporaryImportAlias.isPresent() &&
169169
!AliasedEagerImportingStrategy.isTemporaryImportAlias(variables) &&
170-
!interpreter.getContext().getMetaContextVariables().contains(variables)
170+
!interpreter.getContext().getComputedMetaContextVariables().contains(variables)
171171
) {
172172
if (!interpreter.getContext().containsKey(maybeTemporaryImportAlias.get())) {
173173
if (

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public String getFinalOutput(
7272
Set<String> metaContextVariables = importingData
7373
.getOriginalInterpreter()
7474
.getContext()
75-
.getMetaContextVariables();
75+
.getComputedMetaContextVariables();
7676
// defer imported variables
7777
EagerReconstructionUtils.buildSetTag(
7878
child

src/main/java/com/hubspot/jinjava/mode/EagerExecutionMode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ public void prepareContext(Context context) {
5353
.filter(Optional::isPresent)
5454
.forEach(maybeEagerTag -> context.registerTag(maybeEagerTag.get()));
5555
context.setExpressionStrategy(new EagerExpressionStrategy());
56-
context.getMetaContextVariables().addAll(STATIC_META_CONTEXT_VARIABLES);
56+
context.addMetaContextVariables(STATIC_META_CONTEXT_VARIABLES);
5757
}
5858
}

src/main/java/com/hubspot/jinjava/util/DeferredValueUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ private static void markDeferredProperties(Context context, Set<String> props) {
119119
props
120120
.stream()
121121
.filter(prop -> !(context.get(prop) instanceof DeferredValue))
122-
.filter(prop -> !context.getMetaContextVariables().contains(prop))
122+
.filter(prop -> !context.getComputedMetaContextVariables().contains(prop))
123123
.forEach(prop -> {
124124
Object value = context.get(prop);
125125
if (value != null) {

0 commit comments

Comments
 (0)