summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md17
-rw-r--r--src/lapi.js46
-rw-r--r--src/ldblib.js21
-rw-r--r--tests/ldblib.js36
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"
+ );
+
+});