Skip to content

Commit f8c03d1

Browse files
authored
Allow RCTBundleURLProvider to request an inline source map (#37878) (#38995)
Summary: See: http://blog.nparashuram.com/2019/10/debugging-react-native-ios-apps-with.html When using direct debugging with JavaScriptCore, Safari Web Inspector doesn't pick up the source map over the network. Instead, as far as I can tell, it expects you to pass the source URL at the time you load your bundle: https://developer.apple.com/documentation/javascriptcore/jscontext/1451384-evaluatescript?language=objc . This leads to a very sub-par developer experience debugging the JSbundle directly. It will however, pick up an inline source map. Therefore, let's add a way to have React Native tell metro to request an inline source map. I did this by modifying `RCTBundleURLProvider` to have a new query parameter for `inlineSourceMap`, and set to true by default for JSC. [IOS] [ADDED] - Added support to inline the source map via RCTBundleURLProvider Pull Request resolved: #37878 Test Plan: I can put a breakpoint in RNTester, via Safari Web Inspector, in human readable code :D <img width="1728" alt="Screenshot 2023-06-14 at 4 09 03 AM" src="https://github.com/facebook/react-native/assets/6722175/055277fa-d887-4566-9dc6-3ea07a1a60b0"> Reviewed By: motiz88 Differential Revision: D46855418 Pulled By: huntie fbshipit-source-id: 2134cdbcd0a3e81052d26ed75f83601ae4ddecfe
1 parent b3c7a5d commit f8c03d1

File tree

4 files changed

+120
-60
lines changed

4 files changed

+120
-60
lines changed

React/Base/RCTBundleURLProvider.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
101101

102102
@property (nonatomic, assign) BOOL enableMinification;
103103
@property (nonatomic, assign) BOOL enableDev;
104+
@property (nonatomic, assign) BOOL inlineSourceMap;
104105

105106
/**
106107
* The scheme/protocol used of the packager, the default is the http protocol
@@ -125,13 +126,32 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
125126
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
126127
packagerHost:(NSString *)packagerHost
127128
enableDev:(BOOL)enableDev
128-
enableMinification:(BOOL)enableMinification;
129+
enableMinification:(BOOL)enableMinification
130+
__deprecated_msg(
131+
"Use `jsBundleURLForBundleRoot:packagerHost:enableDev:enableMinification:inlineSourceMap:` instead");
132+
133+
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
134+
packagerHost:(NSString *)packagerHost
135+
packagerScheme:(NSString *)scheme
136+
enableDev:(BOOL)enableDev
137+
enableMinification:(BOOL)enableMinification
138+
modulesOnly:(BOOL)modulesOnly
139+
runModule:(BOOL)runModule
140+
__deprecated_msg(
141+
"Use jsBundleURLForBundleRoot:packagerHost:enableDev:enableMinification:inlineSourceMap:modulesOnly:runModule:` instead");
142+
143+
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
144+
packagerHost:(NSString *)packagerHost
145+
enableDev:(BOOL)enableDev
146+
enableMinification:(BOOL)enableMinification
147+
inlineSourceMap:(BOOL)inlineSourceMap;
129148

130149
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
131150
packagerHost:(NSString *)packagerHost
132151
packagerScheme:(NSString *)scheme
133152
enableDev:(BOOL)enableDev
134153
enableMinification:(BOOL)enableMinification
154+
inlineSourceMap:(BOOL)inlineSourceMap
135155
modulesOnly:(BOOL)modulesOnly
136156
runModule:(BOOL)runModule;
137157
/**
@@ -142,6 +162,17 @@ RCT_EXTERN void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed);
142162
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
143163
packagerHost:(NSString *)packagerHost
144164
scheme:(NSString *)scheme
145-
query:(NSString *)query;
165+
query:(NSString *)query
166+
__deprecated_msg("Use version with queryItems parameter instead");
167+
168+
/**
169+
* Given a hostname for the packager and a resource path (including "/"), return the URL to the resource.
170+
* In general, please use the instance method to decide if the packager is running and fallback to the pre-packaged
171+
* resource if it is not: -resourceURLForResourceRoot:resourceName:resourceExtension:offlineBundle:
172+
*/
173+
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
174+
packagerHost:(NSString *)packagerHost
175+
scheme:(NSString *)scheme
176+
queryItems:(NSArray<NSURLQueryItem *> *)queryItems;
146177

147178
@end

React/Base/RCTBundleURLProvider.mm

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed)
2222
kRCTAllowPackagerAccess = allowed;
2323
}
2424
#endif
25+
static NSString *const kRCTPlatformName = @"ios";
2526
static NSString *const kRCTPackagerSchemeKey = @"RCT_packager_scheme";
2627
static NSString *const kRCTJsLocationKey = @"RCT_jsLocation";
2728
static NSString *const kRCTEnableDevKey = @"RCT_enableDev";
2829
static NSString *const kRCTEnableMinificationKey = @"RCT_enableMinification";
30+
static NSString *const kRCTInlineSourceMapKey = @"RCT_inlineSourceMap";
2931

