cleanup 1
This commit is contained in:
parent
23239b00fc
commit
0a18167df7
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -24,7 +24,4 @@ go.work
|
||||||
|
|
||||||
# Test directories and files
|
# Test directories and files
|
||||||
config.lua
|
config.lua
|
||||||
routes/
|
test/
|
||||||
static/
|
|
||||||
libs/
|
|
||||||
override/
|
|
||||||
|
|
12
Moonshark.go
12
Moonshark.go
|
@ -172,12 +172,12 @@ func (s *Moonshark) initRunner() error {
|
||||||
|
|
||||||
// Configure session cookies
|
// Configure session cookies
|
||||||
sessionManager.SetCookieOptions(
|
sessionManager.SetCookieOptions(
|
||||||
"MSESSID", // name
|
"MSSESSID", // name
|
||||||
"/", // path
|
"/", // path
|
||||||
"", // domain
|
"", // domain
|
||||||
false, // secure
|
false, // secure
|
||||||
true, // httpOnly
|
true, // httpOnly
|
||||||
86400, // maxAge (1 day)
|
86400, // maxAge (1 day)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set up runner options
|
// Set up runner options
|
||||||
|
|
|
@ -29,7 +29,6 @@ type Config struct {
|
||||||
HTTPLoggingEnabled bool
|
HTTPLoggingEnabled bool
|
||||||
Watchers struct {
|
Watchers struct {
|
||||||
Routes bool
|
Routes bool
|
||||||
Static bool
|
|
||||||
Modules bool
|
Modules bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,121 +63,106 @@ func New() *Config {
|
||||||
|
|
||||||
// Load loads configuration from a Lua file
|
// Load loads configuration from a Lua file
|
||||||
func Load(filePath string) (*Config, error) {
|
func Load(filePath string) (*Config, error) {
|
||||||
// For simple configs, use standard libraries to ensure proper loading
|
// Create Lua state
|
||||||
state := luajit.New(true)
|
state := luajit.New(true)
|
||||||
if state == nil {
|
if state == nil {
|
||||||
return nil, errors.New("failed to create Lua state")
|
return nil, errors.New("failed to create Lua state")
|
||||||
}
|
}
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
defer state.Cleanup()
|
||||||
|
|
||||||
// Create config with default values
|
// Create config with default values
|
||||||
config := New()
|
config := New()
|
||||||
|
|
||||||
// Execute the config file
|
// Execute the config file
|
||||||
if err := state.DoFile(filePath); err != nil {
|
if err := state.DoFile(filePath); err != nil {
|
||||||
return nil, fmt.Errorf("%w", err)
|
return nil, fmt.Errorf("failed to load config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract configuration values
|
// Store values directly to the config
|
||||||
extractConfig(state, config)
|
config.values = make(map[string]any)
|
||||||
|
|
||||||
|
// Extract all globals individually
|
||||||
|
globalKeys := []string{
|
||||||
|
"debug", "log_level", "port", "routes_dir", "static_dir",
|
||||||
|
"override_dir", "pool_size", "http_logging_enabled",
|
||||||
|
"watchers", "lib_dirs",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range globalKeys {
|
||||||
|
state.GetGlobal(key)
|
||||||
|
if !state.IsNil(-1) {
|
||||||
|
value, err := state.ToValue(-1)
|
||||||
|
if err == nil {
|
||||||
|
config.values[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.Pop(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply configuration values
|
||||||
|
applyConfig(config, config.values)
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractConfig extracts configuration values directly by name
|
// applyConfig applies configuration values from the globals map
|
||||||
func extractConfig(state *luajit.State, config *Config) {
|
func applyConfig(config *Config, globals map[string]any) {
|
||||||
// Process known config values directly by key
|
// Server settings
|
||||||
if value := extractValue(state, "debug"); value != nil {
|
if v, ok := globals["debug"].(bool); ok {
|
||||||
if boolVal, ok := value.(bool); ok {
|
config.Debug = v
|
||||||
config.Debug = boolVal
|
}
|
||||||
}
|
if v, ok := globals["log_level"].(string); ok {
|
||||||
|
config.LogLevel = v
|
||||||
|
}
|
||||||
|
if v, ok := globals["port"].(float64); ok {
|
||||||
|
config.Port = int(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value := extractValue(state, "log_level"); value != nil {
|
// Directory paths
|
||||||
if strVal, ok := value.(string); ok {
|
if v, ok := globals["routes_dir"].(string); ok {
|
||||||
config.LogLevel = strVal
|
config.RoutesDir = v
|
||||||
}
|
}
|
||||||
|
if v, ok := globals["static_dir"].(string); ok {
|
||||||
|
config.StaticDir = v
|
||||||
|
}
|
||||||
|
if v, ok := globals["override_dir"].(string); ok {
|
||||||
|
config.OverrideDir = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if value := extractValue(state, "port"); value != nil {
|
// Performance settings
|
||||||
if numVal, ok := value.(float64); ok {
|
if v, ok := globals["pool_size"].(float64); ok {
|
||||||
config.Port = int(numVal)
|
config.PoolSize = int(v)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if value := extractValue(state, "routes_dir"); value != nil {
|
// Feature flags
|
||||||
if strVal, ok := value.(string); ok {
|
if v, ok := globals["http_logging_enabled"].(bool); ok {
|
||||||
config.RoutesDir = strVal
|
config.HTTPLoggingEnabled = v
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if value := extractValue(state, "static_dir"); value != nil {
|
// Handle lib_dirs array more efficiently
|
||||||
if strVal, ok := value.(string); ok {
|
if libDirs, ok := globals["lib_dirs"]; ok {
|
||||||
config.StaticDir = strVal
|
if dirs := extractStringArray(libDirs); len(dirs) > 0 {
|
||||||
}
|
config.LibDirs = dirs
|
||||||
}
|
|
||||||
|
|
||||||
if value := extractValue(state, "override_dir"); value != nil {
|
|
||||||
if strVal, ok := value.(string); ok {
|
|
||||||
config.OverrideDir = strVal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if value := extractValue(state, "pool_size"); value != nil {
|
|
||||||
if numVal, ok := value.(float64); ok {
|
|
||||||
config.PoolSize = int(numVal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if value := extractValue(state, "http_logging_enabled"); value != nil {
|
|
||||||
if boolVal, ok := value.(bool); ok {
|
|
||||||
config.HTTPLoggingEnabled = boolVal
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle watchers table
|
// Handle watchers table
|
||||||
if value := extractValue(state, "watchers"); value != nil {
|
if watchersVal, ok := globals["watchers"]; ok {
|
||||||
if table, ok := value.(map[string]any); ok {
|
if watchers, ok := watchersVal.(map[string]any); ok {
|
||||||
if routes, ok := table["routes"].(bool); ok {
|
if v, ok := watchers["routes"].(bool); ok {
|
||||||
config.Watchers.Routes = routes
|
config.Watchers.Routes = v
|
||||||
}
|
}
|
||||||
if static, ok := table["static"].(bool); ok {
|
if v, ok := watchers["modules"].(bool); ok {
|
||||||
config.Watchers.Static = static
|
config.Watchers.Modules = v
|
||||||
}
|
}
|
||||||
if modules, ok := table["modules"].(bool); ok {
|
|
||||||
config.Watchers.Modules = modules
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle lib_dirs array
|
|
||||||
if value := extractValue(state, "lib_dirs"); value != nil {
|
|
||||||
if dirs := extractStringArray(value); len(dirs) > 0 {
|
|
||||||
config.LibDirs = dirs
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractValue extracts a specific global value from the Lua state
|
// extractStringArray extracts a string array from a Lua table
|
||||||
func extractValue(state *luajit.State, key string) any {
|
|
||||||
state.GetGlobal(key)
|
|
||||||
defer state.Pop(1)
|
|
||||||
|
|
||||||
if state.IsNil(-1) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
value, err := state.ToValue(-1)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
// extractStringArray extracts a string array from various possible formats
|
|
||||||
func extractStringArray(value any) []string {
|
func extractStringArray(value any) []string {
|
||||||
// Check if it's a direct array
|
// Direct array case
|
||||||
if arr, ok := value.([]any); ok {
|
if arr, ok := value.([]any); ok {
|
||||||
result := make([]string, 0, len(arr))
|
result := make([]string, 0, len(arr))
|
||||||
for _, v := range arr {
|
for _, v := range arr {
|
||||||
|
@ -189,35 +173,15 @@ func extractStringArray(value any) []string {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it's in special array format (map with empty key)
|
// Map with numeric keys case
|
||||||
valueMap, ok := value.(map[string]any)
|
if tableMap, ok := value.(map[string]any); ok {
|
||||||
if !ok {
|
result := make([]string, 0, len(tableMap))
|
||||||
return nil
|
for _, v := range tableMap {
|
||||||
}
|
|
||||||
|
|
||||||
arr, ok := valueMap[""]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle different array types
|
|
||||||
switch arr := arr.(type) {
|
|
||||||
case []string:
|
|
||||||
return arr
|
|
||||||
case []any:
|
|
||||||
result := make([]string, 0, len(arr))
|
|
||||||
for _, v := range arr {
|
|
||||||
if str, ok := v.(string); ok {
|
if str, ok := v.(string); ok {
|
||||||
result = append(result, str)
|
result = append(result, str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
case []float64:
|
|
||||||
result := make([]string, 0, len(arr))
|
|
||||||
for _, v := range arr {
|
|
||||||
result = append(result, fmt.Sprintf("%g", v))
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -486,3 +486,15 @@ func (l *ModuleLoader) ResetModules(state *luajit.State) error {
|
||||||
end
|
end
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// escapeLuaString escapes special characters in a string for Lua
|
||||||
|
func escapeLuaString(s string) string {
|
||||||
|
replacer := strings.NewReplacer(
|
||||||
|
"\\", "\\\\",
|
||||||
|
"\"", "\\\"",
|
||||||
|
"\n", "\\n",
|
||||||
|
"\r", "\\r",
|
||||||
|
"\t", "\\t",
|
||||||
|
)
|
||||||
|
return replacer.Replace(s)
|
||||||
|
}
|
||||||
|
|
|
@ -1,388 +0,0 @@
|
||||||
package runner
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RequireConfig holds configuration for Lua's require mechanism
|
|
||||||
type RequireConfig struct {
|
|
||||||
ScriptDir string // Base directory for script being executed
|
|
||||||
LibDirs []string // Additional library directories
|
|
||||||
}
|
|
||||||
|
|
||||||
// NativeModuleLoader uses Lua's native package.loaded as the cache
|
|
||||||
type NativeModuleLoader struct {
|
|
||||||
registry *ModuleRegistry
|
|
||||||
config *RequireConfig
|
|
||||||
mu sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNativeModuleLoader creates a new native module loader
|
|
||||||
func NewNativeModuleLoader(config *RequireConfig) *NativeModuleLoader {
|
|
||||||
return &NativeModuleLoader{
|
|
||||||
registry: NewModuleRegistry(),
|
|
||||||
config: config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// escapeLuaString escapes special characters in a string for Lua
|
|
||||||
func escapeLuaString(s string) string {
|
|
||||||
replacer := strings.NewReplacer(
|
|
||||||
"\\", "\\\\",
|
|
||||||
"\"", "\\\"",
|
|
||||||
"\n", "\\n",
|
|
||||||
"\r", "\\r",
|
|
||||||
"\t", "\\t",
|
|
||||||
)
|
|
||||||
return replacer.Replace(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetupRequire configures the require system
|
|
||||||
func (l *NativeModuleLoader) SetupRequire(state *luajit.State) error {
|
|
||||||
// Initialize our module registry in Lua
|
|
||||||
return state.DoString(`
|
|
||||||
-- Initialize global module registry
|
|
||||||
__module_paths = {}
|
|
||||||
|
|
||||||
-- Setup fast module loading system
|
|
||||||
__module_results = {}
|
|
||||||
|
|
||||||
-- Create module preload table
|
|
||||||
package.preload = package.preload or {}
|
|
||||||
|
|
||||||
-- Setup module loader registry
|
|
||||||
__ready_modules = {}
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreloadAllModules fully preloads modules for maximum performance
|
|
||||||
func (l *NativeModuleLoader) PreloadAllModules(state *luajit.State) error {
|
|
||||||
l.mu.Lock()
|
|
||||||
defer l.mu.Unlock()
|
|
||||||
|
|
||||||
// Reset registry
|
|
||||||
l.registry = NewModuleRegistry()
|
|
||||||
|
|
||||||
// Reset preloaded modules in Lua
|
|
||||||
if err := state.DoString(`
|
|
||||||
-- Reset module registry
|
|
||||||
__module_paths = {}
|
|
||||||
__module_results = {}
|
|
||||||
|
|
||||||
-- Clear non-core modules from package.loaded
|
|
||||||
local core_modules = {
|
|
||||||
string = true, table = true, math = true, os = true,
|
|
||||||
package = true, io = true, coroutine = true, debug = true, _G = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for name in pairs(package.loaded) do
|
|
||||||
if not core_modules[name] then
|
|
||||||
package.loaded[name] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Reset preload table
|
|
||||||
package.preload = package.preload or {}
|
|
||||||
for name in pairs(package.preload) do
|
|
||||||
package.preload[name] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Reset ready modules
|
|
||||||
__ready_modules = {}
|
|
||||||
`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up paths for require
|
|
||||||
absPaths := []string{}
|
|
||||||
pathsMap := map[string]bool{}
|
|
||||||
|
|
||||||
// Add script directory (absolute path)
|
|
||||||
if l.config.ScriptDir != "" {
|
|
||||||
absPath, err := filepath.Abs(l.config.ScriptDir)
|
|
||||||
if err == nil && !pathsMap[absPath] {
|
|
||||||
absPaths = append(absPaths, filepath.Join(absPath, "?.lua"))
|
|
||||||
pathsMap[absPath] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add lib directories (absolute paths)
|
|
||||||
for _, dir := range l.config.LibDirs {
|
|
||||||
if dir == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
absPath, err := filepath.Abs(dir)
|
|
||||||
if err == nil && !pathsMap[absPath] {
|
|
||||||
absPaths = append(absPaths, filepath.Join(absPath, "?.lua"))
|
|
||||||
pathsMap[absPath] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set package.path
|
|
||||||
escapedPathStr := escapeLuaString(strings.Join(absPaths, ";"))
|
|
||||||
if err := state.DoString(`package.path = "` + escapedPathStr + `"`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process and preload all modules from lib directories
|
|
||||||
for _, dir := range l.config.LibDirs {
|
|
||||||
if dir == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
absDir, err := filepath.Abs(dir)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all Lua files
|
|
||||||
err = filepath.Walk(absDir, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil || info.IsDir() || !strings.HasSuffix(path, ".lua") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get module name
|
|
||||||
relPath, err := filepath.Rel(absDir, path)
|
|
||||||
if err != nil || strings.HasPrefix(relPath, "..") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
modName := strings.TrimSuffix(relPath, ".lua")
|
|
||||||
modName = strings.ReplaceAll(modName, string(filepath.Separator), ".")
|
|
||||||
|
|
||||||
// Register module path
|
|
||||||
l.registry.Register(path, modName)
|
|
||||||
|
|
||||||
// Register path in Lua
|
|
||||||
escapedPath := escapeLuaString(path)
|
|
||||||
escapedName := escapeLuaString(modName)
|
|
||||||
if err := state.DoString(`__module_paths["` + escapedName + `"] = "` + escapedPath + `"`); err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile the module
|
|
||||||
content, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Precompile bytecode
|
|
||||||
bytecode, err := state.CompileBytecode(string(content), path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load bytecode
|
|
||||||
if err := state.LoadBytecode(bytecode, path); err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store in package.preload for fast loading
|
|
||||||
// We use string concat for efficiency (no string.format overhead)
|
|
||||||
luaCode := `
|
|
||||||
local modname = "` + escapedName + `"
|
|
||||||
local chunk = ...
|
|
||||||
package.preload[modname] = chunk
|
|
||||||
__ready_modules[modname] = true
|
|
||||||
`
|
|
||||||
if err := state.DoString(luaCode); err != nil {
|
|
||||||
state.Pop(1) // Remove chunk from stack
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
state.Pop(1) // Remove chunk from stack
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install optimized require implementation
|
|
||||||
return state.DoString(`
|
|
||||||
-- Ultra-fast module loader
|
|
||||||
function __fast_require(env, modname)
|
|
||||||
-- 1. Check already loaded modules
|
|
||||||
if package.loaded[modname] then
|
|
||||||
return package.loaded[modname]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 2. Check preloaded chunks
|
|
||||||
if __ready_modules[modname] then
|
|
||||||
local loader = package.preload[modname]
|
|
||||||
if loader then
|
|
||||||
-- Set environment
|
|
||||||
setfenv(loader, env)
|
|
||||||
|
|
||||||
-- Execute and store result
|
|
||||||
local result = loader()
|
|
||||||
if result == nil then
|
|
||||||
result = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Cache in shared registry
|
|
||||||
package.loaded[modname] = result
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 3. Direct file load as fallback
|
|
||||||
if __module_paths[modname] then
|
|
||||||
local path = __module_paths[modname]
|
|
||||||
local chunk, err = loadfile(path)
|
|
||||||
if chunk then
|
|
||||||
setfenv(chunk, env)
|
|
||||||
local result = chunk()
|
|
||||||
if result == nil then
|
|
||||||
result = true
|
|
||||||
end
|
|
||||||
package.loaded[modname] = result
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 4. Full path search as last resort
|
|
||||||
local err_msgs = {}
|
|
||||||
for path in package.path:gmatch("[^;]+") do
|
|
||||||
local file_path = path:gsub("?", modname:gsub("%.", "/"))
|
|
||||||
local chunk, err = loadfile(file_path)
|
|
||||||
if chunk then
|
|
||||||
setfenv(chunk, env)
|
|
||||||
local result = chunk()
|
|
||||||
if result == nil then
|
|
||||||
result = true
|
|
||||||
end
|
|
||||||
package.loaded[modname] = result
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
table.insert(err_msgs, "no file '" .. file_path .. "'")
|
|
||||||
end
|
|
||||||
|
|
||||||
error("module '" .. modname .. "' not found:\n" .. table.concat(err_msgs, "\n"), 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Install require factory
|
|
||||||
function __setup_require(env)
|
|
||||||
-- Create highly optimized require with closure
|
|
||||||
env.require = function(modname)
|
|
||||||
return __fast_require(env, modname)
|
|
||||||
end
|
|
||||||
return env
|
|
||||||
end
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyFileChanged invalidates modules when files change
|
|
||||||
func (l *NativeModuleLoader) NotifyFileChanged(state *luajit.State, path string) bool {
|
|
||||||
path = filepath.Clean(path)
|
|
||||||
|
|
||||||
// Get module name from registry
|
|
||||||
modName, found := l.registry.GetModuleName(path)
|
|
||||||
if !found {
|
|
||||||
// Try to find by path for lib dirs
|
|
||||||
for _, libDir := range l.config.LibDirs {
|
|
||||||
absDir, err := filepath.Abs(libDir)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
relPath, err := filepath.Rel(absDir, path)
|
|
||||||
if err != nil || strings.HasPrefix(relPath, "..") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasSuffix(relPath, ".lua") {
|
|
||||||
modName = strings.TrimSuffix(relPath, ".lua")
|
|
||||||
modName = strings.ReplaceAll(modName, string(filepath.Separator), ".")
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this is a core module
|
|
||||||
coreName, isCoreModule := GlobalRegistry.MatchModuleName(modName)
|
|
||||||
|
|
||||||
// Invalidate module in Lua
|
|
||||||
escapedName := escapeLuaString(modName)
|
|
||||||
invalidateCode := `
|
|
||||||
package.loaded["` + escapedName + `"] = nil
|
|
||||||
__ready_modules["` + escapedName + `"] = nil
|
|
||||||
if package.preload then
|
|
||||||
package.preload["` + escapedName + `"] = nil
|
|
||||||
end
|
|
||||||
`
|
|
||||||
if err := state.DoString(invalidateCode); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// For core modules, reinitialize them
|
|
||||||
if isCoreModule {
|
|
||||||
if err := GlobalRegistry.InitializeModule(state, coreName); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// For regular modules, update bytecode if the file still exists
|
|
||||||
content, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
// File might have been deleted - just invalidate
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recompile module
|
|
||||||
bytecode, err := state.CompileBytecode(string(content), path)
|
|
||||||
if err != nil {
|
|
||||||
// Invalid Lua - just invalidate
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load bytecode
|
|
||||||
if err := state.LoadBytecode(bytecode, path); err != nil {
|
|
||||||
// Unable to load - just invalidate
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update preload with new chunk for regular modules
|
|
||||||
luaCode := `
|
|
||||||
-- Update module in package.preload and clear loaded
|
|
||||||
package.loaded["` + escapedName + `"] = nil
|
|
||||||
package.preload["` + escapedName + `"] = ...
|
|
||||||
__ready_modules["` + escapedName + `"] = true
|
|
||||||
`
|
|
||||||
if err := state.DoString(luaCode); err != nil {
|
|
||||||
state.Pop(1) // Remove chunk from stack
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
state.Pop(1) // Remove chunk from stack
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetModules clears all non-core modules
|
|
||||||
func (l *NativeModuleLoader) ResetModules(state *luajit.State) error {
|
|
||||||
return state.DoString(`
|
|
||||||
local core_modules = {
|
|
||||||
string = true, table = true, math = true, os = true,
|
|
||||||
package = true, io = true, coroutine = true, debug = true, _G = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for name in pairs(package.loaded) do
|
|
||||||
if not core_modules[name] then
|
|
||||||
package.loaded[name] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
`)
|
|
||||||
}
|
|
14
go.mod
14
go.mod
|
@ -2,18 +2,20 @@ module git.sharkk.net/Sky/Moonshark
|
||||||
|
|
||||||
go 1.24.1
|
go 1.24.1
|
||||||
|
|
||||||
require git.sharkk.net/Sky/LuaJIT-to-Go v0.0.0
|
require (
|
||||||
|
git.sharkk.net/Sky/LuaJIT-to-Go v0.0.0
|
||||||
|
github.com/VictoriaMetrics/fastcache v1.12.2
|
||||||
|
github.com/goccy/go-json v0.10.5
|
||||||
|
github.com/panjf2000/ants/v2 v2.11.2
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0
|
||||||
|
github.com/valyala/fasthttp v1.60.0
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
|
|
||||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/panjf2000/ants/v2 v2.11.2 // indirect
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
|
||||||
github.com/valyala/fasthttp v1.60.0 // indirect
|
|
||||||
golang.org/x/sync v0.12.0 // indirect
|
golang.org/x/sync v0.12.0 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -1,11 +1,13 @@
|
||||||
github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
|
github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
|
||||||
github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
|
github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
|
||||||
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
||||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
||||||
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
|
@ -15,16 +17,22 @@ github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zt
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/panjf2000/ants/v2 v2.11.2 h1:AVGpMSePxUNpcLaBO34xuIgM1ZdKOiGnpxLXixLi5Jo=
|
github.com/panjf2000/ants/v2 v2.11.2 h1:AVGpMSePxUNpcLaBO34xuIgM1ZdKOiGnpxLXixLi5Jo=
|
||||||
github.com/panjf2000/ants/v2 v2.11.2/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek=
|
github.com/panjf2000/ants/v2 v2.11.2/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.60.0 h1:kBRYS0lOhVJ6V+bYN8PqAHELKHtXqwq9zNMLKx1MBsw=
|
github.com/valyala/fasthttp v1.60.0 h1:kBRYS0lOhVJ6V+bYN8PqAHELKHtXqwq9zNMLKx1MBsw=
|
||||||
github.com/valyala/fasthttp v1.60.0/go.mod h1:iY4kDgV3Gc6EqhRZ8icqcmlG6bqhcDXfuHgTO4FXCvc=
|
github.com/valyala/fasthttp v1.60.0/go.mod h1:iY4kDgV3Gc6EqhRZ8icqcmlG6bqhcDXfuHgTO4FXCvc=
|
||||||
|
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
Loading…
Reference in New Issue
Block a user