update quickjs, support async by gojs.Start

This commit is contained in:
Star 2024-07-04 11:10:22 +08:00
parent 87639935c6
commit 9e0d17f0a3
4 changed files with 138 additions and 14 deletions

View File

@ -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
View File

@ -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
View File

@ -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 {

View File

@ -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()