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