I'm creating a node.js addon, which has bunch of classes. I want to organize them in a hierarchical namespace. If I were doing this in Javascript it would look like this
var com = function() {};
com.example = function() {};
com.example.Person = function () {};
var p = new com.example.Person();
I'm using Nan to write my node.js binding. To achieve the above result I've written code as follows:
com.h
namespace addon {
void init(Local<Object> exports);
}
com.cpp
void addon::init(Local<Object> exports)
{
addon::Example::Init(exports);
}
NODE_MODULE(com, com::init)
example.h
namespace addon {
class Example : public Nan::ObjectWrap {
static void Init(v8::Local<v8::Object> exports);
}
}
example.cpp
void addon::Example::Init(v8::Local<v8::Object> exports) {
// Prepare constructor template
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("example").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
addon::Person::Init(tpl);
constructor.Reset(tpl->GetFunction());
}
person.h
namespace addon {
class Person : public Nan::ObjectWrap {
static void Init(v8::Local<v8::FunctionTemplate> exports);
}
}
person.cpp
void addon::Person::Init(v8::Local<v8::FunctionTemplate> nmspace) {
Nan::HandleScope scope;
// Prepare constructor template
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Person").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
// ...
constructor.Reset(tpl->GetFunction());
nmspace->Set(Nan::New("Person").ToLocalChecked(), tpl->GetFunction()); // XXXXXX
}
This code compiles and also successfully passes the tests when run. However I get a warning when the addon is loaded.
(node) v8::FunctionTemplate::Set() with non-primitive values is deprecated
(node) and will stop working in the next major release.
It prints a stack trace. The top of this trace is at the line marked XXXXXX
.
If this is not the recommended way to define a FunctionTemplate as a member of another FunctionTemplate, then what's the right way to achieve it? Any ideas?
I found an easy way to do this. It occured to me that I could achieve the same thing with the following Javascript code.
var com = {};
com.example = {};
com.example.Person = function () {};
var p = new com.example.Person();
So I found that it's totally unnecessary to define a ObjectWrap class for Example. Instead I defined it as a simple object
v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::Handle<Object> example = v8::Object::New(isolate);
and then passed it to Person::Init()
like this
void addon::Person::Init(v8::Local<v8::Object> nmspace) {
// ...
nmspace->Set(Nan::New("Person").ToLocalChecked(), tpl->GetFunction());
}
The resulting code works without any warnings or errors.