+
Skip to content

Issue #1818 - When searching in the stack chart, the matched nodes should be highlighted #2957

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/components/stack-chart/Canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// @flow
import { GREY_30 } from 'photon-colors';
import { GREY_30, BLUE_60 } from 'photon-colors';
import * as React from 'react';
import memoize from 'memoize-immutable';
import { TIMELINE_MARGIN_RIGHT } from '../../app-logic/constants';
Expand Down Expand Up @@ -69,6 +69,7 @@ type OwnProps = {|
+scrollToSelectionGeneration: number,
+marginLeft: CssPixels,
+displayStackType: boolean,
+searchStringsRegExp: RegExp | null,
|};

type Props = $ReadOnly<{|
Expand Down Expand Up @@ -165,6 +166,7 @@ class StackChartCanvasImpl extends React.PureComponent<Props> {
viewportTop,
viewportBottom,
},
searchStringsRegExp,
} = this.props;
const fastFillStyle = new FastFillStyle(ctx);

Expand Down Expand Up @@ -342,6 +344,7 @@ class StackChartCanvasImpl extends React.PureComponent<Props> {
? colorStyles.selectedFillStyle
: colorStyles.unselectedFillStyle
);

ctx.fillRect(
intX,
intY,
Expand All @@ -352,6 +355,25 @@ class StackChartCanvasImpl extends React.PureComponent<Props> {
intW + BORDER_OPACITY,
intH
);

if (searchStringsRegExp) {
// Reset the position of the search regexp so that previous
// invocations don't influence this one.
searchStringsRegExp.lastIndex = 0;

if (searchStringsRegExp.test(text)) {
ctx.strokeStyle = BLUE_60;
ctx.lineWidth = 1;
// By using these "+1" computations, this is drawing the
// highlight stroke inside the boxes.
if (intW <= 2) {
ctx.strokeRect(intX + 1, intY + 1, 1, intH - 1);
} else {
ctx.strokeRect(intX + 1, intY + 1, intW - 1, intH - 1);
}
}
}

lastDrawnPixelX =
intX +
intW +
Expand Down
5 changes: 5 additions & 0 deletions src/components/stack-chart/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { selectedThreadSelectors } from '../../selectors/per-thread';
import {
getShowUserTimings,
getSelectedThreadsKey,
getSearchStringsAsRegExp,
} from '../../selectors/url-state';
import { getTimelineMarginLeft } from '../../selectors/app';
import { StackChartEmptyReasons } from './StackChartEmptyReasons';
Expand Down Expand Up @@ -82,6 +83,7 @@ type StateProps = {|
+userTimings: MarkerIndex[],
+timelineMarginLeft: CssPixels,
+displayStackType: boolean,
+searchStringsRegExp: RegExp | null,
|};

type DispatchProps = {|
Expand Down Expand Up @@ -182,6 +184,7 @@ class StackChartImpl extends React.PureComponent<Props> {
weightType,
timelineMarginLeft,
displayStackType,
searchStringsRegExp,
} = this.props;

const maxViewportHeight = maxStackDepth * STACK_FRAME_HEIGHT;
Expand Down Expand Up @@ -240,6 +243,7 @@ class StackChartImpl extends React.PureComponent<Props> {
scrollToSelectionGeneration,
marginLeft: timelineMarginLeft,
displayStackType: displayStackType,
searchStringsRegExp,
}}
/>
</div>
Expand Down Expand Up @@ -279,6 +283,7 @@ export const StackChart = explicitConnect<{||}, StateProps, DispatchProps>({
userTimings: selectedThreadSelectors.getUserTimingMarkerIndexes(state),
timelineMarginLeft: getTimelineMarginLeft(state),
displayStackType: getProfileUsesMultipleStackTypes(state),
searchStringsRegExp: getSearchStringsAsRegExp(state),
};
},
mapDispatchToProps: {
Expand Down
76 changes: 71 additions & 5 deletions src/test/components/StackChart.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
} from '../../actions/profile-view';
import { changeSelectedTab } from '../../actions/app';
import { selectedThreadSelectors } from '../../selectors/per-thread';
import { ensureExists } from '../../utils/flow';
import { ensureExists, assertExhaustiveCheck } from '../../utils/flow';

import {
autoMockCanvasContext,
Expand All @@ -58,8 +58,6 @@ import { autoMockElementSize } from '../fixtures/mocks/element-size';

import type { Profile, CssPixels } from 'firefox-profiler/types';

jest.useFakeTimers();

const GRAPH_BASE_WIDTH = 200;
const GRAPH_WIDTH =
GRAPH_BASE_WIDTH + TIMELINE_MARGIN_LEFT + TIMELINE_MARGIN_RIGHT;
Expand Down Expand Up @@ -108,8 +106,6 @@ describe('StackChart', function () {

it('can display a context menu when right clicking the chart', function () {
// Fake timers are indicated when dealing with the context menus.
jest.useFakeTimers();

const { rightClick, getContextMenu, clickMenuItem, findFillTextPosition } =
setupSamples();

Expand Down Expand Up @@ -173,6 +169,42 @@ describe('StackChart', function () {
expect(drawnFrames).not.toContain('Z');
});

it('can search into the stack chart', function () {
const {
profile,
funcNamesPerThread: [funcNames],
} = getProfileFromTextSamples(`
Init Init Init Init Init
RunTask RunTask RunTask RunTask Poll
Task1 Task2 Task1 Task1
`);
const { changeSearchString } = setup(profile, funcNames);

// Flush the draw logs before searching so that we'll have only the new draw
// instructions later.
flushDrawLog();

changeSearchString('Task2');
// Let's check whether only the selected task is drawn.
const drawLogs = flushDrawLog();
const drawnFunctions = drawLogs
.filter(([action]) => action === 'fillText')
.map(([_, value]) => value);
expect(drawnFunctions).toEqual(['Init', 'RunTask', 'Task2']);

expect(findHighlightedFunctions(drawLogs)).toEqual(['Task2']);

changeSearchString('Task');
expect(findHighlightedFunctions(flushDrawLog())).toEqual([
'RunTask',
'Task1',
'Task2',
'Task1',
]);

// Let's search for a more common function
});

describe('EmptyReasons', () => {
it('shows reasons when a profile has no samples', () => {
const profile = getEmptyProfile();
Expand Down Expand Up @@ -339,6 +371,7 @@ function setupSamples(
* Setup the stack chart component with a profile.
*/
function setup(profile: Profile, funcNames: string[] = []) {
jest.useFakeTimers();
const flushRafCalls = mockRaf();

const store = storeWithProfile(profile);
Expand Down Expand Up @@ -418,6 +451,13 @@ function setup(profile: Profile, funcNames: string[] = []) {
fireMouseEvent('mousemove', getPositioningOptions(where));
}

function changeSearchString(searchString) {
const input = screen.getByRole('searchbox', { name: /Filter stacks/ });
fireEvent.change(input, { target: { value: searchString } });
jest.runAllTimers();
flushRafCalls();
}

// Context menu tools
const getContextMenu = () =>
ensureExists(
Expand Down Expand Up @@ -446,6 +486,7 @@ function setup(profile: Profile, funcNames: string[] = []) {
getContextMenu,
getTooltip,
findFillTextPosition,
changeSearchString,
};
}

Expand All @@ -455,3 +496,28 @@ function setup(profile: Profile, funcNames: string[] = []) {
function getCheckedState(element: HTMLElement): mixed {
return (element: any).checked;
}

// This function loops over drawLogs and finds the function names whose box is stroke.
function findHighlightedFunctions(drawLogs): string[] {
const result = [];

let phase: 'finding-stroke' | 'finding-text' = 'finding-stroke';
for (const [operation, arg] of drawLogs) {
switch (phase) {
case 'finding-stroke':
if (operation === 'strokeRect') {
phase = 'finding-text';
}
continue;
case 'finding-text':
if (operation === 'fillText') {
phase = 'finding-stroke';
result.push(arg);
}
continue;
default:
throw assertExhaustiveCheck(phase);
}
}
return result;
}
1 change: 1 addition & 0 deletions src/test/fixtures/mocks/canvas-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function mockCanvasContext() {
moveTo: spyLog('moveTo'),
lineTo: spyLog('lineTo'),
stroke: spyLog('stroke'),
strokeRect: spyLog('strokeRect'),
rect: spyLog('rect'),
arc: spyLog('arc'),
measureText: spyLog('measureText', (text) => ({
Expand Down
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载