desktop/Executable_soffice_bin.mk                  |    2 
 solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk     |    3 -
 static/README.wasm.md                              |    4 -
 static/emscripten/registeroustring.js              |   56 +++++++++++++++++++++
 static/source/unoembindhelpers/PrimaryBindings.cxx |   14 +++--
 5 files changed, 69 insertions(+), 10 deletions(-)

New commits:
commit 453049b93e82bed84ac08eea35930b8881a26672
Author:     Stephan Bergmann <stephan.bergm...@allotropia.de>
AuthorDate: Sat Feb 3 16:01:28 2024 +0100
Commit:     Stephan Bergmann <stephan.bergm...@allotropia.de>
CommitDate: Sat Feb 3 23:44:14 2024 +0100

    First-class Embind JS support for OUString
    
    Change-Id: Ic178737da802e17f87d0b5b09004a847b0fe91be
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162956
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de>

diff --git a/desktop/Executable_soffice_bin.mk 
b/desktop/Executable_soffice_bin.mk
index 40042651a4e9..086abbae4df0 100644
--- a/desktop/Executable_soffice_bin.mk
+++ b/desktop/Executable_soffice_bin.mk
@@ -55,7 +55,7 @@ $(call gb_LinkTarget_get_headers_target,$(call 
gb_Executable_get_linktarget,soff
 $(call gb_LinkTarget__static_lib_dummy_depend,unoembind)
 
 $(eval $(call gb_Executable_add_ldflags,soffice_bin,\
-       -s 
EXPORTED_FUNCTIONS=["_main"$(COMMA)"_libreofficekit_hook"$(COMMA)"_libreofficekit_hook_2"$(COMMA)"_lok_preinit"$(COMMA)"_lok_preinit_2"]
 -Wl$(COMMA)--whole-archive $(call gb_StaticLibrary_get_target,unoembind) 
-Wl$(COMMA)--no-whole-archive \
+       -s 
EXPORTED_FUNCTIONS=["_main"$(COMMA)"_libreofficekit_hook"$(COMMA)"_libreofficekit_hook_2"$(COMMA)"_lok_preinit"$(COMMA)"_lok_preinit_2"$(COMMA)"_malloc"$(COMMA)"_free"]
 -Wl$(COMMA)--whole-archive $(call gb_StaticLibrary_get_target,unoembind) 
-Wl$(COMMA)--no-whole-archive \
 ))
 ifeq ($(ENABLE_QT6),TRUE)
 $(eval $(call gb_Executable_add_ldflags,soffice_bin, \
diff --git a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk 
b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
index a363ac7abe37..f3bb7d7c6c27 100644
--- a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
+++ b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
@@ -14,6 +14,7 @@ include $(GBUILDDIR)/platform/unxgcc.mk
 # don't sort; later can override previous settings!
 gb_EMSCRIPTEN_PRE_JS_FILES = \
     $(SRCDIR)/static/emscripten/environment.js \
+    $(SRCDIR)/static/emscripten/registeroustring.js \
     $(call 
gb_CustomTarget_get_workdir,static/emscripten_fs_image)/soffice.data.js.link \
 
 gb_RUN_CONFIGURE := $(SRCDIR)/solenv/bin/run-configure
@@ -27,7 +28,7 @@ gb_EMSCRIPTEN_LDFLAGS += -s TOTAL_MEMORY=1GB -s 
PTHREAD_POOL_SIZE=4
 # To keep the link time (and memory) down, prevent all rewriting options from 
wasm-emscripten-finalize
 # See emscripten.py, finalize_wasm, modify_wasm = True
 # So we need WASM_BIGINT=1 and ASSERTIONS=1 (2 implies STACK_OVERFLOW_CHECK)
-gb_EMSCRIPTEN_LDFLAGS += --bind -s FORCE_FILESYSTEM=1 -s WASM_BIGINT=1 -s 
ERROR_ON_UNDEFINED_SYMBOLS=1 -s FETCH=1 -s ASSERTIONS=1 -s EXIT_RUNTIME=0 -s 
EXPORTED_RUNTIME_METHODS=["UTF16ToString","stringToUTF16","UTF8ToString","allocateUTF8","printErr","ccall","cwrap"$(if
 $(ENABLE_QT6),$(COMMA)"callMain"$(COMMA)"specialHTMLTargets")]
+gb_EMSCRIPTEN_LDFLAGS += --bind -s FORCE_FILESYSTEM=1 -s WASM_BIGINT=1 -s 
ERROR_ON_UNDEFINED_SYMBOLS=1 -s FETCH=1 -s ASSERTIONS=1 -s EXIT_RUNTIME=0 -s 
EXPORTED_RUNTIME_METHODS=["UTF16ToString","stringToUTF16","UTF8ToString","allocateUTF8","printErr","ccall","cwrap","addOnPreMain","registerType","throwBindingError"$(if
 $(ENABLE_QT6),$(COMMA)"callMain"$(COMMA)"specialHTMLTargets")]
 gb_EMSCRIPTEN_QTDEFS := -DQT_NO_LINKED_LIST -DQT_NO_JAVA_STYLE_ITERATORS 
-DQT_NO_EXCEPTIONS -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
 
 gb_Executable_EXT := .html
diff --git a/static/README.wasm.md b/static/README.wasm.md
index 89c2ac681f4c..44e9b223c5cf 100644
--- a/static/README.wasm.md
+++ b/static/README.wasm.md
@@ -231,7 +231,7 @@ xText = xTextDocument.getText();
 xSimpleText = new css.text.XSimpleText(xText.$query());
 xTextCursor = xSimpleText.createTextCursor();
 xTextRange = new css.text.XTextRange(xTextCursor.$query());
-xTextRange.setString(new Module.OUString("string here!"));
+xTextRange.setString("string here!");
 xSimpleText.delete(); xTextCursor.delete(); xTextRange.delete();
 xModel.delete(); xTextDocument.delete(); xText.delete(); xSimpleText.delete(); 
xTextCursor.delete(); xTextRange.delete();
 ```
@@ -249,7 +249,7 @@ while (xParaEnumeration.hasMoreElements()) {
     xParagraph = new css.text.XTextRange(xParaEnumeration.nextElement(), 
Module.uno_Reference.FromAny);
     if (xParagraph.$is()) {
         xParaProps = new css.beans.XPropertySet(xParagraph.$query());
-        xParaProps.setPropertyValue(new Module.OUString("CharColor"), new 
Module.Any(Math.floor(Math.random() * 0xFFFFFF), css.uno.TypeClass.LONG));
+        xParaProps.setPropertyValue("CharColor", new 
Module.Any(Math.floor(Math.random() * 0xFFFFFF), css.uno.TypeClass.LONG));
     }
 }
 ```
diff --git a/static/emscripten/registeroustring.js 
b/static/emscripten/registeroustring.js
new file mode 100644
index 000000000000..0abd522ca98e
--- /dev/null
+++ b/static/emscripten/registeroustring.js
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+if (!('preRun' in Module)) Module['preRun'] = [];
+Module.preRun.push(function() {
+    // Wait until Embind is set up:
+    Module.addOnPreMain(function() {
+        Module.registerType(Module.getOUStringRawType(), {
+            name: 'rtl::OUString',
+            'fromWireType'(ptr) {
+                let data = Module.HEAPU32[ptr >> 2];
+                let length = Module.HEAPU32[(data >> 2) + 1];
+                let buffer = data + 8;
+                let str = '';
+                for (let i = 0; i < length; ++i) {
+                    let c = Module.HEAPU16[(buffer >> 1) + i];
+                    str += String.fromCharCode(c);
+                }
+                Module.rtl_uString_release(data);
+                Module._free(ptr);
+                return str;
+            },
+            'toWireType'(destructors, value) {
+                if (typeof value != 'string') {
+                    Module.throwBindingError('Cannot pass non-string to C++ 
OUString');
+                }
+                let data = Module._malloc(8 + (value.length + 1) * 2);
+                Module.HEAPU32[data >> 2] = 1;
+                Module.HEAPU32[(data >> 2) + 1] = value.length;
+                let buffer = data + 8;
+                for (let i = 0; i < value.length; ++i) {
+                    Module.HEAPU16[(buffer >> 1) + i] = value.charCodeAt(i);
+                }
+                Module.HEAPU16[(buffer >> 1) + value.length] = 0;
+                let ptr = Module._malloc(4);
+                Module.HEAPU32[ptr >> 2] = data;
+                if (destructors !== null) {
+                    destructors.push(Module._free, ptr);
+                }
+                return ptr;
+            },
+            'argPackAdvance': 8,
+            'readValueFromPointer'(pointer) {
+                return this['fromWireType'](Module.HEAPU32[((pointer)>>2)]);
+            },
+            destructorFunction(ptr) {
+                Module._free(ptr);
+            },
+        });
+    });
+});
diff --git a/static/source/unoembindhelpers/PrimaryBindings.cxx 
b/static/source/unoembindhelpers/PrimaryBindings.cxx
index 91e6fba92f4c..fe3b6e29908f 100644
--- a/static/source/unoembindhelpers/PrimaryBindings.cxx
+++ b/static/source/unoembindhelpers/PrimaryBindings.cxx
@@ -16,6 +16,9 @@
 #include <sfx2/viewsh.hxx>
 #include <static/unoembindhelpers/PrimaryBindings.hxx>
 
+#include <cstdint>
+#include <typeinfo>
+
 using namespace emscripten;
 using namespace css::uno;
 
@@ -27,6 +30,8 @@ template <typename T> void registerInOutParam(char const* 
name)
         "val", &unoembindhelpers::UnoInOutParam<T>::get, 
&unoembindhelpers::UnoInOutParam<T>::set);
 }
 
+std::uintptr_t getOUStringRawType() { return 
reinterpret_cast<std::uintptr_t>(&typeid(OUString)); }
+
 Reference<css::frame::XModel> getCurrentModelFromViewSh()
 {
     SfxViewShell* pSh = nullptr;
@@ -45,12 +50,6 @@ EMSCRIPTEN_BINDINGS(PrimaryBindings)
     enum_<unoembindhelpers::uno_Reference>("uno_Reference")
         .value("FromAny", unoembindhelpers::uno_Reference::FromAny);
 
-    class_<OUString>("OUString")
-        .constructor(+[](const std::u16string& rString) -> OUString { return 
OUString(rString); })
-        .function("toString", +[](const OUString& rSelf) -> std::u16string {
-            return std::u16string(rSelf.getStr(), rSelf.getLength());
-        });
-
     // Any
     class_<Any>("Any").constructor(+[](const val& rObject, const TypeClass& 
rUnoType) -> Any {
         switch (rUnoType)
@@ -112,7 +111,10 @@ EMSCRIPTEN_BINDINGS(PrimaryBindings)
     registerInOutParam<char16_t>("uno_InOutParam_char");
 
     function("getCurrentModelFromViewSh", &getCurrentModelFromViewSh);
+    function("getOUStringRawType", &getOUStringRawType);
     function("getUnoComponentContext", 
&comphelper::getProcessComponentContext);
+    function("rtl_uString_release",
+             +[](std::uintptr_t ptr) { 
rtl_uString_release(reinterpret_cast<rtl_uString*>(ptr)); });
 }
 #endif
 

Reply via email to