Bug 1907210 - Part 1: Use <dashed-ident> for scroll/view timeline name. r=firefox-style-system-reviewers,zrhoffman

Per the spec change, we only accept `<dashed-ident>` for timeline names.

Differential Revision: https://phabricator.services.mozilla.com/D216458
This commit is contained in:
Boris Chiou 2024-07-16 20:31:52 +00:00
Родитель 5abf62b3a9
Коммит be88cfaa3d
17 изменённых файлов: 158 добавлений и 185 удалений

Просмотреть файл

@ -12,7 +12,7 @@
height: 100px;
overflow: scroll;
scrollbar-width: none;
scroll-timeline: scroll_timeline;
scroll-timeline: --scroll_timeline;
}
#target {
width: 100px;
@ -24,7 +24,7 @@
animation-duration: 5s;
animation-timing-function: linear;
animation-delay: 5s;
animation-timeline: scroll_timeline;
animation-timeline: --scroll_timeline;
}
</style>
<script>

Просмотреть файл

@ -421,7 +421,7 @@ cbindgen-types = [
{ gecko = "StyleAnimationFillMode", servo = "crate::values::computed::AnimationFillMode" },
{ gecko = "StyleAnimationPlayState", servo = "crate::values::computed::AnimationPlayState" },
{ gecko = "StyleAnimationComposition", servo = "crate::values::computed::AnimationComposition" },
{ gecko = "StyleScrollTimelineName", servo = "crate::values::computed::ScrollTimelineName" },
{ gecko = "StyleTimelineName", servo = "crate::values::computed::TimelineName" },
{ gecko = "StyleScrollAxis", servo = "crate::values::computed::ScrollAxis" },
{ gecko = "StyleViewTimelineInset", servo = "crate::values::computed::ViewTimelineInset" },
{ gecko = "StyleResize", servo = "crate::values::computed::Resize" },

Просмотреть файл

@ -1164,7 +1164,7 @@ struct StyleScrollTimeline {
StyleScrollTimeline() = default;
explicit StyleScrollTimeline(const StyleScrollTimeline& aCopy) = default;
nsAtom* GetName() const { return mName._0.AsAtom(); }
nsAtom* GetName() const { return mName.AsAtom(); }
StyleScrollAxis GetAxis() const { return mAxis; }
bool operator==(const StyleScrollTimeline& aOther) const {
@ -1175,7 +1175,7 @@ struct StyleScrollTimeline {
}
private:
StyleScrollTimelineName mName;
StyleTimelineName mName;
StyleScrollAxis mAxis = StyleScrollAxis::Block;
};
@ -1183,7 +1183,7 @@ struct StyleViewTimeline {
StyleViewTimeline() = default;
explicit StyleViewTimeline(const StyleViewTimeline& aCopy) = default;
nsAtom* GetName() const { return mName._0.AsAtom(); }
nsAtom* GetName() const { return mName.AsAtom(); }
StyleScrollAxis GetAxis() const { return mAxis; }
const StyleViewTimelineInset& GetInset() const { return mInset; }
@ -1196,7 +1196,7 @@ struct StyleViewTimeline {
}
private:
StyleScrollTimelineName mName;
StyleTimelineName mName;
StyleScrollAxis mAxis = StyleScrollAxis::Block;
StyleViewTimelineInset mInset;
};

Просмотреть файл

@ -34,7 +34,7 @@
width: 100px;
height: 100px;
overflow: scroll;
scroll-timeline-name: scroll_timeline;
scroll-timeline-name: --scroll_timeline;
}
.content {
@ -129,7 +129,7 @@ waitUntilApzStable().then(() => {
// with document-timeline.
addAsyncAnimTest(async function() {
new_scroller();
new_div("animation: geometry 10s scroll_timeline, always_fifty 1s infinite;");
new_div("animation: geometry 10s --scroll_timeline, always_fifty 1s infinite;");
await waitForPaintsFlushed();
// Note: width is not a OMTA property, so it must be running on the main
@ -144,7 +144,7 @@ addAsyncAnimTest(async function() {
// transform property with scroll-driven animations.
addAsyncAnimTest(async function() {
let scroller = new_scroller();
new_div("animation: transform_anim 1s linear scroll_timeline;");
new_div("animation: transform_anim 1s linear --scroll_timeline;");
await waitForPaintsFlushed();
scroller.scrollTop = 50;
@ -163,7 +163,7 @@ addAsyncAnimTest(async function() {
// active phase to the before phase.
addAsyncAnimTest(async function() {
let scroller = new_scroller();
new_div("animation: always_fifty 5s linear 5s scroll_timeline; " +
new_div("animation: always_fifty 5s linear 5s --scroll_timeline; " +
"transform: translate(25px);");
await waitForPaintsFlushed();
@ -212,7 +212,7 @@ addAsyncAnimTest(async function() {
// the active phase to the before phase.
addAsyncAnimTest(async function() {
let scroller = new_scroller();
new_div("animation: always_fifty 5s linear 5s scroll_timeline; ");
new_div("animation: always_fifty 5s linear 5s --scroll_timeline; ");
await waitForPaintsFlushed();
// NOTE: getOMTAStyle() can't detect the animation is running on the
@ -252,7 +252,7 @@ addAsyncAnimTest(async function() {
addAsyncAnimTest(async function() {
let scroller = new_scroller();
new_div("animation: transform_anim 10s linear -5s paused, " +
" always_fifty 5s linear 5s scroll_timeline;");
" always_fifty 5s linear 5s --scroll_timeline;");
await waitForPaintsFlushed();
omta_is_approx("transform", { tx: 100 }, 0.1, RunningOn.Compositor,
@ -335,7 +335,7 @@ addAsyncAnimTest(async function() {
let subject = document.createElement("div");
subject.style.width = "50px";
subject.style.height = "50px";
subject.style.viewTimelineName = "view_timeline";
subject.style.viewTimelineName = "--view_timeline";
scroller.appendChild(subject);
// Let |target| be the child of |subject|, so view-timeline-name property of
@ -362,7 +362,7 @@ addAsyncAnimTest(async function() {
scroller.scrollTop = 0;
target.style.animation = "transform_anim 10s linear";
target.style.animationTimeline = "view_timeline";
target.style.animationTimeline = "--view_timeline";
await waitForPaintsFlushed();
omta_is_approx("transform", { tx: 0 }, 0.1, RunningOn.OnMainThread,

Просмотреть файл

@ -13973,11 +13973,11 @@ if (IsCSSPropertyPrefEnabled("layout.css.scroll-driven-animations.enabled")) {
);
gCSSProperties["animation"].other_values.push(
"none none 0s 0s cubic-bezier(0.25, 0.1, 0.25, 1.0) normal running 1.0 auto",
"bounce 1s linear 2s timeline",
"bounce 1s linear 2s --timeline",
"bounce 1s 2s linear none",
"bounce timeline",
"2s, 1s bounce timeline",
"1s bounce timeline, 2s",
"bounce --timeline",
"2s, 1s bounce --timeline",
"1s bounce --timeline, 2s",
"1s bounce none, 2s none auto"
);
@ -13992,19 +13992,16 @@ if (IsCSSPropertyPrefEnabled("layout.css.scroll-driven-animations.enabled")) {
initial_values: ["auto"],
other_values: [
"none",
"all",
"ball",
"mall",
"color",
"bounce, bubble, opacity",
"foobar",
"\\32bounce",
"-bounce",
"-\\32bounce",
"\\32 0bounce",
"-\\32 0bounce",
"\\2bounce",
"-\\2bounce",
"--all",
"--ball",
"--mall",
"--color",
"--bounce, --bubble, --opacity",
"--foobar",
"--\\32bounce",
"--bounce",
"--\\32 0bounce",
"--\\2bounce",
"scroll()",
"scroll(block)",
"scroll(inline)",
@ -14025,12 +14022,13 @@ if (IsCSSPropertyPrefEnabled("layout.css.scroll-driven-animations.enabled")) {
"view(1px 1% block)",
],
invalid_values: [
"bounce, initial",
"initial, bounce",
"bounce, inherit",
"inherit, bounce",
"bounce, unset",
"unset, bounce",
"abc",
"--bounce, initial",
"initial, --bounce",
"--bounce, inherit",
"inherit, --bounce",
"--bounce, unset",
"unset, --bounce",
],
};
@ -14040,21 +14038,18 @@ if (IsCSSPropertyPrefEnabled("layout.css.scroll-driven-animations.enabled")) {
type: CSS_TYPE_LONGHAND,
initial_values: ["none"],
other_values: [
"all",
"auto",
"ball",
"mall",
"color",
"foobar",
"\\32bounce",
"-bounce",
"-\\32bounce",
"\\32 0bounce",
"-\\32 0bounce",
"\\2bounce",
"-\\2bounce",
"--all",
"--auto",
"--ball",
"--mall",
"--color",
"--foobar",
"--\\32bounce",
"--bounce",
"--\\32 0bounce",
"--\\2bounce",
],
invalid_values: ["abc bounce", "10px", "rgb(1, 2, 3)"],
invalid_values: ["abc", "abc --bounce", "10px", "rgb(1, 2, 3)"],
};
gCSSProperties["scroll-timeline-axis"] = {
@ -14073,17 +14068,17 @@ if (IsCSSPropertyPrefEnabled("layout.css.scroll-driven-animations.enabled")) {
subproperties: ["scroll-timeline-name", "scroll-timeline-axis"],
initial_values: ["none block", "none"],
other_values: [
"auto inline",
"bounce inline",
"bounce y",
"\\32bounce inline",
"-bounce block",
"\\32 0bounce y",
"-\\32 0bounce x",
"a, b, c",
"a block, b inline, c y",
"--auto inline",
"--bounce inline",
"--bounce y",
"--\\32bounce inline",
"--bounce block",
"--\\32 0bounce y",
"--\\32 0bounce x",
"--a, --b, --c",
"--a block, --b inline, --c y",
],
invalid_values: ["", "bounce bounce", "x a", "block abc"],
invalid_values: ["", "--bounce --bounce", "x --a", "block --abc"],
};
gCSSProperties["view-timeline-name"] = {
@ -14092,23 +14087,20 @@ if (IsCSSPropertyPrefEnabled("layout.css.scroll-driven-animations.enabled")) {
type: CSS_TYPE_LONGHAND,
initial_values: ["none"],
other_values: [
"all",
"auto",
"ball",
"mall",
"color",
"foobar",
"\\32bounce",
"-bounce",
"-\\32bounce",
"\\32 0bounce",
"-\\32 0bounce",
"\\2bounce",
"-\\2bounce",
"bounce, abc",
"--all",
"--auto",
"--ball",
"--mall",
"--color",
"--foobar",
"--\\32bounce",
"--bounce",
"--\\32 0bounce",
"--\\2bounce",
"--bounce, --abc",
"none, none",
],
invalid_values: ["abc bounce", "10px", "rgb(1, 2, 3)"],
invalid_values: ["abc", "abc --bounce", "10px", "rgb(1, 2, 3)"],
};
gCSSProperties["view-timeline-axis"] = {
@ -14136,17 +14128,17 @@ if (IsCSSPropertyPrefEnabled("layout.css.scroll-driven-animations.enabled")) {
subproperties: ["view-timeline-name", "view-timeline-axis"],
initial_values: ["none block", "none"],
other_values: [
"auto inline",
"bounce inline",
"bounce y",
"\\32bounce inline",
"-bounce block",
"\\32 0bounce y",
"-\\32 0bounce x",
"a, b, c",
"a block, b inline, c y",
"--auto inline",
"--bounce inline",
"--bounce y",
"--\\32bounce inline",
"--bounce block",
"--\\32 0bounce y",
"--\\32 0bounce x",
"--a, --b, --c",
"--a block, --b inline, --c y",
],
invalid_values: ["", ",", "abc abc", "x a", "block abc"],
invalid_values: ["", ",", "--abc --abc", "x --a", "block --abc"],
};
}

Просмотреть файл

@ -365,8 +365,8 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"scroll-timeline-name",
"ScrollTimelineName",
"computed::ScrollTimelineName::none()",
"TimelineName",
"computed::TimelineName::none()",
vector=True,
need_index=True,
engines="gecko",
@ -393,8 +393,8 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"view-timeline-name",
"ScrollTimelineName",
"computed::ScrollTimelineName::none()",
"TimelineName",
"computed::TimelineName::none()",
vector=True,
need_index=True,
engines="gecko",

Просмотреть файл

@ -12,7 +12,7 @@ use style_traits::{CssWriter, ToCss};
pub use crate::values::specified::animation::{
AnimationComposition, AnimationDirection, AnimationFillMode, AnimationName, AnimationPlayState,
ScrollAxis, ScrollTimelineName, TransitionBehavior, TransitionProperty,
ScrollAxis, TimelineName, TransitionBehavior, TransitionProperty,
};
/// A computed value for the `animation-iteration-count` property.

Просмотреть файл

@ -43,7 +43,7 @@ pub use self::align::{AlignSelf, JustifySelf};
pub use self::angle::Angle;
pub use self::animation::{
AnimationComposition, AnimationDirection, AnimationFillMode, AnimationIterationCount,
AnimationName, AnimationPlayState, AnimationTimeline, ScrollAxis, ScrollTimelineName,
AnimationName, AnimationPlayState, AnimationTimeline, ScrollAxis, TimelineName,
TransitionBehavior, TransitionProperty, ViewTimelineInset,
};
pub use self::background::{BackgroundRepeat, BackgroundSize};

Просмотреть файл

@ -5,8 +5,7 @@
//! Generic values for properties related to animations and transitions.
use crate::values::generics::length::GenericLengthPercentageOrAuto;
use crate::values::specified::animation::{ScrollAxis, ScrollFunction};
use crate::values::TimelineName;
use crate::values::specified::animation::{ScrollAxis, ScrollFunction, TimelineName};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
@ -56,7 +55,8 @@ pub enum GenericAnimationTimeline<LengthPercent> {
/// Use default timeline. The animations timeline is a DocumentTimeline.
Auto,
/// The scroll-timeline name or view-timeline-name.
/// https://drafts.csswg.org/scroll-animations-1/#scroll-timelines-named
/// This also includes `none` value by using an empty atom.
/// https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-name
/// https://drafts.csswg.org/scroll-animations-1/#view-timeline-name
Timeline(TimelineName),
/// The scroll() notation.

Просмотреть файл

@ -723,57 +723,6 @@ impl TimelineOrKeyframesName {
impl Eq for TimelineOrKeyframesName {}
/// The typedef of <timeline-name>.
#[repr(transparent)]
#[derive(
Clone,
Debug,
Deref,
Hash,
Eq,
PartialEq,
MallocSizeOf,
SpecifiedValueInfo,
ToComputedValue,
ToResolvedValue,
ToShmem,
)]
pub struct TimelineName(TimelineOrKeyframesName);
impl TimelineName {
/// Create a new TimelineName from Atom.
#[cfg(feature = "gecko")]
pub fn from_atom(atom: Atom) -> Self {
Self(TimelineOrKeyframesName::from_atom(atom))
}
/// Returns the `none` value.
pub fn none() -> Self {
Self(TimelineOrKeyframesName::none())
}
}
impl Parse for TimelineName {
fn parse<'i, 't>(
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Ok(Self(TimelineOrKeyframesName::parse(
input,
&["none", "auto"],
)?))
}
}
impl ToCss for TimelineName {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
self.0.to_css(dest, &["none", "auto"])
}
}
/// The typedef of <keyframes-name>.
#[repr(transparent)]
#[derive(

Просмотреть файл

@ -8,7 +8,7 @@ use crate::parser::{Parse, ParserContext};
use crate::properties::{NonCustomPropertyId, PropertyId, ShorthandId};
use crate::values::generics::animation as generics;
use crate::values::specified::{LengthPercentage, NonNegativeNumber};
use crate::values::{CustomIdent, KeyframesName, TimelineName};
use crate::values::{CustomIdent, DashedIdent, KeyframesName};
use crate::Atom;
use cssparser::Parser;
use std::fmt::{self, Write};
@ -525,6 +525,63 @@ impl generics::ViewFunction<LengthPercentage> {
}
}
/// The typedef of scroll-timeline-name or view-timeline-name.
///
/// https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-name
/// https://drafts.csswg.org/scroll-animations-1/#view-timeline-name
#[derive(
Clone,
Debug,
Eq,
Hash,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToResolvedValue,
ToShmem,
)]
#[repr(C)]
pub struct TimelineName(DashedIdent);
impl TimelineName {
/// Returns the `none` value.
pub fn none() -> Self {
Self(DashedIdent::empty())
}
/// Check if this is `none` value.
pub fn is_none(&self) -> bool {
self.0.is_empty()
}
}
impl Parse for TimelineName {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input.try_parse(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(Self::none())
}
DashedIdent::parse(context, input).map(TimelineName)
}
}
impl ToCss for TimelineName {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.is_none() {
return dest.write_str("none")
}
self.0.to_css(dest)
}
}
/// A specified value for the `animation-timeline` property.
pub type AnimationTimeline = generics::GenericAnimationTimeline<LengthPercentage>;
@ -535,22 +592,19 @@ impl Parse for AnimationTimeline {
) -> Result<Self, ParseError<'i>> {
use crate::values::generics::animation::ViewFunction;
// <single-animation-timeline> = auto | none | <custom-ident> | <scroll()> | <view()>
// <single-animation-timeline> = auto | none | <dashed-ident> | <scroll()> | <view()>
// https://drafts.csswg.org/css-animations-2/#typedef-single-animation-timeline
if input.try_parse(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(Self::Auto);
}
if input.try_parse(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(AnimationTimeline::Timeline(TimelineName::none()));
}
// This parses none or <dashed-indent>.
if let Ok(name) = input.try_parse(|i| TimelineName::parse(context, i)) {
return Ok(AnimationTimeline::Timeline(name));
}
// Parse possible functions
// Parse <scroll()> or <view()>.
let location = input.current_source_location();
let function = input.expect_function()?.clone();
input.parse_nested_block(move |i| {
@ -567,9 +621,6 @@ impl Parse for AnimationTimeline {
}
}
/// A value for the scroll-timeline-name or view-timeline-name.
pub type ScrollTimelineName = AnimationName;
/// A specified value for the `view-timeline-inset` property.
pub type ViewTimelineInset = generics::GenericViewTimelineInset<LengthPercentage>;

Просмотреть файл

@ -30,7 +30,7 @@ pub use self::align::{JustifyContent, JustifyItems, JustifySelf, SelfAlignment};
pub use self::angle::{AllowUnitlessZeroAngle, Angle};
pub use self::animation::{
AnimationComposition, AnimationDirection, AnimationFillMode, AnimationIterationCount,
AnimationName, AnimationPlayState, AnimationTimeline, ScrollAxis, ScrollTimelineName,
AnimationName, AnimationPlayState, AnimationTimeline, ScrollAxis, TimelineName,
TransitionBehavior, TransitionProperty, ViewTimelineInset,
};
pub use self::background::{BackgroundRepeat, BackgroundSize};

Просмотреть файл

@ -88,6 +88,7 @@ exclude = [
include = [
"AnchorName",
"AnchorScope",
"AnimationName",
"AnimationTimeline",
"AnimationIterationCount",
"AnimationDirection",
@ -157,7 +158,7 @@ include = [
"ScrollSnapStop",
"ScrollSnapStrictness",
"ScrollSnapType",
"ScrollTimelineName",
"TimelineName",
"TransitionBehavior",
"ViewTimelineInset",
"OverflowAnchor",
@ -972,11 +973,6 @@ renaming_overrides_prefixing = true
bool IsNamedFamily(const nsAString&) const;
"""
"TimelineOrKeyframesName" = """
public:
inline nsAtom* AsAtom() const;
"""
"FontWeight" = """
SERVO_FIXED_POINT_HELPERS(StyleFontWeight, uint16_t, StyleFONT_WEIGHT_FRACTION_BITS);
bool IsNormal() const { return *this == NORMAL; }
@ -1018,6 +1014,12 @@ renaming_overrides_prefixing = true
StyleAnimationName() : _0(nsGkAtoms::_empty) {}
"""
"TimelineName" = """
public:
StyleTimelineName() : _0(nsGkAtoms::_empty) {}
nsAtom* AsAtom() const { return _0.AsAtom(); }
"""
"GenericViewTimelineInset" = """
public:
inline StyleGenericViewTimelineInset();

Просмотреть файл

@ -1,6 +0,0 @@
[animation-timeline-parsing.html]
[e.style['animation-timeline'\] = "\\"test\\"" should not set the property value]
expected: FAIL
[e.style['animation-timeline'\] = "test1" should not set the property value]
expected: FAIL

Просмотреть файл

@ -1,6 +0,0 @@
[scroll-timeline-name-parsing.html]
[e.style['scroll-timeline-name'\] = "auto" should not set the property value]
expected: FAIL
[e.style['scroll-timeline-name'\] = "abc" should not set the property value]
expected: FAIL

Просмотреть файл

@ -1,6 +0,0 @@
[view-timeline-name-parsing.html]
[e.style['view-timeline-name'\] = "auto" should not set the property value]
expected: FAIL
[e.style['view-timeline-name'\] = "abc" should not set the property value]
expected: FAIL

Просмотреть файл

@ -26,9 +26,6 @@
[e.style['view-timeline'\] = "--abcd block 1px 1px" should set the property value]
expected: FAIL
[e.style['view-timeline'\] = "auto" should not set the property value]
expected: FAIL
[Property view-timeline value '--abcd block auto']
expected: FAIL