当前位置: 首页 > 后端技术 > Node.js

从源码一步步学习,RyanDahl的Deno实现原理

时间:2023-04-03 20:33:20 Node.js

Node之父ry:在“DesignErrorinNode”演讲中,他说:不允许绑定任何本地函数到V8。所有系统调用都将通过消息传递(protobuf序列化)完成。两个本机函数:发送和接收。这既简化了设计过程,又使系统更易于审计。这些点很大程度上反映了node和deno在设计上的本质区别。同时,这几点体现了deno的安全性(利用了JavaScript本身就是一个安全沙箱的事实)。V8worker2是Go和V8Bridges之间的连接,它允许从GO程序执行JavaScript,只允许在GO和V8之间传递消息(遗留:将C++函数公开为JavaScript中的函数。)维护一个安全的JS沙箱JS中只允许绑定3个函数:$send()$recv()$print()从图中可以清楚的看出V8worker2是实现v8与GoIt之间调用的核心从组件可以看出,V8worker2是通过bindingC++模块来绑定V8的。Binding暴露了基本的操作方法:$v8_init(),$worker_load(),$worker_send_bytes(),$worker_dispose()...提供给GO调用//binding.hconstchar*worker_version();voidworker_set_flags(int*argc,char**argv);voidv8_init();worker*worker_new(inttable_index);intworker_load(worker*w,char*name_s,char*source_s);constchar*worker_last_exception(worker*w);intworker_send_bytes(worker*w,void*data,size_tlen);voidworker_dispose(worker*w);voidworker_terminate_execution(worker*w);Golang的GC提供的CGO模块调用C语言暴露的方法,实现GO与V8的通信:创建实例:v8worker2.New(ReceiveMessageCallback)加载执行JS:worker.Load(scriptName,codeString)//worker.gopackagev8worker2import"C"...funcrecvCb(bufunsafe.Pointer,buflenC.int,indexworkerTableIndex)C.buf{...}funcNew(cbReceiveMessageCallback)*Worker{...initV8Once.Do(func(){C.v8_init()})}函数(w*Worker)Load(scriptNamestring,codestring)错误{...r:=C.worker_load(w.worker.cWorker,scriptName_s,code_s)...}func(w*Worker)SendBytes(msg[]byte)error{...r:=C.worker_send_bytes(w.worker.cWorker,msg_p,C.size_t(len(msg)))}案例展示Js中console.log()方法的实现Js向GoGo发送数据向Js发送数据//hello.gopackagemainimport("fmt""github.com/ry/v8worker2")funcmain(){worker:=v8worker2.New(recv)//实现JSconsole.log方法err:=worker.Load("hello.js",`this["console"]={log(...args){V8Worker2.print(args)}};console.log("HelloWorld");`)如果出错!=nil{fmt.Println(err)}//发送数据到GOerr=worker.Load("sendData.js",`V8Worker2.send(newArrayBuffer(5))`)iferr!=nil{fmt.Println(err)}//向JS发送数据err=worker.Load("recvData.js",`V8Worker2.recv(function(msg){constlen=msg.byteLength;console.log("recvdatafromgo,length:"+len);});`)iferr!=nil{fmt.Println(err)}err=worker.SendBytes([]byte("abcd"))}funcrecv(buf[]byte)[]byte{fmt.Println("接收数据fromjs,length:",len(buf))returnnil}在控制台运行:gorunhello.go需要运行测试代码,可以直接访问我的github:deno案例源码参考RyanDahl在v8worker上的演讲PPTjustjavac:Deno不是下一代Node.jsv8worker2github