react-native 0.83.6 → 0.83.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/React/Base/RCTVersion.m +1 -1
  3. package/React/CoreModules/RCTJscSafeUrl+Internal.h +23 -0
  4. package/React/CoreModules/RCTJscSafeUrl.mm +38 -0
  5. package/React/CoreModules/RCTRedBox+Internal.h +42 -0
  6. package/React/CoreModules/RCTRedBox.mm +30 -450
  7. package/React/CoreModules/RCTRedBox2AnsiParser+Internal.h +22 -0
  8. package/React/CoreModules/RCTRedBox2AnsiParser.mm +55 -0
  9. package/React/CoreModules/RCTRedBox2Controller+Internal.h +34 -0
  10. package/React/CoreModules/RCTRedBox2Controller.mm +764 -0
  11. package/React/CoreModules/RCTRedBox2ErrorParser+Internal.h +46 -0
  12. package/React/CoreModules/RCTRedBox2ErrorParser.mm +57 -0
  13. package/React/CoreModules/RCTRedBoxController+Internal.h +31 -0
  14. package/React/CoreModules/RCTRedBoxController.mm +447 -0
  15. package/React/CoreModules/RCTRedBoxHMRClient+Internal.h +26 -0
  16. package/React/CoreModules/RCTRedBoxHMRClient.mm +125 -0
  17. package/React/CoreModules/React-CoreModules.podspec +1 -0
  18. package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +16 -0
  19. package/ReactAndroid/gradle.properties +1 -1
  20. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +13 -1
  21. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +21 -1
  22. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +5 -1
  23. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +5 -1
  24. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +23 -1
  25. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +5 -1
  26. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
  27. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +29 -1
  28. package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +7 -1
  29. package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
  30. package/ReactCommon/react/debug/CMakeLists.txt +2 -1
  31. package/ReactCommon/react/debug/React-debug.podspec +7 -1
  32. package/ReactCommon/react/debug/redbox/AnsiParser.cpp +139 -0
  33. package/ReactCommon/react/debug/redbox/AnsiParser.h +35 -0
  34. package/ReactCommon/react/debug/redbox/JscSafeUrl.cpp +179 -0
  35. package/ReactCommon/react/debug/redbox/JscSafeUrl.h +27 -0
  36. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.cpp +171 -0
  37. package/ReactCommon/react/debug/redbox/RedBoxErrorParser.h +40 -0
  38. package/ReactCommon/react/debug/redbox/tests/AnsiParserTest.cpp +97 -0
  39. package/ReactCommon/react/debug/redbox/tests/JscSafeUrlTest.cpp +173 -0
  40. package/ReactCommon/react/debug/redbox/tests/RedBoxErrorParserTest.cpp +107 -0
  41. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +9 -1
  42. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +11 -1
  43. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +58 -22
  44. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +6 -2
  45. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +9 -1
  46. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +19 -1
  47. package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +3 -1
  48. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +11 -1
  49. package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +5 -1
  50. package/package.json +8 -8
  51. package/src/private/featureflags/ReactNativeFeatureFlags.js +11 -1
  52. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +3 -1
@@ -28,7 +28,7 @@
28
28
  export default class ReactNativeVersion {
29
29
  static major: number = 0;
30
30
  static minor: number = 83;
31
- static patch: number = 6;
31
+ static patch: number = 8;
32
32
  static prerelease: string | null = null;
33
33
 
34
34
  static getVersionString(): string {
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(83),
26
- RCTVersionPatch: @(6),
26
+ RCTVersionPatch: @(8),
27
27
  RCTVersionPrerelease: [NSNull null],
28
28
  };
29
29
  });
