Skip to content
Permalink
Browse files
Render collapsed frames in RedBox
Summary:
Renders frames in RedBox in a greyed-out style when their `collapse` field is set to `true`. This avoids outright hiding information in the stack trace while still drawing attention to frames that are likely to be more meaningful.

Changelog: [General] [Changed] - Render collapsed JavaScript frames in RedBox

Reviewed By: rickhanlonii

Differential Revision: D18039438

fbshipit-source-id: 527588f11c0bff495842be7036cd1293bab65eb9
  • Loading branch information
motiz88 authored and facebook-github-bot committed Oct 22, 2019
1 parent 25e4265 commit 468d1a2d2e6c72d7c6d435ecaad8499997584de6
Showing 7 changed files with 40 additions and 14 deletions.
@@ -106,12 +106,9 @@ function reportException(e: ExtendedError, isFatal: boolean) {
symbolicateStackTrace(stack)
.then(prettyStack => {
if (prettyStack) {
const stackWithoutCollapsedFrames = prettyStack.filter(
frame => !frame.collapse,
);
NativeExceptionsManager.updateExceptionMessage(
data.message,
stackWithoutCollapsedFrames,
prettyStack,
currentExceptionID,
);
} else {
@@ -13,8 +13,9 @@
@property (nonatomic, copy, readonly) NSString *file;
@property (nonatomic, readonly) NSInteger lineNumber;
@property (nonatomic, readonly) NSInteger column;
@property (nonatomic, readonly) NSInteger collapse;

This comment has been minimized.

Copy link
@alloy

alloy Feb 5, 2020

Contributor

@motiz88 Any specific reason this isn’t a BOOL? (I’m working through build warnings and noticed this.)


- (instancetype)initWithMethodName:(NSString *)methodName file:(NSString *)file lineNumber:(NSInteger)lineNumber column:(NSInteger)column;
- (instancetype)initWithMethodName:(NSString *)methodName file:(NSString *)file lineNumber:(NSInteger)lineNumber column:(NSInteger)column collapse:(NSInteger)collapse;
- (NSDictionary *)toDictionary;

+ (instancetype)stackFrameWithLine:(NSString *)line;
@@ -53,13 +53,14 @@

@implementation RCTJSStackFrame

- (instancetype)initWithMethodName:(NSString *)methodName file:(NSString *)file lineNumber:(NSInteger)lineNumber column:(NSInteger)column
- (instancetype)initWithMethodName:(NSString *)methodName file:(NSString *)file lineNumber:(NSInteger)lineNumber column:(NSInteger)column collapse:(NSInteger)collapse
{
if (self = [super init]) {
_methodName = methodName;
_file = file;
_lineNumber = lineNumber;
_column = column;
_collapse = collapse;
}
return self;
}
@@ -70,7 +71,8 @@ - (NSDictionary *)toDictionary
@"methodName": RCTNullIfNil(self.methodName),
@"file": RCTNullIfNil(self.file),
@"lineNumber": @(self.lineNumber),
@"column": @(self.column)
@"column": @(self.column),
@"collapse": @(self.collapse)
};
}

@@ -91,15 +93,17 @@ + (instancetype)stackFrameWithLine:(NSString *)line
return [[self alloc] initWithMethodName:methodName
file:file
lineNumber:[lineNumber integerValue]
column:[column integerValue]];
column:[column integerValue]
collapse:@NO];
}

+ (instancetype)stackFrameWithDictionary:(NSDictionary *)dict
{
return [[self alloc] initWithMethodName:RCTNilIfNull(dict[@"methodName"])
file:dict[@"file"]
lineNumber:[RCTNilIfNull(dict[@"lineNumber"]) integerValue]
column:[RCTNilIfNull(dict[@"column"]) integerValue]];
column:[RCTNilIfNull(dict[@"column"]) integerValue]
collapse:[RCTNilIfNull(dict[@"collapse"]) integerValue]];
}

