mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b6eb40178 | ||
|
|
a7cd3cc08f | ||
|
|
87f8e85b7f | ||
|
|
f6f5ea0b2e | ||
|
|
6c49572ee4 | ||
|
|
529f55c8c9 | ||
|
|
481fb612a2 | ||
|
|
3ce6a05aac | ||
|
|
813b9441ca | ||
|
|
cf5040b4f8 | ||
|
|
019a553ea4 | ||
|
|
2ae5a74f06 | ||
|
|
3d4a4caac8 | ||
|
|
cdc4a8ead4 | ||
|
|
226d2ba160 | ||
|
|
a16c6c9477 | ||
|
|
59b8974d3c | ||
|
|
2c30215bc7 | ||
|
|
f568c9b953 | ||
|
|
968909488a | ||
|
|
e7ce4ff0bf | ||
|
|
49be01add1 | ||
|
|
13120f630d | ||
|
|
d0140ce53b | ||
|
|
d0fb33822d | ||
|
|
2152180fa0 | ||
|
|
e7aeea26bd | ||
|
|
c04248dc5c | ||
|
|
02e3a999ed | ||
|
|
44b2da0df2 | ||
|
|
dae2f606c7 | ||
|
|
5774bd105d | ||
|
|
3a3f3a417d | ||
|
|
71edbe1548 |
@@ -19,6 +19,7 @@ on:
|
||||
|
||||
jobs:
|
||||
create_release:
|
||||
if: github.repository == 'facebook/react-native'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
@@ -23,6 +23,7 @@ jobs:
|
||||
|
||||
prepare_hermes_workspace:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
env:
|
||||
HERMES_WS_DIR: /tmp/hermes
|
||||
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
|
||||
@@ -50,8 +51,8 @@ jobs:
|
||||
- name: Build HermesC Apple
|
||||
uses: ./.github/actions/build-hermesc-apple
|
||||
with:
|
||||
hermes-version: ${{ needs.prepare_hermes_workspace.output.hermes-version }}
|
||||
react-native-version: ${{ needs.prepare_hermes_workspace.output.react-native-version }}
|
||||
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
|
||||
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
|
||||
|
||||
build_apple_slices_hermes:
|
||||
runs-on: macos-14
|
||||
@@ -75,7 +76,7 @@ jobs:
|
||||
uses: ./.github/actions/build-apple-slices-hermes
|
||||
with:
|
||||
flavor: ${{ matrix.flavor }}
|
||||
slice: ${{ matrix.slice}}
|
||||
slice: ${{ matrix.slice }}
|
||||
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
|
||||
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
|
||||
|
||||
@@ -101,6 +102,7 @@ jobs:
|
||||
flavor: ${{ matrix.flavor }}
|
||||
|
||||
prebuild_apple_dependencies:
|
||||
if: github.repository == 'facebook/react-native'
|
||||
uses: ./.github/workflows/prebuild-ios-dependencies.yml
|
||||
secrets: inherit
|
||||
|
||||
@@ -145,6 +147,7 @@ jobs:
|
||||
|
||||
build_android:
|
||||
runs-on: 8-core-ubuntu
|
||||
if: github.repository == 'facebook/react-native'
|
||||
needs: [set_release_type]
|
||||
container:
|
||||
image: reactnativecommunity/react-native-android:latest
|
||||
|
||||
@@ -9,6 +9,7 @@ on:
|
||||
jobs:
|
||||
publish_bumped_packages:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
env:
|
||||
GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }}
|
||||
steps:
|
||||
|
||||
@@ -21,6 +21,7 @@ jobs:
|
||||
|
||||
prepare_hermes_workspace:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
env:
|
||||
HERMES_WS_DIR: /tmp/hermes
|
||||
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
|
||||
@@ -98,6 +99,7 @@ jobs:
|
||||
flavor: ${{ matrix.flavor }}
|
||||
|
||||
prebuild_apple_dependencies:
|
||||
if: github.repository == 'facebook/react-native'
|
||||
uses: ./.github/workflows/prebuild-ios-dependencies.yml
|
||||
secrets: inherit
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ on:
|
||||
jobs:
|
||||
rerun:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
steps:
|
||||
- name: rerun ${{ inputs.run_id }}
|
||||
env:
|
||||
|
||||
@@ -11,6 +11,7 @@ on:
|
||||
jobs:
|
||||
set_release_type:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
outputs:
|
||||
RELEASE_TYPE: ${{ steps.set_release_type.outputs.RELEASE_TYPE }}
|
||||
env:
|
||||
@@ -34,6 +35,7 @@ jobs:
|
||||
|
||||
prepare_hermes_workspace:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
env:
|
||||
HERMES_WS_DIR: /tmp/hermes
|
||||
HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion
|
||||
@@ -112,6 +114,7 @@ jobs:
|
||||
flavor: ${{ matrix.flavor }}
|
||||
|
||||
prebuild_apple_dependencies:
|
||||
if: github.repository == 'facebook/react-native'
|
||||
uses: ./.github/workflows/prebuild-ios-dependencies.yml
|
||||
secrets: inherit
|
||||
|
||||
@@ -594,6 +597,7 @@ jobs:
|
||||
|
||||
test_js:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -608,6 +612,7 @@ jobs:
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
|
||||
@@ -27,6 +27,7 @@ on:
|
||||
jobs:
|
||||
validate-dotslash-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'facebook/react-native'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# Changelog
|
||||
|
||||
## v0.82.0-rc.1
|
||||
|
||||
### Added
|
||||
|
||||
#### Android specific
|
||||
|
||||
- **Hermes V1:** Added opt-in to use the new Hermes ([3e9990f860](https://github.com/facebook/react-native/commit/3e9990f860eb9380837ef431ca02def32c4261ad) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- **Hermes V1:** Added opt-in to use the new Hermes ([e9cdc308b4](https://github.com/facebook/react-native/commit/e9cdc308b4c04753d85757e8877ac00c3c687b95) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
|
||||
### Changed
|
||||
|
||||
- **Hermes V1:** Changed the source of hermesc binary to be an npm package ([2e0bd13a25](https://github.com/facebook/react-native/commit/2e0bd13a2533fe7ab64125a95b9215b806018c6e) by [@j-piasecki](https://github.com/j-piasecki))
|
||||
|
||||
### Deprecated
|
||||
|
||||
- **APIs:** Deprecate legacy javascript react native apis ([e7aeea26bd](https://github.com/facebook/react-native/commit/e7aeea26bde6e9cda0a3a0a55fc2a0421fb0c0e5) by [@RSNara](https://github.com/RSNara))
|
||||
|
||||
### Fixed
|
||||
|
||||
#### Android specific
|
||||
|
||||
- **Build From Source:** Fix build from source due to missing folder error on Gradle 9.0 ([9fbce3eff1](https://github.com/facebook/react-native/commit/9fbce3eff18060f16e796badc415ba733ede19af) by [@cortinico](https://github.com/cortinico))
|
||||
|
||||
#### iOS specific
|
||||
|
||||
- **RCTAlertController:** Simplify RCTAlertController, don't create additional UIWindow ([05c4321b19](https://github.com/facebook/react-native/commit/05c4321b194c3d0e146b6085bcaccc75acd3fd67) by [@okwasniewski](https://github.com/okwasniewski))
|
||||
- **Prebuild:** Fix Node scripts related to prebuilt tarball extraction for paths containing whitespaces ([9731e8ebc5](https://github.com/facebook/react-native/commit/9731e8ebc5ea87526a91b9903172639e062cd920) by [@kitten](https://github.com/kitten))
|
||||
- **Prebuild:** Use autolinking-generated react-native-config output in second step of cocoapods linking that generates artifacts and generated source ([f170db412b](https://github.com/facebook/react-native/commit/f170db412b3ab46fd0894d5d66431d9c230cd3a8) by [@kitten](https://github.com/kitten))
|
||||
|
||||
## v0.82.0-rc.0
|
||||
|
||||
### Breaking
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
<img src="https://img.shields.io/npm/v/react-native?color=brightgreen&label=npm%20package" alt="Current npm package version." />
|
||||
</a>
|
||||
<a href="https://reactnative.dev/docs/contributing">
|
||||
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs welcome!" />
|
||||
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs are welcome!" />
|
||||
</a>
|
||||
<a href="https://twitter.com/intent/follow?screen_name=reactnative">
|
||||
<img src="https://img.shields.io/twitter/follow/reactnative.svg?label=Follow%20@reactnative" alt="Follow @reactnative" />
|
||||
<img src="https://img.shields.io/twitter/follow/reactnative.svg?label=Follow%20@reactnative" alt="Follow @reactnative on X" />
|
||||
</a>
|
||||
<a href="https://bsky.app/profile/reactnative.dev">
|
||||
<img src="https://img.shields.io/badge/Bluesky-0285FF?logo=bluesky&logoColor=fff" alt="Follow @reactnative.dev on Bluesky" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@
|
||||
"jsonc-parser": "2.2.1",
|
||||
"markdownlint-cli2": "^0.17.2",
|
||||
"markdownlint-rule-relative-links": "^3.0.0",
|
||||
"memfs": "^4.7.7",
|
||||
"memfs": "^4.38.2",
|
||||
"metro-babel-register": "^0.83.1",
|
||||
"metro-transform-plugins": "^0.83.1",
|
||||
"micromatch": "^4.0.4",
|
||||
|
||||
+6
-1
@@ -23,6 +23,7 @@ import com.facebook.react.utils.PropertyUtils.SCOPED_USE_THIRD_PARTY_JSC
|
||||
import com.facebook.react.utils.PropertyUtils.USE_THIRD_PARTY_JSC
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.jetbrains.kotlin.gradle.plugin.extraProperties
|
||||
|
||||
internal object ProjectUtils {
|
||||
|
||||
@@ -75,7 +76,11 @@ internal object ProjectUtils {
|
||||
(project.hasProperty(HERMES_V1_ENABLED) &&
|
||||
project.property(HERMES_V1_ENABLED).toString().toBoolean()) ||
|
||||
(project.hasProperty(SCOPED_HERMES_V1_ENABLED) &&
|
||||
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
|
||||
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean()) ||
|
||||
(project.extraProperties.has(HERMES_V1_ENABLED) &&
|
||||
project.extraProperties.get(HERMES_V1_ENABLED).toString().toBoolean()) ||
|
||||
(project.extraProperties.has(SCOPED_HERMES_V1_ENABLED) &&
|
||||
project.extraProperties.get(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
|
||||
|
||||
internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean {
|
||||
val parsedPackageJson = readPackageJsonFile(this, rootProperty)
|
||||
|
||||
+3
-3
@@ -33,9 +33,9 @@ class GeneratePackageListTaskTest {
|
||||
val inputFile = tempFolder.newFile("config.json")
|
||||
|
||||
val task =
|
||||
createTestTask<GeneratePackageListTask> {
|
||||
it.generatedOutputDirectory.set(outputFolder)
|
||||
it.autolinkInputFile.set(inputFile)
|
||||
createTestTask<GeneratePackageListTask> { testTask ->
|
||||
testTask.generatedOutputDirectory.set(outputFolder)
|
||||
testTask.autolinkInputFile.set(inputFile)
|
||||
}
|
||||
|
||||
assertThat(task.inputs.files.singleFile).isEqualTo(inputFile)
|
||||
|
||||
+5
-5
@@ -82,11 +82,11 @@ class PrepareGflagsTaskTest {
|
||||
val gflagsThirdPartyPath = tempFolder.newFolder("gflagspath/jni")
|
||||
val output = tempFolder.newFolder("output")
|
||||
val task =
|
||||
createTestTask<PrepareGflagsTask> {
|
||||
it.gflagsPath.setFrom(gflagspath)
|
||||
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
|
||||
it.gflagsVersion.set("1.0.0")
|
||||
it.outputDir.set(output)
|
||||
createTestTask<PrepareGflagsTask> { taskConfig ->
|
||||
taskConfig.gflagsPath.setFrom(gflagspath)
|
||||
taskConfig.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
|
||||
taskConfig.gflagsVersion.set("1.0.0")
|
||||
taskConfig.outputDir.set(output)
|
||||
}
|
||||
File(gflagspath, "gflags-1.0.0/src/gflags_declare.h.in").apply {
|
||||
parentFile.mkdirs()
|
||||
|
||||
+5
-5
@@ -25,14 +25,14 @@ class OsRule : TestRule {
|
||||
override fun evaluate() {
|
||||
val annotation = description.annotations.filterIsInstance<WithOs>().firstOrNull()
|
||||
|
||||
annotation?.os?.propertyName?.let {
|
||||
annotation?.os?.propertyName?.let { osName ->
|
||||
retainOs = System.getProperty(OS_NAME_KEY)
|
||||
System.setProperty(OS_NAME_KEY, it)
|
||||
System.setProperty(OS_NAME_KEY, osName)
|
||||
}
|
||||
annotation?.arch?.let {
|
||||
if (it.isNotBlank()) {
|
||||
annotation?.arch?.let { arch ->
|
||||
if (arch.isNotBlank()) {
|
||||
retainArch = System.getProperty(OS_ARCH_KEY)
|
||||
System.setProperty(OS_ARCH_KEY, it)
|
||||
System.setProperty(OS_ARCH_KEY, arch)
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeDelegate.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "RCTDefaultReactNativeFactoryDelegate.h"
|
||||
#import "RCTReactNativeFactory.h"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#import "RCTAppDelegate.h"
|
||||
#import <React/RCTBridgeDelegate.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTRootView.h>
|
||||
#import <React/RCTSurfacePresenterBridgeAdapter.h>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
import NativeTiming from './NativeTiming';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
export * from '../../../src/private/specs_DEPRECATED/modules/NativeTiming';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#import "RCTNetworkConversions.h"
|
||||
|
||||
#import <React/RCTLog.h>
|
||||
#import <jsinspector-modern/network/NetworkReporter.h>
|
||||
#import <react/networking/NetworkReporter.h>
|
||||
|
||||
using namespace facebook::react::jsinspector_modern;
|
||||
using namespace facebook::react;
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
namespace {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @noformat
|
||||
* @nolint
|
||||
* @flow strict
|
||||
* @generated SignedSource<<deb7924d11c790f99448a1c2f0edddb9>>
|
||||
* @generated SignedSource<<c0e57723772ea5f1aa8c3c897ac3c216>>
|
||||
*/
|
||||
|
||||
import type {
|
||||
@@ -135,6 +135,7 @@ export type RenderRootOptions = {
|
||||
error: mixed,
|
||||
errorInfo: {+componentStack?: ?string},
|
||||
) => void,
|
||||
onDefaultTransitionIndicator?: () => void | (() => void),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,7 +67,7 @@ template <typename T>
|
||||
facebook::react::LazyVector<T> RCTBridgingToVec(id value, T (^ctor)(id element))
|
||||
{
|
||||
NSArray *array = RCTBridgingToArray(value);
|
||||
typedef typename facebook::react::LazyVector<T>::size_type _size_t;
|
||||
using _size_t = typename facebook::react::LazyVector<T>::size_type;
|
||||
_size_t size = static_cast<_size_t>(array.count);
|
||||
return facebook::react::LazyVector<T>::fromUnsafeRawValue(array, size, ctor);
|
||||
}
|
||||
|
||||
@@ -211,6 +211,18 @@ let reactHermes = RNTarget(
|
||||
]
|
||||
)
|
||||
|
||||
/// React-networking.podspec
|
||||
let reactNetworking = RNTarget(
|
||||
name: .reactNetworking,
|
||||
path: "ReactCommon/react/networking",
|
||||
excludedPaths: ["tests"],
|
||||
dependencies: [.reactNativeDependencies, .reactJsInspectorNetwork, .reactPerformanceTimeline],
|
||||
defines: [
|
||||
CXXSetting.define("REACT_NATIVE_DEBUGGER_ENABLED", to: "1", .when(configuration: BuildConfiguration.debug)),
|
||||
CXXSetting.define("REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY", to: "1", .when(configuration: BuildConfiguration.debug)),
|
||||
]
|
||||
)
|
||||
|
||||
/// React-performancecdpmetrics.podspec
|
||||
let reactPerformanceCdpMetrics = RNTarget(
|
||||
name: .reactPerformanceCdpMetrics,
|
||||
@@ -304,6 +316,13 @@ let reactIdleCallbacksNativeModule = RNTarget(
|
||||
dependencies: [.reactNativeDependencies, .reactDebug, .reactFeatureFlags, .reactUtils, .reactPerfLogger, .reactCxxReact, .reactTurboModuleCore]
|
||||
)
|
||||
|
||||
/// React-webperformance.podspec
|
||||
let reactWebPerformanceNativeModule = RNTarget(
|
||||
name: .reactWebPerformanceNativeModule,
|
||||
path: "ReactCommon/react/nativemodule/webperformance",
|
||||
dependencies: [.reactNativeDependencies, .reactCxxReact, .reactTurboModuleCore, .reactPerformanceTimeline]
|
||||
)
|
||||
|
||||
/// React-featureflagnativemodule.podspec
|
||||
let reactFeatureflagsNativemodule = RNTarget(
|
||||
name: .reactFeatureflagsNativemodule,
|
||||
@@ -566,6 +585,7 @@ let targets = [
|
||||
reactNativeDependencies,
|
||||
hermesPrebuilt,
|
||||
reactJsiTooling,
|
||||
reactNetworking,
|
||||
reactPerformanceCdpMetrics,
|
||||
reactPerformanceTimeline,
|
||||
reactRuntimeScheduler,
|
||||
@@ -590,6 +610,7 @@ let targets = [
|
||||
reactTurboModuleCoreDefaults,
|
||||
reactTurboModuleCoreMicrotasks,
|
||||
reactIdleCallbacksNativeModule,
|
||||
reactWebPerformanceNativeModule,
|
||||
reactFeatureflagsNativemodule,
|
||||
reactNativeModuleDom,
|
||||
reactAppDelegate,
|
||||
@@ -737,6 +758,7 @@ extension String {
|
||||
static let hermesPrebuilt = "hermes-prebuilt"
|
||||
|
||||
static let reactJsiTooling = "React-jsitooling"
|
||||
static let reactNetworking = "React-networking"
|
||||
static let reactPerformanceCdpMetrics = "React-performancecdpmetrics"
|
||||
static let reactPerformanceTimeline = "React-performancetimeline"
|
||||
static let reactRuntimeScheduler = "React-runtimescheduler"
|
||||
@@ -764,6 +786,7 @@ extension String {
|
||||
static let reactTurboModuleCoreDefaults = "ReactCommon/turbomodule/core/defaults"
|
||||
static let reactTurboModuleCoreMicrotasks = "ReactCommon/turbomodule/core/microtasks"
|
||||
static let reactIdleCallbacksNativeModule = "React-idlecallbacksnativemodule"
|
||||
static let reactWebPerformanceNativeModule = "React-webperformancenativemodule"
|
||||
static let reactFeatureflagsNativemodule = "React-featureflagsnativemodule"
|
||||
static let reactNativeModuleDom = "React-domnativemodule"
|
||||
static let reactAppDelegate = "React-RCTAppDelegate"
|
||||
|
||||
@@ -721,13 +721,13 @@ NSData *__nullable RCTGzipData(NSData *__nullable input, float level)
|
||||
|
||||
void *libz = dlopen("/usr/lib/libz.dylib", RTLD_LAZY);
|
||||
|
||||
typedef int (*DeflateInit2_)(z_streamp, int, int, int, int, int, const char *, int);
|
||||
using DeflateInit2_ = int (*)(z_streamp, int, int, int, int, int, const char *, int);
|
||||
DeflateInit2_ deflateInit2_ = (DeflateInit2_)dlsym(libz, "deflateInit2_");
|
||||
|
||||
typedef int (*Deflate)(z_streamp, int);
|
||||
using Deflate = int (*)(z_streamp, int);
|
||||
Deflate deflate = (Deflate)dlsym(libz, "deflate");
|
||||
|
||||
typedef int (*DeflateEnd)(z_streamp);
|
||||
using DeflateEnd = int (*)(z_streamp);
|
||||
DeflateEnd deflateEnd = (DeflateEnd)dlsym(libz, "deflateEnd");
|
||||
|
||||
z_stream stream;
|
||||
|
||||
@@ -238,11 +238,10 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale)
|
||||
- (void)interfaceOrientationDidChange
|
||||
{
|
||||
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
|
||||
UIApplication *application = RCTSharedApplication();
|
||||
UIInterfaceOrientation nextOrientation = RCTKeyWindow().windowScene.interfaceOrientation;
|
||||
UIWindow *window = RCTKeyWindow();
|
||||
UIInterfaceOrientation nextOrientation = window.windowScene.interfaceOrientation;
|
||||
|
||||
BOOL isRunningInFullScreen =
|
||||
CGRectEqualToRect(application.delegate.window.frame, application.delegate.window.screen.bounds);
|
||||
BOOL isRunningInFullScreen = window ? CGRectEqualToRect(window.frame, window.screen.bounds) : YES;
|
||||
// We are catching here two situations for multitasking view:
|
||||
// a) The app is in Split View and the container gets resized -> !isRunningInFullScreen
|
||||
// b) The app changes to/from fullscreen example: App runs in slide over mode and goes into fullscreen->
|
||||
|
||||
@@ -91,9 +91,9 @@ Pod::Spec.new do |s|
|
||||
add_dependency(s, "React-RCTAnimation", :framework_name => 'RCTAnimation')
|
||||
add_dependency(s, "React-jsinspector", :framework_name => 'jsinspector_modern')
|
||||
add_dependency(s, "React-jsinspectorcdp", :framework_name => 'jsinspector_moderncdp')
|
||||
add_dependency(s, "React-jsinspectornetwork", :framework_name => 'jsinspector_modernnetwork')
|
||||
add_dependency(s, "React-jsinspectortracing", :framework_name => 'jsinspector_moderntracing')
|
||||
add_dependency(s, "React-performancecdpmetrics", :framework_name => 'React_performancecdpmetrics')
|
||||
add_dependency(s, "React-networking", :framework_name => 'React_networking')
|
||||
add_dependency(s, "React-renderercss")
|
||||
add_dependency(s, "React-RCTFBReactNativeSpec")
|
||||
|
||||
|
||||
@@ -2354,12 +2354,14 @@ public class com/facebook/react/fabric/mounting/SurfaceMountingManager {
|
||||
public fun sendAccessibilityEvent (II)V
|
||||
public fun setJSResponder (IIZ)V
|
||||
public fun stopSurface ()V
|
||||
public fun storeSynchronousMountPropsOverride (ILcom/facebook/react/bridge/ReadableMap;)V
|
||||
public fun sweepActiveTouchForTag (I)V
|
||||
public fun updateEventEmitter (ILcom/facebook/react/fabric/events/EventEmitterWrapper;)V
|
||||
public fun updateLayout (IIIIIIII)V
|
||||
public fun updateOverflowInset (IIIII)V
|
||||
public fun updatePadding (IIIII)V
|
||||
public fun updateProps (ILcom/facebook/react/bridge/ReadableMap;)V
|
||||
public fun updatePropsSynchronously (ILcom/facebook/react/bridge/ReadableMap;)V
|
||||
public fun updateState (ILcom/facebook/react/uimanager/StateWrapper;)V
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ val hermesVersionProvider: Provider<String> =
|
||||
val hermesVersionFile =
|
||||
File(
|
||||
reactNativeRootDir,
|
||||
if (hermesV1Enabled) "sdks/.hermesv1version" else "\"sdks/.hermesversion\"",
|
||||
if (hermesV1Enabled) "sdks/.hermesv1version" else "sdks/.hermesversion",
|
||||
)
|
||||
|
||||
if (hermesVersionFile.exists()) {
|
||||
|
||||
+1
-1
@@ -83,6 +83,6 @@ internal class BridgelessDevSupportManager(
|
||||
}
|
||||
|
||||
fun tracingState(): TracingState {
|
||||
return TracingState.DISABLED
|
||||
return TracingState.ENABLEDINCDPMODE
|
||||
}
|
||||
}
|
||||
|
||||
+12
-8
@@ -68,6 +68,7 @@ import com.facebook.react.devsupport.interfaces.StackFrame
|
||||
import com.facebook.react.devsupport.interfaces.TracingState
|
||||
import com.facebook.react.devsupport.interfaces.TracingStateProvider
|
||||
import com.facebook.react.devsupport.perfmonitor.PerfMonitorDevHelper
|
||||
import com.facebook.react.devsupport.perfmonitor.PerfMonitorOverlayManager
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags
|
||||
import com.facebook.react.modules.core.RCTNativeAppEventEmitter
|
||||
@@ -77,6 +78,7 @@ import java.io.File
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import java.util.Locale
|
||||
import javax.inject.Provider
|
||||
|
||||
public abstract class DevSupportManagerBase(
|
||||
protected val applicationContext: Context,
|
||||
@@ -182,7 +184,7 @@ public abstract class DevSupportManagerBase(
|
||||
null
|
||||
}
|
||||
|
||||
private var perfMonitorOverlayManager: PerfMonitorOverlayViewManager? = null
|
||||
private var perfMonitorOverlayManager: PerfMonitorOverlayManager? = null
|
||||
private var tracingStateProvider: TracingStateProvider? = null
|
||||
|
||||
init {
|
||||
@@ -215,19 +217,19 @@ public abstract class DevSupportManagerBase(
|
||||
if (
|
||||
ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
|
||||
ReactNativeFeatureFlags.perfMonitorV2Enabled() &&
|
||||
reactInstanceDevHelper is PerfMonitorDevHelper &&
|
||||
perfMonitorOverlayManager == null
|
||||
reactInstanceDevHelper is PerfMonitorDevHelper
|
||||
) {
|
||||
perfMonitorOverlayManager =
|
||||
PerfMonitorOverlayViewManager(
|
||||
Supplier {
|
||||
PerfMonitorOverlayManager(
|
||||
reactInstanceDevHelper,
|
||||
Provider {
|
||||
val context = reactInstanceDevHelper.currentActivity
|
||||
if (context == null || context.isFinishing) {
|
||||
return@Supplier null
|
||||
return@Provider null
|
||||
}
|
||||
context
|
||||
},
|
||||
reactInstanceDevHelper.inspectorTarget,
|
||||
{ openDebugger(DebuggerFrontendPanelName.PERFORMANCE.toString()) },
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -548,10 +550,11 @@ public abstract class DevSupportManagerBase(
|
||||
override fun onNewReactContextCreated(reactContext: ReactContext) {
|
||||
resetCurrentContext(reactContext)
|
||||
|
||||
if (perfMonitorOverlayManager != null && reactInstanceDevHelper is PerfMonitorDevHelper) {
|
||||
if (reactInstanceDevHelper is PerfMonitorDevHelper) {
|
||||
perfMonitorOverlayManager?.let { manager ->
|
||||
reactInstanceDevHelper.inspectorTarget?.addPerfMonitorListener(manager)
|
||||
}
|
||||
perfMonitorOverlayManager?.enable()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -882,6 +885,7 @@ public abstract class DevSupportManagerBase(
|
||||
|
||||
override fun onPackagerDisconnected() {
|
||||
isPackagerConnected = false
|
||||
perfMonitorOverlayManager?.disable()
|
||||
}
|
||||
|
||||
override fun onPackagerReloadCommand() {
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.devsupport.interfaces
|
||||
|
||||
/** [Experimental] Interface to manage the V2 Perf Monitor overlay. */
|
||||
internal interface PerfMonitorOverlayManager {
|
||||
/** Enable the Perf Monitor overlay. Will be shown when updates are received. */
|
||||
public fun enable()
|
||||
|
||||
/** Disable the Perf Monitor overlay. Will remain hidden when updates are received. */
|
||||
public fun disable()
|
||||
|
||||
/** Reset the Perf Monitor overlay, e.g. after a reload. */
|
||||
public fun reset()
|
||||
}
|
||||
+5
@@ -7,11 +7,16 @@
|
||||
|
||||
package com.facebook.react.devsupport.perfmonitor
|
||||
|
||||
import com.facebook.react.devsupport.interfaces.TracingState
|
||||
|
||||
/**
|
||||
* [Experimental] Interface implemented by [com.facebook.react.runtime.ReactHostInspectorTarget]
|
||||
* exposing actions for the V2 Perf Monitor.
|
||||
*/
|
||||
internal interface PerfMonitorInspectorTargetBinding {
|
||||
/** Get the current CDP or background performance tracing state. */
|
||||
public fun getTracingState(): TracingState
|
||||
|
||||
/** Attempt to pause the current background performance trace, and open in DevTools. */
|
||||
public fun pauseAndAnalyzeBackgroundTrace()
|
||||
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.devsupport.perfmonitor
|
||||
|
||||
import android.content.Context
|
||||
import com.facebook.react.bridge.UiThreadUtil
|
||||
import com.facebook.react.devsupport.interfaces.TracingState
|
||||
import javax.inject.Provider
|
||||
|
||||
internal class PerfMonitorOverlayManager(
|
||||
private val devHelper: PerfMonitorDevHelper,
|
||||
private val contextProvider: Provider<Context?>,
|
||||
private val onRequestOpenDevTools: () -> Unit,
|
||||
) : PerfMonitorUpdateListener {
|
||||
private var enabled: Boolean = false
|
||||
private var initialized: Boolean = false
|
||||
private var view: PerfMonitorOverlayView? = null
|
||||
private var tracingState: TracingState = TracingState.ENABLEDINCDPMODE
|
||||
|
||||
private fun init() {
|
||||
if (initialized || !enabled) {
|
||||
return
|
||||
}
|
||||
|
||||
UiThreadUtil.runOnUiThread {
|
||||
val context = contextProvider.get() ?: return@runOnUiThread
|
||||
view = PerfMonitorOverlayView(context, ::handleRecordingButtonPress)
|
||||
|
||||
// Start background tracing
|
||||
devHelper.inspectorTarget?.resumeBackgroundTrace()
|
||||
|
||||
view?.show()
|
||||
initialized = true
|
||||
}
|
||||
}
|
||||
|
||||
/** Enable the Perf Monitor overlay. Will be shown when updates are received. */
|
||||
fun enable() {
|
||||
enabled = true
|
||||
init()
|
||||
UiThreadUtil.runOnUiThread { view?.show() }
|
||||
}
|
||||
|
||||
/** Disable the Perf Monitor overlay. Will remain hidden when updates are received. */
|
||||
fun disable() {
|
||||
UiThreadUtil.runOnUiThread { view?.hide() }
|
||||
enabled = false
|
||||
}
|
||||
|
||||
/** Reset the Perf Monitor overlay, e.g. after a reload. */
|
||||
fun reset() {
|
||||
UiThreadUtil.runOnUiThread { view?.resetState() }
|
||||
|
||||
// Update with current recording state
|
||||
onRecordingStateChanged(
|
||||
devHelper.inspectorTarget?.getTracingState() ?: TracingState.ENABLEDINCDPMODE
|
||||
)
|
||||
}
|
||||
|
||||
override fun onNewFocusedEvent(data: PerfMonitorUpdateListener.LongTaskEventData) {
|
||||
view?.updateFocusedEvent(data)
|
||||
}
|
||||
|
||||
override fun onRecordingStateChanged(state: TracingState) {
|
||||
tracingState = state
|
||||
view?.updateRecordingState(state)
|
||||
}
|
||||
|
||||
private fun handleRecordingButtonPress() {
|
||||
when (tracingState) {
|
||||
TracingState.ENABLEDINBACKGROUNDMODE -> {
|
||||
devHelper.inspectorTarget?.pauseAndAnalyzeBackgroundTrace()
|
||||
onRequestOpenDevTools()
|
||||
}
|
||||
TracingState.DISABLED -> {
|
||||
devHelper.inspectorTarget?.resumeBackgroundTrace()
|
||||
}
|
||||
TracingState.ENABLEDINCDPMODE -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
+142
-108
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.devsupport
|
||||
package com.facebook.react.devsupport.perfmonitor
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
@@ -20,107 +20,110 @@ import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.util.Supplier
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.facebook.react.R
|
||||
import com.facebook.react.bridge.UiThreadUtil
|
||||
import com.facebook.react.devsupport.interfaces.PerfMonitorOverlayManager
|
||||
import com.facebook.react.devsupport.interfaces.TracingState
|
||||
import com.facebook.react.devsupport.perfmonitor.PerfMonitorInspectorTargetBinding
|
||||
import com.facebook.react.devsupport.perfmonitor.PerfMonitorUpdateListener
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder
|
||||
import com.facebook.react.uimanager.PixelUtil
|
||||
import java.util.Locale
|
||||
|
||||
internal class PerfMonitorOverlayViewManager(
|
||||
private val contextSupplier: Supplier<Context?>,
|
||||
private val inspectorTarget: PerfMonitorInspectorTargetBinding?,
|
||||
) : PerfMonitorOverlayManager, PerfMonitorUpdateListener {
|
||||
private var initialized: Boolean = false
|
||||
private var enabled: Boolean = false
|
||||
private var hasInteractionData: Boolean = false
|
||||
private var interactionDialog: Dialog? = null
|
||||
private var buttonDialog: Dialog? = null
|
||||
private var durationLabel: TextView? = null
|
||||
internal class PerfMonitorOverlayView(
|
||||
private val context: Context,
|
||||
private val onButtonPress: () -> Unit,
|
||||
) {
|
||||
private var hidden: Boolean = true
|
||||
private var hasEventData: Boolean = false
|
||||
private val metricsDialog: Dialog
|
||||
private val toolbarDialog: Dialog
|
||||
private val tooltipDialog: Dialog
|
||||
private lateinit var buttonLabel: TextView
|
||||
private lateinit var recordingStateLabel: TextView
|
||||
private lateinit var durationLabel: TextView
|
||||
private lateinit var tooltipLabel: TextView
|
||||
private var ttl: Int = 0
|
||||
private var hideAfterTimeoutHandler: Handler? = null
|
||||
|
||||
override fun enable() {
|
||||
UiThreadUtil.runOnUiThread {
|
||||
enabled = true
|
||||
if (hasInteractionData) {
|
||||
showOverlay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun disable() {
|
||||
UiThreadUtil.runOnUiThread {
|
||||
enabled = false
|
||||
hideOverlay()
|
||||
}
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
UiThreadUtil.runOnUiThread {
|
||||
hasInteractionData = false
|
||||
hideOverlay()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRecordingStateChanged(state: TracingState) {
|
||||
// recordingState = state
|
||||
// view?.updateRecordingState(state)
|
||||
}
|
||||
|
||||
override fun onNewFocusedEvent(data: PerfMonitorUpdateListener.LongTaskEventData) {
|
||||
UiThreadUtil.runOnUiThread {
|
||||
ensureInitialized()
|
||||
durationLabel?.text = String.format(Locale.US, "%d ms", data.durationMs)
|
||||
durationLabel?.setTextColor(getDurationHighlightColor(data.responsivenessScore))
|
||||
hasInteractionData = true
|
||||
ttl = data.ttl
|
||||
|
||||
hideAfterTimeoutHandler?.removeCallbacksAndMessages(null)
|
||||
|
||||
if (enabled) {
|
||||
showOverlay()
|
||||
|
||||
// Schedule hiding overlay after ttl milliseconds
|
||||
if (ttl > 0) {
|
||||
if (hideAfterTimeoutHandler == null) {
|
||||
hideAfterTimeoutHandler = Handler(Looper.getMainLooper())
|
||||
}
|
||||
hideAfterTimeoutHandler?.postDelayed({ hideOverlay() }, ttl.toLong())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ensureInitialized() {
|
||||
if (initialized) {
|
||||
return
|
||||
}
|
||||
val context = contextSupplier.get() ?: return
|
||||
init {
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
|
||||
createDialog(context)
|
||||
createButton(context)
|
||||
initialized = true
|
||||
tooltipDialog = createTooltipDialog()
|
||||
metricsDialog = createMetricsDialog()
|
||||
toolbarDialog = createToolbarDialog()
|
||||
}
|
||||
|
||||
private fun showOverlay() {
|
||||
interactionDialog?.show()
|
||||
buttonDialog?.show()
|
||||
fun show() {
|
||||
toolbarDialog.show()
|
||||
tooltipDialog.show()
|
||||
if (hasEventData) {
|
||||
toolbarDialog.window?.decorView?.post { updateMetricsDialogPosition() }
|
||||
metricsDialog.show()
|
||||
}
|
||||
hidden = false
|
||||
}
|
||||
|
||||
private fun hideOverlay() {
|
||||
interactionDialog?.hide()
|
||||
buttonDialog?.hide()
|
||||
fun hide() {
|
||||
metricsDialog.hide()
|
||||
toolbarDialog.hide()
|
||||
tooltipDialog.hide()
|
||||
hidden = true
|
||||
}
|
||||
|
||||
private fun createDialog(context: Context) {
|
||||
val containerLayout = createInnerLayout(context)
|
||||
fun resetState() {
|
||||
hasEventData = false
|
||||
metricsDialog.hide()
|
||||
}
|
||||
|
||||
fun updateFocusedEvent(data: PerfMonitorUpdateListener.LongTaskEventData) {
|
||||
durationLabel.text = String.format(Locale.US, "%d ms", data.durationMs)
|
||||
durationLabel.setTextColor(getDurationHighlightColor(data.responsivenessScore))
|
||||
hasEventData = true
|
||||
ttl = data.ttl
|
||||
|
||||
hideAfterTimeoutHandler?.removeCallbacksAndMessages(null)
|
||||
|
||||
if (!hidden) {
|
||||
metricsDialog.show()
|
||||
|
||||
// Schedule hiding metrics overlay after ttl milliseconds
|
||||
if (ttl > 0) {
|
||||
if (hideAfterTimeoutHandler == null) {
|
||||
hideAfterTimeoutHandler = Handler(Looper.getMainLooper())
|
||||
}
|
||||
hideAfterTimeoutHandler?.postDelayed({ metricsDialog.hide() }, ttl.toLong())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateRecordingState(state: TracingState) {
|
||||
recordingStateLabel.text =
|
||||
when (state) {
|
||||
TracingState.ENABLEDINBACKGROUNDMODE -> "Profiling: ON"
|
||||
TracingState.DISABLED -> "Profiling: OFF"
|
||||
TracingState.ENABLEDINCDPMODE -> "Profiling: DISABLED"
|
||||
}
|
||||
buttonLabel.text =
|
||||
when (state) {
|
||||
TracingState.ENABLEDINBACKGROUNDMODE -> "Open ↗️"
|
||||
TracingState.DISABLED -> "Start"
|
||||
TracingState.ENABLEDINCDPMODE -> ""
|
||||
}
|
||||
tooltipLabel.text =
|
||||
when (state) {
|
||||
TracingState.ENABLEDINBACKGROUNDMODE -> "Dev Menu > Finish performance trace"
|
||||
TracingState.DISABLED -> "Dev Menu > Start performance trace"
|
||||
TracingState.ENABLEDINCDPMODE -> ""
|
||||
}
|
||||
if (state == TracingState.ENABLEDINCDPMODE) {
|
||||
tooltipDialog.hide()
|
||||
} else {
|
||||
tooltipDialog.show()
|
||||
}
|
||||
|
||||
toolbarDialog.window?.decorView?.post { updateMetricsDialogPosition() }
|
||||
}
|
||||
|
||||
private fun createMetricsDialog(): Dialog {
|
||||
val containerLayout = createInnerLayout()
|
||||
val longTaskLabel =
|
||||
TextView(context).apply {
|
||||
textSize = TEXT_SIZE_PRIMARY
|
||||
@@ -138,7 +141,7 @@ internal class PerfMonitorOverlayViewManager(
|
||||
containerLayout.addView(durationLabel)
|
||||
|
||||
val dialog =
|
||||
createAnchoredDialog(context, dpToPx(140f), dpToPx(16f)).apply {
|
||||
createAnchoredDialog(getMetricsDialogOffsetX(), dpToPx(16f)).apply {
|
||||
setContentView(containerLayout)
|
||||
}
|
||||
dialog.window?.apply {
|
||||
@@ -151,30 +154,25 @@ internal class PerfMonitorOverlayViewManager(
|
||||
}
|
||||
}
|
||||
|
||||
this.interactionDialog = dialog
|
||||
return dialog
|
||||
}
|
||||
|
||||
fun updateRecordingState(state: TracingState) {}
|
||||
|
||||
private fun createButton(context: Context) {
|
||||
val buttonInner = createInnerLayout(context)
|
||||
buttonInner.addView(
|
||||
private fun createToolbarDialog(): Dialog {
|
||||
val buttonInner = createInnerLayout()
|
||||
recordingStateLabel =
|
||||
TextView(context).apply {
|
||||
text = "Analyze"
|
||||
textSize = TEXT_SIZE_PRIMARY
|
||||
setTextColor(Color.WHITE)
|
||||
typeface = TYPEFACE_BOLD
|
||||
}
|
||||
)
|
||||
buttonInner.addView(
|
||||
buttonInner.addView(recordingStateLabel)
|
||||
buttonLabel =
|
||||
TextView(context).apply {
|
||||
text = "cmd + A"
|
||||
textSize = TEXT_SIZE_ACCESSORY
|
||||
setTextColor(Color.WHITE)
|
||||
alpha = 0.7f
|
||||
textSize = TEXT_SIZE_PRIMARY
|
||||
setTextColor(COLOR_TEXT_BLUE)
|
||||
typeface = TYPEFACE_BOLD
|
||||
}
|
||||
)
|
||||
buttonInner.addView(buttonLabel)
|
||||
val buttonView =
|
||||
LinearLayout(context).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
@@ -185,19 +183,43 @@ internal class PerfMonitorOverlayViewManager(
|
||||
dpToPx(8f).toInt(),
|
||||
)
|
||||
addView(buttonInner)
|
||||
setOnClickListener { inspectorTarget?.pauseAndAnalyzeBackgroundTrace() }
|
||||
setOnClickListener { onButtonPress() }
|
||||
}
|
||||
val dialog =
|
||||
createAnchoredDialog(context, dpToPx(0f), dpToPx(0f)).apply { setContentView(buttonView) }
|
||||
|
||||
val dialog = createAnchoredDialog(dpToPx(0f), dpToPx(0f)).apply { setContentView(buttonView) }
|
||||
dialog.window?.apply {
|
||||
attributes =
|
||||
attributes?.apply { flags = flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE }
|
||||
}
|
||||
|
||||
this.buttonDialog = dialog
|
||||
return dialog
|
||||
}
|
||||
|
||||
private fun createAnchoredDialog(context: Context, offsetX: Float, offsetY: Float): Dialog {
|
||||
private fun createTooltipDialog(): Dialog {
|
||||
val containerLayout = createInnerLayout()
|
||||
tooltipLabel =
|
||||
TextView(context).apply {
|
||||
textSize = TEXT_SIZE_ACCESSORY
|
||||
setTextColor(Color.WHITE)
|
||||
}
|
||||
containerLayout.addView(tooltipLabel)
|
||||
|
||||
val dialog =
|
||||
createAnchoredDialog(dpToPx(16f), dpToPx(52f)).apply { setContentView(containerLayout) }
|
||||
dialog.window?.apply {
|
||||
attributes =
|
||||
attributes?.apply {
|
||||
flags =
|
||||
flags or
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
}
|
||||
}
|
||||
|
||||
return dialog
|
||||
}
|
||||
|
||||
private fun createAnchoredDialog(offsetX: Float, offsetY: Float): Dialog {
|
||||
val dialog =
|
||||
Dialog(context, R.style.NoAnimationDialog).apply {
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
@@ -228,12 +250,12 @@ internal class PerfMonitorOverlayViewManager(
|
||||
return dialog
|
||||
}
|
||||
|
||||
private fun createInnerLayout(context: Context): LinearLayout {
|
||||
private fun createInnerLayout(): LinearLayout {
|
||||
return LinearLayout(context).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
val paddingHorizontal = dpToPx(14f).toInt()
|
||||
val paddingVertical = dpToPx(8f).toInt()
|
||||
val paddingVertical = dpToPx(7f).toInt()
|
||||
setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical)
|
||||
layoutParams =
|
||||
LinearLayout.LayoutParams(
|
||||
@@ -256,10 +278,21 @@ internal class PerfMonitorOverlayViewManager(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMetricsDialogOffsetX(): Float {
|
||||
val toolbarWidth = toolbarDialog?.window?.decorView?.width ?: 0
|
||||
return toolbarWidth.toFloat()
|
||||
}
|
||||
|
||||
private fun updateMetricsDialogPosition() {
|
||||
metricsDialog?.window?.apply {
|
||||
attributes = attributes?.apply { x = getMetricsDialogOffsetX().toInt() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDurationHighlightColor(responsivenessScore: Int): Int {
|
||||
return when (responsivenessScore) {
|
||||
3 -> COLOR_TEXT_RED
|
||||
2 -> COLOR_TEXT_YELLOW
|
||||
2 -> COLOR_TEXT_RED
|
||||
1 -> COLOR_TEXT_YELLOW
|
||||
else -> COLOR_TEXT_GREEN
|
||||
}
|
||||
}
|
||||
@@ -270,6 +303,7 @@ internal class PerfMonitorOverlayViewManager(
|
||||
private val COLOR_TEXT_GREEN = Color.parseColor("#4AEB2F")
|
||||
private val COLOR_TEXT_YELLOW = Color.parseColor("#FFAA00")
|
||||
private val COLOR_TEXT_RED = Color.parseColor("#FF0000")
|
||||
private val COLOR_TEXT_BLUE = Color.parseColor("#00B0FF")
|
||||
private val COLOR_OVERLAY_BORDER = Color.parseColor("#6C6C6C")
|
||||
private val TEXT_SIZE_PRIMARY = 13f
|
||||
private val TEXT_SIZE_ACCESSORY = 9f
|
||||
+2
-1
@@ -791,7 +791,8 @@ public class FabricUIManager
|
||||
@Override
|
||||
public void execute(MountingManager mountingManager) {
|
||||
try {
|
||||
mountingManager.updateProps(reactTag, props);
|
||||
mountingManager.storeSynchronousMountPropsOverride(reactTag, props);
|
||||
mountingManager.updatePropsSynchronously(reactTag, props);
|
||||
} catch (Exception ex) {
|
||||
// TODO T42943890: Fix animations in Fabric and remove this try/catch?
|
||||
// There might always be race conditions between surface teardown and
|
||||
|
||||
+12
-2
@@ -265,13 +265,23 @@ internal class MountingManager(
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun updateProps(reactTag: Int, props: ReadableMap?) {
|
||||
fun storeSynchronousMountPropsOverride(reactTag: Int, props: ReadableMap?) {
|
||||
assertOnUiThread()
|
||||
if (props == null) {
|
||||
return
|
||||
}
|
||||
|
||||
getSurfaceManagerForViewEnforced(reactTag).updateProps(reactTag, props)
|
||||
getSurfaceManagerForViewEnforced(reactTag).storeSynchronousMountPropsOverride(reactTag, props)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun updatePropsSynchronously(reactTag: Int, props: ReadableMap?) {
|
||||
assertOnUiThread()
|
||||
if (props == null) {
|
||||
return
|
||||
}
|
||||
|
||||
getSurfaceManagerForViewEnforced(reactTag).updatePropsSynchronously(reactTag, props)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+115
-1
@@ -27,10 +27,14 @@ import com.facebook.react.bridge.ReactNoCrashSoftException;
|
||||
import com.facebook.react.bridge.ReactSoftExceptionLogger;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableType;
|
||||
import com.facebook.react.bridge.RetryableMountingLayerException;
|
||||
import com.facebook.react.bridge.SoftAssertions;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableNativeArray;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.common.annotations.UnstableReactNativeAPI;
|
||||
import com.facebook.react.common.build.ReactBuildConfig;
|
||||
import com.facebook.react.common.mapbuffer.MapBuffer;
|
||||
@@ -53,7 +57,10 @@ import com.facebook.react.uimanager.ViewManagerRegistry;
|
||||
import com.facebook.react.uimanager.events.EventCategoryDef;
|
||||
import com.facebook.systrace.Systrace;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
@@ -96,6 +103,11 @@ public class SurfaceMountingManager {
|
||||
// This is null *until* StopSurface is called.
|
||||
private SparseArrayCompat<Object> mTagSetForStoppedSurface;
|
||||
|
||||
// This is to make sure direct manipulation result will not be overridden by React update.
|
||||
@ThreadConfined(UI)
|
||||
private final SparseArrayCompat<Map<String, Object>> mTagToSynchronousMountProps =
|
||||
new SparseArrayCompat<>();
|
||||
|
||||
private final int mSurfaceId;
|
||||
|
||||
public SurfaceMountingManager(
|
||||
@@ -682,13 +694,110 @@ public class SurfaceMountingManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static void overridePropsReadableMap(
|
||||
Map<String, Object> patchMap, WritableMap outputReadableMap) {
|
||||
for (Map.Entry<String, Object> entry : patchMap.entrySet()) {
|
||||
String propKey = entry.getKey();
|
||||
if (outputReadableMap.hasKey(propKey)) {
|
||||
Object propValue = entry.getValue();
|
||||
if (propKey.equals("transform")) {
|
||||
assert (outputReadableMap.getType(propKey) == ReadableType.Array
|
||||
&& propValue instanceof ArrayList);
|
||||
WritableArray array = new WritableNativeArray();
|
||||
for (Object item : (ArrayList<?>) propValue) {
|
||||
if (item instanceof HashMap) {
|
||||
WritableNativeMap itemMap = new WritableNativeMap();
|
||||
for (Map.Entry<String, Object> itemEntry :
|
||||
((HashMap<String, Object>) item).entrySet()) {
|
||||
if (itemEntry.getValue() instanceof String) {
|
||||
itemMap.putString(itemEntry.getKey(), (String) itemEntry.getValue());
|
||||
} else if (itemEntry.getValue() instanceof Number) {
|
||||
itemMap.putDouble(
|
||||
itemEntry.getKey(), ((Number) itemEntry.getValue()).doubleValue());
|
||||
}
|
||||
}
|
||||
array.pushMap(itemMap);
|
||||
}
|
||||
}
|
||||
outputReadableMap.putArray(propKey, array);
|
||||
} else if (propKey.equals("opacity")) {
|
||||
assert (outputReadableMap.getType(propKey) == ReadableType.Number
|
||||
&& propValue instanceof Number);
|
||||
outputReadableMap.putDouble(propKey, ((Number) propValue).doubleValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, Object> getHashMapFromPropsReadableMap(ReadableMap readableMap) {
|
||||
HashMap<String, Object> outputMap = new HashMap<>();
|
||||
|
||||
Iterator<Map.Entry<String, Object>> iter = readableMap.getEntryIterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<String, Object> entry = iter.next();
|
||||
String propKey = entry.getKey();
|
||||
Object propValue = entry.getValue();
|
||||
if (propKey.equals("transform") && propValue instanceof ReadableArray) {
|
||||
ArrayList<HashMap<String, Object>> arrayList = new ArrayList<>();
|
||||
for (int i = 0; i < ((ReadableArray) propValue).size(); i++) {
|
||||
ReadableMap map = ((ReadableArray) propValue).getMap(i);
|
||||
if (map != null) {
|
||||
arrayList.add(map.toHashMap());
|
||||
}
|
||||
}
|
||||
outputMap.put(propKey, arrayList);
|
||||
} else if (propKey.equals("opacity") && propValue instanceof Number) {
|
||||
outputMap.put(propKey, ((Number) propValue).doubleValue());
|
||||
}
|
||||
}
|
||||
|
||||
return outputMap;
|
||||
}
|
||||
|
||||
public void storeSynchronousMountPropsOverride(int reactTag, ReadableMap props) {
|
||||
if (ReactNativeFeatureFlags.overrideBySynchronousMountPropsAtMountingAndroid()) {
|
||||
Map<String, Object> propsMap = getHashMapFromPropsReadableMap(props);
|
||||
if (mTagToSynchronousMountProps.containsKey(reactTag)) {
|
||||
Map<String, Object> mergedPropsMap =
|
||||
Assertions.assertNotNull(mTagToSynchronousMountProps.get(reactTag));
|
||||
mergedPropsMap.putAll(propsMap);
|
||||
mTagToSynchronousMountProps.put(reactTag, mergedPropsMap);
|
||||
} else {
|
||||
mTagToSynchronousMountProps.put(reactTag, propsMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePropsSynchronously(int reactTag, ReadableMap props) {
|
||||
updateProps(reactTag, props, true);
|
||||
}
|
||||
|
||||
public void updateProps(int reactTag, ReadableMap props) {
|
||||
updateProps(reactTag, props, false);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void updateProps(
|
||||
int reactTag, ReadableMap props, Boolean shouldSkipSynchronousMountPropsOverride) {
|
||||
if (isStopped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ViewState viewState = getViewState(reactTag);
|
||||
viewState.mCurrentProps = new ReactStylesDiffMap(props);
|
||||
|
||||
if (ReactNativeFeatureFlags.overrideBySynchronousMountPropsAtMountingAndroid()
|
||||
&& !shouldSkipSynchronousMountPropsOverride
|
||||
&& mTagToSynchronousMountProps.containsKey(reactTag)) {
|
||||
WritableMap modifiedProps = new WritableNativeMap();
|
||||
modifiedProps.merge(props);
|
||||
Map<String, Object> directPropsMap =
|
||||
Assertions.assertNotNull(mTagToSynchronousMountProps.get(reactTag));
|
||||
overridePropsReadableMap(directPropsMap, modifiedProps);
|
||||
viewState.mCurrentProps = new ReactStylesDiffMap(modifiedProps);
|
||||
} else {
|
||||
viewState.mCurrentProps = new ReactStylesDiffMap(props);
|
||||
}
|
||||
|
||||
View view = viewState.mView;
|
||||
|
||||
if (view == null) {
|
||||
@@ -1057,6 +1166,11 @@ public class SurfaceMountingManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ReactNativeFeatureFlags.overrideBySynchronousMountPropsAtMountingAndroid()
|
||||
&& mTagToSynchronousMountProps.containsKey(reactTag)) {
|
||||
mTagToSynchronousMountProps.remove(reactTag);
|
||||
}
|
||||
|
||||
ViewState viewState = getNullableViewState(reactTag);
|
||||
|
||||
if (viewState == null) {
|
||||
|
||||
+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<<92a6edded037a504fc1c2c8ae88deae1>>
|
||||
* @generated SignedSource<<8300eb10fb4906468cd5f04afd8e16cd>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -300,6 +300,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun enableVirtualViewWindowFocusDetection(): Boolean = accessor.enableVirtualViewWindowFocusDetection()
|
||||
|
||||
/**
|
||||
* Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun enableWebPerformanceAPIsByDefault(): Boolean = accessor.enableWebPerformanceAPIsByDefault()
|
||||
|
||||
/**
|
||||
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
|
||||
*/
|
||||
@@ -324,6 +330,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun hideOffscreenVirtualViewsOnIOS(): Boolean = accessor.hideOffscreenVirtualViewsOnIOS()
|
||||
|
||||
/**
|
||||
* Override props at mounting with synchronously mounted (i.e. direct manipulation) props from Native Animated.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = accessor.overrideBySynchronousMountPropsAtMountingAndroid()
|
||||
|
||||
/**
|
||||
* Enable the V2 in-app Performance Monitor. This flag is global and should not be changed across React Host lifetimes.
|
||||
*/
|
||||
|
||||
+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<<ebbc6602fc8e3fb4c510bbd47361a7f0>>
|
||||
* @generated SignedSource<<ea5133af611c4d1e7e70155a3a74492d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -65,10 +65,12 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
|
||||
private var enableVirtualViewRenderStateCache: Boolean? = null
|
||||
private var enableVirtualViewWindowFocusDetectionCache: Boolean? = null
|
||||
private var enableWebPerformanceAPIsByDefaultCache: Boolean? = null
|
||||
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
|
||||
private var fuseboxEnabledReleaseCache: Boolean? = null
|
||||
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
|
||||
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
|
||||
private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
|
||||
private var perfMonitorV2EnabledCache: Boolean? = null
|
||||
private var preparedTextCacheSizeCache: Double? = null
|
||||
private var preventShadowTreeCommitExhaustionCache: Boolean? = null
|
||||
@@ -495,6 +497,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableWebPerformanceAPIsByDefault(): Boolean {
|
||||
var cached = enableWebPerformanceAPIsByDefaultCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.enableWebPerformanceAPIsByDefault()
|
||||
enableWebPerformanceAPIsByDefaultCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
|
||||
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
|
||||
if (cached == null) {
|
||||
@@ -531,6 +542,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean {
|
||||
var cached = overrideBySynchronousMountPropsAtMountingAndroidCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.overrideBySynchronousMountPropsAtMountingAndroid()
|
||||
overrideBySynchronousMountPropsAtMountingAndroidCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun perfMonitorV2Enabled(): Boolean {
|
||||
var cached = perfMonitorV2EnabledCache
|
||||
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<<4410628511f112f3eef22434a05fa757>>
|
||||
* @generated SignedSource<<cf5b9f099846d4f954304905f77ebe17>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -118,6 +118,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableVirtualViewWindowFocusDetection(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableWebPerformanceAPIsByDefault(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun fuseboxEnabledRelease(): Boolean
|
||||
@@ -126,6 +128,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun hideOffscreenVirtualViewsOnIOS(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun perfMonitorV2Enabled(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun preparedTextCacheSize(): Double
|
||||
|
||||
+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<<411732d441bacbef37c3474b9041202c>>
|
||||
* @generated SignedSource<<305496047314dc97352a6e0dad0bba54>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -113,6 +113,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun enableVirtualViewWindowFocusDetection(): Boolean = false
|
||||
|
||||
override fun enableWebPerformanceAPIsByDefault(): Boolean = false
|
||||
|
||||
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false
|
||||
|
||||
override fun fuseboxEnabledRelease(): Boolean = false
|
||||
@@ -121,6 +123,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun hideOffscreenVirtualViewsOnIOS(): Boolean = false
|
||||
|
||||
override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = false
|
||||
|
||||
override fun perfMonitorV2Enabled(): Boolean = false
|
||||
|
||||
override fun preparedTextCacheSize(): Double = 200.0
|
||||
|
||||
+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<<2f65e0e9066a8c2c35c44ea7c73dbedc>>
|
||||
* @generated SignedSource<<f3798eada96337cf98715fa580823b30>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -69,10 +69,12 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
|
||||
private var enableVirtualViewRenderStateCache: Boolean? = null
|
||||
private var enableVirtualViewWindowFocusDetectionCache: Boolean? = null
|
||||
private var enableWebPerformanceAPIsByDefaultCache: Boolean? = null
|
||||
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
|
||||
private var fuseboxEnabledReleaseCache: Boolean? = null
|
||||
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
|
||||
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
|
||||
private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
|
||||
private var perfMonitorV2EnabledCache: Boolean? = null
|
||||
private var preparedTextCacheSizeCache: Double? = null
|
||||
private var preventShadowTreeCommitExhaustionCache: Boolean? = null
|
||||
@@ -544,6 +546,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableWebPerformanceAPIsByDefault(): Boolean {
|
||||
var cached = enableWebPerformanceAPIsByDefaultCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.enableWebPerformanceAPIsByDefault()
|
||||
accessedFeatureFlags.add("enableWebPerformanceAPIsByDefault")
|
||||
enableWebPerformanceAPIsByDefaultCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean {
|
||||
var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache
|
||||
if (cached == null) {
|
||||
@@ -584,6 +596,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean {
|
||||
var cached = overrideBySynchronousMountPropsAtMountingAndroidCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.overrideBySynchronousMountPropsAtMountingAndroid()
|
||||
accessedFeatureFlags.add("overrideBySynchronousMountPropsAtMountingAndroid")
|
||||
overrideBySynchronousMountPropsAtMountingAndroidCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun perfMonitorV2Enabled(): Boolean {
|
||||
var cached = perfMonitorV2EnabledCache
|
||||
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<<e97601660cfd4f614ac934ba20ca4635>>
|
||||
* @generated SignedSource<<c36e7ac588eb68660f000e7792ec2384>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -113,6 +113,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableVirtualViewWindowFocusDetection(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableWebPerformanceAPIsByDefault(): Boolean
|
||||
|
||||
@DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
|
||||
|
||||
@DoNotStrip public fun fuseboxEnabledRelease(): Boolean
|
||||
@@ -121,6 +123,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun hideOffscreenVirtualViewsOnIOS(): Boolean
|
||||
|
||||
@DoNotStrip public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
|
||||
|
||||
@DoNotStrip public fun perfMonitorV2Enabled(): Boolean
|
||||
|
||||
@DoNotStrip public fun preparedTextCacheSize(): Double
|
||||
|
||||
+2
-2
@@ -310,8 +310,8 @@ public open class JavaTimerManager(
|
||||
}
|
||||
}
|
||||
}
|
||||
timersToCall?.let {
|
||||
javaScriptTimerExecutor.callTimers(it)
|
||||
timersToCall?.let { timers ->
|
||||
javaScriptTimerExecutor.callTimers(timers)
|
||||
timersToCall = null
|
||||
}
|
||||
reactChoreographer.postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, this)
|
||||
|
||||
+1
-1
@@ -81,6 +81,6 @@ internal class ReactHostImplDevHelper(private val delegate: ReactHostImpl) :
|
||||
delegate.loadBundle(bundleLoader)
|
||||
|
||||
override fun getTracingState(): TracingState {
|
||||
return delegate.reactHostInspectorTarget?.tracingState() ?: TracingState.DISABLED
|
||||
return delegate.reactHostInspectorTarget?.getTracingState() ?: TracingState.ENABLEDINCDPMODE
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
|
||||
|
||||
external fun tracingStateAsInt(): Int
|
||||
|
||||
fun tracingState(): TracingState {
|
||||
override fun getTracingState(): TracingState {
|
||||
return TracingState.entries[tracingStateAsInt()]
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,8 @@ add_react_common_subdir(react/nativemodule/dom)
|
||||
add_react_common_subdir(react/nativemodule/featureflags)
|
||||
add_react_common_subdir(react/nativemodule/microtasks)
|
||||
add_react_common_subdir(react/nativemodule/idlecallbacks)
|
||||
add_react_common_subdir(react/nativemodule/webperformance)
|
||||
add_react_common_subdir(react/networking)
|
||||
add_react_common_subdir(jserrorhandler)
|
||||
add_react_common_subdir(react/runtime)
|
||||
add_react_common_subdir(react/runtime/hermes)
|
||||
@@ -190,6 +192,8 @@ add_library(reactnative
|
||||
$<TARGET_OBJECTS:react_nativemodule_featureflags>
|
||||
$<TARGET_OBJECTS:react_nativemodule_idlecallbacks>
|
||||
$<TARGET_OBJECTS:react_nativemodule_microtasks>
|
||||
$<TARGET_OBJECTS:react_nativemodule_webperformance>
|
||||
$<TARGET_OBJECTS:react_networking>
|
||||
$<TARGET_OBJECTS:react_newarchdefaults>
|
||||
$<TARGET_OBJECTS:react_performance_cdpmetrics>
|
||||
$<TARGET_OBJECTS:react_performance_timeline>
|
||||
@@ -279,6 +283,8 @@ target_include_directories(reactnative
|
||||
$<TARGET_PROPERTY:react_nativemodule_featureflags,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_nativemodule_idlecallbacks,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_nativemodule_microtasks,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_nativemodule_webperformance,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_networking,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_newarchdefaults,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_performance_cdpmetrics,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_performance_timeline,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
|
||||
@@ -20,6 +20,6 @@ target_include_directories(react_devsupportjni PUBLIC .)
|
||||
target_link_libraries(react_devsupportjni
|
||||
fbjni
|
||||
jsinspector
|
||||
jsinspector_network)
|
||||
react_networking)
|
||||
|
||||
target_compile_reactnative_options(react_devsupportjni PRIVATE)
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "JInspectorNetworkReporter.h"
|
||||
|
||||
#include <jsinspector-modern/network/NetworkReporter.h>
|
||||
#include <react/networking/NetworkReporter.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
+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<<f9c4f8d97edff1b016873b0a6121b76b>>
|
||||
* @generated SignedSource<<be39ff0cb3b7c5881510b1528c17465a>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -309,6 +309,12 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableWebPerformanceAPIsByDefault() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableWebPerformanceAPIsByDefault");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
@@ -333,6 +339,12 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool overrideBySynchronousMountPropsAtMountingAndroid() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("overrideBySynchronousMountPropsAtMountingAndroid");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool perfMonitorV2Enabled() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("perfMonitorV2Enabled");
|
||||
@@ -682,6 +694,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableVirtualViewWindowFocusDetection(
|
||||
return ReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableWebPerformanceAPIsByDefault(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
@@ -702,6 +719,11 @@ bool JReactNativeFeatureFlagsCxxInterop::hideOffscreenVirtualViewsOnIOS(
|
||||
return ReactNativeFeatureFlags::hideOffscreenVirtualViewsOnIOS();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::overrideBySynchronousMountPropsAtMountingAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAndroid();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::perfMonitorV2Enabled(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::perfMonitorV2Enabled();
|
||||
@@ -968,6 +990,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableVirtualViewWindowFocusDetection",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableVirtualViewWindowFocusDetection),
|
||||
makeNativeMethod(
|
||||
"enableWebPerformanceAPIsByDefault",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableWebPerformanceAPIsByDefault),
|
||||
makeNativeMethod(
|
||||
"fixMappingOfEventPrioritiesBetweenFabricAndReact",
|
||||
JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact),
|
||||
@@ -980,6 +1005,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"hideOffscreenVirtualViewsOnIOS",
|
||||
JReactNativeFeatureFlagsCxxInterop::hideOffscreenVirtualViewsOnIOS),
|
||||
makeNativeMethod(
|
||||
"overrideBySynchronousMountPropsAtMountingAndroid",
|
||||
JReactNativeFeatureFlagsCxxInterop::overrideBySynchronousMountPropsAtMountingAndroid),
|
||||
makeNativeMethod(
|
||||
"perfMonitorV2Enabled",
|
||||
JReactNativeFeatureFlagsCxxInterop::perfMonitorV2Enabled),
|
||||
|
||||
+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<<6a98f8398948f8d56e51d3eff19c5d05>>
|
||||
* @generated SignedSource<<8cd0afd7badb6739b4e8f9b0e630677c>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -165,6 +165,9 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool enableVirtualViewWindowFocusDetection(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableWebPerformanceAPIsByDefault(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool fixMappingOfEventPrioritiesBetweenFabricAndReact(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
@@ -177,6 +180,9 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool hideOffscreenVirtualViewsOnIOS(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool overrideBySynchronousMountPropsAtMountingAndroid(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool perfMonitorV2Enabled(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ target_compile_reactnative_options(hermes_executor PRIVATE)
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
target_compile_options(hermes_executor PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
if (HERMES_V1_ENABLED)
|
||||
target_compile_options(hermes_executor PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ target_compile_reactnative_options(hermesinstancejni PRIVATE)
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
target_compile_options(hermesinstancejni PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
if (HERMES_V1_ENABLED)
|
||||
target_compile_options(hermesinstancejni PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
@@ -20,7 +20,7 @@ target_compile_reactnative_options(rninstance PRIVATE)
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
target_compile_options(rninstance PRIVATE -DHERMES_ENABLE_DEBUGGER=1)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
if (HERMES_V1_ENABLED)
|
||||
target_compile_options(rninstance PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
@@ -33,7 +33,7 @@ if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
-DHERMES_ENABLE_DEBUGGER=1
|
||||
)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
if (HERMES_V1_ENABLED)
|
||||
target_compile_options(hermes_executor_common PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
else()
|
||||
|
||||
@@ -24,7 +24,7 @@ if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
|
||||
-DHERMES_ENABLE_DEBUGGER=1
|
||||
)
|
||||
|
||||
if (DEFINED HERMES_V1_ENABLED)
|
||||
if (HERMES_V1_ENABLED)
|
||||
target_compile_options(hermes_inspector_modern PRIVATE -DHERMES_V1_ENABLED=1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -15,16 +15,16 @@ namespace facebook::react::jsinspector_modern {
|
||||
namespace {
|
||||
// Vendored from Folly
|
||||
// https://github.com/facebook/folly/blob/v2024.07.08.00/folly/detail/base64_detail/Base64Scalar.h
|
||||
constexpr char kBase64Charset[] =
|
||||
constexpr std::string_view kBase64Charset =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
constexpr char kBase64URLCharset[] =
|
||||
constexpr std::string_view kBase64URLCharset =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
||||
template <bool isURL>
|
||||
struct Base64ScalarImpl {
|
||||
static constexpr const char* kCharset =
|
||||
isURL ? kBase64URLCharset : kBase64Charset;
|
||||
isURL ? kBase64URLCharset.data() : kBase64Charset.data();
|
||||
|
||||
// 0, 1 or 2 bytes
|
||||
static constexpr char* encodeTail(const char* f, const char* l, char* o) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "Base64.h"
|
||||
#include "Utf8.h"
|
||||
|
||||
#include <jsinspector-modern/network/NetworkReporter.h>
|
||||
#include <jsinspector-modern/network/NetworkHandler.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
@@ -272,19 +272,19 @@ bool NetworkIOAgent::handleRequest(
|
||||
}
|
||||
|
||||
if (InspectorFlags::getInstance().getNetworkInspectionEnabled()) {
|
||||
auto& networkReporter = NetworkReporter::getInstance();
|
||||
auto& networkHandler = NetworkHandler::getInstance();
|
||||
|
||||
// @cdp Network.enable support is experimental.
|
||||
if (req.method == "Network.enable") {
|
||||
networkReporter.setFrontendChannel(frontendChannel_);
|
||||
networkReporter.enableDebugging();
|
||||
networkHandler.setFrontendChannel(frontendChannel_);
|
||||
networkHandler.enable();
|
||||
frontendChannel_(cdp::jsonResult(req.id));
|
||||
return true;
|
||||
}
|
||||
|
||||
// @cdp Network.disable support is experimental.
|
||||
if (req.method == "Network.disable") {
|
||||
networkReporter.disableDebugging();
|
||||
networkHandler.disable();
|
||||
frontendChannel_(cdp::jsonResult(req.id));
|
||||
return true;
|
||||
}
|
||||
@@ -497,9 +497,9 @@ void NetworkIOAgent::handleGetResponseBody(const cdp::PreparsedRequest& req) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& networkReporter = NetworkReporter::getInstance();
|
||||
auto& networkHandler = NetworkHandler::getInstance();
|
||||
|
||||
if (!networkReporter.isDebuggingEnabled()) {
|
||||
if (!networkHandler.isEnabled()) {
|
||||
frontendChannel_(cdp::jsonError(
|
||||
requestId,
|
||||
cdp::ErrorCode::InvalidRequest,
|
||||
@@ -508,7 +508,7 @@ void NetworkIOAgent::handleGetResponseBody(const cdp::PreparsedRequest& req) {
|
||||
}
|
||||
|
||||
auto storedResponse =
|
||||
networkReporter.getResponseBody(req.params.at("requestId").asString());
|
||||
networkHandler.getResponseBody(req.params.at("requestId").asString());
|
||||
|
||||
if (!storedResponse) {
|
||||
frontendChannel_(cdp::jsonError(
|
||||
|
||||
@@ -50,7 +50,8 @@ void PerfMonitorUpdateHandler::handlePerfMetricsUpdate(
|
||||
}
|
||||
|
||||
auto responsivenessScore = getInteractionScore(duration);
|
||||
auto ttl = responsivenessScore == InteractionResponsivenessScore::Poor
|
||||
auto ttl =
|
||||
responsivenessScore == InteractionResponsivenessScore::NeedsImprovement
|
||||
? BAD_EVENT_TTL
|
||||
: DEFAULT_TTL;
|
||||
|
||||
|
||||
@@ -24,6 +24,4 @@ target_include_directories(jsinspector_network PUBLIC ${REACT_COMMON_DIR})
|
||||
target_link_libraries(jsinspector_network
|
||||
folly_runtime
|
||||
glog
|
||||
jsinspector_cdp
|
||||
react_performance_timeline
|
||||
react_timing)
|
||||
jsinspector_cdp)
|
||||
|
||||
@@ -27,15 +27,6 @@ folly::dynamic headersToDynamic(const std::optional<Headers>& headers) {
|
||||
|
||||
} // namespace
|
||||
|
||||
/* static */ Request Request::fromInputParams(const RequestInfo& requestInfo) {
|
||||
return {
|
||||
.url = requestInfo.url,
|
||||
.method = requestInfo.httpMethod,
|
||||
.headers = requestInfo.headers,
|
||||
.postData = requestInfo.httpBody,
|
||||
};
|
||||
}
|
||||
|
||||
folly::dynamic Request::toDynamic() const {
|
||||
folly::dynamic result = folly::dynamic::object;
|
||||
|
||||
@@ -48,16 +39,16 @@ folly::dynamic Request::toDynamic() const {
|
||||
}
|
||||
|
||||
/* static */ Response Response::fromInputParams(
|
||||
const ResponseInfo& responseInfo,
|
||||
const std::string& url,
|
||||
uint16_t status,
|
||||
const std::optional<Headers>& headers,
|
||||
int encodedDataLength) {
|
||||
auto headers = responseInfo.headers.value_or(Headers());
|
||||
|
||||
return {
|
||||
.url = responseInfo.url,
|
||||
.status = responseInfo.statusCode,
|
||||
.statusText = httpReasonPhrase(responseInfo.statusCode),
|
||||
.url = url,
|
||||
.status = status,
|
||||
.statusText = httpReasonPhrase(status),
|
||||
.headers = headers,
|
||||
.mimeType = mimeTypeFromHeaders(headers),
|
||||
.mimeType = mimeTypeFromHeaders(headers.value_or(Headers())),
|
||||
.encodedDataLength = encodedDataLength,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NetworkTypes.h"
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#include <string>
|
||||
@@ -18,6 +16,8 @@
|
||||
|
||||
namespace facebook::react::jsinspector_modern::cdp::network {
|
||||
|
||||
using Headers = std::map<std::string, std::string>;
|
||||
|
||||
/**
|
||||
* https://chromedevtools.github.io/devtools-protocol/tot/Network/#type-Request
|
||||
*/
|
||||
@@ -27,12 +27,6 @@ struct Request {
|
||||
std::optional<Headers> headers;
|
||||
std::optional<std::string> postData;
|
||||
|
||||
/**
|
||||
* Convenience function to construct a `Request` from the generic
|
||||
* `RequestInfo` input object.
|
||||
*/
|
||||
static Request fromInputParams(const RequestInfo& requestInfo);
|
||||
|
||||
folly::dynamic toDynamic() const;
|
||||
};
|
||||
|
||||
@@ -52,7 +46,9 @@ struct Response {
|
||||
* `ResponseInfo` input object.
|
||||
*/
|
||||
static Response fromInputParams(
|
||||
const ResponseInfo& responseInfo,
|
||||
const std::string& url,
|
||||
uint16_t status,
|
||||
const std::optional<Headers>& headers,
|
||||
int encodedDataLength);
|
||||
|
||||
folly::dynamic toDynamic() const;
|
||||
|
||||
@@ -146,7 +146,8 @@ std::string httpReasonPhrase(uint16_t status) {
|
||||
return "<Unknown>";
|
||||
}
|
||||
|
||||
std::string mimeTypeFromHeaders(const Headers& headers) {
|
||||
std::string mimeTypeFromHeaders(
|
||||
const std::map<std::string, std::string>& headers) {
|
||||
std::string mimeType = "application/octet-stream";
|
||||
|
||||
for (const auto& [name, value] : headers) {
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NetworkTypes.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
@@ -22,6 +21,7 @@ std::string httpReasonPhrase(uint16_t status);
|
||||
* Get the MIME type for a response based on the 'Content-Type' header. If
|
||||
* the header is not present, returns 'application/octet-stream'.
|
||||
*/
|
||||
std::string mimeTypeFromHeaders(const Headers& headers);
|
||||
std::string mimeTypeFromHeaders(
|
||||
const std::map<std::string, std::string>& headers);
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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 "NetworkHandler.h"
|
||||
|
||||
#include <jsinspector-modern/cdp/CdpJson.h>
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <chrono>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Get the current Unix timestamp in seconds (µs precision, CDP format).
|
||||
*/
|
||||
double getCurrentUnixTimestampSeconds() {
|
||||
auto now = std::chrono::system_clock::now().time_since_epoch();
|
||||
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(now).count();
|
||||
auto micros =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(now).count() %
|
||||
1000000;
|
||||
|
||||
return static_cast<double>(seconds) +
|
||||
(static_cast<double>(micros) / 1000000.0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NetworkHandler& NetworkHandler::getInstance() {
|
||||
static NetworkHandler instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void NetworkHandler::setFrontendChannel(FrontendChannel frontendChannel) {
|
||||
frontendChannel_ = std::move(frontendChannel);
|
||||
}
|
||||
|
||||
bool NetworkHandler::enable() {
|
||||
if (enabled_.load(std::memory_order_acquire)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
enabled_.store(true, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetworkHandler::disable() {
|
||||
if (!enabled_.load(std::memory_order_acquire)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
enabled_.store(false, std::memory_order_release);
|
||||
requestBodyBuffer_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetworkHandler::onRequestWillBeSent(
|
||||
const std::string& requestId,
|
||||
const cdp::network::Request& request,
|
||||
const std::optional<cdp::network::Response>& redirectResponse) {
|
||||
if (!isEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
double timestamp = getCurrentUnixTimestampSeconds();
|
||||
auto params = cdp::network::RequestWillBeSentParams{
|
||||
.requestId = requestId,
|
||||
.loaderId = "",
|
||||
.documentURL = "mobile",
|
||||
.request = request,
|
||||
// NOTE: Both timestamp and wallTime use the same unit, however wallTime
|
||||
// is relative to an "arbitrary epoch". In our implementation, use the
|
||||
// Unix epoch for both.
|
||||
.timestamp = timestamp,
|
||||
.wallTime = timestamp,
|
||||
.initiator = folly::dynamic::object("type", "script"),
|
||||
.redirectHasExtraInfo = redirectResponse.has_value(),
|
||||
.redirectResponse = redirectResponse,
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.requestWillBeSent", params.toDynamic()));
|
||||
}
|
||||
|
||||
void NetworkHandler::onRequestWillBeSentExtraInfo(
|
||||
const std::string& requestId,
|
||||
const Headers& headers) {
|
||||
if (!isEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto params = cdp::network::RequestWillBeSentExtraInfoParams{
|
||||
.requestId = requestId,
|
||||
.headers = headers,
|
||||
.connectTiming = {.requestTime = getCurrentUnixTimestampSeconds()},
|
||||
};
|
||||
|
||||
frontendChannel_(cdp::jsonNotification(
|
||||
"Network.requestWillBeSentExtraInfo", params.toDynamic()));
|
||||
}
|
||||
|
||||
void NetworkHandler::onResponseReceived(
|
||||
const std::string& requestId,
|
||||
const cdp::network::Response& response) {
|
||||
if (!isEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto resourceType = cdp::network::resourceTypeFromMimeType(response.mimeType);
|
||||
resourceTypeMap_.emplace(requestId, resourceType);
|
||||
|
||||
auto params = cdp::network::ResponseReceivedParams{
|
||||
.requestId = requestId,
|
||||
.loaderId = "",
|
||||
.timestamp = getCurrentUnixTimestampSeconds(),
|
||||
.type = resourceType,
|
||||
.response = response,
|
||||
.hasExtraInfo = false,
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.responseReceived", params.toDynamic()));
|
||||
}
|
||||
|
||||
void NetworkHandler::onDataReceived(
|
||||
const std::string& requestId,
|
||||
int dataLength,
|
||||
int encodedDataLength) {
|
||||
if (!isEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto params = cdp::network::DataReceivedParams{
|
||||
.requestId = requestId,
|
||||
.timestamp = getCurrentUnixTimestampSeconds(),
|
||||
.dataLength = dataLength,
|
||||
.encodedDataLength = encodedDataLength,
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.dataReceived", params.toDynamic()));
|
||||
}
|
||||
|
||||
void NetworkHandler::onLoadingFinished(
|
||||
const std::string& requestId,
|
||||
int encodedDataLength) {
|
||||
if (!isEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto params = cdp::network::LoadingFinishedParams{
|
||||
.requestId = requestId,
|
||||
.timestamp = getCurrentUnixTimestampSeconds(),
|
||||
.encodedDataLength = encodedDataLength,
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.loadingFinished", params.toDynamic()));
|
||||
}
|
||||
|
||||
void NetworkHandler::onLoadingFailed(
|
||||
const std::string& requestId,
|
||||
bool cancelled) const {
|
||||
if (!isEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto params = cdp::network::LoadingFailedParams{
|
||||
.requestId = requestId,
|
||||
.timestamp = getCurrentUnixTimestampSeconds(),
|
||||
.type = resourceTypeMap_.find(requestId) != resourceTypeMap_.end()
|
||||
? resourceTypeMap_.at(requestId)
|
||||
: "Other",
|
||||
.errorText = cancelled ? "net::ERR_ABORTED" : "net::ERR_FAILED",
|
||||
.canceled = cancelled,
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.loadingFailed", params.toDynamic()));
|
||||
}
|
||||
|
||||
void NetworkHandler::storeResponseBody(
|
||||
const std::string& requestId,
|
||||
std::string_view body,
|
||||
bool base64Encoded) {
|
||||
std::lock_guard<std::mutex> lock(requestBodyMutex_);
|
||||
requestBodyBuffer_.put(requestId, body, base64Encoded);
|
||||
}
|
||||
|
||||
std::optional<std::tuple<std::string, bool>> NetworkHandler::getResponseBody(
|
||||
const std::string& requestId) {
|
||||
std::lock_guard<std::mutex> lock(requestBodyMutex_);
|
||||
auto responseBody = requestBodyBuffer_.get(requestId);
|
||||
|
||||
if (responseBody == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::make_optional<std::tuple<std::string, bool>>(
|
||||
responseBody->data, responseBody->base64Encoded);
|
||||
}
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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 "BoundedRequestBuffer.h"
|
||||
#include "CdpNetwork.h"
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
/**
|
||||
* A callback that can be used to send debugger messages (method responses and
|
||||
* events) to the frontend. The message must be a JSON-encoded string.
|
||||
* The callback may be called from any thread.
|
||||
*/
|
||||
using FrontendChannel = std::function<void(std::string_view messageJson)>;
|
||||
|
||||
using Headers = std::map<std::string, std::string>;
|
||||
|
||||
/**
|
||||
* [Experimental] Handler for reporting network events via CDP.
|
||||
*/
|
||||
class NetworkHandler {
|
||||
public:
|
||||
static NetworkHandler& getInstance();
|
||||
|
||||
/**
|
||||
* Set the channel used to send CDP events to the frontend. This should be
|
||||
* supplied before calling `enable`.
|
||||
*/
|
||||
void setFrontendChannel(FrontendChannel frontendChannel);
|
||||
|
||||
/**
|
||||
* Enable network debugging. Returns `false` if already enabled.
|
||||
*
|
||||
* @cdp Network.enable
|
||||
*/
|
||||
bool enable();
|
||||
|
||||
/**
|
||||
* Disable network debugging. Returns `false` if not initially enabled.
|
||||
*
|
||||
* @cdp Network.disable
|
||||
*/
|
||||
bool disable();
|
||||
|
||||
/**
|
||||
* Returns whether network debugging is currently enabled.
|
||||
*/
|
||||
inline bool isEnabled() const {
|
||||
return enabled_.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
/**
|
||||
* @cdp Network.requestWillBeSent
|
||||
*/
|
||||
void onRequestWillBeSent(
|
||||
const std::string& requestId,
|
||||
const cdp::network::Request& request,
|
||||
const std::optional<cdp::network::Response>& redirectResponse);
|
||||
|
||||
/**
|
||||
* @cdp Network.requestWillBeSentExtraInfo
|
||||
*/
|
||||
void onRequestWillBeSentExtraInfo(
|
||||
const std::string& requestId,
|
||||
const Headers& headers);
|
||||
|
||||
/**
|
||||
* @cdp Network.responseReceived
|
||||
*/
|
||||
void onResponseReceived(
|
||||
const std::string& requestId,
|
||||
const cdp::network::Response& response);
|
||||
|
||||
/**
|
||||
* @cdp Network.dataReceived
|
||||
*/
|
||||
void onDataReceived(
|
||||
const std::string& requestId,
|
||||
int dataLength,
|
||||
int encodedDataLength);
|
||||
|
||||
/**
|
||||
* @cdp Network.loadingFinished
|
||||
*/
|
||||
void onLoadingFinished(const std::string& requestId, int encodedDataLength);
|
||||
|
||||
/**
|
||||
* @cdp Network.loadingFailed
|
||||
*/
|
||||
void onLoadingFailed(const std::string& requestId, bool cancelled) const;
|
||||
|
||||
/**
|
||||
* Store the fetched response body for a text or image network response.
|
||||
*
|
||||
* Reponse bodies are stored in a bounded buffer with a fixed maximum memory
|
||||
* size, where oldest responses will be evicted if the buffer is exceeded.
|
||||
*
|
||||
* Should be called after checking \ref NetworkHandler::isEnabled.
|
||||
*/
|
||||
void storeResponseBody(
|
||||
const std::string& requestId,
|
||||
std::string_view body,
|
||||
bool base64Encoded);
|
||||
|
||||
/**
|
||||
* Retrieve a stored response body for a given request ID.
|
||||
*
|
||||
* \returns An optional tuple of [responseBody, base64Encoded]. Returns
|
||||
* nullopt if no entry is found in the buffer.
|
||||
*/
|
||||
std::optional<std::tuple<std::string, bool>> getResponseBody(
|
||||
const std::string& requestId);
|
||||
|
||||
private:
|
||||
NetworkHandler() = default;
|
||||
NetworkHandler(const NetworkHandler&) = delete;
|
||||
NetworkHandler& operator=(const NetworkHandler&) = delete;
|
||||
~NetworkHandler() = default;
|
||||
|
||||
std::atomic<bool> enabled_{false};
|
||||
|
||||
inline bool isEnabledNoSync() const {
|
||||
return enabled_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
FrontendChannel frontendChannel_;
|
||||
|
||||
std::map<std::string, std::string> resourceTypeMap_{};
|
||||
|
||||
BoundedRequestBuffer requestBodyBuffer_{};
|
||||
std::mutex requestBodyMutex_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
@@ -1,316 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "NetworkReporter.h"
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
#include "CdpNetwork.h"
|
||||
#endif
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
#include <jsinspector-modern/cdp/CdpJson.h>
|
||||
#endif
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/performance/timeline/PerformanceEntryReporter.h>
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
#include <chrono>
|
||||
#endif
|
||||
#include <glog/logging.h>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Get the current Unix timestamp in seconds (µs precision, CDP format).
|
||||
*/
|
||||
double getCurrentUnixTimestampSeconds() {
|
||||
auto now = std::chrono::system_clock::now().time_since_epoch();
|
||||
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(now).count();
|
||||
auto micros =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(now).count() %
|
||||
1000000;
|
||||
|
||||
return static_cast<double>(seconds) +
|
||||
(static_cast<double>(micros) / 1000000.0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
NetworkReporter& NetworkReporter::getInstance() {
|
||||
static NetworkReporter instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void NetworkReporter::setFrontendChannel(FrontendChannel frontendChannel) {
|
||||
frontendChannel_ = std::move(frontendChannel);
|
||||
}
|
||||
|
||||
bool NetworkReporter::enableDebugging() {
|
||||
if (debuggingEnabled_.load(std::memory_order_acquire)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
debuggingEnabled_.store(true, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetworkReporter::disableDebugging() {
|
||||
if (!debuggingEnabled_.load(std::memory_order_acquire)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
debuggingEnabled_.store(false, std::memory_order_release);
|
||||
requestBodyBuffer_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetworkReporter::reportRequestStart(
|
||||
const std::string& requestId,
|
||||
const RequestInfo& requestInfo,
|
||||
int encodedDataLength,
|
||||
const std::optional<ResponseInfo>& redirectResponse) {
|
||||
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
|
||||
auto now = HighResTimeStamp::now();
|
||||
|
||||
// All builds: Annotate PerformanceResourceTiming metadata
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
|
||||
perfTimingsBuffer_.emplace(
|
||||
requestId,
|
||||
ResourceTimingData{
|
||||
.url = requestInfo.url,
|
||||
.fetchStart = now,
|
||||
.requestStart = now,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
if (!isDebuggingEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
double timestamp = getCurrentUnixTimestampSeconds();
|
||||
auto request = cdp::network::Request::fromInputParams(requestInfo);
|
||||
auto params = cdp::network::RequestWillBeSentParams{
|
||||
.requestId = requestId,
|
||||
.loaderId = "",
|
||||
.documentURL = "mobile",
|
||||
.request = std::move(request),
|
||||
// NOTE: Both timestamp and wallTime use the same unit, however wallTime
|
||||
// is relative to an "arbitrary epoch". In our implementation, use the
|
||||
// Unix epoch for both.
|
||||
.timestamp = timestamp,
|
||||
.wallTime = timestamp,
|
||||
.initiator = folly::dynamic::object("type", "script"),
|
||||
.redirectHasExtraInfo = redirectResponse.has_value(),
|
||||
};
|
||||
|
||||
if (redirectResponse.has_value()) {
|
||||
params.redirectResponse = cdp::network::Response::fromInputParams(
|
||||
redirectResponse.value(), encodedDataLength);
|
||||
}
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.requestWillBeSent", params.toDynamic()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportConnectionTiming(
|
||||
const std::string& requestId,
|
||||
const std::optional<Headers>& headers) {
|
||||
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
|
||||
auto now = HighResTimeStamp::now();
|
||||
|
||||
// All builds: Annotate PerformanceResourceTiming metadata
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
|
||||
auto it = perfTimingsBuffer_.find(requestId);
|
||||
if (it != perfTimingsBuffer_.end()) {
|
||||
it->second.connectStart = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
if (!isDebuggingEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto params = cdp::network::RequestWillBeSentExtraInfoParams{
|
||||
.requestId = requestId,
|
||||
.headers = headers.value_or(Headers{}),
|
||||
.connectTiming = {.requestTime = getCurrentUnixTimestampSeconds()},
|
||||
};
|
||||
|
||||
frontendChannel_(cdp::jsonNotification(
|
||||
"Network.requestWillBeSentExtraInfo", params.toDynamic()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportResponseStart(
|
||||
const std::string& requestId,
|
||||
const ResponseInfo& responseInfo,
|
||||
int encodedDataLength) {
|
||||
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
|
||||
auto now = HighResTimeStamp::now();
|
||||
|
||||
// All builds: Annotate PerformanceResourceTiming metadata
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
|
||||
auto it = perfTimingsBuffer_.find(requestId);
|
||||
if (it != perfTimingsBuffer_.end()) {
|
||||
it->second.connectEnd = now;
|
||||
it->second.responseStart = now;
|
||||
it->second.responseStatus = responseInfo.statusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
if (!isDebuggingEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto response =
|
||||
cdp::network::Response::fromInputParams(responseInfo, encodedDataLength);
|
||||
auto resourceType = cdp::network::resourceTypeFromMimeType(response.mimeType);
|
||||
resourceTypeMap_.emplace(requestId, resourceType);
|
||||
|
||||
auto params = cdp::network::ResponseReceivedParams{
|
||||
.requestId = requestId,
|
||||
.loaderId = "",
|
||||
.timestamp = getCurrentUnixTimestampSeconds(),
|
||||
.type = resourceType,
|
||||
.response = response,
|
||||
.hasExtraInfo = false,
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.responseReceived", params.toDynamic()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportDataReceived(
|
||||
const std::string& requestId,
|
||||
int dataLength,
|
||||
const std::optional<int>& encodedDataLength) {
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
if (!isDebuggingEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto params = cdp::network::DataReceivedParams{
|
||||
.requestId = requestId,
|
||||
.timestamp = getCurrentUnixTimestampSeconds(),
|
||||
.dataLength = dataLength,
|
||||
.encodedDataLength = encodedDataLength.value_or(dataLength),
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.dataReceived", params.toDynamic()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportResponseEnd(
|
||||
const std::string& requestId,
|
||||
int encodedDataLength) {
|
||||
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
|
||||
auto now = HighResTimeStamp::now();
|
||||
|
||||
// All builds: Report PerformanceResourceTiming event
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
|
||||
auto it = perfTimingsBuffer_.find(requestId);
|
||||
if (it != perfTimingsBuffer_.end()) {
|
||||
auto& eventData = it->second;
|
||||
PerformanceEntryReporter::getInstance()->reportResourceTiming(
|
||||
eventData.url,
|
||||
eventData.fetchStart,
|
||||
eventData.requestStart,
|
||||
eventData.connectStart.value_or(now),
|
||||
eventData.connectEnd.value_or(now),
|
||||
eventData.responseStart.value_or(now),
|
||||
now,
|
||||
eventData.responseStatus);
|
||||
perfTimingsBuffer_.erase(requestId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
if (!isDebuggingEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto params = cdp::network::LoadingFinishedParams{
|
||||
.requestId = requestId,
|
||||
.timestamp = getCurrentUnixTimestampSeconds(),
|
||||
.encodedDataLength = encodedDataLength,
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.loadingFinished", params.toDynamic()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportRequestFailed(
|
||||
const std::string& requestId,
|
||||
bool cancelled) const {
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
if (!isDebuggingEnabledNoSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto params = cdp::network::LoadingFailedParams{
|
||||
.requestId = requestId,
|
||||
.timestamp = getCurrentUnixTimestampSeconds(),
|
||||
.type = resourceTypeMap_.find(requestId) != resourceTypeMap_.end()
|
||||
? resourceTypeMap_.at(requestId)
|
||||
: "Other",
|
||||
.errorText = cancelled ? "net::ERR_ABORTED" : "net::ERR_FAILED",
|
||||
.canceled = cancelled,
|
||||
};
|
||||
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("Network.loadingFailed", params.toDynamic()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::storeResponseBody(
|
||||
const std::string& requestId,
|
||||
std::string_view body,
|
||||
bool base64Encoded) {
|
||||
std::lock_guard<std::mutex> lock(requestBodyMutex_);
|
||||
requestBodyBuffer_.put(requestId, body, base64Encoded);
|
||||
}
|
||||
|
||||
std::optional<std::tuple<std::string, bool>> NetworkReporter::getResponseBody(
|
||||
const std::string& requestId) {
|
||||
std::lock_guard<std::mutex> lock(requestBodyMutex_);
|
||||
auto responseBody = requestBodyBuffer_.get(requestId);
|
||||
|
||||
if (responseBody == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::make_optional<std::tuple<std::string, bool>>(
|
||||
responseBody->data, responseBody->base64Encoded);
|
||||
}
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
-3
@@ -44,9 +44,6 @@ Pod::Spec.new do |s|
|
||||
resolve_use_frameworks(s, header_mappings_dir: "../..", module_name: module_name)
|
||||
|
||||
add_dependency(s, "React-jsinspectorcdp", :framework_name => 'jsinspector_moderncdp')
|
||||
add_dependency(s, "React-featureflags")
|
||||
s.dependency "React-performancetimeline"
|
||||
s.dependency "React-timing"
|
||||
|
||||
add_rn_third_party_dependencies(s)
|
||||
add_rncore_dependency(s)
|
||||
|
||||
@@ -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<<5bd932f1d52596dad6ea86a2674170ff>>
|
||||
* @generated SignedSource<<a4fb74cf8a68181f509794e387bf666d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -206,6 +206,10 @@ bool ReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection() {
|
||||
return getAccessor().enableVirtualViewWindowFocusDetection();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault() {
|
||||
return getAccessor().enableWebPerformanceAPIsByDefault();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact() {
|
||||
return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
}
|
||||
@@ -222,6 +226,10 @@ bool ReactNativeFeatureFlags::hideOffscreenVirtualViewsOnIOS() {
|
||||
return getAccessor().hideOffscreenVirtualViewsOnIOS();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAndroid() {
|
||||
return getAccessor().overrideBySynchronousMountPropsAtMountingAndroid();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::perfMonitorV2Enabled() {
|
||||
return getAccessor().perfMonitorV2Enabled();
|
||||
}
|
||||
|
||||
@@ -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<<3cde1e9bcf234515551ba57ecf02e3a7>>
|
||||
* @generated SignedSource<<a4a98649c527be3c936c859ddc59cb33>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -264,6 +264,11 @@ class ReactNativeFeatureFlags {
|
||||
*/
|
||||
RN_EXPORT static bool enableVirtualViewWindowFocusDetection();
|
||||
|
||||
/**
|
||||
* Enable Web Performance APIs (Performance Timeline, User Timings, etc.) by default.
|
||||
*/
|
||||
RN_EXPORT static bool enableWebPerformanceAPIsByDefault();
|
||||
|
||||
/**
|
||||
* Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.
|
||||
*/
|
||||
@@ -284,6 +289,11 @@ class ReactNativeFeatureFlags {
|
||||
*/
|
||||
RN_EXPORT static bool hideOffscreenVirtualViewsOnIOS();
|
||||
|
||||
/**
|
||||
* Override props at mounting with synchronously mounted (i.e. direct manipulation) props from Native Animated.
|
||||
*/
|
||||
RN_EXPORT static bool overrideBySynchronousMountPropsAtMountingAndroid();
|
||||
|
||||
/**
|
||||
* Enable the V2 in-app Performance Monitor. This flag is global and should not be changed across React Host lifetimes.
|
||||
*/
|
||||
|
||||
+61
-25
@@ -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<<bf7bb959d851abb8cd98a2eb3fa43923>>
|
||||
* @generated SignedSource<<91188495ce43a1e1c820cdc3d6302bda>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -839,6 +839,24 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewWindowFocusDetection() {
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::enableWebPerformanceAPIsByDefault() {
|
||||
auto flagValue = enableWebPerformanceAPIsByDefault_.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(45, "enableWebPerformanceAPIsByDefault");
|
||||
|
||||
flagValue = currentProvider_->enableWebPerformanceAPIsByDefault();
|
||||
enableWebPerformanceAPIsByDefault_ = flagValue;
|
||||
}
|
||||
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAndReact() {
|
||||
auto flagValue = fixMappingOfEventPrioritiesBetweenFabricAndReact_.load();
|
||||
|
||||
@@ -848,7 +866,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(45, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
markFlagAsAccessed(46, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
|
||||
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
|
||||
@@ -866,7 +884,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(46, "fuseboxEnabledRelease");
|
||||
markFlagAsAccessed(47, "fuseboxEnabledRelease");
|
||||
|
||||
flagValue = currentProvider_->fuseboxEnabledRelease();
|
||||
fuseboxEnabledRelease_ = flagValue;
|
||||
@@ -884,7 +902,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(47, "fuseboxNetworkInspectionEnabled");
|
||||
markFlagAsAccessed(48, "fuseboxNetworkInspectionEnabled");
|
||||
|
||||
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
|
||||
fuseboxNetworkInspectionEnabled_ = flagValue;
|
||||
@@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(48, "hideOffscreenVirtualViewsOnIOS");
|
||||
markFlagAsAccessed(49, "hideOffscreenVirtualViewsOnIOS");
|
||||
|
||||
flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS();
|
||||
hideOffscreenVirtualViewsOnIOS_ = flagValue;
|
||||
@@ -911,6 +929,24 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() {
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingAndroid() {
|
||||
auto flagValue = overrideBySynchronousMountPropsAtMountingAndroid_.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(50, "overrideBySynchronousMountPropsAtMountingAndroid");
|
||||
|
||||
flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid();
|
||||
overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue;
|
||||
}
|
||||
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() {
|
||||
auto flagValue = perfMonitorV2Enabled_.load();
|
||||
|
||||
@@ -920,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(49, "perfMonitorV2Enabled");
|
||||
markFlagAsAccessed(51, "perfMonitorV2Enabled");
|
||||
|
||||
flagValue = currentProvider_->perfMonitorV2Enabled();
|
||||
perfMonitorV2Enabled_ = flagValue;
|
||||
@@ -938,7 +974,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(50, "preparedTextCacheSize");
|
||||
markFlagAsAccessed(52, "preparedTextCacheSize");
|
||||
|
||||
flagValue = currentProvider_->preparedTextCacheSize();
|
||||
preparedTextCacheSize_ = flagValue;
|
||||
@@ -956,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(51, "preventShadowTreeCommitExhaustion");
|
||||
markFlagAsAccessed(53, "preventShadowTreeCommitExhaustion");
|
||||
|
||||
flagValue = currentProvider_->preventShadowTreeCommitExhaustion();
|
||||
preventShadowTreeCommitExhaustion_ = flagValue;
|
||||
@@ -974,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(52, "shouldPressibilityUseW3CPointerEventsForHover");
|
||||
markFlagAsAccessed(54, "shouldPressibilityUseW3CPointerEventsForHover");
|
||||
|
||||
flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover();
|
||||
shouldPressibilityUseW3CPointerEventsForHover_ = flagValue;
|
||||
@@ -992,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause()
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(53, "skipActivityIdentityAssertionOnHostPause");
|
||||
markFlagAsAccessed(55, "skipActivityIdentityAssertionOnHostPause");
|
||||
|
||||
flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause();
|
||||
skipActivityIdentityAssertionOnHostPause_ = flagValue;
|
||||
@@ -1010,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::sweepActiveTouchOnChildNativeGesturesAndro
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(54, "sweepActiveTouchOnChildNativeGesturesAndroid");
|
||||
markFlagAsAccessed(56, "sweepActiveTouchOnChildNativeGesturesAndroid");
|
||||
|
||||
flagValue = currentProvider_->sweepActiveTouchOnChildNativeGesturesAndroid();
|
||||
sweepActiveTouchOnChildNativeGesturesAndroid_ = flagValue;
|
||||
@@ -1028,7 +1064,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(55, "traceTurboModulePromiseRejectionsOnAndroid");
|
||||
markFlagAsAccessed(57, "traceTurboModulePromiseRejectionsOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
|
||||
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
|
||||
@@ -1046,7 +1082,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(56, "updateRuntimeShadowNodeReferencesOnCommit");
|
||||
markFlagAsAccessed(58, "updateRuntimeShadowNodeReferencesOnCommit");
|
||||
|
||||
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
|
||||
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
|
||||
@@ -1064,7 +1100,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(57, "useAlwaysAvailableJSErrorHandling");
|
||||
markFlagAsAccessed(59, "useAlwaysAvailableJSErrorHandling");
|
||||
|
||||
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
|
||||
useAlwaysAvailableJSErrorHandling_ = flagValue;
|
||||
@@ -1082,7 +1118,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(58, "useFabricInterop");
|
||||
markFlagAsAccessed(60, "useFabricInterop");
|
||||
|
||||
flagValue = currentProvider_->useFabricInterop();
|
||||
useFabricInterop_ = flagValue;
|
||||
@@ -1100,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeEqualsInNativeReadableArrayAndroi
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(59, "useNativeEqualsInNativeReadableArrayAndroid");
|
||||
markFlagAsAccessed(61, "useNativeEqualsInNativeReadableArrayAndroid");
|
||||
|
||||
flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid();
|
||||
useNativeEqualsInNativeReadableArrayAndroid_ = flagValue;
|
||||
@@ -1118,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeTransformHelperAndroid() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(60, "useNativeTransformHelperAndroid");
|
||||
markFlagAsAccessed(62, "useNativeTransformHelperAndroid");
|
||||
|
||||
flagValue = currentProvider_->useNativeTransformHelperAndroid();
|
||||
useNativeTransformHelperAndroid_ = flagValue;
|
||||
@@ -1136,7 +1172,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(61, "useNativeViewConfigsInBridgelessMode");
|
||||
markFlagAsAccessed(63, "useNativeViewConfigsInBridgelessMode");
|
||||
|
||||
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
|
||||
useNativeViewConfigsInBridgelessMode_ = flagValue;
|
||||
@@ -1154,7 +1190,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(62, "useOptimizedEventBatchingOnAndroid");
|
||||
markFlagAsAccessed(64, "useOptimizedEventBatchingOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
|
||||
useOptimizedEventBatchingOnAndroid_ = flagValue;
|
||||
@@ -1172,7 +1208,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(63, "useRawPropsJsiValue");
|
||||
markFlagAsAccessed(65, "useRawPropsJsiValue");
|
||||
|
||||
flagValue = currentProvider_->useRawPropsJsiValue();
|
||||
useRawPropsJsiValue_ = flagValue;
|
||||
@@ -1190,7 +1226,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(64, "useShadowNodeStateOnClone");
|
||||
markFlagAsAccessed(66, "useShadowNodeStateOnClone");
|
||||
|
||||
flagValue = currentProvider_->useShadowNodeStateOnClone();
|
||||
useShadowNodeStateOnClone_ = flagValue;
|
||||
@@ -1208,7 +1244,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(65, "useTurboModuleInterop");
|
||||
markFlagAsAccessed(67, "useTurboModuleInterop");
|
||||
|
||||
flagValue = currentProvider_->useTurboModuleInterop();
|
||||
useTurboModuleInterop_ = flagValue;
|
||||
@@ -1226,7 +1262,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(66, "useTurboModules");
|
||||
markFlagAsAccessed(68, "useTurboModules");
|
||||
|
||||
flagValue = currentProvider_->useTurboModules();
|
||||
useTurboModules_ = flagValue;
|
||||
@@ -1244,7 +1280,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(67, "virtualViewHysteresisRatio");
|
||||
markFlagAsAccessed(69, "virtualViewHysteresisRatio");
|
||||
|
||||
flagValue = currentProvider_->virtualViewHysteresisRatio();
|
||||
virtualViewHysteresisRatio_ = flagValue;
|
||||
@@ -1262,7 +1298,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(68, "virtualViewPrerenderRatio");
|
||||
markFlagAsAccessed(70, "virtualViewPrerenderRatio");
|
||||
|
||||
flagValue = currentProvider_->virtualViewPrerenderRatio();
|
||||
virtualViewPrerenderRatio_ = 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<<a449e9cf8f14bb7381d9779c764d0d7c>>
|
||||
* @generated SignedSource<<17f7a8577d05b191010622fb58ba27f8>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -77,10 +77,12 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
bool enableVirtualViewDebugFeatures();
|
||||
bool enableVirtualViewRenderState();
|
||||
bool enableVirtualViewWindowFocusDetection();
|
||||
bool enableWebPerformanceAPIsByDefault();
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
bool fuseboxEnabledRelease();
|
||||
bool fuseboxNetworkInspectionEnabled();
|
||||
bool hideOffscreenVirtualViewsOnIOS();
|
||||
bool overrideBySynchronousMountPropsAtMountingAndroid();
|
||||
bool perfMonitorV2Enabled();
|
||||
double preparedTextCacheSize();
|
||||
bool preventShadowTreeCommitExhaustion();
|
||||
@@ -112,7 +114,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
|
||||
bool wasOverridden_;
|
||||
|
||||
std::array<std::atomic<const char*>, 69> accessedFeatureFlags_;
|
||||
std::array<std::atomic<const char*>, 71> accessedFeatureFlags_;
|
||||
|
||||
std::atomic<std::optional<bool>> commonTestFlag_;
|
||||
std::atomic<std::optional<bool>> cdpInteractionMetricsEnabled_;
|
||||
@@ -159,10 +161,12 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::atomic<std::optional<bool>> enableVirtualViewDebugFeatures_;
|
||||
std::atomic<std::optional<bool>> enableVirtualViewRenderState_;
|
||||
std::atomic<std::optional<bool>> enableVirtualViewWindowFocusDetection_;
|
||||
std::atomic<std::optional<bool>> enableWebPerformanceAPIsByDefault_;
|
||||
std::atomic<std::optional<bool>> fixMappingOfEventPrioritiesBetweenFabricAndReact_;
|
||||
std::atomic<std::optional<bool>> fuseboxEnabledRelease_;
|
||||
std::atomic<std::optional<bool>> fuseboxNetworkInspectionEnabled_;
|
||||
std::atomic<std::optional<bool>> hideOffscreenVirtualViewsOnIOS_;
|
||||
std::atomic<std::optional<bool>> overrideBySynchronousMountPropsAtMountingAndroid_;
|
||||
std::atomic<std::optional<bool>> perfMonitorV2Enabled_;
|
||||
std::atomic<std::optional<double>> preparedTextCacheSize_;
|
||||
std::atomic<std::optional<bool>> preventShadowTreeCommitExhaustion_;
|
||||
|
||||
+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<<6d8adaa4b960407540afb1d6e42a3840>>
|
||||
* @generated SignedSource<<f387394359fc15af1ecad288f08fefe7>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -207,6 +207,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enableWebPerformanceAPIsByDefault() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
|
||||
return false;
|
||||
}
|
||||
@@ -223,6 +227,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool overrideBySynchronousMountPropsAtMountingAndroid() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool perfMonitorV2Enabled() 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<<ccd274f2ece9c85f23dd87e74d446ecb>>
|
||||
* @generated SignedSource<<e70173d99a68270c77447cd13c556f6d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -450,6 +450,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
|
||||
return ReactNativeFeatureFlagsDefaults::enableVirtualViewWindowFocusDetection();
|
||||
}
|
||||
|
||||
bool enableWebPerformanceAPIsByDefault() override {
|
||||
auto value = values_["enableWebPerformanceAPIsByDefault"];
|
||||
if (!value.isNull()) {
|
||||
return value.getBool();
|
||||
}
|
||||
|
||||
return ReactNativeFeatureFlagsDefaults::enableWebPerformanceAPIsByDefault();
|
||||
}
|
||||
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
|
||||
auto value = values_["fixMappingOfEventPrioritiesBetweenFabricAndReact"];
|
||||
if (!value.isNull()) {
|
||||
@@ -486,6 +495,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
|
||||
return ReactNativeFeatureFlagsDefaults::hideOffscreenVirtualViewsOnIOS();
|
||||
}
|
||||
|
||||
bool overrideBySynchronousMountPropsAtMountingAndroid() override {
|
||||
auto value = values_["overrideBySynchronousMountPropsAtMountingAndroid"];
|
||||
if (!value.isNull()) {
|
||||
return value.getBool();
|
||||
}
|
||||
|
||||
return ReactNativeFeatureFlagsDefaults::overrideBySynchronousMountPropsAtMountingAndroid();
|
||||
}
|
||||
|
||||
bool perfMonitorV2Enabled() override {
|
||||
auto value = values_["perfMonitorV2Enabled"];
|
||||
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<<07b25b19a265e8afe53eeeffade4dfc0>>
|
||||
* @generated SignedSource<<d8b57edf1ba256965238058533a2ea7d>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -70,10 +70,12 @@ class ReactNativeFeatureFlagsProvider {
|
||||
virtual bool enableVirtualViewDebugFeatures() = 0;
|
||||
virtual bool enableVirtualViewRenderState() = 0;
|
||||
virtual bool enableVirtualViewWindowFocusDetection() = 0;
|
||||
virtual bool enableWebPerformanceAPIsByDefault() = 0;
|
||||
virtual bool fixMappingOfEventPrioritiesBetweenFabricAndReact() = 0;
|
||||
virtual bool fuseboxEnabledRelease() = 0;
|
||||
virtual bool fuseboxNetworkInspectionEnabled() = 0;
|
||||
virtual bool hideOffscreenVirtualViewsOnIOS() = 0;
|
||||
virtual bool overrideBySynchronousMountPropsAtMountingAndroid() = 0;
|
||||
virtual bool perfMonitorV2Enabled() = 0;
|
||||
virtual double preparedTextCacheSize() = 0;
|
||||
virtual bool preventShadowTreeCommitExhaustion() = 0;
|
||||
|
||||
+5
-5
@@ -51,7 +51,7 @@ std::vector<const RCTMethodInfo *> getMethodInfos(Class moduleClass)
|
||||
std::vector<const RCTMethodInfo *> methodInfos;
|
||||
|
||||
Class cls = moduleClass;
|
||||
while (cls && cls != [NSObject class] && cls != [NSProxy class]) {
|
||||
while ((cls != nullptr) && cls != [NSObject class] && cls != [NSProxy class]) {
|
||||
unsigned int methodCount;
|
||||
Method *methods = class_copyMethodList(object_getClass(cls), &methodCount);
|
||||
|
||||
@@ -482,7 +482,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg) {
|
||||
if (arg != nullptr) {
|
||||
[retainedObjectsForInvocation addObject:arg];
|
||||
}
|
||||
[inv setArgument:&arg atIndex:(index) + 2];
|
||||
@@ -496,7 +496,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
typeInvocation.target = [RCTConvert class];
|
||||
|
||||
void *returnValue = malloc(typeSignature.methodReturnLength);
|
||||
if (!returnValue) {
|
||||
if (returnValue == nullptr) {
|
||||
// CWE - 391 : Unchecked error condition
|
||||
// https://www.cvedetails.com/cwe-details/391/Unchecked-Error-Condition.html
|
||||
// https://eli.thegreenplace.net/2009/10/30/handling-out-of-memory-conditions-in-c
|
||||
@@ -519,7 +519,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
* RCTModuleMethod doesn't actually call into RCTConvert in this case.
|
||||
*/
|
||||
id arg = [objCArg copy];
|
||||
if (arg) {
|
||||
if (arg != nullptr) {
|
||||
[retainedObjectsForInvocation addObject:arg];
|
||||
}
|
||||
[inv setArgument:&arg atIndex:(index) + 2];
|
||||
@@ -537,7 +537,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
||||
|
||||
RCTResponseSenderBlock arg =
|
||||
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
||||
if (arg) {
|
||||
if (arg != nullptr) {
|
||||
[retainedObjectsForInvocation addObject:arg];
|
||||
}
|
||||
[inv setArgument:&arg atIndex:(index) + 2];
|
||||
|
||||
+15
-15
@@ -59,7 +59,7 @@ static jsi::Value convertNSNumberToJSINumber(jsi::Runtime &runtime, NSNumber *va
|
||||
|
||||
static jsi::String convertNSStringToJSIString(jsi::Runtime &runtime, NSString *value)
|
||||
{
|
||||
return jsi::String::createFromUtf8(runtime, [value UTF8String] ? [value UTF8String] : "");
|
||||
return jsi::String::createFromUtf8(runtime, ([value UTF8String] != nullptr) ? [value UTF8String] : "");
|
||||
}
|
||||
|
||||
static jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value)
|
||||
@@ -124,7 +124,7 @@ static NSArray *convertJSIArrayToNSArray(
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// Insert kCFNull when it's `undefined` value to preserve the indices.
|
||||
id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker, useNSNull);
|
||||
[result addObject:convertedObject ? convertedObject : (id)kCFNull];
|
||||
[result addObject:(convertedObject != nullptr) ? convertedObject : (id)kCFNull];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ static NSDictionary *convertJSIObjectToNSDictionary(
|
||||
jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime);
|
||||
NSString *k = convertJSIStringToNSString(runtime, name);
|
||||
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker, useNSNull);
|
||||
if (v) {
|
||||
if (v != nullptr) {
|
||||
result[k] = v;
|
||||
}
|
||||
}
|
||||
@@ -252,7 +252,7 @@ static jsi::Value convertJSErrorDetailsToJSRuntimeError(jsi::Runtime &runtime, N
|
||||
jsi::Value
|
||||
ObjCTurboModule::createPromise(jsi::Runtime &runtime, const std::string &methodName, PromiseInvocationBlock invoke)
|
||||
{
|
||||
if (!invoke) {
|
||||
if (invoke == nullptr) {
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ id ObjCTurboModule::performMethodInvocation(
|
||||
|
||||
void (^block)() = ^{
|
||||
id<RCTBridgeModule> strongModule = weakModule;
|
||||
if (!strongModule) {
|
||||
if (strongModule == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ void ObjCTurboModule::performVoidMethodInvocation(
|
||||
|
||||
void (^block)() = ^{
|
||||
id<RCTBridgeModule> strongModule = weakModule;
|
||||
if (!strongModule) {
|
||||
if (strongModule == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -560,14 +560,14 @@ jsi::Value ObjCTurboModule::convertReturnIdToJSIValue(
|
||||
*/
|
||||
NSString *ObjCTurboModule::getArgumentTypeName(jsi::Runtime &runtime, NSString *methodName, int argIndex)
|
||||
{
|
||||
if (!methodArgumentTypeNames_) {
|
||||
if (methodArgumentTypeNames_ == nullptr) {
|
||||
NSMutableDictionary<NSString *, NSArray<NSString *> *> *methodArgumentTypeNames = [NSMutableDictionary new];
|
||||
|
||||
unsigned int numberOfMethods;
|
||||
Class cls = [instance_ class];
|
||||
Method *methods = class_copyMethodList(object_getClass(cls), &numberOfMethods);
|
||||
|
||||
if (methods) {
|
||||
if (methods != nullptr) {
|
||||
for (unsigned int i = 0; i < numberOfMethods; i++) {
|
||||
SEL s = method_getName(methods[i]);
|
||||
NSString *mName = NSStringFromSelector(s);
|
||||
@@ -597,7 +597,7 @@ NSString *ObjCTurboModule::getArgumentTypeName(jsi::Runtime &runtime, NSString *
|
||||
methodArgumentTypeNames_ = methodArgumentTypeNames;
|
||||
}
|
||||
|
||||
if (methodArgumentTypeNames_[methodName]) {
|
||||
if (methodArgumentTypeNames_[methodName] != nullptr) {
|
||||
assert([methodArgumentTypeNames_[methodName] count] > argIndex);
|
||||
return methodArgumentTypeNames_[methodName][argIndex];
|
||||
}
|
||||
@@ -656,7 +656,7 @@ void ObjCTurboModule::setInvocationArg(
|
||||
*/
|
||||
BOOL enableModuleArgumentNSNullConversionIOS = ReactNativeFeatureFlags::enableModuleArgumentNSNullConversionIOS();
|
||||
id objCArg = convertJSIValueToObjCObject(runtime, arg, jsInvoker_, enableModuleArgumentNSNullConversionIOS);
|
||||
if (objCArg) {
|
||||
if (objCArg != nullptr) {
|
||||
NSString *methodNameNSString = @(methodName);
|
||||
|
||||
/**
|
||||
@@ -678,7 +678,7 @@ void ObjCTurboModule::setInvocationArg(
|
||||
}
|
||||
|
||||
[inv setArgument:(void *)&convertedObjCArg atIndex:i + 2];
|
||||
if (convertedObjCArg) {
|
||||
if (convertedObjCArg != nullptr) {
|
||||
[retainedObjectsForInvocation addObject:convertedObjCArg];
|
||||
}
|
||||
return;
|
||||
@@ -708,7 +708,7 @@ void ObjCTurboModule::setInvocationArg(
|
||||
* Insert converted args unmodified.
|
||||
*/
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
if (objCArg) {
|
||||
if (objCArg != nullptr) {
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
}
|
||||
}
|
||||
@@ -848,7 +848,7 @@ jsi::Value ObjCTurboModule::invokeObjCMethod(
|
||||
|
||||
BOOL ObjCTurboModule::hasMethodArgConversionSelector(NSString *methodName, size_t argIndex)
|
||||
{
|
||||
return methodArgConversionSelectors_ && methodArgConversionSelectors_[methodName] &&
|
||||
return (methodArgConversionSelectors_ != nullptr) && (methodArgConversionSelectors_[methodName] != nullptr) &&
|
||||
![methodArgConversionSelectors_[methodName][argIndex] isEqual:(id)kCFNull];
|
||||
}
|
||||
|
||||
@@ -860,11 +860,11 @@ SEL ObjCTurboModule::getMethodArgConversionSelector(NSString *methodName, size_t
|
||||
|
||||
void ObjCTurboModule::setMethodArgConversionSelector(NSString *methodName, size_t argIndex, NSString *fnName)
|
||||
{
|
||||
if (!methodArgConversionSelectors_) {
|
||||
if (methodArgConversionSelectors_ == nullptr) {
|
||||
methodArgConversionSelectors_ = [NSMutableDictionary new];
|
||||
}
|
||||
|
||||
if (!methodArgConversionSelectors_[methodName]) {
|
||||
if (methodArgConversionSelectors_[methodName] == nullptr) {
|
||||
auto metaData = methodMap_.at([methodName UTF8String]);
|
||||
auto argCount = metaData.argCount;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ target_link_libraries(react_nativemodule_defaults
|
||||
react_nativemodule_featureflags
|
||||
react_nativemodule_microtasks
|
||||
react_nativemodule_idlecallbacks
|
||||
react_nativemodule_webperformance
|
||||
)
|
||||
target_compile_reactnative_options(react_nativemodule_defaults PRIVATE)
|
||||
target_compile_options(react_nativemodule_defaults PRIVATE -Wpedantic)
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
*/
|
||||
|
||||
#include "DefaultTurboModules.h"
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/nativemodule/dom/NativeDOM.h>
|
||||
#include <react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h>
|
||||
#include <react/nativemodule/idlecallbacks/NativeIdleCallbacks.h>
|
||||
#include <react/nativemodule/microtasks/NativeMicrotasks.h>
|
||||
#include <react/nativemodule/webperformance/NativePerformance.h>
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY
|
||||
#include <react/nativemodule/devtoolsruntimesettings/DevToolsRuntimeSettingsModule.h>
|
||||
@@ -36,6 +38,12 @@ namespace facebook::react {
|
||||
return std::make_shared<NativeDOM>(jsInvoker);
|
||||
}
|
||||
|
||||
if (ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault()) {
|
||||
if (name == NativePerformance::kModuleName) {
|
||||
return std::make_shared<NativePerformance>(jsInvoker);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY
|
||||
if (name == DevToolsRuntimeSettingsModule::kModuleName) {
|
||||
return std::make_shared<DevToolsRuntimeSettingsModule>(jsInvoker);
|
||||
|
||||
+1
@@ -50,5 +50,6 @@ Pod::Spec.new do |s|
|
||||
s.dependency "React-featureflagsnativemodule"
|
||||
s.dependency "React-microtasksnativemodule"
|
||||
s.dependency "React-idlecallbacksnativemodule"
|
||||
s.dependency "React-webperformancenativemodule"
|
||||
add_dependency(s, "React-RCTFBReactNativeSpec")
|
||||
end
|
||||
|
||||
+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<<348005db0ceee698cd7c33f29bcf85a6>>
|
||||
* @generated SignedSource<<702c4023cfafdd477cba85c6efe94d93>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -269,6 +269,11 @@ bool NativeReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection(
|
||||
return ReactNativeFeatureFlags::enableVirtualViewWindowFocusDetection();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::enableWebPerformanceAPIsByDefault();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
@@ -289,6 +294,11 @@ bool NativeReactNativeFeatureFlags::hideOffscreenVirtualViewsOnIOS(
|
||||
return ReactNativeFeatureFlags::hideOffscreenVirtualViewsOnIOS();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAndroid(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAndroid();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::perfMonitorV2Enabled(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::perfMonitorV2Enabled();
|
||||
|
||||
+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<<a27c4788a4b87366ef1e3ee03da53ab6>>
|
||||
* @generated SignedSource<<96e93863588a9878db7c812435564603>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -126,6 +126,8 @@ class NativeReactNativeFeatureFlags
|
||||
|
||||
bool enableVirtualViewWindowFocusDetection(jsi::Runtime& runtime);
|
||||
|
||||
bool enableWebPerformanceAPIsByDefault(jsi::Runtime& runtime);
|
||||
|
||||
bool fixMappingOfEventPrioritiesBetweenFabricAndReact(jsi::Runtime& runtime);
|
||||
|
||||
bool fuseboxEnabledRelease(jsi::Runtime& runtime);
|
||||
@@ -134,6 +136,8 @@ class NativeReactNativeFeatureFlags
|
||||
|
||||
bool hideOffscreenVirtualViewsOnIOS(jsi::Runtime& runtime);
|
||||
|
||||
bool overrideBySynchronousMountPropsAtMountingAndroid(jsi::Runtime& runtime);
|
||||
|
||||
bool perfMonitorV2Enabled(jsi::Runtime& runtime);
|
||||
|
||||
double preparedTextCacheSize(jsi::Runtime& runtime);
|
||||
|
||||
+4
-4
@@ -136,14 +136,14 @@ RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSDictionary *, getValue : (double)x y : (NS
|
||||
{
|
||||
return @{
|
||||
@"x" : @(x),
|
||||
@"y" : y ? y : [NSNull null],
|
||||
@"z" : z ? z : [NSNull null],
|
||||
@"y" : (y != nullptr) ? y : [NSNull null],
|
||||
@"z" : (z != nullptr) ? z : [NSNull null],
|
||||
};
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getValueWithCallback : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
if (!callback) {
|
||||
if (callback == nullptr) {
|
||||
return;
|
||||
}
|
||||
callback(@[ @"value from callback!" ]);
|
||||
@@ -154,7 +154,7 @@ RCT_EXPORT_METHOD(getValueWithPromise
|
||||
: (RCTPromiseResolveBlock)resolve reject
|
||||
: (RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
if (!resolve || !reject) {
|
||||
if ((resolve == nullptr) || (reject == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -136,14 +136,14 @@ RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSDictionary *, getValue : (double)x y : (NS
|
||||
{
|
||||
return @{
|
||||
@"x" : @(x),
|
||||
@"y" : y ? y : [NSNull null],
|
||||
@"z" : z ? z : [NSNull null],
|
||||
@"y" : (y != nullptr) ? y : [NSNull null],
|
||||
@"z" : (z != nullptr) ? z : [NSNull null],
|
||||
};
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getValueWithCallback : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
if (!callback) {
|
||||
if (callback == nullptr) {
|
||||
return;
|
||||
}
|
||||
callback(@[ @"value from callback!" ]);
|
||||
@@ -154,7 +154,7 @@ RCT_EXPORT_METHOD(getValueWithPromise
|
||||
: (RCTPromiseResolveBlock)resolve reject
|
||||
: (RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
if (!resolve || !reject) {
|
||||
if ((resolve == nullptr) || (reject == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@ cmake_minimum_required(VERSION 3.13)
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
|
||||
|
||||
file(GLOB react_nativemodule_webperformance_SRC CONFIGURE_DEPENDS *.cpp)
|
||||
add_library(react_nativemodule_webperformance OBJECT ${react_nativemodule_webperformance_SRC})
|
||||
|
||||
target_include_directories(react_nativemodule_webperformance PUBLIC ${REACT_COMMON_DIR})
|
||||
|
||||
target_link_libraries(react_nativemodule_webperformance
|
||||
react_performance_timeline
|
||||
react_codegen_rncore
|
||||
react_cxxreact
|
||||
)
|
||||
|
||||
+9
@@ -131,9 +131,18 @@ NativePerformance::NativePerformance(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: NativePerformanceCxxSpec(std::move(jsInvoker)) {}
|
||||
|
||||
HighResTimeStamp NativePerformance::now(jsi::Runtime& /*rt*/) {
|
||||
// This is not spec-compliant, as this is the duration from system boot to
|
||||
// now, instead of from app startup to now.
|
||||
// This should be carefully changed eventually.
|
||||
return HighResTimeStamp::now();
|
||||
}
|
||||
|
||||
HighResDuration NativePerformance::timeOrigin(jsi::Runtime& /*rt*/) {
|
||||
// This is not spec-compliant, as this is an approximation from Unix epoch to
|
||||
// system boot, instead of a precise duration from Unix epoch to app startup.
|
||||
return HighResTimeStamp::unsafeOriginFromUnixTimeStamp();
|
||||
}
|
||||
|
||||
void NativePerformance::reportMark(
|
||||
jsi::Runtime& rt,
|
||||
const std::string& name,
|
||||
|
||||
+3
@@ -88,6 +88,9 @@ class NativePerformance : public NativePerformanceCxxSpec<NativePerformance> {
|
||||
// https://www.w3.org/TR/hr-time-3/#now-method
|
||||
HighResTimeStamp now(jsi::Runtime& rt);
|
||||
|
||||
// https://www.w3.org/TR/hr-time-3/#timeorigin-attribute
|
||||
HighResDuration timeOrigin(jsi::Runtime& rt);
|
||||
|
||||
#pragma mark - User Timing Level 3 functions (https://w3c.github.io/user-timing/)
|
||||
|
||||
void reportMark(
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
# 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.
|
||||
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "..", "package.json")))
|
||||
version = package['version']
|
||||
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
||||
else
|
||||
source[:tag] = "v#{version}"
|
||||
end
|
||||
|
||||
header_search_paths = []
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
header_search_paths << "\"$(PODS_TARGET_SRCROOT)/../../..\"" # this is needed to allow the module access its own files
|
||||
end
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React-webperformancenativemodule"
|
||||
s.version = version
|
||||
s.summary = "React Native idle callbacks native module"
|
||||
s.homepage = "https://reactnative.dev/"
|
||||
s.license = package["license"]
|
||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||
s.platforms = min_supported_versions
|
||||
s.source = source
|
||||
s.source_files = podspec_sources("*.{cpp,h}", "*.h")
|
||||
s.header_dir = "react/nativemodule/webperformance"
|
||||
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
|
||||
"OTHER_CFLAGS" => "$(inherited)",
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "webperformancenativemodule"
|
||||
s.header_mappings_dir = "../.."
|
||||
end
|
||||
|
||||
s.dependency "React-jsi"
|
||||
s.dependency "React-jsiexecutor"
|
||||
|
||||
depend_on_js_engine(s)
|
||||
add_rn_third_party_dependencies(s)
|
||||
add_rncore_dependency(s)
|
||||
|
||||
s.dependency "ReactCommon/turbomodule/core"
|
||||
add_dependency(s, "React-RCTFBReactNativeSpec")
|
||||
add_dependency(s, "React-performancetimeline")
|
||||
add_dependency(s, "React-runtimeexecutor", :additional_framework_paths => ["platform/ios"])
|
||||
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
|
||||
|
||||
file(GLOB react_networking_SRC CONFIGURE_DEPENDS *.cpp)
|
||||
add_library(react_networking OBJECT ${react_networking_SRC})
|
||||
|
||||
target_compile_reactnative_options(react_networking PRIVATE)
|
||||
target_compile_options(react_networking PRIVATE -Wpedantic)
|
||||
|
||||
target_include_directories(react_networking PUBLIC ${REACT_COMMON_DIR})
|
||||
target_link_libraries(react_networking
|
||||
folly_runtime
|
||||
react_performance_timeline
|
||||
react_timing)
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 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 "NetworkReporter.h"
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
#include "jsinspector-modern/network/NetworkHandler.h"
|
||||
#endif
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/performance/timeline/PerformanceEntryReporter.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
NetworkReporter& NetworkReporter::getInstance() {
|
||||
static NetworkReporter instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool NetworkReporter::isDebuggingEnabled() const {
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
return jsinspector_modern::NetworkHandler::getInstance().isEnabled();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportRequestStart(
|
||||
const std::string& requestId,
|
||||
const RequestInfo& requestInfo,
|
||||
int encodedDataLength,
|
||||
const std::optional<ResponseInfo>& redirectResponse) {
|
||||
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
|
||||
auto now = HighResTimeStamp::now();
|
||||
|
||||
// All builds: Annotate PerformanceResourceTiming metadata
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
|
||||
perfTimingsBuffer_.emplace(
|
||||
requestId,
|
||||
ResourceTimingData{
|
||||
.url = requestInfo.url,
|
||||
.fetchStart = now,
|
||||
.requestStart = now,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
jsinspector_modern::NetworkHandler::getInstance().onRequestWillBeSent(
|
||||
requestId,
|
||||
{
|
||||
.url = requestInfo.url,
|
||||
.method = requestInfo.httpMethod,
|
||||
.headers = requestInfo.headers,
|
||||
.postData = requestInfo.httpBody,
|
||||
},
|
||||
redirectResponse.has_value()
|
||||
? std::optional<jsinspector_modern::cdp::network::Response>(
|
||||
jsinspector_modern::cdp::network::Response::fromInputParams(
|
||||
redirectResponse->url,
|
||||
redirectResponse->statusCode,
|
||||
redirectResponse->headers,
|
||||
encodedDataLength))
|
||||
: std::nullopt);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportConnectionTiming(
|
||||
const std::string& requestId,
|
||||
const std::optional<Headers>& headers) {
|
||||
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
|
||||
auto now = HighResTimeStamp::now();
|
||||
|
||||
// All builds: Annotate PerformanceResourceTiming metadata
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
|
||||
auto it = perfTimingsBuffer_.find(requestId);
|
||||
if (it != perfTimingsBuffer_.end()) {
|
||||
it->second.connectStart = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
jsinspector_modern::NetworkHandler::getInstance()
|
||||
.onRequestWillBeSentExtraInfo(requestId, headers.value_or(Headers{}));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportResponseStart(
|
||||
const std::string& requestId,
|
||||
const ResponseInfo& responseInfo,
|
||||
int encodedDataLength) {
|
||||
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
|
||||
auto now = HighResTimeStamp::now();
|
||||
|
||||
// All builds: Annotate PerformanceResourceTiming metadata
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
|
||||
auto it = perfTimingsBuffer_.find(requestId);
|
||||
if (it != perfTimingsBuffer_.end()) {
|
||||
it->second.connectEnd = now;
|
||||
it->second.responseStart = now;
|
||||
it->second.responseStatus = responseInfo.statusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
jsinspector_modern::NetworkHandler::getInstance().onResponseReceived(
|
||||
requestId,
|
||||
jsinspector_modern::cdp::network::Response::fromInputParams(
|
||||
responseInfo.url,
|
||||
responseInfo.statusCode,
|
||||
responseInfo.headers,
|
||||
encodedDataLength));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportDataReceived(
|
||||
const std::string& requestId,
|
||||
int dataLength,
|
||||
const std::optional<int>& encodedDataLength) {
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
jsinspector_modern::NetworkHandler::getInstance().onDataReceived(
|
||||
requestId, dataLength, encodedDataLength.value_or(dataLength));
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportResponseEnd(
|
||||
const std::string& requestId,
|
||||
int encodedDataLength) {
|
||||
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
|
||||
auto now = HighResTimeStamp::now();
|
||||
|
||||
// All builds: Report PerformanceResourceTiming event
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
|
||||
auto it = perfTimingsBuffer_.find(requestId);
|
||||
if (it != perfTimingsBuffer_.end()) {
|
||||
auto& eventData = it->second;
|
||||
PerformanceEntryReporter::getInstance()->reportResourceTiming(
|
||||
eventData.url,
|
||||
eventData.fetchStart,
|
||||
eventData.requestStart,
|
||||
eventData.connectStart.value_or(now),
|
||||
eventData.connectEnd.value_or(now),
|
||||
eventData.responseStart.value_or(now),
|
||||
now,
|
||||
eventData.responseStatus);
|
||||
perfTimingsBuffer_.erase(requestId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
jsinspector_modern::NetworkHandler::getInstance().onLoadingFinished(
|
||||
requestId, encodedDataLength);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::reportRequestFailed(
|
||||
const std::string& requestId,
|
||||
bool cancelled) const {
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: CDP event handling
|
||||
jsinspector_modern::NetworkHandler::getInstance().onLoadingFailed(
|
||||
requestId, cancelled);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkReporter::storeResponseBody(
|
||||
const std::string& requestId,
|
||||
std::string_view body,
|
||||
bool base64Encoded) {
|
||||
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
|
||||
// Debug build: Store fetched response body for later CDP retrieval
|
||||
jsinspector_modern::NetworkHandler::getInstance().storeResponseBody(
|
||||
requestId, body, base64Encoded);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
+3
-62
@@ -7,27 +7,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BoundedRequestBuffer.h"
|
||||
#include "NetworkTypes.h"
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
#include <react/timing/primitives.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
/**
|
||||
* A callback that can be used to send debugger messages (method responses and
|
||||
* events) to the frontend. The message must be a JSON-encoded string.
|
||||
* The callback may be called from any thread.
|
||||
*/
|
||||
using FrontendChannel = std::function<void(std::string_view messageJson)>;
|
||||
namespace facebook::react {
|
||||
|
||||
/**
|
||||
* Container for static network event metadata aligning with the
|
||||
@@ -57,34 +46,10 @@ class NetworkReporter {
|
||||
public:
|
||||
static NetworkReporter& getInstance();
|
||||
|
||||
/**
|
||||
* Set the channel used to send CDP events to the frontend. This should be
|
||||
* supplied before calling `enableDebugging`.
|
||||
*/
|
||||
void setFrontendChannel(FrontendChannel frontendChannel);
|
||||
|
||||
/**
|
||||
* Enable network tracking over CDP. Once enabled, network events will be
|
||||
* sent to the debugger client. Returns `false` if already enabled.
|
||||
*
|
||||
* Corresponds to `Network.enable` in CDP.
|
||||
*/
|
||||
bool enableDebugging();
|
||||
|
||||
/**
|
||||
* Disable network tracking over CDP, preventing network events from being
|
||||
* sent to the debugger client. Returns `false` if not initially enabled.
|
||||
*
|
||||
* Corresponds to `Network.disable` in CDP.
|
||||
*/
|
||||
bool disableDebugging();
|
||||
|
||||
/**
|
||||
* Returns whether network tracking over CDP is currently enabled.
|
||||
*/
|
||||
inline bool isDebuggingEnabled() const {
|
||||
return debuggingEnabled_.load(std::memory_order_acquire);
|
||||
}
|
||||
bool isDebuggingEnabled() const;
|
||||
|
||||
/**
|
||||
* Report a network request that is about to be sent.
|
||||
@@ -174,38 +139,14 @@ class NetworkReporter {
|
||||
std::string_view body,
|
||||
bool base64Encoded);
|
||||
|
||||
/**
|
||||
* Retrieve a stored response body for a given request ID.
|
||||
*
|
||||
* \returns An optional tuple of [responseBody, base64Encoded]. Returns
|
||||
* nullopt if no entry is found in the buffer.
|
||||
*/
|
||||
std::optional<std::tuple<std::string, bool>> getResponseBody(
|
||||
const std::string& requestId);
|
||||
|
||||
private:
|
||||
NetworkReporter() = default;
|
||||
NetworkReporter(const NetworkReporter&) = delete;
|
||||
NetworkReporter& operator=(const NetworkReporter&) = delete;
|
||||
~NetworkReporter() = default;
|
||||
|
||||
std::atomic<bool> debuggingEnabled_{false};
|
||||
|
||||
inline bool isDebuggingEnabledNoSync() const {
|
||||
return debuggingEnabled_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
FrontendChannel frontendChannel_;
|
||||
|
||||
std::unordered_map<std::string, ResourceTimingData> perfTimingsBuffer_{};
|
||||
std::mutex perfTimingsMutex_;
|
||||
|
||||
// Only populated when CDP debugging is enabled.
|
||||
std::map<std::string, std::string> resourceTypeMap_{};
|
||||
|
||||
// Only populated when CDP debugging is enabled.
|
||||
BoundedRequestBuffer requestBodyBuffer_{};
|
||||
std::mutex requestBodyMutex_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
} // namespace facebook::react
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
|
||||
// Defines generic input object types for NetworkReporter.
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
namespace facebook::react {
|
||||
|
||||
/**
|
||||
* A collection of parsed HTTP headers.
|
||||
@@ -39,4 +39,4 @@ struct ResponseInfo {
|
||||
std::optional<Headers> headers;
|
||||
};
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
} // namespace facebook::react
|
||||
@@ -0,0 +1,51 @@
|
||||
# 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.
|
||||
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "package.json")))
|
||||
version = package['version']
|
||||
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
||||
else
|
||||
source[:tag] = "v#{version}"
|
||||
end
|
||||
|
||||
header_search_paths = []
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
header_search_paths << "\"$(PODS_TARGET_SRCROOT)/../..\"" # this is needed to allow the feature flags access its own files
|
||||
end
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React-networking"
|
||||
s.version = version
|
||||
s.summary = "Common networking modules for React Native"
|
||||
s.homepage = "https://reactnative.dev/"
|
||||
s.license = package["license"]
|
||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||
s.platforms = min_supported_versions
|
||||
s.source = source
|
||||
s.source_files = podspec_sources("*.{cpp,h}", "*.h")
|
||||
s.header_dir = "react/networking"
|
||||
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'] && ReactNativeCoreUtils.build_rncore_from_source()
|
||||
s.module_name = "React_networking"
|
||||
s.header_mappings_dir = "../.."
|
||||
end
|
||||
add_dependency(s, "React-featureflags")
|
||||
add_dependency(s, "React-jsinspectornetwork", :framework_name => 'jsinspector_modernnetwork')
|
||||
s.dependency "React-performancetimeline"
|
||||
s.dependency "React-timing"
|
||||
|
||||
add_rn_third_party_dependencies(s)
|
||||
add_rncore_dependency(s)
|
||||
end
|
||||
+13
-7
@@ -742,7 +742,8 @@ folly::dynamic NativeAnimatedNodesManager::managedProps(
|
||||
if (const auto node = getAnimatedNode<PropsAnimatedNode>(iter->second)) {
|
||||
return node->props();
|
||||
}
|
||||
} else {
|
||||
} else if (!ReactNativeFeatureFlags::
|
||||
overrideBySynchronousMountPropsAtMountingAndroid()) {
|
||||
std::lock_guard<std::mutex> lockUnsyncedDirectViewProps(
|
||||
unsyncedDirectViewPropsMutex_);
|
||||
if (auto it = unsyncedDirectViewProps_.find(tag);
|
||||
@@ -761,7 +762,8 @@ bool NativeAnimatedNodesManager::hasManagedProps() const noexcept {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (!ReactNativeFeatureFlags::
|
||||
overrideBySynchronousMountPropsAtMountingAndroid()) {
|
||||
std::lock_guard<std::mutex> lock(unsyncedDirectViewPropsMutex_);
|
||||
if (!unsyncedDirectViewProps_.empty()) {
|
||||
return true;
|
||||
@@ -771,10 +773,13 @@ bool NativeAnimatedNodesManager::hasManagedProps() const noexcept {
|
||||
}
|
||||
|
||||
void NativeAnimatedNodesManager::onManagedPropsRemoved(Tag tag) noexcept {
|
||||
std::lock_guard<std::mutex> lock(unsyncedDirectViewPropsMutex_);
|
||||
if (auto iter = unsyncedDirectViewProps_.find(tag);
|
||||
iter != unsyncedDirectViewProps_.end()) {
|
||||
unsyncedDirectViewProps_.erase(iter);
|
||||
if (!ReactNativeFeatureFlags::
|
||||
overrideBySynchronousMountPropsAtMountingAndroid()) {
|
||||
std::lock_guard<std::mutex> lock(unsyncedDirectViewPropsMutex_);
|
||||
if (auto iter = unsyncedDirectViewProps_.find(tag);
|
||||
iter != unsyncedDirectViewProps_.end()) {
|
||||
unsyncedDirectViewProps_.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -828,7 +833,8 @@ void NativeAnimatedNodesManager::schedulePropsCommit(
|
||||
mergeObjects(updateViewPropsDirect_[viewTag], props);
|
||||
} else if (!layoutStyleUpdated && directManipulationCallback_ != nullptr) {
|
||||
mergeObjects(updateViewPropsDirect_[viewTag], props);
|
||||
{
|
||||
if (!ReactNativeFeatureFlags::
|
||||
overrideBySynchronousMountPropsAtMountingAndroid()) {
|
||||
std::lock_guard<std::mutex> lock(unsyncedDirectViewPropsMutex_);
|
||||
mergeObjects(unsyncedDirectViewProps_[viewTag], props);
|
||||
}
|
||||
|
||||
@@ -402,79 +402,79 @@ inline void fromRawValue(
|
||||
inline std::string toString(const FontVariant& fontVariant) {
|
||||
auto result = std::string{};
|
||||
auto separator = std::string{", "};
|
||||
if ((int)fontVariant & (int)FontVariant::SmallCaps) {
|
||||
if (((int)fontVariant & (int)FontVariant::SmallCaps) != 0) {
|
||||
result += "small-caps" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::OldstyleNums) {
|
||||
if (((int)fontVariant & (int)FontVariant::OldstyleNums) != 0) {
|
||||
result += "oldstyle-nums" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::LiningNums) {
|
||||
if (((int)fontVariant & (int)FontVariant::LiningNums) != 0) {
|
||||
result += "lining-nums" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::TabularNums) {
|
||||
if (((int)fontVariant & (int)FontVariant::TabularNums) != 0) {
|
||||
result += "tabular-nums" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::ProportionalNums) {
|
||||
if (((int)fontVariant & (int)FontVariant::ProportionalNums) != 0) {
|
||||
result += "proportional-nums" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticOne) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticOne) != 0) {
|
||||
result += "stylistic-one" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticTwo) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticTwo) != 0) {
|
||||
result += "stylistic-two" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticThree) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticThree) != 0) {
|
||||
result += "stylistic-three" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticFour) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticFour) != 0) {
|
||||
result += "stylistic-four" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticFive) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticFive) != 0) {
|
||||
result += "stylistic-five" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticSix) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticSix) != 0) {
|
||||
result += "stylistic-six" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticSeven) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticSeven) != 0) {
|
||||
result += "stylistic-seven" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticEight) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticEight) != 0) {
|
||||
result += "stylistic-eight" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticNine) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticNine) != 0) {
|
||||
result += "stylistic-nine" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticTen) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticTen) != 0) {
|
||||
result += "stylistic-ten" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticEleven) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticEleven) != 0) {
|
||||
result += "stylistic-eleven" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticTwelve) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticTwelve) != 0) {
|
||||
result += "stylistic-twelve" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticThirteen) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticThirteen) != 0) {
|
||||
result += "stylistic-thirteen" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticFourteen) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticFourteen) != 0) {
|
||||
result += "stylistic-fourteen" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticFifteen) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticFifteen) != 0) {
|
||||
result += "stylistic-fifteen" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticSixteen) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticSixteen) != 0) {
|
||||
result += "stylistic-sixteen" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticSeventeen) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticSeventeen) != 0) {
|
||||
result += "stylistic-seventeen" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticEighteen) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticEighteen) != 0) {
|
||||
result += "stylistic-eighteen" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticNineteen) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticNineteen) != 0) {
|
||||
result += "stylistic-nineteen" + separator;
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::StylisticTwenty) {
|
||||
if (((int)fontVariant & (int)FontVariant::StylisticTwenty) != 0) {
|
||||
result += "stylistic-twenty" + separator;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -63,13 +63,13 @@ static Class getViewManagerFromComponentName(const std::string &componentName)
|
||||
// 1. Try to get the manager with the RCT prefix.
|
||||
auto rctViewManagerName = "RCT" + viewManagerName;
|
||||
Class viewManagerClass = NSClassFromString(RCTNSStringFromString(rctViewManagerName));
|
||||
if (viewManagerClass) {
|
||||
if (viewManagerClass != nullptr) {
|
||||
return viewManagerClass;
|
||||
}
|
||||
|
||||
// 2. Try to get the manager without the prefix.
|
||||
viewManagerClass = NSClassFromString(RCTNSStringFromString(viewManagerName));
|
||||
if (viewManagerClass) {
|
||||
if (viewManagerClass != nullptr) {
|
||||
return viewManagerClass;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ class AndroidTextInputComponentDescriptor final
|
||||
->getMethod<jboolean(jint, jfloatArray)>("getThemeData");
|
||||
|
||||
if (getThemeData(
|
||||
fabricUIManager, surfaceId, defaultTextInputPaddingArray)) {
|
||||
fabricUIManager, surfaceId, defaultTextInputPaddingArray) != 0u) {
|
||||
jfloat* defaultTextInputPadding =
|
||||
env->GetFloatArrayElements(defaultTextInputPaddingArray, nullptr);
|
||||
theme.start = defaultTextInputPadding[0];
|
||||
|
||||
+1
-1
@@ -310,7 +310,7 @@ static void updateBorderColorPropValue(
|
||||
const std::optional<SharedColor>& newColor,
|
||||
const std::optional<SharedColor>& oldColor) {
|
||||
if (newColor != oldColor) {
|
||||
result[propName] = *newColor.value_or(SharedColor());
|
||||
result[propName] = newColor.has_value() ? *newColor.value() : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user