From 2e5b595a2e04fe72555a565af4aae43560946473 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Wed, 29 Mar 2017 11:57:43 +0200 Subject: Never use js strings internally --- src/lapi.js | 48 ++++++++++++++++++---- src/lauxlib.js | 74 +++++++++++++++++---------------- src/lbaselib.js | 43 +++++++++---------- src/lcode.js | 6 +-- src/lcorolib.js | 5 ++- src/ldebug.js | 60 +++++++++++++-------------- src/ldo.js | 8 ++-- src/ljstype.js | 12 +++--- src/llex.js | 125 ++++++++++++++++++++++++++------------------------------ src/lmathlib.js | 20 ++++----- src/lobject.js | 84 ++++++++++++++++++------------------- src/lparser.js | 70 +++++++++++++++---------------- src/ltablib.js | 25 ++++++------ src/ltm.js | 90 ++++++++++++++-------------------------- src/lua.js | 2 +- src/lutf8lib.js | 24 +++++------ 16 files changed, 348 insertions(+), 348 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 8cabf12..6e1471d 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -218,11 +218,11 @@ const lua_pushinteger = function(L, n) { assert(L.top <= L.ci.top, "stack overflow"); }; -const lua_pushlstring = function(L, s, len) { // TODO: embedded \0 - assert(typeof s === "string"); +const lua_pushlstring = function(L, s, len) { + assert(Array.isArray(s), "lua_pushlstring expects array of byte"); assert(typeof len === "number"); - let ts = len === 0 ? L.l_G.intern(lua.to_luastring("")) : L.l_G.intern(lua.to_luastring(s.substr(0, len))); + let ts = len === 0 ? L.l_G.intern(lua.to_luastring("")) : new TValue(CT.LUA_TLNGSTR, s.slice(0, len)); L.stack[L.top++] = ts; assert(L.top <= L.ci.top, "stack overflow"); @@ -231,7 +231,24 @@ const lua_pushlstring = function(L, s, len) { // TODO: embedded \0 }; const lua_pushstring = function (L, s) { - if (typeof s !== "string") + assert(Array.isArray(s), "lua_pushstring expects array of byte"); + + if (s === undefined || s === null) + L.stack[L.top] = new TValue(CT.LUA_TNIL, null); + else { + L.stack[L.top] = new TValue(CT.LUA_TLNGSTR, s); + } + + L.top++; + assert(L.top <= L.ci.top, "stack overflow"); + + return s; +}; + +const lua_pushliteral = function (L, s) { + assert(typeof s === "string", "lua_pushliteral expects a JS string"); + + if (s === undefined || s === null) L.stack[L.top] = new TValue(CT.LUA_TNIL, null); else { let ts = L.l_G.intern(lua.to_luastring(s)); @@ -244,8 +261,6 @@ const lua_pushstring = function (L, s) { return s; }; -const lua_pushliteral = lua_pushstring; - const lua_pushcclosure = function(L, fn, n) { assert(typeof fn === "function"); assert(typeof n === "number"); @@ -315,7 +330,9 @@ 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 = L.l_G.intern(lua.to_luastring(k)); + assert(Array.isArray(k), "key must be an array of bytes"); + + let str = L.l_G.intern(k); assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack"); @@ -392,7 +409,9 @@ const lua_rawset = function(L, idx) { */ const auxgetstr = function(L, t, k) { - let str = L.l_G.intern(lua.to_luastring(k)); + assert(Array.isArray(k), "key must be an array of bytes"); + + let str = L.l_G.intern(k); let slot = t.__index(t, k); if (t.ttistable() && !slot.ttisnil()) { L.stack[L.top++] = slot; @@ -553,11 +572,22 @@ const lua_tolstring = function(L, idx) { if ((!o.ttisstring() && !o.ttisnumber())) return null; - return o.ttisstring() ? o.jsstring() : `${o.value}`; + return o.ttisstring() ? o.value : lua.to_luastring(`${o.value}`); }; const lua_tostring = lua_tolstring; +const lua_toljsstring = function(L, idx) { + let o = index2addr(L, idx); + + if ((!o.ttisstring() && !o.ttisnumber())) + return null; + + return o.ttisstring() ? o.jsstring() : `${o.value}`; +}; + +const lua_tojsstring = lua_toljsstring; + // Convert a string on the stack to a dataview, because lua_tostring will perform utf-8 to utf-16 conversion const lua_todataview = function(L, idx) { let o = index2addr(L, idx); diff --git a/src/lauxlib.js b/src/lauxlib.js index 8bda842..f60bd8c 100644 --- a/src/lauxlib.js +++ b/src/lauxlib.js @@ -58,7 +58,7 @@ const pushglobalfuncname = function(L, ar) { lapi.lua_getfield(L, lua.LUA_REGISTRYINDEX, LUA_LOADED_TABLE); if (findfield(L, top + 1, 2)) { let name = lapi.lua_tostring(L, -1); - if (name.startsWith("_G.")) { + if (name.jsstring().startsWith("_G.")) { lapi.lua_pushstring(L, name.slice(3)); /* name start with '_G.'? */ lapi.lua_remove(L, -2); /* name start with '_G.'? */ } @@ -71,61 +71,65 @@ const pushglobalfuncname = function(L, ar) { }; const panic = function(L) { - throw new Error(`PANIC: unprotected error in call to Lua API (${lapi.lua_tostring(L, -1)})`); + throw new Error(`PANIC: unprotected error in call to Lua API (${lapi.lua_tojsstring(L, -1)})`); }; const luaL_argerror = function(L, arg, extramsg) { let ar = new lua.lua_Debug(); if (!ldebug.lua_getstack(L, 0, ar)) /* no stack frame? */ - return luaL_error(L, 'bad argument #%d (%s)', arg, extramsg); + return luaL_error(L, lua.to_luastring(`bad argument #${arg} (${lobject.jsstring(extramsg)})`)); ldebug.lua_getinfo(L, 'n', ar); if (ar.namewhat === 'method') { arg--; /* do not count 'self' */ if (arg === 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling '%s' on bad self (%s)", ar.name, extramsg); + return luaL_error(L, lua.to_luastring(`calling '${lobject.jsstring(ar.name)}' on bad self (${lobject.jsstring(extramsg)})`)); } if (ar.name === null) ar.name = pushglobalfuncname(L, ar) ? lapi.lua_tostring(L, -1) : "?"; - return luaL_error(L, `bad argument #${arg} to '${ar.name}' (${extramsg})`); + return luaL_error(L, lua.to_luastring(`bad argument #${arg} to '${lobject.jsstring(ar.name)}' (${lobject.jsstring(extramsg)})`)); }; const typeerror = function(L, arg, tname) { let typearg; - if (luaL_getmetafield(L, arg, "__name") === CT.LUA_TSTRING) + if (luaL_getmetafield(L, arg, lua.to_luastring("__name")) === CT.LUA_TSTRING) typearg = lapi.lua_tostring(L, -1); else if (lapi.lua_type(L, arg) === CT.LUA_TLIGHTUSERDATA) - typearg = "light userdata"; + typearg = lua.to_luastring("light userdata"); else typearg = luaL_typename(L, arg); - let msg = lapi.lua_pushstring(L, `${tname} expected, got ${typearg}`); + let msg = lapi.lua_pushstring(L, lua.to_luastring(`${lobject.jsstring(tname)} expected, got ${lobject.jsstring(typearg)}`)); return luaL_argerror(L, arg, msg); }; const luaL_where = function(L, level) { let ar = new lua.lua_Debug(); if (ldebug.lua_getstack(L, level, ar)) { - ldebug.lua_getinfo(L, "Sl", ar); + ldebug.lua_getinfo(L, lua.to_luastring("Sl"), ar); if (ar.currentline > 0) { - lapi.lua_pushstring(L, `${ar.short_src}:${ar.currentline}:`); + lapi.lua_pushstring(L, lua.to_luastring(`${lobject.jsstring(ar.short_src)}:${ar.currentline}:`)); return; } } - lapi.lua_pushstring(L, ""); + lapi.lua_pushstring(L, []); }; const luaL_error = function(L, fmt, ...args) { let i = 0; + fmt = lobject.jsstring(fmt); // TODO: bypassing lua_pushvstring for now - lapi.lua_pushstring(L, fmt.replace(/(^%[sfIpdcU]|([^%])%[sfIpdcU])/g, function (m, p1, p2, off) { + fmt = fmt.replace(/(^%[sfIpdcU]|([^%])%[sfIpdcU])/g, function (m, p1, p2, off) { return p2 ? p2 + args[i++] : args[i++]; - })); + }); + fmt = lua.to_luastring(fmt); + + lapi.lua_pushstring(L, fmt); return lapi.lua_error(L); }; @@ -151,7 +155,7 @@ const luaL_argcheck = function(L, cond, arg, extramsg) { const luaL_checkany = function(L, arg) { if (lapi.lua_type(L, arg) === CT.LUA_TNONE) - luaL_argerror(L, arg, "value expected"); + luaL_argerror(L, arg, lua.to_luastring("value expected")); }; const luaL_checktype = function(L, arg, t) { @@ -165,7 +169,7 @@ const luaL_checkstring = function(L, n) { const luaL_checklstring = function(L, arg) { let s = lapi.lua_tolstring(L, arg); - if (typeof s !== "string") tag_error(L, arg, CT.LUA_TSTRING); + if (s === null || s === undefined) tag_error(L, arg, CT.LUA_TSTRING); return s; }; @@ -179,7 +183,7 @@ const luaL_optstring = luaL_optlstring; const interror = function(L, arg) { if (lapi.lua_isnumber(L, arg)) - luaL_argerror(L, arg, "number has no integer representation"); + luaL_argerror(L, arg, lua.to_luastring("number has no integer representation")); else tag_error(L, arg, CT.LUA_TNUMBER); }; @@ -208,7 +212,7 @@ const luaL_prepbuffsize = function(B, sz) { const luaL_buffinit = function(L, B) { B.L = L; - B.b = ""; + B.b = []; }; const luaL_buffinitsize = function(L, B, sz) { @@ -217,7 +221,7 @@ const luaL_buffinitsize = function(L, B, sz) { }; const luaL_addlstring = function(B, s, l) { - B.b += s.slice(0, l); + B.b = B.b.concat(s.slice(0, l)); }; const luaL_addstring = luaL_addlstring; @@ -228,7 +232,7 @@ const luaL_pushresult = function(B) { }; const luaL_addchar = function(B, c) { - B.b += c; + B.b.push(c); }; const luaL_addvalue = function(B) { @@ -301,18 +305,18 @@ const luaL_tolstring = function(L, idx) { switch(lapi.lua_type(L, idx)) { case CT.LUA_TNUMBER: case CT.LUA_TBOOLEAN: - lapi.lua_pushstring(L, `${lapi.index2addr(L, idx).value}`); + lapi.lua_pushstring(L, lua.to_luastring(`${lapi.index2addr(L, idx).value}`)); break; case CT.LUA_TSTRING: - lapi.lua_pushstring(L, lapi.index2addr(L, idx).jsstring()); + lapi.lua_pushstring(L, lapi.index2addr(L, idx).value); break; case CT.LUA_TNIL: - lapi.lua_pushstring(L, `nil`); + lapi.lua_pushstring(L, lua.to_luastring(`nil`)); break; default: - let tt = luaL_getmetafield(L, idx, "__name"); + let tt = luaL_getmetafield(L, idx, lua.to_luastring("__name")); let kind = tt === CT.LUA_TSTRING ? lapi.lua_tostring(L, -1) : luaL_typename(L, idx); - lapi.lua_pushstring(L, `${kind}: 0x${lapi.index2addr(L, -1).id.toString(16)}`); + lapi.lua_pushstring(L, lua.to_luastring(`${lobject.jsstring(kind)}: 0x${lapi.index2addr(L, -1).id.toString(16)}`)); if (tt !== CT.LUA_TNIL) lapi.lua_remove(L, -2); break; @@ -369,12 +373,12 @@ const luaL_getsubtable = function(L, idx, fname) { ** Returns with only the table at the stack. */ const luaL_setfuncs = function(L, l, nup) { - luaL_checkstack(L, nup, "too many upvalues"); + luaL_checkstack(L, nup, lua.to_luastring("too many upvalues")); for (let lib in l) { /* fill the table with given functions */ for (let i = 0; i < nup; i++) /* copy upvalues to the top */ lapi.lua_pushvalue(L, -nup); lapi.lua_pushcclosure(L, l[lib], nup); /* closure with those upvalues */ - lapi.lua_setfield(L, -(nup + 2), lib); + lapi.lua_setfield(L, -(nup + 2), lua.to_luastring(lib)); } lapi.lua_pop(L, nup); /* remove upvalues */ }; @@ -389,9 +393,9 @@ const luaL_setfuncs = function(L, l, nup) { const luaL_checkstack = function(L, space, msg) { if (!lapi.lua_checkstack(L, space)) { if (msg) - luaL_error(L, `stack overflow (${msg})`); + luaL_error(L, lua.to_luastring(`stack overflow (${lobject.jsstring(msg)})`)); else - luaL_error(L, 'stack overflow'); + luaL_error(L, lua.to_luastring('stack overflow')); } }; @@ -437,14 +441,14 @@ if (typeof require === "function") { lf.pos += bytes; } if (bytes > 0) - return lf.binary ? toDataView(lf.buff) : lobject.jsstring(lf.buff, 0, bytes); // TODO: Here reading utf8 only + return lf.binary ? toDataView(lf.buff) : lf.buff; else return null; }; const errfile = function(L, what, fnameindex, error) { let serr = error.message; let filename = lapi.lua_tostring(L, fnameindex).slice(1); - lapi.lua_pushstring(L, `cannot ${what} ${filename}: ${serr}`); + lapi.lua_pushstring(L, lua.to_luastring(`cannot ${lobject.jsstring(what)} ${lobject.jsstring(filename)}: ${lobject.jsstring(serr)}`)); lapi.lua_remove(L, fnameindex); return lua.thread_status.LUA_ERRFILE; }; @@ -457,12 +461,12 @@ if (typeof require === "function") { }; const skipBOM = function(lf) { - let p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + let p = [0XEF, 0XBB, 0XBF]; /* UTF-8 BOM mark */ lf.n = 0; let c; do { c = getc(lf); - if (c === null || c !== p.charCodeAt(0)) return c; + if (c === null || c !== p[0]) return c; p = p.slice(1); lf.buff[lf.n++] = c; /* to be read by the parser */ } while (p.length > 0); @@ -504,11 +508,11 @@ if (typeof require === "function") { lapi.lua_pushliteral(L, "=stdin"); lf.f = process.stdin.fd; } else { - lapi.lua_pushstring(L, `@${filename}`); + lapi.lua_pushliteral(L, `@${filename}`); try { lf.f = fs.openSync(filename, "r"); } catch (e) { - return errfile(L, "open", fnameindex, e); + return errfile(L, lua.to_luastring("open"), fnameindex, e); } } @@ -527,7 +531,7 @@ if (typeof require === "function") { return status; } catch (err) { lapi.lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ - return errfile(L, "read", fnameindex); + return errfile(L, lua.to_luastring("read"), fnameindex); } }; diff --git a/src/lbaselib.js b/src/lbaselib.js index a6f2ce8..8420672 100644 --- a/src/lbaselib.js +++ b/src/lbaselib.js @@ -5,6 +5,7 @@ const assert = require('assert'); const lua = require('./lua.js'); const lapi = require('./lapi.js'); const lauxlib = require('./lauxlib.js'); +const lobject = require('./lobject.js'); const CT = lua.constant_types; const TS = lua.thread_status; @@ -12,20 +13,20 @@ const luaB_print = function(L) { let n = lapi.lua_gettop(L); /* number of arguments */ let str = ""; - lapi.lua_getglobal(L, "tostring"); + lapi.lua_getglobal(L, lua.to_luastring("tostring")); for (let i = 1; i <= n; i++) { lapi.lua_pushvalue(L, -1); /* function to be called */ lapi.lua_pushvalue(L, i); /* value to print */ lapi.lua_call(L, 1, 1); let s = lapi.lua_tolstring(L, -1); if (s === null) - return lauxlib.luaL_error(L, "'tostring' must return a string to 'print'"); - if (i > 1) s = `\t${s}`; - str = `${str}${s}`; + return lauxlib.luaL_error(L, lua.to_luastring("'tostring' must return a string to 'print'")); + if (i > 1) s = ["\t".charCodeAt(0)].concat(s); + str = str.concat(s); lapi.lua_pop(L, 1); } - console.log(str); + console.log(lobject.jsstring(str)); return 0; }; @@ -42,16 +43,16 @@ const luaB_getmetatable = function(L) { lapi.lua_pushnil(L); return 1; /* no metatable */ } - lauxlib.luaL_getmetafield(L, 1, "__metatable"); + lauxlib.luaL_getmetafield(L, 1, lua.to_luastring("__metatable")); return 1; /* returns either __metatable field (if present) or metatable */ }; const luaB_setmetatable = function(L) { let t = lapi.lua_type(L, 2); lauxlib.luaL_checktype(L, 1, CT.LUA_TTABLE); - lauxlib.luaL_argcheck(L, t === CT.LUA_TNIL || t === CT.LUA_TTABLE, 2, "nil or table expected"); - if (lauxlib.luaL_getmetafield(L, 1, "__metatable") !== CT.LUA_TNIL) - return lauxlib.luaL_error(L, "cannot change a protected metatable"); + lauxlib.luaL_argcheck(L, t === CT.LUA_TNIL || t === CT.LUA_TTABLE, 2, lua.to_luastring("nil or table expected")); + if (lauxlib.luaL_getmetafield(L, 1, lua.to_luastring("__metatable")) !== CT.LUA_TNIL) + return lauxlib.luaL_error(L, lua.to_luastring("cannot change a protected metatable")); lapi.lua_settop(L, 2); lapi.lua_setmetatable(L, 1); return 1; @@ -66,7 +67,7 @@ const luaB_rawequal = function(L) { const luaB_rawlen = function(L) { let t = lapi.lua_type(L, 1); - lauxlib.luaL_argcheck(L, t === CT.LUA_TTABLE || t === CT.LUA_TSTRING, 1, "table or string expected"); + lauxlib.luaL_argcheck(L, t === CT.LUA_TTABLE || t === CT.LUA_TSTRING, 1, lua.to_luastring("table or string expected")); lapi.lua_pushinteger(L, lapi.lua_rawlen(L, 1)); return 1; }; @@ -90,7 +91,7 @@ const luaB_rawset = function(L) { const luaB_type = function(L) { let t = lapi.lua_type(L, 1); - lauxlib.luaL_argcheck(L, t !== CT.LUA_TNONE, 1, "value expected"); + lauxlib.luaL_argcheck(L, t !== CT.LUA_TNONE, 1, lua.to_luastring("value expected")); lapi.lua_pushstring(L, lapi.lua_typename(L, t)); return 1; }; @@ -121,7 +122,7 @@ const luaB_next = function(L) { }; const luaB_pairs = function(L) { - return pairsmeta(L, "__pairs", 0, luaB_next); + return pairsmeta(L, lua.to_luastring("__pairs"), 0, luaB_next); }; /* @@ -163,8 +164,8 @@ const luaB_tonumber = function(L) { let base = lauxlib.luaL_checkinteger(L, 2); lauxlib.luaL_checktype(L, 1, CT.LUA_TSTRING); /* no numbers as strings */ let s = lapi.lua_tostring(L, 1); - lauxlib.luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - let n = parseInt(s, base); + lauxlib.luaL_argcheck(L, 2 <= base && base <= 36, 2, lua.to_luastring("base out of range")); + let n = parseInt(lobject.jsstring(s), base); if (!isNaN(n)) { lapi.lua_pushinteger(L, n); return 1; @@ -207,7 +208,7 @@ const luaB_select = function(L) { let i = lauxlib.luaL_checkinteger(L, 1); if (i < 0) i = n + i; else if (i > n) i = n; - lauxlib.luaL_argcheck(L, 1 <= i, 1, "index out of range"); + lauxlib.luaL_argcheck(L, 1 <= i, 1, lua.to_luastring("index out of range")); return n - i; } }; @@ -281,28 +282,28 @@ const RESERVEDSLOT = 5; ** reserved slot inside the stack. */ const generic_reader = function(L, ud) { - lauxlib.luaL_checkstack(L, 2, "too many nested functions"); + lauxlib.luaL_checkstack(L, 2, lua.to_luastring("too many nested functions")); lapi.lua_pushvalue(L, 1); /* get function */ lapi.lua_call(L, 0, 1); /* call it */ if (lapi.lua_isnil(L, -1)) { lapi.lua_pop(L, 1); /* pop result */ return null; } else if (!lapi.lua_isstring(L, -1)) - lauxlib.luaL_error(L, "reader function must return a string"); + lauxlib.luaL_error(L, lua.to_luastring("reader function must return a string")); lapi.lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ return lapi.lua_tostring(L, RESERVEDSLOT); }; const luaB_load = function(L) { let s = lapi.lua_tostring(L, 1); - let mode = lauxlib.luaL_optstring(L, 3, "bt"); + let mode = lauxlib.luaL_optstring(L, 3, lua.to_luastring("bt")); let env = !lapi.lua_isnone(L, 4) ? 4 : 0; /* 'env' index or 0 if no 'env' */ let status; if (s !== null) { /* loading a string? */ let chunkname = lauxlib.luaL_optstring(L, 2, s); status = lauxlib.luaL_loadbufferx(L, s, chunkname, mode); } else { /* loading from a reader function */ - let chunkname = lauxlib.luaL_optstring(L, 2, "=(load)"); + let chunkname = lauxlib.luaL_optstring(L, 2, lua.to_luastring("=(load)")); lauxlib.luaL_checktype(L, 1, CT.LUA_TFUNCTION); lapi.lua_settop(L, RESERVEDSLOT); /* create reserved slot */ status = lapi.lua_load(L, generic_reader, null, chunkname, mode); @@ -375,10 +376,10 @@ const luaopen_base = function(L) { lauxlib.luaL_setfuncs(L, base_funcs, 0); /* set global _G */ lapi.lua_pushvalue(L, -1); - lapi.lua_setfield(L, -2, "_G"); + lapi.lua_setfield(L, -2, lua.to_luastring("_G")); /* set global _VERSION */ lapi.lua_pushliteral(L, lua.LUA_VERSION); - lapi.lua_setfield(L, -2, "_VERSION"); + lapi.lua_setfield(L, -2, lua.to_luastring("_VERSION")); return 1; }; diff --git a/src/lcode.js b/src/lcode.js index c0ca1ff..8b4a57c 100644 --- a/src/lcode.js +++ b/src/lcode.js @@ -183,7 +183,7 @@ const fixjump = function(fs, pc, dest) { let offset = dest - (pc + 1); assert(dest !== NO_JUMP); if (Math.abs(offset) > lopcode.MAXARG_sBx) - llex.luaX_syntaxerror(fs.ls, "control structure too long"); + llex.luaX_syntaxerror(fs.ls, lua.to_luastring("control structure too long")); lopcode.SETARG_sBx(jmp, offset); }; @@ -425,7 +425,7 @@ const luaK_checkstack = function(fs, n) { let newstack = fs.freereg + n; if (newstack > fs.f.maxstacksize) { if (newstack >= MAXREGS) - llex.luaX_syntaxerror(fs.ls, "function or expression needs to many registers"); + llex.luaX_syntaxerror(fs.ls, lua.to_luastring("function or expression needs to many registers")); fs.f.maxstacksize = newstack; } }; @@ -1277,4 +1277,4 @@ module.exports.luaK_setmultret = luaK_setmultret; module.exports.luaK_setoneret = luaK_setoneret; module.exports.luaK_setreturns = luaK_setreturns; module.exports.luaK_storevar = luaK_storevar; -module.exports.luaK_stringK = luaK_stringK; \ No newline at end of file +module.exports.luaK_stringK = luaK_stringK; diff --git a/src/lcorolib.js b/src/lcorolib.js index b2d0de8..58d061c 100644 --- a/src/lcorolib.js +++ b/src/lcorolib.js @@ -8,12 +8,13 @@ const lauxlib = require('./lauxlib.js'); const lstate = require('./lstate.js'); const ldo = require('./ldo.js'); const ldebug = require('./ldebug.js'); +const lobject = require('./lobject.js'); const CT = lua.constant_types; const TS = lua.thread_status; const getco = function(L) { let co = lapi.lua_tothread(L, 1); - lauxlib.luaL_argcheck(L, co, 1, "thread expected"); + lauxlib.luaL_argcheck(L, co, 1, lua.to_luastring("thread expected")); return co; }; @@ -146,4 +147,4 @@ const luaopen_coroutine = function(L) { return 1; }; -module.exports.luaopen_coroutine = luaopen_coroutine; \ No newline at end of file +module.exports.luaopen_coroutine = luaopen_coroutine; diff --git a/src/ldebug.js b/src/ldebug.js index 7c892a5..507e764 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -55,22 +55,22 @@ const lua_getstack = function(L, level, ar) { const upvalname = function(p, uv) { assert(uv < p.upvalues.length); let s = p.upvalues[uv].name; - if (s === null) return "?"; + if (s === null) return "?".charCodeAt(0); return s; }; const funcinfo = function(ar, cl) { if (cl === null || cl.type === CT.LUA_TCCL) { - ar.source = "=[JS]"; + ar.source = lua.to_luastring("=[JS]"); ar.linedefined = -1; ar.lastlinedefined = -1; ar.what = "J"; } else { let p = cl.p; - ar.source = p.source ? p.source : "=?"; + ar.source = p.source ? p.source : lua.to_luastring("=?"); ar.linedefined = p.linedefined; ar.lastlinedefined = p.lastlinedefined; - ar.what = ar.linedefined === 0 ? "main" : "Lua"; + ar.what = ar.linedefined === 0 ? lua.to_luastring("main") : lua.to_luastring("Lua"); } ar.short_src = lobject.luaO_chunkid(ar.source, luaconf.LUA_IDSIZE); @@ -99,8 +99,8 @@ const getfuncname = function(L, ci) { if (ci === null) return null; else if (ci.callstatus & lstate.CIST_FIN) { /* is this a finalizer? */ - r.name = "__gc"; - r.funcname = "metamethod"; /* report it as such */ + r.name = lua.to_luastring("__gc"); + r.funcname = lua.to_luastring("metamethod"); /* report it as such */ return r; } /* calling function is a known Lua function? */ @@ -112,7 +112,7 @@ const getfuncname = function(L, ci) { const auxgetinfo = function(L, what, ar, f, ci) { let status = 1; for (; what.length > 0; what = what.slice(1)) { - switch (what[0]) { + switch (String.fromCharCode(what[0])) { case 'S': { funcinfo(ar, f); break; @@ -139,7 +139,7 @@ const auxgetinfo = function(L, what, ar, f, ci) { case 'n': { ar.namewhat = getfuncname(L, ci, ar.name); if (ar.namewhat === null) { - ar.namewhat = ""; + ar.namewhat = []; ar.name = null; } break; @@ -157,7 +157,7 @@ const auxgetinfo = function(L, what, ar, f, ci) { const lua_getinfo = function(L, what, ar) { let status, cl, ci, func, funcOff; swapextra(L); - if (what[0] === '>') { + if (what[0] === '>'.charCodeAt(0)) { ci = null; funcOff = L.top - 1; func = L.stack[funcOff]; @@ -173,13 +173,13 @@ const lua_getinfo = function(L, what, ar) { cl = func.ttisclosure() ? func : null; status = auxgetinfo(L, what, ar, cl, ci); - if (what.indexOf('f') >= 0) { + if (what.indexOf('f'.charCodeAt(0)) >= 0) { L.stack[L.top++] = func; assert(L.top <= L.ci.top, "stack overflow"); } swapextra(L); - if (what.indexOf('L') >= 0) + if (what.indexOf('L'.charCodeAt(0)) >= 0) collectvalidlines(L, cl); return status; @@ -200,7 +200,7 @@ const kname = function(p, pc, c) { /* else no reasonable name found */ } else { /* 'c' is a register */ let what = getobjname(p, pc, c); /* search for 'c' */ - if (what && what.name[0] === 'c') { + if (what && what.name[0] === 'c'.charCodeAt(0)) { return what; } /* else no reasonable name found */ @@ -271,7 +271,7 @@ const getobjname = function(p, lastpc, reg) { }; if (r.name) { /* is a local? */ - r.funcname = "local"; + r.funcname = lua.to_luastring("local"); return r; } @@ -293,12 +293,12 @@ const getobjname = function(p, lastpc, reg) { let t = i.B; /* table index */ let vn = op === 'OP_GETTABLE' ? lfunc.luaF_getlocalname(p, t + 1, pc) : upvalname(p, t); r.name = kname(p, pc, k); - r.funcname = vn && vn === "_ENV" ? "global" : "field"; + r.funcname = vn && vn === lua.to_luastring("_ENV") ? lua.to_luastring("global") : lua.to_luastring("field"); return r; } case 'OP_GETUPVAL': { r.name = upvalname(p, i.B); - r.funcname = "upvalue"; + r.funcname = lua.to_luastring("upvalue"); return r; } case 'OP_LOADK': @@ -306,7 +306,7 @@ const getobjname = function(p, lastpc, reg) { let b = op === 'OP_LOADK' ? i.Bx : p.code[pc + 1].Ax; if (p.k[b].ttisstring()) { r.name = p.k[b].value; - r.funcname = "constant"; + r.funcname = lua.to_luastring("constant"); return r; } break; @@ -314,7 +314,7 @@ const getobjname = function(p, lastpc, reg) { case 'OP_SELF': { let k = i.C; r.name = kname(p, pc, k); - r.funcname = "method"; + r.funcname = lua.to_luastring("method"); return r; } default: break; @@ -343,7 +343,7 @@ const funcnamefromcode = function(L, ci) { if (ci.callstatus & lstate.CIST_HOOKED) { r.name = "?"; - r.funcname = "hook"; + r.funcname = lua.to_luastring("hook"); return r; } @@ -352,8 +352,8 @@ const funcnamefromcode = function(L, ci) { case 'OP_TAILCALL': return getobjname(p, pc, i.A); /* get function name */ case 'OP_TFORCALL': - r.name = "for iterator"; - r.funcname = "for iterator"; + r.name = lua.to_luastring("for iterator"); + r.funcname = lua.to_luastring("for iterator"); return r; /* other instructions can do calls through metamethods */ case 'OP_SELF': @@ -389,7 +389,7 @@ const funcnamefromcode = function(L, ci) { } r.name = L.l_G.tmname[tm].jsstring(); - r.funcname = "metamethod"; + r.funcname = lua.to_luastring("metamethod"); return r; }; @@ -413,7 +413,7 @@ const getupvalname = function(L, ci, o, name) { if (c.upvals[i].val(L) === o) { return { name: upvalname(c.p, i), - funcname: 'upvalue' + funcname: lua.to_luastring('upvalue') }; } } @@ -431,17 +431,17 @@ const varinfo = function(L, o) { kind = getobjname(ci.func.p, ci.pcOff, stkid - ci.u.l.base); } - return kind ? ` (${kind.funcname} '${kind.name}')` : ``; + return lua.to_luastring(kind ? ` (${lobject.jsstring(kind.funcname)} '${lobject.jsstring(kind.name)}')` : ``); }; const luaG_typeerror = function(L, o, op) { let t = ltm.luaT_objtypename(L, o); - luaG_runerror(L, `attempt to ${op} a ${t} value${varinfo(L, o)}`); + luaG_runerror(L, lua.to_luastring(`attempt to ${lobject.jsstring(op)} a ${lobject.jsstring(t)} value${lobject.jsstring(varinfo(L, o))}`)); }; const luaG_concaterror = function(L, p1, p2) { if (p1.ttisstring() || p1.ttisnumber()) p1 = p2; - luaG_typeerror(L, p1, 'concatenate'); + luaG_typeerror(L, p1, lua.to_luastring('concatenate')); }; /* @@ -458,18 +458,18 @@ const luaG_ordererror = function(L, p1, p2) { let t1 = ltm.luaT_objtypename(L, p1); let t2 = ltm.luaT_objtypename(L, p2); if (t1 === t2) - luaG_runerror(L, `attempt to compare two ${t1} values`); + luaG_runerror(L, lua.to_luastring(`attempt to compare two ${lobject.jsstring(t1)} values`)); else - luaG_runerror(L, `attempt to compare ${t1} with ${t2}`); + luaG_runerror(L, lua.to_luastring(`attempt to compare ${lobject.jsstring(t1)} with ${lobject.jsstring(t2)}`)); }; /* add src:line information to 'msg' */ const luaG_addinfo = function(L, msg, src, line) { - let buff = '?'; + let buff = ['?'.charCodeAt(0)]; if (src) buff = lobject.luaO_chunkid(src, luaconf.LUA_IDSIZE); - L.stack[L.top++] = L.l_G.intern(lua.to_luastring(`${buff}:${line}: ${msg}`)); // We don't need to check for overflow here + L.stack[L.top++] = L.l_G.intern(lua.to_luastring(`${lobject.jsstring(buff)}:${line}: ${lobject.jsstring(msg)}`)); return L.stack[L.top - 1]; }; @@ -500,7 +500,7 @@ const luaG_tointerror = function(L, p1, p2) { let temp = lvm.tointeger(p1); if (temp === false) p2 = p1; - luaG_runerror(L, `number${varinfo(L, p2)} has no integer representation`); + luaG_runerror(L, lua.to_luastring(`number${lobject.jsstring(varinfo(L, p2))} has no integer representation`)); }; module.exports.lua_getstack = lua_getstack; diff --git a/src/ldo.js b/src/ldo.js index 50d455e..54d1ac0 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -448,9 +448,9 @@ const lua_yieldk = function(L, nresults, ctx, k) { if (L.nny > 0) { if (L !== L.l_G.mainthread) - ldebug.luaG_runerror(L, "attempt to yield across a JS-call boundary"); + ldebug.luaG_runerror(L, lua.to_luastring("attempt to yield across a JS-call boundary")); else - ldebug.luaG_runerror(L, "attempt to yield from outside a coroutine"); + ldebug.luaG_runerror(L, lua.to_luastring("attempt to yield from outside a coroutine")); } L.status = TS.LUA_YIELD; @@ -519,8 +519,8 @@ class SParser { } const checkmode = function(L, mode, x) { - if (mode && mode.indexOf(x.charAt(0)) === -1) { - lapi.lua_pushstring(L, `attempt to load a ${x} chunk (mode is '${mode}')`); + if (mode && mode.indexOf(x.charCodeAt(0)) === -1) { + lapi.lua_pushstring(L, lua.to_luastring(`attempt to load a ${lobject.jsstring(x)} chunk (mode is '${mode}')`)); luaD_throw(L, TS.LUA_ERRSYNTAX); } }; diff --git a/src/ljstype.js b/src/ljstype.js index 7de9d9a..6f371bb 100644 --- a/src/ljstype.js +++ b/src/ljstype.js @@ -3,27 +3,27 @@ const assert = require('assert'); const lisdigit = function(c) { - return typeof c === 'string' && /^\d$/.test(c.charAt(0)); + return /^\d$/.test(String.fromCharCode(c)); }; const lisxdigit = function(c) { - return typeof c === 'string' && /^[0-9a-fA-F]$/.test(c.charAt(0)); + return /^[0-9a-fA-F]$/.test(String.fromCharCode(c)); }; const lisspace = function(c) { - return typeof c === 'string' && /^\s$/.test(c.charAt(0)); + return /^\s$/.test(String.fromCharCode(c)); }; const lislalpha = function(c) { - return typeof c === 'string' && /^[_a-zA-Z]$/.test(c.charAt(0)); + return /^[_a-zA-Z]$/.test(String.fromCharCode(c)); }; const lislalnum = function(c) { - return typeof c === 'string' && /^[_a-zA-Z0-9]$/.test(c.charAt(0)); + return /^[_a-zA-Z0-9]$/.test(String.fromCharCode(c)); }; module.exports.lisdigit = lisdigit; module.exports.lislalnum = lislalnum; module.exports.lislalpha = lislalpha; module.exports.lisspace = lisspace; -module.exports.lisxdigit = lisxdigit; \ No newline at end of file +module.exports.lisxdigit = lisxdigit; diff --git a/src/llex.js b/src/llex.js index 2d34b1f..9b81cd7 100644 --- a/src/llex.js +++ b/src/llex.js @@ -81,7 +81,7 @@ class MBuffer { this.reader = reader ? reader : null; if (!this.reader) { - this.buffer = typeof data === "string" ? data.split('') : (data ? data : []); + this.buffer = typeof data === "string" ? lua.to_luastring(data) : (data ? data : []); this.n = this.buffer instanceof DataView ? this.buffer.byteLength : this.buffer.length; this.off = 0; } @@ -97,7 +97,7 @@ class MBuffer { fill() { if (this.reader) { this.buffer = this.reader(this.L, this.data); - this.buffer = typeof this.buffer === "string" ? this.buffer.split('') : this.buffer; + this.buffer = typeof this.buffer === "string" ? lua.to_luastring(this.buffer) : this.buffer; if (this.buffer === null) return -1; this.n = this.buffer instanceof DataView ? this.buffer.byteLength - 1 : this.buffer.length - 1; @@ -150,25 +150,25 @@ const save = function(ls, c) { let b = ls.buff; if (b.n + 1 > b.buffer.length) { if (b.buffer.length >= Number.MAX_SAFE_INTEGER/2) - lexerror(ls, "lexical element too long", 0); + lexerror(ls, lua.to_luastring("lexical element too long"), 0); } b.buffer[b.n++] = c < 0 ? 255 + c + 1 : c; }; const luaX_token2str = function(ls, token) { if (typeof token === "string" || token < FIRST_RESERVED) { /* single-byte symbols? */ - return `'${typeof token === "string" ? token : String.fromCharCode(token)}'`; + return lua.to_luastring(`'${typeof token === "string" ? token : lobject.jsstring(token)}'`); } else { let s = luaX_tokens[token - FIRST_RESERVED]; if (token < R.TK_EOS) /* fixed format (symbols and reserved words)? */ - return `'${s}'`; + return lua.to_luastring(`'${s}'`); else /* names, strings, and numerals */ - return s; + return lua.to_luastring(s); } }; const currIsNewline = function(ls) { - return ls.current === '\n' || ls.current === '\r'; + return ls.current === '\n'.charCodeAt(0) || ls.current === '\r'.charCodeAt(0); }; const next = function(ls) { @@ -191,7 +191,7 @@ const inclinenumber = function(ls) { if (currIsNewline(ls) && ls.current !== old) next(ls); /* skip '\n\r' or '\r\n' */ if (++ls.linenumber >= Number.MAX_SAFE_INTEGER) - lexerror(ls, "chunk has too many lines", 0); + lexerror(ls, lua.to_luastring("chunk has too many lines"), 0); }; const luaX_setinput = function(L, ls, z, source, firstchar) { @@ -222,7 +222,7 @@ const luaX_setinput = function(L, ls, z, source, firstchar) { }; const check_next1 = function(ls, c) { - if (ls.current === c) { + if (ls.current === c.charCodeAt(0)) { next(ls); return true; } @@ -235,7 +235,7 @@ const check_next1 = function(ls, c) { ** saves it */ const check_next2 = function(ls, set) { - if (ls.current === set.charAt(0) || ls.current === set.charAt(1)) { + if (ls.current === set.charAt(0).charCodeAt(0) || ls.current === set.charAt(1).charCodeAt(0)) { save_and_next(ls); return true; } @@ -261,11 +261,11 @@ const read_numeral = function(ls, seminfo) { else break; } - save(ls, '\0'); + save(ls, 0); let obj = lobject.luaO_str2num(ls.buff.buffer); if (obj === false) /* format error? */ - lexerror(ls, "malformed number", R.TK_FLT); + lexerror(ls, lua.to_luastring("malformed number"), R.TK_FLT); if (obj.ttisinteger()) { seminfo.i = obj.value; return R.TK_INT; @@ -280,8 +280,8 @@ const txtToken = function(ls, token) { switch (token) { case R.TK_NAME: case R.TK_STRING: case R.TK_FLT: case R.TK_INT: - save(ls, '\0'); - return `'${ls.buff.buffer.join('')}'`; + save(ls, 0); + return lua.to_luastring(`'${lobject.jsstring(ls.buff.buffer)}'`); default: return luaX_token2str(ls, token); } @@ -290,12 +290,12 @@ 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, `${msg instanceof TValue ? msg.value : msg} near ${txtToken(ls, token)}`); + lapi.lua_pushstring(ls.L, lua.to_luastring(`${msg instanceof TValue ? msg.jsstring() : msg} near ${lobject.jsstring(txtToken(ls, token))}`)); ldo.luaD_throw(ls.L, TS.LUA_ERRSYNTAX); }; const luaX_syntaxerror = function(ls, msg) { - msg = msg instanceof TValue ? msg.value : msg; + msg = msg instanceof TValue ? msg.value : lua.to_luastring(msg); lexerror(ls, msg, ls.t.token); }; @@ -307,9 +307,9 @@ const luaX_syntaxerror = function(ls, msg) { const skip_sep = function(ls) { let count = 0; let s = ls.current; - assert(s === '[' || s === ']'); + assert(s === '['.charCodeAt(0) || s === ']'.charCodeAt(0)); save_and_next(ls); - while (ls.current === '=') { + while (ls.current === '='.charCodeAt(0)) { save_and_next(ls); count++; } @@ -329,18 +329,18 @@ const read_long_string = function(ls, seminfo, sep) { case -1: { /* error */ let what = seminfo ? "string" : "comment"; let msg = `unfinished long ${what} (starting at line ${line})`; - lexerror(ls, msg, R.TK_EOS); + lexerror(ls, lua.to_luastring(msg), R.TK_EOS); break; } - case ']': { + case ']'.charCodeAt(0): { if (skip_sep(ls) === sep) { save_and_next(ls); /* skip 2nd ']' */ skip = true; } break; } - case '\n': case '\r': { - save(ls, '\n'); + case '\n'.charCodeAt(0): case '\r'.charCodeAt(0): { + save(ls, '\n'.charCodeAt(0)); inclinenumber(ls); if (!seminfo) { ls.buff.n = 0; @@ -358,11 +358,7 @@ const read_long_string = function(ls, seminfo, sep) { if (seminfo) seminfo.ts = new TValue( CT.LUA_TLNGSTR, - lua.to_luastring( - ls.buff.buffer - .slice(2 + sep, 2 + sep - 2 * (2 + sep)) - .join('') - ) + ls.buff.buffer.slice(2 + sep, 2 + sep - 2 * (2 + sep)) ); }; @@ -376,7 +372,7 @@ const esccheck = function(ls, c, msg) { const gethexa = function(ls) { save_and_next(ls); - esccheck(ls, ljstype.lisxdigit(ls.current), "hexadecimal digit expected"); + esccheck(ls, ljstype.lisxdigit(ls.current), lua.to_luastring("hexadecimal digit expected")); return lobject.luaO_hexavalue(ls.current); }; @@ -390,17 +386,17 @@ const readhexaesc = function(ls) { const readutf8desc = function(ls) { let i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ save_and_next(ls); /* skip 'u' */ - esccheck(ls, ls.current === '{', "missing '{'"); + esccheck(ls, ls.current === '{'.charCodeAt(0), lua.to_luastring("missing '{'")); let r = gethexa(ls); /* must have at least one digit */ save_and_next(ls); while (ljstype.lisxdigit(ls.current)) { i++; r = (r << 4) + lobject.luaO_hexavalue(ls.current); - esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large"); + esccheck(ls, r <= 0x10FFFF, lua.to_luastring("UTF-8 value too large")); save_and_next(ls); } - esccheck(ls, ls.current === '}', "missing '}'"); + esccheck(ls, ls.current === '}'.charCodeAt(0), lua.to_luastring("missing '}'")); next(ls); /* skip '}' */ ls.buff.n -= i; /* remove saved chars from buffer */ return r; @@ -420,7 +416,7 @@ const readdecesc = function(ls) { r = 10 * r + parseInt(ls.current); save_and_next(ls); } - esccheck(ls, r <= 255, "decimal escape too large"); + esccheck(ls, r <= 255, lua.to_luastring("decimal escape too large")); ls.buff.n -= i; /* remove read digits from buffer */ return r; }; @@ -431,29 +427,29 @@ const read_string = function(ls, del, seminfo) { while (ls.current !== del) { switch (ls.current) { case -1: - lexerror(ls, "unfinished string", R.TK_EOS); + lexerror(ls, lua.to_luastring("unfinished string"), R.TK_EOS); break; - case '\n': - case '\r': - lexerror(ls, "unfinished string", R.TK_STRING); + case '\n'.charCodeAt(0): + case '\r'.charCodeAt(0): + lexerror(ls, lua.to_luastring("unfinished string"), R.TK_STRING); break; - case '\\': { /* escape sequences */ + case '\\'.charCodeAt(0): { /* escape sequences */ save_and_next(ls); /* keep '\\' for error messages */ let will; let c; switch(ls.current) { - case 'a': c = '\a'; will = 'read_save'; break; - case 'b': c = '\b'; will = 'read_save'; break; - case 'f': c = '\f'; will = 'read_save'; break; - case 'n': c = '\n'; will = 'read_save'; break; - case 'r': c = '\r'; will = 'read_save'; break; - case 't': c = '\t'; will = 'read_save'; break; - case 'v': c = '\v'; will = 'read_save'; break; + case 'a': c = '\a'.charCodeAt(0); will = 'read_save'; break; + case 'b': c = '\b'.charCodeAt(0); will = 'read_save'; break; + case 'f': c = '\f'.charCodeAt(0); will = 'read_save'; break; + case 'n': c = '\n'.charCodeAt(0); will = 'read_save'; break; + case 'r': c = '\r'.charCodeAt(0); will = 'read_save'; break; + case 't': c = '\t'.charCodeAt(0); will = 'read_save'; break; + case 'v': c = '\v'.charCodeAt(0); will = 'read_save'; break; case 'x': c = readhexaesc(ls); will = 'read_save'; break; case 'u': utf8esc(ls); will = 'no_save'; break; - case '\n': case '\r': + case '\n'.charCodeAt(0): case '\r'.charCodeAt(0): inclinenumber(ls); c = '\n'; will = 'only_save'; break; - case '\\': case '\"': case '\'': + case '\\'.charCodeAt(0): case '\"'.charCodeAt(0): case '\''.charCodeAt(0): c = ls.current; will = 'read_save'; break; case -1: will = 'no_save'; break; /* will raise an error next loop */ case 'z': { /* zap following span of spaces */ @@ -466,7 +462,7 @@ const read_string = function(ls, del, seminfo) { will = 'no_save'; break; } default: { - esccheck(ls, ljstype.lisdigit(ls.current), "invalid escape sequence"); + esccheck(ls, ljstype.lisdigit(ls.current), lua.to_luastring("invalid escape sequence")); c = readdecesc(ls); /* digital escape '\ddd' */ will = 'only_save'; break; } @@ -490,10 +486,7 @@ const read_string = function(ls, del, seminfo) { seminfo.ts = new TValue( CT.LUA_TLNGSTR, - ls.buff.buffer - .slice(1, ls.buff.n-1) - .map(e => typeof e === "string" ? lua.to_luastring(e) : [e]) - .reduce((acc, e) => acc = acc.concat(e), []) /* Hex value must not be converted */ + ls.buff.buffer.slice(1, ls.buff.n-1) ); }; @@ -507,20 +500,20 @@ const llex = function(ls, seminfo) { for (;;) { switch (ls.current) { - case '\n': case '\r': { /* line breaks */ + case '\n'.charCodeAt(0): case '\r'.charCodeAt(0): { /* line breaks */ inclinenumber(ls); break; } - case ' ': case '\f': case '\t': case '\v': { /* spaces */ + case ' '.charCodeAt(0): case '\f'.charCodeAt(0): case '\t'.charCodeAt(0): case '\v'.charCodeAt(0): { /* spaces */ next(ls); break; } - case '-': { /* '-' or '--' (comment) */ + case '-'.charCodeAt(0): { /* '-' or '--' (comment) */ next(ls); - if (ls.current !== '-') return '-'; + if (ls.current !== '-'.charCodeAt(0)) return '-'; /* else is a comment */ next(ls); - if (ls.current === '[') { /* long comment? */ + if (ls.current === '['.charCodeAt(0)) { /* long comment? */ let sep = skip_sep(ls); ls.buff.n = 0; /* 'skip_sep' may dirty the buffer */ ls.buff.buffer = []; @@ -537,52 +530,52 @@ const llex = function(ls, seminfo) { next(ls); /* skip until end of line (or end of file) */ break; } - case '[': { /* long string or simply '[' */ + case '['.charCodeAt(0): { /* long string or simply '[' */ let sep = skip_sep(ls); if (sep >= 0) { read_long_string(ls, seminfo, sep); return R.TK_STRING; } else if (sep !== -1) /* '[=...' missing second bracket */ - lexerror(ls, "invalid long string delimiter", R.TK_STRING); + lexerror(ls, lua.to_luastring("invalid long string delimiter"), R.TK_STRING); return '['; } - case '=': { + case '='.charCodeAt(0): { next(ls); if (check_next1(ls, '=')) return R.TK_EQ; else return '='; } - case '<': { + case '<'.charCodeAt(0): { next(ls); if (check_next1(ls, '=')) return R.TK_LE; else if (check_next1(ls, '<')) return R.TK_SHL; else return '<'; } - case '>': { + case '>'.charCodeAt(0): { next(ls); if (check_next1(ls, '=')) return R.TK_GE; else if (check_next1(ls, '>')) return R.TK_SHR; else return '>'; } - case '/': { + case '/'.charCodeAt(0): { next(ls); if (check_next1(ls, '/')) return R.TK_IDIV; else return '/'; } - case '~': { + case '~'.charCodeAt(0): { next(ls); if (check_next1(ls, '=')) return R.TK_NE; else return '~'; } - case ':': { + case ':'.charCodeAt(0): { next(ls); if (check_next1(ls, ':')) return R.TK_DBCOLON; else return ':'; } - case '"': case '\'': { /* short literal strings */ + case '"'.charCodeAt(0): case '\''.charCodeAt(0): { /* short literal strings */ read_string(ls, ls.current, seminfo); return R.TK_STRING; } - case '.': { /* '.', '..', '...', or number */ + case '.'.charCodeAt(0): { /* '.', '..', '...', or number */ save_and_next(ls); if (check_next1(ls, '.')) { if (check_next1(ls, '.')) diff --git a/src/lmathlib.js b/src/lmathlib.js index 7553dfd..500331b 100644 --- a/src/lmathlib.js +++ b/src/lmathlib.js @@ -37,13 +37,13 @@ const math_random = function(L) { up = lauxlib.luaL_checkinteger(L, 2); break; } - default: return lauxlib.luaL_error(L, "wrong number of arguments"); + default: return lauxlib.luaL_error(L, lua.to_luastring("wrong number of arguments")); } /* random integer in the interval [low, up] */ - lauxlib.luaL_argcheck(L, low <= up, 1, "interval is empty"); + lauxlib.luaL_argcheck(L, low <= up, 1, lua.to_luastring("interval is empty")); lauxlib.luaL_argcheck(L, low >= 0 || up <= Number.MAX_SAFE_INTEGER + low, 1, - "interval too large"); + lua.to_luastring("interval too large")); r *= (up - low) + 1; lapi.lua_pushinteger(L, r + low); @@ -173,7 +173,7 @@ const math_rad = function(L) { const math_min = function(L) { let n = lapi.lua_gettop(L); /* number of arguments */ let imin = 1; /* index of current minimum value */ - lauxlib.luaL_argcheck(L, n >= 1, 1, "value expected"); + lauxlib.luaL_argcheck(L, n >= 1, 1, lua.to_luastring("value expected")); for (let i = 2; i <= n; i++){ if (lapi.lua_compare(L, i, imin, lua.LUA_OPLT)) imin = i; @@ -185,7 +185,7 @@ const math_min = function(L) { const math_max = function(L) { let n = lapi.lua_gettop(L); /* number of arguments */ let imax = 1; /* index of current minimum value */ - lauxlib.luaL_argcheck(L, n >= 1, 1, "value expected"); + lauxlib.luaL_argcheck(L, n >= 1, 1, lua.to_luastring("value expected")); for (let i = 2; i <= n; i++){ if (lapi.lua_compare(L, imax, i, lua.LUA_OPLT)) imax = i; @@ -211,7 +211,7 @@ const math_fmod = function(L) { if (lapi.lua_isinteger(L, 1) && lapi.lua_isinteger(L, 2)) { let d = lapi.lua_tointeger(L, 2); if (Math.abs(d) + 1 <= 1) { - lauxlib.luaL_argcheck(L, d !== 0, 2, "zero"); + lauxlib.luaL_argcheck(L, d !== 0, 2, lua.to_luastring("zero")); lapi.lua_pushinteger(L, 0); } else lapi.lua_pushinteger(L, lapi.lua_tointeger(L, 1) % d); @@ -265,13 +265,13 @@ const mathlib = { const luaopen_math = function(L) { lauxlib.luaL_newlib(L, mathlib); lapi.lua_pushnumber(L, Math.PI); - lapi.lua_setfield(L, -2, "pi"); + lapi.lua_setfield(L, -2, lua.to_luastring("pi")); lapi.lua_pushnumber(L, Number.MAX_VALUE); - lapi.lua_setfield(L, -2, "huge"); + lapi.lua_setfield(L, -2, lua.to_luastring("huge")); lapi.lua_pushinteger(L, Number.MAX_SAFE_INTEGER); - lapi.lua_setfield(L, -2, "maxinteger"); + lapi.lua_setfield(L, -2, lua.to_luastring("maxinteger")); lapi.lua_pushinteger(L, Number.MIN_SAFE_INTEGER); - lapi.lua_setfield(L, -2, "mininteger"); + lapi.lua_setfield(L, -2, lua.to_luastring("mininteger")); return 1; }; diff --git a/src/lobject.js b/src/lobject.js index 966bdd8..812ac6a 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -278,49 +278,49 @@ class LocVar { } } -const RETS = "..."; -const PRE = "[string \""; -const POS = "\"]"; +const RETS = lua.to_luastring("..."); +const PRE = lua.to_luastring("[string \""); +const POS = lua.to_luastring("\"]"); const luaO_chunkid = function(source, bufflen) { - source = source instanceof TValue ? source.jsstring() : source; + source = source instanceof TValue ? source.value : source; bufflen = bufflen instanceof TValue ? bufflen.value : bufflen; let l = source.length; - let out = ""; - if (source.charAt(0) === '=') { /* 'literal' source */ + let out = []; + if (source[0] === '='.charCodeAt(0)) { /* 'literal' source */ if (l < bufflen) /* small enough? */ - out = `${source.slice(1)}`; + out = source.slice(1); else { /* truncate it */ - out += `${source.slice(1, bufflen)}`; + out = out.concat(source.slice(1, bufflen)); } } else if (source.charAt(0) === '@') { /* file name */ if (l <= bufflen) /* small enough? */ - out = `${source.slice(1)}`; + out = source.slice(1); else { /* add '...' before rest of name */ bufflen -= RETS.length; - out = `${RETS}${source.slice(1, l - bufflen)}`; + out = RETS.concat(source.slice(1, l - bufflen)); } } else { /* string; format as [string "source"] */ let nli = source.indexOf('\n'); /* find first new line (if any) */ let nl = nli ? source.slice(nli) : null; - out = `${PRE}`; /* add prefix */ + out = PRE; /* add prefix */ bufflen -= PRE.length + RETS.length + POS.length + 1; /* save space for prefix+suffix+'\0' */ if (l < bufflen && nl === null) { /* small one-line source? */ - out += `${source}`; /* keep it */ + out = out.conat(source); /* keep it */ } else { if (nl !== null) l = nl.length - source.length; /* stop at first newline */ if (l > bufflen) l = bufflen; - out += `${source}${RETS}`; + out = out.concat(source).concat(RETS); } - out += POS; + out = out.concat(POS); } return out; }; const luaO_hexavalue = function(c) { - if (ljstype.lisdigit(c)) return c.charCodeAt(0) - '0'.charCodeAt(0); - else return (c.toLowerCase().charCodeAt(0) - 'a'.charCodeAt(0)) + 10; + if (ljstype.lisdigit(c)) return c - '0'.charCodeAt(0); + else return (String.fromCharCode(c).toLowerCase().charCodeAt(0) - 'a'.charCodeAt(0)) + 10; }; const UTF8BUFFSZ = 8; @@ -329,15 +329,15 @@ const luaO_utf8desc = function(buff, x) { let n = 1; /* number of bytes put in buffer (backwards) */ assert(x <= 0x10FFFF); if (x < 0x80) /* ascii? */ - buff[UTF8BUFFSZ - 1] = String.fromCharCode(x); + buff[UTF8BUFFSZ - 1] = x; else { /* need continuation bytes */ let mfb = 0x3f; /* maximum that fits in first byte */ do { - buff[UTF8BUFFSZ - (n++)] = String.fromCharCode(0x80 | (x & 0x3f)); + buff[UTF8BUFFSZ - (n++)] = 0x80 | (x & 0x3f); x >>= 6; /* remove added bits */ mfb >>= 1; /* now there is one less bit available in first byte */ } while (x > mfb); /* still needs continuation byte? */ - buff[UTF8BUFFSZ - n] = String.fromCharCode((~mfb << 1) | x); /* add first byte */ + buff[UTF8BUFFSZ - n] = (~mfb << 1) | x; /* add first byte */ } return n; }; @@ -383,19 +383,19 @@ const lua_strx2number = function(s) { let neg; /* 1 if number is negative */ let hasdot = false; /* true after seen a dot */ - while (ljstype.lisspace(s.charAt(0))) s = s.slice(1); /* skip initial spaces */ + while (ljstype.lisspace(s)) s = s.slice(1); /* skip initial spaces */ - neg = s.charAt(0) === '-'; /* check signal */ - s = neg || s.charAt(0) === '+' ? s.slice(1) : s; /* skip sign if one */ - if (!(s.charAt(0) === '0' && (s.charAt(1) === 'x' || s.charAt(1) === 'X'))) /* check '0x' */ + neg = s[0] === '-'.charCodeAt(0); /* check signal */ + s = neg || s[0] === '+'.charCodeAt(0) ? s.slice(1) : s; /* skip sign if one */ + if (!(s[0] === '0' && (s[1] === 'x'.charCodeAt(0) || s[1] === 'X'.charCodeAt(0)))) /* check '0x' */ return 0.0; /* invalid format (no '0x') */ for (s = s.slice(2); ; s = s.slice(1)) { /* skip '0x' and read numeral */ - if (s.charAt(0) === dot) { + if (s[0] === dot) { if (hasdot) break; /* second dot? stop loop */ else hasdot = true; - } else if (ljstype.lisxdigit(s.charAt(0))) { - if (sigdig === 0 && s.charAt(0) === '0') /* non-significant digit (zero)? */ + } else if (ljstype.lisxdigit(s[0])) { + if (sigdig === 0 && s[0] === '0'.charCodeAt(0)) /* non-significant digit (zero)? */ nosigdig++; else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ r = (r * 16) + luaO_hexavalue(s); @@ -407,35 +407,35 @@ const lua_strx2number = function(s) { if (nosigdig + sigdig === 0) /* no digits? */ return 0.0; /* invalid format */ e *= 4; /* each digit multiplies/divides value by 2^4 */ - if (s.charAt(0) === 'p' || s.charAt(0) === 'P') { /* exponent part? */ + if (s[0] === 'p'.charCodeAt(0) || s[0] === 'P'.charCodeAt(0)) { /* exponent part? */ let exp1 = 0; /* exponent value */ let neg1; /* exponent signal */ s = s.slice(1); /* skip 'p' */ - neg1 = s.charAt(0) === '-'; /* check signal */ - s = neg1 || s.charAt(0) === '+' ? s.slice(1) : s; /* skip sign if one */ - if (!ljstype.lisdigit(s.charAt(0))) + neg1 = s[0] === '-'.charCodeAt(0); /* check signal */ + s = neg1 || s[0] === '+'.charCodeAt(0) ? s.slice(1) : s; /* skip sign if one */ + if (!ljstype.lisdigit(s[0])) return 0.0; /* invalid; must have at least one digit */ - while (ljstype.lisdigit(s.charAt(0))) { /* read exponent */ - exp1 = exp1 * 10 + s.charCodeAt(0) - '0'.charCodeAt(0); + while (ljstype.lisdigit(s[0])) { /* read exponent */ + exp1 = exp1 * 10 + s - '0'.charCodeAt(0); s = s.slice(1); } if (neg1) exp1 = -exp1; e += exp1; } if (neg) r = -r; - return s.trim().search(/s/) < 0 ? ldexp(r, e) : null; /* Only valid if nothing left is s*/ + return 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(s); + let flt = mode === 'x' ? lua_strx2number(s) : parseFloat(jsstring(s)); return !isNaN(flt) ? flt : null; /* OK if no trailing characters */ }; const l_str2d = function(s) { - let pidx = /[.xXnN]/g.exec(s); + let pidx = /[.xXnN]/g.exec(String.fromCharCode(...s)); pidx = pidx ? pidx.index : null; let pmode = pidx ? s[pidx] : null; - let mode = pmode ? pmode.toLowerCase() : 0; + let mode = pmode ? String.fromCharCode(pmode).toLowerCase() : 0; if (mode === 'n') /* reject 'inf' and 'nan' */ return null; let end = l_str2dloc(s, mode); /* try to convert */ @@ -454,12 +454,12 @@ const l_str2int = function(s) { let neg; while (ljstype.lisspace(s[0])) s = s.slice(1); /* skip initial spaces */ - neg = s[0] === '-'; + neg = s[0] === '-'.charCodeAt(0); - if (neg || s[0] === '+') + if (neg || s[0] === '+'.charCodeAt(0)) s = s.slice(1); - if (s[0] === '0' && (s[1] === 'x' || s[1] === 'X')) { /* hex? */ + if (s[0] === '0'.charCodeAt(0) && (s[1] === 'x'.charCodeAt(0) || s[1] === 'X'.charCodeAt(0))) { /* hex? */ s = s.slice(2); /* skip '0x' */ for (; ljstype.lisxdigit(s[0]); s = s.slice(1)) { @@ -468,7 +468,7 @@ const l_str2int = function(s) { } } else { /* decimal */ for (; ljstype.lisdigit(s[0]); s = s.slice(1)) { - let d = parseInt(s[0]); + let d = s[0] - '0'.charCodeAt(0); if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ return null; /* do not accept it (as integer) */ a = a * 10 + d; @@ -478,7 +478,7 @@ const l_str2int = function(s) { while (ljstype.lisspace(s[0])) s = s.slice(1); /* skip trailing spaces */ - if (empty || s[0] !== "\0") return null; /* something wrong in the numeral */ + if (empty || s[0] !== 0) return null; /* something wrong in the numeral */ else { return neg ? -a : a; } @@ -490,7 +490,7 @@ const luaO_str2num = function(s) { if (s2i !== null) { /* try as an integer */ return new TValue(CT.LUA_TNUMINT, s2i); } else { /* else try as a float */ - s2i = l_str2d(s.join('')); + s2i = l_str2d(s); if (s2i !== null) { return new TValue(CT.LUA_TNUMFLT, s2i); diff --git a/src/lparser.js b/src/lparser.js index 1806bbe..01b9a08 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, `${llex.luaX_token2str(ls, token)} expected`); + llex.luaX_syntaxerror(ls, lua.to_luastring(`${lobject.jsstring(llex.luaX_token2str(ls, token))} expected`)); }; const errorlimit = function(fs, limit, what) { @@ -167,7 +167,7 @@ const errorlimit = function(fs, limit, what) { let line = fs.f.linedefined; let where = (line === 0) ? "main function" : `function at line ${line}`; let msg = `too many ${what} (limit is ${limit}) in ${where}`; - llex.luaX_syntaxerror(fs.ls, msg); + llex.luaX_syntaxerror(fs.ls, lua.to_luastring(msg)); }; const checklimit = function(fs, v, l, what) { @@ -204,7 +204,7 @@ const check_match = function(ls, what, who, where) { error_expected(ls, what); else llex.luaX_syntaxerror(ls, - `${llex.luaX_token2str(ls, what)} expected (to close ${llex.luaX_token2str(ls, who)} at line ${where}`); + lua.to_luastring(`${lobject.jsstring(llex.luaX_token2str(ls, what))} expected (to close ${lobject.jsstring(llex.luaX_token2str(ls, who))} at line ${where}`)); } }; @@ -241,7 +241,7 @@ const new_localvar = function(ls, name) { let fs = ls.fs; let dyd = ls.dyd; let reg = registerlocalvar(ls, name); - checklimit(fs, dyd.actvar.n + 1 - fs.firstlocal, MAXVARS, "local variables"); + checklimit(fs, dyd.actvar.n + 1 - fs.firstlocal, MAXVARS, lua.to_luastring("local variables")); dyd.actvar.arr[dyd.actvar.n] = new Vardesc(); dyd.actvar.arr[dyd.actvar.n].idx = reg; dyd.actvar.n++; @@ -273,7 +273,7 @@ const removevars = function(fs, tolevel) { const searchupvalue = function(fs, name) { let up = fs.f.upvalues; for (let i = 0; i < fs.nups; i++) { - if (up[i].name.jsstring() === name.jsstring()) + if (up[i].name.join() === name.join()) return i; } return -1; /* not found */ @@ -281,7 +281,7 @@ const searchupvalue = function(fs, name) { const newupvalue = function(fs, name, v) { let f = fs.f; - checklimit(fs, fs.nups + 1, lfunc.MAXUPVAL, "upvalues"); + checklimit(fs, fs.nups + 1, lfunc.MAXUPVAL, lua.to_luastring("upvalues")); f.upvalues[fs.nups] = new UpVal(fs.ls.L); f.upvalues[fs.nups].instack = v.k === expkind.VLOCAL; f.upvalues[fs.nups].idx = v.u.info; @@ -291,7 +291,7 @@ const newupvalue = function(fs, name, v) { const searchvar = function(fs, n) { for (let i = fs.nactvar - 1; i >= 0; i--) { - if (n.jsstring() === getlocvar(fs, i).varname.jsstring()) + if (n.join() === getlocvar(fs, i).varname.join()) return i; } @@ -372,7 +372,7 @@ const adjust_assign = function(ls, nvars, nexps, e) { const enterlevel = function(ls) { let L = ls.L; ++L.nCcalls; - checklimit(ls.fs, L.nCcalls, llimit.LUAI_MAXCCALLS, "JS levels"); + checklimit(ls.fs, L.nCcalls, llimit.LUAI_MAXCCALLS, lua.to_luastring("JS levels")); }; const leavelevel = function(ls) { @@ -383,10 +383,10 @@ const closegoto = function(ls, g, label) { let fs = ls.fs; let gl = ls.dyd.gt; let gt = gl.arr[g]; - assert(gt.name.jsstring() === label.name.jsstring()); + assert(gt.name.value.join() === label.name.value.join()); if (gt.nactvar < label.nactvar) { let vname = getlocvar(fs, gt.nactvar).varname; - semerror(ls, ` at line ${gt.line} jumps into the scope of local '${vname.value}'`); + semerror(ls, lua.to_luastring(` at line ${gt.line} jumps into the scope of local '${vname.jsstring()}'`)); } lcode.luaK_patchlist(fs, gt.pc, label.pc); /* remove goto from pending list */ @@ -405,7 +405,7 @@ const findlabel = function(ls, g) { /* check labels in current block for a match */ for (let i = bl.firstlabel; i < dyd.label.n; i++) { let lb = dyd.label.arr[i]; - if (lb.name.jsstring() === gt.name.jsstring()) { /* correct label? */ + if (lb.name.value.join() === gt.name.value.join()) { /* correct label? */ if (gt.nactvar > lb.nactvar && (bl.upval || dyd.label.n > bl.firstlabel)) lcode.luaK_patchclose(ls.fs, gt.pc, lb.nactvar); closegoto(ls, g, lb); /* close it */ @@ -434,7 +434,7 @@ const findgotos = function(ls, lb) { let gl = ls.dyd.gt; let i = ls.fs.bl.firstgoto; while (i < gl.n) { - if (gl.arr[i].name.jsstring() === lb.name.jsstring()) + if (gl.arr[i].name.value.join() === lb.name.value.join()) closegoto(ls, i, lb); else i++; @@ -490,9 +490,9 @@ const breaklabel = function(ls) { */ const undefgoto = function(ls, gt) { const msg = llex.isreserved(gt.name.value) - ? `<${gt.name.value}> at line ${gt.line} not inside a loop` - : `no visible label '${gt.name.value}' for at line ${gt.line}`; - semerror(ls, msg); + ? `<${gt.name.jsstring()}> at line ${gt.line} not inside a loop` + : `no visible label '${gt.name.jsstring()}' for at line ${gt.line}`; + semerror(ls, lua.to_luastring(msg)); }; /* @@ -638,7 +638,7 @@ const recfield = function(ls, cc) { let val = new expdesc(); if (ls.t.token === R.TK_NAME) { - checklimit(fs, cc.nh, Number.MAX_SAFE_INTEGER, "items in a constructor"); + checklimit(fs, cc.nh, Number.MAX_SAFE_INTEGER, lua.to_luastring("items in a constructor")); checkname(ls, key); } else /* ls->t.token === '[' */ yindex(ls, key); @@ -676,7 +676,7 @@ const lastlistfield = function(fs, cc) { const listfield = function(ls, cc) { /* listfield -> exp */ expr(ls, cc.v); - checklimit(ls.fs, cc.na, Number.MAX_SAFE_INTEGER, "items in a constructor"); + checklimit(ls.fs, cc.na, Number.MAX_SAFE_INTEGER, lua.to_luastring("items in a constructor")); cc.na++; cc.tostore++; }; @@ -748,7 +748,7 @@ const parlist = function(ls) { f.is_vararg = 1; /* declared vararg */ break; } - default: llex.luaX_syntaxerror(ls, " or '...' expected"); + default: llex.luaX_syntaxerror(ls, lua.to_luastring(" or '...' expected")); } } while(!f.is_vararg && testnext(ls, ',')); } @@ -766,7 +766,7 @@ const body = function(ls, e, ismethod, line) { open_func(ls, new_fs, bl); checknext(ls, '('); if (ismethod) { - new_localvarliteral(ls, "self"); /* create 'self' parameter */ + new_localvarliteral(ls, lua.to_luastring("self")); /* create 'self' parameter */ adjustlocalvars(ls, 1); } parlist(ls); @@ -815,7 +815,7 @@ const funcargs = function(ls, f, line) { break; } default: { - llex.luaX_syntaxerror(ls, "function arguments expected"); + llex.luaX_syntaxerror(ls, lua.to_luastring("function arguments expected")); } } assert(f.k === expkind.VNONRELOC); @@ -855,7 +855,7 @@ const primaryexp = function(ls, v) { return; } default: { - llex.luaX_syntaxerror(ls, "unexpected symbol"); + llex.luaX_syntaxerror(ls, lua.to_luastring("unexpected symbol")); } } }; @@ -929,7 +929,7 @@ const simpleexp = function(ls, v) { } case R.TK_DOTS: { /* vararg */ let fs = ls.fs; - check_condition(ls, fs.f.is_vararg, "cannot use '...' outside a vararg function"); + check_condition(ls, fs.f.is_vararg, lua.to_luastring("cannot use '...' outside a vararg function")); init_exp(v, expkind.VVARARG, lcode.luaK_codeABC(fs, OpCodesI.OP_VARARG, 0, 1, 0)); break; } @@ -1101,14 +1101,14 @@ const check_conflict = function(ls, lh, v) { const assignment = function(ls, lh, nvars) { let e = new expdesc(); - check_condition(ls, vkisvar(lh.v.k), "syntax error"); + check_condition(ls, vkisvar(lh.v.k), lua.to_luastring("syntax error")); if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ let nv = new LHS_assign(); nv.prev = lh; suffixedexp(ls, nv.v); if (nv.v.k !== expkind.VINDEXED) check_conflict(ls, lh, nv.v); - checklimit(ls.fs, nvars + ls.L.nCcalls, llimit.LUAI_MAXCCALLS, "JS levels"); + checklimit(ls.fs, nvars + ls.L.nCcalls, llimit.LUAI_MAXCCALLS, lua.to_luastring("JS levels")); assignment(ls, nv, nvars + 1); } else { /* assignment -> '=' explist */ checknext(ls, '='); @@ -1150,8 +1150,8 @@ const gotostat = function(ls, pc) { /* check for repeated labels on the same block */ const checkrepeated = function(fs, ll, label) { for (let i = fs.bl.firstlabel; i < ll.n; i++) { - if (label.jsstring() === ll.arr[i].name.jsstring()) { - semerror(fs.ls, `label '${label}' already defined on line ${ll.arr[i].line}`); + if (label.value.join() === ll.arr[i].name.value.join()) { + semerror(fs.ls, lua.to_luastring(`label '${label.jsstring()}' already defined on line ${ll.arr[i].line}`)); } } }; @@ -1252,9 +1252,9 @@ const fornum = function(ls, varname, line) { /* fornum -> NAME = exp1,exp1[,exp1] forbody */ let fs = ls.fs; let base = fs.freereg; - new_localvarliteral(ls, "(for index)"); - new_localvarliteral(ls, "(for limit)"); - new_localvarliteral(ls, "(for step)"); + new_localvarliteral(ls, lua.to_luastring("(for index)")); + new_localvarliteral(ls, lua.to_luastring("(for limit)")); + new_localvarliteral(ls, lua.to_luastring("(for step)")); new_localvar(ls, varname); checknext(ls, '='); exp1(ls); /* initial value */ @@ -1276,9 +1276,9 @@ const forlist = function(ls, indexname) { let nvars = 4; /* gen, state, control, plus at least one declared var */ let base = fs.freereg; /* create control variables */ - new_localvarliteral(ls, "(for generator)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for control)"); + new_localvarliteral(ls, lua.to_luastring("(for generator)")); + new_localvarliteral(ls, lua.to_luastring("(for state)")); + new_localvarliteral(ls, lua.to_luastring("(for control)")); /* create declared variables */ new_localvar(ls, indexname); while (testnext(ls, ',')) { @@ -1302,7 +1302,7 @@ const forstat = function(ls, line) { switch (ls.t.token) { case '=': fornum(ls, varname, line); break; case ',': case R.TK_IN: forlist(ls, varname); break; - default: llex.luaX_syntaxerror(ls, "'=' or 'in' expected"); + default: llex.luaX_syntaxerror(ls, lua.to_luastring("'=' or 'in' expected")); } check_match(ls, R.TK_END, R.TK_FOR, line); leaveblock(fs); /* loop scope ('break' jumps to this point) */ @@ -1418,7 +1418,7 @@ const exprstat= function(ls) { assignment(ls, v, 1); } else { /* stat -> func */ - check_condition(ls, v.v.k === expkind.VCALL, "syntax error"); + check_condition(ls, v.v.k === expkind.VCALL, lua.to_luastring("syntax error")); lopcode.SETARG_C(lcode.getinstruction(fs, v.v), 1); /* call statement uses no results */ } }; @@ -1565,4 +1565,4 @@ module.exports.Dyndata = Dyndata; module.exports.expkind = expkind; module.exports.expdesc = expdesc; module.exports.luaY_parser = luaY_parser; -module.exports.vkisinreg = vkisinreg; \ No newline at end of file +module.exports.vkisinreg = vkisinreg; diff --git a/src/ltablib.js b/src/ltablib.js index 20fdf95..c45f7e5 100644 --- a/src/ltablib.js +++ b/src/ltablib.js @@ -9,6 +9,7 @@ const lstate = require('./lstate.js'); const ldo = require('./ldo.js'); const ldebug = require('./ldebug.js'); const llimit = require('./llimit.js'); +const lobject = require('./lobject.js'); const CT = lua.constant_types; const TS = lua.thread_status; @@ -35,9 +36,9 @@ const checktab = function(L, arg, what) { if (lapi.lua_type(L, arg) !== CT.LUA_TTABLE) { /* is it not a table? */ let n = 1; if (lapi.lua_getmetatable(L, arg) && /* must have metatable */ - (!(what & TAB_R) || checkfield(L, "__index", ++n)) && - (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && - (!(what & TAB_L) || checkfield(L, "__len", ++n))) { + (!(what & TAB_R) || checkfield(L, lua.to_luastring("__index"), ++n)) && + (!(what & TAB_W) || checkfield(L, lua.to_luastring("__newindex"), ++n)) && + (!(what & TAB_L) || checkfield(L, lua.to_luastring("__len"), ++n))) { lapi.lua_pop(L, n); /* pop metatable and tested metamethods */ } else @@ -53,7 +54,7 @@ const aux_getn = function(L, n, w) { const addfield = function(L, b, i) { lapi.lua_geti(L, 1, i); if (!lapi.lua_isstring(L, -1)) - lauxlib.luaL_error(L, `invalid value (${lauxlib.luaL_typename(L, -1)}) at index ${i} in table for 'concat'`); + 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_addvalue(b); }; @@ -67,7 +68,7 @@ const tinsert = function(L) { break; case 3: { pos = lauxlib.luaL_checkinteger(L, 2); /* 2nd argument is the position */ - lauxlib.luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); + lauxlib.luaL_argcheck(L, 1 <= pos && pos <= e, 2, lua.to_luastring("position out of bounds")); for (let i = e; i > pos; i--) { /* move up elements */ lapi.lua_geti(L, 1, i - 1); lapi.lua_seti(L, 1, i); /* t[i] = t[i - 1] */ @@ -75,7 +76,7 @@ const tinsert = function(L) { break; } default: { - return lauxlib.luaL_error(L, "wrong number of arguments to 'insert'"); + return lauxlib.luaL_error(L, lua.to_luastring("wrong number of arguments to 'insert'")); } } @@ -87,7 +88,7 @@ const tremove = function(L) { let size = aux_getn(L, 1, TAB_RW); let pos = lauxlib.luaL_optinteger(L, 2, size); if (pos !== size) /* validate 'pos' if given */ - lauxlib.luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); + lauxlib.luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, lua.to_luastring("position out of bounds")); lapi.lua_geti(L, 1, pos); /* result = t[pos] */ for (; pos < size; pos++) { lapi.lua_geti(L, 1, pos + 1); @@ -112,9 +113,9 @@ const tmove = function(L) { checktab(L, 1, TAB_R); checktab(L, tt, TAB_W); if (e >= f) { /* otherwise, nothing to move */ - lauxlib.luaL_argcheck(L, f > 0 || e < llimit.LUA_MAXINTEGER + f, 3, "too many elements to move"); + lauxlib.luaL_argcheck(L, f > 0 || e < llimit.LUA_MAXINTEGER + f, 3, lua.to_luastring("too many elements to move")); let n = e - f + 1; /* number of elements to move */ - lauxlib.luaL_argcheck(L, t <= llimit.LUA_MAXINTEGER - n + 1, 4, "destination wrap around"); + lauxlib.luaL_argcheck(L, t <= llimit.LUA_MAXINTEGER - n + 1, 4, lua.to_luastring("destination wrap around")); if (t > e || t <= f || (tt !== 1 && lapi.lua_compare(L, 1, tt, lua.LUA_OPEQ) !== 1)) { for (let i = 0; i < n; i++) { @@ -172,7 +173,7 @@ const unpack = function(L) { if (i > e) return 0; /* empty range */ let n = e - i; /* number of elements minus 1 (avoid overflows) */ if (n >= Number.MAX_SAFE_INTEGER || !lapi.lua_checkstack(L, ++n)) - return lauxlib.luaL_error(L, "too many results to unpack"); + return lauxlib.luaL_error(L, lua.to_luastring("too many results to unpack")); for (; i < e; i++) /* push arg[i..e - 1] (to avoid overflows) */ lapi.lua_geti(L, 1, i); lapi.lua_geti(L, 1, e); /* push last element */ @@ -213,7 +214,7 @@ const auxsort = function(L) { const sort = function(L) { let n = aux_getn(L, 1, TAB_RW); if (n > 1) { /* non-trivial interval? */ - lauxlib.luaL_argcheck(L, n < Number.MAX_SAFE_INTEGER, 1, "array too big"); + lauxlib.luaL_argcheck(L, n < Number.MAX_SAFE_INTEGER, 1, lua.to_luastring("array too big")); if (!lapi.lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ lauxlib.luaL_checktype(L, 2, CT.LUA_TFUNCTION); /* must be a function */ lapi.lua_settop(L, 2); /* make sure there are two arguments */ @@ -237,4 +238,4 @@ const luaopen_table = function(L) { return 1; }; -module.exports.luaopen_table = luaopen_table; \ No newline at end of file +module.exports.luaopen_table = luaopen_table; diff --git a/src/ltm.js b/src/ltm.js index 7ef772f..d2df961 100644 --- a/src/ltm.js +++ b/src/ltm.js @@ -15,57 +15,30 @@ const CT = lua.constant_types; const TMS = { - TM_INDEX: "__index", - TM_NEWINDEX: "__newindex", - TM_GC: "__gc", - TM_MODE: "__mode", - TM_LEN: "__len", - TM_EQ: "__eq", /* last tag method with fast access */ - TM_ADD: "__add", - TM_SUB: "__sub", - TM_MUL: "__mul", - TM_MOD: "__mod", - TM_POW: "__pow", - TM_DIV: "__div", - TM_IDIV: "__idiv", - TM_BAND: "__band", - TM_BOR: "__bor", - TM_BXOR: "__bxor", - TM_SHL: "__shl", - TM_SHR: "__shr", - TM_UNM: "__unm", - TM_BNOT: "__bnot", - TM_LT: "__lt", - TM_LE: "__le", - TM_CONCAT: "__concat", - TM_CALL: "__call" -}; - -const TMS8 = { - TM_INDEX: lua.to_luastring(TMS.TM_INDEX), - TM_NEWINDEX: lua.to_luastring(TMS.TM_NEWINDEX), - TM_GC: lua.to_luastring(TMS.TM_GC), - TM_MODE: lua.to_luastring(TMS.TM_MODE), - TM_LEN: lua.to_luastring(TMS.TM_LEN), - TM_EQ: lua.to_luastring(TMS.TM_EQ), /* last tag method with fast access */ - TM_ADD: lua.to_luastring(TMS.TM_ADD), - TM_SUB: lua.to_luastring(TMS.TM_SUB), - TM_MUL: lua.to_luastring(TMS.TM_MUL), - TM_MOD: lua.to_luastring(TMS.TM_MOD), - TM_POW: lua.to_luastring(TMS.TM_POW), - TM_DIV: lua.to_luastring(TMS.TM_DIV), - TM_IDIV: lua.to_luastring(TMS.TM_IDIV), - TM_BAND: lua.to_luastring(TMS.TM_BAND), - TM_BOR: lua.to_luastring(TMS.TM_BOR), - TM_BXOR: lua.to_luastring(TMS.TM_BXOR), - TM_SHL: lua.to_luastring(TMS.TM_SHL), - TM_SHR: lua.to_luastring(TMS.TM_SHR), - TM_UNM: lua.to_luastring(TMS.TM_UNM), - TM_BNOT: lua.to_luastring(TMS.TM_BNOT), - TM_LT: lua.to_luastring(TMS.TM_LT), - TM_LE: lua.to_luastring(TMS.TM_LE), - TM_CONCAT: lua.to_luastring(TMS.TM_CONCAT), - TM_CALL: lua.to_luastring(TMS.TM_CALL) + TM_INDEX: lua.to_luastring("__index"), + TM_NEWINDEX: lua.to_luastring("__newindex"), + TM_GC: lua.to_luastring("__gc"), + TM_MODE: lua.to_luastring("__mode"), + TM_LEN: lua.to_luastring("__len"), + TM_EQ: lua.to_luastring("__eq"), /* last tag method with fast access */ + TM_ADD: lua.to_luastring("__add"), + TM_SUB: lua.to_luastring("__sub"), + TM_MUL: lua.to_luastring("__mul"), + TM_MOD: lua.to_luastring("__mod"), + TM_POW: lua.to_luastring("__pow"), + TM_DIV: lua.to_luastring("__div"), + TM_IDIV: lua.to_luastring("__idiv"), + TM_BAND: lua.to_luastring("__band"), + TM_BOR: lua.to_luastring("__bor"), + TM_BXOR: lua.to_luastring("__bxor"), + TM_SHL: lua.to_luastring("__shl"), + TM_SHR: lua.to_luastring("__shr"), + TM_UNM: lua.to_luastring("__unm"), + TM_BNOT: lua.to_luastring("__bnot"), + TM_LT: lua.to_luastring("__lt"), + TM_LE: lua.to_luastring("__le"), + TM_CONCAT: lua.to_luastring("__concat"), + TM_CALL: lua.to_luastring("__call") }; const luaT_typenames_ = [ @@ -88,10 +61,8 @@ const ttypename = function(t) { const luaT_init = function(L) { L.l_G.tmname = []; - for (let event in TMS) { - let name = lua.to_luastring(TMS[event]); - L.l_G.tmname.push(L.l_G.intern(name)); // Strings are already interned by JS - } + for (let event in TMS) + L.l_G.tmname.push(L.l_G.intern(TMS[event])); }; /* @@ -99,9 +70,8 @@ const luaT_init = function(L) { ** with metatable, use their '__name' metafield, if present. */ const luaT_objtypename = function(L, o) { - if ((o.ttistable() && o.metatable !== null) - || (o.ttisfulluserdata() && o.metatable !== null)) { - let name = o.__index(o, '__name'); + if ((o.ttistable() && o.metatable !== null) || (o.ttisfulluserdata() && o.metatable !== null)) { + let name = o.__index(o, lua.to_luastring('__name')); if (name.ttisstring()) return name.jsstring(); } @@ -153,10 +123,10 @@ const luaT_trybinTM = function(L, p1, p2, res, event) { if (n1 !== false && n2 !== false) ldebug.luaG_tointerror(L, p1, p2); else - ldebug.luaG_opinterror(L, p1, p2, "perform bitwise operation on"); + ldebug.luaG_opinterror(L, p1, p2, lua.to_luastring("perform bitwise operation on")); } default: - ldebug.luaG_opinterror(L, p1, p2, "perform arithmetic on"); + ldebug.luaG_opinterror(L, p1, p2, lua.to_luastring("perform arithmetic on")); } } }; diff --git a/src/lua.js b/src/lua.js index b1faccd..4710ded 100644 --- a/src/lua.js +++ b/src/lua.js @@ -240,4 +240,4 @@ module.exports.lua_Debug = lua_Debug; module.exports.lua_upvalueindex = lua_upvalueindex; module.exports.print_version = print_version; module.exports.thread_status = thread_status; -module.exports.to_luastring = to_luastring; \ No newline at end of file +module.exports.to_luastring = to_luastring; diff --git a/src/lutf8lib.js b/src/lutf8lib.js index 053fb56..1df6096 100644 --- a/src/lutf8lib.js +++ b/src/lutf8lib.js @@ -91,8 +91,8 @@ const utflen = function(L) { let posi = u_posrelat(lauxlib.luaL_optinteger(L, 2, 1), s.length); let posj = u_posrelat(lauxlib.luaL_optinteger(L, 3, -1), s.length); - lauxlib.luaL_argcheck(L, 1 <= posi && --posi <= s.length, 2, "initial position out of string"); - lauxlib.luaL_argcheck(L, --posj < s.length, 3, "final position out of string"); + lauxlib.luaL_argcheck(L, 1 <= posi && --posi <= s.length, 2, lua.to_luastring("initial position out of string")); + lauxlib.luaL_argcheck(L, --posj < s.length, 3, lua.to_luastring("final position out of string")); lapi.lua_pushinteger(L, s.slice(posi, posj + 1).length); return 1; @@ -100,7 +100,7 @@ const utflen = function(L) { const pushutfchar = function(L, arg) { let code = lauxlib.luaL_checkinteger(L, arg); - lauxlib.luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); + lauxlib.luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, lua.to_luastring("value out of range")); lapi.lua_pushstring(L, `${String.fromCharCode(code)}`); }; @@ -134,14 +134,14 @@ const byteoffset = function(L) { let posi = n >= 0 ? 1 : s.length + 1; posi = u_posrelat(lauxlib.luaL_optinteger(L, 3, posi), s.length); - lauxlib.luaL_argcheck(L, 1 <= posi && --posi <= s.length, 3, "position ot ouf range"); + lauxlib.luaL_argcheck(L, 1 <= posi && --posi <= s.length, 3, lua.to_luastring("position ot ouf range")); if (n === 0) { /* find beginning of current byte sequence */ while (posi > 0 && iscont(s[posi])) posi--; } else { if (iscont(s[posi])) - lauxlib.luaL_error(L, "initial position is a continuation byte"); + lauxlib.luaL_error(L, lua.to_luastring("initial position is a continuation byte")); if (n < 0) { while (n < 0 && posi > 0) { /* move back */ @@ -179,19 +179,19 @@ const codepoint = function(L) { let posi = u_posrelat(lauxlib.luaL_optinteger(L, 2, 1), s.length); let pose = u_posrelat(lauxlib.luaL_optinteger(L, 3, posi), s.length); - lauxlib.luaL_argcheck(L, posi >= 1, 2, "out of range"); - lauxlib.luaL_argcheck(L, pose <= s.length, 3, "out of range"); + lauxlib.luaL_argcheck(L, posi >= 1, 2, lua.to_luastring("out of range")); + lauxlib.luaL_argcheck(L, pose <= s.length, 3, lua.to_luastring("out of range")); if (posi > pose) return 0; /* empty interval; return no values */ if (pose - posi >= Number.MAX_SAFE_INTEGER) - return lauxlib.luaL_error(L, "string slice too long"); + return lauxlib.luaL_error(L, lua.to_luastring("string slice too long")); let n = (pose - posi) + 1; - lauxlib.luaL_checkstack(L, n, "string slice too long"); + lauxlib.luaL_checkstack(L, n, lua.to_luastring("string slice too long")); n = 0; for (s = s.slice(posi - 1); n < pose - posi;) { let dec = utf8_decode(s); if (dec === null) - return lauxlib.luaL_error(L, "invalid UTF-8 code"); + return lauxlib.luaL_error(L, lua.to_luastring("invalid UTF-8 code")); s = dec.string; let code = dec.code; lapi.lua_pushinteger(L, code); @@ -220,7 +220,7 @@ const iter_aux = function(L) { let code = dec ? dec.code : null; let next = dec ? dec.string : null; if (next === null || iscont(next[0])) - return lauxlib.luaL_error(L, "invalid UTF-8 code"); + return lauxlib.luaL_error(L, lua.to_luastring("invalid UTF-8 code")); lapi.lua_pushinteger(L, n + 1); lapi.lua_pushinteger(L, code); return 2; @@ -253,4 +253,4 @@ const luaopen_utf8 = function(L) { return 1; }; -module.exports.luaopen_utf8 = luaopen_utf8; \ No newline at end of file +module.exports.luaopen_utf8 = luaopen_utf8; -- cgit v1.2.3-54-g00ecf