From ce923e2bbe970633faef4778c1362b4f852618e9 Mon Sep 17 00:00:00 2001 From: Star Date: Wed, 25 Jun 2025 21:36:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E9=83=A8=E5=88=86=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=88=B0gojs/runtime=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=BC=BA=E4=BA=86=E6=97=B6=E9=97=B4=E5=A4=84=E7=90=86=E8=83=BD?= =?UTF-8?q?=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- env.yml | 6 -- go.mod | 27 +++-- test.yml | 5 - util.go | 283 ++++++--------------------------------------------- util.ts | 18 ---- util_test.go | 25 +---- 6 files changed, 50 insertions(+), 314 deletions(-) delete mode 100644 env.yml delete mode 100644 test.yml diff --git a/env.yml b/env.yml deleted file mode 100644 index 52be3b2..0000000 --- a/env.yml +++ /dev/null @@ -1,6 +0,0 @@ -test: - aaa: 111 - bbb: - - 2 - ccc: - c2: "A-8ubk1BEEeytkVuyO9F6w==" diff --git a/go.mod b/go.mod index 6172bd2..e787791 100644 --- a/go.mod +++ b/go.mod @@ -1,26 +1,31 @@ module apigo.cc/gojs/util -go 1.18 +go 1.23.0 + +toolchain go1.24.3 require ( - apigo.cc/gojs v0.0.12 + apigo.cc/gojs v0.0.14 + apigo.cc/gojs/console v0.0.2 github.com/ZZMarquis/gm v1.3.2 - github.com/emmansun/gmsm v0.29.6 + github.com/emmansun/gmsm v0.30.1 github.com/obscuren/ecies v0.0.0-20150213224233-7c0f4a9b18d9 - github.com/ssgo/u v1.7.13 + github.com/ssgo/u v1.7.19 gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/dlclark/regexp2 v1.11.4 // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a // indirect + github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b // indirect github.com/ssgo/config v1.7.9 // indirect github.com/ssgo/log v1.7.7 // indirect github.com/ssgo/standard v1.7.7 // indirect - github.com/ssgo/tool v0.4.28 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + github.com/ssgo/tool v0.4.29 // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.26.0 // indirect ) diff --git a/test.yml b/test.yml deleted file mode 100644 index c53e7ba..0000000 --- a/test.yml +++ /dev/null @@ -1,5 +0,0 @@ -aaa: 11 -bbb: - - 1 -ccc: - c1: 111 diff --git a/util.go b/util.go index 6ee98fb..9051461 100644 --- a/util.go +++ b/util.go @@ -18,15 +18,10 @@ import ( "encoding/hex" "encoding/json" "encoding/pem" - "errors" "math/big" - "os" "path/filepath" - "regexp" - "runtime" "strings" "text/template" - "time" "apigo.cc/gojs" "apigo.cc/gojs/goja" @@ -46,17 +41,6 @@ var utilTS string //go:embed README.md var utilMD string -var envConfigs map[string]map[string]any -var confAes = u.NewAes([]byte("?GQ$0K0GgLdO=f+~L68PLm$uhKr4'=tV"), []byte("VFs7@sK61cj^f?HZ")) -var keysIsSet = false - -func SetSSKey(key, iv []byte) { - if !keysIsSet { - confAes = u.NewAes(key, iv) - keysIsSet = true - } -} - func init() { obj := map[string]any{ "json": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { @@ -106,44 +90,6 @@ func init() { panic(vm.NewGoError(err)) } }, - "save": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - args := gojs.MakeArgs(&argsIn, vm).Check(2) - filename := args.Str(0) - var data []byte - var err error - if strings.HasSuffix(filename, ".yml") || strings.HasSuffix(filename, ".yaml") { - data, err = yaml.Marshal(args.Any(1)) - } else { - data, err = json.Marshal(args.Any(1)) - } - if err == nil { - if err = u.WriteFileBytes(gojs.FindPath(vm, filename), data); err != nil { - panic(vm.NewGoError(err)) - } - return nil - } else { - panic(vm.NewGoError(err)) - } - }, - "load": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - args := gojs.MakeArgs(&argsIn, vm).Check(1) - filename := args.Str(0) - if data, err := u.ReadFileBytes(gojs.FindPath(vm, filename)); err == nil { - var r any - if strings.HasSuffix(filename, ".yml") || strings.HasSuffix(filename, ".yaml") { - err = yaml.Unmarshal(data, &r) - } else { - err = json.Unmarshal(data, &r) - } - if err == nil { - return vm.ToValue(r) - } else { - panic(vm.NewGoError(err)) - } - } else { - panic(vm.NewGoError(err)) - } - }, "base64": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) return vm.ToValue(u.Base64(u.Bytes(args.Arguments[0].Export()))) @@ -264,14 +210,14 @@ func init() { if strings.Contains(keyText, "-----BEGIN PRIVATE KEY-----") { keyType = "private" if block, _ := pem.Decode([]byte(keyText)); block == nil { - panic(vm.NewGoError(errors.New("bad private pem key"))) + panic(vm.NewGoError(u.Error("bad private pem key"))) } else { keyBytes = block.Bytes } } else if strings.Contains(keyText, "-----BEGIN PUBLIC KEY-----") { keyType = "public" if block, _ := pem.Decode([]byte(keyText)); block == nil { - panic(vm.NewGoError(errors.New("bad public pem key"))) + panic(vm.NewGoError(u.Error("bad public pem key"))) } else { keyBytes = block.Bytes } @@ -287,7 +233,7 @@ func init() { panic(vm.NewGoError(err)) } else { if ecdsaPriKey, ok := priKey.(*ecdsa.PrivateKey); !ok { - panic(vm.NewGoError(errors.New("bad private key"))) + panic(vm.NewGoError(u.Error("bad private key"))) } else { return vm.ToValue(ecdsaPriKey.D.Bytes()) } @@ -297,7 +243,7 @@ func init() { panic(vm.NewGoError(err)) } else { if ecdsaPubKey, ok := pubKey.(*ecdsa.PublicKey); !ok { - panic(vm.NewGoError(errors.New("bad public key"))) + panic(vm.NewGoError(u.Error("bad public key"))) } else { var buf bytes.Buffer buf.WriteByte(byte(len(ecdsaPubKey.X.Bytes()))) @@ -401,14 +347,14 @@ func init() { if strings.Contains(keyText, "-----BEGIN PRIVATE KEY-----") { keyType = "private" if block, _ := pem.Decode([]byte(keyText)); block == nil { - panic(vm.NewGoError(errors.New("bad private pem key"))) + panic(vm.NewGoError(u.Error("bad private pem key"))) } else { keyBytes = block.Bytes } } else if strings.Contains(keyText, "-----BEGIN PUBLIC KEY-----") { keyType = "public" if block, _ := pem.Decode([]byte(keyText)); block == nil { - panic(vm.NewGoError(errors.New("bad public pem key"))) + panic(vm.NewGoError(u.Error("bad public pem key"))) } else { keyBytes = block.Bytes } @@ -430,7 +376,7 @@ func init() { panic(vm.NewGoError(err)) } else { if sm2PubKey, ok := pubKey.(*ecdsa.PublicKey); !ok { - panic(vm.NewGoError(errors.New("bad public key"))) + panic(vm.NewGoError(u.Error("bad public key"))) } else { var buf bytes.Buffer buf.WriteByte(byte(len(sm2PubKey.X.Bytes()))) @@ -530,14 +476,14 @@ func init() { if strings.Contains(keyText, "-----BEGIN RSA PRIVATE KEY-----") { keyType = "private" if block, _ := pem.Decode([]byte(keyText)); block == nil { - panic(vm.NewGoError(errors.New("bad private pem key"))) + panic(vm.NewGoError(u.Error("bad private pem key"))) } else { keyBytes = block.Bytes } } else if strings.Contains(keyText, "-----BEGIN RSA PUBLIC KEY-----") { keyType = "public" if block, _ := pem.Decode([]byte(keyText)); block == nil { - panic(vm.NewGoError(errors.New("bad public pem key"))) + panic(vm.NewGoError(u.Error("bad public pem key"))) } else { keyBytes = block.Bytes } @@ -801,119 +747,38 @@ func init() { } return vm.ToValue(buf.String()) }, - "sleep": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - args := gojs.MakeArgs(&argsIn, vm).Check(1) - time.Sleep(time.Duration(args.Int64(0)) * time.Millisecond) - return nil - }, - "setTimeout": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - args := gojs.MakeArgs(&argsIn, vm).Check(1) - callback := args.Func(0) - timeout := time.Duration(args.Int64(1)) * time.Millisecond - if callback != nil { - go func() { - if timeout > 0 { - time.Sleep(timeout) - } - if _, err := callback(args.This, args.Arguments[2:]...); err != nil { - args.Logger.Error(err.Error()) - } - }() - } - return nil - }, - "shell": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - args := gojs.MakeArgs(&argsIn, vm).Check(1) - a := make([]string, len(args.Arguments)-1) - for i := 1; i < len(args.Arguments); i++ { - a[i-1] = args.Str(i) - } - - if r, err := u.RunCommand(args.Str(0), a...); err == nil { - return vm.ToValue(r) - } else { - panic(vm.NewGoError(err)) - } - }, "formatDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) format := args.Str(0) - var tm time.Time - if timestamp := args.Int64(1); timestamp > 0 { - if timestamp < 10000000000 { - timestamp *= 1000 - } - tm = time.UnixMilli(timestamp) - } else { - tm = time.Now() - } - return vm.ToValue(tm.Format(format)) + v := args.Any(1) + return vm.ToValue(u.FormatTime(format, v)) + }, + "addDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { + args := gojs.MakeArgs(&argsIn, vm).Check(1) + addStr := args.Str(0) + v := args.Any(1) + return vm.ToValue(u.AddTime(addStr, v)) }, "timestampMS": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - return vm.ToValue(time.Now().UnixMilli()) + args := gojs.MakeArgs(&argsIn, vm).Check(0) + tm := u.ParseTime(args.Any(0)) + return vm.ToValue(tm.UnixMilli()) }, "timestamp": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - return vm.ToValue(time.Now().Unix()) + args := gojs.MakeArgs(&argsIn, vm).Check(0) + tm := u.ParseTime(args.Any(0)) + return vm.ToValue(tm.Unix()) }, "toDatetime": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) - var tm time.Time - if timestamp := args.Int64(0); timestamp > 0 { - if timestamp < 10000000000 { - timestamp *= 1000 - } - tm = time.UnixMilli(timestamp) - } else { - tm = time.Now() - } - return vm.ToValue(tm.Format("2006-01-02 15:04:05")) - }, - "fromDatetime": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - args := gojs.MakeArgs(&argsIn, vm).Check(1) - timeStr := args.Str(0) - if len(timeStr) > 19 { - timeStr = timeStr[0:19] - } - if strings.ContainsRune(timeStr, 'T') { - timeStr = strings.ReplaceAll(timeStr, "T", " ") - } - if tm, err := time.ParseInLocation("2006-01-02 15:04:05", timeStr, time.Local); err == nil { - return vm.ToValue(tm.UnixMilli()) - } else { - panic(vm.NewGoError(err)) - } + tm := u.ParseTime(args.Any(0)) + return vm.ToValue(tm.Format("2006-01-02 15:04:05.000000")) }, "toDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) - var tm time.Time - if timestamp := args.Int64(0); timestamp > 0 { - if timestamp < 10000000000 { - timestamp *= 1000 - } - tm = time.UnixMilli(timestamp) - } else { - tm = time.Now() - } + tm := u.ParseTime(args.Any(0)) return vm.ToValue(tm.Format("2006-01-02")) }, - "fromDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - args := gojs.MakeArgs(&argsIn, vm).Check(1) - timeStr := args.Str(0) - if len(timeStr) > 10 { - timeStr = timeStr[0:10] - } - if tm, err := time.ParseInLocation("2006-01-02", timeStr, time.Local); err == nil { - return vm.ToValue(tm.UnixMilli()) - } else { - panic(vm.NewGoError(err)) - } - }, - "os": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - return vm.ToValue(runtime.GOOS) - }, - "arch": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - return vm.ToValue(runtime.GOARCH) - }, "joinPath": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) return vm.ToValue(filepath.Join(args.StrArray(0)...)) @@ -966,67 +831,12 @@ func init() { args := gojs.MakeArgs(&argsIn, vm).Check(1) return vm.ToValue(u.Bool(args.Any(0))) }, - "searchFile": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - args := gojs.MakeArgs(&argsIn, vm).Check(1) - filename := args.Str(0) - searchPath := args.Str(1) - findFile := "" - if searchPath != "" { - findFile = searchFile(searchPath, filename) - } else { - findFile = searchFileFromCurrent(vm, filename) - } - return vm.ToValue(findFile) - }, - "loadConfig": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { - if envConfigs == nil { - envConfigs = map[string]map[string]any{} - envFile := searchFileFromCurrent(vm, "env.yml") - if envFile == "" { - envFile = searchFileFromCurrent(vm, "env.json") - } - if envFile != "" { - u.LoadX(envFile, &envConfigs) - } - } - - args := gojs.MakeArgs(&argsIn, vm).Check(1) - confName := args.Str(0) - conf := map[string]any{} - confFile := searchFileFromCurrent(vm, confName+".yml") - if confFile == "" { - confFile = searchFileFromCurrent(vm, confName+".json") - } - if confFile != "" { - u.LoadX(confFile, &conf) - } - if envConf, ok := envConfigs[confName]; ok { - u.Convert(envConf, &conf) - } - - decTimes := 0 - confStr := encryptdMatcher.ReplaceAllStringFunc(u.Json(conf), func(str string) string { - if buf, err := base64.URLEncoding.DecodeString(str[1 : len(str)-1]); err == nil { - if buf1, err1 := confAes.DecryptBytes(buf); err1 == nil && len(buf1) > 0 { - decTimes++ - return "\"" + string(buf1) + "\"" - } - } - return str - }) - if decTimes > 0 { - u.UnJson(confStr, &conf) - } - - return vm.ToValue(conf) - }, } gojs.Register("apigo.cc/gojs/util", gojs.Module{ - Object: obj, - TsCode: utilTS, - Example: utilMD, - SetSSKey: SetSSKey, + Object: obj, + TsCode: utilTS, + Example: utilMD, JsCode: ` $MOD$.keysBy = function (obj, ...fieldAndValues) { let keys = [] @@ -1320,8 +1130,6 @@ $MOD$.excludeByKey = function (obj, ...keys) { }) } -var encryptdMatcher = regexp.MustCompile(`"([\w-=]+)"`) - func makeECDSAPriKey(priKey []byte) *ecdsa.PrivateKey { if len(priKey) >= 60 { return makePriKey(priKey, elliptic.P521()) @@ -1378,36 +1186,3 @@ func makeRSAPubKey(keyBytes []byte) *rsa.PublicKey { } return pubKey } - -func searchFile(searchPath, name string) string { - searched := map[string]bool{} - return _searchFile(searchPath, name, &searched) -} - -func searchFileFromCurrent(vm *goja.Runtime, name string) string { - searched := map[string]bool{} - startPath := u.String(vm.GoData["startPath"]) - filename := _searchFile(startPath, name, &searched) - if filename == "" { - currentPath, _ := os.Getwd() - filename = _searchFile(currentPath, name, &searched) - } - return filename -} - -func _searchFile(checkPath, name string, searched *map[string]bool) string { - for { - if !(*searched)[checkPath] { - (*searched)[checkPath] = true - filename := filepath.Join(checkPath, name) - if u.FileExists(filename) { - return filename - } - } - oldPath := checkPath - checkPath = filepath.Dir(oldPath) - if oldPath == checkPath { - return "" - } - } -} diff --git a/util.ts b/util.ts index 4fa0485..02db7f2 100644 --- a/util.ts +++ b/util.ts @@ -6,8 +6,6 @@ export default { unJson, yaml, unYaml, - load, - save, base64, unBase64, urlBase64, @@ -60,9 +58,6 @@ export default { hmacSHA512, hmacSM3, tpl, - sleep, - setTimeout, - shell, formatDate, timestampMS, timestamp, @@ -70,8 +65,6 @@ export default { fromDatetime, toDate, fromDate, - os, - arch, joinPath, getPathDir, getPathBase, @@ -84,8 +77,6 @@ export default { float, bytes, bool, - searchFile, - loadConfig, keysBy, countBy, listBy, @@ -120,8 +111,6 @@ function jsonP(data: any): string { return '' } function unJson(data: string): any { return null } function yaml(data: any): string { return '' } function unYaml(data: string): any { return null } -function load(filename: string): any { return null } -function save(filename: string, data: any) { } function base64(data: any): string { return '' } function unBase64(data: string): any { return null } function urlBase64(data: any): string { return '' } @@ -174,9 +163,6 @@ function hmacSHA256(key: any, ...data: any[]): any { return '' } function hmacSHA512(key: any, ...data: any[]): any { return '' } function hmacSM3(key: any, ...data: any[]): any { return '' } function tpl(text: string, data: any, functions?: Object): string { return '' } -function sleep(ms: number): void { } -function setTimeout(callback: () => void, ms?: number, ...args: any): void { } -function shell(cmd: string, ...args: string[]): string[] { return [] } function formatDate(format: string, timestamp?: number): string { return '' } function timestampMS(): number { return 0 } function timestamp(): number { return 0 } @@ -184,8 +170,6 @@ function toDatetime(timestamp?: number): string { return '' } function fromDatetime(datetimeStr: string): number { return 0 } function toDate(timestamp?: number): string { return '' } function fromDate(dateStr: string): number { return 0 } -function os(): string { return '' } -function arch(): string { return '' } function joinPath(...paths: string[]): string { return '' } function getPathDir(path: string): string { return '' } function getPathBase(path: string): string { return '' } @@ -198,8 +182,6 @@ function int(value: any): number { return 0 } function float(value: any): number { return 0 } function bytes(value: any): any { return null } function bool(value: any): boolean { return false } -function searchFile(filename: string, searchPath?: string): string { return '' } -function loadConfig(name: string): any { return null } // 返回符合条件的key列表,支持数组和Object对象 function keysBy(obj: Array, ...fieldAndValues: any): any[] { return [] } diff --git a/util_test.go b/util_test.go index bb4e84b..19f94eb 100644 --- a/util_test.go +++ b/util_test.go @@ -9,6 +9,7 @@ import ( "time" "apigo.cc/gojs" + _ "apigo.cc/gojs/console" _ "apigo.cc/gojs/util" "github.com/ZZMarquis/gm/sm3" "github.com/ssgo/u" @@ -16,7 +17,7 @@ import ( func TestHash(t *testing.T) { vm := gojs.New() - vm.RunCode("import util from 'apigo.cc/gojs/util'") + vm.RunCode("import util from 'apigo.cc/gojs/util'\nimport co from 'apigo.cc/gojs/console'") testIsSame(vm, t, "util.md5('hello 123')", u.MD5([]byte("hello 123"))) testIsSame(vm, t, "util.base64(util.md5('hello 123'))", u.MD5Base64("hello 123")) testIsSame(vm, t, "util.hex(util.md5('hello 123'))", u.MD5String("hello 123")) @@ -37,7 +38,9 @@ func TestHash(t *testing.T) { testIsSame(vm, t, "util.unSM4('"+u.String(sm4R)+"','12345678901234567','12345678901234567')", "hello 123") testIsSame(vm, t, "util.gzip('hello 123')", u.GzipN([]byte("hello 123"))) tm, _ := time.ParseInLocation("2006-01-02 15:04:05", "2024-01-01 00:00:00", time.Local) - testIsSame(vm, t, "util.fromDatetime('2024-01-01 00:00:00')", tm.UnixMilli()) + testIsSame(vm, t, "util.timestampMS('2024-01-01 00:00:00')", tm.UnixMilli()) + testIsSame(vm, t, "util.timestampMS('Mon Jan 01 2024 00:00:00 GMT+0800 (中国标准时间)')", tm.UnixMilli()) + testIsSame(vm, t, "util.timestampMS(new Date("+u.String(tm.UnixMilli())+"))", tm.UnixMilli()) } func TestECDSA(t *testing.T) { @@ -124,24 +127,6 @@ func TestRSA(t *testing.T) { fmt.Println(u.Green("ecdsa test passed")) } -func TestConfig(t *testing.T) { - r, err := gojs.Run(` - import util from 'apigo.cc/gojs/util' - let t = util.loadConfig('test') - if (t.aaa != 111) return 'failed to load config, aaa != 111' - if (t.bbb.length !== 2 || t.bbb[0] !== 1 || t.bbb[1] !== 2) return 'failed to load config, bbb != [1,2]' - if (t.ccc.c1 !== 111 || t.ccc.c2 !== "222") return 'failed to load config, ccc != [111,"222"]' - return true - `, "") - if err != nil { - t.Fatal(err) - } - if r != true { - t.Fatal(r) - } - fmt.Println(u.Green("ecdsa test passed")) -} - func testIsSame(vm *gojs.Runtime, t *testing.T, code string, checkValue any) { r, err := vm.RunCode(code) if err != nil {