Compare commits

..
Author SHA1 Message Date
Christian Falch a97e38029d Added missing define to target .reactRuntime
The target needs the HERMES_ENABLE_DEBUGGER flag in debug just like .reactHermes does.

This commit fixes this by adding the define.
2025-06-17 14:28:37 +02:00
512 changed files with 14796 additions and 30056 deletions
+1 -4
View File
@@ -47,10 +47,7 @@ packages/react-native/flow/
[options]
enums=true
experimental.pattern_matching=true
experimental.pattern_matching.includes=<PROJECT_ROOT>/packages/react-native/src/private/components/virtualview/
casting_syntax=both
component_syntax=true
emoji=true
@@ -105,4 +102,4 @@ untyped-import
untyped-type-import
[version]
^0.274.0
^0.273.1
+3
View File
@@ -26,6 +26,9 @@ runs:
- name: Lint code
shell: bash
run: ./.github/workflow-scripts/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml
- name: Lint java
shell: bash
run: ./.github/workflow-scripts/exec_swallow_error.sh yarn lint-java --check
- name: Lint file structure
shell: bash
run: ./.github/workflow-scripts/lint_files.sh
+3
View File
@@ -13,6 +13,9 @@ export GITHUB_REPO=-react-native
echo flow
npm run flow-check --silent --json
echo google-java-format
node scripts/lint-java.js --diff
} | node private/react-native-bots/code-analysis-bot.js
STATUS=$?
+22
View File
@@ -140,6 +140,27 @@ jobs:
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
build_android:
runs-on: 8-core-ubuntu
needs: [set_release_type]
container:
image: reactnativecommunity/react-native-android:latest
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Android
uses: ./.github/actions/build-android
with:
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
build_npm_package:
runs-on: 8-core-ubuntu
needs:
@@ -149,6 +170,7 @@ jobs:
build_hermes_macos,
build_hermesc_linux,
build_hermesc_windows,
build_android,
prebuild_apple_dependencies,
prebuild_react_native_core,
]
+2 -2
View File
@@ -14,8 +14,8 @@ jobs:
with:
repo-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
days-before-stale: 180
stale-issue-message: 'This issue is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.'
stale-pr-message: 'This PR is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.'
stale-issue-message: 'This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
stale-pr-message: 'This PR is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.'
close-pr-message: 'This PR was closed because it has been stalled for 7 days with no activity.'
exempt-issue-labels: 'Help Wanted :octocat:, Good first issue, Never gets stale, Issue: Author Provided Repro'
+1
View File
@@ -139,6 +139,7 @@ vendor/
/packages/react-native/React/FBReactNativeSpec/
/packages/react-native-codegen/lib
/packages/react-native-codegen/tmp/
/packages/react-native/ReactCommon/react/renderer/components/rncore/
/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec*
/**/RCTThirdPartyFabricComponentsProvider.*
-4871
View File
File diff suppressed because it is too large Load Diff
+5114 -257
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -124,7 +124,7 @@ if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoole
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(project(":packages:react-native:ReactAndroid:hermes-engine"))
.using(module("com.facebook.react:hermes-android:0.+"))
.using(module("com.facebook.react:hermes-android:0.0.0-+"))
.because("Users opted to use hermes from nightly")
}
}
+8 -7
View File
@@ -17,6 +17,7 @@
"format": "npm run prettier && npm run clang-format",
"featureflags": "yarn --cwd packages/react-native featureflags",
"lint-ci": "./.github/workflow-scripts/analyze_code.sh && yarn shellcheck",
"lint-java": "node ./scripts/lint-java.js",
"lint-markdown": "markdownlint-cli2 2>&1",
"lint": "eslint --max-warnings 0 .",
"prettier": "prettier --write \"./**/*.{js,md,yml,ts,tsx}\"",
@@ -54,11 +55,11 @@
"@react-native/metro-babel-transformer": "0.80.0-main",
"@react-native/metro-config": "0.80.0-main",
"@tsconfig/node22": "22.0.2",
"@types/react": "^19.1.0",
"@types/react": "^19.0.0",
"@typescript-eslint/parser": "^7.1.1",
"ansi-styles": "^4.2.1",
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
"babel-plugin-syntax-hermes-parser": "0.29.0",
"babel-plugin-syntax-hermes-parser": "0.28.1",
"babel-plugin-transform-define": "^2.1.4",
"babel-plugin-transform-flow-enums": "^0.0.2",
"clang-format": "^1.8.0",
@@ -76,11 +77,11 @@
"eslint-plugin-react-native": "^4.0.0",
"eslint-plugin-redundant-undefined": "^0.4.0",
"eslint-plugin-relay": "^1.8.3",
"flow-api-translator": "0.29.0",
"flow-bin": "^0.274.0",
"flow-api-translator": "0.28.1",
"flow-bin": "^0.273.1",
"glob": "^7.1.1",
"hermes-eslint": "0.29.0",
"hermes-transform": "0.29.0",
"hermes-eslint": "0.28.1",
"hermes-transform": "0.28.1",
"inquirer": "^7.1.0",
"jest": "^29.7.0",
"jest-config": "^29.7.0",
@@ -96,7 +97,7 @@
"node-fetch": "^2.2.0",
"nullthrows": "^1.1.1",
"prettier": "2.8.8",
"prettier-plugin-hermes-parser": "0.29.0",
"prettier-plugin-hermes-parser": "0.28.1",
"react": "19.1.0",
"react-test-renderer": "19.1.0",
"rimraf": "^3.0.2",
+2 -2
View File
@@ -1,5 +1,5 @@
@generated SignedSource<<cf5be4596d1f07e220b710fc286d02fa>>
Git revision: d95ac13bf0ab64a5e6c2eb18eb138587063b9c34
@generated SignedSource<<9ada78dff12dcfc7937c8934261f47f4>>
Git revision: 68cfd0ae84acb0ed8e47b421afd64ae3b0b5b727
Built with --nohooks: false
Is local checkout: false
Remote URL: https://github.com/facebook/react-native-devtools-frontend
File diff suppressed because one or more lines are too long
@@ -81,7 +81,6 @@ export default function createDevMiddleware({
projectRoot,
serverBaseUrl,
logger,
// $FlowFixMe[prop-missing]
unstable_browserLauncher = DefaultBrowserLauncher,
unstable_eventReporter,
unstable_experiments: experimentConfig = {},
@@ -18,8 +18,8 @@
"bugs": "https://github.com/facebook/react-native/issues",
"main": "index.js",
"devDependencies": {
"babel-plugin-syntax-hermes-parser": "0.29.0",
"hermes-eslint": "0.29.0"
"babel-plugin-syntax-hermes-parser": "0.28.1",
"hermes-eslint": "0.28.1"
},
"engines": {
"node": ">= 22.14.0"
+2 -2
View File
@@ -32,8 +32,8 @@
"source-map-support": "0.5.0"
},
"devDependencies": {
"babel-plugin-syntax-hermes-parser": "0.29.0",
"hermes-eslint": "0.29.0"
"babel-plugin-syntax-hermes-parser": "0.28.1",
"hermes-eslint": "0.28.1"
},
"engines": {
"node": ">= 22.14.0"
@@ -1,116 +0,0 @@
/*
* 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.tasks.internal
import javax.inject.Inject
import org.gradle.api.DefaultTask
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.CopySpec
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
/**
* A task that takes care of extracting gflags from a source folder/zip and preparing it to be
* consumed by the NDK. This task will also take care of applying the mapping for gflags parameters.
*/
abstract class PrepareGflagsTask : DefaultTask() {
@get:InputFiles abstract val gflagsPath: ConfigurableFileCollection
@get:InputDirectory abstract val gflagsThirdPartyPath: DirectoryProperty
@get:Input abstract val gflagsVersion: Property<String>
@get:OutputDirectory abstract val outputDir: DirectoryProperty
@get:Inject abstract val fs: FileSystemOperations
@TaskAction
fun taskAction() {
val commonCopyConfig: (action: CopySpec) -> Unit = { action ->
action.from(gflagsPath)
action.from(gflagsThirdPartyPath)
action.duplicatesStrategy = DuplicatesStrategy.INCLUDE
action.includeEmptyDirs = false
action.into(outputDir)
}
fs.copy { action ->
commonCopyConfig(action)
action.include(
"gflags-${gflagsVersion.get()}/src/*.h",
"gflags-${gflagsVersion.get()}/src/*.cc",
"CMakeLists.txt")
action.filesMatching("*/src/*") { matchedFile ->
matchedFile.path = "gflags/${matchedFile.name}"
}
}
fs.copy { action ->
commonCopyConfig(action)
action.include("gflags-${gflagsVersion.get()}/src/gflags_declare.h.in")
action.filesMatching("*/src/*") { matchedFile ->
matchedFile.filter { line ->
// Replace all placeholders with appropriate values
// see https://github.com/gflags/gflags/blob/v2.2.0/src/gflags_declare.h.in
line
.replace(Regex("@GFLAGS_NAMESPACE@"), "gflags")
.replace(
Regex(
"@(HAVE_STDINT_H|HAVE_SYS_TYPES_H|HAVE_INTTYPES_H|GFLAGS_INTTYPES_FORMAT_C99)@"),
"1")
.replace(Regex("@([A-Z0-9_]+)@"), "1")
}
matchedFile.path = "gflags/${matchedFile.name.removeSuffix(".in")}"
}
}
fs.copy { action ->
commonCopyConfig(action)
action.include("gflags-${gflagsVersion.get()}/src/config.h.in")
action.filesMatching("*/src/*") { matchedFile ->
matchedFile.filter { line -> line.replace(Regex("^#cmakedefine"), "//cmakedefine") }
matchedFile.path = "gflags/${matchedFile.name.removeSuffix(".in")}"
}
}
fs.copy { action ->
commonCopyConfig(action)
action.include("gflags-${gflagsVersion.get()}/src/gflags_ns.h.in")
action.filesMatching("*/src/*") { matchedFile ->
matchedFile.filter { line ->
line.replace(Regex("@ns@"), "google").replace(Regex("@NS@"), "google".uppercase())
}
matchedFile.path = "gflags/gflags_google.h"
}
}
fs.copy { action ->
commonCopyConfig(action)
action.include("gflags-${gflagsVersion.get()}/src/gflags.h.in")
action.filesMatching("*/src/*") { matchedFile ->
matchedFile.filter { line ->
line
.replace(Regex("@GFLAGS_ATTRIBUTE_UNUSED@"), "")
.replace(Regex("@INCLUDE_GFLAGS_NS_H@"), "#include \"gflags/gflags_google.h\"")
}
matchedFile.path = "gflags/${matchedFile.name.removeSuffix(".in")}"
}
}
fs.copy { action ->
commonCopyConfig(action)
action.include("gflags-${gflagsVersion.get()}/src/gflags_completions.h.in")
action.filesMatching("*/src/*") { matchedFile ->
matchedFile.filter { line -> line.replace(Regex("@GFLAGS_NAMESPACE@"), "gflags") }
matchedFile.path = "gflags/${matchedFile.name.removeSuffix(".in")}"
}
}
}
}
@@ -126,8 +126,6 @@ internal object NdkConfiguratorUtils {
): Pair<List<String>, List<String>> {
val excludes = mutableListOf<String>()
val includes = mutableListOf<String>()
// note: libjsctooling.so is kept here for backward compatibility.
when {
hermesEnabled -> {
excludes.add("**/libjsc.so")
@@ -1,209 +0,0 @@
/*
* 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.tasks.internal
import com.facebook.react.tests.createProject
import com.facebook.react.tests.createTestTask
import java.io.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
class PrepareGflagsTaskTest {
@get:Rule val tempFolder = TemporaryFolder()
@Test(expected = IllegalStateException::class)
fun prepareGflagsTask_withMissingConfiguration_fails() {
val task = createTestTask<PrepareGflagsTask>()
task.taskAction()
}
@Test
fun prepareGflagsTask_copiesCMakefile() {
val gflagspath = tempFolder.newFolder("gflagspath")
val output = tempFolder.newFolder("output")
val project = createProject()
val gflagsThirdPartyPath = File(project.projectDir, "src/main/jni/third-party/gflags/")
val task =
createTestTask<PrepareGflagsTask>(project = project) {
it.gflagsPath.setFrom(gflagspath)
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
it.gflagsVersion.set("1.0.0")
it.outputDir.set(output)
}
File(gflagsThirdPartyPath, "CMakeLists.txt").apply {
parentFile.mkdirs()
createNewFile()
}
task.taskAction()
assertThat(output.listFiles()!!.any { it.name == "CMakeLists.txt" }).isTrue()
}
@Test
fun prepareGflagsTask_copiesSourceCodeAndHeaders() {
val gflagspath = tempFolder.newFolder("gflagspath")
val gflagsThirdPartyPath = tempFolder.newFolder("gflagspath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareGflagsTask> {
it.gflagsPath.setFrom(gflagspath)
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
it.gflagsVersion.set("1.0.0")
it.outputDir.set(output)
}
File(gflagspath, "gflags-1.0.0/src/gflags.cc").apply {
parentFile.mkdirs()
createNewFile()
}
File(gflagspath, "gflags-1.0.0/src/util.h").apply {
parentFile.mkdirs()
createNewFile()
}
task.taskAction()
assertThat(File(output, "gflags/gflags.cc").exists()).isTrue()
assertThat(File(output, "gflags/util.h").exists()).isTrue()
}
@Test
fun prepareGflagsTask_replacesTokenCorrectly() {
val gflagspath = tempFolder.newFolder("gflagspath")
val gflagsThirdPartyPath = tempFolder.newFolder("gflagspath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareGflagsTask> {
it.gflagsPath.setFrom(gflagspath)
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
it.gflagsVersion.set("1.0.0")
it.outputDir.set(output)
}
File(gflagspath, "gflags-1.0.0/src/gflags_declare.h.in").apply {
parentFile.mkdirs()
writeText(
"""
#define GFLAGS_NAMESPACE @GFLAGS_NAMESPACE@
#include <string>
#if @HAVE_STDINT_H@
# include <stdint.h>
#elif @HAVE_SYS_TYPES_H@
# include <sys/types.h>
#elif @HAVE_INTTYPES_H@
# include <inttypes.h>
#endif
namespace GFLAGS_NAMESPACE {
#if @GFLAGS_INTTYPES_FORMAT_C99@ // C99
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif @GFLAGS_INTTYPES_FORMAT_BSD@ // BSD
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif @GFLAGS_INTTYPES_FORMAT_VC7@ // Windows
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
# error Do not know how to define a 32-bit integer quantity on your system
#endif
} // namespace GFLAGS_NAMESPACE
""")
}
File(gflagspath, "gflags-1.0.0/src/config.h.in").apply {
parentFile.mkdirs()
createNewFile()
writeText("#cmakedefine")
}
File(gflagspath, "gflags-1.0.0/src/gflags_ns.h.in").apply {
parentFile.mkdirs()
createNewFile()
writeText("@ns@ @NS@")
}
File(gflagspath, "gflags-1.0.0/src/gflags.h.in").apply {
parentFile.mkdirs()
createNewFile()
writeText("@GFLAGS_ATTRIBUTE_UNUSED@\n@INCLUDE_GFLAGS_NS_H@")
}
File(gflagspath, "gflags-1.0.0/src/gflags_completions.h.in").apply {
parentFile.mkdirs()
createNewFile()
writeText("@GFLAGS_NAMESPACE@")
}
task.taskAction()
val declareFile = File(output, "gflags/gflags_declare.h")
assertThat(declareFile.exists()).isTrue()
assertEquals(
declareFile.readText(),
"""
#define GFLAGS_NAMESPACE gflags
#include <string>
#if 1
# include <stdint.h>
#elif 1
# include <sys/types.h>
#elif 1
# include <inttypes.h>
#endif
namespace GFLAGS_NAMESPACE {
#if 1 // C99
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif 1 // BSD
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif 1 // Windows
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
# error Do not know how to define a 32-bit integer quantity on your system
#endif
} // namespace GFLAGS_NAMESPACE
""")
val configFile = File(output, "gflags/config.h")
assertThat(configFile.exists()).isTrue()
assertEquals(configFile.readText(), "//cmakedefine")
val nsFile = File(output, "gflags/gflags_google.h")
assertThat(nsFile.exists()).isTrue()
assertEquals(nsFile.readText(), "google GOOGLE")
val gflagsFile = File(output, "gflags/gflags.h")
assertThat(gflagsFile.exists()).isTrue()
assertEquals(gflagsFile.readText(), "\n#include \"gflags/gflags_google.h\"")
val completionsFile = File(output, "gflags/gflags_completions.h")
assertThat(completionsFile.exists()).isTrue()
assertEquals(completionsFile.readText(), "gflags")
}
}
+1 -1
View File
@@ -20,7 +20,7 @@
],
"dependencies": {},
"peerDependencies": {
"@types/react": "^19.1.0",
"@types/react": "^19.0.0",
"react": "*",
"react-native": "*"
},
@@ -67,7 +67,7 @@
"@babel/plugin-transform-unicode-regex": "^7.24.7",
"@babel/template": "^7.25.0",
"@react-native/babel-plugin-codegen": "0.80.0-main",
"babel-plugin-syntax-hermes-parser": "0.29.0",
"babel-plugin-syntax-hermes-parser": "0.28.1",
"babel-plugin-transform-flow-enums": "^0.0.2",
"react-refresh": "^0.14.0"
},
+1 -2
View File
@@ -15,9 +15,8 @@ const lazyImports = require('./lazy-imports');
const EXCLUDED_FIRST_PARTY_PATHS = [
/[/\\]node_modules[/\\]/,
/[/\\]packages[/\\]react-native[/\\]/,
/[/\\]packages[/\\]react-native(?:-fantom)?[/\\]/,
/[/\\]packages[/\\]virtualized-lists[/\\]/,
/[/\\]private[/\\]react-native-fantom[/\\]/,
];
function isTypeScriptSource(fileName) {
@@ -28,7 +28,7 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@react-native/babel-preset": "0.80.0-main",
"hermes-parser": "0.29.0",
"hermes-parser": "0.28.1",
"nullthrows": "^1.1.1"
},
"peerDependencies": {
+2 -2
View File
@@ -30,7 +30,7 @@
],
"dependencies": {
"glob": "^7.1.1",
"hermes-parser": "0.29.0",
"hermes-parser": "0.28.1",
"invariant": "^2.2.4",
"nullthrows": "^1.1.1",
"yargs": "^17.6.2"
@@ -43,7 +43,7 @@
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
"@babel/plugin-transform-optional-chaining": "^7.24.8",
"@babel/preset-env": "^7.25.3",
"hermes-estree": "0.29.0",
"hermes-estree": "0.28.1",
"micromatch": "^4.0.4",
"prettier": "2.8.8",
"rimraf": "^3.0.2"
+9 -9
View File
@@ -73,9 +73,9 @@ const ALL_GENERATORS = {
generateViewConfigJs: generateViewConfigJs.generate,
};
export type FilesOutput = Map<string, string>;
type FilesOutput = Map<string, string>;
export type GenerateFunction = (
type GenerateFunction = (
libraryName: string,
schema: SchemaType,
packageName?: string,
@@ -83,11 +83,11 @@ export type GenerateFunction = (
headerPrefix?: string,
) => FilesOutput;
export type LibraryGeneratorsFunctions = $ReadOnly<{
type LibraryGeneratorsFunctions = $ReadOnly<{
[string]: Array<GenerateFunction>,
}>;
export type LibraryOptions = $ReadOnly<{
type LibraryOptions = $ReadOnly<{
libraryName: string,
schema: SchemaType,
outputDirectory: string,
@@ -97,13 +97,13 @@ export type LibraryOptions = $ReadOnly<{
libraryGenerators?: LibraryGeneratorsFunctions,
}>;
export type SchemasOptions = $ReadOnly<{
type SchemasOptions = $ReadOnly<{
schemas: {[string]: SchemaType},
outputDirectory: string,
supportedApplePlatforms?: {[string]: {[string]: boolean}},
}>;
export type LibraryGenerators =
type LibraryGenerators =
| 'componentsAndroid'
| 'componentsIOS'
| 'descriptors'
@@ -116,14 +116,14 @@ export type LibraryGenerators =
| 'modulesCxx'
| 'modulesIOS';
export type SchemasGenerators = 'providerIOS';
type SchemasGenerators = 'providerIOS';
export type LibraryConfig = $ReadOnly<{
type LibraryConfig = $ReadOnly<{
generators: Array<LibraryGenerators>,
test?: boolean,
}>;
export type SchemasConfig = $ReadOnly<{
type SchemasConfig = $ReadOnly<{
generators: Array<SchemasGenerators>,
test?: boolean,
}>;
@@ -18,10 +18,7 @@ const flowFixtures = require('../../flow/modules/__test_fixtures__/fixtures.js')
const tsFixtures = require('../../typescript/modules/__test_fixtures__/fixtures.js');
const {compareSnaps, compareTsArraySnaps} = require('../compareSnaps.js');
const flowExtraCases = [
'NATIVE_MODULE_WITH_OPAQUE_TYPES',
'PROMISE_WITH_COMMONLY_USED_TYPES',
];
const flowExtraCases = ['PROMISE_WITH_COMMONLY_USED_TYPES'];
const tsExtraCases = [
'NATIVE_MODULE_WITH_ARRAY2_WITH_ALIAS',
'NATIVE_MODULE_WITH_ARRAY2_WITH_UNION_AND_TOUPLE',
@@ -691,37 +691,6 @@ export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
`;
const NATIVE_MODULE_WITH_OPAQUE_TYPES = `
/**
* 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.
*
* @flow strict-local
* @format
*/
'use strict';
import type {TurboModule} from '../RCTExport';
import * as TurboModuleRegistry from '../TurboModuleRegistry';
export opaque type Task = mixed;
export opaque type TimeoutID = number;
export interface Spec extends TurboModule {
+createTask: (callback: () => void) => Task;
+cancelTask: (task: Task) => void;
+setTimeout: (callback: () => void) => TimeoutID;
+clearTimeout: (timeoutID: TimeoutID) => void;
}
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
`;
const ANDROID_ONLY_NATIVE_MODULE = `
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -1007,7 +976,6 @@ module.exports = {
NATIVE_MODULE_WITH_UNION,
NATIVE_MODULE_WITH_UNION_RETURN_TYPES,
NATIVE_MODULE_WITH_EVENT_EMITTERS,
NATIVE_MODULE_WITH_OPAQUE_TYPES,
EMPTY_NATIVE_MODULE,
ANDROID_ONLY_NATIVE_MODULE,
IOS_ONLY_NATIVE_MODULE,
@@ -2187,108 +2187,6 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_OBJECT_W
}"
`;
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_OPAQUE_TYPES 1`] = `
"{
'modules': {
'NativeSampleTurboModule': {
'type': 'NativeModule',
'aliasMap': {},
'enumMap': {},
'spec': {
'eventEmitters': [],
'methods': [
{
'name': 'createTask',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'GenericObjectTypeAnnotation'
},
'params': [
{
'name': 'callback',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'VoidTypeAnnotation'
},
'params': []
}
}
]
}
},
{
'name': 'cancelTask',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'VoidTypeAnnotation'
},
'params': [
{
'name': 'task',
'optional': false,
'typeAnnotation': {
'type': 'GenericObjectTypeAnnotation'
}
}
]
}
},
{
'name': 'setTimeout',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'NumberTypeAnnotation'
},
'params': [
{
'name': 'callback',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'VoidTypeAnnotation'
},
'params': []
}
}
]
}
},
{
'name': 'clearTimeout',
'optional': false,
'typeAnnotation': {
'type': 'FunctionTypeAnnotation',
'returnTypeAnnotation': {
'type': 'VoidTypeAnnotation'
},
'params': [
{
'name': 'timeoutID',
'optional': false,
'typeAnnotation': {
'type': 'NumberTypeAnnotation'
}
}
]
}
}
]
},
'moduleName': 'SampleTurboModule'
}
}
}"
`;
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PARTIALS 1`] = `
"{
'modules': {
@@ -296,7 +296,6 @@ class FlowParser implements Parser {
if (
node.declaration != null &&
(node.declaration.type === 'TypeAlias' ||
node.declaration.type === 'OpaqueType' ||
node.declaration.type === 'InterfaceDeclaration')
) {
types[node.declaration.id.name] = node.declaration;
@@ -310,7 +309,6 @@ class FlowParser implements Parser {
types[node.declaration.id.name] = node.declaration;
} else if (
node.type === 'TypeAlias' ||
node.type === 'OpaqueType' ||
node.type === 'InterfaceDeclaration' ||
node.type === 'EnumDeclaration'
) {
@@ -545,10 +543,6 @@ class FlowParser implements Parser {
}
nextNodeForTypeAlias(typeAnnotation: $FlowFixMe): $FlowFixMe {
if (typeAnnotation.type === 'OpaqueType') {
return typeAnnotation.impltype;
}
return typeAnnotation.right;
}
@@ -1233,8 +1233,7 @@ function handleGenericTypeAnnotation(
let node;
switch (resolvedTypeAnnotation.type) {
case parser.typeAlias:
case 'OpaqueType': {
case parser.typeAlias: {
typeResolutionStatus = getTypeResolutionStatus(
'alias',
typeAnnotation,
@@ -24,7 +24,7 @@
"@react-native/codegen": "0.80.0-main"
},
"peerDependencies": {
"@types/react": "^19.1.0",
"@types/react": "^19.0.0",
"react": "*",
"react-native": "*"
},
@@ -9,8 +9,6 @@
#import <React/RCTUIManager.h>
#import <React/RCTViewManager.h>
#import <string>
static UIColor *UIColorFromHexString(const std::string hexString)
{
unsigned rgbValue = 0;
+2 -2
View File
@@ -29,7 +29,7 @@ export type EventConfig<T> = {
platformConfig?: PlatformConfig,
};
export function attachNativeEventImpl(
export function attachNativeEvent(
viewRef: any,
eventName: string,
argMapping: $ReadOnlyArray<?Mapping>,
@@ -181,7 +181,7 @@ export class AnimatedEvent {
'Only native driven events need to be attached.',
);
this._attachedEvent = attachNativeEventImpl(
this._attachedEvent = attachNativeEvent(
viewRef,
eventName,
this._argMapping,
@@ -10,10 +10,6 @@
import AnimatedImplementation from './AnimatedImplementation';
export type {DecayAnimationConfig} from './animations/DecayAnimation';
export type {SpringAnimationConfig} from './animations/SpringAnimation';
export type {TimingAnimationConfig} from './animations/TimingAnimation';
export {default as FlatList} from './components/AnimatedFlatList';
export {default as Image} from './components/AnimatedImage';
export {default as ScrollView} from './components/AnimatedScrollView';
@@ -37,7 +33,6 @@ export type {default as AnimatedNode} from './nodes/AnimatedNode';
export type {default as AnimatedAddition} from './nodes/AnimatedAddition';
export type {default as AnimatedDiffClamp} from './nodes/AnimatedDiffClamp';
export type {default as AnimatedDivision} from './nodes/AnimatedDivision';
export type {InterpolationConfigType as InterpolationConfig} from './nodes/AnimatedInterpolation';
export type {default as AnimatedModulo} from './nodes/AnimatedModulo';
export type {default as AnimatedMultiplication} from './nodes/AnimatedMultiplication';
export type {default as AnimatedSubtraction} from './nodes/AnimatedSubtraction';
@@ -20,7 +20,7 @@ import type {DecayAnimationConfig} from './animations/DecayAnimation';
import type {SpringAnimationConfig} from './animations/SpringAnimation';
import type {TimingAnimationConfig} from './animations/TimingAnimation';
import {AnimatedEvent, attachNativeEventImpl} from './AnimatedEvent';
import {AnimatedEvent, attachNativeEvent} from './AnimatedEvent';
import DecayAnimation from './animations/DecayAnimation';
import SpringAnimation from './animations/SpringAnimation';
import TimingAnimation from './animations/TimingAnimation';
@@ -47,39 +47,39 @@ export type CompositeAnimation = {
...
};
const addImpl = function (
const add = function (
a: AnimatedNode | number,
b: AnimatedNode | number,
): AnimatedAddition {
return new AnimatedAddition(a, b);
};
const subtractImpl = function (
const subtract = function (
a: AnimatedNode | number,
b: AnimatedNode | number,
): AnimatedSubtraction {
return new AnimatedSubtraction(a, b);
};
const divideImpl = function (
const divide = function (
a: AnimatedNode | number,
b: AnimatedNode | number,
): AnimatedDivision {
return new AnimatedDivision(a, b);
};
const multiplyImpl = function (
const multiply = function (
a: AnimatedNode | number,
b: AnimatedNode | number,
): AnimatedMultiplication {
return new AnimatedMultiplication(a, b);
};
const moduloImpl = function (a: AnimatedNode, modulus: number): AnimatedModulo {
const modulo = function (a: AnimatedNode, modulus: number): AnimatedModulo {
return new AnimatedModulo(a, modulus);
};
const diffClampImpl = function (
const diffClamp = function (
a: AnimatedNode,
min: number,
max: number,
@@ -120,7 +120,7 @@ const maybeVectorAnim = function (
const aY = anim((value: AnimatedValueXY).y, configY);
// We use `stopTogether: false` here because otherwise tracking will break
// because the second animation will get stopped before it can update.
return parallelImpl([aX, aY], {stopTogether: false});
return parallel([aX, aY], {stopTogether: false});
} else if (value instanceof AnimatedColor) {
const configR = {...config};
const configG = {...config};
@@ -146,12 +146,12 @@ const maybeVectorAnim = function (
const aA = anim((value: AnimatedColor).a, configA);
// We use `stopTogether: false` here because otherwise tracking will break
// because the second animation will get stopped before it can update.
return parallelImpl([aR, aG, aB, aA], {stopTogether: false});
return parallel([aR, aG, aB, aA], {stopTogether: false});
}
return null;
};
const springImpl = function (
const spring = function (
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
config: SpringAnimationConfig,
): CompositeAnimation {
@@ -179,7 +179,7 @@ const springImpl = function (
}
};
return (
maybeVectorAnim(value, config, springImpl) || {
maybeVectorAnim(value, config, spring) || {
start: function (callback?: ?EndCallback): void {
start(value, config, callback);
},
@@ -204,7 +204,7 @@ const springImpl = function (
);
};
const timingImpl = function (
const timing = function (
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
config: TimingAnimationConfig,
): CompositeAnimation {
@@ -233,7 +233,7 @@ const timingImpl = function (
};
return (
maybeVectorAnim(value, config, timingImpl) || {
maybeVectorAnim(value, config, timing) || {
start: function (callback?: ?EndCallback, isLooping?: boolean): void {
start(value, {...config, isLooping}, callback);
},
@@ -258,7 +258,7 @@ const timingImpl = function (
);
};
const decayImpl = function (
const decay = function (
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
config: DecayAnimationConfig,
): CompositeAnimation {
@@ -275,7 +275,7 @@ const decayImpl = function (
};
return (
maybeVectorAnim(value, config, decayImpl) || {
maybeVectorAnim(value, config, decay) || {
start: function (callback?: ?EndCallback): void {
start(value, config, callback);
},
@@ -300,7 +300,7 @@ const decayImpl = function (
);
};
const sequenceImpl = function (
const sequence = function (
animations: Array<CompositeAnimation>,
): CompositeAnimation {
let current = 0;
@@ -363,7 +363,7 @@ type ParallelConfig = {
stopTogether?: boolean,
...
};
const parallelImpl = function (
const parallel = function (
animations: Array<CompositeAnimation>,
config?: ?ParallelConfig,
): CompositeAnimation {
@@ -431,9 +431,9 @@ const parallelImpl = function (
return result;
};
const delayImpl = function (time: number): CompositeAnimation {
const delay = function (time: number): CompositeAnimation {
// Would be nice to make a specialized implementation
return timingImpl(new AnimatedValue(0), {
return timing(new AnimatedValue(0), {
toValue: 0,
delay: time,
duration: 0,
@@ -441,13 +441,13 @@ const delayImpl = function (time: number): CompositeAnimation {
});
};
const staggerImpl = function (
const stagger = function (
time: number,
animations: Array<CompositeAnimation>,
): CompositeAnimation {
return parallelImpl(
return parallel(
animations.map((animation, i) => {
return sequenceImpl([delayImpl(time * i), animation]);
return sequence([delay(time * i), animation]);
}),
);
};
@@ -458,7 +458,7 @@ type LoopAnimationConfig = {
...
};
const loopImpl = function (
const loop = function (
animation: CompositeAnimation,
// $FlowFixMe[prop-missing]
{iterations = -1, resetBeforeIteration = true}: LoopAnimationConfig = {},
@@ -514,7 +514,7 @@ const loopImpl = function (
};
};
function forkEventImpl(
function forkEvent(
event: ?AnimatedEvent | ?Function,
listener: Function,
): AnimatedEvent | Function {
@@ -531,7 +531,7 @@ function forkEventImpl(
}
}
function unforkEventImpl(
function unforkEvent(
event: ?AnimatedEvent | ?Function,
listener: Function,
): void {
@@ -540,7 +540,7 @@ function unforkEventImpl(
}
}
const eventImpl = function <T>(
const event = function <T>(
argMapping: $ReadOnlyArray<?Mapping>,
config: EventConfig<T>,
): any {
@@ -606,25 +606,25 @@ export default {
* See https://reactnative.dev/docs/animated#node
*/
Node: AnimatedNode,
decay: decayImpl,
timing: timingImpl,
spring: springImpl,
add: addImpl,
subtract: subtractImpl,
divide: divideImpl,
multiply: multiplyImpl,
modulo: moduloImpl,
diffClamp: diffClampImpl,
delay: delayImpl,
sequence: sequenceImpl,
parallel: parallelImpl,
stagger: staggerImpl,
loop: loopImpl,
event: eventImpl,
decay,
timing,
spring,
add,
subtract,
divide,
multiply,
modulo,
diffClamp,
delay,
sequence,
parallel,
stagger,
loop,
event,
createAnimatedComponent,
attachNativeEvent: attachNativeEventImpl,
forkEvent: forkEventImpl,
unforkEvent: unforkEventImpl,
attachNativeEvent,
forkEvent,
unforkEvent,
/**
* Expose Event class, so it can be used as a type for type checkers.
+2 -2
View File
@@ -17,7 +17,7 @@ import type {DecayAnimationConfig} from './animations/DecayAnimation';
import type {SpringAnimationConfig} from './animations/SpringAnimation';
import type {TimingAnimationConfig} from './animations/TimingAnimation';
import {AnimatedEvent, attachNativeEventImpl} from './AnimatedEvent';
import {AnimatedEvent, attachNativeEvent} from './AnimatedEvent';
import AnimatedImplementation from './AnimatedImplementation';
import createAnimatedComponent from './createAnimatedComponent';
import AnimatedColor from './nodes/AnimatedColor';
@@ -188,7 +188,7 @@ export default {
loop,
event: AnimatedImplementation.event,
createAnimatedComponent,
attachNativeEvent: attachNativeEventImpl,
attachNativeEvent,
forkEvent: AnimatedImplementation.forkEvent,
unforkEvent: AnimatedImplementation.unforkEvent,
Event: AnimatedEvent,
@@ -4,7 +4,6 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @fantom_flags cxxNativeAnimatedRemoveJsSync:*
* @flow strict-local
* @format
*/
@@ -17,8 +16,6 @@ import ensureInstance from '../../../src/private/__tests__/utilities/ensureInsta
import * as Fantom from '@react-native/fantom';
import {createRef} from 'react';
import {Animated, View, useAnimatedValue} from 'react-native';
import {allowStyleProp} from 'react-native/Libraries/Animated/NativeAnimatedAllowlist';
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
test('moving box by 100 points', () => {
@@ -35,9 +32,11 @@ test('moving box by 100 points', () => {
{
width: 100,
height: 100,
backgroundColor: 'red',
},
{transform: [{translateX}]},
]}
testID="box"
/>
);
}
@@ -76,15 +75,11 @@ test('moving box by 100 points', () => {
Fantom.unstable_produceFramesForDuration(500);
// Animation is completed now. C++ Animated will commit the final position to the shadow tree.
if (ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
expect(viewElement.getBoundingClientRect().x).toBe(100);
// TODO(T223344928): this shouldn't be neccessary
Fantom.runWorkLoop();
} else {
expect(viewElement.getBoundingClientRect().x).toBe(0);
Fantom.runWorkLoop(); // Animated still schedules a React state update for synchronisation to shadow tree
}
expect(viewElement.getBoundingClientRect().x).toBe(100);
// TODO: this shouldn't be needed but C++ Animated still schedules a React state update
// for synchronisation, even though it doesn't need to.
Fantom.runWorkLoop();
expect(viewElement.getBoundingClientRect().x).toBe(100);
});
@@ -148,392 +143,6 @@ test('animation driven by onScroll event', () => {
expect(transform.translateY).toBeCloseTo(100, 0.001);
expect(viewElement.getBoundingClientRect().y).toBe(100);
});
test('animated opacity', () => {
let _opacity;
let _opacityAnimation;
const viewRef = createRef<HostInstance>();
function MyApp() {
const opacity = useAnimatedValue(1);
_opacity = opacity;
return (
<Animated.View
ref={viewRef}
style={[
{
width: 100,
height: 100,
opacity: opacity,
},
]}
/>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<MyApp />);
});
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
expect(viewElement.getBoundingClientRect().x).toBe(0);
Fantom.runTask(() => {
_opacityAnimation = Animated.timing(_opacity, {
toValue: 0,
duration: 30,
useNativeDriver: true,
}).start();
});
Fantom.unstable_produceFramesForDuration(30);
expect(Fantom.unstable_getDirectManipulationProps(viewElement).opacity).toBe(
0,
);
// TODO: this shouldn't be neccessary since animation should be stopped after duration
Fantom.runTask(() => {
_opacityAnimation?.stop();
});
expect(root.getRenderedOutput({props: ['opacity']}).toJSX()).toEqual(
<rn-view opacity="0" />,
);
});
test('moving box by 50 points with offset 10', () => {
let _translateX;
const viewRef = createRef<HostInstance>();
function MyApp() {
const translateX = useAnimatedValue(0);
_translateX = translateX;
return (
<Animated.View
ref={viewRef}
style={[
{
width: 100,
height: 100,
},
{transform: [{translateX}]},
]}
/>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<MyApp />);
});
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
expect(viewElement.getBoundingClientRect().x).toBe(0);
let finishValue = null;
Fantom.runTask(() => {
Animated.timing(_translateX, {
toValue: 50,
duration: 1000, // 1 second
useNativeDriver: true,
}).start(result => {
finishValue = result;
});
});
Fantom.runTask(() => {
_translateX.setOffset(10);
});
Fantom.unstable_produceFramesForDuration(500);
// shadow tree is not synchronised yet, position X is still 0.
expect(viewElement.getBoundingClientRect().x).toBe(0);
expect(
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0]
.translateX,
).toBeCloseTo(35, 0.001);
Fantom.unstable_produceFramesForDuration(500);
expect(
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0]
.translateX,
).toBeCloseTo(60, 0.001);
if (ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
<rn-view transform='[{"translateX": 60.000000}]' />,
);
// TODO(T223344928): this shouldn't be neccessary
Fantom.runWorkLoop();
} else {
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
<rn-view transform="[]" />,
);
Fantom.runWorkLoop(); // Animated still schedules a React state update for synchronisation to shadow tree
}
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
<rn-view transform='[{"translateX": 60.000000}]' />, // // must include offset.
);
expect(finishValue?.finished).toBe(true);
expect(finishValue?.value).toBe(50); // must not include offset.
expect(finishValue?.offset).toBe(10);
});
describe('Value.flattenOffset', () => {
it('accumulates offset with onScroll value', () => {
const scrollViewRef = createRef<HostInstance>();
const viewRef = createRef<HostInstance>();
let _onScroll;
function PressableWithNativeDriver() {
_onScroll = useAnimatedValue(0);
return (
<View style={{flex: 1}}>
<Animated.View
ref={viewRef}
style={{
position: 'absolute',
width: 10,
height: 10,
transform: [{translateY: _onScroll}],
}}
/>
<Animated.ScrollView
ref={scrollViewRef}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
y: _onScroll,
},
},
},
],
{useNativeDriver: true},
)}>
<View style={{height: 1000, width: 100}} />
</Animated.ScrollView>
</View>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<PressableWithNativeDriver />);
});
const fn = jest.fn();
Fantom.runTask(() => {
_onScroll.addListener(fn);
});
const scrollViewelement = ensureInstance(
scrollViewRef.current,
ReactNativeElement,
);
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
Fantom.scrollTo(scrollViewelement, {
x: 0,
y: 10,
});
expect(fn).toBeCalledWith({value: 10});
Fantom.runTask(() => {
_onScroll.setOffset(15);
_onScroll.flattenOffset();
});
expect(fn).toHaveBeenCalledTimes(1);
Fantom.runTask(() => {
_onScroll.setOffset(15);
});
expect(fn).toHaveBeenCalledTimes(1);
let transform =
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0];
expect(transform.translateY).toBeCloseTo(40, 0.001);
// TODO(T223344928): this shouldn't be neccessary with cxxNativeAnimatedRemoveJsSync:true
Fantom.runWorkLoop();
});
});
describe('Value.extractOffset', () => {
it('sets the offset value to the base value and resets the base value to zero', () => {
const scrollViewRef = createRef<HostInstance>();
const viewRef = createRef<HostInstance>();
let _onScroll;
function PressableWithNativeDriver() {
_onScroll = useAnimatedValue(0);
return (
<View style={{flex: 1}}>
<Animated.View
ref={viewRef}
style={{
position: 'absolute',
width: 10,
height: 10,
transform: [{translateY: _onScroll}],
}}
/>
<Animated.ScrollView
ref={scrollViewRef}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
y: _onScroll,
},
},
},
],
{useNativeDriver: true},
)}>
<View style={{height: 1000, width: 100}} />
</Animated.ScrollView>
</View>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<PressableWithNativeDriver />);
});
const fn = jest.fn();
Fantom.runTask(() => {
_onScroll.addListener(fn);
});
const scrollViewelement = ensureInstance(
scrollViewRef.current,
ReactNativeElement,
);
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
Fantom.scrollTo(scrollViewelement, {
x: 0,
y: 10,
});
expect(fn).toBeCalledWith({value: 10});
Fantom.runTask(() => {
_onScroll.setOffset(15);
// Sets offset to be 15 + 10 = 25 (this is not observable from JS).
_onScroll.extractOffset();
});
expect(fn).toHaveBeenCalledTimes(1);
let transform =
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0];
// Animated value is now 0 but offset is 25. The final value is 25.
expect(transform.translateY).toBeCloseTo(25, 0.001);
Fantom.runTask(() => {
// Sets offset 35, overriding the previous `setOffset`.
// Due to `extractOffset`, base value was restarted to 0.
_onScroll.setOffset(35);
});
expect(fn).toHaveBeenCalledTimes(1);
transform =
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0];
// `extractOffset` resets value back to 0.
// Previously we set offset to 35. The final value is 35.
expect(transform.translateY).toBeCloseTo(35, 0.001);
// TODO(T223344928): this shouldn't be neccessary with cxxNativeAnimatedRemoveJsSync:true
Fantom.runWorkLoop();
});
});
test('animate layout props', () => {
const viewRef = createRef<HostInstance>();
allowStyleProp('height');
let _animatedHeight;
let _heightAnimation;
function MyApp() {
const animatedHeight = useAnimatedValue(0);
_animatedHeight = animatedHeight;
return (
<Animated.View
ref={viewRef}
style={[
{
width: 100,
height: animatedHeight,
},
]}
/>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<MyApp />);
});
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
Fantom.runTask(() => {
_heightAnimation = Animated.timing(_animatedHeight, {
toValue: 100,
duration: 10,
useNativeDriver: true,
}).start();
});
Fantom.unstable_produceFramesForDuration(10);
// TODO: this shouldn't be neccessary since animation should be stopped after duration
Fantom.runTask(() => {
_heightAnimation?.stop();
});
// $FlowFixMe[incompatible-use]
expect(Fantom.unstable_getDirectManipulationProps(viewElement).height).toBe(
100,
);
expect(Fantom.unstable_getFabricUpdateProps(viewElement).height).toBe(100);
expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
<rn-view height="100.000000" />,
);
// TODO(T226364699): this should `toBe(100)` but we are not syncing shadow tree yet.
expect(viewElement.getBoundingClientRect().y).toBe(0);
});
@@ -13,7 +13,6 @@ import type AnimatedNode from '../nodes/AnimatedNode';
import type AnimatedValue from '../nodes/AnimatedValue';
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
import AnimatedProps from '../nodes/AnimatedProps';
export type EndResult = {
@@ -150,15 +149,8 @@ export default class Animation {
if (value != null) {
animatedValue.__onAnimatedValueUpdateReceived(value, offset);
if (
!(
ReactNativeFeatureFlags.cxxNativeAnimatedEnabled() &&
ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()
)
) {
if (this.__isLooping === true) {
return;
}
if (this.__isLooping === true) {
return;
}
// Once the JS side node is synced with the updated values, trigger an
@@ -15,9 +15,7 @@ import type {
} from '../createAnimatedComponent';
import RefreshControl from '../../Components/RefreshControl/RefreshControl';
import ScrollView, {
type ScrollViewProps,
} from '../../Components/ScrollView/ScrollView';
import ScrollView from '../../Components/ScrollView/ScrollView';
import flattenStyle from '../../StyleSheet/flattenStyle';
import splitLayoutProps from '../../StyleSheet/splitLayoutProps';
import StyleSheet from '../../StyleSheet/StyleSheet';
@@ -28,20 +26,21 @@ import useAnimatedProps from '../useAnimatedProps';
import * as React from 'react';
import {cloneElement, useMemo} from 'react';
type AnimatedScrollViewProps = React.ElementConfig<typeof ScrollView>;
type AnimatedScrollViewInstance = React.ElementRef<typeof ScrollView>;
/**
* @see https://github.com/facebook/react-native/commit/b8c8562
*/
const AnimatedScrollView: AnimatedComponentType<
ScrollViewProps,
AnimatedScrollViewProps,
AnimatedScrollViewInstance,
> = function AnimatedScrollViewWithOrWithoutInvertedRefreshControl({
ref: forwardedRef,
...props
}: {
ref?: React.RefSetter<AnimatedScrollViewInstance>,
...AnimatedProps<ScrollViewProps>,
...AnimatedProps<AnimatedScrollViewProps>,
}) {
// (Android only) When a ScrollView has a RefreshControl and
// any `style` property set with an Animated.Value, the CSS
@@ -112,7 +111,7 @@ const AnimatedScrollViewWithInvertedRefreshControl =
// Handle animated props on `NativeDirectionalScrollView`.
const [scrollViewAnimatedProps, scrollViewRef] = useAnimatedProps<
ScrollViewProps,
AnimatedScrollViewProps,
AnimatedScrollViewInstance,
>(intermediatePropsForScrollView);
const ref = useMergeRefs<AnimatedScrollViewInstance>(
@@ -10,10 +10,13 @@
import type {AnimatedComponentType} from '../createAnimatedComponent';
import Text, {type TextProps} from '../../Text/Text';
import Text from '../../Text/Text';
import createAnimatedComponent from '../createAnimatedComponent';
import * as React from 'react';
export default (createAnimatedComponent(
(Text: $FlowFixMe),
): AnimatedComponentType<TextProps, React.ElementRef<typeof Text>>);
): AnimatedComponentType<
React.ElementConfig<typeof Text>,
React.ElementRef<typeof Text>,
>);
@@ -8,7 +8,6 @@
* @format
*/
import type {ViewProps} from '../../Components/View/ViewPropTypes';
import type {AnimatedComponentType} from '../createAnimatedComponent';
import View from '../../Components/View/View';
@@ -16,6 +15,6 @@ import createAnimatedComponent from '../createAnimatedComponent';
import * as React from 'react';
export default (createAnimatedComponent(View): AnimatedComponentType<
ViewProps,
React.ElementConfig<typeof View>,
React.ElementRef<typeof View>,
>);
@@ -21,7 +21,7 @@ import type AnimatedValue from './nodes/AnimatedValue';
import createAnimatedPropsHook from '../../src/private/animated/createAnimatedPropsHook';
import composeStyles from '../../src/private/styles/composeStyles';
import {type ViewProps} from '../Components/View/ViewPropTypes';
import View from '../Components/View/View';
import useMergeRefs from '../Utilities/useMergeRefs';
import * as React from 'react';
import {useMemo} from 'react';
@@ -60,7 +60,9 @@ type NonAnimatedProps =
| 'disabled'
| 'accessibilityLabel';
type PassThroughProps = $ReadOnly<{
passthroughAnimatedPropExplicitValues?: ViewProps | null,
passthroughAnimatedPropExplicitValues?: React.ElementConfig<
typeof View,
> | null,
}>;
export type AnimatedProps<Props: {...}> = {
@@ -14,8 +14,12 @@
#import <memory>
#if USE_THIRD_PARTY_JSC != 1
#if __has_include(<jsireact/HermesExecutorFactory.h>)
#import <jsireact/HermesExecutorFactory.h>
#elif __has_include(<reacthermes/HermesExecutorFactory.h>)
#import <reacthermes/HermesExecutorFactory.h>
#endif
#endif
#import <ReactCommon/RCTTurboModuleManager.h>
#import <jsireact/JSIExecutor.h>
+4 -7
View File
@@ -63,7 +63,6 @@ export type ButtonProps = $ReadOnly<{
@platform tv
@default false
@deprecated Use `focusable` instead
*/
hasTVPreferredFocus?: ?boolean,
@@ -281,12 +280,10 @@ export type ButtonProps = $ReadOnly<{
```
*/
const NativeTouchable:
| typeof TouchableNativeFeedback
| typeof TouchableOpacity =
const Touchable: typeof TouchableNativeFeedback | typeof TouchableOpacity =
Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity;
type ButtonRef = React.ElementRef<typeof NativeTouchable>;
type ButtonRef = React.ElementRef<typeof Touchable>;
const Button: component(
ref?: React.RefSetter<ButtonRef>,
@@ -364,7 +361,7 @@ const Button: component(
: importantForAccessibility;
return (
<NativeTouchable
<Touchable
accessible={accessible}
accessibilityActions={accessibilityActions}
onAccessibilityAction={onAccessibilityAction}
@@ -393,7 +390,7 @@ const Button: component(
{formattedTitle}
</Text>
</View>
</NativeTouchable>
</Touchable>
);
};
@@ -8,7 +8,6 @@
* @format
*/
import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
import type {
GestureResponderEvent,
LayoutChangeEvent,
@@ -27,6 +26,8 @@ import useAndroidRippleForView, {
import * as React from 'react';
import {memo, useMemo, useRef, useState} from 'react';
type ViewStyleProp = React.ElementConfig<typeof View>['style'];
export type {PressableAndroidRippleConfig};
export type PressableStateCallbackType = $ReadOnly<{
@@ -13,21 +13,12 @@ import {NativeMethods} from '../../../types/public/ReactNativeTypes';
import {ViewProps} from '../View/ViewPropTypes';
/**
* @deprecated
* Use `react-native-safe-area-context` instead. This component is deprecated and will be removed in a future release.
*
* Renders nested content and automatically applies paddings reflect the portion of the view
* that is not covered by navigation bars, tab bars, toolbars, and other ancestor views.
* Moreover, and most importantly, Safe Area's paddings reflect physical limitation of the screen,
* such as rounded corners or camera notches (aka sensor housing area on iPhone X).
*/
declare class SafeAreaViewComponent extends React.Component<ViewProps> {}
declare const SafeAreaViewBase: Constructor<NativeMethods> &
typeof SafeAreaViewComponent;
/**
* @deprecated
* Use `react-native-safe-area-context` instead. This component is deprecated and will be removed in a future release.
*/
export class SafeAreaView extends SafeAreaViewBase {}
@@ -22,9 +22,8 @@ import * as React from 'react';
* Moreover, and most importantly, Safe Area's paddings reflect physical
* limitation of the screen, such as rounded corners or camera notches (aka
* sensor housing area on iPhone X).
* @deprecated Use `react-native-safe-area-context` instead. This component will be removed in a future release.
*/
const SafeAreaView: component(
const exported: component(
ref?: React.RefSetter<React.ElementRef<typeof View>>,
...props: ViewProps
) = Platform.select({
@@ -32,4 +31,4 @@ const SafeAreaView: component(
default: View,
});
export default SafeAreaView;
export default exported;
@@ -10,7 +10,6 @@
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {Insets} from '../../../types/public/Insets';
import {HostInstance} from '../../../types/public/ReactNativeTypes';
import {ColorValue, StyleProp} from '../../StyleSheet/StyleSheet';
import {ViewStyle} from '../../StyleSheet/StyleSheetTypes';
import {
@@ -879,12 +878,6 @@ export class ScrollView extends ScrollViewBase {
// Undocumented
getInnerViewNode(): any;
/**
* Returns a reference to the underlying native scroll view, or null if the
* native instance is not mounted.
*/
getNativeScrollRef: () => HostInstance | null;
/**
* @deprecated Use scrollTo instead
*/
@@ -1480,7 +1480,6 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
// then the second tap goes to the actual interior view)
const {keyboardShouldPersistTaps} = this.props;
const keyboardNeverPersistTaps =
// $FlowFixMe[sketchy-null-bool]
!keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never';
if (typeof e.target === 'number') {
@@ -1563,7 +1562,6 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
const {keyboardShouldPersistTaps} = this.props;
const keyboardNeverPersistsTaps =
// $FlowFixMe[sketchy-null-bool]
!keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never';
// Dismiss the keyboard now if we didn't become responder in capture phase
@@ -35,8 +35,6 @@ export interface StatusBarPropsAndroid {
/**
* The background color of the status bar.
*
* Please note that this prop has no effect on Android 15+
*
* @platform android
*/
backgroundColor?: ColorValue | undefined;
@@ -46,8 +44,6 @@ export interface StatusBarPropsAndroid {
* the app will draw under the status bar. This is useful when using a
* semi transparent status bar color.
*
* Please note that this prop has no effect on Android 15+
*
* @platform android
*/
translucent?: boolean | undefined;
@@ -58,9 +58,6 @@ export type StatusBarAnimation = $Keys<{
export type StatusBarPropsAndroid = $ReadOnly<{
/**
* The background color of the status bar.
*
* Please note that this prop has no effect on Android 15+
*
* @platform android
*/
backgroundColor?: ?ColorValue,
@@ -69,8 +66,6 @@ export type StatusBarPropsAndroid = $ReadOnly<{
* When translucent is set to true, the app will draw under the status bar.
* This is useful when using a semi transparent status bar color.
*
* Please note that this prop has no effect on Android 15+
*
* @platform android
*/
translucent?: ?boolean,
@@ -30,9 +30,6 @@ type AndroidProps = $ReadOnly<{
}>;
type IOSProps = $ReadOnly<{
/**
* @deprecated Use `focusable` instead
*/
hasTVPreferredFocus?: ?boolean,
}>;
@@ -29,7 +29,6 @@ type TVProps = {
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
*
* @platform ios
* @deprecated Use `focusable` instead
*/
hasTVPreferredFocus?: ?boolean,
@@ -16,7 +16,6 @@ export interface TVProps {
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
*
* @platform ios
* @deprecated Use `focusable` instead
*/
hasTVPreferredFocus?: boolean | undefined;
@@ -26,7 +26,6 @@ export type TVProps = $ReadOnly<{
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
*
* @platform ios
* @deprecated Use `focusable` instead
*/
hasTVPreferredFocus?: ?boolean,
+13 -12
View File
@@ -16,6 +16,11 @@ import ViewNativeComponent from './ViewNativeComponent';
import * as React from 'react';
import {use} from 'react';
type PropsWithRef = $ReadOnly<{
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
...ViewProps,
}>;
/**
* The most fundamental component for building a UI, View is a container that
* supports layout with flexbox, style, some touch handling, and accessibility
@@ -23,10 +28,7 @@ import {use} from 'react';
*
* @see https://reactnative.dev/docs/view
*/
export default component View(
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
...props: ViewProps
) {
function View(props: PropsWithRef): React.Node {
const hasTextAncestor = use(TextAncestor);
let actualView;
@@ -53,7 +55,7 @@ export default component View(
} = props;
// Since we destructured props, we can now treat it as mutable
const processedProps = otherProps as {...ViewProps};
const processedProps = otherProps as {...PropsWithRef};
const parsedAriaLabelledBy = ariaLabelledBy?.split(/\s*,\s*/g);
if (parsedAriaLabelledBy !== undefined) {
@@ -116,12 +118,7 @@ export default component View(
};
}
actualView =
ref == null ? (
<ViewNativeComponent {...processedProps} />
) : (
<ViewNativeComponent {...processedProps} ref={ref} />
);
actualView = <ViewNativeComponent {...processedProps} />;
} else {
const {
accessibilityElementsHidden,
@@ -201,7 +198,6 @@ export default component View(
: importantForAccessibility
}
nativeID={id ?? nativeID}
ref={ref}
/>
);
}
@@ -211,3 +207,8 @@ export default component View(
}
return actualView;
}
export default View as component(
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
...props: ViewProps
);
@@ -374,6 +374,13 @@ export type AccessibilityProps = $ReadOnly<{
*/
'aria-label'?: ?Stringish,
/**
* Defines the order in which descendant elements receive accessibility focus.
* The elements in the array represent nativeID values for the respective
* descendant elements.
*/
experimental_accessibilityOrder?: ?Array<string>,
/**
* Indicates to accessibility services to treat UI component like a specific role.
*/
@@ -21,9 +21,6 @@ import {
import {Touchable} from '../Touchable/Touchable';
import {AccessibilityProps} from './ViewAccessibility';
/**
* @deprecated These properties are not implemented natively.
*/
export interface TVViewPropsIOS {
/**
* *(Apple TV only)* When set to true, this view will be focusable
@@ -37,7 +34,6 @@ export interface TVViewPropsIOS {
* *(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view.
*
* @platform ios
* @deprecated Use `focusable` instead
*/
hasTVPreferredFocus?: boolean | undefined;
@@ -280,7 +280,6 @@ export type ViewPropsAndroid = $ReadOnly<{
* Whether to force the Android TV focus engine to move focus to this view.
*
* @platform android
* @deprecated Use `focusable` instead
*/
hasTVPreferredFocus?: ?boolean,
@@ -490,13 +489,6 @@ type ViewBaseProps = $ReadOnly<{
* See https://reactnative.dev/docs/view#removeclippedsubviews
*/
removeClippedSubviews?: ?boolean,
/**
* Defines the order in which descendant elements receive accessibility focus.
* The elements in the array represent nativeID values for the respective
* descendant elements.
*/
experimental_accessibilityOrder?: ?Array<string>,
}>;
export type ViewProps = $ReadOnly<{
@@ -169,20 +169,6 @@ describe('<View>', () => {
});
});
describe('transform style', () => {
it('causes view to be unflattened', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<View style={{transform: [{translateX: 10}]}} />);
});
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
<rn-view transform='[{"translateX": 10.000000}]' />,
);
});
});
describe('props', () => {
describe('pointerEvents', () => {
it('auto does not propagate to the mounting layer, it is the default', () => {
@@ -31,8 +31,8 @@ describe('<Button>', () => {
.toJSX(),
).toEqual(
// Upper case on Android (also used by Fantom)
<rn-view backgroundColor="rgba(33, 150, 243, 1)">
<rn-paragraph foregroundColor="rgba(255, 255, 255, 1)">
<rn-view backgroundColor="rgba(33, 150, 243, 255)">
<rn-paragraph foregroundColor="rgba(255, 255, 255, 255)">
HELLO
</rn-paragraph>
</rn-view>,
@@ -53,8 +53,8 @@ describe('<Button>', () => {
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
.toJSX(),
).toEqual(
<rn-view backgroundColor="rgba(0, 0, 255, 1)">
<rn-paragraph foregroundColor="rgba(255, 255, 255, 1)">
<rn-view backgroundColor="rgba(0, 0, 255, 255)">
<rn-paragraph foregroundColor="rgba(255, 255, 255, 255)">
HELLO
</rn-paragraph>
</rn-view>,
@@ -99,8 +99,8 @@ describe('<Button>', () => {
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
.toJSX(),
).toEqual(
<rn-view backgroundColor="rgba(223, 223, 223, 1)">
<rn-paragraph foregroundColor="rgba(161, 161, 161, 1)">
<rn-view backgroundColor="rgba(223, 223, 223, 255)">
<rn-paragraph foregroundColor="rgba(161, 161, 161, 255)">
HELLO
</rn-paragraph>
</rn-view>,
@@ -181,8 +181,8 @@ describe('<Button>', () => {
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
.toJSX(),
).toEqual(
<rn-view backgroundColor="rgba(33, 150, 243, 1)">
<rn-paragraph foregroundColor="rgba(255, 255, 255, 1)">
<rn-view backgroundColor="rgba(33, 150, 243, 255)">
<rn-paragraph foregroundColor="rgba(255, 255, 255, 255)">
HELLO
</rn-paragraph>
</rn-view>,
@@ -223,8 +223,8 @@ describe('<Button>', () => {
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
.toJSX(),
).toEqual(
<rn-view backgroundColor="rgba(223, 223, 223, 1)">
<rn-paragraph foregroundColor="rgba(161, 161, 161, 1)">
<rn-view backgroundColor="rgba(223, 223, 223, 255)">
<rn-paragraph foregroundColor="rgba(161, 161, 161, 255)">
HELLO
</rn-paragraph>
</rn-view>,
@@ -32,7 +32,7 @@ export type {EventSubscription, EmitterSubscription};
export type NativeEventSubscription = EventSubscription;
// $FlowFixMe[unclear-type] unclear type of events
type UnsafeNativeEventObject = Object;
type UnsafeObject = Object;
/**
* `NativeEventEmitter` is intended for use by Native Modules to emit events to
@@ -46,8 +46,8 @@ type UnsafeNativeEventObject = Object;
*/
export default class NativeEventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeNativeEventObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeNativeEventObject>>>,
Record<string, $ReadOnlyArray<UnsafeObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
_nativeModule: ?NativeModule;
@@ -8,10 +8,9 @@
#import <React/RCTImageLoaderLoggable.h>
#import <React/RCTImageLoaderProtocol.h>
#import <React/RCTImageURLLoader.h>
// TODO (T61325135): Remove C++ checks
#ifdef __cplusplus
#import <string>
namespace facebook::react {
struct ImageURLLoaderAttribution {
@@ -7,7 +7,7 @@
#import <React/RCTImageUtils.h>
#import <cmath>
#import <tgmath.h>
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/UTCoreTypes.h>
@@ -229,8 +229,7 @@ function _processUpdate() {
*/
const InteractionManager = (
ReactNativeFeatureFlags.disableInteractionManager()
? // $FlowFixMe[incompatible-variance]
require('./InteractionManagerStub').default
? require('./InteractionManagerStub').default
: InteractionManagerImpl
) as typeof InteractionManagerImpl;
@@ -45,7 +45,7 @@ type OnAnimationDidFailCallback = () => void;
let isLayoutAnimationEnabled: boolean =
ReactNativeFeatureFlags.isLayoutAnimationEnabled();
function setLayoutAnimationEnabled(value: boolean) {
function setEnabled(value: boolean) {
isLayoutAnimationEnabled = isLayoutAnimationEnabled;
}
@@ -115,7 +115,7 @@ function configureNext(
}
}
function createLayoutAnimation(
function create(
duration: number,
type?: LayoutAnimationType,
property?: LayoutAnimationProperty,
@@ -129,16 +129,12 @@ function createLayoutAnimation(
}
const Presets = {
easeInEaseOut: (createLayoutAnimation(
easeInEaseOut: (create(
300,
'easeInEaseOut',
'opacity',
): LayoutAnimationConfig),
linear: (createLayoutAnimation(
500,
'linear',
'opacity',
): LayoutAnimationConfig),
linear: (create(500, 'linear', 'opacity'): LayoutAnimationConfig),
spring: ({
duration: 700,
create: {
@@ -184,7 +180,7 @@ const LayoutAnimation = {
/**
* Helper for creating a config for `configureNext`.
*/
create: createLayoutAnimation,
create,
Types: Object.freeze({
spring: 'spring',
linear: 'linear',
@@ -212,7 +208,7 @@ const LayoutAnimation = {
spring: (configureNext.bind(null, Presets.spring): (
onAnimationDidEnd?: OnAnimationDidEndCallback,
) => void),
setEnabled: setLayoutAnimationEnabled,
setEnabled,
};
export default LayoutAnimation;
+2 -1
View File
@@ -15,7 +15,6 @@ import type {
ListRenderItemInfo,
ViewabilityConfigCallbackPair,
ViewToken,
VirtualizedListProps,
} from '@react-native/virtualized-lists';
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
@@ -182,6 +181,8 @@ type FlatListBaseProps<ItemT> = {
...OptionalProps<ItemT>,
};
type VirtualizedListProps = React.ElementConfig<typeof VirtualizedList>;
export type FlatListProps<ItemT> = {
...Omit<
VirtualizedListProps,
+2 -8
View File
@@ -35,9 +35,9 @@ export interface ModalBaseProps {
*/
visible?: boolean | undefined;
/**
* The `onRequestClose` callback is called when the user taps the hardware back button on Android, dismisses the sheet using a gesture on iOS (when `allowSwipeDismissal` is set to true) or the menu button on Apple TV.
* The `onRequestClose` callback is called when the user taps the hardware back button on Android or the menu button on Apple TV.
*
* This is required on iOS and Android.
* This is required on Apple TV and Android.
*/
onRequestClose?: ((event: NativeSyntheticEvent<any>) => void) | undefined;
/**
@@ -89,12 +89,6 @@ export interface ModalPropsIOS {
onOrientationChange?:
| ((event: NativeSyntheticEvent<any>) => void)
| undefined;
/**
* Controls whether the modal can be dismissed by swiping down on iOS.
* This requires you to implement the `onRequestClose` prop to handle the dismissal.
*/
allowSwipeDismissal?: boolean | undefined;
}
export interface ModalPropsAndroid {
+2 -19
View File
@@ -86,9 +86,9 @@ export type ModalBaseProps = {
*/
visible?: ?boolean,
/**
* The `onRequestClose` callback is called when the user taps the hardware back button on Android, dismisses the sheet using a gesture on iOS (when `allowSwipeDismissal` is set to true) or the menu button on Apple TV.
* The `onRequestClose` callback is called when the user taps the hardware back button on Android or the menu button on Apple TV.
*
* This is required on iOS and Android.
* This is required on Apple TV and Android.
*/
// onRequestClose?: (event: NativeSyntheticEvent<any>) => void;
onRequestClose?: ?DirectEventHandler<null>,
@@ -147,12 +147,6 @@ export type ModalPropsIOS = {
// | ((event: NativeSyntheticEvent<any>) => void)
// | undefined;
onOrientationChange?: ?DirectEventHandler<OrientationChangeEvent>,
/**
* Controls whether the modal can be dismissed by swiping down on iOS.
* This requires you to implement the `onRequestClose` prop to handle the dismissal.
*/
allowSwipeDismissal?: ?boolean,
};
export type ModalPropsAndroid = {
@@ -198,16 +192,6 @@ function confirmProps(props: ModalProps) {
'Modal with translucent navigation bar and without translucent status bar is not supported.',
);
}
if (
Platform.OS === 'ios' &&
props.allowSwipeDismissal === true &&
!props.onRequestClose
) {
console.warn(
'Modal requires the onRequestClose prop when used with `allowSwipeDismissal`. This is necessary to prevent state corruption.',
);
}
}
}
@@ -343,7 +327,6 @@ class Modal extends React.Component<ModalProps, ModalState> {
onStartShouldSetResponder={this._shouldSetResponder}
supportedOrientations={this.props.supportedOrientations}
onOrientationChange={this.props.onOrientationChange}
allowSwipeDismissal={this.props.allowSwipeDismissal}
testID={this.props.testID}>
<VirtualizedListContextResetter>
<ScrollView.Context.Provider value={null}>
@@ -130,7 +130,7 @@ const PERMISSIONS = Object.freeze({
*
* See https://reactnative.dev/docs/permissionsandroid
*/
class PermissionsAndroidImpl {
class PermissionsAndroid {
PERMISSIONS: PermissionsType = PERMISSIONS;
RESULTS: $ReadOnly<{
DENIED: 'denied',
@@ -297,6 +297,5 @@ class PermissionsAndroidImpl {
}
}
const PermissionsAndroidInstance: PermissionsAndroidImpl =
new PermissionsAndroidImpl();
const PermissionsAndroidInstance: PermissionsAndroid = new PermissionsAndroid();
export default PermissionsAndroidInstance;
@@ -13,8 +13,8 @@ import type {RootTag} from '../Types/RootTagTypes';
import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger';
import type {DisplayModeType} from './DisplayMode';
type HeadlessTask = (taskData: any) => Promise<void>;
export type TaskProvider = () => HeadlessTask;
type Task = (taskData: any) => Promise<void>;
export type TaskProvider = () => Task;
export type ComponentProvider = () => React.ComponentType<any>;
export type ComponentProviderInstrumentationHook = (
@@ -8,7 +8,7 @@
* @format
*/
import type {PartialAttributeConfiguration as AttributeConfiguration} from '../../Renderer/shims/ReactNativeTypes';
import type {AttributeConfiguration} from '../../Renderer/shims/ReactNativeTypes';
import flattenStyle from '../../StyleSheet/flattenStyle';
import deepDiffer from '../../Utilities/differ/deepDiffer';
@@ -61,7 +61,7 @@ function restoreDeletedValuesInNestedArray(
} else if (node && removedKeyCount > 0) {
const obj = node;
for (const propKey in removedKeys) {
// $FlowFixMe[incompatible-use] removedKeys is always non-null
// $FlowFixMe[incompatible-use] found when upgrading Flow
if (!removedKeys[propKey]) {
continue;
}
@@ -133,12 +133,12 @@ function diffNestedArrayProperty(
);
}
for (; i < nextArray.length; i++) {
// Add all remaining properties
const nextProp = nextArray[i];
if (!nextProp) {
continue;
}
updatePayload = addNestedProperty(updatePayload, nextProp, validAttributes);
// Add all remaining properties.
updatePayload = addNestedProperty(
updatePayload,
nextArray[i],
validAttributes,
);
}
return updatePayload;
}
@@ -183,7 +183,9 @@ function diffNestedProperty(
if (Array.isArray(prevProp)) {
return diffProperties(
updatePayload,
// $FlowFixMe - We know that this is always an object when the input is.
flattenStyle(prevProp),
// $FlowFixMe - We know that this isn't an array because of above flow.
nextProp,
validAttributes,
);
@@ -192,11 +194,43 @@ function diffNestedProperty(
return diffProperties(
updatePayload,
prevProp,
// $FlowFixMe - We know that this is always an object when the input is.
flattenStyle(nextProp),
validAttributes,
);
}
/**
* addNestedProperty takes a single set of props and valid attribute
* attribute configurations. It processes each prop and adds it to the
* updatePayload.
*/
function addNestedProperty(
updatePayload: null | Object,
nextProp: NestedNode,
validAttributes: AttributeConfiguration,
): $FlowFixMe {
if (!nextProp) {
return updatePayload;
}
if (!Array.isArray(nextProp)) {
// Add each property of the leaf.
return addProperties(updatePayload, nextProp, validAttributes);
}
for (let i = 0; i < nextProp.length; i++) {
// Add all the properties of the array.
updatePayload = addNestedProperty(
updatePayload,
nextProp[i],
validAttributes,
);
}
return updatePayload;
}
/**
* clearNestedProperty takes a single set of props and valid attributes. It
* adds a null sentinel to the updatePayload, for each prop key.
@@ -251,19 +285,14 @@ function diffProperties(
prevProp = prevProps[propKey];
nextProp = nextProps[propKey];
// functions are converted to booleans as markers that the associated
// events should be sent from native.
if (typeof nextProp === 'function') {
const attributeConfigHasProcess =
typeof attributeConfig === 'object' &&
typeof attributeConfig.process === 'function';
if (!attributeConfigHasProcess) {
// functions are converted to booleans as markers that the associated
// events should be sent from native.
nextProp = (true: any);
// If nextProp is not a function, then don't bother changing prevProp
// since nextProp will win and go into the updatePayload regardless.
if (typeof prevProp === 'function') {
prevProp = (true: any);
}
nextProp = (true: any);
// If nextProp is not a function, then don't bother changing prevProp
// since nextProp will win and go into the updatePayload regardless.
if (typeof prevProp === 'function') {
prevProp = (true: any);
}
}
@@ -413,69 +442,16 @@ function diffProperties(
return updatePayload;
}
function addNestedProperty(
payload: null | Object,
/**
* addProperties adds all the valid props to the payload after being processed.
*/
function addProperties(
updatePayload: null | Object,
props: Object,
validAttributes: AttributeConfiguration,
): null | Object {
// Flatten nested style props.
if (Array.isArray(props)) {
for (let i = 0; i < props.length; i++) {
payload = addNestedProperty(payload, props[i], validAttributes);
}
return payload;
}
for (const propKey in props) {
const prop = props[propKey];
const attributeConfig = ((validAttributes[
propKey
]: any): AttributeConfiguration);
if (attributeConfig == null) {
continue;
}
let newValue;
if (prop === undefined) {
// Discard the prop if it was previously defined.
if (payload && payload[propKey] !== undefined) {
newValue = null;
} else {
continue;
}
} else if (typeof attributeConfig === 'object') {
if (typeof attributeConfig.process === 'function') {
// An atomic prop with custom processing.
newValue = attributeConfig.process(prop);
} else if (typeof attributeConfig.diff === 'function') {
// An atomic prop with custom diffing. We don't need to do diffing when adding props.
newValue = prop;
}
} else {
if (typeof prop === 'function') {
// A function prop. It represents an event handler. Pass it to native as 'true'.
newValue = true;
} else {
// An atomic prop. Doesn't need to be flattened.
newValue = prop;
}
}
if (newValue !== undefined) {
if (!payload) {
payload = ({}: {[string]: $FlowFixMe});
}
payload[propKey] = newValue;
continue;
}
payload = addNestedProperty(payload, prop, attributeConfig);
}
return payload;
// TODO: Fast path
return diffProperties(updatePayload, emptyObject, props, validAttributes);
}
/**
@@ -487,6 +463,7 @@ function clearProperties(
prevProps: Object,
validAttributes: AttributeConfiguration,
): null | Object {
// TODO: Fast path
return diffProperties(updatePayload, prevProps, emptyObject, validAttributes);
}
@@ -494,7 +471,11 @@ export function create(
props: Object,
validAttributes: AttributeConfiguration,
): null | Object {
return addNestedProperty(null, props, validAttributes);
return addProperties(
null, // updatePayload
props,
validAttributes,
);
}
export function diff(
@@ -1,495 +0,0 @@
/**
* 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.
*
* @flow
* @format
*/
'use strict';
import type {PartialAttributeConfiguration as AttributeConfiguration} from '../../../Renderer/shims/ReactNativeTypes';
const {create, diff} = require('../ReactNativeAttributePayload');
describe('ReactNativeAttributePayload.create', () => {
it('should work with simple example', () => {
expect(create({b: 2, c: 3}, {a: true, b: true})).toEqual({
b: 2,
});
});
it('should work with complex example', () => {
const validAttributes: AttributeConfiguration = {
style: {
position: true,
zIndex: true,
flexGrow: true,
flexShrink: true,
flexDirection: true,
overflow: true,
backgroundColor: true,
},
};
expect(
create(
{
style: [
{
flexGrow: 1,
flexShrink: 1,
flexDirection: 'row',
overflow: 'scroll',
},
[
{position: 'relative', zIndex: 2},
{flexGrow: 0},
{backgroundColor: 'red'},
],
],
},
validAttributes,
),
).toEqual({
flexGrow: 0,
flexShrink: 1,
flexDirection: 'row',
overflow: 'scroll',
position: 'relative',
zIndex: 2,
backgroundColor: 'red',
});
});
it('should nullify previously defined style prop that is subsequently set to null or undefined', () => {
expect(
create({style: [{a: 0}, {a: undefined}]}, {style: {a: true}}),
).toEqual({a: null});
expect(create({style: [{a: 0}, {a: null}]}, {style: {a: true}})).toEqual({
a: null,
});
});
it('should ignore non-style fields that are set to undefined', () => {
expect(create({}, {a: true})).toEqual(null);
expect(create({a: undefined}, {a: true})).toEqual(null);
expect(create({a: undefined, b: undefined}, {a: true, b: true})).toEqual(
null,
);
expect(
create({a: undefined, b: undefined, c: 1}, {a: true, b: true}),
).toEqual(null);
expect(
create({a: undefined, b: undefined, c: 1}, {a: true, b: true, c: true}),
).toEqual({c: 1});
expect(
create({a: 1, b: undefined, c: 2}, {a: true, b: true, c: true}),
).toEqual({a: 1, c: 2});
});
it('should ignore invalid fields', () => {
expect(create({b: 2}, {})).toEqual(null);
});
it('should not use the diff attribute', () => {
const diffA = jest.fn();
expect(create({a: [2]}, {a: {diff: diffA}})).toEqual({a: [2]});
expect(diffA).not.toBeCalled();
});
it('should use the process attribute', () => {
const processA = jest.fn(a => a + 1);
expect(create({a: 2}, {a: {process: processA}})).toEqual({a: 3});
expect(processA).toBeCalledWith(2);
});
it('should use the process attribute for functions as well', () => {
const process = (x: Object) => x;
const nextFunction = () => {};
expect(create({a: nextFunction}, {a: {process}})).toEqual({
a: nextFunction,
});
});
it('should work with undefined styles', () => {
expect(create({style: undefined}, {style: {b: true}})).toEqual(null);
expect(create({style: {a: '#ffffff', b: 1}}, {style: {b: true}})).toEqual({
b: 1,
});
});
it('should flatten nested styles and predefined styles', () => {
const validStyleAttribute: AttributeConfiguration = {
style: {foo: true, bar: true},
};
expect(create({style: [{foo: 1}, {bar: 2}]}, validStyleAttribute)).toEqual({
foo: 1,
bar: 2,
});
expect(create({}, validStyleAttribute)).toEqual(null);
const barStyle = {
bar: 3,
};
expect(
create({style: [[{foo: 1}, {foo: 2}], barStyle]}, validStyleAttribute),
).toEqual({foo: 2, bar: 3});
});
it('should not flatten nested props if attribute config is a primitive or only has diff/process', () => {
expect(create({a: {foo: 1, bar: 2}}, {a: true})).toEqual({
a: {foo: 1, bar: 2},
});
expect(create({a: [{foo: 1}, {bar: 2}]}, {a: true})).toEqual({
a: [{foo: 1}, {bar: 2}],
});
expect(create({a: {foo: 1, bar: 2}}, {a: {diff: a => a}})).toEqual({
a: {foo: 1, bar: 2},
});
expect(
create({a: [{foo: 1}, {bar: 2}]}, {a: {diff: a => a, process: a => a}}),
).toEqual({a: [{foo: 1}, {bar: 2}]});
});
it('handles attributes defined multiple times', () => {
const validAttributes: AttributeConfiguration = {
foo: true,
style: {foo: true},
};
expect(create({foo: 4, style: {foo: 2}}, validAttributes)).toEqual({
foo: 2,
});
expect(create({style: {foo: 2}}, validAttributes)).toEqual({
foo: 2,
});
expect(create({style: {foo: 2}, foo: 4}, validAttributes)).toEqual({
foo: 4,
});
expect(create({foo: 4, style: {foo: null}}, validAttributes)).toEqual({
foo: null, // this should ideally be null.
});
expect(
create({foo: 4, style: [{foo: null}, {foo: 5}]}, validAttributes),
).toEqual({
foo: 5,
});
});
// Function properties are just markers to native that events should be sent.
it('should convert functions to booleans', () => {
expect(
create(
{
a: function () {
return 9;
},
b: function () {
return 3;
},
},
{a: true, b: true},
),
).toEqual({a: true, b: true});
});
});
describe('ReactNativeAttributePayload.diff', () => {
it('should work with simple example', () => {
expect(diff({a: 1, c: 3}, {b: 2, c: 3}, {a: true, b: true})).toEqual({
a: null,
b: 2,
});
});
it('should skip fields that are equal', () => {
expect(
diff(
{a: 1, b: 'two', c: true, d: false, e: undefined, f: 0},
{a: 1, b: 'two', c: true, d: false, e: undefined, f: 0},
{a: true, b: true, c: true, d: true, e: true, f: true},
),
).toEqual(null);
});
it('should remove fields', () => {
expect(diff({a: 1}, {}, {a: true})).toEqual({a: null});
});
it('should remove fields that are set to undefined', () => {
expect(diff({a: 1}, {a: undefined}, {a: true})).toEqual({a: null});
});
it('should ignore invalid fields', () => {
expect(diff({a: 1}, {b: 2}, {})).toEqual(null);
});
it('should use the diff attribute', () => {
const diffA = jest.fn((a, b) => true);
const diffB = jest.fn((a, b) => false);
expect(
diff(
{a: [1], b: [3]},
{a: [2], b: [4]},
{a: {diff: diffA}, b: {diff: diffB}},
),
).toEqual({a: [2]});
expect(diffA).toBeCalledWith([1], [2]);
expect(diffB).toBeCalledWith([3], [4]);
});
it('should not use the diff attribute on addition/removal', () => {
const diffA = jest.fn();
const diffB = jest.fn();
expect(
diff({a: [1]}, {b: [2]}, {a: {diff: diffA}, b: {diff: diffB}}),
).toEqual({a: null, b: [2]});
expect(diffA).not.toBeCalled();
expect(diffB).not.toBeCalled();
});
it('should do deep diffs of Objects by default', () => {
expect(
diff(
{a: [1], b: {k: [3, 4]}, c: {k: [4, 4]}},
{a: [2], b: {k: [3, 4]}, c: {k: [4, 5]}},
{a: true, b: true, c: true},
),
).toEqual({a: [2], c: {k: [4, 5]}});
});
it('should work with undefined styles', () => {
expect(
diff(
{style: {a: '#ffffff', b: 1}},
{style: undefined},
{style: {b: true}},
),
).toEqual({b: null});
expect(
diff(
{style: undefined},
{style: {a: '#ffffff', b: 1}},
{style: {b: true}},
),
).toEqual({b: 1});
expect(
diff({style: undefined}, {style: undefined}, {style: {b: true}}),
).toEqual(null);
});
it('should work with empty styles', () => {
const validAttributes: AttributeConfiguration = {a: true, b: true};
expect(diff({a: 1, c: 3}, {}, validAttributes)).toEqual({a: null});
expect(diff({}, {a: 1, c: 3}, validAttributes)).toEqual({a: 1});
expect(diff({}, {}, validAttributes)).toEqual(null);
});
it('should flatten nested styles and predefined styles', () => {
const validStyleAttribute: AttributeConfiguration = {
style: {foo: true, bar: true},
};
expect(
diff({}, {style: [{foo: 1}, {bar: 2}]}, validStyleAttribute),
).toEqual({foo: 1, bar: 2});
expect(
diff({style: [{foo: 1}, {bar: 2}]}, {}, validStyleAttribute),
).toEqual({foo: null, bar: null});
const barStyle = {
bar: 3,
};
expect(
diff({}, {style: [[{foo: 1}, {foo: 2}], barStyle]}, validStyleAttribute),
).toEqual({foo: 2, bar: 3});
});
it('should reset a value to a previous if it is removed', () => {
const validStyleAttribute: AttributeConfiguration = {
style: {foo: true, bar: true},
};
expect(
diff(
{style: [{foo: 1}, {foo: 3}]},
{style: [{foo: 1}, {bar: 2}]},
validStyleAttribute,
),
).toEqual({foo: 1, bar: 2});
});
it('should not clear removed props if they are still in another slot', () => {
const validStyleAttribute: AttributeConfiguration = {
style: {foo: true, bar: true},
};
expect(
diff(
{style: [{}, {foo: 3, bar: 2}]},
{style: [{foo: 3}, {bar: 2}]},
validStyleAttribute,
),
).toEqual({foo: 3}); // this should ideally be null. heuristic tradeoff.
expect(
diff(
{style: [{}, {foo: 3, bar: 2}]},
{style: [{foo: 1, bar: 1}, {bar: 2}]},
validStyleAttribute,
),
).toEqual({bar: 2, foo: 1});
});
it('should clear a prop if a later style is explicit null/undefined', () => {
const validStyleAttribute: AttributeConfiguration = {
style: {foo: true, bar: true},
};
expect(
diff(
{style: [{}, {foo: 3, bar: 2}]},
{style: [{foo: 1}, {bar: 2, foo: null}]},
validStyleAttribute,
),
).toEqual({foo: null});
expect(
diff(
{style: [{foo: 3}, {foo: null, bar: 2}]},
{style: [{foo: null}, {bar: 2}]},
validStyleAttribute,
),
).toEqual({foo: null});
expect(
diff(
{style: [{foo: 1}, {foo: null}]},
{style: [{foo: 2}, {foo: null}]},
validStyleAttribute,
),
).toEqual({foo: null}); // this should ideally be null. heuristic.
// Test the same case with object equality because an early bailout doesn't
// work in this case.
const fooObj = {foo: 3};
expect(
diff(
{style: [{foo: 1}, fooObj]},
{style: [{foo: 2}, fooObj]},
validStyleAttribute,
),
).toEqual({foo: 3}); // this should ideally be null. heuristic.
expect(
diff(
{style: [{foo: 1}, {foo: 3}]},
{style: [{foo: 2}, {foo: undefined}]},
validStyleAttribute,
),
).toEqual({foo: null}); // this should ideally be null. heuristic.
});
it('handles attributes defined multiple times', () => {
const validAttributes: AttributeConfiguration = {
foo: true,
style: {foo: true},
};
expect(diff({}, {foo: 4, style: {foo: 2}}, validAttributes)).toEqual({
foo: 2,
});
expect(diff({foo: 4}, {style: {foo: 2}}, validAttributes)).toEqual({
foo: 2,
});
expect(diff({style: {foo: 2}}, {foo: 4}, validAttributes)).toEqual({
foo: 4,
});
});
// Function properties are just markers to native that events should be sent.
it('should convert functions to booleans', () => {
// Note that if the property changes from one function to another, we don't
// need to send an update.
expect(
diff(
{
a: function () {
return 1;
},
b: function () {
return 2;
},
c: 3,
},
{
b: function () {
return 9;
},
c: function () {
return 3;
},
},
{a: true, b: true, c: true},
),
).toEqual({a: null, c: true});
});
it('should skip changed functions', () => {
expect(
diff(
{
a: function () {
return 1;
},
},
{
a: function () {
return 9;
},
},
{a: true},
),
).toEqual(null);
});
it('should skip deeply-nested changed functions', () => {
expect(
diff(
{
wrapper: {
a: function () {
return 1;
},
},
},
{
wrapper: {
a: function () {
return 9;
},
},
},
{wrapper: true},
),
).toEqual(null);
});
it('should use the process function config when prop is a function', () => {
const process = jest.fn(a => a);
const nextFunction = function () {};
expect(
diff(
{
a: function () {},
},
{
a: nextFunction,
},
{a: {process}},
),
).toEqual({a: nextFunction});
expect(process).toBeCalled();
});
});
@@ -9,4 +9,6 @@
*/
export * from '../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo';
export {default} from '../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo';
import NativeDeviceInfo from '../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo';
export default NativeDeviceInfo;
@@ -23,7 +23,7 @@ type Options = $ReadOnly<{
excludedPlatforms?: $ReadOnlyArray<'iOS' | 'android'>,
}>;
export type NativeComponentType<T: {...}> = HostComponent<T>;
export type NativeComponentType<T> = HostComponent<T>;
// If this function runs then that means the view configs were not
// generated at build time using `GenerateViewConfigJs.js`. Thus
@@ -136,7 +136,7 @@ export type EventConfig<T> = {
useNativeDriver: boolean,
platformConfig?: PlatformConfig,
};
declare export function attachNativeEventImpl(
declare export function attachNativeEvent(
viewRef: any,
eventName: string,
argMapping: $ReadOnlyArray<?Mapping>,
@@ -166,10 +166,7 @@ declare export default {
`;
exports[`public API should not change unintentionally Libraries/Animated/AnimatedExports.js.flow 1`] = `
"export type { DecayAnimationConfig } from \\"./animations/DecayAnimation\\";
export type { SpringAnimationConfig } from \\"./animations/SpringAnimation\\";
export type { TimingAnimationConfig } from \\"./animations/TimingAnimation\\";
export { default as FlatList } from \\"./components/AnimatedFlatList\\";
"export { default as FlatList } from \\"./components/AnimatedFlatList\\";
export { default as Image } from \\"./components/AnimatedImage\\";
export { default as ScrollView } from \\"./components/AnimatedScrollView\\";
export { default as SectionList } from \\"./components/AnimatedSectionList\\";
@@ -188,7 +185,6 @@ export type { default as AnimatedNode } from \\"./nodes/AnimatedNode\\";
export type { default as AnimatedAddition } from \\"./nodes/AnimatedAddition\\";
export type { default as AnimatedDiffClamp } from \\"./nodes/AnimatedDiffClamp\\";
export type { default as AnimatedDivision } from \\"./nodes/AnimatedDivision\\";
export type { InterpolationConfigType as InterpolationConfig } from \\"./nodes/AnimatedInterpolation\\";
export type { default as AnimatedModulo } from \\"./nodes/AnimatedModulo\\";
export type { default as AnimatedMultiplication } from \\"./nodes/AnimatedMultiplication\\";
export type { default as AnimatedSubtraction } from \\"./nodes/AnimatedSubtraction\\";
@@ -226,53 +222,53 @@ exports[`public API should not change unintentionally Libraries/Animated/Animate
reset: () => void,
...
};
declare const addImpl: (
declare const add: (
a: AnimatedNode | number,
b: AnimatedNode | number
) => AnimatedAddition;
declare const subtractImpl: (
declare const subtract: (
a: AnimatedNode | number,
b: AnimatedNode | number
) => AnimatedSubtraction;
declare const divideImpl: (
declare const divide: (
a: AnimatedNode | number,
b: AnimatedNode | number
) => AnimatedDivision;
declare const multiplyImpl: (
declare const multiply: (
a: AnimatedNode | number,
b: AnimatedNode | number
) => AnimatedMultiplication;
declare const moduloImpl: (a: AnimatedNode, modulus: number) => AnimatedModulo;
declare const diffClampImpl: (
declare const modulo: (a: AnimatedNode, modulus: number) => AnimatedModulo;
declare const diffClamp: (
a: AnimatedNode,
min: number,
max: number
) => AnimatedDiffClamp;
declare const springImpl: (
declare const spring: (
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
config: SpringAnimationConfig
) => CompositeAnimation;
declare const timingImpl: (
declare const timing: (
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
config: TimingAnimationConfig
) => CompositeAnimation;
declare const decayImpl: (
declare const decay: (
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
config: DecayAnimationConfig
) => CompositeAnimation;
declare const sequenceImpl: (
declare const sequence: (
animations: Array<CompositeAnimation>
) => CompositeAnimation;
type ParallelConfig = {
stopTogether?: boolean,
...
};
declare const parallelImpl: (
declare const parallel: (
animations: Array<CompositeAnimation>,
config?: ?ParallelConfig
) => CompositeAnimation;
declare const delayImpl: (time: number) => CompositeAnimation;
declare const staggerImpl: (
declare const delay: (time: number) => CompositeAnimation;
declare const stagger: (
time: number,
animations: Array<CompositeAnimation>
) => CompositeAnimation;
@@ -281,19 +277,19 @@ type LoopAnimationConfig = {
resetBeforeIteration?: boolean,
...
};
declare const loopImpl: (
declare const loop: (
animation: CompositeAnimation,
$$PARAM_1$$?: LoopAnimationConfig
) => CompositeAnimation;
declare function forkEventImpl(
declare function forkEvent(
event: ?AnimatedEvent | ?Function,
listener: Function
): AnimatedEvent | Function;
declare function unforkEventImpl(
declare function unforkEvent(
event: ?AnimatedEvent | ?Function,
listener: Function
): void;
declare const eventImpl: <T>(
declare const event: <T>(
argMapping: $ReadOnlyArray<?Mapping>,
config: EventConfig<T>
) => any;
@@ -313,25 +309,25 @@ declare export default {
Color: typeof AnimatedColor,
Interpolation: typeof AnimatedInterpolation,
Node: typeof AnimatedNode,
decay: typeof decayImpl,
timing: typeof timingImpl,
spring: typeof springImpl,
add: typeof addImpl,
subtract: typeof subtractImpl,
divide: typeof divideImpl,
multiply: typeof multiplyImpl,
modulo: typeof moduloImpl,
diffClamp: typeof diffClampImpl,
delay: typeof delayImpl,
sequence: typeof sequenceImpl,
parallel: typeof parallelImpl,
stagger: typeof staggerImpl,
loop: typeof loopImpl,
event: typeof eventImpl,
decay: typeof decay,
timing: typeof timing,
spring: typeof spring,
add: typeof add,
subtract: typeof subtract,
divide: typeof divide,
multiply: typeof multiply,
modulo: typeof modulo,
diffClamp: typeof diffClamp,
delay: typeof delay,
sequence: typeof sequence,
parallel: typeof parallel,
stagger: typeof stagger,
loop: typeof loop,
event: typeof event,
createAnimatedComponent: typeof createAnimatedComponent,
attachNativeEvent: typeof attachNativeEventImpl,
forkEvent: typeof forkEventImpl,
unforkEvent: typeof unforkEventImpl,
attachNativeEvent: typeof attachNativeEvent,
forkEvent: typeof forkEvent,
unforkEvent: typeof unforkEvent,
Event: typeof AnimatedEvent,
};
"
@@ -632,9 +628,10 @@ exports[`public API should not change unintentionally Libraries/Animated/compone
`;
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedScrollView.js 1`] = `
"type AnimatedScrollViewInstance = React.ElementRef<typeof ScrollView>;
"type AnimatedScrollViewProps = React.ElementConfig<typeof ScrollView>;
type AnimatedScrollViewInstance = React.ElementRef<typeof ScrollView>;
declare const AnimatedScrollView: AnimatedComponentType<
ScrollViewProps,
AnimatedScrollViewProps,
AnimatedScrollViewInstance,
>;
declare export default typeof AnimatedScrollView;
@@ -651,7 +648,7 @@ exports[`public API should not change unintentionally Libraries/Animated/compone
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedText.js 1`] = `
"declare export default AnimatedComponentType<
TextProps,
React.ElementConfig<typeof Text>,
React.ElementRef<typeof Text>,
>;
"
@@ -659,7 +656,7 @@ exports[`public API should not change unintentionally Libraries/Animated/compone
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedView.js 1`] = `
"declare export default AnimatedComponentType<
ViewProps,
React.ElementConfig<typeof View>,
React.ElementRef<typeof View>,
>;
"
@@ -698,7 +695,9 @@ type NonAnimatedProps =
| \\"disabled\\"
| \\"accessibilityLabel\\";
type PassThroughProps = $ReadOnly<{
passthroughAnimatedPropExplicitValues?: ViewProps | null,
passthroughAnimatedPropExplicitValues?: React.ElementConfig<
typeof View,
> | null,
}>;
export type AnimatedProps<Props: { ... }> = {
[K in keyof Props]: K extends NonAnimatedProps
@@ -1539,10 +1538,10 @@ exports[`public API should not change unintentionally Libraries/Components/Butto
accessibilityHint?: ?string,
accessibilityLanguage?: ?Stringish,
}>;
declare const NativeTouchable:
declare const Touchable:
| typeof TouchableNativeFeedback
| typeof TouchableOpacity;
type ButtonRef = React.ElementRef<typeof NativeTouchable>;
type ButtonRef = React.ElementRef<typeof Touchable>;
declare const Button: component(
ref?: React.RefSetter<ButtonRef>,
...props: ButtonProps
@@ -1758,7 +1757,8 @@ declare export default typeof LayoutConformanceNativeComponent;
`;
exports[`public API should not change unintentionally Libraries/Components/Pressable/Pressable.js 1`] = `
"export type { PressableAndroidRippleConfig };
"type ViewStyleProp = React.ElementConfig<typeof View>[\\"style\\"];
export type { PressableAndroidRippleConfig };
export type PressableStateCallbackType = $ReadOnly<{
pressed: boolean,
}>;
@@ -1932,11 +1932,11 @@ export { default } from \\"../../../src/private/specs_DEPRECATED/components/RCTS
`;
exports[`public API should not change unintentionally Libraries/Components/SafeAreaView/SafeAreaView.js 1`] = `
"declare const SafeAreaView: component(
"declare const exported: component(
ref?: React.RefSetter<React.ElementRef<typeof View>>,
...props: ViewProps
);
declare export default typeof SafeAreaView;
declare export default typeof exported;
"
`;
@@ -3515,7 +3515,7 @@ declare export default typeof ReactNativeViewAttributes;
`;
exports[`public API should not change unintentionally Libraries/Components/View/View.js 1`] = `
"declare export default component View(
"declare export default component(
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
...props: ViewProps
);
@@ -3685,6 +3685,7 @@ export type AccessibilityProps = $ReadOnly<{
accessibilityLabel?: ?Stringish,
accessibilityHint?: ?Stringish,
\\"aria-label\\"?: ?Stringish,
experimental_accessibilityOrder?: ?Array<string>,
accessibilityRole?: ?AccessibilityRole,
role?: ?Role,
accessibilityState?: ?AccessibilityState,
@@ -3832,7 +3833,6 @@ type ViewBaseProps = $ReadOnly<{
hitSlop?: ?EdgeInsetsOrSizeProp,
pointerEvents?: ?(\\"auto\\" | \\"box-none\\" | \\"box-only\\" | \\"none\\"),
removeClippedSubviews?: ?boolean,
experimental_accessibilityOrder?: ?Array<string>,
}>;
export type ViewProps = $ReadOnly<{
...DirectEventProps,
@@ -4179,11 +4179,11 @@ exports[`public API should not change unintentionally Libraries/EventEmitter/Nat
type EmitterSubscription = EventSubscription;
export type { EventSubscription, EmitterSubscription };
export type NativeEventSubscription = EventSubscription;
type UnsafeNativeEventObject = Object;
type UnsafeObject = Object;
declare export default class NativeEventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeNativeEventObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeNativeEventObject>>>,
Record<string, $ReadOnlyArray<UnsafeObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
constructor(nativeModule?: ?NativeModule): void;
@@ -4859,13 +4859,13 @@ export type LayoutAnimationProperties = $ReadOnly<{
}>;
type OnAnimationDidEndCallback = () => void;
type OnAnimationDidFailCallback = () => void;
declare function setLayoutAnimationEnabled(value: boolean): void;
declare function setEnabled(value: boolean): void;
declare function configureNext(
config: LayoutAnimationConfig,
onAnimationDidEnd?: OnAnimationDidEndCallback,
onAnimationDidFail?: OnAnimationDidFailCallback
): void;
declare function createLayoutAnimation(
declare function create(
duration: number,
type?: LayoutAnimationType,
property?: LayoutAnimationProperty
@@ -4877,7 +4877,7 @@ declare const Presets: {
};
declare const LayoutAnimation: {
configureNext: typeof configureNext,
create: typeof createLayoutAnimation,
create: typeof create,
Types: LayoutAnimationTypes,
Properties: LayoutAnimationProperties,
checkConfig(...args: Array<mixed>): void,
@@ -4885,7 +4885,7 @@ declare const LayoutAnimation: {
easeInEaseOut: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
linear: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
spring: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
setEnabled: typeof setLayoutAnimationEnabled,
setEnabled: typeof setEnabled,
};
declare export default typeof LayoutAnimation;
"
@@ -4940,7 +4940,8 @@ declare export default typeof FillRateHelper;
`;
exports[`public API should not change unintentionally Libraries/Lists/FlatList.js 1`] = `
"type RequiredProps<ItemT> = {
"declare const VirtualizedList: typeof VirtualizedLists.VirtualizedList;
type RequiredProps<ItemT> = {
data: ?$ReadOnly<$ArrayLike<ItemT>>,
};
type OptionalProps<ItemT> = {
@@ -4970,6 +4971,7 @@ type FlatListBaseProps<ItemT> = {
...RequiredProps<ItemT>,
...OptionalProps<ItemT>,
};
type VirtualizedListProps = React.ElementConfig<typeof VirtualizedList>;
export type FlatListProps<ItemT> = {
...Omit<
VirtualizedListProps,
@@ -5687,7 +5689,6 @@ export type ModalPropsIOS = {
>,
onDismiss?: ?() => void,
onOrientationChange?: ?DirectEventHandler<OrientationChangeEvent>,
allowSwipeDismissal?: ?boolean,
};
export type ModalPropsAndroid = {
hardwareAccelerated?: ?boolean,
@@ -6145,7 +6146,7 @@ type PermissionsType = $ReadOnly<{
}>;
export type PermissionStatus = \\"granted\\" | \\"denied\\" | \\"never_ask_again\\";
export type Permission = $Values<PermissionsType>;
declare class PermissionsAndroidImpl {
declare class PermissionsAndroid {
PERMISSIONS: PermissionsType;
RESULTS: $ReadOnly<{
DENIED: \\"denied\\",
@@ -6166,7 +6167,7 @@ declare class PermissionsAndroidImpl {
permissions: Array<Permission>
): Promise<{ [permission: Permission]: PermissionStatus, ... }>;
}
declare const PermissionsAndroidInstance: PermissionsAndroidImpl;
declare const PermissionsAndroidInstance: PermissionsAndroid;
declare export default typeof PermissionsAndroidInstance;
"
`;
@@ -6432,8 +6433,8 @@ declare export default typeof AppContainer;
`;
exports[`public API should not change unintentionally Libraries/ReactNative/AppRegistry.flow.js 1`] = `
"type HeadlessTask = (taskData: any) => Promise<void>;
export type TaskProvider = () => HeadlessTask;
"type Task = (taskData: any) => Promise<void>;
export type TaskProvider = () => Task;
export type ComponentProvider = () => React.ComponentType<any>;
export type ComponentProviderInstrumentationHook = (
component_: ComponentProvider,
@@ -8363,7 +8364,7 @@ declare export default typeof NativeDevLoadingView;
exports[`public API should not change unintentionally Libraries/Utilities/NativeDeviceInfo.js 1`] = `
"export * from \\"../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo\\";
export { default } from \\"../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo\\";
declare export default typeof NativeDeviceInfo;
"
`;
@@ -8654,7 +8655,7 @@ exports[`public API should not change unintentionally Libraries/Utilities/codege
paperComponentNameDeprecated?: string,
excludedPlatforms?: $ReadOnlyArray<\\"iOS\\" | \\"android\\">,
}>;
export type NativeComponentType<T: { ... }> = HostComponent<T>;
export type NativeComponentType<T> = HostComponent<T>;
declare function codegenNativeComponent<Props: { ... }>(
componentName: string,
options?: Options
@@ -8959,12 +8960,12 @@ declare export default ErrorUtils;
`;
exports[`public API should not change unintentionally Libraries/vendor/emitter/EventEmitter.js 1`] = `
"type UnsafeEventObject = Object;
"type UnsafeObject = Object;
export interface EventSubscription {
remove(): void;
}
export interface IEventEmitter<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> {
addListener<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
@@ -8980,8 +8981,8 @@ export interface IEventEmitter<
}
declare export default class EventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeEventObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
Record<string, $ReadOnlyArray<UnsafeObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
constructor(): void;
@@ -9061,8 +9062,6 @@ export type {
export { default as RefreshControl } from \\"./Libraries/Components/RefreshControl/RefreshControl\\";
export { default as SafeAreaView } from \\"./Libraries/Components/SafeAreaView/SafeAreaView\\";
export type {
ScrollViewImperativeMethods,
ScrollViewScrollToOptions,
ScrollResponderType,
ScrollViewProps,
ScrollViewPropsAndroid,
@@ -9349,11 +9348,6 @@ export type {
PublicRootInstance,
PublicTextInstance,
} from \\"./Libraries/ReactPrivate/ReactNativePrivateInterface\\";
export {
default as unstable_VirtualView,
VirtualViewMode,
} from \\"./src/private/components/virtualview/VirtualView\\";
export type { ModeChangeEvent } from \\"./src/private/components/virtualview/VirtualView\\";
"
`;
@@ -12,7 +12,7 @@ import type {TransformVisitor} from 'hermes-transform';
const {
visitors: stripPrivateProperties,
} = require('../../../../scripts/build-types/transforms/flow/stripPrivateProperties');
} = require('../../../../scripts/build-types/transforms/stripPrivateProperties');
const translate = require('flow-api-translator');
const {existsSync, promises: fs} = require('fs');
const glob = require('glob');
@@ -9,14 +9,14 @@
*/
// $FlowFixMe[unclear-type] unclear type of events
type UnsafeEventObject = Object;
type UnsafeObject = Object;
export interface EventSubscription {
remove(): void;
}
export interface IEventEmitter<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> {
addListener<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
@@ -41,7 +41,7 @@ interface Registration<TArgs> {
}
type Registry<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> = {
[K in keyof TEventToArgsMap]: Set<Registration<TEventToArgsMap[K]>>,
};
@@ -68,8 +68,8 @@ type Registry<
*/
export default class EventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeEventObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
Record<string, $ReadOnlyArray<UnsafeObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
#registry: Registry<TEventToArgsMap>;
@@ -157,7 +157,7 @@ export default class EventEmitter<
}
function allocate<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
TEvent: $Keys<TEventToArgsMap>,
TEventArgs: TEventToArgsMap[TEvent],
>(
+1 -4
View File
@@ -397,7 +397,6 @@ let reactFabric = RNTarget(
"components/textinput",
"components/textinput/platform/ios/",
"components/unimplementedview",
"components/virtualview",
"components/root/tests",
],
dependencies: [.reactNativeDependencies, .reactJsiExecutor, .rctTypesafety, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .reactRendererDebug, .reactGraphics, .yoga],
@@ -416,8 +415,6 @@ let reactFabricComponents = RNTarget(
name: .reactFabricComponents,
path: "ReactCommon/react/renderer",
excludedPaths: [
"components/modal/platform/android",
"components/modal/platform/cxx",
"components/view/platform/android",
"components/view/platform/windows",
"components/view/platform/macos",
@@ -433,7 +430,7 @@ let reactFabricComponents = RNTarget(
"conponents/rncore", // this was the old folder where RN Core Components were generated. If you ran codegen in the past, you might have some files in it that might make the build fail.
],
dependencies: [.reactNativeDependencies, .reactCore, .reactJsiExecutor, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .yoga, .reactRendererDebug, .reactGraphics, .reactFabric, .reactTurboModuleBridging],
sources: ["components/inputaccessory", "components/modal", "components/safeareaview", "components/text", "components/text/platform/cxx", "components/textinput", "components/textinput/platform/ios/", "components/unimplementedview", "components/virtualview", "textlayoutmanager", "textlayoutmanager/platform/ios"]
sources: ["components/inputaccessory", "components/modal", "components/safeareaview", "components/text", "components/text/platform/cxx", "components/textinput", "components/textinput/platform/ios/", "components/unimplementedview", "textlayoutmanager", "textlayoutmanager/platform/ios"]
)
/// React-FabricImage.podspec
@@ -1,109 +0,0 @@
# 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.
require "json"
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
version = package['version']
source = ReactNativeCoreUtils.resolve_podspec_source()
header_search_paths = [
"${PODS_ROOT}/Headers/Private/React-Core-prebuilt",
"${PODS_ROOT}/Headers/Private/React-Core-prebuilt/RCTDeprecation",
"${PODS_ROOT}/Headers/Private/React-Core-prebuilt/ReactCommon/yoga",
"${PODS_ROOT}/Headers/Private/React-Core-prebuilt/ReactCommon",
"${PODS_ROOT}/Headers/Private/React-Core-prebuilt/Libraries/AppDelegate",
"${PODS_ROOT}/Headers/Private/React-Core-prebuilt/Libraries",
"$(REACT_NATIVE_PATH)/React/Base",
"$(REACT_NATIVE_PATH)/ReactCommon",
"$(REACT_NATIVE_PATH)/Libraries",
"$(REACT_NATIVE_PATH)/ReactApple",
"$(REACT_NATIVE_PATH)/ReactCxxPlatform",
"$(REACT_NATIVE_PATH)/ReactCommon/react/runtime/platform/ios",
"${REACT_NATIVE_PATH}/ReactCommon/jsi",
"$(REACT_NATIVE_PATH)/ReactCommon/jsiexecutor/",
"$(REACT_NATIVE_PATH)/ReactCommon/react/nativemodule/samples/platform/ios",
"$(REACT_NATIVE_PATH)/ReactCommon/react/nativemodule/samples",
]
Pod::Spec.new do |spec|
spec.name = 'React-Core-prebuilt'
spec.version = version
spec.summary = "Prebuilt core of React Native."
spec.homepage = "https://reactnative.dev/"
spec.description = 'Prebuilt React Native Core libraries and headers'
spec.homepage = 'https://github.com/facebook/react-native'
spec.license = package['license']
spec.authors = 'meta'
spec.platforms = min_supported_versions
spec.source = source
spec.vendored_frameworks = "React.xcframework"
spec.preserve_paths = '**/*.*'
spec.header_mappings_dir = 'React.xcframework/Headers'
spec.source_files = 'React.xcframework/Headers/**/*.{h,hpp}'
spec.module_name = 'React'
spec.module_map = 'React.xcframework/Modules/module.modulemap'
spec.public_header_files = 'React.xcframework/Headers/**/*.h'
# Setup the consuming project's search paths
spec.user_target_xcconfig = {
"HEADER_SEARCH_PATHS" => header_search_paths,
"SWIFT_INCLUDE_PATHS" => "${PODS_ROOT}/Headers/Private/React-Core-prebuilt",
'DEFINES_MODULE' => 'YES',
'CLANG_ENABLE_MODULES' => 'YES',
}
spec.pod_target_xcconfig = {
'WARNING_CFLAGS' => '-Wno-comma -Wno-shorten-64-to-32',
"CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
'DEFINES_MODULE' => 'YES',
'CLANG_ENABLE_MODULES' => 'YES',
}
# We need to make sure that the React.xcframework is copied correctly - in the downloaded tarball
# the root directory is the framework, but when using it we need to have it in a subdirectory
# called React.xcframework, so we need to move the contents of the tarball into that directory.
# This is done in the prepare_command.
spec.prepare_command = <<~'CMD'
CURRENT_PATH=$(pwd)
XCFRAMEWORK_PATH="${CURRENT_PATH}/React.xcframework"
mkdir -p "${XCFRAMEWORK_PATH}"
find "$CURRENT_PATH" -mindepth 1 -maxdepth 1 ! -name "$(basename "$XCFRAMEWORK_PATH")" -exec mv {} "$XCFRAMEWORK_PATH" \;
CMD
# If we are passing a local tarball, we don't want to switch between Debug and Release
if !ENV["RCT_TESTONLY_RNCORE_TARBALL_PATH"]
script_phase = {
:name => "[RNDeps] Replace React Native Core for the right configuration, if needed",
:execution_position => :before_compile,
:script => <<-EOS
. "$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh"
CONFIG="Release"
if echo $GCC_PREPROCESSOR_DEFINITIONS | grep -q "DEBUG=1"; then
CONFIG="Debug"
fi
# TODO(T228219721): Add this for React Native Core as well
##### "$NODE_BINARY" "$REACT_NATIVE_PATH/third-party-podspecs/replace_dependencies_version.js" -c "$CONFIG" -r "#{version}" -p "$PODS_ROOT"
EOS
}
# :always_out_of_date is only available in CocoaPods 1.13.0 and later
if Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.13.0')
# always run the script without warning
script_phase[:always_out_of_date] = "1"
end
spec.script_phase = script_phase
end
end
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
#import <tgmath.h>
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@@ -0,0 +1,31 @@
/*
* 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.
*/
#pragma once
#ifndef RCT_FIT_RM_OLD_RUNTIME
#include <jsireact/JSIExecutor.h>
namespace facebook::react {
class JSCExecutorFactory : public JSExecutorFactory {
public:
explicit JSCExecutorFactory(JSIExecutor::RuntimeInstaller runtimeInstaller)
: runtimeInstaller_(std::move(runtimeInstaller)) {}
std::unique_ptr<JSExecutor> createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> jsQueue) override;
private:
JSIExecutor::RuntimeInstaller runtimeInstaller_;
};
} // namespace facebook::react
#endif // RCT_FIT_RM_OLD_RUNTIME
@@ -0,0 +1,28 @@
/*
* 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 "JSCExecutorFactory.h"
#ifndef RCT_FIT_RM_OLD_RUNTIME
#import <jsc/JSCRuntime.h>
#import <memory>
namespace facebook::react {
std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(
std::shared_ptr<ExecutorDelegate> delegate,
std::shared_ptr<MessageQueueThread> __unused jsQueue)
{
return std::make_unique<JSIExecutor>(
facebook::jsc::makeJSCRuntime(), delegate, JSIExecutor::defaultTimeoutInvoker, runtimeInstaller_);
}
} // namespace facebook::react
#endif // RCT_FIT_RM_OLD_RUNTIME
@@ -22,6 +22,8 @@
}
_touchHandler = [RCTSurfaceTouchHandler new];
self.modalInPresentation = YES;
return self;
}
@@ -124,7 +124,6 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
_viewController = [RCTFabricModalHostViewController new];
_viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
_viewController.delegate = self;
_viewController.modalInPresentation = YES;
}
return _viewController;
}
@@ -240,7 +239,6 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
{
const auto &oldViewProps = static_cast<const ModalHostViewProps &>(*_props);
const auto &newProps = static_cast<const ModalHostViewProps &>(*props);
#if !TARGET_OS_TV
@@ -253,10 +251,6 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
self.viewController.modalPresentationStyle = presentationConfiguration(newProps);
if (oldViewProps.allowSwipeDismissal != newProps.allowSwipeDismissal) {
self.viewController.modalInPresentation = !newProps.allowSwipeDismissal;
}
_shouldPresent = newProps.visible;
[self ensurePresentedOnlyIfNeeded];
@@ -289,16 +283,6 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
}
}
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
{
auto eventEmitter = [self modalEventEmitter];
const auto &props = static_cast<const ModalHostViewProps &>(*_props);
if (eventEmitter && props.allowSwipeDismissal) {
eventEmitter->onRequestClose({});
}
}
@end
#ifdef __cplusplus
@@ -1215,7 +1215,7 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
result = [NSMutableString string];
}
if (result.length > 0) {
[result appendString:@", "];
[result appendString:@" "];
}
[result appendString:label];
}
@@ -1230,10 +1230,7 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
return label;
}
if (self.isAccessibilityElement) {
return RCTRecursiveAccessibilityLabel(self.currentContainerView);
}
return nil;
return RCTRecursiveAccessibilityLabel(self.currentContainerView);
}
- (NSString *)accessibilityLabelForCoopting
@@ -1,24 +0,0 @@
/*
* 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.
*/
#import <UIKit/UIKit.h>
#import <React/RCTViewComponentView.h>
NS_ASSUME_NONNULL_BEGIN
@interface RCTVirtualViewComponentView : RCTViewComponentView
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE;
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END
@@ -1,330 +0,0 @@
/*
* 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.
*/
#import "RCTVirtualViewComponentView.h"
#import <React/RCTAssert.h>
#import <React/RCTConversions.h>
#import <React/RCTScrollViewComponentView.h>
#import <React/RCTScrollableProtocol.h>
#import <React/UIView+React.h>
#import <jsi/jsi.h>
#import <react/featureflags/ReactNativeFeatureFlags.h>
#import <react/renderer/components/FBReactNativeSpec/ComponentDescriptors.h>
#import <react/renderer/components/FBReactNativeSpec/EventEmitters.h>
#import <react/renderer/components/FBReactNativeSpec/Props.h>
#import <react/renderer/components/virtualview/VirtualViewComponentDescriptor.h>
#import <react/renderer/components/virtualview/VirtualViewShadowNode.h>
#import "RCTFabricComponentsPlugins.h"
using namespace facebook;
using namespace facebook::react;
typedef NS_ENUM(NSInteger, RCTVirtualViewMode) {
RCTVirtualViewModeVisible = 0,
RCTVirtualViewModePrerender = 1,
RCTVirtualViewModeHidden = 2,
};
typedef NS_ENUM(NSInteger, RCTVirtualViewRenderState) {
RCTVirtualViewRenderStateUnknown = 0,
RCTVirtualViewRenderStateRendered = 1,
RCTVirtualViewRenderStateNone = 2,
};
/**
* Checks whether one CGRect overlaps with another CGRect.
*
* This is different from CGRectIntersectsRect because a CGRect representing
* a line or a point is considered to overlap with another CGRect if the line
* or point is within the rect bounds. However, two CGRects are not considered
* to overlap if they only share a boundary.
*/
static BOOL CGRectOverlaps(CGRect rect1, CGRect rect2)
{
CGFloat minY1 = CGRectGetMinY(rect1);
CGFloat maxY1 = CGRectGetMaxY(rect1);
CGFloat minY2 = CGRectGetMinY(rect2);
CGFloat maxY2 = CGRectGetMaxY(rect2);
if (minY1 >= maxY2 || minY2 >= maxY1) {
// No overlap on the y-axis.
return NO;
}
CGFloat minX1 = CGRectGetMinX(rect1);
CGFloat maxX1 = CGRectGetMaxX(rect1);
CGFloat minX2 = CGRectGetMinX(rect2);
CGFloat maxX2 = CGRectGetMaxX(rect2);
if (minX1 >= maxX2 || minX2 >= maxX1) {
// No overlap on the x-axis.
return NO;
}
return YES;
}
@interface RCTVirtualViewComponentView () <UIScrollViewDelegate>
@end
@implementation RCTVirtualViewComponentView {
RCTScrollViewComponentView *_lastParentScrollViewComponentView;
std::optional<enum RCTVirtualViewMode> _mode;
enum RCTVirtualViewRenderState _renderState;
std::optional<CGRect> _targetRect;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
_props = VirtualViewShadowNode::defaultSharedProps();
_renderState = RCTVirtualViewRenderStateUnknown;
}
return self;
}
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
{
const auto &newViewProps = static_cast<const VirtualViewProps &>(*props);
if (!_mode.has_value()) {
_mode = newViewProps.initialHidden ? RCTVirtualViewModeHidden : RCTVirtualViewModeVisible;
}
// If disabled, `_renderState` will always be `RCTVirtualViewRenderStateUnknown`.
if (ReactNativeFeatureFlags::enableVirtualViewRenderState()) {
switch (newViewProps.renderState) {
case 1:
_renderState = RCTVirtualViewRenderStateRendered;
break;
case 2:
_renderState = RCTVirtualViewRenderStateNone;
break;
default:
_renderState = RCTVirtualViewRenderStateUnknown;
break;
}
}
[super updateProps:props oldProps:oldProps];
}
- (RCTScrollViewComponentView *)getParentScrollViewComponentView
{
UIView *view = self.superview;
while (view != nil) {
if ([view isKindOfClass:[RCTScrollViewComponentView class]]) {
return (RCTScrollViewComponentView *)view;
}
view = view.superview;
}
return nil;
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
// No need to remove the scroll listener here since the view is always removed from window before being recycled and
// we do that in didMoveToWindow, which gets called when the view is removed from window.
RCTAssert(
_lastParentScrollViewComponentView == nil,
@"_lastParentScrollViewComponentView should already have been cleared in didMoveToWindow.");
_mode.reset();
_targetRect.reset();
}
// Handles case when sibling changes size.
// TODO(T202601695): This doesn't yet handle the case of elements in the ScrollView outside a VirtualColumn changing
// size.
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
{
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:_layoutMetrics];
[self dispatchOnModeChangeIfNeeded:YES];
}
- (void)didMoveToWindow
{
[super didMoveToWindow];
if (_lastParentScrollViewComponentView) {
[_lastParentScrollViewComponentView removeScrollListener:self];
_lastParentScrollViewComponentView = nil;
}
if (RCTScrollViewComponentView *parentScrollViewComponentView = [self getParentScrollViewComponentView]) {
if (self.window) {
// TODO(T202601695): We also want the ScrollView to emit layout changes from didLayoutSubviews so that any event
// that may affect visibily of this view notifies the listeners.
[parentScrollViewComponentView addScrollListener:self];
_lastParentScrollViewComponentView = parentScrollViewComponentView;
// We want to dispatch the event immediately when the view is added to the window before any scrolling occurs.
[self dispatchOnModeChangeIfNeeded:NO];
}
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self dispatchOnModeChangeIfNeeded:NO];
}
- (void)dispatchOnModeChangeIfNeeded:(BOOL)checkForTargetRectChange
{
if (!_lastParentScrollViewComponentView) {
return;
}
UIScrollView *scrollView = _lastParentScrollViewComponentView.scrollView;
CGRect targetRect = [self convertRect:self.bounds toView:scrollView];
// While scrolling, the `targetRect` does not change, so we don't check for changed `targetRect` in that case.
if (checkForTargetRectChange) {
if (_targetRect.has_value() && CGRectEqualToRect(targetRect, _targetRect.value())) {
return;
}
_targetRect = targetRect;
}
enum RCTVirtualViewMode newMode;
CGRect thresholdRect = CGRectMake(
scrollView.contentOffset.x,
scrollView.contentOffset.y,
scrollView.frame.size.width,
scrollView.frame.size.height);
if (CGRectOverlaps(targetRect, thresholdRect)) {
newMode = RCTVirtualViewModeVisible;
} else {
auto prerender = false;
const CGFloat prerenderRatio = ReactNativeFeatureFlags::virtualViewPrerenderRatio();
if (prerenderRatio > 0) {
thresholdRect = CGRectInset(
thresholdRect, -thresholdRect.size.width * prerenderRatio, -thresholdRect.size.height * prerenderRatio);
prerender = CGRectOverlaps(targetRect, thresholdRect);
}
if (prerender) {
newMode = RCTVirtualViewModePrerender;
} else {
newMode = RCTVirtualViewModeHidden;
thresholdRect = CGRectZero;
}
}
if (_mode.has_value() && newMode == _mode.value()) {
return;
}
// NOTE: Make sure to keep these props in sync with dispatchSyncModeChange below where we have to explicitly copy all
// props.
VirtualViewEventEmitter::OnModeChange event = {
.mode = (int)newMode,
.targetRect =
{.x = targetRect.origin.x,
.y = targetRect.origin.y,
.width = targetRect.size.width,
.height = targetRect.size.height},
.thresholdRect =
{.x = thresholdRect.origin.x,
.y = thresholdRect.origin.y,
.width = thresholdRect.size.width,
.height = thresholdRect.size.height},
};
const std::optional<enum RCTVirtualViewMode> oldMode = _mode;
_mode = newMode;
switch (newMode) {
case RCTVirtualViewModeVisible:
if (_renderState == RCTVirtualViewRenderStateUnknown) {
// Feature flag is disabled, so use the former logic.
[self dispatchSyncModeChange:event];
} else {
// If the previous mode was prerender and the result of dispatching that event was committed, we do not need to
// dispatch an event for visible.
const auto wasPrerenderCommitted = oldMode.has_value() && oldMode == RCTVirtualViewModePrerender &&
_renderState == RCTVirtualViewRenderStateRendered;
if (!wasPrerenderCommitted) {
[self dispatchSyncModeChange:event];
}
}
break;
case RCTVirtualViewModePrerender:
if (!oldMode.has_value() || oldMode != RCTVirtualViewModeVisible) {
[self dispatchAsyncModeChange:event];
}
break;
case RCTVirtualViewModeHidden:
[self dispatchAsyncModeChange:event];
break;
}
}
- (void)dispatchAsyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
{
if (!_eventEmitter) {
return;
}
std::shared_ptr<const VirtualViewEventEmitter> emitter =
std::static_pointer_cast<const VirtualViewEventEmitter>(_eventEmitter);
emitter->onModeChange(event);
}
- (void)dispatchSyncModeChange:(VirtualViewEventEmitter::OnModeChange &)event
{
if (!_eventEmitter) {
return;
}
std::shared_ptr<const VirtualViewEventEmitter> emitter =
std::static_pointer_cast<const VirtualViewEventEmitter>(_eventEmitter);
// TODO: Move this into a custom event emitter. We had to duplicate the codegen code here from onModeChange in order
// to dispatch synchronously and discrete.
emitter->experimental_flushSync([&emitter, &event]() {
emitter->dispatchEvent(
"modeChange",
[event](jsi::Runtime &runtime) {
auto payload = jsi::Object(runtime);
payload.setProperty(runtime, "mode", event.mode);
{
auto targetRect = jsi::Object(runtime);
targetRect.setProperty(runtime, "x", event.targetRect.x);
targetRect.setProperty(runtime, "y", event.targetRect.y);
targetRect.setProperty(runtime, "width", event.targetRect.width);
targetRect.setProperty(runtime, "height", event.targetRect.height);
payload.setProperty(runtime, "targetRect", targetRect);
}
{
auto thresholdRect = jsi::Object(runtime);
thresholdRect.setProperty(runtime, "x", event.thresholdRect.x);
thresholdRect.setProperty(runtime, "y", event.thresholdRect.y);
thresholdRect.setProperty(runtime, "width", event.thresholdRect.width);
thresholdRect.setProperty(runtime, "height", event.thresholdRect.height);
payload.setProperty(runtime, "thresholdRect", thresholdRect);
}
return payload;
},
RawEvent::Category::Discrete);
});
}
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<VirtualViewComponentDescriptor>();
}
@end
Class<RCTComponentViewProtocol> VirtualViewCls(void)
{
return RCTVirtualViewComponentView.class;
}
@@ -72,12 +72,6 @@ class SchedulerDelegateProxy : public SchedulerDelegate {
[scheduler.delegate schedulerDidSynchronouslyUpdateViewOnUIThread:tag props:props];
}
void schedulerDidUpdateShadowTree(const std::unordered_map<Tag, folly::dynamic> &tagToProps) override
{
// Does nothing.
// This delegate method is not currently used on iOS.
}
private:
void *scheduler_;
};
@@ -16,13 +16,6 @@ NS_ASSUME_NONNULL_BEGIN
+ (std::vector<facebook::react::ProcessedColorStop>)getFixedColorStops:
(const std::vector<facebook::react::ColorStop> &)colorStops
gradientLineLength:(CGFloat)gradientLineLength;
// CAGradientLayer linear gradient squishes the non-square gradient to square gradient.
// This function fixes the "squished" effect.
// See https://stackoverflow.com/a/43176174 for more information.
+ (std::pair<CGPoint, CGPoint>)pointsForCAGradientLayerLinearGradient:(CGPoint)startPoint
endPoint:(CGPoint)endPoint
bounds:(CGSize)bounds;
@end
NS_ASSUME_NONNULL_END
@@ -9,140 +9,10 @@
#import <React/RCTAnimationUtils.h>
#import <React/RCTConversions.h>
#import <react/utils/FloatComparison.h>
#include <optional>
#import <vector>
using namespace facebook::react;
namespace {
struct Line;
struct LineSegment {
CGPoint p1;
CGPoint p2;
LineSegment(CGPoint p1, CGPoint p2) : p1(p1), p2(p2) {}
LineSegment(CGPoint p1, CGFloat m, CGFloat distance);
CGFloat getLength() const
{
CGFloat dx = p2.x - p1.x;
CGFloat dy = p2.y - p1.y;
return sqrt(dx * dx + dy * dy);
}
CGFloat getDistance() const
{
return p1.x <= p2.x ? getLength() : -getLength();
}
CGPoint getMidpoint() const
{
return CGPointMake((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
}
CGFloat getSlope() const
{
CGFloat dx = p2.x - p1.x;
if (floatEquality(dx, 0.0)) {
return std::numeric_limits<CGFloat>::infinity();
}
return (p2.y - p1.y) / dx;
}
CGFloat getPerpendicularSlope() const
{
CGFloat slope = getSlope();
if (std::isinf(slope)) {
return 0.0;
}
if (floatEquality(slope, 0.0)) {
return -std::numeric_limits<CGFloat>::infinity();
}
return -1 / slope;
}
Line toLine() const;
LineSegment perpendicularBisector() const
{
CGPoint midpoint = getMidpoint();
CGFloat perpSlope = getPerpendicularSlope();
CGFloat dist = getDistance();
return {LineSegment(midpoint, perpSlope, -dist / 2).p2, LineSegment(midpoint, perpSlope, dist / 2).p2};
}
LineSegment multiplied(CGSize multipliers) const
{
return {
CGPointMake(p1.x * multipliers.width, p1.y * multipliers.height),
CGPointMake(p2.x * multipliers.width, p2.y * multipliers.height)};
}
LineSegment divided(CGSize divisors) const
{
return multiplied(CGSizeMake(1 / divisors.width, 1 / divisors.height));
}
};
struct Line {
CGFloat m;
CGFloat b;
Line(CGFloat m, CGFloat b) : m(m), b(b) {}
Line(CGFloat m, CGPoint p) : m(m), b(p.y - m * p.x) {}
Line(CGPoint p1, CGPoint p2) : m(LineSegment(p1, p2).getSlope()), b(p1.y - m * p1.x) {}
CGFloat y(CGFloat x) const
{
return m * x + b;
}
CGPoint point(CGFloat x) const
{
return CGPointMake(x, y(x));
}
std::optional<CGPoint> intersection(const Line &other) const
{
CGFloat n = other.m;
CGFloat c = other.b;
if (floatEquality(m, n)) {
return std::nullopt;
}
CGFloat x = (c - b) / (m - n);
return point(x);
}
};
LineSegment::LineSegment(CGPoint p1, CGFloat m, CGFloat distance) : p1(p1)
{
Line line(m, p1);
CGPoint measuringPoint = line.point(p1.x + 1);
LineSegment measuringSegment(p1, measuringPoint);
CGFloat measuringDeltaH = measuringSegment.getDistance();
CGFloat deltaX = !floatEquality(measuringDeltaH, 0.0) ? distance / measuringDeltaH : 0.0;
p2 = line.point(p1.x + deltaX);
}
Line LineSegment::toLine() const
{
return {p1, p2};
}
CGSize calculateMultipliers(CGSize bounds)
{
if (bounds.height <= bounds.width) {
return CGSizeMake(1, bounds.width / bounds.height);
} else {
return CGSizeMake(bounds.height / bounds.width, 1);
}
}
} // namespace
static std::optional<Float> resolveColorStopPosition(ValueUnit position, CGFloat gradientLineLength)
{
if (position.unit == UnitType::Point) {
@@ -182,21 +52,21 @@ static std::vector<ProcessedColorStop> processColorTransitionHints(const std::ve
auto leftDist = offset - offsetLeft;
auto rightDist = offsetRight - offset;
auto totalDist = offsetRight - offsetLeft;
const SharedColor &leftSharedColor = colorStops[x - 1].color;
const SharedColor &rightSharedColor = colorStops[x + 1].color;
SharedColor leftSharedColor = colorStops[x - 1].color;
SharedColor rightSharedColor = colorStops[x + 1].color;
if (floatEquality(leftDist, rightDist)) {
if (facebook::react::floatEquality(leftDist, rightDist)) {
colorStops.erase(colorStops.begin() + x);
--indexOffset;
continue;
}
if (floatEquality(leftDist, 0.0)) {
if (facebook::react::floatEquality(leftDist, .0f)) {
colorStops[x].color = rightSharedColor;
continue;
}
if (floatEquality(rightDist, 0.0)) {
if (facebook::react::floatEquality(rightDist, .0f)) {
colorStops[x].color = leftSharedColor;
continue;
}
@@ -250,7 +120,7 @@ static std::vector<ProcessedColorStop> processColorTransitionHints(const std::ve
auto green = (interpolatedColor >> 8) & 0xFF;
auto blue = interpolatedColor & 0xFF;
newStop.color = colorFromRGBA(red, green, blue, alpha);
newStop.color = facebook::react::colorFromRGBA(red, green, blue, alpha);
}
// Replace the color hint with new color stops
@@ -331,47 +201,4 @@ static std::vector<ProcessedColorStop> processColorTransitionHints(const std::ve
}
return processColorTransitionHints(fixedColorStops);
}
// CAGradientLayer linear gradient squishes the non-square gradient to square gradient.
// This function fixes the "squished" effect.
// See https://stackoverflow.com/a/43176174 for more information.
+ (std::pair<CGPoint, CGPoint>)pointsForCAGradientLayerLinearGradient:(CGPoint)startPoint
endPoint:(CGPoint)endPoint
bounds:(CGSize)bounds
{
if (floatEquality(startPoint.x, endPoint.x) || floatEquality(startPoint.y, endPoint.y)) {
// Apple's implementation of horizontal and vertical gradients works just fine
return {startPoint, endPoint};
}
LineSegment startEnd(startPoint, endPoint);
LineSegment ab = startEnd.multiplied({bounds.width, bounds.height});
const CGPoint a = ab.p1;
const CGPoint b = ab.p2;
LineSegment cd = ab.perpendicularBisector();
CGSize multipliers = calculateMultipliers(bounds);
LineSegment lineSegmentCD = cd.multiplied(multipliers);
LineSegment lineSegmentEF = lineSegmentCD.perpendicularBisector();
LineSegment ef = lineSegmentEF.divided(multipliers);
Line efLine = ef.toLine();
Line aParallelLine(cd.getSlope(), a);
Line bParallelLine(cd.getSlope(), b);
std::optional<CGPoint> g_opt = efLine.intersection(aParallelLine);
std::optional<CGPoint> h_opt = efLine.intersection(bParallelLine);
if (g_opt && h_opt) {
LineSegment gh(*g_opt, *h_opt);
LineSegment result = gh.divided({bounds.width, bounds.height});
return {result.p1, result.p2};
}
return {startPoint, endPoint};
}
@end
@@ -19,52 +19,54 @@ using namespace facebook::react;
+ (CALayer *)gradientLayerWithSize:(CGSize)size gradient:(const LinearGradient &)gradient
{
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:size];
const auto &direction = gradient.direction;
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
CGPoint startPoint;
CGPoint endPoint;
UIImage *gradientImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) {
CGPoint startPoint;
CGPoint endPoint;
if (direction.type == GradientDirectionType::Angle) {
CGFloat angle = std::get<Float>(direction.value);
std::tie(startPoint, endPoint) = getPointsFromAngle(angle, size);
} else if (direction.type == GradientDirectionType::Keyword) {
auto keyword = std::get<GradientKeyword>(direction.value);
CGFloat angle = getAngleForKeyword(keyword, size);
std::tie(startPoint, endPoint) = getPointsFromAngle(angle, size);
} else {
// Default to top-to-bottom gradient
CGFloat centerX = size.width / 2;
startPoint = CGPointMake(centerX, 0.0);
endPoint = CGPointMake(centerX, size.height);
}
if (direction.type == GradientDirectionType::Angle) {
CGFloat angle = std::get<Float>(direction.value);
std::tie(startPoint, endPoint) = getPointsFromAngle(angle, size);
} else if (direction.type == GradientDirectionType::Keyword) {
auto keyword = std::get<GradientKeyword>(direction.value);
CGFloat angle = getAngleForKeyword(keyword, size);
std::tie(startPoint, endPoint) = getPointsFromAngle(angle, size);
} else {
// Default to top-to-bottom gradient
startPoint = CGPointMake(0.0, 0.0);
endPoint = CGPointMake(0.0, size.height);
}
CGFloat dx = endPoint.x - startPoint.x;
CGFloat dy = endPoint.y - startPoint.y;
CGFloat gradientLineLength = sqrt(dx * dx + dy * dy);
const auto colorStops = [RCTGradientUtils getFixedColorStops:gradient.colorStops
gradientLineLength:gradientLineLength];
NSMutableArray<id> *colors = [NSMutableArray array];
NSMutableArray<NSNumber *> *locations = [NSMutableArray array];
CGPoint relativeStartPoint = CGPointMake(startPoint.x / size.width, startPoint.y / size.height);
CGPoint relativeEndPoint = CGPointMake(endPoint.x / size.width, endPoint.y / size.height);
CGFloat dx = endPoint.x - startPoint.x;
CGFloat dy = endPoint.y - startPoint.y;
CGFloat gradientLineLength = sqrt(dx * dx + dy * dy);
const auto colorStops = [RCTGradientUtils getFixedColorStops:gradient.colorStops
gradientLineLength:gradientLineLength];
CGPoint fixedStartPoint;
CGPoint fixedEndPoint;
CGContextRef context = rendererContext.CGContext;
NSMutableArray *colors = [NSMutableArray array];
CGFloat locations[colorStops.size()];
std::tie(fixedStartPoint, fixedEndPoint) = [RCTGradientUtils pointsForCAGradientLayerLinearGradient:relativeStartPoint
endPoint:relativeEndPoint
bounds:size];
for (size_t i = 0; i < colorStops.size(); ++i) {
const auto &colorStop = colorStops[i];
CGColorRef cgColor = RCTCreateCGColorRefFromSharedColor(colorStop.color);
[colors addObject:(__bridge id)cgColor];
locations[i] = std::max(std::min(colorStop.position.value(), 1.0), 0.0);
}
gradientLayer.startPoint = fixedStartPoint;
gradientLayer.endPoint = fixedEndPoint;
CGGradientRef cgGradient = CGGradientCreateWithColors(NULL, (__bridge CFArrayRef)colors, locations);
for (const auto &colorStop : colorStops) {
[colors addObject:(id)RCTUIColorFromSharedColor(colorStop.color).CGColor];
[locations addObject:@(std::max(std::min(colorStop.position.value(), 1.0), 0.0))];
}
CGContextDrawLinearGradient(context, cgGradient, startPoint, endPoint, 0);
gradientLayer.colors = colors;
gradientLayer.locations = locations;
for (id color in colors) {
CGColorRelease((__bridge CGColorRef)color);
}
CGGradientRelease(cgGradient);
}];
CALayer *gradientLayer = [CALayer layer];
gradientLayer.contents = (__bridge id)gradientImage.CGImage;
return gradientLayer;
}
@@ -153,42 +153,75 @@ static RadiusVector GetRadialGradientRadius(
+ (CALayer *)gradientLayerWithSize:(CGSize)size gradient:(const RadialGradient &)gradient
{
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.type = kCAGradientLayerRadial;
CGPoint centerPoint = CGPointMake(size.width / 2.0, size.height / 2.0);
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:size];
UIImage *gradientImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) {
CGContextRef context = rendererContext.CGContext;
if (gradient.position.top) {
centerPoint.y = gradient.position.top->resolve(size.height);
} else if (gradient.position.bottom) {
centerPoint.y = size.height - gradient.position.bottom->resolve(size.height);
}
CGPoint centerPoint = CGPointMake(size.width / 2.0, size.height / 2.0);
if (gradient.position.left) {
centerPoint.x = gradient.position.left->resolve(size.width);
} else if (gradient.position.right) {
centerPoint.x = size.width - gradient.position.right->resolve(size.width);
}
if (gradient.position.top) {
centerPoint.y = gradient.position.top->resolve(size.height);
} else if (gradient.position.bottom) {
centerPoint.y = size.height - gradient.position.bottom->resolve(size.height);
}
bool isCircle = (gradient.shape == RadialGradientShape::Circle);
auto [radiusX, radiusY] =
GetRadialGradientRadius(isCircle, gradient.size, centerPoint.x, centerPoint.y, size.width, size.height);
const auto gradientLineLength = std::max(radiusX, radiusY);
const auto colorStops = [RCTGradientUtils getFixedColorStops:gradient.colorStops
gradientLineLength:gradientLineLength];
gradientLayer.startPoint = CGPointMake(centerPoint.x / size.width, centerPoint.y / size.height);
// endpoint.x is horizontal length and endpoint.y is vertical length
gradientLayer.endPoint = CGPointMake(
gradientLayer.startPoint.x + radiusX / size.width, gradientLayer.startPoint.y + radiusY / size.height);
if (gradient.position.left) {
centerPoint.x = gradient.position.left->resolve(size.width);
} else if (gradient.position.right) {
centerPoint.x = size.width - gradient.position.right->resolve(size.width);
}
NSMutableArray<id> *colors = [NSMutableArray array];
NSMutableArray<NSNumber *> *locations = [NSMutableArray array];
for (const auto &colorStop : colorStops) {
[colors addObject:(id)RCTUIColorFromSharedColor(colorStop.color).CGColor];
[locations addObject:@(std::max(std::min(colorStop.position.value(), 1.0), 0.0))];
}
bool isCircle = (gradient.shape == RadialGradientShape::Circle);
auto [radiusX, radiusY] =
GetRadialGradientRadius(isCircle, gradient.size, centerPoint.x, centerPoint.y, size.width, size.height);
gradientLayer.colors = colors;
gradientLayer.locations = locations;
CGFloat scale = 1.0;
if (radiusX != radiusY && gradient.shape != RadialGradientShape::Circle) {
scale = radiusX / radiusY;
CGContextSaveGState(context);
// Scale the context to make the circular gradient appear elliptical
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, 1.0, 1.0 / scale);
CGContextTranslateCTM(context, -centerPoint.x, -centerPoint.y);
radiusX = std::max(radiusX, radiusY * scale);
}
const auto colorStops = [RCTGradientUtils getFixedColorStops:gradient.colorStops gradientLineLength:radiusX];
NSMutableArray *colors = [NSMutableArray array];
CGFloat locations[colorStops.size()];
for (size_t i = 0; i < colorStops.size(); ++i) {
const auto &colorStop = colorStops[i];
CGColorRef cgColor = RCTCreateCGColorRefFromSharedColor(colorStop.color);
[colors addObject:(__bridge id)cgColor];
locations[i] = std::max(std::min(colorStop.position.value(), 1.0), 0.0);
}
CGGradientRef cgGradient = CGGradientCreateWithColors(NULL, (__bridge CFArrayRef)colors, locations);
CGContextDrawRadialGradient(
context,
cgGradient,
centerPoint,
0,
centerPoint,
radiusX,
kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
// Restore the context state if we scaled it
if (radiusX != radiusY && gradient.shape != RadialGradientShape::Circle) {
CGContextRestoreGState(context);
}
for (id color in colors) {
CGColorRelease((__bridge CGColorRef)color);
}
CGGradientRelease(cgGradient);
}];
CALayer *gradientLayer = [CALayer layer];
gradientLayer.contents = (__bridge id)gradientImage.CGImage;
return gradientLayer;
}
@@ -5,11 +5,16 @@
* LICENSE file in the root directory of this source tree.
*/
#import <react/runtime/JSRuntimeFactoryCAPI.h>
#pragma once
namespace facebook::react {
struct RenderFormatOptions {
bool includeRoot{false};
bool includeLayoutMetrics{false};
};
} // namespace facebook::react
#ifdef __cplusplus
extern "C" {
#endif
JSRuntimeFactoryRef jsrt_create_jsc_factory(void);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,20 @@
/*
* 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.
*/
#import "RCTJscInstanceFactory.h"
#import <ReactCommon/RCTJscInstance.h>
using namespace facebook::react;
extern "C" {
JSRuntimeFactoryRef jsrt_create_jsc_factory(void)
{
return reinterpret_cast<JSRuntimeFactoryRef>(new RCTJscInstance());
}
} // extern "C"
@@ -24,7 +24,6 @@
@property (nonatomic, copy) RCTDirectEventBlock onShow;
@property (nonatomic, assign) BOOL visible;
@property (nonatomic, assign) BOOL allowSwipeDismissal;
// Android only
@property (nonatomic, assign) BOOL statusBarTranslucent;
@@ -35,7 +35,6 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : coder)
if ((self = [super initWithFrame:CGRectZero])) {
_bridge = bridge;
_modalViewController = [RCTModalHostViewController new];
_modalViewController.modalInPresentation = YES;
UIView *containerView = [UIView new];
containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_modalViewController.view = containerView;
@@ -51,14 +50,6 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : coder)
return self;
}
- (void)setAllowSwipeDismissal:(BOOL)allowSwipeDismissal
{
if (_allowSwipeDismissal != allowSwipeDismissal) {
_allowSwipeDismissal = allowSwipeDismissal;
_modalViewController.modalInPresentation = !allowSwipeDismissal;
}
}
- (void)notifyForBoundsChange:(CGRect)newBounds
{
if (_reactSubview && _isPresented) {
@@ -79,13 +70,6 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : coder)
}
}
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
{
if (_onRequestClose != nil && _allowSwipeDismissal) {
_onRequestClose(nil);
}
}
- (void)notifyForOrientationChange
{
if (!_onOrientationChange) {
@@ -22,6 +22,8 @@
return nil;
}
self.modalInPresentation = YES;
_preferredStatusBarStyle = [RCTUIStatusBarManager() statusBarStyle];
_preferredStatusBarHidden = [RCTUIStatusBarManager() isStatusBarHidden];
@@ -119,7 +119,6 @@ RCT_EXPORT_VIEW_PROPERTY(supportedOrientations, NSArray)
RCT_EXPORT_VIEW_PROPERTY(onOrientationChange, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(visible, BOOL)
RCT_EXPORT_VIEW_PROPERTY(onRequestClose, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(allowSwipeDismissal, BOOL)
// Fabric only
RCT_EXPORT_VIEW_PROPERTY(onDismiss, RCTDirectEventBlock)
+1 -4
View File
@@ -240,10 +240,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
if (label) {
return label;
}
if (self.isAccessibilityElement) {
return RCTRecursiveAccessibilityLabel(self);
}
return nil;
return RCTRecursiveAccessibilityLabel(self);
}
- (NSArray<UIAccessibilityCustomAction *> *)accessibilityCustomActions
@@ -148,29 +148,29 @@ public class com/facebook/react/ReactDelegate {
public fun <init> (Landroid/app/Activity;Lcom/facebook/react/ReactNativeHost;Ljava/lang/String;Landroid/os/Bundle;)V
public fun <init> (Landroid/app/Activity;Lcom/facebook/react/ReactNativeHost;Ljava/lang/String;Landroid/os/Bundle;Z)V
protected fun createRootView ()Lcom/facebook/react/ReactRootView;
public final fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext;
public final fun getReactHost ()Lcom/facebook/react/ReactHost;
public final fun getReactInstanceManager ()Lcom/facebook/react/ReactInstanceManager;
public final fun getReactRootView ()Lcom/facebook/react/ReactRootView;
protected final fun isFabricEnabled ()Z
public final fun loadApp ()V
public final fun loadApp (Ljava/lang/String;)V
public final fun onActivityResult (IILandroid/content/Intent;Z)V
public final fun onBackPressed ()Z
public final fun onConfigurationChanged (Landroid/content/res/Configuration;)V
public final fun onHostDestroy ()V
public final fun onHostPause ()V
public final fun onHostResume ()V
public final fun onKeyDown (ILandroid/view/KeyEvent;)Z
public final fun onKeyLongPress (I)Z
public final fun onNewIntent (Landroid/content/Intent;)Z
public final fun onUserLeaveHint ()V
public final fun onWindowFocusChanged (Z)V
public final fun reload ()V
public final fun setReactRootView (Lcom/facebook/react/ReactRootView;)V
public final fun setReactSurface (Lcom/facebook/react/interfaces/fabric/ReactSurface;)V
public final fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z
public final fun unloadApp ()V
public fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext;
public fun getReactHost ()Lcom/facebook/react/ReactHost;
public fun getReactInstanceManager ()Lcom/facebook/react/ReactInstanceManager;
public fun getReactRootView ()Lcom/facebook/react/ReactRootView;
protected fun isFabricEnabled ()Z
public fun loadApp ()V
public fun loadApp (Ljava/lang/String;)V
public fun onActivityResult (IILandroid/content/Intent;Z)V
public fun onBackPressed ()Z
public fun onConfigurationChanged (Landroid/content/res/Configuration;)V
public fun onHostDestroy ()V
public fun onHostPause ()V
public fun onHostResume ()V
public fun onKeyDown (ILandroid/view/KeyEvent;)Z
public fun onKeyLongPress (I)Z
public fun onNewIntent (Landroid/content/Intent;)Z
public fun onUserLeaveHint ()V
public fun onWindowFocusChanged (Z)V
public fun reload ()V
public fun setReactRootView (Lcom/facebook/react/ReactRootView;)V
public fun setReactSurface (Lcom/facebook/react/interfaces/fabric/ReactSurface;)V
public fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z
public fun unloadApp ()V
}
public class com/facebook/react/ReactFragment : androidx/fragment/app/Fragment, com/facebook/react/modules/core/PermissionAwareActivity {
@@ -259,7 +259,6 @@ public class com/facebook/react/ReactInstanceManager {
public fun createViewManager (Ljava/lang/String;)Lcom/facebook/react/uimanager/ViewManager;
public fun destroy ()V
public fun detachRootView (Lcom/facebook/react/uimanager/ReactRoot;)V
public fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext;
public fun getDevSupportManager ()Lcom/facebook/react/devsupport/interfaces/DevSupportManager;
public fun getJsExecutorName ()Ljava/lang/String;
public fun getLifecycleState ()Lcom/facebook/react/common/LifecycleState;
@@ -601,14 +600,12 @@ public abstract interface class com/facebook/react/bridge/CatalystInstance : com
public abstract fun getSourceURL ()Ljava/lang/String;
public abstract fun hasNativeModule (Ljava/lang/Class;)Z
public abstract fun hasRunJSBundle ()Z
public abstract fun initialize ()V
public abstract fun invokeCallback (ILcom/facebook/react/bridge/NativeArrayInterface;)V
public abstract fun isDestroyed ()Z
public abstract fun registerSegment (ILjava/lang/String;)V
public abstract fun removeBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)V
public abstract fun runJSBundle ()V
public abstract fun setFabricUIManager (Lcom/facebook/react/bridge/UIManager;)V
public abstract fun setGlobalVariable (Ljava/lang/String;Ljava/lang/String;)V
public abstract fun setTurboModuleRegistry (Lcom/facebook/react/internal/turbomodule/core/interfaces/TurboModuleRegistry;)V
}
@@ -2375,6 +2372,24 @@ public final class com/facebook/react/fabric/FabricUIManagerProviderImpl : com/f
public fun createUIManager (Lcom/facebook/react/bridge/ReactApplicationContext;)Lcom/facebook/react/bridge/UIManager;
}
public class com/facebook/react/fabric/mounting/MountItemDispatcher {
public fun <init> (Lcom/facebook/react/fabric/mounting/MountingManager;Lcom/facebook/react/fabric/mounting/MountItemDispatcher$ItemDispatchListener;)V
public fun addMountItem (Lcom/facebook/react/fabric/mounting/mountitems/MountItem;)V
public fun addPreAllocateMountItem (Lcom/facebook/react/fabric/mounting/mountitems/MountItem;)V
public fun addViewCommandMountItem (Lcom/facebook/react/fabric/mounting/mountitems/DispatchCommandMountItem;)V
public fun dispatchMountItems (Ljava/util/Queue;)V
public fun dispatchPreMountItems (J)V
public fun getBatchedExecutionTime ()J
public fun getRunStartTime ()J
public fun tryDispatchMountItems ()V
}
public abstract interface class com/facebook/react/fabric/mounting/MountItemDispatcher$ItemDispatchListener {
public abstract fun didDispatchMountItems ()V
public abstract fun didMountItems (Ljava/util/List;)V
public abstract fun willMountItems (Ljava/util/List;)V
}
public class com/facebook/react/fabric/mounting/SurfaceMountingManager {
public static final field TAG Ljava/lang/String;
public fun <init> (ILcom/facebook/react/touch/JSResponderHandler;Lcom/facebook/react/uimanager/ViewManagerRegistry;Lcom/facebook/react/uimanager/RootViewManager;Lcom/facebook/react/fabric/mounting/MountingManager$MountItemExecutor;Lcom/facebook/react/uimanager/ThemedReactContext;)V
@@ -2433,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 <init> (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 <init> (Lcom/facebook/react/jstasks/HeadlessJsTaskConfig;)V
public fun <init> (Ljava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V
@@ -3107,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 <init> ()V
}
public abstract class com/facebook/react/runtime/JSRuntimeFactory {
public fun <init> (Lcom/facebook/jni/HybridData;)V
}
@@ -3221,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
@@ -3300,7 +3336,6 @@ public abstract class com/facebook/react/uimanager/BaseViewManager : com/faceboo
public fun getExportedCustomBubblingEventTypeConstants ()Ljava/util/Map;
public fun getExportedCustomDirectEventTypeConstants ()Ljava/util/Map;
protected fun onAfterUpdateTransaction (Landroid/view/View;)V
public fun onDropViewInstance (Landroid/view/View;)V
public fun onLayoutChange (Landroid/view/View;IIIIIIII)V
protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
public fun setAccessibilityActions (Landroid/view/View;Lcom/facebook/react/bridge/ReadableArray;)V
@@ -3659,7 +3694,6 @@ public class com/facebook/react/uimanager/ReactAccessibilityDelegate : androidx/
public static final field TOP_ACCESSIBILITY_ACTION_EVENT Ljava/lang/String;
public static final field sActionIdMap Ljava/util/HashMap;
public fun <init> (Landroid/view/View;ZI)V
public fun cleanUp ()V
public static fun createNodeInfoFromView (Landroid/view/View;)Landroidx/core/view/accessibility/AccessibilityNodeInfoCompat;
public fun getAccessibilityNodeProvider (Landroid/view/View;)Landroidx/core/view/accessibility/AccessibilityNodeProviderCompat;
protected fun getHostView ()Landroid/view/View;
@@ -4340,20 +4374,20 @@ public abstract interface class com/facebook/react/uimanager/UIImplementation$La
public abstract fun onLayoutUpdated (Lcom/facebook/react/uimanager/ReactShadowNode;)V
}
public final class com/facebook/react/uimanager/UIManagerHelper {
public static final field INSTANCE Lcom/facebook/react/uimanager/UIManagerHelper;
public class com/facebook/react/uimanager/UIManagerHelper {
public static final field PADDING_BOTTOM_INDEX I
public static final field PADDING_END_INDEX I
public static final field PADDING_START_INDEX I
public static final field PADDING_TOP_INDEX I
public static final fun getDefaultTextInputPadding (Landroid/content/Context;)[F
public static final fun getEventDispatcher (Lcom/facebook/react/bridge/ReactContext;I)Lcom/facebook/react/uimanager/events/EventDispatcher;
public static final fun getEventDispatcherForReactTag (Lcom/facebook/react/bridge/ReactContext;I)Lcom/facebook/react/uimanager/events/EventDispatcher;
public static final fun getReactContext (Landroid/view/View;)Lcom/facebook/react/bridge/ReactContext;
public static final fun getSurfaceId (Landroid/content/Context;)I
public static final fun getSurfaceId (Landroid/view/View;)I
public static final fun getUIManager (Lcom/facebook/react/bridge/ReactContext;I)Lcom/facebook/react/bridge/UIManager;
public static final fun getUIManagerForReactTag (Lcom/facebook/react/bridge/ReactContext;I)Lcom/facebook/react/bridge/UIManager;
public fun <init> ()V
public static fun getDefaultTextInputPadding (Landroid/content/Context;)[F
public static fun getEventDispatcher (Lcom/facebook/react/bridge/ReactContext;I)Lcom/facebook/react/uimanager/events/EventDispatcher;
public static fun getEventDispatcherForReactTag (Lcom/facebook/react/bridge/ReactContext;I)Lcom/facebook/react/uimanager/events/EventDispatcher;
public static fun getReactContext (Landroid/view/View;)Lcom/facebook/react/bridge/ReactContext;
public static fun getSurfaceId (Landroid/content/Context;)I
public static fun getSurfaceId (Landroid/view/View;)I
public static fun getUIManager (Lcom/facebook/react/bridge/ReactContext;I)Lcom/facebook/react/bridge/UIManager;
public static fun getUIManagerForReactTag (Lcom/facebook/react/bridge/ReactContext;I)Lcom/facebook/react/bridge/UIManager;
}
public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/bridge/ReactContextBaseJavaModule, com/facebook/react/bridge/LifecycleEventListener, com/facebook/react/bridge/OnBatchCompleteListener, com/facebook/react/bridge/UIManager {
@@ -4867,6 +4901,20 @@ public abstract interface class com/facebook/react/uimanager/events/EventDispatc
public abstract fun removeListener (Lcom/facebook/react/uimanager/events/EventDispatcherListener;)V
}
public class com/facebook/react/uimanager/events/EventDispatcherImpl : com/facebook/react/bridge/LifecycleEventListener, com/facebook/react/uimanager/events/EventDispatcher {
public fun <init> (Lcom/facebook/react/bridge/ReactApplicationContext;)V
public fun addBatchEventDispatchedListener (Lcom/facebook/react/uimanager/events/BatchEventDispatchedListener;)V
public fun addListener (Lcom/facebook/react/uimanager/events/EventDispatcherListener;)V
public fun dispatchAllEvents ()V
public fun dispatchEvent (Lcom/facebook/react/uimanager/events/Event;)V
public fun onCatalystInstanceDestroyed ()V
public fun onHostDestroy ()V
public fun onHostPause ()V
public fun onHostResume ()V
public fun removeBatchEventDispatchedListener (Lcom/facebook/react/uimanager/events/BatchEventDispatchedListener;)V
public fun removeListener (Lcom/facebook/react/uimanager/events/EventDispatcherListener;)V
}
public abstract interface class com/facebook/react/uimanager/events/EventDispatcherListener {
public abstract fun onEventDispatch (Lcom/facebook/react/uimanager/events/Event;)V
}
@@ -4877,6 +4925,32 @@ public final class com/facebook/react/uimanager/events/NativeGestureUtil {
public static final fun notifyNativeGestureStarted (Landroid/view/View;Landroid/view/MotionEvent;)V
}
public class com/facebook/react/uimanager/events/PointerEvent : com/facebook/react/uimanager/events/Event {
public fun dispatch (Lcom/facebook/react/uimanager/events/RCTEventEmitter;)V
public fun dispatchModern (Lcom/facebook/react/uimanager/events/RCTModernEventEmitter;)V
public fun getCoalescingKey ()S
public fun getEventAnimationDriverMatchSpec ()Lcom/facebook/react/uimanager/events/Event$EventAnimationDriverMatchSpec;
public fun getEventName ()Ljava/lang/String;
public static fun obtain (Ljava/lang/String;ILcom/facebook/react/uimanager/events/PointerEvent$PointerEventState;Landroid/view/MotionEvent;)Lcom/facebook/react/uimanager/events/PointerEvent;
public static fun obtain (Ljava/lang/String;ILcom/facebook/react/uimanager/events/PointerEvent$PointerEventState;Landroid/view/MotionEvent;S)Lcom/facebook/react/uimanager/events/PointerEvent;
public fun onDispose ()V
}
public class com/facebook/react/uimanager/events/PointerEvent$PointerEventState {
public fun <init> (IIIILjava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Set;)V
public fun getActivePointerId ()I
public final fun getEventCoordinatesByPointerId ()Ljava/util/Map;
public final fun getHitPathByPointerId ()Ljava/util/Map;
public final fun getHitPathForActivePointer ()Ljava/util/List;
public fun getHoveringPointerIds ()Ljava/util/Set;
public fun getLastButtonState ()I
public final fun getOffsetByPointerId ()Ljava/util/Map;
public fun getPrimaryPointerId ()I
public final fun getScreenCoordinatesByPointerId ()Ljava/util/Map;
public fun getSurfaceId ()I
public fun supportsHover (I)Z
}
public abstract interface class com/facebook/react/uimanager/events/RCTEventEmitter : com/facebook/react/bridge/JavaScriptModule {
public abstract fun receiveEvent (ILjava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V
public abstract fun receiveTouches (Ljava/lang/String;Lcom/facebook/react/bridge/WritableArray;Lcom/facebook/react/bridge/WritableArray;)V
@@ -5253,7 +5327,6 @@ public class com/facebook/react/viewmanagers/ModalHostViewManagerDelegate : com/
}
public abstract interface class com/facebook/react/viewmanagers/ModalHostViewManagerInterface : com/facebook/react/uimanager/ViewManagerWithGeneratedInterface {
public abstract fun setAllowSwipeDismissal (Landroid/view/View;Z)V
public abstract fun setAnimated (Landroid/view/View;Z)V
public abstract fun setAnimationType (Landroid/view/View;Ljava/lang/String;)V
public abstract fun setHardwareAccelerated (Landroid/view/View;Z)V
@@ -5283,16 +5356,6 @@ public abstract interface class com/facebook/react/viewmanagers/UnimplementedNat
public abstract fun setName (Landroid/view/View;Ljava/lang/String;)V
}
public class com/facebook/react/viewmanagers/VirtualViewManagerDelegate : com/facebook/react/uimanager/BaseViewManagerDelegate {
public fun <init> (Lcom/facebook/react/uimanager/BaseViewManager;)V
public fun setProperty (Landroid/view/View;Ljava/lang/String;Ljava/lang/Object;)V
}
public abstract interface class com/facebook/react/viewmanagers/VirtualViewManagerInterface : com/facebook/react/uimanager/ViewManagerWithGeneratedInterface {
public abstract fun setInitialHidden (Landroid/view/View;Z)V
public abstract fun setRenderState (Landroid/view/View;I)V
}
public final class com/facebook/react/views/drawer/ReactDrawerLayout : androidx/drawerlayout/widget/DrawerLayout {
public fun <init> (Lcom/facebook/react/bridge/ReactContext;)V
public fun onInterceptTouchEvent (Landroid/view/MotionEvent;)Z
@@ -6120,17 +6183,16 @@ public final class com/facebook/react/views/text/ReactFontManager$Companion {
public final fun getInstance ()Lcom/facebook/react/views/text/ReactFontManager;
}
public final class com/facebook/react/views/text/ReactTextShadowNode : com/facebook/react/views/text/ReactBaseTextShadowNode {
public class com/facebook/react/views/text/ReactTextShadowNode : com/facebook/react/views/text/ReactBaseTextShadowNode {
public fun <init> ()V
public fun <init> (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)V
public synthetic fun <init> (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun calculateLayoutOnChildren ()Ljava/lang/Iterable;
public fun hoistNativeChildren ()Z
public fun isVirtualAnchor ()Z
public fun markUpdated ()V
public fun onBeforeLayout (Lcom/facebook/react/uimanager/NativeViewHierarchyOptimizer;)V
public fun onCollectExtraUpdates (Lcom/facebook/react/uimanager/UIViewOperationQueue;)V
public final fun setShouldNotifyOnTextLayout (Z)V
public fun setShouldNotifyOnTextLayout (Z)V
}
public final class com/facebook/react/views/text/ReactTextUpdate {

Some files were not shown because too many files have changed in this diff Show More