Skip to content
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"@codemirror/lang-javascript": "^6.2.5",
"@codemirror/lang-rust": "^6.0.2",
"@codemirror/language": "^6.13.1",
"@codemirror/search": "^6.7.2",
"@codemirror/state": "^6.7.6",
"@codemirror/view": "^6.43.13",
"@firefox-devtools/react-contextmenu": "^5.2.4",
Expand Down
4 changes: 2 additions & 2 deletions src/components/shared/AssemblyView-codemirror.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
updateTimingsEffect,
StringMarker,
createHighlightedLineExtension,
codeViewerExtension,
} from 'firefox-profiler/utils/codemirror-shared';

// An "effect" is like a redux action. This effect is used to replace the value
Expand Down Expand Up @@ -209,8 +210,7 @@ export class AssemblyViewEditor {
instructionAddressGutter,
highlightedLineConf.of(createHighlightedLineExtension(highlightedLine)),
syntaxHighlighting(classHighlighter),
EditorState.readOnly.of(true),
EditorView.editable.of(false),
codeViewerExtension,
],
});
const lineTimings = addressTimingsToLineTimings(
Expand Down
148 changes: 148 additions & 0 deletions src/components/shared/CodeView.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@
--codeview-linenum-foreground-color: ##aaa;
--codeview-nonzero-background-color: #edf6ff;
--codeview-highlight-background-color: #fffbcc;
--codeview-textfield-border-color: var(--grey-90-a20);
--codeview-textfield-hover-border-color: var(--grey-90-a30);
--codeview-search-match-background-color: color-mix(
in srgb,
var(--yellow-50) 40%,
transparent
);
--codeview-search-selected-match-background-color: color-mix(
in srgb,
var(--orange-50) 50%,
transparent
);

display: flex;
min-height: 0;
Expand Down Expand Up @@ -50,6 +62,18 @@
--codeview-linenum-foreground-color: var(--grey-30);
--codeview-nonzero-background-color: var(--grey-80);
--codeview-highlight-background-color: var(--yellow-90);
--codeview-textfield-border-color: var(--grey-10-a20);
--codeview-textfield-hover-border-color: var(--grey-10-a40);
--codeview-search-match-background-color: color-mix(
in srgb,
var(--yellow-60) 35%,
transparent
);
--codeview-search-selected-match-background-color: color-mix(
in srgb,
var(--orange-60) 60%,
transparent
);
--theme-highlight-keyword: var(--magenta-65);
--theme-highlight-type: var(--purple-40);
--theme-highlight-variable: var(--blue-40);
Expand Down Expand Up @@ -174,6 +198,130 @@
word-spacing: normal;
}

/**
* CodeMirror's search panel and search matches. CodeMirror's base theme gives
* the panel tiny fonts, cramped spacing and gradient buttons. Its colors are
* always the light ones, because we don't tell CodeMirror about our dark mode;
* we use our own color variables instead. The base theme's selectors are
* scoped by generated class names. The ".codeView .cm-editor" prefix makes
* these rules more specific than the base theme's.
*/
.codeView .cm-editor {
.cm-panels {
background-color: var(--codeview-header-background-color);
color: var(--codeview-foreground-color);
}

.cm-panels-top {
border-bottom: 1px solid var(--codeview-header-border-color);
}

.cm-textfield {
border: 1px solid var(--codeview-textfield-border-color);
border-radius: 2px;
background-color: var(--base-background-color);
color: var(--base-foreground-color);
font-size: inherit;
}

.cm-textfield:hover {
border-color: var(--codeview-textfield-hover-border-color);
}

/* The same focus ring as .photon-input, which CodeMirror's text field can't
use because CodeMirror creates the element. */
.cm-textfield:focus-visible {
border-color: var(--focus-border-color);
box-shadow:
0 0 0 1px var(--focus-border-color),
0 0 0 4px var(--focus-shadow-color);
outline: 0;
}

.cm-button {
/* No border, so that the focus ring sits on the button's edge. The extra
1px of padding makes up for the text field's border. */
padding: calc(0.2em + 1px) 1em;
border: none;
border-radius: 2px;
background-color: var(--clickable-background-color);
background-image: none;
color: var(--clickable-foreground-color);
font-size: inherit;
}

.cm-button:hover {
background-color: var(--clickable-hover-background-color);
}

/* CodeMirror's base theme has a gradient for pressed buttons, even when the
pointer has left the button. */
.cm-button:active {
background-image: none;
}

.cm-button:active:hover {
background-color: var(--clickable-active-background-color);
}

.cm-searchMatch {
background-color: var(--codeview-search-match-background-color);
}

.cm-searchMatch-selected {
background-color: var(--codeview-search-selected-match-background-color);
}

.cm-panel.cm-search {
display: flex;
flex-wrap: wrap;
align-items: center;
padding: 4px;
font-size: 12px;
row-gap: 4px;

input,
.cm-button,
label {
margin: 0 2px;
}

input[type='checkbox'] {
margin-inline-end: 4px;
vertical-align: -2px;
}

label {
font-size: inherit;
}

/* CodeMirror positions the close button absolutely at the top. Put it at
the end of the row instead, so that it's centered with the other
controls. */
[name='close'] {
position: static;
display: flex;
width: 20px;
height: 20px;
align-items: center;
justify-content: center;
border-radius: 2px;
margin-left: auto;
color: inherit;
font-size: 16px;
line-height: 1;
}

[name='close']:hover {
background-color: var(--clickable-ghost-hover-background-color);
}

[name='close']:active:hover {
background-color: var(--clickable-ghost-active-background-color);
}
}
}

