diff options
-rw-r--r-- | src/embind/embind.js | 105 | ||||
-rw-r--r-- | system/include/emscripten/bind.h | 14 | ||||
-rw-r--r-- | tests/embind/embind.test.js | 11 |
3 files changed, 74 insertions, 56 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index 4821c77b..57178810 100644 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -1614,53 +1614,6 @@ function __embind_register_class_function( }); } -function __embind_register_class_class_function( - rawClassType, - methodName, - argCount, - rawArgTypesAddr, - invokerSignature, - rawInvoker, - fn -) { - var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); - methodName = readLatin1String(methodName); - rawInvoker = requireFunction(invokerSignature, rawInvoker); - whenDependentTypesAreResolved([], [rawClassType], function(classType) { - classType = classType[0]; - var humanName = classType.name + '.' + methodName; - - var unboundTypesHandler = function() { - throwUnboundTypeError('Cannot call ' + humanName + ' due to unbound types', rawArgTypes); - }; - - var proto = classType.registeredClass.constructor; - if (undefined === proto[methodName]) { - // This is the first function to be registered with this name. - unboundTypesHandler.argCount = argCount-1; - proto[methodName] = unboundTypesHandler; - } else { - // There was an existing function with the same name registered. Set up a function overload routing table. - ensureOverloadTable(proto, methodName, humanName); - proto[methodName].overloadTable[argCount-1] = unboundTypesHandler; - } - - whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { - // Replace the initial unbound-types-handler stub with the proper function. If multiple overloads are registered, - // the function handlers go into an overload table. - var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */); - var func = craftInvokerFunction(humanName, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn); - if (undefined === proto[methodName].overloadTable) { - proto[methodName] = func; - } else { - proto[methodName].overloadTable[argCount-1] = func; - } - return []; - }); - return []; - }); -} - function __embind_register_class_property( classType, fieldName, @@ -1730,6 +1683,64 @@ function __embind_register_class_property( }); } +function __embind_register_class_class_function( + rawClassType, + methodName, + argCount, + rawArgTypesAddr, + invokerSignature, + rawInvoker, + fn +) { + var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); + methodName = readLatin1String(methodName); + rawInvoker = requireFunction(invokerSignature, rawInvoker); + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; + var humanName = classType.name + '.' + methodName; + + var unboundTypesHandler = function() { + throwUnboundTypeError('Cannot call ' + humanName + ' due to unbound types', rawArgTypes); + }; + + var proto = classType.registeredClass.constructor; + if (undefined === proto[methodName]) { + // This is the first function to be registered with this name. + unboundTypesHandler.argCount = argCount-1; + proto[methodName] = unboundTypesHandler; + } else { + // There was an existing function with the same name registered. Set up a function overload routing table. + ensureOverloadTable(proto, methodName, humanName); + proto[methodName].overloadTable[argCount-1] = unboundTypesHandler; + } + + whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + // Replace the initial unbound-types-handler stub with the proper function. If multiple overloads are registered, + // the function handlers go into an overload table. + var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */); + var func = craftInvokerFunction(humanName, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn); + if (undefined === proto[methodName].overloadTable) { + proto[methodName] = func; + } else { + proto[methodName].overloadTable[argCount-1] = func; + } + return []; + }); + return []; + }); +} + +function __embind_create_inheriting_constructor(constructorName, wrapperType) { + constructorName = readLatin1String(constructorName); + wrapperType = requireRegisteredType(wrapperType, 'wrapper'); + var registeredClass = wrapperType.registeredClass; + var wrapperPrototype = registeredClass.instancePrototype; + var ctor = createNamedFunction(constructorName, function() { + return new registeredClass.baseClass.constructor.implement(this); + }); + return __emval_register(ctor); +} + var char_0 = '0'.charCodeAt(0); var char_9 = '9'.charCodeAt(0); function makeLegalFunctionName(name) { diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 7399bd37..a0545f3f 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -172,6 +172,10 @@ namespace emscripten { GenericFunction invoker, GenericFunction method); + EM_VAL _embind_create_inheriting_constructor( + const char* constructorName, + TYPEID wrapperType); + void _embind_register_enum( TYPEID enumType, const char* name, @@ -988,9 +992,11 @@ namespace emscripten { } }; - template<typename PointerType, typename WrapperType> - val wrapped_extend(const val& properties) { - return val::undefined(); + template<typename WrapperType> + val wrapped_extend(const std::string& name, const val& properties) { + return val::take_ownership(_embind_create_inheriting_constructor( + name.c_str(), + TypeID<WrapperType>::get())); } }; @@ -1115,7 +1121,7 @@ namespace emscripten { allow_raw_pointer<ret_val>()) .class_function( "extend", - &wrapped_extend<PointerType, WrapperType>) + &wrapped_extend<WrapperType>) ; } diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 523cb1bc..f2e2b348 100644 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1641,16 +1641,17 @@ module({ }); BaseFixture.extend("new-style class inheritance", function() { - var Empty = cm.AbstractClass.extend({}); - // ENABLE THESE AS THEY PASS -/* + var Empty = cm.AbstractClass.extend("Empty", {}); + test("can extend, construct, and delete", function() { var instance = new Empty; instance.delete(); }); +/* ENABLE THESE AS THEY PASS + test("properties set in constructor are externally visible", function() { - var HasProperty = cm.AbstractClass.extend({ + var HasProperty = cm.AbstractClass.extend("AbstractClass", { initialize: function(x) { this.property = x; } @@ -1661,7 +1662,7 @@ module({ }); test("pass derived object to c++", function() { - var Implementation = cm.AbstractClass.extend({ + var Implementation = cm.AbstractClass.extend("AbstractClass", { abstractMethod: function() { return "abc"; }, |