From a8e82fc01f2558550289f76f55c917039296ec11 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Fri, 17 Feb 2017 11:33:23 +0100 Subject: lua_load (bytecode only), lua_call(k) --- README.md | 6 +++--- src/lapi.js | 19 +++++++++++++++++++ src/ldo.js | 35 ++++++++++++++++++----------------- tests/lapi.js | 48 +++++++++++++++++++++++++++++++++++++++--------- tests/tests.js | 6 +++--- 5 files changed, 82 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index fb727b4..e79a6a8 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,11 @@ - [x] lua_pushjsclosure (lua_pushcclosure) - [x] lua_pushjsfunction (lua_pushcfunction) - [x] lua_pop + - [x] lua_load + - [x] lua_call + - [x] lua_callk - [ ] lua_absindex - [ ] lua_arith - - [ ] lua_call - - [ ] lua_callk - [ ] lua_checkstack - [ ] lua_close - [ ] lua_compare @@ -85,7 +86,6 @@ - [ ] lua_isuserdata - [ ] lua_isyieldable - [ ] lua_len - - [ ] lua_load - [ ] lua_newtable - [ ] lua_newthread - [ ] lua_newuserdata diff --git a/src/lapi.js b/src/lapi.js index 976841d..6cc95b2 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -240,6 +240,24 @@ const lua_typename = function(L, t) { ** 'load' and 'call' functions (run Lua code) */ +const lua_load = function(L, data, chunckname) { + if (!chunckname) chunckname = "?"; + + let status = ldo.luaD_protectedparser(L, data, chunckname); + if (status === TS.LUA_OK) { + let f = L.stack[L.top - 1]; /* get newly created function */ + if (f.nupvalues >= 1) { /* does it have an upvalue? */ + /* get global table from registry */ + let reg = L.l_G.l_registry; + let gt = reg.value.array[lua.LUA_RIDX_GLOBALS]; + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + f.upvals[0].v = gt; // TODO: is gt on the stack ? is that upvalue opened or closed ? + } + } + + return status; +}; + const lua_callk = function(L, nargs, nresults, ctx, k) { assert(k === null || !(L.ci.callstatus & CIST_LUA), "cannot use continuations inside hooks"); assert(nargs + 1 < L.top - L.ci.funcOff, "not enough elements in the stack"); @@ -333,6 +351,7 @@ module.exports.lua_tointeger = lua_tointeger; module.exports.lua_toboolean = lua_toboolean; module.exports.lua_tolstring = lua_tolstring; module.exports.lua_tostring = lua_tostring; +module.exports.lua_load = lua_load; module.exports.lua_callk = lua_callk; module.exports.lua_call = lua_call; module.exports.lua_pop = lua_pop; \ No newline at end of file diff --git a/src/ldo.js b/src/ldo.js index 3686f7d..632bc22 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -9,6 +9,8 @@ const lstate = require('./lstate.js'); const llimit = require('./llimit.js'); const ltm = require('./ltm.js'); const lvm = require('./lvm.js'); +const lfunc = require('./lfunc.js'); +const BytecodeParser = require('./lundump.js'); const CT = lua.constant_types; const TS = lua.thread_status; const LUA_MULTRET = lua.LUA_MULTRET; @@ -237,7 +239,7 @@ const luaD_pcall = function(L, func, u, old_top, ef) { let old_errfunc = L.errfunc; L.errfunc = ef; - status = luaD_rawrunprotected(L, func, u); + let status = luaD_rawrunprotected(L, func, u); if (status !== TS.LUA_OK) { lfunc.luaF_close(L, old_top); @@ -263,12 +265,10 @@ const luaD_callnoyield = function(L, off, nResults) { // TODO: since we only handle binary, no need for a reader or mode const f_parser = function(L, data) { - assert(data instanceof DataView, "data must be a DataView"); + let p = new BytecodeParser(data); + let cl = p.luaU_undump(L); - let p = new lundump.BytecodeParser(data); - let cl = p.luaU_undump(); - - assert(cl.nupvalues == cl.p.sizeupvalues); + assert(cl.nupvalues == cl.p.upvalues.length); lfunc.luaF_initupvals(L, cl); }; @@ -283,14 +283,15 @@ const luaD_protectedparser = function(L, data, name) { return status; }; -module.exports.nil = nil; -module.exports.luaD_precall = luaD_precall; -module.exports.luaD_poscall = luaD_poscall; -module.exports.moveresults = moveresults; -module.exports.adjust_varargs = adjust_varargs; -module.exports.tryfuncTM = tryfuncTM; -module.exports.stackerror = stackerror; -module.exports.luaD_call = luaD_call; -module.exports.luaD_callnoyield = luaD_callnoyield; -module.exports.luaD_pcall = luaD_pcall; -module.exports.luaD_rawrunprotected = luaD_rawrunprotected; \ No newline at end of file +module.exports.nil = nil; +module.exports.luaD_precall = luaD_precall; +module.exports.luaD_poscall = luaD_poscall; +module.exports.moveresults = moveresults; +module.exports.adjust_varargs = adjust_varargs; +module.exports.tryfuncTM = tryfuncTM; +module.exports.stackerror = stackerror; +module.exports.luaD_call = luaD_call; +module.exports.luaD_callnoyield = luaD_callnoyield; +module.exports.luaD_pcall = luaD_pcall; +module.exports.luaD_rawrunprotected = luaD_rawrunprotected; +module.exports.luaD_protectedparser = luaD_protectedparser; \ No newline at end of file diff --git a/tests/lapi.js b/tests/lapi.js index fa1fb59..ff76920 100644 --- a/tests/lapi.js +++ b/tests/lapi.js @@ -1,17 +1,19 @@ /*jshint esversion: 6 */ "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 getState = require("./tests.js").getState; +const tests = require("./tests.js"); +const getState = tests.getState; +const toByteCode = tests.toByteCode; -const VM = require("../src/lvm.js"); -const ldo = require("../src/ldo.js"); -const lapi = require("../src/lapi.js"); -const lauxlib = require("../src/lauxlib.js"); -const lua = require('../src/lua.js'); -const CT = lua.constant_types; +const VM = require("../src/lvm.js"); +const ldo = require("../src/ldo.js"); +const lapi = require("../src/lapi.js"); +const lauxlib = require("../src/lauxlib.js"); +const lua = require('../src/lua.js'); +const CT = lua.constant_types; test('luaL_newstate, lua_pushnil, lua_gettop, luaL_typename', function (t) { let L; @@ -378,4 +380,32 @@ test('lua_pop', function (t) { "hello", "Correct element(s) on the stack" ); +}); + + +test('lua_load and lua_call it', function (t) { + let luaCode = ` + local a = "JS > Lua > JS \o/" + return a + `, L; + + t.plan(2); + + t.doesNotThrow(function () { + + let bc = toByteCode(luaCode).dataView; + + L = lauxlib.luaL_newstate(); + + lapi.lua_load(L, bc, "test-lua_load") + + lapi.lua_call(L, 0, 1); + + }, "JS Lua program ran without error"); + + t.strictEqual( + lapi.lua_tostring(L, -1), + "JS > Lua > JS \o/", + "Correct element(s) on the stack" + ); }); \ No newline at end of file diff --git a/tests/tests.js b/tests/tests.js index 5a1b023..a9f8730 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -42,6 +42,6 @@ const getState = function(luaCode) { return L; }; -module.exports = { - getState: getState -} \ No newline at end of file + +module.exports.getState = getState; +module.exports.toByteCode = toByteCode; \ No newline at end of file -- cgit v1.2.3-54-g00ecf