From eeb3d8ac1de70703ce7db4788b7fb43fcda80aa8 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Wed, 12 Apr 2017 10:06:25 +0200 Subject: debug.getinfo --- src/lapi.js | 4 +-- src/ldblib.js | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ldebug.js | 8 +++--- 3 files changed, 97 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lapi.js b/src/lapi.js index fcb07d6..894b5bb 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -230,7 +230,7 @@ const lua_pushlstring = function(L, s, len) { }; const lua_pushstring = function (L, s) { - assert(Array.isArray(s), "lua_pushstring expects array of byte"); + assert(Array.isArray(s) || s === undefined || s === null, "lua_pushstring expects array of byte"); if (s === undefined || s === null) L.stack[L.top] = new TValue(CT.LUA_TNIL, null); @@ -245,7 +245,7 @@ const lua_pushstring = function (L, s) { }; const lua_pushliteral = function (L, s) { - assert(typeof s === "string", "lua_pushliteral expects a JS string"); + assert(typeof s === "string" || s === undefined || s === null, "lua_pushliteral expects a JS string"); if (s === undefined || s === null) L.stack[L.top] = new TValue(CT.LUA_TNIL, null); diff --git a/src/ldblib.js b/src/ldblib.js index 318e616..ea080c0 100644 --- a/src/ldblib.js +++ b/src/ldblib.js @@ -3,6 +3,7 @@ const assert = require('assert'); const lua = require('./lua.js'); +const char = lua.char; const lapi = require('./lapi.js'); const lauxlib = require('./lauxlib.js'); const ldebug = require('./ldebug.js'); @@ -37,6 +38,95 @@ const getthread = function(L) { } }; +/* +** Variations of 'lua_settable', used by 'db_getinfo' to put results +** from 'lua_getinfo' into result table. Key is always a string; +** value can be a string, an int, or a boolean. +*/ +const settabss = function(L, k, v) { + lapi.lua_pushstring(L, v); + lapi.lua_setfield(L, -2, k); +}; + +const settabsi = function(L, k, v) { + lapi.lua_pushinteger(L, v); + lapi.lua_setfield(L, -2, k); +}; + +const settabsb = function(L, k, v) { + lapi.lua_pushboolean(L, v); + lapi.lua_setfield(L, -2, k); +}; + + +/* +** In function 'db_getinfo', the call to 'lua_getinfo' may push +** results on the stack; later it creates the result table to put +** these objects. Function 'treatstackoption' puts the result from +** 'lua_getinfo' on top of the result table so that it can call +** 'lua_setfield'. +*/ +const treatstackoption = function(L, L1, fname) { + if (L == L1) + lapi.lua_rotate(L, -2, 1); /* exchange object and table */ + else + lapi.lua_xmove(L1, L, 1); /* move object to the "main" stack */ + lapi.lua_setfield(L, -2, fname); /* put object into table */ +}; + +/* +** Calls 'lua_getinfo' and collects all results in a new table. +** L1 needs stack space for an optional input (function) plus +** two optional outputs (function and line table) from function +** 'lua_getinfo'. +*/ +const db_getinfo = function(L) { + let ar = new lua.lua_Debug(); + let thread = getthread(L); + let arg = thread.arg; + let L1 = thread.thread; + let options = lauxlib.luaL_optstring(L, arg + 2, lua.to_luastring("flnStu")); + checkstack(L, L1, 3); + if (lapi.lua_isfunction(L, arg + 1)) { /* info about a function? */ + options = [char['>']].concat(options); /* add '>' to 'options' */ + lapi.lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ + lapi.lua_xmove(L, L1, 1); + } else { /* stack level */ + if (!ldebug.lua_getstack(L1, lauxlib.luaL_checkinteger(L, arg + 1), ar)) { + lapi.lua_pushnil(L); /* level out of range */ + return 1; + } + } + + if (!ldebug.lua_getinfo(L1, options, ar)) + lauxlib.luaL_argerror(L, arg + 2, lua.to_luastring("invalid option")); + lapi.lua_newtable(L); /* table to collect results */ + if (options.indexOf(char['S']) > -1) { + settabss(L, lua.to_luastring("source"), ar.source.value); + settabss(L, lua.to_luastring("short_src"), ar.short_src); + settabss(L, lua.to_luastring("linedefined"), lua.to_luastring(`${ar.linedefined}`)); + settabss(L, lua.to_luastring("lastlinedefined"), lua.to_luastring(`${ar.lastlinedefined}`)); + settabss(L, lua.to_luastring("what"), ar.what); + } + if (options.indexOf(char['l']) > -1) + settabsi(L, lua.to_luastring("currentline"), ar.currentline); + if (options.indexOf(char['u']) > -1) + settabsi(L, lua.to_luastring("nups"), ar.nups); + settabsi(L, lua.to_luastring("nparams"), ar.nparams); + settabsb(L, lua.to_luastring("isvararg"), ar.isvararg); + if (options.indexOf(char['n']) > - 1) { + settabss(L, lua.to_luastring("name"), ar.name ? ar.name.value : null); + settabss(L, lua.to_luastring("namewhat"), ar.namewhat ? ar.namewhat : null); + } + if (options.indexOf(char['t']) > - 1) + settabsb(L, lua.to_luastring("istailcall"), ar.istailcall); + if (options.indexOf(char['L']) > - 1) + treatstackoption(L, L1, lua.to_luastring("activelines")); + if (options.indexOf(char['f']) > - 1) + treatstackoption(L, L1, lua.to_luastring("func")); + return 1; /* return table */ +}; + const db_getlocal = function(L) { let thread = getthread(L); let L1 = thread.thread; @@ -99,6 +189,7 @@ const db_traceback = function(L) { }; const dblib = { + "getinfo": db_getinfo, "getlocal": db_getlocal, "traceback": db_traceback, "upvalueid": db_upvalueid diff --git a/src/ldebug.js b/src/ldebug.js index ce62abc..713a0fb 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -179,13 +179,13 @@ const auxgetinfo = function(L, what, ar, f, ci) { break; } case 'u': { - ar.nups = f === null ? 0 : f.c.nupvalues; - if (f === null || f.c.type === CT.LUA_TCCL) { + ar.nups = f === null ? 0 : f.nupvalues; + if (f === null || f.type === CT.LUA_TCCL) { ar.isvararg = true; ar.nparams = 0; } else { - ar.isvararg = f.l.p.is_vararg; - ar.nparams = f.l.p.numparams; + ar.isvararg = f.p.is_vararg; + ar.nparams = f.p.numparams; } break; } -- cgit v1.2.3-70-g09d2