From 7e886ba08a443d9653c3033901ae8c83108d3701 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 21:17:26 +1000 Subject: src/lapi.js: Simplify+optimise lua_rotate --- src/lapi.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index ca5a8a0..f06fc65 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -181,14 +181,14 @@ const reverse = function(L, from, to) { ** rotate x n === BA. But BA === (A^r . B^r)^r. */ const lua_rotate = function(L, idx, n) { - let t = L.stack[L.top - 1]; - let p = index2addr(L, idx); + let t = L.top - 1; let pIdx = index2addr_(L, idx); + let p = L.stack[pIdx]; - assert(p !== lobject.luaO_nilobject && idx > defs.LUA_REGISTRYINDEX, "index not in the stack"); - assert((n >= 0 ? n : -n) <= (L.top - idx), "invalid 'n'"); + assert(isvalid(p) && idx > defs.LUA_REGISTRYINDEX, "index not in the stack"); + assert((n >= 0 ? n : -n) <= (t - pIdx + 1), "invalid 'n'"); - let m = n >= 0 ? L.top - 1 - n : pIdx - n - 1; /* end of prefix */ + let m = n >= 0 ? t - n : pIdx - n - 1; /* end of prefix */ reverse(L, pIdx, m); reverse(L, m + 1, L.top - 1); -- cgit v1.2.3-70-g09d2 From e4c9580d20924a0db1ff7ed0d30da9b71dbb5066 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 21:21:50 +1000 Subject: Introduce lvm.cvt2str In future this could be configurable --- src/lapi.js | 16 +++++++++++----- src/ldebug.js | 2 +- src/lvm.js | 9 +++++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index f06fc65..f7ef82e 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -667,8 +667,11 @@ const lua_toboolean = function(L, idx) { const lua_tolstring = function(L, idx) { let o = index2addr(L, idx); - if ((!o.ttisstring() && !o.ttisnumber())) - return null; + if (!o.ttisstring()) { + if (!lvm.cvt2str(o)) { /* not convertible? */ + return null; + } + } return o.ttisstring() ? o.svalue() : defs.to_luastring(`${o.value}`); }; @@ -678,8 +681,11 @@ const lua_tostring = lua_tolstring; const lua_toljsstring = function(L, idx) { let o = index2addr(L, idx); - if ((!o.ttisstring() && !o.ttisnumber())) - return null; + if (!o.ttisstring()) { + if (!lvm.cvt2str(o)) { /* not convertible? */ + return null; + } + } return o.ttisstring() ? o.jsstring() : `${o.value}`; }; @@ -872,7 +878,7 @@ const lua_isnumber = function(L, idx) { const lua_isstring = function(L, idx) { let o = index2addr(L, idx); - return o.ttisstring() || o.ttisnumber(); + return o.ttisstring() || lvm.cvt2str(o); }; const lua_isuserdata = function(L, idx) { diff --git a/src/ldebug.js b/src/ldebug.js index 1862e55..74a04db 100644 --- a/src/ldebug.js +++ b/src/ldebug.js @@ -546,7 +546,7 @@ const luaG_typeerror = function(L, o, op) { }; const luaG_concaterror = function(L, p1, p2) { - if (p1.ttisstring() || p1.ttisnumber()) p1 = p2; + if (p1.ttisstring() || lvm.cvt2str(p1)) p1 = p2; luaG_typeerror(L, p1, defs.to_luastring('concatenate', true)); }; diff --git a/src/lvm.js b/src/lvm.js index 4804cde..bd370a6 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -958,12 +958,16 @@ const luaV_shiftl = function(x, y) { } }; +const cvt2str = function(o) { + return o.ttisnumber(); +}; + const tostring = function(L, i) { let o = L.stack[i]; if (o.ttisstring()) return true; - if (o.ttisnumber() && !isNaN(o.value)) { + if (cvt2str(o) && !isNaN(o.value)) { L.stack[i] = new lobject.TValue(CT.LUA_TLNGSTR, lstring.luaS_bless(L, defs.to_luastring(`${o.value}`))); return true; } @@ -985,7 +989,7 @@ const luaV_concat = function(L, total) { let top = L.top; let n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(L.stack[top-2].ttisstring() || L.stack[top-2].ttisnumber()) || !tostring(L, top - 1)) { + if (!(L.stack[top-2].ttisstring() || cvt2str(L.stack[top-2])) || !tostring(L, top - 1)) { ltm.luaT_trybinTM(L, L.stack[top-2], L.stack[top-1], top-2, ltm.TMS.TM_CONCAT); delete L.stack[top - 1]; } else if (isemptystr(L.stack[top-1])) { @@ -1090,6 +1094,7 @@ module.exports.RB = RB; module.exports.RC = RC; module.exports.RKB = RKB; module.exports.RKC = RKC; +module.exports.cvt2str = cvt2str; module.exports.dojump = dojump; module.exports.donextjump = donextjump; module.exports.forlimit = forlimit; -- cgit v1.2.3-70-g09d2 From 4f4e76d8de5fea7e636bdf5b5e271a2216531345 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 21:32:41 +1000 Subject: src/lvm.js: Introduce cvt2num at mirror cvt2str --- src/lvm.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/lvm.js b/src/lvm.js index bd370a6..83feb9b 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -804,9 +804,10 @@ const luaV_tointeger = function(obj, mode) { return luaconf.lua_numbertointeger(f); } else if (obj.ttisinteger()) { return obj.value; - } else if (obj.ttisstring()) { - let n = lobject.luaO_str2num(obj.svalue()); - return n !== false ? luaV_tointeger(n, mode) : false; + } else if (cvt2num(obj)) { + let v = lobject.luaO_str2num(obj.svalue()); + if (v !== false) + return luaV_tointeger(v, mode); } return false; @@ -816,13 +817,14 @@ const tointeger = function(o) { return o.ttisinteger() ? o.value : luaV_tointeger(o, 0); }; -const tonumber = function(v) { - if (v.ttnov() === CT.LUA_TNUMBER) - return v.value; +const tonumber = function(o) { + if (o.ttnov() === CT.LUA_TNUMBER) + return o.value; - if (v.ttnov() === CT.LUA_TSTRING) { - let number = lobject.luaO_str2num(v.svalue()); - return number ? number.value : false; + if (cvt2num(o)) { /* string convertible to number? */ + let v = lobject.luaO_str2num(o.svalue()); + if (v !== false) + return v.value; } return false; @@ -962,6 +964,10 @@ const cvt2str = function(o) { return o.ttisnumber(); }; +const cvt2num = function(o) { + return o.ttisstring(); +}; + const tostring = function(L, i) { let o = L.stack[i]; @@ -1095,6 +1101,7 @@ module.exports.RC = RC; module.exports.RKB = RKB; module.exports.RKC = RKC; module.exports.cvt2str = cvt2str; +module.exports.cvt2num = cvt2num; module.exports.dojump = dojump; module.exports.donextjump = donextjump; module.exports.forlimit = forlimit; -- cgit v1.2.3-70-g09d2 From ac706a718bb39aefdac1a9fa2bb37f94ecc4245c Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:50:15 +1000 Subject: yarn.lock: Update sprintf-js version required --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 7a5150e..ddd4564 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1899,7 +1899,7 @@ spdx-license-ids@^1.0.2: sprintf-js@giann/sprintf.js: version "1.0.3" - resolved "https://codeload.github.com/giann/sprintf.js/tar.gz/78f98d4f39ba27579992ea66cbf2b23265c796ba" + resolved "https://codeload.github.com/giann/sprintf.js/tar.gz/432783731ee125b6746495beba5b408b14750840" sprintf@~0.1.3: version "0.1.5" -- cgit v1.2.3-70-g09d2 From 7d849c2df476c92a09ed4067117b5d5e3d5d988e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 23:08:21 +1000 Subject: src/lstrlib: math.mininteger has to print specially --- src/lstrlib.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lstrlib.js b/src/lstrlib.js index 8bc2b0e..8e8b58e 100644 --- a/src/lstrlib.js +++ b/src/lstrlib.js @@ -225,7 +225,10 @@ const addliteral = function(L, b, arg) { checkdp(b); /* ensure it uses a dot */ } else { /* integers */ let n = lua.lua_tointeger(L, arg); - concat(b, lua.to_luastring(sprintf("%d", n))); + let format = (n === llimit.LUA_MININTEGER) /* corner case? */ + ? "0x%" + luaconf.LUA_INTEGER_FRMLEN + "x" /* use hexa */ + : luaconf.LUA_INTEGER_FMT; /* else use default format */ + concat(b, lua.to_luastring(sprintf(format, n))); } break; } -- cgit v1.2.3-70-g09d2 From b525c305b524f5b3ffaba3187ccc828d332aa835 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 23:11:34 +1000 Subject: src/luaconf.js: Implement lua_integer2str and lua_number2str --- src/luaconf.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/luaconf.js b/src/luaconf.js index 3d0d18f..c272178 100644 --- a/src/luaconf.js +++ b/src/luaconf.js @@ -2,6 +2,7 @@ "use strict"; const llimit = require('./llimit.js'); +const sprintf = require('sprintf-js').sprintf; /* @@ LUAI_MAXSTACK limits the size of the Lua stack. @@ -18,6 +19,14 @@ const LUAI_MAXSTACK = 1000000; */ const LUA_IDSIZE = 60; +const lua_integer2str = function(n) { + return sprintf(LUA_INTEGER_FMT, n); +}; + +const lua_number2str = function(n) { + return sprintf(LUA_NUMBER_FMT, n); +}; + const lua_numbertointeger = function(n) { return n >= llimit.MIN_INT && n < -llimit.MIN_INT ? n : false; }; @@ -64,4 +73,6 @@ module.exports.LUA_INTEGER_FRMLEN = LUA_INTEGER_FRMLEN; module.exports.LUA_NUMBER_FMT = LUA_NUMBER_FMT; module.exports.LUA_NUMBER_FRMLEN = LUA_NUMBER_FRMLEN; module.exports.lua_getlocaledecpoint = lua_getlocaledecpoint; +module.exports.lua_integer2str = lua_integer2str; +module.exports.lua_number2str = lua_number2str; module.exports.lua_numbertointeger = lua_numbertointeger; -- cgit v1.2.3-70-g09d2 From 128ae8cc451126ee7201de7efb6cc0c39fb1a2b4 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 23:19:22 +1000 Subject: Introduce luaO_tostring --- src/lapi.js | 8 ++++---- src/lobject.js | 17 ++++++++++++++++- src/lvm.js | 4 ++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index f7ef82e..efc59aa 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -671,9 +671,9 @@ const lua_tolstring = function(L, idx) { if (!lvm.cvt2str(o)) { /* not convertible? */ return null; } + o = lobject.luaO_tostring(L, o); } - - return o.ttisstring() ? o.svalue() : defs.to_luastring(`${o.value}`); + return o.svalue(); }; const lua_tostring = lua_tolstring; @@ -685,9 +685,9 @@ const lua_toljsstring = function(L, idx) { if (!lvm.cvt2str(o)) { /* not convertible? */ return null; } + o = lobject.luaO_tostring(L, o); } - - return o.ttisstring() ? o.jsstring() : `${o.value}`; + return o.jsstring(); }; const lua_tojsstring = lua_toljsstring; diff --git a/src/lobject.js b/src/lobject.js index 41c3a84..e7b716e 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -448,6 +448,18 @@ const luaO_utf8esc = function(x) { }; }; +/* this currently returns new TValue instead of modifying */ +const luaO_tostring = function(L, obj) { + let buff; + if (obj.ttisinteger()) + buff = defs.to_luastring(luaconf.lua_integer2str(obj.value)); + else { + let str = luaconf.lua_number2str(obj.value); + buff = defs.to_luastring(str); + } + return new TValue(CT.LUA_TLNGSTR, lstring.luaS_bless(L, buff)); +}; + const pushstr = function(L, str) { L.stack[L.top++] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, str)); }; @@ -476,8 +488,10 @@ const luaO_pushvfstring = function(L, fmt, argp) { break; case char['d']: case char['I']: + L.stack[L.top++] = luaO_tostring(L, new TValue(CT.LUA_TNUMINT, argp[a++])); + break; case char['f']: - pushstr(L, defs.to_luastring(''+argp[a++])); + L.stack[L.top++] = luaO_tostring(L, new TValue(CT.LUA_TNUMFLT, argp[a++])); break; // case char['p']: case char['U']: @@ -616,6 +630,7 @@ module.exports.luaO_int2fb = luaO_int2fb; module.exports.luaO_pushfstring = luaO_pushfstring; module.exports.luaO_pushvfstring = luaO_pushvfstring; module.exports.luaO_str2num = luaO_str2num; +module.exports.luaO_tostring = luaO_tostring; module.exports.luaO_utf8desc = luaO_utf8desc; module.exports.luaO_utf8esc = luaO_utf8esc; module.exports.numarith = numarith; diff --git a/src/lvm.js b/src/lvm.js index 83feb9b..0081376 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -973,8 +973,8 @@ const tostring = function(L, i) { if (o.ttisstring()) return true; - if (cvt2str(o) && !isNaN(o.value)) { - L.stack[i] = new lobject.TValue(CT.LUA_TLNGSTR, lstring.luaS_bless(L, defs.to_luastring(`${o.value}`))); + if (cvt2str(o)) { + L.stack[i] = lobject.luaO_tostring(L, o); return true; } -- cgit v1.2.3-70-g09d2 From e6639768e4a059aeaf80e232c729dffa3b5e93ba Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 23:20:02 +1000 Subject: src/lauxlib.js: Use lua_pushfstring for formatting numbers --- src/lauxlib.js | 21 +++------------------ tests/test-suite/strings.js | 2 +- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/lauxlib.js b/src/lauxlib.js index 559e1bc..3959817 100644 --- a/src/lauxlib.js +++ b/src/lauxlib.js @@ -473,24 +473,9 @@ const luaL_tolstring = function(L, idx) { switch(t) { case lua.LUA_TNUMBER: { if (lua.lua_isinteger(L, idx)) - lua.lua_pushstring(L, lua.to_luastring(lua.lua_tointeger(L, idx).toString())); - else { - let n = lua.lua_tonumber(L, idx); - let a = Math.abs(n); - let s; - if (Object.is(n, Infinity)) - s = 'inf'; - else if (Object.is(n, -Infinity)) - s = '-inf'; - else if (Number.isNaN(n)) - s = 'nan'; - else if (a >= 100000000000000 || (a > 0 && a < 0.0001)) - s = n.toExponential(); - else - s = n.toPrecision(16).replace(/(\.[0-9][1-9]*)0+$/, "$1"); - - lua.lua_pushstring(L, lua.to_luastring(s)); - } + lua.lua_pushfstring(L, lua.to_luastring("%I"), lua.lua_tointeger(L, idx)); + else + lua.lua_pushfstring(L, lua.to_luastring("%f"), lua.lua_tonumber(L, idx)); break; } case lua.LUA_TSTRING: diff --git a/tests/test-suite/strings.js b/tests/test-suite/strings.js index 3584a80..d7b30a8 100644 --- a/tests/test-suite/strings.js +++ b/tests/test-suite/strings.js @@ -288,7 +288,7 @@ test('[test-suite] strings: tostring', function (t) { end if tostring(0.0) == "0.0" then -- "standard" coercion float->string - -- assert('' .. 12 == '12' and 12.0 .. '' == '12.0') -- TODO: How to do this in JS ? + assert('' .. 12 == '12' and 12.0 .. '' == '12.0') assert(tostring(-1203 + 0.0) == "-1203.0") else -- compatible coercion assert(tostring(0.0) == "0") -- cgit v1.2.3-70-g09d2 From 13328c5bee9b847317313491c3eb9f6f66766de7 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 23:26:44 +1000 Subject: Add luaD_inctop calls where appropriate --- src/ldo.js | 6 ++++++ src/lobject.js | 9 ++++++--- src/lparser.js | 7 +++++-- src/lundump.js | 3 ++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/ldo.js b/src/ldo.js index 83f26cf..fbef68f 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -89,6 +89,11 @@ const luaD_shrinkstack = function(L) { luaD_reallocstack(L, goodsize); }; +const luaD_inctop = function(L) { + luaD_checkstack(L, 1); + L.top++; +}; + /* ** Prepares a function call: checks the stack, creates a new CallInfo ** entry, fills in the relevant information, calls hook if needed. @@ -653,6 +658,7 @@ module.exports.luaD_callnoyield = luaD_callnoyield; module.exports.luaD_checkstack = luaD_checkstack; module.exports.luaD_growstack = luaD_growstack; module.exports.luaD_hook = luaD_hook; +module.exports.luaD_inctop = luaD_inctop; module.exports.luaD_pcall = luaD_pcall; module.exports.luaD_poscall = luaD_poscall; module.exports.luaD_precall = luaD_precall; diff --git a/src/lobject.js b/src/lobject.js index e7b716e..fad3b73 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -461,7 +461,8 @@ const luaO_tostring = function(L, obj) { }; const pushstr = function(L, str) { - L.stack[L.top++] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, str)); + ldo.luaD_inctop(L); + L.stack[L.top-1] = new TValue(CT.LUA_TLNGSTR, lstring.luaS_new(L, str)); }; const luaO_pushvfstring = function(L, fmt, argp) { @@ -488,10 +489,12 @@ const luaO_pushvfstring = function(L, fmt, argp) { break; case char['d']: case char['I']: - L.stack[L.top++] = luaO_tostring(L, new TValue(CT.LUA_TNUMINT, argp[a++])); + ldo.luaD_inctop(L); + L.stack[L.top-1] = luaO_tostring(L, new TValue(CT.LUA_TNUMINT, argp[a++])); break; case char['f']: - L.stack[L.top++] = luaO_tostring(L, new TValue(CT.LUA_TNUMFLT, argp[a++])); + ldo.luaD_inctop(L); + L.stack[L.top-1] = luaO_tostring(L, new TValue(CT.LUA_TNUMFLT, argp[a++])); break; // case char['p']: case char['U']: diff --git a/src/lparser.js b/src/lparser.js index 100342a..13f75c9 100644 --- a/src/lparser.js +++ b/src/lparser.js @@ -4,6 +4,7 @@ const assert = require('assert'); const defs = require('./defs.js'); const lcode = require('./lcode.js'); +const ldo = require('./ldo.js'); const lfunc = require('./lfunc.js'); const llex = require('./llex.js'); const llimit = require('./llimit.js'); @@ -1563,9 +1564,11 @@ const luaY_parser = function(L, z, buff, dyd, name, firstchar) { let lexstate = new llex.LexState(); let funcstate = new FuncState(); let cl = lfunc.luaF_newLclosure(L, 1); /* create main closure */ - L.stack[L.top++] = new TValue(defs.CT.LUA_TLCL, cl); + ldo.luaD_inctop(L); + L.stack[L.top-1] = new TValue(defs.CT.LUA_TLCL, cl); lexstate.h = ltable.luaH_new(L); /* create table for scanner */ - L.stack[L.top++] = new TValue(defs.CT.LUA_TTABLE, lexstate.h); + ldo.luaD_inctop(L); + L.stack[L.top-1] = new TValue(defs.CT.LUA_TTABLE, lexstate.h); funcstate.f = cl.p = new Proto(L); funcstate.f.source = lstring.luaS_new(L, name); lexstate.buff = buff; diff --git a/src/lundump.js b/src/lundump.js index 1891451..4931fe8 100644 --- a/src/lundump.js +++ b/src/lundump.js @@ -265,7 +265,8 @@ const luaU_undump = function(L, Z, name) { let S = new BytecodeParser(L, Z, name); S.checkHeader(); let cl = lfunc.luaF_newLclosure(L, S.readByte()); - L.stack[L.top++] = new lobject.TValue(defs.CT.LUA_TLCL, cl); + ldo.luaD_inctop(L); + L.stack[L.top-1] = new lobject.TValue(defs.CT.LUA_TLCL, cl); cl.p = new lfunc.Proto(L); S.readFunction(cl.p, null); assert(cl.nupvalues === cl.p.upvalues.length); -- cgit v1.2.3-70-g09d2 From 252284298bce111a7b2e1bea07eef54a7835c422 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 23:28:59 +1000 Subject: src/lobject.js: Don't assume LUA_COMPAT_FLOATSTRING --- src/lobject.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lobject.js b/src/lobject.js index fad3b73..8c70985 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -456,6 +456,11 @@ const luaO_tostring = function(L, obj) { else { let str = luaconf.lua_number2str(obj.value); buff = defs.to_luastring(str); + // Assume no LUA_COMPAT_FLOATSTRING + if (/^[-0123456789]+$/.test(str)) { /* looks like an int? */ + buff.push(char[luaconf.lua_getlocaledecpoint()]); + buff.push(char['0']); /* adds '.0' to result */ + } } return new TValue(CT.LUA_TLNGSTR, lstring.luaS_bless(L, buff)); }; -- cgit v1.2.3-70-g09d2 From f83115f90039666b9dc19c3ee9972a3aa98d28e7 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 23:34:25 +1000 Subject: src/lapi.js: Throw errors when attempting to use pseudo-index with index2addr_ --- src/lapi.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index efc59aa..8e0c491 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -66,7 +66,7 @@ const index2addr = function(L, idx) { } }; -// Like index2addr but returns the index on stack +// Like index2addr but returns the index on stack; doesn't allow pseudo indices const index2addr_ = function(L, idx) { let ci = L.ci; if (idx > 0) { @@ -77,16 +77,8 @@ const index2addr_ = function(L, idx) { } else if (idx > defs.LUA_REGISTRYINDEX) { assert(idx !== 0 && -idx <= L.top, "invalid index"); return L.top + idx; - } else if (idx === defs.LUA_REGISTRYINDEX) { - return null; - } else { /* upvalues */ - idx = defs.LUA_REGISTRYINDEX - idx; - assert(idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ci.func.ttislcf()) /* light C function? */ - return null; /* it has no upvalues */ - else { - return idx <= ci.func.nupvalues ? idx - 1 : null; - } + } else { /* registry or upvalue */ + throw Error("attempt to use pseudo-index"); } }; -- cgit v1.2.3-70-g09d2 From 69fdbe3590eb2ddfa970888b7b59e8a84fbda101 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:09:21 +1000 Subject: tests/test-suite/strings.js: un-skip fixed test --- tests/test-suite/strings.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test-suite/strings.js b/tests/test-suite/strings.js index d7b30a8..c501ddd 100644 --- a/tests/test-suite/strings.js +++ b/tests/test-suite/strings.js @@ -365,8 +365,7 @@ test('[test-suite] strings: string.format', function (t) { }); -// TODO: http://lua-users.org/lists/lua-l/2016-05/msg00455.html -test('[test-suite] strings: %q', { skip: true }, function (t) { +test('[test-suite] strings: %q', function (t) { let luaCode = ` do local function checkQ (v) -- cgit v1.2.3-70-g09d2 From ee502076941676ff570866cba36a21bf06c29fc0 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 23:54:15 +1000 Subject: Revert "src/lstate.js: Remove useless luaE_freeCI" This reverts commit 6646bebd474b95a2d4cbb8558c0d1cb5b5353de0. --- src/lstate.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lstate.js b/src/lstate.js index b71e011..124322d 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -86,6 +86,11 @@ const luaE_extendCI = function(L) { return ci; }; +const luaE_freeCI = function(L) { + let ci = L.ci; + ci.next = null; +}; + const stack_init = function(L1, L) { L1.stack = new Array(BASIC_STACK_SIZE); L1.top = 0; @@ -103,6 +108,7 @@ const stack_init = function(L1, L) { const freestack = function(L) { L.ci = L.base_ci; + luaE_freeCI(L); L.stack = null; }; @@ -204,4 +210,5 @@ module.exports.lua_close = lua_close; module.exports.lua_newstate = lua_newstate; module.exports.lua_newthread = lua_newthread; module.exports.luaE_extendCI = luaE_extendCI; +module.exports.luaE_freeCI = luaE_freeCI; module.exports.luaE_freethread = luaE_freethread; -- cgit v1.2.3-70-g09d2 From f7bb8409d6c57b5e9319f4f48d7d02f216b4cc32 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:05:13 +1000 Subject: src/ldo.js: free CallInfo to recover from (lua) stack overflow --- src/ldo.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ldo.js b/src/ldo.js index fbef68f..cda1274 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -85,6 +85,10 @@ const luaD_shrinkstack = function(L) { let goodsize = inuse + Math.floor(inuse / 8) + 2*lstate.EXTRA_STACK; if (goodsize > luaconf.LUAI_MAXSTACK) goodsize = luaconf.LUAI_MAXSTACK; /* respect stack limit */ + if (L.stack.length > luaconf.LUAI_MAXSTACK) /* had been handling stack overflow? */ + lstate.luaE_freeCI(L); /* free all CIs (list grew because of an error) */ + /* if thread is currently not handling a stack overflow and its + good size is smaller than current size, shrink its stack */ if (inuse <= (luaconf.LUAI_MAXSTACK - lstate.EXTRA_STACK) && goodsize < L.stack.length) luaD_reallocstack(L, goodsize); }; -- cgit v1.2.3-70-g09d2 From f6b260d2b97c40f360136d0c1320d8f6468f7e87 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:05:31 +1000 Subject: src/ldo.js: luaG_runerror takes lua strings --- src/ldo.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ldo.js b/src/ldo.js index cda1274..701a211 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -59,7 +59,7 @@ const luaD_growstack = function(L, n) { if (newsize < needed) newsize = needed; if (newsize > luaconf.LUAI_MAXSTACK) { /* stack overflow? */ luaD_reallocstack(L, ERRORSTACKSIZE); - ldebug.luaG_runerror(L, "stack overflow"); + ldebug.luaG_runerror(L, defs.to_luastring("stack overflow", true)); } else luaD_reallocstack(L, newsize); @@ -281,7 +281,7 @@ const tryfuncTM = function(L, off, func) { */ const stackerror = function(L) { if (L.nCcalls === llimit.LUAI_MAXCCALLS) - ldebug.luaG_runerror(L, "JS stack overflow"); + ldebug.luaG_runerror(L, defs.to_luastring("JS stack overflow", true)); else if (L.nCcalls >= llimit.LUAI_MAXCCALLS + (llimit.LUAI_MAXCCALLS >> 3)) luaD_throw(L, TS.LUA_ERRERR); /* error while handing stack error */ }; -- cgit v1.2.3-70-g09d2 From 1188498c1f714c32c287dfb657894d51c77e2c1b Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:06:43 +1000 Subject: tests/test-suite/errors.js: un-skip test as we can now recover from a stack overflow --- tests/test-suite/errors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-suite/errors.js b/tests/test-suite/errors.js index c18adeb..47b4b2a 100644 --- a/tests/test-suite/errors.js +++ b/tests/test-suite/errors.js @@ -836,7 +836,7 @@ test("[test-suite] errors: testing line error", function (t) { }); -test("[test-suite] errors: several tests that exhaust the Lua stack", { skip: true }, function (t) { +test("[test-suite] errors: several tests that exhaust the Lua stack", function (t) { let luaCode = ` C = 0 local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end -- cgit v1.2.3-70-g09d2 From 2aaf4a458734a46cbd3a4bfd8890206ed3c12594 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:07:22 +1000 Subject: tests/test-suite/nextvar.js: un-skip passing test --- tests/test-suite/nextvar.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test-suite/nextvar.js b/tests/test-suite/nextvar.js index d119d97..28a54e7 100644 --- a/tests/test-suite/nextvar.js +++ b/tests/test-suite/nextvar.js @@ -907,8 +907,7 @@ test("[test-suite] nextvar: next", function (t) { }); -// TODO: infinite loop ? -test("[test-suite] nextvar: testing floats in numeric for", { skip: true }, function (t) { +test("[test-suite] nextvar: testing floats in numeric for", function (t) { let luaCode = ` do local a -- cgit v1.2.3-70-g09d2 From 56a72b0c1ce00b4de0b25318c3eabd6c48deab2e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:10:52 +1000 Subject: tests/test-suite/math.js: un-skip passing test --- tests/test-suite/math.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-suite/math.js b/tests/test-suite/math.js index e79281b..b92d304 100644 --- a/tests/test-suite/math.js +++ b/tests/test-suite/math.js @@ -746,7 +746,7 @@ test("[test-suite] math: 'tonumber' with strings", function (t) { }); -test("[test-suite] math: tests with very long numerals", { skip: true }, function (t) { +test("[test-suite] math: tests with very long numerals", function (t) { let luaCode = ` assert(tonumber("0x"..string.rep("f", 13)..".0") == 2.0^(4*13) - 1) assert(tonumber("0x"..string.rep("f", 150)..".0") == 2.0^(4*150) - 1) -- cgit v1.2.3-70-g09d2 From 0085399fa4b4a6e9450ab454a4ac33dd26db003e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:16:59 +1000 Subject: tests/test-suite/errors.js: un-skip passing test --- tests/test-suite/errors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-suite/errors.js b/tests/test-suite/errors.js index 47b4b2a..432ee35 100644 --- a/tests/test-suite/errors.js +++ b/tests/test-suite/errors.js @@ -950,7 +950,7 @@ test("[test-suite] errors: error in error handling", function (t) { }); -test("[test-suite] errors: too many results", { skip: true }, function (t) { +test("[test-suite] errors: too many results", function (t) { let luaCode = ` local function loop (x,y,z) return 1 + loop(x, y, z) end -- cgit v1.2.3-70-g09d2 From 275c497e20df141160b92db6503da0b98f611bc0 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:23:54 +1000 Subject: tests/test-suite/errors.js: copy setup from previous test to get a skipped test passing --- tests/test-suite/errors.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test-suite/errors.js b/tests/test-suite/errors.js index 432ee35..5980724 100644 --- a/tests/test-suite/errors.js +++ b/tests/test-suite/errors.js @@ -871,9 +871,10 @@ test("[test-suite] errors: several tests that exhaust the Lua stack", function ( }); -test("[test-suite] errors: error lines in stack overflow", { skip: true }, function (t) { +test("[test-suite] errors: error lines in stack overflow", function (t) { let luaCode = ` C = 0 + local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end local l1 local function g(x) l1 = debug.getinfo(x, "l").currentline; y() -- cgit v1.2.3-70-g09d2 From 8a439e5563f12335e3d35dd63b4f8cbcc25a9bd8 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 23 May 2017 00:27:09 +1000 Subject: tests/test-suite/events.js: un-skip fixed tests --- tests/test-suite/events.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/test-suite/events.js b/tests/test-suite/events.js index d5ed5ae..0f94f36 100644 --- a/tests/test-suite/events.js +++ b/tests/test-suite/events.js @@ -301,7 +301,6 @@ test("[test-suite] events: test comparison", function (t) { }); -// TODO: uncomment asserts when next is fixed for cleared table entries test("[test-suite] events: test 'partial order'", function (t) { let luaCode = ` t = {} @@ -327,9 +326,9 @@ test("[test-suite] events: test 'partial order'", function (t) { t.__le = nil assert(Set{1,2,3} < Set{1,2,3,4}) - -- assert(not(Set{1,2,3,4} < Set{1,2,3,4})) - -- assert((Set{1,2,3,4} <= Set{1,2,3,4})) - -- assert((Set{1,2,3,4} >= Set{1,2,3,4})) + assert(not(Set{1,2,3,4} < Set{1,2,3,4})) + assert((Set{1,2,3,4} <= Set{1,2,3,4})) + assert((Set{1,2,3,4} >= Set{1,2,3,4})) assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a 'le' method ;-) t.__le = function (a,b) @@ -352,11 +351,11 @@ test("[test-suite] events: test 'partial order'", function (t) { end local s = Set{1,3,5} - -- assert(s == Set{3,5,1}) + assert(s == Set{3,5,1}) assert(not rawequal(s, Set{3,5,1})) assert(rawequal(s, s)) - -- assert(Set{1,3,5,1} == rawSet{3,5,1}) - -- assert(rawSet{1,3,5,1} == Set{3,5,1}) + assert(Set{1,3,5,1} == rawSet{3,5,1}) + assert(rawSet{1,3,5,1} == Set{3,5,1}) assert(Set{1,3,5} ~= Set{3,5,1,6}) -- '__eq' is not used for table accesses -- cgit v1.2.3-70-g09d2