react-native 0.84.0-nightly-20251212-dd390dbbe → 0.84.0-nightly-20251213-07bd24ed0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/WebSocket/WebSocketInterceptor.js +3 -3
- package/React/Base/RCTVersion.m +1 -1
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/ChangeBundleLocationDialog.kt +11 -10
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.cpp +16 -10
- package/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.h +2 -0
- package/jest/mockComponent.js +1 -1
- package/package.json +9 -9
- package/sdks/hermes-engine/version.properties +1 -1
- package/src/private/devsupport/devmenu/elementinspector/Inspector.js +6 -25
- package/src/private/devsupport/devmenu/elementinspector/InspectorPanel.js +0 -26
- package/src/private/devsupport/devmenu/elementinspector/XHRInterceptor.js +3 -2
- package/src/private/devsupport/devmenu/elementinspector/NetworkOverlay.js +0 -628
- package/src/private/devsupport/devmenu/perfmonitor/PerformanceOverlay.js +0 -66
|
@@ -29,7 +29,7 @@ export default class ReactNativeVersion {
|
|
|
29
29
|
static major: number = 0;
|
|
30
30
|
static minor: number = 84;
|
|
31
31
|
static patch: number = 0;
|
|
32
|
-
static prerelease: string | null = 'nightly-
|
|
32
|
+
static prerelease: string | null = 'nightly-20251213-07bd24ed0';
|
|
33
33
|
|
|
34
34
|
static getVersionString(): string {
|
|
35
35
|
return `${this.major}.${this.minor}.${this.patch}${this.prerelease != null ? `-${this.prerelease}` : ''}`;
|
|
@@ -33,10 +33,10 @@ let isInterceptorEnabled = false;
|
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* A network interceptor which monkey-patches RCTWebSocketModule methods
|
|
36
|
-
* to gather all websocket network
|
|
37
|
-
*
|
|
36
|
+
* to gather all websocket network events.
|
|
37
|
+
*
|
|
38
|
+
* @deprecated Since React Native 0.84
|
|
38
39
|
*/
|
|
39
|
-
|
|
40
40
|
const WebSocketInterceptor = {
|
|
41
41
|
/**
|
|
42
42
|
* Invoked when RCTWebSocketModule.close(...) is called.
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -24,7 +24,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
|
|
|
24
24
|
RCTVersionMajor: @(0),
|
|
25
25
|
RCTVersionMinor: @(84),
|
|
26
26
|
RCTVersionPatch: @(0),
|
|
27
|
-
RCTVersionPrerelease: @"nightly-
|
|
27
|
+
RCTVersionPrerelease: @"nightly-20251213-07bd24ed0",
|
|
28
28
|
};
|
|
29
29
|
});
|
|
30
30
|
return __rnVersion;
|
package/ReactAndroid/src/main/java/com/facebook/react/devsupport/ChangeBundleLocationDialog.kt
CHANGED
|
@@ -33,9 +33,6 @@ internal object ChangeBundleLocationDialog {
|
|
|
33
33
|
) {
|
|
34
34
|
val settings = devSettings.packagerConnectionSettings
|
|
35
35
|
val currentHost = settings.debugServerHost
|
|
36
|
-
settings.debugServerHost = ""
|
|
37
|
-
val defaultHost = settings.debugServerHost
|
|
38
|
-
settings.debugServerHost = currentHost
|
|
39
36
|
|
|
40
37
|
val layout = LinearLayout(context)
|
|
41
38
|
layout.orientation = LinearLayout.VERTICAL
|
|
@@ -60,11 +57,11 @@ internal object ChangeBundleLocationDialog {
|
|
|
60
57
|
input.setTextColor(-0x1000000)
|
|
61
58
|
input.setText(currentHost)
|
|
62
59
|
|
|
63
|
-
val
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
val currentHostSuggestion = Button(context)
|
|
61
|
+
currentHostSuggestion.text = currentHost
|
|
62
|
+
currentHostSuggestion.textSize = 12f
|
|
63
|
+
currentHostSuggestion.isAllCaps = false
|
|
64
|
+
currentHostSuggestion.setOnClickListener { input.setText(currentHost) }
|
|
68
65
|
|
|
69
66
|
val networkHost = getDevServerNetworkIpAndPort(context)
|
|
70
67
|
val networkHostSuggestion = Button(context)
|
|
@@ -80,8 +77,12 @@ internal object ChangeBundleLocationDialog {
|
|
|
80
77
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
81
78
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
82
79
|
)
|
|
83
|
-
suggestionRow.addView(
|
|
84
|
-
|
|
80
|
+
suggestionRow.addView(currentHostSuggestion)
|
|
81
|
+
|
|
82
|
+
if (currentHost != networkHost) {
|
|
83
|
+
// We don't want to display two buttons with the same host suggestion.
|
|
84
|
+
suggestionRow.addView(networkHostSuggestion)
|
|
85
|
+
}
|
|
85
86
|
|
|
86
87
|
val instructions = TextView(context)
|
|
87
88
|
instructions.text =
|
|
@@ -22,7 +22,7 @@ constexpr struct {
|
|
|
22
22
|
int32_t Major = 0;
|
|
23
23
|
int32_t Minor = 84;
|
|
24
24
|
int32_t Patch = 0;
|
|
25
|
-
std::string_view Prerelease = "nightly-
|
|
25
|
+
std::string_view Prerelease = "nightly-20251213-07bd24ed0";
|
|
26
26
|
} ReactNativeVersion;
|
|
27
27
|
|
|
28
28
|
} // namespace facebook::react
|
|
@@ -24,11 +24,14 @@ ImageRequest ImageFetcher::requestImage(
|
|
|
24
24
|
SurfaceId surfaceId,
|
|
25
25
|
const ImageRequestParams& imageRequestParams,
|
|
26
26
|
Tag tag) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
{
|
|
28
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
29
|
+
items_[surfaceId].emplace_back(
|
|
30
|
+
ImageRequestItem{
|
|
31
|
+
.imageSource = imageSource,
|
|
32
|
+
.imageRequestParams = imageRequestParams,
|
|
33
|
+
.tag = tag});
|
|
34
|
+
}
|
|
32
35
|
|
|
33
36
|
auto telemetry = std::make_shared<ImageTelemetry>(surfaceId);
|
|
34
37
|
|
|
@@ -40,8 +43,13 @@ ImageRequest ImageFetcher::requestImage(
|
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
void ImageFetcher::flushImageRequests() {
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
std::unordered_map<SurfaceId, std::vector<ImageRequestItem>> items;
|
|
47
|
+
{
|
|
48
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
49
|
+
if (items_.empty()) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
items.swap(items_);
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
auto fabricUIManager_ =
|
|
@@ -52,14 +60,12 @@ void ImageFetcher::flushImageRequests() {
|
|
|
52
60
|
SurfaceId, std::string, JReadableMapBuffer::javaobject)>(
|
|
53
61
|
"experimental_prefetchResources");
|
|
54
62
|
|
|
55
|
-
for (auto& [surfaceId, surfaceImageRequests] :
|
|
63
|
+
for (auto& [surfaceId, surfaceImageRequests] : items) {
|
|
56
64
|
auto readableMapBuffer = JReadableMapBuffer::createWithContents(
|
|
57
65
|
serializeImageRequests(surfaceImageRequests));
|
|
58
66
|
prefetchResources(
|
|
59
67
|
fabricUIManager_, surfaceId, "RCTImageView", readableMapBuffer.get());
|
|
60
68
|
}
|
|
61
|
-
|
|
62
|
-
items_.clear();
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
} // namespace facebook::react
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#include <react/renderer/imagemanager/ImageRequestParams.h>
|
|
12
12
|
#include <react/utils/ContextContainer.h>
|
|
13
13
|
#include <memory>
|
|
14
|
+
#include <mutex>
|
|
14
15
|
#include <unordered_map>
|
|
15
16
|
#include <vector>
|
|
16
17
|
|
|
@@ -38,6 +39,7 @@ class ImageFetcher {
|
|
|
38
39
|
Tag tag);
|
|
39
40
|
|
|
40
41
|
std::unordered_map<SurfaceId, std::vector<ImageRequestItem>> items_;
|
|
42
|
+
std::mutex mutex_;
|
|
41
43
|
std::shared_ptr<const ContextContainer> contextContainer_;
|
|
42
44
|
};
|
|
43
45
|
} // namespace facebook::react
|
package/jest/mockComponent.js
CHANGED
|
@@ -39,7 +39,7 @@ export default function mockComponent<
|
|
|
39
39
|
|
|
40
40
|
const SuperClass: typeof React.Component<{...}> =
|
|
41
41
|
typeof RealComponent === 'function' &&
|
|
42
|
-
RealComponent.prototype
|
|
42
|
+
RealComponent.prototype?.constructor instanceof React.Component
|
|
43
43
|
? RealComponent
|
|
44
44
|
: React.Component;
|
|
45
45
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.84.0-nightly-
|
|
3
|
+
"version": "0.84.0-nightly-20251213-07bd24ed0",
|
|
4
4
|
"description": "A framework for building native apps using React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -160,13 +160,13 @@
|
|
|
160
160
|
},
|
|
161
161
|
"dependencies": {
|
|
162
162
|
"@jest/create-cache-key-function": "^29.7.0",
|
|
163
|
-
"@react-native/assets-registry": "0.84.0-nightly-
|
|
164
|
-
"@react-native/codegen": "0.84.0-nightly-
|
|
165
|
-
"@react-native/community-cli-plugin": "0.84.0-nightly-
|
|
166
|
-
"@react-native/gradle-plugin": "0.84.0-nightly-
|
|
167
|
-
"@react-native/js-polyfills": "0.84.0-nightly-
|
|
168
|
-
"@react-native/normalize-colors": "0.84.0-nightly-
|
|
169
|
-
"@react-native/virtualized-lists": "0.84.0-nightly-
|
|
163
|
+
"@react-native/assets-registry": "0.84.0-nightly-20251213-07bd24ed0",
|
|
164
|
+
"@react-native/codegen": "0.84.0-nightly-20251213-07bd24ed0",
|
|
165
|
+
"@react-native/community-cli-plugin": "0.84.0-nightly-20251213-07bd24ed0",
|
|
166
|
+
"@react-native/gradle-plugin": "0.84.0-nightly-20251213-07bd24ed0",
|
|
167
|
+
"@react-native/js-polyfills": "0.84.0-nightly-20251213-07bd24ed0",
|
|
168
|
+
"@react-native/normalize-colors": "0.84.0-nightly-20251213-07bd24ed0",
|
|
169
|
+
"@react-native/virtualized-lists": "0.84.0-nightly-20251213-07bd24ed0",
|
|
170
170
|
"abort-controller": "^3.0.0",
|
|
171
171
|
"anser": "^1.4.9",
|
|
172
172
|
"ansi-regex": "^5.0.0",
|
|
@@ -175,7 +175,7 @@
|
|
|
175
175
|
"base64-js": "^1.5.1",
|
|
176
176
|
"commander": "^12.0.0",
|
|
177
177
|
"flow-enums-runtime": "^0.0.6",
|
|
178
|
-
"hermes-compiler": "0.
|
|
178
|
+
"hermes-compiler": "0.15.0-commitly-202512121350-fd0e1d3ed",
|
|
179
179
|
"invariant": "^2.2.4",
|
|
180
180
|
"jest-environment-node": "^29.7.0",
|
|
181
181
|
"memoize-one": "^5.0.0",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
HERMES_VERSION_NAME=0.
|
|
1
|
+
HERMES_VERSION_NAME=0.15.0-commitly-202512121350-fd0e1d3ed
|
|
2
2
|
HERMES_V1_VERSION_NAME=250829098.0.4
|
|
@@ -39,10 +39,6 @@ const InspectorPanel = require('./InspectorPanel').default;
|
|
|
39
39
|
const {useState} = React;
|
|
40
40
|
|
|
41
41
|
type PanelPosition = 'top' | 'bottom';
|
|
42
|
-
type SelectedTab =
|
|
43
|
-
| 'elements-inspector'
|
|
44
|
-
| 'network-profiling'
|
|
45
|
-
| 'performance-profiling';
|
|
46
42
|
|
|
47
43
|
export type InspectedElementFrame = TouchedViewDataAtPoint['frame'];
|
|
48
44
|
export type InspectedElement = $ReadOnly<{
|
|
@@ -62,8 +58,7 @@ function Inspector({
|
|
|
62
58
|
onRequestRerenderApp,
|
|
63
59
|
reactDevToolsAgent,
|
|
64
60
|
}: Props): React.Node {
|
|
65
|
-
const [
|
|
66
|
-
useState<?SelectedTab>('elements-inspector');
|
|
61
|
+
const [inspecting, setInspecting] = useState<boolean>(true);
|
|
67
62
|
|
|
68
63
|
const [panelPosition, setPanelPosition] = useState<PanelPosition>('bottom');
|
|
69
64
|
const [inspectedElement, setInspectedElement] =
|
|
@@ -137,18 +132,8 @@ function Inspector({
|
|
|
137
132
|
);
|
|
138
133
|
};
|
|
139
134
|
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
setInspectedElement(null);
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const setPerfing = (enabled: boolean) => {
|
|
146
|
-
setSelectedTab(enabled ? 'performance-profiling' : null);
|
|
147
|
-
setInspectedElement(null);
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const setNetworking = (enabled: boolean) => {
|
|
151
|
-
setSelectedTab(enabled ? 'network-profiling' : null);
|
|
135
|
+
const handleSetInspecting = (enabled: boolean) => {
|
|
136
|
+
setInspecting(enabled);
|
|
152
137
|
setInspectedElement(null);
|
|
153
138
|
};
|
|
154
139
|
|
|
@@ -164,7 +149,7 @@ function Inspector({
|
|
|
164
149
|
|
|
165
150
|
return (
|
|
166
151
|
<View style={styles.container} pointerEvents="box-none">
|
|
167
|
-
{
|
|
152
|
+
{inspecting && (
|
|
168
153
|
<InspectorOverlay
|
|
169
154
|
inspected={inspectedElement}
|
|
170
155
|
onTouchPoint={onTouchPoint}
|
|
@@ -174,18 +159,14 @@ function Inspector({
|
|
|
174
159
|
<SafeAreaView style={[styles.panelContainer, panelContainerStyle]}>
|
|
175
160
|
<InspectorPanel
|
|
176
161
|
devtoolsIsOpen={!!reactDevToolsAgent}
|
|
177
|
-
inspecting={
|
|
178
|
-
|
|
179
|
-
setPerfing={setPerfing}
|
|
180
|
-
setInspecting={setInspecting}
|
|
162
|
+
inspecting={inspecting}
|
|
163
|
+
setInspecting={handleSetInspecting}
|
|
181
164
|
inspected={inspectedElement}
|
|
182
165
|
hierarchy={elementsHierarchy}
|
|
183
166
|
selection={selectionIndex}
|
|
184
167
|
setSelection={setSelection}
|
|
185
168
|
touchTargeting={PressabilityDebug.isEnabled()}
|
|
186
169
|
setTouchTargeting={setTouchTargeting}
|
|
187
|
-
networking={selectedTab === 'network-profiling'}
|
|
188
|
-
setNetworking={setNetworking}
|
|
189
170
|
/>
|
|
190
171
|
</SafeAreaView>
|
|
191
172
|
</View>
|
|
@@ -23,20 +23,14 @@ const View = require('../../../../../Libraries/Components/View/View').default;
|
|
|
23
23
|
const StyleSheet =
|
|
24
24
|
require('../../../../../Libraries/StyleSheet/StyleSheet').default;
|
|
25
25
|
const Text = require('../../../../../Libraries/Text/Text').default;
|
|
26
|
-
const PerformanceOverlay = require('../perfmonitor/PerformanceOverlay').default;
|
|
27
26
|
const ElementProperties = require('./ElementProperties').default;
|
|
28
|
-
const NetworkOverlay = require('./NetworkOverlay').default;
|
|
29
27
|
|
|
30
28
|
type Props = $ReadOnly<{
|
|
31
29
|
devtoolsIsOpen: boolean,
|
|
32
30
|
inspecting: boolean,
|
|
33
31
|
setInspecting: (val: boolean) => void,
|
|
34
|
-
perfing: boolean,
|
|
35
|
-
setPerfing: (val: boolean) => void,
|
|
36
32
|
touchTargeting: boolean,
|
|
37
33
|
setTouchTargeting: (val: boolean) => void,
|
|
38
|
-
networking: boolean,
|
|
39
|
-
setNetworking: (val: boolean) => void,
|
|
40
34
|
hierarchy?: ?ElementsHierarchy,
|
|
41
35
|
selection?: ?number,
|
|
42
36
|
setSelection: number => mixed,
|
|
@@ -67,10 +61,6 @@ class InspectorPanel extends React.Component<Props> {
|
|
|
67
61
|
/>
|
|
68
62
|
</ScrollView>
|
|
69
63
|
);
|
|
70
|
-
} else if (this.props.perfing) {
|
|
71
|
-
contents = <PerformanceOverlay />;
|
|
72
|
-
} else if (this.props.networking) {
|
|
73
|
-
contents = <NetworkOverlay />;
|
|
74
64
|
} else {
|
|
75
65
|
contents = <View style={styles.waiting}>{this.renderWaiting()}</View>;
|
|
76
66
|
}
|
|
@@ -83,22 +73,6 @@ class InspectorPanel extends React.Component<Props> {
|
|
|
83
73
|
pressed={this.props.inspecting}
|
|
84
74
|
onClick={this.props.setInspecting}
|
|
85
75
|
/>
|
|
86
|
-
{global.RN$Bridgeless === true ? null : (
|
|
87
|
-
// These Inspector Panel sub-features are removed under the New Arch.
|
|
88
|
-
// See https://github.com/react-native-community/discussions-and-proposals/pull/777
|
|
89
|
-
<>
|
|
90
|
-
<InspectorPanelButton
|
|
91
|
-
title={'Perf'}
|
|
92
|
-
pressed={this.props.perfing}
|
|
93
|
-
onClick={this.props.setPerfing}
|
|
94
|
-
/>
|
|
95
|
-
<InspectorPanelButton
|
|
96
|
-
title={'Network'}
|
|
97
|
-
pressed={this.props.networking}
|
|
98
|
-
onClick={this.props.setNetworking}
|
|
99
|
-
/>
|
|
100
|
-
</>
|
|
101
|
-
)}
|
|
102
76
|
<InspectorPanelButton
|
|
103
77
|
title={'Touchables'}
|
|
104
78
|
pressed={this.props.touchTargeting}
|
|
@@ -64,10 +64,11 @@ let isInterceptorEnabled = false;
|
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* A network interceptor which monkey-patches XMLHttpRequest methods
|
|
67
|
-
* to gather all network requests/responses
|
|
68
|
-
* information in the React Native inspector development tool.
|
|
67
|
+
* to gather all network requests/responses.
|
|
69
68
|
* This supports interception with XMLHttpRequest API, including Fetch API
|
|
70
69
|
* and any other third party libraries that depend on XMLHttpRequest.
|
|
70
|
+
*
|
|
71
|
+
* @deprecated Since React Native 0.84
|
|
71
72
|
*/
|
|
72
73
|
const XHRInterceptor = {
|
|
73
74
|
/**
|
|
@@ -1,628 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
* @flow
|
|
8
|
-
* @format
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
import type XMLHttpRequest from '../../../../../Libraries/Network/XMLHttpRequest';
|
|
14
|
-
import type {ListRenderItemInfo} from '@react-native/virtualized-lists';
|
|
15
|
-
|
|
16
|
-
import ScrollView from '../../../../../Libraries/Components/ScrollView/ScrollView';
|
|
17
|
-
import * as React from 'react';
|
|
18
|
-
|
|
19
|
-
const TouchableHighlight =
|
|
20
|
-
require('../../../../../Libraries/Components/Touchable/TouchableHighlight').default;
|
|
21
|
-
const View = require('../../../../../Libraries/Components/View/View').default;
|
|
22
|
-
const FlatList = require('../../../../../Libraries/Lists/FlatList').default;
|
|
23
|
-
const StyleSheet =
|
|
24
|
-
require('../../../../../Libraries/StyleSheet/StyleSheet').default;
|
|
25
|
-
const Text = require('../../../../../Libraries/Text/Text').default;
|
|
26
|
-
const WebSocketInterceptor =
|
|
27
|
-
require('../../../../../Libraries/WebSocket/WebSocketInterceptor').default;
|
|
28
|
-
const XHRInterceptor = require('./XHRInterceptor').default;
|
|
29
|
-
|
|
30
|
-
const LISTVIEW_CELL_HEIGHT = 15;
|
|
31
|
-
|
|
32
|
-
// Global id for the intercepted XMLHttpRequest objects.
|
|
33
|
-
let nextXHRId = 0;
|
|
34
|
-
|
|
35
|
-
type NetworkRequestInfo = {
|
|
36
|
-
id: number,
|
|
37
|
-
type?: string,
|
|
38
|
-
url?: string,
|
|
39
|
-
method?: string,
|
|
40
|
-
status?: number,
|
|
41
|
-
dataSent?: any,
|
|
42
|
-
responseContentType?: string,
|
|
43
|
-
responseSize?: number,
|
|
44
|
-
requestHeaders?: Object,
|
|
45
|
-
responseHeaders?: string,
|
|
46
|
-
response?: Object | string,
|
|
47
|
-
responseURL?: string,
|
|
48
|
-
responseType?: string,
|
|
49
|
-
timeout?: number,
|
|
50
|
-
closeReason?: string,
|
|
51
|
-
messages?: string,
|
|
52
|
-
serverClose?: Object,
|
|
53
|
-
serverError?: Object,
|
|
54
|
-
...
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
type Props = $ReadOnly<{}>;
|
|
58
|
-
type State = {
|
|
59
|
-
detailRowId: ?number,
|
|
60
|
-
requests: Array<NetworkRequestInfo>,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
function getStringByValue(value: any): string {
|
|
64
|
-
if (value === undefined) {
|
|
65
|
-
return 'undefined';
|
|
66
|
-
}
|
|
67
|
-
if (typeof value === 'object') {
|
|
68
|
-
return JSON.stringify(value);
|
|
69
|
-
}
|
|
70
|
-
if (typeof value === 'string' && value.length > 500) {
|
|
71
|
-
return String(value)
|
|
72
|
-
.slice(0, 500)
|
|
73
|
-
.concat('\n***TRUNCATED TO 500 CHARACTERS***');
|
|
74
|
-
}
|
|
75
|
-
return value;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function getTypeShortName(type: any): string {
|
|
79
|
-
if (type === 'XMLHttpRequest') {
|
|
80
|
-
return 'XHR';
|
|
81
|
-
} else if (type === 'WebSocket') {
|
|
82
|
-
return 'WS';
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return '';
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function keyExtractor(request: NetworkRequestInfo): string {
|
|
89
|
-
return String(request.id);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const XHR_ID_KEY = Symbol('XHR_ID');
|
|
93
|
-
|
|
94
|
-
function getXHRId(xhr: XMLHttpRequest): number {
|
|
95
|
-
// $FlowExpectedError[prop-missing]
|
|
96
|
-
return xhr[XHR_ID_KEY];
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function setXHRId(xhr: XMLHttpRequest, id: number) {
|
|
100
|
-
// $FlowExpectedError[prop-missing]
|
|
101
|
-
xhr[XHR_ID_KEY] = id;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Show all the intercepted network requests over the InspectorPanel.
|
|
106
|
-
*/
|
|
107
|
-
class NetworkOverlay extends React.Component<Props, State> {
|
|
108
|
-
_requestsListView: ?React.ElementRef<Class<FlatList<NetworkRequestInfo>>>;
|
|
109
|
-
_detailScrollView: ?React.ElementRef<typeof ScrollView>;
|
|
110
|
-
|
|
111
|
-
// Metrics are used to decide when if the request list should be sticky, and
|
|
112
|
-
// scroll to the bottom as new network requests come in, or if the user has
|
|
113
|
-
// intentionally scrolled away from the bottom - to instead flash the scroll bar
|
|
114
|
-
// and keep the current position
|
|
115
|
-
_requestsListViewScrollMetrics: {
|
|
116
|
-
contentLength: number,
|
|
117
|
-
offset: number,
|
|
118
|
-
visibleLength: number,
|
|
119
|
-
} = {
|
|
120
|
-
offset: 0,
|
|
121
|
-
visibleLength: 0,
|
|
122
|
-
contentLength: 0,
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
// Map of `socketId` -> `index in `this.state.requests`.
|
|
126
|
-
_socketIdMap: {[number]: number} = {};
|
|
127
|
-
// Map of `xhr[XHR_ID_KEY]` -> `index in `this.state.requests`.
|
|
128
|
-
_xhrIdMap: {[key: number]: number, ...} = {};
|
|
129
|
-
|
|
130
|
-
state: State = {
|
|
131
|
-
detailRowId: null,
|
|
132
|
-
requests: [],
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
_enableXHRInterception(): void {
|
|
136
|
-
if (XHRInterceptor.isInterceptorEnabled()) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
// Show the XHR request item in listView as soon as it was opened.
|
|
140
|
-
XHRInterceptor.setOpenCallback((method, url, xhr) => {
|
|
141
|
-
// Generate a global id for each intercepted xhr object, add this id
|
|
142
|
-
// to the xhr object as a private `_index` property to identify it,
|
|
143
|
-
// so that we can distinguish different xhr objects in callbacks.
|
|
144
|
-
setXHRId(xhr, nextXHRId++);
|
|
145
|
-
const xhrIndex = this.state.requests.length;
|
|
146
|
-
this._xhrIdMap[getXHRId(xhr)] = xhrIndex;
|
|
147
|
-
|
|
148
|
-
const _xhr: NetworkRequestInfo = {
|
|
149
|
-
id: xhrIndex,
|
|
150
|
-
type: 'XMLHttpRequest',
|
|
151
|
-
method: method,
|
|
152
|
-
url: url,
|
|
153
|
-
};
|
|
154
|
-
this.setState(
|
|
155
|
-
{
|
|
156
|
-
requests: this.state.requests.concat(_xhr),
|
|
157
|
-
},
|
|
158
|
-
this._indicateAdditionalRequests,
|
|
159
|
-
);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
XHRInterceptor.setRequestHeaderCallback((header, value, xhr) => {
|
|
163
|
-
// $FlowFixMe[prop-missing]
|
|
164
|
-
const xhrIndex = this._getRequestIndexByXHRID(getXHRId(xhr));
|
|
165
|
-
if (xhrIndex === -1) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
this.setState(({requests}) => {
|
|
170
|
-
const networkRequestInfo = requests[xhrIndex];
|
|
171
|
-
if (!networkRequestInfo.requestHeaders) {
|
|
172
|
-
networkRequestInfo.requestHeaders = ({}: {[any]: any});
|
|
173
|
-
}
|
|
174
|
-
networkRequestInfo.requestHeaders[header] = value;
|
|
175
|
-
return {requests};
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
XHRInterceptor.setSendCallback((data, xhr) => {
|
|
180
|
-
// $FlowFixMe[prop-missing]
|
|
181
|
-
const xhrIndex = this._getRequestIndexByXHRID(getXHRId(xhr));
|
|
182
|
-
if (xhrIndex === -1) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
this.setState(({requests}) => {
|
|
187
|
-
const networkRequestInfo = requests[xhrIndex];
|
|
188
|
-
networkRequestInfo.dataSent = data;
|
|
189
|
-
return {requests};
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
XHRInterceptor.setHeaderReceivedCallback(
|
|
194
|
-
(type, size, responseHeaders, xhr) => {
|
|
195
|
-
// $FlowFixMe[prop-missing]
|
|
196
|
-
const xhrIndex = this._getRequestIndexByXHRID(getXHRId(xhr));
|
|
197
|
-
if (xhrIndex === -1) {
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
this.setState(({requests}) => {
|
|
202
|
-
const networkRequestInfo = requests[xhrIndex];
|
|
203
|
-
networkRequestInfo.responseContentType = type;
|
|
204
|
-
networkRequestInfo.responseSize = size;
|
|
205
|
-
networkRequestInfo.responseHeaders = responseHeaders;
|
|
206
|
-
return {requests};
|
|
207
|
-
});
|
|
208
|
-
},
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
XHRInterceptor.setResponseCallback(
|
|
212
|
-
(status, timeout, response, responseURL, responseType, xhr) => {
|
|
213
|
-
// $FlowFixMe[prop-missing]
|
|
214
|
-
const xhrIndex = this._getRequestIndexByXHRID(getXHRId(xhr));
|
|
215
|
-
if (xhrIndex === -1) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
this.setState(({requests}) => {
|
|
220
|
-
const networkRequestInfo = requests[xhrIndex];
|
|
221
|
-
networkRequestInfo.status = status;
|
|
222
|
-
networkRequestInfo.timeout = timeout;
|
|
223
|
-
networkRequestInfo.response = response;
|
|
224
|
-
networkRequestInfo.responseURL = responseURL;
|
|
225
|
-
networkRequestInfo.responseType = responseType;
|
|
226
|
-
|
|
227
|
-
return {requests};
|
|
228
|
-
});
|
|
229
|
-
},
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
// Fire above callbacks.
|
|
233
|
-
XHRInterceptor.enableInterception();
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
_enableWebSocketInterception(): void {
|
|
237
|
-
if (WebSocketInterceptor.isInterceptorEnabled()) {
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
// Show the WebSocket request item in listView when 'connect' is called.
|
|
241
|
-
WebSocketInterceptor.setConnectCallback(
|
|
242
|
-
(url, protocols, options, socketId) => {
|
|
243
|
-
const socketIndex = this.state.requests.length;
|
|
244
|
-
this._socketIdMap[socketId] = socketIndex;
|
|
245
|
-
const _webSocket: NetworkRequestInfo = {
|
|
246
|
-
id: socketIndex,
|
|
247
|
-
type: 'WebSocket',
|
|
248
|
-
url: url,
|
|
249
|
-
protocols: protocols,
|
|
250
|
-
};
|
|
251
|
-
this.setState(
|
|
252
|
-
{
|
|
253
|
-
requests: this.state.requests.concat(_webSocket),
|
|
254
|
-
},
|
|
255
|
-
this._indicateAdditionalRequests,
|
|
256
|
-
);
|
|
257
|
-
},
|
|
258
|
-
);
|
|
259
|
-
|
|
260
|
-
WebSocketInterceptor.setCloseCallback(
|
|
261
|
-
(statusCode, closeReason, socketId) => {
|
|
262
|
-
const socketIndex = this._socketIdMap[socketId];
|
|
263
|
-
if (socketIndex === undefined) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
if (statusCode !== null && closeReason !== null) {
|
|
267
|
-
this.setState(({requests}) => {
|
|
268
|
-
const networkRequestInfo = requests[socketIndex];
|
|
269
|
-
networkRequestInfo.status = statusCode;
|
|
270
|
-
networkRequestInfo.closeReason = closeReason;
|
|
271
|
-
return {requests};
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
},
|
|
275
|
-
);
|
|
276
|
-
|
|
277
|
-
WebSocketInterceptor.setSendCallback((data, socketId) => {
|
|
278
|
-
const socketIndex = this._socketIdMap[socketId];
|
|
279
|
-
if (socketIndex === undefined) {
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
this.setState(({requests}) => {
|
|
284
|
-
const networkRequestInfo = requests[socketIndex];
|
|
285
|
-
|
|
286
|
-
if (!networkRequestInfo.messages) {
|
|
287
|
-
networkRequestInfo.messages = '';
|
|
288
|
-
}
|
|
289
|
-
networkRequestInfo.messages += 'Sent: ' + JSON.stringify(data) + '\n';
|
|
290
|
-
|
|
291
|
-
return {requests};
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
WebSocketInterceptor.setOnMessageCallback((message, socketId) => {
|
|
296
|
-
const socketIndex = this._socketIdMap[socketId];
|
|
297
|
-
if (socketIndex === undefined) {
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
this.setState(({requests}) => {
|
|
302
|
-
const networkRequestInfo = requests[socketIndex];
|
|
303
|
-
|
|
304
|
-
if (!networkRequestInfo.messages) {
|
|
305
|
-
networkRequestInfo.messages = '';
|
|
306
|
-
}
|
|
307
|
-
networkRequestInfo.messages +=
|
|
308
|
-
'Received: ' + JSON.stringify(message) + '\n';
|
|
309
|
-
|
|
310
|
-
return {requests};
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
WebSocketInterceptor.setOnCloseCallback((message, socketId) => {
|
|
315
|
-
const socketIndex = this._socketIdMap[socketId];
|
|
316
|
-
if (socketIndex === undefined) {
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
this.setState(({requests}) => {
|
|
321
|
-
const networkRequestInfo = requests[socketIndex];
|
|
322
|
-
networkRequestInfo.serverClose = message;
|
|
323
|
-
|
|
324
|
-
return {requests};
|
|
325
|
-
});
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
WebSocketInterceptor.setOnErrorCallback((message, socketId) => {
|
|
329
|
-
const socketIndex = this._socketIdMap[socketId];
|
|
330
|
-
if (socketIndex === undefined) {
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
this.setState(({requests}) => {
|
|
335
|
-
const networkRequestInfo = requests[socketIndex];
|
|
336
|
-
networkRequestInfo.serverError = message;
|
|
337
|
-
|
|
338
|
-
return {requests};
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
// Fire above callbacks.
|
|
343
|
-
WebSocketInterceptor.enableInterception();
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
componentDidMount() {
|
|
347
|
-
this._enableXHRInterception();
|
|
348
|
-
this._enableWebSocketInterception();
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
componentWillUnmount() {
|
|
352
|
-
XHRInterceptor.disableInterception();
|
|
353
|
-
WebSocketInterceptor.disableInterception();
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
_renderItem = ({
|
|
357
|
-
item,
|
|
358
|
-
index,
|
|
359
|
-
}: ListRenderItemInfo<NetworkRequestInfo>): React.MixedElement => {
|
|
360
|
-
const tableRowViewStyle = [
|
|
361
|
-
styles.tableRow,
|
|
362
|
-
index % 2 === 1 ? styles.tableRowOdd : styles.tableRowEven,
|
|
363
|
-
index === this.state.detailRowId && styles.tableRowPressed,
|
|
364
|
-
];
|
|
365
|
-
const urlCellViewStyle = styles.urlCellView;
|
|
366
|
-
const methodCellViewStyle = styles.methodCellView;
|
|
367
|
-
|
|
368
|
-
return (
|
|
369
|
-
<TouchableHighlight
|
|
370
|
-
onPress={() => {
|
|
371
|
-
this._pressRow(index);
|
|
372
|
-
}}>
|
|
373
|
-
<View>
|
|
374
|
-
<View style={tableRowViewStyle}>
|
|
375
|
-
<View style={urlCellViewStyle}>
|
|
376
|
-
<Text style={styles.cellText} numberOfLines={1}>
|
|
377
|
-
{item.url}
|
|
378
|
-
</Text>
|
|
379
|
-
</View>
|
|
380
|
-
<View style={methodCellViewStyle}>
|
|
381
|
-
<Text style={styles.cellText} numberOfLines={1}>
|
|
382
|
-
{getTypeShortName(item.type)}
|
|
383
|
-
</Text>
|
|
384
|
-
</View>
|
|
385
|
-
</View>
|
|
386
|
-
</View>
|
|
387
|
-
</TouchableHighlight>
|
|
388
|
-
);
|
|
389
|
-
};
|
|
390
|
-
|
|
391
|
-
_renderItemDetail(id: number): React.Node {
|
|
392
|
-
const requestItem = this.state.requests[id];
|
|
393
|
-
const details = Object.keys(requestItem).map(key => {
|
|
394
|
-
if (key === 'id') {
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
return (
|
|
398
|
-
<View style={styles.detailViewRow} key={key}>
|
|
399
|
-
<Text style={[styles.detailViewText, styles.detailKeyCellView]}>
|
|
400
|
-
{key}
|
|
401
|
-
</Text>
|
|
402
|
-
<Text style={[styles.detailViewText, styles.detailValueCellView]}>
|
|
403
|
-
{getStringByValue(requestItem[key])}
|
|
404
|
-
</Text>
|
|
405
|
-
</View>
|
|
406
|
-
);
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
return (
|
|
410
|
-
<View>
|
|
411
|
-
<TouchableHighlight
|
|
412
|
-
style={styles.closeButton}
|
|
413
|
-
onPress={this._closeButtonClicked}>
|
|
414
|
-
<View>
|
|
415
|
-
<Text style={styles.closeButtonText}>v</Text>
|
|
416
|
-
</View>
|
|
417
|
-
</TouchableHighlight>
|
|
418
|
-
<ScrollView
|
|
419
|
-
style={styles.detailScrollView}
|
|
420
|
-
ref={scrollRef => (this._detailScrollView = scrollRef)}>
|
|
421
|
-
{details}
|
|
422
|
-
</ScrollView>
|
|
423
|
-
</View>
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
_indicateAdditionalRequests = (): void => {
|
|
428
|
-
if (this._requestsListView) {
|
|
429
|
-
const distanceFromEndThreshold = LISTVIEW_CELL_HEIGHT * 2;
|
|
430
|
-
const {offset, visibleLength, contentLength} =
|
|
431
|
-
this._requestsListViewScrollMetrics;
|
|
432
|
-
const distanceFromEnd = contentLength - visibleLength - offset;
|
|
433
|
-
const isCloseToEnd = distanceFromEnd <= distanceFromEndThreshold;
|
|
434
|
-
if (isCloseToEnd) {
|
|
435
|
-
this._requestsListView.scrollToEnd();
|
|
436
|
-
} else {
|
|
437
|
-
this._requestsListView.flashScrollIndicators();
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
_captureRequestsListView = (listRef: ?FlatList<NetworkRequestInfo>): void => {
|
|
443
|
-
this._requestsListView = listRef;
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
_requestsListViewOnScroll = (e: Object): void => {
|
|
447
|
-
this._requestsListViewScrollMetrics.offset = e.nativeEvent.contentOffset.y;
|
|
448
|
-
this._requestsListViewScrollMetrics.visibleLength =
|
|
449
|
-
e.nativeEvent.layoutMeasurement.height;
|
|
450
|
-
this._requestsListViewScrollMetrics.contentLength =
|
|
451
|
-
e.nativeEvent.contentSize.height;
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
* Popup a scrollView to dynamically show detailed information of
|
|
456
|
-
* the request, when pressing a row in the network flow listView.
|
|
457
|
-
*/
|
|
458
|
-
_pressRow(rowId: number): void {
|
|
459
|
-
this.setState({detailRowId: rowId}, this._scrollDetailToTop);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
_scrollDetailToTop = (): void => {
|
|
463
|
-
if (this._detailScrollView) {
|
|
464
|
-
this._detailScrollView.scrollTo({
|
|
465
|
-
y: 0,
|
|
466
|
-
animated: false,
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
_closeButtonClicked = () => {
|
|
472
|
-
this.setState({detailRowId: null});
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
_getRequestIndexByXHRID(index: number): number {
|
|
476
|
-
if (index === undefined) {
|
|
477
|
-
return -1;
|
|
478
|
-
}
|
|
479
|
-
const xhrIndex = this._xhrIdMap[index];
|
|
480
|
-
if (xhrIndex === undefined) {
|
|
481
|
-
return -1;
|
|
482
|
-
} else {
|
|
483
|
-
return xhrIndex;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
render(): React.Node {
|
|
488
|
-
const {requests, detailRowId} = this.state;
|
|
489
|
-
|
|
490
|
-
return (
|
|
491
|
-
<View style={styles.container}>
|
|
492
|
-
{detailRowId != null && this._renderItemDetail(detailRowId)}
|
|
493
|
-
<View style={styles.listViewTitle}>
|
|
494
|
-
{requests.length > 0 && (
|
|
495
|
-
<View style={styles.tableRow}>
|
|
496
|
-
<View style={styles.urlTitleCellView}>
|
|
497
|
-
<Text style={styles.cellText} numberOfLines={1}>
|
|
498
|
-
URL
|
|
499
|
-
</Text>
|
|
500
|
-
</View>
|
|
501
|
-
<View style={styles.methodTitleCellView}>
|
|
502
|
-
<Text style={styles.cellText} numberOfLines={1}>
|
|
503
|
-
Type
|
|
504
|
-
</Text>
|
|
505
|
-
</View>
|
|
506
|
-
</View>
|
|
507
|
-
)}
|
|
508
|
-
</View>
|
|
509
|
-
|
|
510
|
-
<FlatList
|
|
511
|
-
ref={this._captureRequestsListView}
|
|
512
|
-
onScroll={this._requestsListViewOnScroll}
|
|
513
|
-
style={styles.listView}
|
|
514
|
-
data={requests}
|
|
515
|
-
renderItem={this._renderItem}
|
|
516
|
-
keyExtractor={keyExtractor}
|
|
517
|
-
extraData={this.state}
|
|
518
|
-
/>
|
|
519
|
-
</View>
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
const styles = StyleSheet.create({
|
|
525
|
-
container: {
|
|
526
|
-
paddingTop: 10,
|
|
527
|
-
paddingBottom: 10,
|
|
528
|
-
paddingLeft: 5,
|
|
529
|
-
paddingRight: 5,
|
|
530
|
-
},
|
|
531
|
-
listViewTitle: {
|
|
532
|
-
height: 20,
|
|
533
|
-
},
|
|
534
|
-
listView: {
|
|
535
|
-
flex: 1,
|
|
536
|
-
height: 60,
|
|
537
|
-
},
|
|
538
|
-
tableRow: {
|
|
539
|
-
flexDirection: 'row',
|
|
540
|
-
flex: 1,
|
|
541
|
-
height: LISTVIEW_CELL_HEIGHT,
|
|
542
|
-
},
|
|
543
|
-
tableRowEven: {
|
|
544
|
-
backgroundColor: '#555',
|
|
545
|
-
},
|
|
546
|
-
tableRowOdd: {
|
|
547
|
-
backgroundColor: '#000',
|
|
548
|
-
},
|
|
549
|
-
tableRowPressed: {
|
|
550
|
-
backgroundColor: '#3B5998',
|
|
551
|
-
},
|
|
552
|
-
cellText: {
|
|
553
|
-
color: 'white',
|
|
554
|
-
fontSize: 12,
|
|
555
|
-
},
|
|
556
|
-
methodTitleCellView: {
|
|
557
|
-
height: 18,
|
|
558
|
-
borderColor: '#DCD7CD',
|
|
559
|
-
borderTopWidth: 1,
|
|
560
|
-
borderBottomWidth: 1,
|
|
561
|
-
borderRightWidth: 1,
|
|
562
|
-
alignItems: 'center',
|
|
563
|
-
justifyContent: 'center',
|
|
564
|
-
backgroundColor: '#444',
|
|
565
|
-
flex: 1,
|
|
566
|
-
},
|
|
567
|
-
urlTitleCellView: {
|
|
568
|
-
height: 18,
|
|
569
|
-
borderColor: '#DCD7CD',
|
|
570
|
-
borderTopWidth: 1,
|
|
571
|
-
borderBottomWidth: 1,
|
|
572
|
-
borderLeftWidth: 1,
|
|
573
|
-
borderRightWidth: 1,
|
|
574
|
-
justifyContent: 'center',
|
|
575
|
-
backgroundColor: '#444',
|
|
576
|
-
flex: 5,
|
|
577
|
-
paddingLeft: 3,
|
|
578
|
-
},
|
|
579
|
-
methodCellView: {
|
|
580
|
-
height: 15,
|
|
581
|
-
borderColor: '#DCD7CD',
|
|
582
|
-
borderRightWidth: 1,
|
|
583
|
-
alignItems: 'center',
|
|
584
|
-
justifyContent: 'center',
|
|
585
|
-
flex: 1,
|
|
586
|
-
},
|
|
587
|
-
urlCellView: {
|
|
588
|
-
height: 15,
|
|
589
|
-
borderColor: '#DCD7CD',
|
|
590
|
-
borderLeftWidth: 1,
|
|
591
|
-
borderRightWidth: 1,
|
|
592
|
-
justifyContent: 'center',
|
|
593
|
-
flex: 5,
|
|
594
|
-
paddingLeft: 3,
|
|
595
|
-
},
|
|
596
|
-
detailScrollView: {
|
|
597
|
-
flex: 1,
|
|
598
|
-
height: 180,
|
|
599
|
-
marginTop: 5,
|
|
600
|
-
marginBottom: 5,
|
|
601
|
-
},
|
|
602
|
-
detailKeyCellView: {
|
|
603
|
-
flex: 1.3,
|
|
604
|
-
},
|
|
605
|
-
detailValueCellView: {
|
|
606
|
-
flex: 2,
|
|
607
|
-
},
|
|
608
|
-
detailViewRow: {
|
|
609
|
-
flexDirection: 'row',
|
|
610
|
-
paddingHorizontal: 3,
|
|
611
|
-
},
|
|
612
|
-
detailViewText: {
|
|
613
|
-
color: 'white',
|
|
614
|
-
fontSize: 11,
|
|
615
|
-
},
|
|
616
|
-
closeButtonText: {
|
|
617
|
-
color: 'white',
|
|
618
|
-
fontSize: 10,
|
|
619
|
-
},
|
|
620
|
-
closeButton: {
|
|
621
|
-
marginTop: 5,
|
|
622
|
-
backgroundColor: '#888',
|
|
623
|
-
justifyContent: 'center',
|
|
624
|
-
alignItems: 'center',
|
|
625
|
-
},
|
|
626
|
-
});
|
|
627
|
-
|
|
628
|
-
export default NetworkOverlay;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
* @flow
|
|
8
|
-
* @format
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
import * as React from 'react';
|
|
14
|
-
|
|
15
|
-
const View = require('../../../../../Libraries/Components/View/View').default;
|
|
16
|
-
const StyleSheet =
|
|
17
|
-
require('../../../../../Libraries/StyleSheet/StyleSheet').default;
|
|
18
|
-
const Text = require('../../../../../Libraries/Text/Text').default;
|
|
19
|
-
const PerformanceLogger =
|
|
20
|
-
require('../../../../../Libraries/Utilities/GlobalPerformanceLogger').default;
|
|
21
|
-
|
|
22
|
-
class PerformanceOverlay extends React.Component<{...}> {
|
|
23
|
-
render(): React.Node {
|
|
24
|
-
const perfLogs = PerformanceLogger.getTimespans();
|
|
25
|
-
const items = [];
|
|
26
|
-
|
|
27
|
-
for (const key in perfLogs) {
|
|
28
|
-
if (perfLogs[key]?.totalTime) {
|
|
29
|
-
const unit = key === 'BundleSize' ? 'b' : 'ms';
|
|
30
|
-
items.push(
|
|
31
|
-
<View style={styles.row} key={key}>
|
|
32
|
-
<Text style={[styles.text, styles.label]}>{key}</Text>
|
|
33
|
-
<Text style={[styles.text, styles.totalTime]}>
|
|
34
|
-
{perfLogs[key].totalTime + unit}
|
|
35
|
-
</Text>
|
|
36
|
-
</View>,
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return <View style={styles.container}>{items}</View>;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const styles = StyleSheet.create({
|
|
46
|
-
container: {
|
|
47
|
-
height: 100,
|
|
48
|
-
paddingTop: 10,
|
|
49
|
-
},
|
|
50
|
-
label: {
|
|
51
|
-
flex: 1,
|
|
52
|
-
},
|
|
53
|
-
row: {
|
|
54
|
-
flexDirection: 'row',
|
|
55
|
-
paddingHorizontal: 10,
|
|
56
|
-
},
|
|
57
|
-
text: {
|
|
58
|
-
color: 'white',
|
|
59
|
-
fontSize: 12,
|
|
60
|
-
},
|
|
61
|
-
totalTime: {
|
|
62
|
-
paddingRight: 100,
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
export default PerformanceOverlay;
|