WebKit 源码调试指南

·
Cover for WebKit 源码调试指南

准备步骤

拉取 WebKit 源码 (如果整体仓库过大,shallow clone 即可)

git clone [email protected]:WebKit/WebKit.git

💡 需要注意的是,WebKit 并不是每个 commit 都一定在某个平台可以编译通过,因此最好根据 Tag 来选择一个已经发布版本的 commit 来进行编译

例如如果需要编译 iOS 的,可以参考各个版本 iOS 中的 WebKit 版本:

Safari 版本iOS 系统版本WebKit Commit SHA1
15.215.2de716213341fb69ca485433834244ae0de02fb03
15.115.1.1ff9adb92d9179a1fddd300aabb6668c1a2ab14e6
15.1
1515.0.26a577b88c820c9744976abfe014ee1089d124150
15.0.1
15.0
14.1.214.8.16b8bcbaee4589e26e97bcb72d526c87432d13340
14.8286902a6bbf9c5053cfccf0a5e9ba81858d96715
14.7.11a96d990c00d74afe807b8cbb99a01d3aee9b010
14.7
14.1.114.6f9201cbe1e7c9984fdcda1eaee63c9d05c5e318e
14.114.5.19ec7053653015cd6ef338238401aa68b99b5eea9
14.55b7748a1c90e9320a8ba011bce9177a600162e88
14.0.314.4.2eb3ba241019dd9a3051782ac667add96e804670c
14.4.1ee23ff460fe47eeba7b8177f599d4ae1acad9fe4
14.41930a636b724417aee30718758977380e1a17acc
14.0.214.38a8595a4cf0646f5700387b303ff7b198c6c0648
14.0.114.2.140746962ad7ea47760e4e36a9bdcc8d6e8b30035
14.2
1414.1132cc44ac1f541e4c729c9138debbd3c77a0559a
14.0.157f5653bc26e0df49fae2b64353f1ab2101eee8c
14.0
13.1.213.7aad0a41ecdca17dd396f40892d08f4f0ce55ebd5
13.6.1
13.6
13.1.113.5.1df1c9b33f49c7ec603491c49836e76a42318bc7c
13.5
13.113.4.18ce9cb98525be3a48f56f2a5dcfba77d91086b57
13.4
13.0.513.3.1e0e5c8297429016745b55545b1454f02e40d83e1
13.0.413.392952ad7158ca6f25f1a63f8a1fb416fec1bf8bb
13.0.313.2.3d14e4c83c74e9694182b4a696ecf3f45b6b31eb1
13.2.2
13.2.1b070e842276e1d9551639700bbc63c738ce57c0e
13.2
13.0.113.1.340c4467f74744ae052fbcf19aa4ad4c17374a78b
13.1.2
13.1.1
13.1de1b4bbe964c471138a3aae9357b669e65c486cc
1313.05a12c04a0d361b7501778a0f172752d340be2795
12.112.2d17ca9c18487274893585275e07c8918da8aea40
1212.1.4a833f886f9bd68c279322104c27498245d5b8dfb
12.1.3
12.1.250bd93f5dcb329ffdd0b77ed3978dfe9f729b573
12.1.1
12.1349ad69a155dd97ffa9f00b3feb75b44c886a319
12.0.13db77fee7fa7da0859a3b6554248ec1ecd4ef078
12.0
1111.4.1266f0468e067e0c2c0e1209313a34bdf5926aa38
11.432424f3f5a4e42bae7472b81bdd81939a1b15e17
11.3.1d81537fc15707555c579e8b4539eb3fdb0b4e495
11.3b8213d462227945fb9ef626834512154a79160e5
11.2.63b82703b553ac28aea8439268a02261dcacdf0ef
11.2.5
11.2.2b99fa459ba06ecb8788cc31ad475572003c5ce42
11.2.13257e06f31019bbdec5036ac93d4301bb38ae95c
11.2
11.1.27b3634daed8681566645dd8d3483a82f0c330f1c
11.1.1
11.1
11.0.3008f2ddae8fe2051d8925bd2fc3662171fa6cc51
11.0.2
11.0.1
11.0
11.0.1-iPhone-X155fff7c3264a12fb299629000cec9438e9a07d8
1010.3.453317847ccebb817a5f66836a0b15d1991b940ca
10.3.3
10.3.2e07767dee09ffcb21fd8fd37de11722160471640
10.3.1d529691c44d95093c643f01e872dca101663ba42
10.3
10.2.17d28968243ac86b7f659bc945c3bc786c75a03fa
10.24e294f84b9b2b5729480aecb46b2024fa012563d
10.1.199cd130ae50c2997291655d18b84c11a928cd6c7
10.1
10.0.313a294fe2453476861b5bf1c088200dc8faab911
10.0.2
10.0.1
10.0
99.3.6f9489655aad3d2b83ed1bb87d19e5144667561fd
9.3.5
9.3.4
9.3.3
9.3.20c275dbbe95eba7b2cdea4bc6dd4eb806fd6c544
9.3.14bb7df4ae990eb3bf373ec0d5bdf6f95ff3e403d
9.3
9.2.14631743b90e9e7a43408643bfdfaf0174a8b61ec
9.24f78901a67f9c54eada232478e7fba9218f19856
9.111b39aa0faab13944f83fca326d012ff391ac4b3

