Skip to content

fast: Measure text that reaches prepaint unmeasured instead of panicking - #83

Merged
huacnlee merged 2 commits into
longbridge:mainfrom
ylinwind:fast-text-unmeasured-fallback
Oct 22, 2026
Merged

huacnlee merged 2 commits into
longbridge:mainfrom
ylinwind:fast-text-unmeasured-fallback

Conversation

@ylinwind

@ylinwind ylinwind commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

TextLayout::prepaint unwraps the text's measurement and panics with measurement has not been performed on … when there is none. That happens when a text node is marked for remeasuring but no layout computed that frame reaches it, while its element is still prepainted. Two such gaps caused crashes so far:

This PR adds a safety net, so the next such gap degrades one frame instead of aborting the app.

Changes

  • Prepaint: unmeasured text is measured there as plain text in the current text style, at the prepaint bounds (unconstrained if the width is zero), then gets its bounds.
  • Paint: text that is still unmeasured or not prepainted is skipped instead of unwrapped.
  • Each case is logged with the first 32 chars of the text: error! the first time in the process, debug! after that.
  • script/upstream-allowlist: elements/text.rs removed 160 → 164.

Test plan

  • New test fast::tests::text::text_reaching_prepaint_unmeasured_is_measured_there_and_painted: a StyledText whose node never joins the computed tree. It panics without the fix and passes with it.
  • cargo test -p gpui --lib fast::tests::: 280 passed.
  • script/check-upstream: 0 violations.
  • On v0.1.8 (without fast: Restore reparented retained children #68) with a fuzz repro of a list whose rows switch structure, the panic reproduces without this change and is gone with it.

Risk

For the frames that fall back, rich text loses its runs (colors, font overrides, decorations) and may wrap differently from its laid-out size.

🤖 Generated with Claude Code

ylinwind and others added 2 commits October 21, 2026 11:22
Text whose measurement was neither carried over nor taken by Taffy reached
TextLayout::prepaint with no measurement, and upstream's unwrap there
aborted the app ("measurement has not been performed on ..."). The gaps
that caused it are fixed (longbridge#46, longbridge#68); this is a safety net so that the next
one degrades a frame rather than crashing.

TextLayout::prepaint now forwards to fast::text::prepaint_text, which
measures unmeasured text as plain text in the text style in effect at the
prepaint bounds (unconstrained when the width is zero), and paint skips
text that is still not measured and prepainted. Both cases are logged once
as an error, then at debug level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep the elements' prepaint parameters as upstream names them and drop
TextLayout::prepaint, which only forwarded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@huacnlee
huacnlee merged commit 91f60ec into longbridge:main Oct 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants