Fix bugs relating to . and this.

First, I missed some reference checks when I stopped interning names. Fixed
those.

Second, when iterating over an array which contained null elements, the wrong
thing was happening.
This commit is contained in:
Michael Bayne
2018-06-04 16:06:50 -07:00
parent b823ed87c5
commit 4533567303
4 changed files with 21 additions and 16 deletions
@@ -35,9 +35,6 @@ public abstract class BasicCollector implements Mustache.Collector
}
public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
// support both .name and this.name to fetch members
if (name == Template.DOT_NAME || name == Template.THIS_NAME) return THIS_FETCHER;
if (ctx instanceof Map<?,?>) return MAP_FETCHER;
// if the name looks like a number, potentially use one of our 'indexing' fetchers
@@ -73,7 +70,7 @@ public abstract class BasicCollector implements Mustache.Collector
Map<?,?> map = (Map<?,?>)ctx;
if (map.containsKey(name)) return map.get(name);
// special case to allow map entry set to be iterated over
if (name == "entrySet") return map.entrySet();
if ("entrySet".equals(name)) return map.entrySet();
return Template.NO_FETCHER_FOUND;
}
@Override public String toString () {
@@ -113,15 +110,6 @@ public abstract class BasicCollector implements Mustache.Collector
}
};
protected static final Mustache.VariableFetcher THIS_FETCHER = new Mustache.VariableFetcher() {
public Object get (Object ctx, String name) throws Exception {
return ctx;
}
@Override public String toString () {
return "THIS_FETCHER";
}
};
protected static abstract class ArrayHelper implements Mustache.VariableFetcher {
public Object get (Object ctx, String name) throws Exception {
try {
@@ -856,8 +856,10 @@ public class Mustache {
@Override public void execute (Template tmpl, Template.Context ctx, Writer out) {
Object value = tmpl.getValueOrDefault(ctx, _name, _line);
if (value == null) {
throw new MustacheException.Context("No key, method or field with name '" + _name +
"' on line " + _line, _name, _line);
String msg = Template.isThisName(_name) ?
"Resolved '.' to null (which is disallowed), on line " + _line :
"No key, method or field with name '" + _name + "' on line " + _line;
throw new MustacheException.Context(msg, _name, _line);
}
write(out, _escaper.escape(_formatter.format(value)));
}
@@ -240,7 +240,7 @@ public class Template {
// if we reach here, we found nothing in this or our parent contexts...
// if we have a compound key, decompose the value and resolve it step by step
if (name != DOT_NAME && name.indexOf(DOT_NAME) != -1) {
if (!name.equals(DOT_NAME) && name.indexOf(DOT_NAME) != -1) {
return getCompoundValue(ctx, name, line, missingIsNull);
} else {
// otherwise let checkForMissing() decide what to do
@@ -297,6 +297,11 @@ public class Template {
}
protected Object getValueIn (Object data, String name, int line) {
// if we're getting `.` or `this` then just return the whole context; we do this before the
// null check because it may be valid for the context to be null (if we're iterating over a
// list which contains nulls, for example)
if (isThisName(name)) return data;
if (data == null) {
throw new NullPointerException(
"Null context for variable '" + name + "' on line " + line);
@@ -412,6 +417,10 @@ public class Template {
}
}
protected static boolean isThisName (String name) {
return DOT_NAME.equals(name) || THIS_NAME.equals(name);
}
protected static final String DOT_NAME = ".";
protected static final String THIS_NAME = "this";
protected static final String FIRST_NAME = "-first";
@@ -321,6 +321,12 @@ public abstract class SharedTests extends GWTTestCase
execute(context("things", Arrays.asList("bar", "baz", "bif"))));
}
@Test public void testNestedNullThis () {
check("bar!bif", Mustache.compiler().defaultValue("!").
compile("{{#things}}{{.}}{{/things}}").
execute(context("things", Arrays.asList("bar", null, "bif"))));
}
@Test public void testNewlineSkipping () {
testNewlineSkipping("\n");
}