0%

浏览器JS运行相关

浏览器JS运行相关

前端学习系列,总觉得学着学着就像自己转前端了一样,起因是今天西湖论剑出了一个XSS的难度正无穷的题,后来放了个hint提到了service worker线程,就提到了JavaScript主进程是单线程的,如此这般如此这般。
最后结束了题做不出来前端知识又学了一点点

浏览器基本模型

当前的浏览器多采用多进程模型,开那么四五六七个进程来执行任务,他们分别有Browser Process,Network Process,GPU Process,Render Process等等等等一大堆进程,各司其职完成工作。
Browser Process是主进程,就是控制诸多进程的控制进程,Network Process必然就是网络请求管理进程了,不多说,今天主要分析的就是这个Render Process,它主要进行页面渲染(加特效什么的),脚本执行,事件处理等等

渲染进程

首先明确一点,一般来说一个tab(就是一个标签页),会对应一个渲染进程(如果资源不足可能会导致多个标签页的渲染进程被合并到一个进程里),然后渲染进程里面有各种各样的线程来完成对这一个标签页的渲染,有

GUI渲染进程 主要负责渲染界面,就是HTML CSS之类的
事件触发线程 控制任务队列,管理异步的触发事件
定时触发线程 setTimeout之类的函数的计时器
异步请求线程 就发Ajax请求之类的线程
JavaScript引擎线程,比如Chrome用的v8引擎

总所周知,在构建DOM树的时候,不能js和HTML独立解析,必须是遇到js就去找js引擎解析,因为js可以操作DOM树,所以GUI引擎和JS引擎互斥。
那么问题就来了,如果我这个js脚本超级计算,一直阻塞DOM树解析咋办,用户表示为什么这么卡?

service worker

终于回到我们初始的话题,所谓的service worker就是来解决这个问题的
service worker是一份放在服务器上的js代码,浏览器访问服务器后就会在本地注册(如果浏览器支持这个功能的话)service worker独立工作在worker上下文,因此无权限操作DOM树,但能辅助完成,加速js代码计算,超级计算全都给新开的线程去做,做好了再返回给js主进程即可,并且他和js主进程独立,所以不阻塞,可以减缓js引擎单线程运作导致的页面渲染缓慢
不仅仅是加速js解析,它还能充当一个浏览器与服务器之间的中间件,或者说代理,能够修改用户获取的资源,甚至在离线情况下可以通过缓存来定义页面行为,提升用户的体验(逐渐跑题)

然后这次西湖论剑的题目似乎就是控制了service worker,使用它能控制用户请求资源的能力完成XSS(但是我还完全没懂我怎么控制service worker,打到服务器上去修改注册代码吗?)

service worker也不同于比较古老的Web Worker,web worker只能加速一个tab的内容,而service work可以控制其注册的路径下所有文件的内容,如果service worker的作用域是网站的根目录,那么你浏览这个网站的所有访问都可以受到service work的帮助(如果service worker被日了也同理能控制所有你请求的资源)但是我还是没懂那个题怎么整,有可能这里有说错的,等wp出了再补

JS EventLoop

都学到这了,就顺便看了一下JS的执行过程,单线程执行的JS使用EventLoop的形式来执行命令,分为同步任务和异步任务,同步任务就按顺序堆等着主进程一个个来做,形成一个执行栈

而JS还有setTimeout之类的函数,在时间到了之后执行回调函数,就是异步任务。因为JS主进程已经忙的自顾不暇了,加上自身是阻塞的单线程,完全没时间管这些,所以这些异步事件还需要一个事件触发线程来管理,事件触发线程管理一个任务队列,当符合条件的事情触发的时候就把对应处理事件推进队尾,等待触发
而JS单线程慢慢跑,所以执行栈上的东西没有被执行完的话,任务队列里的任务是不会被处理的,所以我们看看这个代码

setTimeout(function(){
    console.log('hello!');
}, 0);

console.log('begin');

setTimeout填了个0,意思是马上执行console.log(‘hello!’),感觉应该是显示出hello再输出begin,然而事实并非如此,因为这就是触发了一个异步事件,丢给定时触发线程和时间触发线程去做了,就算是立即执行,也是立即给你推进任务队列,而执行栈上顺序执行的事情还没做完,我begin还没输出,轮不到你任务队列,所以就算timeout是0,你也没办法立即执行
当然其实还有一个小小的点,W3C的规定中小于4ms的间隔被认为是4ms,但是就算间隔真的是0ms,也是会遵循这个执行规则来的
EventLoop就算反复在执行栈和任务队列里面循环,把任务一个个的放进任务池里一个个顺序执行,单线程啊单线程

挖的坑

异步执行的相关内容还有Promise,没学,开始挖坑待填
还突然看到人提到了service work能不能辅助当前窗口下非同源的iframe(我听不懂),前两天AA也和我说过iframe同源策略什么的问题,太复杂了我不会

参考链接

图蛮多的挺可爱的浏览器工作原理讲解
讲的超级清楚的好文章
service worker的MDN文档