diff --git a/compile/common/package_json.lua b/compile/common/package_json.lua index eba919b7..9b0fd992 100644 --- a/compile/common/package_json.lua +++ b/compile/common/package_json.lua @@ -164,6 +164,11 @@ attributes.common = { markdownDescription = "%lua.debug.launch.luaVersion.description%", type = "string", }, + syntaxCompatibility = { + default = false, + markdownDescription = "%lua.debug.launch.syntaxCompatibility.description%", + type = "boolean", + }, outputCapture = { default = { }, diff --git a/extension/package.nls.json b/extension/package.nls.json index 663631af..3d6c6a10 100644 --- a/extension/package.nls.json +++ b/extension/package.nls.json @@ -4,6 +4,7 @@ "lua.debug.launch.console.integratedTerminal.description": "VS Code integrated terminal.", "lua.debug.launch.console.externalTerminal.description": "External terminal that can be configured in user settings.", "lua.debug.launch.luaVersion.description": "Default lua version.", + "lua.debug.launch.syntaxCompatibility.description": "Use the target Lua VM to parse source syntax for breakpoint line information. Note: only takes effect for Lua 5.3+ targets and requires a compatible bytecode format.", "lua.debug.launch.luaArch.description": "Default lua arch.", "lua.debug.launch.sourceCoding.description": "Source encoding.", "lua.debug.launch.path.description": "Search path for Lua programs", diff --git a/extension/script/backend/worker/breakpoint.lua b/extension/script/backend/worker/breakpoint.lua index a80750df..b515cfd4 100644 --- a/extension/script/backend/worker/breakpoint.lua +++ b/extension/script/backend/worker/breakpoint.lua @@ -15,6 +15,11 @@ local protosById = {} -- {["{ld}_{lld}_{srcId}"] = proto} local waitinstbp = {} -- {[funcId] = {[pc] = bp}} local m = {} local enable = false +local syntaxCompatibility = false + +ev.on('initializing', function(config) + syntaxCompatibility = config.syntaxCompatibility == true +end) local function updateHook() local hasInstBp = next(instbreakpoints) ~= nil or next(waitinstbp) ~= nil @@ -211,7 +216,7 @@ function m.find(src, currentline) end local function parserInlineLineinfo(src) - local old = parser(src.content) + local old = parser(src.content, syntaxCompatibility) if not old then return end @@ -241,9 +246,9 @@ local function calcLineInfo(src, content) if src.content then src.lineinfo = parserInlineLineinfo(src) elseif content then - src.lineinfo = parser(content) + src.lineinfo = parser(content, syntaxCompatibility) elseif src.sourceReference then - src.lineinfo = parser(source.getCode(src.sourceReference)) + src.lineinfo = parser(source.getCode(src.sourceReference), syntaxCompatibility) end end return src.lineinfo @@ -531,6 +536,7 @@ ev.on('terminated', function() waitinstbp = {} info = {} enable = false + syntaxCompatibility = false hookmgr.break_open(false) if hookmgr.instbreak_open then hookmgr.instbreak_open(false) diff --git a/extension/script/backend/worker/eval.lua b/extension/script/backend/worker/eval.lua index cea4e9e8..27eab9d8 100644 --- a/extension/script/backend/worker/eval.lua +++ b/extension/script/backend/worker/eval.lua @@ -42,6 +42,27 @@ local function generate(name, init) end end +generate("dump", function() + if luaver.LUAVERSION <= 52 then + local compat_dump = assert(load(readfile 'backend.worker.eval.dump')) + return function(content) + local ok, res, err = pcall(compat_dump, content) + if ok and res ~= nil then + return true, res + end + if ok then + return false, 'can not dump function.' + end + return false, res + end + else + local eval_dump = assert(rdebug.load(readfile 'backend.worker.eval.dump')) + return function(content) + return rdebug.eval(eval_dump, content, 0) + end + end +end) + generate("ffi_reflect", function () if not luaver.isjit then return diff --git a/extension/script/backend/worker/eval/dump.lua b/extension/script/backend/worker/eval/dump.lua new file mode 100644 index 00000000..57963aa2 --- /dev/null +++ b/extension/script/backend/worker/eval/dump.lua @@ -0,0 +1,6 @@ +local content = ... +local f, err = load(content, "=eval.dump") +if not f then + error(err, 0) +end +return string.dump(f) diff --git a/extension/script/backend/worker/parser.lua b/extension/script/backend/worker/parser.lua index 491de068..94548c3d 100644 --- a/extension/script/backend/worker/parser.lua +++ b/extension/script/backend/worker/parser.lua @@ -84,15 +84,38 @@ local function normalize(lineinfo, si) end end -return function (content) - local f, err = load(content) - if not f then +local function dumpTarget(content) + local eval = require 'backend.worker.eval' + local ok, bin = eval.dump(content) + if ok and type(bin) == "string" then + return bin + end + return nil, type(bin) == "string" and bin or "can not dump function." +end + +return function (content, syntaxCompatibility) + local err + local bin + if syntaxCompatibility then + bin, err = dumpTarget(content) + else + local f + f, err = load(content) + if f then + bin = string.dump(f) + end + end + if not bin then + local log = require 'common.log' + log.error("ERROR:"..(err or "unknown error")) + return + end + local ok, cl, v = pcall(undump, bin) + if not ok then local log = require 'common.log' - log.error("ERROR:"..err) + log.error("ERROR:"..tostring(cl)) return end - local bin = string.dump(f) - local cl, v = undump(bin) version = v local si = { activelines = {}, definelines = {} } local lineinfo = {} diff --git a/extension/script/backend/worker/undump.lua b/extension/script/backend/worker/undump.lua index 94e7915a..b86b1f87 100644 --- a/extension/script/backend/worker/undump.lua +++ b/extension/script/backend/worker/undump.lua @@ -528,6 +528,7 @@ local undump55; do end function undump55(cl) + cached = {} CheckHeader() cl.nupvalues = LoadByte() cl.f = {}