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

社会主义新天地 提交于 2020-01-02 02:12:07

问题


I have 2 C++ classes exposed as javascript classes, VanillaOption and NoomraEngine, both inheriting from ObjectWrap.

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

Handle<Value> 
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 ObjectWrap::Unwrap.

My question is how can I make sure that I've received the correct type in args[0] ?


回答1:


EDIT: a better method than the bare V8 one below is to use NanHasInstance (https://github.com/rvagg/nan#api_nan_has_instance)

In MyObject::Init:

Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
tpl->SetClassName(NanNew<String>("MyObject"));
...
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: https://github.com/petli/node-addon-examples/commit/d3e92cd060a26da2623690718e78f9005db060a8

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.




回答2:


Update: Since NanHasInstance has been deprecated, the new solution to this answer is to use bool FunctionTemplate::HasInstance(Local<Value> object). This function returns true if the given object is an instance of this function template.

Persistent<Function> Wrapper::constructor;
Persistent<FunctionTemplate> Wrapper::tpl;

Then in your Wrapper::Init() function, set the public Persistent object:

Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
// ...
Wrapper::tpl.Reset(isolate, tpl);

Now to unwrap:

Local<FunctionTemplate> wrapper_tpl = Wrapper::tpl.Get(isolate);
if (!(wrapper_tpl->HasInstance(args[0]))) {
  isolate->ThrowException(Exception::TypeError(
      String::NewFromUtf8(isolate, "Argument must be a Wrapper object")));
  return;
}
// Now we are safe to call ObjectWrap::Unwrap



回答3:


node::Buffer::HasInstance(args[0]);

Also see: http://www.lamedoc.com/node.js/classnode_1_1Buffer.html#a4cc6fa734527df461641c6e93e6d1197



来源:https://stackoverflow.com/questions/8994196/how-to-check-for-correct-type-when-calling-objectwrapunwrap-in-a-nodejs-add-on

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!