aboutsummaryrefslogtreecommitdiff
path: root/src/lapi.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/lapi.js')
-rw-r--r--src/lapi.js465
1 files changed, 240 insertions, 225 deletions
diff --git a/src/lapi.js b/src/lapi.js
index b42ad92..6196812 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -1,32 +1,76 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ LUA_MULTRET,
+ LUA_OPBNOT,
+ LUA_OPEQ,
+ LUA_OPLE,
+ LUA_OPLT,
+ LUA_OPUNM,
+ LUA_REGISTRYINDEX,
+ LUA_RIDX_GLOBALS,
+ LUA_VERSION_NUM,
+ constant_types: {
+ LUA_NUMTAGS,
+ LUA_TBOOLEAN,
+ LUA_TCCL,
+ LUA_TFUNCTION,
+ LUA_TLCF,
+ LUA_TLCL,
+ LUA_TLIGHTUSERDATA,
+ LUA_TLNGSTR,
+ LUA_TNIL,
+ LUA_TNONE,
+ LUA_TNUMFLT,
+ LUA_TNUMINT,
+ LUA_TSHRSTR,
+ LUA_TTABLE,
+ LUA_TTHREAD,
+ LUA_TUSERDATA
+ },
+ thread_status: { LUA_OK },
+ from_userstring,
+ to_luastring,
+} = require('./defs.js');
+const { api_check } = require('./llimits.js');
const ldebug = require('./ldebug.js');
const ldo = require('./ldo.js');
-const ldump = require('./ldump.js');
+const { luaU_dump } = require('./ldump.js');
const lfunc = require('./lfunc.js');
const lobject = require('./lobject.js');
const lstate = require('./lstate.js');
-const lstring = require('./lstring.js');
+const {
+ luaS_bless,
+ luaS_new,
+ luaS_newliteral
+} = require('./lstring.js');
const ltm = require('./ltm.js');
-const luaconf = require('./luaconf.js');
+const { LUAI_MAXSTACK } = require('./luaconf.js');
const lvm = require('./lvm.js');
const ltable = require('./ltable.js');
-const lzio = require('./lzio.js');
-const MAXUPVAL = lfunc.MAXUPVAL;
-const CT = defs.constant_types;
-const TS = defs.thread_status;
+const { ZIO } = require('./lzio.js');
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;
};
const lua_version = function(L) {
- if (L === null) return defs.LUA_VERSION_NUM;
+ if (L === null) return LUA_VERSION_NUM;
else return L.l_G.version;
};
@@ -47,17 +91,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");
+ } else if (idx > LUA_REGISTRYINDEX) {
+ api_check(L, idx !== 0 && -idx <= L.top, "invalid index");
return L.stack[L.top + idx];
- } else if (idx === defs.LUA_REGISTRYINDEX) {
+ } else if (idx === LUA_REGISTRYINDEX) {
return L.l_G.l_registry;
} else { /* upvalues */
- idx = defs.LUA_REGISTRYINDEX - idx;
- assert(idx <= MAXUPVAL + 1, "upvalue index too large");
+ idx = LUA_REGISTRYINDEX - idx;
+ api_check(L, idx <= lfunc.MAXUPVAL + 1, "upvalue index too large");
if (ci.func.ttislcf()) /* light C function? */
return lobject.luaO_nilobject; /* it has no upvalues */
else {
@@ -71,11 +115,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");
+ } else if (idx > LUA_REGISTRYINDEX) {
+ 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,12 +129,12 @@ 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 */
let inuse = L.top + lstate.EXTRA_STACK;
- if (inuse > luaconf.LUAI_MAXSTACK - n) /* can grow without overflow? */
+ if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */
res = false; /* no */
else { /* try to grow stack */
ldo.luaD_growstack(L, n);
@@ -106,10 +150,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();
@@ -127,7 +170,7 @@ const lua_xmove = function(from, to, n) {
** convert an acceptable stack index into an absolute index
*/
const lua_absindex = function(L, idx) {
- return (idx > 0 || idx <= defs.LUA_REGISTRYINDEX)
+ return (idx > 0 || idx <= LUA_REGISTRYINDEX)
? idx
: (L.top - L.ci.funcOff) + idx;
};
@@ -138,17 +181,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 +218,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 > 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);
@@ -210,93 +250,84 @@ 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");
+ L.stack[L.top] = new TValue(LUA_TNIL, null);
+ api_incr_top(L);
};
const lua_pushnumber = function(L, n) {
- assert(typeof n === "number");
-
- L.stack[L.top] = new TValue(CT.LUA_TNUMFLT, n);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ fengari_argcheck(typeof n === "number");
+ L.stack[L.top] = new TValue(LUA_TNUMFLT, n);
+ api_incr_top(L);
};
const lua_pushinteger = function(L, n) {
- assert(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");
+ fengari_argcheck(typeof n === "number" && (n|0) === n);
+ L.stack[L.top] = new TValue(LUA_TNUMINT, n);
+ api_incr_top(L);
};
const lua_pushlstring = function(L, s, len) {
- assert(typeof len === "number");
+ fengari_argcheck(typeof len === "number");
let ts;
if (len === 0) {
- s = defs.to_luastring("", true);
+ s = to_luastring("", true);
+ ts = luaS_bless(L, s);
} else {
- s = defs.from_userstring(s);
- assert(s.length >= len, "invalid length to lua_pushlstring");
- s = s.slice(0, len);
+ s = from_userstring(s);
+ api_check(L, s.length >= len, "invalid length to lua_pushlstring");
+ ts = luaS_new(L, s.subarray(0, len));
}
- ts = lstring.luaS_bless(L, s);
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;
};
const lua_pushstring = function (L, s) {
if (s === undefined || s === null) {
- L.stack[L.top] = new TValue(CT.LUA_TNIL, null);
+ L.stack[L.top] = new TValue(LUA_TNIL, null);
L.top++;
} else {
- let ts = lstring.luaS_new(L, defs.from_userstring(s));
+ let ts = luaS_new(L, from_userstring(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_pushvfstring = function (L, fmt, argp) {
- fmt = defs.from_userstring(fmt);
+ fmt = from_userstring(fmt);
return lobject.luaO_pushvfstring(L, fmt, argp);
};
const lua_pushfstring = function (L, fmt, ...argp) {
- fmt = defs.from_userstring(fmt);
+ fmt = from_userstring(fmt);
return lobject.luaO_pushvfstring(L, fmt, argp);
};
/* Similar to lua_pushstring, but takes a JS string */
const lua_pushliteral = function (L, s) {
if (s === undefined || s === null) {
- L.stack[L.top] = new TValue(CT.LUA_TNIL, null);
+ L.stack[L.top] = new TValue(LUA_TNIL, null);
L.top++;
} else {
- assert(typeof s === "string", "lua_pushliteral expects a JS string");
- let ts = lstring.luaS_newliteral(L, s);
+ fengari_argcheck(typeof s === "string", "lua_pushliteral expects a JS string");
+ let ts = 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);
+ L.stack[L.top] = new TValue(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 <= lfunc.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 +337,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;
@@ -319,26 +349,23 @@ const lua_pushcfunction = function(L, fn) {
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");
+ L.stack[L.top] = new TValue(LUA_TBOOLEAN, b ? true : false);
+ 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");
+ L.stack[L.top] = new TValue(LUA_TLIGHTUSERDATA, p);
+ 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");
+ L.stack[L.top] = new TValue(LUA_TTHREAD, L);
+ api_incr_top(L);
return L.l_G.mainthread === L;
};
const lua_pushglobaltable = function(L) {
- lua_rawgeti(L, defs.LUA_REGISTRYINDEX, defs.LUA_RIDX_GLOBALS);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
};
/*
@@ -349,10 +376,10 @@ const lua_pushglobaltable = function(L) {
** t[k] = value at the top of the stack (where 'k' is a string)
*/
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");
+ let str = luaS_new(L, from_userstring(k));
+ 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];
@@ -360,23 +387,23 @@ const auxsetstr = function(L, t, k) {
};
const lua_setglobal = function(L, name) {
- auxsetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS), name);
+ auxsetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS), 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;
}
switch (obj.ttnov()) {
- case CT.LUA_TUSERDATA:
- case CT.LUA_TTABLE: {
+ case LUA_TUSERDATA:
+ case LUA_TTABLE: {
obj.value.metatable = mt;
break;
}
@@ -391,8 +418,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 +430,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");
+ L.stack[L.top] = new TValue(LUA_TNUMINT, n);
+ 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 +442,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,18 +459,18 @@ 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");
- let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
+ api_check(L, o.ttistable(), "table expected");
+ let k = new TValue(LUA_TLIGHTUSERDATA, p);
let v = L.stack[L.top - 1];
if (v.ttisnil()) {
ltable.luaH_delete(L, o.value, k);
@@ -461,43 +486,42 @@ const lua_rawsetp = function(L, idx, p) {
*/
const auxgetstr = function(L, t, k) {
- let str = lstring.luaS_new(L, defs.from_userstring(k));
+ let str = luaS_new(L, 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");
- let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
+ api_check(L, t.ttistable(), "table expected");
+ let k = new TValue(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();
};
// narray and nrec are mostly useless for this implementation
const lua_createtable = function(L, narray, nrec) {
- let t = new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L));
+ let t = new lobject.TValue(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) {
@@ -506,30 +530,29 @@ 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");
+ L.stack[L.top] = new lobject.TValue(LUA_TUSERDATA, u);
+ api_incr_top(L);
return u.data;
};
const aux_upvalue = function(L, fi, n) {
switch(fi.ttype()) {
- case CT.LUA_TCCL: { /* C closure */
+ case LUA_TCCL: { /* C closure */
let f = fi.value;
if (!(1 <= n && n <= f.nupvalues)) return null;
return {
- name: defs.to_luastring("", true),
+ name: to_luastring("", true),
val: f.upvalue[n-1]
};
}
- case CT.LUA_TLCL: { /* Lua closure */
+ case LUA_TLCL: { /* Lua closure */
let f = fi.value;
let p = f.p;
if (!(1 <= n && n <= p.upvalues.length)) return null;
let name = p.upvalues[n-1].name;
return {
- name: name ? name.getstr() : defs.to_luastring("(*no name)", true),
- val: f.upvals[n-1].v
+ name: name ? name.getstr() : to_luastring("(*no name)", true),
+ val: f.upvals[n-1]
};
}
default: return null; /* not a closure */
@@ -542,7 +565,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 +573,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;
@@ -576,8 +599,8 @@ const lua_getmetatable = function(L, objindex) {
let mt;
let res = false;
switch (obj.ttnov()) {
- case CT.LUA_TTABLE:
- case CT.LUA_TUSERDATA:
+ case LUA_TTABLE:
+ case LUA_TUSERDATA:
mt = obj.value.metatable;
break;
default:
@@ -586,9 +609,8 @@ 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");
+ L.stack[L.top] = new TValue(LUA_TTABLE, mt);
+ api_incr_top(L);
res = true;
}
@@ -597,11 +619,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,17 +637,16 @@ 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");
+ L.stack[L.top] = new TValue(LUA_TNUMINT, n);
+ api_incr_top(L);
lvm.luaV_gettable(L, t, L.stack[L.top - 1], L.top - 1);
return L.stack[L.top - 1].ttnov();
};
const lua_getglobal = function(L, name) {
- return auxgetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS), name);
+ return auxgetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS), name);
};
/*
@@ -674,12 +694,12 @@ const lua_todataview = function(L, idx) {
const lua_rawlen = function(L, idx) {
let o = index2addr(L, idx);
switch (o.ttype()) {
- case CT.LUA_TSHRSTR:
- case CT.LUA_TLNGSTR:
+ case LUA_TSHRSTR:
+ case LUA_TLNGSTR:
return o.vslen();
- case CT.LUA_TUSERDATA:
+ case LUA_TUSERDATA:
return o.value.len;
- case CT.LUA_TTABLE:
+ case LUA_TTABLE:
return ltable.luaH_getn(o.value);
default:
return 0;
@@ -713,9 +733,9 @@ const lua_tonumberx = function(L, idx) {
const lua_touserdata = function(L, idx) {
let o = index2addr(L, idx);
switch (o.ttnov()) {
- case CT.LUA_TUSERDATA:
+ case LUA_TUSERDATA:
return o.value.data;
- case CT.LUA_TLIGHTUSERDATA:
+ case LUA_TLIGHTUSERDATA:
return o.value;
default: return null;
}
@@ -729,13 +749,13 @@ const lua_tothread = function(L, idx) {
const lua_topointer = function(L, idx) {
let o = index2addr(L, idx);
switch (o.ttype()) {
- case CT.LUA_TTABLE:
- case CT.LUA_TLCL:
- case CT.LUA_TCCL:
- case CT.LUA_TLCF:
- case CT.LUA_TTHREAD:
- case CT.LUA_TUSERDATA: /* note: this differs in behaviour to reference lua implementation */
- case CT.LUA_TLIGHTUSERDATA:
+ case LUA_TTABLE:
+ case LUA_TLCL:
+ case LUA_TCCL:
+ case LUA_TLCF:
+ case LUA_TTHREAD:
+ case LUA_TUSERDATA: /* note: this differs in behaviour to reference lua implementation */
+ case LUA_TLIGHTUSERDATA:
return o.value;
default:
return null;
@@ -759,10 +779,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;
@@ -783,10 +802,10 @@ const lua_compare = function(L, index1, index2, op) {
if (isvalid(o1) && isvalid(o2)) {
switch (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");
+ case LUA_OPEQ: i = lvm.luaV_equalobj(L, o1, o2); break;
+ case LUA_OPLT: i = lvm.luaV_lessthan(L, o1, o2); break;
+ case LUA_OPLE: i = lvm.luaV_lessequal(L, o1, o2); break;
+ default: api_check(L, false, "invalid option");
}
}
@@ -798,8 +817,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;
};
@@ -810,11 +828,11 @@ const f_call = function(L, ud) {
const lua_type = function(L, idx) {
let o = index2addr(L, idx);
- return isvalid(o) ? o.ttnov() : CT.LUA_TNONE;
+ return isvalid(o) ? o.ttnov() : LUA_TNONE;
};
const lua_typename = function(L, t) {
- assert(CT.LUA_TNONE <= t && t < CT.LUA_NUMTAGS, "invalid tag");
+ api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
return ltm.ttypename(t);
};
@@ -824,15 +842,15 @@ const lua_iscfunction = function(L, idx) {
};
const lua_isnil = function(L, n) {
- return lua_type(L, n) === CT.LUA_TNIL;
+ return lua_type(L, n) === LUA_TNIL;
};
const lua_isboolean = function(L, n) {
- return lua_type(L, n) === CT.LUA_TBOOLEAN;
+ return lua_type(L, n) === LUA_TBOOLEAN;
};
const lua_isnone = function(L, n) {
- return lua_type(L, n) === CT.LUA_TNONE;
+ return lua_type(L, n) === LUA_TNONE;
};
const lua_isnoneornil = function(L, n) {
@@ -862,15 +880,15 @@ const lua_isuserdata = function(L, idx) {
};
const lua_isthread = function(L, idx) {
- return lua_type(L, idx) === CT.LUA_TTHREAD;
+ return lua_type(L, idx) === LUA_TTHREAD;
};
const lua_isfunction = function(L, idx) {
- return lua_type(L, idx) === CT.LUA_TFUNCTION;
+ return lua_type(L, idx) === LUA_TFUNCTION;
};
const lua_islightuserdata = function(L, idx) {
- return lua_type(L, idx) === CT.LUA_TLIGHTUSERDATA;
+ return lua_type(L, idx) === LUA_TLIGHTUSERDATA;
};
const lua_rawequal = function(L, index1, index2) {
@@ -880,12 +898,12 @@ 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 */
+ if (op !== LUA_OPUNM && op !== LUA_OPBNOT)
+ 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]);
@@ -896,30 +914,30 @@ const lua_arith = function(L, op) {
** 'load' and 'call' functions (run Lua code)
*/
-const default_chunkname = defs.to_luastring("?");
+const default_chunkname = to_luastring("?");
const lua_load = function(L, reader, data, chunkname, mode) {
if (!chunkname) chunkname = default_chunkname;
- else chunkname = defs.from_userstring(chunkname);
- if (mode !== null) mode = defs.from_userstring(mode);
- let z = new lzio.ZIO(L, reader, data);
+ else chunkname = from_userstring(chunkname);
+ if (mode !== null) mode = from_userstring(mode);
+ let z = new ZIO(L, reader, data);
let status = ldo.luaD_protectedparser(L, z, chunkname, mode);
- if (status === TS.LUA_OK) { /* no errors? */
+ if (status === LUA_OK) { /* no errors? */
let f = L.stack[L.top - 1].value; /* get newly created function */
if (f.nupvalues >= 1) { /* does it have an upvalue? */
/* get global table from registry */
- let gt = ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS);
+ let gt = ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
- f.upvals[0].v.setfrom(gt);
+ f.upvals[0].setfrom(gt);
}
}
return status;
};
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);
+ return luaU_dump(L, o.value.p, writer, data, strip);
return 1;
};
@@ -928,19 +946,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) == 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 === 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;
@@ -950,7 +972,7 @@ const lua_callk = function(L, nargs, nresults, ctx, k) {
ldo.luaD_callnoyield(L, func, nresults);
}
- if (nresults === defs.LUA_MULTRET && L.ci.top < L.top)
+ if (nresults === LUA_MULTRET && L.ci.top < L.top)
L.ci.top = L.top;
};
@@ -959,10 +981,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 === LUA_OK, "cannot do calls on non-normal thread");
+ checkresults(L, nargs, nresults);
let c = {
func: null,
funcOff: NaN,
@@ -998,10 +1020,10 @@ const lua_pcallk = function(L, nargs, nresults, errfunc, ctx, k) {
ldo.luaD_call(L, c.funcOff, nresults); /* do the call */
ci.callstatus &= ~lstate.CIST_YPCALL;
L.errfunc = ci.c_old_errfunc;
- status = TS.LUA_OK;
+ status = LUA_OK;
}
- if (nresults === defs.LUA_MULTRET && L.ci.top < L.top)
+ if (nresults === LUA_MULTRET && L.ci.top < L.top)
L.ci.top = L.top;
return status;
@@ -1016,18 +1038,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 +1058,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");
+ lobject.pushsvalue2s(L, luaS_bless(L, to_luastring("", true)));
+ api_check(L, L.top <= L.ci.top, "stack overflow");
}
};
@@ -1051,35 +1072,34 @@ 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, n|0 === n && 1 <= n && n <= f.p.upvalues.length, "invalid upvalue index");
return {
- closure: f,
- upval: f.upvals[n - 1],
- upvalOff: n - 1
+ f: f,
+ i: 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).upval;
+ case LUA_TLCL: { /* lua closure */
+ let ref = getupvalref(L, fidx, n);
+ return ref.f.upvals[ref.i];
}
- case CT.LUA_TCCL: { /* C closure */
+ case LUA_TCCL: { /* C closure */
let f = fi.value;
- assert(1 <= n && n <= f.nupvalues, "invalid upvalue index");
+ api_check(L, n|0 === n && 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;
}
}
@@ -1088,13 +1108,8 @@ 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.upval;
- let up2 = ref2.upval;
- let f1 = ref1.closure;
- assert(up1.refcount > 0);
- up1.refcount--;
- f1.upvals[ref1.upvalOff] = up2;
- up2.refcount++;
+ let up2 = ref2.f.upvals[ref2.i];
+ ref1.f.upvals[ref1.i] = up2;
};
// This functions are only there for compatibility purposes
@@ -1115,8 +1130,8 @@ const lua_getextraspace = function () {
return 0;
};
-module.exports.index2addr = index2addr;
-module.exports.index2addr_ = index2addr_;
+module.exports.api_incr_top = api_incr_top;
+module.exports.api_checknelems = api_checknelems;
module.exports.lua_absindex = lua_absindex;
module.exports.lua_arith = lua_arith;
module.exports.lua_atpanic = lua_atpanic;