diff --git a/Apps/Playground/UWP/App.cpp b/Apps/Playground/UWP/App.cpp index 61aaceb1c..328063ec1 100644 --- a/Apps/Playground/UWP/App.cpp +++ b/Apps/Playground/UWP/App.cpp @@ -124,6 +124,7 @@ void App::Uninitialize() m_graphics->FinishRenderingCurrentFrame(); } + m_chromeDevTools.reset(); m_inputBuffer.reset(); m_runtime.reset(); m_graphics.reset(); @@ -291,6 +292,12 @@ void App::RestartRuntime(Windows::Foundation::Rect bounds) Babylon::Plugins::NativeXr::Initialize(env); InputManager::Initialize(env, *m_inputBuffer); + + m_chromeDevTools = std::make_unique(Babylon::Plugins::ChromeDevTools::Initialize(env)); + if (m_chromeDevTools->SupportsInspector()) + { + m_chromeDevTools->StartInspector(5643, "BabylonNative Playground"); + } }); Babylon::ScriptLoader loader{*m_runtime}; diff --git a/Apps/Playground/UWP/App.h b/Apps/Playground/UWP/App.h index aefc85a0d..a8b82cbe1 100644 --- a/Apps/Playground/UWP/App.h +++ b/Apps/Playground/UWP/App.h @@ -3,6 +3,7 @@ #include #include #include +#include // 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 @@ -42,6 +43,7 @@ ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView std::unique_ptr m_graphics{}; std::unique_ptr m_runtime{}; std::unique_ptr::InputBuffer> m_inputBuffer{}; + std::unique_ptr m_chromeDevTools{}; Windows::Foundation::Collections::IVectorView^ m_files; bool m_windowClosed; bool m_windowVisible; diff --git a/Apps/Playground/UWP/Package.appxmanifest b/Apps/Playground/UWP/Package.appxmanifest index 67ffde841..d64ab75fd 100644 --- a/Apps/Playground/UWP/Package.appxmanifest +++ b/Apps/Playground/UWP/Package.appxmanifest @@ -36,5 +36,6 @@ + \ No newline at end of file diff --git a/Core/AppRuntime/CMakeLists.txt b/Core/AppRuntime/CMakeLists.txt index 801833367..45d322e8b 100644 --- a/Core/AppRuntime/CMakeLists.txt +++ b/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() diff --git a/Core/AppRuntime/Source/AppRuntimeJSI.cpp b/Core/AppRuntime/Source/AppRuntimeJSI.cpp new file mode 100644 index 000000000..97f188c65 --- /dev/null +++ b/Core/AppRuntime/Source/AppRuntimeJSI.cpp @@ -0,0 +1,51 @@ +#include "AppRuntime.h" +#include "WorkQueue.h" + +#include +#include +#include + +namespace +{ + class TaskRunnerAdapter : public v8runtime::JSITaskRunner + { + public: + TaskRunnerAdapter(Babylon::WorkQueue& workQueue) + : m_workQueue(workQueue) + { + } + + void postTask(std::unique_ptr task) override + { + std::shared_ptr 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(*m_workQueue); + + const auto runtime{v8runtime::makeV8Runtime(std::move(args))}; + const auto env{Napi::Attach(*runtime)}; + Dispatch([&runtime](Napi::Env env) { + JsRuntime::NativeObject::GetFromJavaScript(env) + .Set("_JSIRuntime", Napi::External::New(env, runtime.get())); + }); + Run(env); + Napi::Detach(env); + } +} diff --git a/Dependencies/CMakeExtensions/CMakeLists.txt b/Dependencies/CMakeExtensions/CMakeLists.txt index 0630b422f..386157b9f 100644 --- a/Dependencies/CMakeExtensions/CMakeLists.txt +++ b/Dependencies/CMakeExtensions/CMakeLists.txt @@ -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() \ No newline at end of file diff --git a/Dependencies/napi/CMakeLists.txt b/Dependencies/napi/CMakeLists.txt index 7e6039746..973b717af 100644 --- a/Dependencies/napi/CMakeLists.txt +++ b/Dependencies/napi/CMakeLists.txt @@ -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") \ No newline at end of file diff --git a/Dependencies/napi/napi-direct/OnLinkedAsDependency.cmake b/Dependencies/napi/OnLinkedAsDependency.cmake similarity index 55% rename from Dependencies/napi/napi-direct/OnLinkedAsDependency.cmake rename to Dependencies/napi/OnLinkedAsDependency.cmake index 51b1d9761..497402d6a 100644 --- a/Dependencies/napi/napi-direct/OnLinkedAsDependency.cmake +++ b/Dependencies/napi/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) # 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 $) + set_property(SOURCE ${NAPI_JAVASCRIPT_RUNTIME_OUTPUT_ARTIFACTS_RELEASE} PROPERTY VS_DEPLOYMENT_CONTENT $>) + 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} $) - endforeach(artifact) + endforeach() endif() endif() endif() -endfunction() +endfunction() \ No newline at end of file diff --git a/Dependencies/napi/napi-direct/CMakeLists.txt b/Dependencies/napi/napi-direct/CMakeLists.txt index 6c9ba6288..b0e3077eb 100644 --- a/Dependencies/napi/napi-direct/CMakeLists.txt +++ b/Dependencies/napi/napi-direct/CMakeLists.txt @@ -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() diff --git a/Dependencies/napi/napi-direct/include/napi/napi-inl.h b/Dependencies/napi/napi-direct/include/napi/napi-inl.h index 03f6c525c..a5308334c 100644 --- a/Dependencies/napi/napi-direct/include/napi/napi-inl.h +++ b/Dependencies/napi/napi-direct/include/napi/napi-inl.h @@ -1781,6 +1781,27 @@ inline Value Function::Call(napi_value recv, const std::vector& 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 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(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( diff --git a/Dependencies/napi/napi-direct/include/napi/napi.h b/Dependencies/napi/napi-direct/include/napi/napi.h index 1284e2cc0..aa767f40d 100644 --- a/Dependencies/napi/napi-direct/include/napi/napi.h +++ b/Dependencies/napi/napi-direct/include/napi/napi.h @@ -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& args) const; Value Call(napi_value recv, const std::vector& 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 diff --git a/Dependencies/napi/napi-direct/nuget.config b/Dependencies/napi/napi-direct/nuget.config new file mode 100644 index 000000000..db7d8b6cc --- /dev/null +++ b/Dependencies/napi/napi-direct/nuget.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Dependencies/napi/napi-jsi/CMakeLists.txt b/Dependencies/napi/napi-jsi/CMakeLists.txt index 2d36ae64e..71f3bbba0 100644 --- a/Dependencies/napi/napi-jsi/CMakeLists.txt +++ b/Dependencies/napi/napi-jsi/CMakeLists.txt @@ -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" @@ -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}/$,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 diff --git a/Dependencies/napi/napi-jsi/include/napi/napi.h b/Dependencies/napi/napi-jsi/include/napi/napi.h index 5b7eeb741..56dd9f5c6 100644 --- a/Dependencies/napi/napi-jsi/include/napi/napi.h +++ b/Dependencies/napi/napi-jsi/include/napi/napi.h @@ -8,7 +8,7 @@ #include #include -// Copied from js_native_api.h +// Copied from js_native_api_types.h (https://git.io/J8aI5) typedef enum { napi_default = 0, napi_writable = 1 << 0, @@ -39,6 +39,9 @@ typedef enum { napi_uint32_array, napi_float32_array, napi_float64_array, + // JSI doesn't support bigint. + // napi_bigint64_array, + // napi_biguint64_array, } napi_typedarray_type; struct napi_env__ { diff --git a/Dependencies/napi/napi-jsi/nuget.config b/Dependencies/napi/napi-jsi/nuget.config new file mode 100644 index 000000000..c681fdbd5 --- /dev/null +++ b/Dependencies/napi/napi-jsi/nuget.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Dependencies/napi/napi-jsi/packages.config b/Dependencies/napi/napi-jsi/packages.config new file mode 100644 index 000000000..f91b6758a --- /dev/null +++ b/Dependencies/napi/napi-jsi/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/NOTICE.md b/NOTICE.md index 381274b81..5268fe886 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -2197,3 +2197,31 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` + +# V8JSI + +``` +React Native V8 JSI adapter + +Copyright (c) Microsoft Corporation. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` \ No newline at end of file diff --git a/Plugins/ChromeDevTools/CMakeLists.txt b/Plugins/ChromeDevTools/CMakeLists.txt index 2b00bbf94..0c25df9b5 100644 --- a/Plugins/ChromeDevTools/CMakeLists.txt +++ b/Plugins/ChromeDevTools/CMakeLists.txt @@ -1,9 +1,14 @@ set(SOURCES "Include/Babylon/Plugins/ChromeDevTools.h") -set(CHROME_DEVTOOLS_SUPPORTED_ENGINES "V8") +if (WIN32) + set(CHROME_DEVTOOLS_SUPPORTED_ENGINES ${CHROME_DEVTOOLS_SUPPORTED_ENGINES} "JSI") + if (NOT WINDOWS_STORE) + set(CHROME_DEVTOOLS_SUPPORTED_ENGINES ${CHROME_DEVTOOLS_SUPPORTED_ENGINES} "V8") + endif() +endif() -if (NAPI_JAVASCRIPT_ENGINE IN_LIST CHROME_DEVTOOLS_SUPPORTED_ENGINES AND WIN32) +if (NAPI_JAVASCRIPT_ENGINE IN_LIST CHROME_DEVTOOLS_SUPPORTED_ENGINES) set(SOURCES ${SOURCES} "Source/ChromeDevTools${NAPI_JAVASCRIPT_ENGINE}.cpp") else() set(SOURCES ${SOURCES} "Source/ChromeDevToolsNull.cpp") @@ -12,14 +17,14 @@ endif() add_library(ChromeDevTools ${SOURCES}) warnings_as_errors(ChromeDevTools) +if (NAPI_JAVASCRIPT_ENGINE IN_LIST CHROME_DEVTOOLS_SUPPORTED_ENGINES AND NAPI_JAVASCRIPT_ENGINE STREQUAL "V8") + target_link_to_dependencies(ChromeDevTools PRIVATE v8inspector) +endif() + target_include_directories(ChromeDevTools INTERFACE "Include") target_include_directories(ChromeDevTools PRIVATE "Include/Babylon/Plugins") target_link_to_dependencies(ChromeDevTools PUBLIC JsRuntime) -if (NAPI_JAVASCRIPT_ENGINE STREQUAL "V8" AND WIN32) - target_link_to_dependencies(ChromeDevTools PRIVATE v8inspector) -endif() - set_property(TARGET ChromeDevTools PROPERTY FOLDER Plugins) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES}) diff --git a/Plugins/ChromeDevTools/Source/ChromeDevToolsJSI.cpp b/Plugins/ChromeDevTools/Source/ChromeDevToolsJSI.cpp new file mode 100644 index 000000000..ef5827aab --- /dev/null +++ b/Plugins/ChromeDevTools/Source/ChromeDevToolsJSI.cpp @@ -0,0 +1,76 @@ +#include "ChromeDevTools.h" + +#include +#include + +namespace Babylon::Plugins +{ + class ChromeDevTools::Impl final : public std::enable_shared_from_this + { + public: + explicit Impl(Napi::Env env) + : m_env(env) + { + JsRuntime::GetFromJavaScript(env).Dispatch([this](Napi::Env env) { + m_runtime = JsRuntime::NativeObject::GetFromJavaScript(env).Get("_JSIRuntime").As>().Data(); + }); + } + + ~Impl() + { + } + + bool SupportsInspector() + { + return true; + } + + void StartInspector(const unsigned short, const std::string&) + { + JsRuntime::GetFromJavaScript(m_env).Dispatch([this](Napi::Env) { + if (m_runtime != nullptr) + { + v8runtime::openInspector(*m_runtime); + } + }); + } + + void StopInspector() + { + } + + private: + facebook::jsi::Runtime* m_runtime; + Napi::Env m_env; + }; + + ChromeDevTools ChromeDevTools::Initialize(Napi::Env env) + { + return {std::make_shared(env)}; + } + + ChromeDevTools::ChromeDevTools(std::shared_ptr impl) + : m_impl{std::move(impl)} + { + } + + bool ChromeDevTools::SupportsInspector() const + { + return m_impl->SupportsInspector(); + } + + /* + Note: V8JSI doesn't currently support setting the port or appName at runtime. + For now the port is set to 5643 in AppRuntimeJSI.cpp. + */ + void ChromeDevTools::StartInspector(const unsigned short port, const std::string& appName) const + { + m_impl->StartInspector(port, appName); + } + + /* Note: V8JSI doesn't currently have a method for stopping the inspector at runtime. */ + void ChromeDevTools::StopInspector() const + { + m_impl->StopInspector(); + } +} diff --git a/Plugins/NativeCamera/Source/NativeCamera.cpp b/Plugins/NativeCamera/Source/NativeCamera.cpp index 65a3e4f42..f86a79cad 100644 --- a/Plugins/NativeCamera/Source/NativeCamera.cpp +++ b/Plugins/NativeCamera/Source/NativeCamera.cpp @@ -68,16 +68,16 @@ namespace Babylon Napi::Object mediaDevices = Napi::Object::New(env); mediaDevices.Set("getUserMedia", Napi::Function::New(env, [](const Napi::CallbackInfo& info) { auto env = info.Env(); - auto deferred{ Napi::Promise::Deferred::New(env) }; - auto promise{ deferred.Promise() }; + auto deferred{Napi::Promise::Deferred::New(env)}; + auto promise{deferred.Promise()}; - auto& jsRuntime{ JsRuntime::GetFromJavaScript(env) }; - jsRuntime.Dispatch([deferred{ std::move(deferred) }](Napi::Env env) { + auto& jsRuntime{JsRuntime::GetFromJavaScript(env)}; + jsRuntime.Dispatch([deferred{std::move(deferred)}](Napi::Env env) { deferred.Resolve(env.Null()); }); - return promise; - })); + return static_cast(promise); + }, "getUserMedia")); navigator.Set("mediaDevices", mediaDevices); } diff --git a/Polyfills/Console/Source/Console.cpp b/Polyfills/Console/Source/Console.cpp index 6a90a7569..57f5aee23 100644 --- a/Polyfills/Console/Source/Console.cpp +++ b/Polyfills/Console/Source/Console.cpp @@ -5,9 +5,9 @@ namespace { - std::vector GetCallbackInfoArgs(const Napi::CallbackInfo& info) + std::vector GetCallbackInfoArgs(const Napi::CallbackInfo& info) { - auto args = std::vector(); + auto args = std::vector(); for (unsigned int index = 0; index < info.Length(); index++) args.push_back(info[index]); return args; @@ -34,7 +34,7 @@ namespace Babylon::Polyfills::Internal const auto existingConsole = env.Global().Get(JS_INSTANCE_NAME); if (!existingConsole.IsUndefined()) { - Console::Unwrap(console)->m_engineConsole = std::make_unique(Napi::Persistent(existingConsole.As())); + Console::Unwrap(console)->m_engineConsole = std::make_unique(Napi::Persistent(existingConsole.As())); } env.Global().Set(JS_INSTANCE_NAME, console); } @@ -83,8 +83,10 @@ namespace Babylon::Polyfills::Internal if (m_engineConsole != nullptr) { const auto engineConsoleFunc = m_engineConsole->Value().Get(functionName).As(); - if (!engineConsoleFunc.IsUndefined()) - engineConsoleFunc.As().Call(m_engineConsole->Value(), GetCallbackInfoArgs(info)); + if (!engineConsoleFunc.IsUndefined()) { + const auto args = GetCallbackInfoArgs(info); + engineConsoleFunc.As().Call(m_engineConsole->Value(), args.size(), args.data()); + } } } } diff --git a/Polyfills/Console/Source/Console.h b/Polyfills/Console/Source/Console.h index 210a82eb2..eb2b50916 100644 --- a/Polyfills/Console/Source/Console.h +++ b/Polyfills/Console/Source/Console.h @@ -22,7 +22,7 @@ namespace Babylon::Polyfills::Internal void InvokeCallback(const Napi::CallbackInfo& info, Babylon::Polyfills::Console::LogLevel logLevel) const; void InvokeEngineCallback(const std::string functionName, const Napi::CallbackInfo& info); - std::unique_ptr m_engineConsole{}; + std::unique_ptr m_engineConsole{}; Babylon::Polyfills::Console::CallbackT m_callback{}; }; }