simplify embed

This commit is contained in:
Sky Johnson 2025-06-03 12:00:09 -05:00
parent b596ce9072
commit 98be4aef25

View File

@ -1,11 +1,8 @@
package runner package runner
import ( import (
_ "embed"
"sync"
"sync/atomic"
"Moonshark/utils/logger" "Moonshark/utils/logger"
_ "embed"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go" luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
) )
@ -43,130 +40,67 @@ var mathLuaCode string
//go:embed lua/env.lua //go:embed lua/env.lua
var envLuaCode string var envLuaCode string
// ModuleInfo holds information about an embeddable Lua module // Module represents a Lua module to load
type ModuleInfo struct { type Module struct {
Name string // Module name name string
Code string // Module source code code string
Bytecode atomic.Pointer[[]byte] // Cached bytecode global bool // true if module defines globals, false if it returns a table
Once sync.Once // For one-time compilation
DefinesGlobal bool // Whether module defines globals directly
} }
var ( var modules = []Module{
sandbox = ModuleInfo{Name: "sandbox", Code: sandboxLuaCode, DefinesGlobal: true} {"json", jsonLuaCode, true},
modules = []ModuleInfo{ {"sqlite", sqliteLuaCode, false},
{Name: "json", Code: jsonLuaCode, DefinesGlobal: true}, {"fs", fsLuaCode, true},
{Name: "sqlite", Code: sqliteLuaCode}, {"util", utilLuaCode, true},
{Name: "fs", Code: fsLuaCode, DefinesGlobal: true}, {"string", stringLuaCode, false},
{Name: "util", Code: utilLuaCode, DefinesGlobal: true}, {"table", tableLuaCode, false},
{Name: "string", Code: stringLuaCode}, {"crypto", cryptoLuaCode, true},
{Name: "table", Code: tableLuaCode}, {"time", timeLuaCode, false},
{Name: "crypto", Code: cryptoLuaCode, DefinesGlobal: true}, {"math", mathLuaCode, false},
{Name: "time", Code: timeLuaCode}, {"env", envLuaCode, true},
{Name: "math", Code: mathLuaCode},
{Name: "env", Code: envLuaCode, DefinesGlobal: true},
}
)
// precompileModule compiles a module's code to bytecode once
func precompileModule(m *ModuleInfo) {
m.Once.Do(func() {
tempState := luajit.New(true)
if tempState == nil {
logger.Fatalf("Failed to create temp Lua state for %s module compilation", m.Name)
return
}
defer tempState.Close()
defer tempState.Cleanup()
code, err := tempState.CompileBytecode(m.Code, m.Name+".lua")
if err != nil {
logger.Errorf("Failed to compile %s module: %v", m.Name, err)
return
} }
bytecode := make([]byte, len(code)) // loadModule loads a single module into the Lua state
copy(bytecode, code) func loadModule(state *luajit.State, m Module) error {
m.Bytecode.Store(&bytecode) if m.global {
// Module defines globals directly, just execute it
logger.Debugf("Successfully precompiled %s.lua to bytecode (%d bytes)", m.Name, len(code)) return state.DoString(m.code)
})
} }
// loadModule loads a module into a Lua state // Module returns a table, capture it and set as global
func loadModule(state *luajit.State, m *ModuleInfo, verbose bool) error { if err := state.LoadString(m.code); err != nil {
// Ensure bytecode is compiled
precompileModule(m)
// Attempt to load from bytecode
bytecode := m.Bytecode.Load()
if bytecode != nil && len(*bytecode) > 0 {
if verbose {
logger.Debugf("Loading %s.lua from precompiled bytecode", m.Name)
}
if m.DefinesGlobal {
// Module defines its own globals, just run it
if err := state.LoadAndRunBytecode(*bytecode, m.Name+".lua"); err != nil {
return err
}
} else {
// Module returns a table, capture and set as global
if err := state.LoadAndRunBytecodeWithResults(*bytecode, m.Name+".lua", 1); err != nil {
return err
}
state.SetGlobal(m.Name)
}
} else {
// Fallback to interpreting the source
if verbose {
logger.Warnf("Using non-precompiled %s.lua", m.Name)
}
if m.DefinesGlobal {
if err := state.DoString(m.Code); err != nil {
return err
}
} else {
if err := state.LoadString(m.Code); err != nil {
return err return err
} }
if err := state.Call(0, 1); err != nil { if err := state.Call(0, 1); err != nil {
return err return err
} }
state.SetGlobal(m.Name) state.SetGlobal(m.name)
}
}
return nil return nil
} }
// loadSandboxIntoState loads all modules and sandbox into a Lua state // loadSandboxIntoState loads all modules and sandbox into a Lua state
func loadSandboxIntoState(state *luajit.State, verbose bool) error { func loadSandboxIntoState(state *luajit.State, verbose bool) error {
// Load all utility modules first // Load all utility modules
for i := range modules { for _, module := range modules {
if err := loadModule(state, &modules[i], verbose); err != nil { if err := loadModule(state, module); err != nil {
if verbose {
logger.Errorf("Failed to load %s module: %v", module.name, err)
}
return err return err
} }
if verbose {
logger.Debugf("Loaded %s.lua", module.name)
}
} }
// Initialize any module-specific globals (like SQLite tracking) // Initialize module-specific globals
if err := state.DoString(`__active_sqlite_connections = {}`); err != nil { if err := state.DoString(`__active_sqlite_connections = {}`); err != nil {
return err return err
} }
// Load the sandbox last - it defines __execute and other core functions // Load sandbox last - defines __execute and core functions
precompileModule(&sandbox)
bytecode := sandbox.Bytecode.Load()
if bytecode != nil && len(*bytecode) > 0 {
if verbose { if verbose {
logger.Debugf("Loading sandbox.lua from precompiled bytecode") logger.Debugf("Loading sandbox.lua")
}
return state.LoadAndRunBytecode(*bytecode, "sandbox.lua")
}
if verbose {
logger.Warnf("Using non-precompiled sandbox.lua")
} }
return state.DoString(sandboxLuaCode) return state.DoString(sandboxLuaCode)
} }