3032
@implementation RCTBundleURLProvider
3133

@@ -183,6 +185,7 @@ - (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot fallbackURLProvider:(
183185
packagerScheme:[self packagerScheme]
184186
enableDev:[self enableDev]
185187
enableMinification:[self enableMinification]
188+
inlineSourceMap:[self inlineSourceMap]
186189
modulesOnly:NO
187190
runModule:YES];
188191
}
@@ -195,6 +198,7 @@ - (NSURL *)jsBundleURLForSplitBundleRoot:(NSString *)bundleRoot
195198
packagerScheme:[self packagerScheme]
196199
enableDev:[self enableDev]
197200
enableMinification:[self enableMinification]
201+
inlineSourceMap:[self inlineSourceMap]
198202
modulesOnly:YES
199203
runModule:NO];
200204
}
@@ -234,20 +238,37 @@ - (NSURL *)resourceURLForResourceRoot:(NSString *)root
234238
return [[self class] resourceURLForResourcePath:path
235239
packagerHost:packagerServerHostPort
236240
scheme:packagerServerScheme
237-
query:nil];
241+
queryItems:nil];
238242
}
239243

240244
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
241245
packagerHost:(NSString *)packagerHost
242246
enableDev:(BOOL)enableDev
243247
enableMinification:(BOOL)enableMinification
248+
{
249+
return [self jsBundleURLForBundleRoot:bundleRoot
250+
packagerHost:packagerHost
251+
packagerScheme:nil
252+
enableDev:enableDev
253+
enableMinification:enableMinification
254+
inlineSourceMap:NO
255+
modulesOnly:NO
256+
runModule:YES];
257+
}
258+
259+
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
260+
packagerHost:(NSString *)packagerHost
261+
enableDev:(BOOL)enableDev
262+
enableMinification:(BOOL)enableMinification
263+
inlineSourceMap:(BOOL)inlineSourceMap
244264

