Skip to content

Commit

Permalink
Enable NAPI-JSI build on top of V8JSI (#832)
Browse files Browse the repository at this point in the history
* Working NAPI-JSI

* Use original port

* Cleanup

* Back out CallbackInfo change

* Easier promise type fix

* Simpler NativeCamera function fix

* Clean up all the napi imports

* Add link to source

* Final PR feedback
  • Loading branch information
rgerd authored Jul 23, 2021
1 parent 975bb0b commit e15094d
Show file tree
Hide file tree
Showing 22 changed files with 367 additions and 83 deletions.
7 changes: 7 additions & 0 deletions Apps/Playground/UWP/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ void App::Uninitialize()
m_graphics->FinishRenderingCurrentFrame();
}

m_chromeDevTools.reset();
m_inputBuffer.reset();
m_runtime.reset();
m_graphics.reset();
Expand Down Expand Up @@ -294,6 +295,12 @@ void App::RestartRuntime(Windows::Foundation::Rect bounds)
Babylon::Plugins::NativeXr::Initialize(env);

InputManager<Babylon::AppRuntime>::Initialize(env, *m_inputBuffer);

m_chromeDevTools = std::make_unique<Babylon::Plugins::ChromeDevTools>(Babylon::Plugins::ChromeDevTools::Initialize(env));
if (m_chromeDevTools->SupportsInspector())
{
m_chromeDevTools->StartInspector(5643, "BabylonNative Playground");
}
});

Babylon::ScriptLoader loader{*m_runtime};
Expand Down
2 changes: 2 additions & 0 deletions Apps/Playground/UWP/App.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <Shared/InputManager.h>
#include <Babylon/AppRuntime.h>
#include <Babylon/Graphics.h>
#include <Babylon/Plugins/ChromeDevTools.h>

// Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events.
ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
Expand Down Expand Up @@ -42,6 +43,7 @@ ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
std::unique_ptr<Babylon::Graphics> m_graphics{};
std::unique_ptr<Babylon::AppRuntime> m_runtime{};
std::unique_ptr<InputManager<Babylon::AppRuntime>::InputBuffer> m_inputBuffer{};
std::unique_ptr<Babylon::Plugins::ChromeDevTools> m_chromeDevTools{};
Windows::Foundation::Collections::IVectorView<Windows::Storage::IStorageItem^>^ m_files;
bool m_windowClosed;
bool m_windowVisible;
Expand Down
1 change: 1 addition & 0 deletions Apps/Playground/UWP/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@
<Capability Name="internetClient" />
<rescap:Capability Name="broadFileSystemAccess" />
<uap2:Capability Name="spatialPerception"/>
<Capability Name="internetClientServer"/>
</Capabilities>
</Package>
57 changes: 27 additions & 30 deletions Core/AppRuntime/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,37 +1,34 @@
if(NOT NAPI_JAVASCRIPT_ENGINE STREQUAL "JSI")

set(SOURCES
"Include/Babylon/AppRuntime.h"
"Source/AppRuntime.cpp"
"Source/AppRuntime${NAPI_JAVASCRIPT_ENGINE}.cpp"
"Source/WorkQueue.cpp"
"Source/WorkQueue.h")

if(APPLE)
set(SOURCES ${SOURCES} "Source/AppRuntime${BABYLON_NATIVE_PLATFORM}.mm")
else()
set(SOURCES ${SOURCES} "Source/AppRuntime${BABYLON_NATIVE_PLATFORM}.cpp")
endif()
set(SOURCES
"Include/Babylon/AppRuntime.h"
"Source/AppRuntime.cpp"
"Source/AppRuntime${NAPI_JAVASCRIPT_ENGINE}.cpp"
"Source/WorkQueue.cpp"
"Source/WorkQueue.h")

if(APPLE)
set(SOURCES ${SOURCES} "Source/AppRuntime${BABYLON_NATIVE_PLATFORM}.mm")
else()
set(SOURCES ${SOURCES} "Source/AppRuntime${BABYLON_NATIVE_PLATFORM}.cpp")
endif()

