feat: inject safeMode into context in bridge

This commit is contained in:
AI Engineer 2026-05-30 19:26:05 +08:00
parent 65228a6707
commit 6b19f72101
2 changed files with 23 additions and 12 deletions

View File

@ -8,6 +8,7 @@ import (
"reflect" "reflect"
"apigo.cc/go/cast" "apigo.cc/go/cast"
"apigo.cc/go/jsmod"
"github.com/dop251/goja" "github.com/dop251/goja"
) )
@ -23,19 +24,18 @@ func wrapGoFunc(vm *goja.Runtime, fn any, isUnsafe bool) goja.Value {
return vm.ToValue(func(call goja.FunctionCall) goja.Value { return vm.ToValue(func(call goja.FunctionCall) goja.Value {
// 1. Safety Check // 1. Safety Check
if isUnsafe { safeMode := true // Default to safe mode
safeMode := true // Default to safe mode smVal := vm.Get("__safeMode__")
smVal := vm.Get("__safeMode__") if smVal != nil && !goja.IsUndefined(smVal) {
if smVal != nil && !goja.IsUndefined(smVal) { if sm, ok := smVal.Export().(bool); ok {
if sm, ok := smVal.Export().(bool); ok { safeMode = sm
safeMode = sm
}
}
if safeMode {
panic(vm.NewGoError(fmt.Errorf("unauthorized: unsafe operation blocked by safeMode")))
} }
} }
if isUnsafe && safeMode {
panic(vm.NewGoError(fmt.Errorf("unauthorized: unsafe operation blocked by safeMode")))
}
// 2. Prepare Arguments // 2. Prepare Arguments
numIn := t.NumIn() numIn := t.NumIn()
goArgs := make([]reflect.Value, numIn) goArgs := make([]reflect.Value, numIn)
@ -54,6 +54,8 @@ func wrapGoFunc(vm *goja.Runtime, fn any, isUnsafe bool) goja.Value {
ctx = c ctx = c
} }
} }
// Inject SafeMode status into context
ctx = context.WithValue(ctx, jsmod.SafeModeKey, safeMode)
goArgs[i] = reflect.ValueOf(ctx) goArgs[i] = reflect.ValueOf(ctx)
continue continue
} }

13
doc.go
View File

@ -69,8 +69,8 @@ func formatFunc(t reflect.Type) string {
for i := 0; i < numIn; i++ { for i := 0; i < numIn; i++ {
argType := t.In(i) argType := t.In(i)
// Skip Context and Logger in TS doc // Skip Context and Logger in TS doc
if argType.Implements(reflect.TypeOf((*interface{ Done() <-chan struct{} })(nil)).Elem()) || typeName := argType.String()
argType.String() == "*log.Logger" { if typeName == "context.Context" || typeName == "*log.Logger" {
continue continue
} }
@ -107,6 +107,15 @@ func goTypeToTS(t reflect.Type) string {
return "any" return "any"
} }
// Handle known standard library types to avoid deep recursion and provide clear naming
typeName := t.String()
switch typeName {
case "time.Time", "*time.Time":
return "time.Time"
case "time.Duration", "*time.Duration":
return "time.Duration"
}
// Handle pointers // Handle pointers
for t.Kind() == reflect.Ptr { for t.Kind() == reflect.Ptr {
t = t.Elem() t = t.Elem()