Hi,
Calling JS code from a finalizer (e.g. with JS_Call) is not supported
and will only lead to problems. Finalizers should only be used to free
system resources and JS objects.
Best regards,
Fabrice.
On 1/10/20 8:08 AM, Eduard Suica (Redacted sender rokempes for DMARC) wrote:
Just tried this:
static void js_finalizer_finalizer(JSRuntime *rt, JSValue val) {
JSValueConst *argv2 = (JSValueConst *)JS_GetOpaque(val, js_finalizer_class_id);
if (argv2) {
// ==== > it crashes on the next line. It seems that argv2[0] and argv[1] get collected before the finalizer is called
JS_FreeValueCheckException(js_ctx, JS_Call(js_ctx, argv2[1], argv2[0], 1, argv2));
JS_FreeValueRT(rt, argv2[0]);
JS_FreeValueRT(rt, argv2[1]);
js_free(js_ctx, argv2);
}
}
static JSValue js_finalizer_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) {
if (argc != 2) {
JS_Error(ctx, "2 parameters expected");
}
JSValue proto = JS_GetPropertyStr(ctx, new_target, "prototype");
JSValue obj = JS_NewObjectProtoClass(ctx, proto, js_finalizer_class_id);
if (argc == 2) {
JSValueConst *argv2 = (JSValueConst *)js_malloc(ctx, sizeof(JSValueConst) * 2);
argv2[0] = JS_DupValueRT(JS_GetRuntime(ctx), argv[0]);
argv2[1] = JS_DupValueRT(JS_GetRuntime(ctx), argv[1]);
JS_SetOpaque(obj, argv2);
}
JS_FreeValue(ctx, proto);
return obj;
}
static void js_finalizer_gc_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) {
JSValueConst *argv2 = (JSValueConst *)JS_GetOpaque(val, js_finalizer_class_id);
if (argv2) {
JS_MarkValue(rt, argv2[0], mark_func);
JS_MarkValue(rt, argv2[1], mark_func);
}
}
static JSClassDef js_finalizer_class = {
"__finalizerContainer",
.finalizer = js_finalizer_finalizer,
.gc_mark = js_finalizer_gc_mark,
};
The javascript code for testing (crashes):
var obj = { };
var a = new __finalizerContainer(obj, function(self) {
console.log("finalize");
});
obj = undefined;
gc();
This code works:
function foo(self) {
console.log("finalize");
}
var obj = { };
var a = new __finalizerContainer(obj, foo);
obj = undefined;
gc();
GE.
On Thursday, January 9, 2020, 9:45:40 PM GMT+2, Koushik Dutta <koush@xxxxxxxxxxxxxxxx> wrote:
It's not possible to do it for an arbitrary object, as far as I know. But my workaround is to create a custom class that is a "finalizer object", and then attach as a (hidden) property to any arbitrary object. I can then use the finalizer object to observe when the arbitrary object gets collected. The finalizer object gets collected at the same time as the arbitrary object; just ensure that the finalizer object is only referenced by that object.
Koush
On Thu, Jan 9, 2020 at 11:26 AM Eduard Suica <dmarc-noreply@xxxxxxxxxxxxx <mailto:dmarc-noreply@xxxxxxxxxxxxx>> wrote:
Is possible to define a finalizer/destructor for an object?
Something like Duktape's fin function:
.fin(object, function(self) { ... } )
From the documentation: "When defining a new JS class, it is
possible to declare a finalizer which is called when the object is
destroyed. ".
Is this possible for an arbitrary object? If yes, how?
Great project,
GE.