add_library(AppRuntime ${SOURCES})
warnings_as_errors(AppRuntime)
add_library(AppRuntime ${SOURCES})
warnings_as_errors(AppRuntime)

target_include_directories(AppRuntime
PRIVATE "Include/Babylon"
INTERFACE "Include")
target_include_directories(AppRuntime
PRIVATE "Include/Babylon"
INTERFACE "Include")

if(UNIX AND NOT APPLE AND NOT ANDROID)
target_include_directories(AppRuntime INTERFACE "/usr/include/webkitgtk-4.0/")
endif()
if(UNIX AND NOT APPLE AND NOT ANDROID)
target_include_directories(AppRuntime INTERFACE "/usr/include/webkitgtk-4.0/")
endif()

target_link_to_dependencies(AppRuntime
PRIVATE arcana
PUBLIC JsRuntime)
target_link_to_dependencies(AppRuntime
PRIVATE arcana
PUBLIC JsRuntime)

target_compile_definitions(AppRuntime
PRIVATE NOMINMAX)
target_compile_definitions(AppRuntime
PRIVATE NOMINMAX)

set_property(TARGET AppRuntime PROPERTY FOLDER Core)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})
set_property(TARGET AppRuntime PROPERTY FOLDER Core)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})

endif()
51 changes: 51 additions & 0 deletions Core/AppRuntime/Source/AppRuntimeJSI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "AppRuntime.h"
#include "WorkQueue.h"

#include <napi/env.h>
#include <V8JsiRuntime.h>
#include <ScriptStore.h>

namespace
{
class TaskRunnerAdapter : public v8runtime::JSITaskRunner
{
public:
TaskRunnerAdapter(Babylon::WorkQueue& workQueue)
: m_workQueue(workQueue)
{
}

void postTask(std::unique_ptr<v8runtime::JSITask> task) override
{
std::shared_ptr<v8runtime::JSITask> shared_task(task.release());
m_workQueue.Append([shared_task2 = std::move(shared_task)](Napi::Env) {
shared_task2->run();
});
}

private:
TaskRunnerAdapter(const TaskRunnerAdapter&) = delete;
TaskRunnerAdapter& operator=(const TaskRunnerAdapter&) = delete;

Babylon::WorkQueue& m_workQueue;
};
}

namespace Babylon
{
void AppRuntime::RunEnvironmentTier(const char*)
{
v8runtime::V8RuntimeArgs args{};
args.inspectorPort = 5643;
args.foreground_task_runner = std::make_shared<TaskRunnerAdapter>(*m_workQueue);

const auto runtime{v8runtime::makeV8Runtime(std::move(args))};
const auto env{Napi::Attach<facebook::jsi::Runtime&>(*runtime)};
Dispatch([&runtime](Napi::Env env) {
JsRuntime::NativeObject::GetFromJavaScript(env)
.Set("_JSIRuntime", Napi::External<facebook::jsi::Runtime>::New(env, runtime.get()));
});
Run(env);
Napi::Detach(env);
}
}
16 changes: 16 additions & 0 deletions Dependencies/CMakeExtensions/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,20 @@ function(set_win32_arch)
else()
message(FATAL_ERROR "Unrecognized compiler: ${CMAKE_CXX_COMPILER}")
endif()
endfunction()

# Uses the nuget.config and packages.config files in the current directory to download packages from NuGet.
# NUGET_PATH will be set to the directory where the packages are installed.
function (download_nuget)
set(NUGET_PATH "${CMAKE_BINARY_DIR}/NuGet")
set(NUGET_PATH "${NUGET_PATH}" PARENT_SCOPE)
set(NUGET_EXE "${NUGET_PATH}/nuget.exe")
if(NOT EXISTS ${NUGET_EXE})
file(DOWNLOAD "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" ${NUGET_EXE})
endif()
file(COPY "nuget.config" DESTINATION ${NUGET_PATH})
file(COPY "packages.config" DESTINATION ${NUGET_PATH})

