diff --git a/README.md b/README.md index 8ba43f0..7d2067c 100644 --- a/README.md +++ b/README.md @@ -27,73 +27,87 @@ This document is a developer-oriented description of what event loop does. It tr This is what the spec says: - eventLoop = { - taskQueues: { - events: [], // UI events from native GUI framework - parser: [], // HTML parser - callbacks: [], // setTimeout, requestIdleTask - resources: [], // image loading - domManipulation[] - }, - - microtaskQueue: [ - ], - - nextTask: function() { - // Spec says: - // "Select the oldest task on one of the event loop's task queues" - // Which gives browser implementers lots of freedom - // Queues can have different priorities, etc. - for (let q of taskQueues) - if (q.length > 0) - return q.shift(); - return null; - }, - - executeMicrotasks: function() { - if (scriptExecuting) - return; - let microtasks = this.microtaskQueue; - this.microtaskQueue = []; - for (let t of microtasks) - t.execute(); - }, - - needsRendering: function() { - return vSyncTime() && (needsDomRerender() || hasEventLoopEventsToDispatch()); - }, - - render: function() { - dispatchPendingUIEvents(); - resizeSteps(); - scrollSteps(); - mediaQuerySteps(); - cssAnimationSteps(); - fullscreenRenderingSteps(); - - animationFrameCallbackSteps(); - - intersectionObserverSteps(); - - while (resizeObserverSteps()) { - updateStyle(); - updateLayout(); - } - paint(); +```js +eventLoop = { + taskQueues: { + events: [], // UI events from native GUI framework + parser: [], // HTML parser + callbacks: [], // setTimeout, requestIdleTask + resources: [], // image loading + domManipulation[] + }, + + microtaskQueue: [ + ], + + requestAnimationFrameQueue: [ + ], + + nextTask() { + // Spec says: + // "Select the oldest task on one of the event loop's task queues" + // Which gives browser implementers lots of freedom + // Queues can have different priorities, etc. + for (let q of taskQueues) + if (q.length > 0) + return q.shift(); + return null; + }, + + executeJSCallback(callback) { + callback(); + if (!scriptExecuting) this.executeMicrotasks(); + }, + + executeMicrotasks() { + let microTask; + + while (microtask = this.microtaskQueue.shift()) { + microTask.execute(); } + }, + + executeRequestAnimationFrameCallbacks() { + const callbacks = this.requestAnimationFrameQueue; + this.requestAnimationFrameQueue = []; + + for (const callback of callbacks) this.executeJSCallback(callback); } - while(true) { - task = eventLoop.nextTask(); - if (task) { - task.execute(); + needsRendering() { + return vSyncTime() && (needsDomRerender() || hasEventLoopEventsToDispatch()); + }, + + render() { + dispatchPendingUIEvents(); + resizeSteps(); + scrollSteps(); + mediaQuerySteps(); + cssAnimationSteps(); + fullscreenRenderingSteps(); + + this.executeRequestAnimationFrameCallbacks(); + + intersectionObserverSteps(); + + while (resizeObserverSteps()) { + updateStyle(); + updateLayout(); } - eventLoop.executeMicrotasks(); - if (eventLoop.needsRendering()) - eventLoop.render(); + paint(); } +} - +while(true) { + task = eventLoop.nextTask(); + if (task) { + task.execute(); + } + eventLoop.executeMicrotasks(); + if (eventLoop.needsRendering()) + eventLoop.render(); +} +``` ## Close reading of the spec