chrome-devtools-frontend 1.0.951864 → 1.0.952784
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/config/gni/devtools_grd_files.gni +3 -0
- package/front_end/.eslintrc.js +6 -0
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/i18n/locales/en-US.json +3 -0
- package/front_end/core/i18n/locales/en-XL.json +3 -0
- package/front_end/core/root/Runtime.ts +4 -12
- package/front_end/core/sdk/PageResourceLoader.ts +2 -1
- package/front_end/entrypoints/formatter_worker/AcornTokenizer.ts +39 -39
- package/front_end/entrypoints/formatter_worker/CSSFormatter.ts +54 -54
- package/front_end/entrypoints/formatter_worker/ESTreeWalker.ts +20 -20
- package/front_end/entrypoints/formatter_worker/FormattedContentBuilder.ts +54 -54
- package/front_end/entrypoints/formatter_worker/HTMLFormatter.ts +145 -144
- package/front_end/entrypoints/formatter_worker/JavaScriptFormatter.ts +40 -40
- package/front_end/entrypoints/heap_snapshot_worker/AllocationProfile.ts +64 -69
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +202 -200
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +109 -108
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.ts +17 -17
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +30 -30
- package/front_end/entrypoints/inspector_main/RenderingOptions.ts +25 -25
- package/front_end/entrypoints/main/ExecutionContextSelector.ts +52 -55
- package/front_end/entrypoints/main/MainImpl.ts +49 -49
- package/front_end/entrypoints/node_app/NodeConnectionsPanel.ts +43 -43
- package/front_end/entrypoints/node_app/NodeMain.ts +38 -38
- package/front_end/generated/InspectorBackendCommands.js +5 -1
- package/front_end/generated/protocol.d.ts +16 -0
- package/front_end/legacy/legacy-defs.d.ts +0 -21
- package/front_end/models/heap_snapshot_model/HeapSnapshotModel.ts +1 -1
- package/front_end/models/issues_manager/ClientHintIssue.ts +95 -0
- package/front_end/models/issues_manager/ContentSecurityPolicyIssue.ts +6 -6
- package/front_end/models/issues_manager/ContrastCheckTrigger.ts +15 -15
- package/front_end/models/issues_manager/CorsIssue.ts +9 -9
- package/front_end/models/issues_manager/CrossOriginEmbedderPolicyIssue.ts +5 -5
- package/front_end/models/issues_manager/DeprecationIssue.ts +7 -7
- package/front_end/models/issues_manager/GenericIssue.ts +5 -5
- package/front_end/models/issues_manager/HeavyAdIssue.ts +5 -5
- package/front_end/models/issues_manager/Issue.ts +10 -10
- package/front_end/models/issues_manager/IssueResolver.ts +11 -10
- package/front_end/models/issues_manager/IssuesManager.ts +61 -56
- package/front_end/models/issues_manager/LowTextContrastIssue.ts +4 -4
- package/front_end/models/issues_manager/MixedContentIssue.ts +7 -7
- package/front_end/models/issues_manager/NavigatorUserAgentIssue.ts +7 -7
- package/front_end/models/issues_manager/QuirksModeIssue.ts +4 -4
- package/front_end/models/issues_manager/SameSiteCookieIssue.ts +16 -16
- package/front_end/models/issues_manager/SharedArrayBufferIssue.ts +5 -5
- package/front_end/models/issues_manager/SourceFrameIssuesManager.ts +32 -31
- package/front_end/models/issues_manager/TrustedWebActivityIssue.ts +5 -5
- package/front_end/models/issues_manager/WasmCrossOriginModuleSharingIssue.ts +5 -5
- package/front_end/models/issues_manager/descriptions/clientHintMetaTagAllowListInvalidOrigin.md +4 -0
- package/front_end/models/issues_manager/descriptions/clientHintMetaTagModifiedHTML.md +4 -0
- package/front_end/models/issues_manager/issues_manager.ts +2 -0
- package/front_end/panels/application/components/BackForwardCacheView.ts +33 -33
- package/front_end/panels/application/components/EndpointsGrid.ts +12 -12
- package/front_end/panels/application/components/FrameDetailsView.ts +108 -110
- package/front_end/panels/application/components/OriginTrialTreeView.ts +45 -45
- package/front_end/panels/application/components/PermissionsPolicySection.ts +19 -19
- package/front_end/panels/application/components/ReportsGrid.ts +30 -30
- package/front_end/panels/application/components/StackTrace.ts +48 -47
- package/front_end/panels/application/components/TrustTokensView.ts +31 -31
- package/front_end/panels/console/ConsoleView.ts +1 -1
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +41 -52
- package/front_end/panels/css_overview/CSSOverviewController.ts +2 -2
- package/front_end/panels/css_overview/CSSOverviewPanel.ts +18 -27
- package/front_end/panels/css_overview/CSSOverviewProcessingView.ts +2 -2
- package/front_end/panels/css_overview/CSSOverviewSidebarPanel.ts +6 -6
- package/front_end/panels/css_overview/components/CSSOverviewStartView.ts +4 -4
- package/front_end/panels/elements/components/AccessibilityTreeNode.ts +17 -17
- package/front_end/panels/elements/components/AdornerManager.ts +21 -21
- package/front_end/panels/elements/components/AdornerSettingsPane.ts +14 -14
- package/front_end/panels/elements/components/CSSQuery.ts +16 -16
- package/front_end/panels/elements/components/ComputedStyleProperty.ts +14 -14
- package/front_end/panels/elements/components/ComputedStyleTrace.ts +15 -15
- package/front_end/panels/elements/components/ElementsBreadcrumbs.ts +78 -78
- package/front_end/panels/elements/components/ElementsPanelLink.ts +16 -16
- package/front_end/panels/elements/components/LayoutPane.ts +47 -47
- package/front_end/panels/elements/components/NodeText.ts +18 -18
- package/front_end/panels/elements/components/QueryContainer.ts +40 -40
- package/front_end/panels/elements/components/StylePropertyEditor.ts +18 -18
- package/front_end/panels/emulation/components/DeviceSizeInputElement.ts +4 -4
- package/front_end/panels/issues/AffectedBlockedByResponseView.ts +4 -4
- package/front_end/panels/issues/AffectedCookiesView.ts +4 -5
- package/front_end/panels/issues/AffectedDirectivesView.ts +19 -19
- package/front_end/panels/issues/AffectedDocumentsInQuirksModeView.ts +7 -8
- package/front_end/panels/issues/AffectedElementsView.ts +4 -4
- package/front_end/panels/issues/AffectedElementsWithLowContrastView.ts +7 -8
- package/front_end/panels/issues/AffectedHeavyAdView.ts +8 -8
- package/front_end/panels/issues/AffectedResourcesView.ts +25 -26
- package/front_end/panels/issues/AffectedSharedArrayBufferIssueDetailsView.ts +8 -8
- package/front_end/panels/issues/AffectedSourcesView.ts +4 -4
- package/front_end/panels/issues/AffectedTrustedWebActivityIssueDetailsView.ts +4 -4
- package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +17 -17
- package/front_end/panels/issues/CSPViolationsListView.ts +22 -23
- package/front_end/panels/issues/CSPViolationsView.ts +17 -17
- package/front_end/panels/issues/ComboBoxOfCheckBoxes.ts +13 -13
- package/front_end/panels/issues/CorsIssueDetailsView.ts +23 -23
- package/front_end/panels/issues/GenericIssueDetailsView.ts +4 -4
- package/front_end/panels/issues/HiddenIssuesRow.ts +7 -7
- package/front_end/panels/issues/IssueAggregator.ts +95 -95
- package/front_end/panels/issues/IssueKindView.ts +14 -14
- package/front_end/panels/issues/IssueView.ts +98 -98
- package/front_end/panels/issues/IssuesPane.ts +102 -102
- package/front_end/panels/issues/WasmCrossOriginModuleSharingAffectedResourcesView.ts +5 -5
- package/front_end/panels/issues/components/HideIssuesMenu.ts +10 -10
- package/front_end/panels/media/PlayerListView.ts +160 -97
- package/front_end/panels/media/PlayerMessagesView.ts +1 -0
- package/front_end/panels/media/playerListView.css +58 -0
- package/front_end/panels/network/NetworkLogView.ts +2 -6
- package/front_end/panels/network/NetworkWaterfallColumn.ts +2 -4
- package/front_end/panels/network/components/RequestTrustTokensView.ts +40 -40
- package/front_end/panels/network/components/WebBundleInfoView.ts +9 -9
- package/front_end/panels/performance_monitor/PerformanceMonitor.ts +92 -37
- package/front_end/panels/performance_monitor/performanceMonitor.css +32 -0
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +2 -2
- package/front_end/panels/settings/components/SyncSection.ts +14 -14
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +96 -96
- package/front_end/panels/sources/BreakpointEditDialog.ts +4 -3
- package/front_end/panels/timeline/TimelineFlameChartView.ts +1 -1
- package/front_end/panels/timeline/TimelineTreeView.ts +1 -1
- package/front_end/panels/timeline/components/WebVitalsLane.ts +77 -76
- package/front_end/panels/timeline/components/WebVitalsTimeline.ts +133 -133
- package/front_end/panels/timeline/components/WebVitalsTooltip.ts +9 -9
- package/front_end/panels/webauthn/WebauthnPane.ts +203 -205
- package/front_end/third_party/diff/DiffWrapper.ts +7 -0
- package/front_end/ui/components/adorners/Adorner.ts +2 -2
- package/front_end/ui/components/buttons/Button.ts +9 -9
- package/front_end/ui/components/data_grid/DataGrid.ts +64 -64
- package/front_end/ui/components/data_grid/DataGridController.ts +22 -22
- package/front_end/ui/components/data_grid/DataGridUtils.ts +3 -0
- package/front_end/ui/components/diff_view/DiffView.ts +6 -6
- package/front_end/ui/components/expandable_list/ExpandableList.ts +5 -5
- package/front_end/ui/components/icon_button/Icon.ts +4 -4
- package/front_end/ui/components/icon_button/IconButton.ts +4 -4
- package/front_end/ui/components/issue_counter/IssueCounter.ts +3 -3
- package/front_end/ui/components/issue_counter/IssueLinkIcon.ts +11 -11
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspector.ts +50 -50
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspectorController.ts +6 -6
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspectorPane.ts +4 -4
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryNavigator.ts +12 -12
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryValueInterpreter.ts +11 -11
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryViewer.ts +40 -39
- package/front_end/ui/components/linear_memory_inspector/ValueInterpreterDisplay.ts +18 -18
- package/front_end/ui/components/linear_memory_inspector/ValueInterpreterSettings.ts +6 -6
- package/front_end/ui/components/linkifier/LinkifierImpl.ts +4 -4
- package/front_end/ui/components/markdown_view/MarkdownImage.ts +5 -5
- package/front_end/ui/components/markdown_view/MarkdownLink.ts +2 -2
- package/front_end/ui/components/markdown_view/MarkdownView.ts +4 -4
- package/front_end/ui/components/panel_feedback/FeedbackButton.ts +2 -2
- package/front_end/ui/components/panel_feedback/PanelFeedback.ts +2 -2
- package/front_end/ui/components/panel_feedback/PreviewToggle.ts +4 -4
- package/front_end/ui/components/render_coordinator/RenderCoordinator.ts +22 -22
- package/front_end/ui/components/report_view/ReportView.ts +16 -16
- package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +14 -14
- package/front_end/ui/components/settings/SettingCheckbox.ts +5 -5
- package/front_end/ui/components/survey_link/SurveyLink.ts +8 -8
- package/front_end/ui/components/text_editor/TextEditor.ts +9 -9
- package/front_end/ui/components/text_prompt/TextPrompt.ts +18 -18
- package/front_end/ui/components/tree_outline/TreeOutline.ts +69 -70
- package/front_end/ui/legacy/SearchableView.ts +13 -4
- package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -1
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +13 -12
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +2 -2
- package/front_end/ui/legacy/themeColors.css +2 -0
- package/front_end/ui/legacy/theme_support/theme_support_impl.ts +34 -7
- package/package.json +1 -1
- package/scripts/eslint_rules/lib/use_private_class_members.js +41 -0
- package/scripts/eslint_rules/tests/use_private_class_members_test.js +62 -0
- package/scripts/migration/class-fields/migrate.js +2 -3
- package/scripts/migration/class-fields/migrate.sh +1 -3
- package/scripts/migration/class-fields/package.json +1 -1
- package/config/gni/all_devtools_files.gni +0 -255
- package/scripts/build/devtools_file_hashes.py +0 -82
- package/scripts/devtools_run/devtools_run_cli +0 -49
- package/scripts/devtools_run/package.json +0 -13
- package/scripts/unzip.py +0 -20
- package/scripts/visualize_deps/jquery_svg.html +0 -57
- package/scripts/visualize_deps/run_visualize.js +0 -119
|
@@ -123,19 +123,19 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
123
123
|
attributeChangedCallback(name: 'nowrap'|'toplevelbordercolor', oldValue: string|null, newValue: string|null): void {
|
|
124
124
|
switch (name) {
|
|
125
125
|
case 'nowrap': {
|
|
126
|
-
this
|
|
126
|
+
this.#setNodeKeyNoWrapCSSVariable(newValue);
|
|
127
127
|
break;
|
|
128
128
|
}
|
|
129
129
|
case 'toplevelbordercolor': {
|
|
130
|
-
this
|
|
130
|
+
this.#setTopLevelNodeBorderColorCSSVariable(newValue);
|
|
131
131
|
break;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
connectedCallback(): void {
|
|
137
|
-
this
|
|
138
|
-
this
|
|
137
|
+
this.#setTopLevelNodeBorderColorCSSVariable(this.getAttribute('toplevelbordercolor'));
|
|
138
|
+
this.#setNodeKeyNoWrapCSSVariable(this.getAttribute('nowrap'));
|
|
139
139
|
this.#shadow.adoptedStyleSheets = [treeOutlineStyles, CodeHighlighter.Style.default];
|
|
140
140
|
}
|
|
141
141
|
|
|
@@ -153,7 +153,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
153
153
|
if (!this.#hasRenderedAtLeastOnce) {
|
|
154
154
|
this.#selectedTreeNode = this.#treeData[0];
|
|
155
155
|
}
|
|
156
|
-
this
|
|
156
|
+
this.#render();
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
/**
|
|
@@ -162,8 +162,8 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
162
162
|
* 1 and 2.
|
|
163
163
|
*/
|
|
164
164
|
async expandRecursively(maxDepth = 2): Promise<void> {
|
|
165
|
-
await Promise.all(this.#treeData.map(rootNode => this
|
|
166
|
-
await this
|
|
165
|
+
await Promise.all(this.#treeData.map(rootNode => this.#expandAndRecurse(rootNode, 0, maxDepth)));
|
|
166
|
+
await this.#render();
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
/**
|
|
@@ -171,7 +171,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
171
171
|
*/
|
|
172
172
|
async collapseAllNodes(): Promise<void> {
|
|
173
173
|
this.#nodeExpandedMap.clear();
|
|
174
|
-
await this
|
|
174
|
+
await this.#render();
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
/**
|
|
@@ -193,13 +193,13 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
193
193
|
pathToTreeNode.forEach((node, index) => {
|
|
194
194
|
// We don't expand the very last node, which was the target node.
|
|
195
195
|
if (index < pathToTreeNode.length - 1) {
|
|
196
|
-
this
|
|
196
|
+
this.#setNodeExpandedState(node, true);
|
|
197
197
|
}
|
|
198
198
|
});
|
|
199
199
|
|
|
200
200
|
// Mark the node as pending focus so when it is rendered into the DOM we can focus it
|
|
201
201
|
this.#nodeIdPendingFocus = targetTreeNodeId;
|
|
202
|
-
await this
|
|
202
|
+
await this.#render();
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
/**
|
|
@@ -207,7 +207,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
207
207
|
*/
|
|
208
208
|
expandNodeIds(nodeIds: TreeNodeId[]): Promise<void> {
|
|
209
209
|
nodeIds.forEach(id => this.#nodeExpandedMap.set(id, true));
|
|
210
|
-
return this
|
|
210
|
+
return this.#render();
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
/**
|
|
@@ -215,7 +215,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
215
215
|
*/
|
|
216
216
|
focusNodeId(nodeId: TreeNodeId): Promise<void> {
|
|
217
217
|
this.#nodeIdPendingFocus = nodeId;
|
|
218
|
-
return this
|
|
218
|
+
return this.#render();
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
async collapseChildrenOfNode(domNode: HTMLLIElement): Promise<void> {
|
|
@@ -223,38 +223,38 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
223
223
|
if (!treeNode) {
|
|
224
224
|
return;
|
|
225
225
|
}
|
|
226
|
-
await this
|
|
227
|
-
await this
|
|
226
|
+
await this.#recursivelyCollapseTreeNodeChildren(treeNode);
|
|
227
|
+
await this.#render();
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
#setNodeKeyNoWrapCSSVariable(attributeValue: string|null): void {
|
|
231
231
|
ComponentHelpers.SetCSSProperty.set(
|
|
232
232
|
this, '--override-key-whitespace-wrapping', attributeValue !== null ? 'nowrap' : 'initial');
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
|
|
235
|
+
#setTopLevelNodeBorderColorCSSVariable(attributeValue: string|null): void {
|
|
236
236
|
ComponentHelpers.SetCSSProperty.set(
|
|
237
237
|
this, '--override-top-node-border', attributeValue ? `1px solid ${attributeValue}` : '');
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
|
|
241
|
-
if (!isExpandableNode(treeNode) || !this
|
|
240
|
+
async #recursivelyCollapseTreeNodeChildren(treeNode: TreeNode<TreeNodeDataType>): Promise<void> {
|
|
241
|
+
if (!isExpandableNode(treeNode) || !this.#nodeIsExpanded(treeNode)) {
|
|
242
242
|
return;
|
|
243
243
|
}
|
|
244
|
-
const children = await this
|
|
245
|
-
const childRecursions = Promise.all(children.map(child => this
|
|
244
|
+
const children = await this.#fetchNodeChildren(treeNode);
|
|
245
|
+
const childRecursions = Promise.all(children.map(child => this.#recursivelyCollapseTreeNodeChildren(child)));
|
|
246
246
|
await childRecursions;
|
|
247
|
-
this
|
|
247
|
+
this.#setNodeExpandedState(treeNode, false);
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
|
|
250
|
+
#getSelectedTreeNode(): TreeNode<TreeNodeDataType> {
|
|
251
251
|
if (!this.#selectedTreeNode) {
|
|
252
252
|
throw new Error('getSelectedNode was called but selectedTreeNode is null');
|
|
253
253
|
}
|
|
254
254
|
return this.#selectedTreeNode;
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
|
|
257
|
+
async #fetchNodeChildren(node: TreeNodeWithChildren<TreeNodeDataType>): Promise<TreeNode<TreeNodeDataType>[]> {
|
|
258
258
|
const children = await getNodeChildren(node);
|
|
259
259
|
if (!this.#nodeFilter) {
|
|
260
260
|
return children;
|
|
@@ -263,77 +263,76 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
263
263
|
for (const child of children) {
|
|
264
264
|
const filtering = this.#nodeFilter(child.treeNodeData);
|
|
265
265
|
// We always include the selected node in the tree, regardless of its filtering status.
|
|
266
|
-
if (filtering === FilterOption.SHOW || this
|
|
266
|
+
if (filtering === FilterOption.SHOW || this.#isSelectedNode(child) || child.id === this.#nodeIdPendingFocus) {
|
|
267
267
|
filteredChildren.push(child);
|
|
268
268
|
} else if (filtering === FilterOption.FLATTEN && isExpandableNode(child)) {
|
|
269
|
-
const grandChildren = await this
|
|
269
|
+
const grandChildren = await this.#fetchNodeChildren(child);
|
|
270
270
|
filteredChildren.push(...grandChildren);
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
273
|
return filteredChildren;
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
#setNodeExpandedState(node: TreeNode<TreeNodeDataType>, newExpandedState: boolean): void {
|
|
277
277
|
this.#nodeExpandedMap.set(node.id, newExpandedState);
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
|
|
280
|
+
#nodeIsExpanded(node: TreeNode<TreeNodeDataType>): boolean {
|
|
281
281
|
return this.#nodeExpandedMap.get(node.id) || false;
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
|
|
285
|
-
Promise<void> {
|
|
284
|
+
async #expandAndRecurse(node: TreeNode<TreeNodeDataType>, currentDepth: number, maxDepth: number): Promise<void> {
|
|
286
285
|
if (!isExpandableNode(node)) {
|
|
287
286
|
return;
|
|
288
287
|
}
|
|
289
|
-
this
|
|
288
|
+
this.#setNodeExpandedState(node, true);
|
|
290
289
|
if (currentDepth === maxDepth || !isExpandableNode(node)) {
|
|
291
290
|
return;
|
|
292
291
|
}
|
|
293
|
-
const children = await this
|
|
294
|
-
await Promise.all(children.map(child => this
|
|
292
|
+
const children = await this.#fetchNodeChildren(node);
|
|
293
|
+
await Promise.all(children.map(child => this.#expandAndRecurse(child, currentDepth + 1, maxDepth)));
|
|
295
294
|
}
|
|
296
295
|
|
|
297
|
-
|
|
296
|
+
#onArrowClick(node: TreeNode<TreeNodeDataType>): ((e: Event) => void) {
|
|
298
297
|
return (event: Event): void => {
|
|
299
298
|
event.stopPropagation();
|
|
300
299
|
if (isExpandableNode(node)) {
|
|
301
|
-
this
|
|
302
|
-
this
|
|
300
|
+
this.#setNodeExpandedState(node, !this.#nodeIsExpanded(node));
|
|
301
|
+
this.#render();
|
|
303
302
|
}
|
|
304
303
|
};
|
|
305
304
|
}
|
|
306
305
|
|
|
307
|
-
|
|
306
|
+
#onNodeClick(event: Event): void {
|
|
308
307
|
// Avoid it bubbling up to parent tree elements, else clicking a node deep in the tree will toggle it + all its ancestor's visibility.
|
|
309
308
|
event.stopPropagation();
|
|
310
309
|
const nodeClickExpandsOrContracts = this.getAttribute('clickabletitle') !== null;
|
|
311
310
|
const domNode = event.currentTarget as HTMLLIElement;
|
|
312
311
|
const node = this.#domNodeToTreeNodeMap.get(domNode);
|
|
313
312
|
if (nodeClickExpandsOrContracts && node && isExpandableNode(node)) {
|
|
314
|
-
this
|
|
313
|
+
this.#setNodeExpandedState(node, !this.#nodeIsExpanded(node));
|
|
315
314
|
}
|
|
316
|
-
this
|
|
315
|
+
this.#focusTreeNode(domNode);
|
|
317
316
|
}
|
|
318
317
|
|
|
319
|
-
|
|
318
|
+
async #focusTreeNode(domNode: HTMLLIElement): Promise<void> {
|
|
320
319
|
const treeNode = this.#domNodeToTreeNodeMap.get(domNode);
|
|
321
320
|
if (!treeNode) {
|
|
322
321
|
return;
|
|
323
322
|
}
|
|
324
323
|
this.#selectedTreeNode = treeNode;
|
|
325
|
-
await this
|
|
324
|
+
await this.#render();
|
|
326
325
|
this.dispatchEvent(new ItemSelectedEvent(treeNode));
|
|
327
326
|
coordinator.write('DOMNode focus', () => {
|
|
328
327
|
domNode.focus();
|
|
329
328
|
});
|
|
330
329
|
}
|
|
331
330
|
|
|
332
|
-
|
|
331
|
+
#processHomeAndEndKeysNavigation(key: 'Home'|'End'): void {
|
|
333
332
|
if (key === 'Home') {
|
|
334
333
|
const firstRootNode = this.#shadow.querySelector<HTMLLIElement>('ul[role="tree"] > li[role="treeitem"]');
|
|
335
334
|
if (firstRootNode) {
|
|
336
|
-
this
|
|
335
|
+
this.#focusTreeNode(firstRootNode);
|
|
337
336
|
}
|
|
338
337
|
} else if (key === 'End') {
|
|
339
338
|
/**
|
|
@@ -348,12 +347,12 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
348
347
|
const allTreeItems = this.#shadow.querySelectorAll<HTMLLIElement>('li[role="treeitem"]');
|
|
349
348
|
const lastTreeItem = allTreeItems[allTreeItems.length - 1];
|
|
350
349
|
if (lastTreeItem) {
|
|
351
|
-
this
|
|
350
|
+
this.#focusTreeNode(lastTreeItem);
|
|
352
351
|
}
|
|
353
352
|
}
|
|
354
353
|
}
|
|
355
354
|
|
|
356
|
-
|
|
355
|
+
async #processArrowKeyNavigation(key: Platform.KeyboardUtilities.ArrowKey, currentDOMNode: HTMLLIElement):
|
|
357
356
|
Promise<void> {
|
|
358
357
|
const currentTreeNode = this.#domNodeToTreeNodeMap.get(currentDOMNode);
|
|
359
358
|
if (!currentTreeNode) {
|
|
@@ -364,65 +363,65 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
364
363
|
currentDOMNode,
|
|
365
364
|
currentTreeNode,
|
|
366
365
|
direction: key,
|
|
367
|
-
setNodeExpandedState: (node, expanded) => this
|
|
366
|
+
setNodeExpandedState: (node, expanded) => this.#setNodeExpandedState(node, expanded),
|
|
368
367
|
});
|
|
369
|
-
await this
|
|
368
|
+
await this.#focusTreeNode(domNode);
|
|
370
369
|
}
|
|
371
370
|
|
|
372
|
-
|
|
371
|
+
#processEnterOrSpaceNavigation(currentDOMNode: HTMLLIElement): void {
|
|
373
372
|
const currentTreeNode = this.#domNodeToTreeNodeMap.get(currentDOMNode);
|
|
374
373
|
if (!currentTreeNode) {
|
|
375
374
|
return;
|
|
376
375
|
}
|
|
377
376
|
if (isExpandableNode(currentTreeNode)) {
|
|
378
|
-
const currentExpandedState = this
|
|
379
|
-
this
|
|
380
|
-
this
|
|
377
|
+
const currentExpandedState = this.#nodeIsExpanded(currentTreeNode);
|
|
378
|
+
this.#setNodeExpandedState(currentTreeNode, !currentExpandedState);
|
|
379
|
+
this.#render();
|
|
381
380
|
}
|
|
382
381
|
}
|
|
383
382
|
|
|
384
|
-
|
|
383
|
+
async #onTreeKeyDown(event: KeyboardEvent): Promise<void> {
|
|
385
384
|
if (!(event.target instanceof HTMLLIElement)) {
|
|
386
385
|
throw new Error('event.target was not an <li> element');
|
|
387
386
|
}
|
|
388
387
|
|
|
389
388
|
if (event.key === 'Home' || event.key === 'End') {
|
|
390
389
|
event.preventDefault();
|
|
391
|
-
this
|
|
390
|
+
this.#processHomeAndEndKeysNavigation(event.key);
|
|
392
391
|
} else if (Platform.KeyboardUtilities.keyIsArrowKey(event.key)) {
|
|
393
392
|
event.preventDefault();
|
|
394
|
-
await this
|
|
393
|
+
await this.#processArrowKeyNavigation(event.key, event.target);
|
|
395
394
|
} else if (event.key === 'Enter' || event.key === ' ') {
|
|
396
395
|
event.preventDefault();
|
|
397
|
-
this
|
|
396
|
+
this.#processEnterOrSpaceNavigation(event.target);
|
|
398
397
|
}
|
|
399
398
|
}
|
|
400
399
|
|
|
401
|
-
|
|
400
|
+
#focusPendingNode(domNode: HTMLLIElement): void {
|
|
402
401
|
this.#nodeIdPendingFocus = null;
|
|
403
|
-
this
|
|
402
|
+
this.#focusTreeNode(domNode);
|
|
404
403
|
}
|
|
405
404
|
|
|
406
|
-
|
|
405
|
+
#isSelectedNode(node: TreeNode<TreeNodeDataType>): boolean {
|
|
407
406
|
if (this.#selectedTreeNode) {
|
|
408
407
|
return node.id === this.#selectedTreeNode.id;
|
|
409
408
|
}
|
|
410
409
|
return false;
|
|
411
410
|
}
|
|
412
411
|
|
|
413
|
-
|
|
412
|
+
#renderNode(node: TreeNode<TreeNodeDataType>, {depth, setSize, positionInSet}: {
|
|
414
413
|
depth: number,
|
|
415
414
|
setSize: number,
|
|
416
415
|
positionInSet: number,
|
|
417
416
|
}): LitHtml.TemplateResult {
|
|
418
417
|
let childrenToRender;
|
|
419
|
-
const nodeIsExpanded = this
|
|
418
|
+
const nodeIsExpanded = this.#nodeIsExpanded(node);
|
|
420
419
|
if (!isExpandableNode(node) || !nodeIsExpanded) {
|
|
421
420
|
childrenToRender = LitHtml.nothing;
|
|
422
421
|
} else {
|
|
423
|
-
const childNodes = this
|
|
422
|
+
const childNodes = this.#fetchNodeChildren(node).then(children => {
|
|
424
423
|
return children.map((childNode, index) => {
|
|
425
|
-
return this
|
|
424
|
+
return this.#renderNode(childNode, {depth: depth + 1, setSize: children.length, positionInSet: index});
|
|
426
425
|
});
|
|
427
426
|
});
|
|
428
427
|
// Disabled until https://crbug.com/1079231 is fixed.
|
|
@@ -431,12 +430,12 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
431
430
|
// clang-format on
|
|
432
431
|
}
|
|
433
432
|
|
|
434
|
-
const nodeIsFocusable = this
|
|
433
|
+
const nodeIsFocusable = this.#getSelectedTreeNode() === node;
|
|
435
434
|
const tabIndex = nodeIsFocusable ? 0 : -1;
|
|
436
435
|
const listItemClasses = LitHtml.Directives.classMap({
|
|
437
436
|
expanded: isExpandableNode(node) && nodeIsExpanded,
|
|
438
437
|
parent: isExpandableNode(node),
|
|
439
|
-
selected: this
|
|
438
|
+
selected: this.#isSelectedNode(node),
|
|
440
439
|
'is-top-level': depth === 0,
|
|
441
440
|
});
|
|
442
441
|
const ariaExpandedAttribute =
|
|
@@ -459,7 +458,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
459
458
|
aria-level=${depth + 1}
|
|
460
459
|
aria-posinset=${positionInSet + 1}
|
|
461
460
|
class=${listItemClasses}
|
|
462
|
-
@click=${this
|
|
461
|
+
@click=${this.#onNodeClick}
|
|
463
462
|
track-dom-node-to-tree-node=${trackDOMNodeToTreeNode(this.#domNodeToTreeNodeMap, node)}
|
|
464
463
|
on-render=${ComponentHelpers.Directives.nodeRenderedCallback(domNode => {
|
|
465
464
|
/**
|
|
@@ -474,7 +473,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
474
473
|
}
|
|
475
474
|
|
|
476
475
|
if (this.#nodeIdPendingFocus && node.id === this.#nodeIdPendingFocus) {
|
|
477
|
-
this
|
|
476
|
+
this.#focusPendingNode(domNode);
|
|
478
477
|
}
|
|
479
478
|
})}
|
|
480
479
|
>
|
|
@@ -486,7 +485,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
486
485
|
this.dispatchEvent(new ItemMouseOutEvent(node));
|
|
487
486
|
}}
|
|
488
487
|
>
|
|
489
|
-
<span class="arrow-icon" @click=${this
|
|
488
|
+
<span class="arrow-icon" @click=${this.#onArrowClick(node)}>
|
|
490
489
|
</span>
|
|
491
490
|
<span class="tree-node-key" data-node-key=${node.treeNodeData}>${renderedNodeKey}</span>
|
|
492
491
|
</span>
|
|
@@ -496,7 +495,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
496
495
|
// clang-format on
|
|
497
496
|
}
|
|
498
497
|
|
|
499
|
-
|
|
498
|
+
async #render(): Promise<void> {
|
|
500
499
|
if (this.#scheduledRender) {
|
|
501
500
|
// If we are already rendering, don't render again immediately, but
|
|
502
501
|
// enqueue it to be run after we're done on our current render.
|
|
@@ -511,9 +510,9 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
511
510
|
// clang-format off
|
|
512
511
|
LitHtml.render(LitHtml.html`
|
|
513
512
|
<div class="wrapping-container">
|
|
514
|
-
<ul role="tree" @keydown=${this
|
|
513
|
+
<ul role="tree" @keydown=${this.#onTreeKeyDown}>
|
|
515
514
|
${this.#treeData.map((topLevelNode, index) => {
|
|
516
|
-
return this
|
|
515
|
+
return this.#renderNode(topLevelNode, {
|
|
517
516
|
depth: 0,
|
|
518
517
|
setSize: this.#treeData.length,
|
|
519
518
|
positionInSet: index,
|
|
@@ -533,7 +532,7 @@ export class TreeOutline<TreeNodeDataType> extends HTMLElement {
|
|
|
533
532
|
// to ensure we're not rendering any stale UI.
|
|
534
533
|
if (this.#enqueuedRender) {
|
|
535
534
|
this.#enqueuedRender = false;
|
|
536
|
-
return this
|
|
535
|
+
return this.#render();
|
|
537
536
|
}
|
|
538
537
|
}
|
|
539
538
|
}
|
|
@@ -597,6 +597,11 @@ export interface Replaceable {
|
|
|
597
597
|
replaceAllWith(searchConfig: SearchConfig, replacement: string): void;
|
|
598
598
|
}
|
|
599
599
|
|
|
600
|
+
export interface SearchRegexResult {
|
|
601
|
+
regex: RegExp;
|
|
602
|
+
fromQuery: boolean;
|
|
603
|
+
}
|
|
604
|
+
|
|
600
605
|
export class SearchConfig {
|
|
601
606
|
query: string;
|
|
602
607
|
caseSensitive: boolean;
|
|
@@ -608,20 +613,21 @@ export class SearchConfig {
|
|
|
608
613
|
this.isRegex = isRegex;
|
|
609
614
|
}
|
|
610
615
|
|
|
611
|
-
toSearchRegex(global?: boolean):
|
|
616
|
+
toSearchRegex(global?: boolean): SearchRegexResult {
|
|
612
617
|
let modifiers = this.caseSensitive ? '' : 'i';
|
|
613
618
|
if (global) {
|
|
614
619
|
modifiers += 'g';
|
|
615
620
|
}
|
|
616
621
|
const query = this.isRegex ? '/' + this.query + '/' : this.query;
|
|
617
622
|
|
|
618
|
-
let regex;
|
|
623
|
+
let regex: RegExp|undefined;
|
|
624
|
+
let fromQuery = false;
|
|
619
625
|
|
|
620
626
|
// First try creating regex if user knows the / / hint.
|
|
621
627
|
try {
|
|
622
628
|
if (/^\/.+\/$/.test(query)) {
|
|
623
629
|
regex = new RegExp(query.substring(1, query.length - 1), modifiers);
|
|
624
|
-
|
|
630
|
+
fromQuery = true;
|
|
625
631
|
}
|
|
626
632
|
} catch (e) {
|
|
627
633
|
// Silent catch.
|
|
@@ -632,6 +638,9 @@ export class SearchConfig {
|
|
|
632
638
|
regex = Platform.StringUtilities.createPlainTextSearchRegex(query, modifiers);
|
|
633
639
|
}
|
|
634
640
|
|
|
635
|
-
return
|
|
641
|
+
return {
|
|
642
|
+
regex,
|
|
643
|
+
fromQuery,
|
|
644
|
+
};
|
|
636
645
|
}
|
|
637
646
|
}
|
|
@@ -231,7 +231,7 @@ export class JSONView extends UI.Widget.VBox implements UI.SearchableView.Search
|
|
|
231
231
|
let newIndex: number = this.currentSearchFocusIndex;
|
|
232
232
|
const previousSearchFocusElement = this.currentSearchTreeElements[newIndex];
|
|
233
233
|
this.searchCanceled();
|
|
234
|
-
this.searchRegex = searchConfig.toSearchRegex(true);
|
|
234
|
+
this.searchRegex = searchConfig.toSearchRegex(true).regex;
|
|
235
235
|
|
|
236
236
|
let element: UI.TreeOutline.TreeElement|null;
|
|
237
237
|
for (element = this.treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) {
|
|
@@ -120,7 +120,7 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
120
120
|
private delayedFindSearchMatches: (() => void)|null;
|
|
121
121
|
private currentSearchResultIndex: number;
|
|
122
122
|
private searchResults: SearchMatch[];
|
|
123
|
-
private searchRegex:
|
|
123
|
+
private searchRegex: UI.SearchableView.SearchRegexResult|null;
|
|
124
124
|
private loadError: boolean;
|
|
125
125
|
private muteChangeEventsForSetContent: boolean;
|
|
126
126
|
private readonly sourcePosition: UI.Toolbar.ToolbarText;
|
|
@@ -830,7 +830,7 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
830
830
|
}
|
|
831
831
|
|
|
832
832
|
jumpToSearchResult(index: number): void {
|
|
833
|
-
if (!this.loaded || !this.searchResults.length) {
|
|
833
|
+
if (!this.loaded || !this.searchResults.length || !this.searchRegex) {
|
|
834
834
|
return;
|
|
835
835
|
}
|
|
836
836
|
this.currentSearchResultIndex = (index + this.searchResults.length) % this.searchResults.length;
|
|
@@ -840,7 +840,7 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
840
840
|
const editor = this.textEditor;
|
|
841
841
|
const range = this.searchResults[this.currentSearchResultIndex];
|
|
842
842
|
editor.dispatch({
|
|
843
|
-
effects: setActiveSearch.of(new ActiveSearch(this.searchRegex
|
|
843
|
+
effects: setActiveSearch.of(new ActiveSearch(this.searchRegex, range)),
|
|
844
844
|
selection: {anchor: range.from, head: range.to},
|
|
845
845
|
scrollIntoView: true,
|
|
846
846
|
userEvent: 'select.search',
|
|
@@ -853,7 +853,7 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
853
853
|
return;
|
|
854
854
|
}
|
|
855
855
|
|
|
856
|
-
const insert =
|
|
856
|
+
const insert = this.searchRegex?.fromQuery ? range.insertPlaceholders(replacement) : replacement;
|
|
857
857
|
const editor = this.textEditor;
|
|
858
858
|
const changes = editor.state.changes({from: range.from, to: range.to, insert});
|
|
859
859
|
editor.dispatch(
|
|
@@ -869,7 +869,7 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
869
869
|
return;
|
|
870
870
|
}
|
|
871
871
|
|
|
872
|
-
const isRegExp = regex.
|
|
872
|
+
const isRegExp = regex.fromQuery;
|
|
873
873
|
const changes = ranges.map(
|
|
874
874
|
match =>
|
|
875
875
|
({from: match.from, to: match.to, insert: isRegExp ? match.insertPlaceholders(replacement) : replacement}));
|
|
@@ -877,13 +877,13 @@ export class SourceFrameImpl extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
877
877
|
this.textEditor.dispatch({changes, scrollIntoView: true, userEvent: 'input.replace.all'});
|
|
878
878
|
}
|
|
879
879
|
|
|
880
|
-
private collectRegexMatches(
|
|
880
|
+
private collectRegexMatches({regex}: UI.SearchableView.SearchRegexResult): SearchMatch[] {
|
|
881
881
|
const ranges = [];
|
|
882
882
|
let pos = 0;
|
|
883
883
|
for (const line of this.textEditor.state.doc.iterLines()) {
|
|
884
|
-
|
|
884
|
+
regex.lastIndex = 0;
|
|
885
885
|
for (;;) {
|
|
886
|
-
const match =
|
|
886
|
+
const match = regex.exec(line);
|
|
887
887
|
if (!match) {
|
|
888
888
|
break;
|
|
889
889
|
}
|
|
@@ -1022,7 +1022,8 @@ const config = {
|
|
|
1022
1022
|
};
|
|
1023
1023
|
|
|
1024
1024
|
class ActiveSearch {
|
|
1025
|
-
constructor(
|
|
1025
|
+
constructor(
|
|
1026
|
+
readonly regexp: UI.SearchableView.SearchRegexResult, readonly currentRange: {from: number, to: number}|null) {
|
|
1026
1027
|
}
|
|
1027
1028
|
|
|
1028
1029
|
map(change: CodeMirror.ChangeDesc): ActiveSearch {
|
|
@@ -1036,7 +1037,7 @@ class ActiveSearch {
|
|
|
1036
1037
|
return Boolean(
|
|
1037
1038
|
a === b ||
|
|
1038
1039
|
a && b && a.currentRange?.from === b.currentRange?.from && a.currentRange?.to === b.currentRange?.to &&
|
|
1039
|
-
a.regexp.source === b.regexp.source && a.regexp.flags === b.regexp.flags);
|
|
1040
|
+
a.regexp.regex.source === b.regexp.regex.source && a.regexp.regex.flags === b.regexp.regex.flags);
|
|
1040
1041
|
}
|
|
1041
1042
|
}
|
|
1042
1043
|
|
|
@@ -1084,9 +1085,9 @@ const searchHighlighter = CodeMirror.ViewPlugin.fromClass(class {
|
|
|
1084
1085
|
let pos = from;
|
|
1085
1086
|
for (const part of doc.iterRange(from, to)) {
|
|
1086
1087
|
if (part !== '\n') {
|
|
1087
|
-
active.regexp.lastIndex = 0;
|
|
1088
|
+
active.regexp.regex.lastIndex = 0;
|
|
1088
1089
|
for (;;) {
|
|
1089
|
-
const match = active.regexp.exec(part);
|
|
1090
|
+
const match = active.regexp.regex.exec(part);
|
|
1090
1091
|
if (!match) {
|
|
1091
1092
|
break;
|
|
1092
1093
|
}
|
|
@@ -78,7 +78,7 @@ export class XMLView extends UI.Widget.Widget implements UI.SearchableView.Searc
|
|
|
78
78
|
if (!this.searchConfig) {
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
const regex = this.searchConfig.toSearchRegex(true);
|
|
81
|
+
const {regex} = this.searchConfig.toSearchRegex(true);
|
|
82
82
|
const previousFocusElement = this.currentSearchTreeElements[this.currentSearchFocusIndex];
|
|
83
83
|
if (previousFocusElement) {
|
|
84
84
|
previousFocusElement.setSearchRegex(regex);
|
|
@@ -119,7 +119,7 @@ export class XMLView extends UI.Widget.Widget implements UI.SearchableView.Searc
|
|
|
119
119
|
const previousSearchFocusElement = this.currentSearchTreeElements[newIndex];
|
|
120
120
|
this.innerSearchCanceled();
|
|
121
121
|
this.currentSearchTreeElements = [];
|
|
122
|
-
const regex = this.searchConfig.toSearchRegex(true);
|
|
122
|
+
const {regex} = this.searchConfig.toSearchRegex(true);
|
|
123
123
|
|
|
124
124
|
for (let element: (UI.TreeOutline.TreeElement|null) =
|
|
125
125
|
(this.treeOutline.rootElement() as UI.TreeOutline.TreeElement | null);
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
--color-primary-variant: rgb(66 133 244);
|
|
16
16
|
--color-background: rgb(255 255 255);
|
|
17
17
|
--color-background-inverted: rgb(0 0 0);
|
|
18
|
+
--color-background-inverted-opacity-2: rgb(0 0 0 / 2%);
|
|
18
19
|
--color-background-inverted-opacity-30: rgb(0 0 0 / 30%);
|
|
19
20
|
--color-background-inverted-opacity-50: rgb(0 0 0 / 50%);
|
|
20
21
|
--color-background-opacity-50: rgb(255 255 255 / 50%);
|
|
@@ -192,6 +193,7 @@
|
|
|
192
193
|
--color-primary-variant: rgb(102 157 246);
|
|
193
194
|
--color-background: rgb(32 33 36);
|
|
194
195
|
--color-background-inverted: rgb(255 255 255);
|
|
196
|
+
--color-background-inverted-opacity-2: rgb(255 255 255 / 2%);
|
|
195
197
|
--color-background-inverted-opacity-30: rgb(255 255 255 / 30%);
|
|
196
198
|
--color-background-inverted-opacity-50: rgb(255 255 255 / 50%);
|
|
197
199
|
--color-background-opacity-50: rgb(32 33 36 / 50%);
|
|
@@ -41,7 +41,7 @@ import inspectorSyntaxHighlightDarkStyles from '../inspectorSyntaxHighlightDark.
|
|
|
41
41
|
|
|
42
42
|
let themeSupportInstance: ThemeSupport;
|
|
43
43
|
|
|
44
|
-
const themeValuesCache = new Map<string, string
|
|
44
|
+
const themeValuesCache = new Map<CSSStyleDeclaration, Map<string, string>>();
|
|
45
45
|
|
|
46
46
|
export class ThemeSupport {
|
|
47
47
|
private readonly themeNameInternal: string;
|
|
@@ -96,20 +96,35 @@ export class ThemeSupport {
|
|
|
96
96
|
return themeSupportInstance;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
getComputedValue(variableName: string): string {
|
|
100
|
-
const computedRoot = this.computedRoot();
|
|
101
|
-
|
|
99
|
+
getComputedValue(variableName: string, target: Element|null = null): string {
|
|
100
|
+
const computedRoot = target ? window.getComputedStyle(target) : this.computedRoot();
|
|
102
101
|
if (typeof computedRoot === 'symbol') {
|
|
103
102
|
throw new Error(`Computed value for property (${variableName}) could not be found on :root.`);
|
|
104
103
|
}
|
|
105
104
|
|
|
105
|
+
// Since we might query the same variable name from various targets we need to support
|
|
106
|
+
// per-target caching of computed values. Here we attempt to locate the particular computed
|
|
107
|
+
// value cache for the target. If no target was specified we use the default computed root,
|
|
108
|
+
// which belongs to the document element.
|
|
109
|
+
let computedRootCache = themeValuesCache.get(computedRoot);
|
|
110
|
+
if (!computedRootCache) {
|
|
111
|
+
computedRootCache = new Map<string, string>();
|
|
112
|
+
themeValuesCache.set(computedRoot, computedRootCache);
|
|
113
|
+
}
|
|
114
|
+
|
|
106
115
|
// Since theme changes trigger a reload, we can avoid repeatedly looking up color values
|
|
107
116
|
// dynamically. Instead we can look up the first time and cache them for future use,
|
|
108
117
|
// knowing that the cache will be invalidated by virtue of a reload when the theme changes.
|
|
109
|
-
let cachedValue =
|
|
118
|
+
let cachedValue = computedRootCache.get(variableName);
|
|
110
119
|
if (!cachedValue) {
|
|
111
|
-
cachedValue = computedRoot.getPropertyValue(variableName);
|
|
112
|
-
|
|
120
|
+
cachedValue = computedRoot.getPropertyValue(variableName).trim();
|
|
121
|
+
|
|
122
|
+
// If we receive back an empty value (nothing has been set) we don't store it for the future.
|
|
123
|
+
// This means that subsequent requests will continue to query the styles in case the value
|
|
124
|
+
// has been set.
|
|
125
|
+
if (cachedValue) {
|
|
126
|
+
computedRootCache.set(variableName, cachedValue);
|
|
127
|
+
}
|
|
113
128
|
}
|
|
114
129
|
|
|
115
130
|
return cachedValue;
|
|
@@ -291,6 +306,12 @@ export class ThemeSupport {
|
|
|
291
306
|
output.push(';');
|
|
292
307
|
}
|
|
293
308
|
|
|
309
|
+
/**
|
|
310
|
+
* This legacy function has been supeseded by CSS custom properties. Wherever possible, please use
|
|
311
|
+
* the values declared in global stylesheets.
|
|
312
|
+
*
|
|
313
|
+
* @deprecated
|
|
314
|
+
*/
|
|
294
315
|
patchColorText(text: string, colorUsage: number): string {
|
|
295
316
|
const color = Common.Color.Color.parse(text);
|
|
296
317
|
if (!color) {
|
|
@@ -304,6 +325,12 @@ export class ThemeSupport {
|
|
|
304
325
|
return outText || text;
|
|
305
326
|
}
|
|
306
327
|
|
|
328
|
+
/**
|
|
329
|
+
* This legacy function has been supeseded by CSS custom properties. Wherever possible, please use
|
|
330
|
+
* the values declared in global stylesheets.
|
|
331
|
+
*
|
|
332
|
+
* @deprecated
|
|
333
|
+
*/
|
|
307
334
|
patchColor(color: Common.Color.Color, colorUsage: number): Common.Color.Color {
|
|
308
335
|
const hsla = color.hsla();
|
|
309
336
|
this.patchHSLA(hsla, colorUsage);
|
package/package.json
CHANGED