style: Implement parsing / serialization for container{,-type,-name} CSS properties

Two noteworthy details that may seem random otherwise:

 * Moving values around in nsStyleDisplay is needed so that the struct
   remains under the size limit that we have to avoid jumping allocator
   buckets.

 * All the test expectation churn is because tests depend on
   `container-type: size` parsing to run, and now they run. Tests for
   the relevant bits I implemented are passing, with the only exception
   of some `container-name-computed.html` failures which are
   https://github.com/w3c/csswg-drafts/issues/7181. Safari agrees with
   us there.

Other notes when looking at the spec and seeing how it matches the
implementation:

 * `container` syntax doesn't match spec, but matches tests and sanity:
   https://github.com/w3c/csswg-drafts/issues/7180

 * `container-type` syntax doesn't _quite_ match spec, but matches tests
   and I think it's a spec bug since the definition for the missing
   keyword is gone:
   https://github.com/w3c/csswg-drafts/issues/7179

Differential Revision: https://phabricator.services.mozilla.com/D142419
This commit is contained in:
Emilio Cobos Álvarez 2023-06-18 14:02:56 +02:00 committed by Martin Robinson
parent ee4e09359f
commit ec6099563e
9 changed files with 161 additions and 16 deletions

View file

@ -31,17 +31,35 @@ fn derive_bitflags(input: &syn::DeriveInput, bitflags: &CssBitflagAttrs) -> Toke
let mut has_any = false;
});
if bitflags.overlapping_bits {
body.append_all(quote! {
let mut serialized = Self::empty();
});
}
for (rust_name, css_name) in bitflags.mixed_flags() {
let rust_ident = Ident::new(&rust_name, Span::call_site());
body.append_all(quote! {
if self.intersects(Self::#rust_ident) {
if has_any {
dest.write_char(' ')?;
}
has_any = true;
dest.write_str(#css_name)?;
let serialize = quote! {
if has_any {
dest.write_char(' ')?;
}
});
has_any = true;
dest.write_str(#css_name)?;
};
if bitflags.overlapping_bits {
body.append_all(quote! {
if self.contains(Self::#rust_ident) && !serialized.intersects(Self::#rust_ident) {
#serialize
serialized.insert(Self::#rust_ident);
}
});
} else {
body.append_all(quote! {
if self.intersects(Self::#rust_ident) {
#serialize
}
});
}
}
body.append_all(quote! {
@ -319,6 +337,10 @@ pub struct CssBitflagAttrs {
/// Extra validation of the resulting mixed flags.
#[darling(default)]
pub validate_mixed: Option<Path>,
/// Whether there are overlapping bits we need to take care of when
/// serializing.
#[darling(default)]
pub overlapping_bits: bool,
}
impl CssBitflagAttrs {