style: More container queries plumbing

Provide container information in computed::Context and use it to resolve
the container queries.

This still fails a lot of tests because we are not ensuring that layout
is up-to-date when we style the container descendants, but that's
expected.

Differential Revision: https://phabricator.services.mozilla.com/D146478
This commit is contained in:
Emilio Cobos Álvarez 2023-08-14 23:29:47 +02:00 committed by Martin Robinson
parent 5c2fac087f
commit bbf10a43b8
18 changed files with 420 additions and 143 deletions

View file

@ -28,6 +28,7 @@ use crate::selector_parser::{PerPseudoElementMap, PseudoElement, SelectorImpl, S
use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
use crate::stylesheets::container_rule::ContainerCondition;
use crate::stylesheets::keyframes_rule::KeyframesAnimation;
use crate::stylesheets::layer_rule::{LayerName, LayerOrder};
use crate::stylesheets::viewport_rule::{self, MaybeNew, ViewportRule};
@ -2112,15 +2113,17 @@ impl ContainerConditionId {
#[derive(Clone, Debug, MallocSizeOf)]
struct ContainerCondition {
struct ContainerConditionReference {
parent: ContainerConditionId,
// TODO: condition: Option<Arc<ContainerCondition>> (or so).
#[ignore_malloc_size_of = "Arc"]
condition: Option<Arc<ContainerCondition>>,
}
impl ContainerCondition {
impl ContainerConditionReference {
const fn none() -> Self {
Self {
parent: ContainerConditionId::none(),
condition: None,
}
}
}
@ -2197,7 +2200,7 @@ pub struct CascadeData {
layers: SmallVec<[CascadeLayer; 1]>,
/// The list of container conditions, indexed by their id.
container_conditions: SmallVec<[ContainerCondition; 1]>,
container_conditions: SmallVec<[ContainerConditionReference; 1]>,
/// Effective media query results cached from the last rebuild.
effective_media_query_results: EffectiveMediaQueryResults,
@ -2241,7 +2244,7 @@ impl CascadeData {
animations: Default::default(),
layer_id: Default::default(),
layers: smallvec::smallvec![CascadeLayer::root()],
container_conditions: smallvec::smallvec![ContainerCondition::none()],
container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
extra_data: ExtraStyleData::default(),
effective_media_query_results: EffectiveMediaQueryResults::new(),
rules_source_order: 0,
@ -2356,6 +2359,23 @@ impl CascadeData {
self.layers[id.0 as usize].order
}
pub(crate) fn container_condition_matches<E>(&self, mut id: ContainerConditionId, stylist: &Stylist, element: E) -> bool
where
E: TElement,
{
loop {
let condition_ref = &self.container_conditions[id.0 as usize];
let condition = match condition_ref.condition {
None => return true,
Some(ref c) => c,
};
if !condition.matches(stylist.device(), element) {
return false;
}
id = condition_ref.parent;
}
}
fn did_finish_rebuild(&mut self) {
self.shrink_maps_if_needed();
self.compute_layer_order();
@ -2771,10 +2791,11 @@ impl CascadeData {
}
},
CssRule::Container(ref lock) => {
let _container_rule = lock.read_with(guard);
let container_rule = lock.read_with(guard);
let id = ContainerConditionId(self.container_conditions.len() as u16);
self.container_conditions.push(ContainerCondition {
self.container_conditions.push(ContainerConditionReference {
parent: containing_rule_state.container_condition_id,
condition: Some(container_rule.condition.clone()),
});
containing_rule_state.container_condition_id = id;
},
@ -2959,7 +2980,7 @@ impl CascadeData {
self.layers.clear();
self.layers.push(CascadeLayer::root());
self.container_conditions.clear();
self.container_conditions.push(ContainerCondition::none());
self.container_conditions.push(ContainerConditionReference::none());
#[cfg(feature = "gecko")]
{
self.extra_data.clear();