diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llfloaterluadebug.cpp | 8 | ||||
-rw-r--r-- | indra/newview/llluamanager.cpp | 90 | ||||
-rw-r--r-- | indra/newview/tests/llluamanager_test.cpp | 35 |
3 files changed, 39 insertions, 94 deletions
diff --git a/indra/newview/llfloaterluadebug.cpp b/indra/newview/llfloaterluadebug.cpp index 2d9dc89340..b63600e0e6 100644 --- a/indra/newview/llfloaterluadebug.cpp +++ b/indra/newview/llfloaterluadebug.cpp @@ -58,7 +58,7 @@ BOOL LLFloaterLUADebug::postBuild() .listen("LLFloaterLUADebug", [mResultOutput=mResultOutput](const LLSD& data) { - mResultOutput->insertText(data.asString()); + mResultOutput->pasteTextWithLinebreaks(data.asString()); mResultOutput->addLineBreakChar(true); return false; }); @@ -125,13 +125,13 @@ void LLFloaterLUADebug::completion(int count, const LLSD& result) { // error: show error message mResultOutput->insertText("*** "); - mResultOutput->insertText(result.asString()); + mResultOutput->pasteTextWithLinebreaks(result.asString()); return; } if (count == 1) { // single result - mResultOutput->insertText(stringize(result)); + mResultOutput->pasteTextWithLinebreaks(stringize(result)); return; } // 0 or multiple results @@ -139,7 +139,7 @@ void LLFloaterLUADebug::completion(int count, const LLSD& result) for (const auto& item : llsd::inArray(result)) { mResultOutput->insertText(sep); - mResultOutput->insertText(stringize(item)); + mResultOutput->pasteTextWithLinebreaks(stringize(item)); sep = ", "; } } diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp index 4463fe65f5..0c39f6c8df 100644 --- a/indra/newview/llluamanager.cpp +++ b/indra/newview/llluamanager.cpp @@ -167,82 +167,34 @@ lua_function(post_on, "post_on(pumpname, data): post specified data to specified return 0; } -lua_function(listen_events, - "listen_events(callback): call callback(pumpname, data) with events received\n" - "on this Lua chunk's replypump.\n" - "Returns replypump, commandpump: names of LLEventPumps specific to this chunk.") +lua_function(get_event_pumps, + "get_event_pumps():\n" + "Returns replypump, commandpump: names of LLEventPumps specific to this chunk.\n" + "Events posted to replypump are queued for get_event_next().\n" + "post_on(commandpump, ...) to engage LLEventAPI operations (see helpleap()).") { - if (! lua_isfunction(L, 1)) - { - luaL_typeerror(L, 1, "function"); - return 0; - } luaL_checkstack(L, 2, nullptr); - -/*==========================================================================*| - // Get the lua_State* for the main thread of this state, in case we were - // called from a coroutine thread. We're going to make callbacks into Lua - // code, and we want to do it on the main thread rather than a (possibly - // suspended) coroutine thread. - // Registry table is at pseudo-index LUA_REGISTRYINDEX - // Main thread is at registry key LUA_RIDX_MAINTHREAD - auto regtype {lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD)}; - // Not finding the main thread at the documented place isn't a user error, - // it's a Problem - llassert_always(regtype == LUA_TTHREAD); - lua_State* mainthread{ lua_tothread(L, -1) }; - // pop the main thread - lua_pop(L, 1); -|*==========================================================================*/ - // Luau is based on Lua 5.1, and Lua 5.1 apparently provides no way to get - // back to the main thread from a coroutine thread? - lua_State* mainthread{ L }; - - luaL_checkstack(mainthread, 1, nullptr); - LuaListener::ptr_t listener; - // Does the main thread already have a LuaListener stored in the registry? - // That is, has this Lua chunk already called listen_events()? - auto keytype{ lua_getfield(mainthread, LUA_REGISTRYINDEX, "event.listener") }; - llassert(keytype == LUA_TNIL || keytype == LUA_TNUMBER); - if (keytype == LUA_TNUMBER) - { - // We do already have a LuaListener. Retrieve it. - int isint; - listener = LuaListener::getInstance(lua_tointegerx(mainthread, -1, &isint)); - // pop the int "event.listener" key - lua_pop(mainthread, 1); - // Nobody should have destroyed this LuaListener instance! - llassert(isint && listener); - } - else - { - // pop the nil "event.listener" key - lua_pop(mainthread, 1); - // instantiate a new LuaListener, binding the mainthread state -- but - // use a no-op deleter: we do NOT want to delete this new LuaListener - // on return from listen_events()! - listener.reset(new LuaListener(mainthread), [](LuaListener*){}); - // set its key in the field where we'll look for it later - lua_pushinteger(mainthread, listener->getKey()); - lua_setfield(mainthread, LUA_REGISTRYINDEX, "event.listener"); - } - - // Now that we've found or created our LuaListener, store the passed Lua - // function as the callback. Beware: our caller passed the function on L's - // stack, but we want to store it on the mainthread registry. - if (L != mainthread) - { - // push 1 value (the Lua function) from L's stack to mainthread's - lua_xmove(L, mainthread, 1); - } - lua_setfield(mainthread, LUA_REGISTRYINDEX, "event.function"); - + auto listener{ LuaState::obtainListener(L) }; // return the reply pump name and the command pump name on caller's lua_State lua_pushstdstring(L, listener->getReplyName()); lua_pushstdstring(L, listener->getCommandName()); return 2; } +lua_function(get_event_next, + "get_event_next():\n" + "Returns the next (pumpname, data) pair from the replypump whose name\n" + "is returned by get_event_pumps(). Blocks the calling chunk until an\n" + "event becomes available.") +{ + luaL_checkstack(L, 2, nullptr); + auto listener{ LuaState::obtainListener(L) }; + const auto& [pump, data]{ listener->getNext() }; + lua_pushstdstring(L, pump); + lua_pushllsd(L, data); + return 2; +} + lua_function(await_event, "await_event(pumpname [, timeout [, value to return if timeout (default nil)]]):\n" "pause the running Lua chunk until the next event on the named LLEventPump") @@ -370,7 +322,7 @@ void LLLUAmanager::runScriptLine(LuaState& L, const std::string& chunk, script_r if (shortchunk.length() > shortlen) shortchunk = stringize(shortchunk.substr(0, shortlen), "..."); - std::string desc{ stringize("runScriptLine('", shortchunk, "')") }; + std::string desc{ stringize("lua: ", shortchunk) }; LLCoros::instance().launch(desc, [&L, desc, chunk, cb]() { auto [count, result] = L.expr(desc, chunk); diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 1f25fd5f3b..81ec186cf4 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -108,7 +108,6 @@ namespace tut replypump.listen("llluamanager_test", listener([&fromlua](const LLSD& data){ fromlua = data; }))); const std::string lua(stringize( - "-- test LLSD synthesized by Lua\n", "data = ", construct, "\n" "post_on('testpump', data)\n" )); @@ -134,7 +133,7 @@ namespace tut template<> template<> void object::test<3>() { - set_test_name("test post_on(), listen_events(), await_event()"); + set_test_name("test post_on(), get_event_pumps(), get_event_next()"); StringVec posts; LLEventStream replypump("testpump"); LLTempBoundListener conn( @@ -142,17 +141,14 @@ namespace tut listener([&posts](const LLSD& data) { posts.push_back(data.asString()); }))); const std::string lua( - "-- test post_on,listen_events,await_event\n" + "-- test post_on,get_event_pumps,get_event_next\n" "post_on('testpump', 'entry')\n" - "callback = function(pump, data)\n" - " -- just echo the data we received\n" - " post_on('testpump', data)\n" - "end\n" - "post_on('testpump', 'listen_events()')\n" - "replypump, cmdpump = listen_events(callback)\n" + "post_on('testpump', 'get_event_pumps()')\n" + "replypump, cmdpump = get_event_pumps()\n" "post_on('testpump', replypump)\n" - "post_on('testpump', 'await_event()')\n" - "await_event(replypump)\n" + "post_on('testpump', 'get_event_next()')\n" + "pump, data = get_event_next()\n" + "post_on('testpump', data)\n" "post_on('testpump', 'exit')\n" ); LuaState L; @@ -162,9 +158,9 @@ namespace tut auto future = LLLUAmanager::startScriptLine(L, lua); StringVec expected{ "entry", - "listen_events()", + "get_event_pumps()", "", - "await_event()", + "get_event_next()", "message", "exit" }; @@ -188,18 +184,15 @@ namespace tut listener([&reply](const LLSD& post){ reply = post; }))); const std::string lua( "-- test LLSD round trip\n" - "callback = function(pump, data)\n" - " -- just echo the data we received\n" - " post_on('testpump', data)\n" - "end\n" - "replypump, cmdpump = listen_events(callback)\n" + "replypump, cmdpump = get_event_pumps()\n" "post_on('testpump', replypump)\n" - "await_event(replypump)\n" + "pump, data = get_event_next()\n" + "return data\n" ); LuaState L; auto future = LLLUAmanager::startScriptLine(L, lua); // We woke up again ourselves because the coroutine running Lua has - // reached the await_event() call, which suspends the calling C++ + // reached the get_event_next() call, which suspends the calling C++ // coroutine (including the Lua code running on it) until we post // something to that reply pump. auto luapump{ reply.asString() }; @@ -208,7 +201,7 @@ namespace tut // The C++ coroutine running the Lua script is now ready to run. Run // it so it will echo the LLSD back to us. auto [count, result] = future.get(); - ensure_equals(desc, reply, expect); + ensure_equals(desc, result, expect); } // Define an RTItem to be used for round-trip LLSD testing: what it is, |