1、WebKit的JavaScript引擎简介 基于Webkit-r29753,腾讯研究院 无线中心/无线浏览器组 周晓波(xiaobozhou) 2009.11.2,WebKit代码阅读 之:,提纲,Web系统 JavaScript引擎 DOM DOM标准 WebKit的实现 WebKit宿纳JavaScript引擎,Web系统,目的 显示和编辑远程数据 起源 Hypertext系统 + Internet 发展 静态 - 动态 - Ajax 概述 结构和功能,Hypertext系统的例子: emacs的info子系统,格式化文档,Web 服 务 器,因特网,浏览器,数据库,CGI程序,Form,
2、XMLHttpRequest,Web系统 之 概述,服务器端 静态到动态再到webservice的发展 cgi架构的发展 客户端,即浏览器 功能 获取和显示远程数据,提供一定的编辑能力 结构 获取远程数据可能分多次获取 解析理解远程数据的结构(structure) 渲染生成远程数据的“样子” 布局/显示计算远程数据元素的位置并画在屏幕上,提纲,Web系统 JavaScript引擎 DOM DOM标准 WebKit的实现 WebKit宿纳JavaScript引擎,JavaScript引擎,脚本语言 JavaScript引擎 脚本化/脚本嵌入,JavaScript引擎 之 脚本语言,脚本(Scri
3、pt) 指示“演员”行为的“指令”。 脚本语言 指示“解释器”行为的“指令” 理解: 巨大的入口参数 更高层次的库调用 有语法结构的配置文件 ,操作系统内核,脚本解释器,动态库,操作系统内核,可执行程序,动态库,脚本,一般可执行程序和脚本程序的执行过程对比: 前者直接是机器码,后者是文本,需要脚本解释器来解析和执行。脚本和脚本解释器之间的关系: 站在脚本程序的角度来看,脚本解释器就是执行平台; 站在脚本解释器的角度看,脚本程序就是执行时所需的参数。,JavaScript引擎 之 JavaScript引擎(1/),JavaScript ECMAScript的一种“方言” 其他“方言”:JScri
4、pt、ActionScript、DMDScript等 JavaScript引擎 解释执行JavaScript语言 有多种实现:V8、SpiderMonkey、Rihno、TraceMonkey、Squirrel Fish等,EMCAScript标准 中的类型,EMCAScript标准 中内建对象(类),JavaScript引擎 之 JavaScript引擎(2/),区分语言本身和库 JavaScript和DOM document.getElementById() 就像C语言和libc printf C语言通过link和load来真正操作printf JavaScript通过绑定(binding
5、)来操作document.getElementById(),JavaScript引擎 之 JavaScript引擎(3/),WebKit的JavaScript引擎 以下内容基于WebKit-r29753,现在改动很大 基本结构: 对象模型:Type C+类 内存管理:JSCell为内存管理接口 面向对象:JSObject是面向对象机制的实现层(在对象模型中一并阐述),JavaScript引擎 之 JavaScript引擎(3/),语法树 对象模型 类型 对象类型:即继承自JSObject的C+类 其他原生类型 实现机制 属性表 原型链 用C+实现JavaScript引擎 C+类和JavaScr
6、ipt类对应 创建一个JavaScript对象,在底层也创建了一个C+对象 不是严格的,Object type是一种类型, 和整型等一样,x = y + z,document.cookie = stry + strz,=,.,document,cookie,+,stry,strz,PropertyMap,JSObject,_proto,_prop,JSObject,_proto,_prop,PropertyMap,JSObject,_proto,_prop,属性表和原型链 这是C+类的实现,JavaScript引擎 之 JavaScript引擎(3/),举例 var a = A(); aler
7、t( a.p1 ); var b = a.func1(); 原型链的作用 在JavaScript层面实现继承 属性表的作用 存储和操作对象的属性和方法,那类的属性呢? 如static,d()-functionPrototype = new FunctionPrototype(exec);d()-objectPrototype = new ObjectPrototype(exec, d()-functionPrototype);d()-functionPrototype-setPrototype(d()-objectPrototype);d()-arrayPrototype = new Arra
8、yPrototype(exec, d()-objectPrototype);d()-URIErrorConstructor = new NativeErrorImp(exec, d()-functionPrototype, d()-URIErrorPrototype);d()-functionPrototype-put(exec, exec-propertyNames().constructor, d()-functionConstructor, DontEnum);d()-objectPrototype-put(exec, exec-propertyNames().constructor,
9、d()-objectConstructor, DontEnum | DontDelete | ReadOnly);,JavaScript引擎 之 JavaScript引擎(3/),一个问题:如何创建对象 如:var = A(); 全局对象 JSGlobalobject对象 其实就是JavaScript的执行环境,PropertyMap,JSObject,_proto,_prop,JSObject,_proto,_prop,PropertyMap,JSObject,_proto,_prop,JSObject,_proto,_prop,全局对象的属性表里含有 所有类型的创建函数,JavaScrip
10、t引擎 之 JavaScript引擎(4/),内存管理 只管理对象本身 即JavaScript对象,或原生类型(primitive type)的值对应的内存如何申请和释放。 以JSCell为接口,即内存管理只认识JSCell 全局管理,即只有一个内存管理器 关键是生存期的确定 局部/全局作用域 JavaScript对象本身不维护引用关系 通过mark机制来确定不能回收的对象 通过语法关系来确定 通过其绑定的应用程序来确定 显式维护一个(或几个)集合来确定,内存管理器,处于protect集合 里,mark之,处于当前栈中 mark之,其他,不mark,每次new会触发这个操作,还有其他很多地方也
11、会触发,JavaScript引擎 之 JavaScript引擎(4/),总结一下: 属性表成员变量和成员函数 原型链类成员以及父类成员 全局对象携带所有类型的创建函数 内存管理基于mark 如何mark是难点 继承的实现原型链(还有其他形式) JavaScript的继承是程序员的事,JavaScript引擎 之 脚本化/脚本嵌入(1/),脚本引擎 解释执行脚本语言的程序 脚本化 把应用程序作为脚本引擎的一部分 脚本嵌入 把脚本引擎作为应用程序的一个模块 绑定机制 脚本化/脚本嵌入都需要绑定机制来实现,JavaScript引擎 之 脚本化/脚本嵌入(1/),JavaScript引擎的绑定机制(b
12、inding) 基本思想: 通过扩展解释器来扩展JavaScript的功能 属性表和原型链是根本 典型步骤 继承JSObject 定义自己的原型类(也是继承JSObject) 构造自己的属性表 向全局对象的属性表表中注册创建函数 结果 可以var b = MyObj(); 其实就是增加了解释器的内建类,提纲,Web系统 JavaScript引擎 DOM DOM标准 WebKit的实现 WebKit宿纳JavaScript引擎,DOM,DOM标准介绍 WebKit的DOM实现介绍,DOM 之 DOM标准(1/),DOM(Document Object Model) 源起 解析html后得到结构化
13、的信息 如何保存 如何访问 并对外部提供接口(外部主要是JavaScript) 标准化 如果这个信息对外提供的接口很多样化 绑定JavaScript引擎时该如何做? JavaScript程序员如何做? 不只是JavaScript,DOM 之 DOM标准(1/),DOM标准定义了一个数据结构 级别 Level 1,2,3 内容 Core Views Events Style Traversal and Range HTML Load and Save Validation,DOM 之 DOM标准(1/),Core DOMException, ExceptionCode DOMImplementa
14、tion DocumentFragment, Document Node, NodeList, NamedNodeMap CharacterData Attr(继承自Node但是不属于DOM树) Element(继承自Node) Text, Comment,DOM 之 DOM标准(1/),Events 捕捉和冒泡 注册Listener EventTarget, EventListener Event, EventException, EventExceptionCode,DOM 之 DOM标准(1/),Style StyleSheet和CSS StyleSheet StyleSheet, St
15、yleSheetList, MediaList LinkStyle, DocumentStyle CSS CSSStyleSheet, CSSRuleList, CSSRule, CSSStyleRule ,DOM 之 DOM标准(1/),Traversal and Range Traversal NodeIterator, NodeFilter, TreeWalker Range Range,DOM 之 DOM标准(1/),HTML 每一个HTML标签都对应一个继承自Element的类,DOM 之 WebKit的DOM实现,基于WebKit-r38240 DOM的实现 解析 构建DOM树 C
16、SS解析 CSS存储 Render过程 构建Render树,DOM 之 WebKit的DOM实现,解析源文档 有HTMLTokenizer类和HTMLParser类实现 是一个状态机 解析过程会产生子资源的下载任务 可能等待(如JavaScript子资源) 容错是难点 处理的是已经解码好的源文件 构建DOM树,body,form,input-selfclose,form-end,body-end,DOM 之 WebKit的DOM实现,CSS的解析 解析成一条条规则 放到CSSStyleSheet(继承自StyleSheet)中 HTMLStyleElement、HTMLLinkElement中
17、包含了CSSStyleSheet 这些节点(Node)被放到变量Document:m_styleSheetCandidateNodes CSS的存储 解析之后,Document把所有StyleSheet组合起来 RefPtr m_styleSheets;,DOM 之 WebKit的DOM实现,创建Render树 首先通过所有的CSS规则,创建每个元素的RenderStyle RenderStyle描述了这个元素的样式 根据RenderStyle创建RenderObject和元素对应 并把RenderObject构建成树状 RenderObject类族和DOM类族不是一一对应 但是Render树
18、和DOM树是一一对应的,DOM 之 WebKit的DOM实现,提纲,Web系统 JavaScript引擎 DOM DOM标准 WebKit的实现 WebKit宿纳JavaScript引擎,WebKit宿纳JavaScript引擎,宿纳(Host) 即招待,WebKit用DOM来招待JavaScript引擎 基本方法 绑定 方案 绑定只是一种机制 如何绑定才是难点,WebKit宿纳JavaScript引擎,绑定 为每个DOM类在JavaScript引擎中实现JSObject类 Document JSDocument 用脚本生成h/cpp文件 分裂对象模型 DOM中的对象和JavaScript对象
19、对应 例如document.xxx会在全局对象JSDOMWindow的属性表里找“document”,然后找到对应的JSDocument对象 但是大部分DOM对象对应的JavaScript对象是按需创建的,由toJs全局函数来实现,WebKit宿纳JavaScript引擎,JSXxxx类的一般形式 一个指向DOM对象的引用指针m_impl 由静态变量指向的初始属性表 向全局对象注册(其实不需要,因为是static),WebKit宿纳JavaScript引擎,在JavaScript中访问DOM 基本思想:JSXxxx对象的成员变量m_impl 具体过程 语法解析,例如document.appendChild( newnode ) 通过字符串“document”得到JSDocument对象 在其属性表里查找“appendChild”字符串 在JSNode中才找到,WebKit宿纳JavaScript引擎,在DOM中执行JavaScript 通过Eventlistener接口,WebKit宿纳JavaScript引擎,一个例子,总结,DOM标准 WebKit对DOM的实现 JavaScript语法的理解 属性表 原型链 JavaScript引擎的扩充 脚本化 脚本嵌入 WebKit宿纳JavaScript引擎,结束 Q&A,