当调用ObjectWrap :: Unwrap在一个Nodejs加载项时如何检查正确的types?
我有2个C ++类公开为JavaScript类, VanillaOption
和NoomraEngine
,都从ObjectWrap
inheritance。
在NoomraEngine
的以下方法中,我应该收到一个以前“包装的” 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); }
一切工作正常,但如果我传递错误的types的方法,节点崩溃在ObjectWrap::Unwrap
。
我的问题是我如何确保我已经收到args[0]
正确的types?
编辑:比下面的裸V8更好的方法是使用NanHasInstance
( https://github.com/rvagg/nan#api_nan_has_instance )
在MyObject::Init
:
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); tpl->SetClassName(NanNew<String>("MyObject")); ... NanAssignPersistent(prototype, tpl);
其中prototype
是MyObject
的静态Persistent<FunctionTemplate>
成员。
像这样使用:
if (NanHasInstance(prototype, handle)) { MyObject* obj = ObjectWrap::Unwrap<MyObject>(handle); ... }
有一点需要注意的是,这是我第一次编写一个Node插件,我用自己的UnWrap
封装来检查对象的原型,从而解决了这个问题。
下面是插件工厂类演示的补丁,显示了该方法: https : //github.com/petli/node-addon-examples/commit/d3e92cd060a26da2623690718e78f9005db060a8
它只支持工厂生成的对象,而不支持公开构造函数的对象,以便用户可以inheritance基类。 但是,这可以通过走原型链来推广。
总之,它抓住在MyObject::Init
引用期望的类的原型:
Local<Object> obj = constructor->NewInstance(); prototype = Persistent<Value>::New(obj->GetPrototype());
然后在解引用对象之前检查:
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; }
所有函数然后使用CheckedUnWrap
代替:
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>(); } }
我也在考虑添加一个内部字段,并将其设置为一些魔术指针,但是代码将依赖于该node::ObjectWrap
不会改变它如何使用内部字段。
更新 :因为NanHasInstance
已被弃用,这个答案的新解决scheme是使用bool FunctionTemplate::HasInstance(Local<Value> object)
。 如果给定对象是此函数模板的一个实例,则此函数返回true。
Persistent<Function> Wrapper::constructor; Persistent<FunctionTemplate> Wrapper::tpl;
然后在你的Wrapper::Init()
函数中,设置public Persistent对象:
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New); // ... Wrapper::tpl.Reset(isolate, tpl);
现在解开:
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
节点::缓冲:: HasInstance(参数[0]);
另见: http : //www.lamedoc.com/node.js/classnode_1_1Buffer.html#a4cc6fa734527df461641c6e93e6d1197