JoshMarler / react-juce

Write cross-platform native apps with React.js and JUCE
https://docs.react-juce.dev
MIT License
771 stars 80 forks source link

V8 EcmascriptEngine Pimpl #178

Open nick-thompson opened 3 years ago

nick-thompson commented 3 years ago

As of #145 we now have a cleaner EcmascriptEngine interface which is satisfied via a Duktape implementation Pimpl by default. The task here is to provide another EcmascriptEngine implementation via V8 (https://v8.dev/docs) with a new Pimpl.

Quick details:

nick-thompson commented 3 years ago

Adding a bit more detail here as I think v8 integration will become a big priority after beta.

Generally I think the details of integration here fall into two bits. The first is just getting things to compile, and the second is fleshing out the full EcmascriptEngine interface.

To the first point, I envision something like

// EcmascriptEngine_V8.cpp
#include <libplatform/libplatform.h>
#include <v8.h>

struct EcmascriptEngine::Pimpl
{
    Pimpl()
    {
        // This kinda stuff, probably need to hold some of it as member vars
        std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
        v8::V8::InitializePlatform(platform.get());
        v8::V8::Initialize();
    }
};

Then, for the user to compile successfully, they'll need to -DREACTJUCE_USE_V8=1 which we'll use inside of blueprint.cpp to decide whether we #include EcmascriptEngine_Duktape.cpp or #include EcmascriptEngine_V8.cpp, they'll need to add an include path for their v8 headers: -Ipath/to/v8/include, and link against V8 -lv8_monolith. It's my intention for the v8 source directory to be something that blueprint pays no mind to, the user can put it wherever and do whatever they want with it, just make sure they specify the correct include/link flags in their CMake config or whatever.

Now, step two then is much like what we've already done with Duktape, but it will be a solid chunk of work so I would suggest we split this up into multiple phases as well, where perhaps we only implement evaluate and evaluateInline initially, and for all other EcmascriptEngine methods we'll implement a no-op or a return juce::var(juce::String("not implemented")); for now. That way we're biting this off in small chunks. Aiming at evaluate and evaluateInline first is a good spot to start, in my opinion, because it invites the question of getting from a v8::Local<v8::Value> to a juce::var, which is a translation layer we need to figure out for this to be successful. If we can prove out evaluate, evaluateInline, and v8::Value -> juce::var, I think the rest will fall into place much more easily.

JoshMarler commented 3 years ago

Yep perfect. Given juce modules are just interface libraries under cmake this can be super simple.

Users should need to literally just target_include_directories(/path/to/v8/include) and target_link_libraries(v8_monolith) on their targets using the react-juce submodule.

JoshMarler commented 3 years ago

From a previous discussion between myself an Nick. Examples here have been identified as a good starting point to follow when implementing EcmascriptEngine::evaluate and EcmascriptEngine::evaluateInline:

https://github.com/v8/v8/blob/master/samples/process.cc#L233

https://github.com/v8/v8/blob/master/samples/process.cc#L653

Documentation on embedding V8 into C++ app here:

https://v8.dev/docs/embed