summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/defs.js45
-rw-r--r--src/lauxlib.js25
-rw-r--r--src/lbaselib.js7
-rw-r--r--src/ldebug.js12
-rw-r--r--src/ldo.js2
-rw-r--r--src/llex.js6
-rw-r--r--src/lobject.js51
-rw-r--r--src/lparser.js4
-rw-r--r--src/lstrlib.js8
-rw-r--r--src/ltablib.js3
-rw-r--r--src/lua.js1
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) {
diff --git a/src/ldo.js b/src/ldo.js
index dccee08..9b845e7 100644
--- a/src/ldo.js
+++ b/src/ldo.js
@@ -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);
};
diff --git a/src/lua.js b/src/lua.js
index ce0def4..e6e3f02 100644
--- a/src/lua.js
+++ b/src/lua.js
@@ -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;