react-native 0.83.2 → 0.83.4
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/Core/setUpReactDevTools.js +23 -6
- package/Libraries/Network/RCTHTTPRequestHandler.h +9 -0
- package/Libraries/Network/RCTHTTPRequestHandler.mm +15 -1
- package/Libraries/WebSocket/RCTReconnectingWebSocket.m +4 -1
- package/React/Base/RCTBundleURLProvider.mm +5 -3
- package/React/Base/RCTDevSupportHttpHeaders.h +24 -0
- package/React/Base/RCTDevSupportHttpHeaders.m +65 -0
- package/React/Base/RCTMultipartDataTask.h +9 -0
- package/React/Base/RCTMultipartDataTask.m +16 -1
- package/React/Base/RCTVersion.m +1 -1
- package/React/CoreModules/RCTWebSocketModule.h +6 -0
- package/React/CoreModules/RCTWebSocketModule.mm +14 -1
- package/React/DevSupport/RCTInspectorDevServerHelper.mm +33 -22
- package/React/DevSupport/RCTInspectorNetworkHelper.mm +2 -0
- package/React/Inspector/RCTCxxInspectorWebSocketAdapter.mm +5 -1
- package/ReactAndroid/api/ReactAndroid.api +1 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.kt +2 -8
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.kt +17 -13
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/PackagerStatusCheck.kt +10 -19
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxContentView.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/DevSupportHttpClient.kt +49 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/InspectorNetworkHelper.kt +1 -12
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt +3 -4
- package/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/JSPackagerClient.kt +2 -1
- package/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.kt +2 -8
- package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
- package/package.json +8 -8
- package/scripts/replace-rncore-version.js +62 -8
- package/settings.gradle.kts +21 -1
|
@@ -146,17 +146,34 @@ if (__DEV__) {
|
|
|
146
146
|
? guessHostFromDevServerUrl(devServer.url)
|
|
147
147
|
: 'localhost';
|
|
148
148
|
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
|
|
149
|
+
// Derive scheme and port from the dev server URL when possible,
|
|
150
|
+
// falling back to ws://host:8097 for local development.
|
|
151
|
+
let wsScheme = 'ws';
|
|
152
|
+
let port = 8097;
|
|
153
|
+
|
|
154
|
+
if (
|
|
152
155
|
// $FlowFixMe[prop-missing]
|
|
153
156
|
// $FlowFixMe[incompatible-use]
|
|
154
157
|
window.__REACT_DEVTOOLS_PORT__ != null
|
|
155
|
-
|
|
156
|
-
|
|
158
|
+
) {
|
|
159
|
+
// $FlowFixMe[prop-missing]
|
|
160
|
+
port = window.__REACT_DEVTOOLS_PORT__;
|
|
161
|
+
} else if (devServer.bundleLoadedFromServer) {
|
|
162
|
+
try {
|
|
163
|
+
const devUrl = new URL(devServer.url);
|
|
164
|
+
if (devUrl.protocol === 'https:') {
|
|
165
|
+
wsScheme = 'wss';
|
|
166
|
+
}
|
|
167
|
+
if (devUrl.port) {
|
|
168
|
+
port = parseInt(devUrl.port, 10);
|
|
169
|
+
} else if (devUrl.protocol === 'https:') {
|
|
170
|
+
port = 443;
|
|
171
|
+
}
|
|
172
|
+
} catch (e) {}
|
|
173
|
+
}
|
|
157
174
|
|
|
158
175
|
const WebSocket = require('../WebSocket/WebSocket').default;
|
|
159
|
-
ws = new WebSocket('
|
|
176
|
+
ws = new WebSocket(wsScheme + '://' + host + ':' + port);
|
|
160
177
|
ws.addEventListener('close', event => {
|
|
161
178
|
isWebSocketOpen = false;
|
|
162
179
|
});
|
|
@@ -14,6 +14,15 @@ typedef NSURLSessionConfiguration * (^NSURLSessionConfigurationProvider)(void);
|
|
|
14
14
|
* app.
|
|
15
15
|
*/
|
|
16
16
|
RCT_EXTERN void RCTSetCustomNSURLSessionConfigurationProvider(NSURLSessionConfigurationProvider /*provider*/);
|
|
17
|
+
|
|
18
|
+
typedef NSURLRequest *_Nullable (^RCTHTTPRequestInterceptor)(NSURLRequest *request);
|
|
19
|
+
/**
|
|
20
|
+
* The block provided via this function can inspect/modify HTTP requests before
|
|
21
|
+
* they are sent. Return a modified request to override, or nil to use the
|
|
22
|
+
* original request unchanged.
|
|
23
|
+
*/
|
|
24
|
+
RCT_EXTERN void RCTSetCustomHTTPRequestInterceptor(RCTHTTPRequestInterceptor /*interceptor*/);
|
|
25
|
+
|
|
17
26
|
/**
|
|
18
27
|
* This is the default RCTURLRequestHandler implementation for HTTP requests.
|
|
19
28
|
*/
|
|
@@ -25,6 +25,13 @@ void RCTSetCustomNSURLSessionConfigurationProvider(NSURLSessionConfigurationProv
|
|
|
25
25
|
urlSessionConfigurationProvider = provider;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
static RCTHTTPRequestInterceptor httpRequestInterceptor;
|
|
29
|
+
|
|
30
|
+
void RCTSetCustomHTTPRequestInterceptor(RCTHTTPRequestInterceptor interceptor)
|
|
31
|
+
{
|
|
32
|
+
httpRequestInterceptor = interceptor;
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
@implementation RCTHTTPRequestHandler {
|
|
29
36
|
NSMapTable *_delegates;
|
|
30
37
|
NSURLSession *_session;
|
|
@@ -99,7 +106,14 @@ RCT_EXPORT_MODULE()
|
|
|
99
106
|
valueOptions:NSPointerFunctionsStrongMemory
|
|
100
107
|
capacity:0];
|
|
101
108
|
}
|
|
102
|
-
|
|
109
|
+
NSURLRequest *finalRequest = request;
|
|
110
|
+
if (httpRequestInterceptor != nullptr) {
|
|
111
|
+
NSURLRequest *intercepted = httpRequestInterceptor(request);
|
|
112
|
+
if (intercepted != nil) {
|
|
113
|
+
finalRequest = intercepted;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
NSURLSessionDataTask *task = [_session dataTaskWithRequest:finalRequest];
|
|
103
117
|
[_delegates setObject:delegate forKey:task];
|
|
104
118
|
[task resume];
|
|
105
119
|
return task;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
#import <React/RCTConvert.h>
|
|
11
11
|
#import <React/RCTDefines.h>
|
|
12
|
+
#import <React/RCTDevSupportHttpHeaders.h>
|
|
12
13
|
|
|
13
14
|
#import <SocketRocket/SRWebSocket.h>
|
|
14
15
|
|
|
@@ -46,7 +47,9 @@
|
|
|
46
47
|
{
|
|
47
48
|
[self stop];
|
|
48
49
|
_stopped = NO;
|
|
49
|
-
|
|
50
|
+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_url];
|
|
51
|
+
[[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
|
|
52
|
+
_socket = [[SRWebSocket alloc] initWithURLRequest:request];
|
|
50
53
|
_socket.delegate = self;
|
|
51
54
|
[_socket setDelegateDispatchQueue:_delegateDispatchQueue];
|
|
52
55
|
[_socket open];
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#import "RCTConstants.h"
|
|
11
11
|
#import "RCTConvert.h"
|
|
12
12
|
#import "RCTDefines.h"
|
|
13
|
+
#import "RCTDevSupportHttpHeaders.h"
|
|
13
14
|
#import "RCTLog.h"
|
|
14
15
|
|
|
15
16
|
#import <jsinspector-modern/InspectorFlags.h>
|
|
@@ -93,9 +94,10 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
|
|
|
93
94
|
NSURL *url = [serverRootWithHostPort(hostPort, scheme) URLByAppendingPathComponent:@"status"];
|
|
94
95
|
|
|
95
96
|
NSURLSession *session = [NSURLSession sharedSession];
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
|
|
98
|
+
cachePolicy:NSURLRequestUseProtocolCachePolicy
|
|
99
|
+
timeoutInterval:10];
|
|
100
|
+
[[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
|
|
99
101
|
__block NSURLResponse *response;
|
|
100
102
|
__block NSData *data;
|
|
101
103
|
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Thread-safe singleton that holds custom HTTP headers to be applied
|
|
12
|
+
* to all devsupport network requests (bundle fetches, packager status
|
|
13
|
+
* checks, inspector and HMR WebSocket connections).
|
|
14
|
+
*/
|
|
15
|
+
@interface RCTDevSupportHttpHeaders : NSObject
|
|
16
|
+
|
|
17
|
+
+ (instancetype)sharedInstance;
|
|
18
|
+
|
|
19
|
+
- (void)addRequestHeader:(NSString *)name value:(NSString *)value;
|
|
20
|
+
- (void)removeRequestHeader:(NSString *)name;
|
|
21
|
+
- (NSDictionary<NSString *, NSString *> *)allHeaders;
|
|
22
|
+
- (void)applyHeadersToRequest:(NSMutableURLRequest *)request;
|
|
23
|
+
|
|
24
|
+
@end
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
|
|
8
|
+
#import "RCTDevSupportHttpHeaders.h"
|
|
9
|
+
|
|
10
|
+
@implementation RCTDevSupportHttpHeaders {
|
|
11
|
+
NSMutableDictionary<NSString *, NSString *> *_headers;
|
|
12
|
+
dispatch_queue_t _queue;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
+ (instancetype)sharedInstance
|
|
16
|
+
{
|
|
17
|
+
static RCTDevSupportHttpHeaders *sharedInstance;
|
|
18
|
+
static dispatch_once_t onceToken;
|
|
19
|
+
dispatch_once(&onceToken, ^{
|
|
20
|
+
sharedInstance = [[RCTDevSupportHttpHeaders alloc] init];
|
|
21
|
+
});
|
|
22
|
+
return sharedInstance;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
- (instancetype)init
|
|
26
|
+
{
|
|
27
|
+
if (self = [super init]) {
|
|
28
|
+
_headers = [NSMutableDictionary new];
|
|
29
|
+
_queue = dispatch_queue_create("com.facebook.react.RCTDevSupportHttpHeaders", DISPATCH_QUEUE_SERIAL);
|
|
30
|
+
}
|
|
31
|
+
return self;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
- (void)addRequestHeader:(NSString *)name value:(NSString *)value
|
|
35
|
+
{
|
|
36
|
+
dispatch_sync(_queue, ^{
|
|
37
|
+
self->_headers[name] = value;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
- (void)removeRequestHeader:(NSString *)name
|
|
42
|
+
{
|
|
43
|
+
dispatch_sync(_queue, ^{
|
|
44
|
+
[self->_headers removeObjectForKey:name];
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
- (NSDictionary<NSString *, NSString *> *)allHeaders
|
|
49
|
+
{
|
|
50
|
+
__block NSDictionary<NSString *, NSString *> *snapshot;
|
|
51
|
+
dispatch_sync(_queue, ^{
|
|
52
|
+
snapshot = [self->_headers copy];
|
|
53
|
+
});
|
|
54
|
+
return snapshot;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- (void)applyHeadersToRequest:(NSMutableURLRequest *)request
|
|
58
|
+
{
|
|
59
|
+
NSDictionary<NSString *, NSString *> *headers = [self allHeaders];
|
|
60
|
+
[headers enumerateKeysAndObjectsUsingBlock:^(NSString *headerName, NSString *headerValue, BOOL *stop) {
|
|
61
|
+
[request setValue:headerValue forHTTPHeaderField:headerName];
|
|
62
|
+
}];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@end
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#import <Foundation/Foundation.h>
|
|
9
9
|
|
|
10
|
+
#import <React/RCTDefines.h>
|
|
10
11
|
#import <React/RCTMultipartStreamReader.h>
|
|
11
12
|
|
|
12
13
|
typedef void (^RCTMultipartDataTaskCallback)(
|
|
@@ -16,6 +17,14 @@ typedef void (^RCTMultipartDataTaskCallback)(
|
|
|
16
17
|
NSError *error,
|
|
17
18
|
BOOL done);
|
|
18
19
|
|
|
20
|
+
typedef NSURLRequest * _Nullable (^RCTMultipartDataTaskRequestInterceptor)(NSURLRequest *request);
|
|
21
|
+
/**
|
|
22
|
+
* The block provided via this function can inspect/modify multipart data task
|
|
23
|
+
* requests before they are sent. Return a modified request to override, or nil
|
|
24
|
+
* to use the original request unchanged.
|
|
25
|
+
*/
|
|
26
|
+
RCT_EXTERN void RCTSetCustomMultipartDataTaskRequestInterceptor(RCTMultipartDataTaskRequestInterceptor /*interceptor*/);
|
|
27
|
+
|
|
19
28
|
@interface RCTMultipartDataTask : NSObject
|
|
20
29
|
|
|
21
30
|
- (instancetype)initWithURL:(NSURL *)url
|
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
#import "RCTMultipartDataTask.h"
|
|
9
9
|
|
|
10
|
+
static RCTMultipartDataTaskRequestInterceptor multipartRequestInterceptor;
|
|
11
|
+
|
|
12
|
+
void RCTSetCustomMultipartDataTaskRequestInterceptor(RCTMultipartDataTaskRequestInterceptor interceptor)
|
|
13
|
+
{
|
|
14
|
+
multipartRequestInterceptor = interceptor;
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
@interface RCTMultipartDataTask () <NSURLSessionDataDelegate, NSURLSessionDataDelegate>
|
|
11
18
|
|
|
12
19
|
@end
|
|
@@ -40,7 +47,15 @@
|
|
|
40
47
|
delegateQueue:nil];
|
|
41
48
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_url];
|
|
42
49
|
[request addValue:@"multipart/mixed" forHTTPHeaderField:@"Accept"];
|
|
43
|
-
|
|
50
|
+
NSURLRequest *finalRequest = request;
|
|
51
|
+
if (multipartRequestInterceptor != nil) {
|
|
52
|
+
NSURLRequest *intercepted = multipartRequestInterceptor(request);
|
|
53
|
+
if (intercepted != nil) {
|
|
54
|
+
finalRequest = intercepted;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
NSLog(@"[RCTMultipartDataTask] %@ %@", finalRequest.HTTPMethod ?: @"GET", finalRequest.URL.absoluteString);
|
|
58
|
+
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:finalRequest];
|
|
44
59
|
[dataTask resume];
|
|
45
60
|
[session finishTasksAndInvalidate];
|
|
46
61
|
}
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -18,6 +18,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
18
18
|
|
|
19
19
|
@end
|
|
20
20
|
|
|
21
|
+
@class SRWebSocket;
|
|
22
|
+
|
|
23
|
+
typedef SRWebSocket * (^SRWebSocketProvider)(NSURLRequest *request);
|
|
24
|
+
|
|
25
|
+
RCT_EXTERN void RCTSetCustomSRWebSocketProvider(SRWebSocketProvider provider);
|
|
26
|
+
|
|
21
27
|
@interface RCTWebSocketModule : RCTEventEmitter
|
|
22
28
|
|
|
23
29
|
// Register a custom handler for a specific websocket. The handler will be strongly held by the WebSocketModule.
|
|
@@ -34,6 +34,13 @@
|
|
|
34
34
|
|
|
35
35
|
@end
|
|
36
36
|
|
|
37
|
+
static SRWebSocketProvider srWebSocketProvider;
|
|
38
|
+
|
|
39
|
+
void RCTSetCustomSRWebSocketProvider(SRWebSocketProvider provider)
|
|
40
|
+
{
|
|
41
|
+
srWebSocketProvider = provider;
|
|
42
|
+
}
|
|
43
|
+
|
|
37
44
|
@implementation RCTWebSocketModule {
|
|
38
45
|
NSMutableDictionary<NSNumber *, SRWebSocket *> *_sockets;
|
|
39
46
|
NSMutableDictionary<NSNumber *, id<RCTWebSocketContentHandler>> *_contentHandlers;
|
|
@@ -88,7 +95,13 @@ RCT_EXPORT_METHOD(
|
|
|
88
95
|
}];
|
|
89
96
|
}
|
|
90
97
|
|
|
91
|
-
SRWebSocket *webSocket
|
|
98
|
+
SRWebSocket *webSocket;
|
|
99
|
+
if (srWebSocketProvider != nullptr) {
|
|
100
|
+
webSocket = srWebSocketProvider(request);
|
|
101
|
+
}
|
|
102
|
+
if (webSocket == nil) {
|
|
103
|
+
webSocket = [[SRWebSocket alloc] initWithURLRequest:request protocols:protocols];
|
|
104
|
+
}
|
|
92
105
|
[webSocket setDelegateDispatchQueue:[self methodQueue]];
|
|
93
106
|
webSocket.delegate = self;
|
|
94
107
|
webSocket.reactTag = @(socketID);
|
|
@@ -14,33 +14,39 @@
|
|
|
14
14
|
|
|
15
15
|
#import <React/RCTCxxInspectorPackagerConnection.h>
|
|
16
16
|
#import <React/RCTDefines.h>
|
|
17
|
+
#import <React/RCTDevSupportHttpHeaders.h>
|
|
17
18
|
|
|
18
19
|
#import <CommonCrypto/CommonCrypto.h>
|
|
19
20
|
#import <jsinspector-modern/InspectorFlags.h>
|
|
20
21
|
|
|
21
22
|
static NSString *const kDebuggerMsgDisable = @"{ \"id\":1,\"method\":\"Debugger.disable\" }";
|
|
23
|
+
static const int kDefaultMetroPort = 8081;
|
|
22
24
|
|
|
23
25
|
static NSString *getServerHost(NSURL *bundleURL)
|
|
24
26
|
{
|
|
25
|
-
NSNumber *port = @8081;
|
|
26
|
-
NSString *portStr = [[[NSProcessInfo processInfo] environment] objectForKey:@"RCT_METRO_PORT"];
|
|
27
|
-
if ((portStr != nullptr) && [portStr length] > 0) {
|
|
28
|
-
port = [NSNumber numberWithInt:[portStr intValue]];
|
|
29
|
-
}
|
|
30
|
-
if ([bundleURL port] != nullptr) {
|
|
31
|
-
port = [bundleURL port];
|
|
32
|
-
}
|
|
33
27
|
NSString *host = [bundleURL host];
|
|
34
28
|
if (host == nullptr) {
|
|
35
29
|
host = @"localhost";
|
|
36
30
|
}
|
|
37
31
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
// Use explicit port from URL if available
|
|
33
|
+
if ([bundleURL port] != nullptr) {
|
|
34
|
+
return [NSString stringWithFormat:@"%@:%@", host, [bundleURL port]];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Check environment variable
|
|
38
|
+
NSString *portStr = [[[NSProcessInfo processInfo] environment] objectForKey:@"RCT_METRO_PORT"];
|
|
39
|
+
if ((portStr != nullptr) && [portStr length] > 0) {
|
|
40
|
+
return [NSString stringWithFormat:@"%@:%@", host, portStr];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// For https, omit port — the scheme implies 443
|
|
44
|
+
if ([[bundleURL scheme] isEqualToString:@"https"]) {
|
|
45
|
+
return host;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Default to 8081 for local development (Metro's default port)
|
|
49
|
+
return [NSString stringWithFormat:@"%@:%d", host, kDefaultMetroPort];
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
static NSString *getSHA256(NSString *string)
|
|
@@ -111,13 +117,15 @@ static NSURL *getInspectorDeviceUrl(NSURL *bundleURL)
|
|
|
111
117
|
NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
|
|
112
118
|
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
|
|
113
119
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
NSString *scheme = [bundleURL scheme] != nullptr ? [bundleURL scheme] : @"http";
|
|
121
|
+
return
|
|
122
|
+
[NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/inspector/device?name=%@&app=%@&device=%@&profiling=%@",
|
|
123
|
+
scheme,
|
|
124
|
+
getServerHost(bundleURL),
|
|
125
|
+
escapedDeviceName,
|
|
126
|
+
escapedAppName,
|
|
127
|
+
escapedInspectorDeviceId,
|
|
128
|
+
isProfilingBuild ? @"true" : @"false"]];
|
|
121
129
|
}
|
|
122
130
|
|
|
123
131
|
@implementation RCTInspectorDevServerHelper
|
|
@@ -149,11 +157,14 @@ static void sendEventToAllConnections(NSString *event)
|
|
|
149
157
|
NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
|
|
150
158
|
stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
|
|
151
159
|
|
|
152
|
-
|
|
160
|
+
NSString *scheme = [bundleURL scheme] != nullptr ? [bundleURL scheme] : @"http";
|
|
161
|
+
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/open-debugger?device=%@",
|
|
162
|
+
scheme,
|
|
153
163
|
getServerHost(bundleURL),
|
|
154
164
|
escapedInspectorDeviceId]];
|
|
155
165
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
|
156
166
|
[request setHTTPMethod:@"POST"];
|
|
167
|
+
[[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
|
|
157
168
|
|
|
158
169
|
[[[NSURLSession sharedSession]
|
|
159
170
|
dataTaskWithRequest:request
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
#import "RCTInspectorNetworkHelper.h"
|
|
9
|
+
#import <React/RCTDevSupportHttpHeaders.h>
|
|
9
10
|
#import <React/RCTLog.h>
|
|
10
11
|
|
|
11
12
|
using ListenerBlock = void (^)(RCTInspectorNetworkListener *);
|
|
@@ -47,6 +48,7 @@ using ListenerBlock = void (^)(RCTInspectorNetworkListener *);
|
|
|
47
48
|
|
|
48
49
|
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
|
|
49
50
|
[urlRequest setHTTPMethod:@"GET"];
|
|
51
|
+
[[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:urlRequest];
|
|
50
52
|
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:urlRequest];
|
|
51
53
|
__weak NSURLSessionDataTask *weakDataTask = dataTask;
|
|
52
54
|
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
#if RCT_DEV || RCT_REMOTE_PROFILE
|
|
11
11
|
|
|
12
|
+
#import <React/RCTDevSupportHttpHeaders.h>
|
|
12
13
|
#import <React/RCTInspector.h>
|
|
13
14
|
#import <React/RCTInspectorPackagerConnection.h>
|
|
14
15
|
#import <React/RCTLog.h>
|
|
@@ -36,7 +37,10 @@ NSString *NSStringFromUTF8StringView(std::string_view view)
|
|
|
36
37
|
{
|
|
37
38
|
if ((self = [super init]) != nullptr) {
|
|
38
39
|
_delegate = delegate;
|
|
39
|
-
|
|
40
|
+
NSURL *requestURL = [NSURL URLWithString:NSStringFromUTF8StringView(url)];
|
|
41
|
+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL];
|
|
42
|
+
[[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
|
|
43
|
+
_webSocket = [[SRWebSocket alloc] initWithURLRequest:request];
|
|
40
44
|
_webSocket.delegate = self;
|
|
41
45
|
[_webSocket open];
|
|
42
46
|
}
|
|
@@ -2129,6 +2129,7 @@ public final class com/facebook/react/devsupport/StackTraceHelper$StackFrameImpl
|
|
|
2129
2129
|
public fun toJSON ()Lorg/json/JSONObject;
|
|
2130
2130
|
}
|
|
2131
2131
|
|
|
2132
|
+
|
|
2132
2133
|
public abstract interface class com/facebook/react/devsupport/interfaces/BundleLoadCallback {
|
|
2133
2134
|
public fun onError (Ljava/lang/Exception;)V
|
|
2134
2135
|
public abstract fun onSuccess ()V
|
package/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.kt
CHANGED
|
@@ -12,10 +12,9 @@ import android.os.Looper
|
|
|
12
12
|
import com.facebook.jni.HybridData
|
|
13
13
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
14
14
|
import com.facebook.proguard.annotations.DoNotStripAny
|
|
15
|
+
import com.facebook.react.devsupport.inspector.DevSupportHttpClient
|
|
15
16
|
import com.facebook.soloader.SoLoader
|
|
16
17
|
import java.io.Closeable
|
|
17
|
-
import java.util.concurrent.TimeUnit
|
|
18
|
-
import okhttp3.OkHttpClient
|
|
19
18
|
import okhttp3.Request
|
|
20
19
|
import okhttp3.Response
|
|
21
20
|
import okhttp3.WebSocket
|
|
@@ -78,12 +77,7 @@ internal class CxxInspectorPackagerConnection(
|
|
|
78
77
|
|
|
79
78
|
/** Java implementation of the C++ InspectorPackagerConnectionDelegate interface. */
|
|
80
79
|
private class DelegateImpl {
|
|
81
|
-
private val httpClient =
|
|
82
|
-
OkHttpClient.Builder()
|
|
83
|
-
.connectTimeout(10, TimeUnit.SECONDS)
|
|
84
|
-
.writeTimeout(10, TimeUnit.SECONDS)
|
|
85
|
-
.readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read
|
|
86
|
-
.build()
|
|
80
|
+
private val httpClient = DevSupportHttpClient.websocketClient
|
|
87
81
|
|
|
88
82
|
private val handler = Handler(Looper.getMainLooper())
|
|
89
83
|
|
|
@@ -21,6 +21,7 @@ import com.facebook.react.bridge.ReactContext
|
|
|
21
21
|
import com.facebook.react.common.ReactConstants
|
|
22
22
|
import com.facebook.react.devsupport.InspectorFlags.getFuseboxEnabled
|
|
23
23
|
import com.facebook.react.devsupport.InspectorFlags.getIsProfilingBuild
|
|
24
|
+
import com.facebook.react.devsupport.inspector.DevSupportHttpClient
|
|
24
25
|
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener
|
|
25
26
|
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback
|
|
26
27
|
import com.facebook.react.modules.debug.interfaces.DeveloperSettings
|
|
@@ -39,7 +40,6 @@ import java.io.UnsupportedEncodingException
|
|
|
39
40
|
import java.security.MessageDigest
|
|
40
41
|
import java.security.NoSuchAlgorithmException
|
|
41
42
|
import java.util.Locale
|
|
42
|
-
import java.util.concurrent.TimeUnit
|
|
43
43
|
import okhttp3.Call
|
|
44
44
|
import okhttp3.Callback
|
|
45
45
|
import okhttp3.OkHttpClient
|
|
@@ -79,19 +79,15 @@ public open class DevServerHelper(
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
public val websocketProxyURL: String
|
|
82
|
-
get() =
|
|
82
|
+
get() =
|
|
83
|
+
"${DevSupportHttpClient.wsScheme(packagerConnectionSettings.debugServerHost)}://${packagerConnectionSettings.debugServerHost}/debugger-proxy?role=client"
|
|
83
84
|
|
|
84
85
|
private enum class BundleType(val typeID: String) {
|
|
85
86
|
BUNDLE("bundle"),
|
|
86
87
|
MAP("map"),
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
private val client: OkHttpClient =
|
|
90
|
-
OkHttpClient.Builder()
|
|
91
|
-
.connectTimeout(HTTP_CONNECT_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS)
|
|
92
|
-
.readTimeout(0, TimeUnit.MILLISECONDS)
|
|
93
|
-
.writeTimeout(0, TimeUnit.MILLISECONDS)
|
|
94
|
-
.build()
|
|
90
|
+
private val client: OkHttpClient = DevSupportHttpClient.httpClient
|
|
95
91
|
private val bundleDownloader: BundleDownloader = BundleDownloader(client)
|
|
96
92
|
private val packagerStatusCheck: PackagerStatusCheck = PackagerStatusCheck(client)
|
|
97
93
|
private val packageName: String = applicationContext.packageName
|
|
@@ -129,7 +125,8 @@ public open class DevServerHelper(
|
|
|
129
125
|
get() =
|
|
130
126
|
String.format(
|
|
131
127
|
Locale.US,
|
|
132
|
-
"
|
|
128
|
+
"%s://%s/inspector/device?name=%s&app=%s&device=%s&profiling=%b",
|
|
129
|
+
DevSupportHttpClient.httpScheme(packagerConnectionSettings.debugServerHost),
|
|
133
130
|
packagerConnectionSettings.debugServerHost,
|
|
134
131
|
Uri.encode(getFriendlyDeviceName()),
|
|
135
132
|
Uri.encode(packageName),
|
|
@@ -292,7 +289,8 @@ public open class DevServerHelper(
|
|
|
292
289
|
}
|
|
293
290
|
return (String.format(
|
|
294
291
|
Locale.US,
|
|
295
|
-
"
|
|
292
|
+
"%s://%s/%s.%s?platform=android&dev=%s&lazy=%s&minify=%s&app=%s&modulesOnly=%s&runModule=%s",
|
|
293
|
+
DevSupportHttpClient.httpScheme(host),
|
|
296
294
|
host,
|
|
297
295
|
mainModuleID,
|
|
298
296
|
type.typeID,
|
|
@@ -367,7 +365,8 @@ public open class DevServerHelper(
|
|
|
367
365
|
requestUrlBuilder.append(
|
|
368
366
|
String.format(
|
|
369
367
|
Locale.US,
|
|
370
|
-
"
|
|
368
|
+
"%s://%s/open-debugger?device=%s",
|
|
369
|
+
DevSupportHttpClient.httpScheme(packagerConnectionSettings.debugServerHost),
|
|
371
370
|
packagerConnectionSettings.debugServerHost,
|
|
372
371
|
Uri.encode(inspectorDeviceId),
|
|
373
372
|
)
|
|
@@ -397,7 +396,6 @@ public open class DevServerHelper(
|
|
|
397
396
|
}
|
|
398
397
|
|
|
399
398
|
private companion object {
|
|
400
|
-
private const val HTTP_CONNECT_TIMEOUT_MS = 5000
|
|
401
399
|
private const val DEBUGGER_MSG_DISABLE = "{ \"id\":1,\"method\":\"Debugger.disable\" }"
|
|
402
400
|
|
|
403
401
|
private fun getSHA256(string: String): String {
|
|
@@ -446,7 +444,13 @@ public open class DevServerHelper(
|
|
|
446
444
|
FLog.w(ReactConstants.TAG, "Resource path should not begin with `/`, removing it.")
|
|
447
445
|
resourcePath = resourcePath.substring(1)
|
|
448
446
|
}
|
|
449
|
-
return String.format(
|
|
447
|
+
return String.format(
|
|
448
|
+
Locale.US,
|
|
449
|
+
"%s://%s/%s",
|
|
450
|
+
DevSupportHttpClient.httpScheme(host),
|
|
451
|
+
host,
|
|
452
|
+
resourcePath,
|
|
453
|
+
)
|
|
450
454
|
}
|
|
451
455
|
}
|
|
452
456
|
}
|
|
@@ -11,10 +11,10 @@ package com.facebook.react.devsupport
|
|
|
11
11
|
|
|
12
12
|
import com.facebook.common.logging.FLog
|
|
13
13
|
import com.facebook.react.common.ReactConstants
|
|
14
|
+
import com.facebook.react.devsupport.inspector.DevSupportHttpClient
|
|
14
15
|
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback
|
|
15
16
|
import java.io.IOException
|
|
16
17
|
import java.util.Locale
|
|
17
|
-
import java.util.concurrent.TimeUnit
|
|
18
18
|
import okhttp3.Call
|
|
19
19
|
import okhttp3.Callback
|
|
20
20
|
import okhttp3.OkHttpClient
|
|
@@ -22,22 +22,9 @@ import okhttp3.Request
|
|
|
22
22
|
import okhttp3.Response
|
|
23
23
|
|
|
24
24
|
/** Use this class to check if the JavaScript packager is running on the provided host. */
|
|
25
|
-
internal class PackagerStatusCheck {
|
|
25
|
+
internal class PackagerStatusCheck(private val client: OkHttpClient) {
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
constructor() {
|
|
30
|
-
client =
|
|
31
|
-
OkHttpClient.Builder()
|
|
32
|
-
.connectTimeout(HTTP_CONNECT_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS)
|
|
33
|
-
.readTimeout(0, TimeUnit.MILLISECONDS)
|
|
34
|
-
.writeTimeout(0, TimeUnit.MILLISECONDS)
|
|
35
|
-
.build()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
constructor(client: OkHttpClient) {
|
|
39
|
-
this.client = client
|
|
40
|
-
}
|
|
27
|
+
constructor() : this(DevSupportHttpClient.httpClient)
|
|
41
28
|
|
|
42
29
|
fun run(host: String, callback: PackagerStatusCallback) {
|
|
43
30
|
val statusURL = createPackagerStatusURL(host)
|
|
@@ -92,10 +79,14 @@ internal class PackagerStatusCheck {
|
|
|
92
79
|
|
|
93
80
|
private companion object {
|
|
94
81
|
private const val PACKAGER_OK_STATUS = "packager-status:running"
|
|
95
|
-
private const val
|
|
96
|
-
private const val PACKAGER_STATUS_URL_TEMPLATE = "http://%s/status"
|
|
82
|
+
private const val PACKAGER_STATUS_URL_TEMPLATE = "%s://%s/status"
|
|
97
83
|
|
|
98
84
|
private fun createPackagerStatusURL(host: String): String =
|
|
99
|
-
String.format(
|
|
85
|
+
String.format(
|
|
86
|
+
Locale.US,
|
|
87
|
+
PACKAGER_STATUS_URL_TEMPLATE,
|
|
88
|
+
DevSupportHttpClient.httpScheme(host),
|
|
89
|
+
host,
|
|
90
|
+
)
|
|
100
91
|
}
|
|
101
92
|
}
|
|
@@ -33,12 +33,12 @@ import android.widget.TextView
|
|
|
33
33
|
import com.facebook.common.logging.FLog
|
|
34
34
|
import com.facebook.react.R
|
|
35
35
|
import com.facebook.react.common.ReactConstants
|
|
36
|
+
import com.facebook.react.devsupport.inspector.DevSupportHttpClient
|
|
36
37
|
import com.facebook.react.devsupport.interfaces.DevSupportManager
|
|
37
38
|
import com.facebook.react.devsupport.interfaces.ErrorType
|
|
38
39
|
import com.facebook.react.devsupport.interfaces.RedBoxHandler
|
|
39
40
|
import com.facebook.react.devsupport.interfaces.StackFrame
|
|
40
41
|
import okhttp3.MediaType
|
|
41
|
-
import okhttp3.OkHttpClient
|
|
42
42
|
import okhttp3.Request
|
|
43
43
|
import okhttp3.RequestBody
|
|
44
44
|
import org.json.JSONObject
|
|
@@ -165,7 +165,7 @@ internal class RedBoxContentView(
|
|
|
165
165
|
.query(null)
|
|
166
166
|
.build()
|
|
167
167
|
.toString()
|
|
168
|
-
val client =
|
|
168
|
+
val client = DevSupportHttpClient.httpClient
|
|
169
169
|
for (frame in stackFrames) {
|
|
170
170
|
val payload = stackFrameToJson(checkNotNull(frame)).toString()
|
|
171
171
|
val body: RequestBody = RequestBody.create(JSON, payload)
|
package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/DevSupportHttpClient.kt
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
|
|
8
|
+
@file:Suppress("DEPRECATION_ERROR") // Conflicting okhttp versions
|
|
9
|
+
|
|
10
|
+
package com.facebook.react.devsupport.inspector
|
|
11
|
+
|
|
12
|
+
import com.facebook.react.modules.network.OkHttpClientProvider
|
|
13
|
+
import java.util.concurrent.TimeUnit
|
|
14
|
+
import okhttp3.OkHttpClient
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Shared [OkHttpClient] instances for devsupport networking. Uses a single connection pool and
|
|
18
|
+
* dispatcher across all dev support HTTP and WebSocket usage.
|
|
19
|
+
*/
|
|
20
|
+
internal object DevSupportHttpClient {
|
|
21
|
+
/** Client for HTTP requests: connect=5s, write=disabled, read=disabled. */
|
|
22
|
+
internal val httpClient: OkHttpClient =
|
|
23
|
+
OkHttpClientProvider.getOkHttpClient()
|
|
24
|
+
.newBuilder()
|
|
25
|
+
.connectTimeout(5, TimeUnit.SECONDS)
|
|
26
|
+
.writeTimeout(0, TimeUnit.MILLISECONDS)
|
|
27
|
+
.readTimeout(0, TimeUnit.MINUTES)
|
|
28
|
+
.build()
|
|
29
|
+
|
|
30
|
+
/** Client for WebSocket connections: connect=10s, write=10s, read=disabled. */
|
|
31
|
+
internal val websocketClient: OkHttpClient =
|
|
32
|
+
httpClient
|
|
33
|
+
.newBuilder()
|
|
34
|
+
.connectTimeout(10, TimeUnit.SECONDS)
|
|
35
|
+
.writeTimeout(10, TimeUnit.SECONDS)
|
|
36
|
+
.build()
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns the appropriate HTTP scheme ("http" or "https") for the given host. Uses "https" when
|
|
40
|
+
* the host specifies port 443 explicitly (e.g. "example.com:443").
|
|
41
|
+
*/
|
|
42
|
+
internal fun httpScheme(host: String): String = if (host.endsWith(":443")) "https" else "http"
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns the appropriate WebSocket scheme ("ws" or "wss") for the given host. Uses "wss" when
|
|
46
|
+
* the host specifies port 443 explicitly (e.g. "example.com:443").
|
|
47
|
+
*/
|
|
48
|
+
internal fun wsScheme(host: String): String = if (host.endsWith(":443")) "wss" else "ws"
|
|
49
|
+
}
|
package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/InspectorNetworkHelper.kt
CHANGED
|
@@ -10,26 +10,15 @@
|
|
|
10
10
|
package com.facebook.react.devsupport.inspector
|
|
11
11
|
|
|
12
12
|
import java.io.IOException
|
|
13
|
-
import java.util.concurrent.TimeUnit
|
|
14
13
|
import okhttp3.Call
|
|
15
14
|
import okhttp3.Callback
|
|
16
|
-
import okhttp3.OkHttpClient
|
|
17
15
|
import okhttp3.Request
|
|
18
16
|
import okhttp3.Response
|
|
19
17
|
|
|
20
18
|
internal object InspectorNetworkHelper {
|
|
21
|
-
private lateinit var client: OkHttpClient
|
|
22
19
|
|
|
23
20
|
@JvmStatic
|
|
24
21
|
fun loadNetworkResource(url: String, listener: InspectorNetworkRequestListener) {
|
|
25
|
-
if (!::client.isInitialized) {
|
|
26
|
-
client =
|
|
27
|
-
OkHttpClient.Builder()
|
|
28
|
-
.connectTimeout(10, TimeUnit.SECONDS)
|
|
29
|
-
.writeTimeout(10, TimeUnit.SECONDS)
|
|
30
|
-
.readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read
|
|
31
|
-
.build()
|
|
32
|
-
}
|
|
33
22
|
|
|
34
23
|
val request =
|
|
35
24
|
try {
|
|
@@ -40,7 +29,7 @@ internal object InspectorNetworkHelper {
|
|
|
40
29
|
}
|
|
41
30
|
|
|
42
31
|
// TODO(T196951523): Assign cancel function to listener
|
|
43
|
-
val call =
|
|
32
|
+
val call = DevSupportHttpClient.httpClient.newCall(request)
|
|
44
33
|
|
|
45
34
|
call.enqueue(
|
|
46
35
|
object : Callback {
|
|
@@ -22,6 +22,7 @@ import com.facebook.react.common.ReactConstants
|
|
|
22
22
|
import com.facebook.react.module.annotations.ReactModule
|
|
23
23
|
import com.facebook.react.modules.network.CustomClientBuilder
|
|
24
24
|
import com.facebook.react.modules.network.ForwardingCookieHandler
|
|
25
|
+
import com.facebook.react.modules.network.OkHttpClientProvider
|
|
25
26
|
import java.io.IOException
|
|
26
27
|
import java.net.URI
|
|
27
28
|
import java.net.URISyntaxException
|
|
@@ -80,7 +81,8 @@ public class WebSocketModule(context: ReactApplicationContext) :
|
|
|
80
81
|
) {
|
|
81
82
|
val id = socketID.toInt()
|
|
82
83
|
val okHttpBuilder =
|
|
83
|
-
|
|
84
|
+
OkHttpClientProvider.getOkHttpClient()
|
|
85
|
+
.newBuilder()
|
|
84
86
|
.connectTimeout(10, TimeUnit.SECONDS)
|
|
85
87
|
.writeTimeout(10, TimeUnit.SECONDS)
|
|
86
88
|
.readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read
|
|
@@ -198,9 +200,6 @@ public class WebSocketModule(context: ReactApplicationContext) :
|
|
|
198
200
|
}
|
|
199
201
|
},
|
|
200
202
|
)
|
|
201
|
-
|
|
202
|
-
// Trigger shutdown of the dispatcher's executor so this process can exit cleanly
|
|
203
|
-
client.dispatcher().executorService().shutdown()
|
|
204
203
|
}
|
|
205
204
|
|
|
206
205
|
override fun close(code: Double, reason: String?, socketID: Double) {
|
package/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/JSPackagerClient.kt
CHANGED
|
@@ -9,6 +9,7 @@ package com.facebook.react.packagerconnection
|
|
|
9
9
|
|
|
10
10
|
import android.net.Uri
|
|
11
11
|
import com.facebook.common.logging.FLog
|
|
12
|
+
import com.facebook.react.devsupport.inspector.DevSupportHttpClient
|
|
12
13
|
import com.facebook.react.modules.systeminfo.AndroidInfoHelpers.getFriendlyDeviceName
|
|
13
14
|
import com.facebook.react.packagerconnection.ReconnectingWebSocket.MessageCallback
|
|
14
15
|
import okio.ByteString
|
|
@@ -28,7 +29,7 @@ public constructor(
|
|
|
28
29
|
init {
|
|
29
30
|
val url =
|
|
30
31
|
Uri.Builder()
|
|
31
|
-
.scheme(
|
|
32
|
+
.scheme(DevSupportHttpClient.wsScheme(settings.debugServerHost))
|
|
32
33
|
.encodedAuthority(settings.debugServerHost)
|
|
33
34
|
.appendPath("message")
|
|
34
35
|
.appendQueryParameter("device", getFriendlyDeviceName())
|
package/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.kt
CHANGED
|
@@ -10,10 +10,9 @@ package com.facebook.react.packagerconnection
|
|
|
10
10
|
import android.os.Handler
|
|
11
11
|
import android.os.Looper
|
|
12
12
|
import com.facebook.common.logging.FLog
|
|
13
|
+
import com.facebook.react.devsupport.inspector.DevSupportHttpClient
|
|
13
14
|
import java.io.IOException
|
|
14
15
|
import java.nio.channels.ClosedChannelException
|
|
15
|
-
import java.util.concurrent.TimeUnit
|
|
16
|
-
import okhttp3.OkHttpClient
|
|
17
16
|
import okhttp3.Request
|
|
18
17
|
import okhttp3.Response
|
|
19
18
|
import okhttp3.WebSocket
|
|
@@ -40,12 +39,7 @@ public class ReconnectingWebSocket(
|
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
private val handler = Handler(Looper.getMainLooper())
|
|
43
|
-
private val okHttpClient
|
|
44
|
-
OkHttpClient.Builder()
|
|
45
|
-
.connectTimeout(10, TimeUnit.SECONDS)
|
|
46
|
-
.writeTimeout(10, TimeUnit.SECONDS)
|
|
47
|
-
.readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read
|
|
48
|
-
.build()
|
|
42
|
+
private val okHttpClient = DevSupportHttpClient.websocketClient
|
|
49
43
|
private var closed = false
|
|
50
44
|
private var suppressConnectionErrors = false
|
|
51
45
|
private var webSocket: WebSocket? = null
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
|
|
15
15
|
#define REACT_NATIVE_VERSION_MAJOR 0
|
|
16
16
|
#define REACT_NATIVE_VERSION_MINOR 83
|
|
17
|
-
#define REACT_NATIVE_VERSION_PATCH
|
|
17
|
+
#define REACT_NATIVE_VERSION_PATCH 4
|
|
18
18
|
|
|
19
19
|
namespace facebook::react {
|
|
20
20
|
|
|
21
21
|
constexpr struct {
|
|
22
22
|
int32_t Major = 0;
|
|
23
23
|
int32_t Minor = 83;
|
|
24
|
-
int32_t Patch =
|
|
24
|
+
int32_t Patch = 4;
|
|
25
25
|
std::string_view Prerelease = "";
|
|
26
26
|
} ReactNativeVersion;
|
|
27
27
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.83.
|
|
3
|
+
"version": "0.83.4",
|
|
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.83.
|
|
164
|
-
"@react-native/codegen": "0.83.
|
|
165
|
-
"@react-native/community-cli-plugin": "0.83.
|
|
166
|
-
"@react-native/gradle-plugin": "0.83.
|
|
167
|
-
"@react-native/js-polyfills": "0.83.
|
|
168
|
-
"@react-native/normalize-colors": "0.83.
|
|
169
|
-
"@react-native/virtualized-lists": "0.83.
|
|
163
|
+
"@react-native/assets-registry": "0.83.4",
|
|
164
|
+
"@react-native/codegen": "0.83.4",
|
|
165
|
+
"@react-native/community-cli-plugin": "0.83.4",
|
|
166
|
+
"@react-native/gradle-plugin": "0.83.4",
|
|
167
|
+
"@react-native/js-polyfills": "0.83.4",
|
|
168
|
+
"@react-native/normalize-colors": "0.83.4",
|
|
169
|
+
"@react-native/virtualized-lists": "0.83.4",
|
|
170
170
|
"abort-controller": "^3.0.0",
|
|
171
171
|
"anser": "^1.4.9",
|
|
172
172
|
"ansi-regex": "^5.0.0",
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
const {spawnSync} = require('child_process');
|
|
14
14
|
const fs = require('fs');
|
|
15
|
+
const os = require('os');
|
|
16
|
+
const path = require('path');
|
|
15
17
|
const yargs = require('yargs');
|
|
16
18
|
|
|
17
19
|
const LAST_BUILD_FILENAME = 'React-Core-prebuilt/.last_build_configuration';
|
|
@@ -62,14 +64,66 @@ function replaceRNCoreConfiguration(
|
|
|
62
64
|
const tarballURLPath = `${podsRoot}/ReactNativeCore-artifacts/reactnative-core-${version.toLowerCase()}-${configuration.toLowerCase()}.tar.gz`;
|
|
63
65
|
|
|
64
66
|
const finalLocation = 'React-Core-prebuilt';
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
});
|
|
67
|
+
|
|
68
|
+
// Extract to a temporary directory on a regular filesystem first, then move
|
|
69
|
+
// into the final location. This avoids issues with partial tar extraction on
|
|
70
|
+
// certain filesystems (e.g. EdenFS) where extracting directly can silently
|
|
71
|
+
// produce incomplete results.
|
|
72
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'rncore-'));
|
|
73
|
+
const tmpExtractDir = path.join(tmpDir, 'React-Core-prebuilt');
|
|
74
|
+
fs.mkdirSync(tmpExtractDir, {recursive: true});
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
console.log('Extracting the tarball to temp dir', tarballURLPath);
|
|
78
|
+
const result = spawnSync(
|
|
79
|
+
'tar',
|
|
80
|
+
['-xf', tarballURLPath, '-C', tmpExtractDir],
|
|
81
|
+
{
|
|
82
|
+
stdio: 'inherit',
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if (result.status !== 0) {
|
|
87
|
+
throw new Error(`tar extraction failed with exit code ${result.status}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Verify extraction produced the expected xcframework structure
|
|
91
|
+
const xcfwPath = path.join(tmpExtractDir, 'React.xcframework');
|
|
92
|
+
const modulemapPath = path.join(xcfwPath, 'Modules', 'module.modulemap');
|
|
93
|
+
if (!fs.existsSync(modulemapPath)) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Extraction verification failed: ${modulemapPath} not found`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Move from temp to final location
|
|
100
|
+
console.log('Preparing the final location', finalLocation);
|
|
101
|
+
fs.rmSync(finalLocation, {force: true, recursive: true});
|
|
102
|
+
|
|
103
|
+
// Use mv for an atomic-ish replacement. If the final location is on the
|
|
104
|
+
// same filesystem as tmpDir this is a rename; otherwise it falls back to
|
|
105
|
+
// copy + delete via spawnSync.
|
|
106
|
+
const mvResult = spawnSync('mv', [tmpExtractDir, finalLocation], {
|
|
107
|
+
stdio: 'inherit',
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (mvResult.status !== 0) {
|
|
111
|
+
// Fallback: copy recursively then remove temp
|
|
112
|
+
console.log('mv failed, falling back to cp -R');
|
|
113
|
+
fs.mkdirSync(finalLocation, {recursive: true});
|
|
114
|
+
const cpResult = spawnSync(
|
|
115
|
+
'cp',
|
|
116
|
+
['-R', tmpExtractDir + '/.', finalLocation],
|
|
117
|
+
{stdio: 'inherit'},
|
|
118
|
+
);
|
|
119
|
+
if (cpResult.status !== 0) {
|
|
120
|
+
throw new Error(`cp fallback failed with exit code ${cpResult.status}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} finally {
|
|
124
|
+
// Clean up temp directory
|
|
125
|
+
fs.rmSync(tmpDir, {force: true, recursive: true});
|
|
126
|
+
}
|
|
73
127
|
}
|
|
74
128
|
|
|
75
129
|
function updateLastBuildConfiguration(configuration /*: string */) {
|
package/settings.gradle.kts
CHANGED
|
@@ -47,8 +47,28 @@ buildscript {
|
|
|
47
47
|
val properties = java.util.Properties()
|
|
48
48
|
val propertiesToInherit = listOf("hermesV1Enabled", "react.hermesV1Enabled")
|
|
49
49
|
|
|
50
|
+
// We cannot assume that the node_modules are next to the android project, for example
|
|
51
|
+
// in monorepos, they might get hoisted.
|
|
52
|
+
// In a composite build, this included build can access the invoking (consumer) build
|
|
53
|
+
// via `gradle.parent`. We use its StartParameter to locate the app's `gradle.properties`:
|
|
54
|
+
// - `projectDir/gradle.properties` when Gradle is run with `-p <androidDir>`
|
|
55
|
+
// - `currentDir/gradle.properties` when run from the app android folder
|
|
56
|
+
// If neither exists, we keep the legacy RN fallback path below.
|
|
57
|
+
|
|
58
|
+
val parentGradle = gradle.parent
|
|
59
|
+
val parentProjectDir = parentGradle?.startParameter?.projectDir
|
|
60
|
+
val parentCurrentDir = parentGradle?.startParameter?.currentDir
|
|
61
|
+
val gradlePropertiesCandidates =
|
|
62
|
+
listOfNotNull(
|
|
63
|
+
parentProjectDir?.resolve("gradle.properties"),
|
|
64
|
+
parentCurrentDir?.resolve("gradle.properties"),
|
|
65
|
+
// Backward-compatible fallback for classic RN app layouts.
|
|
66
|
+
file("../../android/gradle.properties"),
|
|
67
|
+
)
|
|
68
|
+
|
|
50
69
|
try {
|
|
51
|
-
|
|
70
|
+
val propertiesFile = gradlePropertiesCandidates.firstOrNull { it.exists() }
|
|
71
|
+
propertiesFile?.inputStream()?.use { properties.load(it) }
|
|
52
72
|
|
|
53
73
|
gradle.rootProject {
|
|
54
74
|
propertiesToInherit.forEach { property ->
|