This sounds like mostly confusion in the meaning of the `callOnIdle` API and perhaps subtle differences in the contract of setTimeout and setInterval in DHTML vs. Flash runtimes:
The idle kernel tries to simulate the Flash concept of code that would run during the "vertical blanking interval", i.e., at the frame rate of the "movie". To that end, it is trying to generate an "idle" event based on a nominal "framerate" (even though there is no such thing in DHTML). This idle event stream is probably important for animators, but even the animator code admits to knowing that the idle event is not precise -- they calculate their motion based on actual elapsed time. The name `callOnIdle` makes it sound like "call this function back when there is nothing else happening"; but the implementation is "call this function back on the next 'idle' event", where the idle event is just a ticker that goes off every 1/framerate seconds. What we are trying to do with these measurement callbacks is really "let the runtime layout and update the display and then, once that display is updated, call us back so we can measure things". What's the difference? I think it is the following: With callOnIdle (as currently implemented): 1. Some event triggers debugger output 2. Debugger queues the callOnIdle 3. (sometimes) the idle interval is already up, while the debugger code is still running 4. Hence, rather than update the display, the idle callback is run immediately 5. You get the wrong values With setTimeout(0) [Which is the DHTML idiom for "call me back when synchronous code is done"] 1. Some event triggers debugger output 2. Debugger queues setTimeout 3. Debugger code finishes running 4. Display updates 5. Now you are really done with synchronous code and you get your callback It may be that this _is_ a bug in the DHTML implementation of callOnIdle, since it appears the contract from SWF days was "call me during the vertical blanking interval". It may be that the SWF implementation of setInterval is such that display updates run _before_ both setTimeout and setInterval callbacks, whereas in DHTML only setTimeout guarantees that the display update will happen. I'm intuiting that the difference lies in setInterval noticing that the event is passed and hence skips the display update in an attempt to signal the event as accurately as possible, whereas setTimeout(0) is, by convention, call me back only when there's nothing else happening. SWF, OTOH, being movie-oriented, always does the display update before the callbacks. Bottom line: Someone needs to do some low-level testing of setInterval and setTimeout. And we might need to adjust the DHTML implementation of callOnIdle to use setTimeout rather than the simulated idle event to maintain compatibility. On 2010-03-29, at 23:59, Henry Minsky wrote: > I noticed a bug in the debugger scrolling in DHTML, after Max's change to > text measurement callbacks. See LPP-8862. It looked like > a race condition where the code was not getting an updated scroll height > after it adds text to > the debugger's output text window. > > The weird thing is that there is already code in the debugger to wait a > frame to defer looking at the text scrollheight. In DHTML. It uses the > lz.Idle.callOnIdle to wait a frame and then look at the scrollheight. > > When I changed it to use lz.Timer.addTimer() to call itself back, instead of > callOnIdle(), then the > bug went away. > > The difference, I think, is in the kernel implentation, callOnIdle uses > setInterval(), whereas addTimer uses > setTimeout(). > > I'm not sure what implications this has for us, but maybe it means we > should be careful to use setTimeout in the > DHTML runtime when we want these layout callbacks to work properly, rather > relying on anything that uses setInterval. > > -- > Henry Minsky > Software Architect > [email protected]
