Deno 原理详解,让我们一起从源码分析开始

2018-06-05 14:05:19 +08:00
 vtexhtllo1

Node 之父 ry:在“ Node 中的设计错误”演讲中表示:

这几点很大程度上体现出了 node 和 deno 在设计本质上的区别,同时这几点体现了 deno 的安全性(利用 JavaScript 本身即为安全沙箱这一事实)

V8worker2 是 Go 和 V8 连接的桥梁

从图中可以清晰的看出,V8worker2 是 v8 和 Go 之间实现调用的核心组件

可以看出 V8worker2 是通过 binding C++ 模块进行绑定 V8,bingding 暴露了基础操作方法:v8_init() 、worker_load()、worker_send_bytes()、worker_dispose()...提供给 GO 进行调用

//binding.h
const char* worker_version();
void worker_set_flags(int* argc, char** argv);
void v8_init();
worker* worker_new(int table_index);
int worker_load(worker* w, char* name_s, char* source_s);
const char* worker_last_exception(worker* w);
int worker_send_bytes(worker* w, void* data, size_t len);
void worker_dispose(worker* w);
void worker_terminate_execution(worker* w);

通过 Golang 的 GC 提供的 CGO 模块调用 C 语言暴露的方法,就可以实现 GO 和 V8 之间的通信了:

  1. 创建一个实例:v8worker2.New(ReceiveMessageCallback)
  2. 加载执行 JS:worker.Load(scriptName,codeString)
// worker.go
package v8worker2

import "C"
...

func recvCb(buf unsafe.Pointer, buflen C.int, index workerTableIndex) C.buf {
    ...
}

func New(cb ReceiveMessageCallback) *Worker {
    ...
	initV8Once.Do(func() {
		C.v8_init()
	})
}

func (w *Worker) Load(scriptName string, code string) error {
    ...
	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)))
}

案例演示

// hello.go
package main

import (
	"fmt"

	"github.com/ry/v8worker2"
)

func main() {
	worker := v8worker2.New(recv)

	// 实现 JS 的 console.log 方法
	err := worker.Load("hello.js", `
		this["console"] = {
			log(...args) {
				V8Worker2.print(args)
			}
		};
		console.log("Hello World");
	`)

	if err != nil {
		fmt.Println(err)
	}

	// 发送数据给 GO
	err = worker.Load("sendData.js", `
		V8Worker2.send(new ArrayBuffer(5))
	`)
	if err != nil {
		fmt.Println(err)
	}

	// 发送数据给 JS
	err = worker.Load("recvData.js", `
		V8Worker2.recv(function(msg) {
			const len =msg.byteLength;
			console.log("recv data from go,length: "+len);
		});
	`)
	if err != nil {
		fmt.Println(err)
	}
	err = worker.SendBytes([]byte("abcd"))

}

func recv(buf []byte) []byte {
	fmt.Println("recv data from js,length:", len(buf))
	return nil
}

在控制台运行: go run hello.go

需要运行测试代码,可以直接访问我的 github:deno 案例源码

参考资料

4553 次点击
所在节点    Node.js
2 条回复
nine99
2018-06-05 23:53:54 +08:00
不错的资料
jziwenchen
2018-06-06 16:58:09 +08:00
加了这么多东西 性能不会很差吗 ?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/460560

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX