* @brief Returns true if the code defines a callable mqtt() global. */
| 537 | * @brief Returns true if the code defines a callable mqtt() global. |
| 538 | */ |
| 539 | bool MQTT::PublisherScriptEditor::definesMqttFunction(const QString& code, int language) |
| 540 | { |
| 541 | if (code.trimmed().isEmpty()) |
| 542 | return false; |
| 543 | |
| 544 | if (language == SerialStudio::Lua) { |
| 545 | lua_State* L = luaL_newstate(); |
| 546 | if (!L) |
| 547 | return false; |
| 548 | |
| 549 | static const luaL_Reg kSafeLibs[] = { |
| 550 | { "_G", luaopen_base}, |
| 551 | { "table", luaopen_table}, |
| 552 | {"string", luaopen_string}, |
| 553 | { "math", luaopen_math}, |
| 554 | { nullptr, nullptr} |
| 555 | }; |
| 556 | |
| 557 | for (const luaL_Reg* lib = kSafeLibs; lib->func; ++lib) { |
| 558 | luaL_requiref(L, lib->name, lib->func, 1); |
| 559 | lua_pop(L, 1); |
| 560 | } |
| 561 | |
| 562 | DataModel::installLuaCompat(L); |
| 563 | |
| 564 | const QByteArray utf8 = code.toUtf8(); |
| 565 | if (luaL_dostring(L, utf8.constData()) != LUA_OK) { |
| 566 | lua_close(L); |
| 567 | return false; |
| 568 | } |
| 569 | |
| 570 | lua_getglobal(L, "mqtt"); |
| 571 | const bool hasFn = lua_isfunction(L, -1); |
| 572 | lua_close(L); |
| 573 | return hasFn; |
| 574 | } |
| 575 | |
| 576 | QJSEngine jsEngine; |
| 577 | jsEngine.installExtensions(QJSEngine::ConsoleExtension | QJSEngine::GarbageCollectionExtension); |
| 578 | const auto evalResult = jsEngine.evaluate(code); |
| 579 | if (evalResult.isError()) |
| 580 | return false; |
| 581 | |
| 582 | const auto fn = jsEngine.globalObject().property(QStringLiteral("mqtt")); |
| 583 | return fn.isCallable(); |
| 584 | } |
| 585 | |
| 586 | /** |
| 587 | * @brief Returns the template index matching the editor text, or -1. |
nothing calls this directly
no test coverage detected