From 58fcb1d7f55424de904fd6ae53954b46d82aae8c Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Tue, 11 Apr 2017 13:58:15 +0200 Subject: debug.upvalueid --- README.md | 17 ++++++++++++++++- src/lapi.js | 46 +++++++++++++++++++++++++++++++++++++++++++--- src/ldblib.js | 21 ++++++++++++++++++++- tests/ldblib.js | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 23e5f15..cb4ad18 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,6 @@ - [ ] lua_setlocal - [ ] lua_setuservalue - [ ] lua_tocfunction - - [ ] lua_upvalueid - [ ] lua_upvaluejoin - [ ] Auxiliary library - [x] ... @@ -87,6 +86,22 @@ - [ ] os - [ ] io - [ ] Debug + - [x] debug.debug + - [x] debug.getlocal + - [ ] debug.gethook + - [ ] debug.getinfo + - [ ] debug.getmetatable + - [ ] debug.getregistry + - [ ] debug.getupvalue + - [ ] debug.getuservalue + - [ ] debug.sethook + - [ ] debug.setlocal + - [ ] debug.setmetatable + - [ ] debug.setupvalue + - [ ] debug.setuservalue + - [ ] debug.traceback + - [ ] debug.upvalueid + - [ ] debug.upvaluejoin - [ ] Run [Lua test suite](https://github.com/lua/tests) - [ ] DOM API binding diff --git a/src/lapi.js b/src/lapi.js index 00db461..7f8cda8 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -463,7 +463,7 @@ const lua_newuserdata = function(L, size) { return L.stack[L.top - 1].value; }; -const aux_upvalue = function(fi, n) { +const aux_upvalue = function(L, fi, n) { switch(fi.ttype()) { case CT.LUAT_TCCL: { /* C closure */ let f = fi.value; @@ -480,17 +480,26 @@ const aux_upvalue = function(fi, n) { let name = p.upvalues[n-1].name; return { name: name ? name : "(*no name)", - val: f.upvals[n-1].val() + val: f.upvals[n-1].val(L) }; } default: return null; /* not a closure */ } }; +const lua_getupvalue = function(L, funcindex, n) { + let up = aux_upvalue(L, index2addr(L, funcindex), n); + let name = up.name; + let val = up.val; + if (name) + L.stack[L.top++] = new TValue(name.type, name.value); + return name; +}; + const lua_setupvalue = function(L, funcindex, n) { let fi = index2addr(L, funcindex); assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); - let aux = aux_upvalue(fi, n); + let aux = aux_upvalue(L, fi, n); let name = aux.name; let val = aux.val; if (name) { @@ -899,6 +908,35 @@ const lua_len = function(L, idx) { assert(L.top <= L.ci.top, "stack overflow"); }; +const getupvalref = function(L, fidx, n, pf) { + let fi = index2addr(L, fidx); + assert(fi.ttisLclosure(), "Lua function expected"); + let f = fi.value; + assert(1 <= n && n <= f.p.upvalues.length, "invalid upvalue index"); + return { + closure: f, + upval: f.upvals[n - 1] + }; +}; + +const lua_upvalueid = function(L, fidx, n) { + let fi = index2addr(L, fidx); + switch (fi.ttype()) { + case CT.LUA_TLCL: { /* lua closure */ + return getupvalref(L, fidx, n, null).upval; + } + case CT.LUA_TCCL: { /* C closure */ + let f = fi.value; + assert(1 <= n && n <= f.nupvalues, "invalid upvalue index"); + return f.upvalue[n - 1]; + } + default: { + assert(false, "closure expected"); + return null; + } + } +}; + // This functions are only there for compatibility purposes const lua_gc = function () {}; @@ -934,6 +972,7 @@ module.exports.lua_geti = lua_geti; module.exports.lua_getmetatable = lua_getmetatable; module.exports.lua_gettable = lua_gettable; module.exports.lua_gettop = lua_gettop; +module.exports.lua_getupvalue = lua_getupvalue; module.exports.lua_insert = lua_insert; module.exports.lua_isfunction = lua_isfunction; module.exports.lua_isinteger = lua_isinteger; @@ -1001,5 +1040,6 @@ module.exports.lua_tothread = lua_tothread; module.exports.lua_touserdata = lua_touserdata; module.exports.lua_type = lua_type; module.exports.lua_typename = lua_typename; +module.exports.lua_upvalueid = lua_upvalueid; module.exports.lua_version = lua_version; module.exports.lua_xmove = lua_xmove; diff --git a/src/ldblib.js b/src/ldblib.js index efab872..426cef2 100644 --- a/src/ldblib.js +++ b/src/ldblib.js @@ -66,8 +66,27 @@ const db_getlocal = function(L) { } }; +/* +** Check whether a given upvalue from a given closure exists and +** returns its index +*/ +const checkupval = function(L, argf, argnup) { + let nup = lauxlib.luaL_checkinteger(L, argnup); /* upvalue index */ + lauxlib.luaL_checktype(L, argf, lua.CT.LUA_TFUNCTION); /* closure */ + lauxlib.luaL_argcheck(L, (lapi.lua_getupvalue(L, argf, nup) !== null), argnup, lua.to_luastring("invalid upvalue index")); + return nup; +}; + + +const db_upvalueid = function(L) { + let n = checkupval(L, 1, 2); + lapi.lua_pushlightuserdata(L, lapi.lua_upvalueid(L, 1, n)); + return 1; +}; + const dblib = { - "getlocal": db_getlocal + "getlocal": db_getlocal, + "upvalueid": db_upvalueid }; // Only with Node diff --git a/tests/ldblib.js b/tests/ldblib.js index 579912d..475c031 100644 --- a/tests/ldblib.js +++ b/tests/ldblib.js @@ -53,3 +53,39 @@ test('debug.getlocal', function (t) { ); }); + +test('debug.upvalueid', function (t) { + let luaCode = ` + local upvalue = "upvalue" + + local l = function() + return upvalue + end + + return debug.upvalueid(l, 1) + `, L; + + t.plan(3); + + t.doesNotThrow(function () { + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lauxlib.luaL_loadstring(L, lua.to_luastring(luaCode)); + + }, "Lua program loaded without error"); + + t.doesNotThrow(function () { + + lapi.lua_call(L, 0, -1); + + }, "Lua program ran without error"); + + t.ok( + lapi.lua_touserdata(L, -1), + "Correct element(s) on the stack" + ); + +}); -- cgit v1.2.3-70-g09d2