Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable NAPI-JSI build on top of V8JSI #832

Merged
merged 9 commits into from Jul 23, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions Apps/Playground/UWP/App.cpp
Expand Up @@ -124,6 +124,7 @@ void App::Uninitialize()
m_graphics->FinishRenderingCurrentFrame();
}

m_chromeDevTools.reset();
m_inputBuffer.reset();
m_runtime.reset();
m_graphics.reset();
Expand Down Expand Up @@ -291,6 +292,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(4653, "BabylonNative Playground");
}
});

Babylon::ScriptLoader loader{*m_runtime};
Expand Down
2 changes: 2 additions & 0 deletions Apps/Playground/UWP/App.h
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
Expand Up @@ -36,5 +36,6 @@
<Capability Name="internetClient" />
<rescap:Capability Name="broadFileSystemAccess" />
<uap2:Capability Name="spatialPerception"/>
<Capability Name="internetClientServer"/>
</Capabilities>
</Package>
2 changes: 1 addition & 1 deletion Apps/Playground/Win32/App.cpp
Expand Up @@ -140,7 +140,7 @@ namespace
chromeDevTools = std::make_unique<Babylon::Plugins::ChromeDevTools>(Babylon::Plugins::ChromeDevTools::Initialize(env));
if (chromeDevTools->SupportsInspector())
{
chromeDevTools->StartInspector(5643, "BabylonNative Playground");
chromeDevTools->StartInspector(4653, "BabylonNative Playground");
rgerd marked this conversation as resolved.
Show resolved Hide resolved
}
});

Expand Down
57 changes: 27 additions & 30 deletions Core/AppRuntime/CMakeLists.txt
@@ -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()
47 changes: 47 additions & 0 deletions Core/AppRuntime/Source/AppRuntimeJSI.cpp
@@ -0,0 +1,47 @@
#include "AppRuntime.h"
#include "WorkQueue.h"

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

namespace Babylon
{
class TaskRunnerAdapter : public v8runtime::JSITaskRunner
{
public:
TaskRunnerAdapter(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;

WorkQueue& m_workQueue;
};
rgerd marked this conversation as resolved.
Show resolved Hide resolved

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

const auto runtime = v8runtime::makeV8Runtime(std::move(args));
Napi::Env env = Napi::Attach<facebook::jsi::Runtime&>(*runtime);
rgerd marked this conversation as resolved.
Show resolved Hide resolved
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
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 (nuget_download)
rgerd marked this conversation as resolved.
Show resolved Hide resolved
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
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")
@@ -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)
rgerd marked this conversation as resolved.
Show resolved Hide resolved
# 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
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})
nuget_download()
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
18 changes: 18 additions & 0 deletions Dependencies/napi/napi-direct/include/napi/napi-inl.h
Expand Up @@ -1781,6 +1781,24 @@ 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 Napi::Value* args) const {
napi_value stackArgs[6];
std::vector<napi_value> heapArgs;
napi_value* argv;
if (argc <= std::size(stackArgs)) {
argv = stackArgs;
} else {
heapArgs.resize(argc);
argv = heapArgs.data();
}

for (size_t i = 0; i < argc; ++i) {
argv[i] = args[i];
}

return Call(recv, argc, argv);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is mostly unmodified from the node repo. If this is actually necessary, then we should try to upstream it to node. We typically don't change the N-API contract.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed a PR here: nodejs/node-addon-api#1026

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
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
@@ -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>
rgerd marked this conversation as resolved.
Show resolved Hide resolved