summaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
authorStephan Bergmann <stephan.bergmann@allotropia.de>2024-04-12 08:57:44 +0200
committerStephan Bergmann <stephan.bergmann@allotropia.de>2024-04-12 20:52:54 +0200
commit3454a73a11722c45016c9b5aa0d95402fc1196f0 (patch)
tree02c9e59260fa617118651218920765c74f452530 /static
parentea462462db187d87d978cb659df8ca81309fd2e7 (diff)
Embind: support .implement()-based JS UNO objects
Change-Id: I3a8bf5986b91b886547cfe57e49275f7c79ddc11 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166020 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
Diffstat (limited to 'static')
-rw-r--r--static/source/embindmaker/embindmaker.cxx160
1 files changed, 151 insertions, 9 deletions
diff --git a/static/source/embindmaker/embindmaker.cxx b/static/source/embindmaker/embindmaker.cxx
index 4241d10b1575..07214c289681 100644
--- a/static/source/embindmaker/embindmaker.cxx
+++ b/static/source/embindmaker/embindmaker.cxx
@@ -501,7 +501,7 @@ void dumpAttributes(std::ostream& out, rtl::Reference<TypeManager> const& manage
}
out << "->get" << attr.name << "(); }";
}
- out << ")\n";
+ out << ", ::emscripten::pure_virtual())\n";
if (!attr.readOnly)
{
out << " .function(\"set" << attr.name << "\", ";
@@ -530,7 +530,7 @@ void dumpAttributes(std::ostream& out, rtl::Reference<TypeManager> const& manage
}
out << "->set" << attr.name << "(the_value); }";
}
- out << ")\n";
+ out << ", ::emscripten::pure_virtual())\n";
}
}
}
@@ -660,7 +660,7 @@ void dumpWrapper(std::ostream& out, rtl::Reference<TypeManager> const& manager,
{
out << ", ::emscripten::allow_raw_pointers()";
}
- out << ")\n";
+ out << ", ::emscripten::pure_virtual())\n";
}
void dumpMethods(std::ostream& out, rtl::Reference<TypeManager> const& manager,
@@ -676,18 +676,18 @@ void dumpMethods(std::ostream& out, rtl::Reference<TypeManager> const& manager,
else
{
out << " .function(\"" << meth.name << "\", &" << cppName(name)
- << "::" << meth.name << ")\n";
+ << "::" << meth.name << ", ::emscripten::pure_virtual())\n";
}
}
}
-rtl::Reference<unoidl::InterfaceTypeEntity> resolveBase(rtl::Reference<TypeManager> const& manager,
- OUString const& name)
+rtl::Reference<unoidl::InterfaceTypeEntity>
+resolveInterface(rtl::Reference<TypeManager> const& manager, OUString const& name)
{
auto const ent = manager->getManager()->findEntity(name);
if (!ent.is() || ent->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
{
- throw CannotDumpException("bad interface base \"" + name + "\"");
+ throw CannotDumpException("bad interface \"" + name + "\"");
}
return static_cast<unoidl::InterfaceTypeEntity*>(ent.get());
}
@@ -695,7 +695,7 @@ rtl::Reference<unoidl::InterfaceTypeEntity> resolveBase(rtl::Reference<TypeManag
void recordVisitedBases(rtl::Reference<TypeManager> const& manager, OUString const& name,
std::set<OUString>& visitedBases)
{
- auto const ent = resolveBase(manager, name);
+ auto const ent = resolveInterface(manager, name);
for (auto const& base : ent->getDirectMandatoryBases())
{
if (visitedBases.insert(base.name).second)
@@ -709,7 +709,7 @@ void dumpBase(std::ostream& out, rtl::Reference<TypeManager> const& manager,
OUString const& interface, OUString const& name, std::set<OUString>& visitedBases,
std::list<OUString> const& baseTrail)
{
- auto const ent = resolveBase(manager, name);
+ auto const ent = resolveInterface(manager, name);
for (auto const& base : ent->getDirectMandatoryBases())
{
if (visitedBases.insert(base.name).second)
@@ -723,6 +723,126 @@ void dumpBase(std::ostream& out, rtl::Reference<TypeManager> const& manager,
dumpMethods(out, manager, interface, ent, baseTrail);
}
+void dumpWrapperClassMembers(std::ostream& out, rtl::Reference<TypeManager> const& manager,
+ OUString const& interface, OUString const& name,
+ std::set<OUString>& visitedBases)
+{
+ auto const ent = resolveInterface(manager, name);
+ for (auto const& base : ent->getDirectMandatoryBases())
+ {
+ if (visitedBases.insert(base.name).second)
+ {
+ dumpWrapperClassMembers(out, manager, interface, base.name, visitedBases);
+ }
+ }
+ for (auto const& attr : ent->getDirectAttributes())
+ {
+ out << " ";
+ dumpType(out, manager, attr.type);
+ out << " get" << attr.name << "() override { return call<";
+ dumpType(out, manager, attr.type);
+ out << ">(\"get" << attr.name << "\"); }\n";
+ if (!attr.readOnly)
+ {
+ out << " void set" << attr.name << "(";
+ dumpType(out, manager, attr.type);
+ switch (manager->getSort(resolveOuterTypedefs(manager, attr.type)))
+ {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Enum:
+ break;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ out << " const &";
+ break;
+ default:
+ throw CannotDumpException("unexpected entity \"" + attr.type
+ + "\" as attribute type");
+ }
+ out << " the_value) override { return call<void>(\"set" << attr.name
+ << "\", the_value); }\n";
+ }
+ }
+ for (auto const& meth : ent->getDirectMethods())
+ {
+ out << " ";
+ dumpType(out, manager, meth.returnType);
+ out << " " << meth.name << "(";
+ bool first = true;
+ for (auto const& param : meth.parameters)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ out << ", ";
+ }
+ dumpType(out, manager, param.type);
+ if (param.direction == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
+ {
+ switch (manager->getSort(resolveOuterTypedefs(manager, param.type)))
+ {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Enum:
+ break;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ out << " const &";
+ break;
+ default:
+ throw CannotDumpException("unexpected entity \"" + param.type
+ + "\" as parameter type");
+ }
+ }
+ else
+ {
+ out << " &";
+ }
+ out << " " << param.name;
+ }
+ out << ") override { return call<";
+ dumpType(out, manager, meth.returnType);
+ out << ">(\"" << meth.name << "\"";
+ for (auto const& param : meth.parameters)
+ {
+ out << ", " << param.name;
+ }
+ out << "); }\n";
+ }
+}
+
void dumpRegisterFunctionProlog(std::ostream& out, unsigned long long& counter)
{
out << "static void __attribute__((noinline)) register" << counter << "() {\n";
@@ -926,6 +1046,21 @@ SAL_IMPLEMENT_MAIN()
assert(ent.is());
assert(ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE);
rtl::Reference const ifcEnt(static_cast<unoidl::InterfaceTypeEntity*>(ent.get()));
+ {
+ auto i = ifc.lastIndexOf('.');
+ auto j = i + 1;
+ if (i == -1)
+ {
+ i = 0;
+ }
+ cppOut << "namespace the_wrappers" << cppName(ifc.copy(0, i)) << " {\n"
+ << "struct " << ifc.copy(j) << " final: public ::emscripten::wrapper<"
+ << cppName(ifc) << "> {\n"
+ << " EMSCRIPTEN_WRAPPER(" << ifc.copy(j) << ");\n";
+ std::set<OUString> visitedBases;
+ dumpWrapperClassMembers(cppOut, mgr, ifc, ifc, visitedBases);
+ cppOut << "};\n}\n";
+ }
dumpRegisterFunctionProlog(cppOut, n);
cppOut << " ::emscripten::class_<" << cppName(ifc);
//TODO: Embind only supports single inheritance, so use that support at least for a UNO
@@ -938,9 +1073,16 @@ SAL_IMPLEMENT_MAIN()
}
cppOut << ">(\"uno_Type_" << jsName(ifc)
<< "\")\n"
+ " .allow_subclass<the_wrappers"
+ << cppName(ifc) << ">(\"uno_Wrapper_" << jsName(ifc)
+ << "\")\n"
" .smart_ptr<::com::sun::star::uno::Reference<"
<< cppName(ifc) << ">>(\"uno_Reference_" << jsName(ifc)
<< "\")\n"
+ " .class_function(\"reference\", +[]("
+ << cppName(ifc)
+ << " * the_interface) { return ::com::sun::star::uno::Reference(the_interface); "
+ "}, ::emscripten::allow_raw_pointers())\n"
" "
".constructor(+[](::com::sun::star::uno::Reference<::com::sun::star::uno::"
"XInterface> const & the_object) { return ::com::sun::star::uno::Reference<"