Bug 1765999 - Move some of the media query code to a more generic queries module. r=hiro

No behavior change, just moving and renaming files.

The code in the "queries" module will be shared between @media and
@container.

@media has some other code that container queries doesn't need like
MediaList / MediaType / etc. That remains in the media_queries module.

Differential Revision: https://phabricator.services.mozilla.com/D144435
This commit is contained in:
Emilio Cobos Álvarez 2022-04-24 21:48:02 +00:00
parent 63420746b0
commit e097b4be55
10 changed files with 127 additions and 118 deletions

View File

@ -6,8 +6,7 @@
use crate::gecko_bindings::bindings; use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs; use crate::gecko_bindings::structs;
use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements}; use crate::queries::feature::{AllowsRanges, Evaluator, ParsingRequirements, QueryFeatureDescription};
use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
use crate::media_queries::{Device, MediaType}; use crate::media_queries::{Device, MediaType};
use crate::values::computed::{Context, CSSPixelLength, Ratio, Resolution}; use crate::values::computed::{Context, CSSPixelLength, Ratio, Resolution};
use app_units::Au; use app_units::Au;
@ -583,7 +582,7 @@ macro_rules! bool_pref_feature {
/// to support new types in these entries and (2) ensuring that either /// to support new types in these entries and (2) ensuring that either
/// nsPresContext::MediaFeatureValuesChanged is called when the value that /// nsPresContext::MediaFeatureValuesChanged is called when the value that
/// would be returned by the evaluator function could change. /// would be returned by the evaluator function could change.
pub static MEDIA_FEATURES: [MediaFeatureDescription; 60] = [ pub static MEDIA_FEATURES: [QueryFeatureDescription; 60] = [
feature!( feature!(
atom!("width"), atom!("width"),
AllowsRanges::Yes, AllowsRanges::Yes,

View File

@ -103,10 +103,11 @@ pub mod invalidation;
#[allow(missing_docs)] // TODO. #[allow(missing_docs)] // TODO.
pub mod logical_geometry; pub mod logical_geometry;
pub mod matching; pub mod matching;
#[macro_use]
pub mod media_queries; pub mod media_queries;
pub mod parallel; pub mod parallel;
pub mod parser; pub mod parser;
#[macro_use]
pub mod queries;
pub mod rule_cache; pub mod rule_cache;
pub mod rule_collector; pub mod rule_collector;
pub mod rule_tree; pub mod rule_tree;

View File

@ -6,7 +6,7 @@
//! //!
//! https://drafts.csswg.org/mediaqueries/#typedef-media-query //! https://drafts.csswg.org/mediaqueries/#typedef-media-query
use super::media_condition::MediaCondition; use crate::queries::QueryCondition;
use crate::parser::ParserContext; use crate::parser::ParserContext;
use crate::str::string_as_ascii_lowercase; use crate::str::string_as_ascii_lowercase;
use crate::values::CustomIdent; use crate::values::CustomIdent;
@ -66,7 +66,7 @@ pub struct MediaQuery {
pub media_type: MediaQueryType, pub media_type: MediaQueryType,
/// The condition that this media query contains. This cannot have `or` /// The condition that this media query contains. This cannot have `or`
/// in the first level. /// in the first level.
pub condition: Option<MediaCondition>, pub condition: Option<QueryCondition>,
} }
impl ToCss for MediaQuery { impl ToCss for MediaQuery {
@ -134,9 +134,9 @@ impl MediaQuery {
.unwrap_or_default(); .unwrap_or_default();
let condition = if explicit_media_type.is_none() { let condition = if explicit_media_type.is_none() {
Some(MediaCondition::parse(context, input)?) Some(QueryCondition::parse(context, input)?)
} else if input.try_parse(|i| i.expect_ident_matching("and")).is_ok() { } else if input.try_parse(|i| i.expect_ident_matching("and")).is_ok() {
Some(MediaCondition::parse_disallow_or(context, input)?) Some(QueryCondition::parse_disallow_or(context, input)?)
} else { } else {
None None
}; };

View File

@ -6,15 +6,9 @@
//! //!
//! [mq]: https://drafts.csswg.org/mediaqueries/ //! [mq]: https://drafts.csswg.org/mediaqueries/
mod media_condition;
mod media_list; mod media_list;
mod media_query; mod media_query;
#[macro_use]
pub mod media_feature;
pub mod media_feature_expression;
pub use self::media_condition::MediaCondition;
pub use self::media_feature_expression::MediaFeatureExpression;
pub use self::media_list::MediaList; pub use self::media_list::MediaList;
pub use self::media_query::{MediaQuery, MediaQueryType, MediaType, Qualifier}; pub use self::media_query::{MediaQuery, MediaQueryType, MediaType, Qualifier};

View File

@ -2,11 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! A media query condition: //! A query condition:
//! //!
//! https://drafts.csswg.org/mediaqueries-4/#typedef-media-condition //! https://drafts.csswg.org/mediaqueries-4/#typedef-media-condition
//! https://drafts.csswg.org/css-contain-3/#typedef-container-condition
use super::MediaFeatureExpression; use super::QueryFeatureExpression;
use crate::parser::ParserContext; use crate::parser::ParserContext;
use crate::values::computed; use crate::values::computed;
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
@ -28,38 +29,38 @@ enum AllowOr {
No, No,
} }
/// Represents a media condition. /// Represents a condition.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum MediaCondition { pub enum QueryCondition {
/// A simple media feature expression, implicitly parenthesized. /// A simple feature expression, implicitly parenthesized.
Feature(MediaFeatureExpression), Feature(QueryFeatureExpression),
/// A negation of a condition. /// A negation of a condition.
Not(Box<MediaCondition>), Not(Box<QueryCondition>),
/// A set of joint operations. /// A set of joint operations.
Operation(Box<[MediaCondition]>, Operator), Operation(Box<[QueryCondition]>, Operator),
/// A condition wrapped in parenthesis. /// A condition wrapped in parenthesis.
InParens(Box<MediaCondition>), InParens(Box<QueryCondition>),
} }
impl ToCss for MediaCondition { impl ToCss for QueryCondition {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where where
W: fmt::Write, W: fmt::Write,
{ {
match *self { match *self {
// NOTE(emilio): MediaFeatureExpression already includes the // NOTE(emilio): QueryFeatureExpression already includes the
// parenthesis. // parenthesis.
MediaCondition::Feature(ref f) => f.to_css(dest), QueryCondition::Feature(ref f) => f.to_css(dest),
MediaCondition::Not(ref c) => { QueryCondition::Not(ref c) => {
dest.write_str("not ")?; dest.write_str("not ")?;
c.to_css(dest) c.to_css(dest)
}, },
MediaCondition::InParens(ref c) => { QueryCondition::InParens(ref c) => {
dest.write_char('(')?; dest.write_char('(')?;
c.to_css(dest)?; c.to_css(dest)?;
dest.write_char(')') dest.write_char(')')
}, },
MediaCondition::Operation(ref list, op) => { QueryCondition::Operation(ref list, op) => {
let mut iter = list.iter(); let mut iter = list.iter();
iter.next().unwrap().to_css(dest)?; iter.next().unwrap().to_css(dest)?;
for item in iter { for item in iter {
@ -74,8 +75,8 @@ impl ToCss for MediaCondition {
} }
} }
impl MediaCondition { impl QueryCondition {
/// Parse a single media condition. /// Parse a single condition.
pub fn parse<'i, 't>( pub fn parse<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
@ -83,9 +84,9 @@ impl MediaCondition {
Self::parse_internal(context, input, AllowOr::Yes) Self::parse_internal(context, input, AllowOr::Yes)
} }
/// Parse a single media condition, disallowing `or` expressions. /// Parse a single condition, disallowing `or` expressions.
/// ///
/// To be used from the legacy media query syntax. /// To be used from the legacy query syntax.
pub fn parse_disallow_or<'i, 't>( pub fn parse_disallow_or<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
@ -109,7 +110,7 @@ impl MediaCondition {
if is_negation { if is_negation {
let inner_condition = Self::parse_in_parens(context, input)?; let inner_condition = Self::parse_in_parens(context, input)?;
return Ok(MediaCondition::Not(Box::new(inner_condition))); return Ok(QueryCondition::Not(Box::new(inner_condition)));
} }
// ParenthesisBlock. // ParenthesisBlock.
@ -134,7 +135,7 @@ impl MediaCondition {
loop { loop {
if input.try_parse(|i| i.expect_ident_matching(delim)).is_err() { if input.try_parse(|i| i.expect_ident_matching(delim)).is_err() {
return Ok(MediaCondition::Operation( return Ok(QueryCondition::Operation(
conditions.into_boxed_slice(), conditions.into_boxed_slice(),
operator, operator,
)); ));
@ -144,7 +145,7 @@ impl MediaCondition {
} }
} }
/// Parse a media condition in parentheses. /// Parse a condition in parentheses.
pub fn parse_in_parens<'i, 't>( pub fn parse_in_parens<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
@ -160,20 +161,20 @@ impl MediaCondition {
input.parse_nested_block(|input| { input.parse_nested_block(|input| {
// Base case. // Base case.
if let Ok(inner) = input.try_parse(|i| Self::parse(context, i)) { if let Ok(inner) = input.try_parse(|i| Self::parse(context, i)) {
return Ok(MediaCondition::InParens(Box::new(inner))); return Ok(QueryCondition::InParens(Box::new(inner)));
} }
let expr = MediaFeatureExpression::parse_in_parenthesis_block(context, input)?; let expr = QueryFeatureExpression::parse_in_parenthesis_block(context, input)?;
Ok(MediaCondition::Feature(expr)) Ok(QueryCondition::Feature(expr))
}) })
} }
/// Whether this condition matches the device and quirks mode. /// Whether this condition matches the device and quirks mode.
pub fn matches(&self, context: &computed::Context) -> bool { pub fn matches(&self, context: &computed::Context) -> bool {
match *self { match *self {
MediaCondition::Feature(ref f) => f.matches(context), QueryCondition::Feature(ref f) => f.matches(context),
MediaCondition::InParens(ref c) => c.matches(context), QueryCondition::InParens(ref c) => c.matches(context),
MediaCondition::Not(ref c) => !c.matches(context), QueryCondition::Not(ref c) => !c.matches(context),
MediaCondition::Operation(ref conditions, op) => { QueryCondition::Operation(ref conditions, op) => {
let mut iter = conditions.iter(); let mut iter = conditions.iter();
match op { match op {
Operator::And => iter.all(|c| c.matches(context)), Operator::And => iter.all(|c| c.matches(context)),

View File

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Media features. //! Query features.
use crate::parser::ParserContext; use crate::parser::ParserContext;
use crate::values::computed::{self, CSSPixelLength, Resolution, Ratio}; use crate::values::computed::{self, CSSPixelLength, Resolution, Ratio};
@ -14,7 +14,7 @@ use style_traits::ParseError;
/// A generic discriminant for an enum value. /// A generic discriminant for an enum value.
pub type KeywordDiscriminant = u8; pub type KeywordDiscriminant = u8;
type MediaFeatureGetter<T> = fn(device: &computed::Context) -> T; type QueryFeatureGetter<T> = fn(device: &computed::Context) -> T;
/// Serializes a given discriminant. /// Serializes a given discriminant.
/// ///
@ -28,19 +28,19 @@ pub type KeywordParser = for<'a, 'i, 't> fn(
input: &'a mut Parser<'i, 't>, input: &'a mut Parser<'i, 't>,
) -> Result<KeywordDiscriminant, ParseError<'i>>; ) -> Result<KeywordDiscriminant, ParseError<'i>>;
/// An evaluator for a given media feature. /// An evaluator for a given feature.
/// ///
/// This determines the kind of values that get parsed, too. /// This determines the kind of values that get parsed, too.
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum Evaluator { pub enum Evaluator {
Length(MediaFeatureGetter<CSSPixelLength>), Length(QueryFeatureGetter<CSSPixelLength>),
Integer(MediaFeatureGetter<u32>), Integer(QueryFeatureGetter<u32>),
Float(MediaFeatureGetter<f32>), Float(QueryFeatureGetter<f32>),
BoolInteger(MediaFeatureGetter<bool>), BoolInteger(QueryFeatureGetter<bool>),
/// A non-negative number ratio, such as the one from device-pixel-ratio. /// A non-negative number ratio, such as the one from device-pixel-ratio.
NumberRatio(MediaFeatureGetter<Ratio>), NumberRatio(QueryFeatureGetter<Ratio>),
/// A resolution. /// A resolution.
Resolution(MediaFeatureGetter<Resolution>), Resolution(QueryFeatureGetter<Resolution>),
/// A keyword value. /// A keyword value.
Enumerated { Enumerated {
/// The parser to get a discriminant given a string. /// The parser to get a discriminant given a string.
@ -67,14 +67,14 @@ macro_rules! keyword_evaluator {
context: &$crate::parser::ParserContext, context: &$crate::parser::ParserContext,
input: &mut $crate::cssparser::Parser<'i, 't>, input: &mut $crate::cssparser::Parser<'i, 't>,
) -> Result< ) -> Result<
$crate::media_queries::media_feature::KeywordDiscriminant, $crate::queries::feature::KeywordDiscriminant,
::style_traits::ParseError<'i>, ::style_traits::ParseError<'i>,
> { > {
let kw = <$keyword_type as $crate::parser::Parse>::parse(context, input)?; let kw = <$keyword_type as $crate::parser::Parse>::parse(context, input)?;
Ok(kw as $crate::media_queries::media_feature::KeywordDiscriminant) Ok(kw as $crate::queries::feature::KeywordDiscriminant)
} }
fn __serialize(kw: $crate::media_queries::media_feature::KeywordDiscriminant) -> String { fn __serialize(kw: $crate::queries::feature::KeywordDiscriminant) -> String {
// This unwrap is ok because the only discriminants that get // This unwrap is ok because the only discriminants that get
// back to us is the ones that `parse` produces. // back to us is the ones that `parse` produces.
let value: $keyword_type = ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap(); let value: $keyword_type = ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap();
@ -83,7 +83,7 @@ macro_rules! keyword_evaluator {
fn __evaluate( fn __evaluate(
context: &$crate::values::computed::Context, context: &$crate::values::computed::Context,
value: Option<$crate::media_queries::media_feature::KeywordDiscriminant>, value: Option<$crate::queries::feature::KeywordDiscriminant>,
) -> bool { ) -> bool {
// This unwrap is ok because the only discriminants that get // This unwrap is ok because the only discriminants that get
// back to us is the ones that `parse` produces. // back to us is the ones that `parse` produces.
@ -92,7 +92,7 @@ macro_rules! keyword_evaluator {
$actual_evaluator(context, value) $actual_evaluator(context, value)
} }
$crate::media_queries::media_feature::Evaluator::Enumerated { $crate::queries::feature::Evaluator::Enumerated {
parser: __parse, parser: __parse,
serializer: __serialize, serializer: __serialize,
evaluator: __evaluate, evaluator: __evaluate,
@ -111,7 +111,7 @@ bitflags! {
} }
} }
/// Whether a media feature allows ranges or not. /// Whether a feature allows ranges or not.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum AllowsRanges { pub enum AllowsRanges {
@ -119,9 +119,9 @@ pub enum AllowsRanges {
No, No,
} }
/// A description of a media feature. /// A description of a feature.
pub struct MediaFeatureDescription { pub struct QueryFeatureDescription {
/// The media feature name, in ascii lowercase. /// The feature name, in ascii lowercase.
pub name: Atom, pub name: Atom,
/// Whether min- / max- prefixes are allowed or not. /// Whether min- / max- prefixes are allowed or not.
pub allows_ranges: AllowsRanges, pub allows_ranges: AllowsRanges,
@ -133,18 +133,18 @@ pub struct MediaFeatureDescription {
pub requirements: ParsingRequirements, pub requirements: ParsingRequirements,
} }
impl MediaFeatureDescription { impl QueryFeatureDescription {
/// Whether this media feature allows ranges. /// Whether this feature allows ranges.
#[inline] #[inline]
pub fn allows_ranges(&self) -> bool { pub fn allows_ranges(&self) -> bool {
self.allows_ranges == AllowsRanges::Yes self.allows_ranges == AllowsRanges::Yes
} }
} }
/// A simple helper to construct a `MediaFeatureDescription`. /// A simple helper to construct a `QueryFeatureDescription`.
macro_rules! feature { macro_rules! feature {
($name:expr, $allows_ranges:expr, $evaluator:expr, $reqs:expr,) => { ($name:expr, $allows_ranges:expr, $evaluator:expr, $reqs:expr,) => {
$crate::media_queries::media_feature::MediaFeatureDescription { $crate::queries::feature::QueryFeatureDescription {
name: $name, name: $name,
allows_ranges: $allows_ranges, allows_ranges: $allows_ranges,
evaluator: $evaluator, evaluator: $evaluator,
@ -153,9 +153,9 @@ macro_rules! feature {
}; };
} }
impl fmt::Debug for MediaFeatureDescription { impl fmt::Debug for QueryFeatureDescription {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("MediaFeatureExpression") f.debug_struct("QueryFeatureDescription")
.field("name", &self.name) .field("name", &self.name)
.field("allows_ranges", &self.allows_ranges) .field("allows_ranges", &self.allows_ranges)
.field("requirements", &self.requirements) .field("requirements", &self.requirements)

View File

@ -2,11 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Parsing for media feature expressions, like `(foo: bar)` or //! Parsing for query feature expressions, like `(foo: bar)` or
//! `(width >= 400px)`. //! `(width >= 400px)`.
use super::media_feature::{Evaluator, MediaFeatureDescription}; use super::feature::{Evaluator, QueryFeatureDescription};
use super::media_feature::{KeywordDiscriminant, ParsingRequirements}; use super::feature::{KeywordDiscriminant, ParsingRequirements};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use crate::gecko::media_features::MEDIA_FEATURES; use crate::gecko::media_features::MEDIA_FEATURES;
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
@ -22,7 +22,7 @@ use std::cmp::{Ordering, PartialOrd};
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// The kind of matching that should be performed on a media feature value. /// The kind of matching that should be performed on a feature value.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum Range { pub enum Range {
/// At least the specified value. /// At least the specified value.
@ -31,7 +31,7 @@ pub enum Range {
Max, Max,
} }
/// The operator that was specified in this media feature. /// The operator that was specified in this feature.
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum Operator { pub enum Operator {
/// = /// =
@ -63,8 +63,7 @@ impl ToCss for Operator {
/// Either a `Range` or an `Operator`. /// Either a `Range` or an `Operator`.
/// ///
/// Ranged media features are not allowed with operations (that'd make no /// Ranged features are not allowed with operations (that'd make no sense).
/// sense).
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
pub enum RangeOrOperator { pub enum RangeOrOperator {
/// A `Range`. /// A `Range`.
@ -121,16 +120,16 @@ impl RangeOrOperator {
} }
} }
/// A feature expression contains a reference to the media feature, the value /// A feature expression contains a reference to the feature, the value the
/// the media query contained, and the range to evaluate. /// query contained, and the range to evaluate.
#[derive(Clone, Debug, MallocSizeOf, ToShmem, PartialEq)] #[derive(Clone, Debug, MallocSizeOf, ToShmem, PartialEq)]
pub struct MediaFeatureExpression { pub struct QueryFeatureExpression {
feature_index: usize, feature_index: usize,
value: Option<MediaExpressionValue>, value: Option<QueryExpressionValue>,
range_or_operator: Option<RangeOrOperator>, range_or_operator: Option<RangeOrOperator>,
} }
impl ToCss for MediaFeatureExpression { impl ToCss for QueryFeatureExpression {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where where
W: fmt::Write, W: fmt::Write,
@ -243,10 +242,10 @@ fn disabled_by_pref(feature: &Atom, context: &ParserContext) -> bool {
false false
} }
impl MediaFeatureExpression { impl QueryFeatureExpression {
fn new( fn new(
feature_index: usize, feature_index: usize,
value: Option<MediaExpressionValue>, value: Option<QueryExpressionValue>,
range_or_operator: Option<RangeOrOperator>, range_or_operator: Option<RangeOrOperator>,
) -> Self { ) -> Self {
debug_assert!(feature_index < MEDIA_FEATURES.len()); debug_assert!(feature_index < MEDIA_FEATURES.len());
@ -257,11 +256,11 @@ impl MediaFeatureExpression {
} }
} }
fn feature(&self) -> &'static MediaFeatureDescription { fn feature(&self) -> &'static QueryFeatureDescription {
&MEDIA_FEATURES[self.feature_index] &MEDIA_FEATURES[self.feature_index]
} }
/// Parse a media expression of the form: /// Parse a feature expression of the form:
/// ///
/// ``` /// ```
/// (media-feature: media-value) /// (media-feature: media-value)
@ -274,8 +273,7 @@ impl MediaFeatureExpression {
input.parse_nested_block(|input| Self::parse_in_parenthesis_block(context, input)) input.parse_nested_block(|input| Self::parse_in_parenthesis_block(context, input))
} }
/// Parse a media feature expression where we've already consumed the /// Parse a feature expression where we've already consumed the parenthesis.
/// parenthesis.
pub fn parse_in_parenthesis_block<'i, 't>( pub fn parse_in_parenthesis_block<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
@ -332,9 +330,8 @@ impl MediaFeatureExpression {
let operator = input.try_parse(consume_operation_or_colon); let operator = input.try_parse(consume_operation_or_colon);
let operator = match operator { let operator = match operator {
Err(..) => { Err(..) => {
// If there's no colon, this is a media query of the // If there's no colon, this is a query of the form
// form '(<feature>)', that is, there's no value // '(<feature>)', that is, there's no value specified.
// specified.
// //
// Gecko doesn't allow ranged expressions without a // Gecko doesn't allow ranged expressions without a
// value, so just reject them here too. // value, so just reject them here too.
@ -370,7 +367,7 @@ impl MediaFeatureExpression {
}, },
}; };
let value = MediaExpressionValue::parse(feature, context, input).map_err(|err| { let value = QueryExpressionValue::parse(feature, context, input).map_err(|err| {
err.location err.location
.new_custom_error(StyleParseErrorKind::MediaQueryExpectedFeatureValue) .new_custom_error(StyleParseErrorKind::MediaQueryExpectedFeatureValue)
})?; })?;
@ -378,15 +375,15 @@ impl MediaFeatureExpression {
Ok(Self::new(feature_index, Some(value), range_or_operator)) Ok(Self::new(feature_index, Some(value), range_or_operator))
} }
/// Returns whether this media query evaluates to true for the given device. /// Returns whether this query evaluates to true for the given device.
pub fn matches(&self, context: &computed::Context) -> bool { pub fn matches(&self, context: &computed::Context) -> bool {
let value = self.value.as_ref(); let value = self.value.as_ref();
macro_rules! expect { macro_rules! expect {
($variant:ident) => { ($variant:ident) => {
value.map(|value| match *value { value.map(|value| match *value {
MediaExpressionValue::$variant(ref v) => v, QueryExpressionValue::$variant(ref v) => v,
_ => unreachable!("Unexpected MediaExpressionValue"), _ => unreachable!("Unexpected QueryExpressionValue"),
}) })
}; };
} }
@ -442,7 +439,7 @@ impl MediaFeatureExpression {
} }
} }
/// A value found or expected in a media expression. /// A value found or expected in a expression.
/// ///
/// FIXME(emilio): How should calc() serialize in the Number / Integer / /// FIXME(emilio): How should calc() serialize in the Number / Integer /
/// BoolInteger / NumberRatio case, as computed or as specified value? /// BoolInteger / NumberRatio case, as computed or as specified value?
@ -451,7 +448,7 @@ impl MediaFeatureExpression {
/// ///
/// See: https://github.com/w3c/csswg-drafts/issues/1968 /// See: https://github.com/w3c/csswg-drafts/issues/1968
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum MediaExpressionValue { pub enum QueryExpressionValue {
/// A length. /// A length.
Length(Length), Length(Length),
/// A (non-negative) integer. /// A (non-negative) integer.
@ -470,19 +467,19 @@ pub enum MediaExpressionValue {
Enumerated(KeywordDiscriminant), Enumerated(KeywordDiscriminant),
} }
impl MediaExpressionValue { impl QueryExpressionValue {
fn to_css<W>(&self, dest: &mut CssWriter<W>, for_expr: &MediaFeatureExpression) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>, for_expr: &QueryFeatureExpression) -> fmt::Result
where where
W: fmt::Write, W: fmt::Write,
{ {
match *self { match *self {
MediaExpressionValue::Length(ref l) => l.to_css(dest), QueryExpressionValue::Length(ref l) => l.to_css(dest),
MediaExpressionValue::Integer(v) => v.to_css(dest), QueryExpressionValue::Integer(v) => v.to_css(dest),
MediaExpressionValue::Float(v) => v.to_css(dest), QueryExpressionValue::Float(v) => v.to_css(dest),
MediaExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }), QueryExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }),
MediaExpressionValue::NumberRatio(ratio) => ratio.to_css(dest), QueryExpressionValue::NumberRatio(ratio) => ratio.to_css(dest),
MediaExpressionValue::Resolution(ref r) => r.to_css(dest), QueryExpressionValue::Resolution(ref r) => r.to_css(dest),
MediaExpressionValue::Enumerated(value) => match for_expr.feature().evaluator { QueryExpressionValue::Enumerated(value) => match for_expr.feature().evaluator {
Evaluator::Enumerated { serializer, .. } => dest.write_str(&*serializer(value)), Evaluator::Enumerated { serializer, .. } => dest.write_str(&*serializer(value)),
_ => unreachable!(), _ => unreachable!(),
}, },
@ -490,18 +487,18 @@ impl MediaExpressionValue {
} }
fn parse<'i, 't>( fn parse<'i, 't>(
for_feature: &MediaFeatureDescription, for_feature: &QueryFeatureDescription,
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
) -> Result<MediaExpressionValue, ParseError<'i>> { ) -> Result<QueryExpressionValue, ParseError<'i>> {
Ok(match for_feature.evaluator { Ok(match for_feature.evaluator {
Evaluator::Length(..) => { Evaluator::Length(..) => {
let length = Length::parse_non_negative(context, input)?; let length = Length::parse_non_negative(context, input)?;
MediaExpressionValue::Length(length) QueryExpressionValue::Length(length)
}, },
Evaluator::Integer(..) => { Evaluator::Integer(..) => {
let integer = Integer::parse_non_negative(context, input)?; let integer = Integer::parse_non_negative(context, input)?;
MediaExpressionValue::Integer(integer.value() as u32) QueryExpressionValue::Integer(integer.value() as u32)
}, },
Evaluator::BoolInteger(..) => { Evaluator::BoolInteger(..) => {
let integer = Integer::parse_non_negative(context, input)?; let integer = Integer::parse_non_negative(context, input)?;
@ -509,22 +506,22 @@ impl MediaExpressionValue {
if value > 1 { if value > 1 {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
} }
MediaExpressionValue::BoolInteger(value == 1) QueryExpressionValue::BoolInteger(value == 1)
}, },
Evaluator::Float(..) => { Evaluator::Float(..) => {
let number = Number::parse(context, input)?; let number = Number::parse(context, input)?;
MediaExpressionValue::Float(number.get()) QueryExpressionValue::Float(number.get())
}, },
Evaluator::NumberRatio(..) => { Evaluator::NumberRatio(..) => {
use crate::values::specified::Ratio as SpecifiedRatio; use crate::values::specified::Ratio as SpecifiedRatio;
let ratio = SpecifiedRatio::parse(context, input)?; let ratio = SpecifiedRatio::parse(context, input)?;
MediaExpressionValue::NumberRatio(Ratio::new(ratio.0.get(), ratio.1.get())) QueryExpressionValue::NumberRatio(Ratio::new(ratio.0.get(), ratio.1.get()))
}, },
Evaluator::Resolution(..) => { Evaluator::Resolution(..) => {
MediaExpressionValue::Resolution(Resolution::parse(context, input)?) QueryExpressionValue::Resolution(Resolution::parse(context, input)?)
}, },
Evaluator::Enumerated { parser, .. } => { Evaluator::Enumerated { parser, .. } => {
MediaExpressionValue::Enumerated(parser(context, input)?) QueryExpressionValue::Enumerated(parser(context, input)?)
}, },
}) })
} }

View File

@ -0,0 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Code shared between [media queries][mq] and [container queries][cq].
//!
//! [mq]: https://drafts.csswg.org/mediaqueries/
//! [cq]: https://drafts.csswg.org/css-contain-3/#container-rule
mod condition;
#[macro_use]
pub mod feature;
pub mod feature_expression;
pub use self::condition::QueryCondition;
pub use self::feature_expression::QueryFeatureExpression;

View File

@ -6,7 +6,7 @@
//! //!
//! [container]: https://drafts.csswg.org/css-contain-3/#container-rule //! [container]: https://drafts.csswg.org/css-contain-3/#container-rule
use crate::media_queries::MediaCondition; use crate::queries::QueryCondition;
use crate::shared_lock::{ use crate::shared_lock::{
DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard, DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard,
}; };
@ -76,4 +76,4 @@ impl ToCssWithGuard for ContainerRule {
} }
/// TODO: Factor out the media query code to work with containers. /// TODO: Factor out the media query code to work with containers.
pub type ContainerCondition = MediaCondition; pub type ContainerCondition = QueryCondition;

View File

@ -6,8 +6,9 @@
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI}; use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use crate::media_queries::{Device, MediaCondition}; use crate::media_queries::Device;
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
use crate::queries::QueryCondition;
use crate::values::computed::{self, ToComputedValue}; use crate::values::computed::{self, ToComputedValue};
use crate::values::specified::{Length, NoCalcLength, ViewportPercentageLength}; use crate::values::specified::{Length, NoCalcLength, ViewportPercentageLength};
use app_units::Au; use app_units::Au;
@ -20,7 +21,7 @@ use style_traits::ParseError;
/// https://html.spec.whatwg.org/multipage/#source-size /// https://html.spec.whatwg.org/multipage/#source-size
#[derive(Debug)] #[derive(Debug)]
pub struct SourceSize { pub struct SourceSize {
condition: MediaCondition, condition: QueryCondition,
value: Length, value: Length,
} }
@ -29,9 +30,8 @@ impl Parse for SourceSize {
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
let condition = MediaCondition::parse(context, input)?; let condition = QueryCondition::parse(context, input)?;
let value = Length::parse_non_negative(context, input)?; let value = Length::parse_non_negative(context, input)?;
Ok(Self { condition, value }) Ok(Self { condition, value })
} }
} }