On Wed, Apr 24, 2013 at 1:07 AM, Mike Moening <[email protected]> wrote:
> Ben,
>
> Can you expand on your example?
> I'm sure this is piece of cake for you, but I'm not getting what you mean.
>
> All the samples I can find show using ObjectTemplate and the
> SetCallAsFunctionHandler() to handle construction from the C++ side.
>
> var o = new MyObject();
> var x = new MyObject();
> o.doSomething(x);
>
> In the above example doSomething() needs to simply validate its 1st argument
> is of type "MyObject".
> That's it.
>
> Apparently HasInstance() (from FunctionTemplate) is for this purpose.
> But ObjectTemplate doesn't have a HasInstance() method.
>
> My object has to do more than just be constructed.
> It's got other methods too.
> How can I fire a C++ constructor function with a FunctionTemplate and have
> other methods on the object?
> Without a more concrete example I'm lost.
>
> I do appreciate the willingness to help. THANK YOU.
This is in a nutshell how you use FunctionTemplate to create a
constructor + prototype methods:
Local<FunctionTemplate> t = FunctionTemplate::New(MyObject::New);
t->SetClassName(String::New("MyObject"));
t->InstanceTemplate()->SetInternalFieldCount(1);
Local<FunctionTemplate> fn = FunctionTemplate::New(MyObject::Foo);
t->PrototypeTemplate()->Set(String::New("foo"), fn);
my_object_template = Persistent<FunctionTemplate>::New(t);
The constructor looks something like this:
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope handle_scope;
if (args.IsConstructCall() === false) {
// Handle non-constructor invocation, i.e. `MyObject()`
Local<Function> constructor = my_object_template->GetFunction();
return handle_scope.Close(constructor->NewInstance(0, NULL));
}
MyObject* instance = new MyObject;
args.This()->SetAlignedPointerInInternalField(0, instance);
return args.This();
}
The foo() method:
Handle<Value> MyObject::Foo(const Arguments& args) {
HandleScope handle_scope;
void* pointer = args.This()->GetAlignedPointerFromInternalField(0);
MyObject* instance = static_cast<MyObject*>(pointer);
// do whatever
return handle_scope.Close(...);
}
The trick I mentioned in my other post is that you add a second
internal field that points to some atom (usually a char
class_name_id[] = "MyClassName") that you check for in your prototype
methods so you can be sure that args.This() is what you expect it to
be. Be sure to check args.This()->InternalFieldCount() as well.
We don't use that trick in node.js actually but that's because native
objects are not exposed directly, there's (almost) always some pure JS
object sitting in front of it. It's a pretty good approach when
you're not operating in a hostile environment (running untrusted
code), it saves a lot of headaches.
--
--
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.