summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llluamanager.cpp93
-rw-r--r--indra/newview/llluamanager.h30
2 files changed, 103 insertions, 20 deletions
diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp
index 596d8cab56..44c7a6ba3b 100644
--- a/indra/newview/llluamanager.cpp
+++ b/indra/newview/llluamanager.cpp
@@ -28,6 +28,7 @@
#include "llviewerprecompiledheaders.h"
#include "llluamanager.h"
+#include "llcoros.h"
#include "llerror.h"
#include "lleventcoro.h"
#include "lua_function.h"
@@ -55,6 +56,14 @@ extern LLUIListener sUIListener;
#include <string_view>
#include <vector>
+lua_function(sleep)
+{
+ F32 seconds = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ llcoro::suspendUntilTimeout(seconds);
+ return 0;
+};
+
/*
// This function consumes ALL Lua stack arguments and returns concatenated
// message string
@@ -262,21 +271,34 @@ lua_function(await_event)
void LLLUAmanager::runScriptFile(const std::string& filename, script_finished_fn cb)
{
- std::string desc{ stringize("runScriptFile('", filename, "')") };
- LLCoros::instance().launch(desc, [desc, filename, cb]()
- {
- LuaState L(desc, cb);
+ // A script_finished_fn is used to initialize the LuaState.
+ // It will be called when the LuaState is destroyed.
+ LuaState L(cb);
+ runScriptFile(L, filename);
+}
- auto LUA_sleep_func = [](lua_State *L)
- {
- F32 seconds = lua_tonumber(L, -1);
- lua_pop(L, 1);
- llcoro::suspendUntilTimeout(seconds);
- return 0;
- };
+void LLLUAmanager::runScriptFile(const std::string& filename, script_result_fn cb)
+{
+ LuaState L;
+ // A script_result_fn will be called when LuaState::expr() completes.
+ runScriptFile(L, filename, cb);
+}
- lua_register(L, "sleep", LUA_sleep_func);
+std::pair<int, LLSD> LLLUAmanager::waitScriptFile(LuaState& L, const std::string& filename)
+{
+ LLCoros::Promise<std::pair<int, LLSD>> promise;
+ auto future{ LLCoros::getFuture(promise) };
+ runScriptFile(L, filename,
+ [&promise](int count, LLSD result)
+ { promise.set_value({ count, result }); });
+ return future.get();
+}
+void LLLUAmanager::runScriptFile(LuaState& L, const std::string& filename, script_result_fn cb)
+{
+ std::string desc{ stringize("runScriptFile('", filename, "')") };
+ LLCoros::instance().launch(desc, [&L, desc, filename, cb]()
+ {
llifstream in_file;
in_file.open(filename.c_str());
@@ -284,17 +306,51 @@ void LLLUAmanager::runScriptFile(const std::string& filename, script_finished_fn
{
std::string text{std::istreambuf_iterator<char>(in_file),
std::istreambuf_iterator<char>()};
- L.checkLua(lluau::dostring(L, desc, text));
+ auto [count, result] = L.expr(desc, text);
+ if (cb)
+ {
+ cb(count, result);
+ }
}
else
{
- LL_WARNS("Lua") << "unable to open script file '" << filename << "'" << LL_ENDL;
+ auto msg{ stringize("unable to open script file '", filename, "'") };
+ LL_WARNS("Lua") << msg << LL_ENDL;
+ if (cb)
+ {
+ cb(-1, msg);
+ }
}
});
}
void LLLUAmanager::runScriptLine(const std::string& cmd, script_finished_fn cb)
{
+ // A script_finished_fn is used to initialize the LuaState.
+ // It will be called when the LuaState is destroyed.
+ LuaState L(cb);
+ runScriptLine(L, cmd);
+}
+
+void LLLUAmanager::runScriptLine(const std::string& cmd, script_result_fn cb)
+{
+ LuaState L;
+ // A script_result_fn will be called when LuaState::expr() completes.
+ runScriptLine(L, cmd, cb);
+}
+
+std::pair<int, LLSD> LLLUAmanager::waitScriptLine(LuaState& L, const std::string& cmd)
+{
+ LLCoros::Promise<std::pair<int, LLSD>> promise;
+ auto future{ LLCoros::getFuture(promise) };
+ runScriptLine(L, cmd,
+ [&promise](int count, LLSD result)
+ { promise.set_value({ count, result }); });
+ return future.get();
+}
+
+void LLLUAmanager::runScriptLine(LuaState& L, const std::string& cmd, script_result_fn cb)
+{
// find a suitable abbreviation for the cmd string
std::string_view shortcmd{ cmd };
const size_t shortlen = 40;
@@ -305,10 +361,13 @@ void LLLUAmanager::runScriptLine(const std::string& cmd, script_finished_fn cb)
shortcmd = stringize(shortcmd.substr(0, shortlen), "...");
std::string desc{ stringize("runScriptLine('", shortcmd, "')") };
- LLCoros::instance().launch(desc, [desc, cmd, cb]()
+ LLCoros::instance().launch(desc, [&L, desc, cmd, cb]()
{
- LuaState L(desc, cb);
- L.checkLua(lluau::dostring(L, desc, cmd));
+ auto [count, result] = L.expr(desc, cmd);
+ if (cb)
+ {
+ cb(count, result);
+ }
});
}
diff --git a/indra/newview/llluamanager.h b/indra/newview/llluamanager.h
index 08d9876ce2..bed12e358a 100644
--- a/indra/newview/llluamanager.h
+++ b/indra/newview/llluamanager.h
@@ -27,19 +27,43 @@
#ifndef LL_LLLUAMANAGER_H
#define LL_LLLUAMANAGER_H
+#include "llsd.h"
#include <functional>
#include <string>
+#include <utility> // std::pair
+
+class LuaState;
class LLLUAmanager
{
public:
+ // Pass a callback with this signature to obtain the error message, if
+ // any, from running a script or source string. Empty msg means success.
typedef std::function<void(std::string msg)> script_finished_fn;
+ // Pass a callback with this signature to obtain the result, if any, of
+ // running a script or source string.
+ // count < 0 means error, and result.asString() is the error message.
+ // count == 0 with result.isUndefined() means the script returned no results.
+ // count == 1 means the script returned one result.
+ // count > 1 with result.isArray() means the script returned multiple
+ // results, represented as the entries of the result array.
+ typedef std::function<void(int count, const LLSD& result)> script_result_fn;
+
+ static void runScriptFile(const std::string &filename, script_finished_fn cb = {});
+ static void runScriptFile(const std::string &filename, script_result_fn cb);
+ static void runScriptFile(LuaState& L, const std::string &filename, script_result_fn cb = {});
+ // Run a Lua script file, and pause the calling coroutine until it completes.
+ // The return value is the (count, result) pair described above.
+ static std::pair<int, LLSD> waitScriptFile(LuaState& L, const std::string& filename);
- static void runScriptFile(const std::string &filename, script_finished_fn cb = script_finished_fn());
- static void runScriptLine(const std::string &cmd, script_finished_fn cb = script_finished_fn());
+ static void runScriptLine(const std::string &cmd, script_finished_fn cb = {});
+ static void runScriptLine(const std::string &cmd, script_result_fn cb);
+ static void runScriptLine(LuaState& L, const std::string &cmd, script_result_fn cb = {});
+ // Run a Lua expression string, and pause the calling coroutine until it completes.
+ // The return value is the (count, result) pair described above.
+ static std::pair<int, LLSD> waitScriptLine(LuaState& L, const std::string& cmd);
static void runScriptOnLogin();
};
-
#endif