diff --git a/servo/components/style/applicable_declarations.rs b/servo/components/style/applicable_declarations.rs index 3a55060cc873..387dcdab07dc 100644 --- a/servo/components/style/applicable_declarations.rs +++ b/servo/components/style/applicable_declarations.rs @@ -42,13 +42,7 @@ pub struct CascadePriority { layer_order: LayerOrder, } -#[allow(dead_code)] -fn size_assert() { - #[allow(unsafe_code)] - unsafe { - std::mem::transmute::(0u32) - }; -} +const_assert_eq!(std::mem::size_of::(), std::mem::size_of::()); impl PartialOrd for CascadePriority { #[inline] diff --git a/servo/components/style/dom.rs b/servo/components/style/dom.rs index d17fb184b29a..4f48298808e6 100644 --- a/servo/components/style/dom.rs +++ b/servo/components/style/dom.rs @@ -935,6 +935,9 @@ pub trait TElement: /// Returns element's namespace. fn namespace(&self) -> &::BorrowedNamespaceUrl; + + /// Returns the size of the primary box of the element. + fn primary_box_size(&self) -> euclid::default::Size2D; } /// TNode and TElement aren't Send because we want to be careful and explicit diff --git a/servo/components/style/gecko/media_features.rs b/servo/components/style/gecko/media_features.rs index 1c84a7ebacc7..a559adbcb1ae 100644 --- a/servo/components/style/gecko/media_features.rs +++ b/servo/components/style/gecko/media_features.rs @@ -6,7 +6,7 @@ use crate::gecko_bindings::bindings; use crate::gecko_bindings::structs; -use crate::queries::feature::{AllowsRanges, Evaluator, ParsingRequirements, QueryFeatureDescription}; +use crate::queries::feature::{AllowsRanges, Evaluator, FeatureFlags, QueryFeatureDescription}; use crate::queries::values::Orientation; use crate::media_queries::{Device, MediaType}; use crate::values::computed::{Context, CSSPixelLength, Ratio, Resolution}; @@ -548,7 +548,7 @@ macro_rules! lnf_int_feature { $feature_name, AllowsRanges::No, Evaluator::BoolInteger(__eval), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ) }}; ($feature_name:expr, $int_id:ident) => {{ @@ -576,7 +576,7 @@ macro_rules! bool_pref_feature { $feature_name, AllowsRanges::No, Evaluator::BoolInteger(__eval), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ) }}; } @@ -591,49 +591,49 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 60] = [ atom!("width"), AllowsRanges::Yes, Evaluator::Length(eval_width), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("height"), AllowsRanges::Yes, Evaluator::Length(eval_height), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("aspect-ratio"), AllowsRanges::Yes, Evaluator::NumberRatio(eval_aspect_ratio), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("orientation"), AllowsRanges::No, keyword_evaluator!(eval_orientation, Orientation), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("device-width"), AllowsRanges::Yes, Evaluator::Length(eval_device_width), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("device-height"), AllowsRanges::Yes, Evaluator::Length(eval_device_height), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("device-aspect-ratio"), AllowsRanges::Yes, Evaluator::NumberRatio(eval_device_aspect_ratio), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("-moz-device-orientation"), AllowsRanges::No, keyword_evaluator!(eval_device_orientation, Orientation), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), // Webkit extensions that we support for de-facto web compatibility. // -webkit-{min|max}-device-pixel-ratio (controlled with its own pref): @@ -641,68 +641,68 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 60] = [ atom!("device-pixel-ratio"), AllowsRanges::Yes, Evaluator::Float(eval_device_pixel_ratio), - ParsingRequirements::WEBKIT_PREFIX, + FeatureFlags::WEBKIT_PREFIX, ), // -webkit-transform-3d. feature!( atom!("transform-3d"), AllowsRanges::No, Evaluator::BoolInteger(eval_transform_3d), - ParsingRequirements::WEBKIT_PREFIX, + FeatureFlags::WEBKIT_PREFIX, ), feature!( atom!("-moz-device-pixel-ratio"), AllowsRanges::Yes, Evaluator::Float(eval_device_pixel_ratio), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("resolution"), AllowsRanges::Yes, Evaluator::Resolution(eval_resolution), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("display-mode"), AllowsRanges::No, keyword_evaluator!(eval_display_mode, DisplayMode), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("grid"), AllowsRanges::No, Evaluator::BoolInteger(eval_grid), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("scan"), AllowsRanges::No, keyword_evaluator!(eval_scan, Scan), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("color"), AllowsRanges::Yes, Evaluator::Integer(eval_color), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("color-index"), AllowsRanges::Yes, Evaluator::Integer(eval_color_index), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("monochrome"), AllowsRanges::Yes, Evaluator::Integer(eval_monochrome), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("prefers-reduced-motion"), AllowsRanges::No, keyword_evaluator!(eval_prefers_reduced_motion, PrefersReducedMotion), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("prefers-contrast"), @@ -713,49 +713,49 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 60] = [ // layout.css.prefers-contrast.enabled preference. See // disabed_by_pref in media_feature_expression.rs for how that // is done. - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("forced-colors"), AllowsRanges::No, keyword_evaluator!(eval_forced_colors, ForcedColors), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("overflow-block"), AllowsRanges::No, keyword_evaluator!(eval_overflow_block, OverflowBlock), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("overflow-inline"), AllowsRanges::No, keyword_evaluator!(eval_overflow_inline, OverflowInline), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("update"), AllowsRanges::No, keyword_evaluator!(eval_update, Update), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("prefers-color-scheme"), AllowsRanges::No, keyword_evaluator!(eval_prefers_color_scheme, PrefersColorScheme), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("dynamic-range"), AllowsRanges::No, keyword_evaluator!(eval_dynamic_range, DynamicRange), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("video-dynamic-range"), AllowsRanges::No, keyword_evaluator!(eval_video_dynamic_range, DynamicRange), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), // Evaluates to the preferred color scheme for content. Only useful in // chrome context, where the chrome color-scheme and the content @@ -764,31 +764,31 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 60] = [ atom!("-moz-content-prefers-color-scheme"), AllowsRanges::No, keyword_evaluator!(eval_content_prefers_color_scheme, PrefersColorScheme), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ), feature!( atom!("pointer"), AllowsRanges::No, keyword_evaluator!(eval_pointer, Pointer), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("any-pointer"), AllowsRanges::No, keyword_evaluator!(eval_any_pointer, Pointer), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("hover"), AllowsRanges::No, keyword_evaluator!(eval_hover, Hover), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), feature!( atom!("any-hover"), AllowsRanges::No, keyword_evaluator!(eval_any_hover, Hover), - ParsingRequirements::empty(), + FeatureFlags::empty(), ), // Internal -moz-is-glyph media feature: applies only inside SVG glyphs. // Internal because it is really only useful in the user agent anyway @@ -797,43 +797,43 @@ pub static MEDIA_FEATURES: [QueryFeatureDescription; 60] = [ atom!("-moz-is-glyph"), AllowsRanges::No, Evaluator::BoolInteger(eval_moz_is_glyph), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ), feature!( atom!("-moz-is-resource-document"), AllowsRanges::No, Evaluator::BoolInteger(eval_moz_is_resource_document), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ), feature!( atom!("-moz-platform"), AllowsRanges::No, keyword_evaluator!(eval_moz_platform, Platform), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ), feature!( atom!("-moz-print-preview"), AllowsRanges::No, Evaluator::BoolInteger(eval_moz_print_preview), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ), feature!( atom!("-moz-non-native-content-theme"), AllowsRanges::No, Evaluator::BoolInteger(eval_moz_non_native_content_theme), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ), feature!( atom!("-moz-windows-non-native-menus"), AllowsRanges::No, Evaluator::BoolInteger(eval_moz_windows_non_native_menus), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ), feature!( atom!("-moz-overlay-scrollbars"), AllowsRanges::No, Evaluator::BoolInteger(eval_moz_overlay_scrollbars), - ParsingRequirements::CHROME_AND_UA_ONLY, + FeatureFlags::CHROME_AND_UA_ONLY, ), lnf_int_feature!( atom!("-moz-scrollbar-start-backward"), diff --git a/servo/components/style/gecko/wrapper.rs b/servo/components/style/gecko/wrapper.rs index 847fd359409d..7aa32764955f 100644 --- a/servo/components/style/gecko/wrapper.rs +++ b/servo/components/style/gecko/wrapper.rs @@ -70,6 +70,8 @@ use crate::values::specified::length::FontBaseSize; use crate::values::{AtomIdent, AtomString}; use crate::CaseSensitivityExt; use crate::LocalName; +use app_units::Au; +use euclid::default::Size2D; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use fxhash::FxHashMap; use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator}; @@ -326,6 +328,11 @@ impl<'ln> GeckoNode<'ln> { self.flags() & (NODE_IS_IN_SHADOW_TREE as u32) != 0 } + #[inline] + fn is_connected(&self) -> bool { + self.get_bool_flag(nsINode_BooleanFlag::IsConnected) + } + /// WARNING: This logic is duplicated in Gecko's FlattenedTreeParentIsParent. /// Make sure to mirror any modifications in both places. #[inline] @@ -1165,6 +1172,21 @@ impl<'le> TElement for GeckoElement<'le> { } } + #[inline] + fn primary_box_size(&self) -> Size2D { + if !self.as_node().is_connected() { + return Size2D::zero(); + } + + unsafe { + let frame = self.0._base._base._base.__bindgen_anon_1.mPrimaryFrame.as_ref(); + if frame.is_null() { + return Size2D::zero(); + } + Size2D::new(Au((**frame).mRect.width), Au((**frame).mRect.height)) + } + } + /// Return the list of slotted nodes of this node. #[inline] fn slotted_nodes(&self) -> &[Self::ConcreteNode] { diff --git a/servo/components/style/lib.rs b/servo/components/style/lib.rs index 83fc58475b89..1e53b8a49bbd 100644 --- a/servo/components/style/lib.rs +++ b/servo/components/style/lib.rs @@ -64,7 +64,6 @@ pub use servo_arc; #[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms; -#[cfg(target_pointer_width = "64")] #[macro_use] extern crate static_assertions; #[macro_use] diff --git a/servo/components/style/logical_geometry.rs b/servo/components/style/logical_geometry.rs index 9113185cf698..d475e9bdfc41 100644 --- a/servo/components/style/logical_geometry.rs +++ b/servo/components/style/logical_geometry.rs @@ -168,6 +168,11 @@ impl WritingMode { flags } + /// Returns the `horizontal-tb` value. + pub fn horizontal_tb() -> Self { + Self::from_bits_truncate(0) + } + #[inline] pub fn is_vertical(&self) -> bool { self.intersects(WritingMode::VERTICAL) diff --git a/servo/components/style/properties/cascade.rs b/servo/components/style/properties/cascade.rs index 5683ceddc991..d0cd18ec3f01 100644 --- a/servo/components/style/properties/cascade.rs +++ b/servo/components/style/properties/cascade.rs @@ -298,6 +298,7 @@ where in_media_query: false, for_smil_animation: false, for_non_inherited_property: None, + container_info: None, font_metrics_provider, quirks_mode, rule_cache_conditions: RefCell::new(rule_cache_conditions), diff --git a/servo/components/style/queries/condition.rs b/servo/components/style/queries/condition.rs index 71f4e2fd0d62..da8ad02d595b 100644 --- a/servo/components/style/queries/condition.rs +++ b/servo/components/style/queries/condition.rs @@ -7,7 +7,7 @@ //! https://drafts.csswg.org/mediaqueries-4/#typedef-media-condition //! https://drafts.csswg.org/css-contain-3/#typedef-container-condition -use super::{QueryFeatureExpression, FeatureType}; +use super::{QueryFeatureExpression, FeatureType, FeatureFlags}; use crate::parser::ParserContext; use crate::values::computed; use cssparser::{Parser, Token}; @@ -85,6 +85,35 @@ impl QueryCondition { Self::parse_internal(context, input, feature_type, AllowOr::Yes) } + fn visit(&self, visitor: &mut F) + where + F: FnMut(&Self), + { + visitor(self); + match *self { + Self::Feature(..) => {}, + Self::Not(ref cond) => cond.visit(visitor), + Self::Operation(ref conds, _op) => { + for cond in conds.iter() { + cond.visit(visitor); + } + }, + Self::InParens(ref cond) => cond.visit(visitor), + } + } + + /// Returns the union of all flags in the expression. This is useful for + /// container queries. + pub fn cumulative_flags(&self) -> FeatureFlags { + let mut result = FeatureFlags::empty(); + self.visit(&mut |condition| { + if let Self::Feature(ref f) = condition { + result.insert(f.feature_flags()) + } + }); + result + } + /// Parse a single condition, disallowing `or` expressions. /// /// To be used from the legacy query syntax. diff --git a/servo/components/style/queries/feature.rs b/servo/components/style/queries/feature.rs index 3390127887b3..9efd64f8c237 100644 --- a/servo/components/style/queries/feature.rs +++ b/servo/components/style/queries/feature.rs @@ -101,13 +101,42 @@ macro_rules! keyword_evaluator { } bitflags! { - /// Different requirements or toggles that change how a expression is - /// parsed. - pub struct ParsingRequirements: u8 { + /// Different flags or toggles that change how a expression is parsed or + /// evaluated. + #[derive(ToShmem)] + pub struct FeatureFlags : u8 { /// The feature should only be parsed in chrome and ua sheets. const CHROME_AND_UA_ONLY = 1 << 0; /// The feature requires a -webkit- prefix. const WEBKIT_PREFIX = 1 << 1; + /// The feature requires the inline-axis containment. + const CONTAINER_REQUIRES_INLINE_AXIS = 1 << 2; + /// The feature requires the block-axis containment. + const CONTAINER_REQUIRES_BLOCK_AXIS = 1 << 3; + /// The feature requires containment in the physical width axis. + const CONTAINER_REQUIRES_WIDTH_AXIS = 1 << 4; + /// The feature requires containment in the physical height axis. + const CONTAINER_REQUIRES_HEIGHT_AXIS = 1 << 5; + } +} + +impl FeatureFlags { + /// Returns parsing requirement flags. + pub fn parsing_requirements(self) -> Self { + self.intersection(Self::CHROME_AND_UA_ONLY | Self::WEBKIT_PREFIX) + } + + /// Returns all the container axis flags. + pub fn all_container_axes() -> Self { + Self::CONTAINER_REQUIRES_INLINE_AXIS | + Self::CONTAINER_REQUIRES_BLOCK_AXIS | + Self::CONTAINER_REQUIRES_WIDTH_AXIS | + Self::CONTAINER_REQUIRES_HEIGHT_AXIS + } + + /// Returns our subset of container axis flags. + pub fn container_axes(self) -> Self { + self.intersection(Self::all_container_axes()) } } @@ -128,9 +157,8 @@ pub struct QueryFeatureDescription { /// The evaluator, which we also use to determine which kind of value to /// parse. pub evaluator: Evaluator, - /// Different requirements that need to hold for the feature to be - /// successfully parsed. - pub requirements: ParsingRequirements, + /// Different feature-specific flags. + pub flags: FeatureFlags, } impl QueryFeatureDescription { @@ -143,12 +171,12 @@ impl QueryFeatureDescription { /// A simple helper to construct a `QueryFeatureDescription`. macro_rules! feature { - ($name:expr, $allows_ranges:expr, $evaluator:expr, $reqs:expr,) => { + ($name:expr, $allows_ranges:expr, $evaluator:expr, $flags:expr,) => { $crate::queries::feature::QueryFeatureDescription { name: $name, allows_ranges: $allows_ranges, evaluator: $evaluator, - requirements: $reqs, + flags: $flags, } }; } @@ -158,7 +186,7 @@ impl fmt::Debug for QueryFeatureDescription { f.debug_struct("QueryFeatureDescription") .field("name", &self.name) .field("allows_ranges", &self.allows_ranges) - .field("requirements", &self.requirements) + .field("flags", &self.flags) .finish() } } diff --git a/servo/components/style/queries/feature_expression.rs b/servo/components/style/queries/feature_expression.rs index 3482fae1340b..0acf822955cf 100644 --- a/servo/components/style/queries/feature_expression.rs +++ b/servo/components/style/queries/feature_expression.rs @@ -6,7 +6,7 @@ //! `(width >= 400px)`. use super::feature::{Evaluator, QueryFeatureDescription}; -use super::feature::{KeywordDiscriminant, ParsingRequirements}; +use super::feature::{KeywordDiscriminant, FeatureFlags}; use crate::parser::{Parse, ParserContext}; use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase}; use crate::values::computed::{self, Ratio, ToComputedValue}; @@ -337,10 +337,7 @@ impl QueryFeatureExpression { W: fmt::Write, { let feature = self.feature(); - if feature - .requirements - .contains(ParsingRequirements::WEBKIT_PREFIX) - { + if feature.flags.contains(FeatureFlags::WEBKIT_PREFIX) { dest.write_str("-webkit-")?; } @@ -361,6 +358,11 @@ impl QueryFeatureExpression { &self.feature_type.features()[self.feature_index] } + /// Returns the feature flags for our feature. + pub fn feature_flags(&self) -> FeatureFlags { + self.feature().flags + } + /// Parse a feature expression of the form: /// /// ``` @@ -382,18 +384,18 @@ impl QueryFeatureExpression { input: &mut Parser<'i, 't>, feature_type: FeatureType, ) -> Result<(usize, Option), ParseError<'i>> { - let mut requirements = ParsingRequirements::empty(); + let mut flags = FeatureFlags::empty(); let location = input.current_source_location(); let ident = input.expect_ident()?; if context.in_ua_or_chrome_sheet() { - requirements.insert(ParsingRequirements::CHROME_AND_UA_ONLY); + flags.insert(FeatureFlags::CHROME_AND_UA_ONLY); } let mut feature_name = &**ident; if starts_with_ignore_ascii_case(feature_name, "-webkit-") { feature_name = &feature_name[8..]; - requirements.insert(ParsingRequirements::WEBKIT_PREFIX); + flags.insert(FeatureFlags::WEBKIT_PREFIX); } let range = if starts_with_ignore_ascii_case(feature_name, "min-") { @@ -417,7 +419,7 @@ impl QueryFeatureExpression { }; if disabled_by_pref(&feature.name, context) || - !requirements.contains(feature.requirements) || + !flags.contains(feature.flags.parsing_requirements()) || (range.is_some() && !feature.allows_ranges()) { return Err(location.new_custom_error( diff --git a/servo/components/style/queries/mod.rs b/servo/components/style/queries/mod.rs index 69df6e37ad87..6bbf197c43bb 100644 --- a/servo/components/style/queries/mod.rs +++ b/servo/components/style/queries/mod.rs @@ -15,4 +15,5 @@ pub mod feature_expression; pub mod values; pub use self::condition::QueryCondition; +pub use self::feature::FeatureFlags; pub use self::feature_expression::{QueryFeatureExpression, FeatureType}; diff --git a/servo/components/style/rule_collector.rs b/servo/components/style/rule_collector.rs index e3f3725f8b55..0e18383455cd 100644 --- a/servo/components/style/rule_collector.rs +++ b/servo/components/style/rule_collector.rs @@ -225,6 +225,7 @@ where &mut self.context, cascade_level, cascade_data, + &self.stylist, ); } @@ -243,6 +244,7 @@ where &mut self.context, cascade_level, cascade_data, + &self.stylist, ); } diff --git a/servo/components/style/selector_map.rs b/servo/components/style/selector_map.rs index 816bb2b8ff92..d71290d05c52 100644 --- a/servo/components/style/selector_map.rs +++ b/servo/components/style/selector_map.rs @@ -10,7 +10,7 @@ use crate::context::QuirksMode; use crate::dom::TElement; use crate::rule_tree::CascadeLevel; use crate::selector_parser::SelectorImpl; -use crate::stylist::{CascadeData, Rule}; +use crate::stylist::{Stylist, CascadeData, Rule, ContainerConditionId}; use crate::AllocErr; use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom}; use precomputed_hash::PrecomputedHash; @@ -188,9 +188,10 @@ impl SelectorMap { element: E, rule_hash_target: E, matching_rules_list: &mut ApplicableDeclarationList, - context: &mut MatchingContext, + matching_context: &mut MatchingContext, cascade_level: CascadeLevel, cascade_data: &CascadeData, + stylist: &Stylist, ) where E: TElement, { @@ -198,16 +199,17 @@ impl SelectorMap { return; } - let quirks_mode = context.quirks_mode(); + let quirks_mode = matching_context.quirks_mode(); if rule_hash_target.is_root() { SelectorMap::get_matching_rules( element, &self.root, matching_rules_list, - context, + matching_context, cascade_level, cascade_data, + stylist, ); } @@ -217,9 +219,10 @@ impl SelectorMap { element, rules, matching_rules_list, - context, + matching_context, cascade_level, cascade_data, + stylist, ) } } @@ -230,9 +233,10 @@ impl SelectorMap { element, rules, matching_rules_list, - context, + matching_context, cascade_level, cascade_data, + stylist, ) } }); @@ -244,9 +248,10 @@ impl SelectorMap { element, rules, matching_rules_list, - context, + matching_context, cascade_level, cascade_data, + stylist, ) } }); @@ -257,9 +262,10 @@ impl SelectorMap { element, rules, matching_rules_list, - context, + matching_context, cascade_level, cascade_data, + stylist, ) } @@ -268,9 +274,10 @@ impl SelectorMap { element, rules, matching_rules_list, - context, + matching_context, cascade_level, cascade_data, + stylist, ) } @@ -278,9 +285,10 @@ impl SelectorMap { element, &self.other, matching_rules_list, - context, + matching_context, cascade_level, cascade_data, + stylist, ); } @@ -289,23 +297,32 @@ impl SelectorMap { element: E, rules: &[Rule], matching_rules: &mut ApplicableDeclarationList, - context: &mut MatchingContext, + matching_context: &mut MatchingContext, cascade_level: CascadeLevel, cascade_data: &CascadeData, + stylist: &Stylist, ) where E: TElement, { for rule in rules { - if matches_selector( + if !matches_selector( &rule.selector, 0, Some(&rule.hashes), &element, - context, + matching_context, ) { - matching_rules - .push(rule.to_applicable_declaration_block(cascade_level, cascade_data)); + continue; } + + if rule.container_condition_id != ContainerConditionId::none() { + if !cascade_data.container_condition_matches(rule.container_condition_id, stylist, element) { + continue; + } + } + + matching_rules + .push(rule.to_applicable_declaration_block(cascade_level, cascade_data)); } } } diff --git a/servo/components/style/stylesheets/container_rule.rs b/servo/components/style/stylesheets/container_rule.rs index b88a41db6224..fe103d8986dc 100644 --- a/servo/components/style/stylesheets/container_rule.rs +++ b/servo/components/style/stylesheets/container_rule.rs @@ -7,32 +7,34 @@ //! [container]: https://drafts.csswg.org/css-contain-3/#container-rule use crate::logical_geometry::{WritingMode, LogicalSize}; -use crate::queries::QueryCondition; +use crate::dom::TElement; +use crate::media_queries::Device; +use crate::parser::ParserContext; +use crate::queries::{QueryCondition, FeatureType}; +use crate::queries::feature::{AllowsRanges, Evaluator, FeatureFlags, QueryFeatureDescription}; +use crate::queries::values::Orientation; +use crate::str::CssStringWriter; use crate::shared_lock::{ DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard, }; use crate::values::specified::ContainerName; use crate::values::computed::{Context, CSSPixelLength, Ratio}; -use crate::str::CssStringWriter; +use crate::properties::ComputedValues; use crate::stylesheets::CssRules; -use crate::queries::feature::{AllowsRanges, Evaluator, ParsingRequirements, QueryFeatureDescription}; -use crate::queries::values::Orientation; use app_units::Au; -use cssparser::SourceLocation; +use cssparser::{SourceLocation, Parser}; use euclid::default::Size2D; #[cfg(feature = "gecko")] use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf}; use servo_arc::Arc; use std::fmt::{self, Write}; -use style_traits::{CssWriter, ToCss}; +use style_traits::{CssWriter, ToCss, ParseError}; /// A container rule. #[derive(Debug, ToShmem)] pub struct ContainerRule { - /// The container name. - pub name: ContainerName, - /// The container query. - pub condition: ContainerCondition, + /// The container query and name. + pub condition: Arc, /// The nested rules inside the block. pub rules: Arc>, /// The source position where this rule was found. @@ -40,6 +42,11 @@ pub struct ContainerRule { } impl ContainerRule { + /// Returns the query condition. + pub fn query_condition(&self) -> &QueryCondition { + &self.condition.condition + } + /// Measure heap usage. #[cfg(feature = "gecko")] pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize { @@ -58,7 +65,6 @@ impl DeepCloneWithLock for ContainerRule { ) -> Self { let rules = self.rules.read_with(guard); Self { - name: self.name.clone(), condition: self.condition.clone(), rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))), source_location: self.source_location.clone(), @@ -71,51 +77,163 @@ impl ToCssWithGuard for ContainerRule { dest.write_str("@container ")?; { let mut writer = CssWriter::new(dest); - if !self.name.is_none() { - self.name.to_css(&mut writer)?; + if !self.condition.name.is_none() { + self.condition.name.to_css(&mut writer)?; writer.write_char(' ')?; } - self.condition.to_css(&mut writer)?; + self.condition.condition.to_css(&mut writer)?; } self.rules.read_with(guard).to_css_block(guard, dest) } } -/// TODO: Factor out the media query code to work with containers. -pub type ContainerCondition = QueryCondition; +/// A container condition and filter, combined. +#[derive(Debug, ToShmem)] +pub struct ContainerCondition { + name: ContainerName, + condition: QueryCondition, + flags: FeatureFlags, +} -fn get_container(_context: &Context) -> (Size2D, WritingMode) { - unimplemented!("TODO: implement container matching"); +impl ContainerCondition { + /// Parse a container condition. + pub fn parse<'a>( + context: &ParserContext, + input: &mut Parser<'a, '_>, + ) -> Result> { + use crate::parser::Parse; + + // FIXME: This is a bit ambiguous: + // https://github.com/w3c/csswg-drafts/issues/7203 + let name = input.try_parse(|input| { + ContainerName::parse(context, input) + }).ok().unwrap_or_else(ContainerName::none); + let condition = QueryCondition::parse(context, input, FeatureType::Container)?; + let flags = condition.cumulative_flags(); + Ok(Self { name, condition, flags }) + } + + fn valid_container_info(&self, potential_container: E) -> Option<(ContainerInfo, Arc)> + where + E: TElement, + { + use crate::values::computed::ContainerType; + + fn container_type_axes(ty_: ContainerType, wm: WritingMode) -> FeatureFlags { + if ty_.intersects(ContainerType::SIZE) { + return FeatureFlags::all_container_axes() + } + if ty_.intersects(ContainerType::INLINE_SIZE) { + let physical_axis = if wm.is_vertical() { + FeatureFlags::CONTAINER_REQUIRES_HEIGHT_AXIS + } else { + FeatureFlags::CONTAINER_REQUIRES_WIDTH_AXIS + }; + return FeatureFlags::CONTAINER_REQUIRES_INLINE_AXIS | physical_axis + } + FeatureFlags::empty() + } + + let data = match potential_container.borrow_data() { + Some(data) => data, + None => return None, + }; + let style = data.styles.primary(); + let wm = style.writing_mode; + let box_style = style.get_box(); + + // Filter by container-type. + let container_type = box_style.clone_container_type(); + let available_axes = container_type_axes(container_type, wm); + if !available_axes.contains(self.flags.container_axes()) { + return None; + } + + // Filter by container-name. + let container_name = box_style.clone_container_name(); + for filter_name in self.name.0.iter() { + if !container_name.0.contains(filter_name) { + return None; + } + } + + let size = potential_container.primary_box_size(); + let style = style.clone(); + Some((ContainerInfo { size, wm }, style)) + } + + fn find_container(&self, mut e: E) -> Option<(ContainerInfo, Arc)> + where + E: TElement, + { + while let Some(element) = e.traversal_parent() { + if let Some(info) = self.valid_container_info(element) { + return Some(info); + } + e = element; + } + + None + } + + /// Tries to match a container query condition for a given element. + pub(crate) fn matches(&self, device: &Device, element: E) -> bool + where + E: TElement, + { + let info = self.find_container(element); + Context::for_container_query_evaluation(device, info, |context| { + self.condition.matches(context) + }) + } +} + + +/// Information needed to evaluate an individual container query. +#[derive(Copy, Clone)] +pub struct ContainerInfo { + size: Size2D, + wm: WritingMode, +} + +fn get_container(context: &Context) -> ContainerInfo { + if let Some(ref info) = context.container_info { + return info.clone() + } + ContainerInfo { + size: context.device().au_viewport_size(), + wm: WritingMode::horizontal_tb(), + } } fn eval_width(context: &Context) -> CSSPixelLength { - let (size, _wm) = get_container(context); - CSSPixelLength::new(size.width.to_f32_px()) + let info = get_container(context); + CSSPixelLength::new(info.size.width.to_f32_px()) } fn eval_height(context: &Context) -> CSSPixelLength { - let (size, _wm) = get_container(context); - CSSPixelLength::new(size.height.to_f32_px()) + let info = get_container(context); + CSSPixelLength::new(info.size.height.to_f32_px()) } fn eval_inline_size(context: &Context) -> CSSPixelLength { - let (size, wm) = get_container(context); - CSSPixelLength::new(LogicalSize::from_physical(wm, size).inline.to_f32_px()) + let info = get_container(context); + CSSPixelLength::new(LogicalSize::from_physical(info.wm, info.size).inline.to_f32_px()) } fn eval_block_size(context: &Context) -> CSSPixelLength { - let (size, wm) = get_container(context); - CSSPixelLength::new(LogicalSize::from_physical(wm, size).block.to_f32_px()) + let info = get_container(context); + CSSPixelLength::new(LogicalSize::from_physical(info.wm, info.size).block.to_f32_px()) } fn eval_aspect_ratio(context: &Context) -> Ratio { - let (size, _wm) = get_container(context); - Ratio::new(size.width.0 as f32, size.height.0 as f32) + let info = get_container(context); + Ratio::new(info.size.width.0 as f32, info.size.height.0 as f32) } fn eval_orientation(context: &Context, value: Option) -> bool { - let (size, _wm) = get_container(context); - Orientation::eval(size, value) + let info = get_container(context); + Orientation::eval(info.size, value) } /// https://drafts.csswg.org/css-contain-3/#container-features @@ -126,36 +244,38 @@ pub static CONTAINER_FEATURES: [QueryFeatureDescription; 6] = [ atom!("width"), AllowsRanges::Yes, Evaluator::Length(eval_width), - ParsingRequirements::empty(), + FeatureFlags::CONTAINER_REQUIRES_WIDTH_AXIS, ), feature!( atom!("height"), AllowsRanges::Yes, Evaluator::Length(eval_height), - ParsingRequirements::empty(), + FeatureFlags::CONTAINER_REQUIRES_HEIGHT_AXIS, ), feature!( atom!("inline-size"), AllowsRanges::Yes, Evaluator::Length(eval_inline_size), - ParsingRequirements::empty(), + FeatureFlags::CONTAINER_REQUIRES_INLINE_AXIS, ), feature!( atom!("block-size"), AllowsRanges::Yes, Evaluator::Length(eval_block_size), - ParsingRequirements::empty(), + FeatureFlags::CONTAINER_REQUIRES_BLOCK_AXIS, ), feature!( atom!("aspect-ratio"), AllowsRanges::Yes, Evaluator::NumberRatio(eval_aspect_ratio), - ParsingRequirements::empty(), + // XXX from_bits_truncate is const, but the pipe operator isn't, so this + // works around it. + FeatureFlags::from_bits_truncate(FeatureFlags::CONTAINER_REQUIRES_BLOCK_AXIS.bits() | FeatureFlags::CONTAINER_REQUIRES_INLINE_AXIS.bits()), ), feature!( atom!("orientation"), AllowsRanges::No, keyword_evaluator!(eval_orientation, Orientation), - ParsingRequirements::empty(), + FeatureFlags::from_bits_truncate(FeatureFlags::CONTAINER_REQUIRES_BLOCK_AXIS.bits() | FeatureFlags::CONTAINER_REQUIRES_INLINE_AXIS.bits()), ), ]; diff --git a/servo/components/style/stylesheets/rule_parser.rs b/servo/components/style/stylesheets/rule_parser.rs index e147ff7b8cb2..e8718832d13f 100644 --- a/servo/components/style/stylesheets/rule_parser.rs +++ b/servo/components/style/stylesheets/rule_parser.rs @@ -10,7 +10,6 @@ use crate::font_face::parse_font_face_block; use crate::media_queries::MediaList; use crate::parser::{Parse, ParserContext}; use crate::properties::parse_property_declaration_list; -use crate::queries::FeatureType; use crate::selector_parser::{SelectorImpl, SelectorParser}; use crate::shared_lock::{Locked, SharedRwLock}; use crate::str::starts_with_ignore_ascii_case; @@ -30,7 +29,6 @@ use crate::stylesheets::{ }; use crate::values::computed::font::FamilyName; use crate::values::{CssUrl, CustomIdent, KeyframesName, TimelineName}; -use crate::values::specified::ContainerName; use crate::{Namespace, Prefix}; use cssparser::{ AtRuleParser, BasicParseError, BasicParseErrorKind, CowRcStr, Parser, ParserState, @@ -192,7 +190,7 @@ pub enum AtRulePrelude { /// A @media rule prelude, with its media queries. Media(Arc>), /// A @container rule prelude. - Container(ContainerName, ContainerCondition), + Container(Arc), /// An @supports rule, with its conditional Supports(SupportsCondition), /// A @viewport rule prelude. @@ -475,13 +473,8 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { AtRulePrelude::FontFace }, "container" if static_prefs::pref!("layout.css.container-queries.enabled") => { - // FIXME: This is a bit ambiguous: - // https://github.com/w3c/csswg-drafts/issues/7203 - let name = input.try_parse(|input| { - ContainerName::parse(self.context, input) - }).ok().unwrap_or_else(ContainerName::none); - let condition = ContainerCondition::parse(self.context, input, FeatureType::Container)?; - AtRulePrelude::Container(name, condition) + let condition = Arc::new(ContainerCondition::parse(self.context, input)?); + AtRulePrelude::Container(condition) }, "layer" if static_prefs::pref!("layout.css.cascade-layers.enabled") => { let names = input.try_parse(|input| { @@ -662,10 +655,9 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { }, )))) }, - AtRulePrelude::Container(name, condition) => { + AtRulePrelude::Container(condition) => { Ok(CssRule::Container(Arc::new(self.shared_lock.wrap( ContainerRule { - name, condition, rules: self.parse_nested_rules(input, CssRuleType::Container), source_location: start.source_location(), diff --git a/servo/components/style/stylesheets/viewport_rule.rs b/servo/components/style/stylesheets/viewport_rule.rs index 9f751ece2651..cf8d1d55ba10 100644 --- a/servo/components/style/stylesheets/viewport_rule.rs +++ b/servo/components/style/stylesheets/viewport_rule.rs @@ -683,7 +683,8 @@ impl MaybeNew for ViewportConstraints { font_metrics_provider: &provider, cached_system_font: None, in_media_query: false, - quirks_mode: quirks_mode, + quirks_mode, + container_info: None, for_smil_animation: false, for_non_inherited_property: None, rule_cache_conditions: RefCell::new(&mut conditions), diff --git a/servo/components/style/stylist.rs b/servo/components/style/stylist.rs index 505588fa1ec6..03f11bc8d930 100644 --- a/servo/components/style/stylist.rs +++ b/servo/components/style/stylist.rs @@ -29,6 +29,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}; @@ -2133,15 +2134,17 @@ impl ContainerConditionId { #[derive(Clone, Debug, MallocSizeOf)] -struct ContainerCondition { +struct ContainerConditionReference { parent: ContainerConditionId, - // TODO: condition: Option> (or so). + #[ignore_malloc_size_of = "Arc"] + condition: Option>, } -impl ContainerCondition { +impl ContainerConditionReference { const fn none() -> Self { Self { parent: ContainerConditionId::none(), + condition: None, } } } @@ -2218,7 +2221,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, @@ -2262,7 +2265,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, @@ -2377,6 +2380,23 @@ impl CascadeData { self.layers[id.0 as usize].order } + pub(crate) fn container_condition_matches(&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(); @@ -2789,10 +2809,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; }, @@ -2977,7 +2998,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()); self.extra_data.clear(); self.rules_source_order = 0; self.num_selectors = 0; diff --git a/servo/components/style/values/computed/mod.rs b/servo/components/style/values/computed/mod.rs index 0a6c8b3b71d1..c5091d86a88d 100644 --- a/servo/components/style/values/computed/mod.rs +++ b/servo/components/style/values/computed/mod.rs @@ -15,6 +15,7 @@ use super::generics::{self, GreaterThanOrEqualToOne, NonNegative, ZeroToOne}; use super::specified; use super::{CSSFloat, CSSInteger}; use crate::context::QuirksMode; +use crate::stylesheets::container_rule::ContainerInfo; use crate::font_metrics::{get_metrics_provider_for_product, FontMetricsProvider}; use crate::media_queries::Device; #[cfg(feature = "gecko")] @@ -172,6 +173,9 @@ pub struct Context<'a> { /// values, which SMIL allows. pub for_smil_animation: bool, + /// Returns the container information to evaluate a given container query. + pub container_info: Option, + /// The property we are computing a value for, if it is a non-inherited /// property. None if we are computed a value for an inherited property /// or not computing for a property at all (e.g. in a media query @@ -202,6 +206,42 @@ impl<'a> Context<'a> { in_media_query: true, quirks_mode, for_smil_animation: false, + container_info: None, + for_non_inherited_property: None, + rule_cache_conditions: RefCell::new(&mut conditions), + }; + + f(&context) + } + + /// Creates a suitable context for container query evaluation for the style + /// specified. + pub fn for_container_query_evaluation( + device: &Device, + container_info_and_style: Option<(ContainerInfo, Arc)>, + f: F, + ) -> R + where + F: FnOnce(&Context) -> R, + { + let mut conditions = RuleCacheConditions::default(); + let provider = get_metrics_provider_for_product(); + + let (container_info, style) = match container_info_and_style { + Some((ci, s)) => (Some(ci), Some(s)), + None => (None, None), + }; + + let style = style.as_ref().map(|s| &**s); + let quirks_mode = device.quirks_mode(); + let context = Context { + builder: StyleBuilder::for_inheritance(device, style, None), + font_metrics_provider: &provider, + cached_system_font: None, + in_media_query: true, + quirks_mode, + for_smil_animation: false, + container_info, for_non_inherited_property: None, rule_cache_conditions: RefCell::new(&mut conditions), }; @@ -265,8 +305,8 @@ impl<'a, 'cx, 'cx_a: 'cx, S: ToComputedValue + 'a> ComputedVecIter<'a, 'cx, 'cx_ /// Construct an iterator from a slice of specified values and a context pub fn new(cx: &'cx Context<'cx_a>, values: &'a [S]) -> Self { ComputedVecIter { - cx: cx, - values: values, + cx, + values, } } } diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 42e4506b4dfd..570c64fc2dbb 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -2959,7 +2959,7 @@ pub extern "C" fn Servo_ContainerRule_GetConditionText( result: &mut nsACString, ) { read_locked_arc(rule, |rule: &ContainerRule| { - rule.condition.to_css(&mut CssWriter::new(result)).unwrap(); + rule.query_condition().to_css(&mut CssWriter::new(result)).unwrap(); }) } @@ -5848,6 +5848,7 @@ fn create_context_for_animation<'a>( quirks_mode: per_doc_data.stylist.quirks_mode(), for_smil_animation, for_non_inherited_property: None, + container_info: None, rule_cache_conditions: RefCell::new(rule_cache_conditions), } } diff --git a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-003.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-003.html.ini new file mode 100644 index 000000000000..e6ff9db8dd58 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-003.html.ini @@ -0,0 +1,2 @@ +[canvas-as-container-003.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-004.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-004.html.ini new file mode 100644 index 000000000000..e745dc1dbaba --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-004.html.ini @@ -0,0 +1,2 @@ +[canvas-as-container-004.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-005.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-005.html.ini index a25595e70d43..69ec819abd95 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-005.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-005.html.ini @@ -1,3 +1,3 @@ [canvas-as-container-005.html] - [Initially display:none, not focusable] + [Focusable after container size change] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-006.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-006.html.ini index 2bec1da93aeb..0aaa7995a130 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-006.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/canvas-as-container-006.html.ini @@ -1,3 +1,3 @@ [canvas-as-container-006.html] - [Initially display:none, not focusable] + [Focusable after container size change] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/change-display-in-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/change-display-in-container.html.ini new file mode 100644 index 000000000000..1a14360fad1d --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/change-display-in-container.html.ini @@ -0,0 +1,2 @@ +[change-display-in-container.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/conditional-container-status.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/conditional-container-status.html.ini new file mode 100644 index 000000000000..ed8d459baace --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/conditional-container-status.html.ini @@ -0,0 +1,3 @@ +[conditional-container-status.html] + [Conditionally applying container-type:initial] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/container-for-shadow-dom.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/container-for-shadow-dom.html.ini index 317da2fa3a2d..b88addca5200 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/container-for-shadow-dom.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/container-for-shadow-dom.html.ini @@ -1,3 +1,30 @@ [container-for-shadow-dom.html] [Match container for ::part selector's originating element tree for exportparts] expected: FAIL + + [Match container in outer tree] + expected: FAIL + + [Match container in same tree, not walking flat tree ancestors] + expected: FAIL + + [Match container in ::slotted selector's originating element tree] + expected: FAIL + + [Match container in outer tree for :host] + expected: FAIL + + [Match container in ::part selector's originating element tree] + expected: FAIL + + [Match container for ::before in ::slotted selector's originating element tree] + expected: FAIL + + [Match container in outer tree for :host::before] + expected: FAIL + + [Match container for ::before in ::part selector's originating element tree] + expected: FAIL + + [Match container for slot light tree child fallback] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/container-nested.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/container-nested.html.ini index 2e4337dc1504..759c4a2e3d08 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/container-nested.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/container-nested.html.ini @@ -5,17 +5,23 @@ [Implicit outer invalidation] expected: FAIL - [Implicit, outer failing] + [Implicit] expected: FAIL - [Implicit, inner failing] + [Outer named, inner named] expected: FAIL - [Failing outer name] + [Outer named, inner named (reverse)] expected: FAIL - [Failing inner name] + [Outer named, inner implicit] expected: FAIL - [Three levels, middle fail] + [Inner named, outer implicit] + expected: FAIL + + [Inner named, outer implicit (reverse)] + expected: FAIL + + [Three levels] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/container-selection.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/container-selection.html.ini index c93aadcc2264..19c7845285b7 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/container-selection.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/container-selection.html.ini @@ -1,9 +1,54 @@ [container-selection.html] - [(height: 16px) for .size > .inline > span] - expected: FAIL - [c (width) for .a-size > .b-size > span] expected: FAIL [c (width) for .ab-size > .size > span] expected: FAIL + + [(width: 16px) for .size > .inline > span] + expected: FAIL + + [(height: 16px) for .inline > .size > span] + expected: FAIL + + [(width: 16px) for .inline > .size > span] + expected: FAIL + + [(height: 32px) for .size > .inline > span] + expected: FAIL + + [a (width: 32px) for .a-size > .b-size > span] + expected: FAIL + + [b (width: 16px) for .a-size > .b-size > span] + expected: FAIL + + [a (width: 16px) for .a-size > .a-size > span] + expected: FAIL + + [a (width: 32px) for .a-size > .a > span] + expected: FAIL + + [a (width: 32px) for .ab-size > .size > span] + expected: FAIL + + [b (width: 32px) for .ab-size > .size > span] + expected: FAIL + + [a (width: 8px) for .a-size > .b-size > .a-inline > span] + expected: FAIL + + [b (width: 16px) for .a-size > .b-size > .a-inline > span] + expected: FAIL + + [a (height: 32px) for .a-size > .b-size > .a-inline > span] + expected: FAIL + + [a (inline-size: 8px) for .a-size > .b-size > .a-inline > span] + expected: FAIL + + [b (inline-size: 16px) for .a-size > .b-size > .a-inline > span] + expected: FAIL + + [a (block-size: 32px) for .a-size > .b-size > .a-inline > span] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/container-size-invalidation-after-load.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/container-size-invalidation-after-load.html.ini new file mode 100644 index 000000000000..489cdd6a8fe2 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/container-size-invalidation-after-load.html.ini @@ -0,0 +1,3 @@ +[container-size-invalidation-after-load.html] + [@container: invalidation of container size after load event] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container-dynamic.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container-dynamic.html.ini new file mode 100644 index 000000000000..7cd3bd77b75d --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container-dynamic.html.ini @@ -0,0 +1,2 @@ +[counters-in-container-dynamic.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container.html.ini new file mode 100644 index 000000000000..4bf610e9b835 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/counters-in-container.html.ini @@ -0,0 +1,2 @@ +[counters-in-container.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/display-contents.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/display-contents.html.ini index 6e621b35be30..3b16182c1827 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/display-contents.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/display-contents.html.ini @@ -4,6 +4,3 @@ [getComputedStyle when intermediate container becomes display:contents] expected: FAIL - - [getComputedStyle when container is display:contents] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/display-none.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/display-none.html.ini index 170b460379a2..5c2a480abeca 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/display-none.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/display-none.html.ini @@ -37,18 +37,3 @@ [getComputedStyle when in display:none with layout dirty outer element] expected: FAIL - - [getComputedStyle when container is display:none] - expected: FAIL - - [getComputedStyle when inner container is display:none] - expected: FAIL - - [getComputedStyle when intermediate ancestor is display:none] - expected: FAIL - - [getComputedStyle when outer container is display:none] - expected: FAIL - - [getComputedStyle on ::before when container is display:none] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/fieldset-legend-change.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/fieldset-legend-change.html.ini new file mode 100644 index 000000000000..9d5d377cd9c5 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/fieldset-legend-change.html.ini @@ -0,0 +1,2 @@ +[fieldset-legend-change.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units-dynamic.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units-dynamic.html.ini index 3a8ce7450987..ab8654432907 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units-dynamic.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units-dynamic.html.ini @@ -1,12 +1,12 @@ [font-relative-units-dynamic.html] - [em relative before change] - expected: FAIL - - [rem relative before change] - expected: FAIL - [ex relative before change] expected: FAIL [ch relative before change] expected: FAIL + + [em relative after change] + expected: FAIL + + [rem relative after change] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units.html.ini new file mode 100644 index 000000000000..3e8e01654403 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/font-relative-units.html.ini @@ -0,0 +1,12 @@ +[font-relative-units.html] + [em relative inline-size] + expected: FAIL + + [rem relative inline-size] + expected: FAIL + + [ex relative inline-size] + expected: FAIL + + [ch relative inline-size] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/fragmented-container-001.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/fragmented-container-001.html.ini new file mode 100644 index 000000000000..06a25a08df23 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/fragmented-container-001.html.ini @@ -0,0 +1,3 @@ +[fragmented-container-001.html] + [Children of fragmented inline-size container should match inline-size of first fragment] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/ineligible-containment.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/ineligible-containment.html.ini index a18c90ee2a2b..1a6d08f1f00c 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/ineligible-containment.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/ineligible-containment.html.ini @@ -1,6 +1,3 @@ [ineligible-containment.html] [Changing containment eligibility invalidates style] expected: FAIL - - [Container ineligible for containment] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/inline-size-and-min-width.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/inline-size-and-min-width.html.ini new file mode 100644 index 000000000000..be23d2784966 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/inline-size-and-min-width.html.ini @@ -0,0 +1,3 @@ +[inline-size-and-min-width.html] + [min-width of inline-size container affects container size] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/multicol-container-001.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/multicol-container-001.html.ini new file mode 100644 index 000000000000..f74fceae162d --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/multicol-container-001.html.ini @@ -0,0 +1,3 @@ +[multicol-container-001.html] + [Children of multicol inline-size container should match inline-size of the container] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/pseudo-elements-003.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/pseudo-elements-003.html.ini index 38287f613b1d..29c1da91da21 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/pseudo-elements-003.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/pseudo-elements-003.html.ini @@ -1,3 +1,9 @@ [pseudo-elements-003.html] [Originating element container for ::backdrop] expected: FAIL + + [Originating element container for outer ::first-line] + expected: FAIL + + [Originating element container for outer ::first-letter] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/query-content-box.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/query-content-box.html.ini new file mode 100644 index 000000000000..f21577ea55e9 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/query-content-box.html.ini @@ -0,0 +1,12 @@ +[query-content-box.html] + [Size queries with content-box sizing] + expected: FAIL + + [Size queries with border-box sizing] + expected: FAIL + + [Size queries with content-box sizing and overflow:scroll] + expected: FAIL + + [Size queries with border-box sizing and overflow:scroll] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/query-evaluation.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/query-evaluation.html.ini index 6582d211b48a..608d6f826143 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/query-evaluation.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/query-evaluation.html.ini @@ -56,38 +56,38 @@ [style((height: 2px) or (not ((height: 2px) and (width: 1px))))] expected: FAIL - [(height)] - expected: FAIL - - [((height))] - expected: FAIL - - [((((height))))] - expected: FAIL - [(not (width))] expected: FAIL - [((height) and (height))] - expected: FAIL - - [((height) and (width) and (width))] - expected: FAIL - - [((width) and (height) and (width))] - expected: FAIL - - [((width) and (width) and (height))] - expected: FAIL - - [((height) or (height))] - expected: FAIL - [(not ((width) and (width)))] expected: FAIL - [((width) and (not ((height) or (width))))] + [(width)] expected: FAIL - [((height) or ((height) and (width)))] + [((width))] + expected: FAIL + + [((((width))))] + expected: FAIL + + [((width) and (width))] + expected: FAIL + + [((width) and (width) and (width))] + expected: FAIL + + [((width) or (width))] + expected: FAIL + + [((width) or (width) or (width))] + expected: FAIL + + [((height) or (width) or (width))] + expected: FAIL + + [((width) or (height) or (width))] + expected: FAIL + + [((width) or (width) or (height))] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/resize-while-content-visibility-hidden.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/resize-while-content-visibility-hidden.html.ini new file mode 100644 index 000000000000..9a43f8e35d16 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/resize-while-content-visibility-hidden.html.ini @@ -0,0 +1,2 @@ +[resize-while-content-visibility-hidden.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/size-feature-evaluation.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/size-feature-evaluation.html.ini index 7c33ab97157b..7877b52b7c77 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/size-feature-evaluation.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/size-feature-evaluation.html.ini @@ -2,83 +2,101 @@ [(width < 100px) (.horizontal)] expected: FAIL - [(min-width: 101px) (.horizontal)] - expected: FAIL - [(max-width: 99px) (.horizontal)] expected: FAIL [(height < 200px) (.horizontal)] expected: FAIL - [(min-height: 201px) (.horizontal)] - expected: FAIL - [(max-height: 199px) (.horizontal)] expected: FAIL - [(orientation: landscape) (.horizontal)] - expected: FAIL - [(aspect-ratio: 2/1) (.horizontal)] expected: FAIL [(width < 100px) (.vertical)] expected: FAIL - [(min-width: 101px) (.vertical)] - expected: FAIL - [(max-width: 99px) (.vertical)] expected: FAIL [(height < 200px) (.vertical)] expected: FAIL - [(min-height: 201px) (.vertical)] - expected: FAIL - [(max-height: 199px) (.vertical)] expected: FAIL - [(orientation: landscape) (.vertical)] - expected: FAIL - [(aspect-ratio: 2/1) (.vertical)] expected: FAIL [(inline-size < 100px) (.horizontal)] expected: FAIL - [(min-inline-size: 101px) (.horizontal)] - expected: FAIL - [(max-inline-size: 99px) (.horizontal)] expected: FAIL [(block-size < 200px) (.horizontal)] expected: FAIL - [(min-block-size: 201px) (.horizontal)] - expected: FAIL - [(max-block-size: 199px) (.horizontal)] expected: FAIL [(block-size < 100px) (.vertical)] expected: FAIL - [(min-block-size: 101px) (.vertical)] - expected: FAIL - [(max-block-size: 99px) (.vertical)] expected: FAIL [(inline-size < 200px) (.vertical)] expected: FAIL - [(min-inline-size: 201px) (.vertical)] - expected: FAIL - [(max-inline-size: 199px) (.vertical)] expected: FAIL + + [(width >= 100px) (.horizontal)] + expected: FAIL + + [(min-width: 100px) (.horizontal)] + expected: FAIL + + [(height >= 200px) (.horizontal)] + expected: FAIL + + [(min-height: 200px) (.horizontal)] + expected: FAIL + + [(inline-size >= 100px) (.horizontal)] + expected: FAIL + + [(min-inline-size: 100px) (.horizontal)] + expected: FAIL + + [(block-size >= 200px) (.horizontal)] + expected: FAIL + + [(min-block-size: 200px) (.horizontal)] + expected: FAIL + + [(width >= 100px) (.vertical)] + expected: FAIL + + [(min-width: 100px) (.vertical)] + expected: FAIL + + [(height >= 200px) (.vertical)] + expected: FAIL + + [(min-height: 200px) (.vertical)] + expected: FAIL + + [(block-size >= 100px) (.vertical)] + expected: FAIL + + [(min-block-size: 100px) (.vertical)] + expected: FAIL + + [(inline-size >= 200px) (.vertical)] + expected: FAIL + + [(min-inline-size: 200px) (.vertical)] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/style-change-in-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/style-change-in-container.html.ini new file mode 100644 index 000000000000..a394a8ae697b --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/style-change-in-container.html.ini @@ -0,0 +1,3 @@ +[style-change-in-container.html] + [Basic test for container query evaluation stability] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/svg-foreignobject-no-size-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/svg-foreignobject-no-size-container.html.ini deleted file mode 100644 index ecfd70444c22..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/svg-foreignobject-no-size-container.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[svg-foreignobject-no-size-container.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/svg-g-no-size-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/svg-g-no-size-container.html.ini deleted file mode 100644 index 4213a08a8113..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/svg-g-no-size-container.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[svg-g-no-size-container.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/svg-root-size-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/svg-root-size-container.html.ini new file mode 100644 index 000000000000..f9b04ee16b71 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/svg-root-size-container.html.ini @@ -0,0 +1,6 @@ +[svg-root-size-container.html] + [SVG text querying SVG root size container] + expected: FAIL + + [div in foreignObject querying SVG root size container] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-container.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-container.html.ini index a2f7493fc77b..8acade9d67c0 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-container.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-dialog-container.html.ini @@ -1,3 +1,3 @@ [top-layer-dialog-container.html] - [#dialog initially sized by #containing-block] + [#dialog sized by viewport] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-nested-dialog.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-nested-dialog.html.ini index e9196d801c12..af9391443a7c 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/top-layer-nested-dialog.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/top-layer-nested-dialog.html.ini @@ -1,6 +1,3 @@ [top-layer-nested-dialog.html] - [Dialogs initially not matching for container queries] - expected: FAIL - - [Dialogs still not matching after showModal] + [@container queries start matching] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/transition-style-change-event.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/transition-style-change-event.html.ini new file mode 100644 index 000000000000..805e5ca57d58 --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/container-queries/transition-style-change-event.html.ini @@ -0,0 +1,3 @@ +[transition-style-change-event.html] + [Container Queries - Style Change Event for transitions] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/unsupported-axis.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/unsupported-axis.html.ini index f74f6d3abcbb..1658c29088e5 100644 --- a/testing/web-platform/meta/css/css-contain/container-queries/unsupported-axis.html.ini +++ b/testing/web-platform/meta/css/css-contain/container-queries/unsupported-axis.html.ini @@ -1,27 +1,6 @@ [unsupported-axis.html] - [(height > 0px)] + [(width > 0px)] expected: FAIL - [((height > 0px) or (width > 0px))] - expected: FAIL - - [((width > 0px) or (height > 0px))] - expected: FAIL - - [((orientation: landscape) or (width > 0px))] - expected: FAIL - - [((width > 0px) or (orientation: landscape))] - expected: FAIL - - [((height > 0px) or (orientation: landscape))] - expected: FAIL - - [((height > 0px) or (orientation: landscape)), with contain:size] - expected: FAIL - - [(block-size > 0px)] - expected: FAIL - - [(block-size > 0px), with writing-mode:vertical-rl] + [(inline-size > 0px)] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/container-queries/whitespace-update-after-removal.html.ini b/testing/web-platform/meta/css/css-contain/container-queries/whitespace-update-after-removal.html.ini deleted file mode 100644 index 4d3034d71f7d..000000000000 --- a/testing/web-platform/meta/css/css-contain/container-queries/whitespace-update-after-removal.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[whitespace-update-after-removal.html] - expected: FAIL