Go使用otto调用JS函数报错:引入Buffer模块后报Unexpected reserved word
问题原因
- 报错指向
import关键字,核心原因是otto库仅兼容ES5语法规范,不支持ES6及以上的ES Module模块语法,import属于ES6新增的保留字,otto解析时无法识别,直接抛出保留字异常。 - 额外注意:即使删掉
import语句,代码也会报错,因为Buffer是Node.js内置API,otto的JS运行时没有内置任何Node.js核心模块,无法直接识别Buffer对象。
解决方案
可以根据你的业务需求任选以下一种方案处理:
方案1:移除模块导入,改用ES5兼容实现
如果你的Buffer使用逻辑比较简单,可以直接替换为otto支持的原生ES5 API,不需要引入额外依赖,修改后的secret.js示例如下:
// 删掉import语句,直接用ES5兼容API实现逻辑 var Q = function(e) { // 示例:如果要做base64编码,直接用otto原生支持的btoa方法 return btoa("asdfl" + e) };
如果需要用到二进制处理能力,也可以直接用ES5原生支持的Uint8Array等类型实现。
方案2:注入Buffer实现到otto运行时
可以在Go侧直接给otto虚拟机注入Buffer构造函数,在Go层实现对应的编码能力,无需修改JS代码的核心逻辑:
修改后的main.go示例:
import "encoding/base64" func main() { jsFile := "./secret.js" bytes, err := ioutil.ReadFile(jsFile) if err != nil { panic(err) } vm := otto.New() // 提前注入Buffer实现到JS运行时 vm.Set("Buffer", func(call otto.FunctionCall) otto.Value { input, _ := call.Argument(0).ToString() // 这里在Go层实现你需要的Buffer逻辑,示例为转base64 res := base64.StdEncoding.EncodeToString([]byte(input)) val, _ := vm.ToValue(res) return val }) _, err = vm.Run(string(bytes)) if err != nil { panic(err) } enc, err := vm.Call("Q", nil, "123456") if err != nil { panic(err) } fmt.Println(enc.String()) }
对应的secret.js直接删掉第一行的import语句即可。
方案3:打包JS为单文件ES5代码
如果你的JS依赖比较多,需要用Node.js模块,可以用browserify、webpack等打包工具,把所有依赖打包为单文件的ES5兼容代码,自动剔除import/export等ES6语法,打包后的文件可以直接在otto中运行。
内容的提问来源于stack exchange,提问作者xiun xiao
相关产品推荐
相关产品推荐

