Skip to content

Commit 139d000

Browse files
committed
Add prev/next buttons in the assembly view.
1 parent 6fbbad5 commit 139d000

File tree

9 files changed

+184
-20
lines changed

9 files changed

+184
-20
lines changed

src/actions/profile-view.js

+7
Original file line numberDiff line numberDiff line change
@@ -2033,6 +2033,13 @@ export function openAssemblyView(): Action {
20332033
};
20342034
}
20352035

2036+
export function changeAssemblyViewNativeSymbolEntryIndex(entryIndex: number): Action {
2037+
return {
2038+
type: 'CHANGE_ASSEMBLY_VIEW_NATIVE_SYMBOL_ENTRY_INDEX',
2039+
entryIndex,
2040+
}
2041+
}
2042+
20362043
export function closeAssemblyView(): Action {
20372044
return {
20382045
type: 'CLOSE_ASSEMBLY_VIEW',

src/app-logic/url-handling.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,16 @@ export function getQueryStringFromUrlState(urlState: UrlState): string {
423423
if (sourceView.sourceFile !== null) {
424424
query.sourceView = sourceView.sourceFile;
425425
}
426-
if (assemblyView.isOpen && assemblyView.nativeSymbol !== null) {
426+
if (
427+
assemblyView.isOpen &&
428+
assemblyView.currentNativeSymbolEntryIndex !== null
429+
) {
430+
const {
431+
currentNativeSymbolEntryIndex,
432+
allNativeSymbolsForInitiatingCallNode,
433+
} = assemblyView;
427434
query.assemblyView = stringifyAssemblyViewSymbol(
428-
assemblyView.nativeSymbol
435+
allNativeSymbolsForInitiatingCallNode[currentNativeSymbolEntryIndex]
429436
);
430437
}
431438
}
@@ -606,7 +613,6 @@ export function stateFromLocation(
606613
const assemblyView: AssemblyViewState = {
607614
isOpen: false,
608615
scrollGeneration: 0,
609-
nativeSymbol: null,
610616
currentNativeSymbolEntryIndex: null,
611617
allNativeSymbolsForInitiatingCallNode: [],
612618
allNativeSymbolWeightsForInitiatingCallNode: [],
@@ -620,7 +626,7 @@ export function stateFromLocation(
620626
if (query.assemblyView) {
621627
const symbol = parseAssemblyViewSymbol(query.assemblyView);
622628
if (symbol !== null) {
623-
assemblyView.nativeSymbol = symbol;
629+
assemblyView.currentNativeSymbolEntryIndex = 0;
624630
assemblyView.allNativeSymbolsForInitiatingCallNode = [symbol];
625631
assemblyView.isOpen = true;
626632
isBottomBoxOpenPerPanel[selectedTab] = true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
// @flow
5+
6+
import React from 'react';
7+
import classNames from 'classnames';
8+
9+
import {
10+
getAssemblyViewCurrentNativeSymbolEntryIndex,
11+
getAssemblyViewNativeSymbolEntryCount,
12+
} from 'firefox-profiler/selectors/url-state';
13+
import { changeAssemblyViewNativeSymbolEntryIndex } from 'firefox-profiler/actions/profile-view';
14+
import explicitConnect from 'firefox-profiler/utils/connect';
15+
16+
import type { ConnectedProps } from 'firefox-profiler/utils/connect';
17+
18+
import { Localized } from '@fluent/react';
19+
20+
type StateProps = {|
21+
+assemblyViewCurrentNativeSymbolEntryIndex: number | null,
22+
+assemblyViewNativeSymbolEntryCount: number,
23+
|};
24+
25+
type DispatchProps = {|
26+
+changeAssemblyViewNativeSymbolEntryIndex: typeof changeAssemblyViewNativeSymbolEntryIndex,
27+
|};
28+
29+
type Props = ConnectedProps<{||}, StateProps, DispatchProps>;
30+
31+
class AssemblyViewNativeSymbolNavigatorImpl extends React.PureComponent<Props> {
32+
_onPreviousClick = () => {
33+
this._changeIndexBy(-1);
34+
};
35+
36+
_onNextClick = () => {
37+
this._changeIndexBy(1);
38+
};
39+
40+
_changeIndexBy(delta: number) {
41+
const {
42+
assemblyViewCurrentNativeSymbolEntryIndex: index,
43+
assemblyViewNativeSymbolEntryCount: count,
44+
changeAssemblyViewNativeSymbolEntryIndex,
45+
} = this.props;
46+
const newIndex = index + delta;
47+
if (newIndex >= 0 && newIndex < count) {
48+
changeAssemblyViewNativeSymbolEntryIndex(newIndex);
49+
}
50+
}
51+
52+
render() {
53+
const {
54+
assemblyViewCurrentNativeSymbolEntryIndex: index,
55+
assemblyViewNativeSymbolEntryCount: count,
56+
} = this.props;
57+
58+
if (index === null || count <= 1) {
59+
return null;
60+
}
61+
62+
return (
63+
<>
64+
<h3 className="bottom-box-title-trailer">
65+
{index !== null && count > 1 ? `${index + 1} of ${count}` : ''}
66+
</h3>
67+
<Localized id="AssemblyView--prev-button" attrs={{ title: true }}>
68+
<button
69+
className={classNames(
70+
'bottom-prev-button',
71+
'photon-button',
72+
'photon-button-ghost'
73+
)}
74+
title="Previous"
75+
type="button"
76+
disabled={index === null || index <= 0}
77+
onClick={this._onPreviousClick}
78+
>
79+
80+
</button>
81+
</Localized>
82+
<Localized id="AssemblyView--next-button" attrs={{ title: true }}>
83+
<button
84+
className={classNames(
85+
'bottom-next-button',
86+
'photon-button',
87+
'photon-button-ghost'
88+
)}
89+
title="Next"
90+
type="button"
91+
disabled={index === null || index >= count - 1}
92+
onClick={this._onNextClick}
93+
>
94+
95+
</button>
96+
</Localized>
97+
</>
98+
);
99+
}
100+
}
101+
102+
export const AssemblyViewNativeSymbolNavigator = explicitConnect<
103+
{||},
104+
StateProps,
105+
DispatchProps,
106+
>({
107+
mapStateToProps: (state) => ({
108+
assemblyViewCurrentNativeSymbolEntryIndex:
109+
getAssemblyViewCurrentNativeSymbolEntryIndex(state),
110+
assemblyViewNativeSymbolEntryCount:
111+
getAssemblyViewNativeSymbolEntryCount(state),
112+
}),
113+
mapDispatchToProps: {
114+
changeAssemblyViewNativeSymbolEntryIndex,
115+
},
116+
component: AssemblyViewNativeSymbolNavigatorImpl,
117+
});

src/components/app/BottomBox.css

+18-2
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,18 @@
4646
line-height: 18px;
4747
}
4848

49-
.bottom-box-title {
49+
.bottom-box-title, .bottom-box-title-trailer {
5050
overflow: hidden;
5151
margin: 0 8px;
5252
font: inherit;
5353
text-overflow: ellipsis;
5454
white-space: nowrap;
5555
}
5656

57+
.bottom-box-title-trailer {
58+
margin: 0;
59+
}
60+
5761
.bottom-box-header-trailing-buttons {
5862
display: flex;
5963
height: 100%;
@@ -62,7 +66,9 @@
6266
}
6367

6468
.bottom-close-button,
65-
.bottom-assembly-button {
69+
.bottom-assembly-button,
70+
.bottom-prev-button,
71+
.bottom-next-button {
6672
width: 24px;
6773
height: 24px;
6874
flex-shrink: 0;
@@ -71,6 +77,16 @@
7177
background-size: 16px 16px;
7278
}
7379

80+
.bottom-prev-button,
81+
.bottom-next-button {
82+
font-size: 9px;
83+
width: 16px;
84+
}
85+
86+
.bottom-next-button {
87+
margin-right: 8px;
88+
}
89+
7490
.bottom-close-button {
7591
background-image: url(/res/img/svg/close-dark.svg);
7692
}

src/components/app/BottomBox.js

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import classNames from 'classnames';
1010
import { SourceView } from '../shared/SourceView';
1111
import { AssemblyView } from '../shared/AssemblyView';
1212
import { AssemblyViewToggleButton } from './AssemblyViewToggleButton';
13+
import { AssemblyViewNativeSymbolNavigator } from './AssemblyViewNativeSymbolNavigator';
1314
import { CodeLoadingOverlay } from './CodeLoadingOverlay';
1415
import { CodeErrorOverlay } from './CodeErrorOverlay';
1516
import {
@@ -187,6 +188,7 @@ class BottomBoxImpl extends React.PureComponent<Props> {
187188
// These trailing header buttons go into the bottom-box-bar of the last pane.
188189
const trailingHeaderButtons = (
189190
<div className="bottom-box-header-trailing-buttons">
191+
{assemblyViewIsOpen ? <AssemblyViewNativeSymbolNavigator /> : null}
190192
<AssemblyViewToggleButton />
191193
<Localized id="SourceView--close-button" attrs={{ title: true }}>
192194
<button

src/reducers/url-state.js

+8-11
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,6 @@ const sourceView: Reducer<SourceViewState> = (
595595
const assemblyView: Reducer<AssemblyViewState> = (
596596
state = {
597597
scrollGeneration: 0,
598-
nativeSymbol: null,
599598
currentNativeSymbolEntryIndex: null,
600599
allNativeSymbolsForInitiatingCallNode: [],
601600
allNativeSymbolWeightsForInitiatingCallNode: [],
@@ -613,17 +612,9 @@ const assemblyView: Reducer<AssemblyViewState> = (
613612
} = action;
614613
return {
615614
scrollGeneration: state.scrollGeneration + 1,
616-
nativeSymbol:
617-
initialNativeSymbolEntryIndex !== null
618-
? allNativeSymbolsForInitiatingCallNode[
619-
initialNativeSymbolEntryIndex
620-
]
621-
: null,
622615
currentNativeSymbolEntryIndex: initialNativeSymbolEntryIndex,
623-
allNativeSymbolsForInitiatingCallNode:
624-
allNativeSymbolsForInitiatingCallNode,
625-
allNativeSymbolWeightsForInitiatingCallNode:
626-
allNativeSymbolWeightsForInitiatingCallNode,
616+
allNativeSymbolsForInitiatingCallNode,
617+
allNativeSymbolWeightsForInitiatingCallNode,
627618
isOpen: state.isOpen || shouldOpenAssemblyView,
628619
};
629620
}
@@ -633,6 +624,12 @@ const assemblyView: Reducer<AssemblyViewState> = (
633624
isOpen: true,
634625
};
635626
}
627+
case 'CHANGE_ASSEMBLY_VIEW_NATIVE_SYMBOL_ENTRY_INDEX': {
628+
return {
629+
...state,
630+
currentNativeSymbolEntryIndex: action.entryIndex,
631+
};
632+
}
636633
case 'CLOSE_ASSEMBLY_VIEW': {
637634
return {
638635
...state,

src/selectors/url-state.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,24 @@ export const getAssemblyViewIsOpen: Selector<boolean> = (state) =>
8686
getProfileSpecificState(state).assemblyView.isOpen;
8787
export const getAssemblyViewNativeSymbol: Selector<NativeSymbolInfo | null> = (
8888
state
89-
) => getProfileSpecificState(state).assemblyView.nativeSymbol;
89+
) => {
90+
const {
91+
currentNativeSymbolEntryIndex,
92+
allNativeSymbolsForInitiatingCallNode,
93+
} = getProfileSpecificState(state).assemblyView;
94+
return currentNativeSymbolEntryIndex !== null
95+
? allNativeSymbolsForInitiatingCallNode[currentNativeSymbolEntryIndex]
96+
: null;
97+
};
98+
export const getAssemblyViewCurrentNativeSymbolEntryIndex: Selector<
99+
number | null,
100+
> = (state) =>
101+
getProfileSpecificState(state).assemblyView.currentNativeSymbolEntryIndex;
102+
export const getAssemblyViewNativeSymbolEntryCount: Selector<number> = (
103+
state
104+
) =>
105+
getProfileSpecificState(state).assemblyView
106+
.allNativeSymbolsForInitiatingCallNode.length;
90107
export const getAssemblyViewScrollGeneration: Selector<number> = (state) =>
91108
getProfileSpecificState(state).assemblyView.scrollGeneration;
92109
export const getShowJsTracerSummary: Selector<boolean> = (state) =>

src/types/actions.js

+4
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ type ProfileAction =
374374
| {|
375375
+type: 'OPEN_ASSEMBLY_VIEW',
376376
|}
377+
| {|
378+
+type: 'CHANGE_ASSEMBLY_VIEW_NATIVE_SYMBOL_ENTRY_INDEX',
379+
+entryIndex: number,
380+
|}
377381
| {|
378382
+type: 'CLOSE_ASSEMBLY_VIEW',
379383
|}

src/types/state.js

-2
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,6 @@ export type AssemblyViewState = {|
269269
scrollGeneration: number,
270270
// The native symbol for which the assembly code is being shown at the moment.
271271
// Null if the initiating call node did not have a native symbol.
272-
// Always equal to allNativeSymbolsForInitiatingCallNode[currentNativeSymbolEntryIndex]
273-
nativeSymbol: NativeSymbolInfo | null,
274272
currentNativeSymbolEntryIndex: number | null,
275273
// The set of native symbols which contributed samples to the initiating call
276274
// node. Often, this will just be one element (the same as `nativeSymbol`),

0 commit comments

Comments
 (0)