Moonshark/core/runner/embed.go
2025-05-02 08:02:36 -05:00

121 lines
3.0 KiB
Go

package runner
import (
_ "embed"
"sync"
"sync/atomic"
"Moonshark/core/utils/logger"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
)
//go:embed sandbox.lua
var sandboxLuaCode string
//go:embed json.lua
var jsonLuaCode string
// Global bytecode cache to improve performance
var (
sandboxBytecode atomic.Pointer[[]byte]
jsonBytecode atomic.Pointer[[]byte]
bytecodeOnce sync.Once
jsonBytecodeOnce sync.Once
)
// precompileSandboxCode compiles the sandbox.lua code to bytecode once
func precompileSandboxCode() {
tempState := luajit.New()
if tempState == nil {
logger.Fatal("Failed to create temp Lua state for bytecode compilation")
}
defer tempState.Close()
defer tempState.Cleanup()
code, err := tempState.CompileBytecode(sandboxLuaCode, "sandbox.lua")
if err != nil {
logger.Error("Failed to compile sandbox code: %v", err)
return
}
bytecode := make([]byte, len(code))
copy(bytecode, code)
sandboxBytecode.Store(&bytecode)
logger.Debug("Successfully precompiled sandbox.lua to bytecode (%d bytes)", len(code))
}
// precompileJsonModule compiles the json.lua code to bytecode once
func precompileJsonModule() {
tempState := luajit.New()
if tempState == nil {
logger.Fatal("Failed to create temp Lua state for JSON module compilation")
}
defer tempState.Close()
defer tempState.Cleanup()
code, err := tempState.CompileBytecode(jsonLuaCode, "json.lua")
if err != nil {
logger.Error("Failed to compile JSON module: %v", err)
return
}
bytecode := make([]byte, len(code))
copy(bytecode, code)
jsonBytecode.Store(&bytecode)
logger.Debug("Successfully precompiled json.lua to bytecode (%d bytes)", len(code))
}
// loadSandboxIntoState loads the sandbox code into a Lua state
func loadSandboxIntoState(state *luajit.State, verbose bool) error {
bytecodeOnce.Do(precompileSandboxCode)
jsonBytecodeOnce.Do(precompileJsonModule)
// First load and execute the JSON module
jsBytecode := jsonBytecode.Load()
if jsBytecode != nil && len(*jsBytecode) > 0 {
if verbose {
logger.Debug("Loading json.lua from precompiled bytecode")
}
// Execute JSON module bytecode and store result to _G.json
if err := state.LoadBytecode(*jsBytecode, "json.lua"); err != nil {
return err
}
// Execute with 1 result and store to _G.json
if err := state.RunBytecodeWithResults(1); err != nil {
return err
}
// The module table is now on top of stack, set it to _G.json
state.SetGlobal("json")
} else {
// Fallback - compile and execute JSON module directly
if verbose {
logger.Warning("Using non-precompiled json.lua")
}
if err := state.DoString(jsonLuaCode); err != nil {
return err
}
}
// Then load sandbox
bytecode := sandboxBytecode.Load()
if bytecode != nil && len(*bytecode) > 0 {
if verbose {
logger.Debug("Loading sandbox.lua from precompiled bytecode")
}
return state.LoadAndRunBytecode(*bytecode, "sandbox.lua")
}
// Fallback
if verbose {
logger.Warning("Using non-precompiled sandbox.lua")
}
return state.DoString(sandboxLuaCode)
}