@@ -0,0 +1,23 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #import <Foundation/Foundation.h>
9
+
10
+ /**
11
+ * Converts between standard URLs and JSC-safe URLs.
12
+ *
13
+ * JSC (JavaScriptCore) strips query strings from source URLs in stack traces
14
+ * as of iOS 16.4. Metro works around this by encoding the query string into
15
+ * the URL path. These methods convert between the two formats.
16
+ */
17
+ @interface RCTJscSafeUrl : NSObject
18
+
19
+ + (nonnull NSString *)normalUrlFromJscSafeUrl:(nonnull NSString *)url;
20
+ + (nonnull NSString *)jscSafeUrlFromNormalUrl:(nonnull NSString *)url;
21
+ + (BOOL)isJscSafeUrl:(nonnull NSString *)url;
22
+
23
+ @end
@@ -0,0 +1,38 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #import "RCTJscSafeUrl+Internal.h"
9
+
10
+ #import <React/RCTDefines.h>
11
+ #import <react/debug/redbox/JscSafeUrl.h>
12
+
13
+ #if RCT_DEV_MENU
14
+
15
+ using facebook::react::unstable_redbox::isJscSafeUrl;
16
+ using facebook::react::unstable_redbox::toJscSafeUrl;
17
+ using facebook::react::unstable_redbox::toNormalUrl;
18
+
19
+ @implementation RCTJscSafeUrl
20
+
21
+ + (NSString *)normalUrlFromJscSafeUrl:(NSString *)url
22
+ {
23
+ return [NSString stringWithUTF8String:toNormalUrl(url.UTF8String).c_str()];
24
+ }
25
+
26
+ + (NSString *)jscSafeUrlFromNormalUrl:(NSString *)url
27
+ {
28
+ return [NSString stringWithUTF8String:toJscSafeUrl(url.UTF8String).c_str()];
29
+ }
30
+
31
+ + (BOOL)isJscSafeUrl:(NSString *)url
32
+ {
33
+ return isJscSafeUrl(url.UTF8String);
34
+ }
35
+
36
+ @end
37
+
38
+ #endif
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #import <React/RCTDefines.h>
9
+ #import <UIKit/UIKit.h>
10
+
11
+ #if RCT_DEV_MENU
12
+
13
+ @class RCTJSStackFrame;
14
+
15
+ @protocol RCTRedBoxControllerActionDelegate <NSObject>
16
+
17
+ - (void)redBoxController:(UIViewController *)redBoxController openStackFrameInEditor:(RCTJSStackFrame *)stackFrame;
18
+ - (void)reloadFromRedBoxController:(UIViewController *)redBoxController;
19
+ - (void)loadExtraDataViewController;
20
+
21
+ @end
22
+
23
+ @protocol RCTRedBoxControlling <NSObject>
24
+
25
+ @property (nonatomic, weak) id<RCTRedBoxControllerActionDelegate> actionDelegate;
26
+
27
+ - (void)showErrorMessage:(NSString *)message
28
+ withStack:(NSArray<RCTJSStackFrame *> *)stack
29
+ isUpdate:(BOOL)isUpdate
30
+ errorCookie:(int)errorCookie;
31
+
32
+ - (void)dismiss;
33
+
34
+ @end
35
+
36
+ @protocol RCTRedBox2Controlling <RCTRedBoxControlling>
37
+
38
+ @property (nonatomic, strong, nullable) NSURL *bundleURL;
39
+
40
+ @end
41
+
42
+ #endif
@@ -16,451 +16,15 @@
16
16
  #import <React/RCTRedBoxExtraDataViewController.h>
17
17
  #import <React/RCTReloadCommand.h>
18
18
  #import <React/RCTUtils.h>
19
-
20
- #import <objc/runtime.h>
19
+ #import <react/featureflags/ReactNativeFeatureFlags.h>
21
20
 
22
21
  #import "CoreModulesPlugins.h"
22
+ #import "RCTRedBox+Internal.h"
23
+ #import "RCTRedBox2Controller+Internal.h"
24
+ #import "RCTRedBoxController+Internal.h"
23
25
 
24
26
  #if RCT_DEV_MENU
25
27
 
