update quickjs, support async by gojs.Start
This commit is contained in:
parent
87639935c6
commit
9e0d17f0a3
@ -2,7 +2,7 @@ package gojs
|
||||
|
||||
import (
|
||||
"apigo.cc/apigo/plugin"
|
||||
quickjs "apigo.cc/apigo/qjs"
|
||||
"apigo.cc/apigo/quickjs-go"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ssgo/log"
|
||||
|
12
go.mod
12
go.mod
@ -1,16 +1,16 @@
|
||||
module apigo.cc/apigo/gojs
|
||||
|
||||
go 1.17
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
apigo.cc/apigo/plugin v1.0.2
|
||||
github.com/ssgo/log v1.7.5
|
||||
github.com/ssgo/u v1.7.5
|
||||
apigo.cc/apigo/quickjs-go v0.4.12
|
||||
github.com/ssgo/log v1.7.6
|
||||
github.com/ssgo/u v1.7.6
|
||||
)
|
||||
|
||||
require (
|
||||
apigo.cc/apigo/qjs v0.0.3 // indirect
|
||||
github.com/ssgo/config v1.7.5 // indirect
|
||||
github.com/ssgo/standard v1.7.5 // indirect
|
||||
github.com/ssgo/config v1.7.6 // indirect
|
||||
github.com/ssgo/standard v1.7.6 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
90
gojs.go
90
gojs.go
@ -2,7 +2,7 @@ package gojs
|
||||
|
||||
import (
|
||||
"apigo.cc/apigo/plugin"
|
||||
quickjs "apigo.cc/apigo/qjs"
|
||||
"apigo.cc/apigo/quickjs-go"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ssgo/log"
|
||||
@ -248,7 +248,9 @@ func PreCompile(code, filename string, logger *log.Logger) (*PreCompiledCode, er
|
||||
}
|
||||
return "let " + m[1] + " = " + varName
|
||||
} else {
|
||||
return "throw new Error('import file not found: " + jsFile + " in [" + strings.Join(searchList, ", ") + "]')"
|
||||
// import 未知模块是保留代码
|
||||
//return "throw new Error('import file not found: " + jsFile + " in [" + strings.Join(searchList, ", ") + "]')"
|
||||
return importStr
|
||||
}
|
||||
} else {
|
||||
outErr = err
|
||||
@ -290,6 +292,12 @@ func (rt *JSRuntime) ExecPreCompiled(cc *PreCompiledCode) (jsErr *JSError) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (rt *JSRuntime) StartPreCompiled(cc *PreCompiledCode) (jsErr *JSError) {
|
||||
err := rt.ExecPreCompiled(cc)
|
||||
rt.JsCtx.Loop()
|
||||
return err
|
||||
}
|
||||
|
||||
func (rt *JSRuntime) RunPreCompiled(cc *PreCompiledCode) (out interface{}, jsErr *JSError) {
|
||||
return rt.runPreCompiled(cc, true, "")
|
||||
}
|
||||
@ -304,9 +312,12 @@ func (rt *JSRuntime) runPreCompiled(cc *PreCompiledCode, isClosure bool, setToVa
|
||||
}
|
||||
}
|
||||
for _, plg := range cc.Plugins {
|
||||
rt.JsCtx.Globals().Set(fixPluginId(plg.Id), MakeJsValueForPlugin(rt.GoCtx, plg.Objects, plg.Id, false))
|
||||
plgImpVar := fixPluginId(plg.Id)
|
||||
rt.JsCtx.Globals().Set(plgImpVar, MakeJsValueForPlugin(rt.GoCtx, plg.Objects, plg.Id, false))
|
||||
if plg.JsCode != "" {
|
||||
if result, err := rt.JsCtx.EvalFile(plg.JsCode, plg.Id+".js"); err != nil {
|
||||
jsCode := strings.ReplaceAll(plg.JsCode, "${OBJECT}", plgImpVar)
|
||||
//if result, err := rt.JsCtx.EvalFile(jsCode, plg.Id+".js"); err != nil {
|
||||
if result, err := rt.JsCtx.Eval(jsCode, quickjs.EvalFileName(plg.Id+".js")); err != nil {
|
||||
stack := rt.getJSError(err)
|
||||
rt.logger.Error(err.Error(), "stack", stack)
|
||||
} else {
|
||||
@ -330,7 +341,8 @@ func (rt *JSRuntime) runPreCompiled(cc *PreCompiledCode, isClosure bool, setToVa
|
||||
}
|
||||
}
|
||||
|
||||
if r, err := rt.JsCtx.EvalFile(fixedCode, cc.Filename); err == nil {
|
||||
//if r, err := rt.JsCtx.EvalFile(fixedCode, cc.Filename); err == nil {
|
||||
if r, err := rt.JsCtx.Eval(fixedCode, quickjs.EvalFileName(cc.Filename)); err == nil {
|
||||
result := MakeFromJsValue(r, rt.GoCtx)
|
||||
r.Free()
|
||||
return result, nil
|
||||
@ -473,6 +485,30 @@ func (rt *JSRuntime) ExecAtFile(code string, filename string) (jsErr *JSError) {
|
||||
return jsErr
|
||||
}
|
||||
|
||||
func (rt *JSRuntime) Start(code string) (jsErr *JSError) {
|
||||
err := rt.ExecAt(code, "")
|
||||
rt.JsCtx.Loop()
|
||||
return err
|
||||
}
|
||||
|
||||
func (rt *JSRuntime) StartAt(code string, dir string) (jsErr *JSError) {
|
||||
err := rt.ExecAt(code, dir)
|
||||
rt.JsCtx.Loop()
|
||||
return err
|
||||
}
|
||||
|
||||
func (rt *JSRuntime) StartFile(filename string) (jsErr *JSError) {
|
||||
err := rt.ExecFile(filename)
|
||||
rt.JsCtx.Loop()
|
||||
return err
|
||||
}
|
||||
|
||||
func (rt *JSRuntime) StartAtFile(code string, filename string) (jsErr *JSError) {
|
||||
err := rt.ExecAtFile(code, filename)
|
||||
rt.JsCtx.Loop()
|
||||
return err
|
||||
}
|
||||
|
||||
func (rt *JSRuntime) Run(code string) (out interface{}, jsErr *JSError) {
|
||||
return rt.RunAt(code, "")
|
||||
}
|
||||
@ -758,6 +794,50 @@ func RunPreCompiled(cc *PreCompiledCode, option *RuntimeOption) (out interface{}
|
||||
return rt.RunPreCompiled(cc)
|
||||
}
|
||||
|
||||
func Start(code string, option *RuntimeOption) *JSError {
|
||||
rt := New(option)
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
rt.logger.Error(u.String(err))
|
||||
}
|
||||
rt.Close()
|
||||
}()
|
||||
return rt.Start(code)
|
||||
}
|
||||
|
||||
func StartAt(code, dir string, option *RuntimeOption) *JSError {
|
||||
rt := New(option)
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
rt.logger.Error(u.String(err))
|
||||
}
|
||||
rt.Close()
|
||||
}()
|
||||
return rt.StartAt(code, dir)
|
||||
}
|
||||
|
||||
func StartFile(filename string, option *RuntimeOption) *JSError {
|
||||
rt := New(option)
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
rt.logger.Error(u.String(err))
|
||||
}
|
||||
rt.Close()
|
||||
}()
|
||||
return rt.StartFile(filename)
|
||||
}
|
||||
|
||||
func StartPreCompiled(cc *PreCompiledCode, option *RuntimeOption) *JSError {
|
||||
rt := New(option)
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
rt.logger.Error(u.String(err))
|
||||
}
|
||||
rt.Close()
|
||||
}()
|
||||
return rt.StartPreCompiled(cc)
|
||||
}
|
||||
|
||||
var jsErrorCodeMatcher = regexp.MustCompile(`([\w./\\\-]+):(\d+)`)
|
||||
|
||||
func (rt *JSRuntime) getJSError(err error) string {
|
||||
|
48
gojs_test.go
48
gojs_test.go
@ -266,6 +266,51 @@ func TestCallback(t *testing.T) {
|
||||
rt.Close()
|
||||
}
|
||||
|
||||
func TestInnerModule(t *testing.T) {
|
||||
rt := gojs.New(nil)
|
||||
rt.Exec(`
|
||||
import {loadFile} from "std"
|
||||
import * as os from "os"
|
||||
import console from 'console'
|
||||
globalThis.goMod = loadFile('go.mod')
|
||||
globalThis.platform = os.platform
|
||||
`)
|
||||
goModStr, _ := rt.Run(`
|
||||
return goMod
|
||||
`)
|
||||
platformStr, _ := rt.Run(`
|
||||
return platform
|
||||
`)
|
||||
test(t, "check std.loadFile", strings.Contains(u.String(goModStr), "apigo"), goModStr)
|
||||
test(t, "check os.platform", u.String(platformStr) != "", platformStr)
|
||||
rt.Close()
|
||||
}
|
||||
|
||||
func TestAsync(t *testing.T) {
|
||||
rt := gojs.New(nil)
|
||||
rt.Start(`
|
||||
import console from 'console'
|
||||
let t1 = new Date().getTime()
|
||||
new Promise(resolve => {
|
||||
setTimeout(resolve, 200)
|
||||
}).then(()=>{
|
||||
globalThis.promiseValue = new Date().getTime() - t1
|
||||
})
|
||||
setTimeout(()=>{
|
||||
globalThis.timeoutValue = new Date().getTime() - t1
|
||||
}, 300)
|
||||
`)
|
||||
timeoutValue, _ := rt.Run(`
|
||||
return timeoutValue
|
||||
`)
|
||||
promiseValue, _ := rt.Run(`
|
||||
return promiseValue
|
||||
`)
|
||||
test(t, "check timeoutValue", u.Int(timeoutValue) >= 300 && u.Int(timeoutValue) <= 400, timeoutValue)
|
||||
test(t, "check promiseValue", u.Int(promiseValue) >= 200 && u.Int(promiseValue) <= 300, promiseValue)
|
||||
rt.Close()
|
||||
}
|
||||
|
||||
func BenchmarkEcho(tb *testing.B) {
|
||||
tb.StopTimer()
|
||||
ms1 := runtime.MemStats{}
|
||||
@ -291,13 +336,12 @@ func BenchmarkCallback(tb *testing.B) {
|
||||
runtime.ReadMemStats(&ms1)
|
||||
tb.StartTimer()
|
||||
for i := 0; i < tb.N; i++ {
|
||||
gojs.Run(`
|
||||
gojs.Start(`
|
||||
import obj from 'obj'
|
||||
out = ''
|
||||
obj.echoTimes(function(text){
|
||||
out += text
|
||||
})
|
||||
return out
|
||||
`, nil)
|
||||
}
|
||||
tb.StopTimer()
|
||||
|
Loading…
Reference in New Issue
Block a user