Skip to content

Commit de424cc

Browse files
pakoitofacebook-github-bot
authored andcommittedDec 5, 2017
Add inspector attach to RN Dev Menu (iOS)
Reviewed By: Hypuk Differential Revision: D6405831 fbshipit-source-id: ffecfbf85a35fad4d0c9a823c5e637a6b9e202ee
1 parent d71d28f commit de424cc

5 files changed

+83
-6
lines changed
 

‎React/DevSupport/RCTDevMenu.m

+18-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
#if RCT_DEV
1919

20+
#if RCT_ENABLE_INSPECTOR
21+
#import "RCTInspectorDevServerHelper.h"
22+
#endif
23+
2024
NSString *const RCTShowDevMenuNotification = @"RCTShowDevMenuNotification";
2125

2226
@implementation UIWindow (RCTDevMenu)
@@ -199,6 +203,14 @@ - (void)addItem:(RCTDevMenuItem *)item
199203
[bridge reload];
200204
}]];
201205

206+
if (devSettings.isNuclideDebuggingAvailable) {
207+
[items addObject:[RCTDevMenuItem buttonItemWithTitle:[NSString stringWithFormat:@"Debug JS in Nuclide %@", @"\U0001F4AF"] handler:^{
208+
#if RCT_ENABLE_INSPECTOR
209+
[RCTInspectorDevServerHelper attachDebugger:@"ReactNative" withBundleURL:bridge.bundleURL withView: RCTPresentedViewController()];
210+
#endif
211+
}]];
212+
}
213+
202214
if (!devSettings.isRemoteDebuggingAvailable) {
203215
[items addObject:[RCTDevMenuItem buttonItemWithTitle:@"Remote JS Debugger Unavailable" handler:^{
204216
UIAlertController *alertController = [UIAlertController
@@ -209,7 +221,12 @@ - (void)addItem:(RCTDevMenuItem *)item
209221
}]];
210222
} else {
211223
[items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString *{
212-
return devSettings.isDebuggingRemotely ? @"Stop Remote JS Debugging" : @"Debug JS Remotely";
224+
NSString *title = devSettings.isDebuggingRemotely ? @"Stop Remote JS Debugging" : @"Debug JS Remotely";
225+
if (devSettings.isNuclideDebuggingAvailable) {
226+
return [NSString stringWithFormat:@"%@ %@", title, @"\U0001F645"];
227+
} else {
228+
return title;
229+
}
213230
} handler:^{
214231
devSettings.isDebuggingRemotely = !devSettings.isDebuggingRemotely;
215232
}]];

‎React/DevSupport/RCTInspectorDevServerHelper.h

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#import <Foundation/Foundation.h>
44
#import <JavaScriptCore/JSBase.h>
5+
#import <UIKit/UIKit.h>
6+
57
#import <React/RCTDefines.h>
68

79
#if RCT_DEV
@@ -11,6 +13,9 @@
1113
+ (void)connectForContext:(JSGlobalContextRef)context
1214
withBundleURL:(NSURL *)bundleURL;
1315
+ (void)disableDebugger;
16+
+ (void)attachDebugger:(NSString *)owner
17+
withBundleURL:(NSURL *)bundleURL
18+
withView:(UIViewController *)view;
1419
@end
1520

1621
#endif

‎React/DevSupport/RCTInspectorDevServerHelper.mm

+50-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#import <jschelpers/JSCWrapper.h>
66
#import <UIKit/UIKit.h>
7+
#import <React/RCTLog.h>
78

89
#import "RCTDefines.h"
910
#import "RCTInspectorPackagerConnection.h"
@@ -12,16 +13,13 @@
1213

1314
static NSString *const kDebuggerMsgDisable = @"{ \"id\":1,\"method\":\"Debugger.disable\" }";
1415

15-
static NSString *getDebugServerHost(NSURL *bundleURL)
16+
static NSString *getServerHost(NSURL *bundleURL, NSNumber *port)
1617
{
1718
NSString *host = [bundleURL host];
1819
if (!host) {
1920
host = @"localhost";
2021
}
2122

22-
// Inspector Proxy is run on a separate port (from packager).
23-
NSNumber *port = @8082;
24-
2523
// this is consistent with the Android implementation, where http:// is the
2624
// hardcoded implicit scheme for the debug server. Note, packagerURL
2725
// technically looks like it could handle schemes/protocols other than HTTP,
@@ -32,14 +30,26 @@
3230

3331
static NSURL *getInspectorDeviceUrl(NSURL *bundleURL)
3432
{
33+
NSNumber *inspectorProxyPort = @8082;
3534
NSString *escapedDeviceName = [[[UIDevice currentDevice] name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
3635
NSString *escapedAppName = [[[NSBundle mainBundle] bundleIdentifier] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
3736
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@",
38-
getDebugServerHost(bundleURL),
37+
getServerHost(bundleURL, inspectorProxyPort),
3938
escapedDeviceName,
4039
escapedAppName]];
4140
}
4241

42+
static NSURL *getAttachDeviceUrl(NSURL *bundleURL, NSString *title)
43+
{
44+
NSNumber *metroBundlerPort = @8081;
45+
NSString *escapedDeviceName = [[[UIDevice currentDevice] name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
46+
NSString *escapedAppName = [[[NSBundle mainBundle] bundleIdentifier] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
47+
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/attach-debugger-nuclide?title=%@&device=%@&app=%@",
48+
getServerHost(bundleURL, metroBundlerPort),
49+
title,
50+
escapedDeviceName,
51+
escapedAppName]];
52+
}
4353

4454
@implementation RCTInspectorDevServerHelper
4555

@@ -54,6 +64,41 @@ static void sendEventToAllConnections(NSString *event)
5464
}
5565
}
5666

67+
static void displayErrorAlert(UIViewController *view, NSString *message) {
68+
UIAlertController *alert =
69+
[UIAlertController alertControllerWithTitle:nil
70+
message:message
71+
preferredStyle:UIAlertControllerStyleAlert];
72+
[view presentViewController:alert animated:YES completion:nil];
73+
dispatch_after(
74+
dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 2.5),
75+
dispatch_get_main_queue(),
76+
^{
77+
[alert dismissViewControllerAnimated:YES completion:nil];
78+
});
79+
}
80+
81+
+ (void)attachDebugger:(NSString *)owner
82+
withBundleURL:(NSURL *)bundleURL
83+
withView:(UIViewController *)view
84+
{
85+
NSURL *url = getAttachDeviceUrl(bundleURL, owner);
86+
87+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
88+
[request setHTTPMethod:@"GET"];
89+
90+
__weak UIViewController *viewCapture = view;
91+
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:
92+
^(NSData *_Nullable data,
93+
NSURLResponse *_Nullable response,
94+
NSError *_Nullable error) {
95+
UIViewController *viewCaptureStrong = viewCapture;
96+
if (error != nullptr && viewCaptureStrong != nullptr) {
97+
displayErrorAlert(viewCaptureStrong, @"The request to attach Nuclide couldn't reach Metro Bundler!");
98+
}
99+
}] resume];
100+
}
101+
57102
+ (void)disableDebugger
58103
{
59104
sendEventToAllConnections(kDebuggerMsgDisable);

‎React/Modules/RCTDevSettings.h

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
@property (nonatomic, readonly) BOOL isHotLoadingAvailable;
3939
@property (nonatomic, readonly) BOOL isLiveReloadAvailable;
4040
@property (nonatomic, readonly) BOOL isRemoteDebuggingAvailable;
41+
@property (nonatomic, readonly) BOOL isNuclideDebuggingAvailable;
4142
@property (nonatomic, readonly) BOOL isJSCSamplingProfilerAvailable;
4243

4344
/**

‎React/Modules/RCTDevSettings.mm

+9
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,15 @@ - (id)settingForKey:(NSString *)key
252252
return [_dataSource settingForKey:key];
253253
}
254254

255+
- (BOOL)isNuclideDebuggingAvailable
256+
{
257+
#if RCT_ENABLE_INSPECTOR
258+
return true;
259+
#else
260+
return false;
261+
#endif //RCT_ENABLE_INSPECTOR
262+
}
263+
255264
- (BOOL)isRemoteDebuggingAvailable
256265
{
257266
Class jsDebuggingExecutorClass = objc_lookUpClass("RCTWebSocketExecutor");

0 commit comments

Comments
 (0)