aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lapi.js235
-rw-r--r--src/lcode.js49
-rw-r--r--src/ldblib.js5
-rw-r--r--src/ldebug.js22
-rw-r--r--src/llimits.js14
-rw-r--r--src/luaconf.js5
-rw-r--r--src/lualib.js3
-rw-r--r--src/lvm.js25
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<n; i++)
cl.upvalue[i].setfrom(L.stack[L.top - n + i]);
@@ -306,8 +308,7 @@ const lua_pushcclosure = function(L, fn, n) {
--L.top;
L.stack[L.top].setclCvalue(cl);
}
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
const lua_pushjsclosure = lua_pushcclosure;
@@ -320,20 +321,17 @@ const lua_pushjsfunction = lua_pushcfunction;
const lua_pushboolean = function(L, b) {
L.stack[L.top] = new TValue(CT.LUA_TBOOLEAN, b ? true : false);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
const lua_pushlightuserdata = function(L, p) {
L.stack[L.top] = new TValue(CT.LUA_TLIGHTUSERDATA, p);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
const lua_pushthread = function(L) {
L.stack[L.top] = new TValue(CT.LUA_TTHREAD, L);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
return L.l_G.mainthread === L;
};
@@ -350,9 +348,9 @@ const lua_pushglobaltable = function(L) {
*/
const auxsetstr = function(L, t, k) {
let str = lstring.luaS_new(L, defs.from_userstring(k));
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
lobject.pushsvalue2s(L, str); /* push 'str' (to make it a TValue) */
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]);
/* pop value and key */
delete L.stack[--L.top];
@@ -364,13 +362,13 @@ const lua_setglobal = function(L, name) {
};
const lua_setmetatable = function(L, objindex) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let mt;
let obj = index2addr(L, objindex);
if (L.stack[L.top - 1].ttisnil())
mt = null;
else {
- assert(L.stack[L.top - 1].ttistable(), "table expected");
+ api_check(L, L.stack[L.top - 1].ttistable(), "table expected");
mt = L.stack[L.top - 1].value;
}
@@ -391,8 +389,7 @@ const lua_setmetatable = function(L, objindex) {
};
const lua_settable = function(L, idx) {
- assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack");
-
+ api_checknelems(L, 2);
let t = index2addr(L, idx);
lvm.settable(L, t, L.stack[L.top - 2], L.stack[L.top - 1]);
delete L.stack[--L.top];
@@ -404,12 +401,11 @@ const lua_setfield = function(L, idx, k) {
};
const lua_seti = function(L, idx, n) {
- assert(typeof n === "number" && (n|0) === n);
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ fengari_argcheck(typeof n === "number" && (n|0) === n);
+ api_checknelems(L, 1);
let t = index2addr(L, idx);
L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]);
/* pop value and key */
delete L.stack[--L.top];
@@ -417,9 +413,9 @@ const lua_seti = function(L, idx, n) {
};
const lua_rawset = function(L, idx) {
- assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 2);
let o = index2addr(L, idx);
- assert(o.ttistable(), "table expected");
+ api_check(L, o.ttistable(), "table expected");
let k = L.stack[L.top - 2];
let v = L.stack[L.top - 1];
if (v.ttisnil()) {
@@ -434,17 +430,17 @@ const lua_rawset = function(L, idx) {
};
const lua_rawseti = function(L, idx, n) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let o = index2addr(L, idx);
- assert(o.ttistable(), "table expected");
+ api_check(L, o.ttistable(), "table expected");
ltable.luaH_setint(o.value, n, L.stack[L.top - 1]);
delete L.stack[--L.top];
};
const lua_rawsetp = function(L, idx, p) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let o = index2addr(L, idx);
- assert(L, o.ttistable(), "table expected");
+ api_check(L, o.ttistable(), "table expected");
let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
let v = L.stack[L.top - 1];
if (v.ttisnil()) {
@@ -463,31 +459,31 @@ const lua_rawsetp = function(L, idx, p) {
const auxgetstr = function(L, t, k) {
let str = lstring.luaS_new(L, defs.from_userstring(k));
lobject.pushsvalue2s(L, str);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
lvm.luaV_gettable(L, t, L.stack[L.top - 1], L.top - 1);
return L.stack[L.top - 1].ttnov();
};
const lua_rawgeti = function(L, idx, n) {
let t = index2addr(L, idx);
- assert(t.ttistable(), "table expected");
+ api_check(L, t.ttistable(), "table expected");
lobject.pushobj2s(L, ltable.luaH_getint(t.value, n));
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return L.stack[L.top - 1].ttnov();
};
const lua_rawgetp = function(L, idx, p) {
let t = index2addr(L, idx);
- assert(t.ttistable(), "table expected");
+ api_check(L, t.ttistable(), "table expected");
let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
lobject.pushobj2s(L, ltable.luaH_get(L, t.value, k));
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return L.stack[L.top - 1].ttnov();
};
const lua_rawget = function(L, idx) {
let t = index2addr(L, idx);
- assert(t.ttistable(t), "table expected");
+ api_check(L, t.ttistable(t), "table expected");
lobject.setobj2s(L, L.top - 1, ltable.luaH_get(L, t.value, L.stack[L.top - 1]));
return L.stack[L.top - 1].ttnov();
};
@@ -496,8 +492,7 @@ const lua_rawget = function(L, idx) {
const lua_createtable = function(L, narray, nrec) {
let t = new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L));
L.stack[L.top] = t;
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
const luaS_newudata = function(L, size) {
@@ -507,8 +502,7 @@ const luaS_newudata = function(L, size) {
const lua_newuserdata = function(L, size) {
let u = luaS_newudata(L, size);
L.stack[L.top] = new lobject.TValue(CT.LUA_TUSERDATA, u);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
return u.data;
};
@@ -542,7 +536,7 @@ const lua_getupvalue = function(L, funcindex, n) {
let name = up.name;
let val = up.val;
lobject.pushobj2s(L, val);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return name;
}
return null;
@@ -550,7 +544,7 @@ const lua_getupvalue = function(L, funcindex, n) {
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");
+ api_checknelems(L, 1);
let aux = aux_upvalue(L, fi, n);
if (aux) {
let name = aux.name;
@@ -587,8 +581,7 @@ const lua_getmetatable = function(L, objindex) {
if (mt !== null && mt !== undefined) {
L.stack[L.top] = new TValue(CT.LUA_TTABLE, mt);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
res = true;
}
@@ -597,11 +590,10 @@ const lua_getmetatable = function(L, objindex) {
const lua_getuservalue = function(L, idx) {
let o = index2addr(L, idx);
- assert(L, o.ttisfulluserdata(), "full userdata expected");
+ api_check(L, o.ttisfulluserdata(), "full userdata expected");
let uv = o.value.uservalue;
L.stack[L.top] = new TValue(uv.type, uv.value);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
return L.stack[L.top - 1].ttnov();
};
@@ -616,11 +608,10 @@ const lua_getfield = function(L, idx, k) {
};
const lua_geti = function(L, idx, n) {
- assert(typeof n === "number" && (n|0) === n);
+ fengari_argcheck(typeof n === "number" && (n|0) === n);
let t = index2addr(L, idx);
L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
lvm.luaV_gettable(L, t, L.stack[L.top - 1], L.top - 1);
return L.stack[L.top - 1].ttnov();
};
@@ -759,10 +750,9 @@ const lua_isproxy = function(p, L) {
/* Use 'create_proxy' helper function so that 'L' is not in scope */
const create_proxy = function(G, type, value) {
let proxy = function(L) {
- assert(L instanceof lstate.lua_State && G === L.l_G, "must be from same global state");
+ api_check(L, L instanceof lstate.lua_State && G === L.l_G, "must be from same global state");
L.stack[L.top] = new TValue(type, value);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
seen.set(proxy, G);
return proxy;
@@ -786,7 +776,7 @@ const lua_compare = function(L, index1, index2, op) {
case defs.LUA_OPEQ: i = lvm.luaV_equalobj(L, o1, o2); break;
case defs.LUA_OPLT: i = lvm.luaV_lessthan(L, o1, o2); break;
case defs.LUA_OPLE: i = lvm.luaV_lessequal(L, o1, o2); break;
- default: assert(false, "invalid option");
+ default: api_check(L, false, "invalid option");
}
}
@@ -798,8 +788,7 @@ const lua_stringtonumber = function(L, s) {
let sz = lobject.luaO_str2num(s, tv);
if (sz !== 0) {
L.stack[L.top] = tv;
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
}
return sz;
};
@@ -814,7 +803,7 @@ const lua_type = function(L, idx) {
};
const lua_typename = function(L, t) {
- assert(CT.LUA_TNONE <= t && t < CT.LUA_NUMTAGS, "invalid tag");
+ api_check(L, CT.LUA_TNONE <= t && t < CT.LUA_NUMTAGS, "invalid tag");
return ltm.ttypename(t);
};
@@ -881,11 +870,11 @@ const lua_rawequal = function(L, index1, index2) {
const lua_arith = function(L, op) {
if (op !== defs.LUA_OPUNM && op !== defs.LUA_OPBNOT)
- assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack"); /* all other operations expect two operands */
+ api_checknelems(L, 2); /* all other operations expect two operands */
else { /* for unary operations, add fake 2nd operand */
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
lobject.pushobj2s(L, L.stack[L.top-1]);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
}
/* first operand at top - 2, second at top - 1; result go to top - 2 */
lobject.luaO_arith(L, op, L.stack[L.top - 2], L.stack[L.top - 1], L.stack[L.top - 2]);
@@ -916,7 +905,7 @@ const lua_load = function(L, reader, data, chunkname, mode) {
};
const lua_dump = function(L, writer, data, strip) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let o = L.stack[L.top -1];
if (o.ttisLclosure())
return ldump.luaU_dump(L, o.value.p, writer, data, strip);
@@ -928,19 +917,23 @@ const lua_status = function(L) {
};
const lua_setuservalue = function(L, idx) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let o = index2addr(L, idx);
- assert(L, o.ttisfulluserdata(), "full userdata expected");
+ api_check(L, o.ttisfulluserdata(), "full userdata expected");
o.value.uservalue.setfrom(L.stack[L.top - 1]);
delete L.stack[--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");
- 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");
+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) */