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

发布时间:2019-07-03 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了从源码一步步学习,Ryan Dahl的Deno实现原理脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

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

  • 不允许将任意本地函数绑定至 V8 当中。
  • 所有系统调用都将通过消息传递完成(PRotobuf 序列化)。
  • 两项原生函数:send 与 recv
  • 这既简化了设计流程,又使得系统更易于审计。

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

V8worker2是Go和V8连接的桥梁

  • 允许从GO程序执行JavaScript
  • 只允许GO和V8之间的消息传递(传统:暴露C++函数作为函数在JavaScript。)
  • 维护一个安全的JS沙箱
  • JS中只允许绑定3个函数:$send() $recv() $print()

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


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

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

可以看出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)))
}

案例演示

  • 实现Js中的console.LOG() 方法
  • Js发送数据给Go
  • Go发送数据给Js
// 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

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

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

参考资料

脚本宝典总结

以上是脚本宝典为你收集整理的从源码一步步学习,Ryan Dahl的Deno实现原理全部内容,希望文章能够帮你解决从源码一步步学习,Ryan Dahl的Deno实现原理所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。