1212import com .hubspot .jinjava .interpret .JinjavaInterpreter .InterpreterScopeClosable ;
1313import com .hubspot .jinjava .lib .fn .MacroFunction ;
1414import com .hubspot .jinjava .lib .tag .MacroTag ;
15- import com .hubspot .jinjava .lib .tag .eager .DeferredToken ;
1615import com .hubspot .jinjava .lib .tag .eager .EagerExecutionResult ;
1716import com .hubspot .jinjava .objects .serialization .PyishObjectMapper ;
1817import com .hubspot .jinjava .tree .Node ;
1918import com .hubspot .jinjava .util .EagerContextWatcher ;
19+ import com .hubspot .jinjava .util .EagerContextWatcher .EagerChildContextConfig ;
2020import com .hubspot .jinjava .util .EagerExpressionResolver .EagerExpressionResult ;
2121import com .hubspot .jinjava .util .EagerReconstructionUtils ;
22- import java .util .HashSet ;
2322import java .util .LinkedHashMap ;
2423import java .util .List ;
2524import java .util .Map ;
2625import java .util .Optional ;
27- import java .util .Set ;
2826import java .util .StringJoiner ;
2927import java .util .concurrent .atomic .AtomicInteger ;
28+ import java .util .function .Supplier ;
3029
3130public class EagerMacroFunction extends MacroFunction {
3231 private AtomicInteger callCount = new AtomicInteger ();
@@ -60,9 +59,19 @@ public Object doEvaluate(
6059 JinjavaInterpreter interpreter = JinjavaInterpreter .getCurrent ();
6160 if (reconstructing ) {
6261 Optional <String > importFile = getImportFile (interpreter );
63- try (InterpreterScopeClosable c = interpreter .enterNonStackingScope ()) {
64- interpreter .getContext ().setDeferredExecutionMode (true );
65- return getEvaluationResult (argMap , kwargMap , varArgs , interpreter );
62+ try (InterpreterScopeClosable c = interpreter .enterScope ()) {
63+ EagerExecutionResult result = eagerEvaluateInDeferredExecutionMode (
64+ () -> getEvaluationResultDirectly (argMap , kwargMap , varArgs , interpreter ),
65+ interpreter
66+ );
67+ if (!result .getResult ().isFullyResolved ()) {
68+ result =
69+ eagerEvaluateInDeferredExecutionMode (
70+ () -> getEvaluationResultDirectly (argMap , kwargMap , varArgs , interpreter ),
71+ interpreter
72+ );
73+ }
74+ return result .asTemplateString ();
6675 } finally {
6776 importFile .ifPresent (
6877 path -> interpreter .getContext ().getCurrentPathStack ().pop ()
@@ -71,21 +80,9 @@ public Object doEvaluate(
7180 }
7281
7382 int currentCallCount = callCount .getAndIncrement ();
74- Set <DeferredToken > addedTokens = new HashSet <>();
75- EagerExecutionResult result = EagerContextWatcher .executeInChildContext (
76- eagerInterpreter -> {
77- EagerExpressionResult expressionResult = EagerExpressionResult .fromSupplier (
78- () -> super .doEvaluate (argMap , kwargMap , varArgs ).toString (),
79- eagerInterpreter
80- );
81- addedTokens .addAll (eagerInterpreter .getContext ().getDeferredTokens ());
82- return expressionResult ;
83- },
84- interpreter ,
85- EagerContextWatcher
86- .EagerChildContextConfig .newBuilder ()
87- .withCheckForContextChanges (!interpreter .getContext ().isDeferredExecutionMode ())
88- .build ()
83+ EagerExecutionResult result = eagerEvaluate (
84+ () -> super .doEvaluate (argMap , kwargMap , varArgs ).toString (),
85+ interpreter
8986 );
9087 if (
9188 !result .getResult ().isFullyResolved () &&
@@ -95,14 +92,11 @@ public Object doEvaluate(
9592 interpreter .getContext ().isDeferredExecutionMode ()
9693 )
9794 ) {
98- // EagerReconstructionUtils.resetSpeculativeBindings(interpreter, result);
99- // interpreter.getContext().removeDeferredTokens(addedTokens);
100- EagerExecutionResult firstRunResult = runLoopOnce (
101- argMap ,
102- kwargMap ,
103- varArgs ,
104- interpreter
105- );
95+ result =
96+ eagerEvaluateInDeferredExecutionMode (
97+ () -> super .doEvaluate (argMap , kwargMap , varArgs ).toString (),
98+ interpreter
99+ );
106100 String tempVarName = MacroFunctionTempVariable .getVarName (
107101 getName (),
108102 hashCode (),
@@ -111,87 +105,64 @@ public Object doEvaluate(
111105 interpreter
112106 .getContext ()
113107 .getParent ()
114- .put (
115- tempVarName ,
116- new MacroFunctionTempVariable (firstRunResult .asTemplateString ())
117- );
108+ .put (tempVarName , new MacroFunctionTempVariable (result .asTemplateString ()));
118109 throw new DeferredParsingException (this , tempVarName );
119- // }
120- //
121- // if (
122- // interpreter.getContext().isDeferredExecutionMode() ||
123- // !result.getSpeculativeBindings().isEmpty()
124- // ) {
125- // return reconstructImage();
126- // EagerReconstructionUtils.resetSpeculativeBindings(interpreter, result);
127- // interpreter.getContext().removeDeferredTokens(addedTokens);
128- // String prefix = "";
129- //
130- // EagerExecutionResult firstRunResult = runLoopOnce(
131- // argMap,
132- // kwargMap,
133- // varArgs,
134- // interpreter
135- // );
136- // if (!firstRunResult.getSpeculativeBindings().isEmpty()) {
137- // // Set<String> toRemove = firstRunResult
138- // // .getSpeculativeBindings()
139- // // .keySet()
140- // // .stream()
141- // // .filter(key -> argMap.containsKey(key) || kwargMap.containsKey(key))
142- // // .collect(Collectors.toSet());
143- // // toRemove.forEach(key -> firstRunResult.getSpeculativeBindings().remove(key));
144- // // Defer any variables that we tried to modify during the loop
145- // prefix = firstRunResult.getPrefixToPreserveState(true);
146- // }
147- // // Run for loop again now that the necessary values have been deferred
148- // EagerExecutionResult secondRunResult = runLoopOnce(
149- // argMap,
150- // kwargMap,
151- // varArgs,
152- // interpreter
153- // );
154- // if (
155- // secondRunResult
156- // .getSpeculativeBindings()
157- // .keySet()
158- // .stream()
159- // .anyMatch(key -> !firstRunResult.getSpeculativeBindings().containsKey(key))
160- // ) {
161- // throw new DeferredValueException(
162- // "Modified values in deferred for loop: " +
163- // String.join(", ", secondRunResult.getSpeculativeBindings().keySet())
164- // );
165- // }
166- // return (
167- // prefix +
168- // EagerReconstructionUtils.wrapInChildScope(
169- // secondRunResult.getResult().toString(true),
170- // interpreter
171- // )
172- // );
173- // }
174110 }
175111 return result .getResult ().toString (true );
176112 }
177113
178- private EagerExecutionResult runLoopOnce (
114+ private String getEvaluationResultDirectly (
179115 Map <String , Object > argMap ,
180116 Map <String , Object > kwargMap ,
181117 List <Object > varArgs ,
182118 JinjavaInterpreter interpreter
119+ ) {
120+ String evaluationResult = getEvaluationResult (argMap , kwargMap , varArgs , interpreter );
121+ interpreter .getContext ().getScope ().remove (KWARGS_KEY );
122+ interpreter .getContext ().getScope ().remove (VARARGS_KEY );
123+ return evaluationResult ;
124+ }
125+
126+ private EagerExecutionResult eagerEvaluate (
127+ Supplier <String > stringSupplier ,
128+ JinjavaInterpreter interpreter
129+ ) {
130+ return eagerEvaluate (
131+ stringSupplier ,
132+ EagerChildContextConfig
133+ .newBuilder ()
134+ .withCheckForContextChanges (!interpreter .getContext ().isDeferredExecutionMode ())
135+ .build (),
136+ interpreter
137+ );
138+ }
139+
140+ private EagerExecutionResult eagerEvaluateInDeferredExecutionMode (
141+ Supplier <String > stringSupplier ,
142+ JinjavaInterpreter interpreter
143+ ) {
144+ return eagerEvaluate (
145+ stringSupplier ,
146+ EagerChildContextConfig
147+ .newBuilder ()
148+ .withForceDeferredExecutionMode (true )
149+ .withTakeNewValue (true )
150+ .withCheckForContextChanges (true )
151+ .build (),
152+ interpreter
153+ );
154+ }
155+
156+ private EagerExecutionResult eagerEvaluate (
157+ Supplier <String > stringSupplier ,
158+ EagerChildContextConfig eagerChildContextConfig ,
159+ JinjavaInterpreter interpreter
183160 ) {
184161 return EagerContextWatcher .executeInChildContext (
185162 eagerInterpreter ->
186- EagerExpressionResult .fromSupplier (
187- () -> super .doEvaluate (argMap , kwargMap , varArgs ).toString (),
188- eagerInterpreter
189- ),
163+ EagerExpressionResult .fromSupplier (stringSupplier , eagerInterpreter ),
190164 interpreter ,
191- EagerContextWatcher
192- .EagerChildContextConfig .newBuilder ()
193- .withForceDeferredExecutionMode (true )
194- .build ()
165+ eagerChildContextConfig
195166 );
196167 }
197168
@@ -292,16 +263,6 @@ public String reconstructImage(String fullName) {
292263 String evaluation = (String ) evaluate (
293264 getArguments ().stream ().map (arg -> DeferredMacroValueImpl .instance ()).toArray ()
294265 );
295-
296- if (!interpreter .getContext ().getDeferredTokens ().isEmpty ()) {
297- evaluation =
298- (String ) evaluate (
299- getArguments ()
300- .stream ()
301- .map (arg -> DeferredMacroValueImpl .instance ())
302- .toArray ()
303- );
304- }
305266 result =
306267 (getStartTag (fullName , interpreter ) + evaluation + getEndTag (interpreter ));
307268 } catch (DeferredValueException e ) {
0 commit comments