Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 31 additions & 19 deletions src/embind/embind.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/*global typeDependencies, flushPendingDeletes, getTypeName, getBasestPointer, throwBindingError, UnboundTypeError, _embind_repr, registeredInstances, registeredTypes, getShiftFromSize*/
/*global ensureOverloadTable, embind__requireFunction, awaitingDependencies, makeLegalFunctionName, embind_charCodes:true, registerType, createNamedFunction, RegisteredPointer, throwInternalError*/
/*global simpleReadValueFromPointer, floatReadValueFromPointer, integerReadValueFromPointer, enumReadValueFromPointer, replacePublicSymbol, craftInvokerFunction, tupleRegistrations*/
/*global finalizationGroup, attachFinalizer, detachFinalizer, releaseClassHandle, runDestructor*/
/*global finalizationRegistry, attachFinalizer, detachFinalizer, releaseClassHandle, runDestructor*/
/*global ClassHandle, makeClassHandle, structRegistrations, whenDependentTypesAreResolved, BindingError, deletionQueue, delayFunction:true, upcastPointer*/
/*global exposePublicSymbol, heap32VectorToArray, new_, RegisteredPointer_getPointee, RegisteredPointer_destructor, RegisteredPointer_deleteObject, char_0, char_9*/
/*global getInheritedInstanceCount, getLiveInheritedInstances, setDelayFunction, InternalError, runDestructors*/
Expand Down Expand Up @@ -1722,38 +1722,50 @@ var LibraryEmbind = {
}
},

$finalizationGroup: false,
$finalizationRegistry: false,

$detachFinalizer_deps: ['$finalizationGroup'],
$detachFinalizer_deps: ['$finalizationRegistry'],
$detachFinalizer: function(handle) {},

$attachFinalizer__deps: ['$finalizationGroup', '$detachFinalizer',
$attachFinalizer__deps: ['$finalizationRegistry', '$detachFinalizer',
'$releaseClassHandle'],
$attachFinalizer: function(handle) {
if ('undefined' === typeof FinalizationGroup) {
if ('undefined' === typeof FinalizationRegistry) {
attachFinalizer = function (handle) { return handle; };
return handle;
}
// If the running environment has a FinalizationGroup (see
// If the running environment has a FinalizationRegistry (see
// https://github.com/tc39/proposal-weakrefs), then attach finalizers
// for class handles. We check for the presence of FinalizationGroup
// for class handles. We check for the presence of FinalizationRegistry
// at run-time, not build-time.
finalizationGroup = new FinalizationGroup(function (iter) {
for (var result = iter.next(); !result.done; result = iter.next()) {
var $$ = result.value;
if (!$$.ptr) {
console.warn('object already deleted: ' + $$.ptr);
} else {
releaseClassHandle($$);
}
}
finalizationRegistry = new FinalizationRegistry(function (info) {
#if ASSERTIONS
console.warn(info.leakWarning.stack.replace(/^Error: /, ''));
#endif
releaseClassHandle(info.$$);
});
attachFinalizer = function(handle) {
finalizationGroup.register(handle, handle.$$, handle.$$);
return handle;
var $$ = handle.$$;
var info = { $$: $$ };
#if ASSERTIONS
// Create a warning as an Error instance in advance so that we can store
// the current stacktrace and point to it when / if a leak is detected.
// This is more useful than the empty stacktrace of `FinalizationRegistry`
// callback.
var cls = $$.ptrType.registeredClass;
info.leakWarning = new Error("Embind found a leaked C++ instance " + cls.name + " <0x" + $$.ptr.toString(16) + ">.\n" +
"We'll free it automatically in this case, but this functionality is not reliable across various environments.\n" +
"Make sure to invoke .delete() manually once you're done with the instance instead.\n" +
"Originally allocated"); // `.stack` will add "at ..." after this sentence
Comment thread
kripken marked this conversation as resolved.
if ('captureStackTrace' in Error) {
Error.captureStackTrace(info.leakWarning, cls.constructor);
}
#endif
finalizationRegistry.register(handle, info, handle);
return handle;
};
detachFinalizer = function(handle) {
finalizationGroup.unregister(handle.$$);
finalizationRegistry.unregister(handle);
};
return attachFinalizer(handle);
},
Expand Down