Embind: Fix C++ UNO exception catching
...with a new Module.catchUnoException JS function that can be used in a JS catch block to provide the thrown UNO exception as an Any. (For a non-C++ exception, it rethrows the exception, and for a non-UNO C++ exception it maps it to css.uno.RuntimeException.) The implementation reuses parts of bridges/source/cpp_uno/gcc3_wasm/, which have been moved to a new StaticLibrary_emscriptencxxabi. Change-Id: I708fe6121c43a1b9736de5dff449f6c4f32a45f3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169325 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
This commit is contained in:
parent
54f7308641
commit
eedbe966bb
@ -90,6 +90,9 @@ $(eval $(call gb_Library_add_generated_asmobjects,$(CPPU_ENV)_uno, \
|
|||||||
$(eval $(call gb_Library_add_generated_exception_objects,$(CPPU_ENV)_uno, \
|
$(eval $(call gb_Library_add_generated_exception_objects,$(CPPU_ENV)_uno, \
|
||||||
CustomTarget/bridges/gcc3_wasm/callvirtualfunction-wrapper \
|
CustomTarget/bridges/gcc3_wasm/callvirtualfunction-wrapper \
|
||||||
))
|
))
|
||||||
|
$(eval $(call gb_Library_use_static_libraries,$(CPPU_ENV)_uno, \
|
||||||
|
emscriptencxxabi \
|
||||||
|
))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
else ifeq ($(CPUNAME),M68K)
|
else ifeq ($(CPUNAME),M68K)
|
||||||
|
@ -20,7 +20,10 @@ $(eval $(call gb_Module_add_targets,bridges,\
|
|||||||
$(if $(filter ANDROID LINUX,$(OS)),\
|
$(if $(filter ANDROID LINUX,$(OS)),\
|
||||||
CustomTarget_gcc3_linux_arm) \
|
CustomTarget_gcc3_linux_arm) \
|
||||||
) \
|
) \
|
||||||
$(if $(filter EMSCRIPTEN,$(OS)),CustomTarget_gcc3_wasm) \
|
$(if $(filter EMSCRIPTEN,$(OS)), \
|
||||||
|
CustomTarget_gcc3_wasm \
|
||||||
|
StaticLibrary_emscriptencxxabi \
|
||||||
|
) \
|
||||||
))
|
))
|
||||||
|
|
||||||
ifeq (,$(filter build,$(gb_Module_SKIPTARGETS)))
|
ifeq (,$(filter build,$(gb_Module_SKIPTARGETS)))
|
||||||
|
16
bridges/StaticLibrary_emscriptencxxabi.mk
Normal file
16
bridges/StaticLibrary_emscriptencxxabi.mk
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# -*- 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_StaticLibrary_StaticLibrary,emscriptencxxabi))
|
||||||
|
|
||||||
|
$(eval $(call gb_StaticLibrary_add_exception_objects,emscriptencxxabi, \
|
||||||
|
bridges/source/emscriptencxxabi/cxxabi \
|
||||||
|
))
|
||||||
|
|
||||||
|
# vim: set noet sw=4 ts=4:
|
@ -10,12 +10,11 @@
|
|||||||
#include <sal/config.h>
|
#include <sal/config.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
|
#include <bridges/emscriptencxxabi/cxxabi.hxx>
|
||||||
#include <com/sun/star/uno/RuntimeException.hpp>
|
#include <com/sun/star/uno/RuntimeException.hpp>
|
||||||
#include <cppu/unotype.hxx>
|
#include <cppu/unotype.hxx>
|
||||||
#include <rtl/ustrbuf.hxx>
|
|
||||||
#include <rtl/ustring.hxx>
|
#include <rtl/ustring.hxx>
|
||||||
#include <typelib/typedescription.h>
|
#include <typelib/typedescription.h>
|
||||||
#include <uno/any2.h>
|
#include <uno/any2.h>
|
||||||
@ -23,49 +22,12 @@
|
|||||||
|
|
||||||
#include "abi.hxx"
|
#include "abi.hxx"
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
OUString toUnoName(char const* name)
|
|
||||||
{
|
|
||||||
assert(name != nullptr);
|
|
||||||
OUStringBuffer b;
|
|
||||||
bool scoped = *name == 'N';
|
|
||||||
if (scoped)
|
|
||||||
{
|
|
||||||
++name;
|
|
||||||
}
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
assert(*name >= '0' && *name <= '9');
|
|
||||||
std::size_t n = *name++ - '0';
|
|
||||||
while (*name >= '0' && *name <= '9')
|
|
||||||
{
|
|
||||||
n = 10 * n + (*name++ - '0');
|
|
||||||
}
|
|
||||||
b.appendAscii(name, n);
|
|
||||||
name += n;
|
|
||||||
if (!scoped)
|
|
||||||
{
|
|
||||||
assert(*name == 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (*name == 'E')
|
|
||||||
{
|
|
||||||
assert(name[1] == 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
b.append('.');
|
|
||||||
}
|
|
||||||
return b.makeStringAndClear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void abi_wasm::mapException(__cxxabiv1::__cxa_exception* exception, std::type_info const* type,
|
void abi_wasm::mapException(__cxxabiv1::__cxa_exception* exception, std::type_info const* type,
|
||||||
uno_Any* any, uno_Mapping* mapping)
|
uno_Any* any, uno_Mapping* mapping)
|
||||||
{
|
{
|
||||||
assert(exception != nullptr);
|
assert(exception != nullptr);
|
||||||
assert(type != nullptr);
|
assert(type != nullptr);
|
||||||
OUString unoName(toUnoName(type->name()));
|
OUString unoName(emscriptencxxabi::toUnoName(type->name()));
|
||||||
typelib_TypeDescription* td = nullptr;
|
typelib_TypeDescription* td = nullptr;
|
||||||
typelib_typedescription_getByName(&td, unoName.pData);
|
typelib_typedescription_getByName(&td, unoName.pData);
|
||||||
if (td == nullptr)
|
if (td == nullptr)
|
||||||
|
@ -11,95 +11,15 @@
|
|||||||
|
|
||||||
#include <sal/config.h>
|
#include <sal/config.h>
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <exception>
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
|
|
||||||
|
#include <bridges/emscriptencxxabi/cxxabi.hxx>
|
||||||
#include <config_cxxabi.h>
|
#include <config_cxxabi.h>
|
||||||
#include <uno/any2.h>
|
#include <uno/any2.h>
|
||||||
#include <uno/mapping.h>
|
#include <uno/mapping.h>
|
||||||
|
|
||||||
#if !HAVE_CXXABI_H_CXA_EXCEPTION
|
|
||||||
|
|
||||||
// <https://github.com/emscripten-core/emscripten/>, system/lib/libunwind/include/unwind_itanium.h,
|
|
||||||
// except where MODIFIED:
|
|
||||||
typedef std::/*MODIFIED*/ uint64_t _Unwind_Exception_Class;
|
|
||||||
struct _Unwind_Exception
|
|
||||||
{
|
|
||||||
_Unwind_Exception_Class exception_class;
|
|
||||||
void (*exception_cleanup)(/*MODIFIED: _Unwind_Reason_Code reason, _Unwind_Exception* exc*/);
|
|
||||||
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
|
|
||||||
std::/*MODIFIED*/ uintptr_t private_[6];
|
|
||||||
#elif !defined(__USING_WASM_EXCEPTIONS__)
|
|
||||||
std::/*MODIFIED*/ uintptr_t private_1; // non-zero means forced unwind
|
|
||||||
std::/*MODIFIED*/ uintptr_t private_2; // holds sp that phase1 found for phase2 to use
|
|
||||||
#endif
|
|
||||||
#if __SIZEOF_POINTER__ == 4
|
|
||||||
// The implementation of _Unwind_Exception uses an attribute mode on the
|
|
||||||
// above fields which has the side effect of causing this whole struct to
|
|
||||||
// round up to 32 bytes in size (48 with SEH). To be more explicit, we add
|
|
||||||
// pad fields added for binary compatibility.
|
|
||||||
std::/*MODIFIED*/ uint32_t reserved[3];
|
|
||||||
#endif
|
|
||||||
// The Itanium ABI requires that _Unwind_Exception objects are "double-word
|
|
||||||
// aligned". GCC has interpreted this to mean "use the maximum useful
|
|
||||||
// alignment for the target"; so do we.
|
|
||||||
} __attribute__((__aligned__));
|
|
||||||
|
|
||||||
// <https://github.com/emscripten-core/emscripten/>, system/lib/libcxxabi/src/cxa_exception.h,
|
|
||||||
// except where MODIFIED:
|
|
||||||
namespace __cxxabiv1
|
|
||||||
{
|
|
||||||
struct __cxa_exception
|
|
||||||
{
|
|
||||||
#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
|
|
||||||
// Now _Unwind_Exception is marked with __attribute__((aligned)),
|
|
||||||
// which implies __cxa_exception is also aligned. Insert padding
|
|
||||||
// in the beginning of the struct, rather than before unwindHeader.
|
|
||||||
void* reserve;
|
|
||||||
// This is a new field to support C++11 exception_ptr.
|
|
||||||
// For binary compatibility it is at the start of this
|
|
||||||
// struct which is prepended to the object thrown in
|
|
||||||
// __cxa_allocate_exception.
|
|
||||||
std::/*MODIFIED*/ size_t referenceCount;
|
|
||||||
#endif
|
|
||||||
// Manage the exception object itself.
|
|
||||||
std::type_info* exceptionType;
|
|
||||||
#if 1 //MODIFIED: #ifdef __USING_WASM_EXCEPTIONS__
|
|
||||||
// In wasm, destructors return their argument
|
|
||||||
void*(/*MODIFIED: _LIBCXXABI_DTOR_FUNC*/ *exceptionDestructor)(void*);
|
|
||||||
#else
|
|
||||||
void(/*MODIFIED: _LIBCXXABI_DTOR_FUNC*/ *exceptionDestructor)(void*);
|
|
||||||
#endif
|
|
||||||
void* /*MODIFIED: std::unexpected_handler*/ unexpectedHandler;
|
|
||||||
std::terminate_handler terminateHandler;
|
|
||||||
__cxa_exception* nextException;
|
|
||||||
int handlerCount;
|
|
||||||
#if defined(_LIBCXXABI_ARM_EHABI)
|
|
||||||
__cxa_exception* nextPropagatingException;
|
|
||||||
int propagationCount;
|
|
||||||
#else
|
|
||||||
int handlerSwitchValue;
|
|
||||||
const unsigned char* actionRecord;
|
|
||||||
const unsigned char* languageSpecificData;
|
|
||||||
void* catchTemp;
|
|
||||||
void* adjustedPtr;
|
|
||||||
#endif
|
|
||||||
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
|
|
||||||
// This is a new field to support C++11 exception_ptr.
|
|
||||||
// For binary compatibility it is placed where the compiler
|
|
||||||
// previously added padding to 64-bit align unwindHeader.
|
|
||||||
std::/*MODIFIED*/ size_t referenceCount;
|
|
||||||
#endif
|
|
||||||
_Unwind_Exception unwindHeader;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !HAVE_CXXABI_H_CXA_EH_GLOBALS
|
#if !HAVE_CXXABI_H_CXA_EH_GLOBALS
|
||||||
// <https://github.com/emscripten-core/emscripten/>, system/lib/libcxxabi/src/cxa_exception.h:
|
// <https://github.com/emscripten-core/emscripten/>, system/lib/libcxxabi/src/cxa_exception.h:
|
||||||
namespace __cxxabiv1
|
namespace __cxxabiv1
|
||||||
|
53
bridges/source/emscriptencxxabi/cxxabi.cxx
Normal file
53
bridges/source/emscriptencxxabi/cxxabi.cxx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/* -*- 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 <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <bridges/emscriptencxxabi/cxxabi.hxx>
|
||||||
|
#include <rtl/ustrbuf.hxx>
|
||||||
|
#include <rtl/ustring.hxx>
|
||||||
|
|
||||||
|
OUString emscriptencxxabi::toUnoName(char const* name)
|
||||||
|
{
|
||||||
|
assert(name != nullptr);
|
||||||
|
OUStringBuffer b;
|
||||||
|
bool scoped = *name == 'N';
|
||||||
|
if (scoped)
|
||||||
|
{
|
||||||
|
++name;
|
||||||
|
}
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
assert(*name >= '0' && *name <= '9');
|
||||||
|
std::size_t n = *name++ - '0';
|
||||||
|
while (*name >= '0' && *name <= '9')
|
||||||
|
{
|
||||||
|
n = 10 * n + (*name++ - '0');
|
||||||
|
}
|
||||||
|
b.appendAscii(name, n);
|
||||||
|
name += n;
|
||||||
|
if (!scoped)
|
||||||
|
{
|
||||||
|
assert(*name == 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*name == 'E')
|
||||||
|
{
|
||||||
|
assert(name[1] == 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
b.append('.');
|
||||||
|
}
|
||||||
|
return b.makeStringAndClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
107
include/bridges/emscriptencxxabi/cxxabi.hxx
Normal file
107
include/bridges/emscriptencxxabi/cxxabi.hxx
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/* -*- 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 <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <exception>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
#include <cxxabi.h>
|
||||||
|
|
||||||
|
#include <config_cxxabi.h>
|
||||||
|
#include <rtl/ustring.hxx>
|
||||||
|
|
||||||
|
#if !HAVE_CXXABI_H_CXA_EXCEPTION
|
||||||
|
|
||||||
|
// <https://github.com/emscripten-core/emscripten/>, system/lib/libunwind/include/unwind_itanium.h,
|
||||||
|
// except where MODIFIED:
|
||||||
|
typedef std::/*MODIFIED*/ uint64_t _Unwind_Exception_Class;
|
||||||
|
struct _Unwind_Exception
|
||||||
|
{
|
||||||
|
_Unwind_Exception_Class exception_class;
|
||||||
|
void (*exception_cleanup)(/*MODIFIED: _Unwind_Reason_Code reason, _Unwind_Exception* exc*/);
|
||||||
|
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
|
||||||
|
std::/*MODIFIED*/ uintptr_t private_[6];
|
||||||
|
#elif !defined(__USING_WASM_EXCEPTIONS__)
|
||||||
|
std::/*MODIFIED*/ uintptr_t private_1; // non-zero means forced unwind
|
||||||
|
std::/*MODIFIED*/ uintptr_t private_2; // holds sp that phase1 found for phase2 to use
|
||||||
|
#endif
|
||||||
|
#if __SIZEOF_POINTER__ == 4
|
||||||
|
// The implementation of _Unwind_Exception uses an attribute mode on the
|
||||||
|
// above fields which has the side effect of causing this whole struct to
|
||||||
|
// round up to 32 bytes in size (48 with SEH). To be more explicit, we add
|
||||||
|
// pad fields added for binary compatibility.
|
||||||
|
std::/*MODIFIED*/ uint32_t reserved[3];
|
||||||
|
#endif
|
||||||
|
// The Itanium ABI requires that _Unwind_Exception objects are "double-word
|
||||||
|
// aligned". GCC has interpreted this to mean "use the maximum useful
|
||||||
|
// alignment for the target"; so do we.
|
||||||
|
} __attribute__((__aligned__));
|
||||||
|
|
||||||
|
// <https://github.com/emscripten-core/emscripten/>, system/lib/libcxxabi/src/cxa_exception.h,
|
||||||
|
// except where MODIFIED:
|
||||||
|
namespace __cxxabiv1
|
||||||
|
{
|
||||||
|
struct __cxa_exception
|
||||||
|
{
|
||||||
|
#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
|
||||||
|
// Now _Unwind_Exception is marked with __attribute__((aligned)),
|
||||||
|
// which implies __cxa_exception is also aligned. Insert padding
|
||||||
|
// in the beginning of the struct, rather than before unwindHeader.
|
||||||
|
void* reserve;
|
||||||
|
// This is a new field to support C++11 exception_ptr.
|
||||||
|
// For binary compatibility it is at the start of this
|
||||||
|
// struct which is prepended to the object thrown in
|
||||||
|
// __cxa_allocate_exception.
|
||||||
|
std::/*MODIFIED*/ size_t referenceCount;
|
||||||
|
#endif
|
||||||
|
// Manage the exception object itself.
|
||||||
|
std::type_info* exceptionType;
|
||||||
|
#if 1 //MODIFIED: #ifdef __USING_WASM_EXCEPTIONS__
|
||||||
|
// In wasm, destructors return their argument
|
||||||
|
void*(/*MODIFIED: _LIBCXXABI_DTOR_FUNC*/ *exceptionDestructor)(void*);
|
||||||
|
#else
|
||||||
|
void(/*MODIFIED: _LIBCXXABI_DTOR_FUNC*/ *exceptionDestructor)(void*);
|
||||||
|
#endif
|
||||||
|
void* /*MODIFIED: std::unexpected_handler*/ unexpectedHandler;
|
||||||
|
std::terminate_handler terminateHandler;
|
||||||
|
__cxa_exception* nextException;
|
||||||
|
int handlerCount;
|
||||||
|
#if defined(_LIBCXXABI_ARM_EHABI)
|
||||||
|
__cxa_exception* nextPropagatingException;
|
||||||
|
int propagationCount;
|
||||||
|
#else
|
||||||
|
int handlerSwitchValue;
|
||||||
|
const unsigned char* actionRecord;
|
||||||
|
const unsigned char* languageSpecificData;
|
||||||
|
void* catchTemp;
|
||||||
|
void* adjustedPtr;
|
||||||
|
#endif
|
||||||
|
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
|
||||||
|
// This is a new field to support C++11 exception_ptr.
|
||||||
|
// For binary compatibility it is placed where the compiler
|
||||||
|
// previously added padding to 64-bit align unwindHeader.
|
||||||
|
std::/*MODIFIED*/ size_t referenceCount;
|
||||||
|
#endif
|
||||||
|
_Unwind_Exception unwindHeader;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace emscriptencxxabi
|
||||||
|
{
|
||||||
|
OUString toUnoName(char const* name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
@ -22,6 +22,10 @@ $(eval $(call gb_StaticLibrary_use_api,unoembind,\
|
|||||||
udkapi \
|
udkapi \
|
||||||
))
|
))
|
||||||
|
|
||||||
|
$(eval $(call gb_StaticLibrary_use_static_libraries,unoembind, \
|
||||||
|
emscriptencxxabi \
|
||||||
|
))
|
||||||
|
|
||||||
$(call gb_StaticLibrary_get_target,unoembind): $(call gb_CustomTarget_get_target,static/unoembind)
|
$(call gb_StaticLibrary_get_target,unoembind): $(call gb_CustomTarget_get_target,static/unoembind)
|
||||||
|
|
||||||
# vim: set noet sw=4 ts=4:
|
# vim: set noet sw=4 ts=4:
|
||||||
|
@ -15,6 +15,18 @@ Module.initUno = function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Module.catchUnoException = function(exception) {
|
||||||
|
// Rethrow non-C++ exceptions (non-UNO C++ exceptions are mapped to css.uno.RuntimeException in
|
||||||
|
// Module.getUnoExceptionFromCxaException):
|
||||||
|
if (!(exception instanceof WebAssembly.Exception && exception.is(getCppExceptionTag()))) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
const any = Module.getUnoExceptionFromCxaException(
|
||||||
|
getCppExceptionThrownObjectFromWebAssemblyException(exception));
|
||||||
|
decrementExceptionRefcount(exception);
|
||||||
|
return any;
|
||||||
|
}
|
||||||
|
|
||||||
Module.unoObject = function(interfaces, obj) {
|
Module.unoObject = function(interfaces, obj) {
|
||||||
Module.initUno();
|
Module.initUno();
|
||||||
interfaces = ['com.sun.star.lang.XTypeProvider'].concat(interfaces);
|
interfaces = ['com.sun.star.lang.XTypeProvider'].concat(interfaces);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/bind.h>
|
#include <emscripten/bind.h>
|
||||||
|
|
||||||
|
#include <bridges/emscriptencxxabi/cxxabi.hxx>
|
||||||
#include <com/sun/star/uno/Any.hxx>
|
#include <com/sun/star/uno/Any.hxx>
|
||||||
#include <com/sun/star/uno/Reference.hxx>
|
#include <com/sun/star/uno/Reference.hxx>
|
||||||
#include <com/sun/star/uno/RuntimeException.hpp>
|
#include <com/sun/star/uno/RuntimeException.hpp>
|
||||||
@ -414,6 +415,28 @@ EMSCRIPTEN_BINDINGS(PrimaryBindings)
|
|||||||
css::uno::Reference<css::uno::XInterface> const& ref2) { return ref1 == ref2; });
|
css::uno::Reference<css::uno::XInterface> const& ref2) { return ref1 == ref2; });
|
||||||
function("rtl_uString_release",
|
function("rtl_uString_release",
|
||||||
+[](std::uintptr_t ptr) { rtl_uString_release(reinterpret_cast<rtl_uString*>(ptr)); });
|
+[](std::uintptr_t ptr) { rtl_uString_release(reinterpret_cast<rtl_uString*>(ptr)); });
|
||||||
|
function("getUnoExceptionFromCxaException", +[](std::uintptr_t ptr) {
|
||||||
|
// Cf. __get_exception_message in <https://github.com/emscripten-core/emscripten/>,
|
||||||
|
// system/lib/libcxxabi/src/cxa_exception_js_utils.cpp:
|
||||||
|
auto const header = reinterpret_cast<__cxxabiv1::__cxa_exception const*>(ptr) - 1;
|
||||||
|
css::uno::Any exc;
|
||||||
|
OUString unoName(emscriptencxxabi::toUnoName(header->exceptionType->name()));
|
||||||
|
typelib_TypeDescription* td = nullptr;
|
||||||
|
typelib_typedescription_getByName(&td, unoName.pData);
|
||||||
|
if (td == nullptr)
|
||||||
|
{
|
||||||
|
css::uno::RuntimeException e("exception type not found: " + unoName);
|
||||||
|
uno_type_any_construct(
|
||||||
|
&exc, &e, cppu::UnoType<css::uno::RuntimeException>::get().getTypeLibType(),
|
||||||
|
cpp_acquire);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uno_any_construct(&exc, reinterpret_cast<void*>(ptr), td, cpp_acquire);
|
||||||
|
typelib_typedescription_release(td);
|
||||||
|
}
|
||||||
|
return exc;
|
||||||
|
});
|
||||||
|
|
||||||
jsRegisterChar(&typeid(char16_t));
|
jsRegisterChar(&typeid(char16_t));
|
||||||
jsRegisterString(&typeid(OUString));
|
jsRegisterString(&typeid(OUString));
|
||||||
|
@ -640,11 +640,11 @@ Module.addOnPostRun(function() {
|
|||||||
test.throwRuntimeException();
|
test.throwRuntimeException();
|
||||||
console.assert(false);
|
console.assert(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const [type, message] = getExceptionMessage(e);
|
const any = Module.catchUnoException(e);
|
||||||
console.assert(type === 'com::sun::star::uno::RuntimeException');
|
console.assert(any.getType() == 'com.sun.star.uno.RuntimeException');
|
||||||
console.assert(message === undefined); //TODO
|
const exc = any.get();
|
||||||
//TODO: verify css.uno.RuntimeException's Message startsWith('test')
|
console.assert(exc.Message.startsWith('test'));
|
||||||
decrementExceptionRefcount(e);
|
any.delete();
|
||||||
}
|
}
|
||||||
const obj = Module.unoObject(
|
const obj = Module.unoObject(
|
||||||
['com.sun.star.task.XJob', 'com.sun.star.task.XJobExecutor'],
|
['com.sun.star.task.XJob', 'com.sun.star.task.XJobExecutor'],
|
||||||
@ -1086,11 +1086,14 @@ Module.addOnPostRun(function() {
|
|||||||
console.assert(false);
|
console.assert(false);
|
||||||
ret.delete();
|
ret.delete();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const [type, message] = getExceptionMessage(e);
|
const any = Module.catchUnoException(e);
|
||||||
console.assert(type === 'com::sun::star::reflection::InvocationTargetException');
|
console.assert(any.getType() == 'com.sun.star.reflection.InvocationTargetException');
|
||||||
console.assert(message === undefined); //TODO
|
const target = any.get().TargetException;
|
||||||
//TODO: inspect wrapped css.uno.RuntimeException
|
console.assert(target.getType() == 'com.sun.star.uno.RuntimeException');
|
||||||
decrementExceptionRefcount(e);
|
const exc = target.get();
|
||||||
|
console.assert(exc.Message.startsWith('test'));
|
||||||
|
any.delete();
|
||||||
|
target.delete();
|
||||||
}
|
}
|
||||||
params.delete();
|
params.delete();
|
||||||
outparamindex.delete();
|
outparamindex.delete();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user