diff --git a/.github/actions/build-android/action.yml b/.github/actions/build-android/action.yml index 4f32483d975a65..b18e605c8eb90d 100644 --- a/.github/actions/build-android/action.yml +++ b/.github/actions/build-android/action.yml @@ -20,8 +20,6 @@ runs: - name: Set React Native Version shell: bash run: node ./scripts/releases/set-rn-artifacts-version.js --build-type ${{ inputs.release-type }} - # We don't want to re-set the artifacts version if we're on the release branch. - if: ${{ !contains(github.ref, '-stable') }} - name: Setup gradle uses: ./.github/actions/setup-gradle with: diff --git a/.github/workflow-scripts/publishTemplate.js b/.github/workflow-scripts/publishTemplate.js index b0c8946b6793df..da22f90d1eac26 100644 --- a/.github/workflow-scripts/publishTemplate.js +++ b/.github/workflow-scripts/publishTemplate.js @@ -68,6 +68,10 @@ module.exports.verifyPublishedTemplate = async ( latest = false, retries = MAX_RETRIES, ) => { + if (version.startsWith('v')) { + version = version.slice(1); + } + log(`🔍 Is ${TEMPLATE_NPM_PKG}@${version} on npm?`); let count = retries; @@ -86,7 +90,7 @@ module.exports.verifyPublishedTemplate = async ( return; } log( - `🐌 ${TEMPLATE_NPM_PKG}@latest → ${pkg.version} on npm and not ${version} as expected, retrying...`, + `🐌 ${TEMPLATE_NPM_PKG}@latest → ${json.version} on npm and not ${version} as expected, retrying...`, ); } catch (e) { log(`Nope, fetch failed: ${e.message}`); diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index fe6de2c89c6400..a2a77530c9db10 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -157,7 +157,7 @@ jobs: react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} test_ios_rntester: - runs-on: macos-13 + runs-on: macos-13-large needs: [build_apple_slices_hermes, prepare_hermes_workspace, build_hermes_macos] env: @@ -369,6 +369,11 @@ jobs: sed -i 's/newArchEnabled=true/newArchEnabled=false/' android/gradle.properties fi + if [[ ${{matrix.jsengine}} == "JSC" ]]; then + echo "Using JSC instead of Hermes" + sed -i 's/hermesEnabled=true/hermesEnabled=false/' android/gradle.properties + fi + # Build cd android CAPITALIZED_FLAVOR=$(echo "${{ matrix.flavor }}" | awk '{print toupper(substr($0, 1, 1)) substr($0, 2)}') diff --git a/Gemfile b/Gemfile index ec2e5c6b0f130f..4dd36df9782cad 100644 --- a/Gemfile +++ b/Gemfile @@ -6,3 +6,4 @@ ruby ">= 2.6.10" gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1' gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' gem 'xcodeproj', '< 1.26.0' +gem 'concurrent-ruby', '< 1.3.4' diff --git a/build.gradle.kts b/build.gradle.kts index d848efee0ab69c..567cbcfa592b3d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { alias(libs.plugins.nexus.publish) - alias(libs.plugins.android.library) apply false + id(libs.plugins.android.library.get().pluginId) version libs.plugins.android.library.get().version.requiredVersion apply false alias(libs.plugins.android.application) apply false alias(libs.plugins.download) apply false alias(libs.plugins.kotlin.android) apply false diff --git a/discord/bump_version.py b/discord/bump_version.py new file mode 100755 index 00000000000000..fb41c7bc277276 --- /dev/null +++ b/discord/bump_version.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 + +from pathlib import Path +from typing import List +import re +import subprocess +import sys + + +def check_output(args: List[str]) -> str: + return subprocess.check_output(args).decode('utf-8').strip() + + +VERSION_MATCHER = re.compile(r'^(.*)-discord-(\d*)$') + +status = check_output(['git', 'status', '--porcelain']) +if status != '': + print('Detected changed files, please remove or commit them first.\n') + print(status) + sys.exit(1) + + +root = check_output(['git', 'rev-parse', '--show-toplevel']) +android_path = Path(root) / "ReactAndroid" +props_path = android_path / "gradle.properties" + +version = None +property_lines = [line.strip() for line in props_path.read_text().splitlines()] +for line in property_lines: + if line.startswith("VERSION_NAME="): + version = line.split('=')[1] + +assert version, "unable to find current version" + +matches = VERSION_MATCHER.match(version) +assert matches, f'{version} did not match expected format, X.Y.Z-discord-N' + +upstream = matches[1] +local = int(matches[2]) + +new_version = f'{upstream}-discord-{local + 1}' + +with open(props_path, 'w') as f: + for line in property_lines: + if line.startswith("VERSION_NAME="): + f.write(f'VERSION_NAME={new_version}\n') + else: + f.write(f'{line}\n') + + +branch_name = check_output(['git', 'symbolic-ref', '--short', 'HEAD']) + +subprocess.check_call( + ['../gradlew', 'publishReleasePublicationToDiscordRepository'], + cwd=android_path.absolute() + ) + +subprocess.check_call(['git', 'add', props_path.absolute()]) +subprocess.check_call(['git', 'commit', '-m', f'version bump: {new_version}']) +subprocess.check_call(['git', 'push', 'origin', branch_name]) + +new_commit = check_output(['git', 'rev-parse', 'HEAD']) + + +print(f'NEW TAGGED VERSION: {new_version}') +print(f'NEW COMMIT: {new_commit}') diff --git a/package.json b/package.json index 142e0a21932271..7db61c111711bf 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,8 @@ "@babel/preset-flow": "^7.24.7", "@definitelytyped/dtslint": "^0.0.127", "@jest/create-cache-key-function": "^29.6.3", - "@react-native/metro-babel-transformer": "0.77.0-main", - "@react-native/metro-config": "0.77.0-main", + "@react-native/metro-babel-transformer": "0.78.2", + "@react-native/metro-config": "0.78.2", "@tsconfig/node18": "1.0.1", "@types/react": "^19.0.0", "@typescript-eslint/parser": "^7.1.1", @@ -87,9 +87,9 @@ "jest-junit": "^10.0.0", "jest-snapshot": "^29.7.0", "jscodeshift": "^0.14.0", - "metro-babel-register": "^0.81.0", - "metro-memory-fs": "^0.81.0", - "metro-transform-plugins": "^0.81.0", + "metro-babel-register": "^0.81.3", + "metro-memory-fs": "^0.81.3", + "metro-transform-plugins": "^0.81.3", "micromatch": "^4.0.4", "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", diff --git a/packages/assets/package.json b/packages/assets/package.json index 07f15969ba657f..5e5135b0660ffa 100644 --- a/packages/assets/package.json +++ b/packages/assets/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/assets-registry", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Asset support code for React Native.", "license": "MIT", "repository": { diff --git a/packages/babel-plugin-codegen/package.json b/packages/babel-plugin-codegen/package.json index 98924cb4aae7c5..9d77de73f305a1 100644 --- a/packages/babel-plugin-codegen/package.json +++ b/packages/babel-plugin-codegen/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/babel-plugin-codegen", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Babel plugin to generate native module and view manager code for React Native.", "license": "MIT", "repository": { @@ -26,7 +26,7 @@ ], "dependencies": { "@babel/traverse": "^7.25.3", - "@react-native/codegen": "0.77.0-main" + "@react-native/codegen": "0.78.2" }, "devDependencies": { "@babel/core": "^7.25.2" diff --git a/packages/community-cli-plugin/README.md b/packages/community-cli-plugin/README.md index 12fcffb9c026ff..dc4c687208c341 100644 --- a/packages/community-cli-plugin/README.md +++ b/packages/community-cli-plugin/README.md @@ -15,7 +15,7 @@ Start the React Native development server. #### Usage ```sh -npx react-native start [options] +npx @react-native-community/cli start [options] ``` #### Options @@ -37,6 +37,7 @@ npx react-native start [options] | `--cert ` | Specify path to a custom SSL cert. | | `--config ` | Path to the CLI configuration file. | | `--no-interactive` | Disable interactive mode. | +| `--client-logs` | **[Deprecated]** Enable plain text JavaScript log streaming for all connected apps. | ### `bundle` @@ -45,7 +46,7 @@ Build the bundle for the provided JavaScript entry file. #### Usage ```sh -npx react-native bundle --entry-file [options] +npx @react-native-community/cli bundle --entry-file [options] ``` #### Options diff --git a/packages/community-cli-plugin/package.json b/packages/community-cli-plugin/package.json index f1daf525ec572e..fc797310131e53 100644 --- a/packages/community-cli-plugin/package.json +++ b/packages/community-cli-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/community-cli-plugin", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Core CLI commands for React Native", "keywords": [ "react-native", @@ -22,25 +22,25 @@ "dist" ], "dependencies": { - "@react-native/dev-middleware": "0.77.0-main", - "@react-native/metro-babel-transformer": "0.77.0-main", + "@react-native/dev-middleware": "0.78.2", + "@react-native/metro-babel-transformer": "0.78.2", "chalk": "^4.0.0", "debug": "^2.2.0", "invariant": "^2.2.4", - "metro": "^0.81.0", - "metro-config": "^0.81.0", - "metro-core": "^0.81.0", + "metro": "^0.81.3", + "metro-config": "^0.81.3", + "metro-core": "^0.81.3", "readline": "^1.3.0", "semver": "^7.1.3" }, "devDependencies": { - "metro-resolver": "^0.81.0" + "metro-resolver": "^0.81.3" }, "peerDependencies": { - "@react-native-community/cli-server-api": "*" + "@react-native-community/cli": "*" }, "peerDependenciesMeta": { - "@react-native-community/cli-server-api": { + "@react-native-community/cli": { "optional": true } }, diff --git a/packages/community-cli-plugin/src/commands/start/index.js b/packages/community-cli-plugin/src/commands/start/index.js index cd438b2115fe67..7b5ba161dd3c8f 100644 --- a/packages/community-cli-plugin/src/commands/start/index.js +++ b/packages/community-cli-plugin/src/commands/start/index.js @@ -95,6 +95,14 @@ const startCommand: Command = { name: '--no-interactive', description: 'Disables interactive mode', }, + { + name: '--client-logs', + description: + '[Deprecated] Enable plain text JavaScript log streaming for all ' + + 'connected apps. This feature is deprecated and will be removed in ' + + 'future.', + default: false, + }, ], }; diff --git a/packages/community-cli-plugin/src/commands/start/middleware.js b/packages/community-cli-plugin/src/commands/start/middleware.js index db6b46bad276a6..611dfbe3fd7b6f 100644 --- a/packages/community-cli-plugin/src/commands/start/middleware.js +++ b/packages/community-cli-plugin/src/commands/start/middleware.js @@ -9,7 +9,8 @@ * @oncall react_native */ -import type {NextHandleFunction, Server} from 'connect'; +import typeof * as CLIServerAPI from '@react-native-community/cli-server-api'; +import type {Server} from 'connect'; import type {TerminalReportableEvent} from 'metro/src/lib/TerminalReporter'; const debug = require('debug')('ReactNative:CommunityCliPlugin'); @@ -30,10 +31,6 @@ type MiddlewareReturn = { ... }; -const noopNextHandle: NextHandleFunction = (req, res, next) => { - next(); -}; - // $FlowFixMe const unusedStubWSServer: ws$WebSocketServer = {}; // $FlowFixMe @@ -45,6 +42,12 @@ const communityMiddlewareFallback = { port: number, watchFolders: $ReadOnlyArray, }): MiddlewareReturn => ({ + // FIXME: Several features will break without community middleware and + // should be migrated into core. + // e.g. used by Libraries/Core/Devtools: + // - /open-stack-frame + // - /open-url + // - /symbolicate middleware: unusedMiddlewareStub, websocketEndpoints: {}, messageSocketEndpoint: { @@ -59,17 +62,30 @@ const communityMiddlewareFallback = { reportEvent: (event: TerminalReportableEvent) => {}, }, }), - indexPageMiddleware: noopNextHandle, }; // Attempt to use the community middleware if it exists, but fallback to // the stubs if it doesn't. try { - const community = require('@react-native-community/cli-server-api'); - communityMiddlewareFallback.indexPageMiddleware = - community.indexPageMiddleware; + // `@react-native-community/cli` is an optional peer dependency of this + // package, and should be a dev dependency of the host project (via the + // community template's package.json). + const communityCliPath = require.resolve('@react-native-community/cli'); + + // `@react-native-community/cli-server-api` is a dependency of + // `@react-native-community/cli`, but is not re-exported by it, so we need + // to resolve the former through the latter. + const communityCliServerApiPath = require.resolve( + '@react-native-community/cli-server-api', + {paths: [communityCliPath]}, + ); + // $FlowIgnore[unsupported-syntax] dynamic import + const communityCliServerApi: CLIServerAPI = require( + communityCliServerApiPath, + ); + // $FlowIgnore[unsupported-syntax] dynamic import communityMiddlewareFallback.createDevServerMiddleware = - community.createDevServerMiddleware; + communityCliServerApi.createDevServerMiddleware; } catch { debug(`⚠️ Unable to find @react-native-community/cli-server-api Starting the server without the community middleware.`); @@ -77,5 +93,3 @@ Starting the server without the community middleware.`); export const createDevServerMiddleware = communityMiddlewareFallback.createDevServerMiddleware; -export const indexPageMiddleware = - communityMiddlewareFallback.indexPageMiddleware; diff --git a/packages/community-cli-plugin/src/commands/start/runServer.js b/packages/community-cli-plugin/src/commands/start/runServer.js index ce4f7bcd9dead4..d4a8636ac45db9 100644 --- a/packages/community-cli-plugin/src/commands/start/runServer.js +++ b/packages/community-cli-plugin/src/commands/start/runServer.js @@ -19,7 +19,7 @@ import isDevServerRunning from '../../utils/isDevServerRunning'; import loadMetroConfig from '../../utils/loadMetroConfig'; import * as version from '../../utils/version'; import attachKeyHandlers from './attachKeyHandlers'; -import {createDevServerMiddleware, indexPageMiddleware} from './middleware'; +import {createDevServerMiddleware} from './middleware'; import {createDevMiddleware} from '@react-native/dev-middleware'; import chalk from 'chalk'; import Metro from 'metro'; @@ -44,6 +44,7 @@ export type StartCommandArgs = { config?: string, projectRoot?: string, interactive: boolean, + clientLogs: boolean, }; async function runServer( @@ -96,6 +97,11 @@ async function runServer( require.resolve(plugin), ); } + // TODO(T214991636): Remove legacy Metro log forwarding + if (!args.clientLogs) { + // $FlowIgnore[cannot-write] Assigning to readonly property + metroConfig.server.forwardClientLogs = false; + } let reportEvent: (event: TerminalReportableEvent) => void; const terminal = new Terminal(process.stdout); @@ -146,11 +152,7 @@ async function runServer( secure: args.https, secureCert: args.cert, secureKey: args.key, - unstable_extraMiddleware: [ - communityMiddleware, - indexPageMiddleware, - middleware, - ], + unstable_extraMiddleware: [communityMiddleware, middleware], websocketEndpoints: { ...communityWebsocketEndpoints, ...websocketEndpoints, diff --git a/packages/core-cli-utils/package.json b/packages/core-cli-utils/package.json index 99f098a80e8e04..1ecbb0a32b8f3d 100644 --- a/packages/core-cli-utils/package.json +++ b/packages/core-cli-utils/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/core-cli-utils", - "version": "0.77.0-main", + "version": "0.78.2", "description": "React Native CLI library for Frameworks to build on", "license": "MIT", "main": "./src/index.flow.js", diff --git a/packages/debugger-frontend/package.json b/packages/debugger-frontend/package.json index 03ca64cf90e151..3609e1eb6d57f7 100644 --- a/packages/debugger-frontend/package.json +++ b/packages/debugger-frontend/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/debugger-frontend", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Debugger frontend for React Native based on Chrome DevTools", "keywords": [ "react-native", diff --git a/packages/dev-middleware/package.json b/packages/dev-middleware/package.json index 3dfde88432fe5b..22926156f091b1 100644 --- a/packages/dev-middleware/package.json +++ b/packages/dev-middleware/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/dev-middleware", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Dev server middleware for React Native", "keywords": [ "react-native", @@ -23,11 +23,12 @@ ], "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.77.0-main", + "@react-native/debugger-frontend": "0.78.2", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^2.2.0", + "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "selfsigned": "^2.4.1", diff --git a/packages/dev-middleware/src/createDevMiddleware.js b/packages/dev-middleware/src/createDevMiddleware.js index b74d8f30b51430..8ec17f75743e95 100644 --- a/packages/dev-middleware/src/createDevMiddleware.js +++ b/packages/dev-middleware/src/createDevMiddleware.js @@ -150,6 +150,17 @@ function createWrappedEventReporter( `Profiling build target "${event.appId}" registered for debugging`, ); break; + case 'fusebox_console_notice': + logger?.info( + '\n' + + '\u001B[7m' + + ' \u001B[1m💡 JavaScript logs have moved!\u001B[22m They can now be ' + + 'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' + + 'the terminal to open (requires Google Chrome or Microsoft Edge).' + + '\u001B[27m' + + '\n', + ); + break; } reporter?.logEvent(event); diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index 69bf668c06cfac..b935da37b554f1 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -41,6 +41,8 @@ const PAGES_POLLING_INTERVAL = 1000; // more details. const FILE_PREFIX = 'file://'; +let fuseboxConsoleNoticeLogged = false; + type DebuggerConnection = { // Debugger web socket connection socket: WS, @@ -519,6 +521,7 @@ export default class Device { // created instead of manually checking this on every getPages result. for (const page of this.#pages.values()) { if (this.#pageHasCapability(page, 'nativePageReloads')) { + this.#logFuseboxConsoleNotice(); continue; } @@ -1073,4 +1076,14 @@ export default class Device { dangerouslyGetSocket(): WS { return this.#deviceSocket; } + + // TODO(T214991636): Remove notice + #logFuseboxConsoleNotice() { + if (fuseboxConsoleNoticeLogged) { + return; + } + + this.#deviceEventReporter?.logFuseboxConsoleNotice(); + fuseboxConsoleNoticeLogged = true; + } } diff --git a/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js b/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js index 048d0efb56c41f..1d467ce6a1da41 100644 --- a/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js +++ b/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js @@ -223,6 +223,12 @@ class DeviceEventReporter { }); } + logFuseboxConsoleNotice(): void { + this.#eventReporter.logEvent({ + type: 'fusebox_console_notice', + }); + } + #logExpiredCommand(pendingCommand: PendingCommand): void { this.#eventReporter.logEvent({ type: 'debugger_command', diff --git a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js index e37d348f6e3773..37498da570da7e 100644 --- a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js +++ b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js @@ -39,7 +39,7 @@ const WS_DEBUGGER_URL = '/inspector/debug'; const PAGES_LIST_JSON_URL = '/json'; const PAGES_LIST_JSON_URL_2 = '/json/list'; const PAGES_LIST_JSON_VERSION_URL = '/json/version'; -const MAX_PONG_LATENCY_MS = 5000; +const MAX_PONG_LATENCY_MS = 60000; const DEBUGGER_HEARTBEAT_INTERVAL_MS = 10000; const INTERNAL_ERROR_CODE = 1011; diff --git a/packages/dev-middleware/src/types/EventReporter.js b/packages/dev-middleware/src/types/EventReporter.js index 56942f5c569676..1564f3381471c9 100644 --- a/packages/dev-middleware/src/types/EventReporter.js +++ b/packages/dev-middleware/src/types/EventReporter.js @@ -82,6 +82,9 @@ export type ReportableEvent = status: 'success', ...DebuggerSessionIDs, } + | { + type: 'fusebox_console_notice', + } | { type: 'proxy_error', status: 'error', diff --git a/packages/eslint-config-react-native/package.json b/packages/eslint-config-react-native/package.json index a1aee9ed4437d2..90d997c329be48 100644 --- a/packages/eslint-config-react-native/package.json +++ b/packages/eslint-config-react-native/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/eslint-config", - "version": "0.77.0-main", + "version": "0.78.2", "description": "ESLint config for React Native", "license": "MIT", "repository": { @@ -22,7 +22,7 @@ "dependencies": { "@babel/core": "^7.25.2", "@babel/eslint-parser": "^7.25.1", - "@react-native/eslint-plugin": "0.77.0-main", + "@react-native/eslint-plugin": "0.78.2", "@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/parser": "^7.1.1", "eslint-config-prettier": "^8.5.0", diff --git a/packages/eslint-plugin-react-native/package.json b/packages/eslint-plugin-react-native/package.json index 82151c1f614e0c..05fc56ef7a5f49 100644 --- a/packages/eslint-plugin-react-native/package.json +++ b/packages/eslint-plugin-react-native/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/eslint-plugin", - "version": "0.77.0-main", + "version": "0.78.2", "description": "ESLint rules for @react-native/eslint-config", "license": "MIT", "repository": { diff --git a/packages/eslint-plugin-specs/package.json b/packages/eslint-plugin-specs/package.json index ca94060a48eec1..f5a2254cb7d408 100644 --- a/packages/eslint-plugin-specs/package.json +++ b/packages/eslint-plugin-specs/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/eslint-plugin-specs", - "version": "0.77.0-main", + "version": "0.78.2", "description": "ESLint rules to validate NativeModule and Component Specs", "license": "MIT", "repository": { @@ -26,7 +26,7 @@ "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-transform-flow-strip-types": "^7.25.2", - "@react-native/codegen": "0.77.0-main", + "@react-native/codegen": "0.78.2", "make-dir": "^2.1.0", "pirates": "^4.0.1", "source-map-support": "0.5.0" diff --git a/packages/gradle-plugin/package.json b/packages/gradle-plugin/package.json index a3d8c09a64498c..2aa91e7b18ba6b 100644 --- a/packages/gradle-plugin/package.json +++ b/packages/gradle-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/gradle-plugin", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Gradle Plugin for React Native", "license": "MIT", "repository": { diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt index e3da9e4aa448b3..3abec5c2435a41 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt @@ -33,7 +33,9 @@ abstract class PrepareBoostTask : DefaultTask() { it.from(project.file("src/main/jni/third-party/boost")) it.include( "CMakeLists.txt", + "boost_${boostVersion.get()}/boost/**/*.h", "boost_${boostVersion.get()}/boost/**/*.hpp", + "boost/boost/**/*.h", "boost/boost/**/*.hpp", "asm/**/*.S") it.includeEmptyDirs = false diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt index f30392dd3ebc1c..08b3562bcad549 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt @@ -70,6 +70,19 @@ abstract class PreparePrefabHeadersTask : DefaultTask() { it.include("boost/cstdint.hpp") it.include("boost/utility.hpp") it.include("boost/version.hpp") + // Extra files for kv-storage + it.include("boost/*.hpp") + it.include("boost/align/**/*.hpp") + it.include("boost/container/**/*.hpp") + it.include("boost/intrusive/**/*.hpp") + it.include("boost/iterator/**/*.hpp") + it.include("boost/lockfree/**/*.hpp") + it.include("boost/move/**/*.hpp") + it.include("boost/mp11/**/*.hpp") + it.include("boost/mpl/**/*.hpp") + it.include("boost/parameter/**/*.hpp") + it.include("boost/type_traits/**/*.hpp") + it.include("boost/utility/**/*.hpp") it.into(File(outputFolder.asFile, headerPrefix)) } } diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt index 80248e4657ba39..e81ed851a81af5 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt @@ -11,7 +11,6 @@ import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.api.variant.Variant import com.facebook.react.ReactExtension import com.facebook.react.utils.ProjectUtils.getReactNativeArchitectures -import com.facebook.react.utils.ProjectUtils.isNewArchEnabled import java.io.File import org.gradle.api.Project @@ -20,10 +19,6 @@ internal object NdkConfiguratorUtils { fun configureReactNativeNdk(project: Project, extension: ReactExtension) { project.pluginManager.withPlugin("com.android.application") { project.extensions.getByType(AndroidComponentsExtension::class.java).finalizeDsl { ext -> - if (!project.isNewArchEnabled(extension)) { - // For Old Arch, we don't need to setup the NDK - return@finalizeDsl - } // We enable prefab so users can consume .so/headers from ReactAndroid and hermes-engine // .aar ext.buildFeatures.prefab = true @@ -72,20 +67,12 @@ internal object NdkConfiguratorUtils { * sure we specify the correct .pickFirsts for all the .so files we are producing or that we're * aware of as some of our dependencies are pulling them in. */ + @Suppress("UNUSED_PARAMETER") fun configureNewArchPackagingOptions( project: Project, extension: ReactExtension, variant: Variant ) { - if (!project.isNewArchEnabled(extension)) { - // For Old Arch, we set a pickFirst only on libraries that we know are - // clashing with our direct dependencies (mainly FBJNI and Hermes). - variant.packaging.jniLibs.pickFirsts.addAll( - listOf( - "**/libfbjni.so", - "**/libc++_shared.so", - )) - } else { // We set some packagingOptions { pickFirst ... } for our users for libraries we own. variant.packaging.jniLibs.pickFirsts.addAll( listOf( @@ -99,7 +86,6 @@ internal object NdkConfiguratorUtils { // AGP will give priority of libc++_shared coming from App modules. "**/libc++_shared.so", )) - } } /** diff --git a/packages/helloworld/Gemfile b/packages/helloworld/Gemfile index a8af404e61ae85..1036ed276bed1c 100644 --- a/packages/helloworld/Gemfile +++ b/packages/helloworld/Gemfile @@ -5,3 +5,4 @@ ruby ">= 2.6.10" gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1' gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' gem 'xcodeproj', '< 1.26.0' +gem 'concurrent-ruby', '< 1.3.4' diff --git a/packages/helloworld/package.json b/packages/helloworld/package.json index e83ee292686332..d4c4b62ef86a5c 100644 --- a/packages/helloworld/package.json +++ b/packages/helloworld/package.json @@ -1,6 +1,6 @@ { "name": "helloworld", - "version": "0.77.0-main", + "version": "0.78.2", "private": true, "scripts": { "bootstrap": "node ./cli.js bootstrap", @@ -13,16 +13,16 @@ }, "dependencies": { "react": "19.0.0", - "react-native": "1000.0.0" + "react-native": "0.78.2" }, "devDependencies": { "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.3", "@babel/runtime": "^7.25.0", - "@react-native/babel-preset": "0.77.0-main", - "@react-native/core-cli-utils": "0.77.0-main", - "@react-native/eslint-config": "0.77.0-main", - "@react-native/metro-config": "0.77.0-main", + "@react-native/babel-preset": "0.78.2", + "@react-native/core-cli-utils": "0.78.2", + "@react-native/eslint-config": "0.78.2", + "@react-native/metro-config": "0.78.2", "chalk": "^4.1.2", "commander": "^12.0.0", "eslint": "^8.19.0", diff --git a/packages/metro-config/package.json b/packages/metro-config/package.json index 875347ef99a9ab..662b3b7a0583a5 100644 --- a/packages/metro-config/package.json +++ b/packages/metro-config/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/metro-config", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Metro configuration for React Native.", "license": "MIT", "repository": { @@ -26,9 +26,9 @@ "dist" ], "dependencies": { - "@react-native/js-polyfills": "0.77.0-main", - "@react-native/metro-babel-transformer": "0.77.0-main", - "metro-config": "^0.81.0", - "metro-runtime": "^0.81.0" + "@react-native/js-polyfills": "0.78.2", + "@react-native/metro-babel-transformer": "0.78.2", + "metro-config": "^0.81.3", + "metro-runtime": "^0.81.3" } } diff --git a/packages/metro-config/src/index.flow.js b/packages/metro-config/src/index.flow.js index 452f6b7e02aab6..5af84c787467d2 100644 --- a/packages/metro-config/src/index.flow.js +++ b/packages/metro-config/src/index.flow.js @@ -54,7 +54,7 @@ export function getDefaultConfig(projectRoot: string): ConfigT { resolver: { resolverMainFields: ['react-native', 'browser', 'main'], platforms: ['android', 'ios'], - unstable_conditionNames: ['require', 'import', 'react-native'], + unstable_conditionNames: ['react-native'], }, serializer: { // Note: This option is overridden in cli-plugin-metro (getOverrideConfig) diff --git a/packages/normalize-color/package.json b/packages/normalize-color/package.json index 5db370d8b5c361..2d645d54b779a9 100644 --- a/packages/normalize-color/package.json +++ b/packages/normalize-color/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/normalize-colors", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Color normalization for React Native.", "license": "MIT", "repository": { diff --git a/packages/polyfills/package.json b/packages/polyfills/package.json index b80037150fdbfd..2ad16684227b47 100644 --- a/packages/polyfills/package.json +++ b/packages/polyfills/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/js-polyfills", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Polyfills for React Native.", "license": "MIT", "repository": { diff --git a/packages/react-native-babel-preset/package.json b/packages/react-native-babel-preset/package.json index ba57efc6941582..abdb23cb042304 100644 --- a/packages/react-native-babel-preset/package.json +++ b/packages/react-native-babel-preset/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/babel-preset", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Babel preset for React Native applications", "main": "src/index.js", "repository": { @@ -55,7 +55,7 @@ "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.77.0-main", + "@react-native/babel-plugin-codegen": "0.78.2", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" diff --git a/packages/react-native-babel-transformer/package.json b/packages/react-native-babel-transformer/package.json index 524baafe464a56..821aa7e8af41e7 100644 --- a/packages/react-native-babel-transformer/package.json +++ b/packages/react-native-babel-transformer/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/metro-babel-transformer", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Babel transformer for React Native applications.", "main": "src/index.js", "repository": { @@ -16,7 +16,7 @@ "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", - "@react-native/babel-preset": "0.77.0-main", + "@react-native/babel-preset": "0.78.2", "hermes-parser": "0.25.1", "nullthrows": "^1.1.1" }, diff --git a/packages/react-native-bots/package.json b/packages/react-native-bots/package.json index facc1e3fcab814..ea1f789f77eb06 100644 --- a/packages/react-native-bots/package.json +++ b/packages/react-native-bots/package.json @@ -1,7 +1,7 @@ { "name": "@react-native/bots", "description": "React Native Bots", - "version": "0.77.0-main", + "version": "0.78.2", "private": true, "license": "MIT", "repository": { diff --git a/packages/react-native-codegen-typescript-test/package.json b/packages/react-native-codegen-typescript-test/package.json index 5d124daf46c8b2..94beb5ef08f8bd 100644 --- a/packages/react-native-codegen-typescript-test/package.json +++ b/packages/react-native-codegen-typescript-test/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/codegen-typescript-test", - "version": "0.77.0-main", + "version": "0.78.2", "private": true, "description": "TypeScript related unit test for @react-native/codegen", "license": "MIT", @@ -19,7 +19,7 @@ "prepare": "yarn run build" }, "dependencies": { - "@react-native/codegen": "0.77.0-main" + "@react-native/codegen": "0.78.2" }, "devDependencies": { "@babel/core": "^7.25.2", diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index 80f3e14e658670..0b2bb85f0f3cb5 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/codegen", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Code generation tools for React Native", "license": "MIT", "repository": { diff --git a/packages/react-native-fantom/package.json b/packages/react-native-fantom/package.json index c4c61cc5384f62..63fae569b2c018 100644 --- a/packages/react-native-fantom/package.json +++ b/packages/react-native-fantom/package.json @@ -1,11 +1,11 @@ { - "name": "@react-native/fantom", - "private": true, - "version": "0.77.0-main", - "main": "src/index.js", - "description": "Internal integration testing and benchmarking tool for React Native", - "peerDependencies":{ - "jest":"^29.7.0", - "jest-snapshot": "^29.7.0" - } + "name": "@react-native/fantom", + "private": true, + "version": "0.78.2", + "main": "src/index.js", + "description": "Internal integration testing and benchmarking tool for React Native", + "peerDependencies": { + "jest": "^29.7.0", + "jest-snapshot": "^29.7.0" + } } diff --git a/packages/react-native-info/package.json b/packages/react-native-info/package.json index 6381b4f2cb631b..8837293894ab3e 100644 --- a/packages/react-native-info/package.json +++ b/packages/react-native-info/package.json @@ -1,6 +1,6 @@ { "name": "react-native-info", - "version": "0.77.0-main", + "version": "0.78.2", "main": "build/index.js", "license": "MIT", "private": true, diff --git a/packages/react-native-popup-menu-android/package.json b/packages/react-native-popup-menu-android/package.json index c07e3fd1ad9fd0..f6183d3d2f7f86 100644 --- a/packages/react-native-popup-menu-android/package.json +++ b/packages/react-native-popup-menu-android/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/popup-menu-android", - "version": "0.77.0-main", + "version": "0.78.2", "description": "PopupMenu for the Android platform", "main": "index.js", "files": [ @@ -17,7 +17,7 @@ ], "license": "MIT", "devDependencies": { - "@react-native/codegen": "0.77.0-main" + "@react-native/codegen": "0.78.2" }, "peerDependencies": { "@types/react": "^19.0.0", diff --git a/packages/react-native-test-library/package.json b/packages/react-native-test-library/package.json index c378871432ff36..fd6cb2e1ffabd4 100644 --- a/packages/react-native-test-library/package.json +++ b/packages/react-native-test-library/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/oss-library-example", - "version": "0.77.0-main", + "version": "0.78.2", "private": true, "description": "Package that includes native module exapmle, native component example, targets both the old and the new architecture. It should serve as an example of a real-world OSS library.", "license": "MIT", @@ -26,8 +26,8 @@ ], "devDependencies": { "@babel/core": "^7.25.2", - "@react-native/babel-preset": "0.77.0-main", - "react-native": "1000.0.0" + "@react-native/babel-preset": "0.78.2", + "react-native": "0.78.2" }, "peerDependencies": { "react": "*", diff --git a/packages/react-native/Libraries/Animated/createAnimatedComponent.js b/packages/react-native/Libraries/Animated/createAnimatedComponent.js index cef22cd810fd45..bc240c4eff9e28 100644 --- a/packages/react-native/Libraries/Animated/createAnimatedComponent.js +++ b/packages/react-native/Libraries/Animated/createAnimatedComponent.js @@ -19,12 +19,7 @@ import {useMemo} from 'react'; export type AnimatedProps = { // eslint-disable-next-line no-unused-vars - +[_K in keyof (Props & - $ReadOnly<{ - passthroughAnimatedPropExplicitValues?: React.ElementConfig< - typeof View, - >, - }>)]: any, + +[_K]: any, }; // We could use a mapped type here to introduce acceptable Animated variants diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js b/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js index 889bfa51825e1c..8ab98a06246ac2 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js @@ -9,6 +9,7 @@ */ import type {EventSubscription} from '../../vendor/emitter/EventEmitter'; +import type {PlatformConfig} from '../AnimatedPlatformConfig'; import type Animation, {EndCallback} from '../animations/Animation'; import type {InterpolationConfigType} from './AnimatedInterpolation'; import type AnimatedNode from './AnimatedNode'; @@ -84,6 +85,7 @@ function _executeAsAnimatedBatch(id: string, operation: () => void) { * See https://reactnative.dev/docs/animatedvalue */ export default class AnimatedValue extends AnimatedWithChildren { + #attached: boolean = false; #updateSubscription: ?EventSubscription = null; _value: number; @@ -106,14 +108,8 @@ export default class AnimatedValue extends AnimatedWithChildren { } __attach(): void { - if (this.__isNative) { - // NOTE: In theory, we should only need to call this when any listeners - // are added. However, there is a global `onUserDrivenAnimationEnded` - // listener that relies on `onAnimatedValueUpdate` having fired to update - // the values in JavaScript. If that listener is removed, this could be - // re-optimized. - this.#ensureUpdateSubscriptionExists(); - } + this.#attached = true; + this.#ensureUpdateSubscriptionExists(); } __detach(): void { @@ -125,16 +121,34 @@ export default class AnimatedValue extends AnimatedWithChildren { } this.stopAnimation(); super.__detach(); + this.#attached = false; } __getValue(): number { return this._value + this._offset; } + __makeNative(platformConfig: ?PlatformConfig): void { + super.__makeNative(platformConfig); + this.#ensureUpdateSubscriptionExists(); + } + + /** + * NOTE: In theory, we should only need to call this when any listeners + * are added. However, there is a global `onUserDrivenAnimationEnded` + * listener that relies on `onAnimatedValueUpdate` having fired to update + * the values in JavaScript. If that listener is removed, this could be + * re-optimized. + */ #ensureUpdateSubscriptionExists(): void { if (this.#updateSubscription != null) { return; } + // The order in which `__attach` and `__makeNative` are called is not + // deterministic, and we only want to do this when both have occurred. + if (!this.#attached || !this.__isNative) { + return; + } const nativeTag = this.__getNativeTag(); NativeAnimatedAPI.startListeningToAnimatedNodeValue(nativeTag); const subscription: EventSubscription = diff --git a/packages/react-native/Libraries/Animated/useAnimatedProps.js b/packages/react-native/Libraries/Animated/useAnimatedProps.js index 9c66dfa827dafa..98fc5678373071 100644 --- a/packages/react-native/Libraries/Animated/useAnimatedProps.js +++ b/packages/react-native/Libraries/Animated/useAnimatedProps.js @@ -276,6 +276,20 @@ function useAnimatedPropsLifecycle_insertionEffects(node: AnimatedProps): void { // if the queue is empty. When multiple animated components are mounted at // the same time. Only first component flushes the queue and the others will noop. NativeAnimatedHelper.API.flushQueue(); + let drivenAnimationEndedListener: ?EventSubscription = null; + if (node.__isNative) { + drivenAnimationEndedListener = + NativeAnimatedHelper.nativeEventEmitter.addListener( + 'onUserDrivenAnimationEnded', + data => { + node.update(); + }, + ); + } + + return () => { + drivenAnimationEndedListener?.remove(); + }; }); useInsertionEffect(() => { @@ -287,17 +301,6 @@ function useAnimatedPropsLifecycle_insertionEffects(node: AnimatedProps): void { useInsertionEffect(() => { node.__attach(); - let drivenAnimationEndedListener: ?EventSubscription = null; - - if (node.__isNative) { - drivenAnimationEndedListener = - NativeAnimatedHelper.nativeEventEmitter.addListener( - 'onUserDrivenAnimationEnded', - data => { - node.update(); - }, - ); - } if (prevNodeRef.current != null) { const prevNode = prevNodeRef.current; // TODO: Stop restoring default values (unless `reset` is called). @@ -312,8 +315,6 @@ function useAnimatedPropsLifecycle_insertionEffects(node: AnimatedProps): void { } else { prevNodeRef.current = node; } - - drivenAnimationEndedListener?.remove(); }; }, [node]); } diff --git a/packages/react-native/Libraries/AppDelegate/RCTDefaultReactNativeFactoryDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTDefaultReactNativeFactoryDelegate.mm index 710f00e3142c3f..737dcaf07d87d2 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTDefaultReactNativeFactoryDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTDefaultReactNativeFactoryDelegate.mm @@ -118,4 +118,11 @@ - (Class)getModuleClassFromName:(const char *)name return nullptr; } +- (void)loadSourceForBridge:(RCTBridge *)bridge + onProgress:(RCTSourceLoadProgressBlock)onProgress + onComplete:(RCTSourceLoadBlock)loadCallback +{ + [RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] onProgress:onProgress onComplete:loadCallback]; +} + @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm index 75c963a3a990c7..fa0c5fab711025 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.mm @@ -156,6 +156,15 @@ - (Class)getModuleClassFromName:(const char *)name return RCTAppSetupDefaultModuleFromClass(moduleClass, self.delegate.dependencyProvider); } +- (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge +{ + if ([_delegate respondsToSelector:@selector(extraModulesForBridge:)]) { + return [_delegate extraModulesForBridge:bridge]; + } + + return @[]; +} + #pragma mark - RCTComponentViewFactoryComponentProvider - (NSDictionary> *)thirdPartyFabricComponents @@ -228,6 +237,21 @@ - (RCTRootViewFactory *)createRCTRootViewFactory }; } + if ([self.delegate respondsToSelector:@selector(loadSourceForBridge:onProgress:onComplete:)]) { + configuration.loadSourceForBridgeWithProgress = + ^(RCTBridge *_Nonnull bridge, + RCTSourceLoadProgressBlock _Nonnull onProgress, + RCTSourceLoadBlock _Nonnull loadCallback) { + [weakSelf.delegate loadSourceForBridge:bridge onProgress:onProgress onComplete:loadCallback]; + }; + } + + if ([self.delegate respondsToSelector:@selector(loadSourceForBridge:withBlock:)]) { + configuration.loadSourceForBridge = ^(RCTBridge *_Nonnull bridge, RCTSourceLoadBlock _Nonnull loadCallback) { + [weakSelf.delegate loadSourceForBridge:bridge withBlock:loadCallback]; + }; + } + return [[RCTRootViewFactory alloc] initWithTurboModuleDelegate:self hostDelegate:self configuration:configuration]; } @@ -255,9 +279,12 @@ bool useNativeViewConfigsInBridgelessMode() override - (void)_setUpFeatureFlags { - if ([self bridgelessEnabled]) { - ReactNativeFeatureFlags::override(std::make_unique()); - } + static dispatch_once_t setupFeatureFlagsToken; + dispatch_once(&setupFeatureFlagsToken, ^{ + if ([self bridgelessEnabled]) { + ReactNativeFeatureFlags::override(std::make_unique()); + } + }); } @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h index d3ce6212fac15f..20c0b3a39ce9a8 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h @@ -31,6 +31,11 @@ typedef NSURL *_Nullable (^RCTBundleURLBlock)(void); typedef NSArray> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge); typedef NSDictionary *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge); typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName); +typedef void (^RCTLoadSourceForBridgeWithProgressBlock)( + RCTBridge *bridge, + RCTSourceLoadProgressBlock onProgress, + RCTSourceLoadBlock loadCallback); +typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBlock loadCallback); #pragma mark - RCTRootViewFactory Configuration @interface RCTRootViewFactoryConfiguration : NSObject @@ -145,6 +150,19 @@ typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *modu */ @property (nonatomic, nullable) RCTBridgeDidNotFindModuleBlock bridgeDidNotFindModule; +/** + * The bridge will automatically attempt to load the JS source code from the + * location specified by the `sourceURLForBridge:` method, however, if you want + * to handle loading the JS yourself, you can do so by setting this property. + */ +@property (nonatomic, nullable) RCTLoadSourceForBridgeWithProgressBlock loadSourceForBridgeWithProgress; + +/** + * Similar to loadSourceForBridgeWithProgress but without progress + * reporting. + */ +@property (nonatomic, nullable) RCTLoadSourceForBridgeBlock loadSourceForBridge; + @end #pragma mark - RCTRootViewFactory diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm index 5b3f575089b5ce..054540765eb547 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm @@ -302,6 +302,22 @@ - (BOOL)bridge:(RCTBridge *)bridge didNotFindModule:(NSString *)moduleName return NO; } +- (void)loadSourceForBridge:(RCTBridge *)bridge withBlock:(RCTSourceLoadBlock)loadCallback +{ + if (_configuration.loadSourceForBridge != nil) { + _configuration.loadSourceForBridge(bridge, loadCallback); + } +} + +- (void)loadSourceForBridge:(RCTBridge *)bridge + onProgress:(RCTSourceLoadProgressBlock)onProgress + onComplete:(RCTSourceLoadBlock)loadCallback +{ + if (_configuration.loadSourceForBridgeWithProgress != nil) { + _configuration.loadSourceForBridgeWithProgress(bridge, onProgress, loadCallback); + } +} + - (NSURL *)bundleURL { return self->_configuration.bundleURLBlock(); diff --git a/packages/react-native/Libraries/Components/Pressable/useAndroidRippleForView.js b/packages/react-native/Libraries/Components/Pressable/useAndroidRippleForView.js index 20dd19e969181b..ed6eb2f67e10dd 100644 --- a/packages/react-native/Libraries/Components/Pressable/useAndroidRippleForView.js +++ b/packages/react-native/Libraries/Components/Pressable/useAndroidRippleForView.js @@ -24,12 +24,14 @@ type NativeBackgroundProp = $ReadOnly<{| color: ?number, borderless: boolean, rippleRadius: ?number, + rippleCornerRadius: ?number, |}>; export type RippleConfig = {| color?: ColorValue, borderless?: boolean, radius?: number, + cornerRadius?: number, foreground?: boolean, |}; @@ -48,7 +50,8 @@ export default function useAndroidRippleForView( | $ReadOnly<{|nativeBackgroundAndroid: NativeBackgroundProp|}> | $ReadOnly<{|nativeForegroundAndroid: NativeBackgroundProp|}>, |}> { - const {color, borderless, radius, foreground} = rippleConfig ?? {}; + const {color, borderless, radius, cornerRadius, foreground} = + rippleConfig ?? {}; return useMemo(() => { if ( @@ -66,6 +69,7 @@ export default function useAndroidRippleForView( color: processedColor, borderless: borderless === true, rippleRadius: radius, + rippleCornerRadius: cornerRadius, }; return { diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.js b/packages/react-native/Libraries/Components/TextInput/TextInput.js index 48a3c99609a870..db199daa8b695a 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.js @@ -1019,7 +1019,7 @@ function useTextInputStateSynchronization_STATE({ mostRecentEventCount: number, selection: ?Selection, inputRef: React.RefObject, - text: string, + text?: string, viewCommands: ViewCommands, }): { setLastNativeText: string => void, @@ -1100,7 +1100,7 @@ function useTextInputStateSynchronization_REFS({ mostRecentEventCount: number, selection: ?Selection, inputRef: React.RefObject, - text: string, + text?: string, viewCommands: ViewCommands, }): { setLastNativeText: string => void, @@ -1314,7 +1314,7 @@ function InternalTextInput(props: Props): React.Node { ? props.value : typeof props.defaultValue === 'string' ? props.defaultValue - : ''; + : undefined; const viewCommands = AndroidTextInputCommands || diff --git a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js index 5173b8975acc9e..45bd8d3aa61bd8 100644 --- a/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js +++ b/packages/react-native/Libraries/Components/TextInput/__tests__/TextInput-test.js @@ -7,7 +7,7 @@ * @format */ -const {create} = require('../../../../jest/renderer'); +const {create, update} = require('../../../../jest/renderer'); const ReactNativeFeatureFlags = require('../../../../src/private/featureflags/ReactNativeFeatureFlags'); const ReactNative = require('../../../ReactNative/RendererProxy'); const { @@ -20,8 +20,14 @@ const ReactTestRenderer = require('react-test-renderer'); jest.unmock('../TextInput'); -[true, false].forEach(useRefsForTextInputState => { - describe(`TextInput tests (useRefsForTextInputState = ${useRefsForTextInputState}`, () => { +[ + {useRefsForTextInputState: true, useTextChildren: true}, + {useRefsForTextInputState: false, useTextChildren: true}, + {useRefsForTextInputState: true, useTextChildren: false}, + {useRefsForTextInputState: false, useTextChildren: false}, +].forEach(testCase => { + const {useRefsForTextInputState, useTextChildren} = testCase; + describe(`TextInput tests (useRefsForTextInputState = ${useRefsForTextInputState}) useTextChildren = ${useTextChildren}`, () => { let input; let inputRef; let onChangeListener; @@ -43,15 +49,16 @@ jest.unmock('../TextInput'); return ( { onChangeTextListener(text); setState({text}); }} onChange={event => { onChangeListener(event); - }} - /> + }}> + {useTextChildren ? state.text : undefined} + ); } const renderTree = await create(); @@ -75,12 +82,20 @@ jest.unmock('../TextInput'); ); }); it('calls onChange callbacks', () => { - expect(input.props.value).toBe(initialValue); + if (!useTextChildren) { + expect(input.props.value).toBe(initialValue); + } else { + expect(input.props.children).toBe(initialValue); + } const message = 'This is a test message'; ReactTestRenderer.act(() => { enter(input, message); }); - expect(input.props.value).toBe(message); + if (!useTextChildren) { + expect(input.props.value).toBe(message); + } else { + expect(input.props.children).toBe(message); + } expect(onChangeTextListener).toHaveBeenCalledWith(message); expect(onChangeListener).toHaveBeenCalledWith({ nativeEvent: {text: message}, @@ -90,7 +105,12 @@ jest.unmock('../TextInput'); async function createTextInput(extraProps) { const textInputRef = React.createRef(null); await create( - , + + {useTextChildren ? 'value1' : undefined} + , ); return textInputRef; } @@ -134,14 +154,55 @@ jest.unmock('../TextInput'); expect(TextInput.State.currentlyFocusedInput()).toBe(null); }); + it('change selection keeps content', async () => { + const defaultValue = 'value1'; + // create content + let renderTree = await create( + + {useTextChildren ? defaultValue : undefined} + , + ); + input = renderTree.root.findByType(TextInput); + expect( + useTextChildren ? input.children[0].props.children : input.props.value, + ).toBe(defaultValue); + expect(input.props.position.start).toBe(1); + expect(input.props.position.end).toBe(1); + + // update position + renderTree = await update( + renderTree, + + {useTextChildren ? defaultValue : undefined} + , + ); + expect( + useTextChildren ? input.children[0].props.children : input.props.value, + ).toBe(defaultValue); + expect(input.props.position.start).toBe(2); + expect(input.props.position.end).toBe(2); + }); + it('should unfocus when other TextInput is focused', async () => { const textInputRe1 = React.createRef(null); const textInputRe2 = React.createRef(null); await create( <> - - + + {useTextChildren ? 'value1' : undefined} + + + {useTextChildren ? 'value2' : undefined} + , ); ReactNative.findNodeHandle = jest.fn().mockImplementation(ref => { @@ -210,7 +271,6 @@ jest.unmock('../TextInput'); rejectResponderTermination={true} selection={null} submitBehavior="blurAndSubmit" - text="" textContentType="emailAddress" underlineColorAndroid="transparent" /> @@ -255,7 +315,6 @@ jest.unmock('../TextInput'); rejectResponderTermination={true} selection={null} submitBehavior="blurAndSubmit" - text="" underlineColorAndroid="transparent" /> `); @@ -301,7 +360,6 @@ jest.unmock('../TextInput'); selection={null} submitBehavior="blurAndSubmit" testID="testID" - text="" underlineColorAndroid="transparent" /> `); @@ -432,7 +490,6 @@ jest.unmock('../TextInput'); role="main" selection={null} submitBehavior="blurAndSubmit" - text="" underlineColorAndroid="transparent" /> `); @@ -489,7 +546,6 @@ jest.unmock('../TextInput'); ] } submitBehavior="blurAndSubmit" - text="" underlineColorAndroid="transparent" /> `); diff --git a/packages/react-native/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap b/packages/react-native/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap index 6f672ac96c52e7..ba3c5771de94a7 100644 --- a/packages/react-native/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap +++ b/packages/react-native/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TextInput tests (useRefsForTextInputState = false should render as expected: should deep render when mocked (please verify output manually) 1`] = ` +exports[`TextInput tests (useRefsForTextInputState = false) useTextChildren = false should render as expected: should deep render when mocked (please verify output manually) 1`] = ` `; -exports[`TextInput tests (useRefsForTextInputState = false should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` +exports[`TextInput tests (useRefsForTextInputState = false) useTextChildren = false should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` `; -exports[`TextInput tests (useRefsForTextInputState = true should render as expected: should deep render when mocked (please verify output manually) 1`] = ` +exports[`TextInput tests (useRefsForTextInputState = false) useTextChildren = true should render as expected: should deep render when mocked (please verify output manually) 1`] = ` `; -exports[`TextInput tests (useRefsForTextInputState = true should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` +exports[`TextInput tests (useRefsForTextInputState = false) useTextChildren = true should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` + +`; + +exports[`TextInput tests (useRefsForTextInputState = true) useTextChildren = false should render as expected: should deep render when mocked (please verify output manually) 1`] = ` + +`; + +exports[`TextInput tests (useRefsForTextInputState = true) useTextChildren = false should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` + +`; + +exports[`TextInput tests (useRefsForTextInputState = true) useTextChildren = true should render as expected: should deep render when mocked (please verify output manually) 1`] = ` + +`; + +exports[`TextInput tests (useRefsForTextInputState = true) useTextChildren = true should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` `; diff --git a/packages/react-native/Libraries/Components/View/ViewPropTypes.js b/packages/react-native/Libraries/Components/View/ViewPropTypes.js index f56e28d86e0c4b..9f209a4fc21678 100644 --- a/packages/react-native/Libraries/Components/View/ViewPropTypes.js +++ b/packages/react-native/Libraries/Components/View/ViewPropTypes.js @@ -261,6 +261,7 @@ type AndroidDrawableRipple = $ReadOnly<{| color?: ?number, borderless?: ?boolean, rippleRadius?: ?number, + rippleCornerRadius?: ?number, |}>; type AndroidDrawable = AndroidDrawableThemeAttr | AndroidDrawableRipple; diff --git a/packages/react-native/Libraries/Core/ReactNativeVersion.js b/packages/react-native/Libraries/Core/ReactNativeVersion.js index 786a34fcdd1f2c..e47992fc8d2e01 100644 --- a/packages/react-native/Libraries/Core/ReactNativeVersion.js +++ b/packages/react-native/Libraries/Core/ReactNativeVersion.js @@ -14,9 +14,9 @@ const version: $ReadOnly<{ patch: number, prerelease: string | null, }> = { - major: 1000, - minor: 0, - patch: 0, + major: 0, + minor: 78, + patch: 2, prerelease: null, }; diff --git a/packages/react-native/Libraries/Core/setUpDeveloperTools.js b/packages/react-native/Libraries/Core/setUpDeveloperTools.js index 5cc39eae9c1274..57f4f5916c262c 100644 --- a/packages/react-native/Libraries/Core/setUpDeveloperTools.js +++ b/packages/react-native/Libraries/Core/setUpDeveloperTools.js @@ -42,9 +42,8 @@ if (__DEV__) { if (!Platform.isTesting) { const HMRClient = require('../Utilities/HMRClient'); - if (global.__FUSEBOX_HAS_FULL_CONSOLE_SUPPORT__) { - HMRClient.unstable_notifyFuseboxConsoleEnabled(); - } else if (console._isPolyfilled) { + // TODO(T214991636): Remove legacy Metro log forwarding + if (console._isPolyfilled) { // We assume full control over the console and send JavaScript logs to Metro. [ 'trace', diff --git a/packages/react-native/Libraries/Image/Image.android.js b/packages/react-native/Libraries/Image/Image.android.js index 08fbe9d1faca02..752c339ffeea30 100644 --- a/packages/react-native/Libraries/Image/Image.android.js +++ b/packages/react-native/Libraries/Image/Image.android.js @@ -133,6 +133,7 @@ let BaseImage: AbstractImageAndroid = React.forwardRef( width: undefined, height: undefined, }; + const defaultSource = resolveAssetSource(props.defaultSource); const loadingIndicatorSource = resolveAssetSource( props.loadingIndicatorSource, ); @@ -178,6 +179,7 @@ let BaseImage: AbstractImageAndroid = React.forwardRef( /* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found * when making Flow check .android.js files. */ headers: (source?.[0]?.headers || source?.headers: ?{[string]: string}), + defaultSource: defaultSource ? defaultSource.uri : null, loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null, diff --git a/packages/react-native/Libraries/Image/ImageViewNativeComponent.js b/packages/react-native/Libraries/Image/ImageViewNativeComponent.js index 22ac430c2190ef..a6fa43b27feabd 100644 --- a/packages/react-native/Libraries/Image/ImageViewNativeComponent.js +++ b/packages/react-native/Libraries/Image/ImageViewNativeComponent.js @@ -21,6 +21,7 @@ import type { } from '../StyleSheet/StyleSheet'; import type {ResolvedAssetSource} from './AssetSourceResolver'; import type {ImageProps} from './ImageProps'; +import type {ImageSource} from './ImageSource'; import * as NativeComponentRegistry from '../NativeComponent/NativeComponentRegistry'; import {ConditionallyIgnoredEventHandlers} from '../NativeComponent/ViewConfigIgnore'; @@ -42,7 +43,7 @@ type Props = $ReadOnly<{ | ?ResolvedAssetSource | ?$ReadOnlyArray>, headers?: ?{[string]: string}, - defaultSrc?: ?string, + defaultSource?: ?ImageSource | ?string, loadingIndicatorSrc?: ?string, }>; @@ -82,9 +83,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = }, validAttributes: { blurRadius: true, - defaultSource: { - process: require('./resolveAssetSource'), - }, + defaultSource: true, internal_analyticTag: true, resizeMethod: true, resizeMode: true, diff --git a/packages/react-native/Libraries/Image/RCTImageLoader.mm b/packages/react-native/Libraries/Image/RCTImageLoader.mm index 68a12d351227ef..3caaf7bdf10a0b 100644 --- a/packages/react-native/Libraries/Image/RCTImageLoader.mm +++ b/packages/react-native/Libraries/Image/RCTImageLoader.mm @@ -477,7 +477,15 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req // Add missing png extension if (request.URL.fileURL && request.URL.pathExtension.length == 0) { - mutableRequest.URL = [request.URL URLByAppendingPathExtension:@"png"]; + // Check if there exists a file with that url on disk already + // This should fix issue https://github.com/facebook/react-native/issues/46870 + if ([[NSFileManager defaultManager] fileExistsAtPath:request.URL.path]) { + mutableRequest.URL = request.URL; + } else { + // This is the default behavior in case there is no file on disk with no extension. + // We assume that the extension is `png`. + mutableRequest.URL = [request.URL URLByAppendingPathExtension:@"png"]; + } } if (_redirectDelegate != nil) { mutableRequest.URL = [_redirectDelegate redirectAssetsURL:mutableRequest.URL]; diff --git a/packages/react-native/Libraries/Network/RCTDataRequestHandler.mm b/packages/react-native/Libraries/Network/RCTDataRequestHandler.mm index f95d0c078e0d5a..2aff977cf65a8f 100644 --- a/packages/react-native/Libraries/Network/RCTDataRequestHandler.mm +++ b/packages/react-native/Libraries/Network/RCTDataRequestHandler.mm @@ -8,6 +8,8 @@ #import #import +#import + #import "RCTNetworkPlugins.h" @interface RCTDataRequestHandler () @@ -15,14 +17,22 @@ @interface RCTDataRequestHandler () @implementation RCTDataRequestHandler { NSOperationQueue *_queue; + std::mutex _operationHandlerMutexLock; } RCT_EXPORT_MODULE() - (void)invalidate { - [_queue cancelAllOperations]; - _queue = nil; + std::lock_guard lock(_operationHandlerMutexLock); + if (_queue) { + for (NSOperation *operation in _queue.operations) { + if (!operation.isCancelled && !operation.isFinished) { + [operation cancel]; + } + } + _queue = nil; + } } - (BOOL)canHandleRequest:(NSURLRequest *)request @@ -32,6 +42,7 @@ - (BOOL)canHandleRequest:(NSURLRequest *)request - (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id)delegate { + std::lock_guard lock(_operationHandlerMutexLock); // Lazy setup if (!_queue) { _queue = [NSOperationQueue new]; @@ -69,7 +80,10 @@ - (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id lock(_operationHandlerMutexLock); + if (!op.isCancelled && !op.isFinished) { + [op cancel]; + } } - (std::shared_ptr)getTurboModule: diff --git a/packages/react-native/Libraries/Network/RCTFileRequestHandler.mm b/packages/react-native/Libraries/Network/RCTFileRequestHandler.mm index 19d025c51e19df..4ca36256c681af 100644 --- a/packages/react-native/Libraries/Network/RCTFileRequestHandler.mm +++ b/packages/react-native/Libraries/Network/RCTFileRequestHandler.mm @@ -7,6 +7,8 @@ #import +#import + #import #import @@ -19,14 +21,22 @@ @interface RCTFileRequestHandler () @implementation RCTFileRequestHandler { NSOperationQueue *_fileQueue; + std::mutex _operationHandlerMutexLock; } RCT_EXPORT_MODULE() - (void)invalidate { - [_fileQueue cancelAllOperations]; - _fileQueue = nil; + std::lock_guard lock(_operationHandlerMutexLock); + if (_fileQueue) { + for (NSOperation *operation in _fileQueue.operations) { + if (!operation.isCancelled && !operation.isFinished) { + [operation cancel]; + } + } + _fileQueue = nil; + } } - (BOOL)canHandleRequest:(NSURLRequest *)request @@ -36,6 +46,7 @@ - (BOOL)canHandleRequest:(NSURLRequest *)request - (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id)delegate { + std::lock_guard lock(_operationHandlerMutexLock); // Lazy setup if (!_fileQueue) { _fileQueue = [NSOperationQueue new]; @@ -83,7 +94,10 @@ - (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id lock(_operationHandlerMutexLock); + if (!op.isCancelled && !op.isFinished) { + [op cancel]; + } } - (std::shared_ptr)getTurboModule: diff --git a/packages/react-native/Libraries/Text/BaseText/RCTBaseTextViewManager.mm b/packages/react-native/Libraries/Text/BaseText/RCTBaseTextViewManager.mm index e9ce272b5f55fb..6e88d6f922799a 100644 --- a/packages/react-native/Libraries/Text/BaseText/RCTBaseTextViewManager.mm +++ b/packages/react-native/Libraries/Text/BaseText/RCTBaseTextViewManager.mm @@ -28,6 +28,7 @@ - (RCTShadowView *)shadowView // Color RCT_REMAP_SHADOW_PROPERTY(color, textAttributes.foregroundColor, UIColor) RCT_REMAP_SHADOW_PROPERTY(backgroundColor, textAttributes.backgroundColor, UIColor) +RCT_REMAP_SHADOW_PROPERTY(gradientColors, textAttributes.gradientColors, NSArray) RCT_REMAP_SHADOW_PROPERTY(opacity, textAttributes.opacity, CGFloat) // Font RCT_REMAP_SHADOW_PROPERTY(fontFamily, textAttributes.fontFamily, NSString) diff --git a/packages/react-native/Libraries/Text/RCTTextAttributes.h b/packages/react-native/Libraries/Text/RCTTextAttributes.h index 1b72abe51df44e..ad48554f36f31d 100644 --- a/packages/react-native/Libraries/Text/RCTTextAttributes.h +++ b/packages/react-native/Libraries/Text/RCTTextAttributes.h @@ -26,6 +26,7 @@ extern NSString *const RCTTextAttributesTagAttributeName; // Color @property (nonatomic, strong, nullable) UIColor *foregroundColor; @property (nonatomic, strong, nullable) UIColor *backgroundColor; +@property (nonatomic, copy, nullable) NSArray *gradientColors; @property (nonatomic, assign) CGFloat opacity; // Font @property (nonatomic, copy, nullable) NSString *fontFamily; diff --git a/packages/react-native/Libraries/Text/RCTTextAttributes.mm b/packages/react-native/Libraries/Text/RCTTextAttributes.mm index 43dd1f7c18ee0e..acd157939436b2 100644 --- a/packages/react-native/Libraries/Text/RCTTextAttributes.mm +++ b/packages/react-native/Libraries/Text/RCTTextAttributes.mm @@ -46,6 +46,7 @@ - (void)applyTextAttributes:(RCTTextAttributes *)textAttributes // Color _foregroundColor = textAttributes->_foregroundColor ?: _foregroundColor; _backgroundColor = textAttributes->_backgroundColor ?: _backgroundColor; + _gradientColors = textAttributes->_gradientColors ?: _gradientColors; _opacity = !isnan(textAttributes->_opacity) ? (isnan(_opacity) ? 1.0 : _opacity) * textAttributes->_opacity : _opacity; @@ -223,14 +224,52 @@ - (NSParagraphStyle *)effectiveParagraphStyle - (UIFont *)effectiveFont { - // FIXME: RCTFont has thread-safety issues and must be rewritten. - return [RCTFont updateFont:nil - withFamily:_fontFamily - size:@(isnan(_fontSize) ? 0 : _fontSize) - weight:_fontWeight - style:_fontStyle - variant:_fontVariant - scaleMultiplier:self.effectiveFontSizeMultiplier]; + NSArray *rawFontFamilies = [_fontFamily componentsSeparatedByString:@","]; + + // If _fontFamily is nil or has a single fontFamily, then use the original RN logic. + if (rawFontFamilies.count <= 1) { + // FIXME: RCTFont has thread-safety issues and must be rewritten. + return [RCTFont updateFont:nil + withFamily:_fontFamily + size:@(isnan(_fontSize) ? 0 : _fontSize) + weight:_fontWeight + style:_fontStyle + variant:_fontVariant + scaleMultiplier:self.effectiveFontSizeMultiplier]; + } + + NSMutableArray *fonts = [NSMutableArray new]; + for (NSString *rawFontFamily in rawFontFamilies) { + NSString *fontFamily = [rawFontFamily stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + if (fontFamily.length == 0) { + continue; + } + + UIFont *font = [RCTFont updateFont:nil + withFamily:fontFamily + size:@(isnan(_fontSize) ? 0 : _fontSize) + weight:_fontWeight + style:_fontStyle + variant:_fontVariant + scaleMultiplier:self.effectiveFontSizeMultiplier]; + + if (font) { + [fonts addObject:font]; + } + } + + UIFont *primaryFont = fonts[0]; + + NSMutableArray *fontDescriptors = [NSMutableArray new]; + for (NSUInteger i = 1; i < fonts.count; i++) { + UIFont *font = fonts[i]; + [fontDescriptors addObject:font.fontDescriptor]; + } + + UIFontDescriptor *fontDescriptor = [primaryFont.fontDescriptor fontDescriptorByAddingAttributes: + @{UIFontDescriptorCascadeListAttribute: fontDescriptors}]; + + return [UIFont fontWithDescriptor:fontDescriptor size:primaryFont.pointSize]; } - (CGFloat)effectiveFontSizeMultiplier @@ -256,6 +295,35 @@ - (UIColor *)effectiveForegroundColor { UIColor *effectiveForegroundColor = _foregroundColor ?: [UIColor blackColor]; + if (_gradientColors != nil) { + NSMutableArray *cgColors = [NSMutableArray array]; + for (NSNumber *rawColor in _gradientColors) { + if (rawColor != nil) { + UIColor *color = [RCTConvert UIColor:@((0xFF << 24) | [rawColor integerValue])]; + [cgColors addObject:(id)color.CGColor]; + } + } + + if([cgColors count] > 0) { + [cgColors addObject:cgColors[0]]; + CAGradientLayer *gradient = [CAGradientLayer layer]; + // this pattern width corresponds roughly to desktop's pattern width + int patternWidth = 100; + CGFloat height = _lineHeight * self.effectiveFontSizeMultiplier; + gradient.frame = CGRectMake(0, 0, patternWidth, height); + gradient.colors = cgColors; + gradient.startPoint = CGPointMake(0.0, 0.5); + gradient.endPoint = CGPointMake(1.0, 0.5); + + UIGraphicsBeginImageContextWithOptions(gradient.frame.size, NO, 0.0); + [gradient renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + effectiveForegroundColor = [UIColor colorWithPatternImage:gradientImage]; + } + } + if (!isnan(_opacity)) { effectiveForegroundColor = [effectiveForegroundColor colorWithAlphaComponent:CGColorGetAlpha(effectiveForegroundColor.CGColor) * _opacity]; diff --git a/packages/react-native/Libraries/Text/Text.d.ts b/packages/react-native/Libraries/Text/Text.d.ts index 2481ba7707ce20..8a1170d6d84ae4 100644 --- a/packages/react-native/Libraries/Text/Text.d.ts +++ b/packages/react-native/Libraries/Text/Text.d.ts @@ -214,6 +214,11 @@ export interface TextProps * Controls how touch events are handled. Similar to `View`'s `pointerEvents`. */ pointerEvents?: ViewStyle['pointerEvents'] | undefined; + + /** + * Adds a horizontal gradient using the int based color values. + */ + gradientColors?: number[] | undefined; } /** diff --git a/packages/react-native/Libraries/Text/TextNativeComponent.js b/packages/react-native/Libraries/Text/TextNativeComponent.js index db354707320cfa..26bcb60b6e2518 100644 --- a/packages/react-native/Libraries/Text/TextNativeComponent.js +++ b/packages/react-native/Libraries/Text/TextNativeComponent.js @@ -48,6 +48,7 @@ const textViewConfig = { dataDetectorType: true, android_hyphenationFrequency: true, lineBreakStrategyIOS: true, + gradientColors: true, }, directEventTypes: { topTextLayout: { diff --git a/packages/react-native/Libraries/Utilities/HMRClient.js b/packages/react-native/Libraries/Utilities/HMRClient.js index c7832f7bb469e0..9e715ddc19b3a9 100644 --- a/packages/react-native/Libraries/Utilities/HMRClient.js +++ b/packages/react-native/Libraries/Utilities/HMRClient.js @@ -26,7 +26,6 @@ let hmrUnavailableReason: string | null = null; let currentCompileErrorMessage: string | null = null; let didConnect: boolean = false; let pendingLogs: Array<[LogLevel, $ReadOnlyArray]> = []; -let pendingFuseboxConsoleNotification = false; type LogLevel = | 'trace' @@ -52,7 +51,6 @@ export type HMRClientNativeInterface = {| isEnabled: boolean, scheme?: string, ): void, - unstable_notifyFuseboxConsoleEnabled(): void, |}; /** @@ -142,29 +140,6 @@ const HMRClient: HMRClientNativeInterface = { } }, - unstable_notifyFuseboxConsoleEnabled() { - if (!hmrClient) { - pendingFuseboxConsoleNotification = true; - return; - } - hmrClient.send( - JSON.stringify({ - type: 'log', - level: 'info', - data: [ - '\n' + - '\u001B[7m' + - ' \u001B[1m💡 JavaScript logs have moved!\u001B[22m They can now be ' + - 'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' + - 'the terminal to open (requires Google Chrome or Microsoft Edge).' + - '\u001B[27m' + - '\n', - ], - }), - ); - pendingFuseboxConsoleNotification = false; - }, - // Called once by the bridge on startup, even if Fast Refresh is off. // It creates the HMR client but doesn't actually set up the socket yet. setup( @@ -341,9 +316,6 @@ function flushEarlyLogs(client: MetroHMRClient) { pendingLogs.forEach(([level, data]) => { HMRClient.log(level, data); }); - if (pendingFuseboxConsoleNotification) { - HMRClient.unstable_notifyFuseboxConsoleEnabled(); - } } finally { pendingLogs.length = 0; } diff --git a/packages/react-native/Libraries/Utilities/HMRClientProdShim.js b/packages/react-native/Libraries/Utilities/HMRClientProdShim.js index c4492b845454c1..4d36db2bc525e8 100644 --- a/packages/react-native/Libraries/Utilities/HMRClientProdShim.js +++ b/packages/react-native/Libraries/Utilities/HMRClientProdShim.js @@ -25,7 +25,6 @@ const HMRClientProdShim: HMRClientNativeInterface = { disable() {}, registerBundle() {}, log() {}, - unstable_notifyFuseboxConsoleEnabled() {}, }; module.exports = HMRClientProdShim; diff --git a/packages/react-native/Libraries/WebSocket/WebSocket.js b/packages/react-native/Libraries/WebSocket/WebSocket.js index 08d737493c3e23..92b0b61712df31 100644 --- a/packages/react-native/Libraries/WebSocket/WebSocket.js +++ b/packages/react-native/Libraries/WebSocket/WebSocket.js @@ -245,7 +245,8 @@ class WebSocket extends (EventTarget(...WEBSOCKET_EVENTS): typeof EventTarget) { data = BlobManager.createFromOptions(ev.data); break; } - this.dispatchEvent(new WebSocketEvent('message', {data})); + const raw_length = ev.raw_length; + this.dispatchEvent(new WebSocketEvent('message', {data, raw_length})); }), this._eventEmitter.addListener('websocketOpen', ev => { if (ev.id !== this._socketId) { diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 32b72e85d0ba5d..2356abada34c63 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -1169,6 +1169,7 @@ declare export default class AnimatedValue extends AnimatedWithChildren { __attach(): void; __detach(): void; __getValue(): number; + __makeNative(platformConfig: ?PlatformConfig): void; setValue(value: number): void; setOffset(offset: number): void; flattenOffset(): void; @@ -5064,7 +5065,7 @@ exports[`public API should not change unintentionally Libraries/Image/ImageViewN | ?ResolvedAssetSource | ?$ReadOnlyArray>, headers?: ?{ [string]: string }, - defaultSrc?: ?string, + defaultSource?: ?ImageSource | ?string, loadingIndicatorSrc?: ?string, }>; interface NativeCommands { @@ -9000,7 +9001,6 @@ export type HMRClientNativeInterface = {| isEnabled: boolean, scheme?: string ): void, - unstable_notifyFuseboxConsoleEnabled(): void, |}; declare const HMRClient: HMRClientNativeInterface; declare module.exports: HMRClient; diff --git a/packages/react-native/Libraries/vendor/emitter/EventEmitter.js b/packages/react-native/Libraries/vendor/emitter/EventEmitter.js index 1087654ea57827..5beed1d4de3c3a 100644 --- a/packages/react-native/Libraries/vendor/emitter/EventEmitter.js +++ b/packages/react-native/Libraries/vendor/emitter/EventEmitter.js @@ -36,7 +36,7 @@ interface Registration { } type Registry = { - [K in keyof TEventToArgsMap]: Set>, + [K]: Set>, }; /** diff --git a/packages/react-native/React/Base/RCTDisplayLink.m b/packages/react-native/React/Base/RCTDisplayLink.m index 4aed812ed7e04f..83fdff06ca5d55 100644 --- a/packages/react-native/React/Base/RCTDisplayLink.m +++ b/packages/react-native/React/Base/RCTDisplayLink.m @@ -19,7 +19,8 @@ #define RCTAssertRunLoop() \ RCTAssert(_runLoop == [NSRunLoop currentRunLoop], @"This method must be called on the CADisplayLink run loop") -@implementation RCTDisplayLink { +@implementation RCTDisplayLink +{ CADisplayLink *_jsDisplayLink; NSMutableSet *_frameUpdateObservers; NSRunLoop *_runLoop; diff --git a/packages/react-native/React/Base/RCTVersion.m b/packages/react-native/React/Base/RCTVersion.m index 69ce4f75320e63..917c106e42e9c3 100644 --- a/packages/react-native/React/Base/RCTVersion.m +++ b/packages/react-native/React/Base/RCTVersion.m @@ -21,9 +21,9 @@ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^(void){ __rnVersion = @{ - RCTVersionMajor: @(1000), - RCTVersionMinor: @(0), - RCTVersionPatch: @(0), + RCTVersionMajor: @(0), + RCTVersionMinor: @(78), + RCTVersionPatch: @(2), RCTVersionPrerelease: [NSNull null], }; }); diff --git a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm index 95395e190cfa8d..91db28b374c8e5 100644 --- a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm +++ b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm @@ -78,7 +78,7 @@ - (void)initialize _currentInterfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation; [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(interfaceFrameDidChange) + selector:@selector(interfaceFrameDidChangeAsync) name:UIDeviceOrientationDidChangeNotification object:nil]; #endif @@ -260,6 +260,23 @@ - (void)interfaceFrameDidChange RCTExecuteOnMainQueue(^{ [weakSelf _interfaceFrameDidChange]; }); + +} + +// Because this RCTDeviceInfo uses dispatch_get_main_queue, RCTExecuteOnMainQueue +// as specified in the interfaceFrameDidChange method will run without delay. +// +// The call to get window measurements may not be accurate as the window +// may not have updated yet. To ensure we get the correct window measurements +// use `dispatch_async` to delay a tick and wait for the window to update. +// +// This bug was observed and reproduced on an iPad but may exist for iPhone as well. +- (void)interfaceFrameDidChangeAsync +{ + __weak __typeof(self) weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf _interfaceFrameDidChange]; + }); } - (void)_interfaceFrameDidChange diff --git a/packages/react-native/React/CoreModules/RCTWebSocketModule.h b/packages/react-native/React/CoreModules/RCTWebSocketModule.h index f92bfc42e3aea3..cf9da4ed2a8f18 100644 --- a/packages/react-native/React/CoreModules/RCTWebSocketModule.h +++ b/packages/react-native/React/CoreModules/RCTWebSocketModule.h @@ -25,6 +25,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)sendData:(NSData *)data forSocketID:(nonnull NSNumber *)socketID; +// Blocking call that waits until there are no more remaining actions on the queue +- (void)flush; + @end @interface RCTBridge (RCTWebSocketModule) diff --git a/packages/react-native/React/CoreModules/RCTWebSocketModule.mm b/packages/react-native/React/CoreModules/RCTWebSocketModule.mm index 3fd7238911f559..eb44017e2d50b2 100644 --- a/packages/react-native/React/CoreModules/RCTWebSocketModule.mm +++ b/packages/react-native/React/CoreModules/RCTWebSocketModule.mm @@ -51,6 +51,14 @@ - (NSArray *)supportedEvents return @[ @"websocketMessage", @"websocketOpen", @"websocketFailed", @"websocketClosed" ]; } + +- (void)flush +{ + for (SRWebSocket *socket in _sockets.allValues) { + [socket close]; + } +} + - (void)invalidate { [super invalidate]; @@ -167,7 +175,6 @@ - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { NSNumber *socketID = [webSocket reactTag]; _contentHandlers[socketID] = nil; - _sockets[socketID] = nil; NSDictionary *body = @{@"message" : error.localizedDescription ?: @"Undefined, error is nil", @"id" : socketID ?: @(-1)}; [self sendEventWithName:@"websocketFailed" body:body]; @@ -180,7 +187,6 @@ - (void)webSocket:(SRWebSocket *)webSocket { NSNumber *socketID = [webSocket reactTag]; _contentHandlers[socketID] = nil; - _sockets[socketID] = nil; [self sendEventWithName:@"websocketClosed" body:@{ @"code" : @(code), diff --git a/packages/react-native/React/DevSupport/RCTPausedInDebuggerOverlayController.mm b/packages/react-native/React/DevSupport/RCTPausedInDebuggerOverlayController.mm index 8be2bce952a330..32697c942eea9a 100644 --- a/packages/react-native/React/DevSupport/RCTPausedInDebuggerOverlayController.mm +++ b/packages/react-native/React/DevSupport/RCTPausedInDebuggerOverlayController.mm @@ -54,13 +54,11 @@ - (void)viewDidLoad ]]; UIButton *resumeButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [resumeButton setImage:[UIImage systemImageNamed:@"forward.frame.fill"] forState:UIControlStateNormal]; + UIImage *image = [UIImage systemImageNamed:@"forward.frame.fill"]; + [resumeButton setImage:image forState:UIControlStateNormal]; + [resumeButton setImage:image forState:UIControlStateDisabled]; resumeButton.tintColor = [UIColor colorWithRed:0.37 green:0.37 blue:0.37 alpha:1]; - resumeButton.configurationUpdateHandler = ^(UIButton *button) { - button.imageView.tintAdjustmentMode = UIViewTintAdjustmentModeNormal; - }; - resumeButton.enabled = NO; [NSLayoutConstraint activateConstraints:@[ [resumeButton.widthAnchor constraintEqualToConstant:48], diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index faa494a615dc0f..6896e9df020091 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -101,11 +101,7 @@ - (void)updateEventEmitter:(const EventEmitter::Shared &)eventEmitter NSMutableDictionary *defaultAttributes = [_backedTextInputView.defaultTextAttributes mutableCopy]; -#if !TARGET_OS_MACCATALYST - RCTWeakEventEmitterWrapper *eventEmitterWrapper = [RCTWeakEventEmitterWrapper new]; - eventEmitterWrapper.eventEmitter = _eventEmitter; - defaultAttributes[RCTAttributedStringEventEmitterKey] = eventEmitterWrapper; -#endif + defaultAttributes[RCTAttributedStringEventEmitterKey] = RCTWrapEventEmitter(_eventEmitter); _backedTextInputView.defaultTextAttributes = defaultAttributes; } @@ -266,10 +262,8 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & if (newTextInputProps.textAttributes != oldTextInputProps.textAttributes) { NSMutableDictionary *defaultAttributes = RCTNSTextAttributesFromTextAttributes(newTextInputProps.getEffectiveTextAttributes(RCTFontSizeMultiplier())); -#if !TARGET_OS_MACCATALYST defaultAttributes[RCTAttributedStringEventEmitterKey] = _backedTextInputView.defaultTextAttributes[RCTAttributedStringEventEmitterKey]; -#endif _backedTextInputView.defaultTextAttributes = defaultAttributes; } diff --git a/packages/react-native/React/Views/RCTSwitchManager.m b/packages/react-native/React/Views/RCTSwitchManager.m index b04b51f844e11a..9f47d5eb7f0eba 100644 --- a/packages/react-native/React/Views/RCTSwitchManager.m +++ b/packages/react-native/React/Views/RCTSwitchManager.m @@ -49,7 +49,17 @@ - (void)onChange:(RCTSwitch *)sender RCT_EXPORT_VIEW_PROPERTY(onTintColor, UIColor); RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor); RCT_EXPORT_VIEW_PROPERTY(thumbTintColor, UIColor); -RCT_REMAP_VIEW_PROPERTY(value, on, BOOL); +//RCT_REMAP_VIEW_PROPERTY(value, on, BOOL); +RCT_CUSTOM_VIEW_PROPERTY(value, BOOL, RCTSwitch) +{ + if (json) { + BOOL on = [RCTConvert BOOL:json]; + if (view.wasOn != on) { + [(UISwitch *)view setOn:on animated:YES]; + view.wasOn = on; + } + } +} RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock); RCT_CUSTOM_VIEW_PROPERTY(disabled, BOOL, RCTSwitch) { diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 26d6ca721334b8..bcd1984958efc1 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1870,38 +1870,6 @@ public abstract interface annotation class com/facebook/react/common/annotations public abstract interface annotation class com/facebook/react/common/annotations/VisibleForTesting : java/lang/annotation/Annotation { } -public final class com/facebook/react/common/assets/ReactFontManager { - public static final field Companion Lcom/facebook/react/common/assets/ReactFontManager$Companion; - public fun ()V - public final fun addCustomFont (Landroid/content/Context;Ljava/lang/String;I)V - public final fun addCustomFont (Ljava/lang/String;Landroid/graphics/Typeface;)V - public static final fun getInstance ()Lcom/facebook/react/common/assets/ReactFontManager; - public final fun getTypeface (Ljava/lang/String;IILandroid/content/res/AssetManager;)Landroid/graphics/Typeface; - public final fun getTypeface (Ljava/lang/String;ILandroid/content/res/AssetManager;)Landroid/graphics/Typeface; - public final fun getTypeface (Ljava/lang/String;IZLandroid/content/res/AssetManager;)Landroid/graphics/Typeface; - public final fun getTypeface (Ljava/lang/String;Lcom/facebook/react/common/assets/ReactFontManager$TypefaceStyle;Landroid/content/res/AssetManager;)Landroid/graphics/Typeface; - public final fun setTypeface (Ljava/lang/String;ILandroid/graphics/Typeface;)V -} - -public final class com/facebook/react/common/assets/ReactFontManager$Companion { - public final fun getInstance ()Lcom/facebook/react/common/assets/ReactFontManager; -} - -public final class com/facebook/react/common/assets/ReactFontManager$TypefaceStyle { - public static final field BOLD I - public static final field Companion Lcom/facebook/react/common/assets/ReactFontManager$TypefaceStyle$Companion; - public static final field NORMAL I - public fun (I)V - public fun (II)V - public synthetic fun (IIILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun (IZ)V - public final fun apply (Landroid/graphics/Typeface;)Landroid/graphics/Typeface; - public final fun getNearestStyle ()I -} - -public final class com/facebook/react/common/assets/ReactFontManager$TypefaceStyle$Companion { -} - public final class com/facebook/react/common/build/ReactBuildConfig { public static final field DEBUG Z public static final field EXOPACKAGE_FLAGS I @@ -2215,7 +2183,7 @@ public abstract interface class com/facebook/react/devsupport/HMRClient : com/fa public abstract fun disable ()V public abstract fun enable ()V public abstract fun registerBundle (Ljava/lang/String;)V - public abstract fun setup (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZ)V + public abstract fun setup (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZLjava/lang/String;)V } public final class com/facebook/react/devsupport/InspectorFlags { @@ -3482,6 +3450,14 @@ public class com/facebook/react/modules/network/ResponseUtil { public static fun onResponseReceived (Lcom/facebook/react/bridge/ReactApplicationContext;IILcom/facebook/react/bridge/WritableMap;Ljava/lang/String;)V } +public final class com/facebook/react/modules/network/ReactCookieJarContainer : com/facebook/react/modules/network/CookieJarContainer { + public fun ()V + public fun loadForRequest (Lokhttp3/HttpUrl;)Ljava/util/List; + public fun removeCookieJar ()V + public fun saveFromResponse (Lokhttp3/HttpUrl;Ljava/util/List;)V + public fun setCookieJar (Lokhttp3/CookieJar;)V +} + public class com/facebook/react/modules/network/TLSSocketFactory : javax/net/ssl/SSLSocketFactory { public fun ()V public fun createSocket (Ljava/lang/String;I)Ljava/net/Socket; @@ -7342,6 +7318,7 @@ public class com/facebook/react/views/text/TextAttributeProps { public static final field TA_KEY_LETTER_SPACING S public static final field TA_KEY_LINE_BREAK_STRATEGY S public static final field TA_KEY_LINE_HEIGHT S + public static final field TA_KEY_MAX_FONT_SIZE_MULTIPLIER S public static final field TA_KEY_OPACITY S public static final field TA_KEY_ROLE S public static final field TA_KEY_TEXT_DECORATION_COLOR S @@ -7374,6 +7351,7 @@ public class com/facebook/react/views/text/TextAttributeProps { protected field mLetterSpacingInput F protected field mLineHeight F protected field mLineHeightInput F + protected field mMaxFontSizeMultiplier F protected field mNumberOfLines I protected field mOpacity F protected field mRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role; @@ -7823,4 +7801,3 @@ public final class com/facebook/react/views/view/WindowUtilKt { public static final fun setStatusBarVisibility (Landroid/view/Window;Z)V public static final fun setSystemBarsTranslucency (Landroid/view/Window;Z)V } - diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index 2f31180ade13f1..e132a49c05c274 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -16,9 +16,9 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("maven-publish") id("com.facebook.react") - alias(libs.plugins.android.library) - alias(libs.plugins.download) - alias(libs.plugins.kotlin.android) + id(libs.plugins.android.library.get().pluginId) + id(libs.plugins.download.get().pluginId) + id(libs.plugins.kotlin.android.get().pluginId) } version = project.findProperty("VERSION_NAME")?.toString()!! @@ -467,6 +467,55 @@ val packageReactNdkLibsForBuck by into("src/main/jni/prebuilt/lib") } +// Derivative of the packageReactNdkDebugLibsForBuck task, appends "debug" to the "into" dir +val packageReactNdkDebugLibsForDiscord by + tasks.registering(Copy::class) { + dependsOn("mergeDebugNativeLibs") + // Shared libraries (.so) are copied from the merged_native_libs folder instead + from("$buildDir/intermediates/merged_native_libs/debug/out/lib/") + exclude("**/libjsc.so") + exclude("**/libhermes.so") + into("src/main/jni/prebuilt/lib/debug") + } + +// Derivative of the packageReactNdkReleaseLibsForBuck task, appends "release" to the "into" dir +val packageReactNdkReleaseLibsForDiscord by + tasks.registering(Copy::class) { + dependsOn("mergeReleaseNativeLibs") + // Shared libraries (.so) are copied from the merged_native_libs folder instead + from("$buildDir/intermediates/merged_native_libs/release/out/lib/") + exclude("**/libjsc.so") + exclude("**/libhermes.so") + into("src/main/jni/prebuilt/lib/release") + } + +val createReactNdkLibraryZipArchiveForDiscord by + tasks.registering(Zip::class) { + // This dependsOn tasks gets all our *.so files into the src/main/jni/prebuilt/lib directory + dependsOn("packageReactNdkDebugLibsForDiscord") + dependsOn("packageReactNdkReleaseLibsForDiscord") + + // A searchable self-documenting name for the build process, but its final packaged name will end up being react-native-{version}.zip + archiveFileName.set("ReactNativeLibrariesForDiscord.zip") + from(layout.projectDirectory.dir("src/main/jni/prebuilt")) { + // Get all *.so files in the prebuilt directory + include("**/*.so") + val fileCopyAction = object: Action { + override fun execute(fcd: FileCopyDetails) { + // Trim down each file's directory to just include the "lib/{debug/release}/{architecture}" part + val relativeFileName = RelativePath(true, *fcd.relativePath.segments.takeLast(4).toTypedArray()) + fcd.relativePath = relativeFileName + } + } + eachFile(fileCopyAction) + // Removes empty dirs resulting from the eachFile directory remapping above + includeEmptyDirs = false + } + + // Place this .zip right into our ReactAndroid directory + destinationDirectory.set(layout.projectDirectory) + } + repositories { // Normally RNGP will set repositories for all modules, // but when consumed from source, we need to re-declare @@ -709,5 +758,15 @@ apply(from = "./publish.gradle") // Please note that the original coordinates, `react-native`, have been voided // as they caused https://github.com/facebook/react-native/issues/35210 publishing { - publications { getByName("release", MavenPublication::class) { artifactId = "react-android" } } + publications { + getByName("release", MavenPublication::class) { + artifactId = "react-android" + } + create("libZip") { + groupId = "com.facebook.react" + version = "test" + artifactId = "discord-rn-libs" + artifact(tasks.named("createReactNdkLibraryZipArchiveForDiscord").get()) + } + } } diff --git a/packages/react-native/ReactAndroid/gradle.properties b/packages/react-native/ReactAndroid/gradle.properties index 8866d933a00e53..a38d501b6839c4 100644 --- a/packages/react-native/ReactAndroid/gradle.properties +++ b/packages/react-native/ReactAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=1000.0.0 +VERSION_NAME=0.78.2 react.internal.publishingGroup=com.facebook.react android.useAndroidX=true diff --git a/packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts b/packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts index d8b0d5f382f564..0bbaa06b11ec3e 100644 --- a/packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts +++ b/packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts @@ -12,8 +12,8 @@ import org.apache.tools.ant.taskdefs.condition.Os plugins { id("maven-publish") id("signing") - alias(libs.plugins.android.library) - alias(libs.plugins.download) + id(libs.plugins.android.library.get().pluginId) + id(libs.plugins.download.get().pluginId) } group = "com.facebook.react" @@ -147,6 +147,7 @@ val configureBuildForHermes by "-B", hermesBuildDir.toString(), "-DJSI_DIR=" + jsiDir.absolutePath, + "-DICU_FOUND=1", )) standardOutput = FileOutputStream("$buildDir/configure-hermesc.log") } @@ -221,6 +222,11 @@ android { ndkVersion = libs.versions.ndkVersion.get() } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + defaultConfig { minSdk = libs.versions.minSdk.get().toInt() diff --git a/packages/react-native/ReactAndroid/publish.gradle b/packages/react-native/ReactAndroid/publish.gradle index 32287a7c81392c..2e44520d6620cb 100644 --- a/packages/react-native/ReactAndroid/publish.gradle +++ b/packages/react-native/ReactAndroid/publish.gradle @@ -68,6 +68,10 @@ publishing { name = "mavenTempLocal" url = mavenTempLocalUrl } + maven { + name = "discord" + url = uri("gcs://discord-maven") + } } if (signingKey && signingPwd) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactAndroidHWInputDeviceHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactAndroidHWInputDeviceHelper.java index c34e63d8489e91..433af185d317b2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactAndroidHWInputDeviceHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactAndroidHWInputDeviceHelper.java @@ -64,6 +64,10 @@ public void handleKeyEvent(KeyEvent ev) { /** Called from {@link ReactRootView} when focused view changes. */ public void onFocusChanged(View newFocusedView) { + if (newFocusedView == null) { + return; + } + if (mLastFocusedViewId == newFocusedView.getId()) { return; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaMethodWrapper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaMethodWrapper.java index daa3eaca785272..d312648f9f4527 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaMethodWrapper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaMethodWrapper.java @@ -356,7 +356,7 @@ public void invoke(JSInstance jsInstance, ReadableArray parameters) { mArgumentExtractors[i].extractArgument(jsInstance, parameters, jsArgumentsConsumed); jsArgumentsConsumed += mArgumentExtractors[i].getJSArgumentsNeeded(); } - } catch (UnexpectedNativeTypeException | NullPointerException e) { + } catch (UnexpectedNativeTypeException | NullPointerException | ClassCastException e) { throw new NativeArgumentsParseException( e.getMessage() + " (constructing arguments for " diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/assets/ReactFontManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/assets/ReactFontManager.kt deleted file mode 100644 index 8850773c4e9c1b..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/assets/ReactFontManager.kt +++ /dev/null @@ -1,197 +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.common.assets - -import android.content.Context -import android.content.res.AssetManager -import android.graphics.Typeface -import android.os.Build -import android.util.SparseArray -import androidx.core.content.res.ResourcesCompat -import com.facebook.react.common.ReactConstants - -/** - * Responsible for loading and caching Typeface objects. - * - * This will first try to load a typeface from the assets/fonts folder. If one is not found in that - * folder, this will fallback to the best matching system typeface. - * - * Custom fonts support the extensions `.ttf` and `.otf` and the variants `bold`, `italic`, and - * `bold_italic`. For example, given a font named "ExampleFontFamily", the following are supported: - * * ExampleFontFamily.ttf (or .otf) - * * ExampleFontFamily_bold.ttf (or .otf) - * * ExampleFontFamily_italic.ttf (or .otf) - * * ExampleFontFamily_bold_italic.ttf (or .otf) - */ -public class ReactFontManager { - - private val fontCache: MutableMap = mutableMapOf() - private val customTypefaceCache: MutableMap = mutableMapOf() - - public fun getTypeface( - fontFamilyName: String, - style: Int, - assetManager: AssetManager?, - ): Typeface = getTypeface(fontFamilyName, TypefaceStyle(style), assetManager) - - public fun getTypeface( - fontFamilyName: String, - weight: Int, - italic: Boolean, - assetManager: AssetManager?, - ): Typeface = getTypeface(fontFamilyName, TypefaceStyle(weight, italic), assetManager) - - public fun getTypeface( - fontFamilyName: String, - style: Int, - weight: Int, - assetManager: AssetManager?, - ): Typeface = getTypeface(fontFamilyName, TypefaceStyle(style, weight), assetManager) - - public fun getTypeface( - fontFamilyName: String, - typefaceStyle: TypefaceStyle, - assetManager: AssetManager?, - ): Typeface { - if (customTypefaceCache.containsKey(fontFamilyName)) { - // Apply `typefaceStyle` because custom fonts configure variants using `app:fontStyle` and - // `app:fontWeight` in their resource XML configuration file. - return typefaceStyle.apply(customTypefaceCache[fontFamilyName]) - } - - val assetFontFamily = fontCache.getOrPut(fontFamilyName) { AssetFontFamily() } - val style = typefaceStyle.nearestStyle - return assetFontFamily.getTypefaceForStyle(style) - ?: createAssetTypeface(fontFamilyName, style, assetManager).also { - assetFontFamily.setTypefaceForStyle(style, it) - } - } - - /* - * This method allows you to load custom fonts from res/font folder as provided font family name. - * Fonts may be one of .ttf, .otf or XML (https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml). - * To support multiple font styles or weights, you must provide a font in XML format. - * - * ReactFontManager.getInstance().addCustomFont(this, "Srisakdi", R.font.srisakdi); - */ - public fun addCustomFont(context: Context, fontFamily: String, fontId: Int): Unit { - addCustomFont(fontFamily, ResourcesCompat.getFont(context, fontId)) - } - - /** - * Equivalent method to {@see addCustomFont(Context, String, int)} which accepts a Typeface - * object. - */ - public fun addCustomFont(fontFamily: String, font: Typeface?): Unit { - if (font != null) { - customTypefaceCache[fontFamily] = font - } - } - - /** - * Add additional font family, or replace the exist one in the font memory cache. - * - * @see [Typeface.DEFAULT] - * @see [Typeface.BOLD] - * @see [Typeface.ITALIC] - * @see [Typeface.BOLD_ITALIC] - */ - public fun setTypeface(fontFamilyName: String, style: Int, typeface: Typeface?): Unit { - if (typeface != null) { - fontCache.getOrPut(fontFamilyName) { AssetFontFamily() }.setTypefaceForStyle(style, typeface) - } - } - - /** Responsible for normalizing style and numeric weight for backward compatibility. */ - public class TypefaceStyle { - private val italic: Boolean - private val weight: Int - - public constructor(weight: Int, italic: Boolean) { - this.italic = italic - this.weight = if (weight == ReactConstants.UNSET) NORMAL else weight - } - - /** - * If `weight` is supplied, it will be combined with the italic bit from `style`. Otherwise, any - * existing weight bit in `style` will be used. - */ - @JvmOverloads - public constructor(style: Int, weight: Int = ReactConstants.UNSET) { - val fixedStyle = if (style == ReactConstants.UNSET) Typeface.NORMAL else style - italic = (fixedStyle and Typeface.ITALIC) != 0 - this.weight = - if (weight == ReactConstants.UNSET) - (if ((fixedStyle and Typeface.BOLD) != 0) BOLD else NORMAL) - else weight - } - - public val nearestStyle: Int - get() = - if (weight < BOLD) { - if (italic) Typeface.ITALIC else Typeface.NORMAL - } else { - if (italic) Typeface.BOLD_ITALIC else Typeface.BOLD - } - - public fun apply(typeface: Typeface?): Typeface = - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - Typeface.create(typeface, nearestStyle) - } else { - Typeface.create(typeface, weight, italic) - } - - public companion object { - public const val BOLD: Int = 700 - public const val NORMAL: Int = 400 - } - } - - public companion object { - - // NOTE: Indices in `EXTENSIONS` correspond to the `TypeFace` style constants. - private val EXTENSIONS = arrayOf("", "_bold", "_italic", "_bold_italic") - private val FILE_EXTENSIONS = arrayOf(".ttf", ".otf") - private const val FONTS_ASSET_PATH = "fonts/" - - private val _instance = ReactFontManager() - - @JvmStatic public fun getInstance(): ReactFontManager = _instance - - private fun createAssetTypeface( - fontFamilyName: String, - style: Int, - assetManager: AssetManager?, - ): Typeface { - if (assetManager != null) { - val extension = EXTENSIONS[style] - for (fileExtension in FILE_EXTENSIONS) { - val fileName = "$FONTS_ASSET_PATH$fontFamilyName$extension$fileExtension" - try { - return Typeface.createFromAsset(assetManager, fileName) - } catch (e: RuntimeException) { - // If the typeface asset does not exist, try another extension. - continue - } - } - } - return Typeface.create(fontFamilyName, style) - } - } - - /** Responsible for caching typefaces for each custom font family. */ - private class AssetFontFamily { - private val typefaceSparseArray: SparseArray = SparseArray(4) - - fun getTypefaceForStyle(style: Int): Typeface? = typefaceSparseArray[style] - - fun setTypefaceForStyle(style: Int, typeface: Typeface?) { - typefaceSparseArray.put(style, typeface) - } - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt index f90ad0246a36f9..662a98ab1f8f41 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt @@ -51,6 +51,11 @@ public object DefaultNewArchitectureEntryPoint { bridgelessEnabled || fabricEnabled override fun useTurboModules(): Boolean = bridgelessEnabled || turboModulesEnabled + + // Fixes reanimated flickering issues where shadow node updates on the UI thread wouldn't be + // propagated back to the react JS fiber node/tree. + override fun useRuntimeShadowNodeReferenceUpdate(): Boolean = + bridgelessEnabled || turboModulesEnabled }) privateFabricEnabled = fabricEnabled diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt index b816bad9ae6b27..f3391c5862fbb6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt @@ -35,12 +35,7 @@ protected constructor( ) : ReactNativeHost(application) { override fun getReactPackageTurboModuleManagerDelegateBuilder(): - ReactPackageTurboModuleManagerDelegate.Builder? = - if (isNewArchEnabled) { - DefaultTurboModuleManagerDelegate.Builder() - } else { - null - } + ReactPackageTurboModuleManagerDelegate.Builder? = DefaultTurboModuleManagerDelegate.Builder() override fun getUIManagerProvider(): UIManagerProvider? = if (isNewArchEnabled) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index 8278b93d955936..6f9aa23a0d5e88 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -685,10 +685,12 @@ private void resetCurrentContext(@Nullable ReactContext reactContext) { URL sourceUrl = new URL(getSourceUrl()); String path = sourceUrl.getPath().substring(1); // strip initial slash in path String host = sourceUrl.getHost(); + String scheme = sourceUrl.getProtocol(); int port = sourceUrl.getPort() != -1 ? sourceUrl.getPort() : sourceUrl.getDefaultPort(); mCurrentReactContext .getJSModule(HMRClient.class) - .setup("android", path, host, port, mDevSettings.isHotModuleReplacementEnabled()); + .setup( + "android", path, host, port, mDevSettings.isHotModuleReplacementEnabled(), scheme); } catch (MalformedURLException e) { showNewJavaError(e.getMessage(), e); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/HMRClient.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/HMRClient.java index 7807ef449018a5..143d9cd168ac09 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/HMRClient.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/HMRClient.java @@ -26,8 +26,11 @@ public interface HMRClient extends JavaScriptModule { * @param host The host that the HMRClient should communicate with. * @param port The port that the HMRClient should communicate with on the host. * @param isEnabled Whether HMR is enabled initially. + * @param scheme The protocol that the HMRClient should communicate with on the host (defaults to + * http). */ - void setup(String platform, String bundleEntry, String host, int port, boolean isEnabled); + void setup( + String platform, String bundleEntry, String host, int port, boolean isEnabled, String scheme); /** Registers an additional JS bundle with HMRClient. */ void registerBundle(String bundleUrl); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 6d4c7155803aa4..2e8cab11087744 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -173,7 +173,7 @@ public class FabricUIManager private final CopyOnWriteArrayList mListeners = new CopyOnWriteArrayList<>(); private boolean mMountNotificationScheduled = false; - private final List mMountedSurfaceIds = new ArrayList<>(); + private List mSurfaceIdsWithPendingMountNotification = new ArrayList<>(); @ThreadConfined(UI) @NonNull @@ -1250,12 +1250,15 @@ public void didMountItems(@Nullable List mountItems) { // Collect surface IDs for all the mount items for (MountItem mountItem : mountItems) { - if (mountItem != null && !mMountedSurfaceIds.contains(mountItem.getSurfaceId())) { - mMountedSurfaceIds.add(mountItem.getSurfaceId()); + if (mountItem != null + && !mSurfaceIdsWithPendingMountNotification.contains(mountItem.getSurfaceId())) { + mSurfaceIdsWithPendingMountNotification.add(mountItem.getSurfaceId()); } } - if (!mMountNotificationScheduled && !mMountedSurfaceIds.isEmpty()) { + if (!mMountNotificationScheduled && !mSurfaceIdsWithPendingMountNotification.isEmpty()) { + mMountNotificationScheduled = true; + // Notify mount when the effects are visible and prevent mount hooks to // delay paint. UiThreadUtil.getUiThreadHandler() @@ -1265,17 +1268,19 @@ public void didMountItems(@Nullable List mountItems) { public void run() { mMountNotificationScheduled = false; + // Create a copy in case mount hooks trigger more mutations + final List surfaceIdsToReportMount = + mSurfaceIdsWithPendingMountNotification; + mSurfaceIdsWithPendingMountNotification = new ArrayList<>(); + final @Nullable FabricUIManagerBinding binding = mBinding; if (binding == null || mDestroyed) { - mMountedSurfaceIds.clear(); return; } - for (int surfaceId : mMountedSurfaceIds) { + for (int surfaceId : surfaceIdsToReportMount) { binding.reportMount(surfaceId); } - - mMountedSurfaceIds.clear(); } }); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java index 7523a99a7d306e..574346f475b20c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java @@ -331,14 +331,11 @@ public void clearJSResponder() { @AnyThread @ThreadConfined(ANY) public @Nullable EventEmitterWrapper getEventEmitter(int surfaceId, int reactTag) { - SurfaceMountingManager surfaceMountingManager = - (surfaceId == ViewUtil.NO_SURFACE_ID - ? getSurfaceManagerForView(reactTag) - : getSurfaceManager(surfaceId)); - if (surfaceMountingManager == null) { + SurfaceMountingManager smm = getSurfaceMountingManager(surfaceId, reactTag); + if (smm == null) { return null; } - return surfaceMountingManager.getEventEmitter(reactTag); + return smm.getEventEmitter(reactTag); } /** @@ -458,11 +455,21 @@ public void enqueuePendingEvent( boolean canCoalesceEvent, @Nullable WritableMap params, @EventCategoryDef int eventCategory) { - @Nullable SurfaceMountingManager smm = getSurfaceManager(surfaceId); + SurfaceMountingManager smm = getSurfaceMountingManager(surfaceId, reactTag); if (smm == null) { - // Cannot queue event without valid surface mountng manager. Do nothing here. + FLog.d( + TAG, + "Cannot queue event without valid surface mounting manager for tag: %d, surfaceId: %d", + reactTag, + surfaceId); return; } smm.enqueuePendingEvent(reactTag, eventName, canCoalesceEvent, params, eventCategory); } + + private @Nullable SurfaceMountingManager getSurfaceMountingManager(int surfaceId, int reactTag) { + return (surfaceId == ViewUtil.NO_SURFACE_ID + ? getSurfaceManagerForView(reactTag) + : getSurfaceManager(surfaceId)); + } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 53c4bd6c186d09..ee33a8467aab94 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3e10f8d2f623da3b7b502d8fa78f82a4>> + * @generated SignedSource<<99da5cf948e469e385bd70b4c59cd764>> */ /** @@ -286,6 +286,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun useRuntimeShadowNodeReferenceUpdate(): Boolean = accessor.useRuntimeShadowNodeReferenceUpdate() + /** + * Use the state stored on the source shadow node when cloning it instead of reading in the most recent state on the shadow node family. + */ + @JvmStatic + public fun useShadowNodeStateOnClone(): Boolean = accessor.useShadowNodeStateOnClone() + /** * In Bridgeless mode, should legacy NativeModules use the TurboModule system? */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index c25a7ad0a77d46..f16e6b88855156 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<497bbb23778fe0f9763e9bfa715ea3aa>> + * @generated SignedSource<<5e1d8c0e728715d4110b6d1d156357c5>> */ /** @@ -63,6 +63,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null private var useRawPropsJsiValueCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateCache: Boolean? = null + private var useShadowNodeStateOnCloneCache: Boolean? = null private var useTurboModuleInteropCache: Boolean? = null private var useTurboModulesCache: Boolean? = null @@ -453,6 +454,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun useShadowNodeStateOnClone(): Boolean { + var cached = useShadowNodeStateOnCloneCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.useShadowNodeStateOnClone() + useShadowNodeStateOnCloneCache = cached + } + return cached + } + override fun useTurboModuleInterop(): Boolean { var cached = useTurboModuleInteropCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 181c06d9c7cb03..cd57aa387902ea 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -114,6 +114,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun useRuntimeShadowNodeReferenceUpdate(): Boolean + @DoNotStrip @JvmStatic public external fun useShadowNodeStateOnClone(): Boolean + @DoNotStrip @JvmStatic public external fun useTurboModuleInterop(): Boolean @DoNotStrip @JvmStatic public external fun useTurboModules(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index ca2265e22368bb..6cdd06a7ec7fe8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5de2cfc00f486b7d07266939ce18a397>> + * @generated SignedSource<<11d93a900862ed8ce98f90f9af2de47b>> */ /** @@ -109,6 +109,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun useRuntimeShadowNodeReferenceUpdate(): Boolean = true + override fun useShadowNodeStateOnClone(): Boolean = true + override fun useTurboModuleInterop(): Boolean = false override fun useTurboModules(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 0200670573d136..7c22c3bdd3d0dd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<0614fa80cbc66806fa45aef70f34e2d7>> */ /** @@ -67,6 +67,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null private var useRawPropsJsiValueCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateCache: Boolean? = null + private var useShadowNodeStateOnCloneCache: Boolean? = null private var useTurboModuleInteropCache: Boolean? = null private var useTurboModulesCache: Boolean? = null @@ -500,6 +501,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun useShadowNodeStateOnClone(): Boolean { + var cached = useShadowNodeStateOnCloneCache + if (cached == null) { + cached = currentProvider.useShadowNodeStateOnClone() + accessedFeatureFlags.add("useShadowNodeStateOnClone") + useShadowNodeStateOnCloneCache = cached + } + return cached + } + override fun useTurboModuleInterop(): Boolean { var cached = useTurboModuleInteropCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index e3fb3270f52fce..31c4f90f10b730 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3cd802bdd1d383ea0668e43319d53b3f>> + * @generated SignedSource<<5f4ff90382b2d69df401535cb33e64c5>> */ /** @@ -109,6 +109,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun useRuntimeShadowNodeReferenceUpdate(): Boolean + @DoNotStrip public fun useShadowNodeStateOnClone(): Boolean + @DoNotStrip public fun useTurboModuleInterop(): Boolean @DoNotStrip public fun useTurboModules(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/AppStateModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/AppStateModule.kt index 543ab79fba8677..385fd1582a261c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/AppStateModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/AppStateModule.kt @@ -7,6 +7,8 @@ package com.facebook.react.modules.appstate +import android.app.ActivityManager +import com.facebook.common.logging.FLog import com.facebook.fbreact.specs.NativeAppStateSpec import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.Callback @@ -26,11 +28,27 @@ internal class AppStateModule(reactContext: ReactApplicationContext) : init { reactContext.addLifecycleEventListener(this) reactContext.addWindowFocusChangeListener(this) + val isAppForegroundedByMemoryState = isAppForegroundedByMemoryState() + // pasten: temporary debug log - remove after we validate with real users + FLog.w("AppStateModule", "initial isAppForegroundedByMemoryState = $isAppForegroundedByMemoryState, " + + "reactContext.lifecycleState = ${reactContext.lifecycleState}") + appState = if (reactContext.lifecycleState === LifecycleState.RESUMED) APP_STATE_ACTIVE + // pasten: during cold start appState=APP_STATE_BACKGROUND while tha is actually in the foreground + // best effort foreground detection when LifecycleState.BEFORE_CREATE (which is the initial state) + else if (reactContext.lifecycleState === LifecycleState.BEFORE_CREATE && isAppForegroundedByMemoryState) { + APP_STATE_ACTIVE + } else if (isAppForegroundedByMemoryState) APP_STATE_ACTIVE else APP_STATE_BACKGROUND } + private fun isAppForegroundedByMemoryState(): Boolean { + return ActivityManager.RunningAppProcessInfo().apply { + ActivityManager.getMyMemoryState(this) + }.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND + } + public override fun getTypedExportedConstants(): Map = mapOf(INITIAL_STATE to appState) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index 5b24caff523e15..d9ef5d90de1982 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -177,7 +177,7 @@ public static void setCustomClientBuilder( * https://github.com/facebook/react-native/pull/37798#pullrequestreview-1518338914 */ @Deprecated - public interface CustomClientBuilder + public static interface CustomClientBuilder extends com.facebook.react.modules.network.CustomClientBuilder {} private static void applyCustomBuilder(OkHttpClient.Builder builder) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ReactCookieJarContainer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ReactCookieJarContainer.kt index 85266bc8904fa0..8cc78e0a75a040 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ReactCookieJarContainer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ReactCookieJarContainer.kt @@ -16,7 +16,7 @@ import okhttp3.Headers import okhttp3.HttpUrl /** Basic okhttp3 CookieJar container */ -internal class ReactCookieJarContainer : CookieJarContainer { +public class ReactCookieJarContainer : CookieJarContainer { private var cookieJar: CookieJar? = null diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java index dd881ce78cacdc..2c82f1d3cc4421 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java @@ -15,8 +15,8 @@ public class ReactNativeVersion { public static final Map VERSION = MapBuilder.of( - "major", 1000, - "minor", 0, - "patch", 0, + "major", 0, + "minor", 78, + "patch", 2, "prerelease", null); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt index 06c891c51f3913..861d776f8dde14 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt @@ -44,10 +44,17 @@ public class WebSocketModule(context: ReactApplicationContext) : public fun onMessage(byteString: ByteString, params: WritableMap) } + public interface OnOpenHandler { + + public fun onOpen(webSocket: WebSocket, socketId: Int) + } + private val webSocketConnections: MutableMap = ConcurrentHashMap() private val contentHandlers: MutableMap = ConcurrentHashMap() private val cookieHandler: ForwardingCookieHandler = ForwardingCookieHandler() + public var mOnOpenHandler: OnOpenHandler? = null + override fun invalidate() { for (socket in webSocketConnections.values) { socket.close(1_001 /* endpoint is going away */, null) @@ -145,6 +152,7 @@ public class WebSocketModule(context: ReactApplicationContext) : params.putInt("id", id) params.putString("protocol", response.header("Sec-WebSocket-Protocol", "")) sendEvent("websocketOpen", params) + mOnOpenHandler?.onOpen(webSocket, id) } override fun onClosing(websocket: WebSocket, code: Int, reason: String) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactOverflowView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactOverflowView.kt index 155715754b6e18..71c505b63757a5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactOverflowView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactOverflowView.kt @@ -17,5 +17,5 @@ public interface ReactOverflowView { * Gets the overflow state of a view. If set, this should be one of [ViewProps#HIDDEN], * [ViewProps#VISIBLE] or [ViewProps#SCROLL]. */ - public fun getOverflow(): String? + public val overflow: String? } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactPointerEventsView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactPointerEventsView.kt index 0cd84c41bbcec2..f9b5a2d9d0e5f3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactPointerEventsView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactPointerEventsView.kt @@ -13,6 +13,6 @@ package com.facebook.react.uimanager */ public interface ReactPointerEventsView { - /** Return the PointerEvents of the View. */ - public fun getPointerEvents(): PointerEvents + /** The PointerEvents of the View. */ + public val pointerEvents: PointerEvents } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIBlock.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIBlock.kt index e4879d46d51721..43852f80646cca 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIBlock.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIBlock.kt @@ -9,5 +9,5 @@ package com.facebook.react.uimanager /** A task to execute on the UI View for third party libraries. */ public fun interface UIBlock { - public fun execute(nativeViewHierarchyManager: NativeViewHierarchyManager?): Unit + public fun execute(nativeViewHierarchyManager: NativeViewHierarchyManager): Unit } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 7a3cfc55ae68ec..8481e0cea4e15f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -148,6 +148,8 @@ public UIManagerModule( minTimeLeftInFrameForNonBatchedOperationMs); reactContext.addLifecycleEventListener(this); + mEventDispatcher.registerEventEmitter( + DEFAULT, getReactApplicationContext().getJSModule(RCTEventEmitter.class)); } /** @@ -175,8 +177,6 @@ public Map getConstants() { public void initialize() { getReactApplicationContext().registerComponentCallbacks(mMemoryTrimCallback); getReactApplicationContext().registerComponentCallbacks(mViewManagerRegistry); - mEventDispatcher.registerEventEmitter( - DEFAULT, getReactApplicationContext().getJSModule(RCTEventEmitter.class)); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt index 7105d09d60a53a..cc82e684490a3c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt @@ -16,6 +16,7 @@ import android.graphics.drawable.LayerDrawable import android.os.Build import com.facebook.react.common.annotations.UnstableReactNativeAPI import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags +import com.facebook.react.uimanager.PixelUtil.dpToPx import com.facebook.react.uimanager.style.BorderInsets import com.facebook.react.uimanager.style.BorderRadiusStyle @@ -198,17 +199,17 @@ internal class CompositeBackgroundDrawable( computedBorderRadius?.let { pathForOutline.addRoundRect( - RectF(bounds), - floatArrayOf( - it.topLeft.horizontal + (computedBorderInsets?.left ?: 0f), - it.topLeft.vertical + (computedBorderInsets?.top ?: 0f), - it.topRight.horizontal + (computedBorderInsets?.right ?: 0f), - it.topRight.vertical + (computedBorderInsets?.top ?: 0f), - it.bottomRight.horizontal + (computedBorderInsets?.right ?: 0f), - it.bottomRight.vertical + (computedBorderInsets?.bottom ?: 0f), - it.bottomLeft.horizontal + (computedBorderInsets?.left ?: 0f), - it.bottomLeft.vertical) + (computedBorderInsets?.bottom ?: 0f), - Path.Direction.CW) + RectF(bounds), + floatArrayOf( + (it.topLeft.horizontal + (computedBorderInsets?.left ?: 0f)).dpToPx(), + (it.topLeft.vertical + (computedBorderInsets?.top ?: 0f)).dpToPx(), + (it.topRight.horizontal + (computedBorderInsets?.right ?: 0f)).dpToPx(), + (it.topRight.vertical + (computedBorderInsets?.top ?: 0f)).dpToPx(), + (it.bottomRight.horizontal + (computedBorderInsets?.right ?: 0f)).dpToPx(), + (it.bottomRight.vertical + (computedBorderInsets?.bottom ?: 0f)).dpToPx(), + (it.bottomLeft.horizontal + (computedBorderInsets?.left ?: 0f)).dpToPx(), + (it.bottomLeft.vertical + (computedBorderInsets?.bottom ?: 0f)).dpToPx()), + Path.Direction.CW) } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.kt index 5abca56df78ceb..403583f205acf3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.kt @@ -93,6 +93,11 @@ public constructor( public override fun getName(): String = REACT_CLASS + @ReactProp(name = "useSmallCache") + public fun setUseSmallCache(view: ReactImageView, useSmallCache: Boolean) { + view.setUseSmallCache(useSmallCache) + } + @ReactProp(name = "accessible") public fun setAccessible(view: ReactImageView, accessible: Boolean) { view.isFocusable = accessible @@ -124,7 +129,7 @@ public constructor( } } - @ReactProp(name = "defaultSource", customType = "ImageSource") + @ReactProp(name = "defaultSource") public fun setDefaultSource(view: ReactImageView, source: String?) { view.setDefaultSource(source) } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.kt index 4662a3bc074eb2..3243031c9ced4a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.kt @@ -22,6 +22,7 @@ import android.graphics.Shader.TileMode import android.graphics.drawable.Animatable import android.graphics.drawable.Drawable import android.net.Uri +import android.widget.Toast import com.facebook.common.references.CloseableReference import com.facebook.common.util.UriUtil import com.facebook.drawee.backends.pipeline.Fresco @@ -97,6 +98,7 @@ public class ReactImageView( private var scaleType = defaultValue() private var tileMode = defaultTileMode() private var isDirty = false + private var useSmallCache = false private var tilePostprocessor: TilePostprocessor? = null private var iterativeBoxBlurPostProcessor: IterativeBoxBlurPostProcessor? = null private var downloadListener: ReactImageDownloadListener? = null @@ -120,6 +122,13 @@ public class ReactImageView( } } + public fun setUseSmallCache(useSmallCache: Boolean) { + if (this.useSmallCache != useSmallCache) { + this.useSmallCache = useSmallCache + isDirty = true + } + } + public fun setShouldNotifyLoadEvents(shouldNotify: Boolean) { // Skip update if shouldNotify is already in sync with the download listener if (shouldNotify == (downloadListener != null)) { @@ -282,15 +291,32 @@ public class ReactImageView( for (idx in 0 until sources.size()) { val source = sources.getMap(idx) ?: continue val cacheControl = computeCacheControl(source.getString("cache")) + val uri = source.getString("uri") + val isForceCached = if (source.hasKey("isForceCached")) { + source.getBoolean("isForceCached") + } else { + false + } + val width = if (source.hasKey("width")) { + source.getDouble("width") + } else { + 0.0 + } + val height = if (source.hasKey("height")) { + source.getDouble("height") + } else { + 0.0 + } var imageSource = ImageSource( context, - source.getString("uri"), - source.getDouble("width"), - source.getDouble("height"), - cacheControl) + uri, + width, + height, + cacheControl, + isForceCached) if (Uri.EMPTY == imageSource.uri) { - warnImageSource(source.getString("uri")) + warnImageSource(uri) imageSource = getTransparentBitmapImageSource(context) } tmpSources.add(imageSource) @@ -462,6 +488,12 @@ public class ReactImageView( imageRequestBuilder.setDownsampleOverride(DownsampleMode.NEVER) } + if (useSmallCache) { + imageRequestBuilder.setCacheChoice(ImageRequest.CacheChoice.SMALL); + } else { + imageRequestBuilder.setCacheChoice(ImageRequest.CacheChoice.DEFAULT); + } + val imageRequest: ImageRequest = ReactNetworkImageRequest.fromBuilderWithHeaders(imageRequestBuilder, headers, cacheControl) @@ -491,7 +523,15 @@ public class ReactImageView( if (resizeMethod == ImageResizeMethod.NONE) { cachedImageRequestBuilder.setDownsampleOverride(DownsampleMode.NEVER) } - builder.setLowResImageRequest(cachedImageRequestBuilder.build()) + + if (useSmallCache) { + cachedImageRequestBuilder.setCacheChoice(ImageRequest.CacheChoice.SMALL); + } else { + cachedImageRequestBuilder.setCacheChoice(ImageRequest.CacheChoice.DEFAULT); + } + + val cachedImageRequest = cachedImageRequestBuilder.build() + builder.setLowResImageRequest(cachedImageRequest) } if (downloadListener != null && controllerForTesting != null) { @@ -583,6 +623,12 @@ public class ReactImageView( // 4. Rinse and repeat. if (ReactBuildConfig.DEBUG && !ReactNativeFeatureFlags.enableBridgelessArchitecture()) { RNLog.w(context as ReactContext, "ReactImageView: Image source \"$uri\" doesn't exist") + + Toast.makeText( + context, + "Warning: Image source \"$uri\" doesn't exist", + Toast.LENGTH_SHORT) + .show(); } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.kt index 289dd445bfb006..2acbcbb37a1982 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.kt @@ -10,6 +10,7 @@ package com.facebook.react.views.imagehelper import android.content.Context import android.net.Uri import com.facebook.react.modules.fresco.ImageCacheControl +import androidx.arch.core.util.Function import java.util.Objects /** Class describing an image source (network URI or resource) and size. */ @@ -18,10 +19,11 @@ public open class ImageSource constructor( context: Context, /** Get the source of this image, as it was passed to the constructor. */ - public val source: String?, + public var source: String?, width: Double = 0.0, height: Double = 0.0, public val cacheControl: ImageCacheControl = ImageCacheControl.DEFAULT, + public val isForceCached: Boolean = false ) { /** Get the URI for this image - can be either a parsed network URI or a resource URI. */ @@ -55,6 +57,9 @@ constructor( private fun computeUri(context: Context): Uri = try { + sourceOverride?.let { + source = it.apply(source) + } val uri = Uri.parse(source) // Verify scheme is set, so that relative uri (used by static resources) are not handled. if (uri.scheme == null) computeLocalUri(context) else uri @@ -68,6 +73,7 @@ constructor( } public companion object { + public var sourceOverride: Function? = null private const val TRANSPARENT_BITMAP_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/MultiSourceHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/MultiSourceHelper.kt index c7619aac19b696..cfee94cfa28576 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/MultiSourceHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/MultiSourceHelper.kt @@ -59,8 +59,10 @@ public object MultiSourceHelper { for (source in sources) { val precision = Math.abs(1.0 - source.size / viewArea) if (precision < bestPrecision) { - bestPrecision = precision - best = source + if (!source.isForceCached) { + bestPrecision = precision + best = source + } } if (precision < bestCachePrecision && source.cacheControl != ImageCacheControl.RELOAD && @@ -71,6 +73,10 @@ public object MultiSourceHelper { bestCachePrecision = precision bestCached = source } + if (source.isForceCached) { + bestCachePrecision = 0.0 + bestCached = source + } } if (bestCached != null && best != null && bestCached.source == best.source) { bestCached = null diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt index ff673906481810..a811a613524529 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt @@ -27,6 +27,11 @@ import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityNodeInfo import android.widget.FrameLayout import androidx.annotation.UiThread +import androidx.core.view.ViewCompat +import androidx.core.content.ContextCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsCompat.CONSUMED import com.facebook.common.logging.FLog import com.facebook.react.R import com.facebook.react.bridge.GuardedRunnable @@ -38,6 +43,7 @@ import com.facebook.react.bridge.WritableNativeMap import com.facebook.react.common.ReactConstants import com.facebook.react.common.annotations.VisibleForTesting import com.facebook.react.config.ReactFeatureFlags +import com.facebook.react.uimanager.DisplayMetricsHolder import com.facebook.react.uimanager.JSPointerDispatcher import com.facebook.react.uimanager.JSTouchDispatcher import com.facebook.react.uimanager.PixelUtil.pxToDp @@ -50,6 +56,7 @@ import com.facebook.react.views.common.ContextUtils import com.facebook.react.views.view.ReactViewGroup import com.facebook.react.views.view.setStatusBarTranslucency import com.facebook.react.views.view.setSystemBarsTranslucency +import com.facebook.yoga.annotations.DoNotStrip import java.util.Objects /** @@ -120,6 +127,7 @@ public class ReactModalHostView(context: ThemedReactContext) : private var createNewDialog = false init { + initStatusBarHeight(context) dialogRootViewGroup = DialogRootViewGroup(context) } @@ -265,6 +273,15 @@ public class ReactModalHostView(context: ThemedReactContext) : WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) + // Enabled Edge to Edge modal when transparent/translucent system UI. + if (transparent && statusBarTranslucent) { + newDialog.window?.let { + it.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + it.navigationBarColor = ContextCompat.getColor(context, android.R.color.transparent); + WindowCompat.setDecorFitsSystemWindows(it, false) + }; + } + newDialog.setContentView(contentView) updateProperties() @@ -401,6 +418,18 @@ public class ReactModalHostView(context: ThemedReactContext) : } } + private fun initStatusBarHeight(reactContext: ReactContext) { + val windowInsets = + reactContext.getCurrentActivity()?.window?.decorView?.let(ViewCompat::getRootWindowInsets) + statusBarHeight = + windowInsets + ?.getInsets( + WindowInsetsCompat.Type.statusBars() or + WindowInsetsCompat.Type.navigationBars() or + WindowInsetsCompat.Type.displayCutout()) + ?.top ?: 0 + } + /** * Sets the testID on the DialogRootViewGroup. Since the accessibility events are not triggered on * the on the ReactModalHostView, the testID is forwarded to the DialogRootViewGroup to set the @@ -419,8 +448,22 @@ public class ReactModalHostView(context: ThemedReactContext) : private companion object { private const val TAG = "ReactModalHost" + + // We store the status bar height to be able to properly position + // the modal on the first render. + private var statusBarHeight = 0 + + @JvmStatic + @DoNotStrip + private fun getScreenDisplayMetricsWithoutInsets(): FloatArray { + val displayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics() + return floatArrayOf( + displayMetrics.widthPixels.toFloat().pxToDp(), + (displayMetrics.heightPixels - statusBarHeight).toFloat().pxToDp()) + } } + /** * DialogRootViewGroup is the ViewGroup which contains all the children of a Modal. It gets all * child information forwarded from [ReactModalHostView] and uses that to create children. It is @@ -468,10 +511,21 @@ public class ReactModalHostView(context: ThemedReactContext) : updateState(viewWidth, viewHeight) } + /** + * Updates the shadow tree via the local fabric view state manager. Can noop if the same values + * are passed multiple times. Can also ignore params if the local variables for viewWidth & + * viewHeight are non-zero. + * + * @param width target width of the container as pixels. Will be converted to DIP. + * @param height target height of the container as pixels. Will be converted to DIP. + */ @UiThread public fun updateState(width: Int, height: Int) { - val realWidth: Float = width.toFloat().pxToDp() - val realHeight: Float = height.toFloat().pxToDp() + // Once viewWidth & viewHeight are set by an onSizeChanged callback they become our source + // of truth. This makes the fabric renderer function like the paper renderer is currently + // functioning. + val realWidth = (if ((viewWidth > 0)) viewWidth else width).toFloat().pxToDp() + val realHeight = (if ((viewHeight > 0)) viewHeight else height).toFloat().pxToDp() stateWrapper?.let { sw -> // new architecture @@ -546,3 +600,4 @@ public class ReactModalHostView(context: ThemedReactContext) : } } } + diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index adf92c118eae31..604b93be4be06d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -83,6 +83,8 @@ public class ReactScrollView extends ScrollView HasScrollEventThrottle, HasSmoothScroll { + static Integer MAX_FLING_VELOCITY = null; + private static @Nullable Field sScrollerField; private static boolean sTriedToGetScrollerField = false; @@ -557,7 +559,14 @@ public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point of @Override public void fling(int velocityY) { - final int correctedVelocityY = correctFlingVelocityY(velocityY); + final int correctedVelocityY; + if (MAX_FLING_VELOCITY != null) { + int velocityYBeforeMaxFling = correctFlingVelocityY(velocityY); + correctedVelocityY = (int) ((Math.min(Math.abs(velocityYBeforeMaxFling), MAX_FLING_VELOCITY)) * + Math.signum(velocityYBeforeMaxFling)); + } else { + correctedVelocityY = correctFlingVelocityY(velocityY); + } if (mPagingEnabled) { flingAndSnap(correctedVelocityY); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/CreateTypefaceObject.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/CreateTypefaceObject.kt new file mode 100644 index 00000000000000..604f4162151fc6 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/CreateTypefaceObject.kt @@ -0,0 +1,9 @@ +package com.facebook.react.views.text + +import android.content.res.AssetManager + +public class CreateTypefaceObject( + public var fontFamilyName: String, + public var style: Int, + public var assetManager: AssetManager +) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java index 6cb16d00028de2..8a38e05a5b345f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java @@ -20,6 +20,7 @@ import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.ReadableType; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.IllegalViewOperationException; import com.facebook.react.uimanager.LayoutShadowNode; @@ -34,6 +35,7 @@ import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan; import com.facebook.react.views.text.internal.span.CustomLineHeightSpan; import com.facebook.react.views.text.internal.span.CustomStyleSpan; +import com.facebook.react.views.text.internal.span.LinearGradientSpan; import com.facebook.react.views.text.internal.span.ReactAbsoluteSizeSpan; import com.facebook.react.views.text.internal.span.ReactBackgroundColorSpan; import com.facebook.react.views.text.internal.span.ReactClickableSpan; @@ -161,8 +163,11 @@ private static void buildSpannedFromShadowNode( int end = sb.length(); if (end >= start) { if (textShadowNode.mIsColorSet) { - ops.add( - new SetSpanOperation(start, end, new ReactForegroundColorSpan(textShadowNode.mColor))); + ops.add(new SetSpanOperation(start, end, new ReactForegroundColorSpan(textShadowNode.mColor))); + } + if (textShadowNode.mGradientColors != null && textShadowNode.mGradientColors.length >= 2) { + int effectiveFontSize = textAttributes.getEffectiveFontSize(); + ops.add(new SetSpanOperation(start, end, new LinearGradientSpan(start * effectiveFontSize, textShadowNode.mGradientColors))); } if (textShadowNode.mIsBackgroundColorSet) { ops.add( @@ -319,6 +324,8 @@ protected Spannable spannedFromShadowNode( protected boolean mIsBackgroundColorSet = false; protected int mBackgroundColor; + protected @Nullable int[] mGradientColors = null; + protected @Nullable AccessibilityRole mAccessibilityRole = null; protected @Nullable Role mRole = null; @@ -479,6 +486,30 @@ public void setColor(@Nullable Integer color) { markUpdated(); } + @ReactProp(name = "gradientColors") + public void setGradientColors(@Nullable ReadableArray gradientColors) { + if (gradientColors != null) { + ArrayList colors = new ArrayList(); + + for (int i = 0; i < gradientColors.size(); i++) { + if (!gradientColors.isNull(i) && gradientColors.getType(i) == ReadableType.Number) { + int color = gradientColors.getInt(i); + colors.add(color); + } + } + + int colorsSize = colors.size(); + if (colorsSize >= 2) { + int[] colorsAsList = new int[colorsSize]; + for (int i = 0; i < colorsSize; i++) { + colorsAsList[i] = colors.get(i); + } + + mGradientColors = colorsAsList; + } + } + } + @ReactProp(name = ViewProps.BACKGROUND_COLOR, customType = "Color") public void setBackgroundColor(@Nullable Integer color) { // Background color needs to be handled here for virtual nodes so it can be incorporated into diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.kt index 5b4cee489b41a7..c67a11a617b97b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactFontManager.kt @@ -10,51 +10,270 @@ package com.facebook.react.views.text import android.content.Context import android.content.res.AssetManager import android.graphics.Typeface -import com.facebook.react.common.assets.ReactFontManager as ReactFontAssetManager +import android.graphics.fonts.Font +import android.graphics.fonts.FontFamily +import android.os.Build +import android.util.SparseArray +import androidx.annotation.Nullable +import androidx.annotation.RequiresApi +import androidx.core.content.res.ResourcesCompat +import com.facebook.infer.annotation.Nullsafe +import androidx.arch.core.util.Function +import com.facebook.react.common.ReactConstants +import java.io.IOException +import java.util.ArrayList +import java.util.HashMap -/** Responsible for loading and caching Typeface objects. */ -@Deprecated( - message = - "This class is deprecated and will be deleted in the near future. Please use [com.facebook.react.common.assets.ReactFontManager] instead.") -@Suppress("DEPRECATION") -public class ReactFontManager private constructor(private val delegate: ReactFontAssetManager) { +/** + * Responsible for loading and caching Typeface objects. + * + * @deprecated This class is deprecated and it will be deleted in the near future. Please use + * [com.facebook.react.common.assets.ReactFontManager] instead. + */ +@Nullsafe(Nullsafe.Mode.LOCAL) +public class ReactFontManager private constructor() { + + public companion object { + public var createAssetTypefaceOverride: Function? = null + + // NOTE: Indices in `EXTENSIONS` correspond to the `TypeFace` style constants. + private val EXTENSIONS = arrayOf("", "_bold", "_italic", "_bold_italic") + private val FILE_EXTENSIONS = arrayOf(".ttf", ".otf") + private const val FONTS_ASSET_PATH = "fonts/" + + private var sReactFontManagerInstance: ReactFontManager? = null + + @JvmStatic + public fun getInstance(): ReactFontManager { + return sReactFontManagerInstance ?: ReactFontManager().also { sReactFontManagerInstance = it } + } + + private fun createAssetTypeface( + fontFamilyName: String, + style: Int, + assetManager: AssetManager + ): Typeface { + createAssetTypefaceOverride?.let { override -> + return override.apply(CreateTypefaceObject(fontFamilyName, style, assetManager)) + } + + // This is the original RN logic for getting the typeface. + val extension = EXTENSIONS[style] + for (fileExtension in FILE_EXTENSIONS) { + val fileName = StringBuilder() + .append(FONTS_ASSET_PATH) + .append(fontFamilyName) + .append(extension) + .append(fileExtension) + .toString() + try { + return Typeface.createFromAsset(assetManager, fileName) + } catch (e: RuntimeException) { + // If the typeface asset does not exist, try another extension. + continue + } + } + return Typeface.create(fontFamilyName, style) + } + + @RequiresApi(Build.VERSION_CODES.Q) + private fun createAssetTypefaceWithFallbacks( + fontFamilyNames: Array, + style: Int, + assetManager: AssetManager + ): Typeface { + val fontFamilies = ArrayList() + + // Iterate over the list of fontFamilyNames, constructing new FontFamily objects + // for use in the CustomFallbackBuilder below. + for (fontFamilyName in fontFamilyNames) { + for (fileExtension in FILE_EXTENSIONS) { + val fileName = StringBuilder() + .append(FONTS_ASSET_PATH) + .append(fontFamilyName) + .append(fileExtension) + .toString() + try { + val font = Font.Builder(assetManager, fileName).build() + val family = FontFamily.Builder(font).build() + fontFamilies.add(family) + } catch (e: RuntimeException) { + // If the typeface asset does not exist, try another extension. + continue + } catch (e: IOException) { + // If the font asset does not exist, try another extension. + continue + } + } + } - public fun getTypeface(fontFamilyName: String, style: Int, assetManager: AssetManager): Typeface = - delegate.getTypeface(fontFamilyName, style, assetManager) + // If there's some problem constructing fonts, fall back to the default behavior. + if (fontFamilies.isEmpty()) { + return createAssetTypeface(fontFamilyNames[0], style, assetManager) + } + + val fallbackBuilder = Typeface.CustomFallbackBuilder(fontFamilies[0]) + for (i in 1 until fontFamilies.size) { + fallbackBuilder.addCustomFallback(fontFamilies[i]) + } + return fallbackBuilder.build() + } + } + + private val mFontCache = HashMap() + private val mCustomTypefaceCache = HashMap() + + public fun getTypeface(fontFamilyName: String, style: Int, assetManager: AssetManager): Typeface { + return getTypeface(fontFamilyName, TypefaceStyle(style), assetManager) + } public fun getTypeface( fontFamilyName: String, weight: Int, italic: Boolean, assetManager: AssetManager - ): Typeface = delegate.getTypeface(fontFamilyName, weight, italic, assetManager) + ): Typeface { + return getTypeface(fontFamilyName, TypefaceStyle(weight, italic), assetManager) + } public fun getTypeface( fontFamilyName: String, style: Int, weight: Int, assetManager: AssetManager - ): Typeface = delegate.getTypeface(fontFamilyName, style, weight, assetManager) + ): Typeface { + return getTypeface(fontFamilyName, TypefaceStyle(style, weight), assetManager) + } + public fun getTypeface( + fontFamilyName: String, + typefaceStyle: TypefaceStyle, + assetManager: AssetManager + ): Typeface { + mCustomTypefaceCache[fontFamilyName]?.let { customTypeface -> + // Apply `typefaceStyle` because custom fonts configure variants using `app:fontStyle` and + // `app:fontWeight` in their resource XML configuration file. + return typefaceStyle.apply(customTypeface) + } + + var assetFontFamily = mFontCache[fontFamilyName] + if (assetFontFamily == null) { + assetFontFamily = AssetFontFamily() + mFontCache[fontFamilyName] = assetFontFamily + } + + val style = typefaceStyle.getNearestStyle() + + var assetTypeface = assetFontFamily.getTypefaceForStyle(style) + if (assetTypeface == null) { + assetTypeface = createAssetTypeface(fontFamilyName, style, assetManager) + assetFontFamily.setTypefaceForStyle(style, assetTypeface) + } + // Do not apply `typefaceStyle` because asset font files already incorporate the style. + return assetTypeface + } + + /* + * This method allows you to load custom fonts from res/font folder as provided font family name. + * Fonts may be one of .ttf, .otf or XML (https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml). + * To support multiple font styles or weights, you must provide a font in XML format. + * + * ReactFontManager.getInstance().addCustomFont(this, "Srisakdi", R.font.srisakdi); + */ public fun addCustomFont(context: Context, fontFamily: String, fontId: Int) { - delegate.addCustomFont(context, fontFamily, fontId) + ResourcesCompat.getFont(context, fontId)?.let { font -> + mCustomTypefaceCache[fontFamily] = font + } } + /** + * Equivalent method to [addCustomFont] which accepts a Typeface object. + */ public fun addCustomFont(fontFamily: String, font: Typeface?) { - delegate.addCustomFont(fontFamily, font) + font?.let { mCustomTypefaceCache[fontFamily] = it } } - public fun setTypeface(fontFamilyName: String, style: Int, typeface: Typeface) { - delegate.setTypeface(fontFamilyName, style, typeface) + /** + * Add additional font family, or replace the exist one in the font memory cache. + * + * @param style see [Typeface.DEFAULT], [Typeface.BOLD], [Typeface.ITALIC], [Typeface.BOLD_ITALIC] + */ + public fun setTypeface(fontFamilyName: String, style: Int, typeface: Typeface?) { + typeface?.let { font -> + var assetFontFamily = mFontCache[fontFamilyName] + if (assetFontFamily == null) { + assetFontFamily = AssetFontFamily() + mFontCache[fontFamilyName] = assetFontFamily + } + assetFontFamily.setTypefaceForStyle(style, font) + } } - public companion object { - private var instance: ReactFontManager? = null + public class TypefaceStyle { + public companion object { + public const val BOLD: Int = 700 + public const val NORMAL: Int = 400 + private const val MIN_WEIGHT: Int = 1 + private const val MAX_WEIGHT: Int = 1000 + } - @JvmStatic - public fun getInstance(): ReactFontManager { - return instance - ?: ReactFontManager(ReactFontAssetManager.getInstance()).also { instance = it } + private val mItalic: Boolean + private val mWeight: Int + + public constructor(weight: Int, italic: Boolean) { + mItalic = italic + mWeight = if (weight == ReactConstants.UNSET) NORMAL else weight + } + + public constructor(style: Int) { + var styleValue = if (style == ReactConstants.UNSET) Typeface.NORMAL else style + + mItalic = (styleValue and Typeface.ITALIC) != 0 + mWeight = if ((styleValue and Typeface.BOLD) != 0) BOLD else NORMAL + } + + /** + * If `weight` is supplied, it will be combined with the italic bit from `style`. Otherwise, any + * existing weight bit in `style` will be used. + */ + public constructor(style: Int, weight: Int) { + var styleValue = if (style == ReactConstants.UNSET) Typeface.NORMAL else style + + mItalic = (styleValue and Typeface.ITALIC) != 0 + mWeight = when { + weight != ReactConstants.UNSET -> weight + (styleValue and Typeface.BOLD) != 0 -> BOLD + else -> NORMAL + } + } + + public fun getNearestStyle(): Int { + return if (mWeight < BOLD) { + if (mItalic) Typeface.ITALIC else Typeface.NORMAL + } else { + if (mItalic) Typeface.BOLD_ITALIC else Typeface.BOLD + } + } + + public fun apply(typeface: Typeface): Typeface { + return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + Typeface.create(typeface, getNearestStyle()) + } else { + Typeface.create(typeface, mWeight, mItalic) + } + } + } + + /** Responsible for caching typefaces for each custom font family. */ + private class AssetFontFamily { + private val mTypefaceSparseArray = SparseArray(4) + + fun getTypefaceForStyle(style: Int): Typeface? { + return mTypefaceSparseArray.get(style) + } + + fun setTypefaceForStyle(style: Int, typeface: Typeface) { + mTypefaceSparseArray.put(style, typeface) } } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.kt index 517466055c7217..db5feca6671511 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.kt @@ -12,7 +12,6 @@ import android.graphics.Typeface import android.text.TextUtils import com.facebook.react.bridge.ReadableArray import com.facebook.react.common.ReactConstants -import com.facebook.react.common.assets.ReactFontManager public object ReactTypefaceUtils { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index 999e4279a7ac7c..ae8bb00bed3203 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -61,6 +61,7 @@ public class TextAttributeProps { public static final short TA_KEY_LINE_BREAK_STRATEGY = 25; public static final short TA_KEY_ROLE = 26; public static final short TA_KEY_TEXT_TRANSFORM = 27; + public static final short TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29; public static final int UNSET = -1; @@ -81,6 +82,7 @@ public class TextAttributeProps { protected float mLineHeight = Float.NaN; protected boolean mIsColorSet = false; protected boolean mAllowFontScaling = true; + protected float mMaxFontSizeMultiplier = Float.NaN; protected int mColor; protected boolean mIsBackgroundColorSet = false; protected int mBackgroundColor; @@ -227,6 +229,9 @@ public static TextAttributeProps fromMapBuffer(MapBuffer props) { case TA_KEY_TEXT_TRANSFORM: result.setTextTransform(entry.getStringValue()); break; + case TA_KEY_MAX_FONT_SIZE_MULTIPLIER: + result.setMaxFontSizeMultiplier((float) entry.getDoubleValue()); + break; } } @@ -243,6 +248,8 @@ public static TextAttributeProps fromReadableMap(ReactStylesDiffMap props) { result.setLineHeight(getFloatProp(props, ViewProps.LINE_HEIGHT, ReactConstants.UNSET)); result.setLetterSpacing(getFloatProp(props, ViewProps.LETTER_SPACING, Float.NaN)); result.setAllowFontScaling(getBooleanProp(props, ViewProps.ALLOW_FONT_SCALING, true)); + result.setMaxFontSizeMultiplier( + getFloatProp(props, ViewProps.MAX_FONT_SIZE_MULTIPLIER, Float.NaN)); result.setFontSize(getFloatProp(props, ViewProps.FONT_SIZE, ReactConstants.UNSET)); result.setColor(props.hasKey(ViewProps.COLOR) ? props.getInt(ViewProps.COLOR, 0) : null); result.setColor( @@ -411,7 +418,14 @@ private void setAllowFontScaling(boolean allowFontScaling) { mAllowFontScaling = allowFontScaling; setFontSize(mFontSizeInput); setLineHeight(mLineHeightInput); - setLetterSpacing(mLetterSpacingInput); + } + } + + private void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) { + if (maxFontSizeMultiplier != mMaxFontSizeMultiplier) { + mMaxFontSizeMultiplier = maxFontSizeMultiplier; + setFontSize(mFontSizeInput); + setLineHeight(mLineHeightInput); } } @@ -420,7 +434,7 @@ private void setFontSize(float fontSize) { if (fontSize != ReactConstants.UNSET) { fontSize = mAllowFontScaling - ? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize)) + ? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize, mMaxFontSizeMultiplier)) : (float) Math.ceil(PixelUtil.toPixelFromDIP(fontSize)); } mFontSize = (int) fontSize; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomLineHeightSpan.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomLineHeightSpan.kt index c73d42fd48ff8e..d0424f6a5b96f3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomLineHeightSpan.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomLineHeightSpan.kt @@ -9,6 +9,7 @@ package com.facebook.react.views.text.internal.span import android.graphics.Paint.FontMetricsInt import android.text.style.LineHeightSpan +import com.facebook.react.bridge.Callback import kotlin.math.ceil import kotlin.math.floor @@ -37,6 +38,10 @@ public class CustomLineHeightSpan(height: Float) : LineHeightSpan, ReactSpan { // ascent above the baseline of A′ = A + L/2, and an effective descent of D′ = D + L/2. However, // if line-fit-edge is not leading and this is not the root inline box, if the half-leading is // positive, treat it as zero. The layout bounds exactly encloses this effective A′ and D′. + chooseHeightOverride?.let { + it.invoke(fm, lineHeight) + return + } val leading = lineHeight - ((-fm.ascent) + fm.descent) fm.ascent -= ceil(leading / 2.0f).toInt() @@ -53,4 +58,8 @@ public class CustomLineHeightSpan(height: Float) : LineHeightSpan, ReactSpan { fm.bottom = fm.descent } } + + public companion object { + public var chooseHeightOverride: Callback? = null + } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt index 81bb303e6a3052..3e5f13e89e7da7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt @@ -13,7 +13,7 @@ import android.graphics.Typeface import android.text.TextPaint import android.text.style.MetricAffectingSpan import com.facebook.react.common.ReactConstants -import com.facebook.react.common.assets.ReactFontManager +import com.facebook.react.views.text.ReactFontManager import com.facebook.react.views.text.ReactTypefaceUtils /** diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/LinearGradientSpan.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/LinearGradientSpan.kt new file mode 100644 index 00000000000000..8f4a4753572c54 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/LinearGradientSpan.kt @@ -0,0 +1,30 @@ +package com.facebook.react.views.text.internal.span + +import android.graphics.LinearGradient +import android.graphics.Shader +import android.text.TextPaint +import android.text.style.CharacterStyle +import android.text.style.UpdateAppearance + +public class LinearGradientSpan( + private val start: Float, + private val colors: IntArray, +) : CharacterStyle(), ReactSpan, + UpdateAppearance { + public override fun updateDrawState(tp: TextPaint) { + // without setting the paint color, the gradient appears "faded" if no foreground color span is also applied + // https://stackoverflow.com/a/52289927 + tp.setColor(colors[0]) + val textShader: Shader = + LinearGradient( + start, + 0f, + start + 150.0f, + 0f, + colors, + null, + Shader.TileMode.MIRROR, + ) + tp.setShader(textShader) + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index a0370775f5c288..ed7557a8a62b69 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -143,6 +143,8 @@ public class ReactEditText extends AppCompatEditText { private static final KeyListener sKeyListener = QwertyKeyListener.getInstanceForFullKeyboard(); private @Nullable EventDispatcher mEventDispatcher; + private final ReactEditTextClickDetector clickDetector = new ReactEditTextClickDetector(this); + public ReactEditText(Context context) { super(context); setFocusableInTouchMode(false); @@ -264,6 +266,13 @@ public boolean onTouchEvent(MotionEvent ev) { // Disallow parent views to intercept touch events, until we can detect if we should be // capturing these touches or not. this.getParent().requestDisallowInterceptTouchEvent(true); + clickDetector.handleDown(ev); + break; + case MotionEvent.ACTION_UP: + clickDetector.handleUp(ev); + break; + case MotionEvent.ACTION_CANCEL: + clickDetector.cancelPress(); break; case MotionEvent.ACTION_MOVE: if (mDetectScrollMovement) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextClickDetector.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextClickDetector.java new file mode 100644 index 00000000000000..9098d25ce06cf5 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextClickDetector.java @@ -0,0 +1,92 @@ +package com.facebook.react.views.textinput; + +import android.os.Build; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.Nullable; + +class ReactEditTextClickDetector { + + private static final long MAX_CLICK_DURATION_MS = 250L; + private static final int MAX_CLICK_DISTANCE_DP = 12; + + private final ReactEditText reactEditText; + private final float screenDensity; + + @Nullable + private TimestampedMotionEvent currentDownEvent; + + public ReactEditTextClickDetector(final ReactEditText reactEditText) { + this.reactEditText = reactEditText; + screenDensity = reactEditText.getResources().getDisplayMetrics().density; + } + + void handleDown(final MotionEvent downEvent) { + currentDownEvent = new TimestampedMotionEvent(System.currentTimeMillis(), downEvent); + } + + void cancelPress() { + currentDownEvent = null; + } + + void handleUp(final MotionEvent upEvent) { + if (currentDownEvent == null) { + return; + } + + final TimestampedMotionEvent downEvent = currentDownEvent; + currentDownEvent = null; + + // for now, if we're not forcing showing the keyboard on clicks, we don't care if it was a + // click. we also early return if the view is not enabled. + if (!(forceShowKeyboardOnClicks() && reactEditText.isEnabled())) { + return; + } + + // make sure the press event was close enough in time + final long now = System.currentTimeMillis(); + final long timeDelta = now - downEvent.timestamp; + if (timeDelta > MAX_CLICK_DURATION_MS) { + return; + } + + // make sure the press event was close enough in distance + final float oldX = downEvent.motionEvent.getRawX(); + final float oldY = downEvent.motionEvent.getRawY(); + final float newX = upEvent.getRawX(); + final float newY = upEvent.getRawY(); + + // distance = sqrt((x2 − x1)^2 + (y2 − y1)^2) + final double distancePx = Math.sqrt( + Math.pow((newX - oldX), 2) + Math.pow((newY - oldY), 2) + ); + + double distanceDp = distancePx / screenDensity; + if (distanceDp > MAX_CLICK_DISTANCE_DP) { + return; + } + + reactEditText.showSoftKeyboard(); + } + + /** + * There is a bug on Android 7/8/9 where clicking the view while it is already + * focused does not show the keyboard. On those API levels, we force showing + * the keyboard when we detect a click. + */ + private static boolean forceShowKeyboardOnClicks() { + return Build.VERSION.SDK_INT <= Build.VERSION_CODES.P; + } + + private static class TimestampedMotionEvent { + + final long timestamp; + final MotionEvent motionEvent; + + TimestampedMotionEvent(final long timestamp, final MotionEvent motionEvent) { + this.timestamp = timestamp; + this.motionEvent = motionEvent; + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.kt index 735d69bd2909f7..58448140809291 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.kt @@ -14,6 +14,8 @@ import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import android.graphics.drawable.RippleDrawable +import android.graphics.drawable.ShapeDrawable +import android.graphics.drawable.shapes.RoundRectShape import android.util.TypedValue import com.facebook.react.bridge.JSApplicationIllegalArgumentException import com.facebook.react.bridge.ReadableMap @@ -101,6 +103,22 @@ public object ReactDrawableHelper { } private fun getMask(drawableDescriptionDict: ReadableMap): Drawable? { + if (drawableDescriptionDict.hasKey("borderless") && drawableDescriptionDict.getBoolean("borderless")) { + // Borderless ripples don't have masks. + return null + } + + if (drawableDescriptionDict.hasKey("rippleCornerRadius")) { + val rippleRadius = PixelUtil.toPixelFromDIP(drawableDescriptionDict.getDouble("rippleCornerRadius")) + return ShapeDrawable( + RoundRectShape( + FloatArray(8) { rippleRadius }, + null, + null + ) + ) + } + if (!drawableDescriptionDict.hasKey("borderless") || drawableDescriptionDict.isNull("borderless") || !drawableDescriptionDict.getBoolean("borderless")) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index da20629d4faec9..1df2615e038806 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -139,6 +139,7 @@ public void shutdown() { private float mBackfaceOpacity; private boolean mBackfaceVisible; private @Nullable Set mChildrenRemovedWhileTransitioning; + private boolean mPreventClipping; /** * Creates a new `ReactViewGroup` instance. @@ -174,6 +175,7 @@ private void initView() { mBackfaceOpacity = 1.f; mBackfaceVisible = true; mChildrenRemovedWhileTransitioning = null; + mPreventClipping = false; } /* package */ void recycleView() { @@ -350,6 +352,19 @@ public void setBorderStyle(@Nullable String style) { this, style == null ? null : BorderStyle.fromString(style)); } + public void setPreventClipping(boolean preventClipping) { + mPreventClipping = preventClipping; + + // TODO(apkumar) + // + // It would be nice to trigger the LayoutChangeListener at this point. + } + + public boolean getPreventClipping() { + return mPreventClipping; + } + + @Override public void setRemoveClippedSubviews(boolean removeClippedSubviews) { if (removeClippedSubviews == mRemoveClippedSubviews) { @@ -486,20 +501,61 @@ private void updateSubviewClipStatus(Rect clippingRect, int idx, int clippedSoFa // it won't be size and located properly. Animation animation = child.getAnimation(); boolean isAnimating = animation != null && !animation.hasEnded(); - if (!intersects && !isViewClipped(child, idx) && !isAnimating) { + + // NOTE (apkumar): + // + // The `preventClipping` logic here, and the `getDrawingOrderHelper().*` + // calls within the if-else statements below, are added in our fork. They + // work together to support `removeClippedSubviews` in the presence of + // animated subviews. + // + // Typically, when `removeClippedSubviews` is turned on, you run the risk + // of animated subviews being clipped when they shouldn't be, since their + // bounding rectangle may be outside the clipping window, but due to the + // animation transforming the view, the actual rendering _would be_ inside + // the clipping window. To fix this, we added a `preventClipping` prop to + // Views, and here we simply never clip any View that has that prop set to + // true. + // + // That change fixes the clipping issue, but exposed a second problem: when + // `removeClippedSubviews` is turned on, React Native's zIndex system is + // not respected. The issue is that, normally, the drawing order helper is + // informed of new and removed views via handleAddView and + // handleRemoveView, called in `addView` and `removeView` respectively. + // However, when removeClippedSubviews is true, + // `addViewWithSubviewClippingEnabled` is called _instead of_ `addView`, + // which _does not_ call into the drawing order helper's handleAddView + // (with a similar story for removing views). Because of this, the drawing + // order helper is not aware of any child views, and so does not perform + // any of the z-indexing logic it normally does. + // + // To fix that second issue, we simply have to call handleRemoveView / + // handleAddView explicitly here, when the clipping logic adds or removes + // views because of their intersection with the clipping window. + boolean preventClipping = false; + if (child instanceof ReactViewGroup) { + preventClipping = ((ReactViewGroup)child).getPreventClipping(); + } + + if (!intersects && !isViewClipped(child, idx) && !isAnimating && !preventClipping) { setViewClipped(child, true); + getDrawingOrderHelper().handleRemoveView(child); + setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); // We can try saving on invalidate call here as the view that we remove is out of visible area // therefore invalidation is not necessary. removeViewInLayout(child); needUpdateClippingRecursive = true; - } else if (intersects && isViewClipped(child, idx)) { + } else if (((intersects && isViewClipped(child, idx)) || preventClipping) && child.getParent() == null) { int adjustedIdx = idx - clippedSoFar; Assertions.assertCondition(adjustedIdx >= 0); + getDrawingOrderHelper().handleAddView(child); + setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); + setViewClipped(child, false); addViewInLayout(child, adjustedIdx, sDefaultLayoutParam, true); invalidate(); needUpdateClippingRecursive = true; - } else if (intersects) { + } else if (intersects || preventClipping) { // If there is any intersection we need to inform the child to update its clipping rect needUpdateClippingRecursive = true; } @@ -588,9 +644,6 @@ public void onViewRemoved(View child) { UiThreadUtil.assertOnUiThread(); checkViewClippingTag(child, Boolean.TRUE); if (!customDrawOrderDisabled()) { - if (indexOfChild(child) == -1) { - return; - } getDrawingOrderHelper().handleRemoveView(child); setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); } else { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt index 99d64164593b0f..c24247af70525c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt @@ -81,6 +81,11 @@ public open class ReactViewManager : ReactClippingViewManager() view.isFocusable = accessible } + @ReactProp(name = "preventClipping") + public open fun setPreventClipping(view: ReactViewGroup, preventClipping: Boolean) { + view.preventClipping = preventClipping + } + @ReactProp(name = "hasTVPreferredFocus") public open fun setTVPreferredFocus(view: ReactViewGroup, hasTVPreferredFocus: Boolean) { if (hasTVPreferredFocus) { diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index d3d0dc3ea1e040..1ede11bdd9ed6a 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<7c3853858da56eb5f471abccf9dcbf55>> + * @generated SignedSource<<28069af1f34c79e9907c85697a291c0e>> */ /** @@ -297,6 +297,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool useShadowNodeStateOnClone() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useShadowNodeStateOnClone"); + return method(javaProvider_); + } + bool useTurboModuleInterop() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useTurboModuleInterop"); @@ -528,6 +534,11 @@ bool JReactNativeFeatureFlagsCxxInterop::useRuntimeShadowNodeReferenceUpdate( return ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate(); } +bool JReactNativeFeatureFlagsCxxInterop::useShadowNodeStateOnClone( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::useShadowNodeStateOnClone(); +} + bool JReactNativeFeatureFlagsCxxInterop::useTurboModuleInterop( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::useTurboModuleInterop(); @@ -698,6 +709,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "useRuntimeShadowNodeReferenceUpdate", JReactNativeFeatureFlagsCxxInterop::useRuntimeShadowNodeReferenceUpdate), + makeNativeMethod( + "useShadowNodeStateOnClone", + JReactNativeFeatureFlagsCxxInterop::useShadowNodeStateOnClone), makeNativeMethod( "useTurboModuleInterop", JReactNativeFeatureFlagsCxxInterop::useTurboModuleInterop), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 80ef331dff8352..665dd08e57343d 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<77b4ed5aa33290ba9da1719544e974cb>> + * @generated SignedSource<<763d595784bdf31a852ebf2a492a1393>> */ /** @@ -159,6 +159,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool useRuntimeShadowNodeReferenceUpdate( facebook::jni::alias_ref); + static bool useShadowNodeStateOnClone( + facebook::jni::alias_ref); + static bool useTurboModuleInterop( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h b/packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h index c2509cc0404a27..a061a541ae3752 100644 --- a/packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h +++ b/packages/react-native/ReactCommon/cxxreact/ReactNativeVersion.h @@ -15,9 +15,9 @@ namespace facebook::react { constexpr struct { - int32_t Major = 1000; - int32_t Minor = 0; - int32_t Patch = 0; + int32_t Major = 0; + int32_t Minor = 78; + int32_t Patch = 2; std::string_view Prerelease = ""; } ReactNativeVersion; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/ForwardingConsoleMethods.def b/packages/react-native/ReactCommon/jsinspector-modern/ForwardingConsoleMethods.h similarity index 100% rename from packages/react-native/ReactCommon/jsinspector-modern/ForwardingConsoleMethods.def rename to packages/react-native/ReactCommon/jsinspector-modern/ForwardingConsoleMethods.h diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp index a129d662339adc..52bb80602fbe1c 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp @@ -321,7 +321,7 @@ void consoleAssert( runtime, \ {timestampMs, type, std::move(argsVec), std::move(stackTrace)}); \ } -#include "ForwardingConsoleMethods.def" +#include "ForwardingConsoleMethods.h" #undef FORWARDING_CONSOLE_METHOD } // namespace @@ -469,7 +469,7 @@ void RuntimeTarget::installConsoleHandler() { // Install forwarding console methods. #define FORWARDING_CONSOLE_METHOD(name, type) \ installConsoleMethod(#name, console_##name); -#include "ForwardingConsoleMethods.def" +#include "ForwardingConsoleMethods.h" #undef FORWARDING_CONSOLE_METHOD runtime.global().setProperty(runtime, "console", console); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index f71795970ae0c7..811d4fef5a177c 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<7d301656072183649246db8fa738fc4d>> + * @generated SignedSource<<511c1667fab247b77d771a7a26e87b46>> */ /** @@ -198,6 +198,10 @@ bool ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate() { return getAccessor().useRuntimeShadowNodeReferenceUpdate(); } +bool ReactNativeFeatureFlags::useShadowNodeStateOnClone() { + return getAccessor().useShadowNodeStateOnClone(); +} + bool ReactNativeFeatureFlags::useTurboModuleInterop() { return getAccessor().useTurboModuleInterop(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 4d075604aa7da4..f082b18249f424 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<19cfd8b41dd429c83a5e0f0df514d1d1>> */ /** @@ -254,6 +254,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool useRuntimeShadowNodeReferenceUpdate(); + /** + * Use the state stored on the source shadow node when cloning it instead of reading in the most recent state on the shadow node family. + */ + RN_EXPORT static bool useShadowNodeStateOnClone(); + /** * In Bridgeless mode, should legacy NativeModules use the TurboModule system? */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 4e528eff110880..c8ef7996747ccf 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -803,6 +803,24 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() { + auto flagValue = useShadowNodeStateOnClone_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(43, "useShadowNodeStateOnClone"); + + flagValue = currentProvider_->useShadowNodeStateOnClone(); + useShadowNodeStateOnClone_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { auto flagValue = useTurboModuleInterop_.load(); @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useTurboModuleInterop"); + markFlagAsAccessed(44, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "useTurboModules"); + markFlagAsAccessed(45, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index ac0c3e53a1dbd7..1d453a762d518a 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<8eb2b5d6dd367826ff7bc899afbdea60>> + * @generated SignedSource<<2a6cbfd5de86a5bb840f1fc5f47c51a6>> */ /** @@ -75,6 +75,7 @@ class ReactNativeFeatureFlagsAccessor { bool useOptimizedEventBatchingOnAndroid(); bool useRawPropsJsiValue(); bool useRuntimeShadowNodeReferenceUpdate(); + bool useShadowNodeStateOnClone(); bool useTurboModuleInterop(); bool useTurboModules(); @@ -88,7 +89,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 45> accessedFeatureFlags_; + std::array, 46> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> completeReactInstanceCreationOnBgThreadOnAndroid_; @@ -133,6 +134,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> useOptimizedEventBatchingOnAndroid_; std::atomic> useRawPropsJsiValue_; std::atomic> useRuntimeShadowNodeReferenceUpdate_; + std::atomic> useShadowNodeStateOnClone_; std::atomic> useTurboModuleInterop_; std::atomic> useTurboModules_; }; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index aec774f80d20dc..08f09fe37764e9 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<830cdd4b394262ee65abc63a54833674>> */ /** @@ -199,6 +199,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return true; } + bool useShadowNodeStateOnClone() override { + return false; + } + bool useTurboModuleInterop() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index 5a6b8a82ae33f2..9e436f6ecd0b18 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<627094b444d8b7a513d7190272848a9e>> */ /** @@ -432,6 +432,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::useRuntimeShadowNodeReferenceUpdate(); } + bool useShadowNodeStateOnClone() override { + auto value = values_["useShadowNodeStateOnClone"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::useShadowNodeStateOnClone(); + } + bool useTurboModuleInterop() override { auto value = values_["useTurboModuleInterop"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index c89d65c0d88b54..e7f1ceaf8e6e67 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<36bfe0037e4dba3b6eb6e95075914fce>> + * @generated SignedSource<<190bad7388fb33884eebca0fed4ad61f>> */ /** @@ -68,6 +68,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool useOptimizedEventBatchingOnAndroid() = 0; virtual bool useRawPropsJsiValue() = 0; virtual bool useRuntimeShadowNodeReferenceUpdate() = 0; + virtual bool useShadowNodeStateOnClone() = 0; virtual bool useTurboModuleInterop() = 0; virtual bool useTurboModules() = 0; }; diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm index ad267de81138df..740a202bca7a71 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm @@ -123,6 +123,15 @@ NSArray *arguments; SEL objCMethodSelector = NSSelectorFromString(RCTParseMethodSignature(methodInfo->objcName, &arguments)); NSMethodSignature *objCMethodSignature = [moduleClass instanceMethodSignatureForSelector:objCMethodSelector]; + if (objCMethodSignature == nullptr) { + RCTLogWarn( + @"The objective-c `%s` method signature for the JS method `%@` can not be found in the ObjecitveC definition of the %s module.\nThe `%@` JS method will not be available.", + methodInfo->objcName, + jsMethodName, + moduleName.c_str(), + jsMethodName); + continue; + } std::string objCMethodReturnType = [objCMethodSignature methodReturnType]; if (objCMethodSignature.numberOfArguments - 2 != [arguments count]) { @@ -337,7 +346,7 @@ T RCTConvertTo(SEL selector, id json) SEL selector = selectorForType(argumentType); if ([RCTConvert respondsToSelector:selector]) { - id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_); + id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES); if (objCArgType == @encode(char)) { char arg = RCTConvertTo(selector, objCArg); @@ -437,6 +446,15 @@ T RCTConvertTo(SEL selector, id json) if (objCArgType == @encode(id)) { id arg = RCTConvertTo(selector, objCArg); + + // Handle the special case where there is an argument and it must be nil + // Without this check, the JS side will receive an object. + // See: discussion at + // https://github.com/facebook/react-native/pull/49250#issuecomment-2668465893 + if (arg == [NSNull null]) { + return; + } + if (arg) { [retainedObjectsForInvocation addObject:arg]; } @@ -491,7 +509,7 @@ T RCTConvertTo(SEL selector, id json) } RCTResponseSenderBlock arg = - (RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_); + (RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES); if (arg) { [retainedObjectsForInvocation addObject:arg]; } @@ -506,7 +524,7 @@ T RCTConvertTo(SEL selector, id json) } RCTResponseSenderBlock senderBlock = - (RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_); + (RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES); RCTResponseErrorBlock arg = ^(NSError *error) { senderBlock(@[ RCTJSErrorFromNSError(error) ]); }; @@ -536,7 +554,7 @@ T RCTConvertTo(SEL selector, id json) runtime, errorPrefix + "JavaScript argument must be a plain object. Got " + getType(runtime, jsiArg)); } - id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_); + id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES); RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend; RCTManagedPointer *box = convert([RCTCxxConvert class], selector, arg); diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h index f54e1751fb9465..7899037ee0b4fe 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h @@ -32,6 +32,7 @@ using EventEmitterCallback = std::function; namespace TurboModuleConvertUtils { jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value); id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker); +id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker, BOOL useNSNull); } // namespace TurboModuleConvertUtils template <> diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm index 1b4b8762cdfe53..ac9bbe1176114a 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm @@ -57,7 +57,7 @@ static int32_t getUniqueId() static jsi::String convertNSStringToJSIString(jsi::Runtime &runtime, NSString *value) { - return jsi::String::createFromUtf8(runtime, [value UTF8String] ?: ""); + return jsi::String::createFromUtf8(runtime, [value UTF8String] ? [value UTF8String] : ""); } static jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value) @@ -112,20 +112,20 @@ static int32_t getUniqueId() } static NSArray * -convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr jsInvoker) +convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr jsInvoker, BOOL useNSNull) { size_t size = value.size(runtime); NSMutableArray *result = [NSMutableArray new]; for (size_t i = 0; i < size; i++) { // Insert kCFNull when it's `undefined` value to preserve the indices. - id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker); + id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker, useNSNull); [result addObject:convertedObject ? convertedObject : (id)kCFNull]; } return [result copy]; } static NSDictionary * -convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr jsInvoker) +convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr jsInvoker, BOOL useNSNull) { jsi::Array propertyNames = value.getPropertyNames(runtime); size_t size = propertyNames.size(runtime); @@ -133,7 +133,7 @@ static int32_t getUniqueId() for (size_t i = 0; i < size; i++) { jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime); NSString *k = convertJSIStringToNSString(runtime, name); - id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker); + id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker, useNSNull); if (v) { result[k] = v; } @@ -159,11 +159,14 @@ static int32_t getUniqueId() }; } -id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker) +id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker, BOOL useNSNull) { - if (value.isUndefined() || value.isNull()) { + if (value.isUndefined() || (value.isNull() && !useNSNull)) { return nil; } + if (value.isNull() && useNSNull) { + return [NSNull null]; + } if (value.isBool()) { return @(value.getBool()); } @@ -176,17 +179,22 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s if (value.isObject()) { jsi::Object o = value.getObject(runtime); if (o.isArray(runtime)) { - return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker); + return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker, useNSNull); } if (o.isFunction(runtime)) { return convertJSIFunctionToCallback(runtime, o.getFunction(runtime), jsInvoker); } - return convertJSIObjectToNSDictionary(runtime, o, jsInvoker); + return convertJSIObjectToNSDictionary(runtime, o, jsInvoker, useNSNull); } throw std::runtime_error("Unsupported jsi::Value kind"); } +id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker) +{ + return convertJSIValueToObjCObject(runtime, value, jsInvoker, NO); +} + static jsi::Value createJSRuntimeError(jsi::Runtime &runtime, const std::string &message) { return runtime.global().getPropertyAsFunction(runtime, "Error").call(runtime, message); @@ -195,7 +203,11 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s /** * Creates JSError with current JS runtime and NSException stack trace. */ -static jsi::JSError convertNSExceptionToJSError(jsi::Runtime &runtime, NSException *exception) +static jsi::JSError convertNSExceptionToJSError( + jsi::Runtime &runtime, + NSException *exception, + const std::string &moduleName, + const std::string &methodName) { std::string reason = [exception.reason UTF8String]; @@ -206,7 +218,8 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s cause.setProperty( runtime, "stackReturnAddresses", convertNSArrayToJSIArray(runtime, exception.callStackReturnAddresses)); - jsi::Value error = createJSRuntimeError(runtime, "Exception in HostFunction: " + reason); + std::string message = moduleName + "." + methodName + " raised an exception: " + reason; + jsi::Value error = createJSRuntimeError(runtime, message); error.asObject(runtime).setProperty(runtime, "cause", std::move(cause)); return {runtime, std::move(error)}; } @@ -338,28 +351,34 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s } if (isSync) { - TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodNameStr.c_str()); + TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodName); } else { - TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodNameStr.c_str(), asyncCallCounter); + TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodName, asyncCallCounter); } @try { [inv invokeWithTarget:strongModule]; } @catch (NSException *exception) { - throw convertNSExceptionToJSError(runtime, exception); + if (isSync) { + // We can only convert NSException to JSError in sync method calls. + // See https://github.com/reactwg/react-native-new-architecture/discussions/276#discussioncomment-12567155 + throw convertNSExceptionToJSError(runtime, exception, std::string{moduleName}, methodNameStr); + } else { + @throw exception; + } } @finally { [retainedObjectsForInvocation removeAllObjects]; } if (!isSync) { - TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodNameStr.c_str(), asyncCallCounter); + TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodName, asyncCallCounter); return; } void *rawResult; [inv getReturnValue:&rawResult]; result = (__bridge id)rawResult; - TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodNameStr.c_str()); + TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodName); }; if (isSync) { @@ -401,23 +420,23 @@ TraceSection s( } if (shouldVoidMethodsExecuteSync_) { - TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodNameStr.c_str()); + TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodName); } else { - TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodNameStr.c_str(), asyncCallCounter); + TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodName, asyncCallCounter); } @try { [inv invokeWithTarget:strongModule]; } @catch (NSException *exception) { - throw convertNSExceptionToJSError(runtime, exception); + throw convertNSExceptionToJSError(runtime, exception, std::string{moduleName}, methodNameStr); } @finally { [retainedObjectsForInvocation removeAllObjects]; } if (shouldVoidMethodsExecuteSync_) { - TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodNameStr.c_str()); + TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodName); } else { - TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodNameStr.c_str(), asyncCallCounter); + TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodName, asyncCallCounter); } return; diff --git a/packages/react-native/ReactCommon/react/nativemodule/devtoolsruntimesettings/DevToolsRuntimeSettingsModule.cpp b/packages/react-native/ReactCommon/react/nativemodule/devtoolsruntimesettings/DevToolsRuntimeSettingsModule.cpp index 4b0e5ca0bd2f6a..99424585afc880 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/devtoolsruntimesettings/DevToolsRuntimeSettingsModule.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/devtoolsruntimesettings/DevToolsRuntimeSettingsModule.cpp @@ -6,7 +6,10 @@ */ #include "DevToolsRuntimeSettingsModule.h" + +#ifdef RN_DISABLE_OSS_PLUGIN_HEADER #include "Plugins.h" +#endif std::shared_ptr ReactDevToolsRuntimeSettingsModuleProvider( diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index f326fcd073b5f8..f2ea23f46d83f3 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<2911cd67b3a434c7d3610740befac4f9>> */ /** @@ -259,6 +259,11 @@ bool NativeReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate( return ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate(); } +bool NativeReactNativeFeatureFlags::useShadowNodeStateOnClone( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::useShadowNodeStateOnClone(); +} + bool NativeReactNativeFeatureFlags::useTurboModuleInterop( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::useTurboModuleInterop(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 7f4364d355d522..e6260245a1e94e 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<9df551425337f50b9bb8837684bbbba0>> */ /** @@ -123,6 +123,8 @@ class NativeReactNativeFeatureFlags bool useRuntimeShadowNodeReferenceUpdate(jsi::Runtime& runtime); + bool useShadowNodeStateOnClone(jsi::Runtime& runtime); + bool useTurboModuleInterop(jsi::Runtime& runtime); bool useTurboModules(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp index 93b1728d2c0698..193b75b71cc9fe 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp @@ -46,6 +46,9 @@ void TextAttributes::apply(TextAttributes textAttributes) { allowFontScaling = textAttributes.allowFontScaling.has_value() ? textAttributes.allowFontScaling : allowFontScaling; + maxFontSizeMultiplier = !std::isnan(textAttributes.maxFontSizeMultiplier) + ? textAttributes.maxFontSizeMultiplier + : maxFontSizeMultiplier; dynamicTypeRamp = textAttributes.dynamicTypeRamp.has_value() ? textAttributes.dynamicTypeRamp : dynamicTypeRamp; @@ -168,6 +171,7 @@ bool TextAttributes::operator==(const TextAttributes& rhs) const { rhs.accessibilityRole, rhs.role, rhs.textTransform) && + floatEquality(maxFontSizeMultiplier, rhs.maxFontSizeMultiplier) && floatEquality(opacity, rhs.opacity) && floatEquality(fontSize, rhs.fontSize) && floatEquality(fontSizeMultiplier, rhs.fontSizeMultiplier) && @@ -224,6 +228,10 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const { "allowFontScaling", allowFontScaling, textAttributes.allowFontScaling), + debugStringConvertibleItem( + "maxFontSizeMultiplier", + maxFontSizeMultiplier, + textAttributes.maxFontSizeMultiplier), debugStringConvertibleItem( "dynamicTypeRamp", dynamicTypeRamp, textAttributes.dynamicTypeRamp), debugStringConvertibleItem( diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h index 37db36656f8d67..55b4de33223fc2 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -51,6 +51,7 @@ class TextAttributes : public DebugStringConvertible { std::optional fontStyle{}; std::optional fontVariant{}; std::optional allowFontScaling{}; + Float maxFontSizeMultiplier{std::numeric_limits::quiet_NaN()}; std::optional dynamicTypeRamp{}; Float letterSpacing{std::numeric_limits::quiet_NaN()}; std::optional textTransform{}; @@ -117,6 +118,7 @@ struct hash { textAttributes.opacity, textAttributes.fontFamily, textAttributes.fontSize, + textAttributes.maxFontSizeMultiplier, textAttributes.fontSizeMultiplier, textAttributes.fontWeight, textAttributes.fontStyle, diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h index de8676939e4630..de53360ce2f043 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h @@ -910,6 +910,7 @@ constexpr static MapBuffer::Key TA_KEY_LINE_BREAK_STRATEGY = 25; constexpr static MapBuffer::Key TA_KEY_ROLE = 26; constexpr static MapBuffer::Key TA_KEY_TEXT_TRANSFORM = 27; constexpr static MapBuffer::Key TA_KEY_ALIGNMENT_VERTICAL = 28; +constexpr static MapBuffer::Key TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29; // constants for ParagraphAttributes serialization constexpr static MapBuffer::Key PA_KEY_MAX_NUMBER_OF_LINES = 0; @@ -1004,6 +1005,10 @@ inline MapBuffer toMapBuffer(const TextAttributes& textAttributes) { builder.putBool( TA_KEY_ALLOW_FONT_SCALING, *textAttributes.allowFontScaling); } + if (!std::isnan(textAttributes.maxFontSizeMultiplier)) { + builder.putDouble( + TA_KEY_MAX_FONT_SIZE_MULTIPLIER, textAttributes.maxFontSizeMultiplier); + } if (!std::isnan(textAttributes.letterSpacing)) { builder.putDouble(TA_KEY_LETTER_SPACING, textAttributes.letterSpacing); } diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/components/modal/CMakeLists.txt index dd1a291061ba22..a84728b6b2811a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/modal/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/CMakeLists.txt @@ -14,7 +14,10 @@ add_compile_options( -Wpedantic -DLOG_TAG=\"Fabric\") -file(GLOB rrc_modal_SRC CONFIGURE_DEPENDS *.cpp) +file(GLOB rrc_modal_SRC CONFIGURE_DEPENDS + *.cpp + platform/android/*.cpp) + add_library(rrc_modal STATIC ${rrc_modal_SRC}) target_include_directories(rrc_modal PUBLIC ${REACT_COMMON_DIR}) diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.h b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.h index 2b713926dd5efc..e8e97707930436 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.h +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewState.h @@ -9,14 +9,13 @@ #include #include +#include "ModalHostViewUtils.h" #ifdef ANDROID #include #endif -#if defined(__APPLE__) && TARGET_OS_IOS #include "ModalHostViewUtils.h" -#endif namespace facebook::react { @@ -27,12 +26,7 @@ class ModalHostViewState final { public: using Shared = std::shared_ptr; -#if defined(__APPLE__) && TARGET_OS_IOS - ModalHostViewState() : screenSize(RCTModalHostViewScreenSize()) { -#else - ModalHostViewState(){ -#endif - }; + ModalHostViewState() : screenSize(RCTModalHostViewScreenSize()) {} ModalHostViewState(Size screenSize_) : screenSize(screenSize_){}; #ifdef ANDROID @@ -54,3 +48,4 @@ class ModalHostViewState final { }; } // namespace facebook::react + diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewUtils.h b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewUtils.h index fc038ad33de5fd..b4881ff22974fd 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewUtils.h +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewUtils.h @@ -7,7 +7,7 @@ #pragma once -#include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/platform/android/JReactModalHostView.h b/packages/react-native/ReactCommon/react/renderer/components/modal/platform/android/JReactModalHostView.h new file mode 100644 index 00000000000000..eeae4d73356e8f --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/platform/android/JReactModalHostView.h @@ -0,0 +1,35 @@ +/* + * 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 + +#include +#include + +#include + +namespace facebook::react { + +class JReactModalHostView + : public facebook::jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = + "Lcom/facebook/react/views/modal/ReactModalHostView;"; + + static Size getDisplayMetrics() { + static auto method = JReactModalHostView::javaClassStatic() + ->getStaticMethod( + "getScreenDisplayMetricsWithoutInsets"); + auto result = method(javaClassStatic()); + size_t size = result->size(); + std::vector elements(size + 1L); + result->getRegion(0, size, elements.data()); + return Size{elements[0], elements[1]}; + } +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/modal/platform/android/ModalHostViewUtils.cpp b/packages/react-native/ReactCommon/react/renderer/components/modal/platform/android/ModalHostViewUtils.cpp new file mode 100644 index 00000000000000..7489ee509b0e24 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/modal/platform/android/ModalHostViewUtils.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include "JReactModalHostView.h" + +namespace facebook::react { + +Size RCTModalHostViewScreenSize(void) { + return JReactModalHostView::getDisplayMetrics(); +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp index 132281e8ab8333..9f89192ebf4dfa 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp @@ -73,6 +73,12 @@ static TextAttributes convertRawProp( "allowFontScaling", sourceTextAttributes.allowFontScaling, defaultTextAttributes.allowFontScaling); + textAttributes.maxFontSizeMultiplier = convertRawProp( + context, + rawProps, + "maxFontSizeMultiplier", + sourceTextAttributes.maxFontSizeMultiplier, + defaultTextAttributes.maxFontSizeMultiplier); textAttributes.dynamicTypeRamp = convertRawProp( context, rawProps, @@ -266,6 +272,12 @@ void BaseTextProps::setProp( defaults, value, textAttributes, fontVariant, "fontVariant"); REBUILD_FIELD_SWITCH_CASE( defaults, value, textAttributes, allowFontScaling, "allowFontScaling"); + REBUILD_FIELD_SWITCH_CASE( + defaults, + value, + textAttributes, + maxFontSizeMultiplier, + "maxFontSizeMultiplier"); REBUILD_FIELD_SWITCH_CASE( defaults, value, textAttributes, letterSpacing, "letterSpacing"); REBUILD_FIELD_SWITCH_CASE( diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp index dfbae60abd7c94..352b8274c929db 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp @@ -133,4 +133,25 @@ SharedDebugStringConvertibleList HostPlatformViewProps::getDebugProps() const { } #endif +#ifdef ANDROID + +folly::dynamic HostPlatformViewProps::getDiffProps( + const Props* prevProps) const { + folly::dynamic result = folly::dynamic::object(); + + static const auto defaultProps = HostPlatformViewProps(); + + const HostPlatformViewProps* oldProps = prevProps == nullptr + ? &defaultProps + : static_cast(prevProps); + + if (focusable != oldProps->focusable) { + result["focusable"] = focusable; + } + + return result; +} + +#endif + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h index 25a6cd30529b1a..d18d7e863bbdf9 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h @@ -55,6 +55,12 @@ class HostPlatformViewProps : public BaseViewProps { #if RN_DEBUG_STRING_CONVERTIBLE SharedDebugStringConvertibleList getDebugProps() const override; #endif + +#ifdef ANDROID + + folly::dynamic getDiffProps(const Props* prevProps) const override; + +#endif }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp index a9ca4d71c9d6a8..690c3d16645074 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp @@ -112,7 +112,9 @@ ShadowNode::ShadowNode( fragment.children ? fragment.children : sourceShadowNode.children_), state_( fragment.state ? fragment.state - : sourceShadowNode.getMostRecentState()), + : (ReactNativeFeatureFlags::useShadowNodeStateOnClone() + ? sourceShadowNode.state_ + : sourceShadowNode.getMostRecentState())), orderIndex_(sourceShadowNode.orderIndex_), family_(sourceShadowNode.family_), traits_(sourceShadowNode.traits_) { @@ -308,13 +310,20 @@ void ShadowNode::setRuntimeShadowNodeReference( runtimeShadowNodeReference_ = runtimeShadowNodeReference; } +void ShadowNode::updateRuntimeShadowNodeReference( + const Shared& destinationShadowNode) const { + if (auto reference = runtimeShadowNodeReference_.lock()) { + reference->shadowNode = destinationShadowNode; + } +} + void ShadowNode::transferRuntimeShadowNodeReference( const Shared& destinationShadowNode) const { destinationShadowNode->runtimeShadowNodeReference_ = runtimeShadowNodeReference_; - if (auto reference = runtimeShadowNodeReference_.lock()) { - reference->shadowNode = destinationShadowNode; + if (!ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate()) { + updateRuntimeShadowNodeReference(destinationShadowNode); } } diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h index 7a3ad9cbc1b8b3..ae648988875ade 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h @@ -187,6 +187,12 @@ class ShadowNode : public Sealable, void setRuntimeShadowNodeReference(const std::shared_ptr& runtimeShadowNodeReference) const; + /* + * Update the runtime reference to point to the provided shadow node. + */ + void updateRuntimeShadowNodeReference( + const Shared& destinationShadowNode) const; + /* * Transfer the runtime reference to this `ShadowNode` to a new instance, * updating the reference to point to the new `ShadowNode` referencing it. diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/updateMountedFlag.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/updateMountedFlag.cpp index 4b501294144878..42d8695977fb2f 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/updateMountedFlag.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/updateMountedFlag.cpp @@ -7,6 +7,8 @@ #include "updateMountedFlag.h" +#include + namespace facebook::react { void updateMountedFlag( const ShadowNode::ListOfShared& oldChildren, @@ -47,6 +49,10 @@ void updateMountedFlag( newChild->setMounted(true); oldChild->setMounted(false); + if (ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate()) { + newChild->updateRuntimeShadowNodeReference(newChild); + } + updateMountedFlag(oldChild->getChildren(), newChild->getChildren()); } diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h index 3427663d53d8f6..908cfc0b612b08 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h @@ -52,8 +52,29 @@ BOOL RCTIsAttributedStringEffectivelySame( NSDictionary *insensitiveAttributes, const facebook::react::TextAttributes &baseTextAttributes); -@interface RCTWeakEventEmitterWrapper : NSObject -@property (nonatomic, assign) facebook::react::SharedEventEmitter eventEmitter; -@end +static inline NSData *RCTWrapEventEmitter(const facebook::react::SharedEventEmitter &eventEmitter) +{ + auto eventEmitterPtr = new std::weak_ptr(eventEmitter); + return [[NSData alloc] initWithBytesNoCopy:eventEmitterPtr + length:sizeof(eventEmitterPtr) + deallocator:^(void *ptrToDelete, NSUInteger) { + delete (std::weak_ptr *)ptrToDelete; + }]; +} + +static inline facebook::react::SharedEventEmitter RCTUnwrapEventEmitter(NSData *data) +{ + if (data.length == 0) { + return nullptr; + } + + auto weakPtr = dynamic_cast *>( + (std::weak_ptr *)data.bytes); + if (weakPtr) { + return weakPtr->lock(); + } + + return nullptr; +} NS_ASSUME_NONNULL_END diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm index 2a5185d344ccf3..d08d0ba6e13a80 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm @@ -16,45 +16,6 @@ using namespace facebook::react; -@implementation RCTWeakEventEmitterWrapper { - std::weak_ptr _weakEventEmitter; -} - -- (void)setEventEmitter:(SharedEventEmitter)eventEmitter -{ - _weakEventEmitter = eventEmitter; -} - -- (SharedEventEmitter)eventEmitter -{ - return _weakEventEmitter.lock(); -} - -- (void)dealloc -{ - _weakEventEmitter.reset(); -} - -- (BOOL)isEqual:(id)object -{ - // We consider the underlying EventEmitter as the identity - if (![object isKindOfClass:[self class]]) { - return NO; - } - - auto thisEventEmitter = [self eventEmitter]; - auto otherEventEmitter = [((RCTWeakEventEmitterWrapper *)object) eventEmitter]; - return thisEventEmitter == otherEventEmitter; -} - -- (NSUInteger)hash -{ - // We consider the underlying EventEmitter as the identity - return (NSUInteger)_weakEventEmitter.lock().get(); -} - -@end - inline static UIFontWeight RCTUIFontWeightFromInteger(NSInteger fontWeight) { assert(fontWeight > 50); @@ -135,6 +96,7 @@ inline static CGFloat RCTBaseSizeForDynamicTypeRamp(const DynamicTypeRamp &dynam inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const TextAttributes &textAttributes) { if (textAttributes.allowFontScaling.value_or(true)) { + CGFloat fontSizeMultiplier = !isnan(textAttributes.fontSizeMultiplier) ? textAttributes.fontSizeMultiplier : 1.0; if (textAttributes.dynamicTypeRamp.has_value()) { DynamicTypeRamp dynamicTypeRamp = textAttributes.dynamicTypeRamp.value(); UIFontMetrics *fontMetrics = @@ -142,10 +104,11 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex // Using a specific font size reduces rounding errors from -scaledValueForValue: CGFloat requestedSize = isnan(textAttributes.fontSize) ? RCTBaseSizeForDynamicTypeRamp(dynamicTypeRamp) : textAttributes.fontSize; - return [fontMetrics scaledValueForValue:requestedSize] / requestedSize; - } else { - return textAttributes.fontSizeMultiplier; + fontSizeMultiplier = [fontMetrics scaledValueForValue:requestedSize] / requestedSize; } + CGFloat maxFontSizeMultiplier = + !isnan(textAttributes.maxFontSizeMultiplier) ? textAttributes.maxFontSizeMultiplier : 0.0; + return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier; } else { return 1.0; } @@ -407,10 +370,8 @@ void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText) { auto nsAttributedStringFragment = RCTNSAttributedStringFragmentFromFragment(fragment, placeholderImage); -#if !TARGET_OS_MACCATALYST if (fragment.parentShadowView.componentHandle) { - RCTWeakEventEmitterWrapper *eventEmitterWrapper = [RCTWeakEventEmitterWrapper new]; - eventEmitterWrapper.eventEmitter = fragment.parentShadowView.eventEmitter; + auto eventEmitterWrapper = RCTWrapEventEmitter(fragment.parentShadowView.eventEmitter); NSDictionary *additionalTextAttributes = @{RCTAttributedStringEventEmitterKey : eventEmitterWrapper}; @@ -418,7 +379,6 @@ void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText) [nsAttributedStringFragment addAttributes:additionalTextAttributes range:NSMakeRange(0, nsAttributedStringFragment.length)]; } -#endif return nsAttributedStringFragment; } diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm index b48a427fceab2c..86409360da8ac3 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm @@ -192,8 +192,23 @@ static UIFontDescriptorSystemDesign RCTGetFontDescriptorSystemDesign(NSString *f fontNames = [UIFont fontNamesForFamilyName:font.familyName]; fontWeight = fontWeight ?: RCTGetFontWeight(font); } else { - // Failback to system font. - font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight]; + // Check if font string is a list of fonts comma separated + NSArray *rawFontFamilies = [fontProperties.family componentsSeparatedByString:@","]; + if (rawFontFamilies.count >= 1) { + NSArray *updatedFontNames = fontNames; + + for (NSString *name in rawFontFamilies) { + UIFont *font = [UIFont fontWithName:name size:effectiveFontSize]; + if (font) { + updatedFontNames = [updatedFontNames arrayByAddingObject:font.fontName]; + } + } + + fontNames = updatedFontNames; + } else { + // Failback to system font. + font = [UIFont systemFontOfSize:effectiveFontSize weight:fontProperties.weight]; + } } } diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm index 9ffe117c4e1b84..f34fb9f568d5ee 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm @@ -268,11 +268,10 @@ - (SharedEventEmitter)getEventEmitterWithAttributeString:(AttributedString)attri // after (fraction == 1.0) the last character, then the attribute is valid. if (textStorage.length > 0 && (fraction > 0 || characterIndex > 0) && (fraction < 1 || characterIndex < textStorage.length - 1)) { - RCTWeakEventEmitterWrapper *eventEmitterWrapper = - (RCTWeakEventEmitterWrapper *)[textStorage attribute:RCTAttributedStringEventEmitterKey - atIndex:characterIndex - effectiveRange:NULL]; - return eventEmitterWrapper.eventEmitter; + NSData *eventEmitterWrapper = (NSData *)[textStorage attribute:RCTAttributedStringEventEmitterKey + atIndex:characterIndex + effectiveRange:NULL]; + return RCTUnwrapEventEmitter(eventEmitterWrapper); } return nil; diff --git a/packages/react-native/package.json b/packages/react-native/package.json index b2df8ae87aab28..8521fff1cbba2c 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "1000.0.0", + "version": "0.78.2", "description": "A framework for building native apps using React", "license": "MIT", "repository": { @@ -108,13 +108,13 @@ }, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native/assets-registry": "0.77.0-main", - "@react-native/codegen": "0.77.0-main", - "@react-native/community-cli-plugin": "0.77.0-main", - "@react-native/gradle-plugin": "0.77.0-main", - "@react-native/js-polyfills": "0.77.0-main", - "@react-native/normalize-colors": "0.77.0-main", - "@react-native/virtualized-lists": "0.77.0-main", + "@react-native/assets-registry": "0.78.2", + "@react-native/codegen": "0.78.2", + "@react-native/community-cli-plugin": "0.78.2", + "@react-native/gradle-plugin": "0.78.2", + "@react-native/js-polyfills": "0.78.2", + "@react-native/normalize-colors": "0.78.2", + "@react-native/virtualized-lists": "0.78.2", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", @@ -129,8 +129,8 @@ "invariant": "^2.2.4", "jest-environment-node": "^29.6.3", "memoize-one": "^5.0.0", - "metro-runtime": "^0.81.0", - "metro-source-map": "^0.81.0", + "metro-runtime": "^0.81.3", + "metro-source-map": "^0.81.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", diff --git a/packages/react-native/react-native.config.js b/packages/react-native/react-native.config.js index 3b572bb1e9c6d6..97750587c8dcf4 100644 --- a/packages/react-native/react-native.config.js +++ b/packages/react-native/react-native.config.js @@ -44,27 +44,11 @@ try { const commands = []; -try { - const { - bundleCommand, - startCommand, - } = require('@react-native/community-cli-plugin'); - commands.push(bundleCommand, startCommand); -} catch (e) { - const known = - e.code === 'MODULE_NOT_FOUND' && - e.message.includes('@react-native-community/cli-server-api'); - - if (!known) { - throw e; - } - - if (verbose) { - console.warn( - '@react-native-community/cli-server-api not found, the react-native.config.js may be unusable.', - ); - } -} +const { + bundleCommand, + startCommand, +} = require('@react-native/community-cli-plugin'); +commands.push(bundleCommand, startCommand); const codegenCommand = { name: 'codegen', @@ -84,12 +68,18 @@ const codegenCommand = { name: '--outputPath ', description: 'Path where generated artifacts will be output to.', }, + { + name: '--source ', + description: 'Whether the script is invoked from an `app` or a `library`', + default: 'app', + }, ], func: (argv, config, args) => require('./scripts/codegen/generate-artifacts-executor').execute( args.path, args.platform, args.outputPath, + args.source, ), }; diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 480bc8c5cce17c..f33d8133ef7998 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -495,7 +495,13 @@ function shouldSkipGenerationForRncore(schemaInfo, platform) { if (platform !== 'ios' || schemaInfo.library.config.name !== 'rncore') { return false; } - const rncoreOutputPath = CORE_LIBRARIES_WITH_OUTPUT_FOLDER.rncore.ios; + const rncoreOutputPath = path.join( + RNCORE_CONFIGS.ios, + 'react', + 'renderer', + 'components', + 'rncore', + ); const rncoreAbsolutePath = path.resolve(rncoreOutputPath); return ( rncoreAbsolutePath.includes('node_modules') && @@ -899,11 +905,12 @@ function generateFBReactNativeSpecIOS(projectRoot /*: string */) /*: void*/ { * @parameter projectRoot: the directory with the app source code, where the package.json lives. * @parameter baseOutputPath: the base output path for the CodeGen. * @parameter targetPlatform: the target platform. Supported values: 'android', 'ios', 'all'. + * @parameter source: the source that is invoking codegen. Supported values: 'app', 'library'. * @throws If it can't find a config file for react-native. * @throws If it can't find a CodeGen configuration in the file. * @throws If it can't find a cli for the CodeGen. */ -function execute(projectRoot, targetPlatform, baseOutputPath) { +function execute(projectRoot, targetPlatform, baseOutputPath, source) { try { codegenLog(`Analyzing ${path.join(projectRoot, 'package.json')}`); @@ -951,9 +958,12 @@ function execute(projectRoot, targetPlatform, baseOutputPath) { platform, ); - generateRCTThirdPartyComponents(libraries, outputPath); - generateCustomURLHandlers(libraries, outputPath); - generateAppDependencyProvider(outputPath); + if (source === 'app') { + // These components are only required by apps, not by libraries + generateRCTThirdPartyComponents(libraries, outputPath); + generateCustomURLHandlers(libraries, outputPath); + generateAppDependencyProvider(outputPath); + } cleanupEmptyFilesAndFolders(outputPath); } diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 744e112311a77e..5b28c10110c32f 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -458,6 +458,17 @@ const definitions: FeatureFlagDefinitions = { purpose: 'experimentation', }, }, + useShadowNodeStateOnClone: { + defaultValue: false, + metadata: { + dateAdded: '2025-04-16', + description: + 'Use the state stored on the source shadow node when cloning it instead of reading in the most recent state on the shadow node family.', + expectedReleaseValue: true, + purpose: 'experimentation', + }, + ossReleaseStage: 'none', + }, useTurboModuleInterop: { defaultValue: false, metadata: { diff --git a/packages/react-native/scripts/generate-codegen-artifacts.js b/packages/react-native/scripts/generate-codegen-artifacts.js index a8d4fa2db9cfb7..0f0ecdda7b4616 100644 --- a/packages/react-native/scripts/generate-codegen-artifacts.js +++ b/packages/react-native/scripts/generate-codegen-artifacts.js @@ -25,7 +25,12 @@ const argv = yargs alias: 'outputPath', description: 'Path where generated artifacts will be output to.', }) + .option('s', { + alias: 'source', + description: 'Whether the script is invoked from an `app` or a `library`', + default: 'app', + }) .usage('Usage: $0 -p [path to app] -t [target platform] -o [output path]') .demandOption(['p', 't']).argv; -executor.execute(argv.path, argv.targetPlatform, argv.outputPath); +executor.execute(argv.path, argv.targetPlatform, argv.outputPath, argv.source); diff --git a/packages/react-native/scripts/ios-configure-glog.sh b/packages/react-native/scripts/ios-configure-glog.sh index 6b2c9026843938..0450aafa684170 100755 --- a/packages/react-native/scripts/ios-configure-glog.sh +++ b/packages/react-native/scripts/ios-configure-glog.sh @@ -42,15 +42,15 @@ EOF patch -p1 config.sub fix_glog_0.3.5_apple_silicon.patch fi -XCRUN="$(which xcrun || true)" -if [ -n "$XCRUN" ]; then - export CC="$(xcrun -find -sdk $PLATFORM_NAME cc) -arch $CURRENT_ARCH -isysroot $(xcrun -sdk $PLATFORM_NAME --show-sdk-path)" - export CXX="$CC" -else - export CC="$CC:-$(which gcc)" - export CXX="$CXX:-$(which g++ || true)" -fi -export CXX="$CXX:-$CC" +# XCRUN="$(which xcrun || true)" +# if [ -n "$XCRUN" ]; then +# export CC="$(xcrun -find -sdk $PLATFORM_NAME cc) -arch $CURRENT_ARCH -isysroot $(xcrun -sdk $PLATFORM_NAME --show-sdk-path)" +# export CXX="$CC" +# else +# export CC="$CC:-$(which gcc)" +# export CXX="$CXX:-$(which g++ || true)" +# fi +# export CXX="$CXX:-$CC" # Remove automake symlink if it exists if [ -h "test-driver" ]; then diff --git a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh index 92325f1ad078f4..ae3dd62eb0090f 100755 --- a/packages/react-native/scripts/react_native_pods_utils/script_phases.sh +++ b/packages/react-native/scripts/react_native_pods_utils/script_phases.sh @@ -21,6 +21,18 @@ error () { exit 1 } +# Determine path to react-native-codegen +# DISCORD FIX: Our repo path isn't valid (has the files under `src` +# rather than `lib`), so the order of this `if` was modified to prefer +# the NPM path. +if [ -d "$CODEGEN_NPM_PATH" ]; then + CODEGEN_CLI_PATH=$(cd "$CODEGEN_NPM_PATH" && pwd) +elif [ -d "$CODEGEN_REPO_PATH" ]; then + CODEGEN_CLI_PATH=$(cd "$CODEGEN_REPO_PATH" && pwd) +else + error "error: Could not determine react-native-codegen location in $CODEGEN_REPO_PATH or $CODEGEN_NPM_PATH. Try running 'yarn install' or 'npm install' in your project root." +fi + find_node () { NODE_BINARY="${NODE_BINARY:-$(command -v node || true)}" if [ -z "$NODE_BINARY" ]; then diff --git a/packages/react-native/sdks/.hermesversion b/packages/react-native/sdks/.hermesversion new file mode 100644 index 00000000000000..4d7c96a0fd5566 --- /dev/null +++ b/packages/react-native/sdks/.hermesversion @@ -0,0 +1 @@ +hermes-2025-01-13-RNv0.78.0-a942ef374897d85da38e9c8904574f8376555388 \ No newline at end of file diff --git a/packages/react-native/src/private/animated/NativeAnimatedHelper.js b/packages/react-native/src/private/animated/NativeAnimatedHelper.js index 9ef311408a894c..b1acf6d995f4df 100644 --- a/packages/react-native/src/private/animated/NativeAnimatedHelper.js +++ b/packages/react-native/src/private/animated/NativeAnimatedHelper.js @@ -135,7 +135,7 @@ const API = { } : (tag, saveValueCallback) => { NativeOperations.getValue(tag, saveValueCallback); - }) as $NonMaybeType['getValue'], + }), setWaitingForIdentifier(id: string): void { waitingForQueuedOperations.add(id); @@ -218,7 +218,7 @@ const API = { if (Platform.OS === 'android') { NativeAnimatedModule?.finishOperationBatch?.(); } - }) as () => void, + }), createAnimatedNode(tag: number, config: AnimatedNodeConfig): void { NativeOperations.createAnimatedNode(tag, config); @@ -260,7 +260,7 @@ const API = { config, endCallback, ); - }) as $NonMaybeType['startAnimatingNode'], + }), stopAnimation(animationId: number) { NativeOperations.stopAnimation(animationId); diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index cebed3c31eafc8..d958b2fa0e53b9 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3037cf1c938dae492b656333cec9633c>> + * @generated SignedSource<<63601ec83ade8f3774d185ebacf4c792>> * @flow strict */ @@ -94,6 +94,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ useOptimizedEventBatchingOnAndroid: Getter, useRawPropsJsiValue: Getter, useRuntimeShadowNodeReferenceUpdate: Getter, + useShadowNodeStateOnClone: Getter, useTurboModuleInterop: Getter, useTurboModules: Getter, }>; @@ -359,6 +360,10 @@ export const useRawPropsJsiValue: Getter = createNativeFlagGetter('useR * When enabled, cloning shadow nodes within react native will update the reference held by the current JS fiber tree. */ export const useRuntimeShadowNodeReferenceUpdate: Getter = createNativeFlagGetter('useRuntimeShadowNodeReferenceUpdate', true); +/** + * Use the state stored on the source shadow node when cloning it instead of reading in the most recent state on the shadow node family. + */ +export const useShadowNodeStateOnClone: Getter = createNativeFlagGetter('useShadowNodeStateOnClone', false); /** * In Bridgeless mode, should legacy NativeModules use the TurboModule system? */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index f9f4a5bc187baf..03e8d13530798f 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<37e95652ef5d824bb05e78ebdb051e43>> + * @generated SignedSource<> * @flow strict */ @@ -67,6 +67,7 @@ export interface Spec extends TurboModule { +useOptimizedEventBatchingOnAndroid?: () => boolean; +useRawPropsJsiValue?: () => boolean; +useRuntimeShadowNodeReferenceUpdate?: () => boolean; + +useShadowNodeStateOnClone?: () => boolean; +useTurboModuleInterop?: () => boolean; +useTurboModules?: () => boolean; } diff --git a/packages/react-native/third-party-podspecs/DoubleConversion.podspec b/packages/react-native/third-party-podspecs/DoubleConversion.podspec index 56923bcab13a3e..9c89ac48e77ea1 100644 --- a/packages/react-native/third-party-podspecs/DoubleConversion.podspec +++ b/packages/react-native/third-party-podspecs/DoubleConversion.podspec @@ -3,6 +3,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +require_relative "../scripts/react_native_pods" + double_conversion_config = get_double_conversion_config() double_conversion_git_url = double_conversion_config[:git] diff --git a/packages/react-native/third-party-podspecs/RCT-Folly.podspec b/packages/react-native/third-party-podspecs/RCT-Folly.podspec index b3c60a50a9e3fd..ea2a44b708af95 100644 --- a/packages/react-native/third-party-podspecs/RCT-Folly.podspec +++ b/packages/react-native/third-party-podspecs/RCT-Folly.podspec @@ -3,6 +3,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +require_relative "../scripts/react_native_pods" + folly_config = get_folly_config() folly_compiler_flags = folly_config[:compiler_flags] folly_release_version = folly_config[:version] diff --git a/packages/react-native/third-party-podspecs/boost.podspec b/packages/react-native/third-party-podspecs/boost.podspec index e30a2305df8e9f..5c29c4c7e5f860 100644 --- a/packages/react-native/third-party-podspecs/boost.podspec +++ b/packages/react-native/third-party-podspecs/boost.podspec @@ -3,6 +3,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +require_relative "../scripts/react_native_pods" + boost_config = get_boost_config() boost_git_url = boost_config[:git] @@ -13,8 +15,8 @@ Pod::Spec.new do |spec| spec.homepage = 'http://www.boost.org' spec.summary = 'Boost provides free peer-reviewed portable C++ source libraries.' spec.authors = 'Rene Rivera' - spec.source = { :git => boost_git_url, - :tag => "v1.84.0" } + spec.source = { :http => 'https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.gz', + :sha256 => 'a5800f405508f5df8114558ca9855d2640a2de8f0445f051fa1c7c3383045724' } # Pinning to the same version as React.podspec. spec.platforms = min_supported_versions diff --git a/packages/react-native/third-party-podspecs/fast_float.podspec b/packages/react-native/third-party-podspecs/fast_float.podspec index 8c89d9da18f54f..00ddbe85585de0 100644 --- a/packages/react-native/third-party-podspecs/fast_float.podspec +++ b/packages/react-native/third-party-podspecs/fast_float.podspec @@ -3,6 +3,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +require_relative "../scripts/react_native_pods" + fast_float_config = get_fast_float_config() fast_float_git_url = fast_float_config[:git] diff --git a/packages/react-native/third-party-podspecs/fmt.podspec b/packages/react-native/third-party-podspecs/fmt.podspec index 2f38990e226c13..0c92fb26257628 100644 --- a/packages/react-native/third-party-podspecs/fmt.podspec +++ b/packages/react-native/third-party-podspecs/fmt.podspec @@ -3,6 +3,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +require_relative "../scripts/react_native_pods" + fmt_config = get_fmt_config() fmt_git_url = fmt_config[:git] diff --git a/packages/react-native/third-party-podspecs/glog.podspec b/packages/react-native/third-party-podspecs/glog.podspec index af7668077f9045..c03f6038d0fc0f 100644 --- a/packages/react-native/third-party-podspecs/glog.podspec +++ b/packages/react-native/third-party-podspecs/glog.podspec @@ -3,6 +3,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +require_relative "../scripts/react_native_pods" + glog_config = get_glog_config() glog_git_url = glog_config[:git] diff --git a/packages/rn-tester/Gemfile b/packages/rn-tester/Gemfile index 22f0060db385f6..120dcb2bf5d1e3 100644 --- a/packages/rn-tester/Gemfile +++ b/packages/rn-tester/Gemfile @@ -9,3 +9,4 @@ gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1' gem 'rexml' gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' gem 'xcodeproj', '< 1.26.0' +gem 'concurrent-ruby', '< 1.3.4' diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 7d6b03bb3920b8..257b9fda42cc01 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -2,13 +2,13 @@ PODS: - boost (1.84.0) - DoubleConversion (1.1.6) - fast_float (6.1.4) - - FBLazyVector (1000.0.0) + - FBLazyVector (0.78.1) - fmt (11.0.2) - glog (0.3.5) - - hermes-engine (1000.0.0): - - hermes-engine/Pre-built (= 1000.0.0) - - hermes-engine/Pre-built (1000.0.0) - - MyNativeView (0.77.0-main): + - hermes-engine (0.78.1): + - hermes-engine/Pre-built (= 0.78.1) + - hermes-engine/Pre-built (0.78.1) + - MyNativeView (0.78.1): - DoubleConversion - glog - hermes-engine @@ -29,7 +29,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - NativeCxxModuleExample (0.77.0-main): + - NativeCxxModuleExample (0.78.1): - DoubleConversion - glog - hermes-engine @@ -51,7 +51,7 @@ PODS: - ReactCommon/turbomodule/core - Yoga - OCMock (3.9.4) - - OSSLibraryExample (0.77.0-main): + - OSSLibraryExample (0.78.1): - DoubleConversion - glog - hermes-engine @@ -91,32 +91,32 @@ PODS: - fast_float (= 6.1.4) - fmt (= 11.0.2) - glog - - RCTDeprecation (1000.0.0) - - RCTRequired (1000.0.0) - - RCTTypeSafety (1000.0.0): - - FBLazyVector (= 1000.0.0) - - RCTRequired (= 1000.0.0) - - React-Core (= 1000.0.0) - - React (1000.0.0): - - React-Core (= 1000.0.0) - - React-Core/DevSupport (= 1000.0.0) - - React-Core/RCTWebSocket (= 1000.0.0) - - React-RCTActionSheet (= 1000.0.0) - - React-RCTAnimation (= 1000.0.0) - - React-RCTBlob (= 1000.0.0) - - React-RCTImage (= 1000.0.0) - - React-RCTLinking (= 1000.0.0) - - React-RCTNetwork (= 1000.0.0) - - React-RCTSettings (= 1000.0.0) - - React-RCTText (= 1000.0.0) - - React-RCTVibration (= 1000.0.0) - - React-callinvoker (1000.0.0) - - React-Core (1000.0.0): + - RCTDeprecation (0.78.1) + - RCTRequired (0.78.1) + - RCTTypeSafety (0.78.1): + - FBLazyVector (= 0.78.1) + - RCTRequired (= 0.78.1) + - React-Core (= 0.78.1) + - React (0.78.1): + - React-Core (= 0.78.1) + - React-Core/DevSupport (= 0.78.1) + - React-Core/RCTWebSocket (= 0.78.1) + - React-RCTActionSheet (= 0.78.1) + - React-RCTAnimation (= 0.78.1) + - React-RCTBlob (= 0.78.1) + - React-RCTImage (= 0.78.1) + - React-RCTLinking (= 0.78.1) + - React-RCTNetwork (= 0.78.1) + - React-RCTSettings (= 0.78.1) + - React-RCTText (= 0.78.1) + - React-RCTVibration (= 0.78.1) + - React-callinvoker (0.78.1) + - React-Core (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - RCTDeprecation - - React-Core/Default (= 1000.0.0) + - React-Core/Default (= 0.78.1) - React-cxxreact - React-featureflags - React-hermes @@ -128,7 +128,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/CoreModulesHeaders (1000.0.0): + - React-Core/CoreModulesHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -145,7 +145,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/Default (1000.0.0): + - React-Core/Default (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -161,13 +161,13 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/DevSupport (1000.0.0): + - React-Core/DevSupport (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - RCTDeprecation - - React-Core/Default (= 1000.0.0) - - React-Core/RCTWebSocket (= 1000.0.0) + - React-Core/Default (= 0.78.1) + - React-Core/RCTWebSocket (= 0.78.1) - React-cxxreact - React-featureflags - React-hermes @@ -179,7 +179,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTActionSheetHeaders (1000.0.0): + - React-Core/RCTActionSheetHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -196,7 +196,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTAnimationHeaders (1000.0.0): + - React-Core/RCTAnimationHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -213,7 +213,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTBlobHeaders (1000.0.0): + - React-Core/RCTBlobHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -230,7 +230,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTImageHeaders (1000.0.0): + - React-Core/RCTImageHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -247,7 +247,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTLinkingHeaders (1000.0.0): + - React-Core/RCTLinkingHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -264,7 +264,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTNetworkHeaders (1000.0.0): + - React-Core/RCTNetworkHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -281,7 +281,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTPushNotificationHeaders (1000.0.0): + - React-Core/RCTPushNotificationHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -298,7 +298,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTSettingsHeaders (1000.0.0): + - React-Core/RCTSettingsHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -315,7 +315,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTTextHeaders (1000.0.0): + - React-Core/RCTTextHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -332,7 +332,7 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTVibrationHeaders (1000.0.0): + - React-Core/RCTVibrationHeaders (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -349,12 +349,12 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-Core/RCTWebSocket (1000.0.0): + - React-Core/RCTWebSocket (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - RCTDeprecation - - React-Core/Default (= 1000.0.0) + - React-Core/Default (= 0.78.1) - React-cxxreact - React-featureflags - React-hermes @@ -366,22 +366,22 @@ PODS: - React-utils - SocketRocket (= 0.7.1) - Yoga - - React-CoreModules (1000.0.0): + - React-CoreModules (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) - RCT-Folly (= 2024.11.18.00) - - RCTTypeSafety (= 1000.0.0) - - React-Core/CoreModulesHeaders (= 1000.0.0) - - React-jsi (= 1000.0.0) + - RCTTypeSafety (= 0.78.1) + - React-Core/CoreModulesHeaders (= 0.78.1) + - React-jsi (= 0.78.1) - React-jsinspector - React-NativeModulesApple - React-RCTBlob - React-RCTFBReactNativeSpec - - React-RCTImage (= 1000.0.0) + - React-RCTImage (= 0.78.1) - ReactCommon - SocketRocket (= 0.7.1) - - React-cxxreact (1000.0.0): + - React-cxxreact (0.78.1): - boost - DoubleConversion - fast_float (= 6.1.4) @@ -389,16 +389,16 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - - React-callinvoker (= 1000.0.0) - - React-debug (= 1000.0.0) - - React-jsi (= 1000.0.0) + - React-callinvoker (= 0.78.1) + - React-debug (= 0.78.1) + - React-jsi (= 0.78.1) - React-jsinspector - - React-logger (= 1000.0.0) - - React-perflogger (= 1000.0.0) - - React-runtimeexecutor (= 1000.0.0) - - React-timing (= 1000.0.0) - - React-debug (1000.0.0) - - React-defaultsnativemodule (1000.0.0): + - React-logger (= 0.78.1) + - React-perflogger (= 0.78.1) + - React-runtimeexecutor (= 0.78.1) + - React-timing (= 0.78.1) + - React-debug (0.78.1) + - React-defaultsnativemodule (0.78.1): - hermes-engine - RCT-Folly - React-domnativemodule @@ -408,7 +408,7 @@ PODS: - React-jsiexecutor - React-microtasksnativemodule - React-RCTFBReactNativeSpec - - React-domnativemodule (1000.0.0): + - React-domnativemodule (0.78.1): - hermes-engine - RCT-Folly - React-Fabric @@ -419,7 +419,7 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - Yoga - - React-Fabric (1000.0.0): + - React-Fabric (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -431,22 +431,22 @@ PODS: - React-Core - React-cxxreact - React-debug - - React-Fabric/animations (= 1000.0.0) - - React-Fabric/attributedstring (= 1000.0.0) - - React-Fabric/componentregistry (= 1000.0.0) - - React-Fabric/componentregistrynative (= 1000.0.0) - - React-Fabric/components (= 1000.0.0) - - React-Fabric/consistency (= 1000.0.0) - - React-Fabric/core (= 1000.0.0) - - React-Fabric/dom (= 1000.0.0) - - React-Fabric/imagemanager (= 1000.0.0) - - React-Fabric/leakchecker (= 1000.0.0) - - React-Fabric/mounting (= 1000.0.0) - - React-Fabric/observers (= 1000.0.0) - - React-Fabric/scheduler (= 1000.0.0) - - React-Fabric/telemetry (= 1000.0.0) - - React-Fabric/templateprocessor (= 1000.0.0) - - React-Fabric/uimanager (= 1000.0.0) + - React-Fabric/animations (= 0.78.1) + - React-Fabric/attributedstring (= 0.78.1) + - React-Fabric/componentregistry (= 0.78.1) + - React-Fabric/componentregistrynative (= 0.78.1) + - React-Fabric/components (= 0.78.1) + - React-Fabric/consistency (= 0.78.1) + - React-Fabric/core (= 0.78.1) + - React-Fabric/dom (= 0.78.1) + - React-Fabric/imagemanager (= 0.78.1) + - React-Fabric/leakchecker (= 0.78.1) + - React-Fabric/mounting (= 0.78.1) + - React-Fabric/observers (= 0.78.1) + - React-Fabric/scheduler (= 0.78.1) + - React-Fabric/telemetry (= 0.78.1) + - React-Fabric/templateprocessor (= 0.78.1) + - React-Fabric/uimanager (= 0.78.1) - React-featureflags - React-graphics - React-jsi @@ -456,7 +456,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/animations (1000.0.0): + - React-Fabric/animations (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -477,7 +477,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/attributedstring (1000.0.0): + - React-Fabric/attributedstring (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -498,7 +498,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/componentregistry (1000.0.0): + - React-Fabric/componentregistry (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -519,7 +519,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/componentregistrynative (1000.0.0): + - React-Fabric/componentregistrynative (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -540,7 +540,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components (1000.0.0): + - React-Fabric/components (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -552,9 +552,9 @@ PODS: - React-Core - React-cxxreact - React-debug - - React-Fabric/components/legacyviewmanagerinterop (= 1000.0.0) - - React-Fabric/components/root (= 1000.0.0) - - React-Fabric/components/view (= 1000.0.0) + - React-Fabric/components/legacyviewmanagerinterop (= 0.78.1) + - React-Fabric/components/root (= 0.78.1) + - React-Fabric/components/view (= 0.78.1) - React-featureflags - React-graphics - React-jsi @@ -564,7 +564,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/legacyviewmanagerinterop (1000.0.0): + - React-Fabric/components/legacyviewmanagerinterop (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -585,7 +585,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/root (1000.0.0): + - React-Fabric/components/root (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -606,7 +606,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/components/view (1000.0.0): + - React-Fabric/components/view (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -628,7 +628,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-Fabric/consistency (1000.0.0): + - React-Fabric/consistency (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -649,7 +649,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/core (1000.0.0): + - React-Fabric/core (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -670,7 +670,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/dom (1000.0.0): + - React-Fabric/dom (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -691,7 +691,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/imagemanager (1000.0.0): + - React-Fabric/imagemanager (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -712,7 +712,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/leakchecker (1000.0.0): + - React-Fabric/leakchecker (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -733,7 +733,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/mounting (1000.0.0): + - React-Fabric/mounting (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -754,7 +754,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/observers (1000.0.0): + - React-Fabric/observers (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -766,7 +766,7 @@ PODS: - React-Core - React-cxxreact - React-debug - - React-Fabric/observers/events (= 1000.0.0) + - React-Fabric/observers/events (= 0.78.1) - React-featureflags - React-graphics - React-jsi @@ -776,7 +776,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/observers/events (1000.0.0): + - React-Fabric/observers/events (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -797,7 +797,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/scheduler (1000.0.0): + - React-Fabric/scheduler (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -820,7 +820,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/telemetry (1000.0.0): + - React-Fabric/telemetry (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -841,7 +841,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/templateprocessor (1000.0.0): + - React-Fabric/templateprocessor (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -862,7 +862,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/uimanager (1000.0.0): + - React-Fabric/uimanager (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -874,7 +874,7 @@ PODS: - React-Core - React-cxxreact - React-debug - - React-Fabric/uimanager/consistency (= 1000.0.0) + - React-Fabric/uimanager/consistency (= 0.78.1) - React-featureflags - React-graphics - React-jsi @@ -885,7 +885,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-Fabric/uimanager/consistency (1000.0.0): + - React-Fabric/uimanager/consistency (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -907,7 +907,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - - React-FabricComponents (1000.0.0): + - React-FabricComponents (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -920,8 +920,8 @@ PODS: - React-cxxreact - React-debug - React-Fabric - - React-FabricComponents/components (= 1000.0.0) - - React-FabricComponents/textlayoutmanager (= 1000.0.0) + - React-FabricComponents/components (= 0.78.1) + - React-FabricComponents/textlayoutmanager (= 0.78.1) - React-featureflags - React-graphics - React-jsi @@ -932,7 +932,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components (1000.0.0): + - React-FabricComponents/components (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -945,15 +945,15 @@ PODS: - React-cxxreact - React-debug - React-Fabric - - React-FabricComponents/components/inputaccessory (= 1000.0.0) - - React-FabricComponents/components/iostextinput (= 1000.0.0) - - React-FabricComponents/components/modal (= 1000.0.0) - - React-FabricComponents/components/rncore (= 1000.0.0) - - React-FabricComponents/components/safeareaview (= 1000.0.0) - - React-FabricComponents/components/scrollview (= 1000.0.0) - - React-FabricComponents/components/text (= 1000.0.0) - - React-FabricComponents/components/textinput (= 1000.0.0) - - React-FabricComponents/components/unimplementedview (= 1000.0.0) + - React-FabricComponents/components/inputaccessory (= 0.78.1) + - React-FabricComponents/components/iostextinput (= 0.78.1) + - React-FabricComponents/components/modal (= 0.78.1) + - React-FabricComponents/components/rncore (= 0.78.1) + - React-FabricComponents/components/safeareaview (= 0.78.1) + - React-FabricComponents/components/scrollview (= 0.78.1) + - React-FabricComponents/components/text (= 0.78.1) + - React-FabricComponents/components/textinput (= 0.78.1) + - React-FabricComponents/components/unimplementedview (= 0.78.1) - React-featureflags - React-graphics - React-jsi @@ -964,7 +964,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/inputaccessory (1000.0.0): + - React-FabricComponents/components/inputaccessory (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -987,7 +987,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/iostextinput (1000.0.0): + - React-FabricComponents/components/iostextinput (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1010,7 +1010,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/modal (1000.0.0): + - React-FabricComponents/components/modal (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1033,7 +1033,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/rncore (1000.0.0): + - React-FabricComponents/components/rncore (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1056,7 +1056,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/safeareaview (1000.0.0): + - React-FabricComponents/components/safeareaview (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1079,7 +1079,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/scrollview (1000.0.0): + - React-FabricComponents/components/scrollview (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1102,7 +1102,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/text (1000.0.0): + - React-FabricComponents/components/text (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1125,7 +1125,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/textinput (1000.0.0): + - React-FabricComponents/components/textinput (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1148,7 +1148,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/components/unimplementedview (1000.0.0): + - React-FabricComponents/components/unimplementedview (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1171,7 +1171,7 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricComponents/textlayoutmanager (1000.0.0): + - React-FabricComponents/textlayoutmanager (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1194,29 +1194,29 @@ PODS: - React-utils - ReactCommon/turbomodule/core - Yoga - - React-FabricImage (1000.0.0): + - React-FabricImage (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) - - RCTRequired (= 1000.0.0) - - RCTTypeSafety (= 1000.0.0) + - RCTRequired (= 0.78.1) + - RCTTypeSafety (= 0.78.1) - React-Fabric - React-featureflags - React-graphics - React-ImageManager - React-jsi - - React-jsiexecutor (= 1000.0.0) + - React-jsiexecutor (= 0.78.1) - React-logger - React-rendererdebug - React-utils - ReactCommon - Yoga - - React-featureflags (1000.0.0): + - React-featureflags (0.78.1): - RCT-Folly (= 2024.11.18.00) - - React-featureflagsnativemodule (1000.0.0): + - React-featureflagsnativemodule (0.78.1): - hermes-engine - RCT-Folly - React-featureflags @@ -1224,7 +1224,7 @@ PODS: - React-jsiexecutor - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - - React-graphics (1000.0.0): + - React-graphics (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1234,20 +1234,20 @@ PODS: - React-jsi - React-jsiexecutor - React-utils - - React-hermes (1000.0.0): + - React-hermes (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - - React-cxxreact (= 1000.0.0) + - React-cxxreact (= 0.78.1) - React-jsi - - React-jsiexecutor (= 1000.0.0) + - React-jsiexecutor (= 0.78.1) - React-jsinspector - - React-perflogger (= 1000.0.0) + - React-perflogger (= 0.78.1) - React-runtimeexecutor - - React-idlecallbacksnativemodule (1000.0.0): + - React-idlecallbacksnativemodule (0.78.1): - glog - hermes-engine - RCT-Folly @@ -1256,7 +1256,7 @@ PODS: - React-RCTFBReactNativeSpec - React-runtimescheduler - ReactCommon/turbomodule/core - - React-ImageManager (1000.0.0): + - React-ImageManager (0.78.1): - glog - RCT-Folly/Fabric - React-Core/Default @@ -1265,7 +1265,7 @@ PODS: - React-graphics - React-rendererdebug - React-utils - - React-jserrorhandler (1000.0.0): + - React-jserrorhandler (0.78.1): - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1274,7 +1274,7 @@ PODS: - React-featureflags - React-jsi - ReactCommon/turbomodule/bridging - - React-jsi (1000.0.0): + - React-jsi (0.78.1): - boost - DoubleConversion - fast_float (= 6.1.4) @@ -1282,18 +1282,18 @@ PODS: - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - - React-jsiexecutor (1000.0.0): + - React-jsiexecutor (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - - React-cxxreact (= 1000.0.0) - - React-jsi (= 1000.0.0) + - React-cxxreact (= 0.78.1) + - React-jsi (= 0.78.1) - React-jsinspector - - React-perflogger (= 1000.0.0) - - React-jsinspector (1000.0.0): + - React-perflogger (= 0.78.1) + - React-jsinspector (0.78.1): - DoubleConversion - glog - hermes-engine @@ -1301,25 +1301,25 @@ PODS: - React-featureflags - React-jsi - React-jsinspectortracing - - React-perflogger (= 1000.0.0) - - React-runtimeexecutor (= 1000.0.0) - - React-jsinspectortracing (1000.0.0): + - React-perflogger (= 0.78.1) + - React-runtimeexecutor (= 0.78.1) + - React-jsinspectortracing (0.78.1): - RCT-Folly - - React-jsitracing (1000.0.0): + - React-jsitracing (0.78.1): - React-jsi - - React-logger (1000.0.0): + - React-logger (0.78.1): - glog - - React-Mapbuffer (1000.0.0): + - React-Mapbuffer (0.78.1): - glog - React-debug - - React-microtasksnativemodule (1000.0.0): + - React-microtasksnativemodule (0.78.1): - hermes-engine - RCT-Folly - React-jsi - React-jsiexecutor - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - - React-NativeModulesApple (1000.0.0): + - React-NativeModulesApple (0.78.1): - glog - hermes-engine - React-callinvoker @@ -1330,18 +1330,18 @@ PODS: - React-runtimeexecutor - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-perflogger (1000.0.0): + - React-perflogger (0.78.1): - DoubleConversion - RCT-Folly (= 2024.11.18.00) - - React-performancetimeline (1000.0.0): + - React-performancetimeline (0.78.1): - RCT-Folly (= 2024.11.18.00) - React-cxxreact - React-featureflags - React-jsinspectortracing - React-timing - - React-RCTActionSheet (1000.0.0): - - React-Core/RCTActionSheetHeaders (= 1000.0.0) - - React-RCTAnimation (1000.0.0): + - React-RCTActionSheet (0.78.1): + - React-Core/RCTActionSheetHeaders (= 0.78.1) + - React-RCTAnimation (0.78.1): - RCT-Folly (= 2024.11.18.00) - RCTTypeSafety - React-Core/RCTAnimationHeaders @@ -1349,7 +1349,7 @@ PODS: - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-RCTAppDelegate (1000.0.0): + - React-RCTAppDelegate (0.78.1): - RCT-Folly (= 2024.11.18.00) - RCTRequired - RCTTypeSafety @@ -1373,7 +1373,7 @@ PODS: - React-runtimescheduler - React-utils - ReactCommon - - React-RCTBlob (1000.0.0): + - React-RCTBlob (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1387,7 +1387,7 @@ PODS: - React-RCTFBReactNativeSpec - React-RCTNetwork - ReactCommon - - React-RCTFabric (1000.0.0): + - React-RCTFabric (0.78.1): - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1410,7 +1410,7 @@ PODS: - React-runtimescheduler - React-utils - Yoga - - React-RCTFBReactNativeSpec (1000.0.0): + - React-RCTFBReactNativeSpec (0.78.1): - hermes-engine - RCT-Folly - RCTRequired @@ -1420,7 +1420,7 @@ PODS: - React-jsiexecutor - React-NativeModulesApple - ReactCommon - - React-RCTImage (1000.0.0): + - React-RCTImage (0.78.1): - RCT-Folly (= 2024.11.18.00) - RCTTypeSafety - React-Core/RCTImageHeaders @@ -1429,14 +1429,14 @@ PODS: - React-RCTFBReactNativeSpec - React-RCTNetwork - ReactCommon - - React-RCTLinking (1000.0.0): - - React-Core/RCTLinkingHeaders (= 1000.0.0) - - React-jsi (= 1000.0.0) + - React-RCTLinking (0.78.1): + - React-Core/RCTLinkingHeaders (= 0.78.1) + - React-jsi (= 0.78.1) - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - ReactCommon/turbomodule/core (= 1000.0.0) - - React-RCTNetwork (1000.0.0): + - ReactCommon/turbomodule/core (= 0.78.1) + - React-RCTNetwork (0.78.1): - RCT-Folly (= 2024.11.18.00) - RCTTypeSafety - React-Core/RCTNetworkHeaders @@ -1444,14 +1444,14 @@ PODS: - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-RCTPushNotification (1000.0.0): + - React-RCTPushNotification (0.78.1): - RCTTypeSafety - React-Core/RCTPushNotificationHeaders - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-RCTSettings (1000.0.0): + - React-RCTSettings (0.78.1): - RCT-Folly (= 2024.11.18.00) - RCTTypeSafety - React-Core/RCTSettingsHeaders @@ -1459,31 +1459,31 @@ PODS: - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-RCTTest (1000.0.0): + - React-RCTTest (0.78.1): - RCT-Folly (= 2024.11.18.00) - - React-Core (= 1000.0.0) - - React-CoreModules (= 1000.0.0) - - React-jsi (= 1000.0.0) - - ReactCommon/turbomodule/core (= 1000.0.0) - - React-RCTText (1000.0.0): - - React-Core/RCTTextHeaders (= 1000.0.0) + - React-Core (= 0.78.1) + - React-CoreModules (= 0.78.1) + - React-jsi (= 0.78.1) + - ReactCommon/turbomodule/core (= 0.78.1) + - React-RCTText (0.78.1): + - React-Core/RCTTextHeaders (= 0.78.1) - Yoga - - React-RCTVibration (1000.0.0): + - React-RCTVibration (0.78.1): - RCT-Folly (= 2024.11.18.00) - React-Core/RCTVibrationHeaders - React-jsi - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - React-rendererconsistency (1000.0.0) - - React-rendererdebug (1000.0.0): + - React-rendererconsistency (0.78.1) + - React-rendererdebug (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) - RCT-Folly (= 2024.11.18.00) - React-debug - - React-rncore (1000.0.0) - - React-RuntimeApple (1000.0.0): + - React-rncore (0.78.1) + - React-RuntimeApple (0.78.1): - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) - React-callinvoker @@ -1504,7 +1504,7 @@ PODS: - React-RuntimeHermes - React-runtimescheduler - React-utils - - React-RuntimeCore (1000.0.0): + - React-RuntimeCore (0.78.1): - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1519,9 +1519,9 @@ PODS: - React-runtimeexecutor - React-runtimescheduler - React-utils - - React-runtimeexecutor (1000.0.0): - - React-jsi (= 1000.0.0) - - React-RuntimeHermes (1000.0.0): + - React-runtimeexecutor (0.78.1): + - React-jsi (= 0.78.1) + - React-RuntimeHermes (0.78.1): - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) - React-featureflags @@ -1531,7 +1531,7 @@ PODS: - React-jsitracing - React-RuntimeCore - React-utils - - React-runtimescheduler (1000.0.0): + - React-runtimescheduler (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -1546,16 +1546,16 @@ PODS: - React-runtimeexecutor - React-timing - React-utils - - React-timing (1000.0.0) - - React-utils (1000.0.0): + - React-timing (0.78.1) + - React-utils (0.78.1): - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - React-debug - - React-jsi (= 1000.0.0) - - ReactAppDependencyProvider (1000.0.0): + - React-jsi (= 0.78.1) + - ReactAppDependencyProvider (0.78.1): - ReactCodegen - - ReactCodegen (1000.0.0): + - ReactCodegen (0.78.1): - DoubleConversion - glog - hermes-engine @@ -1576,9 +1576,9 @@ PODS: - React-utils - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - ReactCommon (1000.0.0): - - ReactCommon/turbomodule (= 1000.0.0) - - ReactCommon-Samples (1000.0.0): + - ReactCommon (0.78.1): + - ReactCommon/turbomodule (= 0.78.1) + - ReactCommon-Samples (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) @@ -1590,48 +1590,48 @@ PODS: - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - ReactCommon/turbomodule (1000.0.0): + - ReactCommon/turbomodule (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - - React-callinvoker (= 1000.0.0) - - React-cxxreact (= 1000.0.0) - - React-jsi (= 1000.0.0) - - React-logger (= 1000.0.0) - - React-perflogger (= 1000.0.0) - - ReactCommon/turbomodule/bridging (= 1000.0.0) - - ReactCommon/turbomodule/core (= 1000.0.0) - - ReactCommon/turbomodule/bridging (1000.0.0): + - React-callinvoker (= 0.78.1) + - React-cxxreact (= 0.78.1) + - React-jsi (= 0.78.1) + - React-logger (= 0.78.1) + - React-perflogger (= 0.78.1) + - ReactCommon/turbomodule/bridging (= 0.78.1) + - ReactCommon/turbomodule/core (= 0.78.1) + - ReactCommon/turbomodule/bridging (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - - React-callinvoker (= 1000.0.0) - - React-cxxreact (= 1000.0.0) - - React-jsi (= 1000.0.0) - - React-logger (= 1000.0.0) - - React-perflogger (= 1000.0.0) - - ReactCommon/turbomodule/core (1000.0.0): + - React-callinvoker (= 0.78.1) + - React-cxxreact (= 0.78.1) + - React-jsi (= 0.78.1) + - React-logger (= 0.78.1) + - React-perflogger (= 0.78.1) + - ReactCommon/turbomodule/core (0.78.1): - DoubleConversion - fast_float (= 6.1.4) - fmt (= 11.0.2) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - - React-callinvoker (= 1000.0.0) - - React-cxxreact (= 1000.0.0) - - React-debug (= 1000.0.0) - - React-featureflags (= 1000.0.0) - - React-jsi (= 1000.0.0) - - React-logger (= 1000.0.0) - - React-perflogger (= 1000.0.0) - - React-utils (= 1000.0.0) - - ScreenshotManager (0.77.0-main): + - React-callinvoker (= 0.78.1) + - React-cxxreact (= 0.78.1) + - React-debug (= 0.78.1) + - React-featureflags (= 0.78.1) + - React-jsi (= 0.78.1) + - React-logger (= 0.78.1) + - React-perflogger (= 0.78.1) + - React-utils (= 0.78.1) + - ScreenshotManager (0.78.1): - DoubleConversion - glog - hermes-engine @@ -1753,7 +1753,7 @@ EXTERNAL SOURCES: :podspec: "../react-native/third-party-podspecs/glog.podspec" hermes-engine: :podspec: "../react-native/sdks/hermes-engine/hermes-engine.podspec" - :tag: '' + :tag: hermes-2025-01-13-RNv0.78.0-a942ef374897d85da38e9c8904574f8376555388 MyNativeView: :path: NativeComponentExample NativeCxxModuleExample: @@ -1891,78 +1891,78 @@ SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 - FBLazyVector: d3c2dd739a63c1a124e775df075dc7c517a719cb + FBLazyVector: bba368dacede4c9dec7a58c9be5a2d3e9ea30cc7 fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 - hermes-engine: 60e4048240c6d6c4bf6fe622e6ea9a1fb6d9706d - MyNativeView: d92d8827d14b7c296f84424a8aed94fad2c689f5 - NativeCxxModuleExample: a9058817bb3f1776256d9def25c341fa1aa9cc07 + hermes-engine: f493b0a600aed5dc06532141603688a30a5b2f61 + MyNativeView: 2f73ce8600018e6fa3eedc663dbe4c299f0c81fe + NativeCxxModuleExample: 44498f1d064fe1603abc0ab922f9bae4b33493a4 OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74 - OSSLibraryExample: fb99bfb6f1033e5ac3cc1e382343e90676cc5a7a - RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 - RCTDeprecation: 3808e36294137f9ee5668f4df2e73dc079cd1dcf - RCTRequired: a00614e2da5344c2cda3d287050b6cee00e21dc6 - RCTTypeSafety: 459a16418c6b413060d35434ba3e83f5b0bd2651 - React: 170a01a19ba2525ab7f11243e2df6b19bf268093 - React-callinvoker: f08f425e4043cd1998a158b6e39a6aed1fd1d718 - React-Core: a1d04289bb054eb9f2de0b1ddbbd5ff22b8dbab9 - React-CoreModules: 60a8ca66ac2348dee82ecc768b4d631f02baa549 - React-cxxreact: 7d2cf5415a8e75e0d4b3e9a467e1a72c76a15a24 - React-debug: 195df38487d3f48a7af04deddeb4a5c6d4440416 - React-defaultsnativemodule: 809281bb19b5ba6aad8973694f6a73f3e10d8c5d - React-domnativemodule: 31be96c046c8537cbdf92943b07cd9fe8d830d19 - React-Fabric: 93aea764b03a651c7b103d3a07b2535c3a3c08b2 - React-FabricComponents: 5d813c8f71c50c397c7320dbf130ebffba2422a4 - React-FabricImage: be4b453a55590a65b2d35dbf956dae3a8f1853f9 - React-featureflags: 7faf26669323dc8b2869ba9d15cfa453b71685f1 - React-featureflagsnativemodule: 09e3acf24f068d883d93bbfc5a20a00d3835b6c0 - React-graphics: 1981e7fe8e9a7046577d8fc9df17c022ed927be5 - React-hermes: 695f334095ee48442dee2783970199525cecaf72 - React-idlecallbacksnativemodule: 899e0a7fc71a51f1fda81d26fea67456780e0019 - React-ImageManager: 575cefd6f3fe4a9998409eebe9c26eee9ed702f7 - React-jserrorhandler: 021a49bbc21c7612c53acb3397cd9f61e8a4db84 - React-jsi: e666d26bdc29dccfe681075979b924cbe1f183a8 - React-jsiexecutor: 7300101e6928e353da00e7d2e9647ac86b8501bc - React-jsinspector: ab0371bb964beed1af6d9bab664cc30bde684ff9 - React-jsinspectortracing: 701e33adfb5b14f0fb675a97ab2e0c63283cad43 - React-jsitracing: ef82947481b8bf7d49adbaacd8ae0e01028b8ddb - React-logger: b19e99fbaaf73d83adaca8917c133d1da71df8de - React-Mapbuffer: 11fabe7a2a035584622004cd476699897492927b - React-microtasksnativemodule: 8558ac343d183b631db1453dca484640b0eb3c05 - React-NativeModulesApple: 0596f545e307887fc7bcee2abf958190599934e1 - React-perflogger: a6ddeb969540aab135d6adbaa132938518587f63 - React-performancetimeline: bbdd8e1bc2c06d5fe7e3f37c37e47f21a87d02d9 - React-RCTActionSheet: 1bf8cc8086ad1c15da3407dfb7bc9dd94dc7595d - React-RCTAnimation: ac4a08b91b12a5d61e522698162d92a52581dcc5 - React-RCTAppDelegate: 148645da9bc427c825da55d2b63686545ca463f3 - React-RCTBlob: 310559ebf6e64228675806a145f43aa7197a9d14 - React-RCTFabric: 64387d220300433e81bb4cc045bcd53b114215dc - React-RCTFBReactNativeSpec: 5ac2a4a112a4fdd830bf33816563cee67b0793f6 - React-RCTImage: d84619c84f38ba644ec0d6fb8049cee8435b28c3 - React-RCTLinking: 4b179cdacf8dfab5ee483546ff9353797361f520 - React-RCTNetwork: 830b1da36cd5950b88248e1cb4a939906d1f28e4 - React-RCTPushNotification: c9868b10d51b51081cdcec5833cc9567bfc27b59 - React-RCTSettings: 9ff4d7a991f6199eafa3dfde10c138fe96f1731d - React-RCTTest: b3b23ad60a85dc33e5b48ffaf9a4694a0cea23e6 - React-RCTText: e5a08c3829b35f1db001c9cbdf1917936f5dbd25 - React-RCTVibration: 0a46dd90d07c0e6323781b0b67829932a53e0c44 - React-rendererconsistency: 777c894edc43dde01499189917ac54ee76ae6a6a - React-rendererdebug: 5578683edef6807f7b01c90d0d4981409abce41c - React-rncore: 4a81ce7b8e47448973a6b29c765b07e01715921e - React-RuntimeApple: 6c664f1800a3dee277af5efa6b82fb7a08fd78ee - React-RuntimeCore: 378bf39635fe0b6c7ef10aa8dd222e08ca093081 - React-runtimeexecutor: fb2d342a477bb13f7128cceb711ee8311edce0c0 - React-RuntimeHermes: d2ae89cd74457bfe5790287d29fa0848bc89ed0c - React-runtimescheduler: 78f50328f9c9b6d39dbee4b193145b9e84e77433 - React-timing: 9d49179631e5e3c759e6e82d4c613c73da80a144 - React-utils: 1a450d57b1bdf1c6946b36ce16f33e897d110b6b - ReactAppDependencyProvider: d62d00ee22412c6ac6074ea5e220a6a26737cdab - ReactCodegen: 7cfa434acb2911bda43c92149ea7a6b7935bb696 - ReactCommon: 86a4859be6f6455e177185a1bcfefd43477f859a - ReactCommon-Samples: 921a9a38ed66f267559171430ae000a5aa0973d8 - ScreenshotManager: 6c5a166001490d34391f6d7c441409849544f730 + OSSLibraryExample: ec2165757b63df536097e3d67683de4efbc82bdb + RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 + RCTDeprecation: 082fbc90409015eac1366795a0b90f8b5cb28efe + RCTRequired: ca966f4da75b62ce3ea8c538d82cb5ecbb06f12a + RCTTypeSafety: 2f0bc11f9584fde4c7e6d8b26577c97681051c00 + React: e6035d3a639f6668a18429aaf2fdc0c12b1e7a81 + React-callinvoker: 3740fb1716428dabd205486c818ce6a5999e7f11 + React-Core: d12b31b149ff71e5054dec137d651a9955569321 + React-CoreModules: e392c711449f260d9ba7556a264ef5cfacdab3f9 + React-cxxreact: dcb3c48b13b298a270edefb24d2a9211809ff147 + React-debug: d8d938ee3aecd7ab9c92198324ed33cac3d42566 + React-defaultsnativemodule: 599c11bfe99a3b88cd1fa2dc478be1b6b0e57be9 + React-domnativemodule: 4f278903cad707415026dacbb96768704a705569 + React-Fabric: 9e83424b66a00da675c6684568dc026399746236 + React-FabricComponents: 26da28dd7115005866fdf2f8d4e294e07dd6e3df + React-FabricImage: b60fb253651746de12418e1308b4da2c54b8fde6 + React-featureflags: 04a42c3099a4a12fdf34c42b84512b96caaf9d41 + React-featureflagsnativemodule: 32a69405f053b25640cac519dbb24c5e79185e1b + React-graphics: 49bacefc908533e59e1b65ac479bd00c43dad2d0 + React-hermes: 809429058aa7610601c552556a132df2f446fe0c + React-idlecallbacksnativemodule: d6c574b38b6497189dcdb1c4953c049ed93a67d1 + React-ImageManager: 9cb4d8d83f0d43591f06bd07b1d845144cb9bc72 + React-jserrorhandler: 5d010f2c65066e682b5973ea0e39bfc7bfdf46fe + React-jsi: 0be2628a04b7ab6b60565ccc0e11069c6a3e5a91 + React-jsiexecutor: cb431019ea945006b0ad62ba34dba8475926eda9 + React-jsinspector: 094b9197c4aa166c565273b5b80604c3c25f262a + React-jsinspectortracing: 5498aaae966956939808ecd72635a6937c7e724d + React-jsitracing: 9d28564942b168004da194785024ddc730caf0dc + React-logger: 74ddb793d36b48bba176328c7af75e5e656fd405 + React-Mapbuffer: 39e87693178fd6483bb5ca8b851fae362d49409a + React-microtasksnativemodule: b740ebae7fad70aa78bc24cc0dfc15ac9637b6eb + React-NativeModulesApple: af0571ac115d09c9a669ed45ce6a4ca960598a2d + React-perflogger: 26d07766b033f84559bd520e949453dba8bf1cd8 + React-performancetimeline: 0f3e0b6e2152951257bd8c90f95d527cf4316fa8 + React-RCTActionSheet: 9488eac05a056a124f500beaecf0a5bd722b2916 + React-RCTAnimation: d4fe0beca00060dc3628d81ea65410180974a18a + React-RCTAppDelegate: 6c81adc5689b4276368c9dc61eec211b18ca82c0 + React-RCTBlob: 1b89799400af7ca0ee598fa7d3bcd9d84ab1794d + React-RCTFabric: 7dd42c2d2339184896aaa5cf1974d00c6b97875b + React-RCTFBReactNativeSpec: 9487cf2e72e2b0da766afe2a71e1afca12e73325 + React-RCTImage: 7042262e823fe7849f1263f054c24ef2f4394e9d + React-RCTLinking: 7cb75b965f19399f67e75f771f7bd6f097c263d1 + React-RCTNetwork: b9a7eab793a36b3a74d4d184b917e59842a30a58 + React-RCTPushNotification: 73d602bfbd4aa0f99dfe8c6673f3ba0a83ef537a + React-RCTSettings: 7866a50ecc34b202d736d1f4b9164bb711a68a9c + React-RCTTest: aa11c6156d32aba6478b30300544b02690816b7b + React-RCTText: ce131e974c81c0ea4a187f24db12b262a1beab01 + React-RCTVibration: 16c24efa3a7fb96f6147ec129d554cc43b1ab707 + React-rendererconsistency: 4171665056d2a6039523e5aa8c9f5fbbe9553ad6 + React-rendererdebug: 9751d74346f583800af42b1fbb0b3561f66b5ff2 + React-rncore: 3e1894f8ebb4759f2d56b450645677547b9e3c52 + React-RuntimeApple: 0937e0055990b4dd81b2dbb8acc39f209aa6369b + React-RuntimeCore: dec19daf6dbb5dad077c8bd2ceb5f612cdd34917 + React-runtimeexecutor: f2fc17f0bbfa5a697d94d2f18d7d5f74c8d41c48 + React-RuntimeHermes: 0e01cd1fbf82f1fabc66d6f8316c7ee35d8dc871 + React-runtimescheduler: 3f02922ff1cf0d4fdf5c60b868bed4da3b15a504 + React-timing: 34f46e46507ab2e215d801223f898a1f3d95a7a3 + React-utils: 6330b3336d328a09ccc89a45d68d1f2588021318 + ReactAppDependencyProvider: 5da0393968ce2767e79f9fda7caa108592b9b63e + ReactCodegen: 14ab3644485c6d4e2372d7cf5288ced727862383 + ReactCommon: 269d0d36423fad044eaea49900e88684ac670a16 + ReactCommon-Samples: a8d1454f86a3915f29e459da34c9a097e94cabb6 + ScreenshotManager: e33e439baf5e763f4b935e591995d4dd2c0263ec SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - Yoga: 216ee0d4bcba7186f47624eeac1477a068bceea0 + Yoga: dea3cbe52f93ef8f722493a505c1add295fe7fba PODFILE CHECKSUM: 8591f96a513620a2a83a0b9a125ad3fa32ea1369 diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index a2d0ac54605ad3..20b45f36819143 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -76,13 +76,6 @@ - (BOOL)application:(UIApplication *)app return [RCTLinkingManager application:app openURL:url options:options]; } -- (void)loadSourceForBridge:(RCTBridge *)bridge - onProgress:(RCTSourceLoadProgressBlock)onProgress - onComplete:(RCTSourceLoadBlock)loadCallback -{ - [RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] onProgress:onProgress onComplete:loadCallback]; -} - - (std::shared_ptr)getTurboModule:(const std::string &)name jsInvoker:(std::shared_ptr)jsInvoker { diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.kt b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.kt index 2fe4530c3e2798..e34f58083ac012 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.kt +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.kt @@ -18,7 +18,6 @@ import com.facebook.react.ReactPackage import com.facebook.react.ViewManagerOnDemandReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.common.assets.ReactFontManager import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load import com.facebook.react.defaults.DefaultReactHost import com.facebook.react.defaults.DefaultReactNativeHost @@ -32,6 +31,7 @@ import com.facebook.react.uiapp.component.MyLegacyViewManager import com.facebook.react.uiapp.component.MyNativeViewManager import com.facebook.react.uimanager.ReactShadowNode import com.facebook.react.uimanager.ViewManager +import com.facebook.react.views.text.ReactFontManager; import com.facebook.soloader.SoLoader internal class RNTesterApplication : Application(), ReactApplication { diff --git a/packages/rn-tester/js/examples/Text/TextExample.android.js b/packages/rn-tester/js/examples/Text/TextExample.android.js index 5d4aa05fb967dd..c6e3858ac49f88 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.android.js +++ b/packages/rn-tester/js/examples/Text/TextExample.android.js @@ -482,6 +482,37 @@ function AllowFontScalingExample(props: {}): React.Node { ); } +function MaxFontSizeMultiplierExample(props: {}): React.Node { + return ( + + + When allowFontScaling is enabled, you can use the maxFontSizeMultiplier + prop to set an upper limit on how much the font size will be scaled. + + + This text will not scale up (max 1x) + + + This text will scale up (max 1.5x) + + + Inherit max (max 1x) + + + + Override inherited max (max 1.5x) + + + + Ignore inherited max (no max) + + + ); +} + function NumberOfLinesExample(props: {}): React.Node { return ( <> @@ -1462,6 +1493,13 @@ const examples = [ return ; }, }, + { + title: 'maxFontSizeMultiplier attribute', + name: 'maxFontSizeMultiplier', + render(): React.Node { + return ; + }, + }, { title: 'selectable attribute', name: 'selectable', diff --git a/packages/rn-tester/js/examples/Text/TextExample.ios.js b/packages/rn-tester/js/examples/Text/TextExample.ios.js index 10c6d43a9c12f1..a6fb19245fa0a3 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.ios.js +++ b/packages/rn-tester/js/examples/Text/TextExample.ios.js @@ -1175,6 +1175,62 @@ const examples = [ ); }, }, + { + title: 'maxFontSizeMultiplier attribute', + name: 'maxFontSizeMultiplier', + render(): React.Node { + return ( + + + When allowFontScaling is enabled, you can use the + maxFontSizeMultiplier prop to set an upper limit on how much the + font size will be scaled. + + + This text will not scale up (max 1x) + + + This text will scale up (max 1.5x) + + + Inherit max (max 1x) + + + + Override inherited max (max 1.5x) + + + + Ignore inherited max (no max) + + + This text will scale with 'title2' dynamic type ramp (no max) + + + This text will scale with 'title2' dynamic type ramp (max 1.2x) + + + This text uses 'title2' dynamic type ramp but will not scale up (max + 1x) + + + ); + }, + }, { title: 'Inline views', render: (): React.Node => , @@ -1440,9 +1496,27 @@ const examples = [ Title 3 + + Headline + Body + + Callout + + + Subheadline + + + Footnote + + + Caption + + + Caption 2 + Without `dynamicTypeRamp`: @@ -1450,7 +1524,13 @@ const examples = [ Title Title 2 Title 3 + Headline Body + Callout + Subheadline + Footnote + Caption + Caption 2 ); diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js index 7aaaa032889851..948635ff940109 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js @@ -305,6 +305,59 @@ const examples: Array = [ ); }, }, + { + title: 'allowFontScaling attribute', + render: function (): React.Node { + return ( + + + By default, text will respect Text Size accessibility setting on + Android. It means that all font sizes will be increased or decreased + depending on the value of the Text Size setting in the OS's Settings + app. + + + + + ); + }, + }, + { + title: 'maxFontSizeMultiplier attribute', + name: 'maxFontSizeMultiplier', + render(): React.Node { + return ( + + + When allowFontScaling is enabled, you can use the + maxFontSizeMultiplier prop to set an upper limit on how much the + font size will be scaled. + + + + + ); + }, + }, { title: 'Text Auto Complete', render: function (): React.Node { diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js index d04484191ef55d..7b483fcf07a003 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js @@ -730,6 +730,61 @@ const textInputExamples: Array = [ ); }, }, + { + title: 'allowFontScaling attribute', + render: function (): React.Node { + return ( + + + By default, text will respect Text Size accessibility setting on + iOS. It means that all font sizes will be increased or decreased + depending on the value of Text Size setting in{' '} + + Settings.app - Display & Brightness - Text Size + + + + + + ); + }, + }, + { + title: 'maxFontSizeMultiplier attribute', + name: 'maxFontSizeMultiplier', + render(): React.Node { + return ( + + + When allowFontScaling is enabled, you can use the + maxFontSizeMultiplier prop to set an upper limit on how much the + font size will be scaled. + + + + + ); + }, + }, { title: 'Auto-expanding', render: function (): React.Node { diff --git a/packages/rn-tester/package.json b/packages/rn-tester/package.json index 00e65fc2e61451..ebb9ae27781e84 100644 --- a/packages/rn-tester/package.json +++ b/packages/rn-tester/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/tester", - "version": "0.77.0-main", + "version": "0.78.2", "private": true, "description": "React Native tester app.", "license": "MIT", @@ -27,8 +27,8 @@ "e2e-test-ios": "./scripts/maestro-test-ios.sh" }, "dependencies": { - "@react-native/oss-library-example": "0.77.0-main", - "@react-native/popup-menu-android": "0.77.0-main", + "@react-native/oss-library-example": "0.78.2", + "@react-native/popup-menu-android": "0.78.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "nullthrows": "^1.1.1" diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index ac400bc87f4a58..7765cb66e2b5b2 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/typescript-config", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Default TypeScript configuration for React Native apps", "license": "MIT", "repository": { diff --git a/packages/virtualized-lists/Lists/VirtualizedList.js b/packages/virtualized-lists/Lists/VirtualizedList.js index 43632c60cdd1fd..0e89261e2a69e1 100644 --- a/packages/virtualized-lists/Lists/VirtualizedList.js +++ b/packages/virtualized-lists/Lists/VirtualizedList.js @@ -841,7 +841,7 @@ class VirtualizedList extends StateSafePureComponent { return { first: clamp(0, cells.first, maxFirst), - last: Math.min(lastPossibleCellIndex, cells.last), + last: clamp(-1, cells.last, lastPossibleCellIndex), }; } diff --git a/packages/virtualized-lists/package.json b/packages/virtualized-lists/package.json index d292128acb634b..8f5273d14d2329 100644 --- a/packages/virtualized-lists/package.json +++ b/packages/virtualized-lists/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/virtualized-lists", - "version": "0.77.0-main", + "version": "0.78.2", "description": "Virtualized lists for React Native.", "license": "MIT", "repository": { diff --git a/scripts/release-testing/test-e2e-local.js b/scripts/release-testing/test-e2e-local.js index fcb23721ee4a9d..7698b1427eab03 100644 --- a/scripts/release-testing/test-e2e-local.js +++ b/scripts/release-testing/test-e2e-local.js @@ -85,40 +85,66 @@ async function testRNTesterIOS( } version of RNTester iOS with the new Architecture enabled`, ); + // if everything succeeded so far, we can launch Metro and the app + // start the Metro server in a separate window + launchPackagerInSeparateWindow(pwd().toString()); + // remember that for this to be successful // you should have run bundle install once // in your local setup - if (argv.hermes === true && ciArtifacts != null) { - const hermesURL = await ciArtifacts.artifactURLHermesDebug(); - const hermesZipPath = path.join(ciArtifacts.baseTmpPath(), 'hermes.zip'); - // download hermes source code from manifold - ciArtifacts.downloadArtifact(hermesURL, hermesZipPath); - // GHA zips by default the artifacts. - const outputFolder = path.join(ciArtifacts.baseTmpPath(), 'hermes'); - exec(`rm -rf ${outputFolder}`); - exec(`unzip ${hermesZipPath} -d ${outputFolder}`); - const hermesPath = path.join(outputFolder, 'hermes-ios-Debug.tar.gz'); - - console.info(`Downloaded Hermes in ${hermesPath}`); - exec( - `HERMES_ENGINE_TARBALL_PATH=${hermesPath} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`, + if (ciArtifacts != null) { + const appOutputFolder = path.join( + ciArtifacts.baseTmpPath(), + 'RNTester.app', ); + exec(`rm -rf ${appOutputFolder}`); + if (argv.hermes === true) { + // download hermes App + const hermesAppUrl = await ciArtifacts.artifactURLForHermesRNTesterApp(); + const hermesAppZipPath = path.join( + ciArtifacts.baseTmpPath(), + 'RNTesterAppHermes.zip', + ); + ciArtifacts.downloadArtifact(hermesAppUrl, hermesAppZipPath); + exec(`unzip ${hermesAppZipPath} -d ${appOutputFolder}`); + } else { + // download JSC app + const hermesAppUrl = await ciArtifacts.artifactURLForJSCRNTesterApp(); + const hermesAppZipPath = path.join( + ciArtifacts.baseTmpPath(), + 'RNTesterAppJSC.zip', + ); + ciArtifacts.downloadArtifact(hermesAppUrl, hermesAppZipPath); + exec(`unzip ${hermesAppZipPath} -d ${appOutputFolder}`); + } + + // boot device + const bootedDevice = String( + exec('xcrun simctl list | grep "iPhone 16 Pro" | grep Booted', { + silent: true, + }), + ).trim(); + if (!bootedDevice || bootedDevice.length === 0) { + exec('xcrun simctl boot "iPhone 16 Pro"'); + } + + // install app on device + exec(`xcrun simctl install booted ${appOutputFolder}`); + + // launch the app on iOS simulator + exec('xcrun simctl launch booted com.meta.RNTester.localDevelopment'); } else { exec( `USE_HERMES=${ argv.hermes === true ? 1 : 0 } CI=${onReleaseBranch.toString()} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`, ); - } - - // if everything succeeded so far, we can launch Metro and the app - // start the Metro server in a separate window - launchPackagerInSeparateWindow(pwd().toString()); - // launch the app on iOS simulator - exec( - 'npx react-native run-ios --scheme RNTester --simulator "iPhone 15 Pro"', - ); + // launch the app on iOS simulator + exec( + 'npx react-native run-ios --scheme RNTester --simulator "iPhone 15 Pro"', + ); + } } /** @@ -201,7 +227,7 @@ async function testRNTesterAndroid( * - @onReleaseBranch whether we are on a release branch or not */ async function testRNTester( - circleCIArtifacts /*:Unwrap> */, + ciArtifacts /*:Unwrap> */, onReleaseBranch /*: boolean */, ) { // FIXME: make sure that the commands retains colors @@ -210,9 +236,9 @@ async function testRNTester( pushd('packages/rn-tester'); if (argv.platform === 'ios') { - await testRNTesterIOS(circleCIArtifacts, onReleaseBranch); + await testRNTesterIOS(ciArtifacts, onReleaseBranch); } else { - await testRNTesterAndroid(circleCIArtifacts); + await testRNTesterAndroid(ciArtifacts); } popd(); } diff --git a/scripts/release-testing/utils/github-actions-utils.js b/scripts/release-testing/utils/github-actions-utils.js index 501e3e9c3d791e..b9e3d466850440 100644 --- a/scripts/release-testing/utils/github-actions-utils.js +++ b/scripts/release-testing/utils/github-actions-utils.js @@ -214,6 +214,14 @@ async function artifactURLForHermesRNTesterAPK( return getArtifactURL('rntester-hermes-debug'); } +async function artifactURLForJSCRNTesterApp() /*: Promise */ { + return getArtifactURL('RNTesterApp-NewArch-JSC-Debug'); +} + +async function artifactURLForHermesRNTesterApp() /*: Promise */ { + return getArtifactURL('RNTesterApp-NewArch-Hermes-Debug'); +} + async function artifactURLForMavenLocal() /*: Promise */ { return getArtifactURL('maven-local'); } @@ -247,6 +255,8 @@ module.exports = { downloadArtifact, artifactURLForJSCRNTesterAPK, artifactURLForHermesRNTesterAPK, + artifactURLForJSCRNTesterApp, + artifactURLForHermesRNTesterApp, artifactURLForMavenLocal, artifactURLHermesDebug, artifactURLForReactNative, diff --git a/yarn.lock b/yarn.lock index 509720779f3eff..47f3e4ee7fb8dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1064,17 +1064,6 @@ "@babel/plugin-transform-modules-commonjs" "^7.24.7" "@babel/plugin-transform-typescript" "^7.24.7" -"@babel/register@7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.22.5.tgz#e4d8d0f615ea3233a27b5c6ada6750ee59559939" - integrity sha512-vV6pm/4CijSQ8Y47RH5SopXzursN35RQINfGJkmOlcpAtGuf94miFvIPhCKGQN7WGIcsgG1BHEX2KVdTYwTwUQ== - dependencies: - clone-deep "^4.0.1" - find-cache-dir "^2.0.0" - make-dir "^2.1.0" - pirates "^4.0.5" - source-map-support "^0.5.16" - "@babel/register@^7.13.16", "@babel/register@^7.24.6": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.24.6.tgz#59e21dcc79e1d04eed5377633b0f88029a6bef9e" @@ -1107,7 +1096,20 @@ "@babel/parser" "^7.25.0" "@babel/types" "^7.25.0" -"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4": +"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3": + version "7.25.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.6.tgz#04fad980e444f182ecf1520504941940a90fea41" + integrity sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.6" + "@babel/parser" "^7.25.6" + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.6" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4": version "7.25.6" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.6.tgz#04fad980e444f182ecf1520504941940a90fea41" integrity sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ== @@ -2778,13 +2780,6 @@ babel-plugin-replace-ts-export-assignment@^0.0.2: resolved "https://registry.yarnpkg.com/babel-plugin-replace-ts-export-assignment/-/babel-plugin-replace-ts-export-assignment-0.0.2.tgz#927a30ba303fcf271108980a8d4f80a693e1d53f" integrity sha512-BiTEG2Ro+O1spuheL5nB289y37FFmz0ISE6GjpNCG2JuA/WNcuEHSYw01+vN8quGf208sID3FnZFDwVyqX18YQ== -babel-plugin-syntax-hermes-parser@0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.24.0.tgz#79d0c73daae7bd7d4b07f64ee281c75aa48845cf" - integrity sha512-J4wETqz7ehbyYl2uge65zsfr0Ue+0yJYYMMkGAWpZc0fB02z4JAcx+mJEXVU14yiihGwqVUlR7oS4/gDYOxUdA== - dependencies: - hermes-parser "0.24.0" - babel-plugin-syntax-hermes-parser@0.25.1: version "0.25.1" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz#58b539df973427fcfbb5176a3aec7e5dee793cb0" @@ -3609,11 +3604,6 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -denodeify@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" - integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== - depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -4799,23 +4789,11 @@ hermes-eslint@0.25.1: hermes-estree "0.25.1" hermes-parser "0.25.1" -hermes-estree@0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.24.0.tgz#487dc1ddc0bae698c2d79f34153ac9bf62d7b3c0" - integrity sha512-LyoXLB7IFzeZW0EvAbGZacbxBN7t6KKSDqFJPo3Ydow7wDlrDjXwsdiAHV6XOdvEN9MEuWXsSIFN4tzpyrXIHw== - hermes-estree@0.25.1: version "0.25.1" resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.25.1.tgz#6aeec17d1983b4eabf69721f3aa3eb705b17f480" integrity sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw== -hermes-parser@0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.24.0.tgz#2ed19d079efc0848eb1f800f0c393a074c4696fb" - integrity sha512-IJooSvvu2qNRe7oo9Rb04sUT4omtZqZqf9uq9WM25Tb6v3usmvA93UqfnnoWs5V0uYjEl9Al6MNU10MCGKLwpg== - dependencies: - hermes-estree "0.24.0" - hermes-parser@0.25.1: version "0.25.1" resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.25.1.tgz#5be0e487b2090886c62bd8a11724cd766d5f54d1" @@ -5736,7 +5714,7 @@ jest-validate@^24.9.0: leven "^3.1.0" pretty-format "^24.9.0" -jest-validate@^29.6.3, jest-validate@^29.7.0: +jest-validate@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== @@ -5762,7 +5740,7 @@ jest-watcher@^29.7.0: jest-util "^29.7.0" string-length "^4.0.1" -jest-worker@^29.6.3, jest-worker@^29.7.0: +jest-worker@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== @@ -6303,154 +6281,149 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -metro-babel-register@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.81.0.tgz#05e9deda5633e38aceb7120b1865cbbc63c5b8ef" - integrity sha512-CU9D49k9ti02ebHXuYlbDNPdBj0C4SnCDIGk328epmcO0p++WzFSWWO92cGc7i0HqKyzgeMskPGJV825Eh7zSg== +metro-babel-register@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.81.3.tgz#8a514cc79f59e7efbf61fe0fc39f746ee6b1b8b8" + integrity sha512-Td4cVGZ+EbLCz5nMrW4qusS3c2Nd2qKceagFutaOZ7RZI0h6gHsBeqD+jDZ6Ytjm/ztdq9jHwOsc+ELu5Qh8dA== dependencies: "@babel/core" "^7.25.2" "@babel/plugin-proposal-export-namespace-from" "^7.18.9" "@babel/plugin-transform-flow-strip-types" "^7.25.2" "@babel/plugin-transform-modules-commonjs" "^7.24.8" "@babel/preset-typescript" "^7.24.7" - "@babel/register" "7.22.5" + "@babel/register" "^7.24.6" babel-plugin-replace-ts-export-assignment "^0.0.2" - babel-plugin-syntax-hermes-parser "0.24.0" + babel-plugin-syntax-hermes-parser "0.25.1" babel-plugin-transform-flow-enums "^0.0.2" escape-string-regexp "^1.0.5" flow-enums-runtime "^0.0.6" -metro-babel-transformer@0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.81.0.tgz#cf468eafea52e4d8a77844eb7257f8a76e9d9d94" - integrity sha512-Dc0QWK4wZIeHnyZ3sevWGTnnSkIDDn/SWyfrn99zbKbDOCoCYy71PAn9uCRrP/hduKLJQOy+tebd63Rr9D8tXg== +metro-babel-transformer@0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.81.3.tgz#908b8ed7ce07e34d44db2a24b282d8728f7f9c0c" + integrity sha512-ENqtnPy2mQZFOuKrbqHRcAwZuaYe43X+30xIF0xlkLuMyCvc0CsFzrrSK9EqrQwexhVlqaRALb0GQbBMcE/y8g== dependencies: "@babel/core" "^7.25.2" flow-enums-runtime "^0.0.6" - hermes-parser "0.24.0" + hermes-parser "0.25.1" nullthrows "^1.1.1" -metro-cache-key@0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.81.0.tgz#5db34fa1a323a2310205bda7abd0df9614e36f45" - integrity sha512-qX/IwtknP9bQZL78OK9xeSvLM/xlGfrs6SlUGgHvrxtmGTRSsxcyqxR+c+7ch1xr05n62Gin/O44QKg5V70rNQ== +metro-cache-key@0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.81.3.tgz#afbd48f2847419cf27b925d83def31758b17b049" + integrity sha512-KPsPSRUd6uRva7k7k/DqiiD8td7URQWx0RkX/Cj5+bed5zSXEg/XoQA+b+DmMxS5C7TqP61Fh3XvHx6TQRW82A== dependencies: flow-enums-runtime "^0.0.6" -metro-cache@0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.81.0.tgz#90470d10d190ad708f04c6e337eec2c7cddb3db0" - integrity sha512-DyuqySicHXkHUDZFVJmh0ygxBSx6pCKUrTcSgb884oiscV/ROt1Vhye+x+OIHcsodyA10gzZtrVtxIFV4l9I4g== +metro-cache@0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.81.3.tgz#8239ccc7fecd24aa6c76af8975aa03be95dfe4e9" + integrity sha512-6UelMQYjlto/79tTXu0vsTxAX4e+Bkf0tgtDL1BNx3wd68pBg8qKIYpJPaUlOIaNUzFXTBDjYwUverkEW0KAtA== dependencies: exponential-backoff "^3.1.1" flow-enums-runtime "^0.0.6" - metro-core "0.81.0" + metro-core "0.81.3" -metro-config@0.81.0, metro-config@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.81.0.tgz#8f8074033cb7e9ddb5b0459642adf6880bc9fbc1" - integrity sha512-6CinEaBe3WLpRlKlYXXu8r1UblJhbwD6Gtnoib5U8j6Pjp7XxMG9h/DGMeNp9aGLDu1OieUqiXpFo7O0/rR5Kg== +metro-config@0.81.3, metro-config@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.81.3.tgz#8e6c3d1f377bf7fa840ba99f7f05bd7b91a21eae" + integrity sha512-WpTaT0iQr5juVY50Y/cyacG2ggZqF38VshEQepT+ovPK8E/xUVxlbO5yxLSXUxxUXX3Hka9r6g64+y2WC6c/xQ== dependencies: connect "^3.6.5" cosmiconfig "^5.0.5" flow-enums-runtime "^0.0.6" - jest-validate "^29.6.3" - metro "0.81.0" - metro-cache "0.81.0" - metro-core "0.81.0" - metro-runtime "0.81.0" + jest-validate "^29.7.0" + metro "0.81.3" + metro-cache "0.81.3" + metro-core "0.81.3" + metro-runtime "0.81.3" -metro-core@0.81.0, metro-core@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.81.0.tgz#d0b634f9cf97849b7730c59457ab7a439811d4c8" - integrity sha512-CVkM5YCOAFkNMvJai6KzA0RpztzfEKRX62/PFMOJ9J7K0uq/UkOFLxcgpcncMIrfy0PbfEj811b69tjULUQe1Q== +metro-core@0.81.3, metro-core@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.81.3.tgz#86c29bcd90fc3157f52abd7f94bf9d6d7fb03977" + integrity sha512-WZ+qohnpvvSWdPj1VJPUrZz+2ik29M+UUpMU6YrmzQUfDyZ6JYHhzlw5WVBtwpt/+2xTsIyrZ2C1fByT/DsLQA== dependencies: flow-enums-runtime "^0.0.6" lodash.throttle "^4.1.1" - metro-resolver "0.81.0" + metro-resolver "0.81.3" -metro-file-map@0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.81.0.tgz#af0ccf4f8db4fd8429f78f231faa49dde2c402c3" - integrity sha512-zMDI5uYhQCyxbye/AuFx/pAbsz9K+vKL7h1ShUXdN2fz4VUPiyQYRsRqOoVG1DsiCgzd5B6LW0YW77NFpjDQeg== +metro-file-map@0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.81.3.tgz#0204d8584c1115a94f38c07afeb0689629939c44" + integrity sha512-F+t4lnVRoauJxtr9xmI4pWIOE77/vl0IrHDGeJSI9cW6LmuqxkpOlZHTKpbs/hMAo6+KhG2JMJACQDvXDLd/GA== dependencies: - anymatch "^3.0.3" debug "^2.2.0" fb-watchman "^2.0.0" flow-enums-runtime "^0.0.6" graceful-fs "^4.2.4" invariant "^2.2.4" - jest-worker "^29.6.3" + jest-worker "^29.7.0" micromatch "^4.0.4" - node-abort-controller "^3.1.1" nullthrows "^1.1.1" walker "^1.0.7" - optionalDependencies: - fsevents "^2.3.2" -metro-memory-fs@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.81.0.tgz#f11ac95bb294f3fd4c933cf93ab9ee6da626d352" - integrity sha512-hbmyOuVigPU81Kd+CUCq7tXgEkrHmteWG1WJHTEwldoLHuYUzSeaoE8LlLUbqPF+OPW0asYx/cTDrfNM8KCuqw== +metro-memory-fs@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.81.3.tgz#8c3a00eb9346bd3541633935ac7e67542eba2d6c" + integrity sha512-r6bMg6G3GXSyJLEa7HxGl6dbThA2fQAXM4JwNV+rtmxUa2FfPHYjRlOuApz5RNZGriunE2HzGwptfphElftGnw== dependencies: flow-enums-runtime "^0.0.6" -metro-minify-terser@0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.81.0.tgz#8b0abe977d63a99b99fa94d53678ef3170d5b659" - integrity sha512-U2ramh3W822ZR1nfXgIk+emxsf5eZSg10GbQrT0ZizImK8IZ5BmJY+BHRIkQgHzWFpExOVxC7kWbGL1bZALswA== +metro-minify-terser@0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.81.3.tgz#68e15ffbcaa21d7daa01840405168704cd9b5b67" + integrity sha512-912AYv3OmwcbUwzCdWbdQRk+RV6kXXluHKlhBdYFD3kr4Ece691rzlofU/Mlt9qZrhHtctD5Q8cFqOEf9Z69bQ== dependencies: flow-enums-runtime "^0.0.6" terser "^5.15.0" -metro-resolver@0.81.0, metro-resolver@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.81.0.tgz#141f4837e1e0c5a1810ea02f2d9be3c9f6cf3766" - integrity sha512-Uu2Q+buHhm571cEwpPek8egMbdSTqmwT/5U7ZVNpK6Z2ElQBBCxd7HmFAslKXa7wgpTO2FAn6MqGeERbAtVDUA== +metro-resolver@0.81.3, metro-resolver@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.81.3.tgz#8a61df2c15d30336cd96cdc1918826dde0ff8938" + integrity sha512-XnjENY1c6jcsEfFVIjN/8McUIInCVgGxv5eva+9ZWeCTyiAE/L5HPj2ai/Myb349+6QuSMR0dscTkKCnOwWXdw== dependencies: flow-enums-runtime "^0.0.6" -metro-runtime@0.81.0, metro-runtime@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.81.0.tgz#63af9b3fec15d1f307d89ef4881f5ba2c592291e" - integrity sha512-6oYB5HOt37RuGz2eV4A6yhcl+PUTwJYLDlY9vhT+aVjbUWI6MdBCf69vc4f5K5Vpt+yOkjy+2LDwLS0ykWFwYw== +metro-runtime@0.81.3, metro-runtime@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.81.3.tgz#0cb5d8c8e5843fbf6fe6e9595821f0f434953aba" + integrity sha512-neuGRMC2pgGKIFPbmbrxW41/SmvL7OX4i1LN+saUY2t1cZfxf9haQHUMCGhO3498uEL2N+ulKRSlQrHt6XwGaw== dependencies: "@babel/runtime" "^7.25.0" flow-enums-runtime "^0.0.6" -metro-source-map@0.81.0, metro-source-map@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.81.0.tgz#ca83964124bb227d5f0bdb1ee304dbfe635f869e" - integrity sha512-TzsVxhH83dyxg4A4+L1nzNO12I7ps5IHLjKGZH3Hrf549eiZivkdjYiq/S5lOB+p2HiQ+Ykcwtmcja95LIC62g== +metro-source-map@0.81.3, metro-source-map@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.81.3.tgz#d0aed42b3bb0842cb6f71c2b8f3d58e96a5b8a05" + integrity sha512-BHJJurmDQRn3hCbBawh/UHzPz3duMpwpE3ofImO2DoWHYzn6nSg/D4wfCN4y14d9fFLE4e0I+BAOX1HWNP4jsw== dependencies: "@babel/traverse" "^7.25.3" "@babel/traverse--for-generate-function-map" "npm:@babel/traverse@^7.25.3" "@babel/types" "^7.25.2" flow-enums-runtime "^0.0.6" invariant "^2.2.4" - metro-symbolicate "0.81.0" + metro-symbolicate "0.81.3" nullthrows "^1.1.1" - ob1 "0.81.0" + ob1 "0.81.3" source-map "^0.5.6" vlq "^1.0.0" -metro-symbolicate@0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.81.0.tgz#b7b1eae8bfd6ad2a922fa2bcb9f2144e464adafb" - integrity sha512-C/1rWbNTPYp6yzID8IPuQPpVGzJ2rbWYBATxlvQ9dfK5lVNoxcwz77hjcY8ISLsRRR15hyd/zbjCNKPKeNgE1Q== +metro-symbolicate@0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.81.3.tgz#e68fa6a4f7f426dc9e99ceb01bcb138a48a8fbf4" + integrity sha512-LQLT6WopQmIz2SDSVh3Lw7nLzF58HpsrPYqRB7RpRXBYhYmPFIjiGaP8qqtKHXczM/5YAOJzpgt8t/OGZgh6Eg== dependencies: flow-enums-runtime "^0.0.6" invariant "^2.2.4" - metro-source-map "0.81.0" + metro-source-map "0.81.3" nullthrows "^1.1.1" source-map "^0.5.6" - through2 "^2.0.1" vlq "^1.0.0" -metro-transform-plugins@0.81.0, metro-transform-plugins@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.81.0.tgz#614c0e50593df545487b3f3383fed810c608fb32" - integrity sha512-uErLAPBvttGCrmGSCa0dNHlOTk3uJFVEVWa5WDg6tQ79PRmuYRwzUgLhVzn/9/kyr75eUX3QWXN79Jvu4txt6Q== +metro-transform-plugins@0.81.3, metro-transform-plugins@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.81.3.tgz#04d168fa29cc4eee92d72cf6a2c27810adcf4273" + integrity sha512-4JMUXhBB5y4h3dyA272k7T7+U3+J4fSBcct0Y8Yur9ziZB/dK8fieEQg5ZPfEGsgOGI+54zTzOUqga6AgmZSNg== dependencies: "@babel/core" "^7.25.2" "@babel/generator" "^7.25.0" @@ -6459,29 +6432,29 @@ metro-transform-plugins@0.81.0, metro-transform-plugins@^0.81.0: flow-enums-runtime "^0.0.6" nullthrows "^1.1.1" -metro-transform-worker@0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.81.0.tgz#43e63c95014f36786f0e1a132c778c6392950de7" - integrity sha512-HrQ0twiruhKy0yA+9nK5bIe3WQXZcC66PXTvRIos61/EASLAP2DzEmW7IxN/MGsfZegN2UzqL2CG38+mOB45vg== +metro-transform-worker@0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.81.3.tgz#467839d40c12841fe140943a902013ef3118adb2" + integrity sha512-KZqm9sVyBKRygUxRm+yP4DguE9R1EEv28KJhIxghNp5dcdVXBYUPe1xHoc3QVdzD9c3tf8JFzA2FBlKTlwMwNg== dependencies: "@babel/core" "^7.25.2" "@babel/generator" "^7.25.0" "@babel/parser" "^7.25.3" "@babel/types" "^7.25.2" flow-enums-runtime "^0.0.6" - metro "0.81.0" - metro-babel-transformer "0.81.0" - metro-cache "0.81.0" - metro-cache-key "0.81.0" - metro-minify-terser "0.81.0" - metro-source-map "0.81.0" - metro-transform-plugins "0.81.0" + metro "0.81.3" + metro-babel-transformer "0.81.3" + metro-cache "0.81.3" + metro-cache-key "0.81.3" + metro-minify-terser "0.81.3" + metro-source-map "0.81.3" + metro-transform-plugins "0.81.3" nullthrows "^1.1.1" -metro@0.81.0, metro@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.81.0.tgz#cffe9b7d597728dee8b57903ca155417b7c13a4f" - integrity sha512-kzdzmpL0gKhEthZ9aOV7sTqvg6NuTxDV8SIm9pf9sO8VVEbKrQk5DNcwupOUjgPPFAuKUc2NkT0suyT62hm2xg== +metro@0.81.3, metro@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.81.3.tgz#aed8815b45716003aa0cd17387c312c08ed4baf2" + integrity sha512-upilFs7z1uLKvdzFYHiVKrGT/uC7h7d53R0g/FaJoQvLfA8jQG2V69jeOcGi4wCsFYvl1zBSZvKxpQb0nA3giQ== dependencies: "@babel/code-frame" "^7.24.7" "@babel/core" "^7.25.2" @@ -6495,33 +6468,31 @@ metro@0.81.0, metro@^0.81.0: ci-info "^2.0.0" connect "^3.6.5" debug "^2.2.0" - denodeify "^1.2.1" error-stack-parser "^2.0.6" flow-enums-runtime "^0.0.6" graceful-fs "^4.2.4" - hermes-parser "0.24.0" + hermes-parser "0.25.1" image-size "^1.0.2" invariant "^2.2.4" - jest-worker "^29.6.3" + jest-worker "^29.7.0" jsc-safe-url "^0.2.2" lodash.throttle "^4.1.1" - metro-babel-transformer "0.81.0" - metro-cache "0.81.0" - metro-cache-key "0.81.0" - metro-config "0.81.0" - metro-core "0.81.0" - metro-file-map "0.81.0" - metro-resolver "0.81.0" - metro-runtime "0.81.0" - metro-source-map "0.81.0" - metro-symbolicate "0.81.0" - metro-transform-plugins "0.81.0" - metro-transform-worker "0.81.0" + metro-babel-transformer "0.81.3" + metro-cache "0.81.3" + metro-cache-key "0.81.3" + metro-config "0.81.3" + metro-core "0.81.3" + metro-file-map "0.81.3" + metro-resolver "0.81.3" + metro-runtime "0.81.3" + metro-source-map "0.81.3" + metro-symbolicate "0.81.3" + metro-transform-plugins "0.81.3" + metro-transform-worker "0.81.3" mime-types "^2.1.27" nullthrows "^1.1.1" serialize-error "^2.1.0" source-map "^0.5.6" - strip-ansi "^6.0.0" throat "^5.0.0" ws "^7.5.10" yargs "^17.6.2" @@ -6689,11 +6660,6 @@ nocache@^3.0.1: resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.4.tgz#5b37a56ec6e09fc7d401dceaed2eab40c8bfdf79" integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw== -node-abort-controller@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" - integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== - node-cleanup@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" @@ -6794,10 +6760,10 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -ob1@0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.81.0.tgz#dc3154cca7aa9c2eb58f5ac63e9ee23ff4c6f520" - integrity sha512-6Cvrkxt1tqaRdWqTAMcVYEiO5i1xcF9y7t06nFdjFqkfPsEloCf8WwhXdwBpNUkVYSQlSGS7cDgVQR86miBfBQ== +ob1@0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.81.3.tgz#1b0c5138bc40aeac77bd8b7b9b344e6ad9693c95" + integrity sha512-wd8zdH0DWsn2iDVn2zT/QURihcqoc73K8FhNCmQ16qkJaoYJLNb/N+huOwdCgsbNP8Lk/s1+dPnDETx+RzsrWA== dependencies: flow-enums-runtime "^0.0.6" @@ -7120,7 +7086,7 @@ pinpoint@^1.1.0: resolved "https://registry.yarnpkg.com/pinpoint/-/pinpoint-1.1.0.tgz#0cf7757a6977f1bf7f6a32207b709e377388e874" integrity sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg== -pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.5, pirates@^4.0.6: +pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== @@ -7327,7 +7293,7 @@ react@19.0.0: resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== -readable-stream@^2.0.6, readable-stream@~2.3.6: +readable-stream@^2.0.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -8311,14 +8277,6 @@ throat@^5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== -through2@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"