Compare commits

..
455 changed files with 1918 additions and 8106 deletions
+2 -5
View File
@@ -75,10 +75,7 @@ module.system.haste.module_ref_prefix=m#
react.runtime=automatic
experimental.only_support_flow_fixme_and_expected_error=true
experimental.require_suppression_with_error_code=true
experimental.invariant_subtyping_error_message_improvement=true
experimental.natural_inference.local_object_literals.followup_fix=true
experimental.error_code_migration=new
ban_spread_key_props=true
@@ -103,4 +100,4 @@ untyped-import
untyped-type-import
[version]
^0.280.0
^0.279.0
@@ -188,7 +188,6 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
status: 201,
json: () =>
Promise.resolve({
id: 1,
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
}),
@@ -209,11 +208,9 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
body: fetchBody,
},
);
expect(response).toEqual({
id: 1,
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
});
expect(response).toEqual(
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
);
});
it('creates a draft release for prerelease on GitHub', async () => {
@@ -241,7 +238,6 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
status: 201,
json: () =>
Promise.resolve({
id: 1,
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
}),
@@ -262,11 +258,9 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
body: fetchBody,
},
);
expect(response).toEqual({
id: 1,
html_url:
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
});
expect(response).toEqual(
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
);
});
it('throws if the post failes', async () => {
@@ -101,11 +101,7 @@ async function _createDraftReleaseOnGitHub(version, body, latest, token) {
}
const data = await response.json();
const {html_url, id} = data;
return {
html_url,
id,
};
return data.html_url;
}
function moveToChangelogBranch(version) {
@@ -128,8 +124,7 @@ async function createDraftRelease(version, latest, token) {
latest,
token,
);
log(`Created draft release: ${release.html_url}, ID ${release.id}`);
return release;
log(`Created draft release: ${release}`);
}
module.exports = {
-1
View File
@@ -10,7 +10,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
+1 -16
View File
@@ -21,24 +21,9 @@ jobs:
git config --local user.name "React Native Bot"
- name: Create draft release
uses: actions/github-script@v6
id: create-draft-release
with:
script: |
const {createDraftRelease} = require('./.github/workflow-scripts/createDraftRelease.js');
const version = '${{ github.ref_name }}';
const {isLatest} = require('./.github/workflow-scripts/publishTemplate.js');
return (await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}')).id;
result-encoding: string
- name: Upload release assets for DotSlash
uses: actions/github-script@v6
env:
RELEASE_ID: ${{ steps.create-draft-release.outputs.result }}
with:
script: |
const {uploadReleaseAssetsForDotSlashFiles} = require('./scripts/releases/upload-release-assets-for-dotslash.js');
const version = '${{ github.ref_name }}';
await uploadReleaseAssetsForDotSlashFiles({
version,
token: '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}',
releaseId: process.env.RELEASE_ID,
});
await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}');
-2
View File
@@ -10,7 +10,6 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
@@ -23,7 +22,6 @@ jobs:
- name: Generate Changelog
uses: actions/github-script@v6
with:
github-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
script: |
const {generateChangelog} = require('./.github/workflow-scripts/generateChangelog');
const version = '${{ github.ref_name }}';
+2 -4
View File
@@ -273,8 +273,7 @@ jobs:
NEW_ARCH_ENABLED=1
export RCT_USE_LOCAL_RN_DEP=/tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
# Disable prebuilds for now, as they are causing issues with E2E tests for 0.82-stable branch
# export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz"
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ matrix.flavor }}.xcframework.tar.gz"
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
xcodebuild \
@@ -380,8 +379,7 @@ jobs:
runs-on: 8-core-ubuntu
needs: [set_release_type]
container:
# Version is pinned to v18.0 to unblock `run_fantom_tests` - see https://github.com/react-native-community/docker-android/pull/242#issuecomment-3280029122
image: reactnativecommunity/react-native-android:v18.0
image: reactnativecommunity/react-native-android:latest
env:
TERM: "dumb"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
@@ -1,48 +0,0 @@
name: Validate DotSlash Artifacts
on:
workflow_dispatch:
release:
types: [published]
push:
branches:
- main
paths:
- packages/debugger-shell/bin/react-native-devtools
- "scripts/releases/**"
- package.json
- yarn.lock
pull_request:
branches:
- main
paths:
- packages/debugger-shell/bin/react-native-devtools
- "scripts/releases/**"
- package.json
- yarn.lock
# Same time as the nightly build: 2:15 AM UTC
schedule:
- cron: "15 2 * * *"
jobs:
validate-dotslash-artifacts:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Configure Git
shell: bash
run: |
git config --local user.email "bot@reactnative.dev"
git config --local user.name "React Native Bot"
- name: Validate DotSlash artifacts
uses: actions/github-script@v6
with:
script: |
const {validateDotSlashArtifacts} = require('./scripts/releases/validate-dotslash-artifacts.js');
await validateDotSlashArtifacts();
-29
View File
@@ -1,34 +1,5 @@
# Changelog
## v0.81.1
### Added
#### iOS specific
- **Prebuild:** Added setting SWIFT_ENABLE_EXPLICIT_MODULES=NO when using precompiled to support Xcode 26 ([939a75b5ce](https://github.com/facebook/react-native/commit/939a75b5ce2a580ece4a62689582ea81480c3e97) by [@chrfalch](https://github.com/chrfalch))
### Fixed
- **Infra:** Add missing Babel dependencies ([bf2c3af93b](https://github.com/facebook/react-native/commit/bf2c3af93b146943cb35866fa9badcd188e63f5b) by [@tido64](https://github.com/tido64))
- **Accessibility:** fix `aria-label` on `TextInput` ([6965d57e75](https://github.com/facebook/react-native/commit/6965d57e75ed0cf9f265c6020d478ddb9af4bf10) by [@mdjastrzebski](https://github.com/mdjastrzebski))
#### iOS specific
- **TextInput:** Setting maxLength to 0 in TextInput now correctly blocks typing ([c5956da8c0](https://github.com/facebook/react-native/commit/c5956da8c0b735d47761af51019ed25b49001c00) by [@riteshshukla04](https://github.com/riteshshukla04))
- **Switch:** Fix Switch layout to work with iOS 26 ([ba51aeaa90](https://github.com/facebook/react-native/commit/ba51aeaa9040014e1d77c93158c96e9bf09940cf) by [@cipolleschi](https://github.com/cipolleschi))
- **C++:** Fix import RuntimeExecutor.h with USE_FRAMEWORKS ([dacd8f26fd](https://github.com/facebook/react-native/commit/dacd8f26fda61b16b52a4953267f2108181c3282) by [@sharifhh](https://github.com/sharifhh))
- **Infra:** Fix scripts for paths containing whitespaces ([94623ca8ec](https://github.com/facebook/react-native/commit/94623ca8ec969f09d8ec430e7633c3bf49a3d71e) by [@kitten](https://github.com/kitten))
- **Prebuild:** Fixed how we copy and build the Symbols folder when precompiling ReactNativeDependencies ([a843119ff1](https://github.com/facebook/react-native/commit/a843119ff1f0e2dfb1d3884ccf255784e3cea1a7) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Fixed wrong jsi symbols in use when using React.xcframework ([8a2e7efe01](https://github.com/facebook/react-native/commit/8a2e7efe010c49a293c146654094b1cb5d6e6acd) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Fixed copying bundles correctly to xcframeworks when precompiling ReactNativeDependencies.xcframework ([e3adf47214](https://github.com/facebook/react-native/commit/e3adf4721467557f19e6cd7a65c4e2314796bc17) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Aligned Symbols folder in React.xcframework symbols with ReactNativeDependencies.xcframework symbols. ([8c444f773a](https://github.com/facebook/react-native/commit/8c444f773a44e8554745c9cfc1451083c12b00e3) by [@chrfalch](https://github.com/chrfalch))
- **Prebuild:** Fix "file exists" error in `ReactNativeDependencies.podspec` ([4c570b5d31](https://github.com/facebook/react-native/commit/4c570b5d31ef46e04e5fa26fa92d7f7090bf15e2) by [@vonovak](https://github.com/vonovak))
- **Prebuild:** added explicit handling of ReactCodegen ([6526a98d68](https://github.com/facebook/react-native/commit/6526a98d68dbc8578ea15cbf117c0a216c6e9af0) by [@cipolleschi](https://github.com/cipolleschi))
## v0.81.0
### Breaking
-1
View File
@@ -135,7 +135,6 @@ if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoole
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(project(":packages:react-native:ReactAndroid:hermes-engine"))
// TODO: T237406039 update coordinates
.using(module("com.facebook.react:hermes-android:0.+"))
.because("Users opted to use hermes from nightly")
}
-46
View File
@@ -1,46 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
declare module '@expo/spawn-async' {
type SpawnOptions = {
cwd?: string,
env?: Object,
argv0?: string,
stdio?: string | Array<any>,
detached?: boolean,
uid?: number,
gid?: number,
shell?: boolean | string,
windowsVerbatimArguments?: boolean,
windowsHide?: boolean,
encoding?: string,
ignoreStdio?: boolean,
};
declare class SpawnPromise<T> extends Promise<T> {
child: child_process$ChildProcess;
}
type SpawnResult = {
pid?: number,
output: string[],
stdout: string,
stderr: string,
status: number | null,
signal: string | null,
};
declare function spawnAsync(
command: string,
args?: $ReadOnlyArray<string>,
options?: SpawnOptions,
): SpawnPromise<SpawnResult>;
declare module.exports: typeof spawnAsync;
}
-61
View File
@@ -1,61 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// Partial types for Octokit based on the usage in react-native-github
declare module '@octokit/rest' {
declare class Octokit {
constructor(options?: {auth?: string, ...}): this;
repos: $ReadOnly<{
listReleaseAssets: (
params: $ReadOnly<{
owner: string,
repo: string,
release_id: string,
}>,
) => Promise<{
data: Array<{
id: string,
name: string,
...
}>,
...
}>,
uploadReleaseAsset: (
params: $ReadOnly<{
owner: string,
repo: string,
release_id: string,
name: string,
data: Buffer,
headers: $ReadOnly<{
'content-type': string,
...
}>,
...
}>,
) => Promise<{
data: {
browser_download_url: string,
...
},
...
}>,
deleteReleaseAsset: (params: {
owner: string,
repo: string,
asset_id: string,
...
}) => Promise<mixed>,
}>;
}
declare export {Octokit};
}
-13
View File
@@ -1,13 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
declare module 'fb-dotslash' {
declare module.exports: string;
}
-421
View File
@@ -1,421 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
declare module 'jsonc-parser' {
/**
* Creates a JSON scanner on the given text.
* If ignoreTrivia is set, whitespaces or comments are ignored.
*/
declare export const createScanner: (
text: string,
ignoreTrivia?: boolean,
) => JSONScanner;
export type ScanError = number;
export type SyntaxKind = number;
/**
* The scanner object, representing a JSON scanner at a position in the input string.
*/
export type JSONScanner = $ReadOnly<{
/**
* Sets the scan position to a new offset. A call to 'scan' is needed to get the first token.
*/
setPosition(pos: number): void,
/**
* Read the next token. Returns the token code.
*/
scan(): SyntaxKind,
/**
* Returns the zero-based current scan position, which is after the last read token.
*/
getPosition(): number,
/**
* Returns the last read token.
*/
getToken(): SyntaxKind,
/**
* Returns the last read token value. The value for strings is the decoded string content. For numbers it's of type number, for boolean it's true or false.
*/
getTokenValue(): string,
/**
* The zero-based start offset of the last read token.
*/
getTokenOffset(): number,
/**
* The length of the last read token.
*/
getTokenLength(): number,
/**
* The zero-based start line number of the last read token.
*/
getTokenStartLine(): number,
/**
* The zero-based start character (column) of the last read token.
*/
getTokenStartCharacter(): number,
/**
* An error code of the last scan.
*/
getTokenError(): ScanError,
}>;
/**
* For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.
*/
declare export const getLocation: (
text: string,
position: number,
) => Location;
/**
* Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
* Therefore, always check the errors list to find out if the input was valid.
*/
declare export const parse: (
text: string,
errors?: ParseError[],
options?: ParseOptions,
) => any;
/**
* Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
*/
declare export const parseTree: (
text: string,
errors?: ParseError[],
options?: ParseOptions,
) => Node | void;
/**
* Finds the node at the given path in a JSON DOM.
*/
declare export const findNodeAtLocation: (
root: Node,
path: JSONPath,
) => Node | void;
/**
* Finds the innermost node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.
*/
declare export const findNodeAtOffset: (
root: Node,
offset: number,
includeRightBound?: boolean,
) => Node | void;
/**
* Gets the JSON path of the given JSON DOM node
*/
declare export const getNodePath: (node: Node) => JSONPath;
/**
* Evaluates the JavaScript object of the given JSON DOM node
*/
declare export const getNodeValue: (node: Node) => any;
/**
* Parses the given text and invokes the visitor functions for each object, array and literal reached.
*/
declare export const visit: (
text: string,
visitor: JSONVisitor,
options?: ParseOptions,
) => any;
/**
* Takes JSON with JavaScript-style comments and remove
* them. Optionally replaces every none-newline character
* of comments with a replaceCharacter
*/
declare export const stripComments: (
text: string,
replaceCh?: string,
) => string;
export type ParseError = {
error: ParseErrorCode,
offset: number,
length: number,
};
export type ParseErrorCode = number;
declare export function printParseErrorCode(
code: ParseErrorCode,
):
| 'InvalidSymbol'
| 'InvalidNumberFormat'
| 'PropertyNameExpected'
| 'ValueExpected'
| 'ColonExpected'
| 'CommaExpected'
| 'CloseBraceExpected'
| 'CloseBracketExpected'
| 'EndOfFileExpected'
| 'InvalidCommentToken'
| 'UnexpectedEndOfComment'
| 'UnexpectedEndOfString'
| 'UnexpectedEndOfNumber'
| 'InvalidUnicode'
| 'InvalidEscapeCharacter'
| 'InvalidCharacter'
| '<unknown ParseErrorCode>';
export type NodeType =
| 'object'
| 'array'
| 'property'
| 'string'
| 'number'
| 'boolean'
| 'null';
export type Node = {
type: NodeType,
value?: any,
offset: number,
length: number,
colonOffset?: number,
parent?: Node,
children?: Node[],
};
/**
* A {@linkcode JSONPath} segment. Either a string representing an object property name
* or a number (starting at 0) for array indices.
*/
export type Segment = string | number;
export type JSONPath = Segment[];
export type Location = {
/**
* The previous property key or literal value (string, number, boolean or null) or undefined.
*/
previousNode?: Node,
/**
* The path describing the location in the JSON document. The path consists of a sequence of strings
* representing an object property or numbers for array indices.
*/
path: JSONPath,
/**
* Matches the locations path against a pattern consisting of strings (for properties) and numbers (for array indices).
* '*' will match a single segment of any property name or index.
* '**' will match a sequence of segments of any property name or index, or no segment.
*/
matches: (patterns: JSONPath) => boolean,
/**
* If set, the location's offset is at a property key.
*/
isAtPropertyKey: boolean,
};
export type ParseOptions = {
disallowComments?: boolean,
allowTrailingComma?: boolean,
allowEmptyContent?: boolean,
};
/**
* Visitor called by {@linkcode visit} when parsing JSON.
*
* The visitor functions have the following common parameters:
* - `offset`: Global offset within the JSON document, starting at 0
* - `startLine`: Line number, starting at 0
* - `startCharacter`: Start character (column) within the current line, starting at 0
*
* Additionally some functions have a `pathSupplier` parameter which can be used to obtain the
* current `JSONPath` within the document.
*/
export type JSONVisitor = {
/**
* Invoked when an open brace is encountered and an object is started. The offset and length represent the location of the open brace.
*/
onObjectBegin?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
pathSupplier: () => JSONPath,
) => void,
/**
* Invoked when a property is encountered. The offset and length represent the location of the property name.
* The `JSONPath` created by the `pathSupplier` refers to the enclosing JSON object, it does not include the
* property name yet.
*/
onObjectProperty?: (
property: string,
offset: number,
length: number,
startLine: number,
startCharacter: number,
pathSupplier: () => JSONPath,
) => void,
/**
* Invoked when a closing brace is encountered and an object is completed. The offset and length represent the location of the closing brace.
*/
onObjectEnd?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
/**
* Invoked when an open bracket is encountered. The offset and length represent the location of the open bracket.
*/
onArrayBegin?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
pathSupplier: () => JSONPath,
) => void,
/**
* Invoked when a closing bracket is encountered. The offset and length represent the location of the closing bracket.
*/
onArrayEnd?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
/**
* Invoked when a literal value is encountered. The offset and length represent the location of the literal value.
*/
onLiteralValue?: (
value: any,
offset: number,
length: number,
startLine: number,
startCharacter: number,
pathSupplier: () => JSONPath,
) => void,
/**
* Invoked when a comma or colon separator is encountered. The offset and length represent the location of the separator.
*/
onSeparator?: (
character: string,
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
/**
* When comments are allowed, invoked when a line or block comment is encountered. The offset and length represent the location of the comment.
*/
onComment?: (
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
/**
* Invoked on an error.
*/
onError?: (
error: ParseErrorCode,
offset: number,
length: number,
startLine: number,
startCharacter: number,
) => void,
};
/**
* An edit result describes a textual edit operation. It is the result of a {@linkcode format} and {@linkcode modify} operation.
* It consist of one or more edits describing insertions, replacements or removals of text segments.
* * The offsets of the edits refer to the original state of the document.
* * No two edits change or remove the same range of text in the original document.
* * Multiple edits can have the same offset if they are multiple inserts, or an insert followed by a remove or replace.
* * The order in the array defines which edit is applied first.
* To apply an edit result use {@linkcode applyEdits}.
* In general multiple EditResults must not be concatenated because they might impact each other, producing incorrect or malformed JSON data.
*/
export type EditResult = Edit[];
/**
* Represents a text modification
*/
export type Edit = {
/**
* The start offset of the modification.
*/
offset: number,
/**
* The length of the modification. Must not be negative. Empty length represents an *insert*.
*/
length: number,
/**
* The new content. Empty content represents a *remove*.
*/
content: string,
};
/**
* A text range in the document
*/
export type Range = {
/**
* The start offset of the range.
*/
offset: number,
/**
* The length of the range. Must not be negative.
*/
length: number,
};
/**
* Options used by {@linkcode format} when computing the formatting edit operations
*/
export type FormattingOptions = $ReadOnly<{
/**
* If indentation is based on spaces (`insertSpaces` = true), the number of spaces that make an indent.
*/
tabSize?: number,
/**
* Is indentation based on spaces?
*/
insertSpaces?: boolean,
/**
* The default 'end of line' character. If not set, '\n' is used as default.
*/
eol?: string,
}>;
/**
* Computes the edit operations needed to format a JSON document.
*
* @param documentText The input text
* @param range The range to format or `undefined` to format the full content
* @param options The formatting options
* @returns The edit operations describing the formatting changes to the original document following the format described in {@linkcode EditResult}.
* To apply the edit operations to the input, use {@linkcode applyEdits}.
*/
declare export function format(
documentText: string,
range: Range | void,
options: FormattingOptions,
): EditResult;
/**
* Options used by {@linkcode modify} when computing the modification edit operations
*/
export type ModificationOptions = {
/**
* Formatting options.
*/
formattingOptions: FormattingOptions,
/**
* Optional function to define the insertion index given an existing list of properties.
*/
getInsertionIndex?: (properties: string[]) => number,
};
/**
* Computes the edit operations needed to modify a value in the JSON document.
*
* @param documentText The input text
* @param path The path of the value to change. The path represents either to the document root, a property or an array item.
* If the path points to an non-existing property or item, it will be created.
* @param value The new value for the specified property or item. If the value is undefined,
* the property or item will be removed.
* @param options Options
* @returns The edit operations describing the changes to the original document, following the format described in {@linkcode EditResult}.
* To apply the edit operations to the input, use {@linkcode applyEdits}.
*/
declare export function modify(
text: string,
path: JSONPath,
value: any,
options: ModificationOptions,
): EditResult;
/**
* Applies edits to an input string.
* @param text The input text
* @param edits Edit operations following the format described in {@linkcode EditResult}.
* @returns The text with the applied edits.
* @throws An error if the edit operations are not well-formed as described in {@linkcode EditResult}.
*/
declare export function applyEdits(text: string, edits: EditResult): string;
}
-3
View File
@@ -12,6 +12,3 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
# Controls whether to use Hermes from nightly builds. This will speed up builds
# but should NOT be turned on for CI or release builds.
react.internal.useHermesNightly=false
# Controls whether to use Hermes 1.0. Clean and rebuild when changing.
hermesV1Enabled=false
+4 -9
View File
@@ -54,16 +54,13 @@
"@babel/preset-env": "^7.25.3",
"@babel/preset-flow": "^7.24.7",
"@electron/packager": "^18.3.6",
"@expo/spawn-async": "^1.7.2",
"@jest/create-cache-key-function": "^29.7.0",
"@microsoft/api-extractor": "^7.52.2",
"@octokit/rest": "^22.0.0",
"@react-native/metro-babel-transformer": "0.82.1",
"@react-native/metro-config": "0.82.1",
"@react-native/metro-babel-transformer": "0.82.0-main",
"@react-native/metro-config": "0.82.0-main",
"@tsconfig/node22": "22.0.2",
"@types/react": "^19.1.0",
"@typescript-eslint/parser": "^8.36.0",
"ansi-regex": "^5.0.0",
"ansi-styles": "^4.2.1",
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
"babel-plugin-syntax-hermes-parser": "0.32.0",
@@ -84,9 +81,8 @@
"eslint-plugin-react-native": "^4.0.0",
"eslint-plugin-redundant-undefined": "^0.4.0",
"eslint-plugin-relay": "^1.8.3",
"fb-dotslash": "0.5.8",
"flow-api-translator": "0.32.0",
"flow-bin": "^0.280.0",
"flow-bin": "^0.279.0",
"glob": "^7.1.1",
"hermes-eslint": "0.32.0",
"hermes-transform": "0.32.0",
@@ -95,9 +91,8 @@
"jest": "^29.7.0",
"jest-config": "^29.7.0",
"jest-diff": "^29.7.0",
"jest-junit": "^16.0.0",
"jest-junit": "^10.0.0",
"jest-snapshot": "^29.7.0",
"jsonc-parser": "2.2.1",
"markdownlint-cli2": "^0.17.2",
"markdownlint-rule-relative-links": "^3.0.0",
"memfs": "^4.7.7",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/assets-registry",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Asset support code for React Native.",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-plugin-codegen",
"version": "0.82.1",
"version": "0.82.0-main",
"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.82.1"
"@react-native/codegen": "0.82.0-main"
},
"devDependencies": {
"@babel/core": "^7.25.2"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/community-cli-plugin",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Core CLI commands for React Native",
"keywords": [
"react-native",
@@ -22,7 +22,7 @@
"dist"
],
"dependencies": {
"@react-native/dev-middleware": "0.82.1",
"@react-native/dev-middleware": "0.82.0-main",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"metro": "^0.83.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/core-cli-utils",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "React Native CLI library for Frameworks to build on",
"license": "MIT",
"main": "./src/index.flow.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-frontend",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Debugger frontend for React Native based on Chrome DevTools",
"keywords": [
"react-native",
@@ -1,86 +1,71 @@
#!/usr/bin/env dotslash
// @generated SignedSource<<ea146009f0eb66caf2e1e8c6ad9a664b>>
// @generated SignedSource<<134c50a92ea8bbff7e42738b3e38c148>>
{
"name": "React Native DevTools",
"platforms": {
"linux-aarch64": {
"size": 116060647,
"size": 116052435,
"hash": "sha256",
"digest": "4352f1c9848ca919101ec628bd08b87a72a828d1ab55fa43a02098329fa452fa",
"digest": "957719cc5fc97f7a8841b3d2a7e1f8d625ab47b9031814ed11e0576b53552555",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-linux-aarch64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQM24LW0nPZRk0ypuIG9prz_72YjBJNcVlGSIEpO4zdlLXgw4dFNodH7MKg9eKNTnx7wrVDDBNACrnEPt_OfXOjZyZsV9Oaqu0-vNFRdlEyis4YqmpqGLtz3LvD-9R6fzcWxJI9zrhdPvOvlXP-3Syt1UNITaxXDVqIwAAYpCaAh0oLpupAFCc2yvYw"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOj5i7H4UTSZnrzYlWsTuSz6NHYS2de67x1ZurivOvqQdO7dsCf5R7C06hj7a2PydZR1HOmVEoGsuswoiGRg80pmS2AhhCds1lkchqG5puV5Bx2IY1rUosYTsZceD2AXgR7ptTD6NqgEGVG7O2KFpruI08RIQZUm60Kdn8LBeGfN3JddCIdsVQEsOk"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-arm64/React Native DevTools"
},
"linux-x86_64": {
"size": 115930333,
"size": 115924513,
"hash": "sha256",
"digest": "11c7b07942928a6301b07fbf2bc77ce1229b2a52891f23541cdd9858b5250e64",
"digest": "d8fe8e8df471e486697d5a42c7e77e7260ad3c44b10830f28529dca9f290535a",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-linux-x86_64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQNDwm7HZRhtNxHqMr1FfSb0afHFGrn1OHxH0gOiggrLrht9QRUgJ3GG5jj7huhQzMRogE-LCMsnxh1ioOZks-YYX4KRt6Kj1-whdWsGFc7lBhPOpk1ssbYFGN1NNyuyFRmH-3nCY3lBC4AmbCUkbDTUeCi9DidCtJeyc73CZJEu7M62rIzxR2yV"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQO_hyY-qUuuZXCew5qzp-tMfPL8fLLTUr5h4TLRbynsM3CmTlSILlmDcWP_xKAi5BJZSb6sOhATNKtRxn4pduIVkniIcL_6m1mGbt-1Qy8iKt0aUmANj5Nv8Wpryw6XL5OKYqtxHIsBg6YiZHW9JXYRCBk6oGCl1LGbhUZp2LGIFXAsOJy_DRcV"
}
],
"format": "tar.gz",
"path": "React Native DevTools-linux-x64/React Native DevTools"
},
"macos-aarch64": {
"size": 110891041,
"size": 110899100,
"hash": "sha256",
"digest": "3cbe8b1b3d17e433347f1601435bb9a6cb758528a5c176a66fc52d9977223175",
"digest": "fe4dd8fa12bcb5a82e9843c6d80a9199d7b144487bde3d05e62cb4492d050f49",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-macos-aarch64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOmC2cqqSv4OrSJKJroYVg_NE8OE4O73AXqY7wXiYqiWQVkDt0Xnyw3ZeUpQT_Qb0-OoT5F8REKoFrB6eqwat8Ovkyina30peYTTwNUzmwnnGQEg7J0fOHNxLF4dkmU1FagXtsoWgex4dKgsK_VpcMsHj3Vp7diomkYvWBVTf_gPVEseYSN9oKq92qa"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOFvf5d4K1OypXm39lo851JiwM_hB2yfmdcFhZxgP6rN9jYNH0kg97ZF8HDc6DMYIBxVojrm7jlFgpk4Inc6AzXF6z5ypQfZwgM54F8wLaZqYY9Yk46nnQlQefjwGqrXKsniE_S9S2nqFQDTmQUbGGQIuM_bQjGievQsxXLrUadSGAcMu-MEB79a64Z"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"macos-x86_64": {
"size": 117766158,
"size": 117756587,
"hash": "sha256",
"digest": "6fb79bc2ba3008401b4c9c128248657b95b98581ccde60f8fadb622163779775",
"digest": "3fe8a73843c3f0e1b72ffff0d069f9f1064f845be6fd44380d55aa1ab87220ac",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-macos-x86_64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQMMtGn-YGdfLfTVWC8zbQkQx65Asq6iArKt1t__cjZ8UY_s6-sX5XBHr8k1SaexAO21dFZENQVZ1jW_wn_gJ9ENvosQDG1KfWMViKsHli0xRzZ1HVsgPIj_KVXe907QZwwtJf2XhgH0HT8dfH-AQdDcd0_TB5DFUwOsHzhH0nBrHet7YFkbJtPTaA"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQNzRlsBElUT0wqSwTvxhvwPnuYpfI8Aka8Z4Wlmkmw_0pIwU0iEIh16wwH3OZTAMJ4_pM8YpyBl51FQXR5bai58MVtI_cI7aRxTfF63HKvk0iU0IxV06etgiaYiEmcyneLTb7UdYVdaZiwx7x_a0oaZU8FiuBlhg_YRzE6tM8oTD1hQf0T-a17USg"
}
],
"format": "tar.gz",
"path": "React Native DevTools.app/Contents/MacOS/React Native DevTools"
},
"windows-x86_64": {
"size": 125527537,
"size": 125513328,
"hash": "sha256",
"digest": "579a5b0944c51c3b1b541ad5af66c1ffedf93cae2a891ecdf88cb7219fd9b096",
"digest": "2477ee80171fc9f1c1f0b57418502bc103c6b40138f97f74d0b6470bdfee634c",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-windows-x86_64.tar.gz"
},
{
"type": "http",
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQOQ3E8lBXqdVHbDPyVb5AOQMrDWjFrFV8fnLLBsygQvLWdpu6ixyG9PgWdwpi5jM-XcDdCHkhBdhaq-5dwT_tgRWKCAMsEBoAIUk0Xg77mGyHG2VF7bNfQ2qFBMuObrsTmrKy1nJ-UFDDm29pJD4GkFQW5NesiBwndJj8t3B8Ur8cczh_XR8rF5"
"url": "https://scontent.xx.fbcdn.net/mci_ab/uap/?ab_b=m&ab_page=react_native_devtools_binaries&ab_entry=AQMwDMTAKLhSOn54OBOfhm6F9HDvQN0kUXp7ekfFik2NdgGoL_eVBu9ZcB2LM8x3YNpk0KxCAJE75jDfNTvGD2CnmLLRNOPCkdQP3tko7TTNkTSA2uTSd-ov8butKl1w4RP7ZMOy-0tmjyUoJMQtE1DlN5_4FdCo9DsHmQ7aB3wq_nz90nH0V_iS"
}
],
"format": "tar.gz",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-shell",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Experimental debugger shell for React Native for use with @react-native/debugger-frontend",
"keywords": [
"react-native",
@@ -1,13 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
export default {
revision: 'dev',
};
@@ -1,19 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* %s
* @flow strict-local
* @format
*/
'use strict';
module.exports = {
default: {
revision: %s,
},
__esModule: true,
};
@@ -64,8 +64,6 @@ function handleLaunchArgs(argv: string[]) {
// Icon for Linux
icon: path.join(__dirname, 'resources', 'icon.png'),
});
// Auto-hide the Windows/Linux menu bar
frontendWindow.setMenuBarVisibility(false);
}
// Open links in the default browser instead of in new Electron windows.
@@ -8,18 +8,9 @@
* @format
*/
import buildInfo from './BuildInfo';
// $FlowFixMe[untyped-import] Flow doesn't infer JSON types
const pkg = require('../../package.json');
const util = require('util');
// $FlowFixMe[unclear-type] We have no Flow types for the Electron API.
const {app} = require('electron') as any;
// Set the app name and version early - these are used in --version as well as
// in the User-Agent string.
app.setName(pkg.name);
app.setVersion(pkg.version + '-' + buildInfo.revision);
const util = require('util');
// Handle global command line arguments which don't require a window
// or the single instance lock to be held.
@@ -152,7 +152,11 @@ function getShellBinaryAndArgs(
): [string, Array<string>] {
switch (flavor) {
case 'prebuilt':
return [require('fb-dotslash'), [DEVTOOLS_BINARY_DOTSLASH_FILE]];
return [
// $FlowIssue[cannot-resolve-module] fb-dotslash includes Flow types but Flow does not pick them up
require('fb-dotslash'),
[DEVTOOLS_BINARY_DOTSLASH_FILE],
];
case 'dev':
return [
// NOTE: Internally at Meta, this is aliased to a workspace that is
@@ -44,11 +44,11 @@ async function spawnAndGetStderr(
async function prepareDebuggerShellFromDotSlashFile(
filePath: string,
): Promise<DebuggerShellPreparationResult> {
const {code, stderr} = await spawnAndGetStderr(require('fb-dotslash'), [
'--',
'fetch',
filePath,
]);
const {code, stderr} = await spawnAndGetStderr(
// $FlowIssue[cannot-resolve-module] fb-dotslash includes Flow types but Flow does not pick them up
require('fb-dotslash'),
['--', 'fetch', filePath],
);
if (code === 0) {
return {code: 'success'};
}
-10
View File
@@ -88,16 +88,6 @@ WebSocket handler for registering device connections.
WebSocket handler that proxies CDP messages to/from the corresponding device.
## Experimental features
React Native frameworks may pass an `unstable_experiments` option to `createDevMiddleware` to configure experimental features. Note that these features might not work correctly, and they may change or be removed in the future without notice. Some of the experiment flags available are documented below.
### `unstable_experiments.enableStandaloneFuseboxShell`
When `true`, the debugger frontend will launch in a standalone app shell (provided by the `@react-native/debugger-shell` package) rather than in a browser window. The standalone shell provides an improved experience and will become the default in a future version of React Native.
The shell is powered by a separate binary that is downloaded and cached in the background (immediately after the call to `createDevMiddleware`). If there is a problem downloading or invoking this binary for the first time, the debugger frontend will revert to launching in a browser window until the next time `createDevMiddleware` is called (typically, on the next dev server start).
## Contributing
Changes to this package can be made locally and tested against the `rn-tester` app, per the [Contributing guide](https://reactnative.dev/contributing/overview#contributing-code). During development, this package is automatically run from source with no build step.
+3 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/dev-middleware",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Dev server middleware for React Native",
"keywords": [
"react-native",
@@ -23,8 +23,7 @@
],
"dependencies": {
"@isaacs/ttlcache": "^1.4.1",
"@react-native/debugger-frontend": "0.82.1",
"@react-native/debugger-shell": "0.82.1",
"@react-native/debugger-frontend": "0.82.0-main",
"chrome-launcher": "^0.15.2",
"chromium-edge-launcher": "^0.2.0",
"connect": "^3.6.5",
@@ -39,7 +38,7 @@
"node": ">= 20.19.4"
},
"devDependencies": {
"@react-native/debugger-shell": "0.82.1",
"@react-native/debugger-shell": "0.82.0-main",
"selfsigned": "^2.4.1",
"undici": "^5.29.0",
"wait-for-expect": "^3.0.2"
@@ -28,9 +28,6 @@ describe('enableStandaloneFuseboxShell experiment', () => {
unstable_showFuseboxShell: () => {
throw new Error('Not implemented');
},
unstable_prepareFuseboxShell: async () => {
return {code: 'not_implemented'};
},
};
const serverRef = withServerForEachTest({
logger: undefined,
@@ -130,7 +127,5 @@ describe('enableStandaloneFuseboxShell experiment', () => {
device.close();
}
});
// TODO(moti): Add tests around unstable_prepareFuseboxShell
});
});
@@ -92,7 +92,6 @@ export default function createDevMiddleware({
const eventReporter = createWrappedEventReporter(
unstable_eventReporter,
logger,
experiments,
);
const inspectorProxy = new InspectorProxy(
@@ -153,7 +152,6 @@ function getExperiments(config: ExperimentsConfig): Experiments {
function createWrappedEventReporter(
reporter: ?EventReporter,
logger: ?Logger,
experiments: Experiments,
): EventReporter {
return {
logEvent(event: ReportableEvent) {
@@ -168,11 +166,8 @@ function createWrappedEventReporter(
logger?.info(
'\u001B[1m\u001B[7m💡 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' +
(experiments.enableStandaloneFuseboxShell
? ''
: ' (requires Google Chrome or Microsoft Edge)') +
'.\u001B[27m',
'the terminal to open (requires Google Chrome or Microsoft Edge).' +
'\u001B[27m',
);
break;
case 'fusebox_shell_preparation_attempt':
@@ -20,5 +20,3 @@ export type {
CustomMessageHandlerConnection,
CreateCustomMessageHandlerFn,
} from './inspector-proxy/CustomMessageHandler';
export {default as unstable_DefaultBrowserLauncher} from './utils/DefaultBrowserLauncher';
@@ -46,10 +46,7 @@ export interface BrowserLauncher {
* the host of dev-middleware. Implementations are responsible for rewriting
* this as necessary where the server is remote.
*/
+unstable_showFuseboxShell?: (
url: string,
windowKey: string,
) => Promise<void>;
unstable_showFuseboxShell?: (url: string, windowKey: string) => Promise<void>;
/**
* Attempt to prepare the debugger shell for use and returns a coded result
@@ -62,5 +59,5 @@ export interface BrowserLauncher {
* SHOULD NOT return a rejecting promise in any case, and instead SHOULD report
* errors via the returned result object.
*/
+unstable_prepareFuseboxShell?: () => Promise<DebuggerShellPreparationResult>;
unstable_prepareFuseboxShell?: () => Promise<DebuggerShellPreparationResult>;
}
@@ -26,7 +26,9 @@ export type Experiments = $ReadOnly<{
/**
* Launch the Fusebox frontend in a standalone shell instead of a browser.
* When this is enabled, we will use the optional unstable_showFuseboxShell
* method on the BrowserLauncher, or throw an error if the method is missing.
* method on the framework-provided BrowserLauncher, or throw an error if the
* method is missing. Note that the default BrowserLauncher does *not*
* implement unstable_showFuseboxShell.
*/
enableStandaloneFuseboxShell: boolean,
}>;
@@ -8,12 +8,6 @@
* @format
*/
import type {DebuggerShellPreparationResult} from '../';
const {
unstable_prepareDebuggerShell,
unstable_spawnDebuggerShellWithArgs,
} = require('@react-native/debugger-shell');
const {spawn} = require('child_process');
const ChromeLauncher = require('chrome-launcher');
const {Launcher: EdgeLauncher} = require('chromium-edge-launcher');
@@ -68,25 +62,6 @@ const DefaultBrowserLauncher = {
});
});
},
async unstable_showFuseboxShell(
url: string,
windowKey: string,
): Promise<void> {
return await unstable_spawnDebuggerShellWithArgs(
['--frontendUrl=' + url, '--windowKey=' + windowKey],
{
mode: 'detached',
flavor: process.env.RNDT_DEV === '1' ? 'dev' : 'prebuilt',
},
);
},
async unstable_prepareFuseboxShell(): Promise<DebuggerShellPreparationResult> {
return await unstable_prepareDebuggerShell(
process.env.RNDT_DEV === '1' ? 'dev' : 'prebuilt',
);
},
};
export default DefaultBrowserLauncher;
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-config",
"version": "0.82.1",
"version": "0.82.0-main",
"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.82.1",
"@react-native/eslint-plugin": "0.82.0-main",
"@typescript-eslint/eslint-plugin": "^8.36.0",
"@typescript-eslint/parser": "^8.36.0",
"eslint-config-prettier": "^8.5.0",
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "ESLint rules for @react-native/eslint-config",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin-specs",
"version": "0.82.1",
"version": "0.82.0-main",
"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.82.1",
"@react-native/codegen": "0.82.0-main",
"make-dir": "^2.1.0",
"pirates": "^4.0.1",
"source-map-support": "0.5.0"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/gradle-plugin",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Gradle Plugin for React Native",
"license": "MIT",
"repository": {
@@ -28,7 +28,6 @@ import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings
import com.facebook.react.utils.JdkConfiguratorUtils.configureJavaToolChains
import com.facebook.react.utils.JsonUtils
import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk
import com.facebook.react.utils.ProjectUtils.isHermesV1Enabled
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
import com.facebook.react.utils.findPackageJsonFile
import java.io.File
@@ -55,10 +54,6 @@ class ReactPlugin : Plugin<Project> {
project,
)
if (project.rootProject.isHermesV1Enabled) {
rootExtension.hermesV1Enabled.set(true)
}
// App Only Configuration
project.pluginManager.withPlugin("com.android.application") {
// We wire the root extension with the values coming from the app (either user populated or
@@ -71,12 +66,10 @@ class ReactPlugin : Plugin<Project> {
project.afterEvaluate {
val reactNativeDir = extension.reactNativeDir.get().asFile
val propertiesFile = File(reactNativeDir, "ReactAndroid/gradle.properties")
val hermesVersionPropertiesFile =
File(reactNativeDir, "sdks/hermes-engine/version.properties")
val versionAndGroupStrings =
readVersionAndGroupStrings(propertiesFile, hermesVersionPropertiesFile)
val hermesV1Enabled = rootExtension.hermesV1Enabled.get()
configureDependencies(project, versionAndGroupStrings, hermesV1Enabled)
val versionAndGroupStrings = readVersionAndGroupStrings(propertiesFile)
val versionString = versionAndGroupStrings.first
val groupString = versionAndGroupStrings.second
configureDependencies(project, versionString, groupString)
configureRepositories(project)
}
@@ -11,7 +11,6 @@ import javax.inject.Inject
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
/**
* A private extension we set on the rootProject to make easier to share values at execution time
@@ -58,6 +57,4 @@ abstract class PrivateReactExtension @Inject constructor(project: Project) {
val codegenDir: DirectoryProperty =
objects.directoryProperty().convention(root.dir("node_modules/@react-native/codegen"))
val hermesV1Enabled: Property<Boolean> = objects.property(Boolean::class.java).convention(false)
}
@@ -34,15 +34,15 @@ abstract class BundleHermesCTask : DefaultTask() {
@get:InputFiles
val sources: ConfigurableFileTree =
project.fileTree(root) { fileTree ->
fileTree.include("**/*.js")
fileTree.include("**/*.jsx")
fileTree.include("**/*.ts")
fileTree.include("**/*.tsx")
fileTree.exclude("**/android/**/*")
fileTree.exclude("**/ios/**/*")
fileTree.exclude("**/build/**/*")
fileTree.exclude("**/node_modules/**/*")
project.fileTree(root) {
it.include("**/*.js")
it.include("**/*.jsx")
it.include("**/*.ts")
it.include("**/*.tsx")
it.exclude("**/android/**/*")
it.exclude("**/ios/**/*")
it.exclude("**/build/**/*")
it.exclude("**/node_modules/**/*")
}
@get:Input abstract val nodeExecutableAndArgs: ListProperty<String>
@@ -94,12 +94,7 @@ abstract class BundleHermesCTask : DefaultTask() {
runCommand(bundleCommand)
if (hermesEnabled.get()) {
val hermesV1Enabled =
if (project.rootProject.hasProperty("hermesV1Enabled"))
project.rootProject.findProperty("hermesV1Enabled") == "true"
else false
val detectedHermesCommand =
detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get(), hermesV1Enabled)
val detectedHermesCommand = detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get())
val bytecodeFile = File("${bundleFile}.hbc")
val outputSourceMap = resolveOutputSourceMap(bundleAssetFilename)
val compilerSourceMap = resolveCompilerSourceMap(bundleAssetFilename)
@@ -42,35 +42,35 @@ abstract class PreparePrefabHeadersTask : DefaultTask() {
input.get().forEach { (libraryName, pathToPrefixCouples) ->
val outputFolder: RegularFile = outputDir.file(libraryName).get()
pathToPrefixCouples.forEach { (headerPath, headerPrefix) ->
fs.copy { copySpec ->
copySpec.from(headerPath)
copySpec.include("**/*.h")
copySpec.exclude("**/*.cpp")
copySpec.exclude("**/*.txt")
fs.copy {
it.from(headerPath)
it.include("**/*.h")
it.exclude("**/*.cpp")
it.exclude("**/*.txt")
// We don't want to copy all the boost headers as they are 250Mb+
copySpec.include("boost/config.hpp")
copySpec.include("boost/config/**/*.hpp")
copySpec.include("boost/core/*.hpp")
copySpec.include("boost/detail/workaround.hpp")
copySpec.include("boost/operators.hpp")
copySpec.include("boost/preprocessor/**/*.hpp")
it.include("boost/config.hpp")
it.include("boost/config/**/*.hpp")
it.include("boost/core/*.hpp")
it.include("boost/detail/workaround.hpp")
it.include("boost/operators.hpp")
it.include("boost/preprocessor/**/*.hpp")
// Headers needed for exposing rrc_text and rrc_textinput
copySpec.include("boost/container_hash/**/*.hpp")
copySpec.include("boost/detail/**/*.hpp")
copySpec.include("boost/intrusive/**/*.hpp")
copySpec.include("boost/iterator/**/*.hpp")
copySpec.include("boost/move/**/*.hpp")
copySpec.include("boost/mpl/**/*.hpp")
copySpec.include("boost/mp11/**/*.hpp")
copySpec.include("boost/describe/**/*.hpp")
copySpec.include("boost/type_traits/**/*.hpp")
copySpec.include("boost/utility/**/*.hpp")
copySpec.include("boost/assert.hpp")
copySpec.include("boost/static_assert.hpp")
copySpec.include("boost/cstdint.hpp")
copySpec.include("boost/utility.hpp")
copySpec.include("boost/version.hpp")
copySpec.into(File(outputFolder.asFile, headerPrefix))
it.include("boost/container_hash/**/*.hpp")
it.include("boost/detail/**/*.hpp")
it.include("boost/intrusive/**/*.hpp")
it.include("boost/iterator/**/*.hpp")
it.include("boost/move/**/*.hpp")
it.include("boost/mpl/**/*.hpp")
it.include("boost/mp11/**/*.hpp")
it.include("boost/describe/**/*.hpp")
it.include("boost/type_traits/**/*.hpp")
it.include("boost/utility/**/*.hpp")
it.include("boost/assert.hpp")
it.include("boost/static_assert.hpp")
it.include("boost/cstdint.hpp")
it.include("boost/utility.hpp")
it.include("boost/version.hpp")
it.into(File(outputFolder.asFile, headerPrefix))
}
}
}
@@ -7,15 +7,12 @@
package com.facebook.react.utils
import com.facebook.react.utils.PropertyUtils.DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.DEFAULT_INTERNAL_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.EXCLUSIVE_ENTEPRISE_REPOSITORY
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY_DEFAULT
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_V1_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.INTERNAL_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_USE_HERMES_NIGHTLY
import com.facebook.react.utils.PropertyUtils.INTERNAL_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.SCOPED_EXCLUSIVE_ENTEPRISE_REPOSITORY
@@ -28,14 +25,6 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository
internal object DependencyUtils {
internal data class Coordinates(
val versionString: String,
val hermesVersionString: String,
val hermesV1VersionString: String,
val reactGroupString: String = DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP,
val hermesGroupString: String = DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP,
)
/**
* This method takes care of configuring the repositories{} block for both the app and all the 3rd
* party libraries which are auto-linked.
@@ -106,20 +95,14 @@ internal object DependencyUtils {
* This method takes care of configuring the resolution strategy for both the app and all the 3rd
* party libraries which are auto-linked. Specifically it takes care of:
* - Forcing the react-android/hermes-android version to the one specified in the package.json
* - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`
* - Selecting between the classic Hermes and Hermes V1
* - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`.
*/
fun configureDependencies(
project: Project,
coordinates: Coordinates,
hermesV1Enabled: Boolean = false,
versionString: String,
groupString: String = DEFAULT_INTERNAL_PUBLISHING_GROUP,
) {
if (
coordinates.versionString.isBlank() ||
(!hermesV1Enabled && coordinates.hermesVersionString.isBlank()) ||
(hermesV1Enabled && coordinates.hermesV1VersionString.isBlank())
)
return
if (versionString.isBlank()) return
project.rootProject.allprojects { eachProject ->
eachProject.configurations.all { configuration ->
// Here we set a dependencySubstitution for both react-native and hermes-engine as those
@@ -127,83 +110,61 @@ internal object DependencyUtils {
// This allows users to import libraries that are still using
// implementation("com.facebook.react:react-native:+") and resolve the right dependency.
configuration.resolutionStrategy.dependencySubstitution {
getDependencySubstitutions(coordinates, hermesV1Enabled).forEach { (module, dest, reason)
->
getDependencySubstitutions(versionString, groupString).forEach { (module, dest, reason) ->
it.substitute(it.module(module)).using(it.module(dest)).because(reason)
}
}
configuration.resolutionStrategy.force(
"${coordinates.reactGroupString}:react-android:${coordinates.versionString}",
"${groupString}:react-android:${versionString}",
)
if (!(eachProject.findProperty(INTERNAL_USE_HERMES_NIGHTLY) as? String).toBoolean()) {
// Contributors only: The hermes-engine version is forced only if the user has
// not opted into using nightlies for local development.
configuration.resolutionStrategy.force(
// TODO: T237406039 update coordinates
if (hermesV1Enabled)
"${coordinates.hermesGroupString}:hermes-android:${coordinates.hermesV1VersionString}"
else
"${coordinates.reactGroupString}:hermes-android:${coordinates.hermesVersionString}"
)
configuration.resolutionStrategy.force("${groupString}:hermes-android:${versionString}")
}
}
}
}
internal fun getDependencySubstitutions(
coordinates: Coordinates,
hermesV1Enabled: Boolean = false,
versionString: String,
groupString: String = DEFAULT_INTERNAL_PUBLISHING_GROUP,
): List<Triple<String, String, String>> {
// TODO: T231755027 update coordinates and versioning
val dependencySubstitution = mutableListOf<Triple<String, String, String>>()
// TODO: T237406039 update coordinates
val hermesVersionString =
if (hermesV1Enabled)
"${coordinates.hermesGroupString}:hermes-android:${coordinates.hermesV1VersionString}"
else "${coordinates.reactGroupString}:hermes-android:${coordinates.hermesVersionString}"
dependencySubstitution.add(
Triple(
"com.facebook.react:react-native",
"${coordinates.reactGroupString}:react-android:${coordinates.versionString}",
"${groupString}:react-android:${versionString}",
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210.",
)
)
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-engine",
hermesVersionString,
"${groupString}:hermes-android:${versionString}",
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.",
)
)
if (coordinates.reactGroupString != DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP) {
if (groupString != DEFAULT_INTERNAL_PUBLISHING_GROUP) {
dependencySubstitution.add(
Triple(
"com.facebook.react:react-android",
"${coordinates.reactGroupString}:react-android:${coordinates.versionString}",
"${groupString}:react-android:${versionString}",
"The react-android dependency was modified to use the correct Maven group.",
)
)
// TODO: T237406039 update coordinates
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-android",
hermesVersionString,
"${groupString}:hermes-android:${versionString}",
"The hermes-android dependency was modified to use the correct Maven group.",
)
)
} else if (hermesV1Enabled) {
dependencySubstitution.add(
Triple(
"com.facebook.react:hermes-android",
hermesVersionString,
"The hermes-android dependency was modified to use Hermes V1.",
)
)
}
return dependencySubstitution
}
fun readVersionAndGroupStrings(propertiesFile: File, hermesVersionFile: File): Coordinates {
fun readVersionAndGroupStrings(propertiesFile: File): Pair<String, String> {
val reactAndroidProperties = Properties()
propertiesFile.inputStream().use { reactAndroidProperties.load(it) }
val versionStringFromFile = (reactAndroidProperties[INTERNAL_VERSION_NAME] as? String).orEmpty()
@@ -215,27 +176,10 @@ internal object DependencyUtils {
versionStringFromFile
}
// Returns Maven group for repos using different group for Maven artifacts
val reactGroupString =
reactAndroidProperties[INTERNAL_REACT_PUBLISHING_GROUP] as? String
?: DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP
val hermesGroupString =
reactAndroidProperties[INTERNAL_HERMES_PUBLISHING_GROUP] as? String
?: DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP
// TODO: T237406039 read both versions from the same file
val hermesVersionProperties = Properties()
hermesVersionFile.inputStream().use { hermesVersionProperties.load(it) }
val hermesVersion = versionString
val hermesV1Version =
(hermesVersionProperties[INTERNAL_HERMES_V1_VERSION_NAME] as? String).orEmpty()
return Coordinates(
versionString,
hermesVersion,
hermesV1Version,
reactGroupString,
hermesGroupString,
)
val groupString =
reactAndroidProperties[INTERNAL_PUBLISHING_GROUP] as? String
?: DEFAULT_INTERNAL_PUBLISHING_GROUP
return Pair(versionString, groupString)
}
fun Project.mavenRepoFromUrl(
@@ -122,16 +122,11 @@ private fun detectCliFile(reactNativeRoot: File, preconfiguredCliFile: File?): F
* used if the user is building Hermes from source.
* 3. The file located in `node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc` where `%OS-BIN%`
* is substituted with the correct OS arch. This will be used if the user is using a precompiled
* hermes-engine package. Or, if the user has opted in to use Hermes V1, the used file will be
* located in `node_modules/hermes-compiler/%OS-BIN%/hermesc` where `%OS-BIN%` is substituted
* with the correct OS arch.
* hermes-engine package.
* 4. Fails otherwise
*/
internal fun detectOSAwareHermesCommand(
projectRoot: File,
hermesCommand: String,
hermesV1Enabled: Boolean = false,
): String { // 1. If the project specifies a Hermes command, don't second guess it.
internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String): String {
// 1. If the project specifies a Hermes command, don't second guess it.
if (hermesCommand.isNotBlank()) {
val osSpecificHermesCommand =
if ("%OS-BIN%" in hermesCommand) {
@@ -151,13 +146,9 @@ internal fun detectOSAwareHermesCommand(
return builtHermesc.cliPath(projectRoot)
}
// 3. If Hermes V1 is enabled, use hermes-compiler from npm, otherwise, if the
// react-native contains a pre-built hermesc, use it.
// TODO: T237406039 use hermes-compiler from npm for both
val hermesCPath = if (hermesV1Enabled) HERMES_COMPILER_NPM_DIR else HERMESC_IN_REACT_NATIVE_DIR
// 3. If the react-native contains a pre-built hermesc, use it.
val prebuiltHermesPath =
hermesCPath
.plus(getHermesCBin())
HERMESC_IN_REACT_NATIVE_DIR.plus(getHermesCBin())
.replace("%OS-BIN%", getHermesOSBin())
// Execution on Windows fails with / as separator
.replace('/', File.separatorChar)
@@ -242,7 +233,6 @@ internal fun readPackageJsonFile(
return packageJson?.let { JsonUtils.fromPackageJson(it) }
}
private const val HERMES_COMPILER_NPM_DIR = "node_modules/hermes-compiler/hermesc/%OS-BIN%/"
private const val HERMESC_IN_REACT_NATIVE_DIR = "node_modules/react-native/sdks/hermesc/%OS-BIN%/"
private const val HERMESC_BUILT_FROM_SOURCE_DIR =
"node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/bin/"
@@ -13,17 +13,14 @@ import com.facebook.react.utils.KotlinStdlibCompatUtils.lowercaseCompat
import com.facebook.react.utils.KotlinStdlibCompatUtils.toBooleanStrictOrNullCompat
import com.facebook.react.utils.PropertyUtils.EDGE_TO_EDGE_ENABLED
import com.facebook.react.utils.PropertyUtils.HERMES_ENABLED
import com.facebook.react.utils.PropertyUtils.HERMES_V1_ENABLED
import com.facebook.react.utils.PropertyUtils.REACT_NATIVE_ARCHITECTURES
import com.facebook.react.utils.PropertyUtils.SCOPED_EDGE_TO_EDGE_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_HERMES_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_HERMES_V1_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_REACT_NATIVE_ARCHITECTURES
import com.facebook.react.utils.PropertyUtils.SCOPED_USE_THIRD_PARTY_JSC
import com.facebook.react.utils.PropertyUtils.USE_THIRD_PARTY_JSC
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.jetbrains.kotlin.gradle.plugin.extraProperties
internal object ProjectUtils {
@@ -71,17 +68,6 @@ internal object ProjectUtils {
(project.hasProperty(SCOPED_USE_THIRD_PARTY_JSC) &&
project.property(SCOPED_USE_THIRD_PARTY_JSC).toString().toBoolean())
internal val Project.isHermesV1Enabled: Boolean
get() =
(project.hasProperty(HERMES_V1_ENABLED) &&
project.property(HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.hasProperty(SCOPED_HERMES_V1_ENABLED) &&
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.extraProperties.has(HERMES_V1_ENABLED) &&
project.extraProperties.get(HERMES_V1_ENABLED).toString().toBoolean()) ||
(project.extraProperties.has(SCOPED_HERMES_V1_ENABLED) &&
project.extraProperties.get(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean {
val parsedPackageJson = readPackageJsonFile(this, rootProperty)
return needsCodegenFromPackageJson(parsedPackageJson)
@@ -18,10 +18,6 @@ object PropertyUtils {
const val HERMES_ENABLED = "hermesEnabled"
const val SCOPED_HERMES_ENABLED = "react.hermesEnabled"
/** Public property that toggles Hermes V1 */
const val HERMES_V1_ENABLED = "hermesV1Enabled"
const val SCOPED_HERMES_V1_ENABLED = "react.hermesV1Enabled"
/** Public property that toggles edge-to-edge */
const val EDGE_TO_EDGE_ENABLED = "edgeToEdgeEnabled"
const val SCOPED_EDGE_TO_EDGE_ENABLED = "react.edgeToEdgeEnabled"
@@ -72,17 +68,9 @@ object PropertyUtils {
const val INTERNAL_USE_HERMES_NIGHTLY = "react.internal.useHermesNightly"
/** Internal property used to override the publishing group for the React Native artifacts. */
const val INTERNAL_REACT_PUBLISHING_GROUP = "react.internal.publishingGroup"
const val INTERNAL_HERMES_PUBLISHING_GROUP = "react.internal.hermesPublishingGroup"
const val DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP = "com.facebook.react"
const val DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP = "com.facebook.hermes"
const val INTERNAL_PUBLISHING_GROUP = "react.internal.publishingGroup"
const val DEFAULT_INTERNAL_PUBLISHING_GROUP = "com.facebook.react"
/** Internal property used to control the version name of React Native */
const val INTERNAL_VERSION_NAME = "VERSION_NAME"
/**
* Internal property, shared with iOS, used to control the version name of Hermes Engine. This is
* stored in sdks/hermes-engine/version.properties
*/
const val INTERNAL_HERMES_V1_VERSION_NAME = "HERMES_V1_VERSION_NAME"
}
@@ -122,11 +122,11 @@ class PrepareGlogTaskTest {
val glogThirdPartyJniPath = tempFolder.newFolder("glogpath/jni")
val output = tempFolder.newFolder("output")
val task =
createTestTask<PrepareGlogTask> { task ->
task.glogPath.setFrom(glogpath)
task.glogThirdPartyJniPath.set(glogThirdPartyJniPath)
task.glogVersion.set("1.0.0")
task.outputDir.set(output)
createTestTask<PrepareGlogTask> {
it.glogPath.setFrom(glogpath)
it.glogThirdPartyJniPath.set(glogThirdPartyJniPath)
it.glogVersion.set("1.0.0")
it.outputDir.set(output)
}
File(glogpath, "glog-1.0.0/src/logging.h.in").apply {
parentFile.mkdirs()
@@ -275,160 +275,71 @@ class DependencyUtilsTest {
fun configureDependencies_withEmptyVersion_doesNothing() {
val project = createProject()
configureDependencies(project, DependencyUtils.Coordinates("", "", ""))
configureDependencies(project, "")
assertThat(project.configurations.first().resolutionStrategy.forcedModules.isEmpty()).isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesResolutionStrategy_withClassicHermes() {
fun configureDependencies_withVersionString_appliesResolutionStrategy() {
val project = createProject()
configureDependencies(project, DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"))
configureDependencies(project, "1.2.3")
val forcedModules = project.configurations.first().resolutionStrategy.forcedModules
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
assertThat(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
.isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesResolutionStrategy_withHermesV1() {
val project = createProject()
configureDependencies(
project,
DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"),
hermesV1Enabled = true,
)
val forcedModules = project.configurations.first().resolutionStrategy.forcedModules
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(forcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesOnAllProjects_withClassicHermes() {
fun configureDependencies_withVersionString_appliesOnAllProjects() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(appProject, DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"))
configureDependencies(appProject, "1.2.3")
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:4.5.6" })
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
.isTrue()
}
@Test
fun configureDependencies_withVersionString_appliesOnAllProjects_withHermesV1() {
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(
appProject,
DependencyUtils.Coordinates("1.2.3", "4.5.6", "7.8.9"),
hermesV1Enabled = true,
)
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
.isTrue()
}
@Test
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects_withClassicHermes() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(
appProject,
DependencyUtils.Coordinates(
"1.2.3",
"4.5.6",
"7.8.9",
"io.github.test",
"io.github.test.hermes",
),
)
configureDependencies(appProject, "1.2.3", "io.github.test")
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(appForcedModules.any { it.toString() == "io.github.test:hermes-android:4.5.6" })
assertThat(appForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:hermes-android:4.5.6" })
assertThat(libForcedModules.any { it.toString() == "io.github.test:hermes-android:1.2.3" })
.isTrue()
}
@Test
fun configureDependencies_withVersionStringAndGroupString_appliesOnAllProjects_withHermesV1() {
val rootProject = ProjectBuilder.builder().build()
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
appProject.plugins.apply("com.android.application")
libProject.plugins.apply("com.android.library")
configureDependencies(
appProject,
DependencyUtils.Coordinates(
"1.2.3",
"4.5.6",
"7.8.9",
"io.github.test",
"io.github.test.hermes",
),
hermesV1Enabled = true,
)
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
assertThat(appForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(
appForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:7.8.9" }
)
.isTrue()
assertThat(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
.isTrue()
assertThat(
libForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:7.8.9" }
)
.isTrue()
}
@Test
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withClassicHermes() {
val dependencySubstitutions =
getDependencySubstitutions(DependencyUtils.Coordinates("0.42.0", "0.42.0", "0.43.0"))
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly() {
val dependencySubstitutions = getDependencySubstitutions("0.42.0")
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("com.facebook.react:react-android:0.42.0")
@@ -447,41 +358,8 @@ class DependencyUtilsTest {
}
@Test
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withHermesV1() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates("0.42.0", "0.42.0", "0.43.0"),
hermesV1Enabled = true,
)
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("com.facebook.react:react-android:0.42.0")
.isEqualTo(dependencySubstitutions[0].second)
assertThat(
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[0].third)
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
assertThat("com.facebook.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[1].second)
assertThat(
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[1].third)
}
@Test
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withClassicHermes() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates(
"0.42.0",
"0.42.0",
"0.43.0",
"io.github.test",
"io.github.test.hermes",
)
)
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly() {
val dependencySubstitutions = getDependencySubstitutions("0.42.0", "io.github.test")
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[0].second)
@@ -505,44 +383,6 @@ class DependencyUtilsTest {
.isEqualTo(dependencySubstitutions[3].third)
}
@Test
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withHermesV1() {
val dependencySubstitutions =
getDependencySubstitutions(
DependencyUtils.Coordinates(
"0.42.0",
"0.42.0",
"0.43.0",
"io.github.test",
"io.github.test.hermes",
),
hermesV1Enabled = true,
)
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[0].second)
assertThat(
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[0].third)
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
assertThat("io.github.test.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[1].second)
assertThat(
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
)
.isEqualTo(dependencySubstitutions[1].third)
assertThat("com.facebook.react:react-android").isEqualTo(dependencySubstitutions[2].first)
assertThat("io.github.test:react-android:0.42.0").isEqualTo(dependencySubstitutions[2].second)
assertThat("The react-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[2].third)
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[3].first)
assertThat("io.github.test.hermes:hermes-android:0.43.0")
.isEqualTo(dependencySubstitutions[3].second)
assertThat("The hermes-android dependency was modified to use the correct Maven group.")
.isEqualTo(dependencySubstitutions[3].third)
}
@Test
fun readVersionString_withCorrectVersionString_returnsIt() {
val propertiesFile =
@@ -556,25 +396,9 @@ class DependencyUtilsTest {
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=1000.0.0
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
val versionString = readVersionAndGroupStrings(propertiesFile).first
assertThat(versionString).isEqualTo("1000.0.0")
assertThat(hermesVersionString).isEqualTo("1000.0.0")
assertThat(hermesV1VersionString).isEqualTo("1000.0.0")
}
@Test
@@ -584,33 +408,15 @@ class DependencyUtilsTest {
writeText(
"""
VERSION_NAME=0.0.0-20221101-2019-cfe811ab1
HERMES_VERSION_NAME=0.12.0-commitly-20221101-2019-cfe811ab1
HERMES_V1_VERSION_NAME=250829098.0.0-stable
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=250829098.0.0-stable
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
val versionString = readVersionAndGroupStrings(propertiesFile).first
assertThat(versionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
assertThat(hermesVersionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
assertThat(hermesV1VersionString).isEqualTo("250829098.0.0-stable")
}
@Test
@@ -625,23 +431,8 @@ class DependencyUtilsTest {
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
val versionString = readVersionAndGroupStrings(propertiesFile).first
assertThat(versionString).isEqualTo("")
assertThat(hermesVersionString).isEqualTo("")
assertThat(hermesV1VersionString).isEqualTo("")
}
@Test
@@ -657,24 +448,8 @@ class DependencyUtilsTest {
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val versionString = strings.versionString
val hermesVersionString = strings.hermesVersionString
val hermesV1VersionString = strings.hermesV1VersionString
val versionString = readVersionAndGroupStrings(propertiesFile).first
assertThat(versionString).isEqualTo("")
assertThat(hermesVersionString).isEqualTo("")
assertThat(hermesV1VersionString).isEqualTo("")
}
@Test
@@ -684,30 +459,15 @@ class DependencyUtilsTest {
writeText(
"""
react.internal.publishingGroup=io.github.test
react.internal.hermesPublishingGroup=io.github.test
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val groupString = readVersionAndGroupStrings(propertiesFile).second
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val reactGroupString = strings.reactGroupString
val hermesGroupString = strings.hermesGroupString
assertThat(reactGroupString).isEqualTo("io.github.test")
assertThat(hermesGroupString).isEqualTo("io.github.test")
assertThat(groupString).isEqualTo("io.github.test")
}
@Test
@@ -722,23 +482,9 @@ class DependencyUtilsTest {
)
}
val hermesVersionFile =
tempFolder.newFile("version.properties").apply {
writeText(
"""
HERMES_V1_VERSION_NAME=
ANOTHER_PROPERTY=true
"""
.trimIndent()
)
}
val groupString = readVersionAndGroupStrings(propertiesFile).second
val strings = readVersionAndGroupStrings(propertiesFile, hermesVersionFile)
val reactGroupString = strings.reactGroupString
val hermesGroupString = strings.hermesGroupString
assertThat(reactGroupString).isEqualTo("com.facebook.react")
assertThat(hermesGroupString).isEqualTo("com.facebook.hermes")
assertThat(groupString).isEqualTo("com.facebook.react")
}
@Test
@@ -162,16 +162,6 @@ class PathUtilsTest {
assertThat(detectOSAwareHermesCommand(tempFolder.root, "")).isEqualTo(expected.toString())
}
@Test
@WithOs(OS.MAC)
fun detectOSAwareHermesCommand_withHermesV1Enabled() {
tempFolder.newFolder("node_modules/hermes-compiler/hermesc/osx-bin/")
val expected = tempFolder.newFile("node_modules/hermes-compiler/hermesc/osx-bin/hermesc")
assertThat(detectOSAwareHermesCommand(tempFolder.root, "", hermesV1Enabled = true))
.isEqualTo(expected.toString())
}
@Test(expected = IllegalStateException::class)
@WithOs(OS.MAC)
fun detectOSAwareHermesCommand_failsIfNotFound() {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-config",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Metro configuration for React Native.",
"license": "MIT",
"repository": {
@@ -26,8 +26,8 @@
"dist"
],
"dependencies": {
"@react-native/js-polyfills": "0.82.1",
"@react-native/metro-babel-transformer": "0.82.1",
"@react-native/js-polyfills": "0.82.0-main",
"@react-native/metro-babel-transformer": "0.82.0-main",
"metro-config": "^0.83.1",
"metro-runtime": "^0.83.1"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/new-app-screen",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "NewAppScreen component for React Native",
"keywords": [
"react-native"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/normalize-colors",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Color normalization for React Native.",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/js-polyfills",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Polyfills for React Native.",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-preset",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Babel preset for React Native applications",
"repository": {
"type": "git",
@@ -66,7 +66,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.82.1",
"@react-native/babel-plugin-codegen": "0.82.0-main",
"babel-plugin-syntax-hermes-parser": "0.32.0",
"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.82.1",
"version": "0.82.0-main",
"description": "Babel transformer for React Native applications.",
"repository": {
"type": "git",
@@ -27,7 +27,7 @@
],
"dependencies": {
"@babel/core": "^7.25.2",
"@react-native/babel-preset": "0.82.1",
"@react-native/babel-preset": "0.82.0-main",
"hermes-parser": "0.32.0",
"nullthrows": "^1.1.1"
},
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Code generation tools for React Native",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/compatibility-check",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "Check a React Native app's boundary between JS and Native for incompatibilities",
"license": "MIT",
"repository": {
@@ -29,7 +29,7 @@
"dist"
],
"dependencies": {
"@react-native/codegen": "0.82.1"
"@react-native/codegen": "0.82.0-main"
},
"devDependencies": {
"flow-remove-types": "^2.237.2",
@@ -1,6 +1,6 @@
{
"name": "@react-native/popup-menu-android",
"version": "0.82.1",
"version": "0.82.0-main",
"description": "PopupMenu for the Android platform",
"main": "index.js",
"files": [
@@ -21,7 +21,7 @@
},
"license": "MIT",
"devDependencies": {
"@react-native/codegen": "0.82.1"
"@react-native/codegen": "0.82.0-main"
},
"peerDependencies": {
"@types/react": "^19.1.0",
@@ -10,7 +10,6 @@
import AnimatedImplementation from './AnimatedImplementation';
export type {CompositeAnimation} from './AnimatedImplementation';
export type {DecayAnimationConfig} from './animations/DecayAnimation';
export type {SpringAnimationConfig} from './animations/SpringAnimation';
export type {TimingAnimationConfig} from './animations/TimingAnimation';
@@ -873,6 +873,56 @@ describe('Animated', () => {
});
});
describe('Animated Interactions', () => {
let Animated; // eslint-disable-line no-shadow
let InteractionManager;
beforeEach(() => {
jest.mock('../../Interaction/InteractionManager');
Animated = require('../Animated').default;
InteractionManager =
require('../../Interaction/InteractionManager').default;
});
afterEach(() => {
jest.unmock('../../Interaction/InteractionManager');
});
it('registers an interaction by default', () => {
// $FlowFixMe[prop-missing]
InteractionManager.createInteractionHandle.mockReturnValue(777);
const value = new Animated.Value(0);
const callback = jest.fn();
Animated.timing(value, {
toValue: 100,
duration: 100,
useNativeDriver: false,
}).start(callback);
jest.runAllTimers();
expect(InteractionManager.createInteractionHandle).toBeCalled();
expect(InteractionManager.clearInteractionHandle).toBeCalledWith(777);
expect(callback).toBeCalledWith({finished: true});
});
it('does not register an interaction when specified', () => {
const value = new Animated.Value(0);
const callback = jest.fn();
Animated.timing(value, {
toValue: 100,
duration: 100,
isInteraction: false,
useNativeDriver: false,
}).start(callback);
jest.runAllTimers();
expect(InteractionManager.createInteractionHandle).not.toBeCalled();
expect(InteractionManager.clearInteractionHandle).not.toBeCalled();
expect(callback).toBeCalledWith({finished: true});
});
});
describe('Animated Tracking', () => {
it('should track values', () => {
const value1 = new Animated.Value(0);
@@ -17,7 +17,6 @@ type ValueListenerCallback = (state: {value: number, ...}) => mixed;
export type AnimatedNodeConfig = $ReadOnly<{
debugID?: string,
unstable_disableBatchingForNativeCreate?: boolean,
}>;
let _uniqueId = 1;
@@ -43,8 +42,6 @@ export default class AnimatedNode {
if (__DEV__) {
this.__debugID = config?.debugID;
}
this.__disableBatchingForNativeCreate =
config?.unstable_disableBatchingForNativeCreate;
}
__attach(): void {}
@@ -68,7 +65,6 @@ export default class AnimatedNode {
/* Methods and props used by native Animated impl */
__isNative: boolean = false;
__nativeTag: ?number = undefined;
__disableBatchingForNativeCreate: ?boolean = undefined;
__makeNative(platformConfig: ?PlatformConfig): void {
// Subclasses are expected to set `__isNative` to true before this.
@@ -146,9 +142,6 @@ export default class AnimatedNode {
if (this._platformConfig) {
config.platformConfig = this._platformConfig;
}
if (this.__disableBatchingForNativeCreate) {
config.disableBatchingForNativeCreate = true;
}
NativeAnimatedHelper.API.createAnimatedNode(nativeTag, config);
}
return nativeTag;
@@ -18,6 +18,7 @@ import type {AnimatedNodeConfig} from './AnimatedNode';
import type AnimatedTracking from './AnimatedTracking';
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
import InteractionManager from '../../Interaction/InteractionManager';
import AnimatedInterpolation from './AnimatedInterpolation';
import AnimatedWithChildren from './AnimatedWithChildren';
@@ -311,6 +312,10 @@ export default class AnimatedValue extends AnimatedWithChildren {
* See https://reactnative.dev/docs/animatedvalue#animate
*/
animate(animation: Animation, callback: ?EndCallback): void {
let handle = null;
if (animation.__isInteraction) {
handle = InteractionManager.createInteractionHandle();
}
const previousAnimation = this._animation;
this._animation && this._animation.stop();
this._animation = animation;
@@ -323,6 +328,9 @@ export default class AnimatedValue extends AnimatedWithChildren {
},
result => {
this._animation = null;
if (handle !== null) {
InteractionManager.clearInteractionHandle(handle);
}
callback && callback(result);
},
previousAnimation,
@@ -68,8 +68,7 @@ __attribute__((deprecated(
/// The window object, used to render the UViewControllers
@property (nonatomic, strong, nonnull) UIWindow *window;
@property (nonatomic, nullable) RCTBridge *bridge
__attribute__((deprecated("The bridge is deprecated and will be removed when removing the legacy architecture.")));
@property (nonatomic, nullable) RCTBridge *bridge;
@property (nonatomic, strong, nullable) NSString *moduleName;
@property (nonatomic, strong, nullable) NSDictionary *initialProps;
@property (nonatomic, strong) RCTReactNativeFactory *reactNativeFactory;
@@ -77,9 +76,7 @@ __attribute__((deprecated(
/// If `automaticallyLoadReactNativeWindow` is set to `true`, the React Native window will be loaded automatically.
@property (nonatomic, assign) BOOL automaticallyLoadReactNativeWindow;
@property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter __attribute__((
deprecated("The bridge adapter is deprecated and will be removed when removing the legacy architecture.")));
;
@property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter;
- (RCTRootViewFactory *)rootViewFactory;
@@ -40,20 +40,17 @@ std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupDefaultJsExecutor
std::unique_ptr<facebook::react::JSExecutorFactory> RCTAppSetupJsExecutorFactoryForOldArch(
RCTBridge *bridge,
const std::shared_ptr<facebook::react::RuntimeScheduler> &runtimeScheduler)
__attribute__((deprecated(
"RCTAppSetupJsExecutorFactoryForOldArch(RCTBridge *, RuntimeScheduler) is deprecated and will be removed when we remove the legacy architecture.")));
;
const std::shared_ptr<facebook::react::RuntimeScheduler> &runtimeScheduler);
#endif // __cplusplus
RCT_EXTERN_C_BEGIN
void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) __attribute__((deprecated(
"RCTAppSetupPrepareApp(UIApplication, BOOL) is deprecated and it's signature will change when we remove the legacy arch")));
UIView *
RCTAppSetupDefaultRootView(RCTBridge *bridge, NSString *moduleName, NSDictionary *initialProperties, BOOL fabricEnabled)
__attribute__((deprecated(
"RCTAppSetupDefaultRootView(RCTBridge *, NSString *, NSDictionary *, BOOL) is deprecated and it's signature will change when we remove the legacy arch")));
void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled);
UIView *RCTAppSetupDefaultRootView(
RCTBridge *bridge,
NSString *moduleName,
NSDictionary *initialProperties,
BOOL fabricEnabled);
RCT_EXTERN_C_END
@@ -10,29 +10,27 @@
NS_ASSUME_NONNULL_BEGIN
__attribute__((deprecated(
"RCTArchConfiguratorProtocol is deprecated and will be removed when we remove the legacy architecture.")));
@protocol RCTArchConfiguratorProtocol
/// This method controls whether the `turboModules` feature of the New Architecture is turned on or off.
///
/// @note: This is required to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the Turbo Native Module are enabled. Otherwise, it returns `false`.
- (BOOL)turboModuleEnabled __attribute__((deprecated("This will be removed in a future version of React Native")));
- (BOOL)turboModuleEnabled __attribute__((deprecated("Use RCTIsNewArchEnabled instead")));
/// This method controls whether the App will use the Fabric renderer of the New Architecture or not.
///
/// @return: `true` if the Fabric Renderer is enabled. Otherwise, it returns `false`.
- (BOOL)fabricEnabled __attribute__((deprecated("This will be removed in a future version of React Native")));
- (BOOL)fabricEnabled __attribute__((deprecated("Use RCTIsNewArchEnabled instead")));
/// This method controls whether React Native's new initialization layer is enabled.
///
/// @return: `true` if the new initialization layer is enabled. Otherwise returns `false`.
- (BOOL)bridgelessEnabled __attribute__((deprecated("This will be removed in a future version of React Native")));
- (BOOL)bridgelessEnabled __attribute__((deprecated("Use RCTIsNewArchEnabled instead")));
/// This method controls whether React Native uses new Architecture.
///
/// @return: `true` if the new architecture is enabled. Otherwise returns `false`.
- (BOOL)newArchEnabled __attribute__((deprecated("This will be removed in a future version of React Native")));
- (BOOL)newArchEnabled __attribute__((deprecated("Use RCTIsNewArchEnabled instead")));
@end
NS_ASSUME_NONNULL_END
@@ -56,10 +56,7 @@ typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable };
*
* @returns: a newly created instance of RCTBridge.
*/
- (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate
launchOptions:(NSDictionary *)launchOptions
__attribute__((deprecated(
"createBridgeWithDelegate:launchOptions: is deprecated and will be removed when removing the legacy architecture.")));
- (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate launchOptions:(NSDictionary *)launchOptions;
/**
* It creates a `UIView` starting from a bridge, a module name and a set of initial properties.
@@ -75,9 +72,7 @@ typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable };
*/
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps
__attribute__((deprecated(
"createRootViewWithBridge:moduleName:initProps is deprecated and will be removed when removing the legacy architecture.")));
initProps:(NSDictionary *)initProps;
/// This method returns a map of Component Descriptors and Components classes that needs to be registered in the
/// new renderer. The Component Descriptor is a string which represent the name used in JS to refer to the native
@@ -106,13 +101,10 @@ typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable };
initialProperties:(NSDictionary *_Nullable)initialProperties
launchOptions:(NSDictionary *_Nullable)launchOptions;
@property (nonatomic, nullable) RCTBridge *bridge
__attribute__((deprecated("The bridge is deprecated and will be removed when removing the legacy architecture.")));
@property (nonatomic, nullable) RCTBridge *bridge;
@property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory;
@property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter __attribute__((
deprecated("The bridgeAdapter is deprecated and will be removed when removing the legacy architecture.")));
;
@property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter;
@property (nonatomic, weak) id<RCTReactNativeFactoryDelegate> delegate;
@@ -65,15 +65,14 @@ typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBloc
- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock
newArchEnabled:(BOOL)newArchEnabled
turboModuleEnabled:(BOOL)turboModuleEnabled
bridgelessEnabled:(BOOL)bridgelessEnabled __deprecated;
bridgelessEnabled:(BOOL)bridgelessEnabled NS_DESIGNATED_INITIALIZER __deprecated;
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
newArchEnabled:(BOOL)newArchEnabled
turboModuleEnabled:(BOOL)turboModuleEnabled
bridgelessEnabled:(BOOL)bridgelessEnabled __deprecated;
- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock
newArchEnabled:(BOOL)newArchEnabled NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock newArchEnabled:(BOOL)newArchEnabled;
- (instancetype)initWithBundleURL:(NSURL *)bundleURL newArchEnabled:(BOOL)newArchEnabled;
@@ -38,12 +38,18 @@
- (instancetype)initWithBundleURL:(NSURL *)bundleURL newArchEnabled:(BOOL)newArchEnabled
{
return [self initWithBundleURL:bundleURL];
return [self initWithBundleURL:bundleURL
newArchEnabled:newArchEnabled
turboModuleEnabled:newArchEnabled
bridgelessEnabled:newArchEnabled];
}
- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock newArchEnabled:(BOOL)newArchEnabled
{
return [self initWithBundleURLBlock:bundleURLBlock];
return [self initWithBundleURLBlock:bundleURLBlock
newArchEnabled:newArchEnabled
turboModuleEnabled:newArchEnabled
bridgelessEnabled:newArchEnabled];
}
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
@@ -51,9 +57,13 @@
turboModuleEnabled:(BOOL)turboModuleEnabled
bridgelessEnabled:(BOOL)bridgelessEnabled
{
return [self initWithBundleURLBlock:^{
return bundleURL;
}];
return [self
initWithBundleURLBlock:^{
return bundleURL;
}
newArchEnabled:newArchEnabled
turboModuleEnabled:turboModuleEnabled
bridgelessEnabled:bridgelessEnabled];
}
- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock
@@ -70,24 +80,6 @@
return self;
}
- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock
{
if (self = [super init]) {
_bundleURLBlock = bundleURLBlock;
_fabricEnabled = YES;
_turboModuleEnabled = YES;
_bridgelessEnabled = YES;
}
return self;
}
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
{
return [self initWithBundleURLBlock:^{
return bundleURL;
}];
}
@end
@interface RCTRootViewFactory () <RCTCxxBridgeDelegate> {
@@ -194,8 +186,8 @@
RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
delegate:_turboModuleManagerDelegate
jsInvoker:callInvoker];
_contextContainer->erase(facebook::react::RuntimeSchedulerKey);
_contextContainer->insert(facebook::react::RuntimeSchedulerKey, _runtimeScheduler);
_contextContainer->erase("RuntimeScheduler");
_contextContainer->insert("RuntimeScheduler", _runtimeScheduler);
return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler);
}
@@ -6,7 +6,6 @@
*
* @flow strict
* @format
* @deprecated
*/
'use strict';
@@ -6,7 +6,6 @@
*
* @flow strict
* @format
* @deprecated
*/
'use strict';
@@ -264,7 +264,7 @@ const Switch: component(
disabled,
onTintColor: trackColorForTrue,
style: StyleSheet.compose(
{alignSelf: 'flex-start' as const},
{height: 31, width: 51},
StyleSheet.compose(
style,
ios_backgroundColor == null
@@ -677,9 +677,6 @@ function InternalTextInput(props: TextInputProps): React.Node {
flattenedStyle.paddingVertical == null &&
flattenedStyle.paddingTop == null));
const _accessibilityElementsHidden =
props['aria-hidden'] ?? props.accessibilityElementsHidden;
textInput = (
<RCTTextInputView
// Figure out imperative + forward refs.
@@ -689,7 +686,6 @@ function InternalTextInput(props: TextInputProps): React.Node {
acceptDragAndDropTypes={props.experimental_acceptDragAndDropTypes}
accessibilityLabel={_accessibilityLabel}
accessibilityState={_accessibilityState}
accessibilityElementsHidden={_accessibilityElementsHidden}
accessible={accessible}
submitBehavior={submitBehavior}
caretHidden={caretHidden}
@@ -718,10 +714,6 @@ function InternalTextInput(props: TextInputProps): React.Node {
const autoCapitalize = props.autoCapitalize || 'sentences';
const _accessibilityLabelledBy =
props?.['aria-labelledby'] ?? props?.accessibilityLabelledBy;
const _importantForAccessibility =
props['aria-hidden'] === true
? ('no-hide-descendants' as const)
: undefined;
const placeholder = props.placeholder ?? '';
let children = props.children;
const childCount = React.Children.count(children);
@@ -767,7 +759,6 @@ function InternalTextInput(props: TextInputProps): React.Node {
children={children}
disableFullscreenUI={props.disableFullscreenUI}
focusable={tabIndex !== undefined ? !tabIndex : focusable}
importantForAccessibility={_importantForAccessibility}
mostRecentEventCount={mostRecentEventCount}
nativeID={id ?? props.nativeID}
numberOfLines={props.rows ?? props.numberOfLines}
@@ -432,7 +432,6 @@ jest.unmock('../TextInput');
expect(instance.toJSON()).toMatchInlineSnapshot(`
<RCTSinglelineTextInputView
accessibilityElementsHidden={true}
accessibilityLabel="label"
accessibilityState={
Object {
@@ -339,30 +339,18 @@ describe('<View>', () => {
});
describe('accessibilityElementsHidden', () => {
it("is an iOS-only prop and ignored by Fantom (Android)'s BaseViewConfig", () => {
it('is not propagated to mounting layer, it is iOS only prop', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<View accessibilityElementsHidden={true} collapsable={false} />,
);
root.render(<View accessibilityElementsHidden={true} />);
});
expect(root.getRenderedOutput().toJSX()).toEqual(<rn-view />);
});
});
describe('aria-hidden', () => {
it('is mapped to importantForAccessibility', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<View aria-hidden={true} collapsable={false} />);
});
expect(root.getRenderedOutput().toJSX()).toEqual(
<rn-view importantForAccessibility="no-hide-descendants" />,
);
expect(
root
.getRenderedOutput({props: ['accessibilityElementsHidden']})
.toJSX(),
).toEqual(null);
});
});
+3 -3
View File
@@ -26,9 +26,9 @@
* ```
*/
export default class ReactNativeVersion {
static major: number = 0;
static minor: number = 82;
static patch: number = 1;
static major: number = 1000;
static minor: number = 0;
static patch: number = 0;
static prerelease: string | null = null;
static getVersionString(): string {
@@ -6,7 +6,6 @@
*
* @flow
* @format
* @deprecated
*/
import NativeTiming from './NativeTiming';
@@ -478,10 +477,8 @@ if (!NativeTiming) {
ExportedJSTimers = ({
callReactNativeMicrotasks: JSTimers.callReactNativeMicrotasks,
queueReactNativeMicrotask: JSTimers.queueReactNativeMicrotask,
// $FlowFixMe[incompatible-variance]
}: typeof JSTimers);
} else {
// $FlowFixMe[incompatible-variance]
ExportedJSTimers = JSTimers;
}
@@ -6,7 +6,6 @@
*
* @flow strict
* @format
* @deprecated
*/
export * from '../../../src/private/specs_DEPRECATED/modules/NativeTiming';
@@ -6,7 +6,6 @@
*
* @flow
* @format
* @deprecated
*/
'use strict';
+5 -3
View File
@@ -4,17 +4,19 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @flow strict
* @format
*/
import setUpPerformanceModern from '../../src/private/setup/setUpPerformanceModern';
import NativePerformance from '../../src/private/webapis/performance/specs/NativePerformance';
// In case if the native implementation of the Performance API is available, use it,
// otherwise fall back to the legacy/default one, which only defines 'Performance.now()'
if (NativePerformance) {
setUpPerformanceModern();
const Performance =
require('../../src/private/webapis/performance/Performance').default;
// $FlowExpectedError[cannot-write]
global.performance = new Performance();
} else {
if (!global.performance) {
// $FlowExpectedError[cannot-write]
@@ -148,7 +148,6 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInImage()) {
'aria-checked': ariaChecked,
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-hidden': ariaHidden,
'aria-label': ariaLabel,
'aria-selected': ariaSelected,
accessibilityLabel,
@@ -303,10 +302,6 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInImage()) {
};
}
if (ariaHidden === true) {
nativeProps.importantForAccessibility = 'no-hide-descendants';
}
const flattenedStyle_ = flattenStyle<ImageStyleProp>(style);
const objectFit_ = convertObjectFitToResizeMode(flattenedStyle_?.objectFit);
const resizeMode_ =
@@ -411,10 +406,6 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInImage()) {
expanded: props['aria-expanded'] ?? props.accessibilityState?.expanded,
selected: props['aria-selected'] ?? props.accessibilityState?.selected,
},
importantForAccessibility:
props['aria-hidden'] === true
? ('no-hide-descendants' as const)
: props.importantForAccessibility,
};
const flattenedStyle = flattenStyle<ImageStyleProp>(style);
@@ -153,7 +153,6 @@ let BaseImage: AbstractImageIOS = ({
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-selected': ariaSelected,
'aria-hidden': ariaHidden,
src,
...restProps
} = props;
@@ -165,10 +164,6 @@ let BaseImage: AbstractImageIOS = ({
expanded: ariaExpanded ?? props.accessibilityState?.expanded,
selected: ariaSelected ?? props.accessibilityState?.selected,
};
// In order for `aria-hidden` to work on iOS we must set `accessible` to false (`accessibilityElementsHidden` is not enough).
const accessible =
ariaHidden !== true && (props.alt !== undefined ? true : props.accessible);
const accessibilityLabel = props['aria-label'] ?? props.accessibilityLabel;
const actualRef = useWrapRefWithImageAttachedCallbacks(forwardedRef);
@@ -180,7 +175,7 @@ let BaseImage: AbstractImageIOS = ({
<ImageViewNativeComponent
accessibilityState={_accessibilityState}
{...restProps}
accessible={accessible}
accessible={props.alt !== undefined ? true : props.accessible}
accessibilityLabel={accessibilityLabel ?? props.alt}
ref={actualRef}
style={style}
@@ -9,7 +9,6 @@
#ifndef RCT_FIT_RM_OLD_COMPONENT
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTImageShadowView : RCTShadowView
@end
@@ -14,7 +14,6 @@
@class RCTBridge;
@class RCTImageSource;
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTImageView : RCTView
- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
@@ -9,7 +9,6 @@
#ifndef RCT_FIT_RM_OLD_COMPONENT
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTImageViewManager : RCTViewManager
@end
@@ -597,20 +597,6 @@ describe('<Image>', () => {
});
});
describe('aria-hidden', () => {
it('is is passed as importantForAccessibility', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<Image aria-hidden={true} />);
});
expect(
root
.getRenderedOutput({props: ['importantForAccessibility']})
.toJSX(),
).toEqual(<rn-image importantForAccessibility="no-hide-descendants" />);
});
});
component TestComponent(testID?: ?string, ...props: AccessibilityProps) {
return <Image {...props} testID={testID} source={LOGO_SOURCE} />;
}
+51 -6
View File
@@ -12,6 +12,7 @@
import type {GestureResponderEvent} from '../Types/CoreEventTypes';
const InteractionManager = require('./InteractionManager').default;
const TouchHistoryMath = require('./TouchHistoryMath').default;
const currentCentroidXOfTouchesChangedAfter =
@@ -30,6 +31,9 @@ const currentCentroidY = TouchHistoryMath.currentCentroidY;
* single-touch gestures resilient to extra touches, and can be used to
* recognize simple multi-touch gestures.
*
* By default, `PanResponder` holds an `InteractionManager` handle to block
* long-running JS events from interrupting active gestures.
*
* It provides a predictable wrapper of the responder handlers provided by the
* [gesture responder system](docs/gesture-responder-system.html).
* For each handler, it provides a new `gestureState` object alongside the
@@ -401,6 +405,9 @@ const PanResponder = {
getInteractionHandle: () => ?number,
panHandlers: GestureResponderHandlerMethods,
} {
const interactionState = {
handle: (null: ?number),
};
const gestureState: PanResponderGestureState = {
// Useful for debugging
stateID: Math.random(),
@@ -457,6 +464,10 @@ const PanResponder = {
},
onResponderGrant(event: GestureResponderEvent): boolean {
if (!interactionState.handle) {
interactionState.handle =
InteractionManager.createInteractionHandle();
}
gestureState.x0 = currentCentroidX(event.touchHistory);
gestureState.y0 = currentCentroidY(event.touchHistory);
gestureState.dx = 0;
@@ -471,11 +482,21 @@ const PanResponder = {
},
onResponderReject(event: GestureResponderEvent): void {
config.onPanResponderReject?.call(undefined, event, gestureState);
clearInteractionHandle(
interactionState,
config.onPanResponderReject,
event,
gestureState,
);
},
onResponderRelease(event: GestureResponderEvent): void {
config.onPanResponderRelease?.call(undefined, event, gestureState);
clearInteractionHandle(
interactionState,
config.onPanResponderRelease,
event,
gestureState,
);
PanResponder._initializeGestureState(gestureState);
},
@@ -508,11 +529,21 @@ const PanResponder = {
onResponderEnd(event: GestureResponderEvent): void {
const touchHistory = event.touchHistory;
gestureState.numberActiveTouches = touchHistory.numberActiveTouches;
config.onPanResponderEnd?.call(undefined, event, gestureState);
clearInteractionHandle(
interactionState,
config.onPanResponderEnd,
event,
gestureState,
);
},
onResponderTerminate(event: GestureResponderEvent): void {
config.onPanResponderTerminate?.call(undefined, event, gestureState);
clearInteractionHandle(
interactionState,
config.onPanResponderTerminate,
event,
gestureState,
);
PanResponder._initializeGestureState(gestureState);
},
@@ -525,13 +556,27 @@ const PanResponder = {
return {
panHandlers,
getInteractionHandle(): ?number {
// TODO: Deprecate and delete this method.
return null;
return interactionState.handle;
},
};
},
};
function clearInteractionHandle(
interactionState: {handle: ?number, ...},
callback: ?(ActiveCallback | PassiveCallback),
event: GestureResponderEvent,
gestureState: PanResponderGestureState,
) {
if (interactionState.handle) {
InteractionManager.clearInteractionHandle(interactionState.handle);
interactionState.handle = null;
}
if (callback) {
callback(event, gestureState);
}
}
export type PanResponderInstance = ReturnType<(typeof PanResponder)['create']>;
export default PanResponder;
@@ -76,7 +76,6 @@ export default function renderApplication<Props: Object>(
if (useOffscreen && displayMode != null) {
// $FlowFixMe[incompatible-type]
// $FlowFixMe[prop-missing]
// $FlowFixMe[missing-export]
const Activity: ActivityType = React.unstable_Activity;
renderable = (
+22 -7
View File
@@ -17,7 +17,13 @@ export interface StyleSheetProperties {
type Falsy = undefined | null | false | '';
interface RecursiveArray<T>
extends Array<T | ReadonlyArray<T> | RecursiveArray<T>> {}
export type StyleProp<T> = T | RecursiveArray<T | Falsy> | Falsy;
/** Keep a brand of 'T' so that calls to `StyleSheet.flatten` can take `RegisteredStyle<T>` and return `T`. */
type RegisteredStyle<T> = number & {__registeredStyleBrand: T};
export type StyleProp<T> =
| T
| RegisteredStyle<T>
| RecursiveArray<T | RegisteredStyle<T> | Falsy>
| Falsy;
type OpaqueColorValue = symbol & {__TYPE__: 'Color'};
export type ColorValue = string | OpaqueColorValue;
@@ -121,15 +127,24 @@ export namespace StyleSheet {
bottom: 0;
}
/**
* Sometimes you may want `absoluteFill` but with a couple tweaks - `absoluteFillObject` can be
* used to create a customized entry in a `StyleSheet`, e.g.:
*
* const styles = StyleSheet.create({
* wrapper: {
* ...StyleSheet.absoluteFillObject,
* top: 10,
* backgroundColor: 'transparent',
* },
* });
*/
export const absoluteFillObject: AbsoluteFillStyle;
/**
* A very common pattern is to create overlays with position absolute and zero positioning,
* so `absoluteFill` can be used for convenience and to reduce duplication of these repeated
* styles.
*/
export const absoluteFill: AbsoluteFillStyle;
/**
* @deprecated Use `StyleSheet.absoluteFill`.
*/
export const absoluteFillObject: AbsoluteFillStyle;
export const absoluteFill: RegisteredStyle<AbsoluteFillStyle>;
}
@@ -24,7 +24,13 @@ if (hairlineWidth === 0) {
hairlineWidth = 1 / PixelRatio.get();
}
const absoluteFill = {
const absoluteFill: {
+bottom: 0,
+left: 0,
+position: 'absolute',
+right: 0,
+top: 0,
} = {
position: 'absolute',
left: 0,
right: 0,
@@ -102,7 +108,7 @@ export default {
* so `absoluteFill` can be used for convenience and to reduce duplication of these repeated
* styles.
*/
absoluteFill,
absoluteFill: (absoluteFill: any), // TODO: This should be updated after we fix downstream Flow sites.
/**
* Sometimes you may want `absoluteFill` but with a couple tweaks - `absoluteFillObject` can be
@@ -13,14 +13,6 @@ import type {____Styles_Internal} from './StyleSheetTypes';
import composeStyles from '../../src/private/styles/composeStyles';
import flattenStyle from './flattenStyle';
type AbsoluteFillStyle = $ReadOnly<{
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
}>;
/**
* This is defined as the width of a thin line on the platform. It can be
* used as the thickness of a border or division between two elements.
@@ -45,12 +37,27 @@ declare export const hairlineWidth: number;
* so `absoluteFill` can be used for convenience and to reduce duplication of these repeated
* styles.
*/
declare export const absoluteFill: AbsoluteFillStyle;
declare export const absoluteFill: any;
/**
* @deprecated Use `StyleSheet.absoluteFill`.
* Sometimes you may want `absoluteFill` but with a couple tweaks - `absoluteFillObject` can be
* used to create a customized entry in a `StyleSheet`, e.g.:
*
* const styles = StyleSheet.create({
* wrapper: {
* ...StyleSheet.absoluteFillObject,
* top: 10,
* backgroundColor: 'transparent',
* },
* });
*/
declare export const absoluteFillObject: AbsoluteFillStyle;
declare export const absoluteFillObject: {
+bottom: 0,
+left: 0,
+position: 'absolute',
+right: 0,
+top: 0,
};
/**
* Combines two styles such that style2 will override any styles in style1.
@@ -13,10 +13,8 @@
NS_ASSUME_NONNULL_BEGIN
extern NSString *const RCTBaseTextShadowViewEmbeddedShadowViewAttributeName
__attribute__((deprecated("This API will be removed along with the legacy architecture.")));
extern NSString *const RCTBaseTextShadowViewEmbeddedShadowViewAttributeName;
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTBaseTextShadowView : RCTShadowView {
@protected
NSAttributedString *_Nullable cachedAttributedText;
@@ -11,7 +11,6 @@
NS_ASSUME_NONNULL_BEGIN
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTBaseTextViewManager : RCTViewManager
@end
@@ -15,18 +15,15 @@
NS_ASSUME_NONNULL_BEGIN
extern NSString *const RCTTextAttributesIsHighlightedAttributeName
__attribute__((deprecated("This API will be removed along with the legacy architecture.")));
extern NSString *const RCTTextAttributesTagAttributeName
__attribute__((deprecated("This API will be removed along with the legacy architecture.")));
extern NSString *const RCTTextAttributesIsHighlightedAttributeName;
extern NSString *const RCTTextAttributesTagAttributeName;
/**
* Represents knowledge about all supported *text* attributes
* assigned to some text component such as <Text>, <VirtualText>,
* and <TextInput>.
*/
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTTextAttributes : NSObject<NSCopying>
@interface RCTTextAttributes : NSObject <NSCopying>
// Color
@property (nonatomic, strong, nullable) UIColor *foregroundColor;
@@ -11,7 +11,6 @@
NS_ASSUME_NONNULL_BEGIN
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTRawTextShadowView : RCTShadowView
@property (nonatomic, copy, nullable) NSString *text;
@@ -11,7 +11,6 @@
NS_ASSUME_NONNULL_BEGIN
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTRawTextViewManager : RCTViewManager
@end
-26
View File
@@ -51,7 +51,6 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
'aria-checked': ariaChecked,
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-hidden': ariaHidden,
'aria-label': ariaLabel,
'aria-selected': ariaSelected,
children,
@@ -127,13 +126,6 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
_accessibilityState.disabled = _disabled;
}
if (ariaHidden !== undefined) {
processedProps.accessibilityElementsHidden = ariaHidden;
if (ariaHidden === true) {
processedProps.importantForAccessibility = 'no-hide-descendants';
}
}
const _accessible = Platform.select({
ios: accessible !== false,
android:
@@ -314,8 +306,6 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
) = ({
ref: forwardedRef,
accessible,
accessibilityElementsHidden,
importantForAccessibility,
accessibilityLabel,
accessibilityState,
allowFontScaling,
@@ -323,7 +313,6 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
'aria-checked': ariaChecked,
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-hidden': ariaHidden,
'aria-label': ariaLabel,
'aria-selected': ariaSelected,
children,
@@ -385,13 +374,6 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
const _accessibilityStateDisabled = _accessibilityState?.disabled;
const _disabled = disabled ?? _accessibilityStateDisabled;
let _accessibilityElementsHidden =
ariaHidden ?? accessibilityElementsHidden;
let _importantForAccessibility = importantForAccessibility;
if (ariaHidden === true) {
_importantForAccessibility = 'no-hide-descendants';
}
const isPressable =
(onPress != null ||
onLongPress != null ||
@@ -460,10 +442,8 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
ref={forwardedRef}
textProps={{
...restProps,
accessibilityElementsHidden: _accessibilityElementsHidden,
accessibilityLabel: _accessibilityLabel,
accessibilityState: _accessibilityState,
importantForAccessibility: _importantForAccessibility,
nativeID: _nativeID,
numberOfLines: _numberOfLines,
selectable: _selectable,
@@ -493,10 +473,8 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
return (
<NativeVirtualText
{...restProps}
accessibilityElementsHidden={_accessibilityElementsHidden}
accessibilityLabel={_accessibilityLabel}
accessibilityState={_accessibilityState}
importantForAccessibility={_importantForAccessibility}
nativeID={_nativeID}
numberOfLines={_numberOfLines}
ref={forwardedRef}
@@ -536,14 +514,12 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
ref={forwardedRef}
textProps={{
...restProps,
accessibilityElementsHidden: _accessibilityElementsHidden,
accessibilityLabel: _accessibilityLabel,
accessibilityState: _accessibilityState,
accessible: _accessible,
allowFontScaling: allowFontScaling !== false,
disabled: _disabled,
ellipsizeMode: ellipsizeMode ?? 'tail',
importantForAccessibility: _importantForAccessibility,
nativeID: _nativeID,
numberOfLines: _numberOfLines,
selectable: _selectable,
@@ -571,14 +547,12 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInText()) {
nativeText = (
<NativeText
{...restProps}
accessibilityElementsHidden={_accessibilityElementsHidden}
accessibilityLabel={_accessibilityLabel}
accessibilityState={_accessibilityState}
accessible={_accessible}
allowFontScaling={allowFontScaling !== false}
disabled={_disabled}
ellipsizeMode={ellipsizeMode ?? 'tail'}
importantForAccessibility={_importantForAccessibility}
nativeID={_nativeID}
numberOfLines={_numberOfLines}
ref={forwardedRef}
@@ -13,7 +13,6 @@
NS_ASSUME_NONNULL_BEGIN
__attribute__((deprecated("This API will be removed along with the legacy architecture.")))
@interface RCTTextShadowView : RCTBaseTextShadowView
- (instancetype)initWithBridge:(RCTBridge *)bridge;

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