react-juce icon indicating copy to clipboard operation
react-juce copied to clipboard

V8 EcmascriptEngine Pimpl

Open nick-thompson opened this issue 5 years ago • 3 comments

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:

  • Let's move the existing EcmascriptEngine.cpp to EcmascriptEngine_Duktape.cpp
  • Let's add a new EcmascriptEngine_V8.cpp
  • Let's add a preprocessor definition to allow the user to toggle which engine they want to build with
    • e.g. -DBLUEPRINT_USE_V8=1
  • Let's not include the v8 source with the project, as we do with Duktape.
    • With Duktape, it's cool because the source is really quite small and provides an easy default
    • With v8 things are slightly more complicated, so we'll ask that users bring their own V8 directory somewhere else and configure their project with the correct header includes -Ipath/to/your/v8

nick-thompson avatar Dec 15 '20 13:12 nick-thompson

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.

nick-thompson avatar Jan 05 '21 14:01 nick-thompson

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 avatar Jan 05 '21 14:01 JoshMarler

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

JoshMarler avatar Jan 05 '21 14:01 JoshMarler