Skip to content

Commit

Permalink
Fix for range limits
Browse files Browse the repository at this point in the history
Fixes #9120
  • Loading branch information
sebastienros committed Apr 10, 2021
1 parent a990d02 commit f31ed36
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 21 deletions.
63 changes: 63 additions & 0 deletions Fluid.Tests/ForStatementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,69 @@ public async Task ForEvaluatesMemberOptionsOffsetOnly()

Assert.Equal("54", sw.ToString());
}

[Fact]
public async Task NegativeTargetShouldNotRenderLoop()
{
var e = new ForStatement(
new List<Statement> { new TextSpanStatement("x") },
"i",
new RangeExpression(
new LiteralExpression(NumberValue.Create(0)),
new LiteralExpression(NumberValue.Create(-1))
),
null, null, false
);

var sw = new StringWriter();
await e.WriteToAsync(sw, HtmlEncoder.Default, new TemplateContext());

Assert.Equal("", sw.ToString());
}

[Fact]
public async Task InvalidRangeShouldNotRenderLoop()
{
var e = new ForStatement(
new List<Statement> { new TextSpanStatement("x") },
"i",
new RangeExpression(
new LiteralExpression(NumberValue.Create(-10)),
new LiteralExpression(NumberValue.Create(-20))
),
null, null, false
);

var sw = new StringWriter();
await e.WriteToAsync(sw, HtmlEncoder.Default, new TemplateContext());

Assert.Equal("", sw.ToString());
}

[Fact]
public async Task NegativeLimitShouldStripFromEnd()
{
var context = new TemplateContext()
.SetValue("limit", -3)
;

var e = new ForStatement(
new List<Statement> { CreateMemberStatement("i") },
"i",
new RangeExpression(
new LiteralExpression(NumberValue.Create(1)),
new LiteralExpression(NumberValue.Create(9))
),
new MemberExpression(new IdentifierSegment("limit")),
offset: null,
false
);

var sw = new StringWriter();
await e.WriteToAsync(sw, HtmlEncoder.Default, context);

Assert.Equal("123456", sw.ToString());
}

static Statement CreateMemberStatement(string p)
{
Expand Down
36 changes: 15 additions & 21 deletions Fluid/Ast/ForStatement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ public ForStatement(
public bool Reversed { get; }
public Statement Else { get; }

private List<FluidValue> _rangeElements;
private int _rangeStart, _rangeEnd;

public override async ValueTask<Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context)
{
List<FluidValue> list = null;
Expand All @@ -68,26 +65,14 @@ public override async ValueTask<Completion> WriteToAsync(TextWriter writer, Text
}
else if (Range != null)
{
int start = Convert.ToInt32((await Range.From.EvaluateAsync(context)).ToNumberValue());
int end = Convert.ToInt32((await Range.To.EvaluateAsync(context)).ToNumberValue());
var start = Convert.ToInt32((await Range.From.EvaluateAsync(context)).ToNumberValue());
var end = Convert.ToInt32((await Range.To.EvaluateAsync(context)).ToNumberValue());

// Cache range
if (_rangeElements == null || _rangeStart != start || _rangeEnd != end)
{
_rangeElements = new List<FluidValue>(end - start);
list = new List<FluidValue>(Math.Max(1, end - start));

for (var i = start; i <= end; i++)
{
_rangeElements.Add(NumberValue.Create(i));
}

list = _rangeElements;
_rangeStart = start;
_rangeEnd = end;
}
else
for (var i = start; i <= end; i++)
{
list = _rangeElements;
list.Add(NumberValue.Create(i));
}
}

Expand All @@ -113,7 +98,16 @@ public override async ValueTask<Completion> WriteToAsync(TextWriter writer, Text
if (Limit is not null)
{
var limit = (int) (await Limit.EvaluateAsync(context)).ToNumberValue();
count = Math.Min(count, limit);

// Limit can be negative
if (limit >= 0)
{
count = Math.Min(count, limit);
}
else
{
count = Math.Max(0, count + limit);
}
}

if (count == 0)
Expand Down

0 comments on commit f31ed36

Please sign in to comment.