245265
{
246266
return [self jsBundleURLForBundleRoot:bundleRoot
247267
packagerHost:packagerHost
248268
packagerScheme:nil
249269
enableDev:enableDev
250270
enableMinification:enableMinification
271+
inlineSourceMap:inlineSourceMap
251272
modulesOnly:NO
252273
runModule:YES];
253274
}
@@ -259,27 +280,45 @@ + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
259280
enableMinification:(BOOL)enableMinification
260281
modulesOnly:(BOOL)modulesOnly
261282
runModule:(BOOL)runModule
283+
{
284+
return [self jsBundleURLForBundleRoot:bundleRoot
285+
packagerHost:packagerHost
286+
packagerScheme:nil
287+
enableDev:enableDev
288+
enableMinification:enableMinification
289+
inlineSourceMap:NO
290+
modulesOnly:modulesOnly
291+
runModule:runModule];
292+
}
293+
294+
+ (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot
295+
packagerHost:(NSString *)packagerHost
296+
packagerScheme:(NSString *)scheme
297+
enableDev:(BOOL)enableDev
298+
enableMinification:(BOOL)enableMinification
299+
inlineSourceMap:(BOOL)inlineSourceMap
300+
modulesOnly:(BOOL)modulesOnly
301+
runModule:(BOOL)runModule
262302
{
263303
NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot];
304+
BOOL lazy = enableDev;
305+
NSArray<NSURLQueryItem *> *queryItems = @[
306+
[[NSURLQueryItem alloc] initWithName:@"platform" value:kRCTPlatformName],
307+
[[NSURLQueryItem alloc] initWithName:@"dev" value:enableDev ? @"true" : @"false"],
308+
[[NSURLQueryItem alloc] initWithName:@"minify" value:enableMinification ? @"true" : @"false"],
309+
[[NSURLQueryItem alloc] initWithName:@"inlineSourceMap" value:inlineSourceMap ? @"true" : @"false"],
310+
[[NSURLQueryItem alloc] initWithName:@"modulesOnly" value:modulesOnly ? @"true" : @"false"],
311+
[[NSURLQueryItem alloc] initWithName:@"runModule" value:runModule ? @"true" : @"false"],
264312
#ifdef HERMES_BYTECODE_VERSION
265-
NSString *runtimeBytecodeVersion = [NSString stringWithFormat:@"&runtimeBytecodeVersion=%u", HERMES_BYTECODE_VERSION];
266-
#else
267-
NSString *runtimeBytecodeVersion = @"";
313+
[[NSURLQueryItem alloc] initWithName:@"runtimeBytecodeVersion" value:HERMES_BYTECODE_VERSION],
268314
#endif
269-
270-
// When we support only iOS 8 and above, use queryItems for a better API.
271-
NSString *query = [NSString stringWithFormat:@"platform=ios&dev=%@&minify=%@&modulesOnly=%@&runModule=%@%@",
272-
enableDev ? @"true" : @"false",
273-
enableMinification ? @"true" : @"false",
274-
modulesOnly ? @"true" : @"false",
275-
runModule ? @"true" : @"false",
276-
runtimeBytecodeVersion];
315+
];
277316

278317
NSString *bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];
279318
if (bundleID) {
280-
query = [NSString stringWithFormat:@"%@&app=%@", query, bundleID];
319+
queryItems = [queryItems arrayByAddingObject:[[NSURLQueryItem alloc] initWithName:@"app" value:bundleID]];
281320
}
282-
return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme query:query];
321+
return [[self class] resourceURLForResourcePath:path packagerHost:packagerHost scheme:scheme queryItems:queryItems];
283322
}
284323

285324
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
@@ -296,6 +335,20 @@ + (NSURL *)resourceURLForResourcePath:(NSString *)path
296335
return components.URL;
297336
}
298337

338+
+ (NSURL *)resourceURLForResourcePath:(NSString *)path
339+
packagerHost:(NSString *)packagerHost
340+
scheme:(NSString *)scheme
341+
queryItems:(NSArray<NSURLQueryItem *> *)queryItems
342+
{
343+
NSURLComponents *components = [NSURLComponents componentsWithURL:serverRootWithHostPort(packagerHost, scheme)
344+
resolvingAgainstBaseURL:NO];
345+
components.path = path;
346+
if (queryItems != nil) {
347+
components.queryItems = queryItems;
348+
}
349+
return components.URL;
350+
}
351+
299352
- (void)updateValue:(id)object forKey:(NSString *)key
300353
{
301354
[[NSUserDefaults standardUserDefaults] setObject:object forKey:key];
@@ -313,6 +366,11 @@ - (BOOL)enableMinification
313366
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTEnableMinificationKey];
314367
}
315368

369+
- (BOOL)inlineSourceMap
370+
{
371+
return [[NSUserDefaults standardUserDefaults] boolForKey:kRCTInlineSourceMapKey];
372+
}
373+
316374
- (NSString *)jsLocation
317375
{
318376
return [[NSUserDefaults standardUserDefaults] stringForKey:kRCTJsLocationKey];
@@ -342,6 +400,11 @@ - (void)setEnableMinification:(BOOL)enableMinification
342400
[self updateValue:@(enableMinification) forKey:kRCTEnableMinificationKey];
343401
}
344402

