Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/embind/embind.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ var LibraryEmbind = {
$registeredPointers: {},

$registerType__deps: [
'$awaitingDependencies', '$registeredTypes',
'$awaitingDependencies', '$registeredTypes', '$getTypeName',
'$typeDependencies', '$throwBindingError',
'$whenDependentTypesAreResolved'],
$registerType__docs: '/** @param {Object=} options */',
Expand All @@ -319,6 +319,12 @@ var LibraryEmbind = {
}
}

#if MAIN_MODULE
// Store type name as well, which may or may not match the registered
// name, depending on mangling and the actual calls to register_foo.
registeredInstance.typeName = getTypeName(rawType);
#endif

registeredTypes[rawType] = registeredInstance;
delete typeDependencies[rawType];

Expand Down Expand Up @@ -416,6 +422,20 @@ var LibraryEmbind = {
$requireRegisteredType: function(rawType, humanName) {
var impl = registeredTypes[rawType];
if (undefined === impl) {
#if MAIN_MODULE
// Fallback, in case of shared libraries, where the TypeID (rawType)
// for each type is not stable across library boundaries.
var typeName = getTypeName(rawType);
for (const typeId in registeredTypes) {
var type = registeredTypes[typeId];
if (type.typeName == typeName) {
registerType(rawType, type, {
ignoreDuplicateRegistrations: true,
});
return type;
}
}
#endif
throwBindingError(humanName + " has unknown type " + getTypeName(rawType));
}
return impl;
Expand Down
4 changes: 4 additions & 0 deletions system/include/emscripten/wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ constexpr bool has_unbound_type_names = false;

namespace internal {

// Note: Neither CanonicalizedID nor the typeid-based approach
// is guaranteed to produce stable type ids across library
// boundaries. See core.test_dylink_typeid for more info.

typedef const void* TYPEID;

// We don't need the full std::type_info implementation. We
Expand Down
59 changes: 59 additions & 0 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5227,6 +5227,40 @@ def test_dylink_tls_export(self):
self.dylink_testf(test_file('core/test_dylink_tls_export.c'),
need_reverse=False)

@needs_dylink
@disabled('TypeID does not currently handle this')
def test_dylink_typeid(self):
# When the default visibility of the library's symbols is hidden,
# the type info is not merged, and we end up with different type
# ids in the shared library and the executable.
self.emcc_args.append('-fvisibility=hidden')
self.dylink_test(header=r'''
#include <emscripten/wire.h>

using namespace emscripten::internal;
struct SomeType {};
__attribute__((visibility("default"))) TYPEID getSomeTypeId();
''', main=r'''
#include "header.h"
#include <stdio.h>

int main() {
if (getSomeTypeId() != TypeID<SomeType>::get()) {
puts("type ids are not the same");
return 1;
}
puts("success");
return 0;
}
''', side=r'''
#include "header.h"
#include <stdio.h>

TYPEID getSomeTypeId() {
return TypeID<SomeType>::get();
}
''', expected=['success'], need_reverse=False)

def test_random(self):
src = r'''#include <stdlib.h>
#include <stdio.h>
Expand Down Expand Up @@ -7650,6 +7684,31 @@ def test_embind_no_rtti_followed_by_rtti(self):
self.emcc_args += ['-lembind', '-fno-rtti', '-frtti']
self.do_run(src, '418\ndotest returned: 42\n')

@needs_dylink
def test_embind_type_registration_when_typeid_is_not_stable(self):
# See test_dylink_typeid
self.emcc_args += ['-lembind', '-fvisibility=hidden']
self.dylink_test(header=r'''
#include <emscripten.h>
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include <stdio.h>
''', main=r'''
#include "header.h"
int main() {
emscripten::val intVal(42);
emscripten::val valVal(intVal);
puts("success");
return 0;
}
''', side=r'''
#include "header.h"
__attribute__((constructor)) void kaboom() {
emscripten::val intVal(42);
emscripten::val valVal(intVal);
}
''', expected=['success'], need_reverse=False)

@no_wasm64('webidl not compatible with MEMORY64 yet')
@parameterized({
'': ('DEFAULT', False),
Expand Down