summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rw-r--r--src/lapi.js21
-rw-r--r--src/ldblib.js40
-rw-r--r--src/ldebug.js15
-rw-r--r--tests/ldblib.js66
5 files changed, 145 insertions, 6 deletions
diff --git a/README.md b/README.md
index 46a31ae..47c80bf 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,6 @@
- [ ] lua_getinfo
- [ ] lua_getstack
- [ ] lua_getupvalue
- - [ ] lua_getuservalue
- [ ] lua_isboolean
- [ ] lua_iscfunction
- [ ] lua_islightuserdata
@@ -48,8 +47,6 @@
- [ ] lua_register
- [ ] lua_setallocf
- [ ] lua_sethook
- - [ ] lua_setlocal
- - [ ] lua_setuservalue
- [ ] lua_tocfunction
- [ ] lua_upvaluejoin
- [ ] Auxiliary library
@@ -91,14 +88,14 @@
- [x] debug.getmetatable
- [x] debug.getregistry
- [x] debug.getupvalue
+ - [x] debug.getuservalue
+ - [x] debug.setlocal
- [x] debug.setmetatable
- [x] debug.setupvalue
+ - [x] debug.setuservalue
- [x] debug.traceback
- [ ] debug.gethook
- - [ ] debug.getuservalue
- [ ] debug.sethook
- - [ ] debug.setlocal
- - [ ] debug.setuservalue
- [ ] debug.upvalueid
- [ ] debug.upvaluejoin
- [ ] Run [Lua test suite](https://github.com/lua/tests)
diff --git a/src/lapi.js b/src/lapi.js
index 048a6b7..b41cfbe 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -537,6 +537,15 @@ const lua_getmetatable = function(L, objindex) {
return res;
};
+const lua_getuservalue = function(L, idx) {
+ let o = index2addr(L, idx);
+ assert(L, o.ttisfulluserdata(), "full userdata expected");
+ L.stack[L.top].type = o.type;
+ L.stack[L.top++].value = o.value;
+ assert(L.top <= L.ci.top, "stack overflow");
+ return L.stack[L.top - 1].ttnov();
+};
+
const lua_gettable = function(L, idx) {
let t = index2addr(L, idx);
lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1);
@@ -793,6 +802,16 @@ const lua_status = function(L) {
return L.status;
};
+const lua_setuservalue = function(L, idx) {
+ assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ let o = index2addr(L, idx);
+ assert(L, o.ttisfulluserdata(), "full userdata expected");
+ L.stack[L.top - 1].type = o.type;
+ L.stack[L.top - 1].value = o.value;
+ L.top--;
+};
+
+
const lua_callk = function(L, nargs, nresults, ctx, k) {
assert(k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks");
assert(nargs + 1 < L.top - L.ci.funcOff, "not enough elements in the stack");
@@ -972,6 +991,7 @@ 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_getuservalue = lua_getuservalue;
module.exports.lua_insert = lua_insert;
module.exports.lua_isfunction = lua_isfunction;
module.exports.lua_isinteger = lua_isinteger;
@@ -1023,6 +1043,7 @@ module.exports.lua_setmetatable = lua_setmetatable;
module.exports.lua_settable = lua_settable;
module.exports.lua_settop = lua_settop;
module.exports.lua_setupvalue = lua_setupvalue;
+module.exports.lua_setuservalue = lua_setuservalue;
module.exports.lua_status = lua_status;
module.exports.lua_stringtonumber = lua_stringtonumber;
module.exports.lua_toboolean = lua_toboolean;
diff --git a/src/ldblib.js b/src/ldblib.js
index d3e3c7c..9fc6ce6 100644
--- a/src/ldblib.js
+++ b/src/ldblib.js
@@ -39,6 +39,23 @@ const db_setmetatable = function(L) {
return 1; /* return 1st argument */
};
+const db_getuservalue = function(L) {
+ if (lapi.lua_type(L, 1) !== lua.CT.LUA_TUSERDATA)
+ lapi.lua_pushnil(L);
+ else
+ lapi.lua_getuservalue(L, 1);
+ return 1;
+};
+
+
+const db_setuservalue = function(L) {
+ lauxlib.luaL_checktype(L, 1, lua.CT.LUA_TUSERDATA);
+ lauxlib.luaL_checkany(L, 2);
+ lapi.lua_settop(L, 2);
+ lapi.lua_setuservalue(L, 1);
+ return 1;
+};
+
/*
** Auxiliary function used by several library functions: check for
** an optional thread as function's first argument and set 'arg' with
@@ -177,6 +194,26 @@ const db_getlocal = function(L) {
}
};
+const db_setlocal = function(L) {
+ let thread = getthread(L);
+ let L1 = thread.thread;
+ let arg = thread.arg;
+ let ar = new lua.lua_Debug();
+ let level = lauxlib.luaL_checkinteger(L, arg + 1);
+ let nvar = lauxlib.luaL_checkinteger(L, arg + 2);
+ if (!ldebug.lua_getstack(L1, level, ar)) /* out of range? */
+ return lauxlib.luaL_argerror(L, arg + 1, "level out of range");
+ lauxlib.luaL_checkany(L, arg + 3);
+ lapi.lua_settop(L, arg + 3);
+ checkstack(L, L1, 1);
+ lapi.lua_xmove(L, L1, 1);
+ let name = ldebug.lua_setlocal(L1, ar, nvar);
+ if (name === null)
+ lapi.lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */
+ lapi.lua_pushstring(L, name.value);
+ return 1;
+};
+
/*
** get (if 'get' is true) or set an upvalue from a closure
*/
@@ -238,8 +275,11 @@ const dblib = {
"getmetatable": db_getmetatable,
"getregistry": db_getregistry,
"getupvalue": db_getupvalue,
+ "getuservalue": db_getuservalue,
+ "setlocal": db_setlocal,
"setmetatable": db_setmetatable,
"setupvalue": db_setupvalue,
+ "setuservalue": db_setuservalue,
"traceback": db_traceback,
"upvalueid": db_upvalueid
};
diff --git a/src/ldebug.js b/src/ldebug.js
index 713a0fb..44410a6 100644
--- a/src/ldebug.js
+++ b/src/ldebug.js
@@ -116,6 +116,20 @@ const lua_getlocal = function(L, ar, n) {
return name;
};
+const lua_setlocal = function(L, ar, n) {
+ swapextra(L);
+ let local = findlocal(L, ar.i_ci, n);
+ let name = local.name;
+ let pos = local.pos;
+ if (name) {
+ L.stack[pos].type = L.stack[L.top - 1].type;
+ L.stack[pos].value = L.stack[L.top - 1].value;
+ L.top--; /* pop value */
+ }
+ swapextra(L);
+ return name;
+};
+
const funcinfo = function(ar, cl) {
if (cl === null || cl.type === CT.LUA_TCCL) {
ar.source = lua.to_luastring("=[JS]");
@@ -574,3 +588,4 @@ module.exports.luaG_typeerror = luaG_typeerror;
module.exports.lua_getinfo = lua_getinfo;
module.exports.lua_getlocal = lua_getlocal;
module.exports.lua_getstack = lua_getstack;
+module.exports.lua_setlocal = lua_setlocal;
diff --git a/tests/ldblib.js b/tests/ldblib.js
index a770c76..30a3eb6 100644
--- a/tests/ldblib.js
+++ b/tests/ldblib.js
@@ -54,6 +54,72 @@ test('debug.getlocal', function (t) {
});
+test('debug.setlocal', function (t) {
+ let luaCode = `
+ local alocal = "alocal"
+ local another = "another"
+
+ local l = function()
+ local infunction = "infunction"
+ local anotherin = "anotherin"
+
+ debug.setlocal(2, 1, 1)
+ debug.setlocal(2, 2, 2)
+ debug.setlocal(1, 1, 3)
+ debug.setlocal(1, 2, 4)
+
+ return infunction, anotherin
+ end
+
+ local a, b = l()
+
+ return alocal, another, a, b
+ `, L;
+
+ t.plan(6);
+
+ 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.strictEqual(
+ lapi.lua_tointeger(L, -4),
+ 1,
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -3),
+ 2,
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -2),
+ 3,
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -1),
+ 4,
+ "Correct element(s) on the stack"
+ );
+
+});
+
test('debug.upvalueid', function (t) {
let luaCode = `
local upvalue = "upvalue"