mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
48
Commits
@@ -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:
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
@@ -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)}')
|
||||
|
||||
@@ -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'
|
||||
|
||||
+2
-2
@@ -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.1",
|
||||
"@react-native/metro-config": "0.78.1",
|
||||
"@tsconfig/node18": "1.0.1",
|
||||
"@types/react": "^19.0.0",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/assets-registry",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Asset support code for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-plugin-codegen",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2"
|
||||
|
||||
@@ -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 <path>` | Specify path to a custom SSL cert. |
|
||||
| `--config <string>` | 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 <path> [options]
|
||||
npx @react-native-community/cli bundle --entry-file <path> [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/community-cli-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Core CLI commands for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -22,8 +22,8 @@
|
||||
"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.1",
|
||||
"@react-native/metro-babel-transformer": "0.78.1",
|
||||
"chalk": "^4.0.0",
|
||||
"debug": "^2.2.0",
|
||||
"invariant": "^2.2.4",
|
||||
@@ -37,10 +37,10 @@
|
||||
"metro-resolver": "^0.81.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-native-community/cli-server-api": "*"
|
||||
"@react-native-community/cli": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@react-native-community/cli-server-api": {
|
||||
"@react-native-community/cli": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -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<string>,
|
||||
}): 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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/core-cli-utils",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "React Native CLI library for Frameworks to build on",
|
||||
"license": "MIT",
|
||||
"main": "./src/index.flow.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/debugger-frontend",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Debugger frontend for React Native based on Chrome DevTools",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/dev-middleware",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1",
|
||||
"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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -82,6 +82,9 @@ export type ReportableEvent =
|
||||
status: 'success',
|
||||
...DebuggerSessionIDs,
|
||||
}
|
||||
| {
|
||||
type: 'fusebox_console_notice',
|
||||
}
|
||||
| {
|
||||
type: 'proxy_error',
|
||||
status: 'error',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-config",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "ESLint rules for @react-native/eslint-config",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin-specs",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1",
|
||||
"make-dir": "^2.1.0",
|
||||
"pirates": "^4.0.1",
|
||||
"source-map-support": "0.5.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/gradle-plugin",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Gradle Plugin for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "helloworld",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1"
|
||||
},
|
||||
"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.1",
|
||||
"@react-native/core-cli-utils": "0.78.1",
|
||||
"@react-native/eslint-config": "0.78.1",
|
||||
"@react-native/metro-config": "0.78.1",
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^12.0.0",
|
||||
"eslint": "^8.19.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-config",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Metro configuration for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,8 +26,8 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/js-polyfills": "0.77.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.77.0-main",
|
||||
"@react-native/js-polyfills": "0.78.1",
|
||||
"@react-native/metro-babel-transformer": "0.78.1",
|
||||
"metro-config": "^0.81.0",
|
||||
"metro-runtime": "^0.81.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/normalize-colors",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Color normalization for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/js-polyfills",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Polyfills for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-preset",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1",
|
||||
"babel-plugin-syntax-hermes-parser": "0.25.1",
|
||||
"babel-plugin-transform-flow-enums": "^0.0.2",
|
||||
"react-refresh": "^0.14.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-babel-transformer",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1",
|
||||
"hermes-parser": "0.25.1",
|
||||
"nullthrows": "^1.1.1"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-native/bots",
|
||||
"description": "React Native Bots",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen-typescript-test",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Code generation tools for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -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.1",
|
||||
"main": "src/index.js",
|
||||
"description": "Internal integration testing and benchmarking tool for React Native",
|
||||
"peerDependencies": {
|
||||
"jest": "^29.7.0",
|
||||
"jest-snapshot": "^29.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-info",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"main": "build/index.js",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/popup-menu-android",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/oss-library-example",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1",
|
||||
"react-native": "0.78.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
|
||||
@@ -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 =
|
||||
|
||||
+14
-13
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -156,6 +156,15 @@ using namespace facebook::react;
|
||||
return RCTAppSetupDefaultModuleFromClass(moduleClass, self.delegate.dependencyProvider);
|
||||
}
|
||||
|
||||
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(extraModulesForBridge:)]) {
|
||||
return [_delegate extraModulesForBridge:bridge];
|
||||
}
|
||||
|
||||
return @[];
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewFactoryComponentProvider
|
||||
|
||||
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
|
||||
@@ -228,6 +237,21 @@ using namespace facebook::react;
|
||||
};
|
||||
}
|
||||
|
||||
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 @@ class RCTAppDelegateBridgelessFeatureFlags : public ReactNativeFeatureFlagsDefau
|
||||
|
||||
- (void)_setUpFeatureFlags
|
||||
{
|
||||
if ([self bridgelessEnabled]) {
|
||||
ReactNativeFeatureFlags::override(std::make_unique<RCTAppDelegateBridgelessFeatureFlags>());
|
||||
}
|
||||
static dispatch_once_t setupFeatureFlagsToken;
|
||||
dispatch_once(&setupFeatureFlagsToken, ^{
|
||||
if ([self bridgelessEnabled]) {
|
||||
ReactNativeFeatureFlags::override(std::make_unique<RCTAppDelegateBridgelessFeatureFlags>());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -31,6 +31,11 @@ typedef NSURL *_Nullable (^RCTBundleURLBlock)(void);
|
||||
typedef NSArray<id<RCTBridgeModule>> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge);
|
||||
typedef NSDictionary<NSString *, Class> *_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
|
||||
|
||||
@@ -302,6 +302,22 @@
|
||||
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();
|
||||
|
||||
@@ -14,9 +14,9 @@ const version: $ReadOnly<{
|
||||
patch: number,
|
||||
prerelease: string | null,
|
||||
}> = {
|
||||
major: 1000,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
major: 0,
|
||||
minor: 78,
|
||||
patch: 1,
|
||||
prerelease: null,
|
||||
};
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<?$ReadOnly<{uri?: ?string, ...}>>,
|
||||
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,
|
||||
|
||||
@@ -477,7 +477,15 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, CGSize size, CGFloat scal
|
||||
|
||||
// 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];
|
||||
|
||||
@@ -26,7 +26,6 @@ let hmrUnavailableReason: string | null = null;
|
||||
let currentCompileErrorMessage: string | null = null;
|
||||
let didConnect: boolean = false;
|
||||
let pendingLogs: Array<[LogLevel, $ReadOnlyArray<mixed>]> = [];
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ const HMRClientProdShim: HMRClientNativeInterface = {
|
||||
disable() {},
|
||||
registerBundle() {},
|
||||
log() {},
|
||||
unstable_notifyFuseboxConsoleEnabled() {},
|
||||
};
|
||||
|
||||
module.exports = HMRClientProdShim;
|
||||
|
||||
@@ -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<?$ReadOnly<{ uri?: ?string, ... }>>,
|
||||
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;
|
||||
|
||||
@@ -21,9 +21,9 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(void){
|
||||
__rnVersion = @{
|
||||
RCTVersionMajor: @(1000),
|
||||
RCTVersionMinor: @(0),
|
||||
RCTVersionPatch: @(0),
|
||||
RCTVersionMajor: @(0),
|
||||
RCTVersionMinor: @(78),
|
||||
RCTVersionPatch: @(1),
|
||||
RCTVersionPrerelease: [NSNull null],
|
||||
};
|
||||
});
|
||||
|
||||
@@ -54,13 +54,11 @@
|
||||
]];
|
||||
|
||||
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],
|
||||
|
||||
+1
-7
@@ -101,11 +101,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
||||
NSMutableDictionary<NSAttributedStringKey, id> *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 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
||||
if (newTextInputProps.textAttributes != oldTextInputProps.textAttributes) {
|
||||
NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
|
||||
RCTNSTextAttributesFromTextAttributes(newTextInputProps.getEffectiveTextAttributes(RCTFontSizeMultiplier()));
|
||||
#if !TARGET_OS_MACCATALYST
|
||||
defaultAttributes[RCTAttributedStringEventEmitterKey] =
|
||||
_backedTextInputView.defaultTextAttributes[RCTAttributedStringEventEmitterKey];
|
||||
#endif
|
||||
_backedTextInputView.defaultTextAttributes = defaultAttributes;
|
||||
}
|
||||
|
||||
|
||||
@@ -2215,7 +2215,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 +3482,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 <init> ()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 <init> ()V
|
||||
public fun createSocket (Ljava/lang/String;I)Ljava/net/Socket;
|
||||
@@ -7342,6 +7350,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 +7383,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 +7833,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
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1000.0.0
|
||||
VERSION_NAME=0.78.1
|
||||
react.internal.publishingGroup=com.facebook.react
|
||||
|
||||
android.useAndroidX=true
|
||||
|
||||
+3
-1
@@ -685,10 +685,12 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
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);
|
||||
}
|
||||
|
||||
+4
-1
@@ -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);
|
||||
|
||||
+15
-8
@@ -331,14 +331,11 @@ public class MountingManager {
|
||||
@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 class MountingManager {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
+3
-3
@@ -15,8 +15,8 @@ import java.util.Map;
|
||||
|
||||
public class ReactNativeVersion {
|
||||
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
|
||||
"major", 1000,
|
||||
"minor", 0,
|
||||
"patch", 0,
|
||||
"major", 0,
|
||||
"minor", 78,
|
||||
"patch", 1,
|
||||
"prerelease", null);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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?
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
+12
-11
@@ -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) {
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ public constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "defaultSource", customType = "ImageSource")
|
||||
@ReactProp(name = "defaultSource")
|
||||
public fun setDefaultSource(view: ReactImageView, source: String?) {
|
||||
view.setDefaultSource(source)
|
||||
}
|
||||
|
||||
+16
-2
@@ -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 class TextAttributeProps {
|
||||
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 class TextAttributeProps {
|
||||
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 @@ public class TextAttributeProps {
|
||||
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 @@ public class TextAttributeProps {
|
||||
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;
|
||||
|
||||
@@ -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 = 1;
|
||||
std::string_view Prerelease = "";
|
||||
} ReactNativeVersion;
|
||||
|
||||
|
||||
+22
-4
@@ -123,6 +123,15 @@ std::vector<ExportedMethod> parseExportedMethods(std::string moduleName, Class m
|
||||
NSArray<RCTMethodArgument *> *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 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
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<char>(selector, objCArg);
|
||||
@@ -437,6 +446,15 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
|
||||
if (objCArgType == @encode(id)) {
|
||||
id arg = RCTConvertTo<id>(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 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
}
|
||||
|
||||
RCTResponseSenderBlock arg =
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
if (arg) {
|
||||
[retainedObjectsForInvocation addObject:arg];
|
||||
}
|
||||
@@ -506,7 +524,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
}
|
||||
|
||||
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 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
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);
|
||||
|
||||
+1
@@ -32,6 +32,7 @@ using EventEmitterCallback = std::function<void(const std::string &, id)>;
|
||||
namespace TurboModuleConvertUtils {
|
||||
jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value);
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker);
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker, BOOL useNSNull);
|
||||
} // namespace TurboModuleConvertUtils
|
||||
|
||||
template <>
|
||||
|
||||
+16
-8
@@ -112,20 +112,20 @@ static NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::St
|
||||
}
|
||||
|
||||
static NSArray *
|
||||
convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<CallInvoker> 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<CallInvoker> jsInvoker)
|
||||
convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr<CallInvoker> jsInvoker, BOOL useNSNull)
|
||||
{
|
||||
jsi::Array propertyNames = value.getPropertyNames(runtime);
|
||||
size_t size = propertyNames.size(runtime);
|
||||
@@ -133,7 +133,7 @@ convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value,
|
||||
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 @@ convertJSIFunctionToCallback(jsi::Runtime &rt, jsi::Function &&function, std::sh
|
||||
};
|
||||
}
|
||||
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker)
|
||||
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> 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<CallInvoker> 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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -51,6 +51,7 @@ class TextAttributes : public DebugStringConvertible {
|
||||
std::optional<FontStyle> fontStyle{};
|
||||
std::optional<FontVariant> fontVariant{};
|
||||
std::optional<bool> allowFontScaling{};
|
||||
Float maxFontSizeMultiplier{std::numeric_limits<Float>::quiet_NaN()};
|
||||
std::optional<DynamicTypeRamp> dynamicTypeRamp{};
|
||||
Float letterSpacing{std::numeric_limits<Float>::quiet_NaN()};
|
||||
std::optional<TextTransform> textTransform{};
|
||||
@@ -117,6 +118,7 @@ struct hash<facebook::react::TextAttributes> {
|
||||
textAttributes.opacity,
|
||||
textAttributes.fontFamily,
|
||||
textAttributes.fontSize,
|
||||
textAttributes.maxFontSizeMultiplier,
|
||||
textAttributes.fontSizeMultiplier,
|
||||
textAttributes.fontWeight,
|
||||
textAttributes.fontStyle,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
+24
-3
@@ -52,8 +52,29 @@ BOOL RCTIsAttributedStringEffectivelySame(
|
||||
NSDictionary<NSAttributedStringKey, id> *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<const facebook::react::EventEmitter>(eventEmitter);
|
||||
return [[NSData alloc] initWithBytesNoCopy:eventEmitterPtr
|
||||
length:sizeof(eventEmitterPtr)
|
||||
deallocator:^(void *ptrToDelete, NSUInteger) {
|
||||
delete (std::weak_ptr<facebook::react::EventEmitter> *)ptrToDelete;
|
||||
}];
|
||||
}
|
||||
|
||||
static inline facebook::react::SharedEventEmitter RCTUnwrapEventEmitter(NSData *data)
|
||||
{
|
||||
if (data.length == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto weakPtr = dynamic_cast<std::weak_ptr<const facebook::react::EventEmitter> *>(
|
||||
(std::weak_ptr<const facebook::react::EventEmitter> *)data.bytes);
|
||||
if (weakPtr) {
|
||||
return weakPtr->lock();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
+6
-46
@@ -16,45 +16,6 @@
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTWeakEventEmitterWrapper {
|
||||
std::weak_ptr<const EventEmitter> _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 @@ static NSMutableAttributedString *RCTNSAttributedStringFragmentWithAttributesFro
|
||||
{
|
||||
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<NSAttributedStringKey, id> *additionalTextAttributes =
|
||||
@{RCTAttributedStringEventEmitterKey : eventEmitterWrapper};
|
||||
@@ -418,7 +379,6 @@ static NSMutableAttributedString *RCTNSAttributedStringFragmentWithAttributesFro
|
||||
[nsAttributedStringFragment addAttributes:additionalTextAttributes
|
||||
range:NSMakeRange(0, nsAttributedStringFragment.length)];
|
||||
}
|
||||
#endif
|
||||
|
||||
return nsAttributedStringFragment;
|
||||
}
|
||||
|
||||
+4
-5
@@ -268,11 +268,10 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
||||
// 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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "1000.0.0",
|
||||
"version": "0.78.1",
|
||||
"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.1",
|
||||
"@react-native/codegen": "0.78.1",
|
||||
"@react-native/community-cli-plugin": "0.78.1",
|
||||
"@react-native/gradle-plugin": "0.78.1",
|
||||
"@react-native/js-polyfills": "0.78.1",
|
||||
"@react-native/normalize-colors": "0.78.1",
|
||||
"@react-native/virtualized-lists": "0.78.1",
|
||||
"abort-controller": "^3.0.0",
|
||||
"anser": "^1.4.9",
|
||||
"ansi-regex": "^5.0.0",
|
||||
|
||||
@@ -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 <path>',
|
||||
description: 'Path where generated artifacts will be output to.',
|
||||
},
|
||||
{
|
||||
name: '--source <string>',
|
||||
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,
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
@@ -899,11 +899,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 +952,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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hermes-2025-01-13-RNv0.78.0-a942ef374897d85da38e9c8904574f8376555388
|
||||
@@ -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'
|
||||
|
||||
+291
-291
File diff suppressed because it is too large
Load Diff
@@ -482,6 +482,37 @@ function AllowFontScalingExample(props: {}): React.Node {
|
||||
);
|
||||
}
|
||||
|
||||
function MaxFontSizeMultiplierExample(props: {}): React.Node {
|
||||
return (
|
||||
<View testID={'max-font-size-multiplier'}>
|
||||
<Text>
|
||||
When allowFontScaling is enabled, you can use the maxFontSizeMultiplier
|
||||
prop to set an upper limit on how much the font size will be scaled.
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1}
|
||||
style={{marginTop: 10}}>
|
||||
This text will not scale up (max 1x)
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1.5}>
|
||||
This text will scale up (max 1.5x)
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text>Inherit max (max 1x)</Text>
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text maxFontSizeMultiplier={1.5}>
|
||||
Override inherited max (max 1.5x)
|
||||
</Text>
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text maxFontSizeMultiplier={0}>Ignore inherited max (no max)</Text>
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function NumberOfLinesExample(props: {}): React.Node {
|
||||
return (
|
||||
<>
|
||||
@@ -1462,6 +1493,13 @@ const examples = [
|
||||
return <AllowFontScalingExample />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'maxFontSizeMultiplier attribute',
|
||||
name: 'maxFontSizeMultiplier',
|
||||
render(): React.Node {
|
||||
return <MaxFontSizeMultiplierExample />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'selectable attribute',
|
||||
name: 'selectable',
|
||||
|
||||
@@ -1175,6 +1175,62 @@ const examples = [
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'maxFontSizeMultiplier attribute',
|
||||
name: 'maxFontSizeMultiplier',
|
||||
render(): React.Node {
|
||||
return (
|
||||
<View testID={'max-font-size-multiplier'}>
|
||||
<Text>
|
||||
When allowFontScaling is enabled, you can use the
|
||||
maxFontSizeMultiplier prop to set an upper limit on how much the
|
||||
font size will be scaled.
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1}
|
||||
style={{marginTop: 10}}>
|
||||
This text will not scale up (max 1x)
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1.5}>
|
||||
This text will scale up (max 1.5x)
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text>Inherit max (max 1x)</Text>
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text maxFontSizeMultiplier={1.5}>
|
||||
Override inherited max (max 1.5x)
|
||||
</Text>
|
||||
</Text>
|
||||
<Text allowFontScaling={true} maxFontSizeMultiplier={1}>
|
||||
<Text maxFontSizeMultiplier={0}>Ignore inherited max (no max)</Text>
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
style={{fontSize: 22}}
|
||||
dynamicTypeRamp="title2">
|
||||
This text will scale with 'title2' dynamic type ramp (no max)
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
style={{fontSize: 22}}
|
||||
dynamicTypeRamp="title2"
|
||||
maxFontSizeMultiplier={1.2}>
|
||||
This text will scale with 'title2' dynamic type ramp (max 1.2x)
|
||||
</Text>
|
||||
<Text
|
||||
allowFontScaling={true}
|
||||
style={{fontSize: 22}}
|
||||
dynamicTypeRamp="title2"
|
||||
maxFontSizeMultiplier={1}>
|
||||
This text uses 'title2' dynamic type ramp but will not scale up (max
|
||||
1x)
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Inline views',
|
||||
render: (): React.Node => <TextInlineView.Basic />,
|
||||
@@ -1440,9 +1496,27 @@ const examples = [
|
||||
<Text style={{fontSize: 20}} dynamicTypeRamp="title3">
|
||||
Title 3
|
||||
</Text>
|
||||
<Text style={{fontSize: 17}} dynamicTypeRamp="headline">
|
||||
Headline
|
||||
</Text>
|
||||
<Text style={{fontSize: 17}} dynamicTypeRamp="body">
|
||||
Body
|
||||
</Text>
|
||||
<Text style={{fontSize: 16}} dynamicTypeRamp="callout">
|
||||
Callout
|
||||
</Text>
|
||||
<Text style={{fontSize: 15}} dynamicTypeRamp="subheadline">
|
||||
Subheadline
|
||||
</Text>
|
||||
<Text style={{fontSize: 13}} dynamicTypeRamp="footnote">
|
||||
Footnote
|
||||
</Text>
|
||||
<Text style={{fontSize: 12}} dynamicTypeRamp="caption1">
|
||||
Caption
|
||||
</Text>
|
||||
<Text style={{fontSize: 11}} dynamicTypeRamp="caption2">
|
||||
Caption 2
|
||||
</Text>
|
||||
</View>
|
||||
<View style={boxStyle}>
|
||||
<Text style={boldStyle}>Without `dynamicTypeRamp`:</Text>
|
||||
@@ -1450,7 +1524,13 @@ const examples = [
|
||||
<Text style={{fontSize: 28}}>Title</Text>
|
||||
<Text style={{fontSize: 22}}>Title 2</Text>
|
||||
<Text style={{fontSize: 20}}>Title 3</Text>
|
||||
<Text style={{fontSize: 17}}>Headline</Text>
|
||||
<Text style={{fontSize: 17}}>Body</Text>
|
||||
<Text style={{fontSize: 16}}>Callout</Text>
|
||||
<Text style={{fontSize: 15}}>Subheadline</Text>
|
||||
<Text style={{fontSize: 13}}>Footnote</Text>
|
||||
<Text style={{fontSize: 12}}>Caption</Text>
|
||||
<Text style={{fontSize: 11}}>Caption 2</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -305,6 +305,59 @@ const examples: Array<RNTesterModuleExample> = [
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'allowFontScaling attribute',
|
||||
render: function (): React.Node {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
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.
|
||||
</Text>
|
||||
<ExampleTextInput
|
||||
placeholder="allowFontScaling = false"
|
||||
allowFontScaling={false}
|
||||
/>
|
||||
<ExampleTextInput
|
||||
style={{marginTop: 10}}
|
||||
placeholder="allowFontScaling = false"
|
||||
allowFontScaling={true}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'maxFontSizeMultiplier attribute',
|
||||
name: 'maxFontSizeMultiplier',
|
||||
render(): React.Node {
|
||||
return (
|
||||
<View testID={'max-font-size-multiplier'}>
|
||||
<Text>
|
||||
When allowFontScaling is enabled, you can use the
|
||||
maxFontSizeMultiplier prop to set an upper limit on how much the
|
||||
font size will be scaled.
|
||||
</Text>
|
||||
<ExampleTextInput
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1}
|
||||
placeholder="This text will not scale up (max 1x)"
|
||||
style={{marginTop: 10}}
|
||||
testID={'non-scalable-text-input'}
|
||||
/>
|
||||
<ExampleTextInput
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1.5}
|
||||
placeholder="This text will scale up (max 1.5x)"
|
||||
style={{marginTop: 10}}
|
||||
testID={'scalable-text-input'}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Text Auto Complete',
|
||||
render: function (): React.Node {
|
||||
|
||||
@@ -730,6 +730,61 @@ const textInputExamples: Array<RNTesterModuleExample> = [
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'allowFontScaling attribute',
|
||||
render: function (): React.Node {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
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{' '}
|
||||
<Text style={{fontWeight: 'bold'}}>
|
||||
Settings.app - Display & Brightness - Text Size
|
||||
</Text>
|
||||
</Text>
|
||||
<ExampleTextInput
|
||||
placeholder="allowFontScaling = false"
|
||||
allowFontScaling={false}
|
||||
/>
|
||||
<ExampleTextInput
|
||||
style={{marginTop: 10}}
|
||||
placeholder="allowFontScaling = false"
|
||||
allowFontScaling={true}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'maxFontSizeMultiplier attribute',
|
||||
name: 'maxFontSizeMultiplier',
|
||||
render(): React.Node {
|
||||
return (
|
||||
<View testID={'max-font-size-multiplier'}>
|
||||
<Text>
|
||||
When allowFontScaling is enabled, you can use the
|
||||
maxFontSizeMultiplier prop to set an upper limit on how much the
|
||||
font size will be scaled.
|
||||
</Text>
|
||||
<ExampleTextInput
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1}
|
||||
placeholder="This text will not scale up (max 1x)"
|
||||
style={{marginTop: 10}}
|
||||
testID={'non-scalable-text-input'}
|
||||
/>
|
||||
<ExampleTextInput
|
||||
allowFontScaling={true}
|
||||
maxFontSizeMultiplier={1.5}
|
||||
placeholder="This text will scale up (max 1.5x)"
|
||||
style={{marginTop: 10}}
|
||||
testID={'scalable-text-input'}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Auto-expanding',
|
||||
render: function (): React.Node {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/tester",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"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.1",
|
||||
"@react-native/popup-menu-android": "0.78.1",
|
||||
"flow-enums-runtime": "^0.0.6",
|
||||
"invariant": "^2.2.4",
|
||||
"nullthrows": "^1.1.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/typescript-config",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Default TypeScript configuration for React Native apps",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/virtualized-lists",
|
||||
"version": "0.77.0-main",
|
||||
"version": "0.78.1",
|
||||
"description": "Virtualized lists for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -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`,
|
||||
);
|
||||
|
||||
// launch the app on iOS simulator
|
||||
exec(
|
||||
'npx react-native run-ios --scheme RNTester --simulator "iPhone 15 Pro"',
|
||||
);
|
||||
}
|
||||
|
||||
// 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"',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +227,7 @@ async function testRNTesterAndroid(
|
||||
* - @onReleaseBranch whether we are on a release branch or not
|
||||
*/
|
||||
async function testRNTester(
|
||||
circleCIArtifacts /*:Unwrap<ReturnType<typeof setupGHAArtifacts>> */,
|
||||
ciArtifacts /*:Unwrap<ReturnType<typeof setupGHAArtifacts>> */,
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -214,6 +214,14 @@ async function artifactURLForHermesRNTesterAPK(
|
||||
return getArtifactURL('rntester-hermes-debug');
|
||||
}
|
||||
|
||||
async function artifactURLForJSCRNTesterApp() /*: Promise<string> */ {
|
||||
return getArtifactURL('RNTesterApp-NewArch-JSC-Debug');
|
||||
}
|
||||
|
||||
async function artifactURLForHermesRNTesterApp() /*: Promise<string> */ {
|
||||
return getArtifactURL('RNTesterApp-NewArch-Hermes-Debug');
|
||||
}
|
||||
|
||||
async function artifactURLForMavenLocal() /*: Promise<string> */ {
|
||||
return getArtifactURL('maven-local');
|
||||
}
|
||||
@@ -247,6 +255,8 @@ module.exports = {
|
||||
downloadArtifact,
|
||||
artifactURLForJSCRNTesterAPK,
|
||||
artifactURLForHermesRNTesterAPK,
|
||||
artifactURLForJSCRNTesterApp,
|
||||
artifactURLForHermesRNTesterApp,
|
||||
artifactURLForMavenLocal,
|
||||
artifactURLHermesDebug,
|
||||
artifactURLForReactNative,
|
||||
|
||||
Reference in New Issue
Block a user