[Webkit-unassigned] [Bug 196729] New: IntersectionObserver delivers incorrect records and fires at the wrong time
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Tue Apr 9 03:40:55 PDT 2019
https://bugs.webkit.org/show_bug.cgi?id=196729
Bug ID: 196729
Summary: IntersectionObserver delivers incorrect records and
fires at the wrong time
Product: WebKit
Version: WebKit Nightly Build
Hardware: Unspecified
OS: Unspecified
Status: NEW
Severity: Normal
Priority: P2
Component: DOM
Assignee: webkit-unassigned at lists.webkit.org
Reporter: esprehn at chromium.org
The implementation of scheduling done here https://bugs.webkit.org/show_bug.cgi?id=189007 does not follow the spec which requires that the observations be computed after the next layout. Instead they seem to be on a one shot timer that's not connected to the rendering system. This means they report about elements not in the document, and also that there's both ordering bugs compared to other browsers as well as race conditions where sometimes the wrong records are delivered.
ex.
// Does not notify in Chrome or Firefox, notifies with a zero sized rect in Safari.
o = new IntersectionObserver((records) => console.log(records))
d = document.createElement('div')
o.observe(d)
ex.
// Delivers intersection records once with the right width and height in Chrome and Firefox. Delivers zero sized rects in Safari and then the correct ones later.
o = new IntersectionObserver((records) => console.log(records))
d = document.createElement('div')
o.observe(d)
requestAnimationFrame(() => { document.body.append(d); d.textContent = 'Hello World' })
ex.
// Delivers a record with zero height and *never* delivers the correct rects.
document.body.style.fontSize = 32;
o = new IntersectionObserver((records) => {
// prints [0], but should print a number greater than 32.
console.log(records.map(r => r.boundingClientRect.height));
})
d = document.createElement('div')
o.observe(d)
setTimeout(() => {
let x = document.createElement('div')
x.textContent = 'Hello World'
d.appendChild(x);
});
document.body.append(d);
The code also skips computing intersections if there's a pending style recalc or layout:
https://github.com/WebKit/webkit/blob/9029c43e695bf886fffb15eec951f0605e34509b/Source/WebCore/dom/Document.cpp#L7540
and then restarts the timer if no layout is required in Document::resolveStyle
https://github.com/WebKit/webkit/blob/9029c43e695bf886fffb15eec951f0605e34509b/Source/WebCore/dom/Document.cpp#L1918
but if layout was required nothing seems to restart the timer. I think this works today because updateLayoutAndStyleIfNeededRecursive will always run all the steps twice so the timer gets restarted on the second pass. If that loop wasn't there I don't think IntersectionObserver would work.
--
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20190409/be852adc/attachment.html>
More information about the webkit-unassigned
mailing list