From ada30cd5b14d97ac5b0bc4893b5bce797b53a3e9 Mon Sep 17 00:00:00 2001 From: wznmickey Date: Tue, 5 Nov 2024 03:27:25 -0500 Subject: [PATCH] Fix unstoppable empty footnote loop (#5354) (#5364) --- crates/typst-layout/src/flow/compose.rs | 5 ++++- ...e-5354-footnote-empty-frame-infinite-loop.png | Bin 0 -> 2342 bytes tests/suite/layout/flow/footnote.typ | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/ref/issue-5354-footnote-empty-frame-infinite-loop.png diff --git a/crates/typst-layout/src/flow/compose.rs b/crates/typst-layout/src/flow/compose.rs index 932ccc9ad..d49c3fc32 100644 --- a/crates/typst-layout/src/flow/compose.rs +++ b/crates/typst-layout/src/flow/compose.rs @@ -431,6 +431,9 @@ impl<'a, 'b> Composer<'a, 'b, '_, '_> { // Find nested footnotes in the entry. let nested = find_in_frames::(&frames); + // Check if there are any non-empty frames. + let exist_non_empty_frame = frames.iter().any(|f| !f.is_empty()); + // Extract the first frame. let mut iter = frames.into_iter(); let first = iter.next().unwrap(); @@ -440,7 +443,7 @@ impl<'a, 'b> Composer<'a, 'b, '_, '_> { // possible, we then migrate the origin frame to the next region to // uphold the footnote invariant (that marker and entry are on the same // page). If not, we just queue the footnote for the next page. - if first.is_empty() { + if first.is_empty() && exist_non_empty_frame { if migratable { return Err(Stop::Finish(false)); } else { diff --git a/tests/ref/issue-5354-footnote-empty-frame-infinite-loop.png b/tests/ref/issue-5354-footnote-empty-frame-infinite-loop.png new file mode 100644 index 0000000000000000000000000000000000000000..acad56b68b409512e542508268fc805d32bbcc31 GIT binary patch literal 2342 zcmb7`eNYo;9>-&?2DKVJNAZ;?deYWv&a)LgAUPEqIquBaJ13_oIR{VX4mF^2Br(ax zm$9j$7h6=sD7lsv?@BQp9SN3Y7t}yBKy;`^8cZNBL|!DD7m{qUFSoni_(!L6GdHt4 zyR);;+voTFexK*`@3#r3PhBvT#bQm*+nW0k^^{ZhyD5|Dw{*j57AxgtUhc*}$|t;R zo%qk?J1?~dN!i#rOXu~&`9(JlIvW3b{q=0krQaB9ez`V%3@tbP?P#4gtK^BOv1N#ho$k(F!}C2$L?{>oSO%4B;cvN>%_R^)B$}xVchikcRwQ5jEjHU zbAKgxcO}v{gTp~_7pX2Bm{WMXGD8&lVnN5J%>hVXaOln{a+9S|F$?SG5K9cf`G&SC z)q^S|DkYgzp*r_X@*;uR$g2U| z8Ss_B(Gmr~MoAMXYnEVU#rEBOIsMVBu>pE;^h*);r)`T|ZaC%U!NOdfqO(Yj zdAPQT_+1|MhDej>*=e+cc4bSd)%Te$@h_b_#}&>&ues30&~QC;CV+JZz6>bK%gg0v zv1$u{xR!s06FL7uFTOcRq~Lk8j;sZ7cWdx*?5Px=8z6~*jY|f(N91w~)AHAFvKhAa)I{G0VlqutL&GX4 zS^{4ZBx(h29q~fPl8=~xlC;DlZRj{Req7}h0?T=Xo7ZhpSxqx%y;qgbk8BoPfH5oV zEr5Il^4==-&I92AE-^sUWCMs0J?Dx~hdd6rx-z2?<()X7PkmgJ7M_oV#GkvaHIIE) zLF4dK*sn34)9@Fh>({3D*3ZjFR^WC%p{@CIY}SH^obyw6tVQpbX; z1EJN-I8-aiM*H7YqaDC|#^iTKEA>CGCziufDwQe?PtZxz57$y?RcMuFgEYEd z+HS;uFqQ>cVxc-|qK?u4Hi?4FwFm*P@G$+ER-$UK7+B$o9(1+ukv%sTtDhDJ``Loa z^g2A9)oVNbM^=xem6pX=$7Xk!)|aU&$aLCYIfH9-13{f8n|1FOND?NK*dq=;lkVrk z{h?9lBp7uwJjBYFjFF99ddY8$spY)R0TL>?Hh2ie2h zb?%E2^djmJ5Ji+Uh)-xG`By^jl})Zn1GbMJ2=jG}z4kbLd*Wa466tAJKRf)Gi$4Z~ z3*j|9^fTTAttPI$)zZ=xqg;zjk|2}7NIv{NLt`P>wh-wN;61yWN{`d^@Y5jT?NaQ+ zMw3aQi^)08$nRVixD<46Jm_Iz)WoJpC~??gYF8}i*ARYHAO`TbfuB^ zD?9Y5&YLGX`m@(?L-}wd|A15)rc}~~`6R^8C5f*j4>=^l2|qMq53wMZToY?>=@iBnK-ik|BR8679J^I) z3oS4P7hqj3Y&sPtf(Ih(z6jYYh-?Nst>9Z!io)$GK4U+W(#9MoJt}SIeYbZ7DXc!s zD=A7l=k2rt1vVu}1bfRn#vzSA7d~>0}66oWq zqyMgQ@8u}x3F0RO7BWENrg%6F!}DDnx?|-nw(6RYAu`1X0!$+$2?MEP#U-Bu&vNY zGgQ%gpgju?XN7M|lD9!>IxD33Q)w3tP)ShjqN2>VLo&Vtt$^dx_|)_+*VZlr;#$q+ z*%{lAb<*&6;t7$WoDd_zw!ZOf6, C @fn, D @fn, E @fn. + +--- issue-5354-footnote-empty-frame-infinite-loop --- +// Test whether an empty footnote would cause infinite loop +#show footnote.entry: it => {} +#lorem(3) #footnote[A footnote]