Commit 3498bfdc authored by Anders Hartvoll Ruud's avatar Anders Hartvoll Ruud Committed by Commit Bot

[scroll-animations] Handle element-based offsets with null targets

Currently we assume that element-based offsets always have non-null
targets ResolveOffset-time, since we enforce this during the creation
of the (non-CSS) ScrollTimelines.

However, for CSSScrollTimelines, we can't invalidate the rule this way,
since we're referring to an element indirectly via an ID, not with a
pointer to a specific element.

Checking whether or not the target is null during ResolveOffset fixes
this, and it's also what we're supposed to be doing per spec.

This fixes a crash when using @scroll-timelines with element-based
offsets that reference non-existent IDs.

Also removed a nearby comment that's outdated (but not strictly
related to the change in this CL).

Bug: 1074052, 1102788
Change-Id: I4e138b55c3ef8cb122c58755a72a586e94c97e69
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2498463
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: default avatarKevin Ellis <kevers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821682}
parent 0597fd97
...@@ -129,15 +129,8 @@ base::Optional<double> ScrollTimelineOffset::ResolveOffset( ...@@ -129,15 +129,8 @@ base::Optional<double> ScrollTimelineOffset::ResolveOffset(
return resolved; return resolved;
} else if (element_based_offset_) { } else if (element_based_offset_) {
// We assume that the root is the target's ancestor in layout tree. Under if (!element_based_offset_->hasTarget())
// this assumption |target.LocalToAncestorRect()| returns the targets's return base::nullopt;
// position relative to the root's border box, while ignoring scroll offset.
//
// TODO(majidvp): We need to validate this assumption and deal with cases
// where it is not true. See the spec discussion here:
// https://github.com/w3c/csswg-drafts/issues/4337#issuecomment-610989843
DCHECK(element_based_offset_->hasTarget());
Element* target = element_based_offset_->target(); Element* target = element_based_offset_->target();
const LayoutBox* target_box = target->GetLayoutBox(); const LayoutBox* target_box = target->GetLayoutBox();
......
...@@ -77,6 +77,12 @@ ...@@ -77,6 +77,12 @@
start: selector(#offset_display_none); start: selector(#offset_display_none);
end: auto; end: auto;
} }
@scroll-timeline timeline_null_target {
source: selector(#scroller);
time-range: 10s;
start: selector(#no_such_id);
end: selector(#no_such_id);
}
#container > div { #container > div {
width: 0px; width: 0px;
...@@ -97,6 +103,7 @@ ...@@ -97,6 +103,7 @@
#element_50px_end { animation-timeline: timeline_50px_end; } #element_50px_end { animation-timeline: timeline_50px_end; }
#element_outside { animation-timeline: timeline_outside; } #element_outside { animation-timeline: timeline_outside; }
#element_display_none { animation-timeline: timeline_display_none; } #element_display_none { animation-timeline: timeline_display_none; }
#element_null_target { animation-timeline: timeline_null_target; }
</style> </style>
<div id=scroller> <div id=scroller>
<div id=contents> <div id=contents>
...@@ -119,6 +126,7 @@ ...@@ -119,6 +126,7 @@
<div id=element_50px_end></div> <div id=element_50px_end></div>
<div id=element_outside></div> <div id=element_outside></div>
<div id=element_display_none></div> <div id=element_display_none></div>
<div id=element_null_target></div>
</div> </div>
<script> <script>
...@@ -238,4 +246,12 @@ ...@@ -238,4 +246,12 @@
test_width_at_scroll_top(element_display_none, 400, '0px'); test_width_at_scroll_top(element_display_none, 400, '0px');
test_width_at_scroll_top(element_display_none, 450, '0px'); test_width_at_scroll_top(element_display_none, 450, '0px');
// Target of element-based offset is null (=> no effect value)
test_width_at_scroll_top(element_null_target, 0, '0px');
test_width_at_scroll_top(element_null_target, 100, '0px');
test_width_at_scroll_top(element_null_target, 200, '0px');
test_width_at_scroll_top(element_null_target, 300, '0px');
test_width_at_scroll_top(element_null_target, 400, '0px');
test_width_at_scroll_top(element_null_target, 450, '0px');
</script> </script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment