Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (237283 => 237284)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,3 +1,18 @@
+2018-10-19 Ali Juma <[email protected]>
+
+ [IntersectionObserver] Handle zero-area intersections
+ https://bugs.webkit.org/show_bug.cgi?id=189624
+
+ Reviewed by Simon Fraser.
+
+ Rebaseline expectations for tests that now pass.
+
+ * web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt:
+ * web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt:
+ * web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt:
+ * web-platform-tests/intersection-observer/text-target-expected.txt:
+ * web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt:
+
2018-10-18 Yusuke Suzuki <[email protected]>
[JSC] JSC should have "parseFunction" to optimize Function constructor
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt (237283 => 237284)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt 2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt 2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,7 +1,7 @@
PASS IntersectionObserver should detect and report edge-adjacent and zero-area intersections.
PASS First rAF.
-FAIL Set transform=translateY(200px) on target. assert_equals: entries.length expected 2 but got 1
-FAIL Set transform=translateY(201px) on target. assert_equals: entries.length expected 3 but got 1
-FAIL Set transform=translateY(185px) on target. assert_equals: entries.length expected 4 but got 1
+PASS Set transform=translateY(200px) on target.
+PASS Set transform=translateY(201px) on target.
+PASS Set transform=translateY(185px) on target.
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt (237283 => 237284)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt 2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt 2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,4 +1,7 @@
PASS isIntersecting changes should trigger notifications.
-FAIL Rects in initial notifications should report initial positions. assert_equals: entries[2].target.isIntersecting equals true expected true but got false
+PASS Rects in initial notifications should report initial positions.
+PASS Set scrollTop=100 and check for no new notifications.
+PASS Add 4th target.
+PASS Set scrollTop=100 and check for one new notification.
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt (237283 => 237284)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt 2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt 2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,6 +1,6 @@
PASS Observing a zero-area target.
PASS First rAF
-FAIL document.scrollingElement.scrollTop = 300 assert_equals: entries.length expected 2 but got 1
-FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1
+PASS document.scrollingElement.scrollTop = 300
+PASS document.scrollingElement.scrollTop = 100
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/text-target-expected.txt (237283 => 237284)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/text-target-expected.txt 2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/text-target-expected.txt 2018-10-19 13:47:25 UTC (rev 237284)
@@ -2,6 +2,6 @@
PASS IntersectionObserver observing a br element.
PASS First rAF.
-FAIL document.scrollingElement.scrollTop = 300 assert_equals: entries.length expected 2 but got 1
-FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1
+PASS document.scrollingElement.scrollTop = 300
+PASS document.scrollingElement.scrollTop = 100
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt (237283 => 237284)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt 2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt 2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,4 +1,4 @@
PASS Ensure that a zero-area target intersecting root generates a notification with intersectionRatio == 1
-FAIL First rAF should generate a notification. assert_equals: intersectionRatio == 1 expected 1 but got 0
+PASS First rAF should generate a notification.
Modified: trunk/Source/WebCore/ChangeLog (237283 => 237284)
--- trunk/Source/WebCore/ChangeLog 2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/Source/WebCore/ChangeLog 2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,3 +1,21 @@
+2018-10-19 Ali Juma <[email protected]>
+
+ [IntersectionObserver] Handle zero-area intersections
+ https://bugs.webkit.org/show_bug.cgi?id=189624
+
+ Reviewed by Simon Fraser.
+
+ Use edge-inclusive intersection when applying clips and intersecting with the
+ root, so that two rects that touch each other are considered intersecting even
+ if the area of their intersection is 0.
+
+ Covered by rebased tests in imported/w3c/web-platform-tests/intersection-observer.
+
+ * dom/Document.cpp:
+ (WebCore::computeIntersectionState):
+ (WebCore::Document::updateIntersectionObservations):
+ (WebCore::computeIntersectionRects): Deleted.
+
2018-10-18 Eric Carlson <[email protected]>
[MediaStream] Allow ports to optionally do screen capture in the UI process
Modified: trunk/Source/WebCore/dom/Document.cpp (237283 => 237284)
--- trunk/Source/WebCore/dom/Document.cpp 2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/Source/WebCore/dom/Document.cpp 2018-10-19 13:47:25 UTC (rev 237284)
@@ -7592,25 +7592,32 @@
localRootBounds.expand(rootMarginFloatBox);
}
-static void computeIntersectionRects(FrameView& frameView, IntersectionObserver& observer, Element& target, FloatRect& absTargetRect, FloatRect& absIntersectionRect, FloatRect& absRootBounds)
+struct IntersectionObservationState {
+ FloatRect absoluteTargetRect;
+ FloatRect absoluteRootBounds;
+ FloatRect absoluteIntersectionRect;
+ bool isIntersecting { false };
+};
+
+static std::optional<IntersectionObservationState> computeIntersectionState(FrameView& frameView, const IntersectionObserver& observer, Element& target)
{
// FIXME: Implement intersection computation for the cross-document case.
if (observer.trackingDocument() != &target.document())
- return;
+ return std::nullopt;
auto* targetRenderer = target.renderer();
if (!targetRenderer)
- return;
+ return std::nullopt;
FloatRect localRootBounds;
RenderBlock* rootRenderer;
if (observer.root()) {
if (!observer.root()->renderer() || !is<RenderBlock>(observer.root()->renderer()))
- return;
+ return std::nullopt;
rootRenderer = downcast<RenderBlock>(observer.root()->renderer());
if (!rootRenderer->isContainingBlockAncestorFor(*targetRenderer))
- return;
+ return std::nullopt;
if (rootRenderer->hasOverflowClip())
localRootBounds = rootRenderer->contentBoxRect();
@@ -7632,14 +7639,19 @@
else if (is<RenderLineBreak>(targetRenderer))
localTargetBounds = downcast<RenderLineBreak>(targetRenderer)->linesBoundingBox();
- FloatRect rootLocalIntersectionRect = targetRenderer->computeRectForRepaint(localTargetBounds, rootRenderer);
- rootLocalIntersectionRect.intersect(localRootBounds);
+ OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls };
+ std::optional<LayoutRect> rootLocalTargetRect = targetRenderer->computeVisibleRectInContainer(localTargetBounds, rootRenderer, { false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions });
+ FloatRect rootLocalIntersectionRect = localRootBounds;
- if (!rootLocalIntersectionRect.isEmpty())
- absIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox();
+ IntersectionObservationState intersectionState;
+ intersectionState.isIntersecting = rootLocalTargetRect && rootLocalIntersectionRect.edgeInclusiveIntersect(*rootLocalTargetRect);
- absTargetRect = targetRenderer->localToAbsoluteQuad(FloatRect(localTargetBounds)).boundingBox();
- absRootBounds = rootRenderer->localToAbsoluteQuad(localRootBounds).boundingBox();
+ if (intersectionState.isIntersecting)
+ intersectionState.absoluteIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox();
+
+ intersectionState.absoluteTargetRect = targetRenderer->localToAbsoluteQuad(FloatRect(localTargetBounds)).boundingBox();
+ intersectionState.absoluteRootBounds = rootRenderer->localToAbsoluteQuad(localRootBounds).boundingBox();
+ return intersectionState;
}
void Document::updateIntersectionObservations()
@@ -7667,28 +7679,38 @@
ASSERT(index != notFound);
auto& registration = targetRegistrations[index];
- FloatRect absTargetRect;
- FloatRect absIntersectionRect;
- FloatRect absRootBounds;
- computeIntersectionRects(*frameView, *observer, *target, absTargetRect, absIntersectionRect, absRootBounds);
+ auto intersectionState = computeIntersectionState(*frameView, *observer, *target);
- // FIXME: Handle zero-area intersections (e.g., intersections involving zero-area targets).
- bool isIntersecting = absIntersectionRect.area();
- float intersectionRatio = isIntersecting ? absIntersectionRect.area() / absTargetRect.area() : 0;
+ float intersectionRatio = 0;
size_t thresholdIndex = 0;
- if (isIntersecting) {
- auto& thresholds = observer->thresholds();
- while (thresholdIndex < thresholds.size() && thresholds[thresholdIndex] <= intersectionRatio)
- ++thresholdIndex;
+ if (intersectionState) {
+ if (intersectionState->isIntersecting) {
+ float absTargetArea = intersectionState->absoluteTargetRect.area();
+ if (absTargetArea)
+ intersectionRatio = intersectionState->absoluteIntersectionRect.area() / absTargetArea;
+ else
+ intersectionRatio = 1;
+
+ auto& thresholds = observer->thresholds();
+ while (thresholdIndex < thresholds.size() && thresholds[thresholdIndex] <= intersectionRatio)
+ ++thresholdIndex;
+ }
}
+
if (!registration.previousThresholdIndex || thresholdIndex != registration.previousThresholdIndex) {
- FloatRect targetBoundingClientRect = frameView->absoluteToClientRect(absTargetRect);
- FloatRect clientIntersectionRect = isIntersecting ? frameView->absoluteToClientRect(absIntersectionRect) : FloatRect();
+ FloatRect targetBoundingClientRect;
+ FloatRect clientIntersectionRect;
+ FloatRect clientRootBounds;
+ if (intersectionState) {
+ targetBoundingClientRect = frameView->absoluteToClientRect(intersectionState->absoluteTargetRect);
+ clientRootBounds = frameView->absoluteToClientRect(intersectionState->absoluteRootBounds);
+ if (intersectionState->isIntersecting)
+ clientIntersectionRect = frameView->absoluteToClientRect(intersectionState->absoluteIntersectionRect);
+ }
// FIXME: Once cross-document observation is implemented, only report root bounds if the target document and
// the root document are similar-origin.
- FloatRect clientRootBounds = frameView->absoluteToClientRect(absRootBounds);
std::optional<DOMRectInit> reportedRootBounds = DOMRectInit({
clientRootBounds.x(),
clientRootBounds.y(),
@@ -7703,7 +7725,7 @@
{ clientIntersectionRect.x(), clientIntersectionRect.y(), clientIntersectionRect.width(), clientIntersectionRect.height() },
intersectionRatio,
target,
- isIntersecting,
+ intersectionState? intersectionState->isIntersecting : false,
}));
needNotify = true;
registration.previousThresholdIndex = thresholdIndex;