Closed asynts closed 3 years ago
Huh - It certainly works with LibWeb's OOPWV:
Also Spreadsheet's ConditionsView
.
Extending your example like this works:
#include <LibGUI/Widget.h>
#include <LibWeb/InProcessWebView.h>
int main(int argc, char** argv)
{
// Constructing a `GUI::Application` is technically not required but not doing so makes `Web::InProcessWebView`'s constructor crash.
auto app = GUI::Application::construct(argc, argv);
GUI::WidgetClassRegistration::for_each([](const auto& registration) {
dbgln("{}", registration.class_name());
});
Web::InProcessWebView::construct();
}
Including LibWeb/InProcessWebView.h
alone is not enough, but once InProcessWebView
is constructed (anywhere), it also appears in the list of registered widgets.
Why? No clue.
"Deferred dynamic initialization" goes on my list with the worst C++ anti-features:
If no variable or function is odr-used from a given translation unit, the non-local variables defined in that translation unit may never be initialized (this models the behavior of an on-demand dynamic library).
https://en.cppreference.com/w/cpp/language/initialization#Deferred_dynamic_initialization
Basically, if you don't touch a translation unit, static variables might never be created.
Not sure how to fix it though.
I spend some time thinking about this and this isn't really an issue, it's just a bit unintuitive. In my opinion it is acceptable if a registration is missing provided that the class isn't being used. This should allow the compiler to not link the library at all unless it is actually used.
The following snippet should register
Web::InProcessWebView
inGUI::WidgetClassRegistration
, but doesn't:https://github.com/SerenityOS/serenity/blob/54ade31d84c8078fd0113dd9b0d188c04a4dea0c/Libraries/LibWeb/InProcessWebView.cpp#L62
The following example application prints out all registered classes,
Web::InProcessWebView
is missing from that list, even ifLibWeb
was linked.Here is a list that is produced by that application:
Note that
GUI::TabWidget
is present in that list even though it is defined in a different compilation unit than sayGUI::Button
:https://github.com/SerenityOS/serenity/blob/54ade31d84c8078fd0113dd9b0d188c04a4dea0c/Libraries/LibGUI/Widget.cpp#L60
https://github.com/SerenityOS/serenity/blob/54ade31d84c8078fd0113dd9b0d188c04a4dea0c/Libraries/LibGUI/TabWidget.cpp#L38
At first I though this is an "static initialization fiasco", but this does not appear to be the case because it worked for
GUI::TabWidget
and the helper function seems well defined.My second thought was that maybe we have two
widget_classes
functions defined because that function was markedstatic
, but moving it into the header didn't change a thing.https://github.com/SerenityOS/serenity/blob/54ade31d84c8078fd0113dd9b0d188c04a4dea0c/Libraries/LibGUI/Widget.cpp#L78-L84
I don't understand this. Any ideas?
Here is a reproducible example: asynts@05af80fc036739f303be8ff0aa99efec5ff72457