diff options
author | Steve Golton <stevegolton@google.com> | 2024-05-08 17:13:20 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-05-08 17:13:20 +0000 |
commit | b9bf2c223d322173fb029dabce022e0c679d260b (patch) | |
tree | 12ef89a35a60997ea0a091b3ce3ca474e0b92ed8 /ui | |
parent | 96f6035f4aeaf14567e2db67f85d58aa125d4a02 (diff) | |
parent | 29be9fa35ffa474041465bcfbc51e25aee932ceb (diff) | |
download | perfetto-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.ts | 5 | ||||
-rw-r--r-- | ui/src/frontend/globals.ts | 88 | ||||
-rw-r--r-- | ui/src/frontend/keyboard_event_handler.ts | 5 |
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); } |