diff options
-rw-r--r-- | src/defs.js | 45 | ||||
-rw-r--r-- | src/lauxlib.js | 25 | ||||
-rw-r--r-- | src/lbaselib.js | 7 | ||||
-rw-r--r-- | src/ldebug.js | 12 | ||||
-rw-r--r-- | src/ldo.js | 2 | ||||
-rw-r--r-- | src/llex.js | 6 | ||||
-rw-r--r-- | src/lobject.js | 51 | ||||
-rw-r--r-- | src/lparser.js | 4 | ||||
-rw-r--r-- | src/lstrlib.js | 8 | ||||
-rw-r--r-- | src/ltablib.js | 3 | ||||
-rw-r--r-- | src/lua.js | 1 |
11 files changed, 81 insertions, 83 deletions
diff --git a/src/defs.js b/src/defs.js index fd8038a..34316e9 100644 --- a/src/defs.js +++ b/src/defs.js @@ -134,6 +134,50 @@ class lua_Debug { } +const to_jsstring = function(value, from, to) { + assert(Array.isArray(value), "jsstring expect a array of bytes"); + + let u0, u1, u2, u3, u4, u5; + let idx = 0; + value = value.slice(from ? from : 0, to); + + var str = ''; + while (1) { + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 + u0 = value[idx++]; + if (u0 === 0) { str += "\0"; continue; } // Lua string embed '\0' + if (!u0) return str; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + u1 = value[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + u2 = value[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + u3 = value[idx++] & 63; + if ((u0 & 0xF8) == 0xF0) { + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3; + } else { + u4 = value[idx++] & 63; + if ((u0 & 0xFC) == 0xF8) { + u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4; + } else { + u5 = value[idx++] & 63; + u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5; + } + } + } + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + + return str; +}; + const to_luastring_cache = {}; const to_luastring = function(str, cache, maxBytesToWrite) { @@ -277,4 +321,5 @@ module.exports.constant_types = constant_types; module.exports.lua_Debug = lua_Debug; module.exports.lua_upvalueindex = lua_upvalueindex; module.exports.thread_status = thread_status; +module.exports.to_jsstring = to_jsstring; module.exports.to_luastring = to_luastring; diff --git a/src/lauxlib.js b/src/lauxlib.js index 7d48e11..bb2cd00 100644 --- a/src/lauxlib.js +++ b/src/lauxlib.js @@ -3,7 +3,6 @@ const lapi = require('./lapi.js'); const lua = require('./lua.js'); -const lobject = require('./lobject.js'); const linit = require('./linit.js'); const LUA_LOADED_TABLE = "_LOADED"; @@ -59,7 +58,7 @@ const pushglobalfuncname = function(L, ar) { lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, lua.to_luastring(LUA_LOADED_TABLE, true)); if (findfield(L, top + 1, 2)) { let name = lua.lua_tostring(L, -1); - if (lobject.jsstring(name).startsWith("_G.")) { /* name start with '_G.'? */ + if (lua.to_jsstring(name).startsWith("_G.")) { /* name start with '_G.'? */ lua.lua_pushstring(L, name.slice(3)); /* push name without prefix */ lua.lua_remove(L, -2); /* remove original name */ } @@ -140,20 +139,20 @@ const luaL_argerror = function(L, arg, extramsg) { let ar = new lua.lua_Debug(); if (!lua.lua_getstack(L, 0, ar)) /* no stack frame? */ - return luaL_error(L, lua.to_luastring(`bad argument #${arg} (${lobject.jsstring(extramsg)})`)); + return luaL_error(L, lua.to_luastring(`bad argument #${arg} (${lua.to_jsstring(extramsg)})`)); lua.lua_getinfo(L, 'n', ar); if (ar.namewhat === lua.to_luastring('method', true)) { arg--; /* do not count 'self' */ if (arg === 0) /* error is in the self argument itself? */ - return luaL_error(L, lua.to_luastring(`calling '${lobject.jsstring(ar.name)}' on bad self (${lobject.jsstring(extramsg)})`)); + return luaL_error(L, lua.to_luastring(`calling '${lua.to_jsstring(ar.name)}' on bad self (${lua.to_jsstring(extramsg)})`)); } if (ar.name === null) ar.name = pushglobalfuncname(L, ar) ? lua.lua_tostring(L, -1) : ["?".charCodeAt(0)]; - return luaL_error(L, lua.to_luastring(`bad argument #${arg} to '${lobject.jsstring(ar.name)}' (${lobject.jsstring(extramsg)})`)); + return luaL_error(L, lua.to_luastring(`bad argument #${arg} to '${lua.to_jsstring(ar.name)}' (${lua.to_jsstring(extramsg)})`)); }; const typeerror = function(L, arg, tname) { @@ -165,7 +164,7 @@ const typeerror = function(L, arg, tname) { else typearg = luaL_typename(L, arg); - let msg = lua.lua_pushstring(L, lua.to_luastring(`${lobject.jsstring(tname)} expected, got ${lobject.jsstring(typearg)}`)); + let msg = lua.lua_pushstring(L, lua.to_luastring(`${lua.to_jsstring(tname)} expected, got ${lua.to_jsstring(typearg)}`)); return luaL_argerror(L, arg, msg); }; @@ -174,7 +173,7 @@ const luaL_where = function(L, level) { if (lua.lua_getstack(L, level, ar)) { lua.lua_getinfo(L, lua.to_luastring("Sl", true), ar); if (ar.currentline > 0) { - lua.lua_pushstring(L, lua.to_luastring(`${lobject.jsstring(ar.short_src)}:${ar.currentline}:`)); + lua.lua_pushstring(L, lua.to_luastring(`${lua.to_jsstring(ar.short_src)}:${ar.currentline}:`)); return; } } @@ -184,7 +183,7 @@ const luaL_where = function(L, level) { const luaL_error = function(L, fmt, ...args) { let i = 0; - fmt = lobject.jsstring(fmt); + fmt = lua.to_jsstring(fmt); // TODO: bypassing lua_pushvstring for now fmt = fmt.replace(/(^%[sfIpdcU]|([^%])%[sfIpdcU])/g, function (m, p1, p2, off) { return p2 ? p2 + args[i++] : args[i++]; @@ -205,7 +204,7 @@ const luaL_fileresult = function(L, stat, fname, e) { else { lua.lua_pushnil(L); if (fname) - lua.lua_pushstring(L, lua.to_luastring(`${lobject.jsstring(fname)}: ${e.message}`)); + lua.lua_pushstring(L, lua.to_luastring(`${lua.to_jsstring(fname)}: ${e.message}`)); else lua.lua_pushstring(L, lua.to_luastring(e.message)); lua.lua_pushinteger(L, -e.errno); @@ -460,7 +459,7 @@ const luaL_tolstring = function(L, idx) { default: let tt = luaL_getmetafield(L, idx, lua.to_luastring("__name", true)); let kind = tt === lua.LUA_TSTRING ? lua.lua_tostring(L, -1) : luaL_typename(L, idx); - lua.lua_pushstring(L, lua.to_luastring(`${lobject.jsstring(kind)}: 0x${lapi.index2addr(L, -1).id.toString(16)}`)); + lua.lua_pushstring(L, lua.to_luastring(`${lua.to_jsstring(kind)}: 0x${lapi.index2addr(L, -1).id.toString(16)}`)); if (tt !== lua.LUA_TNIL) lua.lua_remove(L, -2); break; @@ -537,7 +536,7 @@ const luaL_setfuncs = function(L, l, nup) { const luaL_checkstack = function(L, space, msg) { if (!lua.lua_checkstack(L, space)) { if (msg) - luaL_error(L, lua.to_luastring(`stack overflow (${lobject.jsstring(msg)})`)); + luaL_error(L, lua.to_luastring(`stack overflow (${lua.to_jsstring(msg)})`)); else luaL_error(L, lua.to_luastring('stack overflow', true)); } @@ -592,7 +591,7 @@ if (typeof require === "function") { const errfile = function(L, what, fnameindex, error) { let serr = error.message; let filename = lua.lua_tostring(L, fnameindex).slice(1); - lua.lua_pushstring(L, lua.to_luastring(`cannot ${what} ${lobject.jsstring(filename)}: ${serr}`)); + lua.lua_pushstring(L, lua.to_luastring(`cannot ${what} ${lua.to_jsstring(filename)}: ${serr}`)); lua.lua_remove(L, fnameindex); return lua.LUA_ERRFILE; }; @@ -652,7 +651,7 @@ if (typeof require === "function") { lua.lua_pushliteral(L, "=stdin"); lf.f = process.stdin.fd; } else { - let jsfilename = lobject.jsstring(filename); + let jsfilename = lua.to_jsstring(filename); lua.lua_pushliteral(L, `@${jsfilename}`); try { lf.f = fs.openSync(jsfilename, "r"); diff --git a/src/lbaselib.js b/src/lbaselib.js index fe329d6..5e3fff6 100644 --- a/src/lbaselib.js +++ b/src/lbaselib.js @@ -2,7 +2,6 @@ const lua = require('./lua.js'); const lauxlib = require('./lauxlib.js'); -const lobject = require('./lobject.js'); const luaB_print = function(L) { let n = lua.lua_gettop(L); /* number of arguments */ @@ -22,8 +21,8 @@ const luaB_print = function(L) { } // Don't use console.log if Node - if (process.stdout) process.stdout.write(lobject.jsstring(str) + "\n"); - else console.log(lobject.jsstring(str)); + if (process.stdout) process.stdout.write(lua.to_jsstring(str) + "\n"); + else console.log(lua.to_jsstring(str)); return 0; }; @@ -162,7 +161,7 @@ const luaB_tonumber = function(L) { lauxlib.luaL_checktype(L, 1, lua.LUA_TSTRING); /* no numbers as strings */ let s = lua.lua_tostring(L, 1); lauxlib.luaL_argcheck(L, 2 <= base && base <= 36, 2, lua.to_luastring("base out of range", true)); - let n = parseInt(lobject.jsstring(s), base); + let n = parseInt(lua.to_jsstring(s), base); if (!isNaN(n)) { lua.lua_pushinteger(L, n); return 1; diff --git a/src/ldebug.js b/src/ldebug.js index 27caf8b..984f441 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -532,12 +532,12 @@ const varinfo = function(L, o) { kind = getobjname(ci.func.p, ci.pcOff, stkid - ci.u.l.base); } - return defs.to_luastring(kind ? ` (${lobject.jsstring(kind.funcname)} '${lobject.jsstring(kind.name.value ? kind.name.value : kind.name)}')` : ``); + return defs.to_luastring(kind ? ` (${defs.to_jsstring(kind.funcname)} '${defs.to_jsstring(kind.name.value ? kind.name.value : kind.name)}')` : ``); }; const luaG_typeerror = function(L, o, op) { let t = ltm.luaT_objtypename(L, o); - luaG_runerror(L, defs.to_luastring(`attempt to ${lobject.jsstring(op)} a ${lobject.jsstring(t)} value${lobject.jsstring(varinfo(L, o))}`)); + luaG_runerror(L, defs.to_luastring(`attempt to ${defs.to_jsstring(op)} a ${defs.to_jsstring(t)} value${defs.to_jsstring(varinfo(L, o))}`)); }; const luaG_concaterror = function(L, p1, p2) { @@ -559,9 +559,9 @@ const luaG_ordererror = function(L, p1, p2) { let t1 = ltm.luaT_objtypename(L, p1); let t2 = ltm.luaT_objtypename(L, p2); if (t1.join() === t2.join()) - luaG_runerror(L, defs.to_luastring(`attempt to compare two ${lobject.jsstring(t1)} values`)); + luaG_runerror(L, defs.to_luastring(`attempt to compare two ${defs.to_jsstring(t1)} values`)); else - luaG_runerror(L, defs.to_luastring(`attempt to compare ${lobject.jsstring(t1)} with ${lobject.jsstring(t2)}`)); + luaG_runerror(L, defs.to_luastring(`attempt to compare ${defs.to_jsstring(t1)} with ${defs.to_jsstring(t2)}`)); }; /* add src:line information to 'msg' */ @@ -570,7 +570,7 @@ const luaG_addinfo = function(L, msg, src, line) { if (src) buff = lobject.luaO_chunkid(src, luaconf.LUA_IDSIZE); - L.stack[L.top++] = L.l_G.intern(defs.to_luastring(`${lobject.jsstring(buff)}:${line}: ${lobject.jsstring(msg)}`)); + L.stack[L.top++] = L.l_G.intern(defs.to_luastring(`${defs.to_jsstring(buff)}:${line}: ${defs.to_jsstring(msg)}`)); return L.stack[L.top - 1]; }; @@ -601,7 +601,7 @@ const luaG_tointerror = function(L, p1, p2) { let temp = lvm.tointeger(p1); if (temp === false) p2 = p1; - luaG_runerror(L, defs.to_luastring(`number${lobject.jsstring(varinfo(L, p2))} has no integer representation`)); + luaG_runerror(L, defs.to_luastring(`number${defs.to_jsstring(varinfo(L, p2))} has no integer representation`)); }; const luaG_traceexec = function(L) { @@ -555,7 +555,7 @@ class SParser { const checkmode = function(L, mode, x) { if (mode && mode.indexOf(x[0]) === -1) { - lapi.lua_pushstring(L, defs.to_luastring(`attempt to load a ${lobject.jsstring(x)} chunk (mode is '${lobject.jsstring(mode)}')`)); + lapi.lua_pushstring(L, defs.to_luastring(`attempt to load a ${defs.to_jsstring(x)} chunk (mode is '${defs.to_jsstring(mode)}')`)); luaD_throw(L, TS.LUA_ERRSYNTAX); } }; diff --git a/src/llex.js b/src/llex.js index c19452c..da15b2f 100644 --- a/src/llex.js +++ b/src/llex.js @@ -159,7 +159,7 @@ const save = function(ls, c) { const luaX_token2str = function(ls, token) { if (typeof token === "string" || token < FIRST_RESERVED) { /* single-byte symbols? */ - return defs.to_luastring(`'${typeof token === "string" ? token : lobject.jsstring([token])}'`); + return defs.to_luastring(`'${typeof token === "string" ? token : defs.to_jsstring([token])}'`); } else { let s = luaX_tokens[token - FIRST_RESERVED]; if (token < R.TK_EOS) /* fixed format (symbols and reserved words)? */ @@ -283,7 +283,7 @@ const txtToken = function(ls, token) { case R.TK_NAME: case R.TK_STRING: case R.TK_FLT: case R.TK_INT: save(ls, 0); - return defs.to_luastring(`'${lobject.jsstring(ls.buff.buffer)}'`); + return defs.to_luastring(`'${defs.to_jsstring(ls.buff.buffer)}'`); default: return luaX_token2str(ls, token); } @@ -292,7 +292,7 @@ const txtToken = function(ls, token) { const lexerror = function(ls, msg, token) { msg = ldebug.luaG_addinfo(ls.L, msg, ls.source, ls.linenumber); if (token) - lapi.lua_pushstring(ls.L, defs.to_luastring(`${msg instanceof TValue ? msg.jsstring() : msg} near ${lobject.jsstring(txtToken(ls, token))}`)); + lapi.lua_pushstring(ls.L, defs.to_luastring(`${msg instanceof TValue ? msg.jsstring() : msg} near ${defs.to_jsstring(txtToken(ls, token))}`)); ldo.luaD_throw(ls.L, TS.LUA_ERRSYNTAX); }; diff --git a/src/lobject.js b/src/lobject.js index c2ec123..f02f8f3 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -117,7 +117,7 @@ class TValue { } jsstring(from, to) { - return jsstring(this.value, from, to); + return defs.to_jsstring(this.value, from, to); } } @@ -125,50 +125,6 @@ class TValue { const luaO_nilobject = new TValue(CT.LUA_TNIL, null); module.exports.luaO_nilobject = luaO_nilobject; -const jsstring = function(value, from, to) { - assert(Array.isArray(value), "jsstring expect a array of bytes"); - - let u0, u1, u2, u3, u4, u5; - let idx = 0; - value = value.slice(from ? from : 0, to); - - var str = ''; - while (1) { - // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 - u0 = value[idx++]; - if (u0 === 0) { str += "\0"; continue; } // Lua string embed '\0' - if (!u0) return str; - if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } - u1 = value[idx++] & 63; - if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } - u2 = value[idx++] & 63; - if ((u0 & 0xF0) == 0xE0) { - u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; - } else { - u3 = value[idx++] & 63; - if ((u0 & 0xF8) == 0xF0) { - u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3; - } else { - u4 = value[idx++] & 63; - if ((u0 & 0xFC) == 0xF8) { - u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4; - } else { - u5 = value[idx++] & 63; - u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5; - } - } - } - if (u0 < 0x10000) { - str += String.fromCharCode(u0); - } else { - var ch = u0 - 0x10000; - str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); - } - } - - return str; -}; - const table_keyValue = function(key) { // Those lua values are used by value, others by reference if (key instanceof TValue) { @@ -398,11 +354,11 @@ const lua_strx2number = function(s) { e += exp1; } if (neg) r = -r; - return jsstring(s).trim().search(/s/) < 0 ? ldexp(r, e) : null; /* Only valid if nothing left is s*/ + return defs.to_jsstring(s).trim().search(/s/) < 0 ? ldexp(r, e) : null; /* Only valid if nothing left is s*/ }; const l_str2dloc = function(s, mode) { - let flt = mode === 'x' ? lua_strx2number(s) : parseFloat(jsstring(s)); + let flt = mode === 'x' ? lua_strx2number(s) : parseFloat(defs.to_jsstring(s)); return !isNaN(flt) ? flt : null; /* OK if no trailing characters */ }; @@ -552,7 +508,6 @@ module.exports.TValue = TValue; module.exports.UTF8BUFFSZ = UTF8BUFFSZ; module.exports.frexp = frexp; module.exports.intarith = intarith; -module.exports.jsstring = jsstring; module.exports.ldexp = ldexp; module.exports.luaO_chunkid = luaO_chunkid; module.exports.luaO_hexavalue = luaO_hexavalue; diff --git a/src/lparser.js b/src/lparser.js index 9ba5941..41a0b22 100644 --- a/src/lparser.js +++ b/src/lparser.js @@ -159,7 +159,7 @@ const semerror = function(ls, msg) { }; const error_expected = function(ls, token) { - llex.luaX_syntaxerror(ls, defs.to_luastring(`${lobject.jsstring(llex.luaX_token2str(ls, token))} expected`)); + llex.luaX_syntaxerror(ls, defs.to_luastring(`${defs.to_jsstring(llex.luaX_token2str(ls, token))} expected`)); }; const errorlimit = function(fs, limit, what) { @@ -204,7 +204,7 @@ const check_match = function(ls, what, who, where) { error_expected(ls, what); else llex.luaX_syntaxerror(ls, - defs.to_luastring(`${lobject.jsstring(llex.luaX_token2str(ls, what))} expected (to close ${lobject.jsstring(llex.luaX_token2str(ls, who))} at line ${where}`)); + defs.to_luastring(`${defs.to_jsstring(llex.luaX_token2str(ls, what))} expected (to close ${defs.to_jsstring(llex.luaX_token2str(ls, who))} at line ${where}`)); } }; diff --git a/src/lstrlib.js b/src/lstrlib.js index 370e672..5bd08d4 100644 --- a/src/lstrlib.js +++ b/src/lstrlib.js @@ -346,7 +346,7 @@ const str_format = function(L) { lua.lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ } else { /* format the string into 'buff' */ // TODO: will failt if s is not valid UTF-8 - concat(b, lua.to_luastring(sprintf(String.fromCharCode(...form), lobject.jsstring(s)))); + concat(b, lua.to_luastring(sprintf(String.fromCharCode(...form), lua.to_jsstring(s)))); lua.lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ } } @@ -642,13 +642,13 @@ const str_reverse = function(L) { const str_lower = function(L) { // TODO: will fail on invalid UTF-8 - lua.lua_pushstring(L, lua.to_luastring(lobject.jsstring(lauxlib.luaL_checkstring(L, 1)).toLowerCase())); + lua.lua_pushstring(L, lua.to_luastring(lua.to_jsstring(lauxlib.luaL_checkstring(L, 1)).toLowerCase())); return 1; }; const str_upper = function(L) { // TODO: will fail on invalid UTF-8 - lua.lua_pushstring(L, lua.to_luastring(lobject.jsstring(lauxlib.luaL_checkstring(L, 1)).toUpperCase())); + lua.lua_pushstring(L, lua.to_luastring(lua.to_jsstring(lauxlib.luaL_checkstring(L, 1)).toUpperCase())); return 1; }; @@ -1319,7 +1319,7 @@ const add_value = function(ms, b, s, e, tr) { lua.lua_pop(L, 1); lua.lua_pushlstring(L, s, e - s); /* keep original text */ } else if (!lua.lua_isstring(L, -1)) - lauxlib.luaL_error(L, lua.to_luastring(`invalid replacement value (a ${lobject.jsstring(lauxlib.luaL_typename(L, -1))})`)); + lauxlib.luaL_error(L, lua.to_luastring(`invalid replacement value (a ${lua.to_jsstring(lauxlib.luaL_typename(L, -1))})`)); lauxlib.luaL_addvalue(b); /* add result to accumulator */ }; diff --git a/src/ltablib.js b/src/ltablib.js index bc283ae..78c71e4 100644 --- a/src/ltablib.js +++ b/src/ltablib.js @@ -4,7 +4,6 @@ const lua = require('./lua.js'); const lapi = require('./lapi.js'); const lauxlib = require('./lauxlib.js'); const llimit = require('./llimit.js'); -const lobject = require('./lobject.js'); /* @@ -47,7 +46,7 @@ const aux_getn = function(L, n, w) { const addfield = function(L, b, i) { lua.lua_geti(L, 1, i); if (!lua.lua_isstring(L, -1)) - lauxlib.luaL_error(L, lua.to_luastring(`invalid value (${lobject.jsstring(lauxlib.luaL_typename(L, -1))}) at index ${i} in table for 'concat'`)); + lauxlib.luaL_error(L, lua.to_luastring(`invalid value (${lua.to_jsstring(lauxlib.luaL_typename(L, -1))}) at index ${i} in table for 'concat'`)); lauxlib.luaL_addvalue(b); }; @@ -79,6 +79,7 @@ module.exports.LUA_VERSUFFIX = defs.LUA_VERSUFFIX; module.exports.LUA_YIELD = defs.thread_status.LUA_YIELD; module.exports.lua_Debug = defs.lua_Debug; module.exports.lua_upvalueindex = defs.lua_upvalueindex; +module.exports.to_jsstring = defs.to_jsstring; module.exports.to_luastring = defs.to_luastring; module.exports.lua_absindex = lapi.lua_absindex; |