A generic, sandboxed Luau host: VM lifecycle,
luaL_sandbox, a CPU-time watchdog, a per-engine heap cap, bytecode compile/load, and aQVariant↔Lua marshalling layer, with no knowledge of tiling or any other domain.
Phosphor runs user-authored scripts (tiling algorithms today, other shell surfaces later). This library owns the embedding of Luau so each domain binding can stay small. A binding marshals its params into QVariant, calls a script, and reads the result back. It deliberately knows nothing about what the scripts compute.
LuauEngine.** Owns one lua_State. Lifecycle: construct → init (open restricted stdlib, wire the interrupt callback, install the capped allocator) → runPrelude (zero or more, to install host globals such as a domain standard library) → sandbox (freeze globals + stdlib) → loadModule (per script) → callModule / moduleField. The public surface is entirely QVariant-based, and lua_State is forward-declared and never leaks across the shared-library boundary.LuauWatchdog.** A shared supervisor thread that bounds CPU time: it only ever flips a co-owned atomic flag the engine's interrupt callback reads, and never touches the lua_State, so a late fire during teardown is safe. One watchdog can be shared across many engines.lua_Alloc tracks live/peak bytes and fails any allocation that would cross the cap, turning a runaway script into a catchable Luau out-of-memory error rather than a host crash. Default 64 MiB, configurable per engine. Enforcement is armed only around the lua_pcall of sandboxed script execution, so trusted init/preludes and host-side QVariant marshalling (which touch the VM outside any protected call) can never be spuriously OOM-killed into an uncatchable abort.| Type | Purpose |
|---|---|
PhosphorScripting::LuauEngine | The sandboxed VM, with a QVariant-only API (init / runPrelude / sandbox / loadModule / releaseModule / moduleField / hasFunction / callModule) |
PhosphorScripting::LuauWatchdog | Shared CPU-deadline supervisor that aborts runaway scripts via the interrupt callback |
#include <PhosphorScripting/LuauEngine.h>
#include <PhosphorScripting/LuauWatchdog.h>
using namespace PhosphorScripting;
auto watchdog = std::make_shared<LuauWatchdog>();
LuauEngine engine(watchdog); // default 64 MiB heap cap
engine.init();
engine.runPrelude(QStringLiteral("pluau"), preludeSource); // install host globals
engine.sandbox(); // freeze globals + stdlib
QString err;
const int mod = engine.loadModule(QStringLiteral("script"), source, &err);
const auto out = engine.callModule(mod, QStringLiteral("tile"), {ctx}, 100 /*ms*/);
if (out.status == LuauEngine::CallStatus::Ok) {
// out.result is a QVariant marshalled from the script's return value.
}Luau is vendored as a committed source tarball (extern/luau-<ver>.tar.gz, pinned to 0.723), extracted at configure time via file(ARCHIVE_EXTRACT) and built as part of this library, so source tarballs and offline distro builds are self-contained with no network. Pass -DPLASMAZONES_SYSTEM_LUAU=ON to link a system-provided Luau instead. The Luau libraries are linked PRIVATE and the VM is built PIC, with -fexceptions force-enabled and unity builds disabled on the vendored targets only (Luau needs C++ unwinding for lua_pcall, and its file-local symbol names collide under unity batching). This is independent of the project's global build settings.
lua_State is private.** Public headers forward-declare it and expose only QVariant. The Luau libraries are a PRIVATE link dependency, so no Luau symbols cross the .so boundary. Domain bindings marshal their own params.QtCore, Threadsextern/luau-*.tar.gz), or a system Luau via -DPLASMAZONES_SYSTEM_LUAU=ONLuauTileAlgorithm + the pluau tiling standard library.