/**
* Syntax highlighting uses the Lezer's classHighlighter. From its documentation:
*
Expand Down
10 changes: 1 addition & 9 deletions src/components/shared/SourceView-codemirror.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
timingsExtension,
updateTimingsEffect,
createHighlightedLineExtension,
codeViewerExtension,
} from 'firefox-profiler/utils/codemirror-shared';

// This "compartment" allows us to swap the syntax highlighting language when
Expand Down Expand Up @@ -84,15 +85,6 @@ function _languageExtForPath(path: string | null): LanguageSupport | [] {
return javascript();
}

// Adjustments to make a CodeMirror editor work as a non-editable code viewer.
const codeViewerExtension = [
EditorState.readOnly.of(true),
EditorView.editable.of(false),
// Allow tabbing to the view (to an element *inside* the scroller so that the
// up / down keys trigger scrolling), and take focus on mousedown.
EditorView.contentAttributes.of({ tabindex: '0' }),
];

// Creates a lineNumbers extension that displays line numbers offset by startLine - 1.
function _lineNumbersForStartLine(startLine: number) {
if (startLine <= 1) {
Expand Down
1 change: 1 addition & 0 deletions src/test/components/__snapshots__/BottomBox.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ exports[`BottomBox should show the assembly view when pressing the toggle button
role="textbox"
spellcheck="false"
style="tab-size: 4;"
tabindex="0"
translate="no"
writingsuggestions="false"
>
Expand Down
26 changes: 24 additions & 2 deletions src/utils/codemirror-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ import {
GutterMarker,
gutter,
gutterLineClass,
keymap,
} from '@codemirror/view';
import type { EditorState } from '@codemirror/state';
import { StateField, StateEffect, RangeSet } from '@codemirror/state';
import {
EditorState,
StateField,
StateEffect,
RangeSet,
} from '@codemirror/state';
import { search, searchKeymap } from '@codemirror/search';

import type { LineTimings } from 'firefox-profiler/types';

Expand Down Expand Up @@ -193,4 +199,20 @@ export const timingsExtension = [
nonZeroLineDecorationHighlighter,
];

// Adjustments to make a CodeMirror editor work as a non-editable code viewer.
export const codeViewerExtension = [
EditorState.readOnly.of(true),
EditorView.editable.of(false),
// Allow tabbing to the view (to an element *inside* the scroller so that the
// up / down keys trigger scrolling), and take focus on mousedown.
EditorView.contentAttributes.of({ tabindex: '0' }),
// CodeMirror only renders the lines in and near the viewport, so the
// browser's find-in-page can't find text outside of it. CodeMirror's own
// search panel searches the whole document. It opens with Ctrl/Cmd+F while
// the editor has focus. The replace controls are hidden because the editor
// is read-only.
search({ top: true }),
keymap.of(searchKeymap),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

searchKeymap binds more than find. It also includes Mod-Alt-G (gotoLine), Mod-D (selectNextOccurrence) and Mod-Shift-L (selectSelectionMatches).

gotoLine won't work properly because the counting of the line numbers differes.
selectNextOccurrence takes over the browser's bookmark shortcut.

Would it be better if we bind only the find-related entries?

];

export { createHighlightedLineExtension };
17 changes: 13 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1866,6 +1866,15 @@
"@codemirror/view" "^6.0.0"
crelt "^1.0.5"

"@codemirror/search@^6.7.2":
version "6.7.2"
resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.7.2.tgz#93a49eb21c026de473c4fc3a047b8fd67784b0f0"
integrity sha512-gUYkYhT2+n/+VGZ+8EzE5WFkYZUZYm1VOKDudIsNqh42uRVQJ0a6Yss9sdKT3MeOYfuL1N6AZA57oza0Oyr0LA==
dependencies:
"@codemirror/state" "^6.0.0"
"@codemirror/view" "^6.37.0"
crelt "^1.0.5"

"@codemirror/state@^6.0.0", "@codemirror/state@^6.7.0", "@codemirror/state@^6.7.6":
version "6.7.6"
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.7.6.tgz#48af761fae3947745f17fa143cc5b5084225388d"
Expand All @@ -1878,10 +1887,10 @@
resolved "https://registry.yarnpkg.com/@codemirror/streamparser/-/streamparser-6.0.0.tgz#cc48a8f67e9001222d69938fabab157d68ce59d6"
integrity sha512-JTFPF6xrfjt0mnfGPgzcLiMwYmvIyNaoizp8BYzv8FE8KrT6GBGDZ190rtt+O7Wke3gG/MFHyiY9YGNeimof4w==

"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.43.13":
version "6.43.13"
resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.43.13.tgz#a2d0286bf9e6051cb89076fd1c8dd58b907008d0"
integrity sha512-sihaFrUzAsYBQsL9J2t69y8nfMQGwcYmggAZsk+kjPbjYZMyuf2hU8tUNTZ+P+isb6XRr8JE22TZlJxBoVdH1A==
"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.37.0", "@codemirror/view@^6.43.13":
version "6.43.15"
resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.43.15.tgz#3da2515b3919e199b68520a5b6e559c2a4cfbe9e"
integrity sha512-HHsfpqFeHyXLs983pSRe38Xajs0vFWZQ2BuX0m7Ki8w3jZ5iD8cuR3lBz2/5/X53Dhf32SBHKh6rtSTB6tKeGw==
dependencies:
"@codemirror/state" "^6.7.0"
crelt "^1.0.6"
Expand Down
Loading