diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index e4da3cec69cf..6fc2809f4629 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -424,11 +424,11 @@ jobs: uses: ./.github/actions/build-android with: release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }} - run-e2e-tests: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }} + run-e2e-tests: true #${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }} gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} test_e2e_android_rntester: - if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }} + #if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, 'stable') || inputs.run-e2e-tests }} runs-on: 4-core-ubuntu needs: [build_android] strategy: diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt index fcd48e2cd9c6..c1c550cd6491 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt @@ -126,8 +126,6 @@ internal object NdkConfiguratorUtils { ): Pair, List> { val excludes = mutableListOf() val includes = mutableListOf() - - // note: libjsctooling.so is kept here for backward compatibility. when { hermesEnabled -> { excludes.add("**/libjsc.so") diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 19eef9468a74..f4e0a5b99a94 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -2448,6 +2448,19 @@ public abstract interface class com/facebook/react/interfaces/fabric/ReactSurfac public abstract fun stop ()Lcom/facebook/react/interfaces/TaskInterface; } +public final class com/facebook/react/jscexecutor/JSCExecutor : com/facebook/react/bridge/JavaScriptExecutor { + public fun getName ()Ljava/lang/String; + public static final fun loadLibrary ()V +} + +public final class com/facebook/react/jscexecutor/JSCExecutorFactory : com/facebook/react/bridge/JavaScriptExecutorFactory { + public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun create ()Lcom/facebook/react/bridge/JavaScriptExecutor; + public fun startSamplingProfiler ()V + public fun stopSamplingProfiler (Ljava/lang/String;)V + public fun toString ()Ljava/lang/String; +} + public final class com/facebook/react/jstasks/HeadlessJsTaskConfig { public fun (Lcom/facebook/react/jstasks/HeadlessJsTaskConfig;)V public fun (Ljava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V @@ -3122,6 +3135,10 @@ public class com/facebook/react/runtime/CoreReactPackage$$ReactModuleInfoProvide public fun getReactModuleInfos ()Ljava/util/Map; } +public final class com/facebook/react/runtime/JSCInstance : com/facebook/react/runtime/JSRuntimeFactory { + public fun ()V +} + public abstract class com/facebook/react/runtime/JSRuntimeFactory { public fun (Lcom/facebook/jni/HybridData;)V } @@ -3236,6 +3253,10 @@ public final class com/facebook/react/soloader/OpenSourceMergedSoMapping : com/f public final fun libhermes_executor_so ()I public final fun libhermesinstancejni_so ()I public final fun libhermestooling_so ()I + public final fun libjscexecutor_so ()I + public final fun libjscinstance_so ()I + public final fun libjscruntime_so ()I + public final fun libjsctooling_so ()I public final fun libjsijniprofiler_so ()I public final fun libjsinspector_so ()I public final fun libmapbufferjni_so ()I diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index 1b3991d46793..c0ddc00a0da5 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -87,6 +87,8 @@ val preparePrefab by // hermes_executor // This prefab targets is used by Expo & Reanimated Pair("../ReactCommon/hermes/inspector-modern/", "hermes/inspector-modern/"), + // jscexecutor + Pair("../ReactCommon/jsc/", "jsc/"), // fabricjni Pair("src/main/jni/react/fabric", "react/fabric/"), // glog @@ -234,6 +236,10 @@ val preparePrefab by "hermestooling", // hermes_executor Pair("../ReactCommon/hermes/inspector-modern/", "hermes/inspector-modern/")), + PrefabPreprocessingEntry( + "jsctooling", + // jsc + Pair("../ReactCommon/jsc/", "jsc/")), )) outputDir.set(prefabHeadersDir) } @@ -528,6 +534,7 @@ android { "reactnative", "jsi", "hermestooling", + "jsctooling", ) } } @@ -576,9 +583,10 @@ android { resources.excludes.add("META-INF/LICENSE") // We intentionally don't want to bundle any JS Runtime inside the Android AAR // we produce. The reason behind this is that we want to allow users to pick the - // JS engine by specifying a dependency on either `hermes-engine` or other engines + // JS engine by specifying a dependency on either `hermes-engine` or `android-jsc` // that will include the necessary .so files to load. jniLibs.excludes.add("**/libhermes.so") + jniLibs.excludes.add("**/libjsc.so") } buildFeatures { @@ -591,6 +599,7 @@ android { create("jsi") { headers = File(prefabHeadersDir, "jsi").absolutePath } create("reactnative") { headers = File(prefabHeadersDir, "reactnative").absolutePath } create("hermestooling") { headers = File(prefabHeadersDir, "hermestooling").absolutePath } + create("jsctooling") { headers = File(prefabHeadersDir, "jsctooling").absolutePath } } publishing { @@ -635,9 +644,10 @@ dependencies { compileOnly(libs.javax.annotation.api) api(libs.javax.inject) - // It's up to the consumer to decide if hermes or other engines should be included or not. - // Therefore hermes-engine is a compileOnly dependencies. + // It's up to the consumer to decide if hermes/jsc should be included or not. + // Therefore hermes-engine and jsc are compileOnly dependencies. compileOnly(project(":packages:react-native:ReactAndroid:hermes-engine")) + compileOnly(libs.jsc.android) testImplementation(libs.junit) testImplementation(libs.assertj) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt index 11b2814c48bb..7478a99a5ca8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt @@ -17,6 +17,7 @@ import com.facebook.react.common.annotations.UnstableReactNativeAPI import com.facebook.react.common.build.ReactBuildConfig import com.facebook.react.fabric.ComponentFactory import com.facebook.react.runtime.BindingsInstaller +import com.facebook.react.runtime.JSCInstance import com.facebook.react.runtime.JSRuntimeFactory import com.facebook.react.runtime.ReactHostImpl import com.facebook.react.runtime.cxxreactpackage.CxxReactPackage @@ -207,7 +208,7 @@ public object DefaultReactHost { jsMainModulePath, jsBundleAssetPath, jsBundleFilePath, - HermesInstance(), + if (isHermesEnabled) HermesInstance() else JSCInstance(), useDevSupport, cxxReactPackageProviders, exceptionHandler, @@ -263,7 +264,7 @@ public object DefaultReactHost { jsMainModulePath, jsBundleAssetPath, jsBundleFilePath, - HermesInstance(), + if (isHermesEnabled) HermesInstance() else JSCInstance(), useDevSupport, cxxReactPackageProviders, ) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt index 8a98a43c91fc..ba4679613892 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt @@ -17,6 +17,7 @@ import com.facebook.react.bridge.UIManagerProvider import com.facebook.react.common.annotations.UnstableReactNativeAPI import com.facebook.react.fabric.ComponentFactory import com.facebook.react.fabric.FabricUIManagerProviderImpl +import com.facebook.react.runtime.JSCInstance import com.facebook.react.runtime.JSRuntimeFactory import com.facebook.react.runtime.hermes.HermesInstance import com.facebook.react.uimanager.ViewManagerRegistry @@ -92,9 +93,6 @@ protected constructor( * If true, the app will load the Hermes engine, and fail if not found. If false, the app will * load the JSC engine, and fail if not found. */ - @Deprecated( - "Setting isHermesEnabled inside `ReactNativeHost` is deprecated and this field will be ignored. If this field is set to true, you can safely remove it. If this field is set to false, please follow the setup on https://github.com/react-native-community/javascriptcore to continue using JSC", - ReplaceWith("")) protected open val isHermesEnabled: Boolean get() = true @@ -108,7 +106,8 @@ protected constructor( context: Context, jsRuntimeFactory: JSRuntimeFactory? = null ): ReactHost { - val concreteJSRuntimeFactory = jsRuntimeFactory ?: HermesInstance() + val concreteJSRuntimeFactory = + jsRuntimeFactory ?: if (isHermesEnabled) HermesInstance() else JSCInstance() return DefaultReactHost.getDefaultReactHost( context, packages, diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.kt new file mode 100644 index 000000000000..d0b3a466b80e --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.jscexecutor + +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.facebook.react.bridge.JavaScriptExecutor +import com.facebook.react.bridge.ReadableNativeMap +import com.facebook.react.common.annotations.internal.LegacyArchitecture +import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger +import com.facebook.soloader.SoLoader + +@DoNotStrip +@LegacyArchitecture +public class JSCExecutor internal constructor(jscConfig: ReadableNativeMap) : + JavaScriptExecutor(initHybrid(jscConfig)) { + + override fun getName(): String { + return "JSCExecutor" + } + + internal companion object { + init { + loadLibrary() + LegacyArchitectureLogger.assertLegacyArchitecture("JSCExecutor") + } + + @JvmStatic + @Throws(UnsatisfiedLinkError::class) + fun loadLibrary() { + SoLoader.loadLibrary("jscexecutor") + } + + @JvmStatic private external fun initHybrid(jscConfig: ReadableNativeMap): HybridData + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutorFactory.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutorFactory.kt new file mode 100644 index 000000000000..6994187fa446 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutorFactory.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.jscexecutor + +import com.facebook.react.bridge.JavaScriptExecutor +import com.facebook.react.bridge.JavaScriptExecutorFactory +import com.facebook.react.bridge.WritableNativeMap +import com.facebook.react.common.annotations.internal.LegacyArchitecture +import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel +import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger + +@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR) +public class JSCExecutorFactory(private val appName: String, private val deviceName: String) : + JavaScriptExecutorFactory { + + init { + LegacyArchitectureLogger.assertLegacyArchitecture( + "JSCExecutorFactory", LegacyArchitectureLogLevel.ERROR) + } + + @Throws(Exception::class) + override fun create(): JavaScriptExecutor { + val jscConfig = + WritableNativeMap().apply { + putString("OwnerIdentity", "ReactNative") + putString("AppIdentity", appName) + putString("DeviceIdentity", deviceName) + } + return JSCExecutor(jscConfig) + } + + override fun startSamplingProfiler() { + throw UnsupportedOperationException("Starting sampling profiler not supported on ${toString()}") + } + + override fun stopSamplingProfiler(filename: String) { + throw UnsupportedOperationException("Stopping sampling profiler not supported on ${toString()}") + } + + override fun toString(): String = "JSIExecutor+JSCRuntime" +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSCInstance.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSCInstance.kt new file mode 100644 index 000000000000..3f2227547c23 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/JSCInstance.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.runtime + +import com.facebook.jni.HybridData +import com.facebook.jni.annotations.DoNotStrip +import com.facebook.jni.annotations.DoNotStripAny +import com.facebook.soloader.SoLoader + +@DoNotStripAny +public class JSCInstance : JSRuntimeFactory(initHybrid()) { + private companion object { + init { + SoLoader.loadLibrary("jscinstance") + } + + @DoNotStrip @JvmStatic private external fun initHybrid(): HybridData + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/soloader/OpenSourceMergedSoMapping.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/soloader/OpenSourceMergedSoMapping.kt index 3dff8f2cd33e..f12130841bcd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/soloader/OpenSourceMergedSoMapping.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/soloader/OpenSourceMergedSoMapping.kt @@ -42,6 +42,11 @@ public object OpenSourceMergedSoMapping : ExternalSoMapping { "jsijniprofiler" -> { "hermestooling" } + "jscexecutor", + "jscruntime", + "jscinstance" -> { + "jsctooling" + } else -> input } @@ -51,6 +56,10 @@ public object OpenSourceMergedSoMapping : ExternalSoMapping { "hermes_executor" -> libhermes_executor_so() "hermesinstancejni" -> libhermesinstancejni_so() "hermestooling" -> libhermestooling_so() + "jscexecutor" -> libjscexecutor_so() + "jscinstance" -> libjscinstance_so() + "jscruntime" -> libjscruntime_so() + "jsctooling" -> libjsctooling_so() "jsijniprofiler" -> libjsijniprofiler_so() "jsinspector" -> libjsinspector_so() "mapbufferjni" -> libmapbufferjni_so() @@ -76,6 +85,14 @@ public object OpenSourceMergedSoMapping : ExternalSoMapping { public external fun libhermestooling_so(): Int + public external fun libjscexecutor_so(): Int + + public external fun libjscinstance_so(): Int + + public external fun libjscruntime_so(): Int + + public external fun libjsctooling_so(): Int + public external fun libjsijniprofiler_so(): Int public external fun libjsinspector_so(): Int diff --git a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt index 8af445da612e..4c9074580694 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt @@ -51,7 +51,9 @@ endfunction() # Third-party prefabs find_package(hermes-engine REQUIRED CONFIG) find_package(fbjni REQUIRED CONFIG) +find_package(jsc-android REQUIRED CONFIG) add_library(fbjni ALIAS fbjni::fbjni) +add_library(jsc ALIAS jsc-android::jsc) # Third-party downloaded targets add_react_third_party_ndk_subdir(glog) @@ -69,6 +71,7 @@ add_react_common_subdir(logger) add_react_common_subdir(jsiexecutor) add_react_common_subdir(jsitooling) add_react_common_subdir(cxxreact) +add_react_common_subdir(jsc) add_react_common_subdir(jsi) add_react_common_subdir(callinvoker) add_react_common_subdir(oscompat) @@ -137,6 +140,8 @@ add_react_android_subdir(src/main/jni/first-party/yogajni) add_react_android_subdir(src/main/jni/first-party/jni-lib-merge) add_react_android_subdir(src/main/jni/react/jni) add_react_android_subdir(src/main/jni/react/reactperflogger) +add_react_android_subdir(src/main/jni/react/jscexecutor) +add_react_android_subdir(src/main/jni/react/jsctooling) add_react_android_subdir(src/main/jni/react/turbomodule) add_react_android_subdir(src/main/jni/react/uimanager) add_react_android_subdir(src/main/jni/react/mapbuffer) @@ -150,6 +155,7 @@ add_react_android_subdir(src/main/jni/react/hermes/instrumentation/) add_react_android_subdir(src/main/jni/react/runtime/cxxreactpackage) add_react_android_subdir(src/main/jni/react/runtime/jni) add_react_android_subdir(src/main/jni/react/runtime/hermes/jni) +add_react_android_subdir(src/main/jni/react/runtime/jsc/jni) add_react_android_subdir(src/main/jni/react/devsupport) # SoMerging Utils diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/hermes/tooling/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/hermes/tooling/CMakeLists.txt index 5ef9fcc9bae5..5450a254f16b 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/hermes/tooling/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/react/hermes/tooling/CMakeLists.txt @@ -12,6 +12,7 @@ include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake) # hermestooling is a shared library where we merge all the hermes* related libraries. # # It acts as an 'umbrella' library and gets removed by RNGP (see `configureJsEnginePackagingOptions`) +# Please note that this library gets removed for users that opt to use JSC as their JS engine. add_library(hermestooling SHARED diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/jscexecutor/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/jscexecutor/CMakeLists.txt new file mode 100644 index 000000000000..45220a760c8a --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/jscexecutor/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +add_compile_options(-fvisibility=hidden -fexceptions -frtti) + +include(${REACT_ANDROID_DIR}/src/main/jni/first-party/jni-lib-merge/SoMerging-utils.cmake) +include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake) + +file(GLOB jscexecutor_SRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +add_library(jscexecutor OBJECT ${jscexecutor_SRC}) + +target_include_directories(jscexecutor PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_merge_so(jscexecutor) + +# Patch from Expo: https://github.com/expo/react-native/blob/02714ab44d1e206fa80e81aef618e61017cccdc1/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/CMakeLists.txt#L16-L25 +# Explicitly link libgcc.a to prevent undefined `_Unwind_Resume` symbol and crash from throwing c++ exceptions even someone tries to catch the exceptions. +# according to https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#unwinding, +# we should put the unwinder between static libs and shared libs. +# +# TODO(ncor): we don't need this patch anymore after upgrading to ndk r23 +if(ANDROID_NDK_REVISION VERSION_LESS "23.0.0") + set(LIB_UNWIND gcc) +else() + set(LIB_UNWIND unwind) +endif() + +target_link_libraries(jscexecutor + ${LIB_UNWIND} + jscruntime + jsi + reactnative) +target_compile_reactnative_options(jscexecutor PRIVATE) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/jscexecutor/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/jscexecutor/OnLoad.cpp new file mode 100644 index 000000000000..7cf63d7ceba2 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/jscexecutor/OnLoad.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace facebook::react { + +namespace { + +class JSCExecutorFactory : public JSExecutorFactory { + public: + std::unique_ptr createJSExecutor( + std::shared_ptr delegate, + std::shared_ptr jsQueue) override { + return std::make_unique( + jsc::makeJSCRuntime(), + delegate, + JSIExecutor::defaultTimeoutInvoker, + [](jsi::Runtime& runtime) { + react::bindNativeLogger(runtime, &reactAndroidLoggingHook); + }); + } +}; + +} // namespace + +// This is not like JSCJavaScriptExecutor, which calls JSC directly. This uses +// JSIExecutor with JSCRuntime. +class JSCExecutorHolder + : public jni::HybridClass { + public: + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/jscexecutor/JSCExecutor;"; + + static jni::local_ref initHybrid( + jni::alias_ref, + ReadableNativeMap*) { + // This is kind of a weird place for stuff, but there's no other + // good place for initialization which is specific to JSC on + // Android. + JReactMarker::setLogPerfMarkerIfNeeded(); + // TODO mhorowitz T28461666 fill in some missing nice to have glue + return makeCxxInstance(std::make_unique()); + } + + static void registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JSCExecutorHolder::initHybrid), + }); + } + + private: + friend HybridBase; + using HybridBase::HybridBase; +}; + +} // namespace facebook::react + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { + return facebook::jni::initialize( + vm, [] { facebook::react::JSCExecutorHolder::registerNatives(); }); +} diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/jsctooling/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/jsctooling/CMakeLists.txt new file mode 100644 index 000000000000..a69153fe3cea --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/jsctooling/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +include(${REACT_ANDROID_DIR}/src/main/jni/first-party/jni-lib-merge/SoMerging-utils.cmake) +include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake) + +# jsctooling is a shared library where we merge all the jsc* related libraries. +# +# It acts as an 'umbrella' library and gets removed by RNGP (see `configureJsEnginePackagingOptions`) +# Please note that this library gets removed for users that opt to use Hermes as their JS engine. + +add_library(jsctooling + SHARED + $ + $ + $ + $ +) +target_merge_so(jsctooling) +target_link_libraries(jsctooling + PUBLIC + reactnative + jsc +) +target_include_directories(jsctooling + PUBLIC + $ + $ + $ +) +target_compile_reactnative_options(jsctooling PRIVATE) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/CMakeLists.txt new file mode 100644 index 000000000000..3bc33bb105d5 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + + +include(${REACT_ANDROID_DIR}/src/main/jni/first-party/jni-lib-merge/SoMerging-utils.cmake) +include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake) + +file(GLOB jscinstance_SRC CONFIGURE_DEPENDS "*.cpp") + +add_library(jscinstance OBJECT ${jscinstance_SRC}) + +target_include_directories(jscinstance PUBLIC .) +target_merge_so(jscinstance) + +target_link_libraries(jscinstance + jscruntime + fbjni + reactnative +) +target_compile_reactnative_options(jscinstance PRIVATE) +target_compile_options(jscinstance PRIVATE -fvisibility=hidden) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp new file mode 100644 index 000000000000..e49a55d50243 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jsc/jni/OnLoad.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace facebook::react { + +class JSCInstance : public jni::HybridClass { + public: + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/runtime/JSCInstance;"; + + static jni::local_ref initHybrid(jni::alias_ref) { + return makeCxxInstance(); + } + + static void registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JSCInstance::initHybrid), + }); + } + + std::unique_ptr createJSRuntime( + std::shared_ptr msgQueueThread) noexcept { + return std::make_unique(jsc::makeJSCRuntime()); + } + + private: + friend HybridBase; + using HybridBase::HybridBase; +}; + +} // namespace facebook::react + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { + return facebook::jni::initialize( + vm, [] { facebook::react::JSCInstance::registerNatives(); }); +}