翻译webappapis中关于eventloop的部分 https://www.w3.org/TR/html5/webappapis.html#event-loops
6.1.4 Event loops
6.1.4 Event loops
6.1.4.1 定义
对于坐标事件,用户交互,脚本,渲染,网络等等,用户代理会用到本节描述的event loops。
每个用户代理至少存在一个event loop,and at most one event loop per unit of related similar-origin browsing contexts.
When there is more than one event loop for a unit of related browsing contexts, complications arise when a browsing context in that group is navigated such that it switches from one unit of related similar-origin browsing contexts to another. This specification does not currently describe how to handle these complications.
一个event loop总是至少有一个个浏览上下文。如果一个event loop的浏览上下文全部销毁,那么这个event loop也同时销毁。一个浏览上下文总是有一个event loop来协调他的活动。
一个event loop有一个或者多个任务队列。任务队列是一个有序的任务列表,which are algorithms that are responsible for such work as:
Events
Asynchronously dispatching an Event object at a particular EventTarget object is often done by a dedicated task.
Not all events are dispatched using the task queue, many are dispatched synchronously during other tasks.
Parsing
The HTML parser tokenizing one or more bytes, and then processing any resulting tokens, is typically a task.
Callbacks
Calling a callback asynchronously is often done by a dedicated task.
Using a resource
When an algorithm fetches a resource, if the fetching occurs asynchronously then the processing of the resource once some or all of the resource is available is performed by a task.
Reacting to DOM manipulation
Some elements have tasks that trigger in response to DOM manipulation, e.g. when that element is inserted into the document.
Each task is associated with a Document; if the task was queued in the context of an element, then it is the element’s Document; if the task was queued in the context of a browsing context, then it is the browsing context’s active document at the time the task was queued; if the task was queued by or for a script then the document is the responsible document specified by the script’s settings object.
A task is intended for a specific event loop: the event loop that is handling tasks for the task’s associated Document.
When a user agent is to queue a task, it must add the given task to one of the task queues of the relevant event loop.
Each task is defined as coming from a specific task source. All the tasks from one particular task source and destined to a particular event loop (e.g. the callbacks generated by timers of a Document, the events fired for mouse movements over that Document, the tasks queued for the parser of that Document) must always be added to the same task queue, but tasks from different task sources may be placed in different task queues.
For example, a user agent could have one task queue for mouse and key events (the user interaction task source), and another for everything else. The user agent could then give keyboard and mouse events preference over other tasks three quarters of the time, keeping the interface responsive but not starving other task queues, and never processing events from any one task source out of order.
A user agent may have one storage mutex. This mutex is used to control access to shared state like cookies. At any one point, the storage mutex is either free, or owned by a particular event loop or instance of the fetching algorithm.
If a user agent does not implement a storage mutex, it is exempt from implementing the requirements that require it to acquire or release it.
Note:User agent implementors have to make a choice between two evils. On the one hand, not implementing the storage mutex means that there is a risk of data corruption: a site could, for instance, try to read a cookie, increment its value, then write it back out, using the new value of the cookie as a unique identifier for the session; if the site does this twice in two different browser windows at the same time, it might end up using the same “unique” identifier for both sessions, with potentially disastrous effects. On the other hand, implementing the storage mutex has potentially serious performance implications: whenever a site uses Web Storage or cookies, all other sites that try to use Web Storage or cookies are blocked until the first site finishes.
Whenever a script calls into a plugin, and whenever a plugin calls into a script, the user agent must release the storage mutex.
6.1.4.2 Processing model
An event loop must continually run through the following steps for as long as it exists:
- Run the oldest task on one of the event loop’s task queues, if any, ignoring tasks whose associated Documents are not fully active. The user agent may pick any task queue.
- If the storage mutex is now owned by the event loop, release it so that it is once again free.
- If a task was run in the first step above, remove that task from its task queue.
- If this event loop is not a worker’s event loop, run these substeps:
- Perform a microtask checkpoint.
- Provide a stable state.
- If necessary, update the rendering or user interface of any Document or browsing context to reflect the current state.
- Otherwise, if this event loop is running for a WorkerGlobalScope, but there are no events in the event loop’s task queues and the WorkerGlobalScope object’s closing flag is true, then destroy the event loop, aborting these steps.
- Return to the first step of the event loop.
When a user agent is to perform a microtask checkpoint, if the performing a microtask checkpoint flag is false, then the user agent must run the following steps:
- Let the performing a microtask checkpoint flag be true.
- Perform a custom elements checkpoint. [CUSTOM]
- Sort the tables with pending sorts.
- Invoke MutationObserver objects for the unit of related similar-origin browsing contexts to which the responsible browsing context specified by the script’s settings object belongs, using the task wrapper algorithm as the steps to invoke each callback.
Note:This will typically invoke scripted callbacks, which eventually calls the clean up after running a callback steps, which call this perform a microtask checkpoint algorithm again, which is why we use the performing a microtask checkpoint flag to avoid reentrancy.
- Let the performing a microtask checkpoint flag be false.
When the user agent is to provide a stable state, if any asynchronously-running algorithms are awaiting a stable state, then the user agent must run their synchronous section and then resume running their asynchronous algorithm (if appropriate).
Note:A synchronous section never mutates the DOM, runs any script, or has any side-effects detectable from another synchronous section, and thus synchronous sections can be run in any order, and cannot spin the event loop.
Note:Steps in synchronous sections are marked with ⌛.
The task wrapper algorithm, which is implicitly invoked in the context of an event loop and is used to invoke a given callback in a specific way, is as follows:
1.Invoke callback as specified.
The above will change in due course; see bug 20821.
When an algorithm says to spin the event loop until a condition goal is met, the user agent must run the following steps:
- Let task source be the task source of the currently running task.
- Let old stack of script settings objects be a copy of the stack of script settings objects.
- Empty the stack of script settings objects.
- Run the global script clean-up jobs.
- Perform a microtask checkpoint.
- Stop the currently running task, allowing the event loop to resume, but continue these steps asynchronously.
This causes the event loop to move on to the second step of its processing model (defined above).
- Wait until the condition goal is met.
- Queue a task to continue running these steps, using the task source task source. Wait until this task runs before continuing these steps.
- Replace the stack of script settings objects with the old stack of script settings objects.
- Return to the caller.
Some of the algorithms in this specification, for historical reasons, require the user agent to pause while running a task until a condition goal is met. This means running the following steps:
- If any asynchronously-running algorithms are awaiting a stable state, then run their synchronous section and then resume running their asynchronous algorithm. (See the event loop processing model definition above for details.)
- If necessary, update the rendering or user interface of any Document or browsing context to reflect the current state.
- Wait until the condition goal is met. While a user agent has a paused task, the corresponding event loop must not run further tasks, and any script in the currently running task must block. User agents should remain responsive to user input while paused, however, albeit in a reduced capacity since the event loop will not be doing anything.
When a user agent is to obtain the storage mutex as part of running a task, it must run through the following steps:
- If the storage mutex is already owned by this task’s event loop, then abort these steps.
- Otherwise, pause until the storage mutex can be taken by the event loop.
- Take ownership of the storage mutex.
6.1.4.3 Generic task sources
The following task sources are used by a number of mostly unrelated features in this and other specifications.
The DOM manipulation task source
This task source is used for features that react to DOM manipulations, such as things that happen asynchronously when an element is inserted into the document.
The user interaction task source
This task source is used for features that react to user interaction, for example keyboard or mouse input.
Asynchronous events sent in response to user input (e.g. click events) must be fired using tasks queued with the user interaction task source. [DOMEVENTS]
The networking task source
This task source is used for features that trigger in response to network activity.
The history traversal task source
This task source is used to queue calls to history.back() and similar APIs.