diff options
-rwxr-xr-x | src/embind/embind.js | 25 | ||||
-rwxr-xr-x | system/include/emscripten/bind.h | 25 | ||||
-rwxr-xr-x | tests/embind/embind.test.js | 10 | ||||
-rw-r--r-- | tests/embind/embind_test.cpp | 1 |
4 files changed, 49 insertions, 12 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index ee717f4b..03af7010 100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -1154,42 +1154,47 @@ function __embind_register_class_class_function( } function __embind_register_class_property( - rawClassType, + classType, fieldName, - rawFieldType, + getterReturnType, getter, + getterContext, + setterArgumentType, setter, - context + setterContext ) { fieldName = Pointer_stringify(fieldName); getter = FUNCTION_TABLE[getter]; setter = FUNCTION_TABLE[setter]; - whenDependentTypesAreResolved([], [rawClassType], function(classType) { + + whenDependentTypesAreResolved([], [classType], function(classType) { classType = classType[0]; var humanName = classType.name + '.' + fieldName; Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, { get: function() { - throwUnboundTypeError('Cannot access ' + humanName + ' due to unbound types', [rawFieldType]); + throwUnboundTypeError('Cannot access ' + humanName + ' due to unbound types', [getterReturnType, setterArgumentType]); }, set: function() { - throwUnboundTypeError('Cannot access ' + humanName + ' due to unbound types', [rawFieldType]); + throwUnboundTypeError('Cannot access ' + humanName + ' due to unbound types', [getterReturnType, setterArgumentType]); }, enumerable: true, configurable: true }); - whenDependentTypesAreResolved([], [rawFieldType], function(fieldType) { - fieldType = fieldType[0]; + whenDependentTypesAreResolved([], [getterReturnType, setterArgumentType], function(types) { + var getterReturnType = types[0]; + var setterArgumentType = types[1]; + Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, { get: function() { var ptr = validateThis(this, classType, humanName + ' getter'); - return fieldType.fromWireType(getter(context, ptr)); + return getterReturnType.fromWireType(getter(getterContext, ptr)); }, set: function(v) { var ptr = validateThis(this, classType, humanName + ' setter'); var destructors = []; - setter(context, ptr, fieldType.toWireType(destructors, v)); + setter(setterContext, ptr, setterArgumentType.toWireType(destructors, v)); runDestructors(destructors); }, enumerable: true diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 57e44c0c..d70aec91 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -136,10 +136,12 @@ namespace emscripten { void _embind_register_class_property( TYPEID classType, const char* fieldName, - TYPEID fieldType, + TYPEID getterReturnType, GenericFunction getter, + void* getterContext, + TYPEID setterArgumentType, GenericFunction setter, - void* context); + void* setterContext); void _embind_register_class_class_function( TYPEID classType, @@ -980,11 +982,30 @@ namespace emscripten { fieldName, TypeID<FieldType>::get(), reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>), + getContext(field), + TypeID<FieldType>::get(), reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template setWire<ClassType>), getContext(field)); return *this; } + template<typename Getter, typename Setter> + class_& property(const char* fieldName, Getter getter, Setter setter) { + using namespace internal; + typedef GetterPolicy<Getter> GP; + typedef SetterPolicy<Setter> SP; + _embind_register_class_property( + TypeID<ClassType>::get(), + fieldName, + TypeID<typename GP::ReturnType>::get(), + reinterpret_cast<GenericFunction>(&GP::template get<ClassType>), + GP::getContext(getter), + TypeID<typename SP::ArgumentType>::get(), + reinterpret_cast<GenericFunction>(&SP::template set<ClassType>), + SP::getContext(setter)); + return *this; + } + template<typename ReturnType, typename... Args, typename... Policies> class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) { using namespace internal; diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 290fed72..82dbeb25 100755 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -837,6 +837,16 @@ module({ assert.equal(0, cm.count_emval_handles()); }); + test("class properties can be methods", function() { + var a = {}; + var b = {foo: 'foo'}; + var c = new cm.ValHolder(a); + assert.equal(a, c.val); + c.val = b; + assert.equal(b, c.val); + c.delete(); + }); + test("class instance $$ property is non-enumerable", function() { var c = new cm.ValHolder(undefined); assert.deepEqual([], Object.keys(c)); diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index 1384406a..f3e2cbee 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -1527,6 +1527,7 @@ EMSCRIPTEN_BINDINGS(tests) { .function("getConstVal", &ValHolder::getConstVal)
.function("getValConstRef", &ValHolder::getValConstRef)
.function("setVal", &ValHolder::setVal)
+ .property("val", &ValHolder::getVal, &ValHolder::setVal)
.class_function("makeConst", &ValHolder::makeConst, allow_raw_pointer<ret_val>())
.class_function("makeValHolder", &ValHolder::makeValHolder)
.class_function("some_class_method", &ValHolder::some_class_method)
|