setInternalFieldCount

932 views
Skip to first unread message

strattonbrazil

unread,
Jul 18, 2011, 7:18:25 PM7/18/11
to v8-users
I've read of the docs for v8 several times, but I'm having a hard time
understanding with the purpose of internal field counts.

From an the docs:

Handle<ObjectTemplate> point_templ = ObjectTemplate::New();
point_templ->SetInternalFieldCount(1);
Point* p = ...;
Local<Object> obj = point_templ->NewInstance();
obj->SetInternalField(0, External::New(p));

From what I understand, SetInternalFieldCount(1) tells the template
there will be one C++ object accessible from javascript, and
SetInternalField(0, External::New(p)) actually puts that C++ object
into the Local<Object> making it accessible to javascript, correct?

So, say for example, if I wanted to make 25 Point instances accessible
to javascript, I'd do something like:

Handle<ObjectTemplate> point_templ = ObjectTemplate::New();
point_templ->SetInternalFieldCount(25);
Point* p[] = ...; // 25 instances of Point
Local<Object> obj = point_templ->NewInstance();
for (int i = 0; i < 25; i++)
obj->SetInternalField(i, External::New(p[i]));

Is that correct? Does this need to be done on classes that return
other classes as return types? So if I setup a class template for
class A, if it returns a class B on a query, do I just need a template
for class B, or do I need to actually "expose" all the possible B's to
javascript first before making any calls to A that can return a B?

Stephan Beal

unread,
Jul 18, 2011, 8:02:58 PM7/18/11
to v8-u...@googlegroups.com
On Tue, Jul 19, 2011 at 1:18 AM, strattonbrazil <stratto...@gmail.com> wrote:
From what I understand, SetInternalFieldCount(1) tells the template
there will be one C++ object accessible from javascript, and

Almost - it tells v8 that you are reserving enough space for 1 (void *). What you do with that (void*) is your business. It doesn't have to be a bound C++ object (though it normally is).
 
SetInternalField(0, External::New(p)) actually puts that C++ object
into the Local<Object> making it accessible to javascript, correct?

Almost - it doesn't make the native available to JS, it makes it available to your C++ code which receives calls from JS.
 
So, say for example, if I wanted to make 25 Point instances accessible
to javascript, I'd do something like:

Handle<ObjectTemplate> point_templ = ObjectTemplate::New();
point_templ->SetInternalFieldCount(25);
Point* p[] = ...; // 25 instances of Point
Local<Object> obj = point_templ->NewInstance();
for (int i = 0; i < 25; i++)
  obj->SetInternalField(i, External::New(p[i]));

Is that correct?

That is technically legal but almost certainly _not_ what you want. JS cannot access those Point objects. It can only access obj, which itself contains a single Point[25].

 Does this need to be done on classes that return
other classes as return types?  So if I setup a class template for
class A, if it returns a class B on a query, do I just need a template
for class B, or do I need to actually "expose" all the possible B's to
javascript first before making any calls to A that can return a B?

i would first recommend reading through:


That explains the basics and shows you roughly what you need to do. The devil is in the details, though, and getting it "just right" can take a good deal of trial, error, and practice.

The mappings between C++ and JS objects are typically 1-to-1, so yes, you have expose each Point to JS separately (and store in in an InternalField). You also have to tell v8 how to access all of the native-side properties you want to be made available to JS. This is easy enough to do, but lots of it is repetitive and tedious, and i highly recommend using a framework designed to simplify that process. See:


for one such framework, and see the "Related Works" section on that page for links to several others.

--
----- stephan beal
http://wanderinghorse.net/home/stephan/

Stephan Beal

unread,
Jul 18, 2011, 8:06:12 PM7/18/11
to v8-u...@googlegroups.com
On Tue, Jul 19, 2011 at 2:02 AM, Stephan Beal <sgb...@googlemail.com> wrote:
On Tue, Jul 19, 2011 at 1:18 AM, strattonbrazil <stratto...@gmail.com> wrote:

Handle<ObjectTemplate> point_templ = ObjectTemplate::New();
point_templ->SetInternalFieldCount(25);
Point* p[] = ...; // 25 instances of Point
Local<Object> obj = point_templ->NewInstance();
for (int i = 0; i < 25; i++)
  obj->SetInternalField(i, External::New(p[i]));

Is that correct?

That is technically legal but almost certainly _not_ what you want. JS cannot access those Point objects. It can only access obj, which itself contains a single Point[25].

Sorry, i misinterpreted the code - i read it as stuffing p into a single field, and not p[i] into 25 internal fields. You could do what you've shown here, but it is still certainly not what you want to do (except for maybe some really weird exotic case). i've never personally seen a use case which would benefit from more than 2 internal fields, and even 2 is rather exotic in my experience.

Stephan Beal

unread,
Jul 18, 2011, 11:31:18 PM7/18/11
to v8-u...@googlegroups.com
On Tue, Jul 19, 2011 at 2:02 AM, Stephan Beal <sgb...@googlemail.com> wrote:
On Tue, Jul 19, 2011 at 1:18 AM, strattonbrazil <stratto...@gmail.com> wrote:
From what I understand, SetInternalFieldCount(1) tells the template
there will be one C++ object accessible from javascript, and

Almost - it tells v8 that you are reserving enough space for 1 (void *).
 
Correcting myself: it tells v8 that you are reserving space for one Handle<Value>. What you store in that slot is your own business, but in practically all cases they hold a v8::External, which holds a (void *).

Reply all
Reply to author
Forward
0 new messages