从Chrome源码看JavaScript的执行流程(三)调试

注:这一段是我调试过程中的记录,包括如何找到关键函数,如何理解程序流程,想看结论的可以跳过这一段

打一个断点

打开chromium,然后xcode去attach返回的pid
可以看到在渲染之前断了下来,但是在渲染开始到构建DOM还需要经过许多的操作,我们在开始构建DOM的地方打个断点:

再次打开chromium,发现断到了

此时在左侧的crrendermain队列可以看到chromium在开启到这一步经过了哪些步骤
可以看到回到调用commitData的部分:

再往上一个函数,调用finishedloading的函数

然后正式进入loading部分:

但是这里maybbeloadempty为真,直接返回了,然后再次进入一个检查frame, owner的函数

进到了一个这里:

奇怪的函数:

额,然后到这里:

我用continue之后再次进入了commitdata函数,也就是说,这个函数被调用了两次?
可能是第一次调用进行初始化,然后再次回到commitData,这里发现之前的request的url是true了,应该是进行了一次初始化
到了这个函数:

可能就是渲染的入口点,给这里打个断点
再次重新调试发现进入了两次appendbybtes的函数,并且第一次的时候,bybtes参数为null
第二次进入函数时,bytes参数为html文件源码
之后进入了

data也为源码
再往后进入这里:

参数里出现了p_body的指针,但是里面还是空的
找到一个貌似是DOM树解析的主函数:

这里下个断点试试,有点晕…
如果想要看chromium从渲染开始到DOM树的构建之间发生了什么,可以看下这个
https://zhuanlan.zhihu.com/p/24911872
这里还是主要关注在DOM树构建和操作的时候,如何处理javascript
即主要看html_tree_builder.cc中的东西
遇到了一个需要理解的东西
atomicHTMLtoken
DOM树中的每一个标签和内容都会被定义成这个token,然后交给treebuilder里对应的tokenprocess函数处理
直接先看一看只有一个script标签的页面的解析吧

出现了一个问题,在这个页面下,第一个token的type竟然是endOfFile???
发现了一个有趣的地方:html_tree_builder.cc

注意中间的 tree_.Flush 如果process的是character,即不是标签的话,就不会进行 flush 操作
在process一个token之后会进入一系列的操作,值得注意的是这一个地方:
html_document_parse.cc

再一次出现了flush
同时看到下面的isStopped()函数,他的定义是

这可能与我们要找的东西有关
看一下IsWaitingForScripts这个函数

从上面的注释可以看到,是在解析的时候,会进入js runner,所以逻辑可能是在ProcessEndTag里,所以可以注意一下这个函数
如何查看token的信息?lldb里用expr执行token的函数,例如expr token->GetType()
一个token的函数和属性有:

在atomicHTMLtoken的定义里还有一个Show函数,但是调用这个函数没有打印(突然发现,这个函数将输出打印在了命令行里而不是在lldb里,那么就可以用这个函数来观察token了)

往后执行,执行到html_document_parser.cc里的

时JS执行,所以这一段逻辑就是判断DOM树解析时的JS执行的
JS执行完之后会再次进入ValidateSpeculations这个函数

好像会反复检查是否有script暂停了解析,然后会再次进入bind_inernal,意思是再次创建一遍渲染进程然后接着解析页面?

发表评论