deno
node.js之父Ryan Dahl在一个月前发起了名为deno的项目,项目的初衷是打造一个基于v8引擎的安全的TypeScript运行时 ,同时实现HTML5的基础API。所谓的安全运行时,是将TS代码运行在一个沙盒里,访问受限的文件系统、网络功能,这比较类似于web里的iframe sandbox。
现阶段,deno的变化可谓翻天覆地。Ryan的项目一个月前提供了golang版本的deno简易源码,而如今不仅仅重构了项目,底层语言都切换为c++,接口也做了很大的更新,这源自于社区内热情的讨论,有太多太多的开发者、协作人员提出了太多的优化以及改进意见,这也就导致接下来未来几个月deno仍然会出现大改变,这在后文会提及。现在,我就带领大家进入最初的deno微观世界探索deno最初的设计。
架构
q 本文讲解deno的golang版本,当前最新的deno由于性能问题放弃了golang的实现,但这不影响我们分析deno的原理。未来在七月deno估计会释放出基于Rust的底层特权级实现,性能更优。
q 由于deno涉及之处是为了直接运行TS,因此下文会用TS来代指JS(现阶段TS没有自己的运行时,仍是基于编译为JS在运行在v8)
deno的设计初期来看比较简单,宏观上看包括三部分:deno的go运行时、v8引擎以及连接go运行时和v8的v8worker2库。
go运行时是deno的特权级,它负责deno对系统资源的申请、使用、释放;v8引擎此处不仅仅执行JS代码,同时也负责TypeScript的编译;而v8worker2负责go与v8的全双工通信,通过ArrayBuffer传输数据,传输的协议规范为protobuf。
深入到go运行时里,目前deno对TS层提供了几种能力:Console、fetch、fs、module、timer、stack trace ,虽然有些功能没有提供用户端API,不过golang的接口已完成,扩展很容易。
go运行时
deno在特权级代码执行了3端逻辑:
初始化go运行时环境
初始化TS运行时环境
启动go这一侧的事件循环(该事件循环不同于node的基于libuv的event loop,下文会提到)
初始化go运行时环境
// HOME目录下创建 cache和src目录 createDirs()
// 利用 afero 库创建虚拟fs对象;同时订阅 v8端的 os事件,在go端实现 文件抓取、获取缓存、磁盘I/O,同时返回 proto序列化数据 给v8
InitOS()
// 心跳
InitEcho()
// 接受v8消息,进行 timeout、interval和clear
InitTimers()
// 订阅 fetch 事件,代理服务器。当代理请求结束时,返回两个消息:第一个为状态码;第二个为body体
InitFetch()
// recv为 v8->go 的回调函数,处理v8的消息
worker = v8worker2.New(recv)
// 初始化ts的相关环境,和go端对应
main_js = stringAsset("main.js")
err := worker.Load("/main.js", main_js)
exitOnError(err)
依次执行以下任务:
- 创建缓存目录,存储TS文件编译后的JS文件
- 订阅 os 事件,处理来自v8层的操作,如fs等
- 订阅 timer 事件,处理来自v8的定时器操作
- 订阅 fetch 事件,处理来自v8的http request
- 初始化v8worker2实例,实现go与v8的绑定
- 加载js入口文件main.js,该文件定义了js的全局接口、初始化逻辑和与go运行时通信的方法,等待下一阶段的执行。
初始化js运行时环境
// v8端执行 denoMain函数,在main.ts中定义
deno.Eval("deno_main.js", "denoMain()")
上一步v8已经加载并执行了main.js 文件,现在该执行denoMain方法了。denoMain是在main.js中定义的初始化方法,它定义了deno在js层的API以及v8worker实例,也是开发者密切相关的一层。
关于ts层的逻辑留在下文讲述。
启动事件循环
var resChan = make(chan *BaseMsg, 10) var doneChan = make(chan bool)
var wg sync.WaitGroup
wg.Add(1)
first := true
// In a goroutine, we wait on for all goroutines to complete (for example
// timers). We use this to signal to the main thread to exit.
// wg.Add(1) basically translates to uv_ref, if this was Node.
// wg.Done() basically translates to uv_unref
go func() {
wg.Wait()
doneChan
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com