chrome-devtools-frontend 1.0.1705227 → 1.0.1706026
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/eslint.config.mjs +1 -0
- package/front_end/Images/src/nodejsHex.svg +28 -0
- package/front_end/core/sdk/CPUThrottlingManager.ts +14 -10
- package/front_end/core/sdk/DOMModel.ts +65 -20
- package/front_end/core/sdk/DebuggerModel.ts +0 -4
- package/front_end/core/sdk/PageResourceLoader.ts +12 -11
- package/front_end/core/sdk/SourceMap.ts +7 -5
- package/front_end/core/sdk/SourceMapFunctionRanges.ts +22 -37
- package/front_end/core/sdk/SourceMapScopeChainEntry.ts +3 -3
- package/front_end/core/sdk/SourceMapScopesInfo.ts +50 -62
- package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +7 -2
- package/front_end/entrypoints/heap_snapshot_worker/ContextAnalyzer.ts +140 -20
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +16 -5
- package/front_end/entrypoints/inspector_main/nodeIcon.css +1 -1
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +1 -1
- package/front_end/models/ai_assistance/AiConversation.ts +16 -3
- package/front_end/models/ai_assistance/skills/accessibility.md +8 -7
- package/front_end/models/formatter/FormatterWorkerPool.ts +6 -1
- package/front_end/models/javascript_metadata/NativeFunctions.ts +6 -2
- package/front_end/models/source_map_scopes/NamesResolver.ts +7 -9
- package/front_end/panels/application/BackgroundServiceView.ts +1 -0
- package/front_end/panels/application/components/AdsView.ts +6 -6
- package/front_end/panels/application/components/BackForwardCacheView.ts +1 -1
- package/front_end/panels/elements/CSSRuleValidator.ts +3 -0
- package/front_end/panels/elements/ClassesPaneWidget.ts +4 -1
- package/front_end/panels/elements/LayoutPane.ts +17 -20
- package/front_end/panels/network/NetworkLogViewColumns.ts +10 -3
- package/front_end/panels/network/ShowMoreDetailsWidget.ts +1 -1
- package/front_end/panels/security/SecurityPanel.ts +14 -7
- package/front_end/panels/sources/BreakpointEditDialog.ts +13 -1
- package/front_end/panels/sources/DebuggerPlugin.ts +66 -54
- package/front_end/panels/sources/EditingLocationHistoryManager.ts +6 -6
- package/front_end/panels/sources/OpenFileQuickOpen.ts +2 -2
- package/front_end/panels/sources/Plugin.ts +3 -2
- package/front_end/panels/sources/ResourceOriginPlugin.ts +14 -17
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/panels/sources/SourcesView.ts +25 -82
- package/front_end/panels/sources/TabbedEditorContainer.ts +75 -21
- package/front_end/panels/sources/UISourceCodeFrame.ts +22 -13
- package/front_end/panels/sources/sourcesView.css +17 -27
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +1 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/source-map-scopes-codec/README.chromium +2 -2
- package/front_end/third_party/source-map-scopes-codec/package/CONTRIBUTING.md +14 -1
- package/front_end/third_party/source-map-scopes-codec/package/README.md +8 -6
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts +4 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/decode/decode.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/_dist/src/scopes.d.ts.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/deno.json +6 -2
- package/front_end/third_party/source-map-scopes-codec/package/package.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js +18 -2
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.ts +22 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js +33 -5
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.ts +41 -5
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.js +0 -2
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/codec.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js +99 -36
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.ts +143 -49
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.ts +3 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js +40 -18
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.ts +51 -21
- package/front_end/third_party/source-map-scopes-codec/package/src/scopes.ts +4 -3
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js +18 -4
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/vlq.ts +18 -4
- package/front_end/ui/comments/CommentOverlayManager.ts +23 -10
- package/front_end/ui/components/text_editor/javascript.ts +128 -52
- package/front_end/ui/legacy/SearchableView.ts +125 -74
- package/front_end/ui/legacy/components/source_frame/FontView.ts +5 -5
- package/front_end/ui/legacy/components/source_frame/ImageView.ts +13 -13
- package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +2 -6
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +3 -2
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
- package/front_end/Images/nodeIcon.avif +0 -0
|
@@ -144,7 +144,12 @@ export class FormatterWorkerPool {
|
|
|
144
144
|
return Promise.resolve(expression);
|
|
145
145
|
}
|
|
146
146
|
return this.runTask(FormatterActions.FormatterActions.JAVASCRIPT_SUBSTITUTE, {content: expression, mapping})
|
|
147
|
-
.then(result
|
|
147
|
+
.then((result: string|{error: string}|null) => {
|
|
148
|
+
if (result && typeof result === 'object') {
|
|
149
|
+
throw new Error(result.error);
|
|
150
|
+
}
|
|
151
|
+
return result || '';
|
|
152
|
+
});
|
|
148
153
|
}
|
|
149
154
|
|
|
150
155
|
javaScriptScopeTree(expression: string, sourceType: 'module'|'script' = 'script'):
|
|
@@ -8972,11 +8972,15 @@ export const NativeFunctions: readonly NativeFunctionValue[] = [
|
|
|
8972
8972
|
signatures: [["type","?eventInitDict"]]
|
|
8973
8973
|
},
|
|
8974
8974
|
{
|
|
8975
|
-
name: "
|
|
8975
|
+
name: "ToolActivatedEvent",
|
|
8976
8976
|
signatures: [["type","?eventInitDict"]]
|
|
8977
8977
|
},
|
|
8978
8978
|
{
|
|
8979
|
-
name: "
|
|
8979
|
+
name: "ToolCancelEvent",
|
|
8980
|
+
signatures: [["type","?eventInitDict"]]
|
|
8981
|
+
},
|
|
8982
|
+
{
|
|
8983
|
+
name: "TouchEvent",
|
|
8980
8984
|
signatures: [["type","?eventInitDict"]]
|
|
8981
8985
|
},
|
|
8982
8986
|
{
|
|
@@ -408,12 +408,11 @@ export const resolveScopeChain =
|
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
if (callFrame.script.isWasm()) {
|
|
411
|
-
return callFrame.scopeChain()
|
|
411
|
+
return callFrame.scopeChain();
|
|
412
412
|
}
|
|
413
413
|
const thisObject = await resolveThisObject(callFrame, debuggerWorkspaceBinding);
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
return scopes.map(scope => new ScopeWithSourceMappedVariables(scope, thisObject, debuggerWorkspaceBinding));
|
|
414
|
+
return callFrame.scopeChain().map(
|
|
415
|
+
scope => new ScopeWithSourceMappedVariables(scope, thisObject, debuggerWorkspaceBinding));
|
|
417
416
|
};
|
|
418
417
|
|
|
419
418
|
/**
|
|
@@ -472,7 +471,7 @@ export const allVariablesInCallFrame = async(
|
|
|
472
471
|
}
|
|
473
472
|
}
|
|
474
473
|
|
|
475
|
-
const scopeChain = callFrame.scopeChain()
|
|
474
|
+
const scopeChain = callFrame.scopeChain();
|
|
476
475
|
const resolvedScopes =
|
|
477
476
|
await Promise.all(scopeChain.map(scope => resolveDebuggerScope(scope, debuggerWorkspaceBinding)));
|
|
478
477
|
const result = resolvedScopes.map(toScopeVariableMapping);
|
|
@@ -529,13 +528,12 @@ export const resolveThisObject = async(
|
|
|
529
528
|
callFrame: SDK.DebuggerModel.CallFrame,
|
|
530
529
|
debuggerWorkspaceBinding:
|
|
531
530
|
Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding): Promise<SDK.RemoteObject.RemoteObject|null> => {
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
if (!innermostScope) {
|
|
531
|
+
const scopeChain = callFrame.scopeChain();
|
|
532
|
+
if (scopeChain.length === 0) {
|
|
535
533
|
return callFrame.thisObject();
|
|
536
534
|
}
|
|
537
535
|
|
|
538
|
-
const {thisMapping} = await resolveDebuggerScope(
|
|
536
|
+
const {thisMapping} = await resolveDebuggerScope(scopeChain[0], debuggerWorkspaceBinding);
|
|
539
537
|
if (!thisMapping) {
|
|
540
538
|
return callFrame.thisObject();
|
|
541
539
|
}
|
|
@@ -120,6 +120,7 @@ const UIStrings = {
|
|
|
120
120
|
* @description Inform users that DevTools are recording/waiting for events in the Periodic Background Sync tool of the Application panel
|
|
121
121
|
* @example {Background Fetch} PH1
|
|
122
122
|
*/
|
|
123
|
+
// eslint-disable-next-line @devtools/l10n-uistrings-sentence-punctuation -- Concatenated with recordingSActivity in UI to form a multi-sentence message.
|
|
123
124
|
devtoolsWillRecordAllSActivity: 'DevTools will record all {PH1} activity for up to 3 days, even when closed.',
|
|
124
125
|
/**
|
|
125
126
|
* @description Text in Background Service View of the Application panel to instruct the user on how to start a recording for
|
|
@@ -147,13 +147,13 @@ const UIStrings = {
|
|
|
147
147
|
settings: 'Settings',
|
|
148
148
|
/**
|
|
149
149
|
* @description The name of a checkbox setting. This setting highlights the
|
|
150
|
-
* rendering elements for
|
|
150
|
+
* rendering elements for ad-related resources that are found on the page.
|
|
151
151
|
*/
|
|
152
|
-
|
|
152
|
+
highlightAdRelatedResources: 'Highlight ad-related resources',
|
|
153
153
|
/**
|
|
154
|
-
* @description Explanation text for the 'Highlight
|
|
154
|
+
* @description Explanation text for the 'Highlight ad-related resources' setting.
|
|
155
155
|
*/
|
|
156
|
-
|
|
156
|
+
highlightsElementsRedDetectedToBeAdRelated: 'Highlights elements (red) detected to be ad-related',
|
|
157
157
|
/**
|
|
158
158
|
* @description Text explaining that ad detection is not perfect.
|
|
159
159
|
*/
|
|
@@ -425,8 +425,8 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
425
425
|
<devtools-checkbox class="setting-container small"
|
|
426
426
|
${bindToSetting(Common.Settings.Settings.instance().resolve(SDK.SDKSettings.showAdHighlightsSettingDescriptor))}>
|
|
427
427
|
<div class="setting-text-container">
|
|
428
|
-
<div class="setting-label">${i18nString(UIStrings.
|
|
429
|
-
<div class="setting-explanation">${i18nString(UIStrings.
|
|
428
|
+
<div class="setting-label">${i18nString(UIStrings.highlightAdRelatedResources)}</div>
|
|
429
|
+
<div class="setting-explanation">${i18nString(UIStrings.highlightsElementsRedDetectedToBeAdRelated)}</div>
|
|
430
430
|
</div>
|
|
431
431
|
</devtools-checkbox>
|
|
432
432
|
<hr class="divider">
|
|
@@ -129,7 +129,7 @@ const UIStrings = {
|
|
|
129
129
|
* 'm' is never less than 2.
|
|
130
130
|
* @example {3} m
|
|
131
131
|
*/
|
|
132
|
-
issuesInMultipleFrames: '{n, plural, =1 {# issue found in {m} frames
|
|
132
|
+
issuesInMultipleFrames: '{n, plural, =1 {# issue found in {m} frames} other {# issues found in {m} frames}}',
|
|
133
133
|
/**
|
|
134
134
|
* @description Shows the number of frames with a particular issue.
|
|
135
135
|
*/
|
|
@@ -26,6 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
* @example {flex-wrap: nowrap} REASON_PROPERTY_DECLARATION_CODE
|
|
27
27
|
* @example {align-content} AFFECTED_PROPERTY_DECLARATION_CODE
|
|
28
28
|
*/
|
|
29
|
+
// eslint-disable-next-line @devtools/l10n-uistrings-sentence-punctuation -- Two sentences displayed together in Styles pane
|
|
29
30
|
ruleViolatedBySameElementRuleReason:
|
|
30
31
|
'The {REASON_PROPERTY_DECLARATION_CODE} property prevents {AFFECTED_PROPERTY_DECLARATION_CODE} from having an effect.',
|
|
31
32
|
/**
|
|
@@ -33,6 +34,7 @@ const UIStrings = {
|
|
|
33
34
|
* @example {flex-wrap} PROPERTY_NAME
|
|
34
35
|
* @example {nowrap} PROPERTY_VALUE
|
|
35
36
|
*/
|
|
37
|
+
// eslint-disable-next-line @devtools/l10n-uistrings-sentence-punctuation -- Two sentences displayed together in Styles pane
|
|
36
38
|
ruleViolatedBySameElementRuleFix: 'Try setting {PROPERTY_NAME} to something other than {PROPERTY_VALUE}.',
|
|
37
39
|
/**
|
|
38
40
|
* @description The message shown in the Styles tab when the user hovers over a property declaration that has no effect due to not being a flex or grid container.
|
|
@@ -71,6 +73,7 @@ const UIStrings = {
|
|
|
71
73
|
* @example {20} PH4
|
|
72
74
|
* @example {Arial} PH5
|
|
73
75
|
*/
|
|
76
|
+
// eslint-disable-next-line @devtools/l10n-uistrings-sentence-punctuation -- Multiple warnings can be joined with a space in the UI to form a multi-sentence message
|
|
74
77
|
fontVariationSettingsWarning:
|
|
75
78
|
'Value for setting "{PH1}" {PH2} is outside the supported range [{PH3}, {PH4}] for font-family "{PH5}".',
|
|
76
79
|
/**
|
|
@@ -359,7 +359,10 @@ export class ClassNamePrompt extends UI.TextPrompt.TextPrompt {
|
|
|
359
359
|
|
|
360
360
|
let completions: string[] = await this.classNamesPromise;
|
|
361
361
|
const classesMap = this.nodeClasses((selectedNode));
|
|
362
|
-
|
|
362
|
+
// Classes may be typed with a leading dot (e.g. `.btn`), while completions
|
|
363
|
+
// are raw class names, so normalize before de-duplicating.
|
|
364
|
+
const existingClasses =
|
|
365
|
+
new Set(expression.split(/[,\s]/).map(className => className.trim().replace(/^\./, '')).filter(Boolean));
|
|
363
366
|
completions = completions.filter(value => !classesMap.get(value) && !existingClasses.has(value));
|
|
364
367
|
|
|
365
368
|
if (prefix[0] === '.') {
|
|
@@ -366,15 +366,21 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
366
366
|
|
|
367
367
|
type View = (input: ViewInput, output: object, element: HTMLElement) => void;
|
|
368
368
|
export class LayoutPane extends UI.Widget.Widget {
|
|
369
|
-
readonly #settings:
|
|
369
|
+
readonly #settings: ReadonlyArray<Common.Settings.Setting<string|boolean>>;
|
|
370
370
|
readonly #uaShadowDOMSetting: Common.Settings.Setting<boolean>;
|
|
371
371
|
#domModels: SDK.DOMModel.DOMModel[];
|
|
372
372
|
readonly #view: View;
|
|
373
373
|
|
|
374
374
|
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
375
375
|
super(element);
|
|
376
|
-
|
|
377
|
-
this.#
|
|
376
|
+
const settings = Common.Settings.Settings.instance();
|
|
377
|
+
this.#settings = [
|
|
378
|
+
settings.resolve(SDK.SDKSettings.showGridLineLabelsSettingDescriptor),
|
|
379
|
+
settings.resolve(SDK.SDKSettings.showGridTrackSizesSettingDescriptor),
|
|
380
|
+
settings.resolve(SDK.SDKSettings.showGridAreasSettingDescriptor),
|
|
381
|
+
settings.resolve(SDK.SDKSettings.extendGridLinesSettingDescriptor),
|
|
382
|
+
];
|
|
383
|
+
this.#uaShadowDOMSetting = settings.moduleSetting('show-ua-shadow-dom');
|
|
378
384
|
this.#domModels = [];
|
|
379
385
|
this.#view = view;
|
|
380
386
|
}
|
|
@@ -445,10 +451,8 @@ export class LayoutPane extends UI.Widget.Widget {
|
|
|
445
451
|
}
|
|
446
452
|
|
|
447
453
|
#makeSettings(): Setting[] {
|
|
448
|
-
const settings = [];
|
|
449
|
-
for (const
|
|
450
|
-
of ['show-grid-line-labels', 'show-grid-track-sizes', 'show-grid-areas', 'extend-grid-lines']) {
|
|
451
|
-
const setting = Common.Settings.Settings.instance().moduleSetting(settingName);
|
|
454
|
+
const settings: Setting[] = [];
|
|
455
|
+
for (const setting of this.#settings) {
|
|
452
456
|
const settingValue = setting.get();
|
|
453
457
|
const settingType = setting.type();
|
|
454
458
|
if (!settingType) {
|
|
@@ -489,13 +493,13 @@ export class LayoutPane extends UI.Widget.Widget {
|
|
|
489
493
|
}
|
|
490
494
|
|
|
491
495
|
onSettingChanged(setting: string, value: string|boolean): void {
|
|
492
|
-
|
|
496
|
+
this.#settings.find(s => s.name === setting)?.set(value);
|
|
493
497
|
}
|
|
494
498
|
|
|
495
499
|
override wasShown(): void {
|
|
496
500
|
super.wasShown();
|
|
497
501
|
for (const setting of this.#settings) {
|
|
498
|
-
|
|
502
|
+
setting.addChangeListener(this.requestUpdate, this);
|
|
499
503
|
}
|
|
500
504
|
for (const domModel of this.#domModels) {
|
|
501
505
|
this.modelRemoved(domModel);
|
|
@@ -510,7 +514,7 @@ export class LayoutPane extends UI.Widget.Widget {
|
|
|
510
514
|
override willHide(): void {
|
|
511
515
|
super.willHide();
|
|
512
516
|
for (const setting of this.#settings) {
|
|
513
|
-
|
|
517
|
+
setting.removeChangeListener(this.requestUpdate, this);
|
|
514
518
|
}
|
|
515
519
|
SDK.TargetManager.TargetManager.instance().unobserveModels(SDK.DOMModel.DOMModel, this);
|
|
516
520
|
UI.Context.Context.instance().removeFlavorChangeListener(SDK.DOMModel.DOMNode, this.requestUpdate, this);
|
|
@@ -537,6 +541,7 @@ export class LayoutPane extends UI.Widget.Widget {
|
|
|
537
541
|
}
|
|
538
542
|
|
|
539
543
|
override async performUpdate(): Promise<void> {
|
|
544
|
+
const settings = this.#makeSettings();
|
|
540
545
|
const input: ViewInput = {
|
|
541
546
|
gridElements: gridNodesToElements(await this.#fetchGridNodes()),
|
|
542
547
|
flexContainerElements: flexContainerNodesToElements(await this.#fetchFlexContainerNodes()),
|
|
@@ -547,22 +552,14 @@ export class LayoutPane extends UI.Widget.Widget {
|
|
|
547
552
|
onMouseEnter: this.#onElementMouseEnter.bind(this),
|
|
548
553
|
onElementToggle: this.#onElementToggle.bind(this),
|
|
549
554
|
onBooleanSettingChange: this.#onBooleanSettingChange.bind(this),
|
|
550
|
-
enumSettings:
|
|
551
|
-
booleanSettings:
|
|
555
|
+
enumSettings: settings.filter(isEnumSetting),
|
|
556
|
+
booleanSettings: settings.filter(isBooleanSetting),
|
|
552
557
|
onSummaryKeyDown: this.#onSummaryKeyDown.bind(this),
|
|
553
558
|
};
|
|
554
559
|
|
|
555
560
|
this.#view(input, {}, this.contentElement);
|
|
556
561
|
}
|
|
557
562
|
|
|
558
|
-
#getEnumSettings(): EnumSetting[] {
|
|
559
|
-
return this.#settings.filter(isEnumSetting);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
#getBooleanSettings(): BooleanSetting[] {
|
|
563
|
-
return this.#settings.filter(isBooleanSetting);
|
|
564
|
-
}
|
|
565
|
-
|
|
566
563
|
#onBooleanSettingChange(setting: BooleanSetting, event: Event): void {
|
|
567
564
|
event.preventDefault();
|
|
568
565
|
this.onSettingChanged(setting.name, (event.target as UI.UIUtils.CheckboxLabel).checked);
|
|
@@ -625,7 +625,7 @@ export class NetworkLogViewColumns {
|
|
|
625
625
|
const setting = savedSettings[columnId];
|
|
626
626
|
let columnConfig = this.columns.find(columnConfig => columnConfig.id === columnId);
|
|
627
627
|
if (!columnConfig && setting.title) {
|
|
628
|
-
columnConfig = this.
|
|
628
|
+
columnConfig = this.registerCustomHeader(setting.title, columnId) || undefined;
|
|
629
629
|
}
|
|
630
630
|
|
|
631
631
|
if (columnConfig) {
|
|
@@ -816,6 +816,15 @@ export class NetworkLogViewColumns {
|
|
|
816
816
|
}
|
|
817
817
|
|
|
818
818
|
private addCustomHeader(headerTitle: string, headerId?: string, index?: number): Descriptor|null {
|
|
819
|
+
const columnConfig = this.registerCustomHeader(headerTitle, headerId, index);
|
|
820
|
+
if (columnConfig) {
|
|
821
|
+
this.saveColumnsSettings();
|
|
822
|
+
this.updateColumns();
|
|
823
|
+
}
|
|
824
|
+
return columnConfig;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
private registerCustomHeader(headerTitle: string, headerId?: string, index?: number): Descriptor|null {
|
|
819
828
|
if (!headerId) {
|
|
820
829
|
headerId = headerTitle;
|
|
821
830
|
}
|
|
@@ -855,8 +864,6 @@ export class NetworkLogViewColumns {
|
|
|
855
864
|
if (this.#dataGrid) {
|
|
856
865
|
this.#dataGrid.addColumn(NetworkLogViewColumns.convertToDataGridDescriptor(columnConfig), index);
|
|
857
866
|
}
|
|
858
|
-
this.saveColumnsSettings();
|
|
859
|
-
this.updateColumns();
|
|
860
867
|
return columnConfig;
|
|
861
868
|
}
|
|
862
869
|
|
|
@@ -35,7 +35,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
35
35
|
if (input.copy) {
|
|
36
36
|
contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copy), input.copy, {jslogContext: 'copy'});
|
|
37
37
|
}
|
|
38
|
-
if (!input.showMore) {
|
|
38
|
+
if (!input.showMore && input.text.length > MAX_LENGTH) {
|
|
39
39
|
contextMenu.newSection().appendItem(i18nString(UIStrings.showMore), input.onToggle, {jslogContext: 'show-more'});
|
|
40
40
|
}
|
|
41
41
|
void contextMenu.show();
|
|
@@ -31,6 +31,7 @@ import {SecurityPanelSidebar} from './SecurityPanelSidebar.js';
|
|
|
31
31
|
|
|
32
32
|
const {widget, widgetRef} = UI.Widget;
|
|
33
33
|
|
|
34
|
+
/* eslint-disable @devtools/l10n-uistrings-sentence-punctuation -- Kept with periods to avoid breaking Blink layout tests in chromium/src: http/tests/devtools/security/ */
|
|
34
35
|
const UIStrings = {
|
|
35
36
|
/**
|
|
36
37
|
* @description Title of the overview section in the Security panel.
|
|
@@ -428,6 +429,7 @@ const UIStrings = {
|
|
|
428
429
|
*/
|
|
429
430
|
enabled: 'enabled',
|
|
430
431
|
} as const;
|
|
432
|
+
/* eslint-enable @devtools/l10n-uistrings-sentence-punctuation */
|
|
431
433
|
const str_ = i18n.i18n.registerUIStrings('panels/security/SecurityPanel.ts', UIStrings);
|
|
432
434
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
433
435
|
|
|
@@ -1560,6 +1562,14 @@ function renderCertificateTransparencySection(input: CertificateTransparencySect
|
|
|
1560
1562
|
// clang-format on
|
|
1561
1563
|
}
|
|
1562
1564
|
|
|
1565
|
+
function renderNoteSection(loadedFromCache: boolean): TemplateResult {
|
|
1566
|
+
// clang-format off
|
|
1567
|
+
return html`
|
|
1568
|
+
${loadedFromCache ? html`<div>${i18nString(UIStrings.thisResponseWasLoadedFromCache)}</div>` : nothing}
|
|
1569
|
+
<div>${i18nString(UIStrings.theSecurityDetailsAboveAreFrom)}</div>`;
|
|
1570
|
+
// clang-format on
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1563
1573
|
export class SecurityOriginView extends UI.Widget.VBox {
|
|
1564
1574
|
readonly #origin: Platform.DevToolsPath.UrlString;
|
|
1565
1575
|
readonly #titleSection: HTMLElement;
|
|
@@ -1584,16 +1594,13 @@ export class SecurityOriginView extends UI.Widget.VBox {
|
|
|
1584
1594
|
|
|
1585
1595
|
const sctListLength = originState.securityDetails.signedCertificateTimestampList.length;
|
|
1586
1596
|
const ctCompliance = originState.securityDetails.certificateTransparencyCompliance;
|
|
1587
|
-
if (
|
|
1588
|
-
|
|
1597
|
+
if (sctListLength || ctCompliance !== Protocol.Network.CertificateTransparencyCompliance.Unknown) {
|
|
1598
|
+
this.#createCertificateTransparencySection(originState.securityDetails);
|
|
1589
1599
|
}
|
|
1590
|
-
this.#createCertificateTransparencySection(originState.securityDetails);
|
|
1591
1600
|
|
|
1592
1601
|
const noteSection = this.element.createChild('div', 'origin-view-section origin-view-notes');
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
}
|
|
1596
|
-
noteSection.createChild('div').textContent = i18nString(UIStrings.theSecurityDetailsAboveAreFrom);
|
|
1602
|
+
// eslint-disable-next-line @devtools/no-lit-render-outside-of-view
|
|
1603
|
+
render(renderNoteSection(originState.loadedFromCache), noteSection);
|
|
1597
1604
|
} else if (originState.securityState === Protocol.Security.SecurityState.Secure) {
|
|
1598
1605
|
// If the security state is secure but there are no security details,
|
|
1599
1606
|
// this means that the origin is a non-cryptographic secure origin, e.g.
|
|
@@ -161,6 +161,7 @@ export class BreakpointEditDialog extends UI.Widget.Widget {
|
|
|
161
161
|
#breakpointType: SDK.DebuggerModel.BreakpointType.LOGPOINT|SDK.DebuggerModel.BreakpointType.CONDITIONAL_BREAKPOINT =
|
|
162
162
|
SDK.DebuggerModel.BreakpointType.CONDITIONAL_BREAKPOINT;
|
|
163
163
|
#onFinish: (result: BreakpointEditDialogResult) => void = () => {};
|
|
164
|
+
#location?: () => Promise<SDK.DebuggerModel.Location|null>;
|
|
164
165
|
#editor?: TextEditor.TextEditor.TextEditor;
|
|
165
166
|
#state?: CodeMirror.EditorState;
|
|
166
167
|
|
|
@@ -207,6 +208,13 @@ export class BreakpointEditDialog extends UI.Widget.Widget {
|
|
|
207
208
|
this.#onFinish = onFinish;
|
|
208
209
|
this.requestUpdate();
|
|
209
210
|
}
|
|
211
|
+
get location(): (() => Promise<SDK.DebuggerModel.Location|null>)|undefined {
|
|
212
|
+
return this.#location;
|
|
213
|
+
}
|
|
214
|
+
set location(location: (() => Promise<SDK.DebuggerModel.Location|null>)|undefined) {
|
|
215
|
+
this.#location = location;
|
|
216
|
+
this.requestUpdate();
|
|
217
|
+
}
|
|
210
218
|
|
|
211
219
|
override focus(): void {
|
|
212
220
|
void this.updateComplete.then(() => {
|
|
@@ -283,6 +291,9 @@ export class BreakpointEditDialog extends UI.Widget.Widget {
|
|
|
283
291
|
},
|
|
284
292
|
];
|
|
285
293
|
|
|
294
|
+
const completionOptions: TextEditor.JavaScript.CompletionOptions = {
|
|
295
|
+
location: () => this.#location ? this.#location() : Promise.resolve(null),
|
|
296
|
+
};
|
|
286
297
|
const editorConfig = [
|
|
287
298
|
CodeMirror.javascript.javascriptLanguage,
|
|
288
299
|
TextEditor.Config.baseConfiguration(this.oldCondition),
|
|
@@ -292,8 +303,9 @@ export class BreakpointEditDialog extends UI.Widget.Widget {
|
|
|
292
303
|
TextEditor.Config.showCompletionHint,
|
|
293
304
|
TextEditor.Config.conservativeCompletion,
|
|
294
305
|
CodeMirror.javascript.javascriptLanguage.data.of({autocomplete}),
|
|
306
|
+
TextEditor.JavaScript.completion(completionOptions),
|
|
295
307
|
CodeMirror.autocompletion(),
|
|
296
|
-
TextEditor.JavaScript.argumentHints(),
|
|
308
|
+
TextEditor.JavaScript.argumentHints(completionOptions),
|
|
297
309
|
];
|
|
298
310
|
|
|
299
311
|
this.#state = CodeMirror.EditorState.create({
|
|
@@ -611,7 +611,7 @@ export class DebuggerPlugin extends Plugin {
|
|
|
611
611
|
tokenType === 'PropertyDefinition';
|
|
612
612
|
}
|
|
613
613
|
|
|
614
|
-
|
|
614
|
+
getPopoverRequest(event: MouseEvent|KeyboardEvent): UI.PopoverHelper.PopoverRequest|null {
|
|
615
615
|
if (event instanceof KeyboardEvent) {
|
|
616
616
|
return null;
|
|
617
617
|
}
|
|
@@ -629,7 +629,6 @@ export class DebuggerPlugin extends Plugin {
|
|
|
629
629
|
if (!debuggableFrame) {
|
|
630
630
|
return null;
|
|
631
631
|
}
|
|
632
|
-
const selectedCallFrame = debuggableFrame.sdkFrame;
|
|
633
632
|
|
|
634
633
|
let textPosition = editor.editor.posAtCoords(event);
|
|
635
634
|
if (!textPosition) {
|
|
@@ -667,65 +666,17 @@ export class DebuggerPlugin extends Plugin {
|
|
|
667
666
|
return {
|
|
668
667
|
box,
|
|
669
668
|
show: async (popover: UI.GlassPane.GlassPane) => {
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
if (scopedVariable.found) {
|
|
673
|
-
if (!scopedVariable.value) {
|
|
674
|
-
return false;
|
|
675
|
-
}
|
|
676
|
-
objectPopoverHelper =
|
|
677
|
-
await ObjectUI.ObjectPopoverHelper.ObjectPopoverHelper.buildObjectPopover(scopedVariable.value, popover);
|
|
678
|
-
const potentiallyUpdatedCallFrame =
|
|
679
|
-
UI.Context.Context.instance().flavor(StackTrace.StackTrace.DebuggableFrameFlavor);
|
|
680
|
-
if (!objectPopoverHelper || debuggableFrame !== potentiallyUpdatedCallFrame) {
|
|
681
|
-
objectPopoverHelper?.dispose();
|
|
682
|
-
return false;
|
|
683
|
-
}
|
|
684
|
-
return true;
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
let resolvedText = '';
|
|
688
|
-
if (selectedCallFrame.script.isJavaScript()) {
|
|
689
|
-
const nameMap = await SourceMapScopes.NamesResolver.allVariablesInCallFrame(
|
|
690
|
-
selectedCallFrame, Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance());
|
|
691
|
-
try {
|
|
692
|
-
resolvedText =
|
|
693
|
-
await Formatter.FormatterWorkerPool.formatterWorkerPool().javaScriptSubstitute(evaluationText, nameMap);
|
|
694
|
-
} catch {
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
// We use side-effect free debug-evaluate when the highlighted expression contains a
|
|
698
|
-
// function/method call. Otherwise we allow side-effects. The motiviation here are
|
|
699
|
-
// frameworks like Vue, that heavily use proxies for caching:
|
|
700
|
-
//
|
|
701
|
-
// * We deem a simple property access of a proxy as deterministic so it should be
|
|
702
|
-
// successful even if V8 thinks its side-effecting.
|
|
703
|
-
// * Explicit function calls on the other hand must be side-effect free. The canonical
|
|
704
|
-
// example is hovering over {Math.random()} which would result in a different value
|
|
705
|
-
// each time the user hovers over it.
|
|
706
|
-
const throwOnSideEffect = highlightRange.containsSideEffects;
|
|
707
|
-
const result = await selectedCallFrame.evaluate({
|
|
708
|
-
expression: resolvedText || evaluationText,
|
|
709
|
-
objectGroup: 'popover',
|
|
710
|
-
includeCommandLineAPI: false,
|
|
711
|
-
silent: true,
|
|
712
|
-
returnByValue: false,
|
|
713
|
-
generatePreview: false,
|
|
714
|
-
throwOnSideEffect,
|
|
715
|
-
});
|
|
716
|
-
if (!result || 'error' in result || !result.object ||
|
|
717
|
-
(result.object.type === 'object' && result.object.subtype === 'error')) {
|
|
669
|
+
const object = await this.#evaluateForPopover(debuggableFrame, highlightRange, evaluationText);
|
|
670
|
+
if (!object) {
|
|
718
671
|
return false;
|
|
719
672
|
}
|
|
720
673
|
objectPopoverHelper =
|
|
721
|
-
await ObjectUI.ObjectPopoverHelper.ObjectPopoverHelper.buildObjectPopover(
|
|
674
|
+
await ObjectUI.ObjectPopoverHelper.ObjectPopoverHelper.buildObjectPopover(object, popover);
|
|
722
675
|
const potentiallyUpdatedCallFrame =
|
|
723
676
|
UI.Context.Context.instance().flavor(StackTrace.StackTrace.DebuggableFrameFlavor);
|
|
724
677
|
if (!objectPopoverHelper || debuggableFrame !== potentiallyUpdatedCallFrame) {
|
|
725
678
|
debuggerModel.runtimeModel().releaseObjectGroup('popover');
|
|
726
|
-
|
|
727
|
-
objectPopoverHelper.dispose();
|
|
728
|
-
}
|
|
679
|
+
objectPopoverHelper?.dispose();
|
|
729
680
|
return false;
|
|
730
681
|
}
|
|
731
682
|
const decoration = CodeMirror.Decoration.set(evalExpressionMark.range(highlightRange.from, highlightRange.to));
|
|
@@ -742,6 +693,52 @@ export class DebuggerPlugin extends Plugin {
|
|
|
742
693
|
};
|
|
743
694
|
}
|
|
744
695
|
|
|
696
|
+
async #evaluateForPopover(debuggableFrame: StackTrace.StackTrace.DebuggableFrameFlavor,
|
|
697
|
+
highlightRange: {from: number, to: number, containsSideEffects: boolean},
|
|
698
|
+
evaluationText: string): Promise<SDK.RemoteObject.RemoteObject|null> {
|
|
699
|
+
const scopeMappings = await this.#getScopeMappings(debuggableFrame) ?? [];
|
|
700
|
+
const scopedVariable = findVariableInScopeMappings(evaluationText, highlightRange.from, scopeMappings);
|
|
701
|
+
if (scopedVariable.found) {
|
|
702
|
+
return scopedVariable.value;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const selectedCallFrame = debuggableFrame.sdkFrame;
|
|
706
|
+
let resolvedText = '';
|
|
707
|
+
if (selectedCallFrame.script.isJavaScript()) {
|
|
708
|
+
const nameMap = await SourceMapScopes.NamesResolver.allVariablesInCallFrame(
|
|
709
|
+
selectedCallFrame, Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance());
|
|
710
|
+
try {
|
|
711
|
+
resolvedText =
|
|
712
|
+
await Formatter.FormatterWorkerPool.formatterWorkerPool().javaScriptSubstitute(evaluationText, nameMap);
|
|
713
|
+
} catch {
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
// We use side-effect free debug-evaluate when the highlighted expression contains a
|
|
717
|
+
// function/method call. Otherwise we allow side-effects. The motivation here are
|
|
718
|
+
// frameworks like Vue, that heavily use proxies for caching:
|
|
719
|
+
//
|
|
720
|
+
// * We deem a simple property access of a proxy as deterministic so it should be
|
|
721
|
+
// successful even if V8 thinks its side-effecting.
|
|
722
|
+
// * Explicit function calls on the other hand must be side-effect free. The canonical
|
|
723
|
+
// example is hovering over {Math.random()} which would result in a different value
|
|
724
|
+
// each time the user hovers over it.
|
|
725
|
+
const throwOnSideEffect = highlightRange.containsSideEffects;
|
|
726
|
+
const result = await selectedCallFrame.evaluate({
|
|
727
|
+
expression: resolvedText || evaluationText,
|
|
728
|
+
objectGroup: 'popover',
|
|
729
|
+
includeCommandLineAPI: false,
|
|
730
|
+
silent: true,
|
|
731
|
+
returnByValue: false,
|
|
732
|
+
generatePreview: false,
|
|
733
|
+
throwOnSideEffect,
|
|
734
|
+
});
|
|
735
|
+
if (!result || 'error' in result || !result.object ||
|
|
736
|
+
(result.object.type === 'object' && result.object.subtype === 'error')) {
|
|
737
|
+
return null;
|
|
738
|
+
}
|
|
739
|
+
return result.object;
|
|
740
|
+
}
|
|
741
|
+
|
|
745
742
|
private onEditorUpdate(update: CodeMirror.ViewUpdate): void {
|
|
746
743
|
if (!update.changes.empty) {
|
|
747
744
|
// If the document changed, adjust known breakpoint positions
|
|
@@ -863,6 +860,15 @@ export class DebuggerPlugin extends Plugin {
|
|
|
863
860
|
dialog.oldCondition = oldCondition,
|
|
864
861
|
dialog.breakpointType = isLogpointForDialog ? SDK.DebuggerModel.BreakpointType.LOGPOINT :
|
|
865
862
|
SDK.DebuggerModel.BreakpointType.CONDITIONAL_BREAKPOINT;
|
|
863
|
+
dialog.location = async () => {
|
|
864
|
+
const uiLocation = breakpoint ? (breakpoint.getClosestResolvedLocation() ??
|
|
865
|
+
{lineNumber: breakpoint.lineNumber(), columnNumber: breakpoint.columnNumber()}) :
|
|
866
|
+
(location ?? await this.defaultBreakpointLocation(line));
|
|
867
|
+
const rawLocations =
|
|
868
|
+
await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().uiLocationToRawLocations(
|
|
869
|
+
this.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber);
|
|
870
|
+
return rawLocations[0] ?? null;
|
|
871
|
+
};
|
|
866
872
|
dialog.onFinish = async result => {
|
|
867
873
|
this.activeBreakpointDialog = null;
|
|
868
874
|
this.#activeBreakpointEditRequest = undefined;
|
|
@@ -2396,6 +2402,12 @@ const evalExpression = defineStatefulDecoration();
|
|
|
2396
2402
|
// Styling for plugin-local elements
|
|
2397
2403
|
|
|
2398
2404
|
const theme = CodeMirror.EditorView.baseTheme({
|
|
2405
|
+
'&.source-frame-debugger-script': {
|
|
2406
|
+
backgroundColor: 'rgb(255 255 194 / 50%)',
|
|
2407
|
+
},
|
|
2408
|
+
'&dark.source-frame-debugger-script': {
|
|
2409
|
+
backgroundColor: 'rgb(61 61 0 / 50%)',
|
|
2410
|
+
},
|
|
2399
2411
|
'.cm-line::selection': {
|
|
2400
2412
|
backgroundColor: 'transparent',
|
|
2401
2413
|
color: 'currentColor',
|
|
@@ -7,7 +7,7 @@ import * as Workspace from '../../models/workspace/workspace.js';
|
|
|
7
7
|
import type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
|
|
8
8
|
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
|
|
9
9
|
|
|
10
|
-
import type {
|
|
10
|
+
import type {TabbedEditorContainer} from './TabbedEditorContainer.js';
|
|
11
11
|
import type {UISourceCodeFrame} from './UISourceCodeFrame.js';
|
|
12
12
|
|
|
13
13
|
export const HistoryDepth = 20;
|
|
@@ -17,7 +17,7 @@ export class EditingLocationHistoryManager {
|
|
|
17
17
|
private current = -1;
|
|
18
18
|
private revealingCount = 0;
|
|
19
19
|
|
|
20
|
-
constructor(private readonly
|
|
20
|
+
constructor(private readonly editorContainer: TabbedEditorContainer) {
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
trackSourceFrameCursorJumps(sourceFrame: UISourceCodeFrame): void {
|
|
@@ -66,12 +66,12 @@ export class EditingLocationHistoryManager {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
private
|
|
69
|
+
private reveal(entry: EditingLocationHistoryEntry): void {
|
|
70
70
|
const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCode(entry.projectId, entry.url);
|
|
71
71
|
if (uiSourceCode) {
|
|
72
72
|
this.revealingCount++;
|
|
73
73
|
try {
|
|
74
|
-
|
|
74
|
+
this.editorContainer.showSourceLocation(uiSourceCode, entry.position, false, true);
|
|
75
75
|
} finally {
|
|
76
76
|
this.revealingCount--;
|
|
77
77
|
}
|
|
@@ -81,14 +81,14 @@ export class EditingLocationHistoryManager {
|
|
|
81
81
|
rollback(): void {
|
|
82
82
|
if (this.current > 0) {
|
|
83
83
|
this.current--;
|
|
84
|
-
|
|
84
|
+
this.reveal(this.entries[this.current]);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
rollover(): void {
|
|
89
89
|
if (this.current < this.entries.length - 1) {
|
|
90
90
|
this.current++;
|
|
91
|
-
|
|
91
|
+
this.reveal(this.entries[this.current]);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -11,13 +11,13 @@ import {PanelUtils} from '../../panels/utils/utils.js';
|
|
|
11
11
|
import {Directives, html, type TemplateResult} from '../../ui/lit/lit.js';
|
|
12
12
|
|
|
13
13
|
import {FilteredUISourceCodeListProvider} from './FilteredUISourceCodeListProvider.js';
|
|
14
|
-
import {
|
|
14
|
+
import {TabbedEditorContainer} from './TabbedEditorContainer.js';
|
|
15
15
|
|
|
16
16
|
const {styleMap} = Directives;
|
|
17
17
|
|
|
18
18
|
export class OpenFileQuickOpen extends FilteredUISourceCodeListProvider {
|
|
19
19
|
override attach(): void {
|
|
20
|
-
this.setDefaultScores(
|
|
20
|
+
this.setDefaultScores(TabbedEditorContainer.defaultUISourceCodeScores());
|
|
21
21
|
super.attach();
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -7,6 +7,7 @@ import type * as CodeMirror from '../../third_party/codemirror.next/codemirror.n
|
|
|
7
7
|
import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
|
|
8
8
|
import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
|
|
9
9
|
import type * as UI from '../../ui/legacy/legacy.js';
|
|
10
|
+
import type {LitTemplate} from '../../ui/lit/lit.js';
|
|
10
11
|
|
|
11
12
|
export class Plugin {
|
|
12
13
|
constructor(
|
|
@@ -21,7 +22,7 @@ export class Plugin {
|
|
|
21
22
|
willHide(): void {
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
rightToolbarItems(): UI.Toolbar.ToolbarItem
|
|
25
|
+
rightToolbarItems(): Array<UI.Toolbar.ToolbarItem|LitTemplate> {
|
|
25
26
|
return [];
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -30,7 +31,7 @@ export class Plugin {
|
|
|
30
31
|
* TODO(szuend): It is OK to asyncify this function (similar to {rightToolbarItems}),
|
|
31
32
|
* but it is currently not strictly necessary.
|
|
32
33
|
*/
|
|
33
|
-
leftToolbarItems(): UI.Toolbar.ToolbarItem
|
|
34
|
+
leftToolbarItems(): Array<UI.Toolbar.ToolbarItem|LitTemplate> {
|
|
34
35
|
return [];
|
|
35
36
|
}
|
|
36
37
|
|