Function::NewInstance calling Constructor

882 views
Skip to first unread message

Alex

unread,
Jan 28, 2009, 11:40:06 AM1/28/09
to v8-users
Apparently, calling Function::NewInstance calls the function. Really,
this sounds logical, but I need to work around it. Here's my
situation:
1. I create a FunctionTemplate (call it functionTemplate)
2. I add some fields to it (functionTemplate->InstanceTemplate()->Set)
3. I set the call handler (functionTemplate->SetCallHandler)
4. I call functionTemplate->GetFunction()->NewInstance() to get my
wrapper.

The problem is, I am trying to use the FunctionTemplate to wrap an
EXISTING object. The function FunctionTemplate wraps creates a NEW
one. I want to create the JavaScript instance, but not call the
function. I have tried calling functionTemplate->InstanceTemplate()-
>NewInstance(), but it does the same thing.

I know that I can create a normal object template for the object, in
addition to the function template, but that seems wasteful. Is there a
way around this?

Thanks,

Alex

vlad

unread,
Jan 28, 2009, 1:13:55 PM1/28/09
to v8-users
I have ran (and i'm currently running into more) issues with things
dealing with function constructor and instantiating new objects. I
have solved a few, and can possibly help you. But I'm not
understanding your questions very well.

From what I can tell, calling NewInstance() always calls the function
constructor. You can't scape it.

If you can re-state your question, I could be of more help.

Alex

unread,
Jan 28, 2009, 1:32:05 PM1/28/09
to v8-users
Thank you for your help.

There are two scenarios I need to address for any given type (for
instance, Point):

First, it should be possible to create the object from within
JavaScript, for instance: "var x = new Point(1, 5);"

Second, it should be possible to create the object from within C++,
and pass it to JavaScript.

Currently, my procedure is to create a single FunctionTemplate (say
pointTemplate). This template's InstanceTemplate has properties like x
and y. The function's callback is a C++ function which generates a new
object (for instance, it might be named Create_Point).

To allow creating objects from JavaScript, I add the function to the
global scope.
To wrap an object from C++, I call pointTemplate->GetFunction()-
>NewInstance().

The problem occurs when I call NewInstance. This causes the actual
function to be called, causing a new C++ Point to be created. I do not
want a new C++ point; instead, I want to wrap an existing one.

The only workaround I can think of is changing pointTemplate from a
FunctionTemplate to an ObjectTemplate, and creating an entirely
separate FunctionTemplate for use as a JavaScript constructor.

Thank you,

Alex

vlad

unread,
Jan 28, 2009, 2:47:39 PM1/28/09
to v8-users
The way I'm dealing with that is by declaring a function like such:

[CODE]
/**
* Get a new instance of this object.
*/
Handle<Object>
Point::instance(const Point3D& p)
{
// The ClassManager is a global which has a list of
instantiated FunctionTemplates
// ClassManager::getFunction() returns a Function from "Point"
FunctionTemplate.
Handle<Function> klass = TheClassManager->getFunction("Point");
v8::Handle<v8::Value> args[] = {
Number::New(p.x),
Number::New(p.y),
Number::New(p.z),
};

// Pass in the same arguments as it would be passed from
JavaScript
return klass->NewInstance(3, args);
}

...

Handle<Object> point = Point::instance(p);
[/CODE]

This is not the same as what you're asking, which is not to have to
create another Point object in the function's constructor. This WILL
still call the function's constructor. I don't know how to set another
constructor function, besides having another FunctionTemplate like you
mentioned.

After I implemented this, though, I thought it wasn't that bad. It's
basically doing what the JavaScript code would be doing; passing
arguments to the constructor function.

Matthias Ernst

unread,
Jan 28, 2009, 2:50:49 PM1/28/09
to v8-u...@googlegroups.com
I don't understand your problem and it sounds like a misunderstanding but anyways:

how "new" works in Javascript (and thus FunctionTemplate->function->NewInstance), it allocates a new object and then calls the function/constructor, passing as "this" the new object.

You can also just call the function and provide your own "this":
FunctionTemplate->function->Call(<your object>, 0, empty argv);


Matthias

Alex

unread,
Jan 28, 2009, 3:27:11 PM1/28/09
to v8-users
Vlad:
That would work under some circumstances, but unfortunately, not for
me. Although I've been using "Point"s in my example, the real classes
I am wrapping will (eventually) need to stay the same object (as it
has many connections aside from scripting ones).

What's interesting is that, looking through Chromium's code, I can't
quite tell what they do. They use a code generator, and it can be a
bit tricky to tell what code will be generated (I am browsing the
source online). However, it appears that they may simply use a
separate FunctionTemplate for JavaScript construction.

Thanks again for your help.


Matthias Ernst: I'm not trying to call the function. Quite the
opposite. I have a function meant to act like a constructor for type T
when called from JavaScript. However, it also functions as my object
template for objects of type T. As such, when I attempt to create a
new V8 object for my EXISTING T object (by using NewInstance), it
calls the constructor.

I think I have a workaround now, though. Thank you for your help.

vlad

unread,
Jan 28, 2009, 4:23:15 PM1/28/09
to v8-users
You could do this as well.

Instead of having the constructor function to create a new Point
whenever it's called, set it to call some globally accessible (or
better yet, class static) function which returns new Point *. You can
then have some flag that you can set before calling NewInstance(), in
which case it would return an existing object instead of a new one.
You would then reset the flag after calling NewInstance() to return
new Points again.

