From 2a6993bf0e23e2a3759abb9d7127525577dc346c Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Sun, 12 Mar 2017 16:48:53 +0100 Subject: Testing 8-bit strings --- src/lapi.js | 3 +- src/ldo.js | 2 +- src/llex.js | 2 +- src/lobject.js | 6 + src/lparser.js | 12 +- src/ltm.js | 32 +- src/lua.js | 6 +- src/lvm.js | 29 +- tests/lexparse.js | 10 +- tests/ltm.js | 867 ++++++++++++------------------------------------------ tests/lvm.js | 62 ++-- tests/tests.js | 1 - 12 files changed, 281 insertions(+), 751 deletions(-) diff --git a/src/lapi.js b/src/lapi.js index 79cd6fb..96fe207 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -231,7 +231,6 @@ const lua_pushstring = function (L, s) { else { let ts = L.l_G.intern(lua.to_luastring(s)); L.stack[L.top] = ts; - s = ts.value; } L.top++; @@ -537,7 +536,7 @@ const lua_tolstring = function(L, idx) { if (!o.ttisstring() && !o.ttisnumber()) return null; - return o.ttisstring() ? String.fromCharCode(...o.value) : `${o.value}`; + return o.ttisstring() ? o.jsstring() : `${o.value}`; }; const lua_tostring = lua_tolstring; diff --git a/src/ldo.js b/src/ldo.js index e088d8d..7df4c62 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -532,7 +532,7 @@ const f_parser = function(L, p) { let c = p.z.getc(); /* read first character */ if (String.fromCharCode(c) === lua.LUA_SIGNATURE.charAt(0)) { checkmode(L, p.mode, "binary"); - cl = new BytecodeParser(L, p.z.buffer); + cl = new BytecodeParser(L, p.z.buffer).luaU_undump(); } else { checkmode(L, p.mode, "text"); cl = lparser.luaY_parser(L, p.z, p.buff, p.dyd, p.name, c); diff --git a/src/llex.js b/src/llex.js index fc3603f..e747fdd 100644 --- a/src/llex.js +++ b/src/llex.js @@ -596,7 +596,7 @@ const llex = function(ls, seminfo) { let ts = new TValue(CT.LUA_TLNGSTR, lua.to_luastring(ls.buff.buffer.join(''))); seminfo.ts = ts; - let kidx = luaX_tokens.slice(0, 22).indexOf(ts.value); + let kidx = luaX_tokens.slice(0, 22).indexOf(ts.jsstring()); if (kidx >= 0) /* reserved word? */ return kidx + FIRST_RESERVED; else diff --git a/src/lobject.js b/src/lobject.js index 92dd560..739db50 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -110,6 +110,10 @@ class TValue { return this.ttisnil() || (this.ttisboolean() && this.value === false); } + jsstring() { + return this.ttisstring() ? String.fromCharCode(...this.value) : null; + } + } const nil = new TValue(CT.LUA_TNIL, null); @@ -133,6 +137,8 @@ class Table extends TValue { } else if ([CT.LUA_TSHRSTR, CT.LUA_TLNGSTR].indexOf(key.type) > -1) { key = key.value.map(e => `${e}|`).join(''); } + } else if (typeof key === "string") { // To avoid + key = lua.to_luastring(key).map(e => `${e}|`).join(''); } return key; diff --git a/src/lparser.js b/src/lparser.js index 42337cc..1806bbe 100644 --- a/src/lparser.js +++ b/src/lparser.js @@ -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.value === name.value) + if (up[i].name.jsstring() === name.jsstring()) return i; } return -1; /* not found */ @@ -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.value === getlocvar(fs, i).varname.value) + if (n.jsstring() === getlocvar(fs, i).varname.jsstring()) return i; } @@ -383,7 +383,7 @@ const closegoto = function(ls, g, label) { let fs = ls.fs; let gl = ls.dyd.gt; let gt = gl.arr[g]; - assert(gt.name.value === label.name.value); + assert(gt.name.jsstring() === label.name.jsstring()); 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}'`); @@ -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.value === gt.name.value) { /* correct label? */ + if (lb.name.jsstring() === gt.name.jsstring()) { /* 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.value === lb.name.value) + if (gl.arr[i].name.jsstring() === lb.name.jsstring()) closegoto(ls, i, lb); else i++; @@ -1150,7 +1150,7 @@ 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.value === ll.arr[i].name.value) { + if (label.jsstring() === ll.arr[i].name.jsstring()) { semerror(fs.ls, `label '${label}' already defined on line ${ll.arr[i].line}`); } } diff --git a/src/ltm.js b/src/ltm.js index 51ab8ec..6377c93 100644 --- a/src/ltm.js +++ b/src/ltm.js @@ -38,8 +38,34 @@ const TMS = { TM_LT: "__lt", TM_LE: "__le", TM_CONCAT: "__concat", - TM_CALL: "__call", - TM_N: 26 + 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) }; const luaT_typenames_ = [ @@ -77,7 +103,7 @@ const luaT_objtypename = function(L, o) { || (o.ttisfulluserdata() && o.metatable !== null)) { let name = o.__index(o, '__name'); if (name.ttisstring()) - return String.fromCharCode(...name.value); + return name.jsstring(); } return ttypename(o.ttnov()); diff --git a/src/lua.js b/src/lua.js index 12d4e65..08bad58 100644 --- a/src/lua.js +++ b/src/lua.js @@ -133,8 +133,8 @@ class lua_Debug { } const to_luastring = function(str, maxBytesToWrite) { - maxBytesToWrite = maxBytesToWrite !== undefined ? maxBytesToWrite : str.length; - let outU8Array = new Array(maxBytesToWrite); + maxBytesToWrite = maxBytesToWrite !== undefined ? maxBytesToWrite : str.length + 1; + let outU8Array = []; if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes. return 0; @@ -184,7 +184,7 @@ const to_luastring = function(str, maxBytesToWrite) { } } // Null-terminate the pointer to the buffer. - outU8Array[outIdx] = 0; + // outU8Array[outIdx] = 0; return outU8Array; }; diff --git a/src/lvm.js b/src/lvm.js index 3cf3fb6..873cd20 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -856,8 +856,7 @@ const luaV_tointeger = function(obj, mode) { } else if (obj.ttisinteger()) { return obj.value|0; } else if (obj.ttisstring()) { - let str = String.fromCharCode(...obj.value); - return luaV_tointeger(new TValue(CT.LUA_TNUMFLT, parseFloat(str)), mode); // TODO: luaO_str2num + return luaV_tointeger(new TValue(CT.LUA_TNUMFLT, parseFloat(obj.jsstring())), mode); // TODO: luaO_str2num } return false; @@ -921,8 +920,8 @@ const LTintfloat = function(l, r) { const l_strcmp = function(ls, rs) { // TODO: lvm.c:248 static int l_strcmp (const TString *ls, const TString *rs) - ls = String.fromCharCode(...ls.value); - rs = String.fromCharCode(...rs.value); + ls = ls.jsstring(); + rs = rs.jsstring(); return ls === rs ? 0 : (ls < rs ? -1 : 1); }; @@ -955,11 +954,11 @@ const luaV_objlen = function(L, ra, rb) { const tostring = function(L, i) { let o = L.stack[i]; - let str = `${o.value}`; - str = lua.to_luastring(str, str.length); - if (o.ttisstring() || (o.ttisnumber() && !isNaN(str))) { - L.stack[i] = L.l_G.intern(str); + if (o.ttisstring()) return true; + + if (o.ttisnumber() && !isNaN(o.value)) { + L.stack[i] = L.l_G.intern(lua.to_luastring(`${o.value}`)); return true; } @@ -975,18 +974,16 @@ const luaV_concat = function(L, total) { do { let top = L.top; let n = 2; /* number of elements handled in this pass (at least 2) */ - let v = L.stack[top-2]; - let v2 = L.stack[top-1]; - if (!(v.ttisstring() || v.ttisnumber()) || !tostring(L, top - 2)) // TODO: tostring - ltm.luaT_trybinTM(L, v, v2, top-2, ltm.TMS.TM_CONCAT); - else if (v2.ttisstring() && v2.value.length === 0) + if (!(L.stack[top-2].ttisstring() || L.stack[top-2].ttisnumber()) || !tostring(L, top - 1)) + ltm.luaT_trybinTM(L, L.stack[top-2], L.stack[top-1], top-2, ltm.TMS.TM_CONCAT); + else if (L.stack[top-1].ttisstring() && L.stack[top-1].value.length === 0) tostring(L, top - 2); - else if (v.ttisstring() && v.value.length === 0) + else if (L.stack[top-2].ttisstring() && L.stack[top-2].value.length === 0) L.stack[top - 2] = L.stack[top - 1]; else { /* at least two non-empty string values; get as many as possible */ - let tl = v.value.length; + let tl = L.stack[top-2].value.length; /* collect total length and number of strings */ for (n = 1; n < total && tostring(L, top - n - 1); n++) { let l = L.stack[top - n - 1].value.length; @@ -1018,7 +1015,7 @@ const gettable = function(L, table, key, ra, recur) { let element = table.__index(table, key); if (!element.ttisnil()) { - L.stack[ra] = table.__index(table, key); + L.stack[ra] = element; } else { luaV_finishget(L, table, key, ra, element, recur); } diff --git a/tests/lexparse.js b/tests/lexparse.js index cd80e43..704f875 100644 --- a/tests/lexparse.js +++ b/tests/lexparse.js @@ -741,13 +741,13 @@ test('SETTABLE, GETTABLE', function (t) { }, "Lua program ran without error"); t.strictEqual( - lapi.lua_topointer(L, -1).get(0).value, + lapi.lua_topointer(L, -1).get(0).jsstring(), "hello", "Program output is correct" ); t.strictEqual( - lapi.lua_topointer(L, -1).get("two").value, + lapi.lua_topointer(L, -1).get('116|119|111|').jsstring(), "world", "Program output is correct" ); @@ -834,13 +834,13 @@ test('SETTABUP, GETTABUP', function (t) { }, "Lua program ran without error"); t.strictEqual( - lapi.lua_topointer(L, -1).get(0).value, + lapi.lua_topointer(L, -1).get(0).jsstring(), "hello", "Program output is correct" ); t.strictEqual( - lapi.lua_topointer(L, -1).get("two").value, + lapi.lua_topointer(L, -1).get('116|119|111|').jsstring(), "world", "Program output is correct" ); @@ -1149,7 +1149,7 @@ test('CONCAT', function (t) { }, "Lua program ran without error"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello 2 you", "Program output is correct" ); diff --git a/tests/ltm.js b/tests/ltm.js index d749d7b..9eedc4c 100644 --- a/tests/ltm.js +++ b/tests/ltm.js @@ -1,13 +1,17 @@ "use strict"; -const test = require('tape'); -const beautify = require('js-beautify').js_beautify; +const test = require('tape'); +const beautify = require('js-beautify').js_beautify; -const VM = require("../src/lvm.js"); -const lapi = require("../src/lapi.js"); -const OC = require('../src/lopcodes.js'); +const VM = require("../src/lvm.js"); +const lapi = require("../src/lapi.js"); +const linit = require("../src/linit.js"); +const lauxlib = require("../src/lauxlib.js"); +const OC = require('../src/lopcodes.js'); -const getState = require("./tests.js").getState; +const tests = require("./tests.js"); +const getState = tests.getState; +const toByteCode = tests.toByteCode; test('__index, __newindex: with actual table', function (t) { @@ -21,28 +25,33 @@ test('__index, __newindex: with actual table', function (t) { t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); + let bc = toByteCode(luaCode).dataView; + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lapi.lua_load(L, null, bc, "test", "binary"); lapi.lua_call(L, 0, -1); }, "Program executed without errors"); - t.strictEqual( - L.stack[L.top - 1].value, - null, + t.ok( + lapi.lua_isnil(L, -1), "Program output is correct" ); t.strictEqual( - L.stack[L.top - 2].value, + lapi.lua_tointeger(L, -2), 1, "Program output is correct" ); }); -test('__index: with non table', function (t) { +test('__newindex: with non table', function (t) { let luaCode = ` local t = "a string" - return t.yo + t.yo = "hello" `, L; t.plan(2); @@ -50,27 +59,13 @@ test('__index: with non table', function (t) { t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); - - t.throws(function () { - lapi.lua_call(L, 0, -1); - }, "Program executed with expected error"); -}); - + let bc = toByteCode(luaCode).dataView; -test('__newindex: with non table', function (t) { - let luaCode = ` - local t = "a string" - t.yo = "hello" - `, L; - - t.plan(2); + L = lauxlib.luaL_newstate(); - t.comment("Running following code: \n" + luaCode); + linit.luaL_openlibs(L); - t.doesNotThrow(function () { - L = getState(luaCode); + lapi.lua_load(L, null, bc, "test", "binary"); }, "Bytecode parsed without errors"); t.throws(function () { @@ -89,78 +84,32 @@ test('__index function in metatable', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t.yo `, L; - t.plan(8); + t.plan(3); t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; + L = lauxlib.luaL_newstate(); - // main (7 instructions at 0x7fe6b4403050) - // 0+ params, 3 slots, 1 upvalue, 2 locals, 2 constants, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7fe6b4403290 - // 3 [4] SETTABLE 0 -1 1 ; "__index" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [9] GETTABLE 2 1 -2 ; "yo" <=== We stop here - // 6 [9] RETURN 2 2 - // 7 [9] RETURN 0 1 - // - // function (3 instructions at 0x7fe6b4403290) - // 2 params, 3 slots, 0 upvalues, 2 locals, 1 constant, 0 functions - // 1 [3] LOADK 2 -1 ; "__index" - // 2 [3] RETURN 2 2 - // 3 [4] RETURN 0 1 + linit.luaL_openlibs(L); - t.strictEqual( - OC.OpCodes[L.stack[1].p.code[4].opcode], - "OP_GETTABLE", - "Correct opcode marked as breakpoint" - ); + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); - t.comment("We set a breakpoint") - L.stack[1].p.code[4].breakpoint = true; t.doesNotThrow(function () { lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); - - t.strictEqual( - OC.OpCodes[L.ci.u.l.savedpc[L.ci.pcOff - 1].opcode], - "OP_GETTABLE", - "Stopped at correct opcode" - ); - - t.comment("We unset the breakpoint and correct pcOff"); - L.ci.pcOff--; - L.stack[1].p.code[4].breakpoint = false; - - t.ok( - L.stack[3].ttistable() && !L.stack[3].value.get("__index"), - "t is on stack at 3" - ); - - t.ok( - L.stack[2].ttistable() && L.stack[2].value.get("__index"), - "mt is on stack at 2" - ); - - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; - - t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "__index", "Program output is correct" ); @@ -177,82 +126,33 @@ test('__newindex function in metatable', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) t.yo = "hello" return t.yo `, L; - t.plan(8); + t.plan(3); t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; + L = lauxlib.luaL_newstate(); - // main (8 instructions at 0x7faadcf00ac0) - // 0+ params, 3 slots, 1 upvalue, 2 locals, 3 constants, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7faadcf00d10 - // 3 [4] SETTABLE 0 -1 1 ; "__newindex" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [11] SETTABLE 1 -2 -3 ; "yo" "hello" <=== We stop here - // 6 [13] GETTABLE 2 1 -2 ; "yo" - // 7 [13] RETURN 2 2 - // 8 [13] RETURN 0 1 - // - // function (3 instructions at 0x7faadcf00d10) - // 3 params, 4 slots, 0 upvalues, 3 locals, 1 constant, 0 functions - // 1 [3] LOADK 3 -1 ; "__newindex" - // 2 [3] RETURN 3 2 - // 3 [4] RETURN 0 1 + linit.luaL_openlibs(L); - t.strictEqual( - OC.OpCodes[L.stack[1].p.code[4].opcode], - "OP_SETTABLE", - "Correct opcode marked as breakpoint" - ); - - t.comment("We set a breakpoint") - L.stack[1].p.code[4].breakpoint = true; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); - - t.strictEqual( - OC.OpCodes[L.ci.u.l.savedpc[L.ci.pcOff - 1].opcode], - "OP_SETTABLE", - "Stopped at correct opcode" - ); - - t.comment("We unset the breakpoint and correct pcOff"); - L.ci.pcOff--; - L.stack[1].p.code[4].breakpoint = false; - - t.ok( - L.stack[3].ttistable() && !L.stack[3].value.get("__newindex"), - "t is on stack at 3" - ); + }, "Program executed without errors"); t.ok( - L.stack[2].ttistable() && L.stack[2].value.get("__newindex"), - "mt is on stack at 2" - ); - - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; - - t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); - - t.strictEqual( - L.stack[L.top - 1].value, - null, + lapi.lua_isnil(L, -1), "Program output is correct" ); }); @@ -270,73 +170,31 @@ test('__index table in metatable', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t.yo `, L; - t.plan(8); + t.plan(3); t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; + L = lauxlib.luaL_newstate(); - // main (8 instructions at 0x7fb57cc03210) - // 0+ params, 4 slots, 1 upvalue, 3 locals, 3 constants, 0 functions - // 1 [1] NEWTABLE 0 0 1 - // 2 [2] SETTABLE 0 -1 -2 ; "yo" "hello" - // 3 [4] NEWTABLE 1 0 1 - // 4 [5] SETTABLE 1 -3 0 ; "__index" - - // 5 [7] NEWTABLE 2 0 0 - // 6 [9] GETTABLE 3 2 -1 ; "yo" <=== We stop here - // 7 [9] RETURN 3 2 - // 8 [9] RETURN 0 1 + linit.luaL_openlibs(L); - t.strictEqual( - OC.OpCodes[L.stack[1].p.code[5].opcode], - "OP_GETTABLE", - "Correct opcode marked as breakpoint" - ); - - t.comment("We set a breakpoint") - L.stack[1].p.code[5].breakpoint = true; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); - - t.strictEqual( - OC.OpCodes[L.ci.u.l.savedpc[L.ci.pcOff - 1].opcode], - "OP_GETTABLE", - "Stopped at correct opcode" - ); - - t.comment("We unset the breakpoint and correct pcOff"); - L.ci.pcOff--; - L.stack[1].p.code[5].breakpoint = false; - - t.ok( - L.stack[4].ttistable() && !L.stack[4].value.get("__index"), - "t is on stack at 4" - ); - - t.ok( - L.stack[3].ttistable() && L.stack[3].value.get("__index"), - "mt is on stack at 3" - ); - - t.comment("We manually set t's metatable to mt"); - L.stack[4].metatable = L.stack[3]; - - t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); @@ -355,84 +213,39 @@ test('__newindex table in metatable', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) t.yo = "world" return t.yo, mmt.yo `, L; - t.plan(9); + t.plan(4); t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; + L = lauxlib.luaL_newstate(); - // main (10 instructions at 0x7fba6a403210) - // 0+ params, 5 slots, 1 upvalue, 3 locals, 4 constants, 0 functions - // 1 [1] NEWTABLE 0 0 1 - // 2 [2] SETTABLE 0 -1 -2 ; "yo" "hello" - // 3 [5] NEWTABLE 1 0 1 - // 4 [6] SETTABLE 1 -3 0 ; "__newindex" - - // 5 [9] NEWTABLE 2 0 0 - // 6 [13] SETTABLE 2 -1 -4 ; "yo" "world" <=== We stop here - // 7 [15] GETTABLE 3 2 -1 ; "yo" - // 8 [15] GETTABLE 4 0 -1 ; "yo" - // 9 [15] RETURN 3 3 - // 10 [15] RETURN 0 1 + linit.luaL_openlibs(L); - t.strictEqual( - OC.OpCodes[L.stack[1].p.code[5].opcode], - "OP_SETTABLE", - "Correct opcode marked as breakpoint" - ); - - t.comment("We set a breakpoint") - L.stack[1].p.code[5].breakpoint = true; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); - - t.strictEqual( - OC.OpCodes[L.ci.u.l.savedpc[L.ci.pcOff - 1].opcode], - "OP_SETTABLE", - "Stopped at correct opcode" - ); - - t.comment("We unset the breakpoint and correct pcOff"); - L.ci.pcOff--; - L.stack[1].p.code[5].breakpoint = false; - - t.ok( - L.stack[4].ttistable() && !L.stack[4].value.get("__newindex"), - "t is on stack at 4" - ); - - t.ok( - L.stack[3].ttistable() && L.stack[3].value.get("__newindex"), - "mt is on stack at 3" - ); - - t.comment("We manually set t's metatable to mt"); - L.stack[4].metatable = L.stack[3]; - - t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "world", "Program output is correct" ); - t.strictEqual( - L.stack[L.top - 2].value, - null, + t.ok( + lapi.lua_isnil(L, -2), "Program output is correct" ); }); @@ -450,7 +263,7 @@ test('__index table with own metatable', function (t) { yoo = "bye" } - -- setmetatable(mmt, mmmt) + setmetatable(mmt, mmmt) local mt = { __index = mmt @@ -458,69 +271,31 @@ test('__index table with own metatable', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t.yo `, L; - t.plan(5); + t.plan(3); t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); - - - // main (11 instructions at 0x7f96e3403210) - // 0+ params, 5 slots, 1 upvalue, 4 locals, 3 constants, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7f96e3403440 - // 3 [4] SETTABLE 0 -1 1 ; "__index" - - // 4 [7] NEWTABLE 1 0 1 - // 5 [8] SETTABLE 1 -2 -3 ; "yo" "bye" - // 6 [13] NEWTABLE 2 0 1 <=== We stop here - // 7 [14] SETTABLE 2 -1 1 ; "__index" - - // 8 [17] NEWTABLE 3 0 0 - // 9 [21] GETTABLE 4 3 -2 ; "yo" <=== We stop here - // 10 [21] RETURN 4 2 - // 11 [21] RETURN 0 1 - // - // function (3 instructions at 0x7f96e3403440) - // 2 params, 3 slots, 0 upvalues, 2 locals, 1 constant, 0 functions - // 1 [3] LOADK 2 -1 ; "hello" - // 2 [3] RETURN 2 2 - // 3 [4] RETURN 0 1 - - L.stack[1].p.code[5].breakpoint = true; - L.stack[1].p.code[8].breakpoint = true; - - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); - - L.ci.pcOff--; - L.stack[1].p.code[5].breakpoint = false; + let bc = toByteCode(luaCode).dataView; - t.comment("We manually set mmt's metatable to mmmt"); - L.stack[3].metatable = L.stack[2]; - - t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + L = lauxlib.luaL_newstate(); - L.ci.pcOff--; - L.stack[1].p.code[8].breakpoint = false; + linit.luaL_openlibs(L); - t.comment("We manually set t's metatable to mt"); - L.stack[5].metatable = L.stack[4]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Third part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); @@ -539,100 +314,49 @@ test('__newindex table with own metatable', function (t) { local mmt = {} - -- setmetatable(mmt, mmmt) + setmetatable(mmt, mmmt) local mt = { __newindex = mmt } - -- setmetatable(mt, mmt) + setmetatable(mt, mmt) local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) t.yo = "hello" return t.yo, up `, L; - t.plan(7); + t.plan(4); t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); - - - // main (13 instructions at 0x7ff6ed500640) - // 0+ params, 7 slots, 1 upvalue, 5 locals, 3 constants, 1 function - // 1 [1] LOADNIL 0 0 - // 2 [3] NEWTABLE 1 0 1 - // 3 [6] CLOSURE 2 0 ; 0x7ff6ed5007f0 - // 4 [6] SETTABLE 1 -1 2 ; "__newindex" - - // 5 [9] NEWTABLE 2 0 0 - // 6 [13] NEWTABLE 3 0 1 <=== We stop here - // 7 [14] SETTABLE 3 -1 2 ; "__newindex" - - // 8 [19] NEWTABLE 4 0 0 <=== We stop here - // 9 [23] SETTABLE 4 -2 -3 ; "yo" "hello" <=== We stop here - // 10 [25] GETTABLE 5 4 -2 ; "yo" - // 11 [25] MOVE 6 0 - // 12 [25] RETURN 5 3 - // 13 [25] RETURN 0 1 - // - // function (2 instructions at 0x7ff6ed5007f0) - // 3 params, 3 slots, 1 upvalue, 3 locals, 0 constants, 0 functions - // 1 [5] SETUPVAL 2 0 ; up - // 2 [6] RETURN 0 1 - - L.stack[1].p.code[5].breakpoint = true; - L.stack[1].p.code[7].breakpoint = true; - L.stack[1].p.code[8].breakpoint = true; - - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); + let bc = toByteCode(luaCode).dataView; - L.ci.pcOff--; - L.stack[1].p.code[5].breakpoint = false; + L = lauxlib.luaL_newstate(); - t.comment("We manually set mmt's metatable to mmmt"); - L.stack[4].metatable = L.stack[3]; + linit.luaL_openlibs(L); - t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); - - L.ci.pcOff--; - L.stack[1].p.code[7].breakpoint = false; - - t.comment("We manually set mt's metatable to mmt"); - L.stack[5].metatable = L.stack[4]; - - t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Third part of the program executed without errors"); - - L.ci.pcOff--; - L.stack[1].p.code[8].breakpoint = false; - - t.comment("We manually set t's metatable to mt"); - L.stack[6].metatable = L.stack[5]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Fourth part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); - t.strictEqual( - L.stack[L.top - 2].value, - null, + t.ok( + lapi.lua_isnil(L, -2), "Program output is correct" ); }); @@ -693,7 +417,7 @@ test('binary __xxx functions in metatable', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t + 1, @@ -710,79 +434,26 @@ test('binary __xxx functions in metatable', function (t) { t >> 1 `, L; - t.plan(4); + t.plan(3); t.comment("Running following code: \n" + luaCode); t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; + L = lauxlib.luaL_newstate(); - - //main (40 instructions at 0x7fd29ac03210) - //0+ params, 14 slots, 1 upvalue, 2 locals, 13 constants, 12 functions - // 1 [1] NEWTABLE 0 0 12 - // 2 [4] CLOSURE 1 0 ; 0x7fd29ac03440 - // 3 [4] SETTABLE 0 -1 1 ; "__add" - - // 4 [8] CLOSURE 1 1 ; 0x7fd29ac03500 - // 5 [8] SETTABLE 0 -2 1 ; "__sub" - - // 6 [12] CLOSURE 1 2 ; 0x7fd29ac038c0 - // 7 [12] SETTABLE 0 -3 1 ; "__mul" - - // 8 [16] CLOSURE 1 3 ; 0x7fd29ac039e0 - // 9 [16] SETTABLE 0 -4 1 ; "__mod" - - // 10 [20] CLOSURE 1 4 ; 0x7fd29ac03c00 - // 11 [20] SETTABLE 0 -5 1 ; "__pow" - - // 12 [24] CLOSURE 1 5 ; 0x7fd29ac036a0 - // 13 [24] SETTABLE 0 -6 1 ; "__div" - - // 14 [28] CLOSURE 1 6 ; 0x7fd29ac037c0 - // 15 [28] SETTABLE 0 -7 1 ; "__idiv" - - // 16 [32] CLOSURE 1 7 ; 0x7fd29ac03ce0 - // 17 [32] SETTABLE 0 -8 1 ; "__band" - - // 18 [36] CLOSURE 1 8 ; 0x7fd29ac03b00 - // 19 [36] SETTABLE 0 -9 1 ; "__bor" - - // 20 [40] CLOSURE 1 9 ; 0x7fd29ac04060 - // 21 [40] SETTABLE 0 -10 1 ; "__bxor" - - // 22 [44] CLOSURE 1 10 ; 0x7fd29ac04180 - // 23 [44] SETTABLE 0 -11 1 ; "__shl" - - // 24 [48] CLOSURE 1 11 ; 0x7fd29ac042a0 - // 25 [48] SETTABLE 0 -12 1 ; "__shr" - - // 26 [52] NEWTABLE 1 0 0 - // 27 [57] ADD 2 1 -13 ; - 1 <=== We stop here - // 28 [58] SUB 3 1 -13 ; - 1 - // 29 [59] MUL 4 1 -13 ; - 1 - // 30 [60] MOD 5 1 -13 - // 31 [61] POW 6 1 -13 ; - 1 - // 32 [62] DIV 7 1 -13 ; - 1 - // 33 [63] IDIV 8 1 -13 ; - 1 - // 34 [64] BAND 9 1 -13 ; - 1 - // 35 [65] BOR 10 1 -13 ; - 1 - // 36 [66] BXOR 11 1 -13 ; - 1 - // 37 [67] SHL 12 1 -13 ; - 1 - // 38 [68] SHR 13 1 -13 ; - 1 - // 39 [68] RETURN 2 13 - // 40 [68] RETURN 0 1 - // - // ... - - L.stack[1].p.code[26].breakpoint = true; + linit.luaL_openlibs(L); - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); - - L.ci.pcOff--; - L.stack[1].p.code[26].breakpoint = false; - - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); t.deepEqual( - L.stack.slice(L.top - 12, L.top).map(e => e.value), + L.stack.slice(L.top - 12, L.top).map(e => e.jsstring()), [ "{} + 1", "{} - 1", @@ -812,54 +483,31 @@ test('__eq', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t == {} `, L; - t.plan(4); + t.plan(3); t.comment("Running following code: \n" + luaCode); - // main (11 instructions at 0x7fce9fc03210) - // 0+ params, 3 slots, 1 upvalue, 2 locals, 1 constant, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7fce9fc03440 - // 3 [4] SETTABLE 0 -1 1 ; "__eq" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [11] NEWTABLE 2 0 0 - // 6 [11] EQ 1 1 2 <=== We stop here - // 7 [11] JMP 0 1 ; to 9 - // 8 [11] LOADBOOL 2 0 1 - // 9 [11] LOADBOOL 2 1 0 - // 10 [11] RETURN 2 2 - // 11 [11] RETURN 0 1 - // - // ... - t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; - L.stack[1].p.code[5].breakpoint = true; + L = lauxlib.luaL_newstate(); - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); + linit.luaL_openlibs(L); - L.ci.pcOff--; - L.stack[1].p.code[5].breakpoint = false; - - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); - t.strictEqual( - L.stack[L.top - 1].value, - true, + t.ok( + lapi.lua_toboolean(L, -1), "Program output is correct" ); }); @@ -875,54 +523,31 @@ test('__lt', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t < {} `, L; - t.plan(4); + t.plan(3); t.comment("Running following code: \n" + luaCode); - // main (11 instructions at 0x7fc879d00ac0) - // 0+ params, 3 slots, 1 upvalue, 2 locals, 1 constant, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7fc879d00d10 - // 3 [4] SETTABLE 0 -1 1 ; "__lt" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [11] NEWTABLE 2 0 0 - // 6 [11] LT 1 1 2 <=== We stop here - // 7 [11] JMP 0 1 ; to 9 - // 8 [11] LOADBOOL 2 0 1 - // 9 [11] LOADBOOL 2 1 0 - // 10 [11] RETURN 2 2 - // 11 [11] RETURN 0 1 - // - // ... - t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); - - L.stack[1].p.code[5].breakpoint = true; + let bc = toByteCode(luaCode).dataView; - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); + L = lauxlib.luaL_newstate(); - L.ci.pcOff--; - L.stack[1].p.code[5].breakpoint = false; + linit.luaL_openlibs(L); - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); - t.strictEqual( - L.stack[L.top - 1].value, - true, + t.ok( + lapi.lua_toboolean(L, -1), "Program output is correct" ); }); @@ -938,54 +563,31 @@ test('__le', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t <= {} `, L; - t.plan(4); + t.plan(3); t.comment("Running following code: \n" + luaCode); - // main (11 instructions at 0x7fc879d00ac0) - // 0+ params, 3 slots, 1 upvalue, 2 locals, 1 constant, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7fc879d00d10 - // 3 [4] SETTABLE 0 -1 1 ; "__lt" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [11] NEWTABLE 2 0 0 - // 6 [11] LE 1 1 2 <=== We stop here - // 7 [11] JMP 0 1 ; to 9 - // 8 [11] LOADBOOL 2 0 1 - // 9 [11] LOADBOOL 2 1 0 - // 10 [11] RETURN 2 2 - // 11 [11] RETURN 0 1 - // - // ... - t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; - L.stack[1].p.code[5].breakpoint = true; + L = lauxlib.luaL_newstate(); - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); - - L.ci.pcOff--; - L.stack[1].p.code[5].breakpoint = false; + linit.luaL_openlibs(L); - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); - t.strictEqual( - L.stack[L.top - 1].value, - true, + t.ok( + lapi.lua_toboolean(L, -1), "Program output is correct" ); }); @@ -1001,54 +603,31 @@ test('__le that uses __lt', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return {} <= t `, L; - t.plan(4); + t.plan(3); t.comment("Running following code: \n" + luaCode); - // main (11 instructions at 0x7fc879d00ac0) - // 0+ params, 3 slots, 1 upvalue, 2 locals, 1 constant, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7fc879d00d10 - // 3 [4] SETTABLE 0 -1 1 ; "__lt" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [11] NEWTABLE 2 0 0 - // 6 [11] LE 1 1 2 <=== We stop here - // 7 [11] JMP 0 1 ; to 9 - // 8 [11] LOADBOOL 2 0 1 - // 9 [11] LOADBOOL 2 1 0 - // 10 [11] RETURN 2 2 - // 11 [11] RETURN 0 1 - // - // ... - t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; - L.stack[1].p.code[5].breakpoint = true; + L = lauxlib.luaL_newstate(); - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); - - L.ci.pcOff--; - L.stack[1].p.code[5].breakpoint = false; + linit.luaL_openlibs(L); - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); - t.strictEqual( - L.stack[L.top - 1].value, - true, + t.ok( + lapi.lua_toboolean(L, -1), "Program output is correct" ); }); @@ -1068,58 +647,37 @@ test('__unm, __bnot', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return -t, ~t `, L; - t.plan(5); + t.plan(4); t.comment("Running following code: \n" + luaCode); - // main (10 instructions at 0x7ff10e403210) - // 0+ params, 4 slots, 1 upvalue, 2 locals, 2 constants, 2 functions - // 1 [1] NEWTABLE 0 0 2 - // 2 [4] CLOSURE 1 0 ; 0x7ff10e403440 - // 3 [4] SETTABLE 0 -1 1 ; "__unm" - - // 4 [8] CLOSURE 1 1 ; 0x7ff10e4033c0 - // 5 [8] SETTABLE 0 -2 1 ; "__bnot" - - // 6 [11] NEWTABLE 1 0 0 - // 7 [15] UNM 2 1 <=== We stop here - // 8 [15] BNOT 3 1 - // 9 [15] RETURN 2 3 - // 10 [15] RETURN 0 1 - // - // ... - t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; - L.stack[1].p.code[6].breakpoint = true; + L = lauxlib.luaL_newstate(); - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); + linit.luaL_openlibs(L); - L.ci.pcOff--; - L.stack[1].p.code[6].breakpoint = false; - - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "world", "Program output is correct" ); t.strictEqual( - L.stack[L.top - 2].value, + lapi.lua_tostring(L, -2), "hello", "Program output is correct" ); @@ -1136,49 +694,31 @@ test('__len', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return #t `, L; - t.plan(4); + t.plan(3); t.comment("Running following code: \n" + luaCode); - // main (7 instructions at 0x7f91f0600ac0) - // 0+ params, 3 slots, 1 upvalue, 2 locals, 1 constant, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7f91f0600d10 - // 3 [4] SETTABLE 0 -1 1 ; "__len" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [11] LEN 2 1 <=== We stop here - // 6 [11] RETURN 2 2 - // 7 [11] RETURN 0 1 - // - // ... - t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); - - L.stack[1].p.code[4].breakpoint = true; + let bc = toByteCode(luaCode).dataView; - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); + L = lauxlib.luaL_newstate(); - L.ci.pcOff--; - L.stack[1].p.code[4].breakpoint = false; + linit.luaL_openlibs(L); - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); @@ -1195,51 +735,31 @@ test('__concat', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t .. " world" `, L; - t.plan(4); + t.plan(3); t.comment("Running following code: \n" + luaCode); - // main (9 instructions at 0x7ffacdc03210) - // 0+ params, 4 slots, 1 upvalue, 2 locals, 2 constants, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7ffacdc03440 - // 3 [4] SETTABLE 0 -1 1 ; "__concat" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [11] MOVE 2 1 - // 6 [11] LOADK 3 -2 ; " world" - // 7 [11] CONCAT 2 2 3 <=== We stop here - // 8 [11] RETURN 2 2 - // 9 [11] RETURN 0 1 - // - // ... - t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); + let bc = toByteCode(luaCode).dataView; - L.stack[1].p.code[6].breakpoint = true; + L = lauxlib.luaL_newstate(); - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); + linit.luaL_openlibs(L); - L.ci.pcOff--; - L.stack[1].p.code[6].breakpoint = false; - - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); @@ -1256,50 +776,31 @@ test('__call', function (t) { local t = {} - -- setmetatable(t, mt) + setmetatable(t, mt) return t("world","wow") `, L; - t.plan(4); + t.plan(3); t.comment("Running following code: \n" + luaCode); - // main (10 instructions at 0x7fc4c9403210) - // 0+ params, 5 slots, 1 upvalue, 2 locals, 3 constants, 1 function - // 1 [1] NEWTABLE 0 0 1 - // 2 [4] CLOSURE 1 0 ; 0x7fc4c9403440 - // 3 [4] SETTABLE 0 -1 1 ; "__call" - - // 4 [7] NEWTABLE 1 0 0 - // 5 [11] MOVE 2 1 - // 6 [11] LOADK 3 -2 ; "world" - // 7 [11] LOADK 4 -3 ; "wow" - // 8 [11] TAILCALL 2 3 0 <=== We stop here - // 9 [11] RETURN 2 0 - // 10 [11] RETURN 0 1 - t.doesNotThrow(function () { - L = getState(luaCode); - }, "Bytecode parsed without errors"); - - L.stack[1].p.code[7].breakpoint = true; + let bc = toByteCode(luaCode).dataView; - t.doesNotThrow(function () { - lapi.lua_call(L, 0, -1); - }, "First part of the program executed without errors"); + L = lauxlib.luaL_newstate(); - L.ci.pcOff--; - L.stack[1].p.code[7].breakpoint = false; + linit.luaL_openlibs(L); - t.comment("We manually set t's metatable to mt"); - L.stack[3].metatable = L.stack[2]; + lapi.lua_load(L, null, bc, "test", "binary"); + }, "Bytecode parsed without errors"); t.doesNotThrow(function () { - VM.luaV_execute(L); - }, "Second part of the program executed without errors"); + lapi.lua_call(L, 0, -1); + }, "Program executed without errors"); t.deepEqual( - L.stack.slice(L.top - 3, L.top).map(e => e.value), + L.stack.slice(L.top - 3, L.top).map(e => e.jsstring()), ["hello", "world", "wow"], "Program output is correct" ); diff --git a/tests/lvm.js b/tests/lvm.js index f5948eb..69195d1 100644 --- a/tests/lvm.js +++ b/tests/lvm.js @@ -26,7 +26,7 @@ test('LOADK, RETURN', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello world", "Program output is correct" ); @@ -50,7 +50,7 @@ test('MOVE', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello world", "Program output is correct" ); @@ -147,7 +147,7 @@ test('CALL', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tointeger(L, -1), 3, "Program output is correct" ); @@ -205,7 +205,7 @@ test('TAILCALL', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tointeger(L, -1), 3, "Program output is correct" ); @@ -255,7 +255,7 @@ test('LE, JMP', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_toboolean(L, -1), true, "Program output is correct" ); @@ -279,7 +279,7 @@ test('LT', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_toboolean(L, -1), false, "Program output is correct" ); @@ -303,7 +303,7 @@ test('EQ', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_toboolean(L, -1), true, "Program output is correct" ); @@ -328,7 +328,7 @@ test('TESTSET (and)', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); @@ -353,7 +353,7 @@ test('TESTSET (or)', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); @@ -382,7 +382,7 @@ test('TEST (true)', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); @@ -411,7 +411,7 @@ test('TEST (false)', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "goodbye", "Program output is correct" ); @@ -439,7 +439,7 @@ test('FORPREP, FORLOOP (int)', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tointeger(L, -1), 55, "Program output is correct" ); @@ -467,7 +467,7 @@ test('FORPREP, FORLOOP (float)', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tonumber(L, -1), 60.5, "Program output is correct" ); @@ -493,14 +493,16 @@ test('SETTABLE, GETTABLE', function (t) { lapi.lua_call(L, 0, -1); }, "Program executed without errors"); - t.strictEqual( - L.stack[L.top - 1].value.get(0).value, + console.log(L.stack[L.top - 1]); + + t.deepEqual( + L.stack[L.top - 1].value.get(0).jsstring(), "hello", "Program output is correct" ); - t.strictEqual( - L.stack[L.top - 1].value.get("two").value, + t.deepEqual( + L.stack[L.top - 1].value.get('116|119|111|').jsstring(), // "two" "world", "Program output is correct" ); @@ -530,7 +532,7 @@ test('SETUPVAL, GETUPVAL', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "world", "Program output is correct" ); @@ -556,15 +558,15 @@ test('SETTABUP, GETTABUP', function (t) { lapi.lua_call(L, 0, -1); }, "Program executed without errors"); - t.strictEqual( - L.stack[L.top - 1].value.get(0).value, - "hello", + t.deepEqual( + L.stack[L.top - 1].value.get(0).jsstring(), + "hello", // "hello" "Program output is correct" ); - t.strictEqual( - L.stack[L.top - 1].value.get("two").value, - "world", + t.deepEqual( + L.stack[L.top - 1].value.get('116|119|111|').jsstring(), // "two" + "world", // "world" "Program output is correct" ); }); @@ -592,7 +594,7 @@ test('SELF', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello", "Program output is correct" ); @@ -732,7 +734,7 @@ test('TFORCALL, TFORLOOP', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tointeger(L, -1), 6, "Program output is correct" ); @@ -758,19 +760,19 @@ test('LEN', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tointeger(L, -1), 5, "Program output is correct" ); t.strictEqual( - L.stack[L.top - 2].value, + lapi.lua_tointeger(L, -2), 3, "Program output is correct" ); t.strictEqual( - L.stack[L.top - 3].value, + lapi.lua_tointeger(L, -3), 0, "Program output is correct" ); @@ -792,7 +794,7 @@ test('CONCAT', function (t) { }, "Program executed without errors"); t.strictEqual( - L.stack[L.top - 1].value, + lapi.lua_tostring(L, -1), "hello 2 you", "Program output is correct" ); diff --git a/tests/tests.js b/tests/tests.js index 32f6563..40bebd8 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -40,6 +40,5 @@ const getState = function(luaCode) { return L; }; - module.exports.getState = getState; module.exports.toByteCode = toByteCode; \ No newline at end of file -- cgit v1.2.3-54-g00ecf