mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c2cc3852d | ||
|
|
f68b918c89 | ||
|
|
ee08261123 | ||
|
|
ac2fe26cf2 | ||
|
|
cdfe1ecd52 | ||
|
|
a65325b586 | ||
|
|
ccb34a1063 | ||
|
|
68e774bb2c | ||
|
|
1cacdf70a1 | ||
|
|
72d4a1cbd4 | ||
|
|
0cfd7230c6 | ||
|
|
4fdefa7193 | ||
|
|
af734f0ccd | ||
|
|
af090eaa69 | ||
|
|
dc585b0f05 | ||
|
|
26cc647db3 | ||
|
|
f194ee5626 | ||
|
|
b6c338780c | ||
|
|
f49ae8a388 | ||
|
|
fdc4da96e4 | ||
|
|
e5647a18a8 | ||
|
|
044d07c670 | ||
|
|
1b359eefba | ||
|
|
92b33c986c |
@@ -188,6 +188,7 @@ 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',
|
||||
}),
|
||||
@@ -208,9 +209,11 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
|
||||
body: fetchBody,
|
||||
},
|
||||
);
|
||||
expect(response).toEqual(
|
||||
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
|
||||
);
|
||||
expect(response).toEqual({
|
||||
id: 1,
|
||||
html_url:
|
||||
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a draft release for prerelease on GitHub', async () => {
|
||||
@@ -238,6 +241,7 @@ 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',
|
||||
}),
|
||||
@@ -258,9 +262,11 @@ View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/
|
||||
body: fetchBody,
|
||||
},
|
||||
);
|
||||
expect(response).toEqual(
|
||||
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
|
||||
);
|
||||
expect(response).toEqual({
|
||||
id: 1,
|
||||
html_url:
|
||||
'https://github.com/facebook/react-native/releases/tag/v0.77.1',
|
||||
});
|
||||
});
|
||||
|
||||
it('throws if the post failes', async () => {
|
||||
|
||||
@@ -101,7 +101,11 @@ async function _createDraftReleaseOnGitHub(version, body, latest, token) {
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data.html_url;
|
||||
const {html_url, id} = data;
|
||||
return {
|
||||
html_url,
|
||||
id,
|
||||
};
|
||||
}
|
||||
|
||||
function moveToChangelogBranch(version) {
|
||||
@@ -124,7 +128,8 @@ async function createDraftRelease(version, latest, token) {
|
||||
latest,
|
||||
token,
|
||||
);
|
||||
log(`Created draft release: ${release}`);
|
||||
log(`Created draft release: ${release.html_url}, ID ${release.id}`);
|
||||
return release;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -21,9 +21,24 @@ 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');
|
||||
await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}');
|
||||
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,
|
||||
});
|
||||
|
||||
@@ -273,7 +273,8 @@ jobs:
|
||||
NEW_ARCH_ENABLED=1
|
||||
|
||||
export RCT_USE_LOCAL_RN_DEP=/tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
|
||||
export RCT_TESTONLY_RNCORE_TARBALL_PATH="/tmp/ReactCore/ReactCore${{ 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"
|
||||
HERMES_ENGINE_TARBALL_PATH=$HERMES_PATH RCT_NEW_ARCH_ENABLED=$NEW_ARCH_ENABLED bundle exec pod install
|
||||
|
||||
xcodebuild \
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
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();
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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};
|
||||
}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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
@@ -0,0 +1,421 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -12,3 +12,6 @@ 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
|
||||
|
||||
+7
-2
@@ -54,13 +54,16 @@
|
||||
"@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",
|
||||
"@react-native/metro-babel-transformer": "0.82.0-main",
|
||||
"@react-native/metro-config": "0.82.0-main",
|
||||
"@octokit/rest": "^22.0.0",
|
||||
"@react-native/metro-babel-transformer": "0.82.0-rc.1",
|
||||
"@react-native/metro-config": "0.82.0-rc.1",
|
||||
"@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",
|
||||
@@ -81,6 +84,7 @@
|
||||
"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",
|
||||
"glob": "^7.1.1",
|
||||
@@ -93,6 +97,7 @@
|
||||
"jest-diff": "^29.7.0",
|
||||
"jest-junit": "^16.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,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/assets-registry",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Asset support code for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-plugin-codegen",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Babel plugin to generate native module and view manager code for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/traverse": "^7.25.3",
|
||||
"@react-native/codegen": "0.82.0-main"
|
||||
"@react-native/codegen": "0.82.0-rc.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/community-cli-plugin",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Core CLI commands for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -22,7 +22,7 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/dev-middleware": "0.82.0-main",
|
||||
"@react-native/dev-middleware": "0.82.0-rc.1",
|
||||
"debug": "^4.4.0",
|
||||
"invariant": "^2.2.4",
|
||||
"metro": "^0.83.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/core-cli-utils",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "React Native CLI library for Frameworks to build on",
|
||||
"license": "MIT",
|
||||
"main": "./src/index.flow.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/debugger-frontend",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Debugger frontend for React Native based on Chrome DevTools",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env dotslash
|
||||
|
||||
// @generated SignedSource<<e93d55b5e28943e44271f5d3738083e0>>
|
||||
// @generated SignedSource<<f413a95849f40718f06ee03ed49972bb>>
|
||||
|
||||
|
||||
{
|
||||
@@ -11,6 +11,9 @@
|
||||
"hash": "sha256",
|
||||
"digest": "4352f1c9848ca919101ec628bd08b87a72a828d1ab55fa43a02098329fa452fa",
|
||||
"providers": [
|
||||
{
|
||||
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0-rc.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"
|
||||
@@ -24,6 +27,9 @@
|
||||
"hash": "sha256",
|
||||
"digest": "11c7b07942928a6301b07fbf2bc77ce1229b2a52891f23541cdd9858b5250e64",
|
||||
"providers": [
|
||||
{
|
||||
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0-rc.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"
|
||||
@@ -37,6 +43,9 @@
|
||||
"hash": "sha256",
|
||||
"digest": "3cbe8b1b3d17e433347f1601435bb9a6cb758528a5c176a66fc52d9977223175",
|
||||
"providers": [
|
||||
{
|
||||
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0-rc.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"
|
||||
@@ -50,6 +59,9 @@
|
||||
"hash": "sha256",
|
||||
"digest": "6fb79bc2ba3008401b4c9c128248657b95b98581ccde60f8fadb622163779775",
|
||||
"providers": [
|
||||
{
|
||||
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0-rc.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"
|
||||
@@ -63,6 +75,9 @@
|
||||
"hash": "sha256",
|
||||
"digest": "579a5b0944c51c3b1b541ad5af66c1ffedf93cae2a891ecdf88cb7219fd9b096",
|
||||
"providers": [
|
||||
{
|
||||
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0-rc.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"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/debugger-shell",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Experimental debugger shell for React Native for use with @react-native/debugger-frontend",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
|
||||
@@ -152,11 +152,7 @@ function getShellBinaryAndArgs(
|
||||
): [string, Array<string>] {
|
||||
switch (flavor) {
|
||||
case 'prebuilt':
|
||||
return [
|
||||
// $FlowFixMe[cannot-resolve-module] fb-dotslash includes Flow types but Flow does not pick them up
|
||||
require('fb-dotslash'),
|
||||
[DEVTOOLS_BINARY_DOTSLASH_FILE],
|
||||
];
|
||||
return [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(
|
||||
// $FlowFixMe[cannot-resolve-module] fb-dotslash includes Flow types but Flow does not pick them up
|
||||
require('fb-dotslash'),
|
||||
['--', 'fetch', filePath],
|
||||
);
|
||||
const {code, stderr} = await spawnAndGetStderr(require('fb-dotslash'), [
|
||||
'--',
|
||||
'fetch',
|
||||
filePath,
|
||||
]);
|
||||
if (code === 0) {
|
||||
return {code: 'success'};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/dev-middleware",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Dev server middleware for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -23,8 +23,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@isaacs/ttlcache": "^1.4.1",
|
||||
"@react-native/debugger-frontend": "0.82.0-main",
|
||||
"@react-native/debugger-shell": "0.82.0-main",
|
||||
"@react-native/debugger-frontend": "0.82.0-rc.1",
|
||||
"@react-native/debugger-shell": "0.82.0-rc.1",
|
||||
"chrome-launcher": "^0.15.2",
|
||||
"chromium-edge-launcher": "^0.2.0",
|
||||
"connect": "^3.6.5",
|
||||
@@ -39,7 +39,7 @@
|
||||
"node": ">= 20.19.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native/debugger-shell": "0.82.0-main",
|
||||
"@react-native/debugger-shell": "0.82.0-rc.1",
|
||||
"selfsigned": "^2.4.1",
|
||||
"undici": "^5.29.0",
|
||||
"wait-for-expect": "^3.0.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-config",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "ESLint config for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -22,7 +22,7 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/eslint-parser": "^7.25.1",
|
||||
"@react-native/eslint-plugin": "0.82.0-main",
|
||||
"@react-native/eslint-plugin": "0.82.0-rc.1",
|
||||
"@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.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "ESLint rules for @react-native/eslint-config",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin-specs",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "ESLint rules to validate NativeModule and Component Specs",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.25.2",
|
||||
"@react-native/codegen": "0.82.0-main",
|
||||
"@react-native/codegen": "0.82.0-rc.1",
|
||||
"make-dir": "^2.1.0",
|
||||
"pirates": "^4.0.1",
|
||||
"source-map-support": "0.5.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/gradle-plugin",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Gradle Plugin for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
+10
-3
@@ -28,6 +28,7 @@ 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
|
||||
@@ -54,6 +55,10 @@ class ReactPlugin : Plugin<Project> {
|
||||
project,
|
||||
)
|
||||
|
||||
if (project.rootProject.isHermesV1Enabled != rootExtension.hermesV1Enabled.get()) {
|
||||
rootExtension.hermesV1Enabled.set(project.rootProject.isHermesV1Enabled)
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -67,9 +72,11 @@ class ReactPlugin : Plugin<Project> {
|
||||
val reactNativeDir = extension.reactNativeDir.get().asFile
|
||||
val propertiesFile = File(reactNativeDir, "ReactAndroid/gradle.properties")
|
||||
val versionAndGroupStrings = readVersionAndGroupStrings(propertiesFile)
|
||||
val versionString = versionAndGroupStrings.first
|
||||
val groupString = versionAndGroupStrings.second
|
||||
configureDependencies(project, versionString, groupString)
|
||||
val hermesV1Enabled =
|
||||
if (project.rootProject.hasProperty("hermesV1Enabled"))
|
||||
project.rootProject.findProperty("hermesV1Enabled") == "true"
|
||||
else false
|
||||
configureDependencies(project, versionAndGroupStrings, hermesV1Enabled)
|
||||
configureRepositories(project)
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -11,6 +11,7 @@ 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
|
||||
@@ -57,4 +58,6 @@ 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)
|
||||
}
|
||||
|
||||
+6
-1
@@ -94,7 +94,12 @@ abstract class BundleHermesCTask : DefaultTask() {
|
||||
runCommand(bundleCommand)
|
||||
|
||||
if (hermesEnabled.get()) {
|
||||
val detectedHermesCommand = detectOSAwareHermesCommand(root.get().asFile, hermesCommand.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 bytecodeFile = File("${bundleFile}.hbc")
|
||||
val outputSourceMap = resolveOutputSourceMap(bundleAssetFilename)
|
||||
val compilerSourceMap = resolveCompilerSourceMap(bundleAssetFilename)
|
||||
|
||||
+52
-21
@@ -7,12 +7,15 @@
|
||||
|
||||
package com.facebook.react.utils
|
||||
|
||||
import com.facebook.react.utils.PropertyUtils.DEFAULT_INTERNAL_PUBLISHING_GROUP
|
||||
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.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_PUBLISHING_GROUP
|
||||
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_PUBLISHING_GROUP
|
||||
import com.facebook.react.utils.PropertyUtils.INTERNAL_HERMES_VERSION_NAME
|
||||
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
|
||||
@@ -25,6 +28,13 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository
|
||||
|
||||
internal object DependencyUtils {
|
||||
|
||||
internal data class Coordinates(
|
||||
val versionString: String,
|
||||
val hermesVersionString: 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.
|
||||
@@ -95,14 +105,15 @@ 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`.
|
||||
* - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`
|
||||
* - Selecting between the classic Hermes and Hermes V1
|
||||
*/
|
||||
fun configureDependencies(
|
||||
project: Project,
|
||||
versionString: String,
|
||||
groupString: String = DEFAULT_INTERNAL_PUBLISHING_GROUP,
|
||||
coordinates: Coordinates,
|
||||
hermesV1Enabled: Boolean = false,
|
||||
) {
|
||||
if (versionString.isBlank()) return
|
||||
if (coordinates.versionString.isBlank() || coordinates.hermesVersionString.isBlank()) return
|
||||
project.rootProject.allprojects { eachProject ->
|
||||
eachProject.configurations.all { configuration ->
|
||||
// Here we set a dependencySubstitution for both react-native and hermes-engine as those
|
||||
@@ -110,53 +121,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(versionString, groupString).forEach { (module, dest, reason) ->
|
||||
getDependencySubstitutions(coordinates, hermesV1Enabled).forEach { (module, dest, reason)
|
||||
->
|
||||
it.substitute(it.module(module)).using(it.module(dest)).because(reason)
|
||||
}
|
||||
}
|
||||
configuration.resolutionStrategy.force(
|
||||
"${groupString}:react-android:${versionString}",
|
||||
"${coordinates.reactGroupString}:react-android:${coordinates.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("${groupString}:hermes-android:${versionString}")
|
||||
configuration.resolutionStrategy.force(
|
||||
"${coordinates.reactGroupString}:hermes-android:${coordinates.versionString}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getDependencySubstitutions(
|
||||
versionString: String,
|
||||
groupString: String = DEFAULT_INTERNAL_PUBLISHING_GROUP,
|
||||
coordinates: Coordinates,
|
||||
hermesV1Enabled: Boolean = false,
|
||||
): List<Triple<String, String, String>> {
|
||||
// TODO: T231755027 update coordinates and versioning
|
||||
val dependencySubstitution = mutableListOf<Triple<String, String, String>>()
|
||||
val hermesVersionString =
|
||||
if (hermesV1Enabled)
|
||||
"${coordinates.hermesGroupString}:hermes-android:${coordinates.versionString}"
|
||||
else "${coordinates.reactGroupString}:hermes-android:${coordinates.versionString}"
|
||||
dependencySubstitution.add(
|
||||
Triple(
|
||||
"com.facebook.react:react-native",
|
||||
"${groupString}:react-android:${versionString}",
|
||||
"${coordinates.reactGroupString}:react-android:${coordinates.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",
|
||||
"${groupString}:hermes-android:${versionString}",
|
||||
hermesVersionString,
|
||||
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.",
|
||||
)
|
||||
)
|
||||
if (groupString != DEFAULT_INTERNAL_PUBLISHING_GROUP) {
|
||||
if (coordinates.reactGroupString != DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP) {
|
||||
dependencySubstitution.add(
|
||||
Triple(
|
||||
"com.facebook.react:react-android",
|
||||
"${groupString}:react-android:${versionString}",
|
||||
"${coordinates.reactGroupString}:react-android:${coordinates.versionString}",
|
||||
"The react-android dependency was modified to use the correct Maven group.",
|
||||
)
|
||||
)
|
||||
dependencySubstitution.add(
|
||||
Triple(
|
||||
"com.facebook.react:hermes-android",
|
||||
"${groupString}:hermes-android:${versionString}",
|
||||
hermesVersionString,
|
||||
"The hermes-android dependency was modified to use the correct Maven group.",
|
||||
)
|
||||
)
|
||||
@@ -164,10 +183,14 @@ internal object DependencyUtils {
|
||||
return dependencySubstitution
|
||||
}
|
||||
|
||||
fun readVersionAndGroupStrings(propertiesFile: File): Pair<String, String> {
|
||||
fun readVersionAndGroupStrings(propertiesFile: File): Coordinates {
|
||||
val reactAndroidProperties = Properties()
|
||||
propertiesFile.inputStream().use { reactAndroidProperties.load(it) }
|
||||
val versionStringFromFile = (reactAndroidProperties[INTERNAL_VERSION_NAME] as? String).orEmpty()
|
||||
// TODO: T231755027 update HERMES_VERSION_NAME in gradle.properties to point to the correct
|
||||
// hermes version
|
||||
val hermesVersionStringFromFile =
|
||||
(reactAndroidProperties[INTERNAL_HERMES_VERSION_NAME] as? String).orEmpty()
|
||||
// If on a nightly, we need to fetch the -SNAPSHOT artifact from Sonatype.
|
||||
val versionString =
|
||||
if (versionStringFromFile.startsWith("0.0.0") || "-nightly-" in versionStringFromFile) {
|
||||
@@ -176,10 +199,18 @@ internal object DependencyUtils {
|
||||
versionStringFromFile
|
||||
}
|
||||
// Returns Maven group for repos using different group for Maven artifacts
|
||||
val groupString =
|
||||
reactAndroidProperties[INTERNAL_PUBLISHING_GROUP] as? String
|
||||
?: DEFAULT_INTERNAL_PUBLISHING_GROUP
|
||||
return Pair(versionString, groupString)
|
||||
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
|
||||
return Coordinates(
|
||||
versionString,
|
||||
hermesVersionStringFromFile,
|
||||
reactGroupString,
|
||||
hermesGroupString,
|
||||
)
|
||||
}
|
||||
|
||||
fun Project.mavenRepoFromUrl(
|
||||
|
||||
+14
-5
@@ -122,11 +122,16 @@ 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.
|
||||
* 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.
|
||||
* 4. Fails otherwise
|
||||
*/
|
||||
internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String): String {
|
||||
// 1. If the project specifies a Hermes command, don't second guess it.
|
||||
internal fun detectOSAwareHermesCommand(
|
||||
projectRoot: File,
|
||||
hermesCommand: String,
|
||||
hermesV1Enabled: Boolean = false,
|
||||
): String { // 1. If the project specifies a Hermes command, don't second guess it.
|
||||
if (hermesCommand.isNotBlank()) {
|
||||
val osSpecificHermesCommand =
|
||||
if ("%OS-BIN%" in hermesCommand) {
|
||||
@@ -146,9 +151,12 @@ internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String
|
||||
return builtHermesc.cliPath(projectRoot)
|
||||
}
|
||||
|
||||
// 3. If the react-native contains a pre-built hermesc, use it.
|
||||
// 3. If Hermes V1 is enabled, use hermes-compiler from npm, otherwise, if the
|
||||
// react-native contains a pre-built hermesc, use it.
|
||||
val hermesCPath = if (hermesV1Enabled) HERMES_COMPILER_NPM_DIR else HERMESC_IN_REACT_NATIVE_DIR
|
||||
val prebuiltHermesPath =
|
||||
HERMESC_IN_REACT_NATIVE_DIR.plus(getHermesCBin())
|
||||
hermesCPath
|
||||
.plus(getHermesCBin())
|
||||
.replace("%OS-BIN%", getHermesOSBin())
|
||||
// Execution on Windows fails with / as separator
|
||||
.replace('/', File.separatorChar)
|
||||
@@ -233,6 +241,7 @@ internal fun readPackageJsonFile(
|
||||
return packageJson?.let { JsonUtils.fromPackageJson(it) }
|
||||
}
|
||||
|
||||
private const val HERMES_COMPILER_NPM_DIR = "node_modules/hermes-compiler/%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/"
|
||||
|
||||
+9
@@ -13,9 +13,11 @@ 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
|
||||
@@ -68,6 +70,13 @@ 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())
|
||||
|
||||
internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean {
|
||||
val parsedPackageJson = readPackageJsonFile(this, rootProperty)
|
||||
return needsCodegenFromPackageJson(parsedPackageJson)
|
||||
|
||||
+10
-2
@@ -18,6 +18,10 @@ 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"
|
||||
@@ -68,9 +72,13 @@ 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_PUBLISHING_GROUP = "react.internal.publishingGroup"
|
||||
const val DEFAULT_INTERNAL_PUBLISHING_GROUP = "com.facebook.react"
|
||||
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"
|
||||
|
||||
/** Internal property used to control the version name of React Native */
|
||||
const val INTERNAL_VERSION_NAME = "VERSION_NAME"
|
||||
/** Internal property used to control the version name of Hermes Engine */
|
||||
const val INTERNAL_HERMES_VERSION_NAME = "HERMES_VERSION_NAME"
|
||||
}
|
||||
|
||||
+21
-12
@@ -271,11 +271,13 @@ class DependencyUtilsTest {
|
||||
.isEqualTo(2)
|
||||
}
|
||||
|
||||
// TODO: T236767053
|
||||
|
||||
@Test
|
||||
fun configureDependencies_withEmptyVersion_doesNothing() {
|
||||
val project = createProject()
|
||||
|
||||
configureDependencies(project, "")
|
||||
configureDependencies(project, DependencyUtils.Coordinates("", ""))
|
||||
|
||||
assertThat(project.configurations.first().resolutionStrategy.forcedModules.isEmpty()).isTrue()
|
||||
}
|
||||
@@ -284,7 +286,7 @@ class DependencyUtilsTest {
|
||||
fun configureDependencies_withVersionString_appliesResolutionStrategy() {
|
||||
val project = createProject()
|
||||
|
||||
configureDependencies(project, "1.2.3")
|
||||
configureDependencies(project, DependencyUtils.Coordinates("1.2.3", "1.2.3"))
|
||||
|
||||
val forcedModules = project.configurations.first().resolutionStrategy.forcedModules
|
||||
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
|
||||
@@ -301,7 +303,7 @@ class DependencyUtilsTest {
|
||||
appProject.plugins.apply("com.android.application")
|
||||
libProject.plugins.apply("com.android.library")
|
||||
|
||||
configureDependencies(appProject, "1.2.3")
|
||||
configureDependencies(appProject, DependencyUtils.Coordinates("1.2.3", "1.2.3"))
|
||||
|
||||
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
|
||||
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
|
||||
@@ -323,7 +325,10 @@ class DependencyUtilsTest {
|
||||
appProject.plugins.apply("com.android.application")
|
||||
libProject.plugins.apply("com.android.library")
|
||||
|
||||
configureDependencies(appProject, "1.2.3", "io.github.test")
|
||||
configureDependencies(
|
||||
appProject,
|
||||
DependencyUtils.Coordinates("1.2.3", "1.2.3", "io.github.test"),
|
||||
)
|
||||
|
||||
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
|
||||
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
|
||||
@@ -339,7 +344,8 @@ class DependencyUtilsTest {
|
||||
|
||||
@Test
|
||||
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly() {
|
||||
val dependencySubstitutions = getDependencySubstitutions("0.42.0")
|
||||
val dependencySubstitutions =
|
||||
getDependencySubstitutions(DependencyUtils.Coordinates("0.42.0", "0.42.0"))
|
||||
|
||||
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
|
||||
assertThat("com.facebook.react:react-android:0.42.0")
|
||||
@@ -359,7 +365,10 @@ class DependencyUtilsTest {
|
||||
|
||||
@Test
|
||||
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly() {
|
||||
val dependencySubstitutions = getDependencySubstitutions("0.42.0", "io.github.test")
|
||||
val dependencySubstitutions =
|
||||
getDependencySubstitutions(
|
||||
DependencyUtils.Coordinates("0.42.0", "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)
|
||||
@@ -396,7 +405,7 @@ class DependencyUtilsTest {
|
||||
)
|
||||
}
|
||||
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).first
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).versionString
|
||||
|
||||
assertThat(versionString).isEqualTo("1000.0.0")
|
||||
}
|
||||
@@ -414,7 +423,7 @@ class DependencyUtilsTest {
|
||||
)
|
||||
}
|
||||
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).first
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).versionString
|
||||
|
||||
assertThat(versionString).isEqualTo("0.0.0-20221101-2019-cfe811ab1-SNAPSHOT")
|
||||
}
|
||||
@@ -431,7 +440,7 @@ class DependencyUtilsTest {
|
||||
)
|
||||
}
|
||||
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).first
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).versionString
|
||||
assertThat(versionString).isEqualTo("")
|
||||
}
|
||||
|
||||
@@ -448,7 +457,7 @@ class DependencyUtilsTest {
|
||||
)
|
||||
}
|
||||
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).first
|
||||
val versionString = readVersionAndGroupStrings(propertiesFile).versionString
|
||||
assertThat(versionString).isEqualTo("")
|
||||
}
|
||||
|
||||
@@ -465,7 +474,7 @@ class DependencyUtilsTest {
|
||||
)
|
||||
}
|
||||
|
||||
val groupString = readVersionAndGroupStrings(propertiesFile).second
|
||||
val groupString = readVersionAndGroupStrings(propertiesFile).reactGroupString
|
||||
|
||||
assertThat(groupString).isEqualTo("io.github.test")
|
||||
}
|
||||
@@ -482,7 +491,7 @@ class DependencyUtilsTest {
|
||||
)
|
||||
}
|
||||
|
||||
val groupString = readVersionAndGroupStrings(propertiesFile).second
|
||||
val groupString = readVersionAndGroupStrings(propertiesFile).reactGroupString
|
||||
|
||||
assertThat(groupString).isEqualTo("com.facebook.react")
|
||||
}
|
||||
|
||||
+10
@@ -162,6 +162,16 @@ class PathUtilsTest {
|
||||
assertThat(detectOSAwareHermesCommand(tempFolder.root, "")).isEqualTo(expected.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithOs(OS.MAC)
|
||||
fun detectOSAwareHermesCommand_withHermesV1Enabled() {
|
||||
tempFolder.newFolder("node_modules/hermes-compiler/osx-bin/")
|
||||
val expected = tempFolder.newFile("node_modules/hermes-compiler/osx-bin//hermesc")
|
||||
|
||||
assertThat(detectOSAwareHermesCommand(tempFolder.root, "", hermesV1Enabled = true))
|
||||
.isEqualTo(expected.toString())
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
@WithOs(OS.MAC)
|
||||
fun detectOSAwareHermesCommand_failsIfNotFound() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-config",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Metro configuration for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,8 +26,8 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/js-polyfills": "0.82.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.82.0-main",
|
||||
"@react-native/js-polyfills": "0.82.0-rc.1",
|
||||
"@react-native/metro-babel-transformer": "0.82.0-rc.1",
|
||||
"metro-config": "^0.83.1",
|
||||
"metro-runtime": "^0.83.1"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/new-app-screen",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "NewAppScreen component for React Native",
|
||||
"keywords": [
|
||||
"react-native"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/normalize-colors",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Color normalization for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/js-polyfills",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Polyfills for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-preset",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"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.0-main",
|
||||
"@react-native/babel-plugin-codegen": "0.82.0-rc.1",
|
||||
"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.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"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.0-main",
|
||||
"@react-native/babel-preset": "0.82.0-rc.1",
|
||||
"hermes-parser": "0.32.0",
|
||||
"nullthrows": "^1.1.1"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "Code generation tools for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/compatibility-check",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"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.0-main"
|
||||
"@react-native/codegen": "0.82.0-rc.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"flow-remove-types": "^2.237.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/popup-menu-android",
|
||||
"version": "0.82.0-main",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "PopupMenu for the Android platform",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@react-native/codegen": "0.82.0-main"
|
||||
"@react-native/codegen": "0.82.0-rc.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.1.0",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
* ```
|
||||
*/
|
||||
export default class ReactNativeVersion {
|
||||
static major: number = 1000;
|
||||
static minor: number = 0;
|
||||
static major: number = 0;
|
||||
static minor: number = 82;
|
||||
static patch: number = 0;
|
||||
static prerelease: string | null = null;
|
||||
static prerelease: string | null = 'rc.1';
|
||||
|
||||
static getVersionString(): string {
|
||||
return `${this.major}.${this.minor}.${this.patch}${this.prerelease != null ? `-${this.prerelease}` : ''}`;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
import NativeTiming from './NativeTiming';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
export * from '../../../src/private/specs_DEPRECATED/modules/NativeTiming';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -4,19 +4,17 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
* @flow strict-local
|
||||
* @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) {
|
||||
const Performance =
|
||||
require('../../src/private/webapis/performance/Performance').default;
|
||||
// $FlowExpectedError[cannot-write]
|
||||
global.performance = new Performance();
|
||||
setUpPerformanceModern();
|
||||
} else {
|
||||
if (!global.performance) {
|
||||
// $FlowExpectedError[cannot-write]
|
||||
|
||||
@@ -21,10 +21,10 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(void){
|
||||
__rnVersion = @{
|
||||
RCTVersionMajor: @(1000),
|
||||
RCTVersionMinor: @(0),
|
||||
RCTVersionMajor: @(0),
|
||||
RCTVersionMinor: @(82),
|
||||
RCTVersionPatch: @(0),
|
||||
RCTVersionPrerelease: [NSNull null],
|
||||
RCTVersionPrerelease: @"rc.1",
|
||||
};
|
||||
});
|
||||
return __rnVersion;
|
||||
|
||||
@@ -20,7 +20,12 @@
|
||||
- (UIWindow *)alertWindow
|
||||
{
|
||||
if (_alertWindow == nil) {
|
||||
_alertWindow = [[UIWindow alloc] initWithWindowScene:RCTKeyWindow().windowScene];
|
||||
UIWindowScene *scene = RCTKeyWindow().windowScene;
|
||||
if (scene != nil) {
|
||||
_alertWindow = [[UIWindow alloc] initWithWindowScene:scene];
|
||||
} else {
|
||||
_alertWindow = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
|
||||
}
|
||||
|
||||
if (_alertWindow) {
|
||||
_alertWindow.rootViewController = [UIViewController new];
|
||||
|
||||
@@ -39,6 +39,9 @@ val downloadsDir =
|
||||
val thirdPartyNdkDir = File("$buildDir/third-party-ndk")
|
||||
val reactNativeRootDir = projectDir.parent
|
||||
|
||||
val hermesV1Enabled =
|
||||
rootProject.extensions.getByType(PrivateReactExtension::class.java).hermesV1Enabled.get()
|
||||
|
||||
// We put the publishing version from gradle.properties inside ext. so other
|
||||
// subprojects can access it as well.
|
||||
extra["publishing_version"] = project.findProperty("VERSION_NAME")?.toString()!!
|
||||
@@ -565,6 +568,10 @@ android {
|
||||
"-DCMAKE_POLICY_DEFAULT_CMP0069=NEW",
|
||||
)
|
||||
|
||||
if (hermesV1Enabled) {
|
||||
arguments("-DHERMES_V1_ENABLED=1")
|
||||
}
|
||||
|
||||
targets(
|
||||
"reactnative",
|
||||
"jsi",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
VERSION_NAME=1000.0.0
|
||||
VERSION_NAME=0.82.0-rc.1
|
||||
HERMES_VERSION_NAME=1000.0.0
|
||||
react.internal.publishingGroup=com.facebook.react
|
||||
react.internal.hermesPublishingGroup=com.facebook.hermes
|
||||
|
||||
android.useAndroidX=true
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import com.facebook.react.internal.PrivateReactExtension
|
||||
import com.facebook.react.tasks.internal.*
|
||||
import de.undercouch.gradle.tasks.download.Download
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
@@ -50,6 +51,8 @@ fun getSDKManagerPath(): String {
|
||||
}
|
||||
}
|
||||
|
||||
val hermesV1Enabled =
|
||||
rootProject.extensions.getByType(PrivateReactExtension::class.java).hermesV1Enabled.get()
|
||||
val reactNativeRootDir = project(":packages:react-native:ReactAndroid").projectDir.parent
|
||||
val customDownloadDir = System.getenv("REACT_NATIVE_DOWNLOADS_DIR")
|
||||
val downloadsDir =
|
||||
@@ -79,12 +82,21 @@ val hermesBuildOutputFileTree =
|
||||
fileTree(hermesBuildDir.toString())
|
||||
.include("**/*.cmake", "**/*.marks", "**/compiler_depends.ts", "**/Makefile", "**/link.txt")
|
||||
|
||||
var hermesVersion = "main"
|
||||
val hermesVersionFile = File(reactNativeRootDir, "sdks/.hermesversion")
|
||||
val hermesVersionProvider: Provider<String> =
|
||||
providers.provider {
|
||||
var hermesVersion = if (hermesV1Enabled) "250829098.0.0-stable" else "main"
|
||||
val hermesVersionFile =
|
||||
File(
|
||||
reactNativeRootDir,
|
||||
if (hermesV1Enabled) "sdks/.hermesv1version" else "sdks/.hermesversion",
|
||||
)
|
||||
|
||||
if (hermesVersionFile.exists()) {
|
||||
hermesVersion = hermesVersionFile.readText()
|
||||
}
|
||||
if (hermesVersionFile.exists()) {
|
||||
hermesVersion = hermesVersionFile.readText()
|
||||
}
|
||||
|
||||
hermesVersion
|
||||
}
|
||||
|
||||
val ndkBuildJobs = Runtime.getRuntime().availableProcessors().toString()
|
||||
val prefabHeadersDir = File("$buildDir/prefab-headers")
|
||||
@@ -95,7 +107,11 @@ val jsiDir = File(reactNativeRootDir, "ReactCommon/jsi")
|
||||
val downloadHermesDest = File(downloadsDir, "hermes.tar.gz")
|
||||
val downloadHermes by
|
||||
tasks.registering(Download::class) {
|
||||
src("https://github.com/facebook/hermes/tarball/${hermesVersion}")
|
||||
src(
|
||||
providers.provider {
|
||||
"https://github.com/facebook/hermes/tarball/${hermesVersionProvider.get()}"
|
||||
}
|
||||
)
|
||||
onlyIfModified(true)
|
||||
overwrite(true)
|
||||
quiet(true)
|
||||
@@ -151,6 +167,7 @@ val configureBuildForHermes by
|
||||
"-B",
|
||||
hermesBuildDir.toString(),
|
||||
"-DJSI_DIR=" + jsiDir.absolutePath,
|
||||
"-DCMAKE_BUILD_TYPE=Release",
|
||||
)
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
cmakeCommandLine = cmakeCommandLine + "-GNMake Makefiles"
|
||||
@@ -295,7 +312,11 @@ android {
|
||||
// Therefore we're passing as build type Release, to provide a faster build.
|
||||
// This has the (unlucky) side effect of letting AGP call the build
|
||||
// tasks `configureCMakeRelease` while is actually building the debug flavor.
|
||||
arguments("-DCMAKE_BUILD_TYPE=Release")
|
||||
arguments(
|
||||
"-DCMAKE_BUILD_TYPE=Release",
|
||||
// For debug builds, explicitly enable the Hermes Debugger.
|
||||
"-DHERMES_ENABLE_DEBUGGER=True",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -1,15 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE file in the root
|
||||
* directory of this source tree.
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated by scripts/releases/set-version.js
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.systeminfo
|
||||
|
||||
public object ReactNativeVersion {
|
||||
@JvmField
|
||||
public val VERSION: Map<String, Any?> =
|
||||
mapOf("major" to 1000, "minor" to 0, "patch" to 0, "prerelease" to null)
|
||||
public val VERSION: Map<String, Any?> = mapOf(
|
||||
"major" to 0,
|
||||
"minor" to 82,
|
||||
"patch" to 0,
|
||||
"prerelease" to "rc.1"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ file(TO_CMAKE_PATH "${REACT_ANDROID_DIR}" REACT_ANDROID_DIR)
|
||||
file(TO_CMAKE_PATH "${REACT_BUILD_DIR}" REACT_BUILD_DIR)
|
||||
file(TO_CMAKE_PATH "${REACT_COMMON_DIR}" REACT_COMMON_DIR)
|
||||
|
||||
set(HERMES_V1_ENABLED OFF CACHE BOOL "Build with support for Hermes v1")
|
||||
|
||||
# If you have ccache installed, we're going to honor it.
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
|
||||
+4
@@ -27,4 +27,8 @@ target_link_libraries(
|
||||
target_compile_reactnative_options(hermes_executor PRIVATE)
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
target_compile_options(hermes_executor PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
target_compile_options(hermes_executor PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
+4
@@ -29,4 +29,8 @@ target_link_libraries(hermesinstancejni
|
||||
target_compile_reactnative_options(hermesinstancejni PRIVATE)
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
target_compile_options(hermesinstancejni PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
target_compile_options(hermesinstancejni PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
@@ -19,6 +19,10 @@ add_library(rninstance
|
||||
target_compile_reactnative_options(rninstance PRIVATE)
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
target_compile_options(rninstance PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
target_compile_options(rninstance PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
target_merge_so(rninstance)
|
||||
|
||||
@@ -12,17 +12,17 @@
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
#define REACT_NATIVE_VERSION_MAJOR 1000
|
||||
#define REACT_NATIVE_VERSION_MINOR 0
|
||||
#define REACT_NATIVE_VERSION_MAJOR 0
|
||||
#define REACT_NATIVE_VERSION_MINOR 82
|
||||
#define REACT_NATIVE_VERSION_PATCH 0
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
constexpr struct {
|
||||
int32_t Major = 1000;
|
||||
int32_t Minor = 0;
|
||||
int32_t Major = 0;
|
||||
int32_t Minor = 82;
|
||||
int32_t Patch = 0;
|
||||
std::string_view Prerelease = "";
|
||||
std::string_view Prerelease = "rc.1";
|
||||
} ReactNativeVersion;
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
@@ -32,6 +32,10 @@ if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
PRIVATE
|
||||
-DHERMES_ENABLE_DEBUGGER=1
|
||||
)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
target_compile_options(hermes_executor_common PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(
|
||||
hermes_executor_common
|
||||
|
||||
@@ -14,8 +14,11 @@
|
||||
#include <jsinspector-modern/InspectorFlags.h>
|
||||
|
||||
#include <hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h>
|
||||
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
#include <hermes/inspector-modern/chrome/Registration.h>
|
||||
#include <hermes/inspector/RuntimeAdapter.h>
|
||||
#endif
|
||||
|
||||
using namespace facebook::hermes;
|
||||
using namespace facebook::jsi;
|
||||
@@ -24,7 +27,7 @@ namespace facebook::react {
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
class HermesExecutorRuntimeAdapter
|
||||
: public facebook::hermes::inspector_modern::RuntimeAdapter {
|
||||
@@ -59,7 +62,7 @@ class HermesExecutorRuntimeAdapter
|
||||
std::shared_ptr<MessageQueueThread> thread_;
|
||||
};
|
||||
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
struct ReentrancyCheck {
|
||||
// This is effectively a very subtle and complex assert, so only
|
||||
@@ -144,7 +147,7 @@ class DecoratedRuntime : public jsi::WithRuntimeDecorator<ReentrancyCheck> {
|
||||
const std::string& debuggerName)
|
||||
: jsi::WithRuntimeDecorator<ReentrancyCheck>(*runtime, reentrancyCheck_),
|
||||
runtime_(std::move(runtime)) {
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
enableDebugger_ = enableDebugger;
|
||||
if (enableDebugger_) {
|
||||
std::shared_ptr<HermesRuntime> rt(runtime_, &hermesRuntime);
|
||||
@@ -159,7 +162,7 @@ class DecoratedRuntime : public jsi::WithRuntimeDecorator<ReentrancyCheck> {
|
||||
}
|
||||
|
||||
~DecoratedRuntime() {
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
if (enableDebugger_) {
|
||||
facebook::hermes::inspector_modern::chrome::disableDebugging(debugToken_);
|
||||
}
|
||||
@@ -176,7 +179,7 @@ class DecoratedRuntime : public jsi::WithRuntimeDecorator<ReentrancyCheck> {
|
||||
|
||||
std::shared_ptr<Runtime> runtime_;
|
||||
ReentrancyCheck reentrancyCheck_;
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
bool enableDebugger_;
|
||||
facebook::hermes::inspector_modern::chrome::DebugSessionToken debugToken_;
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
|
||||
@@ -23,6 +23,10 @@ if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
PRIVATE
|
||||
-DHERMES_ENABLE_DEBUGGER=1
|
||||
)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
target_compile_options(hermes_inspector_modern PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(hermes_inspector_modern PUBLIC ${REACT_COMMON_DIR})
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "ConnectionDemux.h"
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
#include <hermes/inspector/RuntimeAdapter.h>
|
||||
#include <hermes/inspector/chrome/CDPHandler.h>
|
||||
@@ -139,4 +139,4 @@ void ConnectionDemux::removePage(int pageId) {
|
||||
|
||||
} // namespace facebook::hermes::inspector_modern::chrome
|
||||
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -59,4 +59,4 @@ class ConnectionDemux {
|
||||
|
||||
} // namespace facebook::hermes::inspector_modern::chrome
|
||||
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "Registration.h"
|
||||
#include "ConnectionDemux.h"
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
namespace facebook::hermes::inspector_modern::chrome {
|
||||
|
||||
@@ -34,4 +34,4 @@ void disableDebugging(DebugSessionToken session) {
|
||||
|
||||
} // namespace facebook::hermes::inspector_modern::chrome
|
||||
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -38,4 +38,4 @@ extern void disableDebugging(DebugSessionToken session);
|
||||
|
||||
} // namespace facebook::hermes::inspector_modern::chrome
|
||||
|
||||
#endif // HERMES_ENABLE_DEBUGGER
|
||||
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
@@ -54,6 +54,8 @@ Pod::Spec.new do |s|
|
||||
add_dependency(s, "React-jsinspectornetwork", :framework_name => 'jsinspector_modernnetwork')
|
||||
add_dependency(s, "React-jsinspectortracing", :framework_name => 'jsinspector_moderntracing')
|
||||
s.dependency "React-perflogger", version
|
||||
add_dependency(s, "React-oscompat")
|
||||
|
||||
if use_hermes()
|
||||
s.dependency "hermes-engine"
|
||||
end
|
||||
|
||||
@@ -18,6 +18,10 @@ add_library(bridgeless
|
||||
target_compile_reactnative_options(bridgeless PRIVATE)
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
target_compile_options(bridgeless PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
target_compile_options(bridgeless PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif ()
|
||||
target_include_directories(bridgeless PUBLIC .)
|
||||
|
||||
|
||||
@@ -35,4 +35,8 @@ if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
PRIVATE
|
||||
-DHERMES_ENABLE_DEBUGGER=1
|
||||
)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
target_compile_options(bridgelesshermes PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#include <hermes/inspector-modern/chrome/Registration.h>
|
||||
|
||||
#ifndef HERMES_V1_ENABLED
|
||||
#include <hermes/inspector/RuntimeAdapter.h>
|
||||
#endif
|
||||
|
||||
#include <jsi/decorator.h>
|
||||
#endif
|
||||
|
||||
@@ -23,7 +27,7 @@ using namespace facebook::jsi;
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
// Wrapper that strongly retains the HermesRuntime for on device debugging.
|
||||
//
|
||||
@@ -90,7 +94,7 @@ class DecoratedRuntime : public jsi::RuntimeDecorator<jsi::Runtime> {
|
||||
inspector_modern::chrome::DebugSessionToken debugToken_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
|
||||
class HermesJSRuntime : public JSRuntime {
|
||||
public:
|
||||
@@ -157,7 +161,7 @@ std::unique_ptr<JSRuntime> HermesInstance::createJSRuntime(
|
||||
.getPropertyAsObject(*hermesRuntime, "prototype");
|
||||
errorPrototype.setProperty(*hermesRuntime, "jsEngine", "hermes");
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
|
||||
auto& inspectorFlags = jsinspector_modern::InspectorFlags::getInstance();
|
||||
if (!inspectorFlags.getFuseboxEnabled()) {
|
||||
std::unique_ptr<DecoratedRuntime> decoratedRuntime =
|
||||
|
||||
@@ -88,12 +88,169 @@ declare var navigator: Navigator;
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp
|
||||
declare type DOMHighResTimeStamp = number;
|
||||
|
||||
type PerformanceEntryFilterOptions = {
|
||||
entryType: string,
|
||||
name: string,
|
||||
...
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/performance-timeline-2/
|
||||
declare class PerformanceEntry {
|
||||
duration: DOMHighResTimeStamp;
|
||||
entryType: string;
|
||||
name: string;
|
||||
startTime: DOMHighResTimeStamp;
|
||||
toJSON(): string;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/user-timing/#performancemark
|
||||
declare class PerformanceMark extends PerformanceEntry {
|
||||
constructor(name: string, markOptions?: PerformanceMarkOptions): void;
|
||||
+detail: mixed;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/user-timing/#performancemeasure
|
||||
declare class PerformanceMeasure extends PerformanceEntry {
|
||||
+detail: mixed;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/server-timing/#the-performanceservertiming-interface
|
||||
declare class PerformanceServerTiming {
|
||||
description: string;
|
||||
duration: DOMHighResTimeStamp;
|
||||
name: string;
|
||||
toJSON(): string;
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/resource-timing-2/#sec-performanceresourcetiming
|
||||
// https://w3c.github.io/server-timing/#extension-to-the-performanceresourcetiming-interface
|
||||
declare class PerformanceResourceTiming extends PerformanceEntry {
|
||||
connectEnd: number;
|
||||
connectStart: number;
|
||||
decodedBodySize: number;
|
||||
domainLookupEnd: number;
|
||||
domainLookupStart: number;
|
||||
encodedBodySize: number;
|
||||
fetchStart: number;
|
||||
initiatorType: string;
|
||||
nextHopProtocol: string;
|
||||
redirectEnd: number;
|
||||
redirectStart: number;
|
||||
requestStart: number;
|
||||
responseEnd: number;
|
||||
responseStart: number;
|
||||
secureConnectionStart: number;
|
||||
serverTiming: Array<PerformanceServerTiming>;
|
||||
transferSize: number;
|
||||
workerStart: number;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/event-timing/#sec-performance-event-timing
|
||||
declare class PerformanceEventTiming extends PerformanceEntry {
|
||||
cancelable: boolean;
|
||||
interactionId: number;
|
||||
processingEnd: number;
|
||||
processingStart: number;
|
||||
target: ?Node;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/longtasks/#taskattributiontiming
|
||||
declare class TaskAttributionTiming extends PerformanceEntry {
|
||||
containerId: string;
|
||||
containerName: string;
|
||||
containerSrc: string;
|
||||
containerType: string;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/longtasks/#sec-PerformanceLongTaskTiming
|
||||
declare class PerformanceLongTaskTiming extends PerformanceEntry {
|
||||
attribution: $ReadOnlyArray<TaskAttributionTiming>;
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/user-timing/#extensions-performance-interface
|
||||
declare type PerformanceMarkOptions = {
|
||||
detail?: mixed,
|
||||
startTime?: number,
|
||||
};
|
||||
|
||||
declare type PerformanceMeasureOptions = {
|
||||
detail?: mixed,
|
||||
duration?: number,
|
||||
end?: number | string,
|
||||
start?: number | string,
|
||||
};
|
||||
|
||||
type EventCountsForEachCallbackType =
|
||||
| (() => void)
|
||||
| ((value: number) => void)
|
||||
| ((value: number, key: string) => void)
|
||||
| ((value: number, key: string, map: Map<string, number>) => void);
|
||||
|
||||
// https://www.w3.org/TR/event-timing/#eventcounts
|
||||
declare interface EventCounts {
|
||||
entries(): Iterator<[string, number]>;
|
||||
|
||||
forEach(callback: EventCountsForEachCallbackType): void;
|
||||
get(key: string): ?number;
|
||||
has(key: string): boolean;
|
||||
keys(): Iterator<string>;
|
||||
size: number;
|
||||
values(): Iterator<number>;
|
||||
}
|
||||
|
||||
declare class Performance {
|
||||
clearMarks(name?: string): void;
|
||||
|
||||
clearMeasures(name?: string): void;
|
||||
|
||||
eventCounts: EventCounts;
|
||||
getEntries: (
|
||||
options?: PerformanceEntryFilterOptions,
|
||||
) => Array<PerformanceEntry>;
|
||||
getEntriesByName: (name: string, type?: string) => Array<PerformanceEntry>;
|
||||
getEntriesByType: (type: string) => Array<PerformanceEntry>;
|
||||
mark(name: string, options?: PerformanceMarkOptions): PerformanceMark;
|
||||
measure(
|
||||
name: string,
|
||||
startMarkOrOptions?: string | PerformanceMeasureOptions,
|
||||
endMark?: string,
|
||||
): PerformanceMeasure;
|
||||
now: () => DOMHighResTimeStamp;
|
||||
toJSON(): string;
|
||||
}
|
||||
|
||||
declare var performance: Performance;
|
||||
|
||||
type PerformanceEntryList = Array<PerformanceEntry>;
|
||||
|
||||
declare interface PerformanceObserverEntryList {
|
||||
getEntries(): PerformanceEntryList;
|
||||
getEntriesByName(name: string, type: ?string): PerformanceEntryList;
|
||||
getEntriesByType(type: string): PerformanceEntryList;
|
||||
}
|
||||
|
||||
type PerformanceObserverInit = {
|
||||
buffered?: boolean,
|
||||
entryTypes?: Array<string>,
|
||||
type?: string,
|
||||
...
|
||||
};
|
||||
|
||||
declare class PerformanceObserver {
|
||||
constructor(
|
||||
callback: (
|
||||
entries: PerformanceObserverEntryList,
|
||||
observer: PerformanceObserver,
|
||||
) => mixed,
|
||||
): void;
|
||||
|
||||
disconnect(): void;
|
||||
observe(options: ?PerformanceObserverInit): void;
|
||||
static supportedEntryTypes: Array<string>;
|
||||
|
||||
takeRecords(): PerformanceEntryList;
|
||||
}
|
||||
|
||||
type FormDataEntryValue = string | File;
|
||||
|
||||
declare class FormData {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "1000.0.0",
|
||||
"version": "0.82.0-rc.1",
|
||||
"description": "A framework for building native apps using React",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -162,13 +162,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/create-cache-key-function": "^29.7.0",
|
||||
"@react-native/assets-registry": "0.82.0-main",
|
||||
"@react-native/codegen": "0.82.0-main",
|
||||
"@react-native/community-cli-plugin": "0.82.0-main",
|
||||
"@react-native/gradle-plugin": "0.82.0-main",
|
||||
"@react-native/js-polyfills": "0.82.0-main",
|
||||
"@react-native/normalize-colors": "0.82.0-main",
|
||||
"@react-native/virtualized-lists": "0.82.0-main",
|
||||
"@react-native/assets-registry": "0.82.0-rc.1",
|
||||
"@react-native/codegen": "0.82.0-rc.1",
|
||||
"@react-native/community-cli-plugin": "0.82.0-rc.1",
|
||||
"@react-native/gradle-plugin": "0.82.0-rc.1",
|
||||
"@react-native/js-polyfills": "0.82.0-rc.1",
|
||||
"@react-native/normalize-colors": "0.82.0-rc.1",
|
||||
"@react-native/virtualized-lists": "0.82.0-rc.1",
|
||||
"abort-controller": "^3.0.0",
|
||||
"anser": "^1.4.9",
|
||||
"ansi-regex": "^5.0.0",
|
||||
|
||||
@@ -40,6 +40,12 @@ def list_native_modules!(config_command)
|
||||
packages = config["dependencies"]
|
||||
ios_project_root = Pathname.new(config["project"]["ios"]["sourceDir"])
|
||||
react_native_path = Pathname.new(config["reactNativePath"])
|
||||
codegen_output_path = ios_project_root.join("build/generated/autolinking/autolinking.json")
|
||||
|
||||
# Write autolinking react-native-config output to codegen folder
|
||||
FileUtils.mkdir_p(File.dirname(codegen_output_path))
|
||||
File.write(codegen_output_path, json)
|
||||
|
||||
found_pods = []
|
||||
|
||||
packages.each do |package_name, package|
|
||||
|
||||
@@ -87,7 +87,7 @@ class CodegenUtils
|
||||
codegen_path = file_manager.join(ios_folder, codegen_dir)
|
||||
return if !dir_manager.exist?(codegen_path)
|
||||
|
||||
FileUtils.rm_rf(dir_manager.glob("#{codegen_path}/*"))
|
||||
FileUtils.rm_rf("#{codegen_path}")
|
||||
base_provider_path = file_manager.join(rn_path, 'React', 'Fabric', 'RCTThirdPartyFabricComponentsProvider')
|
||||
FileUtils.rm_rf("#{base_provider_path}.h")
|
||||
FileUtils.rm_rf("#{base_provider_path}.mm")
|
||||
|
||||
@@ -13,7 +13,8 @@ def setup_hermes!(react_native_path: "../node_modules/react-native")
|
||||
react_native_dir = Pod::Config.instance.installation_root.join(react_native_path)
|
||||
# This `:tag => hermestag` below is only to tell CocoaPods to update hermes-engine when React Native version changes.
|
||||
# We have custom logic to compute the source for hermes-engine. See sdks/hermes-engine/*
|
||||
hermestag_file = File.join(react_native_dir, "sdks", ".hermesversion")
|
||||
hermestag_file_name = ENV['RCT_HERMES_V1_ENABLED'] == "1" ? ".hermesv1version" : ".hermesversion"
|
||||
hermestag_file = File.join(react_native_dir, "sdks", hermestag_file_name)
|
||||
hermestag = File.exist?(hermestag_file) ? File.read(hermestag_file).strip : ''
|
||||
pod 'hermes-engine', :podspec => "#{react_native_path}/sdks/hermes-engine/hermes-engine.podspec", :tag => hermestag
|
||||
pod 'React-hermes', :path => "#{react_native_path}/ReactCommon/hermes"
|
||||
|
||||
@@ -45,9 +45,15 @@ class ReactNativePodsUtils
|
||||
end
|
||||
|
||||
def self.set_gcc_preprocessor_definition_for_React_hermes(installer)
|
||||
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "React-hermes", :debug)
|
||||
if ENV['RCT_HERMES_V1_ENABLED'] == "1"
|
||||
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1 HERMES_V1_ENABLED=1", "React-hermes", :debug)
|
||||
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1 HERMES_V1_ENABLED=1", "React-RuntimeHermes", :debug)
|
||||
else
|
||||
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "React-hermes", :debug)
|
||||
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "React-RuntimeHermes", :debug)
|
||||
end
|
||||
|
||||
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "hermes-engine", :debug)
|
||||
self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "React-RuntimeHermes", :debug)
|
||||
end
|
||||
|
||||
def self.set_gcc_preprocessor_definition_for_debugger(installer)
|
||||
|
||||
+5
-5
@@ -361,7 +361,7 @@ exports[`execute test-app "ReactAppDependencyProvider.podspec" should match snap
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
version = \\"1000.0.0\\"
|
||||
version = \\"0.82.0-rc.1\\"
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
@@ -399,7 +399,7 @@ exports[`execute test-app "ReactCodegen.podspec" should match snapshot 1`] = `
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
version = \\"1000.0.0\\"
|
||||
version = \\"0.82.0-rc.1\\"
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
@@ -840,7 +840,7 @@ exports[`execute test-app-legacy "ReactAppDependencyProvider.podspec" should mat
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
version = \\"1000.0.0\\"
|
||||
version = \\"0.82.0-rc.1\\"
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
@@ -878,7 +878,7 @@ exports[`execute test-app-legacy "ReactCodegen.podspec" should match snapshot 1`
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
version = \\"1000.0.0\\"
|
||||
version = \\"0.82.0-rc.1\\"
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
@@ -984,4 +984,4 @@ SCRIPT
|
||||
|
||||
end
|
||||
"
|
||||
`;
|
||||
`;
|
||||
@@ -86,10 +86,14 @@ function execute(
|
||||
buildCodegenIfNeeded();
|
||||
}
|
||||
|
||||
const reactNativeConfig = readReactNativeConfig(projectRoot);
|
||||
const reactNativeConfig = readReactNativeConfig(
|
||||
projectRoot,
|
||||
baseOutputPath,
|
||||
);
|
||||
const codegenEnabledLibraries = findCodegenEnabledLibraries(
|
||||
pkgJson,
|
||||
projectRoot,
|
||||
baseOutputPath,
|
||||
reactNativeConfig,
|
||||
);
|
||||
|
||||
|
||||
+41
-10
@@ -97,15 +97,40 @@ function cleanupEmptyFilesAndFolders(filepath /*: string */) {
|
||||
}
|
||||
}
|
||||
|
||||
function readReactNativeConfig(projectRoot /*: string */) /*: $FlowFixMe */ {
|
||||
const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
|
||||
function readGeneratedAutolinkingOutput(
|
||||
baseOutputPath /*: string */,
|
||||
) /*: $FlowFixMe */ {
|
||||
// NOTE: Generated by scripts/cocoapods/autolinking.rb in list_native_modules (called by use_native_modules)
|
||||
const autolinkingGeneratedPath = path.resolve(
|
||||
baseOutputPath,
|
||||
'build/generated/autolinking/autolinking.json',
|
||||
);
|
||||
if (fs.existsSync(autolinkingGeneratedPath)) {
|
||||
// $FlowFixMe[unsupported-syntax]
|
||||
return require(autolinkingGeneratedPath);
|
||||
} else {
|
||||
codegenLog(
|
||||
`Could not find generated autolinking output at: ${autolinkingGeneratedPath}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fs.existsSync(rnConfigFilePath)) {
|
||||
function readReactNativeConfig(
|
||||
projectRoot /*: string */,
|
||||
baseOutputPath /*: string */,
|
||||
) /*: $FlowFixMe */ {
|
||||
const autolinkingOutput = readGeneratedAutolinkingOutput(baseOutputPath);
|
||||
const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
|
||||
if (autolinkingOutput) {
|
||||
return autolinkingOutput;
|
||||
} else if (fs.existsSync(rnConfigFilePath)) {
|
||||
// $FlowFixMe[unsupported-syntax]
|
||||
return require(rnConfigFilePath);
|
||||
} else {
|
||||
codegenLog(`Could not find React Native config at: ${rnConfigFilePath}`);
|
||||
return {};
|
||||
}
|
||||
|
||||
// $FlowFixMe[unsupported-syntax]
|
||||
return require(rnConfigFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,17 +139,23 @@ function readReactNativeConfig(projectRoot /*: string */) /*: $FlowFixMe */ {
|
||||
function findCodegenEnabledLibraries(
|
||||
pkgJson /*: $FlowFixMe */,
|
||||
projectRoot /*: string */,
|
||||
baseOutputPath /*: string */,
|
||||
reactNativeConfig /*: $FlowFixMe */,
|
||||
) /*: Array<$FlowFixMe> */ {
|
||||
const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot);
|
||||
if (pkgJsonIncludesGeneratedCode(pkgJson)) {
|
||||
return projectLibraries;
|
||||
} else {
|
||||
return [
|
||||
...projectLibraries,
|
||||
...findExternalLibraries(pkgJson, projectRoot),
|
||||
const libraries = [...projectLibraries];
|
||||
// If we ran autolinking, we shouldn't try to run our own "autolinking-like"
|
||||
// library discovery
|
||||
if (!readGeneratedAutolinkingOutput(baseOutputPath)) {
|
||||
libraries.push(...findExternalLibraries(pkgJson, projectRoot));
|
||||
}
|
||||
libraries.push(
|
||||
...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),
|
||||
];
|
||||
);
|
||||
return libraries;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -10,7 +10,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {execSync} = require('child_process');
|
||||
const {spawnSync} = require('child_process');
|
||||
const fs = require('fs');
|
||||
const yargs = require('yargs');
|
||||
|
||||
@@ -67,7 +67,9 @@ function replaceRNCoreConfiguration(
|
||||
fs.mkdirSync(finalLocation, {recursive: true});
|
||||
|
||||
console.log('Extracting the tarball', tarballURLPath);
|
||||
execSync(`tar -xf ${tarballURLPath} -C ${finalLocation}`);
|
||||
spawnSync('tar', ['-xf', tarballURLPath, '-C', finalLocation], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
}
|
||||
|
||||
function updateLastBuildConfiguration(configuration /*: string */) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hermes-2025-09-01-RNv0.82.0-265ef62ff3eb7289d17e366664ac0da82303e101
|
||||
@@ -20,6 +20,7 @@ end
|
||||
|
||||
# package.json
|
||||
package = JSON.parse(File.read(File.join(react_native_path, "package.json")))
|
||||
# TODO: T231755000 use the Hermes V1 version instead of React Native version
|
||||
version = package['version']
|
||||
|
||||
source_type = hermes_source_type(version, react_native_path)
|
||||
@@ -62,6 +63,21 @@ Pod::Spec.new do |spec|
|
||||
ss.osx.vendored_frameworks = "destroot/Library/Frameworks/macosx/hermesvm.framework"
|
||||
end
|
||||
|
||||
# When using the local prebuilt tarball, it should include hermesc compatible with the used VM.
|
||||
# In other cases, when using Hermes V1, the prebuilt versioned binaries can be used.
|
||||
# TODO: T236142916 hermesc should be consumed from NPM even when not using Hermes V1
|
||||
if source_type != HermesEngineSourceType::LOCAL_PREBUILT_TARBALL && ENV['RCT_HERMES_V1_ENABLED'] == "1"
|
||||
hermes_compiler_path = File.dirname(Pod::Executable.execute_command('node', ['-p',
|
||||
'require.resolve(
|
||||
"hermes-compiler",
|
||||
{paths: [process.argv[1]]}
|
||||
)', __dir__]).strip
|
||||
)
|
||||
|
||||
spec.user_target_xcconfig = {
|
||||
'HERMES_CLI_PATH' => "#{hermes_compiler_path}/osx-bin/hermesc"
|
||||
}
|
||||
end
|
||||
|
||||
# Right now, even reinstalling pods with the PRODUCTION flag turned on, does not change the version of hermes that is downloaded
|
||||
# To remove the PRODUCTION flag, we want to download the right version of hermes on the flight
|
||||
@@ -100,24 +116,26 @@ Pod::Spec.new do |spec|
|
||||
ss.header_dir = 'hermes/cdp'
|
||||
end
|
||||
|
||||
spec.subspec 'inspector' do |ss|
|
||||
ss.source_files = ''
|
||||
ss.public_header_files = 'API/hermes/inspector/*.h'
|
||||
ss.header_dir = 'hermes/inspector'
|
||||
end
|
||||
|
||||
spec.subspec 'inspector_chrome' do |ss|
|
||||
ss.source_files = ''
|
||||
ss.public_header_files = 'API/hermes/inspector/chrome/*.h'
|
||||
ss.header_dir = 'hermes/inspector/chrome'
|
||||
end
|
||||
|
||||
spec.subspec 'Public' do |ss|
|
||||
ss.source_files = ''
|
||||
ss.public_header_files = 'public/hermes/Public/*.h'
|
||||
ss.header_dir = 'hermes/Public'
|
||||
end
|
||||
|
||||
if ENV['RCT_HERMES_V1_ENABLED'] != "1"
|
||||
spec.subspec 'inspector' do |ss|
|
||||
ss.source_files = ''
|
||||
ss.public_header_files = 'API/hermes/inspector/*.h'
|
||||
ss.header_dir = 'hermes/inspector'
|
||||
end
|
||||
|
||||
spec.subspec 'inspector_chrome' do |ss|
|
||||
ss.source_files = ''
|
||||
ss.public_header_files = 'API/hermes/inspector/chrome/*.h'
|
||||
ss.header_dir = 'hermes/inspector/chrome'
|
||||
end
|
||||
end
|
||||
|
||||
hermesc_path = "${PODS_ROOT}/hermes-engine/build_host_hermesc"
|
||||
|
||||
if ENV.has_key?('HERMES_OVERRIDE_HERMESC_PATH') && File.exist?(ENV['HERMES_OVERRIDE_HERMESC_PATH']) then
|
||||
|
||||
@@ -85,6 +85,10 @@ def hermes_commit_envvar_defined()
|
||||
return ENV.has_key?('HERMES_COMMIT')
|
||||
end
|
||||
|
||||
def hermes_v1_enabled()
|
||||
return ENV['RCT_HERMES_V1_ENABLED'] == "1"
|
||||
end
|
||||
|
||||
def force_build_from_tag(react_native_path)
|
||||
return ENV[ENV_BUILD_FROM_SOURCE] === 'true' && File.exist?(hermestag_file(react_native_path))
|
||||
end
|
||||
@@ -170,13 +174,19 @@ end
|
||||
|
||||
def podspec_source_build_from_github_tag(react_native_path)
|
||||
tag = File.read(hermestag_file(react_native_path)).strip
|
||||
hermes_log("Using tag difined in sdks/.hermesversion: #{tag}")
|
||||
|
||||
if hermes_v1_enabled()
|
||||
hermes_log("Using tag defined in sdks/.hermesv1version: #{tag}")
|
||||
else
|
||||
hermes_log("Using tag defined in sdks/.hermesversion: #{tag}")
|
||||
end
|
||||
return {:git => HERMES_GITHUB_URL, :tag => tag}
|
||||
end
|
||||
|
||||
def podspec_source_build_from_github_main()
|
||||
hermes_log("Using the latest commit from main.")
|
||||
return {:git => HERMES_GITHUB_URL, :commit => `git ls-remote #{HERMES_GITHUB_URL} main | cut -f 1`.strip}
|
||||
branch = hermes_v1_enabled() ? "250829098.0.0-stable" : "main"
|
||||
hermes_log("Using the latest commit from #{branch}.")
|
||||
return {:git => HERMES_GITHUB_URL, :commit => `git ls-remote #{HERMES_GITHUB_URL} #{branch} | cut -f 1`.strip}
|
||||
end
|
||||
|
||||
def podspec_source_download_prebuild_release_tarball(react_native_path, version)
|
||||
@@ -200,7 +210,11 @@ def artifacts_dir()
|
||||
end
|
||||
|
||||
def hermestag_file(react_native_path)
|
||||
return File.join(react_native_path, "sdks", ".hermesversion")
|
||||
if hermes_v1_enabled()
|
||||
return File.join(react_native_path, "sdks", ".hermesv1version")
|
||||
else
|
||||
return File.join(react_native_path, "sdks", ".hermesversion")
|
||||
end
|
||||
end
|
||||
|
||||
def release_tarball_url(version, build_type)
|
||||
@@ -210,10 +224,18 @@ def release_tarball_url(version, build_type)
|
||||
ENV['ENTERPRISE_REPOSITORY'] != nil && ENV['ENTERPRISE_REPOSITORY'] != "" ?
|
||||
ENV['ENTERPRISE_REPOSITORY'] :
|
||||
"https://repo1.maven.org/maven2"
|
||||
namespace = "com/facebook/react"
|
||||
# Sample url from Maven:
|
||||
# https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.71.0/react-native-artifacts-0.71.0-hermes-ios-debug.tar.gz
|
||||
return "#{maven_repo_url}/#{namespace}/react-native-artifacts/#{version}/react-native-artifacts-#{version}-hermes-ios-#{build_type.to_s}.tar.gz"
|
||||
|
||||
if hermes_v1_enabled()
|
||||
namespace = "com/facebook/hermes"
|
||||
# Sample url from Maven:
|
||||
# https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/0.14.0/hermes-ios-0.14.0-debug.tar.gz
|
||||
return "#{maven_repo_url}/#{namespace}/hermes-ios/#{version}/hermes-ios-#{version}-#{build_type.to_s}.tar.gz"
|
||||
else
|
||||
namespace = "com/facebook/react"
|
||||
# Sample url from Maven:
|
||||
# https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.71.0/react-native-artifacts-0.71.0-hermes-ios-debug.tar.gz
|
||||
return "#{maven_repo_url}/#{namespace}/react-native-artifacts/#{version}/react-native-artifacts-#{version}-hermes-ios-#{build_type.to_s}.tar.gz"
|
||||
end
|
||||
end
|
||||
|
||||
def download_stable_hermes(react_native_path, version, configuration)
|
||||
@@ -235,9 +257,18 @@ def download_hermes_tarball(react_native_path, tarball_url, version, configurati
|
||||
end
|
||||
|
||||
def nightly_tarball_url(version)
|
||||
# TODO: T231755027 update coordinates and versioning
|
||||
artifact_coordinate = "react-native-artifacts"
|
||||
artifact_name = "hermes-ios-debug.tar.gz"
|
||||
xml_url = "https://central.sonatype.com/repository/maven-snapshots/com/facebook/react/#{artifact_coordinate}/#{version}-SNAPSHOT/maven-metadata.xml"
|
||||
namespace = "com/facebook/react"
|
||||
|
||||
if hermes_v1_enabled()
|
||||
artifact_coordinate = "hermes-ios"
|
||||
artifact_name = "hermes-ios-debug.tar.gz"
|
||||
namespace = "com/facebook/hermes"
|
||||
end
|
||||
|
||||
xml_url = "https://central.sonatype.com/repository/maven-snapshots/#{namespace}/#{artifact_coordinate}/#{version}-SNAPSHOT/maven-metadata.xml"
|
||||
|
||||
response = Net::HTTP.get_response(URI(xml_url))
|
||||
if response.is_a?(Net::HTTPSuccess)
|
||||
@@ -245,7 +276,7 @@ def nightly_tarball_url(version)
|
||||
timestamp = xml.elements['metadata/versioning/snapshot/timestamp'].text
|
||||
build_number = xml.elements['metadata/versioning/snapshot/buildNumber'].text
|
||||
full_version = "#{version}-#{timestamp}-#{build_number}"
|
||||
final_url = "https://central.sonatype.com/repository/maven-snapshots/com/facebook/react/#{artifact_coordinate}/#{version}-SNAPSHOT/#{artifact_coordinate}-#{full_version}-#{artifact_name}"
|
||||
final_url = "https://central.sonatype.com/repository/maven-snapshots/#{namespace}/#{artifact_coordinate}/#{version}-SNAPSHOT/#{artifact_coordinate}-#{full_version}-#{artifact_name}"
|
||||
|
||||
return final_url
|
||||
else
|
||||
|
||||
@@ -88,6 +88,11 @@ function configure_apple_framework {
|
||||
xcode_15_flags="LINKER:-ld_classic"
|
||||
fi
|
||||
|
||||
boost_context_flag=""
|
||||
if [[ $1 == "catalyst" ]]; then
|
||||
boost_context_flag="-DHERMES_ALLOW_BOOST_CONTEXT=0"
|
||||
fi
|
||||
|
||||
pushd "$HERMES_PATH" > /dev/null || exit 1
|
||||
cmake -S . -B "build_$1" \
|
||||
-DHERMES_EXTRA_LINKER_FLAGS="$xcode_15_flags" \
|
||||
@@ -107,7 +112,8 @@ function configure_apple_framework {
|
||||
-DIMPORT_HOST_COMPILERS:PATH="$IMPORT_HOST_COMPILERS_PATH" \
|
||||
-DJSI_DIR="$JSI_PATH" \
|
||||
-DHERMES_RELEASE_VERSION="for RN $(get_release_version)" \
|
||||
-DCMAKE_BUILD_TYPE="$cmake_build_type"
|
||||
-DCMAKE_BUILD_TYPE="$cmake_build_type" \
|
||||
$boost_context_flag
|
||||
popd > /dev/null || exit 1
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,11 @@ if [[ $xcode_major_version -ge 15 ]]; then
|
||||
xcode_15_flags="LINKER:-ld_classic"
|
||||
fi
|
||||
|
||||
boost_context_flag=""
|
||||
if [[ $PLATFORM_NAME == "catalyst" ]]; then
|
||||
boost_context_flag="-DHERMES_ALLOW_BOOST_CONTEXT=0"
|
||||
fi
|
||||
|
||||
architectures=$( echo "$ARCHS" | tr " " ";" )
|
||||
|
||||
echo "Configure Apple framework"
|
||||
@@ -83,7 +88,8 @@ echo "Configure Apple framework"
|
||||
-DIMPORT_HOST_COMPILERS:PATH="${hermesc_path}" \
|
||||
-DJSI_DIR="$jsi_path" \
|
||||
-DHERMES_RELEASE_VERSION="for RN $release_version" \
|
||||
-DCMAKE_BUILD_TYPE="$cmake_build_type"
|
||||
-DCMAKE_BUILD_TYPE="$cmake_build_type" \
|
||||
$boost_context_flag
|
||||
|
||||
echo "Build Apple framework"
|
||||
|
||||
@@ -96,6 +102,7 @@ echo "Copy Apple framework to destroot/Library/Frameworks"
|
||||
|
||||
platform_copy_destination=$(get_platform_copy_destination $PLATFORM_NAME)
|
||||
|
||||
mkdir -p "${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/${platform_copy_destination}"
|
||||
cp -pfR \
|
||||
"${PODS_ROOT}/hermes-engine/build/${PLATFORM_NAME}/lib/hermesvm.framework" \
|
||||
"${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/${platform_copy_destination}"
|
||||
|
||||
@@ -18,7 +18,7 @@ SDKROOT=$(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
|
||||
env -i \
|
||||
PATH="$PATH" \
|
||||
SDKROOT="$SDKROOT" \
|
||||
"$CMAKE_BINARY" -S "${PODS_ROOT}/hermes-engine" -B "$hermesc_dir_path" -DJSI_DIR="$jsi_path"
|
||||
"$CMAKE_BINARY" -S "${PODS_ROOT}/hermes-engine" -B "$hermesc_dir_path" -DJSI_DIR="$jsi_path" -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
env -i \
|
||||
PATH="$PATH" \
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const {execSync} = require('child_process');
|
||||
const {spawnSync} = require('child_process');
|
||||
const fs = require('fs');
|
||||
const yargs = require('yargs');
|
||||
|
||||
@@ -62,7 +62,9 @@ function replaceHermesConfiguration(configuration, version, podsRoot) {
|
||||
fs.mkdirSync(finalLocation, {recursive: true});
|
||||
|
||||
console.log('Extracting the tarball');
|
||||
execSync(`tar -xf ${tarballURLPath} -C ${finalLocation}`);
|
||||
spawnSync('tar', ['-xf', tarballURLPath, '-C', finalLocation], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
}
|
||||
|
||||
function updateLastBuildConfiguration(configuration) {
|
||||
|
||||
@@ -29,3 +29,12 @@ include(":packages:react-native:ReactAndroid:hermes-engine")
|
||||
|
||||
project(":packages:react-native:ReactAndroid:hermes-engine").projectDir =
|
||||
file("ReactAndroid/hermes-engine/")
|
||||
|
||||
// Since Gradle 9.0, all the projects in the path must have an existing folder.
|
||||
// As we build :packages:react-native:ReactAndroid, we need to declare the folders
|
||||
// for :packages and :packages:react-native as well as otherwise the build from
|
||||
// source will fail with a missing folder exception.
|
||||
|
||||
project(":packages").projectDir = file("/tmp")
|
||||
|
||||
project(":packages:react-native").projectDir = file("/tmp")
|
||||
|
||||
+54
-29
@@ -12,13 +12,62 @@ import {polyfillGlobal} from '../../../Libraries/Utilities/PolyfillFunctions';
|
||||
|
||||
let initialized = false;
|
||||
|
||||
export default function setUpPerformanceObserver() {
|
||||
export default function setUpPerformanceModern() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
|
||||
const Performance = require('../webapis/performance/Performance').default;
|
||||
|
||||
// We don't use `polyfillGlobal` to define this lazily because the
|
||||
// `performance` object is always accessed.
|
||||
// $FlowExpectedError[cannot-write]
|
||||
global.performance = new Performance();
|
||||
|
||||
polyfillGlobal(
|
||||
'EventCounts',
|
||||
() => require('../webapis/performance/EventTiming').EventCounts_public,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'Performance',
|
||||
() => require('../webapis/performance/Performance').Performance_public,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceEntry',
|
||||
() =>
|
||||
require('../webapis/performance/PerformanceEntry')
|
||||
.PerformanceEntry_public,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceEventTiming',
|
||||
() =>
|
||||
require('../webapis/performance/EventTiming')
|
||||
.PerformanceEventTiming_public,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceLongTaskTiming',
|
||||
() =>
|
||||
require('../webapis/performance/LongTasks')
|
||||
.PerformanceLongTaskTiming_public,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceMark',
|
||||
() => require('../webapis/performance/UserTiming').PerformanceMark,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceMeasure',
|
||||
() =>
|
||||
require('../webapis/performance/UserTiming').PerformanceMeasure_public,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceObserver',
|
||||
() =>
|
||||
@@ -29,43 +78,19 @@ export default function setUpPerformanceObserver() {
|
||||
'PerformanceObserverEntryList',
|
||||
() =>
|
||||
require('../webapis/performance/PerformanceObserver')
|
||||
.PerformanceObserverEntryList,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceEntry',
|
||||
() => require('../webapis/performance/PerformanceEntry').PerformanceEntry,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceMark',
|
||||
() => require('../webapis/performance/UserTiming').PerformanceMark,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceMeasure',
|
||||
() => require('../webapis/performance/UserTiming').PerformanceMeasure,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceEventTiming',
|
||||
() => require('../webapis/performance/EventTiming').PerformanceEventTiming,
|
||||
.PerformanceObserverEntryList_public,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceResourceTiming',
|
||||
() =>
|
||||
require('../webapis/performance/ResourceTiming')
|
||||
.PerformanceResourceTiming,
|
||||
.PerformanceResourceTiming_public,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'TaskAttributionTiming',
|
||||
() => require('../webapis/performance/LongTasks').TaskAttributionTiming,
|
||||
);
|
||||
|
||||
polyfillGlobal(
|
||||
'PerformanceLongTaskTiming',
|
||||
() => require('../webapis/performance/LongTasks').PerformanceLongTaskTiming,
|
||||
() =>
|
||||
require('../webapis/performance/LongTasks').TaskAttributionTiming_public,
|
||||
);
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport';
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
*/
|
||||
|
||||
// flowlint unsafe-getters-setters:off
|
||||
|
||||
import type {
|
||||
DOMHighResTimeStamp,
|
||||
PerformanceEntryInit,
|
||||
PerformanceEntryJSON,
|
||||
} from './PerformanceEntry';
|
||||
|
||||
@@ -29,25 +29,20 @@ export type PerformanceEventTimingJSON = {
|
||||
...
|
||||
};
|
||||
|
||||
export interface PerformanceEventTimingInit extends PerformanceEntryInit {
|
||||
+processingStart?: DOMHighResTimeStamp;
|
||||
+processingEnd?: DOMHighResTimeStamp;
|
||||
+interactionId?: number;
|
||||
}
|
||||
|
||||
export class PerformanceEventTiming extends PerformanceEntry {
|
||||
#processingStart: DOMHighResTimeStamp;
|
||||
#processingEnd: DOMHighResTimeStamp;
|
||||
#interactionId: number;
|
||||
|
||||
constructor(init: {
|
||||
name: string,
|
||||
startTime?: DOMHighResTimeStamp,
|
||||
duration?: DOMHighResTimeStamp,
|
||||
processingStart?: DOMHighResTimeStamp,
|
||||
processingEnd?: DOMHighResTimeStamp,
|
||||
interactionId?: number,
|
||||
}) {
|
||||
super({
|
||||
name: init.name,
|
||||
entryType: 'event',
|
||||
startTime: init.startTime ?? 0,
|
||||
duration: init.duration ?? 0,
|
||||
});
|
||||
constructor(init: PerformanceEventTimingInit) {
|
||||
super('event', init);
|
||||
|
||||
this.#processingStart = init.processingStart ?? 0;
|
||||
this.#processingEnd = init.processingEnd ?? 0;
|
||||
this.#interactionId = init.interactionId ?? 0;
|
||||
@@ -75,6 +70,18 @@ export class PerformanceEventTiming extends PerformanceEntry {
|
||||
}
|
||||
}
|
||||
|
||||
export const PerformanceEventTiming_public: typeof PerformanceEventTiming =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function PerformanceEventTiming() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'PerformanceEventTiming': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
PerformanceEventTiming_public.prototype = PerformanceEventTiming.prototype;
|
||||
|
||||
type EventCountsForEachCallbackType =
|
||||
| (() => void)
|
||||
| ((value: number) => void)
|
||||
@@ -139,3 +146,15 @@ export class EventCounts {
|
||||
return getCachedEventCounts().values();
|
||||
}
|
||||
}
|
||||
|
||||
export const EventCounts_public: typeof EventCounts =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function EventCounts() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'EventCounts': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
EventCounts_public.prototype = EventCounts.prototype;
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
*/
|
||||
|
||||
// flowlint unsafe-getters-setters:off
|
||||
|
||||
import type {PerformanceEntryJSON} from './PerformanceEntry';
|
||||
import type {
|
||||
PerformanceEntryInit,
|
||||
PerformanceEntryJSON,
|
||||
} from './PerformanceEntry';
|
||||
|
||||
import {PerformanceEntry} from './PerformanceEntry';
|
||||
|
||||
@@ -22,10 +24,28 @@ export type PerformanceLongTaskTimingJSON = {
|
||||
|
||||
export class TaskAttributionTiming extends PerformanceEntry {}
|
||||
|
||||
export const TaskAttributionTiming_public: typeof TaskAttributionTiming =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function TaskAttributionTiming() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'TaskAttributionTiming': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
TaskAttributionTiming_public.prototype = TaskAttributionTiming.prototype;
|
||||
|
||||
const EMPTY_ATTRIBUTION: $ReadOnlyArray<TaskAttributionTiming> =
|
||||
Object.preventExtensions([]);
|
||||
|
||||
export interface PerformanceLongTaskTimingInit extends PerformanceEntryInit {}
|
||||
|
||||
export class PerformanceLongTaskTiming extends PerformanceEntry {
|
||||
constructor(init: PerformanceEntryInit) {
|
||||
super('longtask', init);
|
||||
}
|
||||
|
||||
get attribution(): $ReadOnlyArray<TaskAttributionTiming> {
|
||||
return EMPTY_ATTRIBUTION;
|
||||
}
|
||||
@@ -37,3 +57,16 @@ export class PerformanceLongTaskTiming extends PerformanceEntry {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const PerformanceLongTaskTiming_public: typeof PerformanceLongTaskTiming =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function PerformanceLongTaskTiming() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'PerformanceLongTaskTiming': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
PerformanceLongTaskTiming_public.prototype =
|
||||
PerformanceLongTaskTiming.prototype;
|
||||
|
||||
@@ -64,12 +64,13 @@ const cachedGetMarkTime = NativePerformance.getMarkTime;
|
||||
const cachedNativeClearMarks = NativePerformance.clearMarks;
|
||||
const cachedNativeClearMeasures = NativePerformance.clearMeasures;
|
||||
|
||||
const MARK_OPTIONS_REUSABLE_OBJECT: {...PerformanceMarkOptions} = {
|
||||
const MARK_OPTIONS_REUSABLE_OBJECT: PerformanceMarkOptions = {
|
||||
startTime: 0,
|
||||
detail: undefined,
|
||||
};
|
||||
|
||||
const MEASURE_OPTIONS_REUSABLE_OBJECT: {...PerformanceMeasureInit} = {
|
||||
const MEASURE_OPTIONS_REUSABLE_OBJECT: PerformanceMeasureInit = {
|
||||
name: '',
|
||||
startTime: 0,
|
||||
duration: 0,
|
||||
detail: undefined,
|
||||
@@ -189,7 +190,9 @@ export default class Performance {
|
||||
resolvedDetail = structuredClone(detail);
|
||||
}
|
||||
|
||||
// $FlowExpectedError[cannot-write]
|
||||
MARK_OPTIONS_REUSABLE_OBJECT.startTime = resolvedStartTime;
|
||||
// $FlowExpectedError[cannot-write]
|
||||
MARK_OPTIONS_REUSABLE_OBJECT.detail = resolvedDetail;
|
||||
|
||||
const entry = new PerformanceMark(
|
||||
@@ -367,14 +370,16 @@ export default class Performance {
|
||||
}
|
||||
}
|
||||
|
||||
// $FlowExpectedError[cannot-write]
|
||||
MEASURE_OPTIONS_REUSABLE_OBJECT.name = resolvedMeasureName;
|
||||
// $FlowExpectedError[cannot-write]
|
||||
MEASURE_OPTIONS_REUSABLE_OBJECT.startTime = resolvedStartTime;
|
||||
// $FlowExpectedError[cannot-write]
|
||||
MEASURE_OPTIONS_REUSABLE_OBJECT.duration = resolvedDuration;
|
||||
// $FlowExpectedError[cannot-write]
|
||||
MEASURE_OPTIONS_REUSABLE_OBJECT.detail = resolvedDetail;
|
||||
|
||||
const entry = new PerformanceMeasure(
|
||||
resolvedMeasureName,
|
||||
MEASURE_OPTIONS_REUSABLE_OBJECT,
|
||||
);
|
||||
const entry = new PerformanceMeasure(MEASURE_OPTIONS_REUSABLE_OBJECT);
|
||||
|
||||
cachedReportMeasure(
|
||||
resolvedMeasureName,
|
||||
@@ -438,4 +443,16 @@ export default class Performance {
|
||||
}
|
||||
}
|
||||
|
||||
export const Performance_public: typeof Performance =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function Performance() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'Performance': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
Performance_public.prototype = Performance.prototype;
|
||||
|
||||
setPlatformObject(Performance);
|
||||
|
||||
@@ -28,24 +28,25 @@ export type PerformanceEntryJSON = {
|
||||
...
|
||||
};
|
||||
|
||||
export interface PerformanceEntryInit {
|
||||
+name: string;
|
||||
+startTime: DOMHighResTimeStamp;
|
||||
+duration: DOMHighResTimeStamp;
|
||||
}
|
||||
|
||||
export class PerformanceEntry {
|
||||
// We don't use private fields because they're significantly slower to
|
||||
// initialize on construction and to access.
|
||||
// We also need these to be protected so they can be initialized in subclasses
|
||||
// where we avoid calling `super()` for performance reasons.
|
||||
__name: string;
|
||||
__entryType: PerformanceEntryType;
|
||||
__name: string;
|
||||
__startTime: DOMHighResTimeStamp;
|
||||
__duration: DOMHighResTimeStamp;
|
||||
|
||||
constructor(init: {
|
||||
name: string,
|
||||
entryType: PerformanceEntryType,
|
||||
startTime: DOMHighResTimeStamp,
|
||||
duration: DOMHighResTimeStamp,
|
||||
}) {
|
||||
constructor(entryType: PerformanceEntryType, init: PerformanceEntryInit) {
|
||||
this.__entryType = entryType;
|
||||
this.__name = init.name;
|
||||
this.__entryType = init.entryType;
|
||||
this.__startTime = init.startTime;
|
||||
this.__duration = init.duration;
|
||||
}
|
||||
@@ -76,6 +77,18 @@ export class PerformanceEntry {
|
||||
}
|
||||
}
|
||||
|
||||
export const PerformanceEntry_public: typeof PerformanceEntry =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function PerformanceEntry() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'PerformanceEntry': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
PerformanceEntry_public.prototype = PerformanceEntry.prototype;
|
||||
|
||||
setPlatformObject(PerformanceEntry);
|
||||
|
||||
export type PerformanceEntryList = $ReadOnlyArray<PerformanceEntry>;
|
||||
|
||||
+30
-1
@@ -57,6 +57,19 @@ export class PerformanceObserverEntryList {
|
||||
}
|
||||
}
|
||||
|
||||
export const PerformanceObserverEntryList_public: typeof PerformanceObserverEntryList =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function PerformanceObserverEntryList() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'PerformanceObserverEntryList': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
PerformanceObserverEntryList_public.prototype =
|
||||
PerformanceObserverEntryList.prototype;
|
||||
|
||||
export type PerformanceObserverCallbackOptions = {
|
||||
droppedEntriesCount: number,
|
||||
};
|
||||
@@ -145,6 +158,22 @@ export class PerformanceObserver {
|
||||
NativePerformance.disconnect(this.#nativeObserverHandle);
|
||||
}
|
||||
|
||||
takeRecords(): PerformanceEntryList {
|
||||
let entries: PerformanceEntryList = [];
|
||||
|
||||
if (this.#nativeObserverHandle != null) {
|
||||
const rawEntries = NativePerformance.takeRecords(
|
||||
this.#nativeObserverHandle,
|
||||
true,
|
||||
);
|
||||
if (rawEntries && rawEntries.length > 0) {
|
||||
entries = rawEntries.map(rawToPerformanceEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
#createNativeObserver(): OpaqueNativeObserverHandle | null {
|
||||
this.#calledAtLeastOnce = false;
|
||||
|
||||
@@ -154,7 +183,7 @@ export class PerformanceObserver {
|
||||
observerHandle,
|
||||
true, // sort records
|
||||
);
|
||||
if (!rawEntries) {
|
||||
if (!rawEntries || rawEntries.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,19 @@ export type PerformanceResourceTimingJSON = {
|
||||
...
|
||||
};
|
||||
|
||||
export interface PerformanceResourceTimingInit {
|
||||
+name: string;
|
||||
+startTime: DOMHighResTimeStamp;
|
||||
+duration: DOMHighResTimeStamp;
|
||||
+fetchStart: DOMHighResTimeStamp;
|
||||
+requestStart: DOMHighResTimeStamp;
|
||||
+connectStart: DOMHighResTimeStamp;
|
||||
+connectEnd: DOMHighResTimeStamp;
|
||||
+responseStart: DOMHighResTimeStamp;
|
||||
+responseEnd: DOMHighResTimeStamp;
|
||||
+responseStatus?: number;
|
||||
}
|
||||
|
||||
export class PerformanceResourceTiming extends PerformanceEntry {
|
||||
#fetchStart: DOMHighResTimeStamp;
|
||||
#requestStart: DOMHighResTimeStamp;
|
||||
@@ -38,24 +51,9 @@ export class PerformanceResourceTiming extends PerformanceEntry {
|
||||
#responseEnd: DOMHighResTimeStamp;
|
||||
#responseStatus: ?number;
|
||||
|
||||
constructor(init: {
|
||||
name: string,
|
||||
startTime: DOMHighResTimeStamp,
|
||||
duration: DOMHighResTimeStamp,
|
||||
fetchStart: DOMHighResTimeStamp,
|
||||
requestStart: DOMHighResTimeStamp,
|
||||
connectStart: DOMHighResTimeStamp,
|
||||
connectEnd: DOMHighResTimeStamp,
|
||||
responseStart: DOMHighResTimeStamp,
|
||||
responseEnd: DOMHighResTimeStamp,
|
||||
responseStatus?: number,
|
||||
}) {
|
||||
super({
|
||||
name: init.name,
|
||||
entryType: 'resource',
|
||||
startTime: init.startTime,
|
||||
duration: init.duration,
|
||||
});
|
||||
constructor(init: PerformanceResourceTimingInit) {
|
||||
super('resource', init);
|
||||
|
||||
this.#fetchStart = init.fetchStart;
|
||||
this.#requestStart = init.requestStart;
|
||||
this.#connectStart = init.connectStart;
|
||||
@@ -106,3 +104,16 @@ export class PerformanceResourceTiming extends PerformanceEntry {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const PerformanceResourceTiming_public: typeof PerformanceResourceTiming =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function PerformanceResourceTiming() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'PerformanceResourceTiming': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
PerformanceResourceTiming_public.prototype =
|
||||
PerformanceResourceTiming.prototype;
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
*/
|
||||
|
||||
// flowlint unsafe-getters-setters:off
|
||||
|
||||
import type {DOMHighResTimeStamp} from './PerformanceEntry';
|
||||
import type {
|
||||
DOMHighResTimeStamp,
|
||||
PerformanceEntryInit,
|
||||
} from './PerformanceEntry';
|
||||
import type {
|
||||
ExtensionMarkerPayload,
|
||||
ExtensionTrackEntryPayload,
|
||||
@@ -25,18 +27,16 @@ export type DetailType =
|
||||
// but we'll use it as documentation for how to use the extensibility API.
|
||||
| {devtools?: ExtensionMarkerPayload | ExtensionTrackEntryPayload, ...};
|
||||
|
||||
export type PerformanceMarkOptions = $ReadOnly<{
|
||||
detail?: DetailType,
|
||||
startTime?: DOMHighResTimeStamp,
|
||||
}>;
|
||||
export interface PerformanceMarkOptions {
|
||||
+detail?: DetailType;
|
||||
+startTime?: DOMHighResTimeStamp;
|
||||
}
|
||||
|
||||
export type TimeStampOrName = DOMHighResTimeStamp | string;
|
||||
|
||||
export type PerformanceMeasureInit = $ReadOnly<{
|
||||
detail?: DetailType,
|
||||
startTime: DOMHighResTimeStamp,
|
||||
duration: DOMHighResTimeStamp,
|
||||
}>;
|
||||
export interface PerformanceMeasureInit extends PerformanceEntryInit {
|
||||
+detail?: DetailType;
|
||||
}
|
||||
|
||||
class PerformanceMarkTemplate extends PerformanceEntry {
|
||||
// We don't use private fields because they're significantly slower to
|
||||
@@ -45,9 +45,8 @@ class PerformanceMarkTemplate extends PerformanceEntry {
|
||||
|
||||
// This constructor isn't really used. See `PerformanceMark` below.
|
||||
constructor(markName: string, markOptions?: PerformanceMarkOptions) {
|
||||
super({
|
||||
super('mark', {
|
||||
name: markName,
|
||||
entryType: 'mark',
|
||||
startTime: markOptions?.startTime ?? getCurrentTimeStamp(),
|
||||
duration: 0,
|
||||
});
|
||||
@@ -72,8 +71,8 @@ export const PerformanceMark: typeof PerformanceMarkTemplate =
|
||||
markName: string,
|
||||
markOptions?: PerformanceMarkOptions,
|
||||
) {
|
||||
this.__name = markName;
|
||||
this.__entryType = 'mark';
|
||||
this.__name = markName;
|
||||
this.__startTime = markOptions?.startTime ?? getCurrentTimeStamp();
|
||||
this.__duration = 0;
|
||||
|
||||
@@ -89,15 +88,10 @@ class PerformanceMeasureTemplate extends PerformanceEntry {
|
||||
__detail: DetailType;
|
||||
|
||||
// This constructor isn't really used. See `PerformanceMeasure` below.
|
||||
constructor(measureName: string, measureOptions: PerformanceMeasureInit) {
|
||||
super({
|
||||
name: measureName,
|
||||
entryType: 'measure',
|
||||
startTime: measureOptions.startTime,
|
||||
duration: measureOptions.duration,
|
||||
});
|
||||
constructor(init: PerformanceMeasureInit) {
|
||||
super('measure', init);
|
||||
|
||||
this.__detail = measureOptions?.detail ?? null;
|
||||
this.__detail = init?.detail ?? null;
|
||||
}
|
||||
|
||||
get detail(): DetailType {
|
||||
@@ -110,16 +104,27 @@ export const PerformanceMeasure: typeof PerformanceMeasureTemplate =
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function PerformanceMeasure(
|
||||
this: PerformanceMeasureTemplate,
|
||||
measureName: string,
|
||||
measureOptions: PerformanceMeasureInit,
|
||||
init: PerformanceMeasureInit,
|
||||
) {
|
||||
this.__name = measureName;
|
||||
this.__entryType = 'measure';
|
||||
this.__startTime = measureOptions.startTime;
|
||||
this.__duration = measureOptions.duration;
|
||||
this.__name = init.name;
|
||||
this.__startTime = init.startTime;
|
||||
this.__duration = init.duration;
|
||||
|
||||
this.__detail = measureOptions.detail ?? null;
|
||||
this.__detail = init.detail ?? null;
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
PerformanceMeasure.prototype = PerformanceMeasureTemplate.prototype;
|
||||
|
||||
export const PerformanceMeasure_public: typeof PerformanceMeasure =
|
||||
/* eslint-disable no-shadow */
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
function PerformanceMeasure() {
|
||||
throw new TypeError(
|
||||
"Failed to construct 'PerformanceMeasure': Illegal constructor",
|
||||
);
|
||||
};
|
||||
|
||||
// $FlowExpectedError[prop-missing]
|
||||
PerformanceMeasure_public.prototype = PerformanceMeasure.prototype;
|
||||
|
||||
+15
-10
@@ -10,24 +10,14 @@
|
||||
|
||||
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
|
||||
|
||||
import type Performance from 'react-native/src/private/webapis/performance/Performance';
|
||||
import type {PerformanceObserverEntryList} from 'react-native/src/private/webapis/performance/PerformanceObserver';
|
||||
|
||||
import MaybeNativePerformance from '../specs/NativePerformance';
|
||||
import * as Fantom from '@react-native/fantom';
|
||||
import nullthrows from 'nullthrows';
|
||||
import {useState} from 'react';
|
||||
import {Text, View} from 'react-native';
|
||||
import setUpPerformanceObserver from 'react-native/src/private/setup/setUpPerformanceObserver';
|
||||
import {PerformanceEventTiming} from 'react-native/src/private/webapis/performance/EventTiming';
|
||||
import {PerformanceObserver} from 'react-native/src/private/webapis/performance/PerformanceObserver';
|
||||
|
||||
const NativePerformance = nullthrows(MaybeNativePerformance);
|
||||
|
||||
setUpPerformanceObserver();
|
||||
|
||||
declare var performance: Performance;
|
||||
|
||||
function sleep(ms: number) {
|
||||
const end = performance.now() + ms;
|
||||
while (performance.now() < end) {}
|
||||
@@ -251,6 +241,21 @@ describe('Event Timing API', () => {
|
||||
expect([...performance.eventCounts.values()]).toEqual([1, 1, 3]);
|
||||
});
|
||||
|
||||
it('does NOT allow creating instances of PerformanceEventTiming directly', () => {
|
||||
expect(() => {
|
||||
return new PerformanceEventTiming();
|
||||
}).toThrow(
|
||||
"Failed to construct 'PerformanceEventTiming': Illegal constructor",
|
||||
);
|
||||
});
|
||||
|
||||
it('does NOT allow creating instances of EventCounts directly', () => {
|
||||
expect(() => {
|
||||
// $FlowExpectedError[cannot-resolve-name]
|
||||
return new EventCounts();
|
||||
}).toThrow("Failed to construct 'EventCounts': Illegal constructor");
|
||||
});
|
||||
|
||||
describe('durationThreshold option', () => {
|
||||
it('works when used with `type`', () => {
|
||||
const callback = jest.fn();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user