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, sincecrates/harness/src/cases.rsElemispub(crate). Every document opens with the same zeroing rule the recipe corpus'sRESETuses. At least three cases per group above under each ofltrandrtl, and at least 60 in all, including a case per logical property whose physical twin is on the opposite side underrtl. - The engine side is
fragment_check.rsengine_dumpcopied, not shared. - The browser side is
harness::oracle::Oracle::startandOracle::dump. A case counts only when every browser dump that came back agrees with the others underharness::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 withdom::Document::parseand yields a box tree; browsers are not needed for it. Add one direct test thatcomputed::margin_leftandcomputed::margin_rightswap underrtlformargin-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:
bench/on-lane.sh --lane-only "$PWD" cargo test -p layout --bin logical_properties_checkbench/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.