simplify embed
This commit is contained in:
parent
b596ce9072
commit
98be4aef25
140
runner/embed.go
140
runner/embed.go
@ -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))
|
|
||||||
copy(bytecode, code)
|
|
||||||
m.Bytecode.Store(&bytecode)
|
|
||||||
|
|
||||||
logger.Debugf("Successfully precompiled %s.lua to bytecode (%d bytes)", m.Name, len(code))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadModule loads a module into a Lua state
|
// loadModule loads a single module into the Lua state
|
||||||
func loadModule(state *luajit.State, m *ModuleInfo, verbose bool) error {
|
func loadModule(state *luajit.State, m Module) error {
|
||||||
// Ensure bytecode is compiled
|
if m.global {
|
||||||
precompileModule(m)
|
// Module defines globals directly, just execute it
|
||||||
|
return state.DoString(m.code)
|
||||||
// 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 returns a table, capture it and set as global
|
||||||
// Module defines its own globals, just run it
|
if err := state.LoadString(m.code); err != nil {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user