aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/embind/embind.js33
-rwxr-xr-xsystem/include/emscripten/bind.h2
-rwxr-xr-xsystem/lib/embind/bind.cpp48
3 files changed, 56 insertions, 27 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js
index e990c1a1..4ff84005 100755
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -497,6 +497,7 @@ function __embind_register_class(
classType,
pointerType,
constPointerType,
+ isPolymorphic,
name,
destructor
) {
@@ -580,17 +581,31 @@ function __embind_register_class(
registerType(pointerType, pointerName, {
name: pointerName,
fromWireType: function(ptr) {
- var dynamicType = ___getDynamicPointerType(ptr); // !!! this won't work if pointer is not dynamic
- if (dynamicType === null || dynamicType === pointerType) {
- return new Handle(ptr);
- }
- try {
- dynamicType = requireRegisteredType(dynamicType);
- } catch (err) {
+ if (isPolymorphic) {
+ var toType = ___getDynamicPointerType(ptr);
+ var toTypeImpl = null;
+ if (toType === null || toType === pointerType) {
+ return new Handle(ptr);
+ }
+ var derivation = Module.__getDerivationPath(toType, classType);
+ var candidate = null;
+ for (var i = 0; i < derivation.size(); i++) {
+ candidate = derivation.at(i);
+ toTypeImpl = typeRegistry[candidate];
+ if (toTypeImpl) {
+ break;
+ }
+ }
+ derivation.delete();
+ if (toTypeImpl === null) {
+ return new Handle(ptr);
+ }
+ var toTypePointerImpl = requireRegisteredType(toTypeImpl.pointerType);
+ var castPtr = ___dynamicPointerCast(ptr, classType, candidate);
+ return toTypePointerImpl.fromWireTypeStatic(castPtr);
+ } else {
return new Handle(ptr);
}
- dynamicType = requireRegisteredType(dynamicType.pointerType);
- return dynamicType.fromWireTypeStatic(ptr);
},
fromWireTypeStatic: function(ptr) {
return new Handle(ptr);
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 54c017ef..7dc34949 100755
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -103,6 +103,7 @@ namespace emscripten {
TYPEID classType,
TYPEID pointerType,
TYPEID constPointerType,
+ bool isPolymorphic,
const char* className,
GenericFunction destructor);
@@ -660,6 +661,7 @@ namespace emscripten {
TypeID<ClassType>::get(),
TypeID<AllowedRawPointer<ClassType>>::get(),
TypeID<AllowedRawPointer<const ClassType>>::get(),
+ std::is_polymorphic<ClassType>::value,
name,
reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
}
diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp
index 1fcf987a..9663ad51 100755
--- a/system/lib/embind/bind.cpp
+++ b/system/lib/embind/bind.cpp
@@ -27,7 +27,7 @@ namespace __cxxabiv1 {
return bases;
}
- void __getDerivationPaths1(const __class_type_info* dv, const __class_type_info* bs, std::vector<const __class_type_info*>path, std::vector<std::vector<const __class_type_info*>>& paths) {
+ void __getDerivationPaths(const __class_type_info* dv, const __class_type_info* bs, std::vector<const __class_type_info*>path, std::vector<std::vector<const __class_type_info*>>& paths) {
std::vector<const __class_type_info*> newPath(path);
newPath.emplace_back(dv);
if (dv == bs) {
@@ -35,7 +35,7 @@ namespace __cxxabiv1 {
} else {
std::vector<const __class_type_info*> bases = __getBaseClasses(dv);
for (int i = 0; i < bases.size(); i++) {
- __getDerivationPaths1(bases[i], bs, newPath, paths);
+ __getDerivationPaths(bases[i], bs, newPath, paths);
}
}
}
@@ -75,12 +75,10 @@ namespace emscripten {
// They are used by embind.js to implement automatic downcasting of return values which are pointers to
// polymorphic objects.
- // __getDerivationPaths returns an array of arrays of type_info pointers (cast as integers to make
- // the Javascript bindings simpler). Each element of the outer array is an array of type_info pointers
- // identifying a derivation path from the derived type to the base type. If either of the type info
- // pointer paramters does not specify a pointer to a class, or if there is no path from the derived type
- // to the base type, this routine returns zero.
- std::vector<std::vector<int>> __getDerivationPaths(int dv, const int bs) {
+ // __getDerivationPath returns an array of type_info pointers describing the derivation chain starting with
+ // the derived type and proceeding toward (and ending with) the base type. Types are only included if they
+ // appear on all possible derivation paths.
+ std::vector<int> __getDerivationPath(int dv, const int bs) {
std::vector<std::vector<const __cxxabiv1::__class_type_info*>> paths;
const std::type_info* dv1 = (std::type_info*)dv;
@@ -89,19 +87,33 @@ namespace emscripten {
const __cxxabiv1::__class_type_info* bs2 = dynamic_cast<const __cxxabiv1::__class_type_info*>(bs1);
if (dv2 && bs2) {
- __cxxabiv1::__getDerivationPaths1(dv2, bs2, std::vector<const __cxxabiv1::__class_type_info*>(), paths);
+ __cxxabiv1::__getDerivationPaths(dv2, bs2, std::vector<const __cxxabiv1::__class_type_info*>(), paths);
}
- std::vector<std::vector<int>> pathsAsTypeInfo;
- for (int i = 0; i < paths.size(); i++) {
- std::vector<int> pathAsTypeInfo;
- for (int j = 0; j < paths[i].size(); j++) {
- pathAsTypeInfo.emplace_back((int)paths[i][j]);
+ std::vector<int> derivationPath;
+ if (paths.size() > 0) {
+ for (int j = 0; j < paths[0].size(); j++) {
+ bool disqualified = false;
+ for (int i = 1; i < paths.size(); i++) {
+ bool found = false;
+ for (int j2 = 0; j2 < paths[i].size(); j2++) {
+ if (paths[i][j2] == paths[0][j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ disqualified = true;
+ break;
+ }
+ }
+ if (!disqualified) {
+ derivationPath.emplace_back((int)paths[0][j]);
+ }
}
- pathsAsTypeInfo.emplace_back(pathAsTypeInfo);
}
- return pathsAsTypeInfo;
+ return derivationPath;
}
// __getDynamicPointerType returns (for polymorphic types only!) the type of the instance actually
@@ -141,10 +153,10 @@ namespace emscripten {
}
EMSCRIPTEN_BINDINGS(([]() {
- // We bind __getDerivationPaths in order to take advantage of the std::vector to Javascript array
+ // We bind __getDerivationPath in order to take advantage of the std::vector to Javascript array
// conversion for the return value. This has the unfortunate side-effect of exposing it to third party
// developers, but perhaps the double underscore will scare them away from calling it.
- function("__getDerivationPaths", &__getDerivationPaths);
+ function("__getDerivationPath", &__getDerivationPath);
}));