Skip to content

Commit ea45395

Browse files
committed
Add closeablePushCurrent for the interpreter
1 parent 86be819 commit ea45395

8 files changed

Lines changed: 167 additions & 127 deletions

File tree

src/main/java/com/hubspot/jinjava/Jinjava.java

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.hubspot.jinjava.el.ExtendedSyntaxBuilder;
2121
import com.hubspot.jinjava.el.TruthyTypeConverter;
2222
import com.hubspot.jinjava.el.ext.eager.EagerExtendedSyntaxBuilder;
23+
import com.hubspot.jinjava.interpret.AutoCloseableSupplier.AutoCloseableImpl;
2324
import com.hubspot.jinjava.interpret.Context;
2425
import com.hubspot.jinjava.interpret.FatalTemplateErrorsException;
2526
import com.hubspot.jinjava.interpret.InterpretException;
@@ -245,52 +246,55 @@ public RenderResult renderForResult(
245246
context = new Context(copyGlobalContext(), bindings, renderConfig.getDisabled());
246247
}
247248

248-
JinjavaInterpreter interpreter = globalConfig
249-
.getInterpreterFactory()
250-
.newInstance(this, context, renderConfig);
251-
JinjavaInterpreter.pushCurrent(interpreter);
252-
253-
try {
254-
String result = interpreter.render(template);
255-
return new RenderResult(
256-
result,
257-
interpreter.getContext(),
258-
interpreter.getErrorsCopy()
259-
);
260-
} catch (InterpretException e) {
261-
if (e instanceof TemplateSyntaxException) {
249+
try (
250+
AutoCloseableImpl<JinjavaInterpreter> interpreterAutoCloseable = JinjavaInterpreter
251+
.closeablePushCurrent(
252+
globalConfig.getInterpreterFactory().newInstance(this, context, renderConfig)
253+
)
254+
.get()
255+
) {
256+
JinjavaInterpreter interpreter = interpreterAutoCloseable.value();
257+
try {
258+
String result = interpreter.render(template);
259+
return new RenderResult(
260+
result,
261+
interpreter.getContext(),
262+
interpreter.getErrorsCopy()
263+
);
264+
} catch (InterpretException e) {
265+
if (e instanceof TemplateSyntaxException) {
266+
return new RenderResult(
267+
TemplateError.fromException((TemplateSyntaxException) e),
268+
interpreter.getContext(),
269+
interpreter.getErrorsCopy()
270+
);
271+
}
272+
return new RenderResult(
273+
TemplateError.fromSyntaxError(e),
274+
interpreter.getContext(),
275+
interpreter.getErrorsCopy()
276+
);
277+
} catch (InvalidArgumentException e) {
278+
return new RenderResult(
279+
TemplateError.fromInvalidArgumentException(e),
280+
interpreter.getContext(),
281+
interpreter.getErrorsCopy()
282+
);
283+
} catch (InvalidInputException e) {
262284
return new RenderResult(
263-
TemplateError.fromException((TemplateSyntaxException) e),
285+
TemplateError.fromInvalidInputException(e),
286+
interpreter.getContext(),
287+
interpreter.getErrorsCopy()
288+
);
289+
} catch (Exception e) {
290+
return new RenderResult(
291+
TemplateError.fromException(e),
264292
interpreter.getContext(),
265293
interpreter.getErrorsCopy()
266294
);
267295
}
268-
return new RenderResult(
269-
TemplateError.fromSyntaxError(e),
270-
interpreter.getContext(),
271-
interpreter.getErrorsCopy()
272-
);
273-
} catch (InvalidArgumentException e) {
274-
return new RenderResult(
275-
TemplateError.fromInvalidArgumentException(e),
276-
interpreter.getContext(),
277-
interpreter.getErrorsCopy()
278-
);
279-
} catch (InvalidInputException e) {
280-
return new RenderResult(
281-
TemplateError.fromInvalidInputException(e),
282-
interpreter.getContext(),
283-
interpreter.getErrorsCopy()
284-
);
285-
} catch (Exception e) {
286-
return new RenderResult(
287-
TemplateError.fromException(e),
288-
interpreter.getContext(),
289-
interpreter.getErrorsCopy()
290-
);
291296
} finally {
292297
globalContext.reset();
293-
JinjavaInterpreter.popCurrent();
294298
}
295299
}
296300

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,10 +724,17 @@ public void setRenderDepth(int renderDepth) {
724724
this.renderDepth = renderDepth;
725725
}
726726

727+
public AutoCloseableSupplier<String> closeablePushRenderStack(String template) {
728+
renderStack.push(template);
729+
return AutoCloseableSupplier.of(template, t -> renderStack.pop());
730+
}
731+
732+
@Deprecated
727733
public void pushRenderStack(String template) {
728734
renderStack.push(template);
729735
}
730736

737+
@Deprecated
731738
public String popRenderStack() {
732739
return renderStack.pop();
733740
}

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

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -381,14 +381,18 @@ private String render(Node root, boolean processExtendRoots, long renderLimit) {
381381
output.addNode(new RenderedOutputNode(renderStr));
382382
} else {
383383
OutputNode out;
384-
context.pushRenderStack(renderStr);
385-
try {
386-
out = node.render(this);
387-
} catch (DeferredValueException e) {
388-
context.handleDeferredNode(node);
389-
out = new RenderedOutputNode(node.getMaster().getImage());
384+
try (
385+
AutoCloseableImpl<String> closeable = context
386+
.closeablePushRenderStack(renderStr)
387+
.get()
388+
) {
389+
try {
390+
out = node.render(this);
391+
} catch (DeferredValueException e) {
392+
context.handleDeferredNode(node);
393+
out = new RenderedOutputNode(node.getMaster().getImage());
394+
}
390395
}
391-
context.popRenderStack();
392396
output.addNode(out);
393397
}
394398
} catch (OutputTooBigException e) {
@@ -435,46 +439,50 @@ private String render(Node root, boolean processExtendRoots, long renderLimit) {
435439
break;
436440
}
437441
extendPaths.add(extendPath.orElse(""));
438-
context
439-
.getCurrentPathStack()
440-
.push(
441-
extendPath.orElse(""),
442-
context.getExtendPathStack().getTopLineNumber(),
443-
context.getExtendPathStack().getTopStartPosition()
444-
);
445-
Node parentRoot = extendParentRoots.removeFirst();
446-
if (context.getDeferredTokens().size() > numDeferredTokensBefore) {
447-
ignoredOutput.append(
448-
output
449-
.getNodes()
450-
.stream()
451-
.filter(node -> node instanceof RenderedOutputNode)
452-
.map(OutputNode::getValue)
453-
.collect(Collectors.joining())
454-
);
455-
}
456-
numDeferredTokensBefore = context.getDeferredTokens().size();
457-
output = new OutputList(config.getMaxOutputSize());
458-
output.addNode(pathSetter);
459-
boolean hasNestedExtends = false;
460-
for (Node node : parentRoot.getChildren()) {
461-
lineNumber = node.getLineNumber() - 1; // The line number is off by one when rendering the extend parent
462-
position = node.getStartPosition();
463-
try {
464-
OutputNode out = node.render(this);
465-
output.addNode(out);
466-
if (isExtendsTag(node)) {
467-
hasNestedExtends = true;
442+
try (
443+
AutoCloseableImpl<String> closeableCurrentPath = context
444+
.getCurrentPathStack()
445+
.closeablePush(
446+
extendPath.orElse(""),
447+
context.getExtendPathStack().getTopLineNumber(),
448+
context.getExtendPathStack().getTopStartPosition()
449+
)
450+
.get()
451+
) {
452+
Node parentRoot = extendParentRoots.removeFirst();
453+
if (context.getDeferredTokens().size() > numDeferredTokensBefore) {
454+
ignoredOutput.append(
455+
output
456+
.getNodes()
457+
.stream()
458+
.filter(node -> node instanceof RenderedOutputNode)
459+
.map(OutputNode::getValue)
460+
.collect(Collectors.joining())
461+
);
462+
}
463+
numDeferredTokensBefore = context.getDeferredTokens().size();
464+
output = new OutputList(config.getMaxOutputSize());
465+
output.addNode(pathSetter);
466+
boolean hasNestedExtends = false;
467+
for (Node node : parentRoot.getChildren()) {
468+
lineNumber = node.getLineNumber() - 1; // The line number is off by one when rendering the extend parent
469+
position = node.getStartPosition();
470+
try {
471+
OutputNode out = node.render(this);
472+
output.addNode(out);
473+
if (isExtendsTag(node)) {
474+
hasNestedExtends = true;
475+
}
476+
} catch (OutputTooBigException e) {
477+
addError(TemplateError.fromOutputTooBigException(e));
478+
return output.getValue();
468479
}
469-
} catch (OutputTooBigException e) {
470-
addError(TemplateError.fromOutputTooBigException(e));
471-
return output.getValue();
472480
}
481+
Optional<String> currentExtendPath = context.getExtendPathStack().pop();
482+
extendPath =
483+
hasNestedExtends ? currentExtendPath : context.getExtendPathStack().peek();
484+
basePath = Optional.of(closeableCurrentPath.value());
473485
}
474-
Optional<String> currentExtendPath = context.getExtendPathStack().pop();
475-
extendPath =
476-
hasNestedExtends ? currentExtendPath : context.getExtendPathStack().peek();
477-
basePath = context.getCurrentPathStack().pop();
478486
}
479487
}
480488

@@ -968,10 +976,20 @@ public static Optional<JinjavaInterpreter> getCurrentMaybe() {
968976
return Optional.ofNullable(getCurrent());
969977
}
970978

979+
public static AutoCloseableSupplier<JinjavaInterpreter> closeablePushCurrent(
980+
JinjavaInterpreter interpreter
981+
) {
982+
Stack<JinjavaInterpreter> stack = CURRENT_INTERPRETER.get();
983+
stack.push(interpreter);
984+
return AutoCloseableSupplier.of(interpreter, i -> stack.pop());
985+
}
986+
987+
@Deprecated
971988
public static void pushCurrent(JinjavaInterpreter interpreter) {
972989
CURRENT_INTERPRETER.get().push(interpreter);
973990
}
974991

992+
@Deprecated
975993
public static void popCurrent() {
976994
if (!CURRENT_INTERPRETER.get().isEmpty()) {
977995
CURRENT_INTERPRETER.get().pop();

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,12 @@ public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) {
9898
.getInterpreterFactory()
9999
.newInstance(interpreter);
100100
child.getContext().put(Context.IMPORT_RESOURCE_PATH_KEY, templateFile);
101-
JinjavaInterpreter.pushCurrent(child);
102-
try {
101+
try (
102+
AutoCloseableImpl<JinjavaInterpreter> a = JinjavaInterpreter
103+
.closeablePushCurrent(child)
104+
.get()
105+
) {
103106
child.render(node);
104-
} finally {
105-
JinjavaInterpreter.popCurrent();
106107
}
107108

108109
interpreter.addAllChildErrors(templateFile, child.getErrorsCopy());
@@ -226,7 +227,8 @@ public static AutoCloseableSupplier<Optional<String>> getTemplateFileWithWrapper
226227
try {
227228
return interpreter
228229
.getContext()
229-
.closeablePushFromStack(
230+
.getFromPathStack()
231+
.closeablePush(
230232
templateFile,
231233
tagToken.getLineNumber(),
232234
tagToken.getStartPosition()

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) {
105105
.newInstance(interpreter);
106106
child.getContext().put(Context.IMPORT_RESOURCE_PATH_KEY, templateFile);
107107

108-
JinjavaInterpreter.pushCurrent(child);
109-
110-
try {
108+
try (
109+
AutoCloseableImpl<JinjavaInterpreter> a = JinjavaInterpreter
110+
.closeablePushCurrent(child)
111+
.get()
112+
) {
111113
child.render(node.value());
112-
} finally {
113-
JinjavaInterpreter.popCurrent();
114114
}
115115

116116
interpreter.addAllChildErrors(templateFile, child.getErrorsCopy());

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,13 @@ public String getEagerTagImage(TagToken tagToken, JinjavaInterpreter interpreter
9595
.getInterpreterFactory()
9696
.newInstance(interpreter);
9797
child.getContext().put(Context.IMPORT_RESOURCE_PATH_KEY, templateFile);
98-
JinjavaInterpreter.pushCurrent(child);
9998
String output;
100-
try {
99+
try (
100+
AutoCloseableImpl<JinjavaInterpreter> a = JinjavaInterpreter
101+
.closeablePushCurrent(child)
102+
.get()
103+
) {
101104
output = child.render(node);
102-
} finally {
103-
JinjavaInterpreter.popCurrent();
104105
}
105106

106107
interpreter.addAllChildErrors(templateFile, child.getErrorsCopy());

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,14 @@ public String getEagerTagImage(TagToken tagToken, JinjavaInterpreter interpreter
5959
.getInterpreterFactory()
6060
.newInstance(interpreter);
6161
child.getContext().put(Context.IMPORT_RESOURCE_PATH_KEY, templateFile);
62-
JinjavaInterpreter.pushCurrent(child);
6362
String output;
64-
try {
63+
try (
64+
AutoCloseableImpl<JinjavaInterpreter> a = JinjavaInterpreter
65+
.closeablePushCurrent(child)
66+
.get()
67+
) {
6568
eagerImportingStrategy.setup(child);
6669
output = child.render(node.value());
67-
} finally {
68-
JinjavaInterpreter.popCurrent();
6970
}
7071
interpreter.addAllChildErrors(templateFile, child.getErrorsCopy());
7172
Map<String, Object> childBindings = child.getContext().getSessionBindings();

0 commit comments

Comments
 (0)