BigONotation BigONotation - 1 year ago 54
Node.js Question

How to check for correct type when calling ObjectWrap::Unwrap in a Nodejs add-on?

I have 2 C++ classes exposed as javascript classes,

, both inheriting from

In the following method in
, I m supposed to receive a previously "wrapped"

NoomraEngine::Price(const Arguments& args) {
HandleScope scope;
Local<Object> object = args[0]->ToObject(); // VanillaOption expected in args[0]

VanillaOption* equityOption = ObjectWrap::Unwrap<VanillaOption>(object);

Local<Number> x = Number::New(this->price(equityOption));
return scope.Close(x);

Everything works fine except that if I pass the wrong type to the method, node crashes in

My question is how can I make sure that I've received the correct type in

Answer Source

EDIT: a better method than the bare V8 one below is to use NanHasInstance (

In MyObject::Init:

Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
NanAssignPersistent(prototype, tpl);

where prototype is a static Persistent<FunctionTemplate> member of MyObject.

Use like this:

if (NanHasInstance(prototype, handle)) {
    MyObject* obj = ObjectWrap::Unwrap<MyObject>(handle);

With the caveat that this is my first go at writing a Node addon, I solved this exact problem by checking the prototype of the object with my own wrapper around UnWrap.

Here's a patch to the addon factory class demo showing the method:

It will only support factory-generated objects, and not ones where a constructor is exposed so that users could inherit from the base class. However, that could be generalised by walking the prototype chain.

In summary, it grabs hold of the reference to the expected class prototype in MyObject::Init:

Local<Object> obj = constructor->NewInstance();
prototype = Persistent<Value>::New(obj->GetPrototype());

And then checks that before dereferencing the object:

MyObject* MyObject::CheckedUnWrap(Handle<Object> handle)
  if (!handle.IsEmpty() && handle->InternalFieldCount() == 1) {
    Handle<Value> objproto = handle->GetPrototype();
    if (objproto == prototype) {
      // OK, this is us
      return ObjectWrap::Unwrap<MyObject>(handle);

  ThrowException(Exception::TypeError(String::New("<this> is not a MyObject")));
  return NULL;

All functions then use CheckedUnWrap instead:

Handle<Value> MyObject::PlusOne(const Arguments& args) {
  HandleScope scope;

  MyObject* obj = CheckedUnWrap(args.This());
  if (obj) {
    obj->counter_ += 1;
    return scope.Close(Number::New(obj->counter_));
  else {
    // Invalid type, an exception has been thrown so return an empty value
    return Handle<Value>();

I was also considering adding an internal field and set that to some some magic pointer, but then the code would have depended on that node::ObjectWrap wouldn't change how it uses the internal fields.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download