[转]How WebKit’s Event Model Works
原文:https://homes.cs.washington.edu/~burg/projects/timelapse/articles/webkit-event-implementation/
First, here are some definitions of major parts of WebKit:
- JavaScriptCore
- The JavaScript execution engine. It has no dependencies on other components.
- WebCore
- The page rendering/layout/event dispatching component. This is the vast majority of the codebase in size and complexity. It depends on JavaScriptCore (JSC). Several portions have different implementations for each platform, such as graphics, sound, network, user input handling, and run loop integration.
- WebKit
- A fairly small layer that makes WebCore easier to embed by exposing a higher-level interface. It depends on all of the above.
- WebKit2
- a more complicated split-process layer for embedding WebKit. It depends on all of the above.
What controls the course of computation?
WebKit2 uses a split process model, where the Web process runs WebCore to handle parsing, layout, rendering, and script running for one web view. The browser/chrome process handles non-rendering tasks such as network communications and niceties for the user, like bookmarks and printing. The browser process communicates with all of its Web processes via inter-process communication (IPC). Essentially, one can view these messages as a queue of events to be handled. I’ll refer to these events as IPC messages.
Occasionally during the course of rendering a page or running a script, WebKit needs to perform (possibly a lot of) computation some time in the future, using timer callbacks. Common uses are implementing JavaScript timers or animations, which must run frequently to fill in many animation frames. I’ll refer to these callbacks as timers.
Timers allow asynchronous computation, and fire in a FIFO fashion: several callbacks with the same timer interval (say, 100ms) will fire in the order that they were registered. But, if an interval for 1s is set immediately after an interval for 10s, the 1s timer should fire first. This is accomplished by using a priority queue to keep track of which timers to fire next. Intervals with less time remaining to completion have greater priority than longer intervals. Among intervals with the same time remaining, those registered earlier have greater priority.
Thus, computation in WebKit is initiated by processing messages on one of two queues:
- Callbacks from the timer priority queue.
- Messages from the Browser process across IPC..
How internal timers are implemented
Periodically, all timers that are due for firing are fired synchronously and evicted from the queue (or re-inserted, for reoccuring timers). This periodic action is performed by a platform-level timer, whose base class is WebCore::SharedTimer. Each platform has its own event loop implementation, so each platform defines its own SharedTimer subclass that hooks into native event loops. The OSX subclass ofSharedTimer (SharedTimerMac), for example, registers a Cocoa CFRunLoopTimer. This is later called periodically by the native event loop, which is invoked inside the WebKit2::RunLoop implementation (RunLoopMac), which is called in the main() method of the Web process.
The shared timer callback is registered via the following code path: ThreadTimers::setSharedTimer(SharedTimer* timer) -> MainThreadSharedTimer->setFiredFunction(ThreadTimers::sharedTimerFired) -> SharedTimer->setFiredFunction(void) -> SharedTimerMac->setSharedTimerFiredFunction(void)
The SharedTimer’s interval is continously adjusted to the interval of the next due timer. This reduces the number of callbacks by SharedTimer to ThreadTimers::sharedTimerFired in cases where few timers are active (or a long ways into the future). When it’s time for a timer to fire, the code path looks something like:
[NSApplication run] (native loop)
-> timerFired()
-> ThreadTimers::sharedTimerFired()
-> threadGlobalData().threadTimers().sharedTimerFiredInternal() [1]
-> WebCore::Timer<WebCore::YourClass>->fired()
Inside of [1] is where eligible timers are looped over and fired, and the SharedTimer interval is possibly adjusted. The gist of routine is to fire events until none are ready to fire or we have exceeded a time limit.
The native run loop fires lots of other native timers and callbacks, as well. At every such point (notably in file IO, streams, networking, and graphics), WebKit includes an implementation for each port/platform, which may add or remove native events from the native RunLoop.
How IPC messages are handled
The Browser process sends messages to each Web process to communicate information such as resource data, user input, window resize, etc. These messages are piped to the Web process, which creates a WorkItem for each message. These work items are queued on the native event loop, and performed in course. In the OSX port, the RunLoop::performWork method is registered as aCFRunLoopSource—-in essence, it is registered as an additional source of events for the event loop. The body of performWork copies the list of WorkItems present upon method entry, works through the copied items, and then returns. Note that new work items may arrive when copied ones are being processed; these will be handled in the next call to performWork. Below is a typical sequence of calls leading from the native event loop through processing the IPC message to calling the respective WebCore handler.
[NSApplication run] (native event loop)
-> RunLoopMac::performWork(void*)
-> RunLoop::performWork()
-> CoreIPC::Connection::dispatchMessages()
-> CoreIPC::Connection::dispatchMessage()
-> WebKit::WebProcess::didReceiveMessage(connection, messageID,
arguments)
-> WebKit::WebPage::didReceiveWebPageMessage(connection, messageId,
arguments)
-> CoreIPC::handleMessage(arguments, WebPageMessageReceiver, targetFn)
-> targetFn(args...)
At the point of targetFn, the message can be handled in several ways. The important thing to note is that once these handlers reach WebCore, they are handled synchronously.
Where do DOM events fit into this picture?
DOM events are the abstraction for event-driven programming in web applications and JavaScript. (TheMugshot paper has a good overview of the DOM event model.) However, DOM events have not yet come into the picture—-where do they originate from?
Most user input DOM events, such as clicks, scroll wheel, and keyboard, are created in response to corresponding IPC messages. In that case, the targetFn above will mediate between the native or browser view of user input and the DOM event standards. This mediation also converts from raw screen coordinates to a DOM target, and excludes some events that should not be reflected into the DOM model as input (for example, clicking on a scrollbar). Here is a typical sequence of calls from IPC targetFn to DOM dispatch as described in the above link:
WebKit::WebPage::mouseEvent(WebMouseEvent)
-> WebKit::handleMouseEvent(WebMouseEvent, Page)
-> WebCore::EventHandler::dispatchMouseEvent(eventType, targetNode,
clickCount, PlatformMouseEvent)
-> Node::dispatchMouseEvent(...)
-> EventDispatcher::dispatchEvent(Node, EventDispatchMediator)
-> MouseEventDispatchMediator::dispatchEvent(EventDispatcher)
-> EventDispatcher::dispatchEvent(Event) // performs event dispatch according to DOM standard.
It is possible for some DOM events to immediately fire other DOM events synchronously. For example, the default event handler for the space or enter keyboard event on the <input type=”submit”> element will typically fire a second DOM “submit” event on the containing <form> element. This can be seen in the body and callers of HTMLFormElement::submitImplicitly. What are the important points?
The top-level event loop is usually defined by the respective WebKit port, such as Cocoa, QT, GTK, etc. Timers internal to WebCore are manually tracked and dispatched by a single native timer that participates in the native run (event) loop. IPC messages are also handled according to the native run loop, and sometimes lead to dispatching DOM user input events. DOM events can potentially be triggered directly by timers internal to WebCore. An example is that animation-related DOM events are triggered by a timer in the AnimationController::animationTimerFired callback. In general though, user input is only triggered by IPC messages.
[转]How WebKit’s Event Model Works的更多相关文章
- This module embeds Lua, via LuaJIT 2.0/2.1, into Nginx and by leveraging Nginx's subrequests, allows the integration of the powerful Lua threads (Lua coroutines) into the Nginx event model.
openresty/lua-nginx-module: Embed the Power of Lua into NGINX HTTP servers https://github.com/openre ...
- 【转向Javascript系列】从setTimeout说事件循环模型
本文首发在alloyteam团队博客,链接地址http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout ...
- JavaScript Interview Questions: Event Delegation and This
David Posin helps you land that next programming position by understanding important JavaScript fund ...
- 事件轮询 event loop
Understanding the node.js event loop The first basic thesis of node.js is that I/O is expensive: So ...
- java event
What is an Event? Change in the state of an object is known as event i.e. event describes the change ...
- Two kinds of item classification model architecture
Introduction: Introduction to Fusing-Probability model: Cause the input has two parts, one is item i ...
- JavaScript 事件对象event
什么是事件对象? 比如当用户单击某个元素的时候,我们给这个元素注册的事件就会触发,该事件的本质就是一个函数,而该函数的形参接收一个event对象. 注:事件通常与函数结合使用,函数不会在事件发生前被执 ...
- Flutter json 2 model with Built Value
Flutter json 2 model with Built Value Flutter中json转换model, 除了手动转之外, 就是利用第三方库做一些代码生成. 流行的库有: json_ser ...
- POI导入导出Excel(HSSF格式,User Model方式)
1.POI说明 Apache POI是Apache软件基金会的开源代码库, POI提供对Microsoft Office格式档案读和写的功能. POI支持的格式: HSSF - 提供读写Microso ...
随机推荐
- Delegate成员变量和Event的区别
上周五有同事问了我一个问题:Delegate和Event有什么区别?具体来说在设计一个类的时候,声明一个事件(Event)和声明一个Delegate类型的成员变量有啥区别. 我的第一反应是没啥区别 ...
- paramiko socket.error: Int or String expected
paramiko socket.error: Int or String expected paramiko的环境: Python 2.6.6 paramiko==1.14.0 正常的paramiko ...
- 宽客的人&&事件映射
看完<宽客>这本书,叙事介绍20世纪华尔街对冲基金.股票.投资者依赖股市从直觉交易数学家的早期演化.物理学家用数学模型开发过程中的交易,这些进入金融数学家.物理学家依靠大数据分析.稍纵即逝 ...
- Swift学习笔记(一)搭配环境以及代码运行成功
原文:Swift学习笔记(一)搭配环境以及代码运行成功 1.Swift是啥? 百度去!度娘告诉你它是苹果最新推出的编程语言,比c,c++,objc要高效简单.能够开发ios,mac相关的app哦!是苹 ...
- printf与++的puzzle
int b = 0; int c = 0; int main(int argc, const char *argv[]) { printf("%d %d %d %d %d",b,b ...
- BAT 特殊符号总结
原文:BAT 特殊符号总结 BAT特殊符号总结,用好特殊符号,利用提高开发效率.^ 转义符 用在特殊符号之前 比如: echo 非常^&批处理 如果不加^ 那么"批处理"将 ...
- 快速构建Windows 8风格应用14-ShareContract概述及原理
原文:快速构建Windows 8风格应用14-ShareContract概述及原理 本篇博文主要介绍Share Contract概述.Share Contract实现原理.实现Share Contra ...
- [译]ava 设计模式之构造器
(文章翻译自Java Design Pattern: Builder) 构造器模式的关键之处在于它使用一步接招一步的流程去构建东西,例如:尽管构建的每一步是不相同的但是每一个产品还是遵循相同的流程. ...
- leetcode[70] Simplify Path
题目的意思是简化一个unix系统的路径.例如: path = "/home/", => "/home"path = "/a/./b/../../ ...
- Apache2.4.x与Apache2.2.x的一些区别
改用Apache2.4一段时间了,一直没发现它和Apache2.2的有什么区别,一些基本配置都是差不多,直到前几天配置虚拟主机是才发现了一些小小的不同 一直以来我都是在htdocs目录下配置虚拟主机的 ...