Alex

unread,
Jan 28, 2009, 4:36:38 PM1/28/09
to v8-users
That's similar to what I did do. My workaround (which, thankfully,
does work) makes the constructor function be a separate function
template. This function template has no instance properties or
methods, and is simply a function. When called with "new Point" in
JavaScript, the function simply creates a new Point in C++, and then
calls the point-wrapping function (the same one used to wrap any
existing point) to wrap the point in a V8 object. Finally, it returns
the wrapped point.

I think, actually, that I now have less code than before, and it seems
simpler too. If this is the "proper way," I think it should be
documented somewhere. Is it? If not, I'd be willing to document it if
someone would point me to the best place/way to do so.

Thanks,

Alex

vlad

unread,
Jan 28, 2009, 6:39:00 PM1/28/09
to v8-users
A user Sudjested in another thread that someone should create a V8
Cookbook. I have taken it upon myself to do that. If you want, you can
leave it up to me to document this by including it in that guide.

Alex

unread,
Jan 28, 2009, 6:42:55 PM1/28/09
to v8-users
A "Cookbook" sounds great! I'm interested in helping, if that is
possible. I'm already planning on writing a blog post about this and
other things (once I get a blog up and running).

vlad

unread,
Jan 28, 2009, 7:07:20 PM1/28/09
to v8-users
I'm currently writing the outline. I'll be posting it here for review
once I actually have something going. I definetly need the input of
the community to get anything decent written.

Victor Grishchenko

unread,
Jan 29, 2009, 5:04:11 AM1/29/09
to v8-u...@googlegroups.com
Yep, that was the second significant pitfall for me; I've got a memory
leak because of that. Basically, I worked it around. It is a
documentation
issue - the fact that the underlying C++ function gets called is not
obvious.

(The N1 pitfall was the Persistent(Handle) constructor semantics
which was not properly commented that days).

Could the cookbook be placed on the v8 wiki?
--

V

vlad

unread,
Jan 29, 2009, 7:35:37 AM1/29/09
to v8-users
"Could the cookbook be placed on the v8 wiki? "

Absolutely.

On Jan 29, 5:04 am, Victor Grishchenko <victor.grishche...@gmail.com>
wrote:

Alex

unread,
Jan 30, 2009, 12:27:04 PM1/30/09
to v8-users
I have made a blog post regarding the NewInstance/constructor topic:
http://create.tpsitulsa.com/blog/2009/01/29/v8-objects/

Feel free to use it. If you have any suggestions or corrections,
please tell me. Also, if the site crashes, please tell me. I only
finished it/put it live this morning.

Alex
Reply all
Reply to author
Forward
0 new messages