Friday, 21 April 2017

How can I clean up C++ objects tracked in Local

I'm creating pure C++ objects (from C++ only) and then attaching them to JS-exposed objects returned as API wrapper instances. The means of attachment is using External::New stored via SetInternalField - pretty much following exactly the pattern outlined in the V8 Embedder's Guide.

These objects are intended to be memory-managed by JS, but even after dropping the references in JS and triggering garbage collection, the C++ objects remain. The destructors are not called, and if I save an independent reference elsewhere, it still works.

I think it makes sense that V8's cleanup of local values wouldn't know how (or whether) to destruct the contents of a void*, but isn't this a prominent use-case? There's no way I can find to hook in any way to the de-scoping/cleanup of externals or locals in general. Further, anything I do with persistents (like MakeWeak) aren't going to affect the locals that become unreachable on the JS side (right?).

How can I ensure that these C++ objects get eventually (preferably immediately) destroyed when the JS wrapper objects containing them fall out of scope?


Example instantiation that gets passed to JS:

Local<Value> createWindow(HWND handle, Isolate* isolate) {
    // Build an instance from a premade FunctionTemplate with object
    // and method prototypes, and SetInternalFieldCount(1)
    Local<Function> fn = Local<Function>::New(isolate, window);

    constructingInternally = true;
    Local<Object> obj = fn->NewInstance(Context::New(isolate)).ToLocalChecked();
    constructingInternally = false;

    CppWindow* win = CppWindow(handle);
    lastWin = win; // added for debugging
    obj->SetInternalField(0, External::New(isolate, win));
    return obj;
}



via HonoredMule

No comments:

Post a Comment