From b3c6f070da658d759be897d7e1a5de9bdd668965 Mon Sep 17 00:00:00 2001 From: kingecg Date: Sat, 20 Sep 2025 16:35:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=A8=A1=E5=9D=97=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E5=8A=9F=E8=83=BD=E5=8F=8A=E8=84=9A=E6=9C=AC=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 +- interceptor/interceptor.go | 85 +++++++++++++++++++--- interceptor/interceptor_test.go | 39 ++++++++++ interceptor/testdata/test_injectmodule.ank | 3 + 4 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 interceptor/testdata/test_injectmodule.ank diff --git a/go.mod b/go.mod index 331a706..5ffc9cd 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.kingecg.top/kingecg/gosh -go 1.23.1 +go 1.23 require ( github.com/ebitengine/purego v0.8.4 diff --git a/interceptor/interceptor.go b/interceptor/interceptor.go index 2c823f9..6fd4e6d 100644 --- a/interceptor/interceptor.go +++ b/interceptor/interceptor.go @@ -17,7 +17,9 @@ type Ankointerceptor struct { } func NewAnkointerceptor(ankoEnv *env.Env) *Ankointerceptor { - + if ankoEnv == nil { + ankoEnv = env.NewEnv() + } a := &Ankointerceptor{ importMap: make(map[string]interface{}), libMap: make(map[string]interface{}), @@ -46,18 +48,60 @@ func NewAnkointerceptor(ankoEnv *env.Env) *Ankointerceptor { // - interface{}: The result of the script execution. // - error: An error if the script file cannot be read or execution fails. func (a *Ankointerceptor) Exec(script string) (interface{}, error) { + st, err := os.Stat(script) + if err != nil { + return nil, err + } + if st.IsDir() { + toExec := filepath.Join(script, "index.ank") + return a.exec(toExec, script) + } + if !filepath.IsAbs(script) { + script = filepath.Join(os.Getenv("PWD"), script) + } + content, err := os.ReadFile(script) + if err != nil { + return nil, err + } + scriptContent := string(content) + result, err := a.exec(scriptContent, script) + if err != nil { + return nil, err + } + return result, nil +} + +// ExecContent executes the specified script content within the Anko environment. +// It sets up the environment with necessary variables and methods, +// executes the script content, and returns the result or an error. +// +// Parameters: +// - scriptContent: The script content to be executed. +// +// Returns: +// - interface{}: The result of the script execution. +// - error: An error if the script execution fails. +func (a *Ankointerceptor) ExecContent(scriptContent string) (interface{}, error) { + result, err := a.exec(scriptContent, "") + if err != nil { + return nil, err + } + return result, nil +} + +func (a *Ankointerceptor) exec(scriptContent string, scriptPath string) (interface{}, error) { e := a.ankoEnv.Copy() // Configure the Anko environment with required variables and methods - e.Define("Require", a.genRequireMethod(script)) - e.Define("__filename", script) - e.Define("__dirname", filepath.Dir(script)) - scriptbytes, frr := os.ReadFile(script) - if frr != nil { - return nil, frr + if scriptPath == "" { + cdir, _ := os.Getwd() + scriptPath = filepath.Join(cdir, "tmp") } - scriptcode := string(scriptbytes) + e.Define("Require", a.genRequireMethod(scriptPath)) + e.Define("__filename", scriptPath) + e.Define("__dirname", filepath.Dir(scriptPath)) + // Execute the script code in the prepared environment - result, err := vm.Execute(e, nil, scriptcode) + result, err := vm.Execute(e, nil, scriptContent) if err != nil { fmt.Println(err) return nil, err @@ -71,9 +115,12 @@ func (a *Ankointerceptor) Exec(script string) (interface{}, error) { // 2. 对相对路径自动转换为基于basePath的绝对路径 // 3. 执行模块加载后自动缓存结果 // 参数: -// basePath - 模块基础路径,用于解析相对路径 +// +// basePath - 模块基础路径,用于解析相对路径 +// // 返回: -// 闭包函数,接收模块路径s,返回解析后的模块对象 +// +// 闭包函数,接收模块路径s,返回解析后的模块对象 func (a *Ankointerceptor) genRequireMethod(basePath string) interface{} { return func(s string) interface{} { if r, ok := a.importMap[s]; ok { @@ -95,3 +142,19 @@ func (a *Ankointerceptor) genRequireMethod(basePath string) interface{} { return result } } + +func (a *Ankointerceptor) RegistModule(name string, m map[string]interface{}) { + _, ok := a.importMap[name] + if ok { + panic("Module already exists") + } + a.importMap[name] = m +} + +func (a *Ankointerceptor) RegistStructAsModule(name string, s interface{}) { + _, ok := a.importMap[name] + if ok { + panic("Module already exists") + } + a.importMap[name] = s +} diff --git a/interceptor/interceptor_test.go b/interceptor/interceptor_test.go index fee3fb4..9a83238 100644 --- a/interceptor/interceptor_test.go +++ b/interceptor/interceptor_test.go @@ -1,6 +1,7 @@ package interceptor import ( + "fmt" "path/filepath" "runtime" "testing" @@ -33,3 +34,41 @@ func TestAnkointerceptor_loadlib(t *testing.T) { t.Errorf("Loadso test failed") } } + +func TestAnkointerceptor_RegistModule(t *testing.T) { + e := env.NewEnv() + interceptor := NewAnkointerceptor(e) + _, file, _, _ := runtime.Caller(0) + scriptPath := filepath.Join(filepath.Dir(file), "testdata/test_injectmodule.ank") + m := make(map[string]interface{}) + m["Hi"] = func() string { + return "Hello, world!" + } + interceptor.RegistModule("inject", m) + v, _ := interceptor.Exec(scriptPath) + if v != "Hello, world!" { + t.Errorf("Inject module test failed") + } +} + +type TestStruct struct { + Name string +} + +func (t *TestStruct) Hi() string { + return fmt.Sprintf("Hello, %s!", t.Name) +} + +func TestAnkointerceptor_RegistStructAsModule(t *testing.T) { + e := env.NewEnv() + interceptor := NewAnkointerceptor(e) + _, file, _, _ := runtime.Caller(0) + scriptPath := filepath.Join(filepath.Dir(file), "testdata/test_injectmodule.ank") + + interceptor.RegistStructAsModule("inject", &TestStruct{"world"}) + v, _ := interceptor.Exec(scriptPath) + if v != "Hello, world!" { + t.Errorf("Inject module test failed") + } + +} diff --git a/interceptor/testdata/test_injectmodule.ank b/interceptor/testdata/test_injectmodule.ank new file mode 100644 index 0000000..7788065 --- /dev/null +++ b/interceptor/testdata/test_injectmodule.ank @@ -0,0 +1,3 @@ +inject=Require("inject") +x=inject.Hi() +x \ No newline at end of file