* @brief Compiles per-dataset Lua transforms into a shared lua_State, caching refs for O(1) hotpath * lookup. */
| 2014 | * lookup. |
| 2015 | */ |
| 2016 | void DataModel::FrameBuilder::compileTransformsLua(TransformEngine& engine, |
| 2017 | int sourceId, |
| 2018 | const std::vector<TransformEntry>& entries) |
| 2019 | { |
| 2020 | lua_State* L = luaL_newstate(); |
| 2021 | Q_ASSERT(L != nullptr); |
| 2022 | if (!L) [[unlikely]] |
| 2023 | return; |
| 2024 | |
| 2025 | lua_atpanic(L, [](lua_State* state) -> int { |
| 2026 | const char* msg = lua_tostring(state, -1); |
| 2027 | qWarning() << "[FrameBuilder] Lua transform panic:" << (msg ? msg : "<unknown>"); |
| 2028 | throw std::runtime_error(msg ? msg : "lua transform panic"); |
| 2029 | }); |
| 2030 | |
| 2031 | openSafeLibsForTransform(L); |
| 2032 | |
| 2033 | DataModel::installLuaConsole(L); |
| 2034 | |
| 2035 | DataModel::installLuaCompat(L); |
| 2036 | |
| 2037 | injectTableApiLua(L); |
| 2038 | |
| 2039 | DataModel::DeviceWriteApi::installLua(L, sourceId); |
| 2040 | |
| 2041 | DataModel::ActionFireApi::installLua(L); |
| 2042 | |
| 2043 | DataModel::DashboardApi::installLua(L); |
| 2044 | |
| 2045 | DataModel::ScriptApiCall::installLua(L, sourceId); |
| 2046 | |
| 2047 | DataModel::NotificationCenter::installScriptApi(L); |
| 2048 | |
| 2049 | lua_pushlightuserdata(L, &engine); |
| 2050 | lua_setfield(L, LUA_REGISTRYINDEX, "__ss_transform__"); |
| 2051 | |
| 2052 | lua_sethook(L, &FrameBuilder::transformLuaWatchdogHook, LUA_MASKCOUNT, kTransformHookInstrCount); |
| 2053 | |
| 2054 | engine.luaDeadline.setRemainingTime(kTransformWatchdogMs); |
| 2055 | |
| 2056 | for (const auto& entry : entries) |
| 2057 | compileTransformsLuaEntry(L, engine, entry); |
| 2058 | |
| 2059 | engine.luaDeadline = QDeadlineTimer(QDeadlineTimer::Forever); |
| 2060 | engine.luaState = L; |
| 2061 | } |
| 2062 | |
| 2063 | /** |
| 2064 | * @brief Compiles a single Lua dataset transform; logs and skips on any error. |
nothing calls this directly
no test coverage detected