include/static/unoembindhelpers/PrimaryBindings.hxx |   36 +++++++++++++++++
 static/source/embindmaker/embindmaker.cxx           |   42 ++++++++++++++++++++
 2 files changed, 78 insertions(+)

New commits:
commit 8869994d5e62c422465f52b25dc3792be9add92d
Author:     Stephan Bergmann <stephan.bergm...@allotropia.de>
AuthorDate: Wed Jan 31 17:31:49 2024 +0100
Commit:     Stephan Bergmann <stephan.bergm...@allotropia.de>
CommitDate: Thu Feb 1 08:46:47 2024 +0100

    embindmaker: Add support for sequence types
    
    Ideally, JS code would have a way to create instances of arbitrary UNO 
sequence
    types (to e.g. put them into Anys), but that goes against the static nature 
of
    Embind.  So at least register JS support for all those UNO sequence types 
that
    are actually used in the UNO API.  (This would cause duplicate failures, 
though,
    if we generated multiple separate .cxx files from embindmaker invocations, 
with
    registration code for the same UNO sequence types.)
    
    (Even more ideally, UNO sequence types could map to JS arrays, and/oror be
    garbage-collected on the JS side rather than needing explicit delete().  The
    resize/size/get/set interface in unoembindhelpers::registerSequence is 
modelled
    after Embind's emscripten::register_vector.)
    
    Change-Id: Icd38b2e03db442dd613b9222b9bd092f947f7bec
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162849
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de>

diff --git a/include/static/unoembindhelpers/PrimaryBindings.hxx 
b/include/static/unoembindhelpers/PrimaryBindings.hxx
index 5b677345b86b..6f8005b1656c 100644
--- a/include/static/unoembindhelpers/PrimaryBindings.hxx
+++ b/include/static/unoembindhelpers/PrimaryBindings.hxx
@@ -11,9 +11,12 @@
 
 #include <sal/config.h>
 
+#include <stdexcept>
+
 #include <emscripten/bind.h>
 
 #include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
 #include <sal/types.h>
 
 template <typename T> struct 
emscripten::smart_ptr_trait<css::uno::Reference<T>>
@@ -48,6 +51,39 @@ template <typename T> struct UnoInOutParam
 
     T value;
 };
+
+template <typename T>
+void checkSequenceAccess(css::uno::Sequence<T> const& sequence, sal_Int32 
index)
+{
+    if (index < 0 || index >= sequence.getLength())
+    {
+        throw std::out_of_range("index out of bounds");
+    }
+}
+
+template <typename T> void registerSequence(char const* name)
+{
+    emscripten::class_<css::uno::Sequence<T>>(name)
+        .template constructor<sal_Int32>()
+        .function("resize",
+                  +[](css::uno::Sequence<T>& self, sal_Int32 size) {
+                      if (size < 0)
+                      {
+                          throw std::invalid_argument("negative size");
+                      }
+                      self.realloc(size);
+                  })
+        .function("size", &css::uno::Sequence<T>::getLength)
+        .function("get",
+                  +[](css::uno::Sequence<T> const& self, sal_Int32 index) {
+                      checkSequenceAccess(self, index);
+                      return self[index];
+                  })
+        .function("set", +[](css::uno::Sequence<T>& self, sal_Int32 index, T 
const& value) {
+            checkSequenceAccess(self, index);
+            self.getArray()[index] = value;
+        });
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/static/source/embindmaker/embindmaker.cxx 
b/static/source/embindmaker/embindmaker.cxx
index 43d315679d6c..fb6ba0880508 100644
--- a/static/source/embindmaker/embindmaker.cxx
+++ b/static/source/embindmaker/embindmaker.cxx
@@ -725,6 +725,16 @@ void dumpRegisterFunctionEpilog(std::ostream& out, 
unsigned long long& counter)
     }
 }
 
+void recordSequenceTypes(rtl::Reference<TypeManager> const& manager, OUString 
const& type,
+                         std::set<OUString>& sequences)
+{
+    auto const res = resolveAllTypedefs(manager, type);
+    if (manager->getSort(res) == codemaker::UnoType::Sort::Sequence)
+    {
+        sequences.insert(res);
+    }
+}
+
 void writeJsMap(std::ostream& out, Module const& module, std::string const& 
prefix)
 {
     auto comma = false;
@@ -852,6 +862,7 @@ SAL_IMPLEMENT_MAIN()
             cppOut << ";
";
             dumpRegisterFunctionEpilog(cppOut, n);
         }
+        std::set<OUString> sequences;
         for (auto const& str : structs)
         {
             auto const ent = mgr->getManager()->findEntity(str);
@@ -878,6 +889,10 @@ SAL_IMPLEMENT_MAIN()
             }
             cppOut << ";
";
             dumpRegisterFunctionEpilog(cppOut, n);
+            for (auto const& mem : strEnt->getDirectMembers())
+            {
+                recordSequenceTypes(mgr, mem.type, sequences);
+            }
         }
         for (auto const& ifc : interfaces)
         {
@@ -931,6 +946,18 @@ SAL_IMPLEMENT_MAIN()
             dumpMethods(cppOut, mgr, ifc, ifcEnt, {});
             cppOut << "        ;
";
             dumpRegisterFunctionEpilog(cppOut, n);
+            for (auto const& attr : ifcEnt->getDirectAttributes())
+            {
+                recordSequenceTypes(mgr, attr.type, sequences);
+            }
+            for (auto const& meth : ifcEnt->getDirectMethods())
+            {
+                for (auto const& param : meth.parameters)
+                {
+                    recordSequenceTypes(mgr, param.type, sequences);
+                }
+                recordSequenceTypes(mgr, meth.returnType, sequences);
+            }
         }
         for (auto const& srv : services)
         {
@@ -960,6 +987,21 @@ SAL_IMPLEMENT_MAIN()
         {
             cppOut << "    register" << i << "();
";
         }
+        for (auto const& seq : sequences)
+        {
+            cppOut << "    ::unoembindhelpers::registerSequence<";
+            assert(seq.startsWith("[]"));
+            dumpType(cppOut, mgr, seq.copy(2));
+            cppOut << ">(\"uno_Sequence";
+            sal_Int32 k;
+            auto const nuc = b2u(codemaker::UnoType::decompose(u2b(seq), &k));
+            assert(k >= 1);
+            if (k > 1)
+            {
+                cppOut << k;
+            }
+            cppOut << "_" << jsName(nuc) << "\");
";
+        }
         cppOut << "}
";
         cppOut.close();
         if (!cppOut)

Reply via email to