Skip to content

Commit

Permalink
Scheduling Profiler marks should include thrown Errors (#22419)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Vaughn authored Sep 24, 2021
1 parent af87f5a commit 1c73cee
Show file tree
Hide file tree
Showing 12 changed files with 417 additions and 85 deletions.
113 changes: 41 additions & 72 deletions packages/react-devtools-scheduling-profiler/src/CanvasPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
SchedulingEventsView,
SnapshotsView,
SuspenseEventsView,
ThrownErrorsView,
TimeAxisMarkersView,
UserTimingMarksView,
} from './content-views';
Expand Down Expand Up @@ -138,6 +139,7 @@ const EMPTY_CONTEXT_INFO: ReactHoverContextInfo = {
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
thrownError: null,
userTimingMark: null,
};

Expand Down Expand Up @@ -178,6 +180,7 @@ function AutoSizedCanvas({
const flamechartViewRef = useRef(null);
const networkMeasuresViewRef = useRef(null);
const snapshotsViewRef = useRef(null);
const thrownErrorsViewRef = useRef(null);

const {hideMenu: hideContextMenu} = useContext(RegistryContext);

Expand Down Expand Up @@ -271,6 +274,20 @@ function AutoSizedCanvas({
true,
);

let thrownErrorsViewWrapper = null;
if (data.thrownErrors.length > 0) {
const thrownErrorsView = new ThrownErrorsView(
surface,
defaultFrame,
data,
);
thrownErrorsViewRef.current = thrownErrorsView;
thrownErrorsViewWrapper = createViewHelper(
thrownErrorsView,
'thrown errors',
);
}

const schedulingEventsView = new SchedulingEventsView(
surface,
defaultFrame,
Expand Down Expand Up @@ -382,6 +399,9 @@ function AutoSizedCanvas({
}
rootView.addSubview(nativeEventsViewWrapper);
rootView.addSubview(schedulingEventsViewWrapper);
if (thrownErrorsViewWrapper !== null) {
rootView.addSubview(thrownErrorsViewWrapper);
}
if (suspenseEventsViewWrapper !== null) {
rootView.addSubview(suspenseEventsViewWrapper);
}
Expand Down Expand Up @@ -461,14 +481,7 @@ function AutoSizedCanvas({
userTimingMarksView.onHover = userTimingMark => {
if (!hoveredEvent || hoveredEvent.userTimingMark !== userTimingMark) {
setHoveredEvent({
componentMeasure: null,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
...EMPTY_CONTEXT_INFO,
userTimingMark,
});
}
Expand All @@ -480,15 +493,8 @@ function AutoSizedCanvas({
nativeEventsView.onHover = nativeEvent => {
if (!hoveredEvent || hoveredEvent.nativeEvent !== nativeEvent) {
setHoveredEvent({
componentMeasure: null,
flamechartStackFrame: null,
measure: null,
...EMPTY_CONTEXT_INFO,
nativeEvent,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
userTimingMark: null,
});
}
};
Expand All @@ -499,15 +505,8 @@ function AutoSizedCanvas({
schedulingEventsView.onHover = schedulingEvent => {
if (!hoveredEvent || hoveredEvent.schedulingEvent !== schedulingEvent) {
setHoveredEvent({
componentMeasure: null,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
...EMPTY_CONTEXT_INFO,
schedulingEvent,
snapshot: null,
suspenseEvent: null,
userTimingMark: null,
});
}
};
Expand All @@ -518,15 +517,8 @@ function AutoSizedCanvas({
suspenseEventsView.onHover = suspenseEvent => {
if (!hoveredEvent || hoveredEvent.suspenseEvent !== suspenseEvent) {
setHoveredEvent({
componentMeasure: null,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
...EMPTY_CONTEXT_INFO,
suspenseEvent,
userTimingMark: null,
});
}
};
Expand All @@ -537,15 +529,8 @@ function AutoSizedCanvas({
reactMeasuresView.onHover = measure => {
if (!hoveredEvent || hoveredEvent.measure !== measure) {
setHoveredEvent({
componentMeasure: null,
flamechartStackFrame: null,
...EMPTY_CONTEXT_INFO,
measure,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
userTimingMark: null,
});
}
};
Expand All @@ -559,15 +544,8 @@ function AutoSizedCanvas({
hoveredEvent.componentMeasure !== componentMeasure
) {
setHoveredEvent({
...EMPTY_CONTEXT_INFO,
componentMeasure,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
userTimingMark: null,
});
}
};
Expand All @@ -578,15 +556,8 @@ function AutoSizedCanvas({
snapshotsView.onHover = snapshot => {
if (!hoveredEvent || hoveredEvent.snapshot !== snapshot) {
setHoveredEvent({
componentMeasure: null,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
...EMPTY_CONTEXT_INFO,
snapshot,
suspenseEvent: null,
userTimingMark: null,
});
}
};
Expand All @@ -600,15 +571,8 @@ function AutoSizedCanvas({
hoveredEvent.flamechartStackFrame !== flamechartStackFrame
) {
setHoveredEvent({
componentMeasure: null,
...EMPTY_CONTEXT_INFO,
flamechartStackFrame,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
userTimingMark: null,
});
}
});
Expand All @@ -619,15 +583,20 @@ function AutoSizedCanvas({
networkMeasuresView.onHover = networkMeasure => {
if (!hoveredEvent || hoveredEvent.networkMeasure !== networkMeasure) {
setHoveredEvent({
componentMeasure: null,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
...EMPTY_CONTEXT_INFO,
networkMeasure,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
userTimingMark: null,
});
}
};
}

const {current: thrownErrorsView} = thrownErrorsViewRef;
if (thrownErrorsView) {
thrownErrorsView.onHover = thrownError => {
if (!hoveredEvent || hoveredEvent.thrownError !== thrownError) {
setHoveredEvent({
...EMPTY_CONTEXT_INFO,
thrownError,
});
}
};
Expand Down
30 changes: 30 additions & 0 deletions packages/react-devtools-scheduling-profiler/src/EventTooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
SchedulingEvent,
Snapshot,
SuspenseEvent,
ThrownError,
UserTimingMark,
} from './types';

Expand Down Expand Up @@ -92,6 +93,7 @@ export default function EventTooltip({
schedulingEvent,
snapshot,
suspenseEvent,
thrownError,
userTimingMark,
} = hoveredEvent;

Expand All @@ -118,6 +120,8 @@ export default function EventTooltip({
content = <TooltipFlamechartNode stackFrame={flamechartStackFrame} />;
} else if (userTimingMark !== null) {
content = <TooltipUserTimingMark mark={userTimingMark} />;
} else if (thrownError !== null) {
content = <TooltipThrownError thrownError={thrownError} />;
}

if (content !== null) {
Expand Down Expand Up @@ -436,3 +440,29 @@ const TooltipUserTimingMark = ({mark}: {|mark: UserTimingMark|}) => {
</div>
);
};

const TooltipThrownError = ({thrownError}: {|thrownError: ThrownError|}) => {
const {componentName, message, phase, timestamp} = thrownError;
const label = `threw an error during ${phase}`;
return (
<div className={styles.TooltipSection}>
{componentName && (
<span className={styles.ComponentName}>
{trimString(componentName, 100)}
</span>
)}
<span className={styles.UserTimingLabel}>{label}</span>
<div className={styles.Divider} />
<div className={styles.DetailsGrid}>
<div className={styles.DetailsGridLabel}>Timestamp:</div>
<div>{formatTimestamp(timestamp)}</div>
{message !== '' && (
<>
<div className={styles.DetailsGridLabel}>Error:</div>
<div>{message}</div>
</>
)}
</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,23 @@ export class ReactMeasuresView extends View {
// Commit phase rects are overlapped by layout and passive rects,
// and it looks bad if text flows underneath/behind these overlayed rects.
if (nextMeasure != null) {
textRect = {
...measureRect,
size: {
width:
timestampToPosition(nextMeasure.timestamp, scaleFactor, frame) -
x,
height: REACT_MEASURE_HEIGHT,
},
};
// This clipping shouldn't apply for measures that don't overlap though,
// like passive effects that are processed after a delay,
// or if there are now layout or passive effects and the next measure is render or idle.
if (nextMeasure.timestamp < measure.timestamp + measure.duration) {
textRect = {
...measureRect,
size: {
width:
timestampToPosition(
nextMeasure.timestamp,
scaleFactor,
frame,
) - x,
height: REACT_MEASURE_HEIGHT,
},
};
}
}
break;
case 'render-idle':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export class SchedulingEventsView extends View {
};
if (rectIntersectsRect(borderFrame, visibleArea)) {
const borderDrawableRect = intersectionOfRects(borderFrame, visibleArea);
context.fillStyle = COLORS.PRIORITY_BORDER;
context.fillStyle = COLORS.REACT_WORK_BORDER;
context.fillRect(
borderDrawableRect.origin.x,
borderDrawableRect.origin.y,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ export class SuspenseEventsView extends View {
borderFrame,
visibleArea,
);
context.fillStyle = COLORS.PRIORITY_BORDER;
context.fillStyle = COLORS.REACT_WORK_BORDER;
context.fillRect(
borderDrawableRect.origin.x,
borderDrawableRect.origin.y,
Expand Down
Loading

0 comments on commit 1c73cee

Please sign in to comment.