aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lauxlib.js19
-rw-r--r--src/lbaselib.js12
-rw-r--r--src/lobject.js11
-rw-r--r--src/ltable.js15
-rw-r--r--tests/lbaselib.js47
5 files changed, 80 insertions, 24 deletions
diff --git a/src/lauxlib.js b/src/lauxlib.js
index 4e32437..29b223f 100644
--- a/src/lauxlib.js
+++ b/src/lauxlib.js
@@ -95,11 +95,8 @@ const typeerror = function(L, arg, tname) {
else
typearg = luaL_typename(L, arg);
- throw new Error(`${tname} expected, got ${typearg}`);
-
- // TODO:
- // let msg = lua_pushstring(L, `${tname} expected, got ${typearg}`);
- // return luaL_argerror(L, arg, msg);
+ let msg = lua_pushstring(L, `${tname} expected, got ${typearg}`);
+ return luaL_argerror(L, arg, msg);
};
const luaL_where = function(L, level) {
@@ -141,12 +138,12 @@ const luaL_typename = function(L, i) {
};
const luaL_argcheck = function(L, cond, arg, extramsg) {
- if (!cond) throw new Error(extramsg); // TODO: luaL_argerror
+ if (!cond) luaL_argerror(L, arg, extramsg);
};
const luaL_checkany = function(L, arg) {
if (lapi.lua_type(L, arg) === CT.LUA_TNONE)
- throw new Error("value expected"); // TODO: luaL_argerror(L, arg, "value expected");
+ luaL_argerror(L, arg, "value expected");
};
const luaL_checktype = function(L, arg, t) {
@@ -170,7 +167,7 @@ const luaL_optstring = luaL_optlstring;
const interror = function(L, arg) {
if (lapi.lua_isnumber(L, arg))
- throw new Error("number has no integer representation");
+ luaL_argerror(L, arg, "number has no integer representation");
else
tag_error(L, arg, CT.LUA_TNUMBER);
};
@@ -216,7 +213,7 @@ const luaL_callmeta = function(L, obj, event) {
const luaL_tolstring = function(L, idx) {
if (luaL_callmeta(L, idx, "__tostring")) {
if (!lapi.lua_isstring(L, -1))
- throw new Error("'__tostring' must return a string"); // TODO: luaL_error
+ luaL_error(L, "'__tostring' must return a string");
} else {
switch(lapi.lua_type(L, idx)) {
case CT.LUA_TNUMBER:
@@ -307,9 +304,9 @@ const luaL_setfuncs = function(L, l, nup) {
const luaL_checkstack = function(L, space, msg) {
if (!lapi.lua_checkstack(L, space)) {
if (msg)
- throw new Error(L, `stack overflow (${msg})`);
+ luaL_error(L, `stack overflow (${msg})`);
else
- throw new Error(L, 'stack overflow'); // TODO: luaL_error
+ luaL_error(L, 'stack overflow');
}
};
diff --git a/src/lbaselib.js b/src/lbaselib.js
index 2eacaaf..f405a7d 100644
--- a/src/lbaselib.js
+++ b/src/lbaselib.js
@@ -110,6 +110,17 @@ const pairsmeta = function(L, method, iszero, iter) {
return 3;
};
+const luaB_next = function(L) {
+ lauxlib.luaL_checktype(L, 1, CT.LUA_TTABLE);
+ lapi.lua_settop(L, 2); /* create a 2nd argument if there isn't one */
+ if (lapi.lua_next(L, 1))
+ return 2;
+ else {
+ lapi.lua_pushnil(L);
+ return 1;
+ }
+};
+
/*
** Traversal function for 'ipairs'
*/
@@ -244,6 +255,7 @@ const base_funcs = {
"tostring": luaB_tostring,
"tonumber": luaB_tonumber,
"getmetatable": luaB_getmetatable,
+ "next": luaB_next,
"ipairs": luaB_ipairs,
"select": luaB_select,
"setmetatable": luaB_setmetatable,
diff --git a/src/lobject.js b/src/lobject.js
index 2ba45ad..4e4b701 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -121,7 +121,8 @@ class Table extends TValue {
static keyValue(key) {
// Those lua values are used by value, others by reference
if (key instanceof TValue
- && [CT.LUA_TSTRING,
+ && [CT.LUA_TNIL,
+ CT.LUA_TSTRING,
CT.LUA_TSHRSTR,
CT.LUA_TLNGSTR,
CT.LUA_TNUMINT].indexOf(key.type) > -1) {
@@ -135,9 +136,9 @@ class Table extends TValue {
key = Table.keyValue(key);
if (typeof key === 'number' && key > 0) {
- table.value.hash.set(key - 1, value); // Lua array starts at 1
+ table.value.set(key - 1, value); // Lua array starts at 1
} else {
- table.value.hash.set(key, value);
+ table.value.set(key, value);
}
}
@@ -146,9 +147,9 @@ class Table extends TValue {
let v = nil;
if (typeof key === 'number' && key > 0) {
- v = table.value.hash.get(key - 1); // Lua array starts at 1
+ v = table.value.get(key - 1); // Lua array starts at 1
} else {
- v = table.value.hash.get(key);
+ v = table.value.get(key);
}
return v ? v : nil;
diff --git a/src/ltable.js b/src/ltable.js
index 14139af..7611b4c 100644
--- a/src/ltable.js
+++ b/src/ltable.js
@@ -8,6 +8,7 @@ const lua = require('./lua.js');
const CT = lua.constant_types;
const nil = require('./ldo.js').nil;
const Table = lobject.Table;
+const TValue = lobject.TValue;
Table.prototype.ordered_intindexes = function() {
@@ -37,9 +38,9 @@ Table.prototype.luaH_getn = function() {
for (let i = 0; i < len; i++) {
let key = indexes[i];
- if (!this.value.get(key).ttisnil() // t[i] is non-nil
- && (i === len - 1 || this.value.get(indexes[i + 1]).ttisinil())) { // t[i+1] is nil or is the last integer indexed element
- return indexes[i];
+ if (!this.__index(this, key).ttisnil() // t[i] is non-nil
+ && (i === len - 1 || this.__index(this, indexes[i + 1]).ttisnil())) { // t[i+1] is nil or is the last integer indexed element
+ return indexes[i] + 1;
}
}
@@ -50,9 +51,13 @@ Table.prototype.luaH_next = function(L, keyI) {
let keyO = L.stack[keyI];
let key = Table.keyValue(keyO);
let indexes = this.ordered_indexes();
+
+ if (indexes.length === 0) return 0;
+
let i = indexes.indexOf(key);
- if (i >= 0 && i < indexes.length - 1) {
+ if ((i >= 0 || key === null) && i < indexes.length - 1) {
+ if (key === null) i = -1;
let nidx = indexes[i+1];
let tnidx = typeof nidx;
@@ -63,7 +68,7 @@ Table.prototype.luaH_next = function(L, keyI) {
else
L.stack[keyI] = indexes[i + 1];
- L.stack[keyI + 1] = this.map.get(indexes[i]);
+ L.stack[keyI + 1] = this.value.get(indexes[i + 1]);
return 1;
}
diff --git a/tests/lbaselib.js b/tests/lbaselib.js
index d71e3ab..d2f0e0e 100644
--- a/tests/lbaselib.js
+++ b/tests/lbaselib.js
@@ -426,19 +426,19 @@ test('select', function (t) {
}, "JS Lua program ran without error");
t.deepEqual(
- lapi.lua_topointer(L, -3).map(e => e.value),
+ [...lapi.lua_topointer(L, -3).entries()].map(e => e[1].value),
[3],
"Correct element(s) on the stack"
);
t.deepEqual(
- lapi.lua_topointer(L, -2).map(e => e.value),
+ [...lapi.lua_topointer(L, -2).entries()].map(e => e[1].value).sort(),
[2, 3],
"Correct element(s) on the stack"
);
t.deepEqual(
- lapi.lua_topointer(L, -1).map(e => e.value),
+ [...lapi.lua_topointer(L, -1).entries()].map(e => e[1].value).sort(),
[2, 3],
"Correct element(s) on the stack"
);
@@ -552,4 +552,45 @@ test('rawlen', function (t) {
5,
"Correct element(s) on the stack"
);
+});
+
+
+test('next', function (t) {
+ let luaCode = `
+ local total = 0
+ local t = {
+ 1,
+ two = 2,
+ 3,
+ four = 4
+ }
+
+ for k,v in next, t, nil do
+ total = total + v
+ end
+
+ return total
+ `, L;
+
+ t.plan(2);
+
+ t.doesNotThrow(function () {
+
+ let bc = toByteCode(luaCode).dataView;
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lapi.lua_load(L, bc, "test-next");
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "JS Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tonumber(L, -1),
+ 10,
+ "Correct element(s) on the stack"
+ );
}); \ No newline at end of file