pmed / v8pp

Bind C++ functions and classes into V8 JavaScript engine
http://pmed.github.io/v8pp/
Other
887 stars 119 forks source link

Override C++ method in JavaScript #151

Closed optifunc closed 2 years ago

optifunc commented 3 years ago

Hi, Thank you for your work on this library! Is it possible to override a class function defined in C++ in JavaScript? Something like:

// C++
class X
{
public:
    virtual void m() {}
};

v8pp::class_<X> xClass(isolate);
file_writer_class
    .set("m", &X::m);

auto xDerivedInstance = create_object_in_js();
xDerivedInstance->m(); // I want to "overriden" to be written to console at this point.
// TypeScript
class XDerived extends X {
   m() {
       console.log("overriden");
   }
}

function create_object_in_js() { return new XDerived(); }

What I tried is:

        virtual void m()
        {
            auto isolate = v8::Isolate::GetCurrent();
            v8::HandleScope scope(isolate);
            auto jsThis = v8pp::to_v8(isolate, this);
            auto onLoaded = jsThis->Get(
                isolate->GetCurrentContext(),
                v8pp::to_v8(isolate, "m")).ToLocalChecked().As<v8::Function>();

            onLoaded->Call(isolate->GetCurrentContext(), jsThis, 0, nullptr);
        }

-- but that of course leads to stack overflow. And even if it worked it would only allow to override a set of special designated methods with such "trampolines" embedded in their base C++ implementations.

Maybe you have some thoughts or pointers on how to tackle this problem? What would be the ways of allowing to extend in JS some classes defined in C++?

pmed commented 3 years ago

Hi,

I suspect you need to manipulate the prototype of XDerived at the JavaScript side. Something like

class XDerived {
    constructor() { _proto_.m = this.m; }
}

Sorry, don't know how to express it in TypeScript.