原文: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的更多相关文章

  1. 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 ...

  2. 【转向Javascript系列】从setTimeout说事件循环模型

    本文首发在alloyteam团队博客,链接地址http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout ...

  3. JavaScript Interview Questions: Event Delegation and This

    David Posin helps you land that next programming position by understanding important JavaScript fund ...

  4. 事件轮询 event loop

    Understanding the node.js event loop The first basic thesis of node.js is that I/O is expensive: So ...

  5. java event

    What is an Event? Change in the state of an object is known as event i.e. event describes the change ...

  6. Two kinds of item classification model architecture

    Introduction: Introduction to Fusing-Probability model: Cause the input has two parts, one is item i ...

  7. JavaScript 事件对象event

    什么是事件对象? 比如当用户单击某个元素的时候,我们给这个元素注册的事件就会触发,该事件的本质就是一个函数,而该函数的形参接收一个event对象. 注:事件通常与函数结合使用,函数不会在事件发生前被执 ...

  8. Flutter json 2 model with Built Value

    Flutter json 2 model with Built Value Flutter中json转换model, 除了手动转之外, 就是利用第三方库做一些代码生成. 流行的库有: json_ser ...

  9. POI导入导出Excel(HSSF格式,User Model方式)

    1.POI说明 Apache POI是Apache软件基金会的开源代码库, POI提供对Microsoft Office格式档案读和写的功能. POI支持的格式: HSSF - 提供读写Microso ...

随机推荐

  1. Instruments-Automation: 通过命令行执行测试用例

    为了实现该脚本的自己主动定时执行.我们需要开始在命令行和脚本,详细代码如下所示的: instruments -t /Applications/Xcode.app/Contents/Applicatio ...

  2. python_random随机

    在数据清洗,评估 ,抽验等等过程中,经常有这样的应用场景 : 需要在一个大的数据集合中随机出来样本,进行人工评估.为了保证足够随机,借助脚本来实现. 下面一个脚本  ,用于应对这种应用场景. 使用方法 ...

  3. Java 递归算法

    其基本思路是递归算法设计:对于一个复杂的问题,原问题分为几个子问题相似相对简单.继续下去,直到孩子可以简单地解决问题,这是导出复发,因此,有复发的原始问题已经解决. 关键是要抓住: (1)递归出口 ( ...

  4. 2440裸 Delay(); 和 while(!(rUTRSTAT0 &amp; 0x2)); 问题

    前两天写RTC中断 使用串行输出 它发现,该方案将while(!(rUTRSTAT0 & 0x2));走不出的情况.的 解决方法: main函数添加: U32 mpll_val = 0,con ...

  5. hdu 4864 Task(贪婪啊)

    主题链接:pid=4864">http://acm.hdu.edu.cn/showproblem.php?pid=4864 Task Time Limit: 4000/2000 MS ...

  6. ajax——client访问webservice基本用法

    学前aps.net当我学会了使用服务器端的访问webservice方法,然后实现一个样本:web server模拟网上购物,今天学习asp.net ajax的时候学习到了client直接訪问webse ...

  7. 搭建一个三台服务器的Memcached集群

    关于memcached的基础知识可以查看博客其他博文,这里只记录了搭建的过程,谢谢! 1.分别在三台服务器上安装Memcached并启动 第一.由于memcached是基于libevent的事件处理, ...

  8. 多线程编程 (2) -NSOperation

    一.NSInvocationOperation 二.NSBlockOperation 三.NSOperation的其他用法 四.自定义NSOperation 1.上一讲简单介绍了NSThread的使用 ...

  9. 多线程编程 (1) -NSThread

    每个iOS应用程序都有个专门用来更新显示UI界面.处理用户触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来极坏的用户体验.一般的解决方案就是将那 ...

  10. 1.cocos2dx它Menu(CCMenuItemFont,CCMenuItemImage,CCMenuItemLabel,CCMenuItemSprite,CCMenuItemToggle)

     CCMenu 基本结构 CCMenu继承自CCLayer,本质是一个容器.须要被addChild到父类中去. CCMenuItem是菜单项,它有例如以下子类: CCMenuItemFont;CC ...