How extend a C++ created class in JavaScript

284 views
Skip to first unread message

George Marques

unread,
Nov 7, 2016, 10:14:14 AM11/7/16
to v8-users
I'm trying to embed V8 5.4 into a game engine. I want to expose the engine types to JavaScript as ES6 classes.

I am actually able to do that, but when I extend the class in JavaScript the methods are not being overridden by the JS code.

Here's a sample of how I am doing it:

class Point {
public:
 
int x;
 
int y;
 
int sum() { return x + y; }
};


void PointConstructor(const FunctionCallbackInfo<Value>& args) {
 
Isolate* isolate = args.GetIsolate();
 
if (!args.IsConstructCall()) {
    isolate
->ThrowException(String::NewFromUtf8(isolate, "Can only be called as constructor."));
 
return;
 
}

 
Point* p = new Point();
  p
->x = args[0]->IntegerValue();
  p
->y = args[1]->IntegerValue();


  args
.This()->SetInternalField(0, External::New(isolate, p));
}


void PointSum(const FunctionCallbackInfo<Value>& args) {
 
Local<External> field = Local<External>::Cast(args.This()->GetInternalField(0));
 
Point* p = static_cast<Point*>(field->Value());

  args
.GetReturnValue().Set(p->sum());
}


int main(int argc, char* argv[]) {
 
// ... initialize V8
 
 
// Create the global object with print function for test
 
Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
 
global->Set(String::NewFromUtf8(isolate, "print"), FunctionTemplate::New(isolate, PrintCallback));

 
// Create the point constructor template
 
Local<FunctionTemplate> point_constructor = FunctionTemplate::New(isolate, PointConstructor);
 
Local<ObjectTemplate> point_template = point_constructor->InstanceTemplate();
  point_template
->SetInternalFieldCount(1);
  point_template
->Set(String::NewFromUtf8(isolate, "sum"), FunctionTemplate::New(isolate, PointSum));
  point_template
->SetHandler(NamedPropertyHandlerConfiguration(NamedGet));

 
// Add the constructor to the global object as the type
 
global->Set(String::NewFromUtf8(isolate, "Point"), point_constructor);
 
 
// ... compile and run code.
}


And here is the Java Script code:

class MyPoint extends Point {
  sum
() {
   
return 25;
 
}
}

var p = new MyPoint(2, 3);
print(p.sum()) // Prints 5, using the native function


My problem is that the sum() method of the child type is not called if the parent method is native. Is there a way to enforce the overriding?

George Marques

unread,
Nov 7, 2016, 11:49:34 PM11/7/16
to v8-users
Solved my problem. I had to use point_constructor->InstanceTemplate() only to set the internal field count. To set the methods I need to use point_constructor->PrototypeTemplate().

Still struggling a bit to understand why it has to be that way. V8 internals is kind of a mystery.

Ben Noordhuis

unread,
Nov 8, 2016, 5:32:45 AM11/8/16
to v8-users
On Tue, Nov 8, 2016 at 5:49 AM, George Marques <george...@gmail.com> wrote:
> Solved my problem. I had to use point_constructor->InstanceTemplate() only
> to set the internal field count. To set the methods I need to use
> point_constructor->PrototypeTemplate().
>
> Still struggling a bit to understand why it has to be that way. V8 internals
> is kind of a mystery.

It sounds like you figured it out but just in case: in your example
the C++ code is overriding the JS method. The prototype template is
the base class (insofar that concept applies to JS) whereas the
instance template is the derived class.
Reply all
Reply to author
Forward
0 new messages