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 |