summaryrefslogtreecommitdiff
path: root/src/lbaselib.js
diff options
context:
space:
mode:
authorBenoit Giannangeli <benoit.giannangeli@boursorama.fr>2017-02-21 15:24:37 +0100
committerBenoit Giannangeli <benoit.giannangeli@boursorama.fr>2017-02-21 15:24:37 +0100
commit653f4a07af6506e0b8ef71e8957976b9559f67e4 (patch)
tree7bf59628c6e68bb33fa278d24f9e07f0104995ad /src/lbaselib.js
parent82ef443de9a3ba53b4a5b9abd161ddc164776a59 (diff)
downloadfengari-653f4a07af6506e0b8ef71e8957976b9559f67e4.tar.gz
fengari-653f4a07af6506e0b8ef71e8957976b9559f67e4.tar.bz2
fengari-653f4a07af6506e0b8ef71e8957976b9559f67e4.zip
pcall, xpcall
Diffstat (limited to 'src/lbaselib.js')
-rw-r--r--src/lbaselib.js44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/lbaselib.js b/src/lbaselib.js
index 205d57a..ac0ac4c 100644
--- a/src/lbaselib.js
+++ b/src/lbaselib.js
@@ -7,6 +7,7 @@ const lua = require('./lua.js');
const lapi = require('./lapi.js');
const lauxlib = require('./lauxlib.js');
const CT = lua.constant_types;
+const TS = lua.thread_status;
const luaB_print = function(L) {
let n = lapi.lua_gettop(L); /* number of arguments */
@@ -99,6 +100,45 @@ const luaB_error = function(L) {
return lapi.lua_error(L);
};
+/*
+** Continuation function for 'pcall' and 'xpcall'. Both functions
+** already pushed a 'true' before doing the call, so in case of success
+** 'finishpcall' only has to return everything in the stack minus
+** 'extra' values (where 'extra' is exactly the number of items to be
+** ignored).
+*/
+const finishpcall = function(L, status, extra) {
+ if (status !== TS.LUA_OK && status !== TS.LUA_YIELD) { /* error? */
+ lapi.lua_pushboolean(L, 0); /* first result (false) */
+ lapi.lua_pushvalue(L, -2); /* error message */
+ return 2; /* return false, msg */
+ } else
+ return lapi.lua_gettop(L) - extra;
+};
+
+const luaB_pcall = function(L) {
+ lauxlib.luaL_checkany(L, 1);
+ lapi.lua_pushboolean(L, 1); /* first result if no errors */
+ lapi.lua_insert(L, 1); /* put it in place */
+ let status = lapi.lua_pcallk(L, lapi.lua_gettop(L) - 2, lua.LUA_MULTRET, 0, 0, finishpcall);
+ return finishpcall(L, status, 0);
+};
+
+/*
+** Do a protected call with error handling. After 'lua_rotate', the
+** stack will have <f, err, true, f, [args...]>; so, the function passes
+** 2 to 'finishpcall' to skip the 2 first values when returning results.
+*/
+const luaB_xpcall = function(L) {
+ let n = lapi.lua_gettop(L);
+ lauxlib.luaL_checktype(L, 2, CT.LUA_TFUNCTION);
+ lapi.lua_pushboolean(L, 1);
+ lapi.lua_pushvalue(L, 1);
+ lapi.lua_rotate(L, 3, 2);
+ let status = lapi.lua_pcallk(L, n - 2, lua.LUA_MULTRET, 2, 2, finishpcall);
+ return finishpcall(L, status, 2);
+};
+
const base_funcs = {
"collectgarbage": function () {},
"print": luaB_print,
@@ -109,7 +149,9 @@ const base_funcs = {
"rawset": luaB_rawset,
"rawget": luaB_rawget,
"type": luaB_type,
- "error": luaB_error
+ "error": luaB_error,
+ "pcall": luaB_pcall,
+ "xpcall": luaB_xpcall,
};
const luaopen_base = function(L) {