summaryrefslogtreecommitdiff
path: root/indra
AgeCommit message (Collapse)Author
2024-06-20Use new popup.lua, which supersedes LLNotification.lua.Nat Goodspeed
Use ClassName(ctor args) for classes using util.classctor().
2024-06-20Merge branch 'release/luau-scripting' into lua-loginNat Goodspeed
2024-06-20Revert LLLuaFloater "idle" events in favor of Lua timers.Timer().nat-goodspeed
2024-06-20Merge branch 'release/luau-scripting' into lua-speedometer-demoNat Goodspeed
2024-06-20Give popup() the ability to not wait; add popup:tip(message).Nat Goodspeed
popup:tip() engages 'SystemMessageTip'.
2024-06-19Move popup.lua to require subdir with the rest of the modules.Nat Goodspeed
2024-06-19Improve LL.help() function.Nat Goodspeed
The help string for each lua_function() must restate the function name and its arguments. The help string is all that's shown; unless it restates the function name, LL.help() output lists terse explanations for functions whose names are not shown. Make help() prepend "LL." to help output, because these functions must be accessed via the "builtin" LL table instead of directly populating the global Lua namespace. Similarly, before string name lookup, remove "LL." prefix if specified.
2024-06-19Try harder to keep Luau's lua_getinfo() from crashing.Nat Goodspeed
2024-06-18Merge branch 'lua-login' of github.com:secondlife/viewer into lua-loginNat Goodspeed
2024-06-18Initialize lua_Debug lluau::source_path() passes to lua_getinfo().Nat Goodspeed
On Mac it doesn't seem to matter, but on Windows, leaving it uninitialized can produce garbage results and even crash the coroutine. This seems strange, since we've been assuming lua_getinfo() treats its lua_Debug* as output-only.
2024-06-18Use LL_DEBUGS("Lua") for LuaLog.Nat Goodspeed
We might decide to leave some of them in place.
2024-06-18Improve diagnostic output from running 'require' module.Nat Goodspeed
2024-06-18Make ~LuaState() walk Registry.atexit table backwardsNat Goodspeed
so cleanup happens in reverse order, as is conventional. Streamline LL.atexit() function: luaL_newmetatable() performs all the find-or-create named Registry table logic.
2024-06-18lua_emplace<T>() should permit GC despite LL.atexit() safety net.Nat Goodspeed
lua_emplace<T>() was passing LL.atexit() a closure binding the new userdata with a cleanup function. The trouble with that was that a strong reference to the new userdata would prevent it ever being garbage collected, even if that was the only remaining reference. Instead, create a new weak table referencing the userdata, and bind that into the cleanup function's closure. Then if the only remaining reference to the userdata is from the weak table, the userdata can be collected. Make lua_emplace_call_gc<T>() check the bound weak table in case the userdata has in fact been collected. Also, in lua_toclass<T>(), use luaL_checkudata() to synopsize comparing the putative userdata's metatable against the one synthesized by lua_emplace<T>(). This saves several explicit steps.
2024-06-18Make lluau::source_path() report top-level script path.Nat Goodspeed
source_path() previously reported the path of the module containing the current (lowest-level) Lua function. The effect was that the Floater.lua module would always try to look up the XUI file relative to scripts/lua/require. It makes more intuitive sense to make source_path() return the path containing the top-level script, so that a script engaging the Floater.lua module looks for the XUI file relative to the script.
2024-06-17Store script's LuaListener in userdata in lua_State's Registry.Nat Goodspeed
Instead of deriving LuaListener from LLInstanceTracker with an int key, generating a unique int key and storing that key in the Registry, use new lua_emplace<LuaState>() to store the LuaListener directly in a Lua userdata object in the Lua Registry. Because lua_emplace<T>() uses LL.atexit() to guarantee that ~LuaState will destroy the T object, we no longer need ~LuaState() to make a special call specifically to destroy the LuaListener, if any. So we no longer need LuaState::getListener() separate from obtainListener(). Since LuaListener is no longer an LLInstanceTracker subclass, make LuaState::obtainListener() return LuaListener& rather than LuaListener::ptr_t.
2024-06-14Introduce LL.atexit(), internal lua_emplace<T>(), lua_toclass<T>().Nat Goodspeed
Publish new LL.atexit() function that accepts a Lua function (or C++ closure) and saves it (in Registry["atexit"] table) to call later. Make ~LuaState() walk the Registry["atexit"] table, if it exists, calling each function appended to that table. (Consider using that mechanism to clean up a LuaListener, if one was instantiated. Possibly also use for p.s. leap.run()? But that's run after every expr() call, instead of only at ~LuaState() time. Pragmatically, though, the distinction only matters for a LUA Debug Console LUA string with "clean lua_State" unchecked.) For use by future lua_function() entry points, lua_emplace<T>(ctor args...) pushes a Lua userdata object containing a newly-constructed T instance -- actually a std::optional<T> to avoid double destruction. lua_emplace<T>() is specifically intended to be usable even for T with a nontrivial destructor: it gives the userdata a metatable with a __gc function that destroys the contained T instance when the userdata is garbage collected. But since garbage collection doesn't guarantee to clean up global variables with __gc methods, lua_emplace<T>() also uses LL.atexit() to ensure that ~T() will run when the LuaState is destroyed. The companion to lua_emplace<T>() is lua_toclass<T>(), which returns a non-nullptr T* if the referenced index is in fact a userdata created by lua_emplace<T>() for the same T, that has not yet been destroyed. This lets C++ code access a T previously embedded in Lua userdata.
2024-06-14Move Lua modules for 'require' to indra/newview/scripts/lua/require.Nat Goodspeed
Make viewer_manifest.py copy them into the viewer install image. Make the require() function look for them there.
2024-06-12Avoid messing up Lua's global namespace in 'require' modules.Nat Goodspeed
2024-06-12Add LL_DEBUGS("LLCoros") start/end messages.Nat Goodspeed
We have log messages when a coroutine terminates abnormally, but we don't report either when it starts or when it terminates normally. Address that.
2024-06-12Provide LUA Debug Console feedback for user typing LUA string.Nat Goodspeed
When the user explicitly types 'return expression[, expression]...' we convert the result of the expressions to LLSD and format them into the LUA Debug Console, which serves as a useful acknowledgment. But until now, if the user neither invoked print() nor ran a 'return' statement, the LUA Debug Console output remained empty. This could be a little disconcerting: you click Execute, or press Enter, and apparently nothing happens. You must either monitor viewer log output, or simply trust that the Lua snippet ran. When there are no 'return' results, at least emit 'ok'. But when the user is entering a series of no-output commands, vary the 'ok' output by appending a counter: 'ok 1', 'ok 2' etc.
2024-06-12Defend LLFloaterLUADebug against recursive calls to handlers.Nat Goodspeed
The special case of a Lua snippet that indirectly invokes the "LLNotifications" listener can result in a recursive call to LLFloaterLUADebug's handler methods. Defend against that case.
2024-06-12LuaState::expr() has log messages for ending, add for starting.Nat Goodspeed
It's helpful to see when expr() is actually going to start running a particular Lua chunk. We already report not only when it's done, but also if/when we start and finish a p.s. fiber.run() call.
2024-06-12For a single string concatenation, use operator+().Nat Goodspeed
stringize() constructs, populates and destroys a std::ostringstream, which is actually less efficient than directly allocating a std::string big enough for the result of operator+(). Maybe someday we'll specialize stringize(p0, p1) for the case in which they're both string-like, and invoke operator+() for that situation...
2024-06-12Make popup() directly pass payload.Nat Goodspeed
The expression (payload or {}) is unnecessary, since that value will be converted to LLSD -- and both Lua nil and empty table convert to LLSD::isUndefined().
2024-06-12Extract TempSet from llcallbacklist.cpp into its own tempset.h.Nat Goodspeed
2024-06-12Merge 'release/luau-scripting' of secondlife/viewer into lua-loginNat Goodspeed
2024-06-11Add popup.lua, a preliminary API for viewer notifications.Nat Goodspeed
WIP: This is known not to work yet.
2024-06-11Add login.lua module with login() function.Nat Goodspeed
The nullary login() call (login with saved credentials) has been tested, but the binary login(username, password) call is known not to work yet.
2024-06-11Add to UI.lua a set of 'LLWindow' listener operations.Nat Goodspeed
Add listviews(), viewinfo(), click(), doubleclick(), drag(), keypress() and type(). WIP: These are ported from Python LEAP equivalents, but the Lua implementation has only been partially tested.
2024-06-11Fix a couple bugs in startup.lua.Nat Goodspeed
The 'startup' table, the module's namespace, must be defined near the top because its local waitfor:process() override references startup. The byname table's metatable's __index() function wants to raise an error if you try to access an undefined entry, but it referenced t[k] to check that, producing infinite recursion. Use rawget(t, k) instead. Also use new leap.WaitFor(args) syntax instead of leap.WaitFor:new(args).
2024-06-11Allow Python-like 'object = ClassName(ctor args)' constructor calls.Nat Goodspeed
The discussions we've read about Lua classes conventionally use ClassName:new() as the constructor, and so far we've followed that convention. But setting metaclass(ClassName).__call = ClassName.new permits Lua to respond to calls of the form ClassName(ctor args) by implicitly calling ClassName:new(ctor args). Introduce util.classctor(). Calling util.classctor(ClassName) sets ClassName's metaclass's __call to ClassName's constructor method. If the constructor method is named something other than new(), pass ClassName.method as the second arg. Use util.classctor() on each of our classes that defines a new() method. Replace ClassName:new(args) calls with ClassName(args) calls throughout.
2024-06-11mapargs() now accepts 'name1,name2,...' as argument namesNat Goodspeed
in addition to a list {'name1', 'name2', ...}.
2024-06-11Update "LLWindow" listener doc to cite github URL, not bitbucket.Nat Goodspeed
2024-06-11Merge branch 'release/luau-scripting' into lua-bradfixNat Goodspeed
2024-06-11clean up LLUIListener::callMaxim Nikolenko
2024-06-11Merge branch 'main' of github.com:secondlife/viewer into lua-bradfixNat Goodspeed
to pick up Featurettes promotion + Brad's GitHub Windows build workaround.
2024-06-11Merge branch 'release/luau-scripting' into lua-loginNat Goodspeed
2024-06-10Merge branch 'main' into brad/materials_featurette_build_workaroundNat Goodspeed
2024-06-10Increment viewer version to 7.1.9Nat Goodspeed
following promotion of secondlife/viewer #648: Release/materials featurette
2024-06-10Merge release/materials_featurette to main on promotion of secondlife/viewer ↵Nat Goodspeed
#648: Release/materials featurette
2024-06-10Attempted workaround for actions/runner-images#10004 build failures.Brad Linden
2024-06-10Merge branch 'release/luau-scripting' into lua-loginNat Goodspeed
2024-06-10Merge branch 'release/luau-scripting' into lua-ui-callbacksMnikolenko Productengine
2024-06-10another batch of changes to use ScopedRegistrarHelperMnikolenko Productengine
2024-06-10Remove SharedCommitCallbackRegistry; add helpers CommitRegistrarHelper and ↵Mnikolenko Productengine
ScopedRegistrarHelper
2024-06-07Introduce mapargs.lua, which defines the mapargs() function.Nat Goodspeed
There are two conventions for Lua function calls. You can call a function with positional arguments as usual: f(1, 2, 3) Lua makes it easy to handle omitted positional arguments: their values are nil. But as in C++, positional arguments get harder to read when there are many, or when you want to omit arguments other than the last ones. Alternatively, using Lua syntactic sugar, you can pass a single argument which is a table containing the desired function arguments. For this you can use table constructor syntax to effect keyword arguments: f{a=1, b=2, c=3} A call passing keyword arguments is more readable because you explicitly associate the parameter name with each argument value. Moreover, it gracefully handles the case of multiple optional arguments. The reader need not be concerned about parameters *not* being passed. Now you're coding a Lua module with a number of functions. Some have numerous or complicated arguments; some do not. For simplicity, you code the simple functions to accept positional arguments, the more complicated functions to accept the single-table argument style. But how the bleep is a consumer of your module supposed to remember which calling style to use for a given function? mapargs() blurs the distinction, accepting either style. Coding a function like this (where '...' is literal code, not documentation ellipsis): function f(...) local args = mapargs({'a', 'b', 'c'}, ...) -- now use args.a, args.b, args.c end supports calls like: f(1, 2, 3) f{1, 2, 3} f{c=3, a=1, b=2} f{1, 2, c=3} f{c=3, 1, 2} -- unlike Python! In every call above, args.a == 1, args.b == 2, args.c == 3. Moreover, omitting arguments (or explicitly passing nil, positionally or by keyword) works correctly. test_mapargs.lua exercises these cases.
2024-06-07Fix another merge glitchNat Goodspeed
2024-06-07Tidy up merge from main.Nat Goodspeed
2024-06-07Merge branch 'main' of secondlife/viewer into release/luau-scriptingNat Goodspeed