diff --git a/layout/generic/ReflowOutput.cpp b/layout/generic/ReflowOutput.cpp index d54684809a371dde17c93a7cd3053c1d01f60c89..a0312dffda9477845408cef49cc121a93584b22f 100644 --- a/layout/generic/ReflowOutput.cpp +++ b/layout/generic/ReflowOutput.cpp @@ -11,6 +11,19 @@ namespace mozilla { +static bool IsValidOverflowRect(const nsRect& aRect) { + // `IsEmpty` in the context of `nsRect` means "width OR height is zero." + // However, in the context of overflow, the rect having one axis as zero is + // NOT considered empty. + if (MOZ_LIKELY(!aRect.IsEmpty())) { + return true; + } + + // Be defensive and consider rects with any negative size as invalid. + return !aRect.IsEqualEdges(nsRect()) && aRect.Width() >= 0 && + aRect.Height() >= 0; +} + /* static */ nsRect OverflowAreas::GetOverflowClipRect(const nsRect& aRectToClip, const nsRect& aBounds, @@ -40,12 +53,20 @@ void OverflowAreas::ApplyOverflowClippingOnRect(nsRect& aOverflowRect, } void OverflowAreas::UnionWith(const OverflowAreas& aOther) { - InkOverflow().UnionRect(InkOverflow(), aOther.InkOverflow()); - ScrollableOverflow().UnionRect(ScrollableOverflow(), - aOther.ScrollableOverflow()); + if (IsValidOverflowRect(aOther.InkOverflow())) { + InkOverflow().UnionRect(InkOverflow(), aOther.InkOverflow()); + } + if (IsValidOverflowRect(aOther.ScrollableOverflow())) { + ScrollableOverflow().UnionRect(ScrollableOverflow(), + aOther.ScrollableOverflow()); + } } void OverflowAreas::UnionAllWith(const nsRect& aRect) { + if (!IsValidOverflowRect(aRect)) { + // Same as `UnionWith()` - avoid losing information. + return; + } InkOverflow().UnionRect(InkOverflow(), aRect); ScrollableOverflow().UnionRect(ScrollableOverflow(), aRect); } diff --git a/testing/web-platform/tests/css/css-overflow/scrollable-overflow-zero-one-axis.html b/testing/web-platform/tests/css/css-overflow/scrollable-overflow-zero-one-axis.html new file mode 100644 index 0000000000000000000000000000000000000000..1986a8d48b98fde17fda826c5bbf9d75d870f45e --- /dev/null +++ b/testing/web-platform/tests/css/css-overflow/scrollable-overflow-zero-one-axis.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Overflow: Scroll Length Calculated Correctly When One Axis Has Zero Length</title> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="author" title="Mozilla" href="http://www.mozilla.org/"> +<link rel="help" href="https://drafts.csswg.org/css-overflow-3/#scrollable"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1800907"> +<style> +.scroll { + overflow: scroll; +} + +.zero-h { + width: 100px; + height: 0px; +} + +.zero-w { + width: 0; + height: 100px; +} + +.flex-row { + display: flex; +} + +.flex-col { + display: flex; + flex-direction: column; +} + +.grid { + display: grid; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> +<body onload="checkLayout('.scroll')"> +<div class="scroll zero-h" data-expected-scroll-height="100"> + <div class="zero-w"></div> +</div> +<div class="scroll zero-w" data-expected-scroll-width="100"> + <div class="zero-h"></div> +</div> + +<div class="scroll zero-h flex-row" data-expected-scroll-height="100"> + <div class="zero-w"></div> +</div> +<div class="scroll zero-w flex-col" data-expected-scroll-width="100"> + <div class="zero-h"></div> +</div> + +<div class="scroll zero-h grid" data-expected-scroll-height="100"> + <div class="zero-w"></div> +</div> +<div class="scroll zero-w grid" data-expected-scroll-width="100"> + <div class="zero-h"></div> +</div>