From 214dcf73833f7a29c58eef2b85d68ee3277039f0 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Thu, 18 Jan 2018 04:29:58 +1100 Subject: src/: Start using lua_assert() instead of plain assert() --- src/lapi.js | 235 +++++++++++++++++++++++++++------------------------------ src/lcode.js | 49 ++++++------ src/ldblib.js | 5 +- src/ldebug.js | 22 +++--- src/llimits.js | 14 ++++ src/luaconf.js | 5 ++ src/lualib.js | 3 + src/lvm.js | 25 +++--- 8 files changed, 185 insertions(+), 173 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 4836e12..29f70bb 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -1,8 +1,10 @@ "use strict"; -const assert = require('assert'); - const defs = require('./defs.js'); +const { + api_check, + lua_assert +} = require('./llimits.js'); const ldebug = require('./ldebug.js'); const ldo = require('./ldo.js'); const ldump = require('./ldump.js'); @@ -21,6 +23,19 @@ const TS = defs.thread_status; const TValue = lobject.TValue; const CClosure = lobject.CClosure; +const api_incr_top = function(L) { + L.top++; + api_check(L, L.top <= L.ci.top, "stack overflow"); +}; + +const api_checknelems = function(L, n) { + api_check(L, n < (L.top - L.ci.funcOff), "not enough elements in the stack"); +}; + +const fengari_argcheck = function(c) { + if (!c) throw TypeError("invalid argument"); +}; + const isvalid = function(o) { return o !== lobject.luaO_nilobject; }; @@ -47,17 +62,17 @@ const index2addr = function(L, idx) { let ci = L.ci; if (idx > 0) { let o = ci.funcOff + idx; - assert(idx <= ci.top - (ci.funcOff + 1), "unacceptable index"); + api_check(L, idx <= ci.top - (ci.funcOff + 1), "unacceptable index"); if (o >= L.top) return lobject.luaO_nilobject; else return L.stack[o]; } else if (idx > defs.LUA_REGISTRYINDEX) { - assert(idx !== 0 && -idx <= L.top, "invalid index"); + api_check(L, idx !== 0 && -idx <= L.top, "invalid index"); return L.stack[L.top + idx]; } else if (idx === defs.LUA_REGISTRYINDEX) { return L.l_G.l_registry; } else { /* upvalues */ idx = defs.LUA_REGISTRYINDEX - idx; - assert(idx <= MAXUPVAL + 1, "upvalue index too large"); + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); if (ci.func.ttislcf()) /* light C function? */ return lobject.luaO_nilobject; /* it has no upvalues */ else { @@ -71,11 +86,11 @@ const index2addr_ = function(L, idx) { let ci = L.ci; if (idx > 0) { let o = ci.funcOff + idx; - assert(idx <= ci.top - (ci.funcOff + 1), "unacceptable index"); + api_check(L, idx <= ci.top - (ci.funcOff + 1), "unacceptable index"); if (o >= L.top) return null; else return o; } else if (idx > defs.LUA_REGISTRYINDEX) { - assert(idx !== 0 && -idx <= L.top, "invalid index"); + api_check(L, idx !== 0 && -idx <= L.top, "invalid index"); return L.top + idx; } else { /* registry or upvalue */ throw Error("attempt to use pseudo-index"); @@ -85,7 +100,7 @@ const index2addr_ = function(L, idx) { const lua_checkstack = function(L, n) { let res; let ci = L.ci; - assert(n >= 0, "negative 'n'"); + api_check(L, n >= 0, "negative 'n'"); if (L.stack_last - L.top > n) /* stack large enough? */ res = true; else { /* no; need to grow stack */ @@ -106,10 +121,9 @@ const lua_checkstack = function(L, n) { const lua_xmove = function(from, to, n) { if (from === to) return; - assert(n < (from.top - from.ci.funcOff), "not enough elements in the stack"); - assert(from.l_G === to.l_G, "moving among independent states"); - assert(to.ci.top - to.top >= n, "stack overflow"); - + api_checknelems(from, n); + api_check(from, from.l_G === to.l_G, "moving among independent states"); + api_check(from, to.ci.top - to.top >= n, "stack overflow"); from.top -= n; for (let i = 0; i < n; i++) { to.stack[to.top] = new lobject.TValue(); @@ -138,17 +152,17 @@ const lua_gettop = function(L) { const lua_pushvalue = function(L, idx) { lobject.pushobj2s(L, index2addr(L, idx)); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); }; const lua_settop = function(L, idx) { let func = L.ci.funcOff; let newtop; if (idx >= 0) { - assert(idx <= L.stack_last - (func + 1), "new top too large"); + api_check(L, idx <= L.stack_last - (func + 1), "new top too large"); newtop = func + 1 + idx; } else { - assert(-(idx + 1) <= L.top - (func + 1), "invalid new top"); + api_check(L, -(idx + 1) <= L.top - (func + 1), "invalid new top"); newtop = L.top + idx + 1; /* 'subtract' index (index is negative) */ } ldo.adjust_top(L, newtop); @@ -175,12 +189,9 @@ const lua_rotate = function(L, idx, n) { let t = L.top - 1; let pIdx = index2addr_(L, idx); let p = L.stack[pIdx]; - - assert(isvalid(p) && idx > defs.LUA_REGISTRYINDEX, "index not in the stack"); - assert((n >= 0 ? n : -n) <= (t - pIdx + 1), "invalid 'n'"); - + api_check(L, isvalid(p) && idx > defs.LUA_REGISTRYINDEX, "index not in the stack"); + api_check(L, (n >= 0 ? n : -n) <= (t - pIdx + 1), "invalid 'n'"); let m = n >= 0 ? t - n : pIdx - n - 1; /* end of prefix */ - reverse(L, pIdx, m); reverse(L, m + 1, L.top - 1); reverse(L, pIdx, L.top - 1); @@ -211,39 +222,34 @@ const lua_replace = function(L, idx) { const lua_pushnil = function(L) { L.stack[L.top] = new TValue(CT.LUA_TNIL, null); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); }; const lua_pushnumber = function(L, n) { - assert(typeof n === "number"); - + fengari_argcheck(L, typeof n === "number"); L.stack[L.top] = new TValue(CT.LUA_TNUMFLT, n); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); }; const lua_pushinteger = function(L, n) { - assert(typeof n === "number" && (n|0) === n); + fengari_argcheck(L, typeof n === "number" && (n|0) === n); L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n); - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); }; const lua_pushlstring = function(L, s, len) { - assert(typeof len === "number"); + fengari_argcheck(L, typeof len === "number"); let ts; if (len === 0) { s = defs.to_luastring("", true); ts = lstring.luaS_bless(L, s); } else { s = defs.from_userstring(s); - assert(s.length >= len, "invalid length to lua_pushlstring"); + api_check(L, s.length >= len, "invalid length to lua_pushlstring"); ts = lstring.luaS_new(L, s.subarray(0, len)); } lobject.pushsvalue2s(L, ts); - assert(L.top <= L.ci.top, "stack overflow"); - + api_check(L, L.top <= L.ci.top, "stack overflow"); return ts.value; }; @@ -256,8 +262,7 @@ const lua_pushstring = function (L, s) { lobject.pushsvalue2s(L, ts); s = ts.getstr(); /* internal copy */ } - assert(L.top <= L.ci.top, "stack overflow"); - + api_check(L, L.top <= L.ci.top, "stack overflow"); return s; }; @@ -277,26 +282,23 @@ const lua_pushliteral = function (L, s) { L.stack[L.top] = new TValue(CT.LUA_TNIL, null); L.top++; } else { - assert(typeof s === "string", "lua_pushliteral expects a JS string"); + fengari_argcheck(typeof s === "string", "lua_pushliteral expects a JS string"); let ts = lstring.luaS_newliteral(L, s); lobject.pushsvalue2s(L, ts); s = ts.getstr(); /* internal copy */ } - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); return s; }; const lua_pushcclosure = function(L, fn, n) { - assert(typeof fn === "function"); - assert(typeof n === "number"); - + fengari_argcheck(typeof fn === "function" || typeof n === "number"); if (n === 0) L.stack[L.top] = new TValue(CT.LUA_TLCF, fn); else { - assert(n < L.top - L.ci.funcOff, "not enough elements in the stack"); - assert(n <= MAXUPVAL, "upvalue index too large"); - + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); let cl = new CClosure(L, fn, n); for (let i=0; i= nargs - nresults), "results from function overflow current stack size"); +const checkresults = function(L,na,nr) { + api_check(L, (nr) == defs.LUA_MULTRET || (L.ci.top - L.top >= (nr) - (na)), + "results from function overflow current stack size"); +}; +const lua_callk = function(L, nargs, nresults, ctx, k) { + api_check(L, k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks"); + api_checknelems(L, nargs + 1); + api_check(L, L.status === TS.LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); let func = L.top - (nargs + 1); if (k !== null && L.nny === 0) { /* need to prepare continuation? */ L.ci.c_k = k; @@ -959,10 +952,10 @@ const lua_call = function(L, n, r) { }; const lua_pcallk = function(L, nargs, nresults, errfunc, ctx, k) { - assert(nargs + 1 < L.top - L.ci.funcOff, "not enough elements in the stack"); - assert(L.status === TS.LUA_OK, "cannot do calls on non-normal thread"); - assert(nargs === defs.LUA_MULTRET || (L.ci.top - L.top >= nargs - nresults), "results from function overflow current stack size"); - + api_check(L, k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks"); + api_checknelems(L, nargs + 1); + api_check(L, L.status === TS.LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); let c = { func: null, funcOff: NaN, @@ -1016,18 +1009,17 @@ const lua_pcall = function(L, n, r, f) { */ const lua_error = function(L) { - assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, 1); ldebug.luaG_errormsg(L); }; const lua_next = function(L, idx) { let t = index2addr(L, idx); - assert(t.ttistable(), "table expected"); + api_check(L, t.ttistable(), "table expected"); L.stack[L.top] = new TValue(); let more = ltable.luaH_next(L, t.value, L.top - 1); if (more) { - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); return 1; } else { delete L.stack[L.top]; @@ -1037,12 +1029,12 @@ const lua_next = function(L, idx) { }; const lua_concat = function(L, n) { - assert(n < L.top - L.ci.funcOff, "not enough elements in the stack"); + api_checknelems(L, n); if (n >= 2) lvm.luaV_concat(L, n); else if (n === 0) { lobject.pushsvalue2s(L, lstring.luaS_bless(L, defs.to_luastring("", true))); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); } }; @@ -1051,15 +1043,14 @@ const lua_len = function(L, idx) { let tv = new TValue(); lvm.luaV_objlen(L, tv, t); L.stack[L.top] = tv; - L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + api_incr_top(L); }; const getupvalref = function(L, fidx, n) { let fi = index2addr(L, fidx); - assert(fi.ttisLclosure(), "Lua function expected"); + api_check(L, fi.ttisLclosure(), "Lua function expected"); let f = fi.value; - assert(1 <= n && n <= f.p.upvalues.length, "invalid upvalue index"); + api_check(L, 1 <= n && n <= f.p.upvalues.length, "invalid upvalue index"); return { closure: f, upval: f.upvals[n - 1], @@ -1075,11 +1066,11 @@ const lua_upvalueid = function(L, fidx, n) { } case CT.LUA_TCCL: { /* C closure */ let f = fi.value; - assert(1 <= n && n <= f.nupvalues, "invalid upvalue index"); + api_check(L, 1 <= n && n <= f.nupvalues, "invalid upvalue index"); return f.upvalue[n - 1]; } default: { - assert(false, "closure expected"); + api_check(L, false, "closure expected"); return null; } } @@ -1091,7 +1082,7 @@ const lua_upvaluejoin = function(L, fidx1, n1, fidx2, n2) { let up1 = ref1.upval; let up2 = ref2.upval; let f1 = ref1.closure; - assert(up1.refcount > 0); + lua_assert(up1.refcount > 0); up1.refcount--; f1.upvals[ref1.upvalOff] = up2; up2.refcount++; diff --git a/src/lcode.js b/src/lcode.js index 8646144..88885b9 100644 --- a/src/lcode.js +++ b/src/lcode.js @@ -1,8 +1,7 @@ "use strict"; -const assert = require('assert'); - const defs = require('./defs.js'); +const { lua_assert } = require("./llimits.js"); const llex = require('./llex.js'); const lobject = require('./lobject.js'); const lopcodes = require('./lopcodes.js'); @@ -141,7 +140,7 @@ const getjump = function(fs, pc) { const fixjump = function(fs, pc, dest) { let jmp = fs.f.code[pc]; let offset = dest - (pc + 1); - assert(dest !== NO_JUMP); + lua_assert(dest !== NO_JUMP); if (Math.abs(offset) > lopcodes.MAXARG_sBx) llex.luaX_syntaxerror(fs.ls, defs.to_luastring("control structure too long", true)); lopcodes.SETARG_sBx(jmp, offset); @@ -299,7 +298,7 @@ const luaK_patchlist = function(fs, list, target) { if (target === fs.pc) /* 'target' is current position? */ luaK_patchtohere(fs, list); /* add list to pending jumps */ else { - assert(target < fs.pc); + lua_assert(target < fs.pc); patchlistaux(fs, list, target, lopcodes.NO_REG, target); } }; @@ -313,7 +312,7 @@ const luaK_patchclose = function(fs, list, level) { level++; /* argument is +1 to reserve 0 as non-op */ for (; list !== NO_JUMP; list = getjump(fs, list)) { let ins = fs.f.code[list]; - assert(ins.opcode === OpCodesI.OP_JMP && (ins.A === 0 || ins.A >= level)); + lua_assert(ins.opcode === OpCodesI.OP_JMP && (ins.A === 0 || ins.A >= level)); lopcodes.SETARG_A(ins, level); } }; @@ -336,10 +335,10 @@ const luaK_code = function(fs, i) { ** of parameters versus opcode.) */ const luaK_codeABC = function(fs, o, a, b, c) { - assert(lopcodes.getOpMode(o) === lopcodes.iABC); - assert(lopcodes.getBMode(o) !== lopcodes.OpArgN || b === 0); - assert(lopcodes.getCMode(o) !== lopcodes.OpArgN || c === 0); - assert(a <= lopcodes.MAXARG_A && b <= lopcodes.MAXARG_B && c <= lopcodes.MAXARG_C); + lua_assert(lopcodes.getOpMode(o) === lopcodes.iABC); + lua_assert(lopcodes.getBMode(o) !== lopcodes.OpArgN || b === 0); + lua_assert(lopcodes.getCMode(o) !== lopcodes.OpArgN || c === 0); + lua_assert(a <= lopcodes.MAXARG_A && b <= lopcodes.MAXARG_B && c <= lopcodes.MAXARG_C); return luaK_code(fs, lopcodes.CREATE_ABC(o, a, b, c)); }; @@ -347,9 +346,9 @@ const luaK_codeABC = function(fs, o, a, b, c) { ** Format and emit an 'iABx' instruction. */ const luaK_codeABx = function(fs, o, a, bc) { - assert(lopcodes.getOpMode(o) === lopcodes.iABx || lopcodes.getOpMode(o) === lopcodes.iAsBx); - assert(lopcodes.getCMode(o) === lopcodes.OpArgN); - assert(a <= lopcodes.MAXARG_A && bc <= lopcodes.MAXARG_Bx); + lua_assert(lopcodes.getOpMode(o) === lopcodes.iABx || lopcodes.getOpMode(o) === lopcodes.iAsBx); + lua_assert(lopcodes.getCMode(o) === lopcodes.OpArgN); + lua_assert(a <= lopcodes.MAXARG_A && bc <= lopcodes.MAXARG_Bx); return luaK_code(fs, lopcodes.CREATE_ABx(o, a, bc)); }; @@ -361,7 +360,7 @@ const luaK_codeAsBx = function(fs,o,A,sBx) { ** Emit an "extra argument" instruction (format 'iAx') */ const codeextraarg = function(fs, a) { - assert(a <= lopcodes.MAXARG_Ax); + lua_assert(a <= lopcodes.MAXARG_Ax); return luaK_code(fs, lopcodes.CREATE_Ax(OpCodesI.OP_EXTRAARG, a)); }; @@ -408,7 +407,7 @@ const luaK_reserveregs = function(fs, n) { const freereg = function(fs, reg) { if (!lopcodes.ISK(reg) && reg >= fs.nactvar) { fs.freereg--; - assert(reg === fs.freereg); + lua_assert(reg === fs.freereg); } }; @@ -526,7 +525,7 @@ const luaK_setreturns = function(fs, e, nresults) { lopcodes.SETARG_A(pc, fs.freereg); luaK_reserveregs(fs, 1); } - else assert(nresults === defs.LUA_MULTRET); + else lua_assert(nresults === defs.LUA_MULTRET); }; const luaK_setmultret = function(fs, e) { @@ -547,7 +546,7 @@ const luaK_setoneret = function(fs, e) { let ek = lparser.expkind; if (e.k === ek.VCALL) { /* expression is an open function call? */ /* already returns 1 value */ - assert(getinstruction(fs, e).C === 2); + lua_assert(getinstruction(fs, e).C === 2); e.k = ek.VNONRELOC; /* result has fixed position */ e.u.info = getinstruction(fs, e).A; } else if (e.k === ek.VVARARG) { @@ -579,7 +578,7 @@ const luaK_dischargevars = function(fs, e) { freereg(fs, e.u.ind.t); op = OpCodesI.OP_GETTABLE; } else { - assert(e.u.ind.vt === ek.VUPVAL); + lua_assert(e.u.ind.vt === ek.VUPVAL); op = OpCodesI.OP_GETTABUP; /* 't' is in an upvalue */ } e.u.info = luaK_codeABC(fs, op, 0, e.u.ind.t, e.u.ind.idx); @@ -638,7 +637,7 @@ const discharge2reg = function(fs, e, reg) { break; } default: { - assert(e.k === ek.VJMP); + lua_assert(e.k === ek.VJMP); return; /* nothing to do... */ } } @@ -825,7 +824,7 @@ const luaK_self = function(fs, e, key) { */ const negatecondition = function(fs, e) { let pc = getjumpcontrol(fs, e.u.info); - assert(lopcodes.testTMode(pc.opcode) && pc.opcode !== OpCodesI.OP_TESTSET && pc.opcode !== OpCodesI.OP_TEST); + lua_assert(lopcodes.testTMode(pc.opcode) && pc.opcode !== OpCodesI.OP_TESTSET && pc.opcode !== OpCodesI.OP_TEST); lopcodes.SETARG_A(pc, !(pc.A)); }; @@ -942,7 +941,7 @@ const codenot = function(fs, e) { */ const luaK_indexed = function(fs, t, k) { let ek = lparser.expkind; - assert(!hasjumps(t) && (lparser.vkisinreg(t.k) || t.k === ek.VUPVAL)); + lua_assert(!hasjumps(t) && (lparser.vkisinreg(t.k) || t.k === ek.VUPVAL)); t.u.ind.t = t.u.info; /* register or upvalue index */ t.u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ t.u.ind.vt = (t.k === ek.VUPVAL) ? ek.VUPVAL : ek.VLOCAL; @@ -1034,7 +1033,7 @@ const codecomp = function(fs, opr, e1, e2) { if (e1.k === ek.VK) rk1 = lopcodes.RKASK(e1.u.info); else { - assert(e1.k === ek.VNONRELOC); + lua_assert(e1.k === ek.VNONRELOC); rk1 = e1.u.info; } @@ -1126,14 +1125,14 @@ const luaK_posfix = function(fs, op, e1, e2, line) { let ek = lparser.expkind; switch (op) { case BinOpr.OPR_AND: { - assert(e1.t === NO_JUMP); /* list closed by 'luK_infix' */ + lua_assert(e1.t === NO_JUMP); /* list closed by 'luK_infix' */ luaK_dischargevars(fs, e2); e2.f = luaK_concat(fs, e2.f, e1.f); e1.to(e2); break; } case BinOpr.OPR_OR: { - assert(e1.f === NO_JUMP); /* list closed by 'luK_infix' */ + lua_assert(e1.f === NO_JUMP); /* list closed by 'luK_infix' */ luaK_dischargevars(fs, e2); e2.t = luaK_concat(fs, e2.t, e1.t); e1.to(e2); @@ -1143,7 +1142,7 @@ const luaK_posfix = function(fs, op, e1, e2, line) { luaK_exp2val(fs, e2); let ins = getinstruction(fs, e2); if (e2.k === ek.VRELOCABLE && ins.opcode === OpCodesI.OP_CONCAT) { - assert(e1.u.info === ins.B - 1); + lua_assert(e1.u.info === ins.B - 1); freeexp(fs, e1); lopcodes.SETARG_B(ins, e1.u.info); e1.k = ek.VRELOCABLE; e1.u.info = e2.u.info; @@ -1189,7 +1188,7 @@ const luaK_fixline = function(fs, line) { const luaK_setlist = function(fs, base, nelems, tostore) { let c = (nelems - 1)/lopcodes.LFIELDS_PER_FLUSH + 1; let b = (tostore === defs.LUA_MULTRET) ? 0 : tostore; - assert(tostore !== 0 && tostore <= lopcodes.LFIELDS_PER_FLUSH); + lua_assert(tostore !== 0 && tostore <= lopcodes.LFIELDS_PER_FLUSH); if (c <= lopcodes.MAXARG_C) luaK_codeABC(fs, OpCodesI.OP_SETLIST, base, b, c); else if (c <= lopcodes.MAXARG_Ax) { diff --git a/src/ldblib.js b/src/ldblib.js index 9698f7a..d7cf629 100644 --- a/src/ldblib.js +++ b/src/ldblib.js @@ -1,9 +1,8 @@ "use strict"; -const assert = require('assert'); - const lua = require('./lua.js'); const lauxlib = require('./lauxlib.js'); +const lualib = require('./lualib.js'); const {luastring_indexOf, to_luastring} = require("./fengaricore.js"); /* @@ -282,7 +281,7 @@ const hookf = function(L, ar) { if (ar.currentline >= 0) lua.lua_pushinteger(L, ar.currentline); /* push current line */ else lua.lua_pushnil(L); - assert(lua.lua_getinfo(L, to_luastring("lS"), ar)); + lualib.lua_assert(lua.lua_getinfo(L, to_luastring("lS"), ar)); lua.lua_call(L, 2, 0); /* call hook function */ } }; diff --git a/src/ldebug.js b/src/ldebug.js index 2aa8396..5a0e480 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -1,8 +1,10 @@ "use strict"; -const assert = require('assert'); - const defs = require('./defs.js'); +const { + api_check, + lua_assert +} = require('./llimits.js'); const ldo = require('./ldo.js'); const lfunc = require('./lfunc.js'); const llex = require('./llex.js'); @@ -19,7 +21,7 @@ const CT = defs.constant_types; const TS = defs.thread_status; const currentpc = function(ci) { - assert(ci.callstatus & lstate.CIST_LUA); + lua_assert(ci.callstatus & lstate.CIST_LUA); return ci.l_savedpc - 1; }; @@ -85,7 +87,7 @@ const lua_getstack = function(L, level, ar) { }; const upvalname = function(p, uv) { - assert(uv < p.upvalues.length); + lua_assert(uv < p.upvalues.length); let s = p.upvalues[uv].name; if (s === null) return defs.to_luastring("?", true); return s.getstr(); @@ -142,7 +144,7 @@ const lua_getlocal = function(L, ar, n) { if (local) { name = local.name; lobject.pushobj2s(L, L.stack[local.pos]); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); } else { name = null; } @@ -187,13 +189,13 @@ const collectvalidlines = function(L, f) { if (f === null || f instanceof lobject.CClosure) { L.stack[L.top] = new lobject.TValue(CT.LUA_TNIL, null); L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + lua_assert(L.top <= L.ci.top, "stack overflow"); } else { let lineinfo = f.p.lineinfo; let t = ltable.luaH_new(L); L.stack[L.top] = new lobject.TValue(CT.LUA_TTABLE, t); L.top++; - assert(L.top <= L.ci.top, "stack overflow"); + lua_assert(L.top <= L.ci.top, "stack overflow"); let v = new lobject.TValue(CT.LUA_TBOOLEAN, true); for (let i = 0; i < lineinfo.length; i++) ltable.luaH_setint(t, lineinfo[i], v); @@ -273,20 +275,20 @@ const lua_getinfo = function(L, what, ar) { if (what[0] === char['>']) { ci = null; func = L.stack[L.top - 1]; - assert(L, func.ttisfunction(), "function expected"); + api_check(L, func.ttisfunction(), "function expected"); what = what.subarray(1); /* skip the '>' */ L.top--; /* pop function */ } else { ci = ar.i_ci; func = ci.func; - assert(ci.func.ttisfunction()); + lua_assert(ci.func.ttisfunction()); } cl = func.ttisclosure() ? func.value : null; status = auxgetinfo(L, what, ar, cl, ci); if (defs.luastring_indexOf(what, char['f']) >= 0) { lobject.pushobj2s(L, func); - assert(L.top <= L.ci.top, "stack overflow"); + api_check(L, L.top <= L.ci.top, "stack overflow"); } swapextra(L); diff --git a/src/llimits.js b/src/llimits.js index 4a76bbe..bd48159 100644 --- a/src/llimits.js +++ b/src/llimits.js @@ -1,5 +1,19 @@ "use strict"; +const {luai_apicheck} = require("./luaconf.js"); + +const lua_assert = function(c) { + if (!c) throw Error("assertion failed"); +}; +module.exports.lua_assert = lua_assert; + +module.exports.luai_apicheck = luai_apicheck || function(l, e) { return lua_assert(e); }; + +const api_check = function(l, e, msg) { + return luai_apicheck(l, e && msg); +}; +module.exports.api_check = api_check; + const LUAI_MAXCCALLS = 200; module.exports.LUAI_MAXCCALLS = LUAI_MAXCCALLS; diff --git a/src/luaconf.js b/src/luaconf.js index 4bf8583..c2a7781 100644 --- a/src/luaconf.js +++ b/src/luaconf.js @@ -41,6 +41,10 @@ const lua_getlocaledecpoint = function() { return (1.1).toLocaleString().substring(1, 2); }; +const luai_apicheck = function(l, e) { + if (!e) throw Error(e); +}; + // See: http://croquetweak.blogspot.fr/2014/08/deconstructing-floats-frexp-and-ldexp.html const frexp = function(value) { if (value === 0) return [value, 0]; @@ -78,3 +82,4 @@ module.exports.lua_getlocaledecpoint = lua_getlocaledecpoint; module.exports.lua_integer2str = lua_integer2str; module.exports.lua_number2str = lua_number2str; module.exports.lua_numbertointeger = lua_numbertointeger; +module.exports.luai_apicheck = luai_apicheck; diff --git a/src/lualib.js b/src/lualib.js index 4fbae44..61bbc76 100644 --- a/src/lualib.js +++ b/src/lualib.js @@ -49,3 +49,6 @@ module.exports.LUA_LOADLIBNAME = LUA_LOADLIBNAME; module.exports.luaopen_package = require("./loadlib.js").luaopen_package; module.exports.luaL_openlibs = linit.luaL_openlibs; + +/* customary export */ +module.exports.lua_assert = function(c) {}; diff --git a/src/lvm.js b/src/lvm.js index 3ace940..d0917b0 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -1,7 +1,5 @@ "use strict"; -const assert = require('assert'); - const { LUA_MASKLINE, LUA_MASKCOUNT, @@ -81,6 +79,7 @@ const { lua_numbertointeger } = require('./luaconf.js'); const { + lua_assert, luai_nummod } = require('./llimits.js'); const lobject = require('./lobject.js'); @@ -115,11 +114,11 @@ const luaV_finishOp = function(L) { let res = !L.stack[L.top - 1].l_isfalse(); delete L.stack[--L.top]; if (ci.callstatus & lstate.CIST_LEQ) { /* "<=" using "<" instead? */ - assert(op === OP_LE); + lua_assert(op === OP_LE); ci.callstatus ^= lstate.CIST_LEQ; /* clear mark */ res = !res; /* negate result */ } - assert(ci.l_code[ci.l_savedpc].opcode === OP_JMP); + lua_assert(ci.l_code[ci.l_savedpc].opcode === OP_JMP); if (res !== (inst.A ? true : false)) /* condition failed? */ ci.l_savedpc++; /* skip jump instruction */ break; @@ -139,7 +138,7 @@ const luaV_finishOp = function(L) { break; } case OP_TFORCALL: { - assert(ci.l_code[ci.l_savedpc].opcode === OP_TFORLOOP); + lua_assert(ci.l_code[ci.l_savedpc].opcode === OP_TFORLOOP); ldo.adjust_top(L, ci.top); /* correct top */ break; } @@ -177,7 +176,7 @@ const luaV_execute = function(L) { ci.callstatus |= lstate.CIST_FRESH; newframe: for (;;) { - assert(ci === L.ci); + lua_assert(ci === L.ci); let cl = ci.func.value; let k = cl.p.k; let base = ci.l_base; @@ -202,7 +201,7 @@ const luaV_execute = function(L) { break; } case OP_LOADKX: { - assert(ci.l_code[ci.l_savedpc].opcode === OP_EXTRAARG); + lua_assert(ci.l_code[ci.l_savedpc].opcode === OP_EXTRAARG); let konst = k[ci.l_code[ci.l_savedpc++].Ax]; lobject.setobj2s(L, ra, konst); break; @@ -545,7 +544,7 @@ const luaV_execute = function(L) { oci.next = null; ci = L.ci = oci; - assert(L.top === oci.l_base + L.stack[ofuncOff].value.p.maxstacksize); + lua_assert(L.top === oci.l_base + L.stack[ofuncOff].value.p.maxstacksize); continue newframe; } @@ -560,8 +559,8 @@ const luaV_execute = function(L) { /* invocation via reentry: continue execution */ ci = L.ci; if (b) ldo.adjust_top(L, ci.top); - assert(ci.callstatus & lstate.CIST_LUA); - assert(ci.l_code[ci.l_savedpc - 1].opcode === OP_CALL); + lua_assert(ci.callstatus & lstate.CIST_LUA); + lua_assert(ci.l_code[ci.l_savedpc - 1].opcode === OP_CALL); continue newframe; } case OP_FORLOOP: { @@ -626,7 +625,7 @@ const luaV_execute = function(L) { /* go straight to OP_TFORLOOP */ i = ci.l_code[ci.l_savedpc++]; ra = RA(L, base, i); - assert(i.opcode === OP_TFORLOOP); + lua_assert(i.opcode === OP_TFORLOOP); } /* fall through */ case OP_TFORLOOP: { @@ -643,7 +642,7 @@ const luaV_execute = function(L) { if (n === 0) n = L.top - ra - 1; if (c === 0) { - assert(ci.l_code[ci.l_savedpc].opcode === OP_EXTRAARG); + lua_assert(ci.l_code[ci.l_savedpc].opcode === OP_EXTRAARG); c = ci.l_code[ci.l_savedpc++].Ax; } @@ -1040,7 +1039,7 @@ const copy2buff = function(L, top, n, buff) { ** from 'L->top - total' up to 'L->top - 1'. */ const luaV_concat = function(L, total) { - assert(total >= 2); + lua_assert(total >= 2); do { let top = L.top; let n = 2; /* number of elements handled in this pass (at least 2) */ -- cgit v1.2.3-54-g00ecf