This repository has no description
bez specs logical-properties.md
6.0 kB


enabled: true touches: [crates/layout/src/bin/logical_properties_check.rs] depends-on: [] #

logical-properties: measure flow-relative box properties against the three browsers #

The Web Features map (docs/web-features-map.json, feature logical-properties) lists it as unknown (its 266 keys are claimed only through parent rules) with 92 WPT test files under css/css-logical. Stylo maps a logical property (margin-inline-start, padding-block, inline-size, inset-inline, border-block-width) onto the physical property for the box's writing-mode and direction at cascade time, and the accessors in crates/dom/src/computed.rs read only the physical ones (width, margin_left, padding_top, left, border_left_width). So the engine should already lay these out. Nothing in the repository measures it, and the direction-dependent mapping is the part a mistake would hide in: margin-inline-start is the left margin under direction: ltr and the right one under rtl.

This spec adds the measurement and nothing else. If the engine agrees with the browsers, no engine code changes; if it does not, the disagreements are the finding and fixing them is a separate spec, since a fix would edit computed.rs or fragment.rs, which the queued generated-function specs edit and this spec's touches therefore leaves alone.

Scope. In: block-level, non-replaced boxes without text, in normal flow or absolutely positioned, under writing-mode: horizontal-tb and both direction: ltr and rtl (crates/layout/src/width.rs reads direction; the engine lays out no other writing mode, so vertical modes would be a change to the layout substrate, not to this feature). The longhands margin-{inline,block}-{start,end}, padding-{inline,block}-{start,end}, border-{inline,block}-{start,end}-width (with a solid style so the width applies), inset-{inline,block}-{start,end}, inline-size and block-size; the two-value shorthands margin-inline, margin-block, padding-inline, padding-block, inset-inline, inset-block; declarations that mix logical and physical properties for the same side, where the later one wins. Out: min-*/max-*-size (the accessors for the block axis do not exist yet), border-*-color and border-*-style (paint only), float and clear with inline-start/inline-end, text-align: start, overflow-inline, caption-side, resize, contain-intrinsic-* and the border-*-radius corner mappings. The 92 WPT files cover all of those, so the count says how large the feature is, not how much of it this spec exercises. Say so in the binary's module doc.

Build. One file, crates/layout/src/bin/logical_properties_check.rs, with the same shape as crates/layout/src/bin/fragment_check.rs; crates/layout/Cargo.toml needs no edit because src/bin/*.rs is discovered.

  • A const CASES: &[(&str, &str, &str)] of (id, category, html) with literal documents, since crates/harness/src/cases.rs Elem is pub(crate). Every document opens with the same zeroing rule the recipe corpus's RESET uses. At least three cases per group above under each of ltr and rtl, and at least 60 in all, including a case per logical property whose physical twin is on the opposite side under rtl.
  • The engine side is fragment_check.rs engine_dump copied, not shared.
  • The browser side is harness::oracle::Oracle::start and Oracle::dump. A case counts only when every browser dump that came back agrees with the others under harness::compare::compare; a case whose browsers disagree, or that a browser failed to dump, is dropped and listed with the reason. It passes when the engine agrees with every dump that counted.
  • A #[cfg(test)] module checks that ids are unique, categories are non-empty, and each document parses with dom::Document::parse and yields a box tree; browsers are not needed for it. Add one direct test that computed::margin_left and computed::margin_right swap under rtl for margin-inline-start: 7px.
  • The binary exits non-zero when fewer than 30 cases were compared, and zero when some disagree with the engine; those cases are the result.

Where the result goes. The binary's module doc records the counts (cases written, dropped with reasons, compared, passed, per group and direction) and, for each failing case, its id and the cause found in Stylo's output or in computed.rs. No other file records it. The binary prints that record in the exact form the module doc holds it, and the module doc's copy is pasted from a real run's output, never typed or recomputed by hand, because a hand-typed table ended the first two runs of this job on a count that did not add up. A #[cfg(test)] test reads the module doc (include_str! of the source file) and fails when the recorded numbers disagree with each other: the per-group and per-direction passed and compared cells must sum to the summary's totals, compared minus passed must equal the number of failing ids listed, and every listed id must be in CASES. This test needs no browser, so the test stage catches a wrong record before review does. No docs/feature-map.json rule is added: a rule for a check-only result could only be hand-written, which the map counts as partial, and that file is edited by the queued generated-function specs.

Heavy steps go to a build lane and never run on the development box; if no lane answers, report that instead of running locally:

  1. bench/on-lane.sh --lane-only "$PWD" cargo test -p layout --bin logical_properties_check
  2. bench/on-lane.sh --lane-only "$PWD" cargo run --release -p layout --bin logical_properties_check

The model-first steps the generated-function specs carry (ground-truth cache, generation loop, model batches through bench/batch-lane.sh) do not apply: this spec adds no generated function, since Stylo, not engine code, does the mapping.

Gates. cargo test --workspace passes. fragment_check --random stays 227/227: no engine source changes.