Skip to content

Instantly share code, notes, and snippets.

@gabrielschulhof
Last active July 6, 2018 13:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gabrielschulhof/43abe2c9686a1c0b19fcf4784fa796ae to your computer and use it in GitHub Desktop.
Save gabrielschulhof/43abe2c9686a1c0b19fcf4784fa796ae to your computer and use it in GitHub Desktop.
GC behaviour wrt. native function vs. plain object vs. JS function
#include <stdio.h>
#include <node.h>
class WeakRef {
public:
WeakRef(v8::Isolate* isolate, v8::Local<v8::Value> func, const char* string):
string_(string) {
pers_.Reset(isolate, func);
pers_.SetWeak(this, DeleteMe, v8::WeakCallbackType::kParameter);
}
~WeakRef() {
fprintf(stderr, "%s is dying\n", string_);
pers_.ClearWeak();
pers_.Reset();
}
static void DeleteMe(const v8::WeakCallbackInfo<WeakRef>& info) {
delete info.GetParameter();
}
private:
v8::Persistent<v8::Value> pers_;
const char* string_;
};
static void TheFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
}
static void MakeFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Function> the_function =
v8::Function::New(context, TheFunction).ToLocalChecked();
// Produce a message on stderr when this function is gc-ed.
new WeakRef(isolate, the_function, "generated function");
info.GetReturnValue().Set(the_function);
}
static void TrackJSFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
// Produce a message on stderr when this function is gc-ed.
new WeakRef(info.GetIsolate(), info[0], "JS function");
}
static void Init(v8::Local<v8::Object> exports,
v8::Local<v8::Value> module,
v8::Local<v8::Context> context) {
v8::Isolate* isolate = context->GetIsolate();
NODE_SET_METHOD(exports, "makeFunction", MakeFunction);
NODE_SET_METHOD(exports, "trackJSFunction", TrackJSFunction);
v8::Local<v8::Object> object = v8::Object::New(context->GetIsolate());
// Produce on message on stderr when this object is gc-ed.
new WeakRef(isolate, object, "object");
exports->Set(context,
v8::String::NewFromUtf8(isolate,
"theObject",
v8::NewStringType::kNormal)
.ToLocalChecked(),
object).FromJust();
}
NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, Init)
'targets': [
{
'target_name': 'binding',
'sources': [ 'binding.cc' ]
}
]
}
// Run with node --expose-gc index.js
const binding = require('./build/Release/binding');
let theFunction = binding.makeFunction();
let object = binding.theObject;
let functionToTrack = function functionToTrack() {};
binding.trackJSFunction(functionToTrack);
delete binding.theObject;
theFunction = null;
functionToTrack = null;
object = null;
gc();
{
"name": "native-function-gc",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "Apache-2.0"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment