Add inspector attach to RN Dev Menu (iOS)
Reviewed By: Hypuk Differential Revision: D6405831 fbshipit-source-id: ffecfbf85a35fad4d0c9a823c5e637a6b9e202ee
This commit is contained in:
parent
d71d28f094
commit
de424cc291
|
@ -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;
|
||||
}]];
|
||||
|
|
|
@ -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 @@ 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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue