chrome-devtools-frontend 1.0.940255 → 1.0.942095

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.
Files changed (133) hide show
  1. package/config/gni/all_devtools_files.gni +0 -13
  2. package/config/gni/devtools_grd_files.gni +13 -13
  3. package/config/gni/devtools_image_files.gni +1 -2
  4. package/front_end/.eslintrc.js +1 -0
  5. package/front_end/Images/src/feedback_button_icon.svg +3 -0
  6. package/front_end/Tests.js +15 -0
  7. package/front_end/core/common/Color.ts +5 -0
  8. package/front_end/core/i18n/locales/en-US.json +39 -30
  9. package/front_end/core/i18n/locales/en-XL.json +39 -30
  10. package/front_end/core/sdk/DOMDebuggerModel.ts +18 -1
  11. package/front_end/core/sdk/sdk-meta.ts +17 -3
  12. package/front_end/entrypoints/devtools_app/devtools_app.json +1 -7
  13. package/front_end/entrypoints/main/MainImpl.ts +26 -0
  14. package/front_end/entrypoints/shell/shell.js +0 -11
  15. package/front_end/entrypoints/shell/shell.json +0 -1
  16. package/front_end/entrypoints/worker_app/worker_app.json +0 -4
  17. package/front_end/generated/InspectorBackendCommands.js +1 -0
  18. package/front_end/generated/protocol.d.ts +2 -0
  19. package/front_end/global_typings/global_defs.d.ts +5 -0
  20. package/front_end/legacy_test_runner/console_test_runner/console_test_runner.js +14 -2
  21. package/front_end/legacy_test_runner/legacy_test_runner.ts +10 -1
  22. package/front_end/legacy_test_runner/test_runner/TestRunner.js +9 -0
  23. package/front_end/models/formatter/SourceFormatter.ts +0 -10
  24. package/front_end/models/workspace/UISourceCode.ts +9 -42
  25. package/front_end/panels/animation/AnimationTimeline.ts +3 -3
  26. package/front_end/panels/application/ApplicationPanelSidebar.ts +3 -3
  27. package/front_end/panels/application/application-meta.ts +0 -3
  28. package/front_end/panels/console/ConsolePinPane.ts +21 -26
  29. package/front_end/panels/coverage/CoverageDecorationManager.ts +4 -5
  30. package/front_end/panels/coverage/CoverageView.ts +2 -105
  31. package/front_end/panels/css_overview/components/CSSOverviewStartView.ts +11 -56
  32. package/front_end/panels/css_overview/components/cssOverviewStartView.css +1 -8
  33. package/front_end/panels/elements/ElementsTreeElement.ts +4 -9
  34. package/front_end/panels/elements/components/adornerSettingsPane.css +0 -4
  35. package/front_end/panels/emulation/emulation-meta.ts +2 -2
  36. package/front_end/panels/issues/IssueKindView.ts +22 -4
  37. package/front_end/panels/issues/issues-meta.ts +0 -2
  38. package/front_end/panels/layers/module.json +0 -1
  39. package/front_end/panels/lighthouse/lighthouseStartView.css +4 -0
  40. package/front_end/panels/media/media-meta.ts +0 -3
  41. package/front_end/panels/network/NetworkLogView.ts +3 -0
  42. package/front_end/panels/network/ResourceWebSocketFrameView.ts +2 -1
  43. package/front_end/panels/network/network-meta.ts +0 -3
  44. package/front_end/panels/profiler/module.json +1 -2
  45. package/front_end/panels/security/security-meta.ts +0 -3
  46. package/front_end/panels/sources/BreakpointEditDialog.ts +16 -30
  47. package/front_end/panels/sources/CSSPlugin.ts +310 -331
  48. package/front_end/panels/sources/CallStackSidebarPane.ts +28 -34
  49. package/front_end/panels/sources/CoveragePlugin.ts +121 -6
  50. package/front_end/panels/sources/DebuggerPlugin.ts +1166 -1243
  51. package/front_end/panels/sources/EditingLocationHistoryManager.ts +71 -101
  52. package/front_end/panels/sources/GoToLineQuickOpen.ts +4 -3
  53. package/front_end/panels/sources/InplaceFormatterEditorAction.ts +3 -3
  54. package/front_end/panels/sources/JavaScriptCompilerPlugin.ts +26 -23
  55. package/front_end/panels/sources/Plugin.ts +20 -4
  56. package/front_end/panels/sources/ProfilePlugin.ts +185 -0
  57. package/front_end/panels/sources/ScriptFormatterEditorAction.ts +3 -3
  58. package/front_end/panels/sources/ScriptOriginPlugin.ts +0 -10
  59. package/front_end/panels/sources/SnippetsPlugin.ts +1 -10
  60. package/front_end/panels/sources/SourcesPanel.ts +15 -10
  61. package/front_end/panels/sources/SourcesView.ts +10 -8
  62. package/front_end/panels/sources/TabbedEditorContainer.ts +31 -27
  63. package/front_end/panels/sources/UISourceCodeFrame.ts +335 -470
  64. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +3 -2
  65. package/front_end/panels/sources/sources-legacy.ts +0 -6
  66. package/front_end/panels/sources/sources.ts +0 -2
  67. package/front_end/panels/timeline/module.json +0 -2
  68. package/front_end/third_party/codemirror.next/bundle.ts +9 -13
  69. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  70. package/front_end/third_party/codemirror.next/chunk/javascript.js +2 -2
  71. package/front_end/third_party/codemirror.next/chunk/markdown.js +2 -6
  72. package/front_end/third_party/codemirror.next/chunk/php.js +2 -6
  73. package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
  74. package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
  75. package/front_end/third_party/codemirror.next/chunk/xml.js +2 -2
  76. package/front_end/third_party/codemirror.next/codemirror.next.d.ts +279 -198
  77. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
  78. package/front_end/third_party/codemirror.next/package.json +13 -11
  79. package/front_end/ui/components/code_highlighter/CodeHighlighter.ts +60 -68
  80. package/front_end/ui/components/data_grid/dataGrid.css +12 -10
  81. package/front_end/ui/components/docs/css_overview/start_view.html +25 -0
  82. package/front_end/ui/components/docs/css_overview/start_view.ts +14 -0
  83. package/front_end/ui/components/docs/panel_feedback/basic.html +25 -0
  84. package/front_end/ui/components/docs/panel_feedback/basic.ts +20 -0
  85. package/front_end/ui/components/docs/panel_feedback/button.html +25 -0
  86. package/front_end/ui/components/docs/panel_feedback/button.ts +18 -0
  87. package/front_end/ui/components/helpers/get-stylesheet.ts +1 -0
  88. package/front_end/ui/components/panel_feedback/FeedbackButton.ts +67 -0
  89. package/front_end/ui/components/panel_feedback/PanelFeedback.ts +100 -0
  90. package/front_end/ui/components/panel_feedback/panelFeedback.css +76 -0
  91. package/front_end/ui/components/panel_feedback/panel_feedback.ts +6 -0
  92. package/front_end/ui/components/report_view/reportValue.css +1 -0
  93. package/front_end/ui/components/text_editor/TextEditor.ts +79 -36
  94. package/front_end/ui/components/text_editor/config.ts +42 -26
  95. package/front_end/ui/components/text_editor/javascript.ts +2 -3
  96. package/front_end/ui/components/text_editor/position.ts +17 -0
  97. package/front_end/ui/components/text_editor/text_editor.ts +1 -0
  98. package/front_end/ui/components/text_editor/theme.ts +5 -1
  99. package/front_end/ui/legacy/Infobar.ts +2 -6
  100. package/front_end/ui/legacy/ShortcutRegistry.ts +11 -7
  101. package/front_end/ui/legacy/Widget.ts +1 -1
  102. package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +2 -1
  103. package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +3 -1
  104. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +2 -1
  105. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +35 -131
  106. package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +2 -1
  107. package/front_end/ui/legacy/components/perf_ui/TimelineGrid.ts +3 -1
  108. package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +2 -1
  109. package/front_end/ui/legacy/components/source_frame/BinaryResourceViewFactory.ts +3 -6
  110. package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +18 -14
  111. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +502 -252
  112. package/front_end/ui/legacy/components/source_frame/source_frame-legacy.ts +0 -11
  113. package/front_end/ui/legacy/components/source_frame/source_frame.ts +0 -2
  114. package/front_end/ui/legacy/components/text_editor/cmdevtools.css +3 -1
  115. package/front_end/ui/legacy/radioButton.css +1 -13
  116. package/front_end/ui/legacy/softContextMenu.css +1 -0
  117. package/front_end/ui/legacy/themeColors.css +36 -0
  118. package/front_end/ui/legacy/utils/append-style.ts +9 -4
  119. package/package.json +1 -1
  120. package/scripts/build/generate_css_js_files.js +23 -9
  121. package/scripts/build/ninja/generate_css.gni +10 -1
  122. package/scripts/eslint_rules/lib/check_css_import.js +2 -2
  123. package/scripts/eslint_rules/tests/check_css_import_test.js +12 -0
  124. package/front_end/Images/radioDot-dark-theme.png +0 -0
  125. package/front_end/Images/radioDot.png +0 -0
  126. package/front_end/panels/application/module.json +0 -7
  127. package/front_end/panels/issues/module.json +0 -6
  128. package/front_end/panels/layer_viewer/module.json +0 -6
  129. package/front_end/panels/media/module.json +0 -6
  130. package/front_end/panels/network/module.json +0 -6
  131. package/front_end/panels/security/module.json +0 -5
  132. package/front_end/ui/legacy/components/perf_ui/module.json +0 -13
  133. package/front_end/ui/legacy/components/source_frame/SourcesTextEditor.ts +0 -1030
@@ -28,146 +28,116 @@
28
28
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
  */
30
30
 
31
- import * as Common from '../../core/common/common.js';
32
- import type * as TextUtils from '../../models/text_utils/text_utils.js';
33
31
  import * as Workspace from '../../models/workspace/workspace.js';
32
+ import type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
34
33
  import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
35
34
 
36
35
  import type {SourcesView} from './SourcesView.js';
37
36
  import type {UISourceCodeFrame} from './UISourceCodeFrame.js';
38
37
 
38
+ export const HistoryDepth = 20;
39
+
39
40
  export class EditingLocationHistoryManager {
40
- private readonly sourcesView: SourcesView;
41
- private readonly historyManager: Common.SimpleHistoryManager.SimpleHistoryManager;
42
- private readonly currentSourceFrameCallback: () => UISourceCodeFrame | null;
43
- constructor(sourcesView: SourcesView, currentSourceFrameCallback: () => UISourceCodeFrame | null) {
44
- this.sourcesView = sourcesView;
45
- this.historyManager = new Common.SimpleHistoryManager.SimpleHistoryManager(HistoryDepth);
46
- this.currentSourceFrameCallback = currentSourceFrameCallback;
41
+ private readonly entries: EditingLocationHistoryEntry[] = [];
42
+ private current = -1;
43
+ private revealing = false;
44
+
45
+ constructor(private readonly sourcesView: SourcesView) {
47
46
  }
48
47
 
49
48
  trackSourceFrameCursorJumps(sourceFrame: UISourceCodeFrame): void {
50
- sourceFrame.textEditor.addEventListener(
51
- SourceFrame.SourcesTextEditor.Events.JumpHappened, this.onJumpHappened.bind(this));
49
+ sourceFrame.addEventListener(
50
+ SourceFrame.SourceFrame.Events.EditorUpdate, event => this.onEditorUpdate(event.data, sourceFrame));
52
51
  }
53
52
 
54
- private onJumpHappened(event: Common.EventTarget.EventTargetEvent<SourceFrame.SourcesTextEditor.JumpHappenedEvent>):
55
- void {
56
- const {from, to} = event.data;
57
- if (from) {
58
- this.updateActiveState(from);
53
+ private onEditorUpdate(update: CodeMirror.ViewUpdate, sourceFrame: UISourceCodeFrame): void {
54
+ if (update.docChanged) {
55
+ this.mapEntriesFor(sourceFrame.uiSourceCode(), update.changes);
59
56
  }
60
- if (to) {
61
- this.pushActiveState(to);
57
+ const prevPos = update.startState.selection.main;
58
+ const newPos = update.state.selection.main;
59
+ const isJump = !this.revealing && prevPos.anchor !== newPos.anchor && update.transactions.some((tr): boolean => {
60
+ return Boolean(
61
+ tr.isUserEvent('select.pointer') || tr.isUserEvent('select.reveal') || tr.isUserEvent('select.search'));
62
+ });
63
+ if (isJump) {
64
+ this.updateCurrentState(sourceFrame.uiSourceCode(), prevPos.head);
65
+ if (this.entries.length > this.current + 1) {
66
+ this.entries.length = this.current + 1;
67
+ }
68
+ this.entries.push(new EditingLocationHistoryEntry(sourceFrame.uiSourceCode(), newPos.head));
69
+ this.current++;
70
+ if (this.entries.length > HistoryDepth) {
71
+ this.entries.shift();
72
+ this.current--;
73
+ }
62
74
  }
63
75
  }
64
76
 
65
- rollback(): void {
66
- this.historyManager.rollback();
67
- }
68
-
69
- rollover(): void {
70
- this.historyManager.rollover();
77
+ updateCurrentState(uiSourceCode: Workspace.UISourceCode.UISourceCode, position: number): void {
78
+ if (!this.revealing) {
79
+ const top = this.current >= 0 ? this.entries[this.current] : null;
80
+ if (top?.matches(uiSourceCode)) {
81
+ top.position = position;
82
+ }
83
+ }
71
84
  }
72
85
 
73
- updateCurrentState(): void {
74
- const sourceFrame = this.currentSourceFrameCallback();
75
- if (!sourceFrame) {
76
- return;
86
+ private mapEntriesFor(uiSourceCode: Workspace.UISourceCode.UISourceCode, change: CodeMirror.ChangeDesc): void {
87
+ for (const entry of this.entries) {
88
+ if (entry.matches(uiSourceCode)) {
89
+ entry.position = change.mapPos(entry.position);
90
+ }
77
91
  }
78
- this.updateActiveState(sourceFrame.textEditor.selection());
79
92
  }
80
93
 
81
- pushNewState(): void {
82
- const sourceFrame = this.currentSourceFrameCallback();
83
- if (!sourceFrame) {
84
- return;
94
+ private reveal(entry: EditingLocationHistoryEntry): void {
95
+ const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCode(entry.projectId, entry.url);
96
+ if (uiSourceCode) {
97
+ this.revealing = true;
98
+ this.sourcesView.showSourceLocation(uiSourceCode, entry.position, false, true);
99
+ this.revealing = false;
85
100
  }
86
- this.pushActiveState(sourceFrame.textEditor.selection());
87
101
  }
88
102
 
89
- private updateActiveState(selection: TextUtils.TextRange.TextRange): void {
90
- const active = (this.historyManager.active() as EditingLocationHistoryEntry | null);
91
- if (!active) {
92
- return;
93
- }
94
- const sourceFrame = this.currentSourceFrameCallback();
95
- if (!sourceFrame) {
96
- return;
103
+ rollback(): void {
104
+ if (this.current > 0) {
105
+ this.current--;
106
+ this.reveal(this.entries[this.current]);
97
107
  }
98
- const entry = new EditingLocationHistoryEntry(this.sourcesView, this, sourceFrame, selection);
99
- active.merge(entry);
100
108
  }
101
109
 
102
- private pushActiveState(selection: TextUtils.TextRange.TextRange): void {
103
- const sourceFrame = this.currentSourceFrameCallback();
104
- if (!sourceFrame) {
105
- return;
110
+ rollover(): void {
111
+ if (this.current < this.entries.length - 1) {
112
+ this.current++;
113
+ this.reveal(this.entries[this.current]);
106
114
  }
107
- const entry = new EditingLocationHistoryEntry(this.sourcesView, this, sourceFrame, selection);
108
- this.historyManager.push(entry);
109
115
  }
110
116
 
111
117
  removeHistoryForSourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
112
- this.historyManager.filterOut(entry => {
113
- const historyEntry = (entry as EditingLocationHistoryEntry);
114
- return historyEntry.projectId === uiSourceCode.project().id() && historyEntry.url === uiSourceCode.url();
115
- });
118
+ for (let i = this.entries.length - 1; i >= 0; i--) {
119
+ if (this.entries[i].matches(uiSourceCode)) {
120
+ this.entries.splice(i, 1);
121
+ if (this.current >= i) {
122
+ this.current--;
123
+ }
124
+ }
125
+ }
116
126
  }
117
127
  }
118
128
 
119
- export const HistoryDepth = 20;
120
-
121
- export class EditingLocationHistoryEntry implements Common.SimpleHistoryManager.HistoryEntry {
122
- private readonly sourcesView: SourcesView;
123
- private readonly editingLocationManager: EditingLocationHistoryManager;
129
+ class EditingLocationHistoryEntry {
124
130
  readonly projectId: string;
125
131
  readonly url: string;
126
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
127
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
- private positionHandle: any;
129
-
130
- constructor(
131
- sourcesView: SourcesView, editingLocationManager: EditingLocationHistoryManager, sourceFrame: UISourceCodeFrame,
132
- selection: TextUtils.TextRange.TextRange) {
133
- this.sourcesView = sourcesView;
134
- this.editingLocationManager = editingLocationManager;
135
- const uiSourceCode = sourceFrame.uiSourceCode();
132
+ position: number;
133
+
134
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode, position: number) {
136
135
  this.projectId = uiSourceCode.project().id();
137
136
  this.url = uiSourceCode.url();
138
-
139
- const position = this.positionFromSelection(selection);
140
- this.positionHandle = sourceFrame.textEditor.textEditorPositionHandle(position.lineNumber, position.columnNumber);
141
- }
142
-
143
- merge(entry: EditingLocationHistoryEntry): void {
144
- if (this.projectId !== entry.projectId || this.url !== entry.url) {
145
- return;
146
- }
147
- this.positionHandle = entry.positionHandle;
137
+ this.position = position;
148
138
  }
149
139
 
150
- private positionFromSelection(selection: TextUtils.TextRange.TextRange): {
151
- lineNumber: number,
152
- columnNumber: number,
153
- } {
154
- return {lineNumber: selection.endLine, columnNumber: selection.endColumn};
155
- }
156
-
157
- valid(): boolean {
158
- const position = this.positionHandle.resolve();
159
- const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCode(this.projectId, this.url);
160
- return Boolean(position && uiSourceCode);
161
- }
162
-
163
- reveal(): void {
164
- const position = this.positionHandle.resolve();
165
- const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCode(this.projectId, this.url);
166
- if (!position || !uiSourceCode) {
167
- return;
168
- }
169
-
170
- this.editingLocationManager.updateCurrentState();
171
- this.sourcesView.showSourceLocation(uiSourceCode, position.lineNumber, position.columnNumber);
140
+ matches(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
141
+ return this.url === uiSourceCode.url() && this.projectId === uiSourceCode.project().id();
172
142
  }
173
143
  }
@@ -97,8 +97,9 @@ export class GoToLineQuickOpen extends QuickOpen.FilteredListWidget.Provider {
97
97
  this.#goToLineStrings.push(i18nString(UIStrings.typeANumberToGoToThatLine));
98
98
  return;
99
99
  }
100
+ const editorState = sourceFrame.textEditor.state;
100
101
  const disassembly = sourceFrame.wasmDisassembly;
101
- const currentLineNumber = sourceFrame.textEditor.currentLineNumber();
102
+ const currentLineNumber = editorState.doc.lineAt(editorState.selection.main.head).number - 1;
102
103
  if (disassembly) {
103
104
  const lastBytecodeOffset = disassembly.lineNumberToBytecodeOffset(disassembly.lineNumbers - 1);
104
105
  const bytecodeOffsetDigits = lastBytecodeOffset.toString(16).length;
@@ -110,7 +111,7 @@ export class GoToLineQuickOpen extends QuickOpen.FilteredListWidget.Provider {
110
111
  }));
111
112
  return;
112
113
  }
113
- const linesCount = sourceFrame.textEditor.linesCount;
114
+ const linesCount = editorState.doc.lines;
114
115
  this.#goToLineStrings.push(
115
116
  i18nString(UIStrings.currentLineSTypeALineNumber, {PH1: currentLineNumber + 1, PH2: linesCount}));
116
117
  return;
@@ -124,7 +125,7 @@ export class GoToLineQuickOpen extends QuickOpen.FilteredListWidget.Provider {
124
125
  this.#goToLineStrings.push(i18nString(UIStrings.goToLineSAndColumnS, {PH1: position.line, PH2: position.column}));
125
126
  return;
126
127
  }
127
- if (sourceFrame && position.line > sourceFrame.textEditor.linesCount) {
128
+ if (sourceFrame && position.line > sourceFrame.textEditor.state.doc.lines) {
128
129
  return;
129
130
  }
130
131
  this.#goToLineStrings.push(i18nString(UIStrings.goToLineS, {PH1: position.line}));
@@ -128,12 +128,12 @@ export class InplaceFormatterEditorAction implements EditorAction {
128
128
  const sourceFrame = (this.sourcesView.viewForFile(uiSourceCode) as SourceFrame.SourceFrame.SourceFrameImpl);
129
129
  let start: number[]|number[] = [0, 0];
130
130
  if (sourceFrame) {
131
- const selection = sourceFrame.selection();
132
- start = formatterMapping.originalToFormatted(selection.startLine, selection.startColumn);
131
+ const selection = sourceFrame.textEditor.toLineColumn(sourceFrame.textEditor.state.selection.main.head);
132
+ start = formatterMapping.originalToFormatted(selection.lineNumber, selection.columnNumber);
133
133
  }
134
134
  uiSourceCode.setWorkingCopy(formattedContent);
135
135
 
136
- this.sourcesView.showSourceLocation(uiSourceCode, start[0], start[1]);
136
+ this.sourcesView.showSourceLocation(uiSourceCode, {lineNumber: start[0], columnNumber: start[1]});
137
137
  }
138
138
  }
139
139
 
@@ -5,32 +5,35 @@
5
5
  import * as SDK from '../../core/sdk/sdk.js';
6
6
  import * as Bindings from '../../models/bindings/bindings.js';
7
7
  import * as Workspace from '../../models/workspace/workspace.js';
8
- import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
8
+ import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
9
9
  import * as UI from '../../ui/legacy/legacy.js';
10
+ import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
10
11
  import * as Snippets from '../snippets/snippets.js';
11
12
 
12
13
  import {Plugin} from './Plugin.js';
13
14
 
14
15
  export class JavaScriptCompilerPlugin extends Plugin {
15
- private readonly textEditor: SourceFrame.SourcesTextEditor.SourcesTextEditor;
16
- private uiSourceCode: Workspace.UISourceCode.UISourceCode;
17
- private compiling: boolean;
18
- private recompileScheduled: boolean;
19
- private timeout: number|null;
20
- private message: Workspace.UISourceCode.Message|null;
21
- private disposed: boolean;
22
- constructor(
23
- textEditor: SourceFrame.SourcesTextEditor.SourcesTextEditor, uiSourceCode: Workspace.UISourceCode.UISourceCode) {
24
- super();
25
- this.textEditor = textEditor;
26
- this.uiSourceCode = uiSourceCode;
27
- this.compiling = false;
28
- this.recompileScheduled = false;
29
- this.timeout = null;
30
- this.message = null;
31
- this.disposed = false;
16
+ private compiling: boolean = false;
17
+ private recompileScheduled: boolean = false;
18
+ private timeout: number|null = null;
19
+ private message: Workspace.UISourceCode.Message|null = null;
20
+ private disposed: boolean = false;
21
+ private editor: TextEditor.TextEditor.TextEditor|null = null;
22
+
23
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
24
+ super(uiSourceCode);
25
+ }
26
+
27
+ editorExtension(): CodeMirror.Extension {
28
+ return CodeMirror.EditorView.updateListener.of(update => {
29
+ if (update.docChanged) {
30
+ this.scheduleCompile();
31
+ }
32
+ });
33
+ }
32
34
 
33
- this.textEditor.addEventListener(UI.TextEditor.Events.TextChanged, this.scheduleCompile, this);
35
+ editorInitialized(editor: TextEditor.TextEditor.TextEditor): void {
36
+ this.editor = editor;
34
37
  if (this.uiSourceCode.hasCommits() || this.uiSourceCode.isDirty()) {
35
38
  this.scheduleCompile();
36
39
  }
@@ -78,7 +81,7 @@ export class JavaScriptCompilerPlugin extends Plugin {
78
81
 
79
82
  private async compile(): Promise<void> {
80
83
  const runtimeModel = this.findRuntimeModel();
81
- if (!runtimeModel) {
84
+ if (!runtimeModel || !this.editor) {
82
85
  return;
83
86
  }
84
87
  const currentExecutionContext = UI.Context.Context.instance().flavor(SDK.RuntimeModel.ExecutionContext);
@@ -86,11 +89,11 @@ export class JavaScriptCompilerPlugin extends Plugin {
86
89
  return;
87
90
  }
88
91
 
89
- const code = this.textEditor.text();
90
- if (code.length > 1024 * 100) {
92
+ if (this.editor.state.doc.length > 1024 * 100) {
91
93
  return;
92
94
  }
93
95
 
96
+ const code = this.editor.state.doc.toString();
94
97
  const scripts =
95
98
  Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().scriptsForResource(this.uiSourceCode);
96
99
  const isModule = scripts.reduce((v, s) => v || s.isModule === true, false);
@@ -109,6 +112,7 @@ export class JavaScriptCompilerPlugin extends Plugin {
109
112
  }
110
113
  if (this.message) {
111
114
  this.uiSourceCode.removeMessage(this.message);
115
+ this.message = null;
112
116
  }
113
117
  if (this.disposed || !result || !result.exceptionDetails) {
114
118
  return;
@@ -125,7 +129,6 @@ export class JavaScriptCompilerPlugin extends Plugin {
125
129
  }
126
130
 
127
131
  dispose(): void {
128
- this.textEditor.removeEventListener(UI.TextEditor.Events.TextChanged, this.scheduleCompile, this);
129
132
  if (this.message) {
130
133
  this.uiSourceCode.removeMessage(this.message);
131
134
  }
@@ -3,9 +3,17 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import type * as Workspace from '../../models/workspace/workspace.js';
6
+ import type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
7
+ import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
6
8
  import type * as UI from '../../ui/legacy/legacy.js';
9
+ import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
7
10
 
8
11
  export class Plugin {
12
+ constructor(
13
+ protected readonly uiSourceCode: Workspace.UISourceCode.UISourceCode,
14
+ _transformer?: SourceFrame.SourceFrame.Transformer) {
15
+ }
16
+
9
17
  static accepts(_uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
10
18
  return false;
11
19
  }
@@ -29,13 +37,21 @@ export class Plugin {
29
37
  return [];
30
38
  }
31
39
 
32
- populateLineGutterContextMenu(_contextMenu: UI.ContextMenu.ContextMenu, _lineNumber: number): Promise<void> {
33
- return Promise.resolve();
40
+ populateLineGutterContextMenu(_contextMenu: UI.ContextMenu.ContextMenu, _lineNumber: number): void {
34
41
  }
35
42
 
36
43
  populateTextAreaContextMenu(_contextMenu: UI.ContextMenu.ContextMenu, _lineNumber: number, _columnNumber: number):
37
- Promise<void> {
38
- return Promise.resolve();
44
+ void {
45
+ }
46
+
47
+ decorationChanged(_type: SourceFrame.SourceFrame.DecoratorType, _editor: TextEditor.TextEditor.TextEditor): void {
48
+ }
49
+
50
+ editorExtension(): CodeMirror.Extension {
51
+ return [];
52
+ }
53
+
54
+ editorInitialized(_editor: TextEditor.TextEditor.TextEditor): void {
39
55
  }
40
56
 
41
57
  dispose(): void {
@@ -0,0 +1,185 @@
1
+ // Copyright 2021 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as i18n from '../../core/i18n/i18n.js';
6
+ import * as Platform from '../../core/platform/platform.js';
7
+ import type * as Workspace from '../../models/workspace/workspace.js';
8
+ import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
9
+ import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
10
+ import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
11
+
12
+ import {Plugin} from './Plugin.js';
13
+
14
+ const UIStrings = {
15
+ /**
16
+ *@description The milisecond unit
17
+ */
18
+ ms: 'ms',
19
+ /**
20
+ *@description Unit for data size in DevTools
21
+ */
22
+ mb: 'MB',
23
+ /**
24
+ *@description A unit
25
+ */
26
+ kb: 'kB',
27
+ };
28
+ const str_ = i18n.i18n.registerUIStrings('panels/sources/ProfilePlugin.ts', UIStrings);
29
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
30
+
31
+ class MemoryMarker extends CodeMirror.GutterMarker {
32
+ constructor(readonly value: number) {
33
+ super();
34
+ }
35
+
36
+ eq(other: MemoryMarker): boolean {
37
+ return this.value === other.value;
38
+ }
39
+
40
+ toDOM(): HTMLElement {
41
+ const element = document.createElement('div');
42
+ element.className = 'cm-profileMarker';
43
+ let value = this.value;
44
+ const intensity = Platform.NumberUtilities.clamp(Math.log10(1 + 2e-3 * value) / 5, 0.02, 1);
45
+ element.style.backgroundColor = `hsla(217, 100%, 70%, ${intensity.toFixed(3)})`;
46
+ value /= 1e3;
47
+ let units;
48
+ let fractionDigits;
49
+ if (value >= 1e3) {
50
+ units = i18nString(UIStrings.mb);
51
+ value /= 1e3;
52
+ fractionDigits = value >= 20 ? 0 : 1;
53
+ } else {
54
+ units = i18nString(UIStrings.kb);
55
+ fractionDigits = 0;
56
+ }
57
+ element.textContent = value.toFixed(fractionDigits);
58
+ const unitElement = element.appendChild(document.createElement('span'));
59
+ unitElement.className = 'cm-units';
60
+ unitElement.textContent = units;
61
+ return element;
62
+ }
63
+ }
64
+
65
+ class PerformanceMarker extends CodeMirror.GutterMarker {
66
+ constructor(readonly value: number) {
67
+ super();
68
+ }
69
+
70
+ eq(other: MemoryMarker): boolean {
71
+ return this.value === other.value;
72
+ }
73
+
74
+ toDOM(): HTMLElement {
75
+ const element = document.createElement('div');
76
+ element.className = 'cm-profileMarker';
77
+ const intensity = Platform.NumberUtilities.clamp(Math.log10(1 + 10 * this.value) / 5, 0.02, 1);
78
+ element.textContent = this.value.toFixed(1);
79
+ element.style.backgroundColor = `hsla(44, 100%, 50%, ${intensity.toFixed(3)})`;
80
+ const span = document.createElement('span');
81
+ span.className = 'cm-units';
82
+ span.textContent = i18nString(UIStrings.ms);
83
+ element.appendChild(span);
84
+ return element;
85
+ }
86
+ }
87
+
88
+ function markersFromProfileData(
89
+ map: Map<number, number>, state: CodeMirror.EditorState,
90
+ type: SourceFrame.SourceFrame.DecoratorType): CodeMirror.RangeSet<CodeMirror.GutterMarker> {
91
+ const markerType = type === SourceFrame.SourceFrame.DecoratorType.PERFORMANCE ? PerformanceMarker : MemoryMarker;
92
+ const markers: CodeMirror.Range<CodeMirror.GutterMarker>[] = [];
93
+ for (const [line, value] of map) {
94
+ if (line <= state.doc.lines) {
95
+ const {from} = state.doc.line(line);
96
+ markers.push(new markerType(value).range(from));
97
+ }
98
+ }
99
+ return CodeMirror.RangeSet.of(markers, true);
100
+ }
101
+
102
+ const makeLineLevelProfilePlugin = (type: SourceFrame.SourceFrame.DecoratorType): typeof Plugin =>
103
+ class extends Plugin {
104
+ updateEffect = CodeMirror.StateEffect.define<Map<number, number>>();
105
+ field: CodeMirror.StateField<CodeMirror.RangeSet<CodeMirror.GutterMarker>>;
106
+ gutter: CodeMirror.Extension;
107
+ compartment: CodeMirror.Compartment = new CodeMirror.Compartment();
108
+
109
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
110
+ super(uiSourceCode);
111
+
112
+ this.field = CodeMirror.StateField.define<CodeMirror.RangeSet<CodeMirror.GutterMarker>>({
113
+ create(): CodeMirror.RangeSet<CodeMirror.GutterMarker> {
114
+ return CodeMirror.RangeSet.empty;
115
+ },
116
+ update: (markers, tr) => {
117
+ return tr.effects.reduce((markers, effect) => {
118
+ return effect.is(this.updateEffect) ? markersFromProfileData(effect.value, tr.state, type) : markers;
119
+ }, markers.map(tr.changes));
120
+ },
121
+ });
122
+
123
+ this.gutter = CodeMirror.gutter({
124
+ markers: (view): CodeMirror.RangeSet<CodeMirror.GutterMarker> => view.state.field(this.field),
125
+ class: `cm-${type}Gutter`,
126
+ });
127
+ }
128
+
129
+ static accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
130
+ return uiSourceCode.contentType().hasScripts();
131
+ }
132
+
133
+ private getLineMap(): Map<number, number>|undefined {
134
+ return this.uiSourceCode.getDecorationData(type);
135
+ }
136
+
137
+ editorExtension(): CodeMirror.Extension {
138
+ const map = this.getLineMap();
139
+ return this.compartment.of(
140
+ !map ? [] : [this.field.init(state => markersFromProfileData(map, state, type)), this.gutter, theme]);
141
+ }
142
+
143
+ decorationChanged(type: SourceFrame.SourceFrame.DecoratorType, editor: TextEditor.TextEditor.TextEditor): void {
144
+ const installed = Boolean(editor.state.field(this.field, false));
145
+ const map = this.getLineMap();
146
+ if (!map) {
147
+ if (installed) {
148
+ editor.dispatch({effects: this.compartment.reconfigure([])});
149
+ }
150
+ } else if (!installed) {
151
+ editor.dispatch({
152
+ effects: this.compartment.reconfigure(
153
+ [this.field.init(state => markersFromProfileData(map, state, type)), this.gutter, theme]),
154
+ });
155
+ } else {
156
+ editor.dispatch({effects: this.updateEffect.of(map)});
157
+ }
158
+ }
159
+ };
160
+
161
+ const theme = CodeMirror.EditorView.baseTheme({
162
+ '.cm-performanceGutter': {
163
+ width: '60px',
164
+ backgroundColor: 'var(--color-background)',
165
+ marginLeft: '3px',
166
+ },
167
+ '.cm-memoryGutter': {
168
+ width: '48px',
169
+ backgroundColor: 'var(--color-background)',
170
+ marginLeft: '3px',
171
+ },
172
+ '.cm-profileMarker': {
173
+ textAlign: 'right',
174
+ paddingRight: '3px',
175
+ },
176
+ '.cm-profileMarker .cm-units': {
177
+ color: 'var(--color-text-secondary)',
178
+ fontSize: '75%',
179
+ marginLeft: '3px',
180
+ },
181
+ });
182
+
183
+ export const MemoryProfilePlugin = makeLineLevelProfilePlugin(SourceFrame.SourceFrame.DecoratorType.MEMORY);
184
+
185
+ export const PerformanceProfilePlugin = makeLineLevelProfilePlugin(SourceFrame.SourceFrame.DecoratorType.PERFORMANCE);
@@ -147,10 +147,10 @@ export class ScriptFormatterEditorAction implements EditorAction {
147
147
  const sourceFrame = this.sourcesView.viewForFile(uiSourceCode);
148
148
  let start: number[]|number[] = [0, 0];
149
149
  if (sourceFrame instanceof SourceFrame.SourceFrame.SourceFrameImpl) {
150
- const selection = sourceFrame.selection();
151
- start = formatData.mapping.originalToFormatted(selection.startLine, selection.startColumn);
150
+ const selection = sourceFrame.textEditor.toLineColumn(sourceFrame.textEditor.state.selection.main.head);
151
+ start = formatData.mapping.originalToFormatted(selection.lineNumber, selection.columnNumber);
152
152
  }
153
- this.sourcesView.showSourceLocation(formatData.formattedSourceCode, start[0], start[1]);
153
+ this.sourcesView.showSourceLocation(formatData.formattedSourceCode, {lineNumber: start[0], columnNumber: start[1]});
154
154
  }
155
155
  }
156
156
 
@@ -6,7 +6,6 @@ import * as i18n from '../../core/i18n/i18n.js';
6
6
  import type * as SDK from '../../core/sdk/sdk.js';
7
7
  import * as Bindings from '../../models/bindings/bindings.js';
8
8
  import type * as Workspace from '../../models/workspace/workspace.js';
9
- import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
10
9
  import * as Components from '../../ui/legacy/components/utils/utils.js';
11
10
  import * as UI from '../../ui/legacy/legacy.js';
12
11
 
@@ -27,15 +26,6 @@ const UIStrings = {
27
26
  const str_ = i18n.i18n.registerUIStrings('panels/sources/ScriptOriginPlugin.ts', UIStrings);
28
27
 
29
28
  export class ScriptOriginPlugin extends Plugin {
30
- private readonly textEditor: SourceFrame.SourcesTextEditor.SourcesTextEditor;
31
- private readonly uiSourceCode: Workspace.UISourceCode.UISourceCode;
32
- constructor(
33
- textEditor: SourceFrame.SourcesTextEditor.SourcesTextEditor, uiSourceCode: Workspace.UISourceCode.UISourceCode) {
34
- super();
35
- this.textEditor = textEditor;
36
- this.uiSourceCode = uiSourceCode;
37
- }
38
-
39
29
  static accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
40
30
  return uiSourceCode.contentType().hasScripts() || Boolean(ScriptOriginPlugin.script(uiSourceCode));
41
31
  }
@@ -5,7 +5,6 @@
5
5
  import * as Host from '../../core/host/host.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import type * as Workspace from '../../models/workspace/workspace.js';
8
- import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
9
8
  import * as UI from '../../ui/legacy/legacy.js';
10
9
  import * as Snippets from '../snippets/snippets.js';
11
10
 
@@ -23,16 +22,8 @@ const UIStrings = {
23
22
  };
24
23
  const str_ = i18n.i18n.registerUIStrings('panels/sources/SnippetsPlugin.ts', UIStrings);
25
24
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
26
- export class SnippetsPlugin extends Plugin {
27
- private readonly textEditor: SourceFrame.SourcesTextEditor.SourcesTextEditor;
28
- private readonly uiSourceCode: Workspace.UISourceCode.UISourceCode;
29
- constructor(
30
- textEditor: SourceFrame.SourcesTextEditor.SourcesTextEditor, uiSourceCode: Workspace.UISourceCode.UISourceCode) {
31
- super();
32
- this.textEditor = textEditor;
33
- this.uiSourceCode = uiSourceCode;
34
- }
35
25
 
26
+ export class SnippetsPlugin extends Plugin {
36
27
  static accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
37
28
  return Snippets.ScriptSnippetFileSystem.isSnippetsUISourceCode(uiSourceCode);
38
29
  }