summaryrefslogtreecommitdiff
path: root/static/source/embindmaker/embindmaker.cxx
diff options
context:
space:
mode:
authorStephan Bergmann <stephan.bergmann@allotropia.de>2024-01-30 18:09:50 +0100
committerStephan Bergmann <stephan.bergmann@allotropia.de>2024-01-30 22:38:14 +0100
commit1b371a4e1fac86fb483a7e62225e130d3684bb59 (patch)
treea5e34b5ea9c153662020a1a51245ce21043d473e /static/source/embindmaker/embindmaker.cxx
parent4a806d6b02fcfa795dd4c47932e98f9fbc1b8ca8 (diff)
embindmaker: Handle new-style services
Change-Id: I41309a20666c17f0c8c8d456943b3c78d0273905 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162772 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
Diffstat (limited to 'static/source/embindmaker/embindmaker.cxx')
-rw-r--r--static/source/embindmaker/embindmaker.cxx99
1 files changed, 79 insertions, 20 deletions
diff --git a/static/source/embindmaker/embindmaker.cxx b/static/source/embindmaker/embindmaker.cxx
index 2c707f9f118a..c7aba58c3089 100644
--- a/static/source/embindmaker/embindmaker.cxx
+++ b/static/source/embindmaker/embindmaker.cxx
@@ -118,11 +118,26 @@ std::pair<OUString, bool> parseRegistryArgument(sal_uInt32 argument)
struct Module
{
std::map<OUString, std::shared_ptr<Module>> modules;
- std::vector<OUString> interfaces;
+ std::vector<std::pair<OUString, OUString>> mappings;
};
+OUString
+getServiceConstructorName(unoidl::SingleInterfaceBasedServiceEntity::Constructor const& constructor)
+{
+ return constructor.defaultConstructor ? u"create"_ustr : constructor.name;
+}
+
+OUString jsName(OUString const& name) { return name.replace('.', '$'); }
+
+OUString
+jsServiceConstructor(OUString const& service,
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor const& constructor)
+{
+ return "uno_Function_" + jsName(service) + "$$" + getServiceConstructorName(constructor);
+}
+
void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view prefix,
- Module* module, std::vector<OUString>& interfaces)
+ Module* module, std::vector<OUString>& interfaces, std::vector<OUString>& services)
{
assert(cursor.is());
assert(module != nullptr);
@@ -145,13 +160,31 @@ void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view p
sub = std::make_shared<Module>();
}
scan(static_cast<unoidl::ModuleEntity*>(ent.get())->createCursor(),
- Concat2View(name + "."), sub.get(), interfaces);
+ Concat2View(name + "."), sub.get(), interfaces, services);
break;
}
case unoidl::Entity::SORT_INTERFACE_TYPE:
- module->interfaces.emplace_back(name);
+ module->mappings.emplace_back(id, "uno_Type_" + jsName(name));
interfaces.emplace_back(name);
break;
+ case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
+ {
+ auto const& ctors
+ = static_cast<unoidl::SingleInterfaceBasedServiceEntity*>(ent.get())
+ ->getConstructors();
+ if (!ctors.empty())
+ {
+ auto sub = std::make_shared<Module>();
+ for (auto const& ctor : ctors)
+ {
+ sub->mappings.emplace_back(getServiceConstructorName(ctor),
+ jsServiceConstructor(name, ctor));
+ }
+ module->modules[id] = sub;
+ services.emplace_back(name);
+ }
+ }
+ break;
default:
break;
}
@@ -160,8 +193,6 @@ void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view p
OUString cppName(OUString const& name) { return "::" + name.replaceAll(u".", u"::"); }
-OUString jsName(OUString const& name) { return name.replace('.', '$'); }
-
OUString resolveOuterTypedefs(rtl::Reference<TypeManager> const& manager, OUString const& name)
{
for (OUString n(name);;)
@@ -529,17 +560,32 @@ void dumpBase(std::ostream& out, rtl::Reference<TypeManager> const& manager,
dumpMethods(out, manager, interface, ent, baseTrail);
}
+void dumpRegisterFunctionProlog(std::ostream& out, unsigned long long& counter)
+{
+ out << "static void __attribute__((noinline)) register" << counter << "() {\n";
+}
+
+void dumpRegisterFunctionEpilog(std::ostream& out, unsigned long long& counter)
+{
+ out << "}\n";
+ ++counter;
+ if (counter == 0)
+ {
+ std::cerr << "Emitting too many register functions\n";
+ std::exit(EXIT_FAILURE);
+ }
+}
+
void writeJsMap(std::ostream& out, Module const& module, std::string const& prefix)
{
auto comma = false;
- for (auto const& ifc : module.interfaces)
+ for (auto const & [ id, to ] : module.mappings)
{
if (comma)
{
out << ",\n";
}
- out << prefix << "'" << ifc.copy(ifc.lastIndexOf('.') + 1) << "': instance.uno_Type_"
- << jsName(ifc);
+ out << prefix << "'" << id << "': instance." << to;
comma = true;
}
for (auto const & [ id, sub ] : module.modules)
@@ -589,9 +635,10 @@ SAL_IMPLEMENT_MAIN()
}
auto const module = std::make_shared<Module>();
std::vector<OUString> interfaces;
+ std::vector<OUString> services;
for (auto const& prov : mgr->getPrimaryProviders())
{
- scan(prov->createRootCursor(), u"", module.get(), interfaces);
+ scan(prov->createRootCursor(), u"", module.get(), interfaces, services);
}
std::ofstream cppOut(cppPathname, std::ios_base::out | std::ios_base::trunc);
if (!cppOut)
@@ -607,6 +654,10 @@ SAL_IMPLEMENT_MAIN()
{
cppOut << "#include <" << ifc.replace('.', '/') << ".hpp>\n";
}
+ for (auto const& srv : services)
+ {
+ cppOut << "#include <" << srv.replace('.', '/') << ".hpp>\n";
+ }
cppOut << "\n"
"// TODO: This is a temporary workaround that likely causes the Embind UNO\n"
"// bindings to leak memory. Reference counting and cloning mechanisms of\n"
@@ -625,10 +676,8 @@ SAL_IMPLEMENT_MAIN()
assert(ent.is());
assert(ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE);
rtl::Reference const ifcEnt(static_cast<unoidl::InterfaceTypeEntity*>(ent.get()));
- cppOut << "static void __attribute__((noinline)) register" << n
- << "() {\n"
- " ::emscripten::class_<"
- << cppName(ifc);
+ dumpRegisterFunctionProlog(cppOut, n);
+ cppOut << " ::emscripten::class_<" << cppName(ifc);
//TODO: Embind only supports single inheritance, so use that support at least for a UNO
// interface's first base, and explicitly spell out the attributes and methods of any
// remaining bases:
@@ -671,14 +720,24 @@ SAL_IMPLEMENT_MAIN()
}
dumpAttributes(cppOut, mgr, ifc, ifcEnt, {});
dumpMethods(cppOut, mgr, ifc, ifcEnt, {});
- cppOut << " ;\n"
- "}\n";
- ++n;
- if (n == 0)
+ cppOut << " ;\n";
+ dumpRegisterFunctionEpilog(cppOut, n);
+ }
+ for (auto const& srv : services)
+ {
+ auto const ent = mgr->getManager()->findEntity(srv);
+ assert(ent.is());
+ assert(ent->getSort() == unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE);
+ rtl::Reference const srvEnt(
+ static_cast<unoidl::SingleInterfaceBasedServiceEntity*>(ent.get()));
+ dumpRegisterFunctionProlog(cppOut, n);
+ for (auto const& ctor : srvEnt->getConstructors())
{
- std::cerr << "Emitting too many register functions\n";
- std::exit(EXIT_FAILURE);
+ cppOut << " ::emscripten::function(\"" << jsServiceConstructor(srv, ctor)
+ << "\", &" << cppName(srv) << "::" << getServiceConstructorName(ctor)
+ << ");\n";
}
+ dumpRegisterFunctionEpilog(cppOut, n);
}
cppOut << "EMSCRIPTEN_BINDINGS(unoembind_" << name << ") {\n";
for (unsigned long long i = 0; i != n; ++i)