实现模块注册功能及脚本执行优化
This commit is contained in:
parent
ae43530608
commit
b3c6f070da
2
go.mod
2
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
|
||||
|
|
|
|||
|
|
@ -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,8 +115,11 @@ func (a *Ankointerceptor) Exec(script string) (interface{}, error) {
|
|||
// 2. 对相对路径自动转换为基于basePath的绝对路径
|
||||
// 3. 执行模块加载后自动缓存结果
|
||||
// 参数:
|
||||
//
|
||||
// basePath - 模块基础路径,用于解析相对路径
|
||||
//
|
||||
// 返回:
|
||||
//
|
||||
// 闭包函数,接收模块路径s,返回解析后的模块对象
|
||||
func (a *Ankointerceptor) genRequireMethod(basePath string) interface{} {
|
||||
return func(s string) interface{} {
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
inject=Require("inject")
|
||||
x=inject.Hi()
|
||||
x
|
||||
Loading…
Reference in New Issue