Skip to content

Commit

Permalink
Merge pull request #219 from trheyi/main
Browse files Browse the repository at this point in the history
refactor: Improve error stack trace output and add source root mapping
  • Loading branch information
trheyi authored Aug 1, 2024
2 parents 785e0d9 + b79f046 commit 04da7c0
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 29 deletions.
7 changes: 7 additions & 0 deletions runtime/v8/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package v8
import (
"context"

"github.com/fatih/color"
"github.com/yaoapp/gou/runtime/v8/bridge"
"github.com/yaoapp/gou/runtime/v8/objects/console"
"github.com/yaoapp/kun/log"
Expand Down Expand Up @@ -43,6 +44,9 @@ func (context *Context) Call(method string, args ...interface{}) (interface{}, e

jsRes, err := global.MethodCall(method, bridge.Valuers(jsArgs)...)
if err != nil {
if e, ok := err.(*v8go.JSError); ok {
color.Red("%s\n\n", StackTrace(e, context.SourceRoots))
}
log.Error("%s.%s %s", context.ID, method, err.Error())
return nil, err
}
Expand Down Expand Up @@ -106,6 +110,9 @@ func (context *Context) CallWith(ctx context.Context, method string, args ...int

jsRes, err := global.MethodCall(method, bridge.Valuers(jsArgs)...)
if err != nil {
if e, ok := err.(*v8go.JSError); ok {
color.Red("%s\n\n", StackTrace(e, context.SourceRoots))
}
errChan <- err
return
}
Expand Down
4 changes: 4 additions & 0 deletions runtime/v8/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strings"
"time"

"github.com/fatih/color"
"github.com/google/uuid"
"github.com/yaoapp/gou/runtime/v8/bridge"
"github.com/yaoapp/gou/runtime/v8/objects/console"
Expand Down Expand Up @@ -228,6 +229,9 @@ func (runner *Runner) _exec() {

jsRes, err := global.MethodCall(runner.method, bridge.Valuers(jsArgs)...)
if err != nil {
if e, ok := err.(*v8go.JSError); ok {
color.Red("%s\n\n", StackTrace(e, runner.script.SourceRoots))
}
runner.chResp <- err
return
}
Expand Down
18 changes: 10 additions & 8 deletions runtime/v8/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,13 +506,14 @@ func (script *Script) NewContext(sid string, global map[string]interface{}) (*Co
}

return &Context{
ID: script.ID,
Sid: sid,
Data: global,
Root: script.Root,
Timeout: timeout,
Runner: runner,
Context: ctx,
ID: script.ID,
Sid: sid,
Data: global,
Root: script.Root,
Timeout: timeout,
Runner: runner,
Context: ctx,
SourceRoots: script.SourceRoots,
}, nil

}
Expand Down Expand Up @@ -550,6 +551,7 @@ func (script *Script) NewContext(sid string, global map[string]interface{}) (*Co
Isolate: iso,
Context: ctx,
UnboundScript: instance,
SourceRoots: script.SourceRoots,
}, nil
}

Expand Down Expand Up @@ -647,7 +649,7 @@ func (script *Script) execStandard(process *process.Process) interface{} {

// Debug output the error stack
if e, ok := err.(*v8go.JSError); ok {
color.Red("%s\n\n", StackTrace(e))
color.Red("%s\n\n", StackTrace(e, script.SourceRoots))
}

log.Error("scripts.%s.%s %s", script.ID, process.Method, err.Error())
Expand Down
26 changes: 19 additions & 7 deletions runtime/v8/sourcemap.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func clearSourceMaps() {
}

// StackTrace get the stack trace
func StackTrace(jserr *v8go.JSError) string {
func StackTrace(jserr *v8go.JSError, rootMapping map[string]string) string {

// Production mode will not show the stack trace
if runtimeOption.Debug == false {
Expand All @@ -79,7 +79,7 @@ func StackTrace(jserr *v8go.JSError) string {
return jserr.StackTrace
}

output, err := entries.String()
output, err := entries.String(rootMapping)
if err != nil {
return err.Error() + "\n" + jserr.StackTrace
}
Expand All @@ -92,7 +92,7 @@ func (entry *StackLogEntry) String() string {
}

// String the stack log entry list to string
func (list StackLogEntryList) String() (string, error) {
func (list StackLogEntryList) String(rootMapping map[string]string) (string, error) {
if len(list) == 0 {
return "", fmt.Errorf("StackLogEntryList.String(), empty list")
}
Expand All @@ -113,7 +113,7 @@ func (list StackLogEntryList) String() (string, error) {

file, fn, line, col, ok := smap.Source(line, entry.Column)
if ok {
entry.File = fmtFilePath(file)
entry.File = fmtFilePath(file, rootMapping)
entry.Line = line
entry.Column = col
if fn != "" {
Expand Down Expand Up @@ -226,13 +226,25 @@ func parseStackTrace(trace string) StackLogEntryList {
res = append(res, entry)
}
}

return res
}

func fmtFilePath(file string) string {
file = string(os.PathSeparator) + strings.ReplaceAll(file, ".."+string(os.PathSeparator), "")
func fmtFilePath(file string, rootMapping map[string]string) string {
file = strings.ReplaceAll(file, ".."+string(os.PathSeparator), "")
if !strings.HasPrefix(file, string(os.PathSeparator)) {
file = string(os.PathSeparator) + file
}

file = strings.TrimPrefix(file, application.App.Root())

if rootMapping != nil {
for name, mappping := range rootMapping {
if strings.HasPrefix(file, name) {
file = mappping + strings.TrimPrefix(file, name)
break
}
}
}
return file
}

Expand Down
8 changes: 4 additions & 4 deletions runtime/v8/sourcemap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ func TestStackTrace(t *testing.T) {
t.Fatal("error is not a JSError")
}

trace := StackTrace(e)
trace := StackTrace(e, map[string]string{"/scripts": "/iscripts"})
assert.NotEmpty(t, trace)
assert.Contains(t, trace, "Exception|400: Error occurred")
assert.Contains(t, trace, "/scripts/runtime/ts/page.ts:12:2")
assert.Contains(t, trace, "/scripts/runtime/ts/lib/bar.ts:7:2")
assert.Contains(t, trace, "/scripts/runtime/ts/lib/err.ts:8:10")
assert.Contains(t, trace, "/iscripts/runtime/ts/page.ts:12:2")
assert.Contains(t, trace, "/iscripts/runtime/ts/lib/bar.ts:7:2")
assert.Contains(t, trace, "/iscripts/runtime/ts/lib/err.ts:8:10")
}
22 changes: 12 additions & 10 deletions runtime/v8/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ type TSConfigCompilerOptions struct {

// Script v8 scripts
type Script struct {
ID string
File string
Source string
Root bool
Timeout time.Duration
ID string
File string
Source string
Root bool
SourceRoots map[string]string // the script source root mappping
Timeout time.Duration
}

// Module the module
Expand Down Expand Up @@ -87,11 +88,12 @@ type Isolates struct {

// Context v8 Context
type Context struct {
ID string // the script id
Sid string // set the session id
Data map[string]interface{} // set the global data
Root bool
Timeout time.Duration // terminate the execution after this time
ID string // the script id
Sid string // set the session id
Data map[string]interface{} // set the global data
Root bool
Timeout time.Duration // terminate the execution after this time
SourceRoots map[string]string // the script source root mappping
*Runner
*store.Isolate
*v8go.UnboundScript
Expand Down

0 comments on commit 04da7c0

Please sign in to comment.