execute_process(COMMAND ${NUGET_EXE} restore WORKING_DIRECTORY ${NUGET_PATH})
execute_process(COMMAND ${NUGET_EXE} install WORKING_DIRECTORY ${NUGET_PATH})
endfunction()
2 changes: 2 additions & 0 deletions Dependencies/napi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ if(NAPI_JAVASCRIPT_ENGINE STREQUAL "JSI")
else()
add_subdirectory(napi-direct)
endif()

add_on_linked_as_dependency_cmake_file(napi "${CMAKE_CURRENT_SOURCE_DIR}/OnLinkedAsDependency.cmake")
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
# Callback to perform custom behavior -- in this case, copying runtime output artifacts like DLLs -- when
# linked from an executable target as a library.
function(on_linked_as_dependency target)
# We only have to do anything if the JavaScript engine is V8.
if (NAPI_JAVASCRIPT_ENGINE STREQUAL "V8")

# Propagate this file to the target so that it will be transitively available to targets that
# link to that one, too.
propagate_on_linked_as_dependency_cmake_file(napi ${target})

# Propagate this file to the target so that it will be transitively available to targets that
# link to that one, too.
propagate_on_linked_as_dependency_cmake_file(napi ${target})
if (DEFINED NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS)
# We only need to actually copy files if we're being linked from an executable.
get_target_property(type ${target} TYPE)
if(${type} STREQUAL "EXECUTABLE")
if (WINDOWS_STORE)
# WINDOWS_STORE allows us to use the VS_DEPLOYMENT_CONTENT property.
target_sources(${target} PRIVATE ${NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS})
set_property(SOURCE ${NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS} PROPERTY VS_DEPLOYMENT_CONTENT 1)

if ((DEFINED NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS_DEBUG) AND (DEFINED NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS_RELEASE))
set_property(SOURCE ${NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS_DEBUG} PROPERTY VS_DEPLOYMENT_CONTENT $<CONFIG:Debug>)
set_property(SOURCE ${NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS_RELEASE} PROPERTY VS_DEPLOYMENT_CONTENT $<NOT:$<CONFIG:Debug>>)
else()
set_property(SOURCE ${NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS} PROPERTY VS_DEPLOYMENT_CONTENT 1)
endif()

set_property(SOURCE ${NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS} PROPERTY VS_DEPLOYMENT_LOCATION ".")
else()
# Without the VS_DEPLOYMENT_CONTENT property, create custom rules to copy the artifacts.
foreach(artifact ${NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS})
add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${artifact} $<TARGET_FILE_DIR:${target}>)
endforeach(artifact)
endforeach()
endif()
endif()
endif()
endfunction()
endfunction()
34 changes: 15 additions & 19 deletions Dependencies/napi/napi-direct/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,32 @@ target_include_directories(napi PUBLIC "include")

# Install v8 SDK from NuGet
function (install_v8_nuget V8_VERSION ARCH VS_PLAT_TOOLSET)
set(NUGET_PATH "${CMAKE_BINARY_DIR}/NuGet")
set(NUGET_EXE "${NUGET_PATH}/nuget.exe")
if(NOT EXISTS ${NUGET_EXE})
file(DOWNLOAD "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" ${NUGET_EXE})
endif()
file(COPY "packages.config" DESTINATION ${NUGET_PATH})
execute_process(COMMAND ${NUGET_EXE} install WORKING_DIRECTORY ${NUGET_PATH})
download_nuget()
set(V8_PACKAGE_PATH "${NUGET_PATH}/packages/v8-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}")
set(V8_REDIST_PACKAGE_PATH "${NUGET_PATH}/packages/v8.redist-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}")

