diff --git a/package.json b/package.json index b207048a35d4..9df784781ff0 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "packages/react-native-reanimated", "packages/eslint-plugin-reanimated", "packages/react-native-reanimated/plugin", + "packages/react-native-worklets", "apps/common-app", "apps/paper-example", "apps/fabric-example", diff --git a/packages/react-native-worklets/.eslintrc.js b/packages/react-native-worklets/.eslintrc.js new file mode 100644 index 000000000000..17799e759208 --- /dev/null +++ b/packages/react-native-worklets/.eslintrc.js @@ -0,0 +1,4 @@ +/** @type {import('eslint').ESLint.ConfigData} */ +module.exports = { + extends: ['../../.eslintrc.js'], +}; diff --git a/packages/react-native-worklets/.gitattributes b/packages/react-native-worklets/.gitattributes new file mode 100644 index 000000000000..e27f70fa4909 --- /dev/null +++ b/packages/react-native-worklets/.gitattributes @@ -0,0 +1,3 @@ +*.pbxproj -text +# specific for windows script files +*.bat text eol=crlf diff --git a/packages/react-native-worklets/.gitignore b/packages/react-native-worklets/.gitignore new file mode 100644 index 000000000000..9a3d039c59d5 --- /dev/null +++ b/packages/react-native-worklets/.gitignore @@ -0,0 +1,62 @@ +# OSX +.DS_Store + +# VSCode +.vscode/ +jsconfig.json + +# Xcode +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +project.xcworkspace + +# Android/IJ +.classpath +.cxx +.gradle +.idea +.project +.settings +local.properties +android.iml + +# node.js +node_modules/ +npm-debug.log +yarn-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +android/app/libs +android/keystores/debug.keystore + +# Yarn +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# generated by bob +lib/ + +# React Native Codegen +apple/generated +android/generated diff --git a/packages/react-native-worklets/.watchmanconfig b/packages/react-native-worklets/.watchmanconfig new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/react-native-worklets/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/packages/react-native-worklets/LICENSE b/packages/react-native-worklets/LICENSE new file mode 100644 index 000000000000..6882e4794af2 --- /dev/null +++ b/packages/react-native-worklets/LICENSE @@ -0,0 +1,20 @@ +MIT License + +Copyright (c) 2024 nobody +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. diff --git a/packages/react-native-worklets/RNWorklets.podspec b/packages/react-native-worklets/RNWorklets.podspec new file mode 100644 index 000000000000..9dcdc62ff156 --- /dev/null +++ b/packages/react-native-worklets/RNWorklets.podspec @@ -0,0 +1,64 @@ +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' + +Pod::Spec.new do |s| + s.name = "RNWorklets" + s.version = package["version"] + s.summary = package["description"] + s.homepage = "https://github.com/software-mansion/react-native-reanimated" + s.license = package["license"] + s.authors = { "author" => "author@domain.com" } + s.platforms = { :ios => min_ios_version_supported } + s.source = { :git => "https://github.com/software-mansion/react-native-reanimated.git", :tag => "#{s.version}" } + + s.source_files = "apple/*.{h,m,mm,cpp}" + + s.subspec "worklets" do |ss| + ss.source_files = "Common/cpp/worklets/**/*.{cpp,h}" + ss.header_dir = "worklets" + ss.header_mappings_dir = "Common/cpp/worklets" + + ss.subspec "apple" do |sss| + # Please be careful with the snakes. + # 🐍🐍🐍 + # Thank you for your understanding. + sss.source_files = "apple/worklets/**/*.{mm,h,m}" + sss.header_dir = "worklets" + sss.header_mappings_dir = "apple/worklets" + end + end + + # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. + # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79. + if respond_to?(:install_modules_dependencies, true) + install_modules_dependencies(s) + else + s.dependency "React-Core" + + # Don't install the dependencies when we run `pod install` in the old architecture. + if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then + s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", + "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + } + s.dependency "React-Codegen" + s.dependency "RCT-Folly" + s.dependency "RCTRequired" + s.dependency "RCTTypeSafety" + s.dependency "ReactCommon/turbomodule/core" + end + end + + s.pod_target_xcconfig = { + "USE_HEADERMAP" => "YES", + "DEFINES_MODULE" => "YES", + "HEADER_SEARCH_PATHS" => '"$(PODS_TARGET_SRCROOT)/ReactCommon" "$(PODS_TARGET_SRCROOT)" "$(PODS_ROOT)/RCT-Folly" "$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/DoubleConversion" "$(PODS_ROOT)/Headers/Private/React-Core" "$(PODS_ROOT)/Headers/Private/Yoga"', + "FRAMEWORK_SEARCH_PATHS" => '"${PODS_CONFIGURATION_BUILD_DIR}/React-hermes"', + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", + } + +end diff --git a/packages/react-native-worklets/android/CMakeLists.txt b/packages/react-native-worklets/android/CMakeLists.txt new file mode 100644 index 000000000000..c2e3256d0724 --- /dev/null +++ b/packages/react-native-worklets/android/CMakeLists.txt @@ -0,0 +1,60 @@ +project(Worklets) +cmake_minimum_required(VERSION 3.8) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS + ON + CACHE INTERNAL "") + +set(CMAKE_CXX_STANDARD 20) + +# default CMAKE_CXX_FLAGS: "-g -DANDROID -fdata-sections -ffunction-sections +# -funwind-tables -fstack-protector-strong -no-canonical-prefixes +# -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fstack-protector-all" +include("${REACT_NATIVE_DIR}/ReactAndroid/cmake-utils/folly-flags.cmake") +add_compile_options(${folly_FLAGS}) + +string( + APPEND + CMAKE_CXX_FLAGS + " -DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION} -DREANIMATED_VERSION=${REANIMATED_VERSION} -DHERMES_ENABLE_DEBUGGER=${HERMES_ENABLE_DEBUGGER}" +) + +string( + APPEND + CMAKE_CXX_FLAGS + " -fexceptions -fno-omit-frame-pointer -frtti -fstack-protector-all -std=c++${CMAKE_CXX_STANDARD} -Wall -Werror" +) + +if(${IS_NEW_ARCHITECTURE_ENABLED}) + string(APPEND CMAKE_CXX_FLAGS " -DRCT_NEW_ARCH_ENABLED") +endif() + +if(${IS_REANIMATED_EXAMPLE_APP}) + string(APPEND CMAKE_CXX_FLAGS " -DIS_REANIMATED_EXAMPLE_APP -Wpedantic") +endif() + +if(NOT ${CMAKE_BUILD_TYPE} MATCHES "Debug") + string(APPEND CMAKE_CXX_FLAGS " -DNDEBUG") +endif() + +if(${JS_RUNTIME} STREQUAL "hermes") + string(APPEND CMAKE_CXX_FLAGS " -DJS_RUNTIME_HERMES=1") +elseif(${JS_RUNTIME} STREQUAL "jsc") + string(APPEND CMAKE_CXX_FLAGS " -DJS_RUNTIME_JSC=1") +elseif(${JS_RUNTIME} STREQUAL "v8") + string(APPEND CMAKE_CXX_FLAGS " -DJS_RUNTIME_V8=1") +else() + message(FATAL_ERROR "Unknown JS runtime ${JS_RUNTIME}.") +endif() + +# Resolves "CMake Warning: Manually-specified variables were not used by the +# project" when any of the following variables is not used in some build +# configuration. +set(ignoreMe "${JS_RUNTIME_DIR}") + +set(BUILD_DIR "${CMAKE_SOURCE_DIR}/build") +set(ANDROID_CPP_DIR "${CMAKE_SOURCE_DIR}/src/main/cpp") +set(COMMON_CPP_DIR "${CMAKE_SOURCE_DIR}/../Common/cpp") + +add_subdirectory("${ANDROID_CPP_DIR}/worklets") diff --git a/packages/react-native-worklets/android/build.gradle b/packages/react-native-worklets/android/build.gradle new file mode 100644 index 000000000000..4c532e212013 --- /dev/null +++ b/packages/react-native-worklets/android/build.gradle @@ -0,0 +1,438 @@ +import com.android.Version +import org.apache.tools.ant.filters.ReplaceTokens +import org.apache.tools.ant.taskdefs.condition.Os +import groovy.json.JsonSlurper +import com.android.build.gradle.tasks.ExternalNativeBuildJsonTask + +import javax.inject.Inject +import java.nio.file.Files +import java.nio.file.Paths + +/** + * Finds the path of the installed npm package with the given name using Node's + * module resolution algorithm, which searches "node_modules" directories up to + * the file system root. This handles various cases, including: + * + * - Working in the open-source RN repo: + * Gradle: /path/to/react-native/ReactAndroid + * Node module: /path/to/react-native/node_modules/[package] + * + * - Installing RN as a dependency of an app and searching for hoisted + * dependencies: + * Gradle: /path/to/app/node_modules/react-native/ReactAndroid + * Node module: /path/to/app/node_modules/[package] + * + * - Working in a larger repo (e.g., Facebook) that contains RN: + * Gradle: /path/to/repo/path/to/react-native/ReactAndroid + * Node module: /path/to/repo/node_modules/[package] + * + * The search begins at the given base directory (a File object). The returned + * path is a string. + */ +static def findNodeModulePath(baseDir, packageName) { + def basePath = baseDir.toPath().normalize() + // Node's module resolution algorithm searches up to the root directory, + // after which the base path will be null + while (basePath) { + def candidatePath = Paths.get(basePath.toString(), "node_modules", packageName) + if (candidatePath.toFile().exists()) { + return candidatePath.toString() + } + basePath = basePath.getParent() + } + return null +} + +def safeExtGet(prop, fallback) { + rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback +} + +def safeAppExtGet(prop, fallback) { + def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') } + appProject?.ext?.has(prop) ? appProject.ext.get(prop) : fallback +} + +def resolveBuildType() { + Gradle gradle = getGradle() + String tskReqStr = gradle.getStartParameter().getTaskRequests()['args'].toString() + return tskReqStr.contains('Release') ? 'release' : 'debug' +} + +def isReanimatedExampleApp() { + return safeAppExtGet("isReanimatedExampleApp", false) +} + +def isNewArchitectureEnabled() { + // To opt-in for the New Architecture, you can either: + // - Set `newArchEnabled` to true inside the `gradle.properties` file + // - Invoke gradle with `-newArchEnabled=true` + // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` + return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" +} + +def resolveReactNativeDirectory() { + def reactNativeLocation = safeAppExtGet("REACT_NATIVE_NODE_MODULES_DIR", null) + if (reactNativeLocation != null) { + return file(reactNativeLocation) + } + + // Fallback to node resolver for custom directory structures like monorepos. + def reactNativePackage = file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()) + if(reactNativePackage.exists()) { + return reactNativePackage.parentFile + } + + throw new GradleException( + "[Reanimated] Unable to resolve react-native location in node_modules. You should project extension property (in `app/build.gradle`) `REACT_NATIVE_NODE_MODULES_DIR` with path to react-native." + ) +} + +def getPlaygroundAppName() { // only for the development + String playgroundAppName = "" + try { + rootProject.getSubprojects().forEach({project -> + if (project.plugins.hasPlugin("com.android.application")) { + var projectCatalogAbsolutePath = project.projectDir.toString().replace("/android/app", "") + var slashPosition = projectCatalogAbsolutePath.lastIndexOf("/") + playgroundAppName = projectCatalogAbsolutePath.substring(slashPosition + 1) + } + }) + } catch (_) { + throw new GradleException("[Reanimated] Couldn't determine playground app name.") + } + return playgroundAppName +} + +def toPlatformFileString(String path) { + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + path = path.replace(File.separatorChar, '/' as char) + } + return path +} + +if (isNewArchitectureEnabled()) { + apply plugin: "com.facebook.react" +} + +def reactNativeRootDir = resolveReactNativeDirectory() + +def reactProperties = new Properties() +file("$reactNativeRootDir/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) } + +def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME") +def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger() +def IS_NEW_ARCHITECTURE_ENABLED = isNewArchitectureEnabled() + +// We download various C++ open-source dependencies into downloads. +// We then copy both the downloaded code and our custom makefiles and headers into third-party-ndk. +// After that we build native code from src/main/jni with module path pointing at third-party-ndk. + +def customDownloadsDir = System.getenv("REACT_NATIVE_DOWNLOADS_DIR") +def downloadsDir = customDownloadsDir ? new File(customDownloadsDir) : new File("$buildDir/downloads") +def thirdPartyNdkDir = new File("$buildDir/third-party-ndk") + +def reactNativeThirdParty = new File("$reactNativeRootDir/ReactAndroid/src/main/jni/third-party") +def reactNativeAndroidDownloadDir = new File("$reactNativeRootDir/ReactAndroid/build/downloads") + +def workletsPrefabHeadersDir = project.file("$buildDir/prefab-headers/worklets") + +def JS_RUNTIME = { + // Override JS runtime with environment variable + if (System.getenv("JS_RUNTIME")) { + return System.getenv("JS_RUNTIME") + } + + // Enable V8 runtime if react-native-v8 is installed + def v8Project = rootProject.getSubprojects().find { project -> project.name == "react-native-v8" } + if (v8Project != null) { + return "v8" + } + + // Check if Hermes is enabled in app setup + def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') } + if (appProject?.hermesEnabled?.toBoolean() || appProject?.ext?.react?.enableHermes?.toBoolean()) { + return "hermes" + } + + // Use JavaScriptCore (JSC) by default + return "jsc" +}.call() + +def jsRuntimeDir = { + if (JS_RUNTIME == "hermes") { + return Paths.get(reactNativeRootDir.path, "sdks", "hermes") + } else if (JS_RUNTIME == "v8") { + return findProject(":react-native-v8").getProjectDir().getParent() + } else { + return Paths.get(reactNativeRootDir.path, "ReactCommon", "jsi") + } +}.call() + +def reactNativeArchitectures() { + def value = project.getProperties().get("reactNativeArchitectures") + return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] +} + +buildscript { + // Buildscript is evaluated before everything else so we can't use getExtOrDefault + def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["Worklets_kotlinVersion"] + + // repositories { + // google() + // mavenCentral() + // } + + repositories { + google() + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "com.android.tools.build:gradle:8.2.1" + classpath "de.undercouch:gradle-download-task:5.6.0" + classpath "com.diffplug.spotless:spotless-plugin-gradle:6.25.0" + // noinspection DifferentKotlinGradleVersion + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +if (project == rootProject) { + apply from: "spotless.gradle" +} + +apply plugin: "com.android.library" +apply plugin: "maven-publish" +apply plugin: "de.undercouch.download" + + +android { + compileSdkVersion safeExtGet("compileSdkVersion", 34) + + def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION + if (agpVersion.tokenize('.')[0].toInteger() >= 7) { + namespace "com.swmansion.worklets" + } + + if (rootProject.hasProperty("ndkPath")) { + ndkPath rootProject.ext.ndkPath + } + if (rootProject.hasProperty("ndkVersion")) { + ndkVersion rootProject.ext.ndkVersion + } + + buildFeatures { + prefab true + prefabPublishing true + buildConfig true + } + + prefab { + worklets { + headers workletsPrefabHeadersDir.absolutePath + } + } + + defaultConfig { + minSdkVersion safeExtGet("minSdkVersion", 23) + targetSdkVersion safeExtGet("targetSdkVersion", 34) + versionCode 1 + versionName "1.0" + buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", IS_NEW_ARCHITECTURE_ENABLED.toString()) + externalNativeBuild { + cmake { + arguments "-DANDROID_STL=c++_shared", + "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}", + "-DANDROID_TOOLCHAIN=clang", + "-DREACT_NATIVE_DIR=${toPlatformFileString(reactNativeRootDir.path)}", + "-DJS_RUNTIME=${JS_RUNTIME}", + "-DJS_RUNTIME_DIR=${jsRuntimeDir}", + "-DIS_NEW_ARCHITECTURE_ENABLED=${IS_NEW_ARCHITECTURE_ENABLED}", + "-DIS_REANIMATED_EXAMPLE_APP=${isReanimatedExampleApp()}" + abiFilters (*reactNativeArchitectures()) + } + } + + buildConfigField("boolean", "IS_INTERNAL_BUILD", "false") + buildConfigField("int", "EXOPACKAGE_FLAGS", "0") + buildConfigField("int", "REACT_NATIVE_MINOR_VERSION", REACT_NATIVE_MINOR_VERSION.toString()) + + consumerProguardFiles 'proguard-rules.pro' + } + externalNativeBuild { + cmake { + version = System.getenv("CMAKE_VERSION") ?: "3.22.1" + path "CMakeLists.txt" + } + } + buildTypes { + debug { + externalNativeBuild { + cmake { + if (JS_RUNTIME == "hermes") { + arguments "-DHERMES_ENABLE_DEBUGGER=1" + } else { + arguments "-DHERMES_ENABLE_DEBUGGER=0" + } + } + } + } + release { + externalNativeBuild { + cmake { + arguments "-DHERMES_ENABLE_DEBUGGER=0" + } + } + } + } + lintOptions { + abortOnError false + } + packagingOptions { + doNotStrip resolveBuildType() == 'debug' ? "**/**/*.so" : '' + // For some reason gradle only complains about the duplicated version of librrc_root and libreact_render libraries + // while there are more libraries copied in intermediates folder of the lib build directory, we exclude + // only the ones that make the build fail (ideally we should only include libreanimated but we + // are only allowed to specify exclude patterns) + excludes = [ + "META-INF", + "META-INF/**", + "**/libc++_shared.so", + "**/libfbjni.so", + "**/libjsi.so", + "**/libfolly_json.so", + "**/libfolly_runtime.so", + "**/libglog.so", + "**/libhermes.so", + "**/libhermes-executor-debug.so", + "**/libhermes_executor.so", + "**/libhermestooling.so", + "**/libreactnativejni.so", + "**/libturbomodulejsijni.so", + "**/libreactnative.so", + "**/libreact_nativemodule_core.so", + "**/libreact_render*.so", + "**/librrc_root.so", + "**/libjscexecutor.so", + "**/libv8executor.so", + ] + } + tasks.withType(JavaCompile) { + compileTask -> + compileTask.dependsOn(packageNdkLibs) + } + configurations { + extractHeaders + extractSO + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +def assertMinimalReactNativeVersion = task assertMinimalReactNativeVersionTask { + // If you change the minimal React Native version remember to update Compatibility Table in docs + def minimalReactNativeVersion = 74 + onlyIf { REACT_NATIVE_MINOR_VERSION < minimalReactNativeVersion } + doFirst { + throw new GradleException("[Reanimated] Unsupported React Native version. Please use $minimalReactNativeVersion. or newer.") + } +} + +task prepareWorkletsHeadersForPrefabs(type: Copy) { + from("$projectDir/src/main/cpp") + from("$projectDir/../Common/cpp") + include("worklets/**/*.h") + into(workletsPrefabHeadersDir) +} + +tasks.preBuild { + dependsOn assertMinimalReactNativeVersion +} + +task cleanCmakeCache() { + tasks.getByName("clean").dependsOn(cleanCmakeCache) + doFirst { + delete "${projectDir}/.cxx" + } +} + +task printVersions { + println "Android gradle plugin: ${Version.ANDROID_GRADLE_PLUGIN_VERSION}" + println "Gradle: ${project.gradle.gradleVersion}" +} + +task createNativeDepsDirectories() { + downloadsDir.mkdirs() + thirdPartyNdkDir.mkdirs() + workletsPrefabHeadersDir.mkdirs() +} + +task packageNdkLibs(type: Copy) { + from("$buildDir/worklets-ndk/all") + include("**/libworklets.so") + into("$projectDir/src/main/jniLibs") +} + +repositories { + mavenCentral() + mavenLocal() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$reactNativeRootDir/android" + } + maven { + // Android JSC is installed from npm + url "$reactNativeRootDir/../jsc-android/dist" + } + google() +} + +dependencies { + implementation "com.facebook.yoga:proguard-annotations:1.19.0" + implementation "androidx.transition:transition:1.1.0" + implementation "androidx.core:core:1.6.0" + + implementation "com.facebook.react:react-android" // version substituted by RNGP + if (JS_RUNTIME == "hermes") { + implementation "com.facebook.react:hermes-android" // version substituted by RNGP + } +} + +def nativeBuildDependsOn(dependsOnTask) { + def buildTasks = tasks.findAll({ task -> ( + !task.name.contains("Clean") + && (task.name.contains("externalNative") + || task.name.contains("CMake") + || task.name.contains("generateJsonModel") + ) + ) }) + buildTasks.forEach { task -> task.dependsOn(dependsOnTask) } +} + +afterEvaluate { + preBuild.dependsOn(prepareWorkletsHeadersForPrefabs) + + tasks.forEach({ task -> + if (task.name.contains("JniLibFolders")) { + task.dependsOn(packageNdkLibs) + } + }) + + if (JS_RUNTIME == "hermes") { + // Do nothing + } else if (JS_RUNTIME == "v8") { + def buildTasks = tasks.findAll({ task -> + !task.name.contains("Clean") && (task.name.contains("externalNative") || task.name.contains("CMake") || task.name.startsWith("generateJsonModel")) }) + buildTasks.forEach { task -> + def buildType = task.name.endsWith('Debug') ? 'Debug' : 'Release' + task.dependsOn(":react-native-v8:copy${buildType}JniLibsProjectOnly") + } + } else if (JS_RUNTIME == "jsc") { + // Do nothing + } else { + throw GradleScriptException("[Reanimated] Unknown JS runtime ${JS_RUNTIME}.") + } +} diff --git a/packages/react-native-worklets/android/gradle.properties b/packages/react-native-worklets/android/gradle.properties new file mode 100644 index 000000000000..2cf6e18a6f83 --- /dev/null +++ b/packages/react-native-worklets/android/gradle.properties @@ -0,0 +1,5 @@ +Worklets_kotlinVersion=1.7.0 +Worklets_minSdkVersion=21 +Worklets_targetSdkVersion=31 +Worklets_compileSdkVersion=31 +Worklets_ndkversion=21.4.7075529 diff --git a/packages/react-native-worklets/android/src/main/AndroidManifest.xml b/packages/react-native-worklets/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..a2f47b6057db --- /dev/null +++ b/packages/react-native-worklets/android/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/packages/react-native-worklets/android/src/main/cpp/worklets/CMakeLists.txt b/packages/react-native-worklets/android/src/main/cpp/worklets/CMakeLists.txt new file mode 100644 index 000000000000..63218fb48ae8 --- /dev/null +++ b/packages/react-native-worklets/android/src/main/cpp/worklets/CMakeLists.txt @@ -0,0 +1,88 @@ +cmake_minimum_required(VERSION 3.8) + +file(GLOB_RECURSE WORKLETS_COMMON_CPP_SOURCES CONFIGURE_DEPENDS + "${COMMON_CPP_DIR}/worklets/*.cpp") +file(GLOB_RECURSE WORKLETS_ANDROID_CPP_SOURCES CONFIGURE_DEPENDS + "${ANDROID_CPP_DIR}/worklets/*.cpp") + +# Consume shared libraries and headers from prefabs +find_package(fbjni REQUIRED CONFIG) +find_package(ReactAndroid REQUIRED CONFIG) + +if(${JS_RUNTIME} STREQUAL "hermes") + find_package(hermes-engine REQUIRED CONFIG) +endif() + +add_library(worklets SHARED ${WORKLETS_COMMON_CPP_SOURCES} + ${WORKLETS_ANDROID_CPP_SOURCES}) + +# includes +target_include_directories(worklets PUBLIC "${COMMON_CPP_DIR}" + "${ANDROID_CPP_DIR}") + +target_include_directories( + worklets + PRIVATE "${REACT_NATIVE_DIR}/ReactCommon" + "${REACT_NATIVE_DIR}/ReactAndroid/src/main/jni/react/turbomodule" + "${REACT_NATIVE_DIR}/ReactCommon/react/nativemodule/core/ReactCommon" + "${REACT_NATIVE_DIR}/ReactCommon/callinvoker" + "${REACT_NATIVE_DIR}/ReactCommon/runtimeexecutor") + +if(${IS_NEW_ARCHITECTURE_ENABLED}) + target_include_directories( + worklets + PRIVATE + "${REACT_NATIVE_DIR}/ReactCommon/yoga" + "${REACT_NATIVE_DIR}/ReactCommon/react/renderer/graphics/platform/cxx") + + if(ReactAndroid_VERSION_MINOR LESS 76) + target_link_libraries( + worklets ReactAndroid::fabricjni ReactAndroid::react_debug + ReactAndroid::react_render_core + ReactAndroid::react_render_componentregistry ReactAndroid::rrc_view) + endif() +endif() + +# build shared lib +set_target_properties(worklets PROPERTIES LINKER_LANGUAGE CXX) + +target_link_libraries(worklets log ReactAndroid::jsi fbjni::fbjni) + +if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) + target_link_libraries(worklets ReactAndroid::reactnative) +else() + target_link_libraries( + worklets ReactAndroid::react_nativemodule_core ReactAndroid::folly_runtime + ReactAndroid::glog ReactAndroid::reactnativejni) +endif() + +if(${JS_RUNTIME} STREQUAL "hermes") + target_link_libraries(worklets hermes-engine::libhermes) + + if(${HERMES_ENABLE_DEBUGGER}) + if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) + target_link_libraries(worklets ReactAndroid::hermestooling) + else() + target_link_libraries(worklets ReactAndroid::hermes_executor) + endif() + endif() +elseif(${JS_RUNTIME} STREQUAL "jsc") + if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) + target_link_libraries(worklets ReactAndroid::jsctooling) + else() + target_link_libraries(worklets ReactAndroid::jscexecutor) + endif() +elseif(${JS_RUNTIME} STREQUAL "v8") # TODO: Refactor this when adding support + # for newest V8 + target_include_directories(worklets PRIVATE "${JS_RUNTIME_DIR}/src") + file( + GLOB + V8_SO_DIR + "${JS_RUNTIME_DIR}/android/build/intermediates/library_jni/*/jni/${ANDROID_ABI}" + ) + find_library( + V8EXECUTOR_LIB v8executor + PATHS ${V8_SO_DIR} + NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + target_link_libraries(worklets ${V8EXECUTOR_LIB}) +endif() diff --git a/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/DummyWorkletsModule.java b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/DummyWorkletsModule.java new file mode 100644 index 000000000000..c5cfd25e155f --- /dev/null +++ b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/DummyWorkletsModule.java @@ -0,0 +1,18 @@ +package com.swmansion.worklets; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.module.annotations.ReactModule; + +@ReactModule(name = DummyWorkletsModule.NAME) +public class DummyWorkletsModule extends + NativeSulphateWorkletsSpec { + + public DummyWorkletsModule(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public boolean installTurboModule() { + return true; + } +} diff --git a/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java new file mode 100644 index 000000000000..23066283cbe7 --- /dev/null +++ b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java @@ -0,0 +1,56 @@ +package com.swmansion.worklets; + +import androidx.annotation.NonNull; + +import com.facebook.react.BaseReactPackage; +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.module.annotations.ReactModuleList; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +@ReactModuleList( + nativeModules = { + DummyWorkletsModule.class + }) +public class WorkletsPackage extends BaseReactPackage implements ReactPackage { + @Override + public NativeModule getModule( + @NonNull String name, @NonNull ReactApplicationContext reactContext) { + return switch (name) { + case DummyWorkletsModule.NAME -> new DummyWorkletsModule(reactContext); + default -> null; + }; + } + + @Override + public ReactModuleInfoProvider getReactModuleInfoProvider() { + Class[] moduleList = + new Class[] { + DummyWorkletsModule.class + }; + + final Map reactModuleInfoMap = new HashMap<>(); + for (Class moduleClass : moduleList) { + ReactModule reactModule = + Objects.requireNonNull(moduleClass.getAnnotation(ReactModule.class)); + + reactModuleInfoMap.put( + reactModule.name(), + new ReactModuleInfo( + reactModule.name(), + moduleClass.getName(), + true, + reactModule.needsEagerInit(), + reactModule.isCxxModule(), + BuildConfig.IS_NEW_ARCHITECTURE_ENABLED)); + } + + return () -> reactModuleInfoMap; + } +} diff --git a/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.h b/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.h new file mode 100644 index 000000000000..c2a6b079ec76 --- /dev/null +++ b/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.h @@ -0,0 +1,5 @@ +#import + +@interface DummyWorkletsModule : NSObject + +@end diff --git a/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.mm b/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.mm new file mode 100644 index 000000000000..2ba55e07e77a --- /dev/null +++ b/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.mm @@ -0,0 +1,19 @@ +#import + +@implementation DummyWorkletsModule{ + std::string valueUnpackerCode_; +} +RCT_EXPORT_MODULE() + +- (std::shared_ptr)getTurboModule : + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} + +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(installTurboModule) +{ + return @YES; +} + +@end diff --git a/packages/react-native-worklets/babel.config.js b/packages/react-native-worklets/babel.config.js new file mode 100644 index 000000000000..5d51f258afcb --- /dev/null +++ b/packages/react-native-worklets/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:react-native-builder-bob/babel-preset'], +}; diff --git a/packages/react-native-worklets/package.json b/packages/react-native-worklets/package.json new file mode 100644 index 000000000000..fb53bca32bdc --- /dev/null +++ b/packages/react-native-worklets/package.json @@ -0,0 +1,82 @@ +{ + "name": "react-native-worklets", + "version": "0.0.1", + "description": "🚀", + "scripts": { + "build": "bob build" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/software-mansion/react-native-reanimated.git", + "directory": "packages/react-native-worklets" + }, + "license": "MIT", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/software-mansion/react-native-reanimated/issues" + }, + "homepage": "https://docs.swmansion.com/react-native-reanimated", + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*" + }, + "devDependencies": { + "@react-native-community/cli": "15.0.1", + "@react-native/eslint-config": "^0.73.1", + "@types/jest": "^29.5.5", + "@types/react": "^18.2.44", + "eslint": "^8.57.0", + "prettier": "^3.3.3", + "react": "18.3.1", + "react-native": "^0.76.1", + "react-native-builder-bob": "0.33.1", + "typescript": "~5.3.0" + }, + "main": "./lib/module/index", + "module": "./lib/module/index", + "react-native": "./src/index", + "source": "./src/index", + "types": "lib/typescript/index.d.ts", + "files": [ + "src", + "lib", + "android", + "apple", + "Common", + "*.podspec", + "react-native.config.js", + "!apple/build", + "!android/build", + "!android/gradle", + "!android/gradlew", + "!android/gradlew.bat", + "!android/local.properties", + "!**/__tests__", + "!**/__fixtures__", + "!**/__mocks__", + "!**/.*" + ], + "react-native-builder-bob": { + "source": "src", + "output": "lib", + "targets": [ + [ + "module", + { + "esm": true, + "jsxRuntime": "classic" + } + ], + "typescript" + ] + }, + "codegenConfig": { + "name": "rnworklets", + "type": "modules", + "jsSrcsDir": "src/specs", + "android": { + "javaPackageName": "com.swmansion.worklets" + } + } +} diff --git a/packages/react-native-worklets/src/index.ts b/packages/react-native-worklets/src/index.ts new file mode 100644 index 000000000000..ba2a736031df --- /dev/null +++ b/packages/react-native-worklets/src/index.ts @@ -0,0 +1,3 @@ +'use strict'; + +export { DummyWorkletsTurboModule } from './specs'; diff --git a/packages/react-native-worklets/src/specs/NativeDummyWorklets.ts b/packages/react-native-worklets/src/specs/NativeDummyWorklets.ts new file mode 100644 index 000000000000..f59202c88c04 --- /dev/null +++ b/packages/react-native-worklets/src/specs/NativeDummyWorklets.ts @@ -0,0 +1,9 @@ +'use strict'; +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +interface Spec extends TurboModule { + installTurboModule: () => boolean; +} + +export default TurboModuleRegistry.get('DummyWorklets'); diff --git a/packages/react-native-worklets/src/specs/index.ts b/packages/react-native-worklets/src/specs/index.ts new file mode 100644 index 000000000000..5b294afa5105 --- /dev/null +++ b/packages/react-native-worklets/src/specs/index.ts @@ -0,0 +1,5 @@ +'use strict'; + +import DummyWorkletsTurboModule from './NativeDummyWorklets'; + +export { DummyWorkletsTurboModule }; diff --git a/packages/react-native-worklets/tsconfig.json b/packages/react-native-worklets/tsconfig.json new file mode 100644 index 000000000000..fd4ac617a0c3 --- /dev/null +++ b/packages/react-native-worklets/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "paths": { + "react-native-worklets": ["./src"] + } + }, + "include": ["src"] +} diff --git a/yarn.lock b/yarn.lock index a87a4799e549..8fcb6ae7d272 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3009,6 +3009,13 @@ __metadata: languageName: node linkType: hard +"@eslint-community/regexpp@npm:^4.4.0": + version: 4.12.1 + resolution: "@eslint-community/regexpp@npm:4.12.1" + checksum: 10/c08f1dd7dd18fbb60bdd0d85820656d1374dd898af9be7f82cb00451313402a22d5e30569c150315b4385907cdbca78c22389b2a72ab78883b3173be317620cc + languageName: node + linkType: hard + "@eslint/eslintrc@npm:^2.1.4": version: 2.1.4 resolution: "@eslint/eslintrc@npm:2.1.4" @@ -4460,6 +4467,30 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-clean@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-clean@npm:15.0.1" + dependencies: + "@react-native-community/cli-tools": "npm:15.0.1" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + fast-glob: "npm:^3.3.2" + checksum: 10/a1ff1824a4c1290271aaef48af0bc30ed50503ac062341fb051bb07895890414f4e208eb949b05bce79f90d1a51dd2fb133f9fbcf6c019bb7fec8c03ec4e4419 + languageName: node + linkType: hard + +"@react-native-community/cli-config-apple@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-config-apple@npm:15.0.1" + dependencies: + "@react-native-community/cli-tools": "npm:15.0.1" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + fast-glob: "npm:^3.3.2" + checksum: 10/3766bb155962d3ad4908b77db6d68e6edb6c8b4130e78c30e8cea3b1e6535e9730dc0bdc7b995b86d145621f4e992e4a2dcaf2be34b045de13d0c68692fd78ed + languageName: node + linkType: hard + "@react-native-community/cli-config@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-config@npm:14.0.0" @@ -4502,6 +4533,20 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-config@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-config@npm:15.0.1" + dependencies: + "@react-native-community/cli-tools": "npm:15.0.1" + chalk: "npm:^4.1.2" + cosmiconfig: "npm:^9.0.0" + deepmerge: "npm:^4.3.0" + fast-glob: "npm:^3.3.2" + joi: "npm:^17.2.1" + checksum: 10/7fc4d4f3554ddc6d76534f3063baf8f3631c333a2445038a617c1c5630718bc775ca35fe59a7ceafd40bc1f316d1c4fae00693ea22feb367fdaf91104ead3efe + languageName: node + linkType: hard + "@react-native-community/cli-debugger-ui@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-debugger-ui@npm:14.0.0" @@ -4538,6 +4583,15 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-debugger-ui@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-debugger-ui@npm:15.0.1" + dependencies: + serve-static: "npm:^1.13.1" + checksum: 10/366b87f67c72455a61de4beb05d3b24c5e8f6a4ea4d0d11a7bb660e738f43a26daa9721527a36f8e9596586240875c1a35d5b87a8cdddc2d84b38b6b56a83902 + languageName: node + linkType: hard + "@react-native-community/cli-doctor@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-doctor@npm:14.0.0" @@ -4610,6 +4664,30 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-doctor@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-doctor@npm:15.0.1" + dependencies: + "@react-native-community/cli-config": "npm:15.0.1" + "@react-native-community/cli-platform-android": "npm:15.0.1" + "@react-native-community/cli-platform-apple": "npm:15.0.1" + "@react-native-community/cli-platform-ios": "npm:15.0.1" + "@react-native-community/cli-tools": "npm:15.0.1" + chalk: "npm:^4.1.2" + command-exists: "npm:^1.2.8" + deepmerge: "npm:^4.3.0" + envinfo: "npm:^7.13.0" + execa: "npm:^5.0.0" + node-stream-zip: "npm:^1.9.1" + ora: "npm:^5.4.1" + semver: "npm:^7.5.2" + strip-ansi: "npm:^5.2.0" + wcwidth: "npm:^1.0.1" + yaml: "npm:^2.2.1" + checksum: 10/89cb3d2c6610c2316e388adf5efe7f85600d56e2fdc68b3f9fa8842ced44bf7ae89a7d4b733e21bb99f5d31c86112208a12f9a6668f6c99385be4ab415f730ca + languageName: node + linkType: hard + "@react-native-community/cli-platform-android@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-platform-android@npm:14.0.0" @@ -4652,6 +4730,20 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-platform-android@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-platform-android@npm:15.0.1" + dependencies: + "@react-native-community/cli-tools": "npm:15.0.1" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + fast-glob: "npm:^3.3.2" + fast-xml-parser: "npm:^4.4.1" + logkitty: "npm:^0.7.1" + checksum: 10/f537ac01ccce117b29020094165e123e84e5baea1bb4d88c1c1db7a5723060871dafab3b7d12f51aa14f94d13d30b59fff052244b14b8a4927b7e16f7e6f0308 + languageName: node + linkType: hard + "@react-native-community/cli-platform-apple@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-platform-apple@npm:14.0.0" @@ -4694,6 +4786,19 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-platform-apple@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-platform-apple@npm:15.0.1" + dependencies: + "@react-native-community/cli-config-apple": "npm:15.0.1" + "@react-native-community/cli-tools": "npm:15.0.1" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + fast-xml-parser: "npm:^4.4.1" + checksum: 10/85a6d39eba5cd474a063d59a12e893ffe77656b522a7adcac9c092f35565fddcf16c2b50c09b63a8d5c7d71f5fbad33069f1a61f23ca3b8f5dd5e4cb284d9bf9 + languageName: node + linkType: hard + "@react-native-community/cli-platform-ios@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-platform-ios@npm:14.0.0" @@ -4721,6 +4826,15 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-platform-ios@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-platform-ios@npm:15.0.1" + dependencies: + "@react-native-community/cli-platform-apple": "npm:15.0.1" + checksum: 10/17844caec8ed5e4101e35fa42fa12028a99c545f0d86a028b5ed12c19072cd8eeeacf11598a271fef5eea028072dd0521545376f3c50522ac6ca606d841f359d + languageName: node + linkType: hard + "@react-native-community/cli-server-api@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-server-api@npm:14.0.0" @@ -4789,6 +4903,23 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-server-api@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-server-api@npm:15.0.1" + dependencies: + "@react-native-community/cli-debugger-ui": "npm:15.0.1" + "@react-native-community/cli-tools": "npm:15.0.1" + compression: "npm:^1.7.1" + connect: "npm:^3.6.5" + errorhandler: "npm:^1.5.1" + nocache: "npm:^3.0.1" + pretty-format: "npm:^26.6.2" + serve-static: "npm:^1.13.1" + ws: "npm:^6.2.3" + checksum: 10/22341610387537e5603cb7b6f1d8b761b5439174bbac650081cf5b40377c0108262320e282329f977bef826e6c4569fbaa3e85f2a697631e755a020216a5515a + languageName: node + linkType: hard + "@react-native-community/cli-tools@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-tools@npm:14.0.0" @@ -4862,6 +4993,25 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-tools@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-tools@npm:15.0.1" + dependencies: + appdirsjs: "npm:^1.2.4" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + find-up: "npm:^5.0.0" + mime: "npm:^2.4.1" + open: "npm:^6.2.0" + ora: "npm:^5.4.1" + prompts: "npm:^2.4.2" + semver: "npm:^7.5.2" + shell-quote: "npm:^1.7.3" + sudo-prompt: "npm:^9.0.0" + checksum: 10/3447257d1650104466b7d59846ddcd45d8432b18d18df71c0606ecfed7892014fa959b917ab435c822b305a9a890bd51e762e941137e29f7824e215beacb42a5 + languageName: node + linkType: hard + "@react-native-community/cli-types@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli-types@npm:14.0.0" @@ -4889,6 +5039,15 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-types@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli-types@npm:15.0.1" + dependencies: + joi: "npm:^17.2.1" + checksum: 10/77452486158afcf1f03a3596135b6dba16dba5dd10209dacd5a6a4b176df36d37b8e49af61590d5a64df4907cf0575b6f37e0a3893335f961a9380edaee32152 + languageName: node + linkType: hard + "@react-native-community/cli@npm:14.0.0": version: 14.0.0 resolution: "@react-native-community/cli@npm:14.0.0" @@ -4967,6 +5126,32 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli@npm:15.0.1": + version: 15.0.1 + resolution: "@react-native-community/cli@npm:15.0.1" + dependencies: + "@react-native-community/cli-clean": "npm:15.0.1" + "@react-native-community/cli-config": "npm:15.0.1" + "@react-native-community/cli-debugger-ui": "npm:15.0.1" + "@react-native-community/cli-doctor": "npm:15.0.1" + "@react-native-community/cli-server-api": "npm:15.0.1" + "@react-native-community/cli-tools": "npm:15.0.1" + "@react-native-community/cli-types": "npm:15.0.1" + chalk: "npm:^4.1.2" + commander: "npm:^9.4.1" + deepmerge: "npm:^4.3.0" + execa: "npm:^5.0.0" + find-up: "npm:^5.0.0" + fs-extra: "npm:^8.1.0" + graceful-fs: "npm:^4.1.3" + prompts: "npm:^2.4.2" + semver: "npm:^7.5.2" + bin: + rnc-cli: build/bin.js + checksum: 10/7673d01bded6e9a368b238031ce237cebcfba230d860804a8f19aa6b4d5adcf4432e0a3b71ea285650c69b6427310f7db152cee6c2152d3303adb8dee6f60923 + languageName: node + linkType: hard + "@react-native-community/slider@npm:^4.5.5": version: 4.5.5 resolution: "@react-native-community/slider@npm:4.5.5" @@ -5646,6 +5831,37 @@ __metadata: languageName: node linkType: hard +"@react-native/eslint-config@npm:^0.73.1": + version: 0.73.2 + resolution: "@react-native/eslint-config@npm:0.73.2" + dependencies: + "@babel/core": "npm:^7.20.0" + "@babel/eslint-parser": "npm:^7.20.0" + "@react-native/eslint-plugin": "npm:0.73.1" + "@typescript-eslint/eslint-plugin": "npm:^5.57.1" + "@typescript-eslint/parser": "npm:^5.57.1" + eslint-config-prettier: "npm:^8.5.0" + eslint-plugin-eslint-comments: "npm:^3.2.0" + eslint-plugin-ft-flow: "npm:^2.0.1" + eslint-plugin-jest: "npm:^26.5.3" + eslint-plugin-prettier: "npm:^4.2.1" + eslint-plugin-react: "npm:^7.30.1" + eslint-plugin-react-hooks: "npm:^4.6.0" + eslint-plugin-react-native: "npm:^4.0.0" + peerDependencies: + eslint: ">=8" + prettier: ">=2" + checksum: 10/01026d001a13df218f9958308a530a02cb57b483202e47ac348d89a2dc1030beb7c1fd6fb01ad10905f8c559fbc64f4c518086fcc18177bbe781c57e491e6f9e + languageName: node + linkType: hard + +"@react-native/eslint-plugin@npm:0.73.1": + version: 0.73.1 + resolution: "@react-native/eslint-plugin@npm:0.73.1" + checksum: 10/59ee5a5a7e17f5d07053d05bdf464d77e3455dcaf7fc65a5784bb085057b098b5dfde9f736464c78b053148ef82feedb01036525680b9dd1049e44ced69b9b59 + languageName: node + linkType: hard + "@react-native/eslint-plugin@npm:0.75.4": version: 0.75.4 resolution: "@react-native/eslint-plugin@npm:0.75.4" @@ -6374,6 +6590,16 @@ __metadata: languageName: node linkType: hard +"@types/jest@npm:^29.5.5": + version: 29.5.14 + resolution: "@types/jest@npm:29.5.14" + dependencies: + expect: "npm:^29.0.0" + pretty-format: "npm:^29.0.0" + checksum: 10/59ec7a9c4688aae8ee529316c43853468b6034f453d08a2e1064b281af9c81234cec986be796288f1bbb29efe943bc950e70c8fa8faae1e460d50e3cf9760f9b + languageName: node + linkType: hard + "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -6493,6 +6719,16 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:^18.2.44": + version: 18.3.13 + resolution: "@types/react@npm:18.3.13" + dependencies: + "@types/prop-types": "npm:*" + csstype: "npm:^3.0.2" + checksum: 10/4f2b851cabdb68430b50998ad18f206edaea5b3c651d92e3573d86b7ac740224a91b7ca63176fa70e1defc78459faf518e5d2f58e1ba2839b1f12365dab70de2 + languageName: node + linkType: hard + "@types/scheduler@npm:^0.16": version: 0.16.8 resolution: "@types/scheduler@npm:0.16.8" @@ -6578,6 +6814,30 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:^5.57.1": + version: 5.62.0 + resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.4.0" + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/type-utils": "npm:5.62.0" + "@typescript-eslint/utils": "npm:5.62.0" + debug: "npm:^4.3.4" + graphemer: "npm:^1.4.0" + ignore: "npm:^5.2.0" + natural-compare-lite: "npm:^1.4.0" + semver: "npm:^7.3.7" + tsutils: "npm:^3.21.0" + peerDependencies: + "@typescript-eslint/parser": ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/9cc8319c6fd8a21938f5b69476974a7e778c283a55ef9fad183c850995b9adcb0087d57cea7b2ac6b9449570eee983aad39491d14cdd2e52d6b4b0485e7b2482 + languageName: node + linkType: hard + "@typescript-eslint/eslint-plugin@npm:^6.19.0": version: 6.21.0 resolution: "@typescript-eslint/eslint-plugin@npm:6.21.0" @@ -6626,6 +6886,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:^5.57.1": + version: 5.62.0 + resolution: "@typescript-eslint/parser@npm:5.62.0" + dependencies: + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/typescript-estree": "npm:5.62.0" + debug: "npm:^4.3.4" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/b6ca629d8f4e6283ff124501731cc886703eb4ce2c7d38b3e4110322ea21452b9d9392faf25be6bd72f54b89de7ffc72a40d9b159083ac54345a3d04b4fa5394 + languageName: node + linkType: hard + "@typescript-eslint/parser@npm:^6.19.0, @typescript-eslint/parser@npm:^6.19.1": version: 6.21.0 resolution: "@typescript-eslint/parser@npm:6.21.0" @@ -6708,6 +6985,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/type-utils@npm:5.62.0" + dependencies: + "@typescript-eslint/typescript-estree": "npm:5.62.0" + "@typescript-eslint/utils": "npm:5.62.0" + debug: "npm:^4.3.4" + tsutils: "npm:^3.21.0" + peerDependencies: + eslint: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/f9a4398d6d2aae09e3e765eff04cf4ab364376a87868031ac5c6a64c9bbb555cb1a7f99b07b3d1017e7422725b5f0bbee537f13b82ab2d930f161c987b3dece0 + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:6.21.0": version: 6.21.0 resolution: "@typescript-eslint/type-utils@npm:6.21.0" @@ -6844,6 +7138,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.10.0": + version: 5.62.0 + resolution: "@typescript-eslint/utils@npm:5.62.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.2.0" + "@types/json-schema": "npm:^7.0.9" + "@types/semver": "npm:^7.3.12" + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/typescript-estree": "npm:5.62.0" + eslint-scope: "npm:^5.1.1" + semver: "npm:^7.3.7" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 10/15ef13e43998a082b15f85db979f8d3ceb1f9ce4467b8016c267b1738d5e7cdb12aa90faf4b4e6dd6486c236cf9d33c463200465cf25ff997dbc0f12358550a1 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:6.21.0, @typescript-eslint/utils@npm:^6.19.1": version: 6.21.0 resolution: "@typescript-eslint/utils@npm:6.21.0" @@ -6875,24 +7187,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:^5.10.0": - version: 5.62.0 - resolution: "@typescript-eslint/utils@npm:5.62.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@types/json-schema": "npm:^7.0.9" - "@types/semver": "npm:^7.3.12" - "@typescript-eslint/scope-manager": "npm:5.62.0" - "@typescript-eslint/types": "npm:5.62.0" - "@typescript-eslint/typescript-estree": "npm:5.62.0" - eslint-scope: "npm:^5.1.1" - semver: "npm:^7.3.7" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10/15ef13e43998a082b15f85db979f8d3ceb1f9ce4467b8016c267b1738d5e7cdb12aa90faf4b4e6dd6486c236cf9d33c463200465cf25ff997dbc0f12358550a1 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:4.33.0": version: 4.33.0 resolution: "@typescript-eslint/visitor-keys@npm:4.33.0" @@ -10582,6 +10876,23 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-jest@npm:^26.5.3": + version: 26.9.0 + resolution: "eslint-plugin-jest@npm:26.9.0" + dependencies: + "@typescript-eslint/utils": "npm:^5.10.0" + peerDependencies: + "@typescript-eslint/eslint-plugin": ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + "@typescript-eslint/eslint-plugin": + optional: true + jest: + optional: true + checksum: 10/6ef994dc4c336e04d6ae3dbc83e526b4b889286c996ebb9bc3c71bb3d40957693fcda94198ae0dc516afc3799a97b5769f2f10ab1b4b9e0b7e735262ea22a5ff + languageName: node + linkType: hard + "eslint-plugin-jest@npm:^27.2.1, eslint-plugin-jest@npm:^27.9.0": version: 27.9.0 resolution: "eslint-plugin-jest@npm:27.9.0" @@ -10651,6 +10962,21 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-prettier@npm:^4.2.1": + version: 4.2.1 + resolution: "eslint-plugin-prettier@npm:4.2.1" + dependencies: + prettier-linter-helpers: "npm:^1.0.0" + peerDependencies: + eslint: ">=7.28.0" + prettier: ">=2.0.0" + peerDependenciesMeta: + eslint-config-prettier: + optional: true + checksum: 10/d387f85dd1bfcb6bc6b794845fee6afb9ebb2375653de6bcde6e615892fb97f85121a7c012a4651b181fc09953bdf54c9bc70cab7ad297019d89ae87dd007e28 + languageName: node + linkType: hard + "eslint-plugin-promise@npm:^6.0.0": version: 6.6.0 resolution: "eslint-plugin-promise@npm:6.6.0" @@ -11434,6 +11760,13 @@ __metadata: languageName: node linkType: hard +"fast-diff@npm:^1.1.2": + version: 1.3.0 + resolution: "fast-diff@npm:1.3.0" + checksum: 10/9e57415bc69cd6efcc720b3b8fe9fdaf42dcfc06f86f0f45378b1fa512598a8aac48aa3928c8751d58e2f01bb4ba4f07e4f3d9bc0d57586d45f1bd1e872c6cde + languageName: node + linkType: hard + "fast-equals@npm:^5.0.1": version: 5.0.1 resolution: "fast-equals@npm:5.0.1" @@ -16177,6 +16510,13 @@ __metadata: languageName: node linkType: hard +"natural-compare-lite@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare-lite@npm:1.4.0" + checksum: 10/5222ac3986a2b78dd6069ac62cbb52a7bf8ffc90d972ab76dfe7b01892485d229530ed20d0c62e79a6b363a663b273db3bde195a1358ce9e5f779d4453887225 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -17310,6 +17650,15 @@ __metadata: languageName: node linkType: hard +"prettier-linter-helpers@npm:^1.0.0": + version: 1.0.0 + resolution: "prettier-linter-helpers@npm:1.0.0" + dependencies: + fast-diff: "npm:^1.1.2" + checksum: 10/00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392 + languageName: node + linkType: hard + "prettier-plugin-jsdoc@npm:^1.3.0": version: 1.3.0 resolution: "prettier-plugin-jsdoc@npm:1.3.0" @@ -17947,6 +18296,27 @@ __metadata: languageName: node linkType: hard +"react-native-worklets@workspace:packages/react-native-worklets": + version: 0.0.0-use.local + resolution: "react-native-worklets@workspace:packages/react-native-worklets" + dependencies: + "@react-native-community/cli": "npm:15.0.1" + "@react-native/eslint-config": "npm:^0.73.1" + "@types/jest": "npm:^29.5.5" + "@types/react": "npm:^18.2.44" + eslint: "npm:^8.57.0" + prettier: "npm:^3.3.3" + react: "npm:18.3.1" + react-native: "npm:^0.76.1" + react-native-builder-bob: "npm:0.33.1" + typescript: "npm:~5.3.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + react: "*" + react-native: "*" + languageName: unknown + linkType: soft + "react-native@npm:0.75.4": version: 0.75.4 resolution: "react-native@npm:0.75.4"