enabled: true touches: [crates/layout/src/bin/custom_properties_check.rs] depends-on: [] #
custom-properties: measure --* and var() against the three browsers #
The Web Features map (docs/web-features-map.json, feature custom-properties) lists it
as none with 249 WPT test files under css/css-variables. Substitution of var(), fallbacks, inheritance
and cycle detection all happen in Stylo's cascade (crates/dom/src/style.rs hands it the
author stylesheets and reads back computed values), so the engine's layout should already
see the substituted value in width, margin-*, padding-* and the rest. Nothing in the
repository measures that, so the map cannot claim it and a regression would go unseen.
This spec adds the measurement and nothing else. The smallest thing that stands on its
own is a corpus and a check binary: if the engine already agrees with the browsers, no
engine code changes; if it does not, the disagreements are the finding, and fixing them is
a separate spec, because a fix would edit crates/dom/src/computed.rs or
crates/layout/src/fragment.rs, which the queued generated-function specs edit and which
this spec's touches therefore leaves alone.
Scope. In: block-level, non-replaced boxes without text, in normal flow or absolutely
positioned, where every declaration reaching layout is a length, a percentage or auto
after substitution. Custom properties declared on the box itself, on an ancestor and on
:root; inheritance and a child overriding an inherited value; var(--x) as the whole
value and inside a shorthand (margin, padding); fallbacks (var(--missing, 10px), a
fallback that is itself a var()); a custom property that references another; a cycle
(--a: var(--b); --b: var(--a)), whose users compute as unset; an invalid substitution
(width: var(--x) with --x: red), which is invalid at computed-value time and leaves
width at auto; !important on a custom property; var() inside a length-only
calc() (calc(var(--a) + 5px), no percentage, so Stylo folds it to a plain length).
Out: registered custom properties (@property, the feature's css.at-rules.property
keys), var() in properties the engine does not lay out, percentage-mixed calc() (its
own spec, calc-lengths), env(), scripted setProperty and every test that reads
getComputedStyle. Say so in the binary's module doc.
Build. One file, crates/layout/src/bin/custom_properties_check.rs, modelled on
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, so body margin does not enter the comparison. At least three cases per category above, and at least 40 in all. - The engine side is
fragment_check.rsengine_dumpcopied, not shared:layoutbinaries cannot import each other. - 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(outcome.passed()); 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 every document parses withdom::Document::parseand yields a box tree. This is the partcargo test --workspaceruns; the browsers are not needed. - The binary exits non-zero when fewer than 20 cases were compared, so an oracle that silently produced nothing cannot pass. It exits zero when some cases disagree with the engine; those cases are the result.
Where the result goes. In the binary's module doc: the counts (cases
written, dropped with reasons, compared, passed, per category) and, for each failing case,
its id and the one-line cause found in Stylo's output or in computed.rs. No other file
records it, so the spec touches nothing shared. No docs/feature-map.json rule is added:
an exact-key rule for a check-only result could only be hand-written, which the map
treats as partial, and that file is edited by every queued generated-function spec.
Heavy steps go to a build lane and never run on the development box:
bench/on-lane.sh --lane-only "$PWD" cargo test -p layout --bin custom_properties_checkbench/on-lane.sh --lane-only "$PWD" cargo run --release -p layout --bin custom_properties_check
If no lane answers, report that instead of running either step locally.
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 substitution, and the corpus
is the entire deliverable.
Gates. cargo test --workspace passes. fragment_check --random stays 227/227: no
engine source changes.