aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/embind/embind.js72
-rw-r--r--tests/embind/embind.test.js7
2 files changed, 63 insertions, 16 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js
index ef16e952..f9bfa9e8 100644
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -153,6 +153,30 @@ function _embind_repr(v) {
}
}
+// raw pointer -> instance
+var registeredInstances = {};
+
+function registerInheritedInstance(ptr, instance) {
+ if (registeredInstances.hasOwnProperty(ptr)) {
+ throwBindingError('Tried to register registered instance: ' + ptr);
+ } else {
+ registeredInstances[ptr] = instance;
+ }
+}
+
+function unregisterInheritedInstance(ptr) {
+ if (registeredInstances.hasOwnProperty(ptr)) {
+ delete registeredInstances[ptr];
+ } else {
+ throwBindingError('Tried to unregister unregistered instance: ' + ptr);
+ }
+}
+
+function getInheritedInstanceCount() {
+ return Object.keys(registeredInstances).length;
+}
+Module['getInheritedInstanceCount'] = getInheritedInstanceCount;
+
// typeID -> { toWireType: ..., fromWireType: ... }
var registeredTypes = {};
@@ -1152,6 +1176,13 @@ RegisteredPointer.prototype['fromWireType'] = function fromWireType(ptr) {
return null;
}
+ var registeredInstance = registeredInstances[rawPointer];
+ if (undefined !== registeredInstance) {
+ var rv = registeredInstance['clone']();
+ this.destructor(ptr);
+ return rv;
+ }
+
function makeDefaultHandle() {
if (this.isSmartPointer) {
return makeClassHandle(this.registeredClass.instancePrototype, {
@@ -1262,14 +1293,19 @@ ClassHandle.prototype['clone'] = function clone() {
throwInstanceAlreadyDeleted(this);
}
- var clone = Object.create(Object.getPrototypeOf(this), {
- $$: {
- value: shallowCopy(this.$$),
- }
- });
+ if (this.$$.preservePointerOnDelete) {
+ this.$$.count.value += 1;
+ return this;
+ } else {
+ var clone = Object.create(Object.getPrototypeOf(this), {
+ $$: {
+ value: shallowCopy(this.$$),
+ }
+ });
- clone.$$.count.value += 1;
- return clone;
+ clone.$$.count.value += 1;
+ return clone;
+ }
};
function runDestructor(handle) {
@@ -1285,16 +1321,21 @@ ClassHandle.prototype['delete'] = function ClassHandle_delete() {
if (!this.$$.ptr) {
throwInstanceAlreadyDeleted(this);
}
+
+ // TODO: test for multiple deleteLater() on JS instance handle
if (this.$$.deleteScheduled) {
throwBindingError('Object already scheduled for deletion');
}
this.$$.count.value -= 1;
- if (0 === this.$$.count.value) {
+ var toDelete = 0 === this.$$.count.value;
+ if (toDelete) {
runDestructor(this);
}
- this.$$.smartPtr = undefined;
- this.$$.ptr = undefined;
+ if (toDelete || !this.$$.preservePointerOnDelete) {
+ this.$$.smartPtr = undefined;
+ this.$$.ptr = undefined;
+ }
};
var deletionQueue = [];
@@ -1359,7 +1400,9 @@ function RegisteredClass(
function shallowCopy(o) {
var rv = {};
for (var k in o) {
- rv[k] = o[k];
+ if (Object.prototype.hasOwnProperty.call(o, k)) {
+ rv[k] = o[k];
+ }
}
return rv;
}
@@ -1764,16 +1807,21 @@ function __embind_create_inheriting_constructor(constructorName, wrapperType, pr
});
// It's a little nasty that we're modifying the wrapper prototype here.
+
wrapperPrototype.__construct = function __construct() {
var inner = baseConstructor.__$implement.apply(
undefined,
[this].concat(arraySlice.call(arguments)));
+ var $$ = inner.$$;
+ $$.preservePointerOnDelete = true;
Object.defineProperty(this, '$$', {
- value: inner.$$
+ value: $$
});
+ registerInheritedInstance($$.ptr, this);
};
wrapperPrototype.__destruct = function __destruct() {
+ unregisterInheritedInstance(this.$$.ptr);
};
ctor.prototype = Object.create(wrapperPrototype);
diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js
index e77a8a43..b174b52d 100644
--- a/tests/embind/embind.test.js
+++ b/tests/embind/embind.test.js
@@ -1776,6 +1776,7 @@ module({
},
__destruct: function() {
calls.push("__destruct");
+ this.__parent.__destruct.call(this);
}
});
var impl = new C;
@@ -1786,7 +1787,6 @@ module({
assert.deepEqual(["__destruct"], calls);
});
-/* does not pass yet
test("if JavaScript implementation of interface is returned, don't wrap in new handle", function() {
var parent = cm.HeldAbstractClass;
var C = parent.extend("C", {
@@ -1795,11 +1795,10 @@ module({
});
var impl = new C;
var rv = cm.passHeldAbstractClass(impl);
- assert.equal(impl, rv);
-
impl.delete();
+ assert.equal(impl, rv);
+ rv.delete();
});
-*/
});
BaseFixture.extend("registration order", function() {