forked from mirrors/gecko-dev
Bug 1897405 p1. Implement parsing of CSS 'anchor-name'. r=emilio,devtools-reviewers,firefox-style-system-reviewers,nchevobbe
Differential Revision: https://phabricator.services.mozilla.com/D210787
This commit is contained in:
parent
12a4e6fb6e
commit
aac256321a
14 changed files with 177 additions and 11 deletions
|
|
@ -9,6 +9,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||||
[
|
[
|
||||||
"discrete",
|
"discrete",
|
||||||
new Set([
|
new Set([
|
||||||
|
"anchor-name",
|
||||||
"align-content",
|
"align-content",
|
||||||
"align-items",
|
"align-items",
|
||||||
"align-self",
|
"align-self",
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ use.counter:
|
||||||
send_in_pings:
|
send_in_pings:
|
||||||
- use-counters
|
- use-counters
|
||||||
|
|
||||||
# Total of 2301 use counter metrics (excludes denominators).
|
# Total of 2303 use counter metrics (excludes denominators).
|
||||||
# Total of 354 'page' use counters.
|
# Total of 354 'page' use counters.
|
||||||
use.counter.page:
|
use.counter.page:
|
||||||
svgsvgelement_getelementbyid:
|
svgsvgelement_getelementbyid:
|
||||||
|
|
@ -15541,7 +15541,7 @@ use.counter.deprecated_ops.doc:
|
||||||
send_in_pings:
|
send_in_pings:
|
||||||
- use-counters
|
- use-counters
|
||||||
|
|
||||||
# Total of 697 'CSS (page)' use counters.
|
# Total of 698 'CSS (page)' use counters.
|
||||||
use.counter.css.page:
|
use.counter.css.page:
|
||||||
css_align_content:
|
css_align_content:
|
||||||
type: counter
|
type: counter
|
||||||
|
|
@ -18586,6 +18586,23 @@ use.counter.css.page:
|
||||||
send_in_pings:
|
send_in_pings:
|
||||||
- use-counters
|
- use-counters
|
||||||
|
|
||||||
|
css_anchor_name:
|
||||||
|
type: counter
|
||||||
|
description: >
|
||||||
|
Whether a page used the CSS property anchor-name.
|
||||||
|
Compare against `use.counter.top_level_content_documents_destroyed`
|
||||||
|
to calculate the rate.
|
||||||
|
bugs:
|
||||||
|
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||||
|
data_reviews:
|
||||||
|
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||||
|
notification_emails:
|
||||||
|
- dom-core@mozilla.com
|
||||||
|
- emilio@mozilla.com
|
||||||
|
expires: never
|
||||||
|
send_in_pings:
|
||||||
|
- use-counters
|
||||||
|
|
||||||
css_animation_composition:
|
css_animation_composition:
|
||||||
type: counter
|
type: counter
|
||||||
description: >
|
description: >
|
||||||
|
|
@ -27392,7 +27409,7 @@ use.counter.css.page:
|
||||||
send_in_pings:
|
send_in_pings:
|
||||||
- use-counters
|
- use-counters
|
||||||
|
|
||||||
# Total of 697 'CSS (document)' use counters.
|
# Total of 698 'CSS (document)' use counters.
|
||||||
use.counter.css.doc:
|
use.counter.css.doc:
|
||||||
css_align_content:
|
css_align_content:
|
||||||
type: counter
|
type: counter
|
||||||
|
|
@ -30437,6 +30454,23 @@ use.counter.css.doc:
|
||||||
send_in_pings:
|
send_in_pings:
|
||||||
- use-counters
|
- use-counters
|
||||||
|
|
||||||
|
css_anchor_name:
|
||||||
|
type: counter
|
||||||
|
description: >
|
||||||
|
Whether a document used the CSS property anchor-name.
|
||||||
|
Compare against `use.counter.content_documents_destroyed`
|
||||||
|
to calculate the rate.
|
||||||
|
bugs:
|
||||||
|
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||||
|
data_reviews:
|
||||||
|
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||||
|
notification_emails:
|
||||||
|
- dom-core@mozilla.com
|
||||||
|
- emilio@mozilla.com
|
||||||
|
expires: never
|
||||||
|
send_in_pings:
|
||||||
|
- use-counters
|
||||||
|
|
||||||
css_animation_composition:
|
css_animation_composition:
|
||||||
type: counter
|
type: counter
|
||||||
description: >
|
description: >
|
||||||
|
|
|
||||||
|
|
@ -620,6 +620,7 @@ cbindgen-types = [
|
||||||
{ gecko = "StyleLockedFontFaceRule", servo = "crate::gecko::arc_types::LockedFontFaceRule" },
|
{ gecko = "StyleLockedFontFaceRule", servo = "crate::gecko::arc_types::LockedFontFaceRule" },
|
||||||
{ gecko = "StyleBaselineSource", servo = "crate::values::computed::BaselineSource" },
|
{ gecko = "StyleBaselineSource", servo = "crate::values::computed::BaselineSource" },
|
||||||
{ gecko = "StyleAu", servo = "app_units::Au" },
|
{ gecko = "StyleAu", servo = "app_units::Au" },
|
||||||
|
{ gecko = "StyleAnchorName", servo = "crate::values::computed::position::AnchorName" },
|
||||||
]
|
]
|
||||||
|
|
||||||
mapped-generic-types = [
|
mapped-generic-types = [
|
||||||
|
|
|
||||||
|
|
@ -2151,7 +2151,8 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
|
||||||
mWebkitLineClamp(aSource.mWebkitLineClamp),
|
mWebkitLineClamp(aSource.mWebkitLineClamp),
|
||||||
mShapeImageThreshold(aSource.mShapeImageThreshold),
|
mShapeImageThreshold(aSource.mShapeImageThreshold),
|
||||||
mShapeMargin(aSource.mShapeMargin),
|
mShapeMargin(aSource.mShapeMargin),
|
||||||
mShapeOutside(aSource.mShapeOutside) {
|
mShapeOutside(aSource.mShapeOutside),
|
||||||
|
mAnchorName(aSource.mAnchorName) {
|
||||||
MOZ_COUNT_CTOR(nsStyleDisplay);
|
MOZ_COUNT_CTOR(nsStyleDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2522,7 +2523,8 @@ nsChangeHint nsStyleDisplay::CalcDifference(
|
||||||
mContentVisibility != aNewData.mContentVisibility ||
|
mContentVisibility != aNewData.mContentVisibility ||
|
||||||
mContainerType != aNewData.mContainerType ||
|
mContainerType != aNewData.mContainerType ||
|
||||||
mContain != aNewData.mContain ||
|
mContain != aNewData.mContain ||
|
||||||
mContainerName != aNewData.mContainerName)) {
|
mContainerName != aNewData.mContainerName ||
|
||||||
|
mAnchorName != aNewData.mAnchorName)) {
|
||||||
hint |= nsChangeHint_NeutralChange;
|
hint |= nsChangeHint_NeutralChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1316,6 +1316,10 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
|
||||||
|
|
||||||
mozilla::StyleShapeOutside mShapeOutside;
|
mozilla::StyleShapeOutside mShapeOutside;
|
||||||
|
|
||||||
|
// 'none', 'all', or a list of one or more `<dashed-ident>` identifiers that
|
||||||
|
// anchor positioned elements may reference.
|
||||||
|
mozilla::StyleAnchorName mAnchorName;
|
||||||
|
|
||||||
mozilla::Maybe<mozilla::WindowButtonType> GetWindowButtonType() const {
|
mozilla::Maybe<mozilla::WindowButtonType> GetWindowButtonType() const {
|
||||||
if (MOZ_LIKELY(mDefaultAppearance == mozilla::StyleAppearance::None)) {
|
if (MOZ_LIKELY(mDefaultAppearance == mozilla::StyleAppearance::None)) {
|
||||||
return mozilla::Nothing();
|
return mozilla::Nothing();
|
||||||
|
|
|
||||||
|
|
@ -13295,6 +13295,25 @@ if (IsCSSPropertyPrefEnabled("layout.css.contain-intrinsic-size.enabled")) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsCSSPropertyPrefEnabled("layout.css.anchor-positioning.enabled")) {
|
||||||
|
gCSSProperties["anchor-name"] = {
|
||||||
|
domProp: "anchorName",
|
||||||
|
inherited: false,
|
||||||
|
type: CSS_TYPE_LONGHAND,
|
||||||
|
initial_values: ["none"],
|
||||||
|
other_values: ["--foo", "--foo, --baz", "--foo,--baz", "--foo ,--baz"],
|
||||||
|
invalid_values: [
|
||||||
|
"--foo --bar",
|
||||||
|
"foo",
|
||||||
|
"none bar",
|
||||||
|
"none --baz",
|
||||||
|
"--foo bar",
|
||||||
|
",--foo",
|
||||||
|
"--foo,",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (false) {
|
if (false) {
|
||||||
// TODO These properties are chrome-only, and are not exposed via CSSOM.
|
// TODO These properties are chrome-only, and are not exposed via CSSOM.
|
||||||
// We may still want to find a way to test them. See bug 1206999.
|
// We may still want to find a way to test them. See bug 1206999.
|
||||||
|
|
|
||||||
|
|
@ -8436,6 +8436,14 @@
|
||||||
value: false
|
value: false
|
||||||
mirror: always
|
mirror: always
|
||||||
|
|
||||||
|
# Whether to enable CSS Anchor Positioning support.
|
||||||
|
# https://drafts.csswg.org/css-anchor-position-1/
|
||||||
|
- name: layout.css.anchor-positioning.enabled
|
||||||
|
type: RelaxedAtomicBool
|
||||||
|
value: false
|
||||||
|
mirror: always
|
||||||
|
rust: true
|
||||||
|
|
||||||
# Override DPI. A value of -1 means use the maximum of 96 and the system DPI.
|
# Override DPI. A value of -1 means use the maximum of 96 and the system DPI.
|
||||||
# A value of 0 means use the system DPI. A positive value is used as the DPI.
|
# A value of 0 means use the system DPI. A positive value is used as the DPI.
|
||||||
# This sets the physical size of a device pixel and thus controls the
|
# This sets the physical size of a device pixel and thus controls the
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,19 @@ impl computed_value::T {
|
||||||
}
|
}
|
||||||
</%helpers:single_keyword>
|
</%helpers:single_keyword>
|
||||||
|
|
||||||
|
// Changes do not invalidate our element. We handle notify/invalidating
|
||||||
|
// elements that reference anchor-name elsewhere.
|
||||||
|
${helpers.predefined_type(
|
||||||
|
"anchor-name",
|
||||||
|
"AnchorName",
|
||||||
|
"computed::AnchorName::none()",
|
||||||
|
engines="gecko",
|
||||||
|
animation_value_type="discrete",
|
||||||
|
gecko_pref="layout.css.anchor-positioning.enabled",
|
||||||
|
spec="https://drafts.csswg.org/css-anchor-position-1/#propdef-anchor-name",
|
||||||
|
affects="",
|
||||||
|
)}
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"float",
|
"float",
|
||||||
"Float",
|
"Float",
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ pub use self::motion::{OffsetPath, OffsetPosition, OffsetRotate};
|
||||||
pub use self::outline::OutlineStyle;
|
pub use self::outline::OutlineStyle;
|
||||||
pub use self::page::{PageName, PageOrientation, PageSize, PageSizeOrientation, PaperSize};
|
pub use self::page::{PageName, PageOrientation, PageSize, PageSizeOrientation, PaperSize};
|
||||||
pub use self::percentage::{NonNegativePercentage, Percentage};
|
pub use self::percentage::{NonNegativePercentage, Percentage};
|
||||||
|
pub use self::position::AnchorName;
|
||||||
pub use self::position::AspectRatio;
|
pub use self::position::AspectRatio;
|
||||||
pub use self::position::{
|
pub use self::position::{
|
||||||
GridAutoFlow, GridTemplateAreas, MasonryAutoFlow, Position, PositionOrAuto, ZIndex,
|
GridAutoFlow, GridTemplateAreas, MasonryAutoFlow, Position, PositionOrAuto, ZIndex,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use crate::values::generics::position::Position as GenericPosition;
|
||||||
use crate::values::generics::position::PositionComponent as GenericPositionComponent;
|
use crate::values::generics::position::PositionComponent as GenericPositionComponent;
|
||||||
use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
|
use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
|
||||||
use crate::values::generics::position::ZIndex as GenericZIndex;
|
use crate::values::generics::position::ZIndex as GenericZIndex;
|
||||||
pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas, MasonryAutoFlow};
|
pub use crate::values::specified::position::{AnchorName, GridAutoFlow, GridTemplateAreas, MasonryAutoFlow};
|
||||||
use crate::Zero;
|
use crate::Zero;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
|
||||||
|
|
@ -592,6 +592,21 @@ impl ToCss for CustomIdent {
|
||||||
)]
|
)]
|
||||||
pub struct DashedIdent(pub Atom);
|
pub struct DashedIdent(pub Atom);
|
||||||
|
|
||||||
|
impl DashedIdent {
|
||||||
|
/// Parse an already-tokenizer identifier
|
||||||
|
pub fn from_ident<'i>(
|
||||||
|
location: SourceLocation,
|
||||||
|
ident: &CowRcStr<'i>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
if !ident.starts_with("--") {
|
||||||
|
return Err(
|
||||||
|
location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(Self(Atom::from(ident.as_ref())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Parse for DashedIdent {
|
impl Parse for DashedIdent {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
_: &ParserContext,
|
_: &ParserContext,
|
||||||
|
|
@ -599,11 +614,7 @@ impl Parse for DashedIdent {
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let location = input.current_source_location();
|
let location = input.current_source_location();
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
if ident.starts_with("--") {
|
Self::from_ident(location, ident)
|
||||||
Ok(Self(Atom::from(ident.as_ref())))
|
|
||||||
} else {
|
|
||||||
Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone())))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ pub use self::outline::OutlineStyle;
|
||||||
pub use self::page::{PageName, PageOrientation, PageSize, PageSizeOrientation, PaperSize};
|
pub use self::page::{PageName, PageOrientation, PageSize, PageSizeOrientation, PaperSize};
|
||||||
pub use self::percentage::{NonNegativePercentage, Percentage};
|
pub use self::percentage::{NonNegativePercentage, Percentage};
|
||||||
pub use self::position::AspectRatio;
|
pub use self::position::AspectRatio;
|
||||||
|
pub use self::position::AnchorName;
|
||||||
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, PositionOrAuto};
|
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, PositionOrAuto};
|
||||||
pub use self::position::{MasonryAutoFlow, MasonryItemOrder, MasonryPlacement};
|
pub use self::position::{MasonryAutoFlow, MasonryItemOrder, MasonryPlacement};
|
||||||
pub use self::position::{PositionComponent, ZIndex};
|
pub use self::position::{PositionComponent, ZIndex};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::selector_map::PrecomputedHashMap;
|
use crate::selector_map::PrecomputedHashMap;
|
||||||
use crate::str::HTML_SPACE_CHARACTERS;
|
use crate::str::HTML_SPACE_CHARACTERS;
|
||||||
|
use crate::values::DashedIdent;
|
||||||
use crate::values::computed::LengthPercentage as ComputedLengthPercentage;
|
use crate::values::computed::LengthPercentage as ComputedLengthPercentage;
|
||||||
use crate::values::computed::{Context, Percentage, ToComputedValue};
|
use crate::values::computed::{Context, Percentage, ToComputedValue};
|
||||||
use crate::values::generics::position::AspectRatio as GenericAspectRatio;
|
use crate::values::generics::position::AspectRatio as GenericAspectRatio;
|
||||||
|
|
@ -22,10 +23,12 @@ use crate::{Atom, Zero};
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::values::specified::AllowedNumericType;
|
use style_traits::values::specified::AllowedNumericType;
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
use style_traits::arc_slice::ArcSlice;
|
||||||
|
|
||||||
/// The specified value of a CSS `<position>`
|
/// The specified value of a CSS `<position>`
|
||||||
pub type Position = GenericPosition<HorizontalPosition, VerticalPosition>;
|
pub type Position = GenericPosition<HorizontalPosition, VerticalPosition>;
|
||||||
|
|
@ -337,6 +340,73 @@ impl<S: Side> PositionComponent<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://drafts.csswg.org/css-anchor-position-1/#propdef-anchor-name
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
Debug,
|
||||||
|
MallocSizeOf,
|
||||||
|
PartialEq,
|
||||||
|
SpecifiedValueInfo,
|
||||||
|
ToComputedValue,
|
||||||
|
ToResolvedValue,
|
||||||
|
ToShmem,
|
||||||
|
)]
|
||||||
|
pub struct AnchorName(#[css(iterable, if_empty = "none")] #[ignore_malloc_size_of = "Arc"] pub crate::ArcSlice<DashedIdent>);
|
||||||
|
|
||||||
|
impl AnchorName {
|
||||||
|
/// Return the `none` value.
|
||||||
|
pub fn none() -> Self {
|
||||||
|
Self(Default::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this is the `none` value.
|
||||||
|
pub fn is_none(&self) -> bool {
|
||||||
|
self.0.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for AnchorName {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
let location = input.current_source_location();
|
||||||
|
let first = input.expect_ident()?;
|
||||||
|
if first.eq_ignore_ascii_case("none") {
|
||||||
|
return Ok(Self::none());
|
||||||
|
}
|
||||||
|
// The common case is probably just to have a single anchor name, so
|
||||||
|
// space for four on the stack should be plenty.
|
||||||
|
let mut idents: SmallVec<[DashedIdent; 4]> = smallvec![DashedIdent::from_ident(
|
||||||
|
location,
|
||||||
|
first,
|
||||||
|
)?];
|
||||||
|
while input.try_parse(|input| input.expect_comma()).is_ok() {
|
||||||
|
idents.push(DashedIdent::parse(context, input)?);
|
||||||
|
}
|
||||||
|
Ok(AnchorName(ArcSlice::from_iter(idents.drain(..))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for AnchorName {
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: fmt::Write,
|
||||||
|
{
|
||||||
|
let mut iter = self.0.iter();
|
||||||
|
match iter.next() {
|
||||||
|
None => return dest.write_str("none"),
|
||||||
|
Some(f) => f.to_css(dest)?,
|
||||||
|
}
|
||||||
|
for name in iter {
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
name.to_css(dest)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a side, either horizontal or vertical, of a CSS position.
|
/// Represents a side, either horizontal or vertical, of a CSS position.
|
||||||
pub trait Side {
|
pub trait Side {
|
||||||
/// Returns the start side.
|
/// Returns the start side.
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ exclude = [
|
||||||
"AuthorStyles",
|
"AuthorStyles",
|
||||||
]
|
]
|
||||||
include = [
|
include = [
|
||||||
|
"AnchorName",
|
||||||
"AnimationTimeline",
|
"AnimationTimeline",
|
||||||
"AnimationIterationCount",
|
"AnimationIterationCount",
|
||||||
"AnimationDirection",
|
"AnimationDirection",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue