-
Notifications
You must be signed in to change notification settings - Fork 79
Node.js native module programming
- Application codes should be removed any node.js and v8 related definitions.
- it can use another languages for application code. e.g. C, Objective-C
- Node.js plug codes are almost for convert arguments and result of the native functions in pure C/C++.
- Explicitly use the namespace
node
andv8
andNan
withoutusing namespace node
orusing v8::XXX
as a glue code
Early days, v8 API was drastically changed incompatibly when version updated.
- type signature and returning result of native functions for
v8::FunctionTemplate
-
v8::Isolate
introduction and hiding from object construction - converting between native and v8 values
- ...
The nan was born for the layer of hiding the detail of v8 API.
But nan API is also changed when nan-2 that based on "maybe" returns. It is also reduced abstraction layers for old v8 used node-0.10 age.
The current node>=4 may apply only nan-2.
3 Handle (smart pointer) type exists as smart pointer of RAII (release the holding resource by its destructor)
-
v8::Local
: automatically managed byv8::HandleScope
-
v8::Persistent
: explicitly callReset(obj)
to hold orReset()
to release -
v8::Global
: for global scope, useReset(..)
same asPersistent
v8::HandleScope
instance is stacked memory manager for Local
handle.
-
v8::HandleScope scope
: make scope upon top ofHandleScope
stack. -
v8::Local<...> v = ...
: managed by stack top scope. the scope destructor release all managed handle
(The current v8 implicitly use HandleScope
just before call native function from JS code via v8::FunctionTemplate
, so explicit using HandleScope
is for using v8 functions from
outside of v8 call stacks: e.g. from multi threading, or from native event callbacks)
In v8 and nan, many function returns "maybe" value instead of throwing exceptions. You can check the result is exist or not via the "maybe" values, and can acquire the real value when existed.
In v8, two maybe types exist:
-
Maybe<native_type>
: is for a native value or "nothing" -
MaybeLocal<V8Type>
: is for a v8 objects viav8::Local
handle or "empty"
Maybe
methods:
- existence:
m.IsJust()
orm.IsNothing()
- acquire:
m.FromJust()
orm.FromMaybe(defaultVal)
MaybeLocal
methods:
- existence:
m.IsEmpty()
- acquire:
m.ToLocalChecked()
orm.FromMaybe(defaultObj)
use nan
-
char*
=>String
:Nan::New(s).ToLocalCheched()
-
String
=>char*
:char* s = *Nan::Utf8Value(str);
-
int32_t
=>Integer
:Nan::New<int32_t>(i)
-
Integer
=>int32_t
:Nan::To<int32_t>(v).FromJust()
-
uint32_t
=>Integer
:Nan::New<uint32_t>(i)
-
Integer
=>uint32_t
:Nan::To<uint32_t>(v).FromJust()
New
is the native method for constructor function
auto clazz = Nan::New(v8::FunctionTemplate>(New);
clazz->InstanceTemplate()->SetInternalFieldCount(1);
n
of SetInternalFieldCount(n)
is count of use SetInernalField(i, v)
(that is called inside
objectWrap->Wrap(self)
, so n
is 1
when holding only ObjectWrap
itself)
// prepare data struct for holding objects used in callback process
struct CallbackData {
v8::Persistent<v8::Object> thisObj;
std::unique_ptr<Nan::Callback> callback;
};
void callbackByUv(uv_poll_t* handle, int status, int events) {
HandleScope scope; // explicitly required because on outside of JS call chain
auto data = static_cast<CallbackData*>(handle->data); // get user data
uv_poll_stop(handle); // stop poll
// handle should delete in close callback (after closed)
// DON'T delete in uv callback!!
uv_close(reinterpret_cast<uv_handle_t*>(handle),
[](uv_handle_t* handle) -> void {delete handle;});
callbackCalling(data); //e.g. do some action for fd then call the callback by the action result)
// destroy callback data
data->thisObj.Reset(); // release thisObj
delete data; // callback will delete inside
}
NAN_METHOD(method) {
// prepare data used in the uv callback (after polled)
auto data = new CallbackData;
auto thisObj = info.Holder();
data->thisObj.Reset(thisObj);
data->callback.reset(new Nan::Callback(info[0].As<v8::Function>()));
int fd = acquireFd(thisObj); // get fd from Object
// poll fd
uv_poll_t* handle = new uv_poll_t;
handle->data = data;
uv_poll_init(uv_default_loop(), handle, fd);
uv_poll_start(handle, UV_READABLE, callbackByUv); // set callback
}
See the annotated native module examples for node-4 and nan-2: