Mastering Node: Addons and FunctionTemplate (uuid.node)

Last night, I pushed an addition to my fork of Mastering Node. I decided to add a bit to the Addons chapter. The first example in this chapter only shows how to add a function to a natively-compiled module (i.e. an addon). This example shows you how to start a module which can be used in the following way:

var Uuid = require('./uuid.node').Uuid;
var uuid = new Uuid();
var myId = uuid.generate();

The project files referenced in the following text can be downloaded from the repo: jimschubert/masteringnode


FunctionTemplate

In v8, a FunctionTemplate is used to create the equivalent to:

var template = function() { }

The function at this point is an object and not an instance of the function.

As an example, we will use the linux package uuid to generate a uuid. We will define the header for this addon as:

// addons/uuid/v0.1/uuid.h
#ifndef __node_uuid_h__
#define __node_uuid_h__

#include <string>
#include <v8.h>
#include <node.h>
#include "uuid/uuid.h"

using namespace v8;
using namespace node;

class Uuid : public node::ObjectWrap {
    public:
        Uuid() { }
        static Persistent<FunctionTemplate> constructor;
        static void Init(Handle<Object> target);
        static Handle<Value> New(const Arguments &args);
        static Handle<Value> Generate(const Arguments &args);
        static Handle<Value> GenerateRandom(const Arguments &args);
        static Handle<Value> GenerateTime(const Arguments &args);
    private:   
        ~Uuid();
        static std::string GetString(uuid_t id);
};

#endif // __node_uuid_h__

This addon will showcase three methods, Generate, GenerateRandom, and GenerateTime. It will also include a trivial private GetString method to demonstrate how to Unwrap a node::ObjectWrap object and interact with C++ code that is not specific to node or v8.

A lot of the public function definitions should look similar to the Echo example. One notable difference is that instead of using a macro and hiding the FunctionTemplate method, we are defining static Persistent constructor;. The Persistent type is used “when you need to keep a reference to an object for more than one function call, or when handle lifetimes do not correspond to C++ scopes.” source. Since we’d expect our object’s constructor to last longer than a single function, we declare it separately and as a persistent handle. Another point to notice is that all of the method we’re pulling from uuid.h have the signature static Handle Method(const Arguments &args) even though we will plan to call it as uuid.generate(). This is because we will be accessing the scope of the call via args.This().

Although more methods are implemented in uuid.cc, we will look at three:

Uuid::Init(Handle<Object> target)
Handle<Value> Uuid::New(const Arguments &args)
Handle<Value> Uuid::Generate(const Arguments &args)

Just as before, node expects to find a signature of extern "C" void init(Handle<Object> target) in order to initialize the addon. Inside this method, we may set parameters such as the version number from the previous example. We may also pass-through initialization to any modules within our node addon. In this example, our addon will be uuid.node and contain a single module, Uuid. There is no reason we can’t later add Uuid2 which, instead of returning a normalized string value might return a Buffer object. To initialize the Uuid module, we pass the target object along to Uuid::Init and add the module definition to target:

// addons/uuid/v0.1/uuid.cc
void Uuid::Init(Handle<Object> target) {
    HandleScope scope;

    // Setup the constructor
    constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Uuid::New));
    constructor->InstanceTemplate()->SetInternalFieldCount(1); // for constructors
    constructor->SetClassName(String::NewSymbol("Uuid"));

    // Setup the prototype
    NODE_SET_PROTOTYPE_METHOD(constructor, "generate", Generate);
    NODE_SET_PROTOTYPE_METHOD(constructor, "generateRandom", GenerateRandom);
    NODE_SET_PROTOTYPE_METHOD(constructor, "generateTime", GenerateTime);

    target->Set(String::NewSymbol("Uuid"), constructor->GetFunction());
}

In this scope, we are instantiating the constructor using Uuid::New as a new FunctionTemplate. We then call InstanceTemplate() and on that object we call SetInternalFieldCount(1). This tells v8 that this object holds a reference to one object.

Next, we setup the prototype using another macro provided by node. These calls say, for instance, “Add a method called generate to the constructor function which executes the native method Generate“.

Lastly, we have to create a “Uuid” module on the object returned by the call to require(). Here, Uuid will point to a function (constructor) which returns a function that internally executes Uuid::New. In other words, we have created something akin to:

var Uuid = function() { };
Uuid.constructor = function() {
    return function() {
        // Uuid::New executes here.
    }
}

Although the above is not exactly what we have done, it may provide a better view for some to understand FunctionTemplate references and why we assign one to the constructor object in such a way.

The Uuid::New method is defined as:

// addons/uuid/v0.1/uuid.cc
Handle<Value> Uuid::New(const Arguments &amp;args) {
    HandleScope scope;
    // no args are checked
    Uuid *uuid = new Uuid();
    uuid->Wrap(args.This());
    return args.This();
}

As you would expect, calling the constructor function multiple times will create newly-scoped Uuid objects on the heap. In this method, we wrap the parameter (scoped object) by setting a reference to Uuid in the args as a contextual scope (i.e. this) and then returns this.

Within the Generate method, we will want to unwrap the contextual Uuid object and call the private method GetString.

// addons/uuid/v0.1/uuid.cc
Handle<Value> Uuid::Generate(const Arguments &amp;args) {
    HandleScope scope;
    uuid_t id;
    uuid_generate(id);

    Uuid *uuid = ObjectWrap::Unwrap<Uuid>(args.This());
    return scope.Close(String::New(uuid->GetString(id).c_str()));
}

As with any JavaScript function call, we have to ensure functional scope. Scoped methods should create a HandleScope object at the start and call scope.Close() at the end. HandleScope will get rid of temporary handles when the scope is closed.

Within each of the Generate* methods, we will create a uuid_t type and call the corresponding method defined in /usr/includes/uuid/uuid.h (location may vary per system). To demonstrate accessing the pointer to our original Uuid object, we unwrap the contextual scope of this function using ObjectWrap::Unwrap(args.This()). From this pointer, we can access any private methods such as GetString. Be careful with your returned values, though. String::New in the v8 library does not take std::string in any of its signatures. Simply enough, std::string provides a c_str() method to return a const char* which String::New does accept.

uuid.node demo

Navigate to addons/uuid/v0.1/ and execute:

$ node-waf configure build

If there are build errors and the func.cc example from before built successfully, check that you have the uuid-dev package installed and rerun the above command. Then, navigate to build/default and try out the Uuid addon:

$ node
> var Uuid = require('./uuid.node').Uuid;
> var uuid = new Uuid();
> uuid.generate();
'83475e0c-212b-402c-bdc7-b81ebb7b34f8'
> uuid.generateRandom();
'4d597bda-8f5f-4c3c-b2fa-1cd6cd4a6903'
> uuid.generateTime();
'25a0dd30-5076-11e1-96be-0022fb93b24c'
> var util = require('util');
> util.inspect(uuid);
'{}'
> util.inspect(Uuid);
'[Function: Uuid]'
> 

The above output may surprise you. Firstly, where is the version option?! It’s at the required module level: require('./uuid.node').version;. Secondly, if we can access uuid.generate() and others, why don’t they display when inspecting the object? That’s because we defined those methods on the prototype:

> uuid.__proto__
{ generate: [Function: generate],
  generateRandom: [Function: generateRandom],
  generateTime: [Function: generateTime] }
>

Thirdly, you may have noticed that I didn’t say anything about constructor->SetClassName(String::NewSymbol("Uuid")); in Uuid::Init. You may have also wondered where SetClassName actually sets a class name, considering JavaScript is a prototypal language. That string value is what is displayed when you call inspect and get the value '[Function: Uuid]'. Just as you would expect, Uuid is the constructor and it is named Uuid.

Now, if you’ve played around with this a bit, you may have noticed that uuid.__proto__ gives us our three functions but uuid.prototype is empty. Why is that? That’s because uuid.__proto__ really is uuid.constructor.prototype, which is also really Uuid.prototype. This is the essence of prototypal inheritance. If this concept is foreign or difficult to grasp, be sure to check out the excellent explanation on JavaScript Garden.

Logically, the next step would be to understand how to declare a prototype of our own.

flattr this!