diff options
author | Chad Austin <chad@imvu.com> | 2013-03-20 20:15:36 -0700 |
---|---|---|
committer | Jukka Jylänki <jujjyl@gmail.com> | 2013-04-12 14:26:32 +0300 |
commit | e10ede1e07ee85d9d99bd34eb4ec8a62ae972616 (patch) | |
tree | 4bad80cb9e227d265333b979d5e938221c117cf1 | |
parent | 0a6f5476f19792164e122c27ffca83baa69c1ca3 (diff) |
Add sensible error messages when working with classes that depend on unbound types.
-rwxr-xr-x | src/embind/embind.js | 172 | ||||
-rwxr-xr-x | system/lib/embind/bind.cpp | 37 |
2 files changed, 128 insertions, 81 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index c27c49b2..ddfc4d43 100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -3,6 +3,7 @@ /*global FUNCTION_TABLE, HEAP32, HEAPU8*/ /*global Pointer_stringify*/ /*global __emval_register, _emval_handle_array, __emval_decref*/ +/*global ___getTypeName*/ var InternalError = Module.InternalError = extendError(Error, 'InternalError'); var BindingError = Module.BindingError = extendError(Error, 'BindingError'); @@ -45,6 +46,13 @@ function exposePublicSymbol(name, value) { Module[name] = value; } +function replacePublicSymbol(name, value) { + if (!Module.hasOwnProperty(name)) { + throwInternalError('Replacing nonexistant public symbol'); + } + Module[name] = value; +} + // from https://github.com/imvu/imvujs/blob/master/src/error.js function extendError(baseErrorType, errorName) { var errorClass = createNamedFunction(errorName, function(message) { @@ -165,7 +173,10 @@ function whenDependentTypesAreResolved(myTypes, dependentTypes, getTypeConverter } function getTypeName(type) { - return Module._embind_getTypeName(type); + var ptr = ___getTypeName(type); + var rv = Pointer_stringify(ptr); + _free(ptr); + return rv; } function heap32VectorToArray(count, firstElement) { @@ -317,16 +328,12 @@ function __embind_register_function(name, argCount, rawArgTypesAddr, rawInvoker, name = Pointer_stringify(name); rawInvoker = FUNCTION_TABLE[rawInvoker]; - var invoker = function() { - throwUnboundTypeError('Cannot call ' + name + ' due to unbound types', argTypes); - }; - exposePublicSymbol(name, function() { - return invoker.apply(this, arguments); + throwUnboundTypeError('Cannot call ' + name + ' due to unbound types', argTypes); }); whenDependentTypesAreResolved([], argTypes, function(argTypes) { - invoker = makeInvoker(name, argCount, argTypes, rawInvoker, fn); + replacePublicSymbol(name, makeInvoker(name, argCount, argTypes, rawInvoker, fn)); return []; }); } @@ -800,6 +807,11 @@ function __embind_register_class( downcast = FUNCTION_TABLE[downcast]; var legalFunctionName = makeLegalFunctionName(name); + exposePublicSymbol(legalFunctionName, function() { + // this code cannot run if baseClassRawType is zero + throwUnboundTypeError('Cannot construct ' + name + ' due to unbound types', [baseClassRawType]); + }); + whenDependentTypesAreResolved( [rawType, rawPointerType, rawConstPointerType], baseClassRawType ? [baseClassRawType] : [], @@ -868,7 +880,7 @@ function __embind_register_class( constPointerType: constPointerConverter }; - exposePublicSymbol(legalFunctionName, constructor); + replacePublicSymbol(legalFunctionName, constructor); return [referenceConverter, pointerConverter, constPointerConverter]; } @@ -885,26 +897,33 @@ function __embind_register_class_constructor( var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); invoker = FUNCTION_TABLE[invoker]; - whenDependentTypesAreResolved([], [rawClassType].concat(rawArgTypes), function(argTypes) { - var classType = argTypes[0]; - argTypes = argTypes.slice(1); + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; var humanName = 'constructor ' + classType.name; - classType.registeredClass.constructor_body = function() { - if (arguments.length !== argCount - 1) { - throwBindingError(humanName + ' called with ' + arguments.length + ' arguments, expected ' + (argCount-1)); - } - var destructors = []; - var args = new Array(argCount); - args[0] = rawConstructor; - for (var i = 1; i < argCount; ++i) { - args[i] = argTypes[i].toWireType(destructors, arguments[i - 1]); - } - - var ptr = invoker.apply(null, args); - runDestructors(destructors); - return argTypes[0].fromWireType(ptr); + classType.registeredClass.constructor_body = function() { + throwUnboundTypeError('Cannot construct ' + classType.name + ' due to unbound types', rawArgTypes); }; + + whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + classType.registeredClass.constructor_body = function() { + if (arguments.length !== argCount - 1) { + throwBindingError(humanName + ' called with ' + arguments.length + ' arguments, expected ' + (argCount-1)); + } + var destructors = []; + var args = new Array(argCount); + args[0] = rawConstructor; + for (var i = 1; i < argCount; ++i) { + args[i] = argTypes[i].toWireType(destructors, arguments[i - 1]); + } + + var ptr = invoker.apply(null, args); + runDestructors(destructors); + + return argTypes[0].fromWireType(ptr); + }; + return []; + }); return []; }); } @@ -961,32 +980,39 @@ function __embind_register_class_function( rawInvoker = FUNCTION_TABLE[rawInvoker]; memberFunction = copyMemberPointer(memberFunction, memberFunctionSize); - whenDependentTypesAreResolved([], [rawClassType].concat(rawArgTypes), function(argTypes) { - var classType = argTypes[0]; - argTypes = argTypes.slice(1); + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; var humanName = classType.name + '.' + methodName; + classType.registeredClass.instancePrototype[methodName] = function() { - if (arguments.length !== argCount - 1) { - throwBindingError('emscripten binding method ' + humanName + ' called with ' + arguments.length + ' arguments, expected ' + (argCount-1)); - } + throwUnboundTypeError('Cannot call ' + humanName + ' due to unbound types', rawArgTypes); + }; - var ptr = validateThis(this, classType, humanName); - if (!isConst && this.$$.ptrType.isConst) { - throwBindingError('Cannot call non-const method ' + humanName + ' on const reference'); - } + whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + classType.registeredClass.instancePrototype[methodName] = function() { + if (arguments.length !== argCount - 1) { + throwBindingError('emscripten binding method ' + humanName + ' called with ' + arguments.length + ' arguments, expected ' + (argCount-1)); + } - var destructors = []; - var args = new Array(argCount + 1); - args[0] = ptr; - args[1] = memberFunction; - for (var i = 1; i < argCount; ++i) { - args[i + 1] = argTypes[i].toWireType(destructors, arguments[i - 1]); - } - var rv = rawInvoker.apply(null, args); - rv = argTypes[0].fromWireType(rv); - runDestructors(destructors); - return rv; - }; + var ptr = validateThis(this, classType, humanName); + if (!isConst && this.$$.ptrType.isConst) { + throwBindingError('Cannot call non-const method ' + humanName + ' on const reference'); + } + + var destructors = []; + var args = new Array(argCount + 1); + args[0] = ptr; + args[1] = memberFunction; + for (var i = 1; i < argCount; ++i) { + args[i + 1] = argTypes[i].toWireType(destructors, arguments[i - 1]); + } + var rv = rawInvoker.apply(null, args); + rv = argTypes[0].fromWireType(rv); + runDestructors(destructors); + return rv; + }; + return []; + }); return []; }); } @@ -999,13 +1025,21 @@ function __embind_register_class_class_function( rawInvoker, fn ) { - var classType = requireRegisteredType(rawClassType, 'class'); var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); methodName = Pointer_stringify(methodName); rawInvoker = FUNCTION_TABLE[rawInvoker]; - whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; var humanName = classType.name + '.' + methodName; - classType.registeredClass.constructor[methodName] = makeInvoker(humanName, argCount, argTypes, rawInvoker, fn); + + classType.registeredClass.constructor[methodName] = function() { + throwUnboundTypeError('Cannot call ' + humanName + ' due to unbound types', rawArgTypes); + }; + + whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + classType.registeredClass.constructor[methodName] = makeInvoker(humanName, argCount, argTypes, rawInvoker, fn); + return []; + }); return []; }); } @@ -1023,23 +1057,39 @@ function __embind_register_class_property( getter = FUNCTION_TABLE[getter]; setter = FUNCTION_TABLE[setter]; memberPointer = copyMemberPointer(memberPointer, memberPointerSize); - whenDependentTypesAreResolved([], [rawClassType, rawFieldType], function(converters) { - var classType = converters[0]; - var fieldType = converters[1]; + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; var humanName = classType.name + '.' + fieldName; + Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, { get: function() { - var ptr = validateThis(this, classType, humanName + ' getter'); - return fieldType.fromWireType(getter(ptr, memberPointer)); + throwUnboundTypeError('Cannot access ' + humanName + ' due to unbound types', [rawFieldType]); }, - set: function(v) { - var ptr = validateThis(this, classType, humanName + ' setter'); - var destructors = []; - setter(ptr, memberPointer, fieldType.toWireType(destructors, v)); - runDestructors(destructors); + set: function() { + throwUnboundTypeError('Cannot access ' + humanName + ' due to unbound types', [rawFieldType]); }, - enumerable: true + enumerable: true, + configurable: true + }); + + whenDependentTypesAreResolved([], [rawFieldType], function(fieldType) { + fieldType = fieldType[0]; + Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, { + get: function() { + var ptr = validateThis(this, classType, humanName + ' getter'); + return fieldType.fromWireType(getter(ptr, memberPointer)); + }, + set: function(v) { + var ptr = validateThis(this, classType, humanName + ' setter'); + var destructors = []; + setter(ptr, memberPointer, fieldType.toWireType(destructors, v)); + runDestructors(destructors); + }, + enumerable: true + }); + return []; }); + return []; }); } diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index a75ba96a..a5c878f5 100755 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -8,25 +8,24 @@ using namespace emscripten;
-static std::string _embind_getTypeName(intptr_t ti_raw) {
- auto ti = reinterpret_cast<const std::type_info*>(ti_raw);
- int stat;
- char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat);
- if (stat == 0) {
- std::string rv(demangled);
- free(demangled);
- return rv;
- }
+extern "C" {
+ const char* EMSCRIPTEN_KEEPALIVE __getTypeName(const std::type_info* ti) {
+ int stat;
+ char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat);
+ if (stat == 0 && demangled) {
+ return demangled;
+ }
- switch (stat) {
- case -1:
- return "<allocation failure>";
- case -2:
- return "<invalid C++ symbol>";
- case -3:
- return "<invalid argument>";
- default:
- return "<unknown error>";
+ switch (stat) {
+ case -1:
+ return strdup("<allocation failure>");
+ case -2:
+ return strdup("<invalid C++ symbol>");
+ case -3:
+ return strdup("<invalid argument>");
+ default:
+ return strdup("<unknown error>");
+ }
}
}
@@ -60,6 +59,4 @@ EMSCRIPTEN_BINDINGS(native_and_builtin_types) { _embind_register_cstring(TypeID<std::string>::get(), "std::string");
_embind_register_emval(TypeID<val>::get(), "emscripten::val");
-
- function("_embind_getTypeName", &_embind_getTypeName);
}
|