add_library(v8_libbase SHARED IMPORTED)
set_target_properties(v8_libbase PROPERTIES IMPORTED_IMPLIB "${NUGET_PATH}/v8-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/v8_libbase.dll.lib")
set_target_properties(v8_libbase PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8_libbase.dll.lib")
add_library(v8_libplatform SHARED IMPORTED)
set_target_properties(v8_libplatform PROPERTIES IMPORTED_IMPLIB "${NUGET_PATH}/v8-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/v8_libplatform.dll.lib")
set_target_properties(v8_libplatform PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8_libplatform.dll.lib")
add_library(v8 SHARED IMPORTED)
set_target_properties(v8 PROPERTIES IMPORTED_IMPLIB "${NUGET_PATH}/v8-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/v8.dll.lib")
set_target_properties(v8 PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8.dll.lib")
target_link_libraries(v8 INTERFACE v8_libbase INTERFACE v8_libplatform)
target_include_directories(v8 INTERFACE "${NUGET_PATH}/v8-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/include")
target_include_directories(v8 INTERFACE "${V8_PACKAGE_PATH}/include")

set(NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS
"${NUGET_PATH}/v8.redist-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/icudtl.dat"
"${NUGET_PATH}/v8.redist-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/icui18n.dll"
"${NUGET_PATH}/v8.redist-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/icuuc.dll"
"${NUGET_PATH}/v8.redist-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/v8.dll"
"${NUGET_PATH}/v8.redist-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/v8_libbase.dll"
"${NUGET_PATH}/v8.redist-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/v8_libplatform.dll"
"${NUGET_PATH}/v8.redist-${VS_PLAT_TOOLSET}-${ARCH}.${V8_VERSION}/lib/Release/zlib.dll"
"${V8_REDIST_PACKAGE_PATH}/lib/Release/icudtl.dat"
"${V8_REDIST_PACKAGE_PATH}/lib/Release/icui18n.dll"
"${V8_REDIST_PACKAGE_PATH}/lib/Release/icuuc.dll"
"${V8_REDIST_PACKAGE_PATH}/lib/Release/v8.dll"
"${V8_REDIST_PACKAGE_PATH}/lib/Release/v8_libbase.dll"
"${V8_REDIST_PACKAGE_PATH}/lib/Release/v8_libplatform.dll"
"${V8_REDIST_PACKAGE_PATH}/lib/Release/zlib.dll"
CACHE STRING "N-API runtime output artifacts")
endfunction()

if(NOT TARGET javascript_engine)
add_library(javascript_engine INTERFACE)
add_on_linked_as_dependency_cmake_file(napi "${CMAKE_CURRENT_SOURCE_DIR}/OnLinkedAsDependency.cmake")
if(NAPI_JAVASCRIPT_ENGINE STREQUAL "V8")
if(WIN32)
set_win32_arch()
Expand Down
21 changes: 21 additions & 0 deletions Dependencies/napi/napi-direct/include/napi/napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1781,6 +1781,27 @@ inline Value Function::Call(napi_value recv, const std::vector<napi_value>& args
return Call(recv, args.size(), args.data());
}

inline Value Function::Call(napi_value recv,
size_t argc,
const Value* args) const {
const size_t stackArgsCount = 6;
napi_value stackArgs[stackArgsCount];
std::vector<napi_value> heapArgs;
napi_value* argv;
if (argc <= stackArgsCount) {
argv = stackArgs;
} else {
heapArgs.resize(argc);
argv = heapArgs.data();
}

for (size_t index = 0; index < argc; index++) {
argv[index] = static_cast<napi_value>(args[index]);
}

return Call(recv, argc, argv);
}

inline Value Function::Call(napi_value recv, size_t argc, const napi_value* args) const {
napi_value result;
napi_status status = napi_call_function(
Expand Down
1 change: 1 addition & 0 deletions Dependencies/napi/napi-direct/include/napi/napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,7 @@ namespace Napi {
Value Call(size_t argc, const napi_value* args) const;
Value Call(napi_value recv, const std::initializer_list<napi_value>& args) const;
Value Call(napi_value recv, const std::vector<napi_value>& args) const;
Value Call(napi_value recv, size_t argc, const Napi::Value* args) const;
Value Call(napi_value recv, size_t argc, const napi_value* args) const;

#ifndef NODE_ADDON_API_DISABLE_NODE_SPECIFIC
Expand Down
13 changes: 13 additions & 0 deletions Dependencies/napi/napi-direct/nuget.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositoryPath" value="packages" />
</config>
<packageSources>
<clear />
<add key="Nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<disabledPackageSources>
<clear />
</disabledPackageSources>
</configuration>
51 changes: 46 additions & 5 deletions Dependencies/napi/napi-jsi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
if(NOT TARGET jsi)
message(FATAL_ERROR "jsi target is required")
endif()

set(SOURCES
"include/napi/env.h"
"include/napi/napi.h"
Expand All @@ -10,7 +6,52 @@ set(SOURCES

add_library(napi ${SOURCES})

target_include_directories(napi
if(NOT TARGET jsi)
if(WIN32)
download_nuget()
set_win32_arch()
set(V8JSI_VERSION "0.64.16")
if (WINDOWS_STORE)
set(V8JSI_PACKAGE_PATH "${NUGET_PATH}/packages/ReactNative.V8Jsi.Windows.UWP.${V8JSI_VERSION}")
set(PLATFORM_FOLDER "uwp")
else()
set(V8JSI_PACKAGE_PATH "${NUGET_PATH}/packages/ReactNative.V8Jsi.Windows.${V8JSI_VERSION}")
set(PLATFORM_FOLDER "win32")
endif()

# TODO: Pull in v8jsi symbols once they're packaged with the debug build.
set(V8JSI_LIB_PATH_DEBUG "${V8JSI_PACKAGE_PATH}/lib/${PLATFORM_FOLDER}/Debug/${WIN32_ARCH}/v8jsi.dll.lib")
set(V8JSI_LIB_PATH_RELEASE "${V8JSI_PACKAGE_PATH}/lib/${PLATFORM_FOLDER}/Release/${WIN32_ARCH}/v8jsi.dll.lib")
set(V8JSI_DLL_PATH "${V8JSI_PACKAGE_PATH}/lib/${PLATFORM_FOLDER}/$<IF:$<CONFIG:Debug>,Debug,Release>/${WIN32_ARCH}/v8jsi.dll")
set(V8JSI_DLL_PATH_DEBUG "${V8JSI_PACKAGE_PATH}/lib/${PLATFORM_FOLDER}/Debug/${WIN32_ARCH}/v8jsi.dll")
set(V8JSI_DLL_PATH_RELEASE "${V8JSI_PACKAGE_PATH}/lib/${PLATFORM_FOLDER}/Release/${WIN32_ARCH}/v8jsi.dll")

add_library(v8jsi SHARED IMPORTED)
set_target_properties(v8jsi PROPERTIES
IMPORTED_IMPLIB_DEBUG ${V8JSI_LIB_PATH_DEBUG}
IMPORTED_IMPLIB_RELEASE ${V8JSI_LIB_PATH_RELEASE}
IMPORTED_IMPLIB_MINSIZEREL ${V8JSI_LIB_PATH_RELEASE}
IMPORTED_IMPLIB_RELWITHDEBINFO ${V8JSI_LIB_PATH_RELEASE})

target_include_directories(v8jsi INTERFACE "${V8JSI_PACKAGE_PATH}/build/native/include")
target_include_directories(v8jsi INTERFACE "${V8JSI_PACKAGE_PATH}/build/native/jsi")
set(NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS_DEBUG ${V8JSI_DLL_PATH_DEBUG} CACHE STRING "N-API runtime output artifacts (debug)")
set(NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS_RELEASE ${V8JSI_DLL_PATH_RELEASE} CACHE STRING "N-API runtime output artifacts (release)")
set(NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS ${V8JSI_DLL_PATH} CACHE STRING "N-API runtime output artifacts")
target_compile_definitions(v8jsi INTERFACE V8JSI_ENABLE_INSPECTOR)

add_library(jsi "${V8JSI_PACKAGE_PATH}/build/native/jsi/jsi/jsi.cpp")
target_include_directories(jsi
PUBLIC "${V8JSI_PACKAGE_PATH}/build/native/include"
PUBLIC "${V8JSI_PACKAGE_PATH}/build/native/jsi")
target_link_libraries(jsi PUBLIC v8jsi)
set_property(TARGET jsi PROPERTY FOLDER Dependencies)
else()
message(FATAL_ERROR "jsi target is required")
endif()
endif()

target_include_directories(napi
PUBLIC "include")

target_link_to_dependencies(napi
Expand Down
Loading

0 comments on commit e15094d

Please sign in to comment.