Lua: Make OptionsPage safer

If the calling script does not keep a reference to the OptionsPage
it will be garbage collected by Lua eventually. That can happen while
the SettingsDialog is open, which cannot cope with a page
being destroyed while its open.

For now we just keep the OptionsPage alive until the plugin is unloaded.

Change-Id: I8d0592731236482bbdc35078c24a5c6b962b1147
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2024-09-25 12:29:05 +02:00
parent 9796e218a8
commit 2d2d136952

View File

@@ -286,9 +286,23 @@ sol::usertype<T> addTypedAspect(sol::table &lua, const QString &name)
sol::bases<TypedAspect<typename T::valueType>, BaseAspect>()); sol::bases<TypedAspect<typename T::valueType>, BaseAspect>());
} }
class ObjectPool
{
public:
mutable std::vector<std::shared_ptr<Core::IOptionsPage>> optionsPages;
template<class T, class... _Args>
std::shared_ptr<T> makePage(_Args &&...__args) const
{
auto page = std::make_shared<T>(std::forward<_Args>(__args)...);
optionsPages.push_back(page);
return page;
}
};
void setupSettingsModule() void setupSettingsModule()
{ {
registerProvider("Settings", [](sol::state_view lua) -> sol::object { registerProvider("Settings", [pool = ObjectPool()](sol::state_view lua) -> sol::object {
const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec"); const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec");
sol::table settings = lua.create_table(); sol::table settings = lua.create_table();
@@ -607,8 +621,8 @@ void setupSettingsModule()
settings.new_usertype<OptionsPage>( settings.new_usertype<OptionsPage>(
"OptionsPage", "OptionsPage",
"create", "create",
[pluginSpec](const sol::table &options) { [&pool, pluginSpec](const sol::table &options) {
return std::make_unique<OptionsPage>(pluginSpec, options); return pool.makePage<OptionsPage>(pluginSpec, options);
}, },
"show", "show",
[](OptionsPage *page) { Core::ICore::showOptionsDialog(page->id()); }); [](OptionsPage *page) { Core::ICore::showOptionsDialog(page->id()); });
@@ -616,8 +630,8 @@ void setupSettingsModule()
settings.new_usertype<ExtensionOptionsPage>( settings.new_usertype<ExtensionOptionsPage>(
"ExtensionOptionsPage", "ExtensionOptionsPage",
"create", "create",
[pluginSpec](AspectContainer *container) { [pluginSpec, &pool](AspectContainer *container) {
return std::make_unique<ExtensionOptionsPage>(pluginSpec, container); return pool.makePage<ExtensionOptionsPage>(pluginSpec, container);
}, },
"show", "show",
[](ExtensionOptionsPage *page) { Core::ICore::showOptionsDialog(page->id()); }); [](ExtensionOptionsPage *page) { Core::ICore::showOptionsDialog(page->id()); });