同时因为各个设备的情况都不同,最靠谱的办法还是先去 webkit 的 CI 机器列表 中找一下和自己的机器操作系统版本、Xcode 版本相近的机器最近构建成功的版本号。

例如我发现 这个 build 和我目前的机器配置相近,同时也是我想 build 的 iOS 15 Simulator 的构建成功记录,那我就试试在这个 commit 上构建(不过这里看不到 commit sha1,可以通过 commit msg 来找到对应的 commit)

将如下内容放置在环境变量中(记得替换 WEBKIT_PROJECT 变量

export WEBKIT_PROJECT="$HOME/path-to-webkit"
export PATH="$WEBKIT_PROJECT/Tools/Scripts:$PATH" # 方便调用各种脚本
export PYTHONPATH="$WEBKIT_PROJECT/Tools/Scripts:$PYTHONPATH" # 让 lldb_webkit.py 能够正确运行
export DYLD_FRAMEWORK_PATH="$WEBKIT_PROJECT/WebKitBuild/Debug" # 让 Xcode 或者 Safari 不要用系统的 WebKit 而是我们编译出来的

然后在 ~/.lldbinit 中添加(记得替换 <path-to-webkit>),这个脚本可以帮我们在 Xcode 将一些 C++ 变量以更好的格式进行展示:

command script import <path-to-webkit>/Tools/lldb/lldb_webkit.py

同时将 lldb_webkit.py 代码的 1063 行从 A 替换为 B(应该是现在 WebKit 脚本的 Bug):

def get_child_index(self, name):
    if name == "m_table":
        return self.tableSize()
    else:
        return int(name.lstrip('[').rstrip(']'))

def get_child_index(self, name):
        if name == "m_table" or name == "m_tableForLLDB":
            return self.tableSize()
        else:
            return int(name.lstrip('[').rstrip(']'))

然后编译代码,产物会被放置在 $WEBKIT_PROJECT/WebKitBuild 目录:

build-webkit --debug

如果需要构建 iOS 的,可以选择:

sudo Tools/Scripts/configure-xcode-for-embedded-development
build-webkit --debug --ios-simulator

这个脚本主要会构建如下的几个工程:

  • libwebrtc
  • TestWebKitAPI
  • gtest
  • WebKitTestRunner
  • DumpRenderTree
  • WebKit
  • WebKitLegacy
  • WebCore
  • WebGPU
  • JavaScriptCore
  • WTF
  • bmalloc
  • ANGLE
  • ImageDiff

接下来用 Xcode 打开工程

open WebKit.xcworkspace/

配置一下工程的配置 (File > Workspace Settings… > Advanced… > Custom > Relative to Workspace),让 Xcode 知道我们构建好的产物在 WebKitBuild 目录中:

在顶部的 Run Scheme 中选择 MiniBrowser:

如果有需要,可以将 Tools/MiniBrowser/Mac/SettingsController.m 中的默认地址换成 localhost 地址:

点击运行,开始调试!

调试入口点

  • 创建 Document 对象:DocumentWriter::begin(const URL& urlReference, bool dispatch, Document* ownerDocument)
  • 解析 HTML StyleSheets:resolveStyle
    • Document::resolveStyle(ResolveStyleType type):解析 document 的 style,这个过程中包含了对文档中 StyleSheet 的解析
    • Element::resolveStyle(const RenderStyle* parentStyle:解析单个 Dom 所属的 Style

调试 Tips

明确当前 RenderObject 对应的 Element

可以在 lldb 中打印:

# 打印 id
p ((WebCore::HTMLElement &)this->m_node).m_elementData.m_ptr->m_idForStyleResolution
# 打印 class
p ((WebCore::HTMLElement &)this->m_node).m_elementData.m_ptr->m_classNames.m_data.m_ptr
# 打印 tag
p ((WebCore::HTMLElement &)this->m_node).m_tagName.m_impl.m_ptr->m_localName

Dump Render 树

<path-to-webkit>/WebKitBuild/Debug/DumpRenderTree <url>

就可以打印出来网页中的 Dom 所对应的 Render Object

参考