Skip to content

Commit 57e4b20

Browse files
MackinnonBuckcaptainsafia
authored andcommitted
[Blazor] Fix ExpressionFormatter sometimes generating malformed expression strings (#58799)
1 parent d093754 commit 57e4b20

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

src/Components/Forms/test/ReverseStringBuilderTest.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,24 @@ public void ToString_Works_AfterExceedingStackAllocatedBuffer()
9292
Assert.Equal(1, builder.SequenceSegmentCount);
9393
}
9494

95+
[Fact]
96+
public void ToString_Works_AfterExceedingStackAllocatedBuffer_WithUnusedSpaceInInitialBuffer()
97+
{
98+
const int InitialBufferSize = 64;
99+
var builder = new ReverseStringBuilder(stackalloc char[InitialBufferSize]);
100+
101+
var firstChunk = new string('A', InitialBufferSize - 10);
102+
var secondChunk = new string('B', 20);
103+
104+
builder.InsertFront(firstChunk);
105+
builder.InsertFront(secondChunk);
106+
107+
var expected = secondChunk + firstChunk;
108+
var actual = builder.ToString();
109+
110+
Assert.Equal(expected, actual);
111+
}
112+
95113
[Fact]
96114
public void ToString_Works_AfterExpandingIntoMultipleBuffersFromEstimatedStringSize()
97115
{

src/Components/Shared/src/ExpressionFormatting/ReverseStringBuilder.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal ref struct ReverseStringBuilder
1717
private SequenceSegment? _fallbackSequenceSegment;
1818

1919
// For testing.
20-
internal int SequenceSegmentCount => _fallbackSequenceSegment?.Count() ?? 0;
20+
internal readonly int SequenceSegmentCount => _fallbackSequenceSegment?.Count() ?? 0;
2121

2222
public ReverseStringBuilder(int conservativeEstimatedStringLength)
2323
{
@@ -33,7 +33,7 @@ public ReverseStringBuilder(Span<char> initialBuffer)
3333
_nextEndIndex = _currentBuffer.Length;
3434
}
3535

36-
public bool Empty => _nextEndIndex == _currentBuffer.Length;
36+
public readonly bool Empty => _nextEndIndex == _currentBuffer.Length;
3737

3838
public void InsertFront(scoped ReadOnlySpan<char> span)
3939
{
@@ -60,13 +60,13 @@ public void InsertFront(scoped ReadOnlySpan<char> span)
6060
var newBuffer = s_arrayPool.Rent(sizeToRent);
6161
_fallbackSequenceSegment = new(newBuffer);
6262

63-
_nextEndIndex = newBuffer.Length - _currentBuffer.Length;
64-
_currentBuffer.CopyTo(newBuffer.AsSpan()[_nextEndIndex..]);
65-
_currentBuffer = newBuffer;
63+
var newEndIndex = newBuffer.Length - _currentBuffer.Length + _nextEndIndex;
64+
_currentBuffer[_nextEndIndex..].CopyTo(newBuffer.AsSpan(newEndIndex));
65+
newEndIndex -= span.Length;
66+
span.CopyTo(newBuffer.AsSpan(newEndIndex));
6667

67-
startIndex = _nextEndIndex - span.Length;
68-
span.CopyTo(_currentBuffer[startIndex..]);
69-
_nextEndIndex = startIndex;
68+
_currentBuffer = newBuffer;
69+
_nextEndIndex = newEndIndex;
7070
}
7171
else
7272
{

0 commit comments

Comments
 (0)