Added a comment to the gist with one possible work-around for the inheritance issue:
https://gist.github.com/982157#gistcomment-31654 There must be a better way to deal with this though... Suggestions welcome. L. On 2011-05-19, at 9:34 PM, Laurie Harper wrote: > I put all the code into a gist which can be downloaded, built and tested > locally: > > $ git clone git://gist.github.com/982157.git > $ cd 982157 > $ node-waf configure build > $ node VectorTests.js > Vector is function Vector() { [native code] } > Vector.proto is [object Object] > v is { x: 1 } > v.x is 1 > v is { x: 9 } > v.x is 9 > Assertion failed: (handle->InternalFieldCount() > 0), function Wrap, file > /Users/laurie/.nvm/v0.4.5/include/node/node_object_wrap.h, line 61. > Abort trap > > L. > > On 2011-05-19, at 8:22 PM, Laurie Harper wrote: > >> Oops, there's a line missing from the JavaScript inheritance setup code; it >> should read: >> >> function f() {}; f.prototype = Vector.prototype; >> function g() { Vector.apply(this, arguments) } >> g.prototype = new f(); >> var v = new g(1,2,3); >> >> It's correct in my test suite, so my questions still stand... >> >> On 2011-05-19, at 4:31 PM, Laurie Harper wrote: >> >>> Hi, I posted these issues first to the Node mailing list as the errors I'm >>> seeing are coming from assertions in Node's API, but they appear to be a >>> direct result of how the v8 JavaScript <-> C++ bridge works, so I'm >>> bringing them here for further clarification. I'll include the full >>> stripped-down C++ code I'm testing with below. >>> >>> So far I have two problems, both of which I think stem from the same >>> underlying issue. The first is that if I set up accessors on the prototype >>> of my c++ proxy I'm unable to unwrap the internal field object; switching >>> from t->PrototypeTemplate()->SetAccessor() to >>> t->InstanceTemplate()->SetAccessor() resolved the problem (see commented >>> line in Initialize() in the code below. Strangely, setting a method on the >>> prototype seems to work just fine. So, question: why does it not work to >>> set an accessor on the prototype? >>> >>> The second problem comes when I try to set up inheritance in JavaScript >>> from an object defined in c++. I think I understand why this one fails, but >>> have no idea how to fix it... I'm using test code like this, where Vector >>> is defined in c++ as show below: >>> >>> function f() {}; f.prototype = Vector.prototype; >>> function g() { Vector.apply(this, arguments) } >>> var v = new g(1,2,3); >>> >>> That emulates a common pattern for inheritance in JavaScript to avoid >>> calling the base type constructor when setting up the prototype of the >>> inheriting class. I think the problem is that, since there is no explicit >>> 'new Vector' anywhere, the c++ instantiation logic isn't fired at the right >>> time. The result is that Arguments::This() returns an object of an >>> unexpected type (?) and wrapping/unwrapping the proxied object fails. So, >>> the question is how to adjust my code to work when a constructor is called >>> without the 'new' operator I think? >>> >>> Here's the test code I'm working with: >>> >>> *** Vector.h: >>> >>> class Vector: public node::ObjectWrap { >>> public: >>> static Persistent<FunctionTemplate> ctor; >>> static void Initialize(Handle<Object> target); >>> >>> static Handle<Value> GetX(Local<String> property, const AccessorInfo& >>> info); >>> static void SetX(Local<String> property, Local<Value> value, const >>> AccessorInfo& info); >>> >>> protected: >>> static Handle<Value> New(const Arguments &args); >>> Vector(btScalar &x, btScalar &y, btScalar &z); >>> >>> private: >>> btVector3* m_btVector3; >>> }; >>> >>> *** Vector.cc: >>> >>> Persistent<FunctionTemplate> Vector::ctor; >>> >>> void >>> Vector::Initialize(Handle<Object> target) { >>> HandleScope scope; >>> >>> ctor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New)); >>> ctor->InstanceTemplate()->SetInternalFieldCount(1); >>> ctor->SetClassName(String::NewSymbol("Vector")); >>> >>> // ctor->PrototypeTemplate()->SetAccessor(String::NewSymbol("x"), GetX, >>> SetX); >>> ctor->InstanceTemplate()->SetAccessor(String::NewSymbol("x"), GetX, SetX); >>> >>> target->Set(String::NewSymbol("Vector"), ctor->GetFunction()); >>> } >>> >>> Handle<Value> >>> Vector::New(const Arguments &args) { >>> float x, y, z; >>> HandleScope scope; >>> >>> if (args.Length() == 1 && args[0]->IsArray()) { >>> x = args[0]->ToObject()->Get(0)->NumberValue(); >>> y = args[0]->ToObject()->Get(1)->NumberValue(); >>> z = args[0]->ToObject()->Get(2)->NumberValue(); >>> } else { >>> x = args[0]->IsNumber() ? args[0]->NumberValue() : 0; >>> y = args[1]->IsNumber() ? args[1]->NumberValue() : 0; >>> z = args[2]->IsNumber() ? args[2]->NumberValue() : 0; >>> } >>> >>> Vector* obj = new Vector(x, y, z); >>> obj->Wrap(args.This()); >>> return args.This(); >>> } >>> >>> Vector::Vector(btScalar &x, btScalar &y, btScalar &z) { >>> m_btVector3 = new btVector3(x, y, z); >>> } >>> >>> Handle<Value> >>> Vector::GetX(Local<String> property, const AccessorInfo& info) { >>> HandleScope scope; >>> // Vector* v = ObjectWrap::Unwrap<Vector>(info.This()); // This vs. Holder? >>> Vector* v = ObjectWrap::Unwrap<Vector>(info.Holder()); // This vs. Holder? >>> Local<Number> result = Number::New(v->m_btVector3->getX()); >>> return scope.Close(result); >>> } >>> >>> void >>> Vector::SetX(Local<String> property, Local<Value> value, const >>> AccessorInfo& info) { >>> Vector* v = ObjectWrap::Unwrap<Vector>(info.Holder()); >>> v->m_btVector3->setX(value->NumberValue()); >>> } >>> >>> -- >>> Laurie Harper >>> http://laurie.holoweb.net/ >>> >>> -- >>> v8-users mailing list >>> [email protected] >>> http://groups.google.com/group/v8-users >> >> -- >> Laurie Harper >> http://laurie.holoweb.net/ >> >> -- >> v8-users mailing list >> [email protected] >> http://groups.google.com/group/v8-users > > -- > Laurie Harper > http://laurie.holoweb.net/ > > -- > v8-users mailing list > [email protected] > http://groups.google.com/group/v8-users -- Laurie Harper http://laurie.holoweb.net/ -- v8-users mailing list [email protected] http://groups.google.com/group/v8-users
