diff options
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | src/lapi.js | 21 | ||||
-rw-r--r-- | src/ldblib.js | 13 | ||||
-rw-r--r-- | tests/ldblib.js | 45 |
4 files changed, 78 insertions, 7 deletions
@@ -34,7 +34,6 @@ - [ ] lua_getstack - [ ] lua_getupvalue - [ ] lua_isboolean - - [ ] lua_iscfunction - [ ] lua_islightuserdata - [ ] lua_isuserdata - [ ] lua_pcallk @@ -48,7 +47,6 @@ - [ ] lua_setallocf - [ ] lua_sethook - [ ] lua_tocfunction - - [ ] lua_upvaluejoin - [ ] Auxiliary library - [x] ... - [ ] luaL_addsize @@ -94,10 +92,10 @@ - [x] debug.setupvalue - [x] debug.setuservalue - [x] debug.traceback + - [x] debug.upvalueid + - [x] debug.upvaluejoin - [ ] debug.gethook - [ ] debug.sethook - - [ ] 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 b41cfbe..caafc0a 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -719,6 +719,11 @@ const lua_typename = function(L, t) { return ltm.ttypename(t); }; +const lua_iscfunction = function(L, idx) { + let o = index2addr(L, idx); + return o.ttislcf(o) || o.ttisCclosure(); +}; + const lua_isnil = function(L, n) { return lua_type(L, n) === CT.LUA_TNIL; }; @@ -933,7 +938,8 @@ const getupvalref = function(L, fidx, n, pf) { assert(1 <= n && n <= f.p.upvalues.length, "invalid upvalue index"); return { closure: f, - upval: f.upvals[n - 1] + upval: f.upvals[n - 1], + upvalOff: n - 1 }; }; @@ -955,6 +961,17 @@ const lua_upvalueid = function(L, fidx, n) { } }; +const lua_upvaluejoin = function(L, fidx1, n1, fidx2, n2) { + let ref1 = getupvalref(L, fidx1, n1); + let ref2 = getupvalref(L, fidx2, n2); + let up1 = ref1.upvalOff; + let up2 = ref2.upval; + let f1 = ref1.closure; + + f1.upvals[up1] = up2; + up2.u.open.touched = true; // TODO: useful +}; + // This functions are only there for compatibility purposes const lua_gc = function () {}; @@ -993,6 +1010,7 @@ 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_iscfunction = lua_iscfunction; module.exports.lua_isfunction = lua_isfunction; module.exports.lua_isinteger = lua_isinteger; module.exports.lua_isnil = lua_isnil; @@ -1061,5 +1079,6 @@ 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_upvaluejoin = lua_upvaluejoin; module.exports.lua_version = lua_version; module.exports.lua_xmove = lua_xmove; diff --git a/src/ldblib.js b/src/ldblib.js index 9fc6ce6..27aca96 100644 --- a/src/ldblib.js +++ b/src/ldblib.js @@ -248,13 +248,21 @@ const checkupval = function(L, argf, argnup) { 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 db_upvaluejoin = function(L) { + let n1 = checkupval(L, 1, 2); + let n2 = checkupval(L, 3, 4); + lauxlib.luaL_argcheck(L, !lapi.lua_iscfunction(L, 1), 1, lua.to_luastring("Lua function expected")); + lauxlib.luaL_argcheck(L, !lapi.lua_iscfunction(L, 3), 3, lua.to_luastring("Lua function expected")); + lapi.lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; +}; + const db_traceback = function(L) { let thread = getthread(L); let L1 = thread.thread; @@ -281,7 +289,8 @@ const dblib = { "setupvalue": db_setupvalue, "setuservalue": db_setuservalue, "traceback": db_traceback, - "upvalueid": db_upvalueid + "upvalueid": db_upvalueid, + "upvaluejoin": db_upvaluejoin }; // Only with Node diff --git a/tests/ldblib.js b/tests/ldblib.js index 30a3eb6..7dd35c3 100644 --- a/tests/ldblib.js +++ b/tests/ldblib.js @@ -157,6 +157,51 @@ test('debug.upvalueid', function (t) { }); +test('debug.upvaluejoin', function (t) { + let luaCode = ` + local upvalue1 = "upvalue1" + local upvalue2 = "upvalue2" + + local l1 = function() + return upvalue1 + end + + local l2 = function() + return upvalue2 + end + + debug.upvaluejoin(l1, 1, l2, 1) + + return l1() + `, 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.strictEqual( + lapi.lua_tojsstring(L, -1), + "upvalue2", + "Correct element(s) on the stack" + ); + +}); + + test('debug.traceback (with a global)', function (t) { let luaCode = ` local trace |