Last active
April 21, 2022 02:04
-
-
Save NotMyWing/a66f8b1c2ae47b38424ff543c31d4239 to your computer and use it in GitHub Desktop.
Leveret Lua Evaluation Commons
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const commons = { | |
initialize: function (ctx) { | |
const newCtx = {}; | |
// Create a shallow copy of the provided context. | |
for(var key in ctx) { | |
newCtx[key] = ctx[key]; | |
} | |
// Since fengari-web is primarily a browser library, | |
// we need to shim browser-specific things. Temporarily, at least. | |
newCtx.window = { | |
dispatchEvent: () => { } | |
} | |
// Fetch and evaluate Fengari. | |
const fengariSrc = http.request("https://github.com/fengari-lua/fengari-web/releases/download/v0.1.4/fengari-web.js").data | |
new Function("window = this.window;" + fengariSrc).call({ window: newCtx }); | |
this.fengari = newCtx.fengari; | |
}, | |
createLuaContext: function () { | |
if (!this.fengari) this.initialize(); | |
const L = this.fengari.lauxlib.luaL_newstate(); | |
this.fengari.lualib.luaL_openlibs(L); | |
this.fengari.interop.luaopen_js(L); | |
this.fengari.lua.lua_setglobal(L, "js"); | |
return L; | |
}, | |
replacePrintFunction: function (L, callback) { | |
if (!this.fengari) this.initialize(); | |
const buffer = []; | |
const lua = this.fengari.lua; | |
// Printer function. | |
// Taken directly from the Fengari source. | |
let print = (L) => { | |
let n = lua.lua_gettop(L); | |
lua.lua_getglobal(L, this.fengari.to_luastring("tostring", true)); | |
let linebuf = []; | |
for (let i = 1; i <= n; i++) { | |
lua.lua_pushvalue(L, -1); | |
lua.lua_pushvalue(L, i); | |
lua.lua_call(L, 1, 1); | |
let s = lua.lua_tolstring(L, -1); | |
if (s === null) | |
return this.fengari.lauxlib.luaL_error(L, | |
this.fengari.to_luastring("'tostring' must return a string to 'print'")); | |
if (i > 1) linebuf.push("\t"); | |
linebuf.push(this.fengari.to_jsstring(s)); | |
lua.lua_pop(L, 1); | |
} | |
callback(linebuf.join("")); | |
return 0; | |
}; | |
// Finally, replace "print" within the context. | |
lua.lua_pushjsfunction(L, print); | |
lua.lua_setglobal(L, "print"); | |
return buffer | |
}, | |
parseInput: function (input) { | |
let code, args; | |
// Parse code block if exists. | |
let parsed = input.match(/^(.*?)`{3}([\S]+)?\n([\s\S]+)`{3}$/mi); | |
if (parsed) { | |
// Args precede the code block. | |
args = parsed[1].trim(); | |
code = parsed[3]; | |
} // Otherwise treat the entire input as code. | |
else code = input; | |
return { code, args } | |
}, | |
runLua: function (L, code) { | |
if (!this.fengari) this.initialize(); | |
const lua = this.fengari.lua; | |
const result = this.fengari.lauxlib | |
.luaL_loadstring(L, this.fengari.to_luastring(code)); | |
if (result === 0) { | |
if (lua.lua_gettop(L) > 0) { | |
const type = lua.lua_type(L, -1); | |
if (type == lua.LUA_TFUNCTION) { | |
lua.lua_call(L, 0, 1); | |
} | |
} | |
} | |
}, | |
getStackTrace: function (L) { | |
const lua = this.fengari.lua; | |
const buf = []; | |
const top = lua.lua_gettop(L); | |
const bottom = 1; | |
lua.lua_getglobal(L, "tostring"); | |
for (let i = top; i >= bottom; i--) { | |
lua.lua_pushvalue(L, -1); | |
lua.lua_pushvalue(L, i); | |
lua.lua_pcall(L, 1, 1, 0); | |
const str = this.fengari.interop.tojs(L, -1); | |
if (str) { | |
buf.push(str); | |
} else { | |
buf.push(this.fengari.lauxlib.luaL_typename(L, i)); | |
} | |
lua.lua_pop(L, 1); | |
} | |
lua.lua_pop(L, 1); | |
return buf; | |
} | |
} | |
return commons; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment