zoukankan      html  css  js  c++  java
  • goja 支持es6的一种方法

    goja 对于es6 的module 模式是不支持的,但是我们可以通过扩展模式支持

    基本原理

    k6 是利用了goja 的js 能力,但是为了支持es6,使用了babel (standalone),同时为了方便扩展ls 的能力,使用了core.js
    同时利用了js可以直接转换为golang 方法的模式,直接使用了golang 方法进行es6 编译处理

    • 核心代码
      使用babel 的transform 方法,转换es6 为es6,同时暴露为一个golang 方法
     
    func newBabel() (*babel, error) {
        var err error
        once.Do(func() {
            conf := rice.Config{
                LocateOrder: []rice.LocateMethod{rice.LocateEmbedded},
            }
            babelSrc := conf.MustFindBox("lib").MustString("babel.min.js")
            vm := goja.New()
            if _, err = vm.RunString(babelSrc); err != nil {
                return
            }
            this := vm.Get("Babel")
            bObj := this.ToObject(vm)
            globalBabel = &babel{vm: vm, this: this}
            if err = vm.ExportTo(bObj.Get("transform"), &globalBabel.transform); err != nil {
                return
            }
        })
        return globalBabel, err
    }

    globalBabel.transform 的定义
    使用了goja 的Callable

     
    transform goja.Callable
    • 进行es6代码编译处理
    func (b *babel) Transform(logger logrus.FieldLogger, src, filename string) (string, *SourceMap, error) {
        b.mutex.Lock()
        defer b.mutex.Unlock()
        opts := make(map[string]interface{})
        for k, v := range DefaultOpts {
            opts[k] = v
        }
        opts["filename"] = filename
        startTime := time.Now()
        v, err := b.transform(b.this, b.vm.ToValue(src), b.vm.ToValue(opts))
        if err != nil {
            return "", nil, err
        }
        logger.WithField("t", time.Since(startTime)).Debug("Babel: Transformed")
        vO := v.ToObject(b.vm)
        var code string
        if err = b.vm.ExportTo(vO.Get("code"), &code); err != nil {
            return code, nil, err
        }
        var rawMap map[string]interface{}
        if err = b.vm.ExportTo(vO.Get("map"), &rawMap); err != nil {
            return code, nil, err
        }
        var srcMap SourceMap
        if err = mapstructure.Decode(rawMap, &srcMap); err != nil {
            return code, &srcMap, err
        }
        return code, &srcMap, err
    }

    一个参考集成babel 的demo

    • 参考代码
    package main
    import (
        "demoapp-goja/pkg"
        "log"
        "github.com/dop251/goja"
    )
    const (
        bablename  = "node_modules/babel.min.js"
        corejsname = "node_modules/index.js"
        demomodule = "node_modules/app.js"
    )
    var convert func(string) string
    var jsCompilerVM *goja.Runtime = goja.New()
    func main() {
        jsCompilerVM = goja.New()
        // 使用go-bindata
        bableContent, _ := pkg.Asset(bablename)
        corejsContent, _ := pkg.Asset(corejsname)
        mydemomodule, _ := pkg.Asset(demomodule)
        corejs, _ := goja.Compile(corejsname, string(corejsContent), false)
        bable, _ := goja.Compile(bablename, string(bableContent), false)
         // 预加载babel 以及core-js
        jsCompilerVM.RunProgram(bable)
        jsCompilerVM.RunProgram(corejs)
       // es6 编译es5 转换为golang 代码
        jsCompilerVM.RunString(`var convert = function(es6code) {
            return Babel.transform(es6code, { presets: ['env'] }).code;
           }
       `)
        err := jsCompilerVM.ExportTo(jsCompilerVM.Get("convert"), &convert)
        if err != nil {
            panic(err)
        }
        // 调用转换
        log.Println(convert(string(mydemomodule)))
    }
     

    node_modules/app.js 内容

    import rong from "./rong.js"
    var demo = new rong("dalong",222)
    console.log(demo.printInfo())

    效果

    说明

    实践方法参考自k6一个很不错的基于golang 开发的压力测试工具,k6集成goja js 引擎还是比较巧妙的,后边说明下方法

    参考资料

    https://github.com/loadimpact/k6/blob/master/js/lib/lib.go
    https://github.com/loadimpact/k6/blob/master/js/compiler/compiler.go#L85
    https://github.com/dop251/goja
    https://github.com/dop251/goja/blob/master/runtime.go#L2017
    https://github.com/loadimpact/k6/blob/master/js/compiler/compiler.go#L116
    https://k6.io/docs/using-k6/modules

  • 相关阅读:
    P1149 火柴棒等式
    SpringMVC之reset风格和form表单格式的curd
    SpringMVC之转发重定向
    文件下载
    文件上传
    数据库分页
    使用代理创建连接池 proxyPool
    Proxy 示例
    Proxy基础---------获取collection接口的构造跟方法
    javaBean中 字符串 转 date 类型转换
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/14232784.html
Copyright © 2011-2022 走看看