Skip to content

Commit 1133893

Browse files
authored
Merge pull request #1068 from HubSpot/isolated-striptags-scope
Isolate interpreter scope when rendering value in striptags filter
2 parents ddb9aba + cbeeba1 commit 1133893

2 files changed

Lines changed: 48 additions & 22 deletions

File tree

src/main/java/com/hubspot/jinjava/lib/filter/StripTagsFilter.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,22 @@ public Object filter(Object object, JinjavaInterpreter interpreter, String... ar
3636
}
3737
int numDeferredTokensStart = interpreter.getContext().getDeferredTokens().size();
3838

39-
String val = interpreter.renderFlat((String) object);
40-
if (interpreter.getContext().getDeferredTokens().size() > numDeferredTokensStart) {
41-
throw new DeferredValueException("Deferred in StripTagsFilter");
42-
}
39+
try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope()) {
40+
String val = interpreter.renderFlat((String) object);
41+
if (interpreter.getContext().getDeferredTokens().size() > numDeferredTokensStart) {
42+
throw new DeferredValueException("Deferred in StripTagsFilter");
43+
}
4344

44-
String cleanedVal = Jsoup.parse(val).text();
45-
cleanedVal = Jsoup.clean(cleanedVal, Whitelist.none());
45+
String cleanedVal = Jsoup.parse(val).text();
46+
cleanedVal = Jsoup.clean(cleanedVal, Whitelist.none());
4647

47-
// backwards compatibility with Jsoup.parse
48-
cleanedVal = cleanedVal.replaceAll(" ", " ");
48+
// backwards compatibility with Jsoup.parse
49+
cleanedVal = cleanedVal.replaceAll(" ", " ");
4950

50-
String normalizedVal = WHITESPACE.matcher(cleanedVal).replaceAll(" ");
51+
String normalizedVal = WHITESPACE.matcher(cleanedVal).replaceAll(" ");
5152

52-
return normalizedVal;
53+
return normalizedVal;
54+
}
5355
}
5456

5557
@Override

src/test/java/com/hubspot/jinjava/lib/filter/StripTagsFilterTest.java

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,44 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44
import static org.assertj.core.api.Assertions.assertThatThrownBy;
5-
import static org.mockito.Matchers.anyString;
6-
import static org.mockito.Mockito.*;
5+
import static org.mockito.Mockito.mock;
6+
import static org.mockito.Mockito.when;
77

8+
import com.hubspot.jinjava.Jinjava;
9+
import com.hubspot.jinjava.JinjavaConfig;
10+
import com.hubspot.jinjava.interpret.Context;
811
import com.hubspot.jinjava.interpret.DeferredValueException;
912
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
1013
import com.hubspot.jinjava.lib.tag.eager.DeferredToken;
1114
import com.hubspot.jinjava.tree.parse.DefaultTokenScannerSymbols;
1215
import com.hubspot.jinjava.tree.parse.ExpressionToken;
1316
import java.util.Collections;
1417
import java.util.concurrent.atomic.AtomicInteger;
18+
import org.junit.After;
1519
import org.junit.Before;
1620
import org.junit.Test;
1721
import org.junit.runner.RunWith;
18-
import org.mockito.Answers;
1922
import org.mockito.InjectMocks;
20-
import org.mockito.Mock;
21-
import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
2223
import org.mockito.runners.MockitoJUnitRunner;
2324

2425
@RunWith(MockitoJUnitRunner.class)
2526
public class StripTagsFilterTest {
26-
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
27-
JinjavaInterpreter interpreter;
27+
private JinjavaInterpreter interpreter;
2828

2929
@InjectMocks
30-
StripTagsFilter filter;
30+
private StripTagsFilter filter;
3131

3232
@Before
3333
public void setup() {
34-
when(interpreter.getContext().getDeferredTokens()).thenReturn(Collections.emptySet());
35-
when(interpreter.renderFlat(anyString())).thenAnswer(new ReturnsArgumentAt(0));
34+
JinjavaConfig config = JinjavaConfig.newBuilder().build();
35+
Jinjava jinjava = new Jinjava(config);
36+
this.interpreter = new JinjavaInterpreter(jinjava.newInterpreter());
37+
JinjavaInterpreter.pushCurrent(interpreter);
38+
}
39+
40+
@After
41+
public void teardown() {
42+
JinjavaInterpreter.popCurrent();
3643
}
3744

3845
@Test
@@ -96,10 +103,27 @@ public void itAddsWhitespaceBetweenParagraphTags() {
96103
.isEqualTo("Test Value");
97104
}
98105

106+
@Test
107+
public void itExecutesJinjavaInsideTag() {
108+
assertThat(
109+
filter.filter("{% for i in [1, 2, 3] %}<div>{{i}}</div>{% endfor %}", interpreter)
110+
)
111+
.isEqualTo("1 2 3");
112+
}
113+
114+
@Test
115+
public void itIsolatesJinjavaScopeWhenExecutingCodeInsideTag() {
116+
filter.filter("{% set test = 'hello' %}", interpreter);
117+
assertThat(interpreter.getContext().get("test")).isNull();
118+
}
119+
99120
@Test
100121
public void itThrowsDeferredValueExceptionWhenDeferredTokensAreLeft() {
101122
AtomicInteger counter = new AtomicInteger();
102-
when(interpreter.getContext().getDeferredTokens())
123+
JinjavaInterpreter mockedInterpreter = mock(JinjavaInterpreter.class);
124+
Context mockedContext = mock(Context.class);
125+
when(mockedInterpreter.getContext()).thenReturn(mockedContext);
126+
when(mockedContext.getDeferredTokens())
103127
.thenAnswer(
104128
i ->
105129
counter.getAndIncrement() == 0
@@ -116,7 +140,7 @@ public void itThrowsDeferredValueExceptionWhenDeferredTokensAreLeft() {
116140
)
117141
)
118142
);
119-
assertThatThrownBy(() -> filter.filter("{{ deferred && other }}", interpreter))
143+
assertThatThrownBy(() -> filter.filter("{{ deferred && other }}", mockedInterpreter))
120144
.isInstanceOf(DeferredValueException.class);
121145
}
122146
}

0 commit comments

Comments
 (0)