style: Fix container query evaluation on unsupported axis

We were falling back to viewport size, which is not what the spec says.

Differential Revision: https://phabricator.services.mozilla.com/D161132
This commit is contained in:
Emilio Cobos Álvarez 2022-11-03 14:07:02 +00:00 committed by Martin Robinson
parent aba0a4bce0
commit 81ae588ec9
3 changed files with 47 additions and 35 deletions

View file

@ -34,11 +34,13 @@ pub type KeywordParser = for<'a, 'i, 't> fn(
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum Evaluator { pub enum Evaluator {
Length(QueryFeatureGetter<CSSPixelLength>), Length(QueryFeatureGetter<CSSPixelLength>),
OptionalLength(QueryFeatureGetter<Option<CSSPixelLength>>),
Integer(QueryFeatureGetter<u32>), Integer(QueryFeatureGetter<u32>),
Float(QueryFeatureGetter<f32>), Float(QueryFeatureGetter<f32>),
BoolInteger(QueryFeatureGetter<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(QueryFeatureGetter<Ratio>), NumberRatio(QueryFeatureGetter<Ratio>),
OptionalNumberRatio(QueryFeatureGetter<Option<Ratio>>),
/// A resolution. /// A resolution.
Resolution(QueryFeatureGetter<Resolution>), Resolution(QueryFeatureGetter<Resolution>),
/// A keyword value. /// A keyword value.

View file

@ -591,6 +591,14 @@ impl QueryFeatureExpression {
self.kind self.kind
.evaluate(v, |v| expect!(Length, v).to_computed_value(context)) .evaluate(v, |v| expect!(Length, v).to_computed_value(context))
}, },
Evaluator::OptionalLength(eval) => {
let v = match eval(context) {
Some(v) => v,
None => return false,
};
self.kind
.evaluate(v, |v| expect!(Length, v).to_computed_value(context))
},
Evaluator::Integer(eval) => { Evaluator::Integer(eval) => {
let v = eval(context); let v = eval(context);
self.kind.evaluate(v, |v| *expect!(Integer, v)) self.kind.evaluate(v, |v| *expect!(Integer, v))
@ -608,6 +616,15 @@ impl QueryFeatureExpression {
self.kind self.kind
.evaluate(ratio, |v| expect!(NumberRatio, v).used_value()) .evaluate(ratio, |v| expect!(NumberRatio, v).used_value())
}, },
Evaluator::OptionalNumberRatio(eval) => {
let ratio = match eval(context) {
Some(v) => v,
None => return false,
};
// See above for subtleties here.
self.kind
.evaluate(ratio, |v| expect!(NumberRatio, v).used_value())
},
Evaluator::Resolution(eval) => { Evaluator::Resolution(eval) => {
let v = eval(context).dppx(); let v = eval(context).dppx();
self.kind.evaluate(v, |v| { self.kind.evaluate(v, |v| {
@ -686,7 +703,7 @@ impl QueryExpressionValue {
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
) -> Result<QueryExpressionValue, ParseError<'i>> { ) -> Result<QueryExpressionValue, ParseError<'i>> {
Ok(match for_feature.evaluator { Ok(match for_feature.evaluator {
Evaluator::Length(..) => { Evaluator::OptionalLength(..) | Evaluator::Length(..) => {
let length = Length::parse_non_negative(context, input)?; let length = Length::parse_non_negative(context, input)?;
QueryExpressionValue::Length(length) QueryExpressionValue::Length(length)
}, },
@ -706,7 +723,7 @@ impl QueryExpressionValue {
let number = Number::parse(context, input)?; let number = Number::parse(context, input)?;
QueryExpressionValue::Float(number.get()) QueryExpressionValue::Float(number.get())
}, },
Evaluator::NumberRatio(..) => { Evaluator::OptionalNumberRatio(..) | 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)?;
QueryExpressionValue::NumberRatio(Ratio::new(ratio.0.get(), ratio.1.get())) QueryExpressionValue::NumberRatio(Ratio::new(ratio.0.get(), ratio.1.get()))

View file

@ -261,51 +261,44 @@ pub struct ContainerInfo {
wm: WritingMode, wm: WritingMode,
} }
fn get_container(context: &Context) -> ContainerInfo { fn eval_width(context: &Context) -> Option<CSSPixelLength> {
if let Some(ref info) = context.container_info { let info = context.container_info.as_ref()?;
return info.clone(); Some(CSSPixelLength::new(info.size.width.to_f32_px()))
}
ContainerInfo {
size: context.device().au_viewport_size(),
wm: WritingMode::horizontal_tb(),
}
} }
fn eval_width(context: &Context) -> CSSPixelLength { fn eval_height(context: &Context) -> Option<CSSPixelLength> {
let info = get_container(context); let info = context.container_info.as_ref()?;
CSSPixelLength::new(info.size.width.to_f32_px()) Some(CSSPixelLength::new(info.size.height.to_f32_px()))
} }
fn eval_height(context: &Context) -> CSSPixelLength { fn eval_inline_size(context: &Context) -> Option<CSSPixelLength> {
let info = get_container(context); let info = context.container_info.as_ref()?;
CSSPixelLength::new(info.size.height.to_f32_px()) Some(CSSPixelLength::new(
}
fn eval_inline_size(context: &Context) -> CSSPixelLength {
let info = get_container(context);
CSSPixelLength::new(
LogicalSize::from_physical(info.wm, info.size) LogicalSize::from_physical(info.wm, info.size)
.inline .inline
.to_f32_px(), .to_f32_px(),
) ))
} }
fn eval_block_size(context: &Context) -> CSSPixelLength { fn eval_block_size(context: &Context) -> Option<CSSPixelLength> {
let info = get_container(context); let info = context.container_info.as_ref()?;
CSSPixelLength::new( Some(CSSPixelLength::new(
LogicalSize::from_physical(info.wm, info.size) LogicalSize::from_physical(info.wm, info.size)
.block .block
.to_f32_px(), .to_f32_px(),
) ))
} }
fn eval_aspect_ratio(context: &Context) -> Ratio { fn eval_aspect_ratio(context: &Context) -> Option<Ratio> {
let info = get_container(context); let info = context.container_info.as_ref()?;
Ratio::new(info.size.width.0 as f32, info.size.height.0 as f32) Some(Ratio::new(info.size.width.0 as f32, info.size.height.0 as f32))
} }
fn eval_orientation(context: &Context, value: Option<Orientation>) -> bool { fn eval_orientation(context: &Context, value: Option<Orientation>) -> bool {
let info = get_container(context); let info = match context.container_info.as_ref() {
Some(info) => info,
None => return false,
};
Orientation::eval(info.size, value) Orientation::eval(info.size, value)
} }
@ -316,31 +309,31 @@ pub static CONTAINER_FEATURES: [QueryFeatureDescription; 6] = [
feature!( feature!(
atom!("width"), atom!("width"),
AllowsRanges::Yes, AllowsRanges::Yes,
Evaluator::Length(eval_width), Evaluator::OptionalLength(eval_width),
FeatureFlags::CONTAINER_REQUIRES_WIDTH_AXIS, FeatureFlags::CONTAINER_REQUIRES_WIDTH_AXIS,
), ),
feature!( feature!(
atom!("height"), atom!("height"),
AllowsRanges::Yes, AllowsRanges::Yes,
Evaluator::Length(eval_height), Evaluator::OptionalLength(eval_height),
FeatureFlags::CONTAINER_REQUIRES_HEIGHT_AXIS, FeatureFlags::CONTAINER_REQUIRES_HEIGHT_AXIS,
), ),
feature!( feature!(
atom!("inline-size"), atom!("inline-size"),
AllowsRanges::Yes, AllowsRanges::Yes,
Evaluator::Length(eval_inline_size), Evaluator::OptionalLength(eval_inline_size),
FeatureFlags::CONTAINER_REQUIRES_INLINE_AXIS, FeatureFlags::CONTAINER_REQUIRES_INLINE_AXIS,
), ),
feature!( feature!(
atom!("block-size"), atom!("block-size"),
AllowsRanges::Yes, AllowsRanges::Yes,
Evaluator::Length(eval_block_size), Evaluator::OptionalLength(eval_block_size),
FeatureFlags::CONTAINER_REQUIRES_BLOCK_AXIS, FeatureFlags::CONTAINER_REQUIRES_BLOCK_AXIS,
), ),
feature!( feature!(
atom!("aspect-ratio"), atom!("aspect-ratio"),
AllowsRanges::Yes, AllowsRanges::Yes,
Evaluator::NumberRatio(eval_aspect_ratio), Evaluator::OptionalNumberRatio(eval_aspect_ratio),
// XXX from_bits_truncate is const, but the pipe operator isn't, so this // XXX from_bits_truncate is const, but the pipe operator isn't, so this
// works around it. // works around it.
FeatureFlags::from_bits_truncate( FeatureFlags::from_bits_truncate(