mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f13eb0a68 | ||
|
|
f70a146699 | ||
|
|
d9c2857e59 | ||
|
|
cbf1710fd5 | ||
|
|
3ac16dd6a8 | ||
|
|
3ad0b8244a | ||
|
|
a02052d37f | ||
|
|
e69e35e370 | ||
|
|
f85b30b24b | ||
|
|
2562440385 | ||
|
|
43c9a609de | ||
|
|
e565c662d7 | ||
|
|
f1e7bbb88b | ||
|
|
f4936894f0 | ||
|
|
d9823d80bb |
@@ -24,6 +24,6 @@ jobs:
|
||||
with:
|
||||
script: |
|
||||
const {createDraftRelease} = require('./.github/workflow-scripts/createDraftRelease.js');
|
||||
const version = ${{ github.ref_name }}';
|
||||
const version = '${{ github.ref_name }}';
|
||||
const {isLatest} = require('./.github/workflow-scripts/publishTemplate.js');
|
||||
await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}');
|
||||
|
||||
+2
-2
@@ -52,8 +52,8 @@
|
||||
"@babel/preset-flow": "^7.24.7",
|
||||
"@definitelytyped/dtslint": "^0.0.127",
|
||||
"@jest/create-cache-key-function": "^29.7.0",
|
||||
"@react-native/metro-babel-transformer": "0.80.0-main",
|
||||
"@react-native/metro-config": "0.80.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.80.0-rc.0",
|
||||
"@react-native/metro-config": "0.80.0-rc.0",
|
||||
"@tsconfig/node18": "1.0.1",
|
||||
"@types/react": "^19.0.0",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/assets-registry",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Asset support code for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-plugin-codegen",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"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.80.0-main"
|
||||
"@react-native/codegen": "0.80.0-rc.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/community-cli-plugin",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Core CLI commands for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -22,7 +22,7 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/dev-middleware": "0.80.0-main",
|
||||
"@react-native/dev-middleware": "0.80.0-rc.0",
|
||||
"chalk": "^4.0.0",
|
||||
"debug": "^4.4.0",
|
||||
"invariant": "^2.2.4",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/core-cli-utils",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"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.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Debugger frontend for React Native based on Chrome DevTools",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/dev-middleware",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Dev server middleware for React Native",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
@@ -23,7 +23,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@isaacs/ttlcache": "^1.4.1",
|
||||
"@react-native/debugger-frontend": "0.80.0-main",
|
||||
"@react-native/debugger-frontend": "0.80.0-rc.0",
|
||||
"chrome-launcher": "^0.15.2",
|
||||
"chromium-edge-launcher": "^0.2.0",
|
||||
"connect": "^3.6.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-config",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"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.80.0-main",
|
||||
"@react-native/eslint-plugin": "0.80.0-rc.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "ESLint rules for @react-native/eslint-config",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/eslint-plugin-specs",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"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.80.0-main",
|
||||
"@react-native/codegen": "0.80.0-rc.0",
|
||||
"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.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Gradle Plugin for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "helloworld",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"bootstrap": "node ./cli.js bootstrap",
|
||||
@@ -13,16 +13,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "19.1.0",
|
||||
"react-native": "1000.0.0"
|
||||
"react-native": "0.80.0-rc.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/runtime": "^7.25.0",
|
||||
"@react-native/babel-preset": "0.80.0-main",
|
||||
"@react-native/core-cli-utils": "0.80.0-main",
|
||||
"@react-native/eslint-config": "0.80.0-main",
|
||||
"@react-native/metro-config": "0.80.0-main",
|
||||
"@react-native/babel-preset": "0.80.0-rc.0",
|
||||
"@react-native/core-cli-utils": "0.80.0-rc.0",
|
||||
"@react-native/eslint-config": "0.80.0-rc.0",
|
||||
"@react-native/metro-config": "0.80.0-rc.0",
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^12.0.0",
|
||||
"eslint": "^8.19.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-config",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Metro configuration for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -26,8 +26,8 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@react-native/js-polyfills": "0.80.0-main",
|
||||
"@react-native/metro-babel-transformer": "0.80.0-main",
|
||||
"@react-native/js-polyfills": "0.80.0-rc.0",
|
||||
"@react-native/metro-babel-transformer": "0.80.0-rc.0",
|
||||
"metro-config": "^0.82.2",
|
||||
"metro-runtime": "^0.82.2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/new-app-screen",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "NewAppScreen component for React Native",
|
||||
"keywords": [
|
||||
"react-native"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/normalize-colors",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Color normalization for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/js-polyfills",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Polyfills for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/babel-preset",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"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.80.0-main",
|
||||
"@react-native/babel-plugin-codegen": "0.80.0-rc.0",
|
||||
"babel-plugin-syntax-hermes-parser": "0.28.1",
|
||||
"babel-plugin-transform-flow-enums": "^0.0.2",
|
||||
"react-refresh": "^0.14.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/metro-babel-transformer",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"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.80.0-main",
|
||||
"@react-native/babel-preset": "0.80.0-rc.0",
|
||||
"hermes-parser": "0.28.1",
|
||||
"nullthrows": "^1.1.1"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-native/bots",
|
||||
"description": "React Native Bots",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen-typescript-test",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"private": true,
|
||||
"description": "TypeScript related unit test for @react-native/codegen",
|
||||
"license": "MIT",
|
||||
@@ -19,7 +19,7 @@
|
||||
"prepare": "yarn run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native/codegen": "0.80.0-main"
|
||||
"@react-native/codegen": "0.80.0-rc.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/codegen",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Code generation tools for React Native",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/compatibility-check",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"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.80.0-main"
|
||||
"@react-native/codegen": "0.80.0-rc.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"flow-remove-types": "^2.237.2",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-native/fantom",
|
||||
"private": true,
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"main": "src/index.js",
|
||||
"description": "Internal integration testing and benchmarking tool for React Native",
|
||||
"peerDependencies": {
|
||||
|
||||
+14
@@ -566,6 +566,20 @@ if (typeof global.EventTarget === 'undefined') {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function that returns the current reference count for the supplied
|
||||
* element's shadow node. If the reference count is zero, that means the shadow
|
||||
* node has been deallocated.
|
||||
*
|
||||
* @param node The node for which to create a reference counting function.
|
||||
*/
|
||||
export function createShadowNodeReferenceCounter(
|
||||
node: ReactNativeElement,
|
||||
): () => number {
|
||||
let shadowNode = getNativeNodeReference(node);
|
||||
return NativeFantom.createShadowNodeReferenceCounter(shadowNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a heap snapshot after forcing garbage collection.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/popup-menu-android",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "PopupMenu for the Android platform",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@react-native/codegen": "0.80.0-main"
|
||||
"@react-native/codegen": "0.80.0-rc.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/oss-library-example",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"private": true,
|
||||
"description": "Package that includes native module exapmle, native component example, targets both the old and the new architecture. It should serve as an example of a real-world OSS library.",
|
||||
"license": "MIT",
|
||||
@@ -26,8 +26,8 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@react-native/babel-preset": "0.80.0-main",
|
||||
"react-native": "1000.0.0"
|
||||
"@react-native/babel-preset": "0.80.0-rc.0",
|
||||
"react-native": "0.80.0-rc.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
|
||||
@@ -14,8 +14,8 @@ export const version: $ReadOnly<{
|
||||
patch: number,
|
||||
prerelease: string | null,
|
||||
}> = {
|
||||
major: 1000,
|
||||
minor: 0,
|
||||
major: 0,
|
||||
minor: 80,
|
||||
patch: 0,
|
||||
prerelease: null,
|
||||
prerelease: 'rc.0',
|
||||
};
|
||||
|
||||
@@ -317,6 +317,45 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, CGSize size, CGFloat scal
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function abstracts away the migration from loadImageForURL to loadImageURL by handling checking whether
|
||||
* the interface responds to the new function signature and calling the appropriate function based on the result.
|
||||
*/
|
||||
static RCTImageLoaderCancellationBlock RCTLoadImageURLFromLoader(
|
||||
id<RCTImageURLLoader> loadHandler,
|
||||
NSURL *imageURL,
|
||||
CGSize size,
|
||||
CGFloat scale,
|
||||
RCTResizeMode resizeMode,
|
||||
RCTImageLoaderProgressBlock progressHandler,
|
||||
RCTImageLoaderPartialLoadBlock partialLoadHandler,
|
||||
RCTImageLoaderCompletionBlockWithMetadata completionHandler)
|
||||
{
|
||||
if ([loadHandler respondsToSelector:@selector(loadImageForURL:
|
||||
size:scale:resizeMode:progressHandler:partialLoadHandler
|
||||
:completionHandlerWithMetadata:)]) {
|
||||
return [loadHandler loadImageForURL:imageURL
|
||||
size:size
|
||||
scale:scale
|
||||
resizeMode:resizeMode
|
||||
progressHandler:progressHandler
|
||||
partialLoadHandler:partialLoadHandler
|
||||
completionHandlerWithMetadata:^(NSError *error, UIImage *image, id metadata) {
|
||||
completionHandler(error, image, metadata);
|
||||
}];
|
||||
} else {
|
||||
return [loadHandler loadImageForURL:imageURL
|
||||
size:size
|
||||
scale:scale
|
||||
resizeMode:resizeMode
|
||||
progressHandler:progressHandler
|
||||
partialLoadHandler:partialLoadHandler
|
||||
completionHandler:^(NSError *error, UIImage *image) {
|
||||
completionHandler(error, image, nil);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - RCTImageLoaderProtocol 2/3
|
||||
|
||||
- (nullable RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)imageURLRequest
|
||||
@@ -566,15 +605,18 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, CGSize size, CGFloat scal
|
||||
completionHandler(error, image, metadata, nil);
|
||||
}];
|
||||
}
|
||||
RCTImageLoaderCancellationBlock cb = [loadHandler loadImageForURL:request.URL
|
||||
size:size
|
||||
scale:scale
|
||||
resizeMode:resizeMode
|
||||
progressHandler:progressHandler
|
||||
partialLoadHandler:partialLoadHandler
|
||||
completionHandler:^(NSError *error, UIImage *image) {
|
||||
completionHandler(error, image, nil, nil);
|
||||
}];
|
||||
|
||||
RCTImageLoaderCancellationBlock cb = RCTLoadImageURLFromLoader(
|
||||
loadHandler,
|
||||
request.URL,
|
||||
size,
|
||||
scale,
|
||||
resizeMode,
|
||||
progressHandler,
|
||||
partialLoadHandler,
|
||||
^(NSError *error, UIImage *image, id metadata) {
|
||||
completionHandler(error, image, metadata, nil);
|
||||
});
|
||||
return [[RCTImageURLLoaderRequest alloc] initWithRequestId:nil imageURL:request.URL cancellationBlock:cb];
|
||||
}
|
||||
|
||||
@@ -608,15 +650,17 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, CGSize size, CGFloat scal
|
||||
}];
|
||||
cancelLoadLocal = loaderRequest.cancellationBlock;
|
||||
} else {
|
||||
cancelLoadLocal = [loadHandler loadImageForURL:request.URL
|
||||
size:size
|
||||
scale:scale
|
||||
resizeMode:resizeMode
|
||||
progressHandler:progressHandler
|
||||
partialLoadHandler:partialLoadHandler
|
||||
completionHandler:^(NSError *error, UIImage *image) {
|
||||
completionHandler(error, image, nil, nil);
|
||||
}];
|
||||
cancelLoadLocal = RCTLoadImageURLFromLoader(
|
||||
loadHandler,
|
||||
request.URL,
|
||||
size,
|
||||
scale,
|
||||
resizeMode,
|
||||
progressHandler,
|
||||
partialLoadHandler,
|
||||
^(NSError *error, UIImage *image, id metadata) {
|
||||
completionHandler(error, image, metadata, nil);
|
||||
});
|
||||
}
|
||||
[cancelLoadLock lock];
|
||||
cancelLoad = cancelLoadLocal;
|
||||
@@ -867,7 +911,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, CGSize size, CGFloat scal
|
||||
{
|
||||
id<RCTImageURLLoader> loadHandler = [self imageURLLoaderForURL:url];
|
||||
if ([loadHandler respondsToSelector:@selector(shouldEnablePerfLogging)]) {
|
||||
return [(id<RCTImageURLLoaderWithAttribution>)loadHandler shouldEnablePerfLogging];
|
||||
return [(id<RCTImageLoaderLoggable>)loadHandler shouldEnablePerfLogging];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock;
|
||||
- (BOOL)canLoadImageURL:(NSURL *)requestURL;
|
||||
|
||||
/**
|
||||
* DEPRECATED: Please use updated signature for loadImageForURL which uses
|
||||
* completionHandlerWithMetadata instead.
|
||||
* Send a network request to load the request URL. The method should call the
|
||||
* progressHandler (if applicable) and the completionHandler when the request
|
||||
* has finished. The method should also return a cancellation block, if
|
||||
@@ -49,10 +51,26 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock;
|
||||
resizeMode:(RCTResizeMode)resizeMode
|
||||
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
|
||||
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
|
||||
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler;
|
||||
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
|
||||
RCT_DEPRECATED;
|
||||
|
||||
@optional
|
||||
|
||||
/*
|
||||
* Send a network request to load the request URL. The method should call the
|
||||
* progressHandler (if applicable) and the completionHandler when the request
|
||||
* has finished. The method should also return a cancellation block, if
|
||||
* applicable.
|
||||
*/
|
||||
- (nullable RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL
|
||||
size:(CGSize)size
|
||||
scale:(CGFloat)scale
|
||||
resizeMode:(RCTResizeMode)resizeMode
|
||||
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
|
||||
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
|
||||
completionHandlerWithMetadata:
|
||||
(RCTImageLoaderCompletionBlockWithMetadata)completionHandlerWithMetadata;
|
||||
|
||||
/**
|
||||
* If more than one RCTImageURLLoader responds YES to `-canLoadImageURL:`
|
||||
* then `loaderPriority` is used to determine which one to use. The loader
|
||||
|
||||
@@ -21,10 +21,10 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^(void){
|
||||
__rnVersion = @{
|
||||
RCTVersionMajor: @(1000),
|
||||
RCTVersionMinor: @(0),
|
||||
RCTVersionMajor: @(0),
|
||||
RCTVersionMinor: @(80),
|
||||
RCTVersionPatch: @(0),
|
||||
RCTVersionPrerelease: [NSNull null],
|
||||
RCTVersionPrerelease: @"rc.0",
|
||||
};
|
||||
});
|
||||
return __rnVersion;
|
||||
|
||||
@@ -2392,12 +2392,14 @@ public class com/facebook/react/fabric/FabricUIManager : com/facebook/react/brid
|
||||
public fun initialize ()V
|
||||
public fun invalidate ()V
|
||||
public fun markActiveTouchForTag (II)V
|
||||
public fun measurePreparedLayout (Lcom/facebook/react/views/text/PreparedLayout;FFFF)[F
|
||||
public fun onAllAnimationsComplete ()V
|
||||
public fun onAnimationStarted ()V
|
||||
public fun onHostDestroy ()V
|
||||
public fun onHostPause ()V
|
||||
public fun onHostResume ()V
|
||||
public fun onRequestEventBeat ()V
|
||||
public fun prepareLayout (ILcom/facebook/react/common/mapbuffer/ReadableMapBuffer;Lcom/facebook/react/common/mapbuffer/ReadableMapBuffer;FF)Lcom/facebook/react/views/text/PreparedLayout;
|
||||
public fun prependUIBlock (Lcom/facebook/react/fabric/interop/UIBlock;)V
|
||||
public fun profileNextBatch ()V
|
||||
public fun receiveEvent (IILjava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1000.0.0
|
||||
VERSION_NAME=0.80.0-rc.0
|
||||
react.internal.publishingGroup=com.facebook.react
|
||||
|
||||
android.useAndroidX=true
|
||||
|
||||
+47
@@ -22,11 +22,13 @@ import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.os.SystemClock;
|
||||
import android.text.Layout;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import androidx.annotation.AnyThread;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.core.util.Preconditions;
|
||||
import androidx.core.view.ViewCompat.FocusRealDirection;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
@@ -49,6 +51,7 @@ import com.facebook.react.bridge.UIManager;
|
||||
import com.facebook.react.bridge.UIManagerListener;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
|
||||
import com.facebook.react.common.build.ReactBuildConfig;
|
||||
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
|
||||
@@ -86,6 +89,7 @@ import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.FabricEventDispatcher;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.facebook.react.uimanager.events.SynchronousEventReceiver;
|
||||
import com.facebook.react.views.text.PreparedLayout;
|
||||
import com.facebook.react.views.text.TextLayoutManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -648,6 +652,49 @@ public class FabricUIManager
|
||||
attachmentsPositions);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@ThreadConfined(ANY)
|
||||
public PreparedLayout prepareLayout(
|
||||
int surfaceId,
|
||||
ReadableMapBuffer attributedString,
|
||||
ReadableMapBuffer paragraphAttributes,
|
||||
float maxWidth,
|
||||
float maxHeight) {
|
||||
SurfaceMountingManager surfaceMountingManager =
|
||||
mMountingManager.getSurfaceManagerEnforced(surfaceId, "prepareLayout");
|
||||
Layout layout =
|
||||
TextLayoutManager.createLayout(
|
||||
Preconditions.checkNotNull(surfaceMountingManager.getContext()),
|
||||
attributedString,
|
||||
paragraphAttributes,
|
||||
PixelUtil.toPixelFromDIP(maxWidth),
|
||||
PixelUtil.toPixelFromDIP(maxHeight),
|
||||
null /* T219881133: Migrate away from ReactTextViewManagerCallback */);
|
||||
|
||||
int maximumNumberOfLines =
|
||||
paragraphAttributes.contains(TextLayoutManager.PA_KEY_MAX_NUMBER_OF_LINES)
|
||||
? paragraphAttributes.getInt(TextLayoutManager.PA_KEY_MAX_NUMBER_OF_LINES)
|
||||
: ReactConstants.UNSET;
|
||||
|
||||
return new PreparedLayout(layout, maximumNumberOfLines);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@ThreadConfined(ANY)
|
||||
public float[] measurePreparedLayout(
|
||||
PreparedLayout preparedLayout,
|
||||
float minWidth,
|
||||
float maxWidth,
|
||||
float minHeight,
|
||||
float maxHeight) {
|
||||
return TextLayoutManager.measurePreparedLayout(
|
||||
preparedLayout,
|
||||
getYogaSize(minWidth, maxWidth),
|
||||
getYogaMeasureMode(minWidth, maxWidth),
|
||||
getYogaSize(minHeight, maxHeight),
|
||||
getYogaMeasureMode(minHeight, maxHeight));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param surfaceId {@link int} surface ID
|
||||
* @param defaultTextInputPadding {@link float[]} output parameter will contain the default theme
|
||||
|
||||
+13
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<b86b8bb1d53ca03240c25adb8b423040>>
|
||||
* @generated SignedSource<<453f8c0a593b173c197fcf54ed834a1b>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -90,6 +90,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun enableCustomFocusSearchOnClippedElementsAndroid(): Boolean = accessor.enableCustomFocusSearchOnClippedElementsAndroid()
|
||||
|
||||
/**
|
||||
* Enables destructor calls for ShadowTreeRevision in the background to reduce UI thread work.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun enableDestroyShadowTreeRevisionAsync(): Boolean = accessor.enableDestroyShadowTreeRevisionAsync()
|
||||
|
||||
/**
|
||||
* When enabled a subset of components will avoid double measurement on Android.
|
||||
*/
|
||||
@@ -174,6 +180,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun enableNewBackgroundAndBorderDrawables(): Boolean = accessor.enableNewBackgroundAndBorderDrawables()
|
||||
|
||||
/**
|
||||
* Enables caching text layout artifacts for later reuse
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun enablePreparedTextLayout(): Boolean = accessor.enablePreparedTextLayout()
|
||||
|
||||
/**
|
||||
* When enabled, Android will receive prop updates based on the differences between the last rendered shadow node and the last committed shadow node.
|
||||
*/
|
||||
|
||||
+21
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<9c1e0e7e87aead96e2554ef5ecf9e7af>>
|
||||
* @generated SignedSource<<a51441451ec25033040ba044ee3371fc>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -30,6 +30,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var enableBridgelessArchitectureCache: Boolean? = null
|
||||
private var enableCppPropsIteratorSetterCache: Boolean? = null
|
||||
private var enableCustomFocusSearchOnClippedElementsAndroidCache: Boolean? = null
|
||||
private var enableDestroyShadowTreeRevisionAsyncCache: Boolean? = null
|
||||
private var enableDoubleMeasurementFixAndroidCache: Boolean? = null
|
||||
private var enableEagerRootViewAttachmentCache: Boolean? = null
|
||||
private var enableFabricLogsCache: Boolean? = null
|
||||
@@ -44,6 +45,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var enableNativeCSSParsingCache: Boolean? = null
|
||||
private var enableNetworkEventReportingCache: Boolean? = null
|
||||
private var enableNewBackgroundAndBorderDrawablesCache: Boolean? = null
|
||||
private var enablePreparedTextLayoutCache: Boolean? = null
|
||||
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
|
||||
private var enableResourceTimingAPICache: Boolean? = null
|
||||
private var enableSynchronousStateUpdatesCache: Boolean? = null
|
||||
@@ -156,6 +158,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableDestroyShadowTreeRevisionAsync(): Boolean {
|
||||
var cached = enableDestroyShadowTreeRevisionAsyncCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.enableDestroyShadowTreeRevisionAsync()
|
||||
enableDestroyShadowTreeRevisionAsyncCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableDoubleMeasurementFixAndroid(): Boolean {
|
||||
var cached = enableDoubleMeasurementFixAndroidCache
|
||||
if (cached == null) {
|
||||
@@ -282,6 +293,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enablePreparedTextLayout(): Boolean {
|
||||
var cached = enablePreparedTextLayoutCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.enablePreparedTextLayout()
|
||||
enablePreparedTextLayoutCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enablePropsUpdateReconciliationAndroid(): Boolean {
|
||||
var cached = enablePropsUpdateReconciliationAndroidCache
|
||||
if (cached == null) {
|
||||
|
||||
+5
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<b95c0d1f576b67fcf9d9df498ea30994>>
|
||||
* @generated SignedSource<<9d0b02395a08331bca956ea600602a31>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -48,6 +48,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableCustomFocusSearchOnClippedElementsAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableDestroyShadowTreeRevisionAsync(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableDoubleMeasurementFixAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableEagerRootViewAttachment(): Boolean
|
||||
@@ -76,6 +78,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableNewBackgroundAndBorderDrawables(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enablePreparedTextLayout(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enablePropsUpdateReconciliationAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableResourceTimingAPI(): Boolean
|
||||
|
||||
+5
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<c7425e6212e4e9d70e64452e550bf638>>
|
||||
* @generated SignedSource<<cf12cdfdfb343e79247379b5549ae92a>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -43,6 +43,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun enableCustomFocusSearchOnClippedElementsAndroid(): Boolean = true
|
||||
|
||||
override fun enableDestroyShadowTreeRevisionAsync(): Boolean = false
|
||||
|
||||
override fun enableDoubleMeasurementFixAndroid(): Boolean = false
|
||||
|
||||
override fun enableEagerRootViewAttachment(): Boolean = false
|
||||
@@ -71,6 +73,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun enableNewBackgroundAndBorderDrawables(): Boolean = true
|
||||
|
||||
override fun enablePreparedTextLayout(): Boolean = false
|
||||
|
||||
override fun enablePropsUpdateReconciliationAndroid(): Boolean = false
|
||||
|
||||
override fun enableResourceTimingAPI(): Boolean = false
|
||||
|
||||
+23
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<5b145ee103cf6b40e13d33c88cd52777>>
|
||||
* @generated SignedSource<<4c81ed8a06c192eb4007219d163650e5>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -34,6 +34,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var enableBridgelessArchitectureCache: Boolean? = null
|
||||
private var enableCppPropsIteratorSetterCache: Boolean? = null
|
||||
private var enableCustomFocusSearchOnClippedElementsAndroidCache: Boolean? = null
|
||||
private var enableDestroyShadowTreeRevisionAsyncCache: Boolean? = null
|
||||
private var enableDoubleMeasurementFixAndroidCache: Boolean? = null
|
||||
private var enableEagerRootViewAttachmentCache: Boolean? = null
|
||||
private var enableFabricLogsCache: Boolean? = null
|
||||
@@ -48,6 +49,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var enableNativeCSSParsingCache: Boolean? = null
|
||||
private var enableNetworkEventReportingCache: Boolean? = null
|
||||
private var enableNewBackgroundAndBorderDrawablesCache: Boolean? = null
|
||||
private var enablePreparedTextLayoutCache: Boolean? = null
|
||||
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
|
||||
private var enableResourceTimingAPICache: Boolean? = null
|
||||
private var enableSynchronousStateUpdatesCache: Boolean? = null
|
||||
@@ -170,6 +172,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableDestroyShadowTreeRevisionAsync(): Boolean {
|
||||
var cached = enableDestroyShadowTreeRevisionAsyncCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.enableDestroyShadowTreeRevisionAsync()
|
||||
accessedFeatureFlags.add("enableDestroyShadowTreeRevisionAsync")
|
||||
enableDestroyShadowTreeRevisionAsyncCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableDoubleMeasurementFixAndroid(): Boolean {
|
||||
var cached = enableDoubleMeasurementFixAndroidCache
|
||||
if (cached == null) {
|
||||
@@ -310,6 +322,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enablePreparedTextLayout(): Boolean {
|
||||
var cached = enablePreparedTextLayoutCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.enablePreparedTextLayout()
|
||||
accessedFeatureFlags.add("enablePreparedTextLayout")
|
||||
enablePreparedTextLayoutCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enablePropsUpdateReconciliationAndroid(): Boolean {
|
||||
var cached = enablePropsUpdateReconciliationAndroidCache
|
||||
if (cached == null) {
|
||||
|
||||
+5
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<9cdb965a420d53cf36b6531684cb07ae>>
|
||||
* @generated SignedSource<<2482f57e0652cfaa4806b5333c50ad9f>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -43,6 +43,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableCustomFocusSearchOnClippedElementsAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableDestroyShadowTreeRevisionAsync(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableDoubleMeasurementFixAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableEagerRootViewAttachment(): Boolean
|
||||
@@ -71,6 +73,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableNewBackgroundAndBorderDrawables(): Boolean
|
||||
|
||||
@DoNotStrip public fun enablePreparedTextLayout(): Boolean
|
||||
|
||||
@DoNotStrip public fun enablePropsUpdateReconciliationAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableResourceTimingAPI(): Boolean
|
||||
|
||||
+3
-3
@@ -12,9 +12,9 @@ package com.facebook.react.modules.systeminfo
|
||||
public object ReactNativeVersion {
|
||||
@JvmField
|
||||
public val VERSION: Map<String, Any?> = mapOf(
|
||||
"major" to 1000,
|
||||
"minor" to 0,
|
||||
"major" to 0,
|
||||
"minor" to 80,
|
||||
"patch" to 0,
|
||||
"prerelease" to null
|
||||
"prerelease" to "rc.0"
|
||||
)
|
||||
}
|
||||
|
||||
+9
-3
@@ -12,7 +12,6 @@
|
||||
package com.facebook.react.runtime
|
||||
|
||||
import android.content.res.AssetManager
|
||||
import com.facebook.proguard.annotations.DoNotStrip
|
||||
import com.facebook.react.bridge.CatalystInstance
|
||||
import com.facebook.react.bridge.JavaScriptContextHolder
|
||||
import com.facebook.react.bridge.JavaScriptModule
|
||||
@@ -26,14 +25,16 @@ import com.facebook.react.bridge.RuntimeScheduler
|
||||
import com.facebook.react.bridge.UIManager
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfiguration
|
||||
import com.facebook.react.common.annotations.VisibleForTesting
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
|
||||
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry
|
||||
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
|
||||
import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder
|
||||
|
||||
@DoNotStrip
|
||||
@Deprecated(
|
||||
message =
|
||||
"This class is deprecated, please to migrate to new architecture using [com.facebook.react.defaults.DefaultReactHost] instead.")
|
||||
@LegacyArchitecture
|
||||
internal class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) : CatalystInstance {
|
||||
|
||||
override fun handleMemoryPressure(level: Int) {
|
||||
@@ -68,7 +69,6 @@ internal class BridgelessCatalystInstance(private val reactHost: ReactHostImpl)
|
||||
throw UnsupportedOperationException("Unimplemented method 'hasRunJSBundle'")
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
override fun invokeCallback(callbackID: Int, arguments: NativeArrayInterface) {
|
||||
throw UnsupportedOperationException("Unimplemented method 'invokeCallback'")
|
||||
}
|
||||
@@ -172,4 +172,10 @@ internal class BridgelessCatalystInstance(private val reactHost: ReactHostImpl)
|
||||
override fun getFabricUIManager(): UIManager {
|
||||
throw UnsupportedOperationException("Unimplemented method 'getFabricUIManager'")
|
||||
}
|
||||
|
||||
private companion object {
|
||||
init {
|
||||
LegacyArchitectureLogger.assertLegacyArchitecture("BridgelessCatalystInstance")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -24,6 +24,7 @@ import com.facebook.react.bridge.UIManager
|
||||
import com.facebook.react.bridge.WritableNativeArray
|
||||
import com.facebook.react.common.annotations.FrameworkAPI
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
||||
import com.facebook.react.common.build.ReactBuildConfig
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager
|
||||
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler
|
||||
@@ -63,6 +64,10 @@ internal class BridgelessReactContext(context: Context, private val reactHost: R
|
||||
override fun getFabricUIManager(): UIManager? = reactHost.uiManager
|
||||
|
||||
override fun getCatalystInstance(): CatalystInstance {
|
||||
if (ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) {
|
||||
throw UnsupportedOperationException(
|
||||
"CatalystInstance is not supported when Bridgeless mode is enabled.")
|
||||
}
|
||||
Log.w(
|
||||
TAG,
|
||||
"[WARNING] Bridgeless doesn't support CatalystInstance. Accessing an API that's not part of" +
|
||||
|
||||
+25
-8
@@ -9,6 +9,7 @@ package com.facebook.react.uimanager
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
|
||||
import com.facebook.react.R
|
||||
import com.facebook.react.bridge.ReadableArray
|
||||
@@ -90,7 +91,11 @@ private object ReactAxOrderHelper {
|
||||
): Array<View?> {
|
||||
val axOrderViews = arrayOfNulls<View?>(axOrderIds.size)
|
||||
|
||||
fun traverseAndDisableAxFromExcludedViews(view: View, parent: View) {
|
||||
fun traverseAndDisableAxFromExcludedViews(
|
||||
view: View,
|
||||
parent: View,
|
||||
hasCooptingAncestor: Boolean
|
||||
) {
|
||||
val nativeId = view.getTag(R.id.view_tag_native_id) as String?
|
||||
|
||||
val isIncluded = nativeId != null && axOrderSet.contains(nativeId)
|
||||
@@ -101,28 +106,40 @@ private object ReactAxOrderHelper {
|
||||
view, view.isFocusable, view.importantForAccessibility)
|
||||
}
|
||||
|
||||
// There is a strange bug with TalkBack where if a focused view has nothing to announce, and
|
||||
// there are no accessibility node's below it, then it will run OCR model on its bounds and
|
||||
// announce any text it sees. Also, if there is a TextView below the View backing the node,
|
||||
// it will announce that text too. This can happen frequently with our implementation here
|
||||
// we change importantForAccessibility for TextView's that are not included in
|
||||
// accessibilityOrder thus kicking off the logic described. To avoid this double announcement
|
||||
// we just do not set importantForAccessibility on TextView's in the case where someone is
|
||||
// coopting them. We will not focus the text since they got coopted.
|
||||
if (isIncluded) {
|
||||
axOrderViews[axOrderIds.indexOf(nativeId)] = view
|
||||
} else {
|
||||
} else if (!(view is TextView && hasCooptingAncestor)) {
|
||||
// Save original state before disabling
|
||||
view.setTag(R.id.original_important_for_ax, view.importantForAccessibility)
|
||||
view.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
||||
}
|
||||
|
||||
val wantsToCoopt = isIncluded && view.contentDescription.isNullOrEmpty()
|
||||
|
||||
if (view is ViewGroup) {
|
||||
// Continue to try to disable children if this view is not included and is focusable.
|
||||
// This view being focusable means it's an element, and not a container which means its
|
||||
// presence doesn't imply all its children should be focusable. And if its not included we
|
||||
// still want to attempt to disable the children of the container
|
||||
// Continue to try to disable children if this view is not included and is
|
||||
// focusable. This view being focusable means it's an element, and not a container which
|
||||
// means its presence doesn't imply all its children should be focusable. And if its not
|
||||
// included we still want to attempt to disable the children of the container
|
||||
if (!isIncluded || view.isFocusable()) {
|
||||
for (i in 0 until view.childCount) {
|
||||
traverseAndDisableAxFromExcludedViews(view.getChildAt(i), parent)
|
||||
traverseAndDisableAxFromExcludedViews(view.getChildAt(i), parent, wantsToCoopt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverseAndDisableAxFromExcludedViews(root, root)
|
||||
// Technically we don't know if there is a coopting ancestor here, as it could be above the root
|
||||
// but those cases should be fairly rare
|
||||
traverseAndDisableAxFromExcludedViews(root, root, false)
|
||||
|
||||
return axOrderViews
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.text
|
||||
|
||||
import android.text.Layout
|
||||
import com.facebook.proguard.annotations.DoNotStrip
|
||||
|
||||
/**
|
||||
* Encapsulates an {android.text.Layout} along with any additional state needed to render or measure
|
||||
* it.
|
||||
*/
|
||||
@DoNotStrip
|
||||
internal class PreparedLayout(public val layout: Layout, public val maximumNumberOfLines: Int)
|
||||
+57
-4
@@ -31,6 +31,7 @@ import com.facebook.react.bridge.ReactNoCrashSoftException;
|
||||
import com.facebook.react.bridge.ReactSoftExceptionLogger;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
|
||||
import com.facebook.react.common.mapbuffer.MapBuffer;
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
@@ -503,7 +504,8 @@ public class TextLayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static Layout createLayout(
|
||||
@UnstableReactNativeAPI
|
||||
public static Layout createLayout(
|
||||
@NonNull Context context,
|
||||
MapBuffer attributedString,
|
||||
MapBuffer paragraphAttributes,
|
||||
@@ -732,6 +734,47 @@ public class TextLayoutManager {
|
||||
return YogaMeasureOutput.make(widthInSP, heightInSP);
|
||||
}
|
||||
|
||||
@UnstableReactNativeAPI
|
||||
public static float[] measurePreparedLayout(
|
||||
PreparedLayout preparedLayout,
|
||||
float width,
|
||||
YogaMeasureMode widthYogaMeasureMode,
|
||||
float height,
|
||||
YogaMeasureMode heightYogaMeasureMode) {
|
||||
Layout layout = preparedLayout.getLayout();
|
||||
Spanned text = (Spanned) layout.getText();
|
||||
int maximumNumberOfLines = preparedLayout.getMaximumNumberOfLines();
|
||||
|
||||
int calculatedLineCount = calculateLineCount(layout, maximumNumberOfLines);
|
||||
float calculatedWidth =
|
||||
calculateWidth(layout, text, width, widthYogaMeasureMode, calculatedLineCount);
|
||||
float calculatedHeight =
|
||||
calculateHeight(layout, text, height, heightYogaMeasureMode, calculatedLineCount);
|
||||
|
||||
ArrayList<Float> retList = new ArrayList<>();
|
||||
retList.add(PixelUtil.toDIPFromPixel(calculatedWidth));
|
||||
retList.add(PixelUtil.toDIPFromPixel(calculatedHeight));
|
||||
|
||||
AttachmentMetrics metrics = new AttachmentMetrics();
|
||||
int lastAttachmentFoundInSpan;
|
||||
for (int i = 0; i < text.length(); i = lastAttachmentFoundInSpan) {
|
||||
lastAttachmentFoundInSpan =
|
||||
nextAttachmentMetrics(layout, text, calculatedWidth, calculatedLineCount, i, metrics);
|
||||
if (metrics.wasFound) {
|
||||
retList.add(PixelUtil.toDIPFromPixel(metrics.top));
|
||||
retList.add(PixelUtil.toDIPFromPixel(metrics.left));
|
||||
retList.add(PixelUtil.toDIPFromPixel(metrics.width));
|
||||
retList.add(PixelUtil.toDIPFromPixel(metrics.height));
|
||||
}
|
||||
}
|
||||
|
||||
float[] ret = new float[retList.size()];
|
||||
for (int i = 0; i < retList.size(); i++) {
|
||||
ret[i] = retList.get(i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static int calculateLineCount(Layout layout, int maximumNumberOfLines) {
|
||||
return maximumNumberOfLines == ReactConstants.UNSET || maximumNumberOfLines == 0
|
||||
? layout.getLineCount()
|
||||
@@ -753,9 +796,19 @@ public class TextLayoutManager {
|
||||
for (int lineIndex = 0; lineIndex < calculatedLineCount; lineIndex++) {
|
||||
boolean endsWithNewLine =
|
||||
text.length() > 0 && text.charAt(layout.getLineEnd(lineIndex) - 1) == '\n';
|
||||
if (!endsWithNewLine && lineIndex + 1 < layout.getLineCount()) {
|
||||
calculatedWidth = width;
|
||||
break;
|
||||
// Line-wrapping or ellipsizing to truncate should result in taking the full available width
|
||||
// of the container, instead of width after line-breaking/ellipsizing.
|
||||
if (ReactNativeFeatureFlags.incorporateMaxLinesDuringAndroidLayout()) {
|
||||
if ((!endsWithNewLine && lineIndex + 1 < layout.getLineCount())
|
||||
|| layout.getEllipsisCount(lineIndex) > 0) {
|
||||
calculatedWidth = width;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!endsWithNewLine && lineIndex + 1 < layout.getLineCount()) {
|
||||
calculatedWidth = width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float lineWidth =
|
||||
endsWithNewLine ? layout.getLineMax(lineIndex) : layout.getLineWidth(lineIndex);
|
||||
|
||||
+29
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<c89831646046b10c7b2a40e14deb3d1a>>
|
||||
* @generated SignedSource<<49dbfe02e06cc5d6b12683ed91ea1d13>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -99,6 +99,12 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableDestroyShadowTreeRevisionAsync() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableDestroyShadowTreeRevisionAsync");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableDoubleMeasurementFixAndroid() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableDoubleMeasurementFixAndroid");
|
||||
@@ -183,6 +189,12 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enablePreparedTextLayout() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enablePreparedTextLayout");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enablePropsUpdateReconciliationAndroid() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enablePropsUpdateReconciliationAndroid");
|
||||
@@ -363,6 +375,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableCustomFocusSearchOnClippedElement
|
||||
return ReactNativeFeatureFlags::enableCustomFocusSearchOnClippedElementsAndroid();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableDestroyShadowTreeRevisionAsync(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableDestroyShadowTreeRevisionAsync();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableDoubleMeasurementFixAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableDoubleMeasurementFixAndroid();
|
||||
@@ -433,6 +450,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableNewBackgroundAndBorderDrawables(
|
||||
return ReactNativeFeatureFlags::enableNewBackgroundAndBorderDrawables();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enablePreparedTextLayout(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enablePreparedTextLayout();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enablePropsUpdateReconciliationAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid();
|
||||
@@ -599,6 +621,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableCustomFocusSearchOnClippedElementsAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableCustomFocusSearchOnClippedElementsAndroid),
|
||||
makeNativeMethod(
|
||||
"enableDestroyShadowTreeRevisionAsync",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableDestroyShadowTreeRevisionAsync),
|
||||
makeNativeMethod(
|
||||
"enableDoubleMeasurementFixAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableDoubleMeasurementFixAndroid),
|
||||
@@ -641,6 +666,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableNewBackgroundAndBorderDrawables",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableNewBackgroundAndBorderDrawables),
|
||||
makeNativeMethod(
|
||||
"enablePreparedTextLayout",
|
||||
JReactNativeFeatureFlagsCxxInterop::enablePreparedTextLayout),
|
||||
makeNativeMethod(
|
||||
"enablePropsUpdateReconciliationAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::enablePropsUpdateReconciliationAndroid),
|
||||
|
||||
+7
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<2a5ad62d2cb4f1111391f1b566e10c1d>>
|
||||
* @generated SignedSource<<ae23312f2dccee934a8a91c05625662a>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -60,6 +60,9 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool enableCustomFocusSearchOnClippedElementsAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableDestroyShadowTreeRevisionAsync(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableDoubleMeasurementFixAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
@@ -102,6 +105,9 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool enableNewBackgroundAndBorderDrawables(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enablePreparedTextLayout(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enablePropsUpdateReconciliationAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
|
||||
@@ -46,12 +46,12 @@ Pod::Spec.new do |s|
|
||||
s.dependency "React-Core"
|
||||
s.dependency "React-debug"
|
||||
s.dependency "React-featureflags"
|
||||
s.dependency "React-utils"
|
||||
s.dependency "React-runtimescheduler"
|
||||
s.dependency "React-cxxreact"
|
||||
|
||||
add_dependency(s, "React-rendererdebug")
|
||||
add_dependency(s, "React-graphics", :additional_framework_paths => ["react/renderer/graphics/platform/ios"])
|
||||
add_dependency(s, "React-utils", :additional_framework_paths => ["react/utils/platform/ios"])
|
||||
|
||||
depend_on_js_engine(s)
|
||||
add_rn_third_party_dependencies(s)
|
||||
|
||||
@@ -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 80
|
||||
#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 = 80;
|
||||
int32_t Patch = 0;
|
||||
std::string_view Prerelease = "";
|
||||
std::string_view Prerelease = "rc.0";
|
||||
} ReactNativeVersion;
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<0eb63ead191be88440cbb73fd760dec7>>
|
||||
* @generated SignedSource<<8410561a80edd67b4528181b1f8557fe>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -66,6 +66,10 @@ bool ReactNativeFeatureFlags::enableCustomFocusSearchOnClippedElementsAndroid()
|
||||
return getAccessor().enableCustomFocusSearchOnClippedElementsAndroid();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::enableDestroyShadowTreeRevisionAsync() {
|
||||
return getAccessor().enableDestroyShadowTreeRevisionAsync();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::enableDoubleMeasurementFixAndroid() {
|
||||
return getAccessor().enableDoubleMeasurementFixAndroid();
|
||||
}
|
||||
@@ -122,6 +126,10 @@ bool ReactNativeFeatureFlags::enableNewBackgroundAndBorderDrawables() {
|
||||
return getAccessor().enableNewBackgroundAndBorderDrawables();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::enablePreparedTextLayout() {
|
||||
return getAccessor().enablePreparedTextLayout();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid() {
|
||||
return getAccessor().enablePropsUpdateReconciliationAndroid();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<80dcd75591a392144c2fd2817cc4408a>>
|
||||
* @generated SignedSource<<8b135b02d868914f6b3487f09e8955ff>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -89,6 +89,11 @@ class ReactNativeFeatureFlags {
|
||||
*/
|
||||
RN_EXPORT static bool enableCustomFocusSearchOnClippedElementsAndroid();
|
||||
|
||||
/**
|
||||
* Enables destructor calls for ShadowTreeRevision in the background to reduce UI thread work.
|
||||
*/
|
||||
RN_EXPORT static bool enableDestroyShadowTreeRevisionAsync();
|
||||
|
||||
/**
|
||||
* When enabled a subset of components will avoid double measurement on Android.
|
||||
*/
|
||||
@@ -159,6 +164,11 @@ class ReactNativeFeatureFlags {
|
||||
*/
|
||||
RN_EXPORT static bool enableNewBackgroundAndBorderDrawables();
|
||||
|
||||
/**
|
||||
* Enables caching text layout artifacts for later reuse
|
||||
*/
|
||||
RN_EXPORT static bool enablePreparedTextLayout();
|
||||
|
||||
/**
|
||||
* When enabled, Android will receive prop updates based on the differences between the last rendered shadow node and the last committed shadow node.
|
||||
*/
|
||||
|
||||
+72
-36
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<0c39183e7858453bfc18515be46eb17f>>
|
||||
* @generated SignedSource<<18cf18662a540ff1bc0f151cd53bcb0d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -209,6 +209,24 @@ bool ReactNativeFeatureFlagsAccessor::enableCustomFocusSearchOnClippedElementsAn
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::enableDestroyShadowTreeRevisionAsync() {
|
||||
auto flagValue = enableDestroyShadowTreeRevisionAsync_.load();
|
||||
|
||||
if (!flagValue.has_value()) {
|
||||
// This block is not exclusive but it is not necessary.
|
||||
// If multiple threads try to initialize the feature flag, we would only
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(10, "enableDestroyShadowTreeRevisionAsync");
|
||||
|
||||
flagValue = currentProvider_->enableDestroyShadowTreeRevisionAsync();
|
||||
enableDestroyShadowTreeRevisionAsync_ = flagValue;
|
||||
}
|
||||
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::enableDoubleMeasurementFixAndroid() {
|
||||
auto flagValue = enableDoubleMeasurementFixAndroid_.load();
|
||||
|
||||
@@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDoubleMeasurementFixAndroid() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(10, "enableDoubleMeasurementFixAndroid");
|
||||
markFlagAsAccessed(11, "enableDoubleMeasurementFixAndroid");
|
||||
|
||||
flagValue = currentProvider_->enableDoubleMeasurementFixAndroid();
|
||||
enableDoubleMeasurementFixAndroid_ = flagValue;
|
||||
@@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEagerRootViewAttachment() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(11, "enableEagerRootViewAttachment");
|
||||
markFlagAsAccessed(12, "enableEagerRootViewAttachment");
|
||||
|
||||
flagValue = currentProvider_->enableEagerRootViewAttachment();
|
||||
enableEagerRootViewAttachment_ = flagValue;
|
||||
@@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(12, "enableFabricLogs");
|
||||
markFlagAsAccessed(13, "enableFabricLogs");
|
||||
|
||||
flagValue = currentProvider_->enableFabricLogs();
|
||||
enableFabricLogs_ = flagValue;
|
||||
@@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricRenderer() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(13, "enableFabricRenderer");
|
||||
markFlagAsAccessed(14, "enableFabricRenderer");
|
||||
|
||||
flagValue = currentProvider_->enableFabricRenderer();
|
||||
enableFabricRenderer_ = flagValue;
|
||||
@@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFixForParentTagDuringReparenting() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(14, "enableFixForParentTagDuringReparenting");
|
||||
markFlagAsAccessed(15, "enableFixForParentTagDuringReparenting");
|
||||
|
||||
flagValue = currentProvider_->enableFixForParentTagDuringReparenting();
|
||||
enableFixForParentTagDuringReparenting_ = flagValue;
|
||||
@@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFontScaleChangesUpdatingLayout() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(15, "enableFontScaleChangesUpdatingLayout");
|
||||
markFlagAsAccessed(16, "enableFontScaleChangesUpdatingLayout");
|
||||
|
||||
flagValue = currentProvider_->enableFontScaleChangesUpdatingLayout();
|
||||
enableFontScaleChangesUpdatingLayout_ = flagValue;
|
||||
@@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSViewClipToPaddingBox() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(16, "enableIOSViewClipToPaddingBox");
|
||||
markFlagAsAccessed(17, "enableIOSViewClipToPaddingBox");
|
||||
|
||||
flagValue = currentProvider_->enableIOSViewClipToPaddingBox();
|
||||
enableIOSViewClipToPaddingBox_ = flagValue;
|
||||
@@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::enableJSRuntimeGCOnMemoryPressureOnIOS() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(17, "enableJSRuntimeGCOnMemoryPressureOnIOS");
|
||||
markFlagAsAccessed(18, "enableJSRuntimeGCOnMemoryPressureOnIOS");
|
||||
|
||||
flagValue = currentProvider_->enableJSRuntimeGCOnMemoryPressureOnIOS();
|
||||
enableJSRuntimeGCOnMemoryPressureOnIOS_ = flagValue;
|
||||
@@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(18, "enableLayoutAnimationsOnAndroid");
|
||||
markFlagAsAccessed(19, "enableLayoutAnimationsOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->enableLayoutAnimationsOnAndroid();
|
||||
enableLayoutAnimationsOnAndroid_ = flagValue;
|
||||
@@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(19, "enableLayoutAnimationsOnIOS");
|
||||
markFlagAsAccessed(20, "enableLayoutAnimationsOnIOS");
|
||||
|
||||
flagValue = currentProvider_->enableLayoutAnimationsOnIOS();
|
||||
enableLayoutAnimationsOnIOS_ = flagValue;
|
||||
@@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMainQueueModulesOnIOS() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(20, "enableMainQueueModulesOnIOS");
|
||||
markFlagAsAccessed(21, "enableMainQueueModulesOnIOS");
|
||||
|
||||
flagValue = currentProvider_->enableMainQueueModulesOnIOS();
|
||||
enableMainQueueModulesOnIOS_ = flagValue;
|
||||
@@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(21, "enableNativeCSSParsing");
|
||||
markFlagAsAccessed(22, "enableNativeCSSParsing");
|
||||
|
||||
flagValue = currentProvider_->enableNativeCSSParsing();
|
||||
enableNativeCSSParsing_ = flagValue;
|
||||
@@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNetworkEventReporting() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(22, "enableNetworkEventReporting");
|
||||
markFlagAsAccessed(23, "enableNetworkEventReporting");
|
||||
|
||||
flagValue = currentProvider_->enableNetworkEventReporting();
|
||||
enableNetworkEventReporting_ = flagValue;
|
||||
@@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNewBackgroundAndBorderDrawables() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(23, "enableNewBackgroundAndBorderDrawables");
|
||||
markFlagAsAccessed(24, "enableNewBackgroundAndBorderDrawables");
|
||||
|
||||
flagValue = currentProvider_->enableNewBackgroundAndBorderDrawables();
|
||||
enableNewBackgroundAndBorderDrawables_ = flagValue;
|
||||
@@ -461,6 +479,24 @@ bool ReactNativeFeatureFlagsAccessor::enableNewBackgroundAndBorderDrawables() {
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() {
|
||||
auto flagValue = enablePreparedTextLayout_.load();
|
||||
|
||||
if (!flagValue.has_value()) {
|
||||
// This block is not exclusive but it is not necessary.
|
||||
// If multiple threads try to initialize the feature flag, we would only
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(25, "enablePreparedTextLayout");
|
||||
|
||||
flagValue = currentProvider_->enablePreparedTextLayout();
|
||||
enablePreparedTextLayout_ = flagValue;
|
||||
}
|
||||
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() {
|
||||
auto flagValue = enablePropsUpdateReconciliationAndroid_.load();
|
||||
|
||||
@@ -470,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(24, "enablePropsUpdateReconciliationAndroid");
|
||||
markFlagAsAccessed(26, "enablePropsUpdateReconciliationAndroid");
|
||||
|
||||
flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid();
|
||||
enablePropsUpdateReconciliationAndroid_ = flagValue;
|
||||
@@ -488,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableResourceTimingAPI() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(25, "enableResourceTimingAPI");
|
||||
markFlagAsAccessed(27, "enableResourceTimingAPI");
|
||||
|
||||
flagValue = currentProvider_->enableResourceTimingAPI();
|
||||
enableResourceTimingAPI_ = flagValue;
|
||||
@@ -506,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(26, "enableSynchronousStateUpdates");
|
||||
markFlagAsAccessed(28, "enableSynchronousStateUpdates");
|
||||
|
||||
flagValue = currentProvider_->enableSynchronousStateUpdates();
|
||||
enableSynchronousStateUpdates_ = flagValue;
|
||||
@@ -524,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(27, "enableViewCulling");
|
||||
markFlagAsAccessed(29, "enableViewCulling");
|
||||
|
||||
flagValue = currentProvider_->enableViewCulling();
|
||||
enableViewCulling_ = flagValue;
|
||||
@@ -542,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(28, "enableViewRecycling");
|
||||
markFlagAsAccessed(30, "enableViewRecycling");
|
||||
|
||||
flagValue = currentProvider_->enableViewRecycling();
|
||||
enableViewRecycling_ = flagValue;
|
||||
@@ -560,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(29, "enableViewRecyclingForText");
|
||||
markFlagAsAccessed(31, "enableViewRecyclingForText");
|
||||
|
||||
flagValue = currentProvider_->enableViewRecyclingForText();
|
||||
enableViewRecyclingForText_ = flagValue;
|
||||
@@ -578,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(30, "enableViewRecyclingForView");
|
||||
markFlagAsAccessed(32, "enableViewRecyclingForView");
|
||||
|
||||
flagValue = currentProvider_->enableViewRecyclingForView();
|
||||
enableViewRecyclingForView_ = flagValue;
|
||||
@@ -596,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(31, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
markFlagAsAccessed(33, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
|
||||
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
|
||||
@@ -614,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(32, "fuseboxEnabledRelease");
|
||||
markFlagAsAccessed(34, "fuseboxEnabledRelease");
|
||||
|
||||
flagValue = currentProvider_->fuseboxEnabledRelease();
|
||||
fuseboxEnabledRelease_ = flagValue;
|
||||
@@ -632,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(33, "fuseboxNetworkInspectionEnabled");
|
||||
markFlagAsAccessed(35, "fuseboxNetworkInspectionEnabled");
|
||||
|
||||
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
|
||||
fuseboxNetworkInspectionEnabled_ = flagValue;
|
||||
@@ -650,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::incorporateMaxLinesDuringAndroidLayout() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(34, "incorporateMaxLinesDuringAndroidLayout");
|
||||
markFlagAsAccessed(36, "incorporateMaxLinesDuringAndroidLayout");
|
||||
|
||||
flagValue = currentProvider_->incorporateMaxLinesDuringAndroidLayout();
|
||||
incorporateMaxLinesDuringAndroidLayout_ = flagValue;
|
||||
@@ -668,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(35, "traceTurboModulePromiseRejectionsOnAndroid");
|
||||
markFlagAsAccessed(37, "traceTurboModulePromiseRejectionsOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
|
||||
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
|
||||
@@ -686,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit(
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(36, "updateRuntimeShadowNodeReferencesOnCommit");
|
||||
markFlagAsAccessed(38, "updateRuntimeShadowNodeReferencesOnCommit");
|
||||
|
||||
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
|
||||
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
|
||||
@@ -704,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(37, "useAlwaysAvailableJSErrorHandling");
|
||||
markFlagAsAccessed(39, "useAlwaysAvailableJSErrorHandling");
|
||||
|
||||
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
|
||||
useAlwaysAvailableJSErrorHandling_ = flagValue;
|
||||
@@ -722,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(38, "useFabricInterop");
|
||||
markFlagAsAccessed(40, "useFabricInterop");
|
||||
|
||||
flagValue = currentProvider_->useFabricInterop();
|
||||
useFabricInterop_ = flagValue;
|
||||
@@ -740,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(39, "useNativeViewConfigsInBridgelessMode");
|
||||
markFlagAsAccessed(41, "useNativeViewConfigsInBridgelessMode");
|
||||
|
||||
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
|
||||
useNativeViewConfigsInBridgelessMode_ = flagValue;
|
||||
@@ -758,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(40, "useOptimizedEventBatchingOnAndroid");
|
||||
markFlagAsAccessed(42, "useOptimizedEventBatchingOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
|
||||
useOptimizedEventBatchingOnAndroid_ = flagValue;
|
||||
@@ -776,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(41, "useRawPropsJsiValue");
|
||||
markFlagAsAccessed(43, "useRawPropsJsiValue");
|
||||
|
||||
flagValue = currentProvider_->useRawPropsJsiValue();
|
||||
useRawPropsJsiValue_ = flagValue;
|
||||
@@ -794,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(42, "useShadowNodeStateOnClone");
|
||||
markFlagAsAccessed(44, "useShadowNodeStateOnClone");
|
||||
|
||||
flagValue = currentProvider_->useShadowNodeStateOnClone();
|
||||
useShadowNodeStateOnClone_ = flagValue;
|
||||
@@ -812,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(43, "useTurboModuleInterop");
|
||||
markFlagAsAccessed(45, "useTurboModuleInterop");
|
||||
|
||||
flagValue = currentProvider_->useTurboModuleInterop();
|
||||
useTurboModuleInterop_ = flagValue;
|
||||
@@ -830,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(44, "useTurboModules");
|
||||
markFlagAsAccessed(46, "useTurboModules");
|
||||
|
||||
flagValue = currentProvider_->useTurboModules();
|
||||
useTurboModules_ = flagValue;
|
||||
|
||||
+6
-2
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<336504fac084993c9aff86f274d45342>>
|
||||
* @generated SignedSource<<2736c730fcd0b82717faa0fea527d007>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -42,6 +42,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
bool enableBridgelessArchitecture();
|
||||
bool enableCppPropsIteratorSetter();
|
||||
bool enableCustomFocusSearchOnClippedElementsAndroid();
|
||||
bool enableDestroyShadowTreeRevisionAsync();
|
||||
bool enableDoubleMeasurementFixAndroid();
|
||||
bool enableEagerRootViewAttachment();
|
||||
bool enableFabricLogs();
|
||||
@@ -56,6 +57,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
bool enableNativeCSSParsing();
|
||||
bool enableNetworkEventReporting();
|
||||
bool enableNewBackgroundAndBorderDrawables();
|
||||
bool enablePreparedTextLayout();
|
||||
bool enablePropsUpdateReconciliationAndroid();
|
||||
bool enableResourceTimingAPI();
|
||||
bool enableSynchronousStateUpdates();
|
||||
@@ -88,7 +90,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
|
||||
bool wasOverridden_;
|
||||
|
||||
std::array<std::atomic<const char*>, 45> accessedFeatureFlags_;
|
||||
std::array<std::atomic<const char*>, 47> accessedFeatureFlags_;
|
||||
|
||||
std::atomic<std::optional<bool>> commonTestFlag_;
|
||||
std::atomic<std::optional<bool>> animatedShouldSignalBatch_;
|
||||
@@ -100,6 +102,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::atomic<std::optional<bool>> enableBridgelessArchitecture_;
|
||||
std::atomic<std::optional<bool>> enableCppPropsIteratorSetter_;
|
||||
std::atomic<std::optional<bool>> enableCustomFocusSearchOnClippedElementsAndroid_;
|
||||
std::atomic<std::optional<bool>> enableDestroyShadowTreeRevisionAsync_;
|
||||
std::atomic<std::optional<bool>> enableDoubleMeasurementFixAndroid_;
|
||||
std::atomic<std::optional<bool>> enableEagerRootViewAttachment_;
|
||||
std::atomic<std::optional<bool>> enableFabricLogs_;
|
||||
@@ -114,6 +117,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::atomic<std::optional<bool>> enableNativeCSSParsing_;
|
||||
std::atomic<std::optional<bool>> enableNetworkEventReporting_;
|
||||
std::atomic<std::optional<bool>> enableNewBackgroundAndBorderDrawables_;
|
||||
std::atomic<std::optional<bool>> enablePreparedTextLayout_;
|
||||
std::atomic<std::optional<bool>> enablePropsUpdateReconciliationAndroid_;
|
||||
std::atomic<std::optional<bool>> enableResourceTimingAPI_;
|
||||
std::atomic<std::optional<bool>> enableSynchronousStateUpdates_;
|
||||
|
||||
+9
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<825294594363fb672b6cd64eaa954dd4>>
|
||||
* @generated SignedSource<<ef056e269a4ed514c18ebaed89885661>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -67,6 +67,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool enableDestroyShadowTreeRevisionAsync() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enableDoubleMeasurementFixAndroid() override {
|
||||
return false;
|
||||
}
|
||||
@@ -123,6 +127,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool enablePreparedTextLayout() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enablePropsUpdateReconciliationAndroid() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
+19
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<d9dc055d9cda1ac17b7039aa70691a6b>>
|
||||
* @generated SignedSource<<53e92dc49c9d5b93de14cde2fd319e92>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -135,6 +135,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
|
||||
return ReactNativeFeatureFlagsDefaults::enableCustomFocusSearchOnClippedElementsAndroid();
|
||||
}
|
||||
|
||||
bool enableDestroyShadowTreeRevisionAsync() override {
|
||||
auto value = values_["enableDestroyShadowTreeRevisionAsync"];
|
||||
if (!value.isNull()) {
|
||||
return value.getBool();
|
||||
}
|
||||
|
||||
return ReactNativeFeatureFlagsDefaults::enableDestroyShadowTreeRevisionAsync();
|
||||
}
|
||||
|
||||
bool enableDoubleMeasurementFixAndroid() override {
|
||||
auto value = values_["enableDoubleMeasurementFixAndroid"];
|
||||
if (!value.isNull()) {
|
||||
@@ -261,6 +270,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
|
||||
return ReactNativeFeatureFlagsDefaults::enableNewBackgroundAndBorderDrawables();
|
||||
}
|
||||
|
||||
bool enablePreparedTextLayout() override {
|
||||
auto value = values_["enablePreparedTextLayout"];
|
||||
if (!value.isNull()) {
|
||||
return value.getBool();
|
||||
}
|
||||
|
||||
return ReactNativeFeatureFlagsDefaults::enablePreparedTextLayout();
|
||||
}
|
||||
|
||||
bool enablePropsUpdateReconciliationAndroid() override {
|
||||
auto value = values_["enablePropsUpdateReconciliationAndroid"];
|
||||
if (!value.isNull()) {
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<905f26c85dc731205b1a6f44c4e32468>>
|
||||
* @generated SignedSource<<7ad3c1ab9913ee5b20d0f6217580a14c>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -35,6 +35,7 @@ class ReactNativeFeatureFlagsProvider {
|
||||
virtual bool enableBridgelessArchitecture() = 0;
|
||||
virtual bool enableCppPropsIteratorSetter() = 0;
|
||||
virtual bool enableCustomFocusSearchOnClippedElementsAndroid() = 0;
|
||||
virtual bool enableDestroyShadowTreeRevisionAsync() = 0;
|
||||
virtual bool enableDoubleMeasurementFixAndroid() = 0;
|
||||
virtual bool enableEagerRootViewAttachment() = 0;
|
||||
virtual bool enableFabricLogs() = 0;
|
||||
@@ -49,6 +50,7 @@ class ReactNativeFeatureFlagsProvider {
|
||||
virtual bool enableNativeCSSParsing() = 0;
|
||||
virtual bool enableNetworkEventReporting() = 0;
|
||||
virtual bool enableNewBackgroundAndBorderDrawables() = 0;
|
||||
virtual bool enablePreparedTextLayout() = 0;
|
||||
virtual bool enablePropsUpdateReconciliationAndroid() = 0;
|
||||
virtual bool enableResourceTimingAPI() = 0;
|
||||
virtual bool enableSynchronousStateUpdates() = 0;
|
||||
|
||||
+11
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<614814062283858cf70138a2ac3d6304>>
|
||||
* @generated SignedSource<<cf54fabb5023a846cadd14482ea80999>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -94,6 +94,11 @@ bool NativeReactNativeFeatureFlags::enableCustomFocusSearchOnClippedElementsAndr
|
||||
return ReactNativeFeatureFlags::enableCustomFocusSearchOnClippedElementsAndroid();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::enableDestroyShadowTreeRevisionAsync(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::enableDestroyShadowTreeRevisionAsync();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::enableDoubleMeasurementFixAndroid(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::enableDoubleMeasurementFixAndroid();
|
||||
@@ -164,6 +169,11 @@ bool NativeReactNativeFeatureFlags::enableNewBackgroundAndBorderDrawables(
|
||||
return ReactNativeFeatureFlags::enableNewBackgroundAndBorderDrawables();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::enablePreparedTextLayout(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::enablePreparedTextLayout();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid();
|
||||
|
||||
+5
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<1c0248c3eda43cc89a61b3e3ff8b4345>>
|
||||
* @generated SignedSource<<4169b34b13c62ab90d7976de908b5f16>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -57,6 +57,8 @@ class NativeReactNativeFeatureFlags
|
||||
|
||||
bool enableCustomFocusSearchOnClippedElementsAndroid(jsi::Runtime& runtime);
|
||||
|
||||
bool enableDestroyShadowTreeRevisionAsync(jsi::Runtime& runtime);
|
||||
|
||||
bool enableDoubleMeasurementFixAndroid(jsi::Runtime& runtime);
|
||||
|
||||
bool enableEagerRootViewAttachment(jsi::Runtime& runtime);
|
||||
@@ -85,6 +87,8 @@ class NativeReactNativeFeatureFlags
|
||||
|
||||
bool enableNewBackgroundAndBorderDrawables(jsi::Runtime& runtime);
|
||||
|
||||
bool enablePreparedTextLayout(jsi::Runtime& runtime);
|
||||
|
||||
bool enablePropsUpdateReconciliationAndroid(jsi::Runtime& runtime);
|
||||
|
||||
bool enableResourceTimingAPI(jsi::Runtime& runtime);
|
||||
|
||||
+45
-15
@@ -165,15 +165,23 @@ void ParagraphShadowNode::updateStateIfNeeded(const Content& content) {
|
||||
Size ParagraphShadowNode::measureContent(
|
||||
const LayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const {
|
||||
if constexpr (TextLayoutManagerExtended::supportsPreparedLayout()) {
|
||||
for (const auto& preparedLayout : preparedLayouts_) {
|
||||
if (preparedLayout.layoutConstraints == layoutConstraints) {
|
||||
return preparedLayout.measureSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto content =
|
||||
getContentWithMeasuredAttachments(layoutContext, layoutConstraints);
|
||||
|
||||
auto attributedString = content.attributedString;
|
||||
if (attributedString.isEmpty()) {
|
||||
// Note: `zero-width space` is insufficient in some cases (e.g. when we need
|
||||
// to measure the "height" of the font).
|
||||
// TODO T67606511: We will redefine the measurement of empty strings as part
|
||||
// of T67606511
|
||||
// Note: `zero-width space` is insufficient in some cases (e.g. when we
|
||||
// need to measure the "height" of the font).
|
||||
// TODO T67606511: We will redefine the measurement of empty strings as
|
||||
// part of T67606511
|
||||
auto string = BaseTextShadowNode::getEmptyPlaceholder();
|
||||
auto textAttributes = TextAttributes::defaultTextAttributes();
|
||||
textAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
|
||||
@@ -186,6 +194,28 @@ Size ParagraphShadowNode::measureContent(
|
||||
.surfaceId = getSurfaceId(),
|
||||
};
|
||||
|
||||
if constexpr (TextLayoutManagerExtended::supportsPreparedLayout()) {
|
||||
if (ReactNativeFeatureFlags::enablePreparedTextLayout()) {
|
||||
TextLayoutManagerExtended tme(*textLayoutManager_);
|
||||
|
||||
auto preparedLayout = tme.prepareLayout(
|
||||
attributedString,
|
||||
content.paragraphAttributes,
|
||||
textLayoutContext,
|
||||
layoutConstraints);
|
||||
auto mesaurements = tme.measurePreparedLayout(
|
||||
preparedLayout, textLayoutContext, layoutConstraints);
|
||||
|
||||
preparedLayouts_.push_back(PreparedLayoutResult{
|
||||
layoutConstraints,
|
||||
mesaurements.size,
|
||||
// PreparedLayout is not trivially copyable on all platforms
|
||||
// NOLINTNEXTLINE(performance-move-const-arg)
|
||||
std::move(preparedLayout)});
|
||||
return mesaurements.size;
|
||||
}
|
||||
}
|
||||
|
||||
return textLayoutManager_
|
||||
->measure(
|
||||
AttributedStringBox{attributedString},
|
||||
@@ -206,10 +236,10 @@ Float ParagraphShadowNode::baseline(
|
||||
auto attributedString = content.attributedString;
|
||||
|
||||
if (attributedString.isEmpty()) {
|
||||
// Note: `zero-width space` is insufficient in some cases (e.g. when we need
|
||||
// to measure the "height" of the font).
|
||||
// TODO T67606511: We will redefine the measurement of empty strings as part
|
||||
// of T67606511
|
||||
// Note: `zero-width space` is insufficient in some cases (e.g. when we
|
||||
// need to measure the "height" of the font).
|
||||
// TODO T67606511: We will redefine the measurement of empty strings as
|
||||
// part of T67606511
|
||||
auto string = BaseTextShadowNode::getEmptyPlaceholder();
|
||||
auto textAttributes = TextAttributes::defaultTextAttributes();
|
||||
textAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
|
||||
@@ -281,8 +311,8 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
|
||||
// `paragraphShadowNode` that represents clones of `this` object.
|
||||
auto paragraphShadowNode = static_cast<ParagraphShadowNode*>(this);
|
||||
// `paragraphOwningShadowNode` is owning pointer to`paragraphShadowNode`
|
||||
// (besides the initial case when `paragraphShadowNode == this`), we need this
|
||||
// only to keep it in memory for a while.
|
||||
// (besides the initial case when `paragraphShadowNode == this`), we need
|
||||
// this only to keep it in memory for a while.
|
||||
auto paragraphOwningShadowNode = ShadowNode::Unshared{};
|
||||
|
||||
react_native_assert(
|
||||
@@ -313,7 +343,7 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
|
||||
const auto& attachmentMeasurement = measurement.attachments[i];
|
||||
if (attachmentMeasurement.isClipped) {
|
||||
layoutableShadowNode.setLayoutMetrics(
|
||||
LayoutMetrics{.displayType = DisplayType::None});
|
||||
LayoutMetrics{.frame = {}, .displayType = DisplayType::None});
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -333,15 +363,15 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
|
||||
layoutableShadowNode.layoutTree(
|
||||
attachmentLayoutContext, attachmentLayoutConstrains);
|
||||
|
||||
// Altering the origin of the `ShadowNode` (which is defined by text layout,
|
||||
// not by internal styles and state).
|
||||
// Altering the origin of the `ShadowNode` (which is defined by text
|
||||
// layout, not by internal styles and state).
|
||||
auto attachmentLayoutMetrics = layoutableShadowNode.getLayoutMetrics();
|
||||
attachmentLayoutMetrics.frame.origin = attachmentOrigin;
|
||||
layoutableShadowNode.setLayoutMetrics(attachmentLayoutMetrics);
|
||||
}
|
||||
|
||||
// If we ended up cloning something, we need to update the list of children to
|
||||
// reflect the changes that we made.
|
||||
// If we ended up cloning something, we need to update the list of children
|
||||
// to reflect the changes that we made.
|
||||
if (paragraphShadowNode != this) {
|
||||
this->children_ =
|
||||
static_cast<const ParagraphShadowNode*>(paragraphShadowNode)->children_;
|
||||
|
||||
+13
@@ -15,6 +15,7 @@
|
||||
#include <react/renderer/core/LayoutContext.h>
|
||||
#include <react/renderer/core/ShadowNode.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManagerExtended.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
@@ -115,6 +116,18 @@ class ParagraphShadowNode final : public ConcreteViewShadowNode<
|
||||
* Cached content of the subtree started from the node.
|
||||
*/
|
||||
mutable std::optional<Content> content_{};
|
||||
|
||||
/*
|
||||
* Intermediate layout results generated during measurement, that may be
|
||||
* reused by the platform.
|
||||
*/
|
||||
struct PreparedLayoutResult {
|
||||
LayoutConstraints layoutConstraints;
|
||||
Size measureSize;
|
||||
TextLayoutManagerExtended::PreparedLayout preparedLayout{};
|
||||
};
|
||||
|
||||
mutable std::vector<PreparedLayoutResult> preparedLayouts_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
#include <cxxreact/TraceSection.h>
|
||||
#include <react/debug/react_native_assert.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/renderer/mounting/ShadowViewMutation.h>
|
||||
#include <react/utils/LowPriorityExecutor.h>
|
||||
#include <condition_variable>
|
||||
#include "updateMountedFlag.h"
|
||||
|
||||
@@ -186,6 +188,9 @@ std::optional<MountingTransaction> MountingCoordinator::pullTransaction(
|
||||
#endif
|
||||
|
||||
if (lastRevision_.has_value()) {
|
||||
if (ReactNativeFeatureFlags::enableDestroyShadowTreeRevisionAsync()) {
|
||||
LowPriorityExecutor::execute([toDelete = std::move(baseRevision_)]() {});
|
||||
}
|
||||
baseRevision_ = std::move(*lastRevision_);
|
||||
lastRevision_.reset();
|
||||
|
||||
|
||||
+63
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <cstddef>
|
||||
|
||||
#include <react/renderer/attributedstring/AttributedStringBox.h>
|
||||
#include <react/renderer/attributedstring/ParagraphAttributes.h>
|
||||
@@ -17,7 +18,36 @@
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
template <typename TextLayoutManagerT>
|
||||
concept TextLayoutManagerWithPreparedLayout = requires(
|
||||
TextLayoutManagerT textLayoutManager,
|
||||
AttributedString attributedString,
|
||||
ParagraphAttributes paragraphAttributes,
|
||||
TextLayoutContext layoutContext,
|
||||
LayoutConstraints layoutConstraints,
|
||||
typename TextLayoutManagerT::PreparedLayout preparedLayout) {
|
||||
sizeof(typename TextLayoutManagerT::PreparedLayout);
|
||||
{
|
||||
textLayoutManager.prepareLayout(
|
||||
attributedString, paragraphAttributes, layoutContext, layoutConstraints)
|
||||
} -> std::same_as<typename TextLayoutManagerT::PreparedLayout>;
|
||||
{
|
||||
textLayoutManager.measurePreparedLayout(
|
||||
preparedLayout, layoutContext, layoutConstraints)
|
||||
} -> std::same_as<TextMeasurement>;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct PreparedLayoutT {
|
||||
using type = std::nullptr_t;
|
||||
};
|
||||
|
||||
template <TextLayoutManagerWithPreparedLayout T>
|
||||
struct PreparedLayoutT<T> {
|
||||
using type = typename T::PreparedLayout;
|
||||
};
|
||||
|
||||
/**
|
||||
* TextLayoutManagerExtended acts as an adapter for TextLayoutManager methods
|
||||
* which may not exist for a specific platform. Callers can check at
|
||||
@@ -36,6 +66,12 @@ class TextLayoutManagerExtended {
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr bool supportsPreparedLayout() {
|
||||
return TextLayoutManagerWithPreparedLayout<TextLayoutManagerT>;
|
||||
}
|
||||
|
||||
using PreparedLayout = typename PreparedLayoutT<TextLayoutManagerT>::type;
|
||||
|
||||
TextLayoutManagerExtended(const TextLayoutManagerT& textLayoutManager)
|
||||
: textLayoutManager_(textLayoutManager) {}
|
||||
|
||||
@@ -50,6 +86,33 @@ class TextLayoutManagerExtended {
|
||||
LOG(FATAL) << "Platform TextLayoutManager does not support measureLines";
|
||||
}
|
||||
|
||||
PreparedLayout prepareLayout(
|
||||
const AttributedString& attributedString,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const TextLayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const {
|
||||
if constexpr (supportsPreparedLayout()) {
|
||||
return textLayoutManager_.prepareLayout(
|
||||
attributedString,
|
||||
paragraphAttributes,
|
||||
layoutContext,
|
||||
layoutConstraints);
|
||||
}
|
||||
LOG(FATAL) << "Platform TextLayoutManager does not support prepareLayout";
|
||||
}
|
||||
|
||||
TextMeasurement measurePreparedLayout(
|
||||
const PreparedLayout& layout,
|
||||
const TextLayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const {
|
||||
if constexpr (supportsPreparedLayout()) {
|
||||
return textLayoutManager_.measurePreparedLayout(
|
||||
layout, layoutContext, layoutConstraints);
|
||||
}
|
||||
LOG(FATAL)
|
||||
<< "Platform TextLayoutManager does not support measurePreparedLayout";
|
||||
}
|
||||
|
||||
private:
|
||||
const TextLayoutManagerT& textLayoutManager_;
|
||||
};
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class JPreparedLayout : public jni::JavaClass<JPreparedLayout> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor =
|
||||
"Lcom/facebook/react/views/text/PreparedLayout;";
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
+97
-2
@@ -5,21 +5,25 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "TextLayoutManager.h"
|
||||
|
||||
#include <span>
|
||||
#include <utility>
|
||||
|
||||
#include <react/common/mapbuffer/JReadableMapBuffer.h>
|
||||
#include <react/debug/react_native_assert.h>
|
||||
#include <react/jni/ReadableNativeMap.h>
|
||||
#include <react/renderer/attributedstring/conversions.h>
|
||||
#include <react/renderer/core/conversions.h>
|
||||
#include <react/renderer/mapbuffer/MapBuffer.h>
|
||||
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
||||
#include <react/renderer/telemetry/TransactionTelemetry.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManagerExtended.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
static_assert(TextLayoutManagerExtended::supportsLineMeasurement());
|
||||
static_assert(TextLayoutManagerExtended::supportsPreparedLayout());
|
||||
|
||||
namespace {
|
||||
|
||||
int countAttachments(const AttributedString& attributedString) {
|
||||
@@ -289,4 +293,95 @@ LinesMeasurements TextLayoutManager::measureLines(
|
||||
return lineMeasurements;
|
||||
}
|
||||
|
||||
TextLayoutManager::PreparedLayout TextLayoutManager::prepareLayout(
|
||||
const AttributedString& attributedString,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const TextLayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const {
|
||||
const auto& fabricUIManager =
|
||||
contextContainer_->at<jni::global_ref<jobject>>("FabricUIManager");
|
||||
|
||||
static auto prepareLayout =
|
||||
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
|
||||
->getMethod<JPreparedLayout::javaobject(
|
||||
jint,
|
||||
JReadableMapBuffer::javaobject,
|
||||
JReadableMapBuffer::javaobject,
|
||||
jfloat,
|
||||
jfloat)>("prepareLayout");
|
||||
|
||||
auto attributedStringMB =
|
||||
JReadableMapBuffer::createWithContents(toMapBuffer(attributedString));
|
||||
auto paragraphAttributesMB =
|
||||
JReadableMapBuffer::createWithContents(toMapBuffer(paragraphAttributes));
|
||||
|
||||
// T222682416: We don't have any global cache here. We should investigate
|
||||
// whether that is desirable
|
||||
return {jni::make_global(prepareLayout(
|
||||
fabricUIManager,
|
||||
layoutContext.surfaceId,
|
||||
attributedStringMB.get(),
|
||||
paragraphAttributesMB.get(),
|
||||
layoutConstraints.maximumSize.width,
|
||||
layoutConstraints.maximumSize.height))};
|
||||
}
|
||||
|
||||
TextMeasurement TextLayoutManager::measurePreparedLayout(
|
||||
const PreparedLayout& preparedLayout,
|
||||
const TextLayoutContext& /*layoutContext*/,
|
||||
const LayoutConstraints& layoutConstraints) const {
|
||||
const auto& fabricUIManager =
|
||||
contextContainer_->at<jni::global_ref<jobject>>("FabricUIManager");
|
||||
|
||||
static auto measurePreparedLayout =
|
||||
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
|
||||
->getMethod<jni::JArrayFloat(
|
||||
JPreparedLayout::javaobject, jfloat, jfloat, jfloat, jfloat)>(
|
||||
"measurePreparedLayout");
|
||||
|
||||
auto minimumSize = layoutConstraints.minimumSize;
|
||||
auto maximumSize = layoutConstraints.maximumSize;
|
||||
|
||||
auto measurementsArr = measurePreparedLayout(
|
||||
fabricUIManager,
|
||||
preparedLayout.get(),
|
||||
minimumSize.width,
|
||||
maximumSize.width,
|
||||
minimumSize.height,
|
||||
maximumSize.height);
|
||||
auto measurements = measurementsArr->getRegion(
|
||||
0, static_cast<jsize>(measurementsArr->size()));
|
||||
|
||||
react_native_assert(measurementsArr->size() >= 2);
|
||||
react_native_assert((measurementsArr->size() - 2) % 4 == 0);
|
||||
|
||||
TextMeasurement textMeasurement;
|
||||
|
||||
textMeasurement.size.width = measurements[0];
|
||||
textMeasurement.size.height = measurements[1];
|
||||
|
||||
if (measurementsArr->size() > 2) {
|
||||
textMeasurement.attachments.reserve((measurementsArr->size() - 2) / 4);
|
||||
for (size_t i = 2; i < measurementsArr->size(); i += 4) {
|
||||
auto top = measurements[i];
|
||||
auto left = measurements[i + 1];
|
||||
auto width = measurements[i + 2];
|
||||
auto height = measurements[i + 3];
|
||||
|
||||
if (std::isnan(top) || std::isnan(left)) {
|
||||
textMeasurement.attachments.push_back(
|
||||
TextMeasurement::Attachment{.frame = Rect{}, .isClipped = true});
|
||||
} else {
|
||||
textMeasurement.attachments.push_back(TextMeasurement::Attachment{
|
||||
.frame =
|
||||
{.origin = {.x = left, .y = top},
|
||||
.size = {.width = width, .height = height}},
|
||||
.isClipped = false});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return textMeasurement;
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
+24
@@ -7,12 +7,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/jni/SafeReleaseJniRef.h>
|
||||
#include <react/renderer/attributedstring/AttributedStringBox.h>
|
||||
#include <react/renderer/attributedstring/ParagraphAttributes.h>
|
||||
#include <react/renderer/core/LayoutConstraints.h>
|
||||
#include <react/renderer/textlayoutmanager/JPreparedLayout.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutContext.h>
|
||||
#include <react/renderer/textlayoutmanager/TextMeasureCache.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react {
|
||||
@@ -25,6 +29,8 @@ class TextLayoutManager;
|
||||
*/
|
||||
class TextLayoutManager {
|
||||
public:
|
||||
using PreparedLayout = SafeReleaseJniRef<jni::global_ref<JPreparedLayout>>;
|
||||
|
||||
TextLayoutManager(const ContextContainer::Shared& contextContainer);
|
||||
|
||||
/*
|
||||
@@ -67,6 +73,24 @@ class TextLayoutManager {
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const Size& size) const;
|
||||
|
||||
/**
|
||||
* Create a platform representation of fully laid out text, to later be
|
||||
* reused.
|
||||
*/
|
||||
PreparedLayout prepareLayout(
|
||||
const AttributedString& attributedString,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const TextLayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const;
|
||||
|
||||
/**
|
||||
* Derive text and attachment measurements from a PreparedLayout.
|
||||
*/
|
||||
TextMeasurement measurePreparedLayout(
|
||||
const PreparedLayout& layout,
|
||||
const TextLayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const ContextContainer> contextContainer_;
|
||||
TextMeasureCache textMeasureCache_;
|
||||
|
||||
@@ -8,10 +8,14 @@ set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
|
||||
|
||||
file(GLOB react_utils_SRC CONFIGURE_DEPENDS *.cpp *.mm)
|
||||
file(GLOB react_utils_SRC CONFIGURE_DEPENDS *.cpp platform/android/react/utils/*.cpp)
|
||||
add_library(react_utils OBJECT ${react_utils_SRC})
|
||||
|
||||
target_include_directories(react_utils PUBLIC ${REACT_COMMON_DIR})
|
||||
target_include_directories(react_utils
|
||||
PUBLIC
|
||||
${REACT_COMMON_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/platform/android/
|
||||
)
|
||||
|
||||
target_link_libraries(react_utils
|
||||
glog
|
||||
|
||||
@@ -16,12 +16,12 @@ else
|
||||
source[:tag] = "v#{version}"
|
||||
end
|
||||
|
||||
header_search_paths = [
|
||||
"\"$(PODS_TARGET_SRCROOT)\"",
|
||||
"\"$(PODS_TARGET_SRCROOT)/ReactCommon\"",
|
||||
]
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
source_files = "*.{m,mm,cpp,h}", "platform/ios/**/*.{m,mm,cpp,h}"
|
||||
header_search_paths = [
|
||||
"\"$(PODS_TARGET_SRCROOT)/../../\"",
|
||||
]
|
||||
|
||||
s.name = "React-utils"
|
||||
s.version = version
|
||||
s.summary = "-" # TODO
|
||||
@@ -30,18 +30,21 @@ Pod::Spec.new do |s|
|
||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||
s.platforms = min_supported_versions
|
||||
s.source = source
|
||||
s.source_files = "**/*.{cpp,h,mm}"
|
||||
s.source_files = source_files
|
||||
s.header_dir = "react/utils"
|
||||
s.exclude_files = "tests"
|
||||
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "React_utils"
|
||||
s.header_mappings_dir = "../.."
|
||||
header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\""]
|
||||
end
|
||||
|
||||
s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO",
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
|
||||
s.dependency "React-jsi", version
|
||||
|
||||
depend_on_js_engine(s)
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
namespace facebook::react::LowPriorityExecutor {
|
||||
|
||||
struct LowPriorityExecutorThread {
|
||||
LowPriorityExecutorThread() : thread_{std::thread([this] { run(); })} {
|
||||
pthread_t hThread = thread_.native_handle();
|
||||
struct sched_param param {};
|
||||
param.sched_priority = 19; // Higher value means lower priority
|
||||
pthread_setschedparam(hThread, SCHED_OTHER, ¶m);
|
||||
}
|
||||
|
||||
// Deleted constructors
|
||||
LowPriorityExecutorThread(const LowPriorityExecutorThread& other) = delete;
|
||||
LowPriorityExecutorThread(LowPriorityExecutorThread&& other) = delete;
|
||||
LowPriorityExecutorThread& operator=(const LowPriorityExecutorThread& other) =
|
||||
delete;
|
||||
LowPriorityExecutorThread& operator=(LowPriorityExecutorThread&& other) =
|
||||
delete;
|
||||
|
||||
~LowPriorityExecutorThread() {
|
||||
// Stop the thread
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
running_ = false;
|
||||
}
|
||||
|
||||
// Unblock the thread to check the running_ flag and terminate.
|
||||
cv_.notify_one();
|
||||
|
||||
// Wait for thread completion to avoid use-after-free on background thread.
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
void post(std::function<void()>&& workItem) {
|
||||
// Move the object to the queue.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
queue_.emplace(std::move(workItem));
|
||||
}
|
||||
|
||||
// Notify the background thread.
|
||||
cv_.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
void run() {
|
||||
pthread_setname_np(pthread_self(), "LowPriorityExecutorThread");
|
||||
|
||||
while (true) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
// Wait until an object is in the queue or the thread is stopped.
|
||||
cv_.wait(lock, [this] { return !queue_.empty() || !running_; });
|
||||
|
||||
// Empty the queue.
|
||||
while (!queue_.empty()) {
|
||||
queue_.front()();
|
||||
queue_.pop();
|
||||
}
|
||||
|
||||
// Check if the thread is stopping.
|
||||
if (!running_) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string threadName_;
|
||||
std::thread thread_;
|
||||
std::queue<std::function<void()>> queue_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cv_;
|
||||
bool running_{true};
|
||||
};
|
||||
|
||||
void execute(std::function<void()>&& workItem) {
|
||||
static LowPriorityExecutorThread thread{};
|
||||
thread.post(std::move(workItem));
|
||||
}
|
||||
|
||||
} // namespace facebook::react::LowPriorityExecutor
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace facebook::react::LowPriorityExecutor {
|
||||
|
||||
void execute(std::function<void()>&& workItem);
|
||||
|
||||
} // namespace facebook::react::LowPriorityExecutor
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace facebook::react::LowPriorityExecutor {
|
||||
|
||||
inline void execute(std::function<void()>&& workItem) {
|
||||
workItem();
|
||||
}
|
||||
|
||||
} // namespace facebook::react::LowPriorityExecutor
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace facebook::react::LowPriorityExecutor {
|
||||
|
||||
void execute(std::function<void()>&& workItem);
|
||||
|
||||
} // namespace facebook::react::LowPriorityExecutor
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "LowPriorityExecutor.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
namespace facebook::react::LowPriorityExecutor {
|
||||
|
||||
void execute(std::function<void()> &&workItem)
|
||||
{
|
||||
std::function<void()> localWorkItem = std::move(workItem);
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
|
||||
localWorkItem();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace facebook::react::LowPriorityExecutor
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "1000.0.0",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "A framework for building native apps using React",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -154,13 +154,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/create-cache-key-function": "^29.7.0",
|
||||
"@react-native/assets-registry": "0.80.0-main",
|
||||
"@react-native/codegen": "0.80.0-main",
|
||||
"@react-native/community-cli-plugin": "0.80.0-main",
|
||||
"@react-native/gradle-plugin": "0.80.0-main",
|
||||
"@react-native/js-polyfills": "0.80.0-main",
|
||||
"@react-native/normalize-colors": "0.80.0-main",
|
||||
"@react-native/virtualized-lists": "0.80.0-main",
|
||||
"@react-native/assets-registry": "0.80.0-rc.0",
|
||||
"@react-native/codegen": "0.80.0-rc.0",
|
||||
"@react-native/community-cli-plugin": "0.80.0-rc.0",
|
||||
"@react-native/gradle-plugin": "0.80.0-rc.0",
|
||||
"@react-native/js-polyfills": "0.80.0-rc.0",
|
||||
"@react-native/normalize-colors": "0.80.0-rc.0",
|
||||
"@react-native/virtualized-lists": "0.80.0-rc.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"anser": "^1.4.9",
|
||||
"ansi-regex": "^5.0.0",
|
||||
|
||||
@@ -155,6 +155,17 @@ const definitions: FeatureFlagDefinitions = {
|
||||
},
|
||||
ossReleaseStage: 'none',
|
||||
},
|
||||
enableDestroyShadowTreeRevisionAsync: {
|
||||
defaultValue: false,
|
||||
metadata: {
|
||||
dateAdded: '2025-04-29',
|
||||
description:
|
||||
'Enables destructor calls for ShadowTreeRevision in the background to reduce UI thread work.',
|
||||
expectedReleaseValue: true,
|
||||
purpose: 'experimentation',
|
||||
},
|
||||
ossReleaseStage: 'none',
|
||||
},
|
||||
enableDoubleMeasurementFixAndroid: {
|
||||
defaultValue: false,
|
||||
metadata: {
|
||||
@@ -297,6 +308,16 @@ const definitions: FeatureFlagDefinitions = {
|
||||
},
|
||||
ossReleaseStage: 'none',
|
||||
},
|
||||
enablePreparedTextLayout: {
|
||||
defaultValue: false,
|
||||
metadata: {
|
||||
dateAdded: '2025-05-01',
|
||||
description: 'Enables caching text layout artifacts for later reuse',
|
||||
expectedReleaseValue: true,
|
||||
purpose: 'experimentation',
|
||||
},
|
||||
ossReleaseStage: 'none',
|
||||
},
|
||||
enablePropsUpdateReconciliationAndroid: {
|
||||
defaultValue: false,
|
||||
metadata: {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hermes-2025-05-06-RNv0.80.0-4eb6132a5bf0450bf4c6c91987675381d7ac8bca
|
||||
+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
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import ReactNativeElement from '../../webapis/dom/nodes/ReadOnlyNode';
|
||||
import ensureInstance from './ensureInstance';
|
||||
import * as Fantom from '@react-native/fantom';
|
||||
|
||||
export function createShadowNodeReferenceCounter(
|
||||
element: ReactNativeElement,
|
||||
): () => number {
|
||||
const getReferenceCount = Fantom.createShadowNodeReferenceCounter(element);
|
||||
// Create the reference counting function in a helper instead of creating a
|
||||
// closure here, which would unintentionally retain a reference to `element`.
|
||||
return createExpirationChecker(getReferenceCount);
|
||||
}
|
||||
|
||||
function createExpirationChecker(
|
||||
getReferenceCount: () => number,
|
||||
): () => number {
|
||||
return () => {
|
||||
Fantom.runTask(() => {
|
||||
global.gc();
|
||||
});
|
||||
return getReferenceCount();
|
||||
};
|
||||
}
|
||||
|
||||
export function createShadowNodeReferenceCountingRef(): [
|
||||
() => number,
|
||||
React.RefSetter<mixed>,
|
||||
] {
|
||||
let getReferenceCount: ?() => number;
|
||||
|
||||
function getShadowNodeReferenceCount() {
|
||||
if (getReferenceCount == null) {
|
||||
throw new Error('ShadowNode reference counter was not initialized.');
|
||||
}
|
||||
return getReferenceCount();
|
||||
}
|
||||
|
||||
function ref(instance: mixed | null) {
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
const element = ensureInstance(instance, ReactNativeElement);
|
||||
if (getReferenceCount != null) {
|
||||
throw new Error('ShadowNode reference counter was already initialized.');
|
||||
}
|
||||
getReferenceCount = createShadowNodeReferenceCounter(element);
|
||||
}
|
||||
|
||||
return [getShadowNodeReferenceCount, ref];
|
||||
}
|
||||
Vendored
+210
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* 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
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import 'react-native/Libraries/Core/InitializeCore';
|
||||
|
||||
import type {Node} from '../../../../../Libraries/Renderer/shims/ReactNativeTypes';
|
||||
|
||||
import {getNodeFromPublicInstance} from '../../../../../Libraries/ReactPrivate/ReactNativePrivateInterface';
|
||||
import ReactNativeElement from '../../../webapis/dom/nodes/ReactNativeElement';
|
||||
import ensureInstance from '../ensureInstance';
|
||||
import isUnreachable from '../isUnreachable';
|
||||
import {
|
||||
createShadowNodeReferenceCounter,
|
||||
createShadowNodeReferenceCountingRef,
|
||||
} from '../ShadowNodeReferenceCounter';
|
||||
import * as Fantom from '@react-native/fantom';
|
||||
import nullthrows from 'nullthrows';
|
||||
import * as React from 'react';
|
||||
import {View} from 'react-native';
|
||||
|
||||
test('shadow node expires when root is destroyed', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
const [getReferenceCount, ref] = createShadowNodeReferenceCountingRef();
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(<View ref={ref} />);
|
||||
});
|
||||
|
||||
expect(getReferenceCount()).toBeGreaterThan(0);
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.destroy();
|
||||
});
|
||||
|
||||
expect(getReferenceCount()).toBe(0);
|
||||
});
|
||||
|
||||
test('element is not retained by `createShadowNodeReferenceCounter`', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
let elementWeakRef: ?WeakRef<ReactNativeElement>;
|
||||
let getReferenceCount: ?() => number;
|
||||
|
||||
function ref(instance: React.ElementRef<typeof View> | null) {
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
const element = ensureInstance(instance, ReactNativeElement);
|
||||
elementWeakRef = new WeakRef(element);
|
||||
getReferenceCount = createShadowNodeReferenceCounter(element);
|
||||
}
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<View>
|
||||
<View ref={ref} />
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(isUnreachable(nullthrows(elementWeakRef))).toBe(false);
|
||||
expect(getReferenceCount?.()).toBeGreaterThan(0);
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.destroy();
|
||||
});
|
||||
|
||||
expect(isUnreachable(nullthrows(elementWeakRef))).toBe(true);
|
||||
expect(getReferenceCount?.()).toBe(0);
|
||||
});
|
||||
|
||||
test('shadow node expires when JavaScript element is reachable', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
let element: ?ReactNativeElement;
|
||||
let getReferenceCount: ?() => number;
|
||||
|
||||
function ref(instance: React.ElementRef<typeof View> | null) {
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
element = ensureInstance(instance, ReactNativeElement);
|
||||
getReferenceCount = createShadowNodeReferenceCounter(element);
|
||||
}
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<View>
|
||||
<View ref={ref} />
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(element).not.toBe(undefined);
|
||||
expect(getNodeFromPublicInstance(nullthrows(element))).not.toBe(null);
|
||||
expect(getReferenceCount?.()).toBeGreaterThan(0);
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.destroy();
|
||||
});
|
||||
|
||||
expect(element).not.toBe(undefined);
|
||||
expect(getNodeFromPublicInstance(nullthrows(element))).toBe(null);
|
||||
expect(getReferenceCount?.()).toBe(0);
|
||||
});
|
||||
|
||||
test('shadow node is retained when JavaScript node is reachable', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
let node: ?Node;
|
||||
let getReferenceCount: ?() => number;
|
||||
|
||||
function ref(instance: React.ElementRef<typeof View> | null) {
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
const element = ensureInstance(instance, ReactNativeElement);
|
||||
node = getNodeFromPublicInstance(element);
|
||||
getReferenceCount = createShadowNodeReferenceCounter(element);
|
||||
}
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<View>
|
||||
<View ref={ref} />
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(node).not.toBe(undefined);
|
||||
expect(getReferenceCount?.()).toBeGreaterThan(0);
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.destroy();
|
||||
});
|
||||
|
||||
expect(node).not.toBe(undefined);
|
||||
expect(getReferenceCount?.()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('shadow node expires when replaced by null', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
const [getReferenceCount, ref] = createShadowNodeReferenceCountingRef();
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<View>
|
||||
<View ref={ref} />
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(getReferenceCount()).toBeGreaterThan(0);
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(<View>{null}</View>);
|
||||
});
|
||||
|
||||
// TODO (T223254666): Delete this and figure out why test fails.
|
||||
Fantom.runTask(() => {
|
||||
root.render(<View>{null}</View>);
|
||||
});
|
||||
|
||||
expect(getReferenceCount()).toBe(0);
|
||||
});
|
||||
|
||||
test('shadow node expires when replaced by another view', () => {
|
||||
const root = Fantom.createRoot();
|
||||
|
||||
const [getReferenceCount, ref] = createShadowNodeReferenceCountingRef();
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<View>
|
||||
<View key="a" ref={ref} />
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(getReferenceCount()).toBeGreaterThan(0);
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<View>
|
||||
<View key="b" />
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
// TODO (T223254666): Delete this and figure out why test fails.
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<View>
|
||||
<View key="b" />
|
||||
</View>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(getReferenceCount()).toBe(0);
|
||||
});
|
||||
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<fab0bb6a5cd8a2b8366e8184659188c0>>
|
||||
* @generated SignedSource<<6667fc8e4fdd2db0b54c908155b110cf>>
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
@@ -56,6 +56,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{
|
||||
enableBridgelessArchitecture: Getter<boolean>,
|
||||
enableCppPropsIteratorSetter: Getter<boolean>,
|
||||
enableCustomFocusSearchOnClippedElementsAndroid: Getter<boolean>,
|
||||
enableDestroyShadowTreeRevisionAsync: Getter<boolean>,
|
||||
enableDoubleMeasurementFixAndroid: Getter<boolean>,
|
||||
enableEagerRootViewAttachment: Getter<boolean>,
|
||||
enableFabricLogs: Getter<boolean>,
|
||||
@@ -70,6 +71,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{
|
||||
enableNativeCSSParsing: Getter<boolean>,
|
||||
enableNetworkEventReporting: Getter<boolean>,
|
||||
enableNewBackgroundAndBorderDrawables: Getter<boolean>,
|
||||
enablePreparedTextLayout: Getter<boolean>,
|
||||
enablePropsUpdateReconciliationAndroid: Getter<boolean>,
|
||||
enableResourceTimingAPI: Getter<boolean>,
|
||||
enableSynchronousStateUpdates: Getter<boolean>,
|
||||
@@ -197,6 +199,10 @@ export const enableCppPropsIteratorSetter: Getter<boolean> = createNativeFlagGet
|
||||
* This enables the fabric implementation of focus search so that we can focus clipped elements
|
||||
*/
|
||||
export const enableCustomFocusSearchOnClippedElementsAndroid: Getter<boolean> = createNativeFlagGetter('enableCustomFocusSearchOnClippedElementsAndroid', true);
|
||||
/**
|
||||
* Enables destructor calls for ShadowTreeRevision in the background to reduce UI thread work.
|
||||
*/
|
||||
export const enableDestroyShadowTreeRevisionAsync: Getter<boolean> = createNativeFlagGetter('enableDestroyShadowTreeRevisionAsync', false);
|
||||
/**
|
||||
* When enabled a subset of components will avoid double measurement on Android.
|
||||
*/
|
||||
@@ -253,6 +259,10 @@ export const enableNetworkEventReporting: Getter<boolean> = createNativeFlagGett
|
||||
* Use BackgroundDrawable and BorderDrawable instead of CSSBackgroundDrawable
|
||||
*/
|
||||
export const enableNewBackgroundAndBorderDrawables: Getter<boolean> = createNativeFlagGetter('enableNewBackgroundAndBorderDrawables', true);
|
||||
/**
|
||||
* Enables caching text layout artifacts for later reuse
|
||||
*/
|
||||
export const enablePreparedTextLayout: Getter<boolean> = createNativeFlagGetter('enablePreparedTextLayout', false);
|
||||
/**
|
||||
* When enabled, Android will receive prop updates based on the differences between the last rendered shadow node and the last committed shadow node.
|
||||
*/
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<715d2a137ded85479120f5090c05b3b6>>
|
||||
* @generated SignedSource<<4bf477efaec82ad8e9e4b1bc17705fd2>>
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,7 @@ export interface Spec extends TurboModule {
|
||||
+enableBridgelessArchitecture?: () => boolean;
|
||||
+enableCppPropsIteratorSetter?: () => boolean;
|
||||
+enableCustomFocusSearchOnClippedElementsAndroid?: () => boolean;
|
||||
+enableDestroyShadowTreeRevisionAsync?: () => boolean;
|
||||
+enableDoubleMeasurementFixAndroid?: () => boolean;
|
||||
+enableEagerRootViewAttachment?: () => boolean;
|
||||
+enableFabricLogs?: () => boolean;
|
||||
@@ -48,6 +49,7 @@ export interface Spec extends TurboModule {
|
||||
+enableNativeCSSParsing?: () => boolean;
|
||||
+enableNetworkEventReporting?: () => boolean;
|
||||
+enableNewBackgroundAndBorderDrawables?: () => boolean;
|
||||
+enablePreparedTextLayout?: () => boolean;
|
||||
+enablePropsUpdateReconciliationAndroid?: () => boolean;
|
||||
+enableResourceTimingAPI?: () => boolean;
|
||||
+enableSynchronousStateUpdates?: () => boolean;
|
||||
|
||||
@@ -93,6 +93,9 @@ interface Spec extends TurboModule {
|
||||
validateEmptyMessageQueue: () => void;
|
||||
getRenderedOutput: (surfaceId: number, config: RenderFormatOptions) => string;
|
||||
reportTestSuiteResultsJSON: (results: string) => void;
|
||||
createShadowNodeReferenceCounter(
|
||||
shadowNode: mixed /* ShadowNode */,
|
||||
): () => number;
|
||||
saveJSMemoryHeapSnapshot: (filePath: string) => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,10 @@ Pod::Spec.new do |spec|
|
||||
mkdir -p Headers
|
||||
XCFRAMEWORK_PATH=$(find "$CURRENT_PATH" -type d -name "ReactNativeDependencies.xcframework")
|
||||
HEADERS_PATH=$(find "$XCFRAMEWORK_PATH" -type d -name "Headers" | head -n 1)
|
||||
rsync -a "$HEADERS_PATH/" Headers
|
||||
cp -R "$HEADERS_PATH/" Headers
|
||||
mkdir -p framework/packages/react-native
|
||||
rsync -a --remove-source-files "$XCFRAMEWORK_PATH/.." framework/packages/react-native/
|
||||
cp -R "$XCFRAMEWORK_PATH/.." framework/packages/react-native/
|
||||
find "$XCFRAMEWORK_PATH/.." -type f -exec rm {} +
|
||||
find "$CURRENT_PATH" -type d -empty -delete
|
||||
CMD
|
||||
|
||||
|
||||
+307
-315
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/tester",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"private": true,
|
||||
"description": "React Native tester app.",
|
||||
"license": "MIT",
|
||||
@@ -26,9 +26,9 @@
|
||||
"e2e-test-ios": "./scripts/maestro-test-ios.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native/oss-library-example": "0.80.0-main",
|
||||
"@react-native/new-app-screen": "0.80.0-main",
|
||||
"@react-native/popup-menu-android": "0.80.0-main",
|
||||
"@react-native/oss-library-example": "0.80.0-rc.0",
|
||||
"@react-native/new-app-screen": "0.80.0-rc.0",
|
||||
"@react-native/popup-menu-android": "0.80.0-rc.0",
|
||||
"flow-enums-runtime": "^0.0.6",
|
||||
"invariant": "^2.2.4",
|
||||
"nullthrows": "^1.1.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/typescript-config",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Default TypeScript configuration for React Native apps",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@react-native/virtualized-lists",
|
||||
"version": "0.80.0-main",
|
||||
"version": "0.80.0-rc.0",
|
||||
"description": "Virtualized lists for React Native.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
Reference in New Issue
Block a user