½ š local edn = require 'builtins.scripts.edn' local mobdebug = require 'builtins.scripts.mobdebug' local M = {} local function identity(v) return v end local function onexit(code, close) sys.exit(code) end local mobdebug_hook local mobdebug_on local breakpoints = {} local coroutines = {}; setmetatable(coroutines, {__mode = "k"}) local continue_execution = true local exit_current_lua_stack = true local last_co = nil local stack_after_suspend = 0 local function set_breakpoint(line, file) if not breakpoints[file] then breakpoints[file] = {} end breakpoints[file][line] = true end local function restore_mobdebug_hook(co) if co then debug.sethook(co, mobdebug_hook, "lcr") else debug.sethook(mobdebug_hook, "lcr") end end local function remove_breakpoint(line, file) if breakpoints[file] then breakpoints[file][line] = nil end if breakpoints[file] and not next(breakpoints[file]) then breakpoints[file] = nil end end local file_cache = {} local function lightweight_hook(source, lastlinedefined, co) local file = file_cache[source] if not file then file = mobdebug.get_filename(source) file_cache[source] = file end mobdebug.get_server_data(file) local brk = breakpoints[file] local in_co = false if co then if lastlinedefined ~= -1 and coroutines[co] == false then coroutines[co] = { ["lines"] = debug.getinfo(2,"L"), ["file"] = file } end if not coroutines[co] and lastlinedefined == -1 then coroutines[co] = false end if not brk then brk = coroutines[co] and breakpoints[coroutines[co].file] in_co = true end end if brk then local lines = nil if not in_co then lines = debug.getinfo(2,"L") else lines = coroutines[co].lines end if lines.activelines then for k, _ in pairs(lines.activelines) do if brk[k] then restore_mobdebug_hook(co) return end end end end end local function set_lightweight_hook(force, co) if (continue_execution and exit_current_lua_stack) or force then exit_current_lua_stack = false continue_execution = false if co then debug.sethook(co, nil, "lcr") sys.set_debugger_lightweight_hook(co, lightweight_hook) else debug.sethook(nil, "lcr") sys.set_debugger_lightweight_hook(lightweight_hook) end end end local function on_return_hook() if not debug.getinfo(4, "l") then exit_current_lua_stack = true set_lightweight_hook() end end local function command_hook(command) if command == "RUN" then continue_execution = true set_lightweight_hook() stack_after_suspend = 0 elseif command == "SUSPEND" then if stack_after_suspend == 0 then stack_after_suspend = 1 end elseif command == "STACK" then if stack_after_suspend == 1 then stack_after_suspend = 0 restore_mobdebug_hook() end elseif command == "EXIT" then onexit(1, true) else stack_after_suspend = 0 end end local function on() if mobdebug_on() then local co, main = coroutine.running() if co and not main then set_lightweight_hook(true, co) end end end function M.start(port) port = port + sys.get_config_int("project.instance_index", 0) mobdebug.line = identity mobdebug.dump = edn.encode mobdebug.setbreakpoint_hook = set_breakpoint mobdebug.removebreakpoint_hook = remove_breakpoint mobdebug.onexit = onexit if jit then jit.flush() end mobdebug_on = mobdebug.on mobdebug.on = on mobdebug.coro() mobdebug.listen(port) mobdebug.command_hook = command_hook mobdebug.on_return_hook = on_return_hook mobdebug_hook = debug.gethook() set_lightweight_hook(true) end return M @builtins/scripts/debugger.luabuiltins.scripts.ednbuiltins.scripts.mobdebug/builtins/scripts/edn.luac/builtins/scripts/mobdebug.luac"