Bug 1553673 - Round intersection observer percentage margins with NSToCoordRound rather than the default rounder. r=dholbert

The default rounder floors percentages instead of rounding, which can cause
subtle issues.

This is generally desirable for most lengths, AIUI, so that pages don't cause
undesired overflow when using percentage widths and such, but for the
intersection observer root margin, it can cause some annoyance as the percentage
going negative may cause the root rect to be negatively sized and report no
intersection.

This also seems to match Blink[1], though it goes back to the initial
implementation of IntersectionObserver.rootMargin[2].

[1]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc?l=52&rcl=8671a050dd117b730bffbad5838f218fcc024845
[2]: c88a8ad4f1

Differential Revision: https://phabricator.services.mozilla.com/D32873

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-06-11 19:16:46 +00:00
Родитель 71e82c0744
Коммит 88b5840556
2 изменённых файлов: 32 добавлений и 1 удалений

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

@ -282,7 +282,7 @@ void DOMIntersectionObserver::Update(Document* aDocument,
nscoord basis = side == eSideTop || side == eSideBottom ? rootRect.Height()
: rootRect.Width();
rootMargin.Side(side) =
nsLayoutUtils::ComputeCBDependentValue(basis, mRootMargin.Get(side));
mRootMargin.Get(side).Resolve(basis, NSToCoordRoundWithClamp);
}
for (Element* target : mObservationTargets) {

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

@ -0,0 +1,31 @@
<!doctype html>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="help" href="https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-rootmargin">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1553673">
<style>
html { width: 100vw; height: 100vh }
</style>
<script>
const t = async_test("IntersectionObserver root margin cannot end up with negative rect (and thus non-intersecting) due to rounding");
let remainingTests = 100;
// This is just a best-effort test to catch issues.
for (let i = 0; i < 100; ++i) {
let offset = i / 100;
let observer;
observer = new IntersectionObserver(t.step_func(function(entries) {
assert_equals(entries.length, 1);
assert_equals(entries[0].target, document.documentElement);
assert_true(entries[0].isIntersecting, "should be intersecting at " + offset);
if (!--remainingTests)
t.done();
observer.disconnect();
}), { rootMargin: `${-100 * (1 - offset)}% 0px ${-100 * offset}%` });
observer.observe(document.documentElement);
}
</script>