Skip to content

OVFL A 1/2: scroll containers in the engine (overflow auto, scroll, clip; Blink scrollable overflow port) - #96

Open
thejackshelton wants to merge 7 commits into
review/ovfl-a-basefrom
ovfl-a2-engine
Open

thejackshelton wants to merge 7 commits into
review/ovfl-a-basefrom
ovfl-a2-engine

Conversation

@thejackshelton

@thejackshelton thejackshelton commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

OVFL Phase A, part 1 of 2 (T078, binding spec notes/T078-ovfl-spec.md): scroll containers in the layout engine and the translator. Stacked on INL1a (#88–#91); the review base is review/inl1a-lowering (afec4d6, the INL1a top). It lands as the OVFL train after the PNT1 train, together with A2 and Phase B (R14).

What changed

  • Engine values. Overflow gains clip, auto and scroll, and the validator accepts css-overflow-3 §3.1 computed pairs only. hidden, auto and scroll make a scroll container. clip does not: margins still collapse through it, and a flex item keeps its automatic minimum size.
  • overflow.ts. A port of Blink 145.0.7632.6 ScrollableOverflowCalculator (scrollable_overflow_calculator.cc/.h, plus the in-flow bounds in box_fragment_builder.cc 241-366). It computes the scrollable overflow and client size of every scroll container and of the viewport, with no scrollbar gutter.
    • It reads the layout's boxes, so layout() output is byte-identical.
    • Three shapes are refused rather than guessed (OVFL-p): a percentage relative offset inside a scroll container, the same on the root, and a percentage height with collapsing end margins.
    • Planted engine faults gutterReserved and overflowIgnoresPadding (appended).
  • R16. PLACED_LINE_FIELDS names every PlacedLine field the line pass accounts for. A test fails typecheck when the line type gains a field, and fails on a stub extra item kind, so a new line item kind (INL2's atomic inlines) can't be skipped silently. The translated engine can't inspect fields at runtime, so this guard replaces a runtime refusal (PM ruling).
  • Translator. Overflow literals, the FAULT_KEYS append, scrollMetrics and scrollMetricsWithFaults roots, and the engine-overflow suite (3000 generated cases) appended after engine-inline. targets.ts declares the suite.
  • Port registry (R12). docs/ports.json registers scrollable_overflow_calculator.cc, its .h and box_fragment_builder.cc as BSD ports. paint_layer_scrollable_area.cc (LGPL) is a class A reference: the basis is css-overflow-3 §2.2 plus Chrome observation. overflow.ts now cites it as "matches Chrome", not as a port. THIRD_PARTY_NOTICES.md is regenerated.
  • Regenerated outputs are in their own commit (/tmp/heavy-lease.sh pnpm regen, fixed point after 3 passes):
    • the translated Swift and Kotlin engines;
    • the corpus digests, which move because the faults objects gain the two keys (results unchanged);
    • the host lanes.json.
    • Every capture, vector, profile row and pixel output is byte-identical.

What passed

  • pnpm typecheck: pass.
  • pnpm test (heavy lease): 3541 passed, 12 failed. All 12 are the device-record tests (lanes, lanes-records, device-failures, p6a-promotion, lanes-concurrent). They fail only because lanes.json has no fresh device run: device step pending.
    • A first run under machine load (load average 49) also hit pr-review and merge-train failures; both passed on the rerun.
  • engine-overflow is 3000/3000 on Swift and Kotlin (host lanes.json).
  • chrome-ports.test.ts passes, and so does the new overflow.test.ts. The R16 test fails when the guard is removed.

Changed tests and pins, with reasons

  • native-dpr-swift and native-dpr-kotlin suite lists gain engine-overflow (the new suite).
  • corpus-dpr.test.ts gains the suite count.
  • chrome-ports.test.ts: the LGPL entry count goes from 20 to 21 for the new class A entry. R12 requires the entry. The file is outside the spec's allowed list, and the PM accepted it.

Pre-landing review fixes

  • Replaced leaves count in the scrollable overflow. overflow.ts now indexes REPL-a's replaced leaves, and a replaced child of a scroll container counts the way Blink's calculator counts it:
    • it adds its border box (its content is never scrollable overflow);
    • it takes part in the in-flow bounds, with its margins and the end padding;
    • the margin read-back never collapses through it.
  • Atomic inlines are refused by name. refuseLineLevelBoxes throws OverflowRefusal for a box or replaced child of an inline formatting context (INL2's atomic inlines), instead of the plain "no end margin strut" error (R16).
  • Corpus. The engine-overflow suite now generates block-level replaced leaves (1004 of its 3000 cases), so the Swift and Kotlin translations run this code too.
  • Tests. Three new overflow.test.ts tests fail without the fix: a 100x200 image in a 100x50 auto box scrolls 200 high; the in-flow bounds count the image's margins and the end padding; and the refusal.
  • Base. REPL-a (repl-a 5a4c407) is merged forward through review/ovfl-a-base (86c15c9 = inl1a-lowering + repl-a), the new review base, so this PR still reviews OVFL only. That merge resolves four source conflicts by intent (computed-checks, elements, ios-layout, pixel-reference). It is not regenerated: it is a review base only, and this branch regenerates (fixed point after 3 passes).
  • Chrome proof. The overflow-replaced fixture (in A2, OVFL A 2/2: scroll containers in the compiler, viewport propagation and Chrome scroll metrics #97) proves this against Chrome's scroll metrics.

Outside the spec

  • packages/parity/test/p6a-dash-oracle.test.ts: the LayoutBox literal gains INL1a's strut field (merge of the REPL-a base).

🤖 Generated with Claude Code

… with the css-overflow-3 §3.1 computed pair; hidden, auto and scroll make scroll containers, clip does not (no BFC, automatic minimum size kept); overflow.ts ports Blink 145.0.7632.6 ScrollableOverflowCalculator (scrollable_overflow_calculator.cc/.h, box_fragment_builder.cc 241-366 inflow bounds, paint_layer_scrollable_area.cc 968-982) for every scroll container and the viewport with a zero gutter, reading the layout's boxes (layout() output unchanged); engine faults gutterReserved and overflowIgnoresPadding (appended); translator: overflow literals, FAULT_KEYS append, the viewportDirection line dispatch in runEngineCase, scrollMetrics roots, and the engine-overflow suite appended after engine-inline in corpus-dpr.ts (suite-list pins extended)

(cherry picked from commit f7c4b432dfac4637d7556146665f896b3d784b26)
…verflow.ts cites (scrollable_overflow_calculator.cc and .h, box_fragment_builder.cc 241-366 as BSD ports; paint_layer_scrollable_area.cc 968-982 as an LGPL class A reference with its ruling), overflow.ts re-cites the scroll rect as css-overflow-3 §2.2 matching Chrome and names the .h; THIRD_PARTY_NOTICES.md from pnpm notices:gen; chrome-ports.test.ts LGPL count pin 20 -> 21 for the new class A entry; PLACED_LINE_FIELDS with a type-level and stub-item test so a new PlacedLine item kind cannot be skipped (R16)
…e compiler commit so the engine branch's lanes see the suite it adds)
… point after 3 passes). The translated Swift and Kotlin engines and harnesses gain overflow.ts (scrollMetrics roots, overflow literals, the two fault keys); corpus.json and corpus-dpr.json digests move because the faults objects gain gutterReserved and overflowIgnoresPadding (results unchanged) and corpus-dpr gains engine-overflow (3000 cases); host lanes.json: engine-overflow 3000/3000 on Swift and Kotlin. Every capture, vector, profile row and pixel output is byte-identical
…nt in the scrollable overflow, and an atomic inline is a named refusal. overflow.ts indexes REPL-a's replaced leaves; a replaced child adds its border box (ScrollableOverflowForPropagation: its content is never scrollable overflow), takes part in the in-flow bounds with its margins and the end padding, and never collapses through in the margin read-back; a replaced leaf with overflow hidden reports its padding box. refuseLineLevelBoxes throws OverflowRefusal for a box or replaced child of an inline formatting context (R16, INL2's atomic inlines) instead of the plain 'no end margin strut' error. engine-overflow generates block-level replaced leaves (1004 of 3000 cases). overflow.test pins the image in a 100x50 auto box scrolling 200, the in-flow bounds with margins and end padding, and the refusal; all three fail without the fix
…review fixes: /tmp/heavy-lease.sh pnpm regen (fixed point after 3 passes). REPL-a's fixtures get their captures, vectors, pixels and profile rows on the INL1a input model; emitted CSS headers move with the digest; the translated engines gain the replaced-leaf overflow handling; corpus-dpr's engine-overflow digest moves (replaced leaves in its generated cases); host lanes.json and the north star
@thejackshelton
thejackshelton changed the base branch from review/inl1a-lowering to review/ovfl-a-base October 4, 2026 02:06
thejackshelton added a commit that referenced this pull request Oct 4, 2026
…-a2: ios-layout.ts's Lowerer carries both the propagated overflow source and the image naturals; explain keeps REPL-a's forced-over losing reasons and OVFL's supportOfRow note; the overflow fixture group follows replaced; pixel-reference pins carry REPL-a's +4 terms before OVFL's; web.json keeps this side (pnpm regen rewrites it)
thejackshelton added a commit that referenced this pull request Oct 4, 2026
…n auto scroll containers (a tall image, margins with padding and border, a relatively positioned image, flex items with an overflow: hidden image), proving the #96 review fix against Chrome's scroll metrics; ovfl-metrics case count 22 -> 24
thejackshelton added a commit that referenced this pull request Oct 4, 2026
 review fixes: /tmp/heavy-lease.sh pnpm regen (fixed point). New files for overflow-replaced (both directions: captures at 4 DPRs, vectors, breaks, pixels, emitted CSS, expected-scroll; engine equals Chrome on every container at 1, 2, 3 and 2.625); the OVFL fixtures' captures gain REPL-a's object-fit and object-position longhands; emitted CSS and font headers move with the digest; profiles, tailwind-sweep, corpus, lanes.json and the north star (errors 319 -> 310 with REPL-a's images)
thejackshelton added a commit that referenced this pull request Oct 8, 2026
OVFL A: scroll containers (overflow auto, scroll, clip), viewport propagation and Chrome scroll metrics, rebuilt on master (supersedes #96/#97)

This branch has not been deployed

No deployments
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.

1 participant