26
- @class RCTRedBoxController;
27
-
28
- @interface UIButton (RCTRedBox)
29
-
30
- @property (nonatomic) RCTRedBoxButtonPressHandler rct_handler;
31
-
32
- - (void)rct_addBlock:(RCTRedBoxButtonPressHandler)handler forControlEvents:(UIControlEvents)controlEvents;
33
-
34
- @end
35
-
36
- @implementation UIButton (RCTRedBox)
37
-
38
- - (RCTRedBoxButtonPressHandler)rct_handler
39
- {
40
- return objc_getAssociatedObject(self, @selector(rct_handler));
41
- }
42
-
43
- - (void)setRct_handler:(RCTRedBoxButtonPressHandler)rct_handler
44
- {
45
- objc_setAssociatedObject(self, @selector(rct_handler), rct_handler, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
46
- }
47
-
48
- - (void)rct_callBlock
49
- {
50
- if (self.rct_handler) {
51
- self.rct_handler();
52
- }
53
- }
54
-
55
- - (void)rct_addBlock:(RCTRedBoxButtonPressHandler)handler forControlEvents:(UIControlEvents)controlEvents
56
- {
57
- self.rct_handler = handler;
58
- [self addTarget:self action:@selector(rct_callBlock) forControlEvents:controlEvents];
59
- }
60
-
61
- @end
62
-
63
- @protocol RCTRedBoxControllerActionDelegate <NSObject>
64
-
65
- - (void)redBoxController:(RCTRedBoxController *)redBoxController openStackFrameInEditor:(RCTJSStackFrame *)stackFrame;
66
- - (void)reloadFromRedBoxController:(RCTRedBoxController *)redBoxController;
67
- - (void)loadExtraDataViewController;
68
-
69
- @end
70
-
71
- @interface RCTRedBoxController : UIViewController <UITableViewDelegate, UITableViewDataSource>
72
- @property (nonatomic, weak) id<RCTRedBoxControllerActionDelegate> actionDelegate;
73
- @end
74
-
75
- @implementation RCTRedBoxController {
76
- UITableView *_stackTraceTableView;
77
- NSString *_lastErrorMessage;
78
- NSArray<RCTJSStackFrame *> *_lastStackTrace;
79
- NSArray<NSString *> *_customButtonTitles;
80
- NSArray<RCTRedBoxButtonPressHandler> *_customButtonHandlers;
81
- int _lastErrorCookie;
82
- }
83
-
84
- - (instancetype)initWithCustomButtonTitles:(NSArray<NSString *> *)customButtonTitles
85
- customButtonHandlers:(NSArray<RCTRedBoxButtonPressHandler> *)customButtonHandlers
86
- {
87
- if (self = [super init]) {
88
- _lastErrorCookie = -1;
89
- _customButtonTitles = customButtonTitles;
90
- _customButtonHandlers = customButtonHandlers;
91
- }
92
-
93
- return self;
94
- }
95
-
96
- - (void)viewDidLoad
97
- {
98
- [super viewDidLoad];
99
- self.view.backgroundColor = [UIColor blackColor];
100
-
101
- const CGFloat buttonHeight = 60;
102
-
103
- CGRect detailsFrame = self.view.bounds;
104
- detailsFrame.size.height -= buttonHeight + (double)[self bottomSafeViewHeight];
105
-
106
- _stackTraceTableView = [[UITableView alloc] initWithFrame:detailsFrame style:UITableViewStylePlain];
107
- _stackTraceTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
108
- _stackTraceTableView.delegate = self;
109
- _stackTraceTableView.dataSource = self;
110
- _stackTraceTableView.backgroundColor = [UIColor clearColor];
111
- _stackTraceTableView.separatorColor = [UIColor colorWithWhite:1 alpha:0.3];
112
- _stackTraceTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
113
- _stackTraceTableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
114
- [self.view addSubview:_stackTraceTableView];
115
-
116
- #if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST
117
- NSString *reloadText = @"Reload\n(\u2318R)";
118
- NSString *dismissText = @"Dismiss\n(ESC)";
119
- NSString *copyText = @"Copy\n(\u2325\u2318C)";
120
- NSString *extraText = @"Extra Info\n(\u2318E)";
121
- #else
122
- NSString *reloadText = @"Reload JS";
123
- NSString *dismissText = @"Dismiss";
124
- NSString *copyText = @"Copy";
125
- NSString *extraText = @"Extra Info";
126
- #endif
127
-
128
- UIButton *dismissButton = [self redBoxButton:dismissText
129
- accessibilityIdentifier:@"redbox-dismiss"
130
- selector:@selector(dismiss)
131
- block:nil];
132
- UIButton *reloadButton = [self redBoxButton:reloadText
133
- accessibilityIdentifier:@"redbox-reload"
134
- selector:@selector(reload)
135
- block:nil];
136
- UIButton *copyButton = [self redBoxButton:copyText
137
- accessibilityIdentifier:@"redbox-copy"
138
- selector:@selector(copyStack)
139
- block:nil];
140
- UIButton *extraButton = [self redBoxButton:extraText
141
- accessibilityIdentifier:@"redbox-extra"
142
- selector:@selector(showExtraDataViewController)
143
- block:nil];
144
-
145
- [NSLayoutConstraint activateConstraints:@[
146
- [dismissButton.heightAnchor constraintEqualToConstant:buttonHeight],
147
- [reloadButton.heightAnchor constraintEqualToConstant:buttonHeight],
148
- [copyButton.heightAnchor constraintEqualToConstant:buttonHeight],
149
- [extraButton.heightAnchor constraintEqualToConstant:buttonHeight]
150
- ]];
151
-
152
- UIStackView *buttonStackView = [[UIStackView alloc] init];
153
- buttonStackView.translatesAutoresizingMaskIntoConstraints = NO;
154
- buttonStackView.axis = UILayoutConstraintAxisHorizontal;
155
- buttonStackView.distribution = UIStackViewDistributionFillEqually;
156
- buttonStackView.alignment = UIStackViewAlignmentTop;
157
- buttonStackView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
158
-
159
- [buttonStackView addArrangedSubview:dismissButton];
160
- [buttonStackView addArrangedSubview:reloadButton];
161
- [buttonStackView addArrangedSubview:copyButton];
162
- [buttonStackView addArrangedSubview:extraButton];
163
-
164
- [self.view addSubview:buttonStackView];
165
-
166
- [NSLayoutConstraint activateConstraints:@[
167
- [buttonStackView.heightAnchor constraintEqualToConstant:buttonHeight + [self bottomSafeViewHeight]],
168
- [buttonStackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
169
- [buttonStackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
170
- [buttonStackView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
171
- ]];
172
-
173
- for (NSUInteger i = 0; i < [_customButtonTitles count]; i++) {
174
- UIButton *button = [self redBoxButton:_customButtonTitles[i]
175
- accessibilityIdentifier:@""
176
- selector:nil
177
- block:_customButtonHandlers[i]];
178
- [button.heightAnchor constraintEqualToConstant:buttonHeight].active = YES;
179
- [buttonStackView addArrangedSubview:button];
180
- }
181
-
182
- UIView *topBorder = [[UIView alloc] init];
183
- topBorder.translatesAutoresizingMaskIntoConstraints = NO;
184
- topBorder.backgroundColor = [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
185
- [topBorder.heightAnchor constraintEqualToConstant:1].active = YES;
186
-
187
- [self.view addSubview:topBorder];
188
-
189
- [NSLayoutConstraint activateConstraints:@[
190
- [topBorder.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
191
- [topBorder.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
192
- [topBorder.bottomAnchor constraintEqualToAnchor:buttonStackView.topAnchor],
193
- ]];
194
- }
195
-
196
- - (UIButton *)redBoxButton:(NSString *)title
197
- accessibilityIdentifier:(NSString *)accessibilityIdentifier
198
- selector:(SEL)selector
199
- block:(RCTRedBoxButtonPressHandler)block
200
- {
201
- UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
202
- button.autoresizingMask =
203
- UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin;
204
- button.accessibilityIdentifier = accessibilityIdentifier;
205
- button.titleLabel.font = [UIFont systemFontOfSize:13];
206
- button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
207
- button.titleLabel.textAlignment = NSTextAlignmentCenter;
208
- button.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
209
- [button setTitle:title forState:UIControlStateNormal];
210
- [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
211
- [button setTitleColor:[UIColor colorWithWhite:1 alpha:0.5] forState:UIControlStateHighlighted];
212
- if (selector) {
213
- [button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
214
- } else if (block) {
215
- [button rct_addBlock:block forControlEvents:UIControlEventTouchUpInside];
216
- }
217
- return button;
218
- }
219
-
220
- - (NSInteger)bottomSafeViewHeight
221
- {
222
- #if TARGET_OS_MACCATALYST
223
- return 0;
224
- #else
225
- return RCTKeyWindow().safeAreaInsets.bottom;
226
- #endif
227
- }
228
-
229
- RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
230
-
231
- - (NSString *)stripAnsi:(NSString *)text
232
- {
233
- NSError *error = nil;
234
- NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\x1b\\[[0-9;]*m"
235
- options:NSRegularExpressionCaseInsensitive
236
- error:&error];
237
- return [regex stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, [text length]) withTemplate:@""];
238
- }
239
-
240
- - (void)showErrorMessage:(NSString *)message
241
- withStack:(NSArray<RCTJSStackFrame *> *)stack
242
- isUpdate:(BOOL)isUpdate
243
- errorCookie:(int)errorCookie
244
- {
245
- // Remove ANSI color codes from the message
246
- NSString *messageWithoutAnsi = [self stripAnsi:message];
247
-
248
- BOOL isRootViewControllerPresented = self.presentingViewController != nil;
249
- // Show if this is a new message, or if we're updating the previous message
250
- BOOL isNew = !isRootViewControllerPresented && !isUpdate;
251
- BOOL isUpdateForSameMessage = !isNew &&
252
- (isRootViewControllerPresented && isUpdate &&
253
- ((errorCookie == -1 && [_lastErrorMessage isEqualToString:messageWithoutAnsi]) ||
254
- (errorCookie == _lastErrorCookie)));
255
- if (isNew || isUpdateForSameMessage) {
256
- _lastStackTrace = stack;
257
- // message is displayed using UILabel, which is unable to render text of
258
- // unlimited length, so we truncate it
259
- _lastErrorMessage = [messageWithoutAnsi substringToIndex:MIN((NSUInteger)10000, messageWithoutAnsi.length)];
260
- _lastErrorCookie = errorCookie;
261
-
262
- [_stackTraceTableView reloadData];
263
-
264
- if (!isRootViewControllerPresented) {
265
- [_stackTraceTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
266
- atScrollPosition:UITableViewScrollPositionTop
267
- animated:NO];
268
- [RCTKeyWindow().rootViewController presentViewController:self animated:YES completion:nil];
269
- }
270
- }
271
- }
272
-
273
- - (void)dismiss
274
- {
275
- [self dismissViewControllerAnimated:YES completion:nil];
276
- }
277
-
278
- - (void)reload
279
- {
280
- if (_actionDelegate != nil) {
281
- [_actionDelegate reloadFromRedBoxController:self];
282
- } else {
283
- // In bridgeless mode `RCTRedBox` gets deallocated, we need to notify listeners anyway.
284
- RCTTriggerReloadCommandListeners(@"Redbox");
285
- [self dismiss];
286
- }
287
- }
288
-
289
- - (void)showExtraDataViewController
290
- {
291
- [_actionDelegate loadExtraDataViewController];
292
- }
293
-
294
- - (void)copyStack
295
- {
296
- NSMutableString *fullStackTrace;
297
-
298
- if (_lastErrorMessage != nil) {
299
- fullStackTrace = [_lastErrorMessage mutableCopy];
300
- [fullStackTrace appendString:@"\n\n"];
301
- } else {
302
- fullStackTrace = [NSMutableString string];
303
- }
304
-
305
- for (RCTJSStackFrame *stackFrame in _lastStackTrace) {
306
- [fullStackTrace appendString:[NSString stringWithFormat:@"%@\n", stackFrame.methodName]];
307
- if (stackFrame.file) {
308
- [fullStackTrace appendFormat:@" %@\n", [self formatFrameSource:stackFrame]];
309
- }
310
- }
311
- UIPasteboard *pb = [UIPasteboard generalPasteboard];
312
- [pb setString:fullStackTrace];
313
- }
314
-
315
- - (NSString *)formatFrameSource:(RCTJSStackFrame *)stackFrame
316
- {
317
- NSString *fileName = RCTNilIfNull(stackFrame.file) ? [stackFrame.file lastPathComponent] : @"<unknown file>";
318
- NSString *lineInfo = [NSString stringWithFormat:@"%@:%lld", fileName, (long long)stackFrame.lineNumber];
319
-
320
- if (stackFrame.column != 0) {
321
- lineInfo = [lineInfo stringByAppendingFormat:@":%lld", (long long)stackFrame.column];
322
- }
323
- return lineInfo;
324
- }
325
-
326
- #pragma mark - TableView
327
-
328
- - (NSInteger)numberOfSectionsInTableView:(__unused UITableView *)tableView
329
- {
330
- return 2;
331
- }
332
-
333
- - (NSInteger)tableView:(__unused UITableView *)tableView numberOfRowsInSection:(NSInteger)section
334
- {
335
- return section == 0 ? 1 : _lastStackTrace.count;
336
- }
337
-
338
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
339
- {
340
- if (indexPath.section == 0) {
341
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"msg-cell"];
342
- return [self reuseCell:cell forErrorMessage:_lastErrorMessage];
343
- }
344
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
345
- NSUInteger index = indexPath.row;
346
- RCTJSStackFrame *stackFrame = _lastStackTrace[index];
347
- return [self reuseCell:cell forStackFrame:stackFrame];
348
- }
349
-
350
- - (UITableViewCell *)reuseCell:(UITableViewCell *)cell forErrorMessage:(NSString *)message
351
- {
352
- if (!cell) {
353
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"msg-cell"];
354
- cell.textLabel.accessibilityIdentifier = @"redbox-error";
355
- cell.textLabel.textColor = [UIColor whiteColor];
356
-
357
- // Prefer a monofont for formatting messages that were designed
358
- // to be displayed in a terminal.
359
- cell.textLabel.font = [UIFont monospacedSystemFontOfSize:14 weight:UIFontWeightBold];
360
-
361
- cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
362
- cell.textLabel.numberOfLines = 0;
363
- cell.detailTextLabel.textColor = [UIColor whiteColor];
364
- cell.backgroundColor = [UIColor colorWithRed:0.82 green:0.10 blue:0.15 alpha:1.0];
365
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
366
- }
367
-
368
- cell.textLabel.text = message;
369
-
370
- return cell;
371
- }
372
-
373
- - (UITableViewCell *)reuseCell:(UITableViewCell *)cell forStackFrame:(RCTJSStackFrame *)stackFrame
374
- {
375
- if (!cell) {
376
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
377
- cell.textLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:14];
378
- cell.textLabel.lineBreakMode = NSLineBreakByCharWrapping;
379
- cell.textLabel.numberOfLines = 2;
380
- cell.detailTextLabel.textColor = [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
381
- cell.detailTextLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:11];
382
- cell.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
383
- cell.backgroundColor = [UIColor clearColor];
384
- cell.selectedBackgroundView = [UIView new];
385
- cell.selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];
386
- }
387
-
388
- cell.textLabel.text = stackFrame.methodName ?: @"(unnamed method)";
389
- if (stackFrame.file) {
390
- cell.detailTextLabel.text = [self formatFrameSource:stackFrame];
391
- } else {
392
- cell.detailTextLabel.text = @"";
393
- }
394
- cell.textLabel.textColor = stackFrame.collapse ? [UIColor lightGrayColor] : [UIColor whiteColor];
395
- cell.detailTextLabel.textColor = stackFrame.collapse ? [UIColor colorWithRed:0.50 green:0.50 blue:0.50 alpha:1.0]
396
- : [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
397
- return cell;
398
- }
399
-
400
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
401
- {
402
- if (indexPath.section == 0) {
403
- NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
404
- paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
405
-
406
- NSDictionary *attributes =
407
- @{NSFontAttributeName : [UIFont boldSystemFontOfSize:16], NSParagraphStyleAttributeName : paragraphStyle};
408
- CGRect boundingRect =
409
- [_lastErrorMessage boundingRectWithSize:CGSizeMake(tableView.frame.size.width - 30, CGFLOAT_MAX)
410
- options:NSStringDrawingUsesLineFragmentOrigin
411
- attributes:attributes
412
- context:nil];
413
- return ceil(boundingRect.size.height) + 40;
414
- } else {
415
- return 50;
416
- }
417
- }
418
-
419
- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
420
- {
421
- if (indexPath.section == 1) {
422
- NSUInteger row = indexPath.row;
423
- RCTJSStackFrame *stackFrame = _lastStackTrace[row];
424
- [_actionDelegate redBoxController:self openStackFrameInEditor:stackFrame];
425
- }
426
- [tableView deselectRowAtIndexPath:indexPath animated:YES];
427
- }
428
-
429
- #pragma mark - Key commands
430
-
431
- - (NSArray<UIKeyCommand *> *)keyCommands
432
- {
433
- // NOTE: We could use RCTKeyCommands for this, but since
434
- // we control this window, we can use the standard, non-hacky
435
- // mechanism instead
436
-
437
- return @[
438
- // Dismiss red box
439
- [UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:0 action:@selector(dismiss)],
440
-
441
- // Reload
442
- [UIKeyCommand keyCommandWithInput:@"r" modifierFlags:UIKeyModifierCommand action:@selector(reload)],
443
-
444
- // Copy = Cmd-Option C since Cmd-C in the simulator copies the pasteboard from
445
- // the simulator to the desktop pasteboard.
446
- [UIKeyCommand keyCommandWithInput:@"c"
447
- modifierFlags:UIKeyModifierCommand | UIKeyModifierAlternate
448
- action:@selector(copyStack)],
449
-
450
- // Extra data
451
- [UIKeyCommand keyCommandWithInput:@"e"
452
- modifierFlags:UIKeyModifierCommand
453
- action:@selector(showExtraDataViewController)]
454
- ];
455
- }
456
-
457
- - (BOOL)canBecomeFirstResponder
458
- {
459
- return YES;
460
- }
461
-
462
- @end
463
-
464
28
  @interface RCTRedBox () <
465
29
  RCTInvalidating,
466
30
  RCTRedBoxControllerActionDelegate,
@@ -469,7 +33,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
469
33
  @end
470
34
 
471
35
  @implementation RCTRedBox {
472
- RCTRedBoxController *_controller;
36
+ id<RCTRedBoxControlling> _controller;
473
37
  NSMutableArray<id<RCTErrorCustomizer>> *_errorCustomizers;
474
38
  RCTRedBoxExtraDataViewController *_extraDataViewController;
475
39
  NSMutableArray<NSString *> *_customButtonTitles;
@@ -601,6 +165,14 @@ RCT_EXPORT_MODULE()
601
165
  [self showErrorMessage:message withParsedStack:stack isUpdate:YES errorCookie:errorCookie];
602
166
  }
603
167
 
168
+ - (id<RCTRedBox2Controlling>)_redBox2Controller
169
+ {
170
+ if ([_controller conformsToProtocol:@protocol(RCTRedBox2Controlling)]) {
171
+ return (id<RCTRedBox2Controlling>)_controller;
172
+ }
173
+ return nil;
174
+ }
175
+
604
176
  - (void)showErrorMessage:(NSString *)message
605
177
  withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
606
178
  isUpdate:(BOOL)isUpdate
@@ -617,14 +189,21 @@ RCT_EXPORT_MODULE()
617
189
  [[self->_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"collectRedBoxExtraData"
618
190
  body:nil];
619
191
  #pragma clang diagnostic pop
620
- if (!self->_controller) {
621
- self->_controller = [[RCTRedBoxController alloc] initWithCustomButtonTitles:self->_customButtonTitles
622
- customButtonHandlers:self->_customButtonHandlers];
623
- self->_controller.actionDelegate = self;
624
- }
625
192
 
626
193
  RCTErrorInfo *errorInfo = [[RCTErrorInfo alloc] initWithErrorMessage:message stack:stack];
627
194
  errorInfo = [self _customizeError:errorInfo];
195
+
196
+ if (self->_controller == nullptr) {
197
+ if (facebook::react::ReactNativeFeatureFlags::redBoxV2IOS()) {
198
+ self->_controller = [[RCTRedBox2Controller alloc] initWithCustomButtonTitles:self->_customButtonTitles
199
+ customButtonHandlers:self->_customButtonHandlers];
200
+ } else {
201
+ self->_controller = [[RCTRedBoxController alloc] initWithCustomButtonTitles:self->_customButtonTitles
202
+ customButtonHandlers:self->_customButtonHandlers];
203
+ }
204
+ self->_controller.actionDelegate = self;
205
+ }
206
+ [self _redBox2Controller].bundleURL = self->_overrideBundleURL ?: self->_bundleManager.bundleURL;
628
207
  [self->_controller showErrorMessage:errorInfo.errorMessage
629
208
  withStack:errorInfo.stack
630
209
  isUpdate:isUpdate
@@ -635,9 +214,10 @@ RCT_EXPORT_MODULE()
635
214
  - (void)loadExtraDataViewController
636
215
  {
637
216
  dispatch_async(dispatch_get_main_queue(), ^{
217
+ UIViewController *controller = static_cast<UIViewController *>(self->_controller);
638
218
  // Make sure the CMD+E shortcut doesn't call this twice
639
- if (self->_extraDataViewController != nil && ![self->_controller presentedViewController]) {
640
- [self->_controller presentViewController:self->_extraDataViewController animated:YES completion:nil];
219
+ if (self->_extraDataViewController != nil && ([controller presentedViewController] == nullptr)) {
220
+ [controller presentViewController:self->_extraDataViewController animated:YES completion:nil];
641
221
  }
642
222
  });
643
223
  }
@@ -659,7 +239,7 @@ RCT_EXPORT_METHOD(dismiss)
659
239
  [self dismiss];
660
240
  }
661
241
 
662
- - (void)redBoxController:(__unused RCTRedBoxController *)redBoxController
242
+ - (void)redBoxController:(__unused UIViewController *)redBoxController
663
243
  openStackFrameInEditor:(RCTJSStackFrame *)stackFrame
664
244
  {
665
245
  NSURL *const bundleURL = _overrideBundleURL ?: _bundleManager.bundleURL;
@@ -686,7 +266,7 @@ RCT_EXPORT_METHOD(dismiss)
686
266
  [self reloadFromRedBoxController:nil];
687
267
  }
688
268
 
689
- - (void)reloadFromRedBoxController:(__unused RCTRedBoxController *)redBoxController
269
+ - (void)reloadFromRedBoxController:(__unused UIViewController *)redBoxController
690
270
  {
691
271
  if (_overrideReloadAction) {
692
272
  _overrideReloadAction();
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #import <UIKit/UIKit.h>
9
+
10
+ /**
11
+ * Parses ANSI escape sequences in text and produces an NSAttributedString
12
+ * with the corresponding foreground/background colors applied.
13
+ *
14
+ * Uses the Afterglow color theme (matching LogBox's AnsiHighlight.js).
15
+ */
16
+ @interface RCTRedBox2AnsiParser : NSObject
17
+
18
+ + (NSAttributedString *)attributedStringFromAnsiText:(NSString *)text
19
+ baseFont:(UIFont *)font
20
+ baseColor:(UIColor *)color;
21
+
22
+ @end