Help representing a data structure in JS + how to get length to work for indexed object templates

19 views
Skip to first unread message

Jack

unread,
Aug 6, 2016, 12:01:47 PM8/6/16
to v8-users
Hey,

Currently I have a data structure that is a little something like this in C++:
Team (class with properties e.g. Name, ID, etc.)
    |____ Members (again has it's own properties, e.g. Name. Team holds a vector of pointers to Member objects.)

I want this to work like this in JS:
Team.Name gives the Team's name (same for ID, etc.)
Team.Members[0].Name gives the Team's first member's name (again same for other basic properties of the Member class.)


I can implement the basic Team class by creating an ObjectTemplate and binding a named property getter callback (this is done the same as the process.cc example, really) which will return things like Team.Id, Team.Name just fine.
However, I'm unsure how to implement the Team.Members part. If I implement it by doing something like this in Team's named property getter callback:
if (property_s == "Members") { // property_s is just the property argument casted to a c++ string
   
Local<Object> owner_obj = self->wrap_members(&team->members); // wrap_members returns a Members object based on an ObjectTemplate with indexed property callbacks
    info
.GetReturnValue().Set(owner_obj);
}
where wrap_members returns an Object created from ObjectTemplate with an indexed property getter callback then I can get it working to some degree, e.g. Team.Members[0] will return the correct name for the first Team member (I set it to just return the name for testing purposes.) My plan after this would be to make it so that the callback for Team.Members[x] would return yet another object based on an ObjectTemplate which then contains the information about that team member (Name, ID, etc.)

However my issues right now are:
  • Is this really the best way to implement this structure? It seems like I'm creating a lot of ObjectTemplates
  • How can I implement .length for Team.Members? Do I have to also bind a named propeerty getter callback function to it? This leaves me creating even more functions.
  • How do I throw an out-of-bounds error or the like if the index provided is out of bounds?


I'm not sure if my explanation is understandable, please reply if it's not and I'll try and improve it. Thanks.

Jack

unread,
Aug 6, 2016, 3:51:22 PM8/6/16
to v8-users
Ok so I've figured out how to make the object behave as an array:
Local<Object> obj = self->wrap_members(&team->members);
obj
->Set(String::NewFromUtf8(info.GetIsolate(), "length", NewStringType::kNormal).ToLocalChecked(), Integer::New(info.GetIsolate(), team->members.size()));
obj
->SetPrototype(Array::New(info.GetIsolate())->GetPrototype());
info
.GetReturnValue().Set(obj);

This feels a little... janky? though. Is there a better way to do this?

Ben Noordhuis

unread,
Aug 8, 2016, 6:39:20 AM8/8/16
to v8-users
Is there a reason you can't convert your data structure to plain JS
objects and arrays?

> How do I throw an out-of-bounds error or the like if the index provided is
> out of bounds?

That would be un-Javascript-y. Out-of-bounds accesses normally
evaluate to `undefined`.

Jack

unread,
Aug 8, 2016, 9:16:28 AM8/8/16
to v8-users
Thanks for the tip with the out-of-bounds.
Unofrtunately I can't just create object - I actually tried this first - my data is a bit more complicated than my simplification here and there is a lot of it, as well as a lot of nesting so generating an object for it each time becomes expensive (and it changes too often to really cache the object too).

Ben Noordhuis

unread,
Aug 8, 2016, 10:10:41 AM8/8/16
to v8-users
On Mon, Aug 8, 2016 at 3:16 PM, Jack <jack....@gmail.com> wrote:
> Thanks for the tip with the out-of-bounds.
> Unofrtunately I can't just create object - I actually tried this first - my
> data is a bit more complicated than my simplification here and there is a
> lot of it, as well as a lot of nesting so generating an object for it each
> time becomes expensive (and it changes too often to really cache the object
> too).

Okay, I understand. You could create an ObjectTemplate with a
NamedPropertyHandlerConfiguration and an
IndexedPropertyHandlerConfiguration. Then you can intercept all
property and indexed accesses and create objects lazily without
creating a new ObjectTemplate for each property or index.

A naive, non-caching implementation would break object identity (i.e.,
`o.x === o.x` would no longer be true) but that is no different from
regular JS getters/setters.
Reply all
Reply to author
Forward
0 new messages