aboutsummaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorSteve Golton <stevegolton@google.com>2024-05-08 17:13:20 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-05-08 17:13:20 +0000
commitb9bf2c223d322173fb029dabce022e0c679d260b (patch)
tree12ef89a35a60997ea0a091b3ce3ca474e0b92ed8 /ui
parent96f6035f4aeaf14567e2db67f85d58aa125d4a02 (diff)
parent29be9fa35ffa474041465bcfbc51e25aee932ceb (diff)
downloadperfetto-b9bf2c223d322173fb029dabce022e0c679d260b.tar.gz
Merge "ui: Fix crash when marking an incomplete thread_state slice" into main
Diffstat (limited to 'ui')
-rw-r--r--ui/src/frontend/app.ts5
-rw-r--r--ui/src/frontend/globals.ts88
-rw-r--r--ui/src/frontend/keyboard_event_handler.ts5
3 files changed, 55 insertions, 43 deletions
diff --git a/ui/src/frontend/app.ts b/ui/src/frontend/app.ts
index 3dea6fd21..ddc682625 100644
--- a/ui/src/frontend/app.ts
+++ b/ui/src/frontend/app.ts
@@ -20,7 +20,7 @@ import {findRef} from '../base/dom_utils';
import {FuzzyFinder} from '../base/fuzzy';
import {assertExists} from '../base/logging';
import {undoCommonChatAppReplacements} from '../base/string_utils';
-import {duration, Span, Time, time, TimeSpan} from '../base/time';
+import {duration, Span, time, TimeSpan} from '../base/time';
import {Actions} from '../common/actions';
import {getLegacySelection} from '../common/state';
import {runQuery} from '../common/queries';
@@ -62,6 +62,7 @@ import {
lockSliceSpan,
moveByFocusedFlow,
} from './keyboard_event_handler';
+import {exists} from '../base/utils';
function renderPermalink(): m.Children {
const permalink = globals.state.permalink;
@@ -1009,7 +1010,7 @@ export class App implements m.ClassComponent {
// there is no current selection.
function getTimeSpanOfSelectionOrVisibleWindow(): Span<time, duration> {
const range = globals.findTimeRangeOfSelection();
- if (range.end !== Time.INVALID && range.start !== Time.INVALID) {
+ if (exists(range)) {
return new TimeSpan(range.start, range.end);
} else {
return globals.stateVisibleTime();
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 68e16a559..50b2286cb 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -55,6 +55,7 @@ import {ServiceWorkerController} from './service_worker_controller';
import {SliceSqlId} from './sql_types';
import {PxSpan, TimeScale} from './time_scale';
import {SelectionManager, LegacySelection} from '../core/selection_manager';
+import {exists} from '../base/utils';
const INSTANT_FOCUS_DURATION = 1n;
const INCOMPLETE_SLICE_DURATION = 30_000n;
@@ -786,46 +787,25 @@ class Globals {
return Time.sub(ts, this.timestampOffset());
}
- findTimeRangeOfSelection(): {start: time; end: time} {
+ findTimeRangeOfSelection(): {start: time; end: time} | undefined {
const selection = getLegacySelection(this.state);
- let start = Time.INVALID;
- let end = Time.INVALID;
if (selection === null) {
- return {start, end};
- } else if (
- selection.kind === 'SLICE' ||
- selection.kind === 'CHROME_SLICE'
- ) {
+ return undefined;
+ }
+
+ if (selection.kind === 'SLICE' || selection.kind === 'CHROME_SLICE') {
const slice = this.sliceDetails;
- if (slice.ts && slice.dur !== undefined && slice.dur > 0) {
- start = slice.ts;
- end = Time.add(start, slice.dur);
- } else if (slice.ts) {
- start = slice.ts;
- // This will handle either:
- // a)slice.dur === -1 -> unfinished slice
- // b)slice.dur === 0 -> instant event
- end =
- slice.dur === -1n
- ? Time.add(start, INCOMPLETE_SLICE_DURATION)
- : Time.add(start, INSTANT_FOCUS_DURATION);
- }
+ return findTimeRangeOfSlice(slice);
} else if (selection.kind === 'THREAD_STATE') {
const threadState = this.threadStateDetails;
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
- if (threadState.ts && threadState.dur) {
- start = threadState.ts;
- end = Time.add(start, threadState.dur);
- }
+ return findTimeRangeOfSlice(threadState);
} else if (selection.kind === 'COUNTER') {
- start = selection.leftTs;
- end = selection.rightTs;
+ return {start: selection.leftTs, end: selection.rightTs};
} else if (selection.kind === 'AREA') {
const selectedArea = this.state.areas[selection.areaId];
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (selectedArea) {
- start = selectedArea.start;
- end = selectedArea.end;
+ return {start: selectedArea.start, end: selectedArea.end};
}
} else if (selection.kind === 'NOTE') {
const selectedNote = this.state.notes[selection.id];
@@ -833,21 +813,21 @@ class Globals {
// above in the AREA case.
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (selectedNote && selectedNote.noteType === 'DEFAULT') {
- start = selectedNote.timestamp;
- end = Time.add(selectedNote.timestamp, INSTANT_FOCUS_DURATION);
+ return {
+ start: selectedNote.timestamp,
+ end: Time.add(selectedNote.timestamp, INSTANT_FOCUS_DURATION),
+ };
}
} else if (selection.kind === 'LOG') {
// TODO(hjd): Make focus selection work for logs.
} else if (selection.kind === 'GENERIC_SLICE') {
- start = selection.start;
- if (selection.duration > 0) {
- end = Time.add(start, selection.duration);
- } else {
- end = Time.add(start, INSTANT_FOCUS_DURATION);
- }
+ return findTimeRangeOfSlice({
+ ts: selection.start,
+ dur: selection.duration,
+ });
}
- return {start, end};
+ return undefined;
}
panToTimestamp(ts: time): void {
@@ -855,4 +835,34 @@ class Globals {
}
}
+interface SliceLike {
+ ts: time;
+ dur: duration;
+}
+
+// Returns the start and end points of a slice-like object If slice is instant
+// or incomplete, dummy time will be returned which instead.
+function findTimeRangeOfSlice(slice: Partial<SliceLike>): {
+ start: time;
+ end: time;
+} {
+ if (exists(slice.ts) && exists(slice.dur)) {
+ if (slice.dur === -1n) {
+ return {
+ start: slice.ts,
+ end: Time.add(slice.ts, INCOMPLETE_SLICE_DURATION),
+ };
+ } else if (slice.dur === 0n) {
+ return {
+ start: slice.ts,
+ end: Time.add(slice.ts, INSTANT_FOCUS_DURATION),
+ };
+ } else {
+ return {start: slice.ts, end: Time.add(slice.ts, slice.dur)};
+ }
+ } else {
+ return {start: Time.INVALID, end: Time.INVALID};
+ }
+}
+
export const globals = new Globals();
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 59f1d95c1..8ca508c65 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {exists} from '../base/utils';
import {Actions} from '../common/actions';
import {Area, getLegacySelection} from '../common/state';
@@ -119,7 +120,7 @@ export function moveByFocusedFlow(direction: Direction): void {
export function lockSliceSpan(persistent = false) {
const range = globals.findTimeRangeOfSelection();
const currentSelection = getLegacySelection(globals.state);
- if (range.start !== -1n && range.end !== -1n && currentSelection !== null) {
+ if (exists(range) && currentSelection !== null) {
const tracks = currentSelection.trackKey ? [currentSelection.trackKey] : [];
const area: Area = {start: range.start, end: range.end, tracks};
globals.dispatch(Actions.markArea({area, persistent}));
@@ -131,7 +132,7 @@ export function findCurrentSelection() {
if (selection === null) return;
const range = globals.findTimeRangeOfSelection();
- if (range.start !== -1n && range.end !== -1n) {
+ if (exists(range)) {
focusHorizontalRange(range.start, range.end);
}