Permalink
Browse files

Add inspector attach to RN Dev Menu (iOS)

Reviewed By: Hypuk

Differential Revision: D6405831

fbshipit-source-id: ffecfbf85a35fad4d0c9a823c5e637a6b9e202ee
  • Loading branch information...
pakoito authored and facebook-github-bot committed Dec 5, 2017
1 parent d71d28f commit de424cc291523a8f4e3d33059b725d5b85f31611
@@ -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 @@ - (void)addItem:(RCTDevMenuItem *)item
[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 @@ - (void)addItem:(RCTDevMenuItem *)item
}]];
} 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;
}]];
@@ -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
@@ -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 @@
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 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);
@@ -38,6 +38,7 @@
@property (nonatomic, readonly) BOOL isHotLoadingAvailable;
@property (nonatomic, readonly) BOOL isLiveReloadAvailable;
@property (nonatomic, readonly) BOOL isRemoteDebuggingAvailable;
@property (nonatomic, readonly) BOOL isNuclideDebuggingAvailable;

This comment has been minimized.

@chirag04

chirag04 Dec 5, 2017

Collaborator

is nuclide the official debugger now? looks odd to have nuclide specific code here in RN. cc @shergin @hramos

This comment has been minimized.

@shergin

shergin Dec 5, 2017

Contributor

IDK cc @pakoito

This comment has been minimized.

@pakoito

pakoito Dec 5, 2017

We're currently experimenting internally with better integration with Nuclide. If something comes out of it, we'll make sure to let you know!

This comment has been minimized.

@shergin

shergin Dec 8, 2017

Contributor

@pakoito That's cool!
Sorry for n00b question, but how deeply is it tight to Nuclide specific internals? Can we share/open this debugging API for all, to make, let's say, developing VisualStudio Code debugger possible?

This comment has been minimized.

@pakoito

pakoito Dec 12, 2017

It's too early to tell right now as we're focusing exclusively on Nuclide integration.

@property (nonatomic, readonly) BOOL isJSCSamplingProfilerAvailable;
/**
@@ -252,6 +252,15 @@ - (id)settingForKey:(NSString *)key
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");

0 comments on commit de424cc

Please sign in to comment.