+ (NSArray<RCTJSStackFrame *> *)stackFramesWithLines:(NSString *)lines
@@ -353,7 +353,6 @@ - (UITableViewCell *)reuseCell:(UITableViewCell *)cell forStackFrame:(RCTJSStack
{
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:14];
cell.textLabel.lineBreakMode = NSLineBreakByCharWrapping;
cell.textLabel.numberOfLines = 2;
@@ -371,6 +370,10 @@ - (UITableViewCell *)reuseCell:(UITableViewCell *)cell forStackFrame:(RCTJSStack
} else {
cell.detailTextLabel.text = @"";
}
cell.textLabel.textColor = stackFrame.collapse ? [UIColor lightGrayColor] : [UIColor whiteColor];
cell.detailTextLabel.textColor = stackFrame.collapse ?
[UIColor colorWithRed:0.50 green:0.50 blue:0.50 alpha:1.0] :
[UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
return cell;
}

@@ -186,6 +186,8 @@ public View getView(int position, View convertView, ViewGroup parent) {
FrameViewHolder holder = (FrameViewHolder) convertView.getTag();
holder.mMethodView.setText(frame.getMethod());
holder.mFileView.setText(StackTraceHelper.formatFrameSource(frame));
holder.mMethodView.setTextColor(frame.isCollapsed() ? 0xFFAAAAAA : Color.WHITE);
holder.mFileView.setTextColor(frame.isCollapsed() ? 0xFF808080 : 0xFFB3B3B3);
return convertView;
}
}
@@ -38,13 +38,19 @@ public static class StackFrameImpl implements StackFrame {
private final int mLine;
private final int mColumn;
private final String mFileName;
private final boolean mIsCollapsed;

private StackFrameImpl(String file, String method, int line, int column) {
private StackFrameImpl(String file, String method, int line, int column, boolean isCollapsed) {
mFile = file;
mMethod = method;
mLine = line;
mColumn = column;
mFileName = file != null ? new File(file).getName() : "";
mIsCollapsed = isCollapsed;
}

private StackFrameImpl(String file, String method, int line, int column) {
this(file, method, line, column, false);
}

private StackFrameImpl(String file, String fileName, String method, int line, int column) {
@@ -53,6 +59,7 @@ private StackFrameImpl(String file, String fileName, String method, int line, in
mMethod = method;
mLine = line;
mColumn = column;
mIsCollapsed = false;
}

/**
@@ -90,14 +97,19 @@ public String getFileName() {
return mFileName;
}

public boolean isCollapsed() {
return mIsCollapsed;
}

/** Convert the stack frame to a JSON representation. */
public JSONObject toJSON() {
return new JSONObject(
MapBuilder.of(
"file", getFile(),
"methodName", getMethod(),
"lineNumber", getLine(),
"column", getColumn()));
"column", getColumn(),
"collapse", isCollapsed()));
}
}

@@ -114,6 +126,8 @@ public static StackFrame[] convertJsStackTrace(@Nullable ReadableArray stack) {
ReadableMap frame = stack.getMap(i);
String methodName = frame.getString("methodName");
String fileName = frame.getString("file");
boolean collapse =
frame.hasKey("collapse") && !frame.isNull("collapse") && frame.getBoolean("collapse");
int lineNumber = -1;
if (frame.hasKey(LINE_NUMBER_KEY) && !frame.isNull(LINE_NUMBER_KEY)) {
lineNumber = frame.getInt(LINE_NUMBER_KEY);
@@ -122,7 +136,7 @@ public static StackFrame[] convertJsStackTrace(@Nullable ReadableArray stack) {
if (frame.hasKey(COLUMN_KEY) && !frame.isNull(COLUMN_KEY)) {
columnNumber = frame.getInt(COLUMN_KEY);
}
result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber);
result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber, collapse);
} else if (type == ReadableType.String) {
result[i] = new StackFrameImpl(null, stack.getString(i), -1, -1);
}
@@ -150,7 +164,9 @@ public static StackFrame[] convertJsStackTrace(JSONArray stack) {
if (frame.has(COLUMN_KEY) && !frame.isNull(COLUMN_KEY)) {
columnNumber = frame.getInt(COLUMN_KEY);
}
result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber);
boolean collapse =
frame.has("collapse") && !frame.isNull("collapse") && frame.getBoolean("collapse");
result[i] = new StackFrameImpl(fileName, methodName, lineNumber, columnNumber, collapse);
}
} catch (JSONException exception) {
throw new RuntimeException(exception);
@@ -36,6 +36,9 @@ public interface StackFrame {
*/
public String getFileName();

/** Whether this frame is collapsed. */
public boolean isCollapsed();

/** Convert the stack frame to a JSON representation. */
public JSONObject toJSON();
}

0 comments on commit 468d1a2

Please sign in to comment.