Compare commits

..

No commits in common. "e754f0afed4f7c1c42fc596923f03c874c0a7559" and "fa8fa86074443dab3e027b736daa86b4d6905228" have entirely different histories.

2 changed files with 123 additions and 362 deletions

400
gojs.go
View File

@ -7,54 +7,30 @@ import (
"fmt" "fmt"
"github.com/ssgo/log" "github.com/ssgo/log"
"github.com/ssgo/u" "github.com/ssgo/u"
"os"
"path" "path"
"path/filepath"
"regexp" "regexp"
"strings" "strings"
) )
// var pluginNameMatcher = regexp.MustCompile(`(\w+?)\.`) var pluginNameMatcher = regexp.MustCompile(`(\w+?)\.`)
var exportMatcher = regexp.MustCompile(`export\s+([\w{}, ]+)\s*;?`) var exportMatcher = regexp.MustCompile(`export\s+([\w{}, ]+)\s*;?`)
var importMatcher = regexp.MustCompile(`import\s+([\w{}, ]+)\s+from\s+['"]([\w./\\\- ]+)['"]`) var importMatcher = regexp.MustCompile(`import\s+([\w{}, ]+)\s+from\s+['"]([\w./\- ]+)['"]`)
var flowMethodTypeMatcher = regexp.MustCompile(`\):\s*([\w<>\[\]]+)\s*{`)
var functionArgsForFlowMatcher = regexp.MustCompile(`\([\w<>\[\]:,\s]+`)
var flowVarTypeMatcher = regexp.MustCompile(`(\w+)\s*:\s*([\w<>\[\]]+)\s*(=|,|\)|$)`)
type RuntimeOption struct { type RuntimeOption struct {
Globals map[string]interface{} Globals map[string]interface{}
Imports map[string]string Imports map[string]string
Logger *log.Logger Logger *log.Logger
DevMode bool
} }
//type watchInfo struct {
// mtime int64
// code string
// codePath string
//}
type JSRuntime struct { type JSRuntime struct {
imports map[string]string imports map[string]string
imported map[string]string imported map[string]string
freeJsValues []quickjs.Value freeJsValues []quickjs.Value
rt quickjs.Runtime rt quickjs.Runtime
JsCtx *quickjs.Context JsCtx *quickjs.Context
GoCtx *plugin.Context GoCtx *plugin.Context
logger *log.Logger logger *log.Logger
plugins map[string]*plugin.Plugin plugins map[string]*plugin.Plugin
rootPath string
currentPath string
devMode bool
codeLines map[string][]string
realCodeLines map[string][]string
anonymousIndex uint
//watchList map[string]watchInfo // watch file changed, for dev mode
}
type JSError struct {
error
stack string
} }
func (rt *JSRuntime) Close() { func (rt *JSRuntime) Close() {
@ -72,20 +48,10 @@ func fixPluginId(id string) string {
return "_" + pluginIdFixer.ReplaceAllString(id, "_") return "_" + pluginIdFixer.ReplaceAllString(id, "_")
} }
func (rt *JSRuntime) run(code string, isClosure bool, setToVar string, fromFilename string) (out interface{}, jsErr *JSError) { func (rt *JSRuntime) run(code string) (out interface{}, err error, stack string) {
// support import // support import
tryPlugins := map[string]bool{} tryPlugins := map[string]bool{}
fixedCode := "" code = importMatcher.ReplaceAllStringFunc(code, func(importStr string) string {
if isClosure {
if setToVar == "" {
fixedCode = "(function(){" + code + "})()"
} else {
fixedCode = "let " + setToVar + " = (function(){" + code + "})()"
}
} else {
fixedCode = code
}
fixedCode = importMatcher.ReplaceAllStringFunc(fixedCode, func(importStr string) string {
m := importMatcher.FindStringSubmatch(importStr) m := importMatcher.FindStringSubmatch(importStr)
importVar := rt.imported[m[2]] importVar := rt.imported[m[2]]
if importVar == "" { if importVar == "" {
@ -99,41 +65,45 @@ func (rt *JSRuntime) run(code string, isClosure bool, setToVar string, fromFilen
if strings.HasSuffix(baseName, ".js") { if strings.HasSuffix(baseName, ".js") {
baseName = baseName[0 : len(baseName)-3] baseName = baseName[0 : len(baseName)-3]
} else { } else {
if plugin.Get(m[2]) != nil { jsFile += ".js"
isTS = true
} else {
jsFile += ".js"
}
} }
if isTS { if !isTS && (rt.imports[m[2]] != "" || u.FileExists(jsFile)) {
importCode := rt.imports[m[2]]
if importCode == "" {
importCode, _ = u.ReadFile(jsFile)
}
if importCode != "" {
importVar = "import_" + u.UniqueId()
rt.imported[m[2]] = importVar
importedCode := exportMatcher.ReplaceAllStringFunc(importCode, func(exportStr string) string {
if strings.Contains(exportStr, "export default") {
exportStr = strings.Replace(exportStr, "export default", "return", 1)
}
exportStr = strings.Replace(exportStr, "export", "return", 1)
return exportStr
})
err, stack := rt.Exec("let " + importVar + " = (function(){" + importedCode + "})()")
if err != nil {
rt.logger.Error(err.Error(), "stack", stack)
}
} else {
importVar = "{}"
}
return "let " + m[1] + " = " + importVar
} else {
if plg := plugin.Get(m[2]); plg != nil { if plg := plugin.Get(m[2]); plg != nil {
tryPlugins[m[2]] = true tryPlugins[m[2]] = true
return "let " + m[1] + " = " + fixPluginId(m[2]) return "let " + m[1] + " = " + fixPluginId(m[2])
} else {
rt.logger.Error("unknown plugin: " + m[2])
return ""
}
} else {
if varName, searchList, err := rt.Import(m[2]); err == nil {
return "let " + m[1] + " = " + varName
} else {
return "throw new Error('import file not found: " + jsFile + " in [" + strings.Join(searchList, ", ") + "]')"
} }
return ""
} }
} else { } else {
return "let " + m[1] + " = " + importVar return "let " + m[1] + " = " + importVar
} }
}) })
fixedCode = flowMethodTypeMatcher.ReplaceAllString(fixedCode, ") {")
fixedCode = functionArgsForFlowMatcher.ReplaceAllStringFunc(fixedCode, func(str string) string {
//if flowVarTypeMatcher.MatchString(str) {
// fmt.Println(">>>>>>>>", str, u.BCyan(flowVarTypeMatcher.ReplaceAllString(str, "$1 $3")))
//}
return flowVarTypeMatcher.ReplaceAllString(str, "$1 $3")
})
//tryPlugins := map[string]bool{} //tryPlugins := map[string]bool{}
//for _, m := range pluginNameMatcher.FindAllStringSubmatch(fixedCode, 1024) { //for _, m := range pluginNameMatcher.FindAllStringSubmatch(code, 1024) {
// tryPlugins[m[1]] = true // tryPlugins[m[1]] = true
//} //}
@ -143,10 +113,8 @@ func (rt *JSRuntime) run(code string, isClosure bool, setToVar string, fromFilen
rt.plugins[plg.Id] = &plg rt.plugins[plg.Id] = &plg
rt.JsCtx.Globals().Set(fixPluginId(plg.Id), MakeJsValueForPlugin(rt.GoCtx, plg.Objects, plg.Id, false)) rt.JsCtx.Globals().Set(fixPluginId(plg.Id), MakeJsValueForPlugin(rt.GoCtx, plg.Objects, plg.Id, false))
if plg.JsCode != "" { if plg.JsCode != "" {
rt.codeLines[plg.Id+".js"] = strings.Split(plg.JsCode, "\n") if result, err := rt.JsCtx.Eval(plg.JsCode); err != nil {
rt.realCodeLines[plg.Id+".js"] = strings.Split(plg.JsCode, "\n") stack := GetJSError(err, plg.JsCode)
if result, err := rt.JsCtx.EvalFile(plg.JsCode, plg.Id+".js"); err != nil {
stack := rt.getJSError(err)
rt.logger.Error(err.Error(), "stack", stack) rt.logger.Error(err.Error(), "stack", stack)
} else { } else {
result.Free() result.Free()
@ -155,200 +123,43 @@ func (rt *JSRuntime) run(code string, isClosure bool, setToVar string, fromFilen
} }
} }
rt.codeLines[fromFilename] = strings.Split(code, "\n") if r, err := rt.JsCtx.Eval(code); err == nil {
rt.realCodeLines[fromFilename] = strings.Split(fixedCode, "\n")
if r, err := rt.JsCtx.EvalFile(fixedCode, fromFilename); err == nil {
result := MakeFromJsValue(r) result := MakeFromJsValue(r)
r.Free() r.Free()
return result, nil return result, nil, ""
} else { } else {
// 检查错误 // 检查错误
stack := rt.getJSError(err) stack := GetJSError(err, code)
//stack2 := getJSError(err, fixedCode) rt.logger.Error(err.Error(), "stack", stack)
rt.logger.Error(err.Error(), "stack", stack) //, "stack2", stack2) return nil, err, stack
return nil, &JSError{error: err}
} }
} }
func (rt *JSRuntime) Exec(code string) (jsErr *JSError) { func (rt *JSRuntime) Exec(code string) (err error, stack string) {
return rt.ExecAt(code, "") _, err, stack = rt.run(code)
return err, stack
} }
func (rt *JSRuntime) ExecAt(code string, dir string) (jsErr *JSError) { func (rt *JSRuntime) ExecFile(filename string) (err error, stack string) {
rt.anonymousIndex++
filename := filepath.Join(dir, fmt.Sprintf("anonymous%d.js", rt.anonymousIndex))
return rt.execAtFile(code, filename)
}
func (rt *JSRuntime) ExecFile(filename string) (jsErr *JSError) {
if code, err := u.ReadFile(filename); err == nil { if code, err := u.ReadFile(filename); err == nil {
return rt.execAtFile(code, filename) return rt.Exec(code)
} else { } else {
rt.logger.Error(err.Error()) return err, ""
return &JSError{error: err}
} }
} }
func (rt *JSRuntime) execAtFile(code string, filename string) (jsErr *JSError) { func (rt *JSRuntime) Run(code string) (out interface{}, err error, stack string) {
if filename == "" { return rt.run("(function(){" + code + "})()")
rt.currentPath = rt.rootPath
} else {
if !filepath.IsAbs(filename) {
filename, _ = filepath.Abs(filename)
}
rt.currentPath = filepath.Dir(filename)
}
_, jsErr = rt.run(code, false, "", filename)
return jsErr
} }
func (rt *JSRuntime) Run(code string) (out interface{}, jsErr *JSError) { func (rt *JSRuntime) RunFile(filename string) (out interface{}, err error, stack string) {
return rt.RunAt(code, "")
}
func (rt *JSRuntime) RunAt(code string, dir string) (out interface{}, jsErr *JSError) {
rt.anonymousIndex++
filename := filepath.Join(dir, fmt.Sprintf("anonymous%d.js", rt.anonymousIndex))
return rt.runAtFile(code, filename)
}
func (rt *JSRuntime) RunFile(filename string) (out interface{}, jsErr *JSError) {
rt.currentPath = filepath.Dir(filename)
if code, err := u.ReadFile(filename); err == nil { if code, err := u.ReadFile(filename); err == nil {
return rt.runAtFile(code, filename) return rt.Run(code)
} else { } else {
rt.logger.Error(err.Error()) return nil, err, ""
return nil, &JSError{error: err}
} }
} }
func (rt *JSRuntime) runAtFile(code string, filename string) (out interface{}, jsErr *JSError) {
if filename == "" {
rt.currentPath = rt.rootPath
} else {
if !filepath.IsAbs(filename) {
filename, _ = filepath.Abs(filename)
}
rt.currentPath = filepath.Dir(filename)
}
return rt.run(code, true, "", filename)
}
func appendSearchFiles(list *[]string, dir, moduleName string, hasJsExt bool) string {
filename := moduleName
if dir != "" {
filename = filepath.Join(dir, moduleName)
}
if hasJsExt {
if u.FileExists(filename) {
return filename
}
*list = append(*list, filename)
} else {
tryFilename := filename + ".js"
if u.FileExists(tryFilename) {
return tryFilename
}
*list = append(*list, tryFilename)
tryFilename = filepath.Join(filename, "index.js")
if u.FileExists(tryFilename) {
return tryFilename
}
*list = append(*list, tryFilename)
}
return ""
}
func (rt *JSRuntime) Import(moduleName string) (varName string, searchList []string, jsErr *JSError) {
searchList = make([]string, 0)
// if imported
importVar := rt.imported[moduleName]
if importVar != "" {
return importVar, searchList, nil
}
// check imports set
importCode := rt.imports[moduleName]
importFile := ""
// search file
if importCode == "" {
hasJsExt := strings.HasSuffix(moduleName, ".js")
importFile = appendSearchFiles(&searchList, "", moduleName, hasJsExt)
if importFile == "" && !filepath.IsAbs(moduleName) {
importFile = appendSearchFiles(&searchList, rt.currentPath, moduleName, hasJsExt)
if importFile == "" && rt.rootPath != rt.currentPath {
importFile = appendSearchFiles(&searchList, rt.rootPath, moduleName, hasJsExt)
}
usedNodeModuleDir := ""
if importFile == "" {
parentPath := rt.currentPath
for i := 0; i < 100; i++ {
nodeModuleDir := filepath.Join(parentPath, "node_modules")
if u.FileExists(nodeModuleDir) {
importFile = appendSearchFiles(&searchList, nodeModuleDir, moduleName, hasJsExt)
break
}
parentPath = filepath.Dir(parentPath)
if parentPath == "" || parentPath == "." {
break
}
}
}
if importFile == "" && rt.rootPath != rt.currentPath {
parentPath := rt.rootPath
for i := 0; i < 100; i++ {
nodeModuleDir := filepath.Join(parentPath, "node_modules")
if u.FileExists(nodeModuleDir) {
if nodeModuleDir != usedNodeModuleDir {
importFile = appendSearchFiles(&searchList, nodeModuleDir, moduleName, hasJsExt)
}
break
}
parentPath = filepath.Dir(parentPath)
if parentPath == "" || parentPath == "." {
break
}
}
}
}
if importFile != "" {
if !filepath.IsAbs(importFile) {
importFile, _ = filepath.Abs(importFile)
}
importVar = rt.imported[importFile]
if importVar != "" {
return importVar, searchList, nil
}
if code, err := u.ReadFile(importFile); err == nil {
importCode = code
} else {
rt.logger.Error(err.Error())
}
}
}
if importCode != "" {
importVar = fmt.Sprintf("_import_%d_%s", len(rt.imported), u.UniqueId())
rt.imported[importFile] = importVar
importCode = exportMatcher.ReplaceAllStringFunc(importCode, func(exportStr string) string {
if strings.Contains(exportStr, "export default") {
exportStr = strings.Replace(exportStr, "export default", "return", 1)
}
exportStr = strings.Replace(exportStr, "export", "return", 1)
return exportStr
})
if _, err := rt.run(importCode, true, importVar, importFile); err == nil {
return importVar, searchList, nil
} else {
return "", searchList, err
}
}
return "", searchList, nil
}
func SetPluginsConfig(conf map[string]plugin.Config) { func SetPluginsConfig(conf map[string]plugin.Config) {
for _, plg := range plugin.List() { for _, plg := range plugin.List() {
if plg.Init != nil { if plg.Init != nil {
@ -359,7 +170,7 @@ func SetPluginsConfig(conf map[string]plugin.Config) {
func New(option *RuntimeOption) *JSRuntime { func New(option *RuntimeOption) *JSRuntime {
if option == nil { if option == nil {
option = &RuntimeOption{nil, nil, nil, false} option = &RuntimeOption{nil, map[string]string{}, log.DefaultLogger}
} }
if option.Imports == nil { if option.Imports == nil {
@ -378,33 +189,18 @@ func New(option *RuntimeOption) *JSRuntime {
}) })
rt := &JSRuntime{ rt := &JSRuntime{
imports: option.Imports, imports: option.Imports,
imported: map[string]string{}, imported: map[string]string{},
freeJsValues: make([]quickjs.Value, 0), freeJsValues: make([]quickjs.Value, 0),
rt: jsRt, rt: jsRt,
JsCtx: jsCtx, JsCtx: jsCtx,
GoCtx: goCtx, GoCtx: goCtx,
logger: option.Logger, logger: option.Logger,
plugins: map[string]*plugin.Plugin{}, plugins: map[string]*plugin.Plugin{},
codeLines: map[string][]string{},
realCodeLines: map[string][]string{},
}
if rt.imports["console"] == "" {
rt.imports["console"] = "return _console"
}
if rt.imports["logger"] == "" {
rt.imports["logger"] = "return _logger"
} }
rt.GoCtx.SetData("_freeJsValues", &rt.freeJsValues) rt.GoCtx.SetData("_freeJsValues", &rt.freeJsValues)
rt.rootPath, _ = os.Getwd()
rt.currentPath = rt.rootPath
//goCtx.SetData("_rootPath", rt.rootPath)
//goCtx.SetData("_currentPath", rt.rootPath)
//rt.JsCtx.Globals().Set("_rootPath", jsCtx.String(rt.rootPath))
//rt.JsCtx.Globals().Set("_currentPath", jsCtx.String(rt.rootPath))
// 全局变量 // 全局变量
if option.Globals != nil { if option.Globals != nil {
for k, obj := range option.Globals { for k, obj := range option.Globals {
@ -413,12 +209,7 @@ func New(option *RuntimeOption) *JSRuntime {
} }
// 注入 console // 注入 console
rt.JsCtx.Globals().Set("_console", MakeJsValue(rt.GoCtx, map[string]interface{}{ rt.JsCtx.Globals().Set("console", MakeJsValue(rt.GoCtx, map[string]interface{}{
"print": func(args ...interface{}) {
},
"println": func(args ...interface{}) {
fmt.Println(makeStringArray(args, u.TextNone, u.BgNone)...)
},
"log": func(args ...interface{}) { "log": func(args ...interface{}) {
fmt.Println(makeStringArray(args, u.TextNone, u.BgNone)...) fmt.Println(makeStringArray(args, u.TextNone, u.BgNone)...)
}, },
@ -431,10 +222,7 @@ func New(option *RuntimeOption) *JSRuntime {
"error": func(args ...interface{}) { "error": func(args ...interface{}) {
fmt.Println(makeStringArray(args, u.TextWhite, u.BgRed)...) fmt.Println(makeStringArray(args, u.TextWhite, u.BgRed)...)
}, },
"input": func(prompt *string) string { "input": func() string {
if prompt != nil {
fmt.Print(*prompt)
}
line := "" line := ""
_, _ = fmt.Scanln(&line) _, _ = fmt.Scanln(&line)
return line return line
@ -442,7 +230,7 @@ func New(option *RuntimeOption) *JSRuntime {
}, false)) }, false))
// 注入 logger // 注入 logger
rt.JsCtx.Globals().Set("_logger", MakeJsValue(rt.GoCtx, map[string]interface{}{ rt.JsCtx.Globals().Set("logger", MakeJsValue(rt.GoCtx, map[string]interface{}{
"debug": func(message string, args *map[string]interface{}) { "debug": func(message string, args *map[string]interface{}) {
rt.logger.Debug(message, makeMapToArray(args)...) rt.logger.Debug(message, makeMapToArray(args)...)
}, },
@ -482,7 +270,7 @@ func makeStringArray(args []interface{}, color u.TextColor, bg u.BgColor) []inte
return stringArgs return stringArgs
} }
func Run(code string, option *RuntimeOption) (out interface{}, jsErr *JSError) { func Run(code string, option *RuntimeOption) (out interface{}, err error, stack string) {
rt := New(option) rt := New(option)
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
@ -493,51 +281,29 @@ func Run(code string, option *RuntimeOption) (out interface{}, jsErr *JSError) {
return rt.Run(code) return rt.Run(code)
} }
func RunAt(code, dir string, option *RuntimeOption) (out interface{}, jsErr *JSError) { func RunFile(filename string, option *RuntimeOption) (out interface{}, err error, stack string) {
rt := New(option) if code, err := u.ReadFile(filename); err == nil {
defer func() { return Run(code, option)
if err := recover(); err != nil { } else {
rt.logger.Error(u.String(err)) return nil, err, ""
} }
rt.Close()
}()
return rt.RunAt(code, dir)
} }
func RunFile(filename string, option *RuntimeOption) (out interface{}, jsErr *JSError) { var jsErrorCodeMatcher = regexp.MustCompile(`code:(\d+)`)
rt := New(option)
defer func() {
if err := recover(); err != nil {
rt.logger.Error(u.String(err))
}
rt.Close()
}()
return rt.RunFile(filename)
}
var jsErrorCodeMatcher = regexp.MustCompile(`([\w./\\\-]+):(\d+)`) func GetJSError(err error, code string) string {
func (rt *JSRuntime) getJSError(err error) string {
if err != nil { if err != nil {
var jsErr *quickjs.Error var jsErr *quickjs.Error
if errors.As(err, &jsErr) { if errors.As(err, &jsErr) {
// 在错误信息中加入代码 // 在错误信息中加入代码
codeLines := strings.Split(code, "\n")
return jsErrorCodeMatcher.ReplaceAllStringFunc(jsErr.Stack, func(s2 string) string { return jsErrorCodeMatcher.ReplaceAllStringFunc(jsErr.Stack, func(s2 string) string {
m := jsErrorCodeMatcher.FindStringSubmatch(s2) errorLineNumber := u.Int(jsErrorCodeMatcher.FindStringSubmatch(s2)[1])
filename := m[1]
errorLineNumber := u.Int(m[2])
errorLine := "" errorLine := ""
codeLines := rt.codeLines[filename] if len(codeLines) >= errorLineNumber {
realCodeLines := rt.realCodeLines[filename] errorLine = codeLines[errorLineNumber-1]
realCodeLineStr := ""
if codeLines != nil && len(codeLines) >= errorLineNumber {
errorLine = strings.TrimSpace(codeLines[errorLineNumber-1])
realErrorLine := strings.TrimSpace(realCodeLines[errorLineNumber-1])
if errorLine != realErrorLine {
realCodeLineStr = " > ```" + realErrorLine + "```"
}
} }
return s2 + " ```" + errorLine + "```" + realCodeLineStr return s2 + " ```" + errorLine + "```"
}) })
} else { } else {
return err.Error() return err.Error()

85
ts.go
View File

@ -261,55 +261,53 @@ func makeFuncInOutArgs(t reflect.Type, existsClasses *map[string]bool, classes *
// *plugin.Context // *plugin.Context
for i := t.NumIn() - 1; i >= 0; i-- { for i := t.NumIn() - 1; i >= 0; i-- {
arg := t.In(i) arg := t.In(i)
isSkip := false
if arg.String() == "*plugin.Context" {
isSkip = true
}
argInfo := ArgInfo{ argInfo := ArgInfo{
index: i, index: i,
isOutArg: false, isOutArg: false,
isFunc: false, isFunc: false,
isSkip: isSkip, isSkip: false,
isOptional: arg.Kind() == reflect.Pointer, isOptional: arg.Kind() == reflect.Pointer,
isVariadic: t.IsVariadic() && i == t.NumIn()-1, isVariadic: t.IsVariadic() && i == t.NumIn()-1,
Name: "", Name: "",
Type: makeFieldElemType(arg, existsClasses, classes, isSkip), Type: makeFieldElemType(arg, existsClasses, classes, true),
}
if arg.String() == "*plugin.Context" {
argInfo.isSkip = true
}
originArg := arg
if arg.Kind() == reflect.Pointer {
arg = arg.Elem()
}
if arg.Kind() == reflect.Func {
argInfo.isFunc = true
argInfo.funcInArgs, argInfo.funcOutArgs = makeFuncInOutArgs(arg, existsClasses, classes)
}
if !argInfo.isSkip && arg.Kind() == reflect.Struct {
makeClass(originArg, existsClasses, classes)
} }
//originArg := arg
//if arg.Kind() == reflect.Pointer {
// arg = arg.Elem()
//}
//if arg.Kind() == reflect.Func {
// argInfo.isFunc = true
// argInfo.funcInArgs, argInfo.funcOutArgs = makeFuncInOutArgs(arg, existsClasses, classes)
//}
//if !argInfo.isSkip && arg.Kind() == reflect.Struct {
// makeClass(originArg, existsClasses, classes)
//}
inArgs[i] = argInfo inArgs[i] = argInfo
} }
for i := t.NumOut() - 1; i >= 0; i-- { for i := t.NumOut() - 1; i >= 0; i-- {
arg := t.Out(i) arg := t.Out(i)
isSkip := false
if arg.String() == "error" {
isSkip = true
}
argInfo := ArgInfo{ argInfo := ArgInfo{
index: i, index: i,
isOutArg: true, isOutArg: true,
isFunc: false, isFunc: false,
isSkip: isSkip, isSkip: false,
isVariadic: false, isVariadic: false,
Name: "", Name: "",
Type: makeFieldElemType(arg, existsClasses, classes, isSkip), Type: makeFieldElemType(arg, existsClasses, classes, true),
}
if arg.String() == "error" {
argInfo.isSkip = true
}
originArg := arg
if arg.Kind() == reflect.Pointer {
arg = arg.Elem()
}
if !argInfo.isSkip && arg.Kind() == reflect.Struct {
makeClass(originArg, existsClasses, classes)
} }
//originArg := arg
//if arg.Kind() == reflect.Pointer {
// arg = arg.Elem()
//}
//if !argInfo.isSkip && arg.Kind() == reflect.Struct {
// makeClass(originArg, existsClasses, classes)
//}
outArgs[i] = argInfo outArgs[i] = argInfo
} }
return inArgs, outArgs return inArgs, outArgs
@ -318,17 +316,9 @@ func makeFuncInOutArgs(t reflect.Type, existsClasses *map[string]bool, classes *
func findObject(v reflect.Value, level int, existsClasses *map[string]bool) (codes []string, classes []string) { func findObject(v reflect.Value, level int, existsClasses *map[string]bool) (codes []string, classes []string) {
codes = make([]string, 0) codes = make([]string, 0)
classes = make([]string, 0) classes = make([]string, 0)
if v.Kind() == reflect.Interface {
v = v.Elem()
}
originT := v.Type()
v = u.FinalValue(v) v = u.FinalValue(v)
t := originT
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
indent := strings.Repeat(" ", level) indent := strings.Repeat(" ", level)
if t.Kind() == reflect.Map { if v.Kind() == reflect.Map {
codes = append(codes, "{") codes = append(codes, "{")
for _, k := range v.MapKeys() { for _, k := range v.MapKeys() {
codes2, classes2 := findObject(v.MapIndex(k), level+1, existsClasses) codes2, classes2 := findObject(v.MapIndex(k), level+1, existsClasses)
@ -336,10 +326,15 @@ func findObject(v reflect.Value, level int, existsClasses *map[string]bool) (cod
codes = append(codes, indent+" \""+k.String()+"\": "+strings.Join(codes2, "\n")+",") codes = append(codes, indent+" \""+k.String()+"\": "+strings.Join(codes2, "\n")+",")
} }
codes = append(codes, indent+"}") codes = append(codes, indent+"}")
} else if t.Kind() == reflect.Struct { } else if v.Kind() == reflect.Struct {
makeClass(originT, existsClasses, &classes) //codes = append(codes, "{")
codes = append(codes, "null as "+t.Name()) //for _, k := range v.MapKeys() {
} else if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { // codes2, classes2 := findObject(v.MapIndex(k), level+1, existsClasses)
// classes = append(classes, classes2...)
// codes = append(codes, indent+" \""+k.String()+"\": "+strings.Join(codes2, "\n")+",")
//}
//codes = append(codes, indent+"}")
} else if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
codes = append(codes, "[") codes = append(codes, "[")
for i := 0; i < v.Len(); i++ { for i := 0; i < v.Len(); i++ {
codes2, classes2 := findObject(v.Index(i), level+1, existsClasses) codes2, classes2 := findObject(v.Index(i), level+1, existsClasses)
@ -347,8 +342,8 @@ func findObject(v reflect.Value, level int, existsClasses *map[string]bool) (cod
codes = append(codes, indent+" "+strings.Join(codes2, "\n")+",") codes = append(codes, indent+" "+strings.Join(codes2, "\n")+",")
} }
codes = append(codes, indent+"]") codes = append(codes, indent+"]")
} else if t.Kind() == reflect.Func { } else if v.Kind() == reflect.Func {
inArgs, outArgs := makeFuncInOutArgs(t, existsClasses, &classes) inArgs, outArgs := makeFuncInOutArgs(v.Type(), existsClasses, &classes)
makeFuncArgsNames(v, inArgs, false) makeFuncArgsNames(v, inArgs, false)
codes = append(codes, "function ("+makeInArgsString(inArgs)+"): "+makeOutArgsString(outArgs)+" {return}") codes = append(codes, "function ("+makeInArgsString(inArgs)+"): "+makeOutArgsString(outArgs)+" {return}")
} else { } else {