Fix panic in spilled block layout (#5085)

This commit is contained in:
Laurenz 2024-10-01 15:32:02 +02:00 committed by GitHub
parent 04df1264ef
commit 3ec5d442d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 6 deletions

View File

@ -403,6 +403,7 @@ impl<'a> MultiChild<'a> {
full: regions.full,
first: regions.size.y,
backlog: vec![],
min_backlog_len: regions.backlog.len(),
});
}
@ -474,6 +475,7 @@ pub struct MultiSpill<'a, 'b> {
first: Abs,
full: Abs,
backlog: Vec<Abs>,
min_backlog_len: usize,
}
impl MultiSpill<'_, '_> {
@ -483,17 +485,18 @@ impl MultiSpill<'_, '_> {
engine: &mut Engine,
regions: Regions,
) -> SourceResult<(Frame, Option<Self>)> {
// We build regions for the whole `MultiChild` with the sizes passed to
// earlier parts of it plus the new regions. Then, we layout the
// complete block, but extract only the suffix that interests us.
// The first region becomes unchangable and committed to our backlog.
self.backlog.push(regions.size.y);
// The remaining regions are ephemeral and may be replaced.
let mut backlog: Vec<_> =
self.backlog.iter().chain(regions.backlog).copied().collect();
// Remove unnecessary backlog items (also to prevent it from growing
// unnecessarily, which would change the region's hash).
while !backlog.is_empty() && backlog.last().copied() == regions.last {
// Remove unnecessary backlog items to prevent it from growing
// unnecessarily, changing the region's hash.
while backlog.len() > self.min_backlog_len
&& backlog.last().copied() == regions.last
{
backlog.pop();
}
@ -513,6 +516,16 @@ impl MultiSpill<'_, '_> {
.into_iter()
.skip(self.backlog.len());
// Ensure that the backlog never shrinks, so that unwrapping below is at
// least fairly safe. Note that the whole region juggling here is
// fundamentally not ideal: It is a compatibility layer between the old
// (all regions provided upfront) & new (each region provided on-demand,
// like an iterator) layout model. This approach is not 100% correct, as
// in the old model later regions could have an effect on earlier
// frames, but it's the best we can do for now, until the multi
// layouters are refactored to the new model.
self.min_backlog_len = self.min_backlog_len.max(backlog.len());
// Save the first frame.
let frame = frames.next().unwrap();

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

View File

@ -76,3 +76,7 @@ Hi
#block(rect(width: 80%, height: 80pt), breakable: false)
#lines(6)
]
--- issue-5024-spill-backlog ---
#set page(columns: 2, height: 50pt)
#columns(2)[Hello]