add GoErr

This commit is contained in:
Star 2025-07-19 10:09:09 +08:00
parent 7bae8c77a2
commit 1a7cdbad3f
5 changed files with 81 additions and 33 deletions

View File

@ -5,6 +5,7 @@ import (
"fmt"
"reflect"
"apigo.cc/gojs/common"
"apigo.cc/gojs/goja"
"github.com/ssgo/u"
)
@ -240,7 +241,7 @@ func go2js(in any, n int) any {
// 抛出异常
if err, ok := outValue.Interface().(error); ok {
panic(vm.NewGoError(err))
} else if err, ok := outValue.Interface().(*u.Err); ok {
} else if err, ok := outValue.Interface().(*common.GoErr); ok {
panic(vm.NewGoError(err))
} else {
panic(vm.NewGoError(errors.New(u.String(outValue.Interface()))))

10
common/goerr.go Normal file
View File

@ -0,0 +1,10 @@
package common
type GoErr struct {
Message string
Stack []string
}
func (e *GoErr) Error() string {
return e.Message
}

2
go.mod
View File

@ -8,7 +8,7 @@ require (
github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a
github.com/ssgo/log v1.7.7
github.com/ssgo/tool v0.4.29
github.com/ssgo/u v1.7.19
github.com/ssgo/u v1.7.21
golang.org/x/net v0.41.0
golang.org/x/text v0.26.0
)

View File

@ -20,6 +20,7 @@ import (
"github.com/ssgo/u"
"golang.org/x/text/collate"
"apigo.cc/gojs/common"
js_ast "apigo.cc/gojs/goja/ast"
"apigo.cc/gojs/goja/file"
"apigo.cc/gojs/goja/parser"
@ -554,7 +555,7 @@ func (r *Runtime) NewTypeError(args ...interface{}) *Object {
func (r *Runtime) NewGoError(err error) *Object {
// 打印Go代码的调用栈
callStacks := make([]string, 0)
if err, ok := err.(*u.Err); ok && err.Stack != nil {
if err, ok := err.(*common.GoErr); ok && err.Stack != nil {
for _, stack := range err.Stack {
if strings.Contains(stack, "/goja/") {
continue

96
gojs.go
View File

@ -8,11 +8,13 @@ import (
"os/signal"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
"syscall"
"time"
"apigo.cc/gojs/common"
"apigo.cc/gojs/goja"
"apigo.cc/gojs/goja_nodejs/require"
"github.com/ssgo/log"
@ -48,7 +50,7 @@ var modulesLock = sync.RWMutex{}
var runInMains = []func(){}
var runInMainsLock = sync.RWMutex{}
type Error struct {
type JsError struct {
Message string
Stack []string
fullMessage string
@ -56,31 +58,31 @@ type Error struct {
exceprion *goja.Exception
}
func (e *Error) Error() string {
func (e *JsError) Error() string {
return e.fullMessage
}
func (e *Error) GetError() error {
func (e *JsError) GetError() error {
return e.err
}
func (e *Error) GetException() error {
func (e *JsError) GetException() error {
return e.exceprion
}
func GetError(err error) *Error {
func GetJsError(err error) *JsError {
if err == nil {
return nil
}
return MakeError(err).(*Error)
return MakeJsError(err).(*JsError)
}
func MakeError(err error) error {
func MakeJsError(err error) error {
if err == nil {
return nil
}
var newErr *Error
if gojsErr, ok := err.(*Error); ok {
var newErr *JsError
if gojsErr, ok := err.(*JsError); ok {
newErr = gojsErr
} else if gojaErr, ok := err.(*goja.Exception); ok {
stack := make([]string, len(gojaErr.Stack()))
@ -88,16 +90,50 @@ func MakeError(err error) error {
stack[i] = fmt.Sprintf("%s @%s", v.Position().String(), v.FuncName())
}
msg, fullMsg, stack1 := parseMessageAndStack(gojaErr.Value().String(), stack)
newErr = &Error{Message: msg, fullMessage: fullMsg, Stack: stack1, err: err, exceprion: gojaErr}
newErr = &JsError{Message: msg, fullMessage: fullMsg, Stack: stack1, err: err, exceprion: gojaErr}
} else {
msg, fullMsg, stack := parseMessageAndStack(err.Error(), []string{})
newErr = &Error{Message: msg, fullMessage: fullMsg, Stack: stack, err: err, exceprion: nil}
newErr = &JsError{Message: msg, fullMessage: fullMsg, Stack: stack, err: err, exceprion: nil}
}
// newErr.Message = strings.ReplaceAll(newErr.Message, "GoError: ", "")
newErr.fullMessage = strings.ReplaceAll(newErr.fullMessage, "GoError: ", "")
return newErr
}
func Errf(format string, args ...any) *common.GoErr {
return Err(fmt.Sprintf(format, args...))
}
func Err(err any) *common.GoErr {
errStr := ""
if e, ok := err.(error); ok {
errStr = e.Error()
} else {
errStr = u.String(err)
}
callStacks := make([]string, 0)
for i := 1; i < 50; i++ {
_, file, line, ok := runtime.Caller(i)
if !ok {
break
}
if strings.Contains(file, "/go/src/") {
continue
}
if strings.Contains(file, "/ssgo/log") {
continue
}
if strings.Contains(file, "/ssgo") {
file = "**" + file[strings.LastIndex(file, "/ssgo"):]
}
callStacks = append(callStacks, fmt.Sprintf("%s:%d", file, line))
}
return &common.GoErr{
Message: errStr,
Stack: callStacks,
}
}
func parseMessageAndStack(msg string, stack []string) (string, string, []string) {
if strings.Contains(msg, "|:|") {
a := strings.Split(msg, "|:|")
@ -241,7 +277,7 @@ func RunFile(file string, args ...any) (any, error) {
if code, err := u.ReadFile(file); err == nil {
return Run(code, file, args...)
} else {
return nil, MakeError(err)
return nil, MakeJsError(err)
}
}
@ -252,7 +288,7 @@ func Run(code string, refFile string, args ...any) (any, error) {
if err == nil {
r, err = rt.RunMain(args...)
}
return r, MakeError(err)
return r, MakeJsError(err)
}
func RunProgram(prg *Program, args ...any) (any, error) {
@ -262,14 +298,14 @@ func RunProgram(prg *Program, args ...any) (any, error) {
if err == nil {
r, err = rt.RunMain(args...)
}
return r, MakeError(err)
return r, MakeJsError(err)
}
func CompileFile(file string) (*Program, error) {
if code, err := u.ReadFile(file); err == nil {
return CompileMain(code, file)
} else {
return nil, MakeError(err)
return nil, MakeJsError(err)
}
}
@ -279,13 +315,13 @@ func CompileMain(code string, refFile string) (*Program, error) {
code = "function main(...Args){" + code + "}"
}
p, err := goja.Compile(refFile, code, false)
return &Program{prg: p, imports: imports, startFile: refFile}, MakeError(err)
return &Program{prg: p, imports: imports, startFile: refFile}, MakeJsError(err)
}
func CompileCode(code string, refFile string) (*Program, error) {
imports := makeImports(&code)
p, err := goja.Compile(refFile, code, false)
return &Program{prg: p, imports: imports, startFile: refFile}, MakeError(err)
return &Program{prg: p, imports: imports, startFile: refFile}, MakeJsError(err)
}
var importModMatcher = regexp.MustCompile(`(?im)^\s*import\s+(.+?)\s+from\s+['"](.+?)['"]`)
@ -369,7 +405,7 @@ func (rt *Runtime) requireMod(modName, realModName string, inVM bool) error {
rt.unlock()
}
if err != nil {
return MakeError(err)
return MakeJsError(err)
}
rt.required[modName] = true
}
@ -401,7 +437,7 @@ func (rt *Runtime) requireAllMod() error {
}
rt.unlock()
if err != nil {
return MakeError(err)
return MakeJsError(err)
}
rt.required[modName] = true
}
@ -568,7 +604,7 @@ func (rt *Runtime) StartFromCode(code, refFile string) error {
_, err := rt.SafeRunScript(rt.file, rt.code)
rt.unlock()
if err != nil {
return MakeError(err)
return MakeJsError(err)
} else {
rt.started = true
return nil
@ -580,7 +616,7 @@ func (rt *Runtime) SafeRunProgram(prg *Program) (v goja.Value, err error) {
if x := recover(); x != nil {
if e, ok := x.(error); ok {
err = e
if e2 := GetError(err); e2 != nil {
if e2 := GetJsError(err); e2 != nil {
err = e2
GetLogger(rt.vm).Error(e2.Error(), "stack", e2.Stack)
}
@ -597,7 +633,7 @@ func (rt *Runtime) SafeRunScript(name, src string) (v goja.Value, err error) {
if x := recover(); x != nil {
if e, ok := x.(error); ok {
err = e
if e2 := GetError(err); e2 != nil {
if e2 := GetJsError(err); e2 != nil {
err = e2
GetLogger(rt.vm).Error(e2.Error(), "stack", e2.Stack)
}
@ -614,7 +650,7 @@ func (rt *Runtime) SafeRunString(str string) (v goja.Value, err error) {
if x := recover(); x != nil {
if e, ok := x.(error); ok {
err = e
if e2 := GetError(err); e2 != nil {
if e2 := GetJsError(err); e2 != nil {
err = e2
GetLogger(rt.vm).Error(e2.Error(), "stack", e2.Stack)
}
@ -651,7 +687,7 @@ func (rt *Runtime) StartFromProgram(prg *Program) error {
_, err := rt.SafeRunProgram(prg)
rt.unlock()
if err != nil {
return MakeError(err)
return MakeJsError(err)
} else {
rt.started = true
return nil
@ -666,7 +702,7 @@ func (rt *Runtime) RunMain(args ...any) (any, error) {
// 解析参数
for i, arg := range args {
if str, ok := arg.(string); ok {
var v interface{}
var v any
if err := json.Unmarshal([]byte(str), &v); err == nil {
args[i] = v
}
@ -677,7 +713,7 @@ func (rt *Runtime) RunMain(args ...any) (any, error) {
err := rt.vm.Set("__args", args)
rt.unlock()
if err != nil {
return nil, MakeError(err)
return nil, MakeJsError(err)
}
rt.lock()
r, err := rt.SafeRunScript("main", "main(...__args)")
@ -689,7 +725,7 @@ func (rt *Runtime) RunVM(callback func(vm *goja.Runtime) (any, error)) (any, err
rt.lock()
r, err := callback(rt.vm)
rt.unlock()
return r, MakeError(err)
return r, MakeJsError(err)
}
func (rt *Runtime) SetGoData(name string, value any) {
@ -707,7 +743,7 @@ func (rt *Runtime) GetGoData(name string) any {
func (rt *Runtime) Set(name string, value any) error {
rt.lock()
defer rt.unlock()
return MakeError(rt.vm.Set(name, value))
return MakeJsError(rt.vm.Set(name, value))
}
func (rt *Runtime) SetGlobal(global Map) error {
@ -716,7 +752,7 @@ func (rt *Runtime) SetGlobal(global Map) error {
defer rt.unlock()
for k, v := range global {
if err = rt.vm.Set(k, v); err != nil {
return MakeError(err)
return MakeJsError(err)
}
}
return nil
@ -768,7 +804,7 @@ func makeResult(r goja.Value, err error) (any, error) {
result = r.Export()
}
}
return result, MakeError(err)
return result, MakeJsError(err)
}
type WatchRunner struct {