diff options
| -rw-r--r-- | README.md | 8 | ||||
| -rw-r--r-- | src/lapi.js | 15 | ||||
| -rw-r--r-- | src/lbaselib.js | 39 | ||||
| -rw-r--r-- | tests/lbaselib.js | 36 | 
4 files changed, 94 insertions, 4 deletions
| @@ -212,16 +212,16 @@          - [x] pcall          - [x] xpcall          - [x] collectgarbage (unavailable) +        - [x] ipairs          - [ ] assert -        - [ ] dofile -        - [ ] ipairs -        - [ ] loadfile -        - [ ] load          - [ ] next          - [ ] pairs          - [ ] rawlen          - [ ] select          - [ ] tonumber +        - [ ] dofile +        - [ ] loadfile +        - [ ] load      - [ ] ...  - [ ] Debug (errors)  - [ ] DOM API binding diff --git a/src/lapi.js b/src/lapi.js index c091150..e149619 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -426,6 +426,20 @@ const lua_getfield = function(L, idx, k) {      return auxgetstr(L, index2addr(L, idx), k);  }; +const lua_geti = function(L, idx, n) { +    let t = index2addr(L, idx); +    let slot = t.__index(t, n); +    if (!slot.ttisnil()) { +        L.stack[L.top++] = slot; +        assert(L.top <= L.ci.top, "stack overflow"); +    } else { +        L.stack[L.top++] = new TValue(CT.LUA_TNUMINT, n); +        assert(L.top <= L.ci.top, "stack overflow"); +        lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1); +    } +    return L.stack[L.top - 1].ttnov(); +}; +  const lua_getglobal = function(L, name) {      return auxgetstr(L, L.l_G.l_registry.value.array[lua.LUA_RIDX_GLOBALS - 1], name);  }; @@ -651,6 +665,7 @@ module.exports.lua_createtable     = lua_createtable;  module.exports.lua_newtable        = lua_newtable;  module.exports.lua_settable        = lua_settable;  module.exports.lua_gettable        = lua_gettable; +module.exports.lua_geti            = lua_geti;  module.exports.lua_absindex        = lua_absindex;  module.exports.index2addr          = index2addr;  module.exports.lua_rawget          = lua_rawget; diff --git a/src/lbaselib.js b/src/lbaselib.js index b3dcd12..d0e094f 100644 --- a/src/lbaselib.js +++ b/src/lbaselib.js @@ -89,6 +89,44 @@ const luaB_type = function(L) {      return 1;  }; +const pairsmeta = function(L, method, iszero, iter) { +    lauxlib.luaL_checkany(L, 1); +    if (lauxlib.luaL_getmetafield(L, 1, method).ttisnil()) {  /* no metamethod? */ +        lapi.lua_pushcfunction(L, iter);  /* will return generator, */ +        lapi.lua_pushvalue(L, 1);  /* state, */ +        if (iszero) lapi.lua_pushinteger(L, 0);  /* and initial value */ +        else lapi.lua_pushnil(L); +    } else { +        lapi.lua_pushvalue(L, 1);  /* argument 'self' to metamethod */ +        lapi.lua_call(L, 1, 3);  /* get 3 values from metamethod */ +    } +    return 3; +}; + +/* +** Traversal function for 'ipairs' +*/ +const ipairsaux = function(L) { +    let i = lauxlib.luaL_checkinteger(L, 2) + 1; +    lapi.lua_pushinteger(L, i); +    return lapi.lua_geti(L, 1, i) === CT.LUA_TNIL ? 1 : 2; +}; + +/* +** 'ipairs' function. Returns 'ipairsaux', given "table", 0. +** (The given "table" may not be a table.) +*/ +const luaB_ipairs = function(L) { +    // Lua 5.2 +    // return pairsmeta(L, "__ipairs", 1, ipairsaux); + +    lauxlib.luaL_checkany(L, 1); +    lapi.lua_pushcfunction(L, ipairsaux);  /* iteration function */ +    lapi.lua_pushvalue(L, 1);  /* state */ +    lapi.lua_pushinteger(L, 0);  /* initial value */ +    return 3; +}; +  const luaB_error = function(L) {      let level = lauxlib.luaL_optinteger(L, 2, 1);      lapi.lua_settop(L, 1); @@ -144,6 +182,7 @@ const base_funcs = {      "print":          luaB_print,      "tostring":       luaB_tostring,      "getmetatable":   luaB_getmetatable, +    "ipairs":         luaB_ipairs,      "setmetatable":   luaB_setmetatable,      "rawequal":       luaB_rawequal,      "rawset":         luaB_rawset, diff --git a/tests/lbaselib.js b/tests/lbaselib.js index 85563da..53191eb 100644 --- a/tests/lbaselib.js +++ b/tests/lbaselib.js @@ -365,4 +365,40 @@ test('xpcall', function (t) {          lapi.lua_tostring(L, -1).endsWith("you fucked up"),          "msgh was called and modified the error"      ) +}); + + +test('ipairs', function (t) { +    let luaCode = ` +        local t = {1, 2, 3, 4, 5, ['yo'] = 'lo'} + +        local sum = 0 +        for i, v in ipairs(t) do +            sum = sum + v +        end + +        return sum +    `, 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-pcall"); + +        lapi.lua_call(L, 0, -1); + +    }, "JS Lua program ran without error"); + +    t.strictEqual( +        lapi.lua_tointeger(L, -1), +        15, +        "Correct element(s) on the stack" +    )  });
\ No newline at end of file | 
