Skip to content

Commit

Permalink
Merge pull request #1068 from HubSpot/isolated-striptags-scope
Browse files Browse the repository at this point in the history
Isolate interpreter scope when rendering value in striptags filter
  • Loading branch information
mattcoley authored May 4, 2023
2 parents ddb9aba + cbeeba1 commit 1133893
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 22 deletions.
22 changes: 12 additions & 10 deletions src/main/java/com/hubspot/jinjava/lib/filter/StripTagsFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,22 @@ public Object filter(Object object, JinjavaInterpreter interpreter, String... ar
}
int numDeferredTokensStart = interpreter.getContext().getDeferredTokens().size();

String val = interpreter.renderFlat((String) object);
if (interpreter.getContext().getDeferredTokens().size() > numDeferredTokensStart) {
throw new DeferredValueException("Deferred in StripTagsFilter");
}
try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope()) {
String val = interpreter.renderFlat((String) object);
if (interpreter.getContext().getDeferredTokens().size() > numDeferredTokensStart) {
throw new DeferredValueException("Deferred in StripTagsFilter");
}

String cleanedVal = Jsoup.parse(val).text();
cleanedVal = Jsoup.clean(cleanedVal, Whitelist.none());
String cleanedVal = Jsoup.parse(val).text();
cleanedVal = Jsoup.clean(cleanedVal, Whitelist.none());

// backwards compatibility with Jsoup.parse
cleanedVal = cleanedVal.replaceAll(" ", " ");
// backwards compatibility with Jsoup.parse
cleanedVal = cleanedVal.replaceAll(" ", " ");

String normalizedVal = WHITESPACE.matcher(cleanedVal).replaceAll(" ");
String normalizedVal = WHITESPACE.matcher(cleanedVal).replaceAll(" ");

return normalizedVal;
return normalizedVal;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,44 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.hubspot.jinjava.Jinjava;
import com.hubspot.jinjava.JinjavaConfig;
import com.hubspot.jinjava.interpret.Context;
import com.hubspot.jinjava.interpret.DeferredValueException;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.lib.tag.eager.DeferredToken;
import com.hubspot.jinjava.tree.parse.DefaultTokenScannerSymbols;
import com.hubspot.jinjava.tree.parse.ExpressionToken;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class StripTagsFilterTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
JinjavaInterpreter interpreter;
private JinjavaInterpreter interpreter;

@InjectMocks
StripTagsFilter filter;
private StripTagsFilter filter;

@Before
public void setup() {
when(interpreter.getContext().getDeferredTokens()).thenReturn(Collections.emptySet());
when(interpreter.renderFlat(anyString())).thenAnswer(new ReturnsArgumentAt(0));
JinjavaConfig config = JinjavaConfig.newBuilder().build();
Jinjava jinjava = new Jinjava(config);
this.interpreter = new JinjavaInterpreter(jinjava.newInterpreter());
JinjavaInterpreter.pushCurrent(interpreter);
}

@After
public void teardown() {
JinjavaInterpreter.popCurrent();
}

@Test
Expand Down Expand Up @@ -96,10 +103,27 @@ public void itAddsWhitespaceBetweenParagraphTags() {
.isEqualTo("Test Value");
}

@Test
public void itExecutesJinjavaInsideTag() {
assertThat(
filter.filter("{% for i in [1, 2, 3] %}<div>{{i}}</div>{% endfor %}", interpreter)
)
.isEqualTo("1 2 3");
}

@Test
public void itIsolatesJinjavaScopeWhenExecutingCodeInsideTag() {
filter.filter("{% set test = 'hello' %}", interpreter);
assertThat(interpreter.getContext().get("test")).isNull();
}

@Test
public void itThrowsDeferredValueExceptionWhenDeferredTokensAreLeft() {
AtomicInteger counter = new AtomicInteger();
when(interpreter.getContext().getDeferredTokens())
JinjavaInterpreter mockedInterpreter = mock(JinjavaInterpreter.class);
Context mockedContext = mock(Context.class);
when(mockedInterpreter.getContext()).thenReturn(mockedContext);
when(mockedContext.getDeferredTokens())
.thenAnswer(
i ->
counter.getAndIncrement() == 0
Expand All @@ -116,7 +140,7 @@ public void itThrowsDeferredValueExceptionWhenDeferredTokensAreLeft() {
)
)
);
assertThatThrownBy(() -> filter.filter("{{ deferred && other }}", interpreter))
assertThatThrownBy(() -> filter.filter("{{ deferred && other }}", mockedInterpreter))
.isInstanceOf(DeferredValueException.class);
}
}

0 comments on commit 1133893

Please sign in to comment.