Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 All of the IntersectionObserver tests feature the following idiom: | |
| 2 | |
| 3 <script> | |
| 4 var observer = new IntersectionObserver(...) | |
| 5 function test_function() { | |
| 6 var entries = observer.takeRecords(); | |
| 7 // Verify entries | |
| 8 } | |
| 9 onload = function() { | |
| 10 observer.observe(target); | |
| 11 requestAnimationFrame(() => { requestAnimationFrame(test_function) }); | |
| 12 } | |
| 13 | |
| 14 Subsequent steps in the test use a single RAF to give the observer a chance to | |
| 15 generate notifications, but the double RAF is required in the onload handler. | |
| 16 Here's the chain of events: | |
| 17 | |
| 18 - onload | |
| 19 - observer.observe() | |
| 20 - First RAF handler is registered | |
| 21 - BeginFrame | |
| 22 - RAF handlers run | |
| 23 - Second RAF handler is registered | |
| 24 - UpdateAllLifecyclePhases | |
| 25 - IntersectionObserver generates notifications | |
| 26 - BeginFrame | |
| 27 - RAF handlers run | |
| 28 - Second RAF handler verifies observer notifications. | |
| 29 | |
| 30 #------------------------------------------------------------------------------- | |
| 31 | |
| 32 All of the IntersectionObserver tests end with: | |
| 33 | |
| 34 requestIdleCallback(finishJSTest, {timeout: 100}); | |
| 35 | |
| 36 To avoid leaking DOM objects, the tests must ensure that all posted tasks have | |
| 37 run before exiting. IntersectionObserverController requests an idle callback | |
| 38 through the document's ScriptedIdleTaskController with a timeout of 100ms. That | |
| 39 callback must be allowed to run before the test finishes to avoid a leak. | |
| 40 | |
| 41 ScriptedIdleTaskController posts two tasks to the WebScheduler: one to run at | |
| 42 the next idle time, and another to run when the timeout expires. | |
| 43 crbug.com/595155 explains that when one of those tasks runs, it does not release | |
|
ojan
2016/03/21 18:19:39
Somewhere in here should be a TODO that we can rem
szager1
2016/03/21 18:27:49
It's the other bug that needs to be fixed; added a
| |
| 44 its reference to the ScriptedIdleTaskController, which is needlessly kept alive | |
| 45 until the both tasks have fired. If a test exits before both tasks have fired, | |
| 46 it will have a DOM leak. | |
| 47 | |
| 48 crbug.com/595152 explains that when running without the threaded compositor -- | |
| 49 as the layout tests do -- idle tasks are never serviced. They will still run | |
| 50 when their timeout expires, but the idle task posted by | |
| 51 ScriptedIdleTaskController will never run. | |
| 52 | |
| 53 Fixing the first bug means that requestIdleCallback will not leak as long as it | |
| 54 actually runs before exit. The second bug means that when running without the | |
| 55 threaded compositor, requestIdleCallback will only ever run when its timeout | |
| 56 expires. | |
| 57 | |
| 58 The upshot of all of this is that the only way to ensure that | |
| 59 IntersectionObserver tests don't leak is to ensure that their idle tasks all run | |
| 60 before the tests exit, and those idle tasks will only run when their 100ms | |
| 61 timeout expires. | |
| 62 | |
| 63 Note that all of this still holds when observer.takeRecords() is called before | |
| 64 the idle task runs. In that case, the idle task is not cancelled (because the | |
| 65 idle task needs to service all observers tracked by a given | |
| 66 IntersectionObserverController); when the idle task runs, it's simply a no-op. | |
| 67 There is no way in javascript to detect that such a no-op has occurred, but | |
| 68 using requestIdleCallback with a timeout of 100 should be guaranteed to run | |
| 69 after the IntersectionObserverController's idle task has run, as long as | |
| 70 ScriptedIdleTaskController honors first-in-first-out semantics. | |
| OLD | NEW |