403+
- (void)setInlineSourceMap:(BOOL)inlineSourceMap
404+
{
405+
[self updateValue:@(inlineSourceMap) forKey:kRCTInlineSourceMapKey];
406+
}
407+
345408
- (void)setPackagerScheme:(NSString *)packagerScheme
346409
{
347410
[self updateValue:packagerScheme forKey:kRCTPackagerSchemeKey];

packages/rn-tester/Podfile.lock

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,6 @@ PODS:
7777
- hermes-engine/Pre-built (= 0.71.12)
7878
- hermes-engine/Pre-built (0.71.12)
7979
- libevent (2.1.12)
80-
- MyNativeView (0.0.1):
81-
- RCT-Folly (= 2021.07.22.00)
82-
- RCTRequired
83-
- RCTTypeSafety
84-
- React-Codegen
85-
- React-Core
86-
- React-RCTFabric
87-
- ReactCommon/turbomodule/bridging
88-
- ReactCommon/turbomodule/core
89-
- NativeCxxModuleExample (0.0.1):
90-
- RCT-Folly (= 2021.07.22.00)
91-
- RCTRequired
92-
- RCTTypeSafety
93-
- React-Codegen
94-
- React-Core
95-
- React-RCTFabric
96-
- ReactCommon/turbomodule/bridging
97-
- ReactCommon/turbomodule/core
9880
- OpenSSL-Universal (1.1.1100)
9981
- RCT-Folly (2021.07.22.00):
10082
- boost
@@ -700,8 +682,6 @@ PODS:
700682
- RCTRequired
701683
- RCTTypeSafety
702684
- React-Core
703-
- React-graphics
704-
- React-RCTFabric
705685
- ReactCommon/turbomodule/core
706686
- React-RCTBlob (0.71.12):
707687
- hermes-engine
@@ -803,13 +783,7 @@ PODS:
803783
- ReactCommon/turbomodule/core (= 0.71.12)
804784
- ScreenshotManager (0.0.1):
805785
- RCT-Folly (= 2021.07.22.00)
806-
- RCTRequired
807-
- RCTTypeSafety
808-
- React-Codegen
809786
- React-Core
810-
- React-RCTFabric
811-
- ReactCommon/turbomodule/bridging
812-
- ReactCommon/turbomodule/core
813787
- SocketRocket (0.6.0)
814788
- Yoga (1.14.0)
815789
- YogaKit (1.18.1):
@@ -844,8 +818,6 @@ DEPENDENCIES:
844818
- glog (from `../../third-party-podspecs/glog.podspec`)
845819
- hermes-engine (from `../../sdks/hermes-engine/hermes-engine.podspec`)
846820
- libevent (~> 2.1.12)
847-
- MyNativeView (from `NativeComponentExample`)
848-
- NativeCxxModuleExample (from `NativeCxxModuleExample`)
849821
- OpenSSL-Universal (= 1.1.1100)
850822
- RCT-Folly (from `../../third-party-podspecs/RCT-Folly.podspec`)
851823
- RCT-Folly/Fabric (from `../../third-party-podspecs/RCT-Folly.podspec`)
@@ -918,10 +890,6 @@ EXTERNAL SOURCES:
918890
:podspec: "../../third-party-podspecs/glog.podspec"
919891
hermes-engine:
920892
:podspec: "../../sdks/hermes-engine/hermes-engine.podspec"
921-
MyNativeView:
922-
:path: NativeComponentExample
923-
NativeCxxModuleExample:
924-
:path: NativeCxxModuleExample
925893
RCT-Folly:
926894
:podspec: "../../third-party-podspecs/RCT-Folly.podspec"
927895
RCTRequired:
@@ -998,7 +966,7 @@ SPEC CHECKSUMS:
998966
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
999967
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
1000968
FBLazyVector: 4eb7ee83e8d0ad7e20a829485295ff48823c4e4c
1001-
FBReactNativeSpec: be2df14ea53a93ca2cfcee55312669505eb90c5f
969+
FBReactNativeSpec: f7e02f3a649db46b9dc6301cb444d06a836d6ef6
1002970
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
1003971
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
1004972
Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30
@@ -1012,15 +980,13 @@ SPEC CHECKSUMS:
1012980
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
1013981
hermes-engine: b60ebc812e0179a612d8146ac54730d533c804a2
1014982
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
1015-
MyNativeView: 1679f1055fcff0bc68bd1267ac4fb277e2adc4b7
1016-
NativeCxxModuleExample: c15855f77dbd3ee1eae90e745d33ecfb8322bc22
1017983
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
1018984
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
1019985
RCTRequired: 4db5e3e18b906377a502da5b358ff159ba4783ed
1020986
RCTTypeSafety: 6c1a8aed043050de0d537336c95cd1be7b66c272
1021987
React: 214e77358d860a3ed707fede9088e7c00663a087
1022988
React-callinvoker: 8fc1c79c26fbcadce2a5d4a3cb4b2ced2dec3436
1023-
React-Codegen: 94d1fe87283899c3964bfbfec8574463d4c628c2
989+
React-Codegen: acb4763004145cdeb16951d2ded3c630a474738e
1024990
React-Core: ea541085ca5be10b2be289c7d82eba368b5c4900
1025991
React-CoreModules: d9680e1d551eef1dd764df736a473cf25f701070
1026992
React-cxxreact: 0792e80e291d086b2cf588410f6bc6e752bc1d83
@@ -1034,7 +1000,7 @@ SPEC CHECKSUMS:
10341000
React-perflogger: 75b0e25075c67565a830985f3c373e2eae5389e0
10351001
React-RCTActionSheet: a0c3e916b327e297d124d9ebe8b0c721840ee04d
10361002
React-RCTAnimation: 3da7025801d7bf0f8cfd94574d6278d5b82a8b88
1037-
React-RCTAppDelegate: 2ef2a2b0f14b0b8e2ed91f88084801fadee5dee6
1003+
React-RCTAppDelegate: f74a567e0bc905aaff66d47ab30e6548f727549c
10381004
React-RCTBlob: 53252ebabe7777fd1c440a34546c64e16b162908
10391005
React-RCTFabric: 7667a890d204af8a42683133250251e698c67e5c
10401006
React-RCTImage: e230761bd34d71362dd8b3d51b5cd72674935aa0
@@ -1045,14 +1011,14 @@ SPEC CHECKSUMS:
10451011
React-RCTTest: c3dc5ccdaa39a3175ee7d5535b756d9f44e78a1a
10461012
React-RCTText: a9c712b13cab90e1432e0ad113edc8bdbc691248
10471013
React-RCTVibration: a283fefb8cc29d9740a7ff2e87f72ad10f25a433
1048-
React-rncore: 1809ecfc14066404da300c0d950876bf95852f87
1014+
React-rncore: a2f1e15fdba845f935c87d887a90c526910949d8
10491015
React-runtimeexecutor: 7902246857a4ead4166869e6c42d4df329ff721d
10501016
ReactCommon: a6d1c76b9e10b439e41db225263341240e1cda9f
1051-
ScreenshotManager: e3849278058266a931c468142bb7594a84e679e7
1017+
ScreenshotManager: e77ad8e427160ebce1f86313e2b21ea56b665285
10521018
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
10531019
Yoga: 39310a10944fc864a7550700de349183450f8aaa
10541020
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
10551021

10561022
PODFILE CHECKSUM: 8da43cb75927abd2bbb2fc21dcebfebb05b89963
10571023

1058-
COCOAPODS: 1.11.3
1024+
COCOAPODS: 1.12.1

packages/rn-tester/RNTesterUnitTests/RCTBundleURLProviderTests.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@
2727
URLWithString:
2828
[NSString
2929
stringWithFormat:
30-
@"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&runtimeBytecodeVersion=%u&app=com.apple.dt.xctest.tool",
30+
@"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&runtimeBytecodeVersion=%u&app=com.apple.dt.xctest.tool",
3131
testFile,
3232
HERMES_BYTECODE_VERSION]];
3333
#else
3434
return [NSURL
3535
URLWithString:
3636
[NSString
3737
stringWithFormat:
38-
@"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=com.apple.dt.xctest.tool",
38+
@"http://localhost:8081/%@.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.apple.dt.xctest.tool",
3939
testFile]];
4040
#endif
4141
}
@@ -47,15 +47,15 @@
4747
URLWithString:
4848
[NSString
4949
stringWithFormat:
50-
@"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&runtimeBytecodeVersion=%u&app=com.apple.dt.xctest.tool",
50+
@"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&runtimeBytecodeVersion=%u&app=com.apple.dt.xctest.tool",
5151
testFile,
5252
HERMES_BYTECODE_VERSION]];
5353
#else
5454
return [NSURL
5555
URLWithString:
5656
[NSString
5757
stringWithFormat:
58-
@"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=com.apple.dt.xctest.tool",
58+
@"http://192.168.1.1:8081/%@.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.apple.dt.xctest.tool",
5959
testFile]];
6060
#endif
6161
}

0 commit comments

Comments
 (0)