Open breenyoung opened 2 years ago
Seems to be the same on 2.1.0
After looking thru the source code for 1.11.5 and an older 1.x version it looks like the 'with' helper changed. It used to unconditionally call 'options.Template(output, arguments[0]);' in which passing '..' would work.
Now in 1.11.5 and onwards it seems to call 'IsTruthyOrNonEmpty' on the argument to support the possibility of an Inverse return, which in turn calls 'IsFalsyOrEmpty' which during it's execution attempts to see if the arg is an IEnumerable and if it is call .Any() on it.
The stacktrace is stemming from there on the attempt to call .Any on '..'
Old 'with' helper:
[Description("with")]
public static void With(TextWriter output, HelperOptions options, dynamic context, params object[] arguments)
{
if (arguments.Length != 1)
{
throw new HandlebarsException("{{with}} helper must have exactly one argument");
}
options.Template(output, arguments[0]);
}
New 'with' helper
[Description("with")]
public static void With(TextWriter output, HelperOptions options, dynamic context, params object[] arguments)
{
if (arguments.Length != 1)
{
throw new HandlebarsException("{{with}} helper must have exactly one argument");
}
if (HandlebarsUtils.IsTruthyOrNonEmpty(arguments[0]))
{
options.Template(output, arguments[0]);
}
else
{
options.Inverse(output, context);
}
}
Further down the stack, IsTruthyOrNonEmpty calls IsFalsyOrNonEmpty and the .Any() check is attempted
public static bool IsFalsyOrEmpty(object value)
{
if(IsFalsy(value))
{
return true;
}
else if (value is IEnumerable && ((IEnumerable)value).OfType<object>().Any() == false) // Blows up here
{
return true;
}
return false;
}
@breenyoung , @pigiax , test below works fine in 2.1.0. The test is based on @breenyoung template. Am I missing something? If so, can you please provide a test that fails?
As for 1.11.5 version, it is not maintained. If you're not able to upgrade to the latest, we can work together to publish a fix to 1.11+ package in case the problem is critical.
[Fact]
public void ObjectEnumeratorWithReferenceToParent()
{
var handlebars = Handlebars.Create();
var source = "{{#each enumerateMe}}{{#with ..}}{{inRoot}} {{/with}}{{/each}}";
var template = handlebars.Compile(source);
var data = new
{
inRoot = 42,
enumerateMe = new
{
foo = "1",
bar = "2"
}
};
var result = template(data);
Assert.Equal("42 42 ", result);
}
Hi guys, was previous using Handlebars.Net 1.0 on project and recently upgraded to 1.11.5 and have noticed one of my previously working templates no longer works. It involves being in a each loop and having to step up into the parent context for a short period using a with block. Is this no longer possible without specifying exactly what you're looking for on the root level.
I've tried swapping out .. with @root and same problem, gives me an error: 'Value cannot be null, Parameter: source'