diff options
-rw-r--r-- | Repository.mk | 2 | ||||
-rw-r--r-- | bridges/CustomTarget_gcc3_wasm.mk | 26 | ||||
-rw-r--r-- | bridges/Library_cpp_uno.mk | 6 | ||||
-rw-r--r-- | bridges/Module_bridges.mk | 1 | ||||
-rw-r--r-- | bridges/inc/wasm/callvirtualfunction.hxx | 21 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx | 226 | ||||
-rw-r--r-- | offapi/UnoApi_offapi.mk | 2 | ||||
-rw-r--r-- | offapi/org/libreoffice/embindtest/StructLong.idl | 18 | ||||
-rw-r--r-- | offapi/org/libreoffice/embindtest/StructString.idl | 18 | ||||
-rw-r--r-- | offapi/org/libreoffice/embindtest/XTest.idl | 4 | ||||
-rw-r--r-- | solenv/gbuild/extensions/pre_BuildTools.mk | 2 | ||||
-rw-r--r-- | static/Executable_wasmcallgen.mk | 26 | ||||
-rw-r--r-- | static/Module_static.mk | 1 | ||||
-rw-r--r-- | static/source/wasmcallgen/wasmcallgen.cxx | 610 | ||||
-rw-r--r-- | unotest/source/embindtest/embindtest.cxx | 23 | ||||
-rw-r--r-- | unotest/source/embindtest/embindtest.js | 330 |
16 files changed, 1313 insertions, 3 deletions
diff --git a/Repository.mk b/Repository.mk index e910b6d572b7..b6ebf64dcf39 100644 --- a/Repository.mk +++ b/Repository.mk @@ -33,7 +33,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \ concat-deps \ cpp \ cppunittester \ - $(if $(or $(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),$(filter EMSCRIPTEN,$(OS))),embindmaker) \ + $(if $(or $(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),$(filter EMSCRIPTEN,$(OS))),embindmaker wasmcallgen) \ gbuildtojson \ $(if $(filter MSC,$(COM)), \ gcc-wrapper \ diff --git a/bridges/CustomTarget_gcc3_wasm.mk b/bridges/CustomTarget_gcc3_wasm.mk new file mode 100644 index 000000000000..a88da8577282 --- /dev/null +++ b/bridges/CustomTarget_gcc3_wasm.mk @@ -0,0 +1,26 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# 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/. +# + +$(eval $(call gb_CustomTarget_CustomTarget,bridges/gcc3_wasm)) + +$(eval $(call gb_CustomTarget_register_targets,bridges/gcc3_wasm, \ + callvirtualfunction-wrapper.cxx \ + callvirtualfunction-impls.s \ +)) + +$(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-impls.s \ +$(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-wrapper.cxx: \ + $(call gb_Executable_get_target_for_build,wasmcallgen) $(call gb_UnoApi_get_target,udkapi) \ + $(call gb_UnoApi_get_target,offapi) + $(call gb_Executable_get_command,wasmcallgen) \ + $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-wrapper.cxx \ + $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-impls.s \ + +$(call gb_UnoApi_get_target,udkapi) +$(call gb_UnoApi_get_target,offapi) + +# vim: set noet sw=4 ts=4: diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk index dcf83cf34e5b..c42778f359c1 100644 --- a/bridges/Library_cpp_uno.mk +++ b/bridges/Library_cpp_uno.mk @@ -84,6 +84,12 @@ bridge_noopt_objects := except else ifeq ($(OS),EMSCRIPTEN) bridges_SELECTED_BRIDGE := gcc3_wasm bridge_noopt_objects := cpp2uno except uno2cpp +$(eval $(call gb_Library_add_generated_asmobjects,$(CPPU_ENV)_uno, \ + CustomTarget/bridges/gcc3_wasm/callvirtualfunction-impls \ +)) +$(eval $(call gb_Library_add_generated_exception_objects,$(CPPU_ENV)_uno, \ + CustomTarget/bridges/gcc3_wasm/callvirtualfunction-wrapper \ +)) endif else ifeq ($(CPUNAME),M68K) diff --git a/bridges/Module_bridges.mk b/bridges/Module_bridges.mk index 3016bf2c404f..def86fea4cb7 100644 --- a/bridges/Module_bridges.mk +++ b/bridges/Module_bridges.mk @@ -20,6 +20,7 @@ $(eval $(call gb_Module_add_targets,bridges,\ $(if $(filter ANDROID LINUX,$(OS)),\ CustomTarget_gcc3_linux_arm) \ ) \ + $(if $(filter EMSCRIPTEN,$(OS)),CustomTarget_gcc3_wasm) \ )) ifeq (,$(filter build,$(gb_Module_SKIPTARGETS))) diff --git a/bridges/inc/wasm/callvirtualfunction.hxx b/bridges/inc/wasm/callvirtualfunction.hxx new file mode 100644 index 000000000000..23b446cd45b3 --- /dev/null +++ b/bridges/inc/wasm/callvirtualfunction.hxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <sal/config.h> + +#include <string_view> + +#include <sal/types.h> + +void callVirtualFunction(std::string_view signature, sal_uInt32 target, sal_uInt64 const* arguments, + void* returnValue); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx index ddb51166b51e..41a471bcc9b0 100644 --- a/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx @@ -7,15 +7,81 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <sal/config.h> + +#include <vector> + #include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/Type.hxx> +#include <o3tl/unreachable.hxx> +#include <rtl/strbuf.hxx> +#include <typelib/typeclass.h> +#include <typelib/typedescription.h> #include <bridge.hxx> #include <types.hxx> #include <unointerfaceproxy.hxx> #include <vtables.hxx> +#include <wasm/callvirtualfunction.hxx> + using namespace ::com::sun::star::uno; +namespace +{ +enum class StructKind +{ + Empty, + I32, + I64, + F32, + F64, + General +}; + +StructKind getKind(typelib_CompoundTypeDescription const* type) +{ + if (type->nMembers > 1) + { + return StructKind::General; + } + auto k = StructKind::Empty; + if (type->pBaseTypeDescription != nullptr) + { + k = getKind(type->pBaseTypeDescription); + } + if (type->nMembers == 0) + { + return k; + } + if (k != StructKind::Empty) + { + return StructKind::General; + } + switch (type->ppTypeRefs[0]->eTypeClass) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + return StructKind::I32; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + return StructKind::I64; + case typelib_TypeClass_FLOAT: + return StructKind::F32; + case typelib_TypeClass_DOUBLE: + return StructKind::F64; + default: + return StructKind::General; + } +} +} + namespace bridges::cpp_uno::shared { void unoInterfaceProxyDispatch(uno_Interface* pUnoI, const typelib_TypeDescription* pMemberDescr, @@ -71,7 +137,165 @@ void unoInterfaceProxyDispatch(uno_Interface* pUnoI, const typelib_TypeDescripti } // else perform queryInterface() [[fallthrough]]; default: - std::abort(); + { + auto const mtd + = reinterpret_cast<typelib_InterfaceMethodTypeDescription const*>( + pMemberDescr); + OStringBuffer sig; + std::vector<sal_uInt64> args; + switch (mtd->pReturnTypeRef->eTypeClass) + { + case typelib_TypeClass_VOID: + sig.append('v'); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + sig.append('i'); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + sig.append('j'); + break; + case typelib_TypeClass_FLOAT: + sig.append('f'); + break; + case typelib_TypeClass_DOUBLE: + sig.append('d'); + break; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + sig.append("vi"); + args.push_back(reinterpret_cast<sal_uInt32>(pReturn)); + break; + case typelib_TypeClass_STRUCT: + { + typelib_TypeDescription* td = nullptr; + css::uno::Type(mtd->pReturnTypeRef).getDescription(&td); + switch (getKind( + reinterpret_cast<typelib_CompoundTypeDescription const*>(td))) + { + case StructKind::Empty: + break; + case StructKind::I32: + sig.append('i'); + break; + case StructKind::I64: + sig.append('j'); + break; + case StructKind::F32: + sig.append('f'); + break; + case StructKind::F64: + sig.append('d'); + break; + case StructKind::General: + sig.append("vi"); + args.push_back(reinterpret_cast<sal_uInt32>(pReturn)); + break; + } + break; + } + default: + O3TL_UNREACHABLE; + } + sig.append('i'); + args.push_back(reinterpret_cast<sal_uInt32>(pThis->pCppI)); + for (sal_Int32 i = 0; i != mtd->nParams; ++i) + { + if (mtd->pParams[i].bOut) + { + sig.append('i'); + args.push_back(reinterpret_cast<sal_uInt32>(pArgs[i])); + } + else + { + switch (mtd->pParams[i].pTypeRef->eTypeClass) + { + case typelib_TypeClass_BOOLEAN: + sig.append('i'); + args.push_back(*reinterpret_cast<sal_Bool const*>(pArgs[i])); + break; + case typelib_TypeClass_BYTE: + sig.append('i'); + args.push_back(*reinterpret_cast<sal_Int8 const*>(pArgs[i])); + break; + case typelib_TypeClass_SHORT: + sig.append('i'); + args.push_back(*reinterpret_cast<sal_Int16 const*>(pArgs[i])); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + sig.append('i'); + args.push_back(*reinterpret_cast<sal_uInt16 const*>(pArgs[i])); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_ENUM: + sig.append('i'); + args.push_back(*reinterpret_cast<sal_Int32 const*>(pArgs[i])); + break; + case typelib_TypeClass_UNSIGNED_LONG: + sig.append('i'); + args.push_back(*reinterpret_cast<sal_uInt32 const*>(pArgs[i])); + break; + case typelib_TypeClass_HYPER: + sig.append('j'); + args.push_back(*reinterpret_cast<sal_Int64 const*>(pArgs[i])); + break; + case typelib_TypeClass_UNSIGNED_HYPER: + sig.append('j'); + args.push_back(*reinterpret_cast<sal_uInt64 const*>(pArgs[i])); + break; + case typelib_TypeClass_FLOAT: + sig.append('f'); + args.push_back(*reinterpret_cast<sal_uInt32 const*>(pArgs[i])); + break; + case typelib_TypeClass_DOUBLE: + sig.append('d'); + args.push_back(*reinterpret_cast<sal_uInt64 const*>(pArgs[i])); + break; + case typelib_TypeClass_CHAR: + sig.append('i'); + args.push_back(*reinterpret_cast<sal_Unicode const*>(pArgs[i])); + break; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_INTERFACE: + sig.append('i'); + args.push_back(reinterpret_cast<sal_uInt32>(pArgs[i])); + break; + default: + O3TL_UNREACHABLE; + } + } + } + try + { + callVirtualFunction(sig, + (*reinterpret_cast<sal_uInt32 const* const*>( + pThis->pCppI))[aVtableSlot.index], + args.data(), pReturn); + *ppException = nullptr; + } + catch (...) + { + css::uno::RuntimeException TODO("Wasm bridge TODO"); + uno_type_any_construct( + *ppException, &TODO, + cppu::UnoType<css::uno::RuntimeException>::get().getTypeLibType(), + nullptr); + } + } } break; } diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index 8e93cd59389f..fe01fc172776 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -4444,6 +4444,8 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,org/libreoffice/embindtest, \ Enum \ Exception \ Struct \ + StructLong \ + StructString \ XTest \ )) $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,org/libreoffice/embindtest, \ diff --git a/offapi/org/libreoffice/embindtest/StructLong.idl b/offapi/org/libreoffice/embindtest/StructLong.idl new file mode 100644 index 000000000000..22447486b3f3 --- /dev/null +++ b/offapi/org/libreoffice/embindtest/StructLong.idl @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +module org { module libreoffice { module embindtest { + +struct StructLong { + long m; +}; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/org/libreoffice/embindtest/StructString.idl b/offapi/org/libreoffice/embindtest/StructString.idl new file mode 100644 index 000000000000..e0c1464cfc84 --- /dev/null +++ b/offapi/org/libreoffice/embindtest/StructString.idl @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +module org { module libreoffice { module embindtest { + +struct StructString { + string m; +}; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/org/libreoffice/embindtest/XTest.idl b/offapi/org/libreoffice/embindtest/XTest.idl index b84753ebb8c6..ac8549d05397 100644 --- a/offapi/org/libreoffice/embindtest/XTest.idl +++ b/offapi/org/libreoffice/embindtest/XTest.idl @@ -40,6 +40,10 @@ interface XTest { boolean isEnum([in] Enum value); Struct getStruct(); boolean isStruct([in] Struct value); + StructLong getStructLong(); + boolean isStructLong([in] StructLong value); + StructString getStructString(); + boolean isStructString([in] StructString value); any getAnyVoid(); boolean isAnyVoid([in] any value); any getAnyBoolean(); diff --git a/solenv/gbuild/extensions/pre_BuildTools.mk b/solenv/gbuild/extensions/pre_BuildTools.mk index 2522a4e7680c..63db68dc7b2a 100644 --- a/solenv/gbuild/extensions/pre_BuildTools.mk +++ b/solenv/gbuild/extensions/pre_BuildTools.mk @@ -16,7 +16,7 @@ gb_BUILD_TOOLS_executables = \ climaker \ cpp \ cppumaker \ - $(if $(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),embindmaker) \ + $(if $(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),embindmaker wasmcallgen) \ gencoll_rule \ genconv_dict \ gendict \ diff --git a/static/Executable_wasmcallgen.mk b/static/Executable_wasmcallgen.mk new file mode 100644 index 000000000000..77f5d9daf782 --- /dev/null +++ b/static/Executable_wasmcallgen.mk @@ -0,0 +1,26 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# 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/. +# + +$(eval $(call gb_Executable_Executable,wasmcallgen)) + +$(eval $(call gb_Executable_add_exception_objects,wasmcallgen, \ + static/source/wasmcallgen/wasmcallgen \ +)) + +$(eval $(call gb_Executable_use_libraries,wasmcallgen, \ + sal \ + salhelper \ + unoidl \ +)) + +$(eval $(call gb_Executable_use_static_libraries,wasmcallgen, \ + codemaker \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/static/Module_static.mk b/static/Module_static.mk index ff036fac3213..7403da211d27 100644 --- a/static/Module_static.mk +++ b/static/Module_static.mk @@ -34,6 +34,7 @@ endif ifneq ($(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),) $(eval $(call gb_Module_add_targets,static, \ Executable_embindmaker \ + Executable_wasmcallgen \ )) endif diff --git a/static/source/wasmcallgen/wasmcallgen.cxx b/static/source/wasmcallgen/wasmcallgen.cxx new file mode 100644 index 000000000000..0453bdb8aff8 --- /dev/null +++ b/static/source/wasmcallgen/wasmcallgen.cxx @@ -0,0 +1,610 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include <algorithm> +#include <cassert> +#include <cstdlib> +#include <fstream> +#include <ios> +#include <iostream> +#include <set> +#include <string> +#include <string_view> +#include <utility> + +#include <codemaker/global.hxx> +#include <codemaker/typemanager.hxx> +#include <codemaker/unotype.hxx> +#include <o3tl/safeint.hxx> +#include <osl/file.hxx> +#include <osl/process.h> +#include <osl/thread.h> +#include <rtl/process.h> +#include <rtl/ref.hxx> +#include <rtl/strbuf.hxx> +#include <rtl/string.hxx> +#include <rtl/textcvt.h> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> +#include <sal/main.h> +#include <sal/types.h> +#include <unoidl/unoidl.hxx> + +namespace +{ +[[noreturn]] void badUsage() +{ + std::cerr + << "Usage:\n\n" + " wasmcallgen <cpp-output> <asm-output> <registries>\n\n" + "where each <registry> is '+' (primary) or ':' (secondary), followed by: either a\n" + "new- or legacy-format .rdb file, a single .idl file, or a root directory of an\n" + ".idl file tree. For all primary registries, Wasm UNO bridge callvirtualfunction\n" + "code is written to <cpp-output>/<asm-output>.\n"; + std::exit(EXIT_FAILURE); +} + +std::string getPathnameArgument(sal_uInt32 argument) +{ + OUString arg; + rtl_getAppCommandArg(argument, &arg.pData); + OString path; + auto const enc = osl_getThreadTextEncoding(); + if (!arg.convertToString(&path, enc, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)) + { + std::cerr << "Cannot convert \"" << arg << "\" to system encoding " << enc << "\n"; + std::exit(EXIT_FAILURE); + } + return std::string(path); +} + +std::pair<OUString, bool> parseRegistryArgument(sal_uInt32 argument) +{ + OUString arg; + rtl_getAppCommandArg(argument, &arg.pData); + bool primary; + if (arg.startsWith(u"+", &arg)) + { + primary = true; + } + else if (arg.startsWith(u":", &arg)) + { + primary = false; + } + else + { + std::cerr << "Bad registry argument \"" << arg << "\"\n"; + std::exit(EXIT_FAILURE); + } + OUString url; + auto const e1 = osl::FileBase::getFileURLFromSystemPath(arg, url); + if (e1 != osl::FileBase::E_None) + { + std::cerr << "Cannot convert \"" << arg << "\" to file URL, error code " << +e1 << "\n"; + std::exit(EXIT_FAILURE); + } + OUString cwd; + auto const e2 = osl_getProcessWorkingDir(&cwd.pData); + if (e2 != osl_Process_E_None) + { + std::cerr << "Cannot obtain working directory, error code " << +e2 << "\n"; + std::exit(EXIT_FAILURE); + } + OUString abs; + auto const e3 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs); + if (e3 != osl::FileBase::E_None) + { + std::cerr << "Cannot make \"" << url << "\" into an absolute file URL, error code " << +e3 + << "\n"; + std::exit(EXIT_FAILURE); + } + return { abs, primary }; +} + +OUString resolveAllTypedefs(rtl::Reference<TypeManager> const& manager, std::u16string_view name) +{ + sal_Int32 k1; + OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k1))); + for (;;) + { + rtl::Reference<unoidl::Entity> ent; + if (manager->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) + { + break; + } + sal_Int32 k2; + n = b2u(codemaker::UnoType::decompose( + u2b(static_cast<unoidl::TypedefEntity*>(ent.get())->getType()), &k2)); + k1 += k2; //TODO: overflow + } + OUStringBuffer b; + for (sal_Int32 i = 0; i != k1; ++i) + { + b.append("[]"); + } + b.append(n); + return b.makeStringAndClear(); +} + +enum class StructKind +{ + Empty, + I32, + I64, + F32, + F64, + General +}; + +StructKind getKind(rtl::Reference<TypeManager> const& manager, std::u16string_view type) +{ + std::vector<OUString> args; + rtl::Reference<unoidl::Entity> ent; + OUString singleMemberType; + switch (manager->decompose(type, true, nullptr, nullptr, &args, &ent)) + { + case codemaker::UnoType::Sort::PlainStruct: + { + auto const strct = static_cast<unoidl::PlainStructTypeEntity const*>(ent.get()); + if (strct->getDirectMembers().size() > 1) + { + return StructKind::General; + } + auto k = StructKind::Empty; + if (!strct->getDirectBase().isEmpty()) + { + k = getKind(manager, strct->getDirectBase()); + } + if (strct->getDirectMembers().empty()) + { + return k; + } + if (k != StructKind::Empty) + { + return StructKind::General; + } + singleMemberType = strct->getDirectMembers()[0].type; + break; + } + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + { + auto const strct + = static_cast<unoidl::PolymorphicStructTypeTemplateEntity const*>(ent.get()); + switch (strct->getMembers().size()) + { + case 0: + return StructKind::Empty; + case 1: + if (strct->getMembers()[0].parameterized) + { + auto const i = std::find(strct->getTypeParameters().begin(), + strct->getTypeParameters().end(), + strct->getMembers()[0].type); + if (i == strct->getTypeParameters().end()) + { + throw CannotDumpException("bad type parameter \"" + + strct->getMembers()[0].type + + "\" in call to getKind"); + } + auto const n = i - strct->getTypeParameters().begin(); + if (o3tl::make_unsigned(n) > args.size()) + { + throw CannotDumpException("bad type parameter \"" + + strct->getMembers()[0].type + + "\" in call to getKind"); + } + singleMemberType = args[n]; + } + else + { + singleMemberType = strct->getMembers()[0].type; + } + break; + default: + return StructKind::General; + } + break; + } + default: + throw CannotDumpException(OUString::Concat("unexpected entity \"") + type + + "\" in call to getKind"); + } + switch (manager->getSort(resolveAllTypedefs(manager, singleMemberType))) + { + 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::Char: + case codemaker::UnoType::Sort::Enum: + return StructKind::I32; + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + return StructKind::I64; + case codemaker::UnoType::Sort::Float: + return StructKind::F32; + case codemaker::UnoType::Sort::Double: + return StructKind::F64; + default: + return StructKind::General; + } +} + +OString computeSignature(rtl::Reference<TypeManager> const& manager, + unoidl::InterfaceTypeEntity::Method const& method) +{ + OStringBuffer buf; + switch (manager->getSort(resolveAllTypedefs(manager, method.returnType))) + { + case codemaker::UnoType::Sort::Void: + buf.append('v'); + break; + 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::Char: + case codemaker::UnoType::Sort::Enum: + buf.append('i'); + break; + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + buf.append('j'); + break; + case codemaker::UnoType::Sort::Float: + buf.append('f'); + break; + case codemaker::UnoType::Sort::Double: + buf.append('d'); + 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::Interface: + buf.append("vi"); + break; + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + { + switch (getKind(manager, method.returnType)) + { + case StructKind::Empty: + break; + case StructKind::I32: + buf.append('i'); + break; + case StructKind::I64: + buf.append('j'); + break; + case StructKind::F32: + buf.append('f'); + break; + case StructKind::F64: + buf.append('d'); + break; + case StructKind::General: + buf.append("vi"); + break; + } + break; + } + default: + throw CannotDumpException("unexpected entity \"" + method.returnType + + "\" in call to computeSignature"); + } + buf.append('i'); + for (auto const& param : method.parameters) + { + if (param.direction == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN) + { + switch (manager->getSort(resolveAllTypedefs(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::Char: + case codemaker::UnoType::Sort::Enum: + 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: + buf.append('i'); + break; + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + buf.append('j'); + break; + case codemaker::UnoType::Sort::Float: + buf.append('f'); + break; + case codemaker::UnoType::Sort::Double: + buf.append('d'); + break; + default: + throw CannotDumpException("unexpected entity \"" + param.type + + "\" in call to computeSignature"); + } + } + else + { + buf.append('i'); + } + } + return buf.makeStringAndClear(); +} + +void scan(rtl::Reference<TypeManager> const& manager, + rtl::Reference<unoidl::MapCursor> const& cursor, std::set<OString>& signatures) +{ + assert(cursor.is()); + for (;;) + { + OUString id; + auto const ent = cursor->getNext(&id); + if (!ent.is()) + { + break; + } + switch (ent->getSort()) + { + case unoidl::Entity::SORT_MODULE: + scan(manager, static_cast<unoidl::ModuleEntity*>(ent.get())->createCursor(), + signatures); + break; + case unoidl::Entity::SORT_INTERFACE_TYPE: + for (auto const& meth : + static_cast<unoidl::InterfaceTypeEntity const*>(ent.get())->getDirectMethods()) + { + signatures.insert(computeSignature(manager, meth)); + } + break; + default: + break; + } + } +} +} + +SAL_IMPLEMENT_MAIN() +{ + try + { + auto const args = rtl_getAppCommandArgCount(); + if (args < 2) + { + badUsage(); + } + auto const cppPathname = getPathnameArgument(0); + auto const asmPathname = getPathnameArgument(1); + rtl::Reference<TypeManager> mgr(new TypeManager); + for (sal_uInt32 i = 2; i != args; ++i) + { + auto const & [ uri, primary ] = parseRegistryArgument(i); + try + { + mgr->loadProvider(uri, primary); + } + catch (unoidl::NoSuchFileException&) + { + std::cerr << "Input <" << uri << "> does not exist\n"; + std::exit(EXIT_FAILURE); + } + } + std::set<OString> signatures; + for (auto const& prov : mgr->getPrimaryProviders()) + { + scan(mgr, prov->createRootCursor(), signatures); + } + std::ofstream cppOut(cppPathname, std::ios_base::out | std::ios_base::trunc); + if (!cppOut) + { + std::cerr << "Cannot open \"" << cppPathname << "\" for writing\n"; + std::exit(EXIT_FAILURE); + } + cppOut << "#include <sal/config.h>\n" + "#include <string_view>\n" + "#include <com/sun/star/uno/RuntimeException.hpp>\n" + "#include <rtl/ustring.hxx>\n" + "#include <wasm/callvirtualfunction.hxx>\n"; + for (auto const& sig : signatures) + { + cppOut << "extern \"C\" void callVirtualFunction_" << sig + << "(sal_uInt32 target, sal_uInt64 const * arguments, void * returnValue);\n"; + } + cppOut << "void callVirtualFunction(std::string_view signature, sal_uInt32 target, " + "sal_uInt64 const * arguments, void * returnValue) {\n"; + for (auto const& sig : signatures) + { + cppOut << " if (signature == \"" << sig << "\") {\n" + << " callVirtualFunction_" << sig << "(target, arguments, returnValue);\n" + << " return;\n" + << " }\n"; + } + cppOut << " throw css::uno::RuntimeException(\"Wasm bridge cannot call virtual function " + "with signature \" + OUString::fromUtf8(signature));\n" + "}\n"; + cppOut.close(); + if (!cppOut) + { + std::cerr << "Failed to write \"" << cppPathname << "\"\n"; + std::exit(EXIT_FAILURE); + } + std::ofstream asmOut(asmPathname, std::ios_base::out | std::ios_base::trunc); + if (!asmOut) + { + std::cerr << "Cannot open \"" << asmPathname << "\" for writing\n"; + std::exit(EXIT_FAILURE); + } + asmOut << "\t.text\n" + "\t.tabletype __indirect_function_table, funcref\n"; + for (auto const& sig : signatures) + { + asmOut << "\t.functype callVirtualFunction_" << sig << " (i32, i32, i32) -> ()\n"; + } + for (auto const& sig : signatures) + { + asmOut << "\t.section .text.callVirtualFunction_" << sig + << ",\"\",@\n" + "\t.globl callVirtualFunction_" + << sig + << "\n" + "\t.type callVirtualFunction_" + << sig + << ",@function\n" + "callVirtualFunction_" + << sig + << ":\n" + "\t.functype callVirtualFunction_" + << sig << " (i32, i32, i32) -> ()\n"; + if (sig[0] != 'v') + { + asmOut << "\tlocal.get 2\n"; + } + unsigned off = 0; + for (auto c : sig.subView(1)) + { + asmOut << "\tlocal.get 1\n" + "\t"; + switch (c) + { + case 'd': + asmOut << "f64"; + break; + case 'f': + asmOut << "f32"; + break; + case 'i': + asmOut << "i32"; + break; + case 'j': + asmOut << "i64"; + break; + default: + assert(false); + } + asmOut << ".load " << off << "\n"; + off += 8; //TODO: overflow + } + asmOut << "\tlocal.get 0\n" + "\tcall_indirect ("; + auto first = true; + for (auto c : sig.subView(1)) + { + if (first) + { + first = false; + } + else + { + asmOut << ", "; + } + switch (c) + { + case 'd': + asmOut << "f64"; + break; + case 'f': + asmOut << "f32"; + break; + case 'i': + asmOut << "i32"; + break; + case 'j': + asmOut << "i64"; + break; + default: + assert(false); + } + } + asmOut << ") -> ("; + switch (sig[0]) + { + case 'd': + asmOut << "f64"; + break; + case 'f': + asmOut << "f32"; + break; + case 'i': + asmOut << "i32"; + break; + case 'j': + asmOut << "i64"; + break; + case 'v': + break; + default: + assert(false); + } + asmOut << ")\n"; + if (sig[0] != 'v') + { + asmOut << "\t"; + switch (sig[0]) + { + case 'd': + asmOut << "f64"; + break; + case 'f': + asmOut << "f32"; + break; + case 'i': + asmOut << "i32"; + break; + case 'j': + asmOut << "i64"; + break; + default: + assert(false); + } + asmOut << ".store 0\n"; + } + asmOut << "\tend_function\n"; + } + asmOut.close(); + if (!asmOut) + { + std::cerr << "Failed to write \"" << asmPathname << "\"\n"; + std::exit(EXIT_FAILURE); + } + return EXIT_SUCCESS; + } + catch (unoidl::FileFormatException const& e) + { + std::cerr << "Bad input <" << e.getUri() << ">: " << e.getDetail() << "\n"; + std::exit(EXIT_FAILURE); + } + catch (CannotDumpException const& e) + { + std::cerr << "Failure: " << e.getMessage() << "\n"; + std::exit(EXIT_FAILURE); + } + catch (std::exception const& e) + { + std::cerr << "Failure: " << e.what() << "\n"; + std::exit(EXIT_FAILURE); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/unotest/source/embindtest/embindtest.cxx b/unotest/source/embindtest/embindtest.cxx index c5fcea1dc42e..7b65ed3ed776 100644 --- a/unotest/source/embindtest/embindtest.cxx +++ b/unotest/source/embindtest/embindtest.cxx @@ -24,6 +24,8 @@ #include <org/libreoffice/embindtest/Enum.hpp> #include <org/libreoffice/embindtest/Exception.hpp> #include <org/libreoffice/embindtest/Struct.hpp> +#include <org/libreoffice/embindtest/StructLong.hpp> +#include <org/libreoffice/embindtest/StructString.hpp> #include <org/libreoffice/embindtest/XTest.hpp> #include <rtl/ustring.hxx> #include <sal/types.h> @@ -112,6 +114,27 @@ class Test : public cppu::WeakImplHelper<org::libreoffice::embindtest::XTest> return value == org::libreoffice::embindtest::Struct{ -123456, 100.5, u"hä"_ustr }; } + org::libreoffice::embindtest::StructLong SAL_CALL getStructLong() override + { + return { -123456 }; + } + + sal_Bool SAL_CALL isStructLong(org::libreoffice::embindtest::StructLong const& value) override + { + return value.m == -123456; + } + + org::libreoffice::embindtest::StructString SAL_CALL getStructString() override + { + return { u"hä"_ustr }; + } + + sal_Bool SAL_CALL + isStructString(org::libreoffice::embindtest::StructString const& value) override + { + return value.m == u"hä"; + } + css::uno::Any SAL_CALL getAnyVoid() override { return {}; } sal_Bool SAL_CALL isAnyVoid(css::uno::Any const& value) override diff --git a/unotest/source/embindtest/embindtest.js b/unotest/source/embindtest/embindtest.js index 16efe9acf169..3944f399e3b1 100644 --- a/unotest/source/embindtest/embindtest.js +++ b/unotest/source/embindtest/embindtest.js @@ -697,6 +697,336 @@ Module.addOnPostRun(function() { test.passJobExecutor(css.task.XJobExecutor.reference(obj.implXJobExecutor)); test.passInterface(css.uno.XInterface.reference(obj.implXTypeProvider)); obj.release(); + + const args = new Module.uno_Sequence_any( + [new Module.uno_Any(Module.uno_Type.Interface('com.sun.star.uno.XInterface'), test)]); + const invoke = css.script.XInvocation2.query(css.script.Invocation.create( + Module.getUnoComponentContext()).createInstanceWithArguments(args)); + args.get(0).delete(); + args.delete(); + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getBoolean', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isBoolean', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getByte', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isByte', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getShort', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isShort', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getUnsignedShort', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isUnsignedShort', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getLong', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isLong', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getUnsignedLong', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isUnsignedLong', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getHyper', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isHyper', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getUnsignedHyper', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isUnsignedHyper', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getFloat', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isFloat', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getDouble', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isDouble', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getChar', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isChar', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getString', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isString', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getType', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isType', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getEnum', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isEnum', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getStruct', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isStruct', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getStructLong', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isStructLong', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getStructString', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isStructString', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getAnyLong', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isAnyLong', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } + { + const params1 = new Module.uno_Sequence_any(0, Module.uno_Sequence.FromSize); + const outparamindex = new Module.uno_InOutParam_sequence_short; + const outparam = new Module.uno_InOutParam_sequence_any; + const ret1 = invoke.invoke('getSequenceLong', params1, outparamindex, outparam); + console.log(ret1.get()); + const params2 = new Module.uno_Sequence_any([ret1]); + const ret2 = invoke.invoke('isSequenceLong', params2, outparamindex, outparam); + console.log(ret2.get()); + console.assert(ret2.get()); + ret1.delete(); + params1.delete(); + ret2.delete(); + params2.delete(); + outparamindex.delete(); + outparam.delete(); + } }); /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |