实现模块注册功能及脚本执行优化
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
|
module git.kingecg.top/kingecg/gosh
|
||||||
|
|
||||||
go 1.23.1
|
go 1.23
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ebitengine/purego v0.8.4
|
github.com/ebitengine/purego v0.8.4
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,9 @@ type Ankointerceptor struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAnkointerceptor(ankoEnv *env.Env) *Ankointerceptor {
|
func NewAnkointerceptor(ankoEnv *env.Env) *Ankointerceptor {
|
||||||
|
if ankoEnv == nil {
|
||||||
|
ankoEnv = env.NewEnv()
|
||||||
|
}
|
||||||
a := &Ankointerceptor{
|
a := &Ankointerceptor{
|
||||||
importMap: make(map[string]interface{}),
|
importMap: make(map[string]interface{}),
|
||||||
libMap: 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.
|
// - interface{}: The result of the script execution.
|
||||||
// - error: An error if the script file cannot be read or execution fails.
|
// - error: An error if the script file cannot be read or execution fails.
|
||||||
func (a *Ankointerceptor) Exec(script string) (interface{}, error) {
|
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()
|
e := a.ankoEnv.Copy()
|
||||||
// Configure the Anko environment with required variables and methods
|
// Configure the Anko environment with required variables and methods
|
||||||
e.Define("Require", a.genRequireMethod(script))
|
if scriptPath == "" {
|
||||||
e.Define("__filename", script)
|
cdir, _ := os.Getwd()
|
||||||
e.Define("__dirname", filepath.Dir(script))
|
scriptPath = filepath.Join(cdir, "tmp")
|
||||||
scriptbytes, frr := os.ReadFile(script)
|
|
||||||
if frr != nil {
|
|
||||||
return nil, frr
|
|
||||||
}
|
}
|
||||||
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
|
// 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 {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -71,9 +115,12 @@ func (a *Ankointerceptor) Exec(script string) (interface{}, error) {
|
||||||
// 2. 对相对路径自动转换为基于basePath的绝对路径
|
// 2. 对相对路径自动转换为基于basePath的绝对路径
|
||||||
// 3. 执行模块加载后自动缓存结果
|
// 3. 执行模块加载后自动缓存结果
|
||||||
// 参数:
|
// 参数:
|
||||||
// basePath - 模块基础路径,用于解析相对路径
|
//
|
||||||
|
// basePath - 模块基础路径,用于解析相对路径
|
||||||
|
//
|
||||||
// 返回:
|
// 返回:
|
||||||
// 闭包函数,接收模块路径s,返回解析后的模块对象
|
//
|
||||||
|
// 闭包函数,接收模块路径s,返回解析后的模块对象
|
||||||
func (a *Ankointerceptor) genRequireMethod(basePath string) interface{} {
|
func (a *Ankointerceptor) genRequireMethod(basePath string) interface{} {
|
||||||
return func(s string) interface{} {
|
return func(s string) interface{} {
|
||||||
if r, ok := a.importMap[s]; ok {
|
if r, ok := a.importMap[s]; ok {
|
||||||
|
|
@ -95,3 +142,19 @@ func (a *Ankointerceptor) genRequireMethod(basePath string) interface{} {
|
||||||
return result
|
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
|
package interceptor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -33,3 +34,41 @@ func TestAnkointerceptor_loadlib(t *testing.T) {
|
||||||
t.Errorf("Loadso test failed")
|
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