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

Reply via email to