Add inspector attach to RN Dev Menu (iOS)

Reviewed By: Hypuk

Differential Revision: D6405831

fbshipit-source-id: ffecfbf85a35fad4d0c9a823c5e637a6b9e202ee
This commit is contained in:
Paco Estevez Garcia 2017-12-05 06:27:32 -08:00 committed by Facebook Github Bot
parent d71d28f094
commit de424cc291
5 changed files with 83 additions and 6 deletions

View File

@ -17,6 +17,10 @@
#if RCT_DEV
#if RCT_ENABLE_INSPECTOR
#import "RCTInspectorDevServerHelper.h"
#endif
NSString *const RCTShowDevMenuNotification = @"RCTShowDevMenuNotification";
@implementation UIWindow (RCTDevMenu)
@ -199,6 +203,14 @@ RCT_EXPORT_MODULE()
[bridge reload];
}]];
if (devSettings.isNuclideDebuggingAvailable) {
[items addObject:[RCTDevMenuItem buttonItemWithTitle:[NSString stringWithFormat:@"Debug JS in Nuclide %@", @"\U0001F4AF"] handler:^{
#if RCT_ENABLE_INSPECTOR
[RCTInspectorDevServerHelper attachDebugger:@"ReactNative" withBundleURL:bridge.bundleURL withView: RCTPresentedViewController()];
#endif
}]];
}
if (!devSettings.isRemoteDebuggingAvailable) {
[items addObject:[RCTDevMenuItem buttonItemWithTitle:@"Remote JS Debugger Unavailable" handler:^{
UIAlertController *alertController = [UIAlertController
@ -209,7 +221,12 @@ RCT_EXPORT_MODULE()
}]];
} else {
[items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString *{
return devSettings.isDebuggingRemotely ? @"Stop Remote JS Debugging" : @"Debug JS Remotely";
NSString *title = devSettings.isDebuggingRemotely ? @"Stop Remote JS Debugging" : @"Debug JS Remotely";
if (devSettings.isNuclideDebuggingAvailable) {
return [NSString stringWithFormat:@"%@ %@", title, @"\U0001F645"];
} else {
return title;
}
} handler:^{
devSettings.isDebuggingRemotely = !devSettings.isDebuggingRemotely;
}]];

View File

@ -2,6 +2,8 @@
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JSBase.h>
#import <UIKit/UIKit.h>
#import <React/RCTDefines.h>
#if RCT_DEV
@ -11,6 +13,9 @@
+ (void)connectForContext:(JSGlobalContextRef)context
withBundleURL:(NSURL *)bundleURL;
+ (void)disableDebugger;
+ (void)attachDebugger:(NSString *)owner
withBundleURL:(NSURL *)bundleURL
withView:(UIViewController *)view;
@end
#endif

View File

@ -4,6 +4,7 @@
#import <jschelpers/JSCWrapper.h>
#import <UIKit/UIKit.h>
#import <React/RCTLog.h>
#import "RCTDefines.h"
#import "RCTInspectorPackagerConnection.h"
@ -12,16 +13,13 @@ using namespace facebook::react;
static NSString *const kDebuggerMsgDisable = @"{ \"id\":1,\"method\":\"Debugger.disable\" }";
static NSString *getDebugServerHost(NSURL *bundleURL)
static NSString *getServerHost(NSURL *bundleURL, NSNumber *port)
{
NSString *host = [bundleURL host];
if (!host) {
host = @"localhost";
}
// Inspector Proxy is run on a separate port (from packager).
NSNumber *port = @8082;
// this is consistent with the Android implementation, where http:// is the
// hardcoded implicit scheme for the debug server. Note, packagerURL
// technically looks like it could handle schemes/protocols other than HTTP,
@ -32,14 +30,26 @@ static NSString *getDebugServerHost(NSURL *bundleURL)
static NSURL *getInspectorDeviceUrl(NSURL *bundleURL)
{
NSNumber *inspectorProxyPort = @8082;
NSString *escapedDeviceName = [[[UIDevice currentDevice] name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *escapedAppName = [[[NSBundle mainBundle] bundleIdentifier] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@",
getDebugServerHost(bundleURL),
getServerHost(bundleURL, inspectorProxyPort),
escapedDeviceName,
escapedAppName]];
}
static NSURL *getAttachDeviceUrl(NSURL *bundleURL, NSString *title)
{
NSNumber *metroBundlerPort = @8081;
NSString *escapedDeviceName = [[[UIDevice currentDevice] name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *escapedAppName = [[[NSBundle mainBundle] bundleIdentifier] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/attach-debugger-nuclide?title=%@&device=%@&app=%@",
getServerHost(bundleURL, metroBundlerPort),
title,
escapedDeviceName,
escapedAppName]];
}
@implementation RCTInspectorDevServerHelper
@ -54,6 +64,41 @@ static void sendEventToAllConnections(NSString *event)
}
}
static void displayErrorAlert(UIViewController *view, NSString *message) {
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:nil
message:message
preferredStyle:UIAlertControllerStyleAlert];
[view presentViewController:alert animated:YES completion:nil];
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 2.5),
dispatch_get_main_queue(),
^{
[alert dismissViewControllerAnimated:YES completion:nil];
});
}
+ (void)attachDebugger:(NSString *)owner
withBundleURL:(NSURL *)bundleURL
withView:(UIViewController *)view
{
NSURL *url = getAttachDeviceUrl(bundleURL, owner);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"GET"];
__weak UIViewController *viewCapture = view;
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:
^(NSData *_Nullable data,
NSURLResponse *_Nullable response,
NSError *_Nullable error) {
UIViewController *viewCaptureStrong = viewCapture;
if (error != nullptr && viewCaptureStrong != nullptr) {
displayErrorAlert(viewCaptureStrong, @"The request to attach Nuclide couldn't reach Metro Bundler!");
}
}] resume];
}
+ (void)disableDebugger
{
sendEventToAllConnections(kDebuggerMsgDisable);

View File

@ -38,6 +38,7 @@
@property (nonatomic, readonly) BOOL isHotLoadingAvailable;
@property (nonatomic, readonly) BOOL isLiveReloadAvailable;
@property (nonatomic, readonly) BOOL isRemoteDebuggingAvailable;
@property (nonatomic, readonly) BOOL isNuclideDebuggingAvailable;
@property (nonatomic, readonly) BOOL isJSCSamplingProfilerAvailable;
/**

View File

@ -252,6 +252,15 @@ static void pokeSamplingProfiler(RCTBridge *const bridge, RCTPackagerClientRespo
return [_dataSource settingForKey:key];
}
- (BOOL)isNuclideDebuggingAvailable
{
#if RCT_ENABLE_INSPECTOR
return true;
#else
return false;
#endif //RCT_ENABLE_INSPECTOR
}
- (BOOL)isRemoteDebuggingAvailable
{
Class jsDebuggingExecutorClass = objc_lookUpClass("RCTWebSocketExecutor");