chrome-devtools-frontend 1.0.941095 → 1.0.943017
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/WATCHLISTS +1 -1
- package/config/gni/all_devtools_files.gni +0 -62
- package/config/gni/devtools_grd_files.gni +55 -19
- package/config/gni/devtools_image_files.gni +2 -3
- package/front_end/.eslintrc.js +12 -1
- package/front_end/Images/src/feedback_button_icon.svg +3 -0
- package/front_end/Images/src/{feedback_thin_16x16_icon.svg → survey_feedback_icon.svg} +1 -1
- package/front_end/Tests.js +1 -32
- package/front_end/core/common/Color.ts +5 -0
- package/front_end/core/i18n/locales/en-US.json +20 -29
- package/front_end/core/i18n/locales/en-XL.json +20 -29
- package/front_end/core/sdk/CPUProfilerModel.ts +7 -9
- package/front_end/core/sdk/ConsoleModel.ts +26 -28
- package/front_end/core/sdk/DebuggerModel.ts +4 -14
- package/front_end/core/sdk/sdk-meta.ts +17 -3
- package/front_end/entrypoints/devtools_app/devtools_app.json +1 -11
- package/front_end/entrypoints/inspector/inspector.json +1 -3
- package/front_end/entrypoints/js_app/js_app.json +1 -3
- package/front_end/entrypoints/main/MainImpl.ts +26 -0
- package/front_end/entrypoints/node_app/node_app.json +1 -3
- package/front_end/entrypoints/shell/shell.js +0 -11
- package/front_end/entrypoints/shell/shell.json +1 -5
- package/front_end/entrypoints/worker_app/worker_app.json +1 -7
- package/front_end/generated/InspectorBackendCommands.js +19 -0
- package/front_end/generated/protocol-mapping.d.ts +31 -1
- package/front_end/generated/protocol-proxy-api.d.ts +34 -2
- package/front_end/generated/protocol.d.ts +81 -6
- package/front_end/global_typings/global_defs.d.ts +5 -0
- package/front_end/legacy_test_runner/bindings_test_runner/IsolatedFilesystemTestRunner.js +2 -2
- package/front_end/legacy_test_runner/console_test_runner/console_test_runner.js +14 -2
- package/front_end/legacy_test_runner/legacy_test_runner.ts +10 -1
- package/front_end/legacy_test_runner/test_runner/TestRunner.js +11 -0
- package/front_end/models/formatter/SourceFormatter.ts +0 -10
- package/front_end/models/workspace/UISourceCode.ts +9 -42
- package/front_end/panels/animation/AnimationTimeline.ts +3 -3
- package/front_end/panels/application/ApplicationPanelSidebar.ts +3 -3
- package/front_end/panels/application/BackForwardCacheStrings.ts +3 -1
- package/front_end/panels/application/application-meta.ts +0 -3
- package/front_end/panels/application/components/EndpointsGrid.ts +1 -1
- package/front_end/panels/application/components/ReportsGrid.ts +1 -1
- package/front_end/panels/console/ConsolePinPane.ts +21 -26
- package/front_end/panels/coverage/CoverageDecorationManager.ts +4 -5
- package/front_end/panels/coverage/CoverageView.ts +2 -105
- package/front_end/panels/css_overview/components/CSSOverviewStartView.ts +11 -56
- package/front_end/panels/css_overview/components/cssOverviewStartView.css +1 -8
- package/front_end/panels/elements/ElementsTreeElement.ts +4 -9
- package/front_end/panels/elements/components/StylePropertyEditor.ts +2 -0
- package/front_end/panels/elements/components/adornerSettingsPane.css +0 -4
- package/front_end/panels/emulation/DeviceModeToolbar.ts +3 -1
- package/front_end/panels/emulation/DeviceModeView.ts +2 -1
- package/front_end/panels/emulation/InspectedPagePlaceholder.ts +3 -1
- package/front_end/panels/emulation/MediaQueryInspector.ts +3 -1
- package/front_end/panels/emulation/emulation-meta.ts +2 -4
- package/front_end/panels/issues/issues-meta.ts +0 -2
- package/front_end/panels/js_profiler/js_profiler-meta.ts +0 -3
- package/front_end/panels/layers/module.json +0 -1
- package/front_end/panels/lighthouse/LighthousePanel.ts +2 -4
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -4
- package/front_end/panels/lighthouse/lighthouseStartView.css +4 -0
- package/front_end/panels/lighthouse/module.json +0 -6
- package/front_end/panels/media/media-meta.ts +0 -3
- package/front_end/panels/network/ResourceWebSocketFrameView.ts +2 -1
- package/front_end/panels/network/network-meta.ts +0 -3
- package/front_end/panels/profiler/CPUProfileView.ts +10 -3
- package/front_end/panels/profiler/profiler-meta.ts +0 -2
- package/front_end/panels/screencast/screencast-meta.ts +0 -3
- package/front_end/panels/security/security-meta.ts +0 -3
- package/front_end/panels/sources/BreakpointEditDialog.ts +16 -30
- package/front_end/panels/sources/CSSPlugin.ts +310 -331
- package/front_end/panels/sources/CallStackSidebarPane.ts +28 -34
- package/front_end/panels/sources/CoveragePlugin.ts +121 -6
- package/front_end/panels/sources/DebuggerPlugin.ts +1166 -1243
- package/front_end/panels/sources/EditingLocationHistoryManager.ts +71 -101
- package/front_end/panels/sources/GoToLineQuickOpen.ts +4 -3
- package/front_end/panels/sources/InplaceFormatterEditorAction.ts +3 -3
- package/front_end/panels/sources/JavaScriptCompilerPlugin.ts +26 -23
- package/front_end/panels/sources/Plugin.ts +20 -4
- package/front_end/panels/sources/ProfilePlugin.ts +185 -0
- package/front_end/panels/sources/ScriptFormatterEditorAction.ts +3 -3
- package/front_end/panels/sources/ScriptOriginPlugin.ts +0 -10
- package/front_end/panels/sources/SnippetsPlugin.ts +1 -10
- package/front_end/panels/sources/SourcesPanel.ts +6 -5
- package/front_end/panels/sources/SourcesView.ts +10 -8
- package/front_end/panels/sources/TabbedEditorContainer.ts +31 -27
- package/front_end/panels/sources/UISourceCodeFrame.ts +335 -470
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +3 -2
- package/front_end/panels/sources/sources-legacy.ts +0 -6
- package/front_end/panels/sources/sources-meta.ts +1 -4
- package/front_end/panels/sources/sources.ts +0 -2
- package/front_end/panels/timeline/timeline-meta.ts +0 -5
- package/front_end/third_party/codemirror.next/bundle.ts +9 -13
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/javascript.js +2 -2
- package/front_end/third_party/codemirror.next/chunk/markdown.js +2 -6
- package/front_end/third_party/codemirror.next/chunk/php.js +2 -6
- package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js +2 -2
- package/front_end/third_party/codemirror.next/codemirror.next.d.ts +279 -198
- package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
- package/front_end/third_party/codemirror.next/package.json +13 -11
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1128 -1158
- package/front_end/third_party/lighthouse/locales/ar-XB.json +211 -79
- package/front_end/third_party/lighthouse/locales/ar.json +213 -81
- package/front_end/third_party/lighthouse/locales/bg.json +211 -79
- package/front_end/third_party/lighthouse/locales/ca.json +212 -80
- package/front_end/third_party/lighthouse/locales/cs.json +211 -79
- package/front_end/third_party/lighthouse/locales/da.json +211 -79
- package/front_end/third_party/lighthouse/locales/de.json +211 -79
- package/front_end/third_party/lighthouse/locales/el.json +213 -81
- package/front_end/third_party/lighthouse/locales/en-GB.json +211 -79
- package/front_end/third_party/lighthouse/locales/en-US.json +186 -75
- package/front_end/third_party/lighthouse/locales/en-XA.json +211 -79
- package/front_end/third_party/lighthouse/locales/en-XL.json +186 -75
- package/front_end/third_party/lighthouse/locales/es-419.json +211 -79
- package/front_end/third_party/lighthouse/locales/es.json +212 -80
- package/front_end/third_party/lighthouse/locales/fi.json +211 -79
- package/front_end/third_party/lighthouse/locales/fil.json +211 -79
- package/front_end/third_party/lighthouse/locales/fr.json +211 -79
- package/front_end/third_party/lighthouse/locales/he.json +212 -80
- package/front_end/third_party/lighthouse/locales/hi.json +214 -82
- package/front_end/third_party/lighthouse/locales/hr.json +211 -79
- package/front_end/third_party/lighthouse/locales/hu.json +211 -79
- package/front_end/third_party/lighthouse/locales/id.json +211 -79
- package/front_end/third_party/lighthouse/locales/it.json +211 -79
- package/front_end/third_party/lighthouse/locales/ja.json +211 -79
- package/front_end/third_party/lighthouse/locales/ko.json +211 -79
- package/front_end/third_party/lighthouse/locales/lt.json +211 -79
- package/front_end/third_party/lighthouse/locales/lv.json +214 -82
- package/front_end/third_party/lighthouse/locales/nl.json +211 -79
- package/front_end/third_party/lighthouse/locales/no.json +211 -79
- package/front_end/third_party/lighthouse/locales/pl.json +211 -79
- package/front_end/third_party/lighthouse/locales/pt-PT.json +211 -79
- package/front_end/third_party/lighthouse/locales/pt.json +211 -79
- package/front_end/third_party/lighthouse/locales/ro.json +212 -80
- package/front_end/third_party/lighthouse/locales/ru.json +211 -79
- package/front_end/third_party/lighthouse/locales/sk.json +211 -79
- package/front_end/third_party/lighthouse/locales/sl.json +211 -79
- package/front_end/third_party/lighthouse/locales/sr-Latn.json +211 -79
- package/front_end/third_party/lighthouse/locales/sr.json +211 -79
- package/front_end/third_party/lighthouse/locales/sv.json +211 -79
- package/front_end/third_party/lighthouse/locales/ta.json +218 -86
- package/front_end/third_party/lighthouse/locales/te.json +251 -119
- package/front_end/third_party/lighthouse/locales/th.json +211 -79
- package/front_end/third_party/lighthouse/locales/tr.json +211 -79
- package/front_end/third_party/lighthouse/locales/uk.json +212 -80
- package/front_end/third_party/lighthouse/locales/vi.json +211 -79
- package/front_end/third_party/lighthouse/locales/zh-HK.json +211 -79
- package/front_end/third_party/lighthouse/locales/zh-TW.json +211 -79
- package/front_end/third_party/lighthouse/locales/zh.json +211 -79
- package/front_end/third_party/lighthouse/report/bundle.d.ts +72 -34
- package/front_end/third_party/lighthouse/report/bundle.js +698 -492
- package/front_end/third_party/lighthouse/report-assets/report-generator.js +1 -2
- package/front_end/third_party/lighthouse/report-assets/report.js +40 -35
- package/front_end/third_party/lighthouse/report-assets/standalone-template.html +2 -4
- package/front_end/ui/components/code_highlighter/CodeHighlighter.ts +60 -68
- package/front_end/ui/components/data_grid/dataGrid.css +12 -10
- package/front_end/ui/components/docs/css_overview/start_view.html +25 -0
- package/front_end/ui/components/docs/css_overview/start_view.ts +14 -0
- package/front_end/ui/components/docs/icon_button/basic.ts +3 -3
- package/front_end/ui/components/docs/panel_feedback/button.html +25 -0
- package/front_end/ui/components/docs/panel_feedback/button.ts +18 -0
- package/front_end/ui/components/helpers/get-stylesheet.ts +0 -14
- package/front_end/ui/components/markdown_view/MarkdownImagesMap.ts +1 -1
- package/front_end/ui/components/panel_feedback/FeedbackButton.ts +67 -0
- package/front_end/ui/components/panel_feedback/panel_feedback.ts +1 -0
- package/front_end/ui/components/survey_link/SurveyLink.ts +1 -1
- package/front_end/ui/components/text_editor/TextEditor.ts +79 -36
- package/front_end/ui/components/text_editor/config.ts +42 -26
- package/front_end/ui/components/text_editor/javascript.ts +2 -3
- package/front_end/ui/components/text_editor/position.ts +17 -0
- package/front_end/ui/components/text_editor/text_editor.ts +1 -0
- package/front_end/ui/components/text_editor/theme.ts +5 -1
- package/front_end/ui/legacy/Dialog.ts +3 -1
- package/front_end/ui/legacy/DropTarget.ts +2 -1
- package/front_end/ui/legacy/EmptyWidget.ts +2 -1
- package/front_end/ui/legacy/FilterBar.ts +2 -1
- package/front_end/ui/legacy/GlassPane.ts +4 -2
- package/front_end/ui/legacy/Infobar.ts +5 -8
- package/front_end/ui/legacy/InspectorView.ts +6 -1
- package/front_end/ui/legacy/ListWidget.ts +2 -1
- package/front_end/ui/legacy/PopoverHelper.ts +2 -1
- package/front_end/ui/legacy/ProgressIndicator.ts +2 -1
- package/front_end/ui/legacy/RemoteDebuggingTerminatedScreen.ts +2 -1
- package/front_end/ui/legacy/ReportView.ts +2 -1
- package/front_end/ui/legacy/RootView.ts +2 -1
- package/front_end/ui/legacy/SearchableView.ts +2 -1
- package/front_end/ui/legacy/ShortcutRegistry.ts +11 -7
- package/front_end/ui/legacy/SoftContextMenu.ts +2 -1
- package/front_end/ui/legacy/SoftDropDown.ts +4 -2
- package/front_end/ui/legacy/SplitWidget.ts +2 -1
- package/front_end/ui/legacy/SuggestBox.ts +2 -1
- package/front_end/ui/legacy/TabbedPane.ts +2 -1
- package/front_end/ui/legacy/TargetCrashedScreen.ts +2 -1
- package/front_end/ui/legacy/TextPrompt.ts +2 -1
- package/front_end/ui/legacy/Toolbar.ts +3 -2
- package/front_end/ui/legacy/Treeoutline.ts +3 -2
- package/front_end/ui/legacy/UIUtils.ts +16 -13
- package/front_end/ui/legacy/ViewManager.ts +2 -1
- package/front_end/ui/legacy/Widget.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/object_ui-meta.ts +0 -3
- package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +2 -1
- package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +3 -1
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +2 -1
- package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +35 -131
- package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +2 -1
- package/front_end/ui/legacy/components/perf_ui/TimelineGrid.ts +3 -1
- package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +2 -1
- package/front_end/ui/legacy/components/perf_ui/perf_ui-meta.ts +0 -2
- package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +2 -2
- package/front_end/ui/legacy/components/source_frame/BinaryResourceViewFactory.ts +3 -6
- package/front_end/ui/legacy/components/source_frame/FontView.ts +1 -0
- package/front_end/ui/legacy/components/source_frame/ImageView.ts +1 -0
- package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -0
- package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +19 -14
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +501 -252
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +2 -0
- package/front_end/ui/legacy/components/source_frame/module.json +0 -3
- package/front_end/ui/legacy/components/source_frame/source_frame-legacy.ts +0 -11
- package/front_end/ui/legacy/components/source_frame/source_frame.ts +0 -2
- package/front_end/ui/legacy/components/text_editor/CodeMirrorTextEditor.ts +2 -0
- package/front_end/ui/legacy/components/text_editor/cmdevtools.css +3 -1
- package/front_end/ui/legacy/components/text_editor/module.json +0 -3
- package/front_end/ui/legacy/components/utils/Linkifier.ts +7 -15
- package/front_end/ui/legacy/radioButton.css +1 -13
- package/front_end/ui/legacy/textButton.css +5 -4
- package/front_end/ui/legacy/themeColors.css +36 -0
- package/front_end/ui/legacy/theme_support/theme_support_impl.ts +7 -9
- package/front_end/ui/legacy/utils/append-style.ts +9 -4
- package/front_end/ui/legacy/utils/create-shadow-root-with-core-styles.ts +2 -2
- package/front_end/ui/legacy/utils/inject-core-styles.ts +7 -4
- package/package.json +1 -1
- package/scripts/build/generate_css_js_files.js +23 -9
- package/scripts/build/ninja/generate_css.gni +10 -1
- package/scripts/eslint_rules/lib/check_css_import.js +2 -2
- package/scripts/eslint_rules/tests/check_css_import_test.js +12 -0
- package/front_end/Images/radioDot-dark-theme.png +0 -0
- package/front_end/Images/radioDot.png +0 -0
- package/front_end/emulated_devices/module.json +0 -6
- package/front_end/panels/application/module.json +0 -7
- package/front_end/panels/emulation/module.json +0 -11
- package/front_end/panels/issues/module.json +0 -6
- package/front_end/panels/js_profiler/module.json +0 -5
- package/front_end/panels/layer_viewer/module.json +0 -6
- package/front_end/panels/media/module.json +0 -6
- package/front_end/panels/network/module.json +0 -6
- package/front_end/panels/profiler/module.json +0 -6
- package/front_end/panels/screencast/module.json +0 -6
- package/front_end/panels/security/module.json +0 -5
- package/front_end/panels/timeline/module.json +0 -8
- package/front_end/third_party/lighthouse/report-assets/report.css +0 -1774
- package/front_end/ui/legacy/components/perf_ui/module.json +0 -13
- package/front_end/ui/legacy/components/source_frame/SourcesTextEditor.ts +0 -1030
- package/front_end/ui/legacy/module.json +0 -41
|
@@ -33,12 +33,11 @@ import * as i18n from '../../../../core/i18n/i18n.js';
|
|
|
33
33
|
import * as Platform from '../../../../core/platform/platform.js';
|
|
34
34
|
import * as Formatter from '../../../../models/formatter/formatter.js';
|
|
35
35
|
import * as TextUtils from '../../../../models/text_utils/text_utils.js';
|
|
36
|
-
import
|
|
36
|
+
import * as CodeMirror from '../../../../third_party/codemirror.next/codemirror.next.js';
|
|
37
|
+
import * as CodeHighlighter from '../../../components/code_highlighter/code_highlighter.js';
|
|
38
|
+
import * as TextEditor from '../../../components/text_editor/text_editor.js';
|
|
37
39
|
import * as UI from '../../legacy.js';
|
|
38
40
|
|
|
39
|
-
import type {SourcesTextEditorDelegate} from './SourcesTextEditor.js';
|
|
40
|
-
import {Events, SourcesTextEditor} from './SourcesTextEditor.js';
|
|
41
|
-
|
|
42
41
|
const UIStrings = {
|
|
43
42
|
/**
|
|
44
43
|
*@description Text for the source of something
|
|
@@ -85,9 +84,25 @@ const UIStrings = {
|
|
|
85
84
|
const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/source_frame/SourceFrame.ts', UIStrings);
|
|
86
85
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
87
86
|
|
|
88
|
-
export
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
export interface SourceFrameOptions {
|
|
88
|
+
// Whether to show line numbers. Defaults to true.
|
|
89
|
+
lineNumbers?: boolean;
|
|
90
|
+
// Whether to wrap lines. Defaults to false.
|
|
91
|
+
lineWrapping?: boolean;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const enum Events {
|
|
95
|
+
EditorUpdate = 'EditorUpdate',
|
|
96
|
+
EditorScroll = 'EditorScroll',
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type EventTypes = {
|
|
100
|
+
[Events.EditorUpdate]: CodeMirror.ViewUpdate,
|
|
101
|
+
[Events.EditorScroll]: void,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes, typeof UI.View.SimpleView>(
|
|
105
|
+
UI.View.SimpleView) implements UI.SearchableView.Searchable, UI.SearchableView.Replaceable, Transformer {
|
|
91
106
|
private readonly lazyContent: () => Promise<TextUtils.ContentProvider.DeferredContent>;
|
|
92
107
|
private prettyInternal: boolean;
|
|
93
108
|
private rawContent: string|null;
|
|
@@ -96,13 +111,14 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
96
111
|
private readonly prettyToggle: UI.Toolbar.ToolbarToggle;
|
|
97
112
|
private shouldAutoPrettyPrint: boolean;
|
|
98
113
|
private readonly progressToolbarItem: UI.Toolbar.ToolbarItem;
|
|
99
|
-
private textEditorInternal:
|
|
100
|
-
private
|
|
101
|
-
private
|
|
114
|
+
private textEditorInternal: TextEditor.TextEditor.TextEditor;
|
|
115
|
+
private prettyBaseDoc: CodeMirror.Text|null = null;
|
|
116
|
+
private baseDoc: CodeMirror.Text;
|
|
117
|
+
private displayedSelection: CodeMirror.EditorSelection|null = null;
|
|
102
118
|
private searchConfig: UI.SearchableView.SearchConfig|null;
|
|
103
119
|
private delayedFindSearchMatches: (() => void)|null;
|
|
104
120
|
private currentSearchResultIndex: number;
|
|
105
|
-
private searchResults:
|
|
121
|
+
private searchResults: SearchMatch[];
|
|
106
122
|
private searchRegex: RegExp|null;
|
|
107
123
|
private loadError: boolean;
|
|
108
124
|
private muteChangeEventsForSetContent: boolean;
|
|
@@ -118,12 +134,11 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
118
134
|
private selectionToSet: TextUtils.TextRange.TextRange|null;
|
|
119
135
|
private loadedInternal: boolean;
|
|
120
136
|
private contentRequested: boolean;
|
|
121
|
-
private highlighterTypeInternal: string;
|
|
122
137
|
private wasmDisassemblyInternal: Common.WasmDisassembly.WasmDisassembly|null;
|
|
123
138
|
contentSet: boolean;
|
|
124
139
|
constructor(
|
|
125
140
|
lazyContent: () => Promise<TextUtils.ContentProvider.DeferredContent>,
|
|
126
|
-
|
|
141
|
+
private readonly options: SourceFrameOptions = {}) {
|
|
127
142
|
super(i18nString(UIStrings.source));
|
|
128
143
|
|
|
129
144
|
this.lazyContent = lazyContent;
|
|
@@ -141,11 +156,11 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
141
156
|
|
|
142
157
|
this.progressToolbarItem = new UI.Toolbar.ToolbarItem(document.createElement('div'));
|
|
143
158
|
|
|
144
|
-
this.textEditorInternal = new
|
|
145
|
-
this.textEditorInternal.
|
|
159
|
+
this.textEditorInternal = new TextEditor.TextEditor.TextEditor(this.placeholderEditorState(''));
|
|
160
|
+
this.textEditorInternal.style.flexGrow = '1';
|
|
161
|
+
this.element.appendChild(this.textEditorInternal);
|
|
146
162
|
|
|
147
|
-
this.
|
|
148
|
-
this.cleanGeneration = 0;
|
|
163
|
+
this.baseDoc = this.textEditorInternal.state.doc;
|
|
149
164
|
|
|
150
165
|
this.searchConfig = null;
|
|
151
166
|
this.delayedFindSearchMatches = null;
|
|
@@ -154,36 +169,109 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
154
169
|
this.searchRegex = null;
|
|
155
170
|
this.loadError = false;
|
|
156
171
|
|
|
157
|
-
this.textEditorInternal.addEventListener(Events.EditorFocused, this.resetCurrentSearchResultIndex, this);
|
|
158
|
-
this.textEditorInternal.addEventListener(Events.SelectionChanged, this.updateSourcePosition, this);
|
|
159
|
-
this.textEditorInternal.addEventListener(UI.TextEditor.Events.TextChanged, event => {
|
|
160
|
-
if (!this.muteChangeEventsForSetContent) {
|
|
161
|
-
this.onTextChanged(event.data.oldRange, event.data.newRange);
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
172
|
this.muteChangeEventsForSetContent = false;
|
|
165
173
|
|
|
166
174
|
this.sourcePosition = new UI.Toolbar.ToolbarText();
|
|
167
175
|
|
|
168
176
|
this.searchableView = null;
|
|
169
177
|
this.editable = false;
|
|
170
|
-
this.textEditorInternal.setReadOnly(true);
|
|
171
178
|
|
|
172
179
|
this.positionToReveal = null;
|
|
173
180
|
this.lineToScrollTo = null;
|
|
174
181
|
this.selectionToSet = null;
|
|
175
182
|
this.loadedInternal = false;
|
|
176
183
|
this.contentRequested = false;
|
|
177
|
-
this.highlighterTypeInternal = '';
|
|
178
184
|
|
|
179
185
|
this.wasmDisassemblyInternal = null;
|
|
180
186
|
this.contentSet = false;
|
|
181
187
|
}
|
|
182
188
|
|
|
189
|
+
private placeholderEditorState(content: string): CodeMirror.EditorState {
|
|
190
|
+
return CodeMirror.EditorState.create({
|
|
191
|
+
doc: content,
|
|
192
|
+
extensions: [
|
|
193
|
+
CodeMirror.EditorState.readOnly.of(true),
|
|
194
|
+
this.options.lineNumbers !== false ? CodeMirror.lineNumbers() : [],
|
|
195
|
+
TextEditor.Config.theme(),
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
protected editorConfiguration(doc: string): CodeMirror.Extension {
|
|
201
|
+
return [
|
|
202
|
+
CodeMirror.EditorView.updateListener.of(update => this.dispatchEventToListeners(Events.EditorUpdate, update)),
|
|
203
|
+
TextEditor.Config.baseConfiguration(doc),
|
|
204
|
+
TextEditor.Config.sourcesAutocompletion.instance(),
|
|
205
|
+
TextEditor.Config.showWhitespace.instance(),
|
|
206
|
+
TextEditor.Config.allowScrollPastEof.instance(),
|
|
207
|
+
TextEditor.Config.codeFolding.instance(),
|
|
208
|
+
TextEditor.Config.autoDetectIndent.instance(),
|
|
209
|
+
CodeMirror.EditorView.theme({
|
|
210
|
+
'&.cm-editor': {height: '100%'},
|
|
211
|
+
'.cm-scroller': {overflow: 'auto'},
|
|
212
|
+
'.cm-lineNumbers .cm-gutterElement.cm-nonBreakableLine': {color: 'var(--color-non-breakable-line)'},
|
|
213
|
+
'.cm-searchMatch': {
|
|
214
|
+
border: '1px solid var(--color-search-match-border)',
|
|
215
|
+
borderRadius: '3px',
|
|
216
|
+
margin: '0 -1px',
|
|
217
|
+
'&.cm-searchMatch-selected': {
|
|
218
|
+
borderRadius: '1px',
|
|
219
|
+
backgroundColor: 'var(--color-selected-search-match-background)',
|
|
220
|
+
borderColor: 'var(--color-selected-search-match-background)',
|
|
221
|
+
'&, & *': {
|
|
222
|
+
color: 'var(--color-selected-search-match) !important',
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
}),
|
|
227
|
+
CodeMirror.EditorView.domEventHandlers({
|
|
228
|
+
focus: () => this.onFocus(),
|
|
229
|
+
blur: () => this.onBlur(),
|
|
230
|
+
scroll: () => this.dispatchEventToListeners(Events.EditorScroll),
|
|
231
|
+
contextmenu: event => this.onContextMenu(event),
|
|
232
|
+
}),
|
|
233
|
+
CodeMirror.lineNumbers({
|
|
234
|
+
domEventHandlers:
|
|
235
|
+
{contextmenu: (_view, block, event) => this.onLineGutterContextMenu(block.from, event as MouseEvent)},
|
|
236
|
+
}),
|
|
237
|
+
CodeMirror.EditorView.updateListener.of(
|
|
238
|
+
(update):
|
|
239
|
+
void => {
|
|
240
|
+
if (update.selectionSet || update.docChanged) {
|
|
241
|
+
this.updateSourcePosition();
|
|
242
|
+
}
|
|
243
|
+
if (update.docChanged) {
|
|
244
|
+
this.onTextChanged();
|
|
245
|
+
}
|
|
246
|
+
}),
|
|
247
|
+
activeSearchState,
|
|
248
|
+
CodeMirror.Prec.lowest(searchHighlighter),
|
|
249
|
+
config.language.of([]),
|
|
250
|
+
this.wasmDisassemblyInternal ? markNonBreakableLines(this.wasmDisassemblyInternal) : nonBreakableLines,
|
|
251
|
+
this.options.lineWrapping ? CodeMirror.EditorView.lineWrapping : [],
|
|
252
|
+
this.options.lineNumbers !== false ? CodeMirror.lineNumbers() : [],
|
|
253
|
+
];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
protected onBlur(): void {
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
protected onFocus(): void {
|
|
260
|
+
this.resetCurrentSearchResultIndex();
|
|
261
|
+
}
|
|
262
|
+
|
|
183
263
|
get wasmDisassembly(): Common.WasmDisassembly.WasmDisassembly|null {
|
|
184
264
|
return this.wasmDisassemblyInternal;
|
|
185
265
|
}
|
|
186
266
|
|
|
267
|
+
editorLocationToUILocation(lineNumber: number, columnNumber: number): {
|
|
268
|
+
lineNumber: number,
|
|
269
|
+
columnNumber: number,
|
|
270
|
+
};
|
|
271
|
+
editorLocationToUILocation(lineNumber: number): {
|
|
272
|
+
lineNumber: number,
|
|
273
|
+
columnNumber: number|undefined,
|
|
274
|
+
};
|
|
187
275
|
editorLocationToUILocation(lineNumber: number, columnNumber?: number): {
|
|
188
276
|
lineNumber: number,
|
|
189
277
|
columnNumber?: number|undefined,
|
|
@@ -215,47 +303,62 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
215
303
|
this.prettyToggle.setVisible(canPrettyPrint);
|
|
216
304
|
}
|
|
217
305
|
|
|
306
|
+
setEditable(editable: boolean): void {
|
|
307
|
+
this.editable = editable;
|
|
308
|
+
if (this.loaded && editable !== !this.textEditor.state.readOnly) {
|
|
309
|
+
this.textEditor.dispatch({effects: config.editable.reconfigure(CodeMirror.EditorState.readOnly.of(!editable))});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
218
313
|
private async setPretty(value: boolean): Promise<void> {
|
|
219
314
|
this.prettyInternal = value;
|
|
220
315
|
this.prettyToggle.setEnabled(false);
|
|
221
316
|
|
|
222
317
|
const wasLoaded = this.loaded;
|
|
223
|
-
const
|
|
318
|
+
const {textEditor} = this;
|
|
319
|
+
const selection = textEditor.state.selection.main;
|
|
320
|
+
const startPos = textEditor.toLineColumn(selection.from), endPos = textEditor.toLineColumn(selection.to);
|
|
224
321
|
let newSelection;
|
|
225
322
|
if (this.prettyInternal) {
|
|
226
323
|
const formatInfo = await this.requestFormattedContent();
|
|
227
324
|
this.formattedMap = formatInfo.formattedMapping;
|
|
228
|
-
this.setContent(formatInfo.formattedContent
|
|
229
|
-
this.
|
|
230
|
-
const start = this.rawToPrettyLocation(
|
|
231
|
-
const end = this.rawToPrettyLocation(
|
|
232
|
-
newSelection =
|
|
325
|
+
await this.setContent(formatInfo.formattedContent);
|
|
326
|
+
this.prettyBaseDoc = textEditor.state.doc;
|
|
327
|
+
const start = this.rawToPrettyLocation(startPos.lineNumber, startPos.columnNumber);
|
|
328
|
+
const end = this.rawToPrettyLocation(endPos.lineNumber, endPos.columnNumber);
|
|
329
|
+
newSelection = textEditor.createSelection(
|
|
330
|
+
{lineNumber: start[0], columnNumber: start[1]}, {lineNumber: end[0], columnNumber: end[1]});
|
|
233
331
|
} else {
|
|
234
|
-
this.setContent(this.rawContent
|
|
235
|
-
this.
|
|
236
|
-
const start = this.prettyToRawLocation(
|
|
237
|
-
const end = this.prettyToRawLocation(
|
|
238
|
-
newSelection =
|
|
332
|
+
await this.setContent(this.rawContent || '');
|
|
333
|
+
this.baseDoc = textEditor.state.doc;
|
|
334
|
+
const start = this.prettyToRawLocation(startPos.lineNumber, startPos.columnNumber);
|
|
335
|
+
const end = this.prettyToRawLocation(endPos.lineNumber, endPos.columnNumber);
|
|
336
|
+
newSelection = textEditor.createSelection(
|
|
337
|
+
{lineNumber: start[0], columnNumber: start[1]}, {lineNumber: end[0], columnNumber: end[1]});
|
|
239
338
|
}
|
|
240
339
|
if (wasLoaded) {
|
|
241
|
-
|
|
242
|
-
this.textEditor.setSelection(newSelection);
|
|
340
|
+
textEditor.revealPosition(newSelection, false);
|
|
243
341
|
}
|
|
244
342
|
this.prettyToggle.setEnabled(true);
|
|
245
343
|
this.updatePrettyPrintState();
|
|
246
344
|
}
|
|
247
345
|
|
|
248
|
-
private
|
|
346
|
+
private getLineNumberFormatter(): CodeMirror.Extension {
|
|
347
|
+
if (this.options.lineNumbers === false) {
|
|
348
|
+
return [];
|
|
349
|
+
}
|
|
350
|
+
let formatNumber = null;
|
|
249
351
|
if (this.wasmDisassemblyInternal) {
|
|
250
352
|
const disassembly = this.wasmDisassemblyInternal;
|
|
251
353
|
const lastBytecodeOffset = disassembly.lineNumberToBytecodeOffset(disassembly.lineNumbers - 1);
|
|
252
354
|
const bytecodeOffsetDigits = lastBytecodeOffset.toString(16).length + 1;
|
|
253
|
-
|
|
254
|
-
const bytecodeOffset =
|
|
355
|
+
formatNumber = (lineNumber: number): string => {
|
|
356
|
+
const bytecodeOffset =
|
|
357
|
+
disassembly.lineNumberToBytecodeOffset(Math.min(disassembly.lineNumbers, lineNumber) - 1);
|
|
255
358
|
return `0x${bytecodeOffset.toString(16).padStart(bytecodeOffsetDigits, '0')}`;
|
|
256
|
-
}
|
|
359
|
+
};
|
|
257
360
|
} else if (this.prettyInternal) {
|
|
258
|
-
|
|
361
|
+
formatNumber = (lineNumber: number): string => {
|
|
259
362
|
const line = this.prettyToRawLocation(lineNumber - 1, 0)[0] + 1;
|
|
260
363
|
if (lineNumber === 1) {
|
|
261
364
|
return String(line);
|
|
@@ -264,17 +367,18 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
264
367
|
return String(line);
|
|
265
368
|
}
|
|
266
369
|
return '-';
|
|
267
|
-
}
|
|
268
|
-
} else {
|
|
269
|
-
this.textEditorInternal.setLineNumberFormatter(lineNumber => {
|
|
270
|
-
return String(lineNumber);
|
|
271
|
-
});
|
|
370
|
+
};
|
|
272
371
|
}
|
|
372
|
+
return formatNumber ? CodeMirror.lineNumbers({formatNumber}) : [];
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
private updateLineNumberFormatter(): void {
|
|
376
|
+
this.textEditor.dispatch({effects: config.lineNumbers.reconfigure(this.getLineNumberFormatter())});
|
|
273
377
|
}
|
|
274
378
|
|
|
275
379
|
private updatePrettyPrintState(): void {
|
|
276
380
|
this.prettyToggle.setToggled(this.prettyInternal);
|
|
277
|
-
this.textEditorInternal.
|
|
381
|
+
this.textEditorInternal.classList.toggle('pretty-printed', this.prettyInternal);
|
|
278
382
|
this.updateLineNumberFormatter();
|
|
279
383
|
}
|
|
280
384
|
|
|
@@ -292,13 +396,6 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
292
396
|
return this.formattedMap.originalToFormatted(line, column);
|
|
293
397
|
}
|
|
294
398
|
|
|
295
|
-
setEditable(editable: boolean): void {
|
|
296
|
-
this.editable = editable;
|
|
297
|
-
if (this.loadedInternal) {
|
|
298
|
-
this.textEditorInternal.setReadOnly(!editable);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
399
|
hasLoadError(): boolean {
|
|
303
400
|
return this.loadError;
|
|
304
401
|
}
|
|
@@ -322,7 +419,7 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
322
419
|
return this.loadedInternal;
|
|
323
420
|
}
|
|
324
421
|
|
|
325
|
-
get textEditor():
|
|
422
|
+
get textEditor(): TextEditor.TextEditor.TextEditor {
|
|
326
423
|
return this.textEditorInternal;
|
|
327
424
|
}
|
|
328
425
|
|
|
@@ -330,6 +427,14 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
330
427
|
return this.prettyInternal;
|
|
331
428
|
}
|
|
332
429
|
|
|
430
|
+
get contentType(): string {
|
|
431
|
+
return this.loadError ? '' : this.getContentType();
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
protected getContentType(): string {
|
|
435
|
+
return '';
|
|
436
|
+
}
|
|
437
|
+
|
|
333
438
|
private async ensureContentLoaded(): Promise<void> {
|
|
334
439
|
if (!this.contentRequested) {
|
|
335
440
|
this.contentRequested = true;
|
|
@@ -351,7 +456,7 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
351
456
|
|
|
352
457
|
progressIndicator.setWorked(1);
|
|
353
458
|
|
|
354
|
-
if (!error && this.
|
|
459
|
+
if (!error && this.contentType === 'application/wasm') {
|
|
355
460
|
const worker = Common.Worker.WorkerWrapper.fromURL(
|
|
356
461
|
new URL('../../../../entrypoints/wasmparser_worker/wasmparser_worker-entrypoint.js', import.meta.url));
|
|
357
462
|
const promise = new Promise<{
|
|
@@ -407,24 +512,14 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
407
512
|
this.prettyToggle.setEnabled(true);
|
|
408
513
|
|
|
409
514
|
if (error) {
|
|
410
|
-
this.
|
|
515
|
+
this.loadError = true;
|
|
516
|
+
this.textEditor.editor.setState(this.placeholderEditorState(error));
|
|
411
517
|
this.prettyToggle.setEnabled(false);
|
|
412
|
-
|
|
413
|
-
// Occasionally on load, there can be a race in which it appears the CodeMirror plugin
|
|
414
|
-
// runs the highlighter type assignment out of order. In case of an error then, set
|
|
415
|
-
// the highlighter type after a short delay. This appears to only occur the first
|
|
416
|
-
// time that CodeMirror is initialized, likely because the highlighter type was first
|
|
417
|
-
// initialized based on the file type, and the syntax highlighting is in a race
|
|
418
|
-
// with the new highlighter assignment. As the option is just an option and is not
|
|
419
|
-
// observable, we can't handle waiting for it here.
|
|
420
|
-
// https://github.com/codemirror/CodeMirror/issues/6019
|
|
421
|
-
// CRBug 1011445
|
|
422
|
-
setTimeout(() => this.setHighlighterType('text/plain'), 50);
|
|
423
518
|
} else {
|
|
424
519
|
if (this.shouldAutoPrettyPrint && TextUtils.TextUtils.isMinified(content)) {
|
|
425
520
|
await this.setPretty(true);
|
|
426
521
|
} else {
|
|
427
|
-
this.setContent(this.rawContent
|
|
522
|
+
await this.setContent(this.rawContent || '');
|
|
428
523
|
}
|
|
429
524
|
}
|
|
430
525
|
this.contentSet = true;
|
|
@@ -436,14 +531,28 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
436
531
|
return this.formattedContentPromise;
|
|
437
532
|
}
|
|
438
533
|
this.formattedContentPromise =
|
|
439
|
-
Formatter.ScriptFormatter.formatScriptContent(this.
|
|
534
|
+
Formatter.ScriptFormatter.formatScriptContent(this.contentType, this.rawContent || '');
|
|
440
535
|
return this.formattedContentPromise;
|
|
441
536
|
}
|
|
442
537
|
|
|
443
|
-
revealPosition(
|
|
538
|
+
revealPosition(position: {lineNumber: number, columnNumber?: number}|number, shouldHighlight?: boolean): void {
|
|
444
539
|
this.lineToScrollTo = null;
|
|
445
540
|
this.selectionToSet = null;
|
|
446
|
-
|
|
541
|
+
let line = 0, column = 0;
|
|
542
|
+
if (typeof position === 'number') {
|
|
543
|
+
const {doc} = this.textEditor.state;
|
|
544
|
+
if (position > doc.length) {
|
|
545
|
+
line = doc.lines - 1;
|
|
546
|
+
} else if (position >= 0) {
|
|
547
|
+
const lineObj = doc.lineAt(position);
|
|
548
|
+
line = lineObj.number - 1;
|
|
549
|
+
column = position - lineObj.from;
|
|
550
|
+
}
|
|
551
|
+
} else {
|
|
552
|
+
line = position.lineNumber;
|
|
553
|
+
column = position.columnNumber ?? 0;
|
|
554
|
+
}
|
|
555
|
+
this.positionToReveal = {line, column, shouldHighlight: shouldHighlight};
|
|
447
556
|
this.innerRevealPositionIfNeeded();
|
|
448
557
|
}
|
|
449
558
|
|
|
@@ -456,15 +565,14 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
456
565
|
return;
|
|
457
566
|
}
|
|
458
567
|
|
|
459
|
-
const
|
|
460
|
-
this.uiLocationToEditorLocation(this.positionToReveal.line, this.positionToReveal.column);
|
|
568
|
+
const location = this.uiLocationToEditorLocation(this.positionToReveal.line, this.positionToReveal.column);
|
|
461
569
|
|
|
462
|
-
|
|
570
|
+
const {textEditor} = this;
|
|
571
|
+
textEditor.revealPosition(textEditor.createSelection(location), this.positionToReveal.shouldHighlight);
|
|
463
572
|
this.positionToReveal = null;
|
|
464
573
|
}
|
|
465
574
|
|
|
466
575
|
private clearPositionToReveal(): void {
|
|
467
|
-
this.textEditorInternal.clearPositionHighlight();
|
|
468
576
|
this.positionToReveal = null;
|
|
469
577
|
}
|
|
470
578
|
|
|
@@ -477,24 +585,28 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
477
585
|
private innerScrollToLineIfNeeded(): void {
|
|
478
586
|
if (this.lineToScrollTo !== null) {
|
|
479
587
|
if (this.loaded && this.isShowing()) {
|
|
480
|
-
this
|
|
588
|
+
const {textEditor} = this;
|
|
589
|
+
const position = textEditor.toOffset({lineNumber: this.lineToScrollTo, columnNumber: 0});
|
|
590
|
+
textEditor.dispatch({effects: CodeMirror.EditorView.scrollTo.of(CodeMirror.EditorSelection.cursor(position))});
|
|
481
591
|
this.lineToScrollTo = null;
|
|
482
592
|
}
|
|
483
593
|
}
|
|
484
594
|
}
|
|
485
595
|
|
|
486
|
-
selection(): TextUtils.TextRange.TextRange {
|
|
487
|
-
return this.textEditor.selection();
|
|
488
|
-
}
|
|
489
|
-
|
|
490
596
|
setSelection(textRange: TextUtils.TextRange.TextRange): void {
|
|
491
597
|
this.selectionToSet = textRange;
|
|
492
598
|
this.innerSetSelectionIfNeeded();
|
|
493
599
|
}
|
|
494
600
|
|
|
495
601
|
private innerSetSelectionIfNeeded(): void {
|
|
496
|
-
|
|
497
|
-
|
|
602
|
+
const sel = this.selectionToSet;
|
|
603
|
+
if (sel && this.loaded && this.isShowing()) {
|
|
604
|
+
const {textEditor} = this;
|
|
605
|
+
textEditor.dispatch({
|
|
606
|
+
selection: textEditor.createSelection(
|
|
607
|
+
{lineNumber: sel.startLine, columnNumber: sel.startColumn},
|
|
608
|
+
{lineNumber: sel.endLine, columnNumber: sel.endColumn}),
|
|
609
|
+
});
|
|
498
610
|
this.selectionToSet = null;
|
|
499
611
|
}
|
|
500
612
|
}
|
|
@@ -505,9 +617,9 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
505
617
|
this.innerScrollToLineIfNeeded();
|
|
506
618
|
}
|
|
507
619
|
|
|
508
|
-
onTextChanged(
|
|
620
|
+
onTextChanged(): void {
|
|
509
621
|
const wasPretty = this.pretty;
|
|
510
|
-
this.prettyInternal = this.
|
|
622
|
+
this.prettyInternal = Boolean(this.prettyBaseDoc && this.textEditor.state.doc.eq(this.prettyBaseDoc));
|
|
511
623
|
if (this.prettyInternal !== wasPretty) {
|
|
512
624
|
this.updatePrettyPrintState();
|
|
513
625
|
}
|
|
@@ -519,14 +631,14 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
519
631
|
}
|
|
520
632
|
|
|
521
633
|
isClean(): boolean {
|
|
522
|
-
return this.textEditor.
|
|
523
|
-
(this.
|
|
634
|
+
return this.textEditor.state.doc.eq(this.baseDoc) ||
|
|
635
|
+
(this.prettyBaseDoc !== null && this.textEditor.state.doc.eq(this.prettyBaseDoc));
|
|
524
636
|
}
|
|
525
637
|
|
|
526
638
|
contentCommitted(): void {
|
|
527
|
-
this.
|
|
528
|
-
this.
|
|
529
|
-
this.rawContent = this.textEditor.
|
|
639
|
+
this.baseDoc = this.textEditorInternal.state.doc;
|
|
640
|
+
this.prettyBaseDoc = null;
|
|
641
|
+
this.rawContent = this.textEditor.state.doc.toString();
|
|
530
642
|
this.formattedMap = null;
|
|
531
643
|
this.formattedContentPromise = null;
|
|
532
644
|
if (this.prettyInternal) {
|
|
@@ -562,52 +674,49 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
562
674
|
return mimeType;
|
|
563
675
|
}
|
|
564
676
|
|
|
565
|
-
|
|
566
|
-
this.
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
677
|
+
protected async getLanguageSupport(content: string): Promise<CodeMirror.Extension> {
|
|
678
|
+
const mimeType = this.simplifyMimeType(content, this.contentType) || '';
|
|
679
|
+
const languageDesc = await CodeHighlighter.CodeHighlighter.languageFromMIME(mimeType);
|
|
680
|
+
if (!languageDesc) {
|
|
681
|
+
return [];
|
|
682
|
+
}
|
|
683
|
+
if (mimeType === 'text/jsx') {
|
|
684
|
+
return [
|
|
685
|
+
languageDesc,
|
|
686
|
+
CodeMirror.javascript.javascriptLanguage.data.of({autocomplete: CodeMirror.completeAnyWord}),
|
|
687
|
+
];
|
|
688
|
+
}
|
|
689
|
+
return languageDesc;
|
|
572
690
|
}
|
|
573
691
|
|
|
574
|
-
|
|
575
|
-
this.
|
|
692
|
+
async updateLanguageMode(content: string): Promise<void> {
|
|
693
|
+
const langExtension = await this.getLanguageSupport(content);
|
|
694
|
+
this.textEditor.dispatch({effects: config.language.reconfigure(langExtension)});
|
|
576
695
|
}
|
|
577
696
|
|
|
578
|
-
setContent(content: string
|
|
697
|
+
async setContent(content: string): Promise<void> {
|
|
579
698
|
this.muteChangeEventsForSetContent = true;
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
this.
|
|
590
|
-
|
|
591
|
-
this.
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// Mark non-breakable lines in the Wasm disassembly after setting
|
|
602
|
-
// up the content for the text editor (which creates the gutter).
|
|
603
|
-
if (this.wasmDisassemblyInternal) {
|
|
604
|
-
for (const lineNumber of this.wasmDisassemblyInternal.nonBreakableLineNumbers()) {
|
|
605
|
-
this.textEditorInternal.toggleLineClass(lineNumber, 'cm-non-breakable-line', true);
|
|
606
|
-
}
|
|
699
|
+
const {textEditor} = this;
|
|
700
|
+
const wasLoaded = this.loadedInternal;
|
|
701
|
+
const scrollTop = textEditor.editor.scrollDOM.scrollTop;
|
|
702
|
+
this.loadedInternal = true;
|
|
703
|
+
|
|
704
|
+
const languageSupport = await this.getLanguageSupport(content);
|
|
705
|
+
const editorState = CodeMirror.EditorState.create({
|
|
706
|
+
doc: content,
|
|
707
|
+
extensions: [
|
|
708
|
+
this.editorConfiguration(content),
|
|
709
|
+
languageSupport,
|
|
710
|
+
config.lineNumbers.of(this.getLineNumberFormatter()),
|
|
711
|
+
config.editable.of(this.editable ? [] : CodeMirror.EditorState.readOnly.of(true)),
|
|
712
|
+
],
|
|
713
|
+
});
|
|
714
|
+
this.baseDoc = editorState.doc;
|
|
715
|
+
textEditor.editor.setState(editorState);
|
|
716
|
+
if (wasLoaded) {
|
|
717
|
+
textEditor.editor.scrollDOM.scrollTop = scrollTop;
|
|
607
718
|
}
|
|
608
|
-
|
|
609
|
-
this.updateLineNumberFormatter();
|
|
610
|
-
this.updateHighlighterType(content || '');
|
|
719
|
+
this.editorInitialized();
|
|
611
720
|
this.wasShownOrLoaded();
|
|
612
721
|
|
|
613
722
|
if (this.delayedFindSearchMatches) {
|
|
@@ -617,6 +726,9 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
617
726
|
this.muteChangeEventsForSetContent = false;
|
|
618
727
|
}
|
|
619
728
|
|
|
729
|
+
protected editorInitialized(): void {
|
|
730
|
+
}
|
|
731
|
+
|
|
620
732
|
setSearchableView(view: UI.SearchableView.SearchableView|null): void {
|
|
621
733
|
this.searchableView = view;
|
|
622
734
|
}
|
|
@@ -624,24 +736,25 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
624
736
|
private doFindSearchMatches(
|
|
625
737
|
searchConfig: UI.SearchableView.SearchConfig, shouldJump: boolean, jumpBackwards: boolean): void {
|
|
626
738
|
this.currentSearchResultIndex = -1;
|
|
627
|
-
this.searchResults = [];
|
|
628
739
|
|
|
629
|
-
|
|
630
|
-
this.
|
|
631
|
-
this.searchResults = this.collectRegexMatches(regex);
|
|
740
|
+
this.searchRegex = searchConfig.toSearchRegex(true);
|
|
741
|
+
this.searchResults = this.collectRegexMatches(this.searchRegex);
|
|
632
742
|
|
|
633
743
|
if (this.searchableView) {
|
|
634
744
|
this.searchableView.updateSearchMatchesCount(this.searchResults.length);
|
|
635
745
|
}
|
|
636
746
|
|
|
747
|
+
const editor = this.textEditor;
|
|
637
748
|
if (!this.searchResults.length) {
|
|
638
|
-
|
|
749
|
+
if (editor.state.field(activeSearchState)) {
|
|
750
|
+
editor.dispatch({effects: setActiveSearch.of(null)});
|
|
751
|
+
}
|
|
639
752
|
} else if (shouldJump && jumpBackwards) {
|
|
640
753
|
this.jumpToPreviousSearchResult();
|
|
641
754
|
} else if (shouldJump) {
|
|
642
755
|
this.jumpToNextSearchResult();
|
|
643
756
|
} else {
|
|
644
|
-
|
|
757
|
+
editor.dispatch({effects: setActiveSearch.of(new ActiveSearch(this.searchRegex, null))});
|
|
645
758
|
}
|
|
646
759
|
}
|
|
647
760
|
|
|
@@ -670,7 +783,11 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
670
783
|
if (this.searchableView) {
|
|
671
784
|
this.searchableView.updateCurrentMatchIndex(this.currentSearchResultIndex);
|
|
672
785
|
}
|
|
673
|
-
|
|
786
|
+
const editor = this.textEditor;
|
|
787
|
+
const currentActiveSearch = editor.state.field(activeSearchState);
|
|
788
|
+
if (currentActiveSearch && currentActiveSearch.currentRange) {
|
|
789
|
+
editor.dispatch({effects: setActiveSearch.of(new ActiveSearch(currentActiveSearch.regexp, null))});
|
|
790
|
+
}
|
|
674
791
|
}
|
|
675
792
|
|
|
676
793
|
private resetSearch(): void {
|
|
@@ -687,10 +804,13 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
687
804
|
if (!this.loaded) {
|
|
688
805
|
return;
|
|
689
806
|
}
|
|
690
|
-
this.
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
807
|
+
const editor = this.textEditor;
|
|
808
|
+
editor.dispatch({
|
|
809
|
+
effects: setActiveSearch.of(null),
|
|
810
|
+
selection: range ? {anchor: range.from, head: range.to} : undefined,
|
|
811
|
+
scrollIntoView: true,
|
|
812
|
+
userEvent: 'select.search.cancel',
|
|
813
|
+
});
|
|
694
814
|
}
|
|
695
815
|
|
|
696
816
|
jumpToLastSearchResult(): void {
|
|
@@ -699,8 +819,7 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
699
819
|
|
|
700
820
|
private searchResultIndexForCurrentSelection(): number {
|
|
701
821
|
return Platform.ArrayUtilities.lowerBound(
|
|
702
|
-
this.searchResults, this.
|
|
703
|
-
TextUtils.TextRange.TextRange.comparator);
|
|
822
|
+
this.searchResults, this.textEditor.state.selection.main, (a, b): number => a.to - b.to);
|
|
704
823
|
}
|
|
705
824
|
|
|
706
825
|
jumpToNextSearchResult(): void {
|
|
@@ -730,8 +849,14 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
730
849
|
if (this.searchableView) {
|
|
731
850
|
this.searchableView.updateCurrentMatchIndex(this.currentSearchResultIndex);
|
|
732
851
|
}
|
|
733
|
-
this.
|
|
734
|
-
|
|
852
|
+
const editor = this.textEditor;
|
|
853
|
+
const range = this.searchResults[this.currentSearchResultIndex];
|
|
854
|
+
editor.dispatch({
|
|
855
|
+
effects: setActiveSearch.of(new ActiveSearch(this.searchRegex as RegExp, range)),
|
|
856
|
+
selection: {anchor: range.from, head: range.to},
|
|
857
|
+
scrollIntoView: true,
|
|
858
|
+
userEvent: 'select.search',
|
|
859
|
+
});
|
|
735
860
|
}
|
|
736
861
|
|
|
737
862
|
replaceSelectionWith(searchConfig: UI.SearchableView.SearchConfig, replacement: string): void {
|
|
@@ -739,146 +864,153 @@ export class SourceFrameImpl extends UI.View.SimpleView implements UI.Searchable
|
|
|
739
864
|
if (!range) {
|
|
740
865
|
return;
|
|
741
866
|
}
|
|
742
|
-
this.textEditorInternal.highlightSearchResults((this.searchRegex as RegExp), null);
|
|
743
|
-
|
|
744
|
-
const oldText = this.textEditorInternal.text(range);
|
|
745
|
-
const regex = searchConfig.toSearchRegex();
|
|
746
|
-
let text;
|
|
747
|
-
if (regex.__fromRegExpQuery) {
|
|
748
|
-
text = oldText.replace(regex, replacement);
|
|
749
|
-
} else {
|
|
750
|
-
text = oldText.replace(regex, function() {
|
|
751
|
-
return replacement;
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
867
|
|
|
755
|
-
const
|
|
756
|
-
this.
|
|
868
|
+
const insert = (this.searchRegex as RegExp).__fromRegExpQuery ? range.insertPlaceholders(replacement) : replacement;
|
|
869
|
+
const editor = this.textEditor;
|
|
870
|
+
const changes = editor.state.changes({from: range.from, to: range.to, insert});
|
|
871
|
+
editor.dispatch(
|
|
872
|
+
{changes, selection: {anchor: changes.mapPos(editor.state.selection.main.to, 1)}, userEvent: 'input.replace'});
|
|
757
873
|
}
|
|
758
874
|
|
|
759
875
|
replaceAllWith(searchConfig: UI.SearchableView.SearchConfig, replacement: string): void {
|
|
760
876
|
this.resetCurrentSearchResultIndex();
|
|
761
877
|
|
|
762
|
-
let text = this.textEditorInternal.text();
|
|
763
|
-
const range = this.textEditorInternal.fullRange();
|
|
764
|
-
|
|
765
878
|
const regex = searchConfig.toSearchRegex(true);
|
|
766
|
-
if (regex.__fromRegExpQuery) {
|
|
767
|
-
text = text.replace(regex, replacement);
|
|
768
|
-
} else {
|
|
769
|
-
text = text.replace(regex, function() {
|
|
770
|
-
return replacement;
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
|
|
774
879
|
const ranges = this.collectRegexMatches(regex);
|
|
775
880
|
if (!ranges.length) {
|
|
776
881
|
return;
|
|
777
882
|
}
|
|
778
883
|
|
|
779
|
-
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
const lastRange = ranges[lastRangeIndex];
|
|
784
|
-
const replacementLineEndings = Platform.StringUtilities.findLineEndingIndexes(replacement);
|
|
785
|
-
const replacementLineCount = replacementLineEndings.length;
|
|
786
|
-
const lastLineNumber = lastRange.startLine + replacementLineEndings.length - 1;
|
|
787
|
-
let lastColumnNumber: number = lastRange.startColumn;
|
|
788
|
-
if (replacementLineEndings.length > 1) {
|
|
789
|
-
lastColumnNumber =
|
|
790
|
-
replacementLineEndings[replacementLineCount - 1] - replacementLineEndings[replacementLineCount - 2] - 1;
|
|
791
|
-
}
|
|
884
|
+
const isRegExp = regex.__fromRegExpQuery;
|
|
885
|
+
const changes = ranges.map(
|
|
886
|
+
match =>
|
|
887
|
+
({from: match.from, to: match.to, insert: isRegExp ? match.insertPlaceholders(replacement) : replacement}));
|
|
792
888
|
|
|
793
|
-
this.
|
|
794
|
-
this.textEditorInternal.revealPosition(lastLineNumber, lastColumnNumber);
|
|
795
|
-
this.textEditorInternal.setSelection(
|
|
796
|
-
TextUtils.TextRange.TextRange.createFromLocation(lastLineNumber, lastColumnNumber));
|
|
889
|
+
this.textEditor.dispatch({changes, scrollIntoView: true, userEvent: 'input.replace.all'});
|
|
797
890
|
}
|
|
798
891
|
|
|
799
|
-
private collectRegexMatches(regexObject: RegExp):
|
|
892
|
+
private collectRegexMatches(regexObject: RegExp): SearchMatch[] {
|
|
800
893
|
const ranges = [];
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
const matchEndIndex = match.index + Math.max(match[0].length, 1);
|
|
809
|
-
if (match[0].length) {
|
|
810
|
-
ranges.push(new TextUtils.TextRange.TextRange(i, offset + match.index, i, offset + matchEndIndex));
|
|
811
|
-
}
|
|
812
|
-
offset += matchEndIndex;
|
|
813
|
-
line = line.substring(matchEndIndex);
|
|
894
|
+
let pos = 0;
|
|
895
|
+
for (const line of this.textEditor.state.doc.iterLines()) {
|
|
896
|
+
regexObject.lastIndex = 0;
|
|
897
|
+
for (;;) {
|
|
898
|
+
const match = regexObject.exec(line);
|
|
899
|
+
if (!match) {
|
|
900
|
+
break;
|
|
814
901
|
}
|
|
815
|
-
|
|
902
|
+
if (match[0].length) {
|
|
903
|
+
const from = pos + match.index;
|
|
904
|
+
ranges.push(new SearchMatch(from, from + match[0].length, match));
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
pos += line.length + 1;
|
|
816
908
|
}
|
|
817
909
|
return ranges;
|
|
818
910
|
}
|
|
819
911
|
|
|
820
|
-
populateLineGutterContextMenu(_contextMenu: UI.ContextMenu.ContextMenu, _editorLineNumber: number): Promise<void> {
|
|
821
|
-
return Promise.resolve();
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
populateTextAreaContextMenu(
|
|
825
|
-
_contextMenu: UI.ContextMenu.ContextMenu, _editorLineNumber: number, _editorColumnNumber: number): Promise<void> {
|
|
826
|
-
return Promise.resolve();
|
|
827
|
-
}
|
|
828
|
-
|
|
829
912
|
canEditSource(): boolean {
|
|
830
913
|
return this.editable;
|
|
831
914
|
}
|
|
832
915
|
|
|
833
916
|
private updateSourcePosition(): void {
|
|
834
|
-
const
|
|
835
|
-
if (
|
|
917
|
+
const {textEditor} = this, {state} = textEditor, {selection} = state;
|
|
918
|
+
if (this.displayedSelection?.eq(selection)) {
|
|
836
919
|
return;
|
|
837
920
|
}
|
|
838
|
-
|
|
839
|
-
|
|
921
|
+
this.displayedSelection = selection;
|
|
922
|
+
|
|
923
|
+
if (selection.ranges.length > 1) {
|
|
924
|
+
this.sourcePosition.setText(i18nString(UIStrings.dSelectionRegions, {PH1: selection.ranges.length}));
|
|
840
925
|
return;
|
|
841
926
|
}
|
|
842
|
-
|
|
843
|
-
if (
|
|
844
|
-
const
|
|
927
|
+
const {main} = state.selection;
|
|
928
|
+
if (main.empty) {
|
|
929
|
+
const {lineNumber, columnNumber} = textEditor.toLineColumn(main.head);
|
|
930
|
+
const location = this.prettyToRawLocation(lineNumber, columnNumber);
|
|
845
931
|
if (this.wasmDisassemblyInternal) {
|
|
846
932
|
const disassembly = this.wasmDisassemblyInternal;
|
|
847
933
|
const lastBytecodeOffset = disassembly.lineNumberToBytecodeOffset(disassembly.lineNumbers - 1);
|
|
848
934
|
const bytecodeOffsetDigits = lastBytecodeOffset.toString(16).length;
|
|
849
935
|
const bytecodeOffset = disassembly.lineNumberToBytecodeOffset(location[0]);
|
|
850
|
-
|
|
851
936
|
this.sourcePosition.setText(i18nString(
|
|
852
937
|
UIStrings.bytecodePositionXs, {PH1: bytecodeOffset.toString(16).padStart(bytecodeOffsetDigits, '0')}));
|
|
853
938
|
} else {
|
|
854
|
-
if (!this.canEditSource()) {
|
|
855
|
-
this.textEditorInternal.revealPosition(textRange.endLine, textRange.endColumn, true);
|
|
856
|
-
}
|
|
857
939
|
this.sourcePosition.setText(i18nString(UIStrings.lineSColumnS, {PH1: location[0] + 1, PH2: location[1] + 1}));
|
|
858
940
|
}
|
|
859
|
-
return;
|
|
860
|
-
}
|
|
861
|
-
textRange = textRange.normalize();
|
|
862
|
-
|
|
863
|
-
const selectedText = this.textEditorInternal.text(textRange);
|
|
864
|
-
if (textRange.startLine === textRange.endLine) {
|
|
865
|
-
this.sourcePosition.setText(i18nString(UIStrings.dCharactersSelected, {PH1: selectedText.length}));
|
|
866
941
|
} else {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
942
|
+
const startLine = state.doc.lineAt(main.from), endLine = state.doc.lineAt(main.to);
|
|
943
|
+
if (startLine.number === endLine.number) {
|
|
944
|
+
this.sourcePosition.setText(i18nString(UIStrings.dCharactersSelected, {PH1: main.to - main.from}));
|
|
945
|
+
} else {
|
|
946
|
+
this.sourcePosition.setText(i18nString(
|
|
947
|
+
UIStrings.dLinesDCharactersSelected,
|
|
948
|
+
{PH1: endLine.number - startLine.number + 1, PH2: main.to - main.from}));
|
|
949
|
+
}
|
|
870
950
|
}
|
|
871
951
|
}
|
|
952
|
+
|
|
953
|
+
onContextMenu(event: MouseEvent): boolean {
|
|
954
|
+
event.consume(true); // Consume event now to prevent document from handling the async menu
|
|
955
|
+
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
956
|
+
const {state} = this.textEditor;
|
|
957
|
+
const pos = state.selection.main.from, line = state.doc.lineAt(pos);
|
|
958
|
+
this.populateTextAreaContextMenu(contextMenu, line.number - 1, pos - line.from);
|
|
959
|
+
contextMenu.appendApplicableItems(this);
|
|
960
|
+
contextMenu.show();
|
|
961
|
+
return true;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
protected populateTextAreaContextMenu(_menu: UI.ContextMenu.ContextMenu, _lineNumber: number, _columnNumber: number):
|
|
965
|
+
void {
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
onLineGutterContextMenu(position: number, event: MouseEvent): boolean {
|
|
969
|
+
event.consume(true); // Consume event now to prevent document from handling the async menu
|
|
970
|
+
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
971
|
+
const lineNumber = this.textEditor.state.doc.lineAt(position).number - 1;
|
|
972
|
+
this.populateLineGutterContextMenu(contextMenu, lineNumber);
|
|
973
|
+
contextMenu.appendApplicableItems(this);
|
|
974
|
+
contextMenu.show();
|
|
975
|
+
return true;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
protected populateLineGutterContextMenu(_menu: UI.ContextMenu.ContextMenu, _lineNumber: number): void {
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
focus(): void {
|
|
982
|
+
this.textEditor.focus();
|
|
983
|
+
}
|
|
872
984
|
}
|
|
873
985
|
|
|
874
|
-
|
|
875
|
-
|
|
986
|
+
class SearchMatch {
|
|
987
|
+
constructor(readonly from: number, readonly to: number, readonly match: RegExpMatchArray) {
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
insertPlaceholders(replacement: string): string {
|
|
991
|
+
return replacement.replace(/\$(\$|&|\d+|<[^>]+>)/g, (_, selector): string => {
|
|
992
|
+
if (selector === '$') {
|
|
993
|
+
return '$';
|
|
994
|
+
}
|
|
995
|
+
if (selector === '&') {
|
|
996
|
+
return this.match[0];
|
|
997
|
+
}
|
|
998
|
+
if (selector[0] === '<') {
|
|
999
|
+
return (this.match.groups && this.match.groups[selector.slice(1, selector.length - 1)]) || '';
|
|
1000
|
+
}
|
|
1001
|
+
return this.match[Number.parseInt(selector, 10)] || '';
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
876
1004
|
}
|
|
877
1005
|
|
|
878
1006
|
export interface Transformer {
|
|
879
|
-
editorLocationToUILocation(lineNumber: number, columnNumber
|
|
1007
|
+
editorLocationToUILocation(lineNumber: number, columnNumber: number): {
|
|
880
1008
|
lineNumber: number,
|
|
881
|
-
columnNumber
|
|
1009
|
+
columnNumber: number,
|
|
1010
|
+
};
|
|
1011
|
+
editorLocationToUILocation(lineNumber: number): {
|
|
1012
|
+
lineNumber: number,
|
|
1013
|
+
columnNumber: number|undefined,
|
|
882
1014
|
};
|
|
883
1015
|
|
|
884
1016
|
uiLocationToEditorLocation(lineNumber: number, columnNumber?: number): {
|
|
@@ -887,16 +1019,6 @@ export interface Transformer {
|
|
|
887
1019
|
};
|
|
888
1020
|
}
|
|
889
1021
|
|
|
890
|
-
const registeredLineDecorators: LineDecoratorRegistration[] = [];
|
|
891
|
-
|
|
892
|
-
export function registerLineDecorator(registration: LineDecoratorRegistration): void {
|
|
893
|
-
registeredLineDecorators.push(registration);
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
export function getRegisteredLineDecorators(): LineDecoratorRegistration[] {
|
|
897
|
-
return registeredLineDecorators;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
1022
|
// TODO(crbug.com/1167717): Make this a const enum again
|
|
901
1023
|
// eslint-disable-next-line rulesdir/const_enum
|
|
902
1024
|
export enum DecoratorType {
|
|
@@ -905,7 +1027,134 @@ export enum DecoratorType {
|
|
|
905
1027
|
COVERAGE = 'coverage',
|
|
906
1028
|
}
|
|
907
1029
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1030
|
+
const config = {
|
|
1031
|
+
editable: new CodeMirror.Compartment(),
|
|
1032
|
+
language: new CodeMirror.Compartment(),
|
|
1033
|
+
lineNumbers: new CodeMirror.Compartment(),
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
class ActiveSearch {
|
|
1037
|
+
constructor(readonly regexp: RegExp, readonly currentRange: {from: number, to: number}|null) {
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
map(change: CodeMirror.ChangeDesc): ActiveSearch {
|
|
1041
|
+
return change.empty || !this.currentRange ?
|
|
1042
|
+
this :
|
|
1043
|
+
new ActiveSearch(
|
|
1044
|
+
this.regexp, {from: change.mapPos(this.currentRange.from), to: change.mapPos(this.currentRange.to)});
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
static eq(a: ActiveSearch|null, b: ActiveSearch|null): boolean {
|
|
1048
|
+
return Boolean(
|
|
1049
|
+
a === b ||
|
|
1050
|
+
a && b && a.currentRange?.from === b.currentRange?.from && a.currentRange?.to === b.currentRange?.to &&
|
|
1051
|
+
a.regexp.source === b.regexp.source && a.regexp.flags === b.regexp.flags);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
const setActiveSearch = CodeMirror.StateEffect.define<ActiveSearch|null>(
|
|
1056
|
+
{map: (value, mapping): ActiveSearch | null => value && value.map(mapping)});
|
|
1057
|
+
|
|
1058
|
+
const activeSearchState = CodeMirror.StateField.define<ActiveSearch|null>({
|
|
1059
|
+
create(): null {
|
|
1060
|
+
return null;
|
|
1061
|
+
},
|
|
1062
|
+
update(state, tr): ActiveSearch |
|
|
1063
|
+
null {
|
|
1064
|
+
return tr.effects.reduce(
|
|
1065
|
+
(state, effect) => effect.is(setActiveSearch) ? effect.value : state, state && state.map(tr.changes));
|
|
1066
|
+
},
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
const searchMatchDeco = CodeMirror.Decoration.mark({class: 'cm-searchMatch'});
|
|
1070
|
+
const currentSearchMatchDeco = CodeMirror.Decoration.mark({class: 'cm-searchMatch cm-searchMatch-selected'});
|
|
1071
|
+
|
|
1072
|
+
const searchHighlighter = CodeMirror.ViewPlugin.fromClass(class {
|
|
1073
|
+
decorations: CodeMirror.DecorationSet;
|
|
1074
|
+
|
|
1075
|
+
constructor(view: CodeMirror.EditorView) {
|
|
1076
|
+
this.decorations = this.computeDecorations(view);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
update(update: CodeMirror.ViewUpdate): void {
|
|
1080
|
+
const active = update.state.field(activeSearchState);
|
|
1081
|
+
if (!ActiveSearch.eq(active, update.startState.field(activeSearchState)) ||
|
|
1082
|
+
(active && (update.viewportChanged || update.docChanged))) {
|
|
1083
|
+
this.decorations = this.computeDecorations(update.view);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
private computeDecorations(view: CodeMirror.EditorView): CodeMirror.DecorationSet {
|
|
1088
|
+
const active = view.state.field(activeSearchState);
|
|
1089
|
+
if (!active) {
|
|
1090
|
+
return CodeMirror.Decoration.none;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
const builder = new CodeMirror.RangeSetBuilder<CodeMirror.Decoration>();
|
|
1094
|
+
const {doc} = view.state;
|
|
1095
|
+
for (const {from, to} of view.visibleRanges) {
|
|
1096
|
+
let pos = from;
|
|
1097
|
+
for (const line of doc.iterLines(doc.lineAt(from).number, doc.lineAt(to).number + 1)) {
|
|
1098
|
+
active.regexp.lastIndex = 0;
|
|
1099
|
+
for (;;) {
|
|
1100
|
+
const match = active.regexp.exec(line);
|
|
1101
|
+
if (!match) {
|
|
1102
|
+
break;
|
|
1103
|
+
}
|
|
1104
|
+
const start = pos + match.index, end = start + match[0].length;
|
|
1105
|
+
const current = active.currentRange && active.currentRange.from === start && active.currentRange.to === end;
|
|
1106
|
+
builder.add(start, end, current ? currentSearchMatchDeco : searchMatchDeco);
|
|
1107
|
+
}
|
|
1108
|
+
pos += line.length + 1;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
return builder.finish();
|
|
1112
|
+
}
|
|
1113
|
+
}, {decorations: (value): CodeMirror.DecorationSet => value.decorations});
|
|
1114
|
+
|
|
1115
|
+
const nonBreakableLineMark = new (class extends CodeMirror.GutterMarker {
|
|
1116
|
+
elementClass = 'cm-nonBreakableLine';
|
|
1117
|
+
})();
|
|
1118
|
+
|
|
1119
|
+
// Effect to add lines (by position) to the set of non-breakable lines.
|
|
1120
|
+
export const addNonBreakableLines = CodeMirror.StateEffect.define<readonly number[]>();
|
|
1121
|
+
|
|
1122
|
+
const nonBreakableLines = CodeMirror.StateField.define<CodeMirror.RangeSet<CodeMirror.GutterMarker>>({
|
|
1123
|
+
create(): CodeMirror.RangeSet<CodeMirror.GutterMarker> {
|
|
1124
|
+
return CodeMirror.RangeSet.empty;
|
|
1125
|
+
},
|
|
1126
|
+
update(deco, tr): CodeMirror.RangeSet<CodeMirror.GutterMarker> {
|
|
1127
|
+
return tr.effects.reduce((deco, effect) => {
|
|
1128
|
+
return !effect.is(addNonBreakableLines) ?
|
|
1129
|
+
deco :
|
|
1130
|
+
deco.update({add: effect.value.map(pos => nonBreakableLineMark.range(pos))});
|
|
1131
|
+
}, deco.map(tr.changes));
|
|
1132
|
+
},
|
|
1133
|
+
provide: field => CodeMirror.lineNumberMarkers.from(field),
|
|
1134
|
+
});
|
|
1135
|
+
|
|
1136
|
+
export function isBreakableLine(state: CodeMirror.EditorState, line: CodeMirror.Line): boolean {
|
|
1137
|
+
const nonBreakable = state.field(nonBreakableLines);
|
|
1138
|
+
if (!nonBreakable.size) {
|
|
1139
|
+
return true;
|
|
1140
|
+
}
|
|
1141
|
+
let found = false;
|
|
1142
|
+
nonBreakable.between(line.from, line.from, () => {
|
|
1143
|
+
found = true;
|
|
1144
|
+
});
|
|
1145
|
+
return !found;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
function markNonBreakableLines(disassembly: Common.WasmDisassembly.WasmDisassembly): CodeMirror.Extension {
|
|
1149
|
+
// Mark non-breakable lines in the Wasm disassembly after setting
|
|
1150
|
+
// up the content for the text editor (which creates the gutter).
|
|
1151
|
+
return nonBreakableLines.init(state => {
|
|
1152
|
+
const marks = [];
|
|
1153
|
+
for (const lineNumber of disassembly.nonBreakableLineNumbers()) {
|
|
1154
|
+
if (lineNumber < state.doc.lines) {
|
|
1155
|
+
marks.push(nonBreakableLineMark.range(state.doc.line(lineNumber + 1).from));
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
return CodeMirror.RangeSet.of(marks);
|
|
1159
|
+
});
|
|
911
1160
|
}
|