chrome-devtools-frontend 1.0.976570 → 1.0.977952

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 (122) hide show
  1. package/config/gni/devtools_grd_files.gni +4 -1
  2. package/front_end/core/host/UserMetrics.ts +46 -24
  3. package/front_end/core/i18n/locales/af.json +5 -5
  4. package/front_end/core/i18n/locales/am.json +5 -5
  5. package/front_end/core/i18n/locales/ar.json +5 -5
  6. package/front_end/core/i18n/locales/as.json +5 -5
  7. package/front_end/core/i18n/locales/az.json +5 -5
  8. package/front_end/core/i18n/locales/be.json +5 -5
  9. package/front_end/core/i18n/locales/bg.json +5 -5
  10. package/front_end/core/i18n/locales/bn.json +5 -5
  11. package/front_end/core/i18n/locales/bs.json +5 -5
  12. package/front_end/core/i18n/locales/ca.json +5 -5
  13. package/front_end/core/i18n/locales/cs.json +5 -5
  14. package/front_end/core/i18n/locales/cy.json +5 -5
  15. package/front_end/core/i18n/locales/da.json +5 -5
  16. package/front_end/core/i18n/locales/de.json +5 -5
  17. package/front_end/core/i18n/locales/el.json +5 -5
  18. package/front_end/core/i18n/locales/en-GB.json +5 -5
  19. package/front_end/core/i18n/locales/en-US.json +24 -15
  20. package/front_end/core/i18n/locales/en-XL.json +24 -15
  21. package/front_end/core/i18n/locales/es-419.json +5 -5
  22. package/front_end/core/i18n/locales/es.json +5 -5
  23. package/front_end/core/i18n/locales/et.json +5 -5
  24. package/front_end/core/i18n/locales/eu.json +5 -5
  25. package/front_end/core/i18n/locales/fa.json +5 -5
  26. package/front_end/core/i18n/locales/fi.json +5 -5
  27. package/front_end/core/i18n/locales/fil.json +5 -5
  28. package/front_end/core/i18n/locales/fr-CA.json +5 -5
  29. package/front_end/core/i18n/locales/fr.json +5 -5
  30. package/front_end/core/i18n/locales/gl.json +5 -5
  31. package/front_end/core/i18n/locales/gu.json +5 -5
  32. package/front_end/core/i18n/locales/he.json +5 -5
  33. package/front_end/core/i18n/locales/hi.json +5 -5
  34. package/front_end/core/i18n/locales/hr.json +5 -5
  35. package/front_end/core/i18n/locales/hu.json +5 -5
  36. package/front_end/core/i18n/locales/hy.json +5 -5
  37. package/front_end/core/i18n/locales/id.json +5 -5
  38. package/front_end/core/i18n/locales/is.json +5 -5
  39. package/front_end/core/i18n/locales/it.json +5 -5
  40. package/front_end/core/i18n/locales/ja.json +5 -5
  41. package/front_end/core/i18n/locales/ka.json +5 -5
  42. package/front_end/core/i18n/locales/kk.json +5 -5
  43. package/front_end/core/i18n/locales/km.json +5 -5
  44. package/front_end/core/i18n/locales/kn.json +5 -5
  45. package/front_end/core/i18n/locales/ko.json +5 -5
  46. package/front_end/core/i18n/locales/ky.json +5 -5
  47. package/front_end/core/i18n/locales/lo.json +5 -5
  48. package/front_end/core/i18n/locales/lt.json +5 -5
  49. package/front_end/core/i18n/locales/lv.json +5 -5
  50. package/front_end/core/i18n/locales/mk.json +5 -5
  51. package/front_end/core/i18n/locales/ml.json +5 -5
  52. package/front_end/core/i18n/locales/mn.json +5 -5
  53. package/front_end/core/i18n/locales/mr.json +5 -5
  54. package/front_end/core/i18n/locales/ms.json +5 -5
  55. package/front_end/core/i18n/locales/my.json +5 -5
  56. package/front_end/core/i18n/locales/ne.json +5 -5
  57. package/front_end/core/i18n/locales/nl.json +5 -5
  58. package/front_end/core/i18n/locales/no.json +5 -5
  59. package/front_end/core/i18n/locales/or.json +5 -5
  60. package/front_end/core/i18n/locales/pa.json +5 -5
  61. package/front_end/core/i18n/locales/pl.json +5 -5
  62. package/front_end/core/i18n/locales/pt-PT.json +5 -5
  63. package/front_end/core/i18n/locales/pt.json +5 -5
  64. package/front_end/core/i18n/locales/ro.json +5 -5
  65. package/front_end/core/i18n/locales/ru.json +5 -5
  66. package/front_end/core/i18n/locales/si.json +5 -5
  67. package/front_end/core/i18n/locales/sk.json +5 -5
  68. package/front_end/core/i18n/locales/sl.json +5 -5
  69. package/front_end/core/i18n/locales/sq.json +5 -5
  70. package/front_end/core/i18n/locales/sr-Latn.json +5 -5
  71. package/front_end/core/i18n/locales/sr.json +5 -5
  72. package/front_end/core/i18n/locales/sv.json +5 -5
  73. package/front_end/core/i18n/locales/sw.json +5 -5
  74. package/front_end/core/i18n/locales/ta.json +5 -5
  75. package/front_end/core/i18n/locales/te.json +5 -5
  76. package/front_end/core/i18n/locales/th.json +5 -5
  77. package/front_end/core/i18n/locales/tr.json +5 -5
  78. package/front_end/core/i18n/locales/uk.json +5 -5
  79. package/front_end/core/i18n/locales/ur.json +5 -5
  80. package/front_end/core/i18n/locales/uz.json +5 -5
  81. package/front_end/core/i18n/locales/vi.json +5 -5
  82. package/front_end/core/i18n/locales/zh-HK.json +5 -5
  83. package/front_end/core/i18n/locales/zh-TW.json +5 -5
  84. package/front_end/core/i18n/locales/zh.json +5 -5
  85. package/front_end/core/i18n/locales/zu.json +5 -5
  86. package/front_end/core/sdk/CSSContainerQuery.ts +1 -1
  87. package/front_end/core/sdk/CSSModel.ts +9 -9
  88. package/front_end/generated/InspectorBackendCommands.js +6 -5
  89. package/front_end/generated/protocol.ts +10 -9
  90. package/front_end/models/issues_manager/{SameSiteCookieIssue.ts → CookieIssue.ts} +75 -79
  91. package/front_end/models/issues_manager/Issue.ts +1 -1
  92. package/front_end/models/issues_manager/IssuesManager.ts +3 -9
  93. package/front_end/models/issues_manager/NavigatorUserAgentIssue.ts +1 -1
  94. package/front_end/models/issues_manager/issues_manager.ts +2 -2
  95. package/front_end/models/persistence/NetworkPersistenceManager.ts +4 -4
  96. package/front_end/panels/application/ApplicationPanelCacheSection.ts +3 -0
  97. package/front_end/panels/application/ApplicationPanelSidebar.ts +15 -0
  98. package/front_end/panels/application/InterestGroupTreeElement.ts +2 -0
  99. package/front_end/panels/application/ReportingApiTreeElement.ts +2 -0
  100. package/front_end/panels/application/TrustTokensTreeElement.ts +2 -0
  101. package/front_end/panels/application/components/BackForwardCacheView.ts +23 -1
  102. package/front_end/panels/elements/ClassesPaneWidget.ts +1 -1
  103. package/front_end/panels/elements/ComputedStyleModel.ts +1 -1
  104. package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
  105. package/front_end/panels/elements/LayersWidget.ts +1 -1
  106. package/front_end/panels/elements/MetricsSidebarPane.ts +2 -2
  107. package/front_end/panels/elements/PlatformFontsWidget.ts +1 -1
  108. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  109. package/front_end/panels/elements/StylesSidebarPane.ts +2 -3
  110. package/front_end/panels/emulation/MediaQueryInspector.ts +1 -1
  111. package/front_end/panels/issues/IssueView.ts +1 -1
  112. package/front_end/panels/issues/IssuesPane.ts +1 -1
  113. package/front_end/panels/network/NetworkLogView.ts +1 -1
  114. package/front_end/panels/sources/CSSPlugin.ts +1 -1
  115. package/front_end/panels/sources/SourcesView.ts +23 -10
  116. package/front_end/panels/sources/components/HeadersView.css +84 -0
  117. package/front_end/panels/sources/components/HeadersView.ts +300 -0
  118. package/front_end/panels/sources/components/components.ts +9 -0
  119. package/front_end/panels/timeline/TimelineController.ts +17 -5
  120. package/front_end/ui/components/expandable_list/expandableList.css +10 -0
  121. package/front_end/ui/components/text_editor/javascript.ts +46 -1
  122. package/package.json +1 -1
@@ -0,0 +1,300 @@
1
+ // Copyright 2022 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 Persistence from '../../../models/persistence/persistence.js';
7
+ import * as Workspace from '../../../models/workspace/workspace.js';
8
+ import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
9
+ import * as UI from '../../../ui/legacy/legacy.js';
10
+ import * as LitHtml from '../../../ui/lit-html/lit-html.js';
11
+
12
+ import HeadersViewStyles from './HeadersView.css.js';
13
+
14
+ const UIStrings = {
15
+ /**
16
+ *@description Error message for files which cannot not be parsed.
17
+ *@example {.headers} PH1
18
+ */
19
+ errorWhenParsing: 'Error when parsing \'\'{PH1}\'\'.',
20
+ /**
21
+ *@description Explainer for files which cannot be parsed.
22
+ *@example {.headers} PH1
23
+ */
24
+ parsingErrorExplainer:
25
+ 'This is most likely due to a syntax error in \'\'{PH1}\'\'. Try opening this file in an external editor to fix the error or delete the file and re-create the override.',
26
+ };
27
+ const str_ = i18n.i18n.registerUIStrings('panels/sources/components/HeadersView.ts', UIStrings);
28
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
29
+
30
+ export class HeadersView extends UI.View.SimpleView {
31
+ readonly #headersViewComponent = new HeadersViewComponent();
32
+ #uiSourceCode: Workspace.UISourceCode.UISourceCode;
33
+
34
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
35
+ super('HeadersView');
36
+ this.#uiSourceCode = uiSourceCode;
37
+ this.#uiSourceCode.addEventListener(
38
+ Workspace.UISourceCode.Events.WorkingCopyChanged, this.#onWorkingCopyChanged, this);
39
+ this.#uiSourceCode.addEventListener(
40
+ Workspace.UISourceCode.Events.WorkingCopyCommitted, this.#onWorkingCopyCommitted, this);
41
+ this.element.appendChild(this.#headersViewComponent);
42
+ void this.#setInitialData();
43
+ }
44
+
45
+ async #setInitialData(): Promise<void> {
46
+ const content = await this.#uiSourceCode.requestContent();
47
+ this.#setComponentData(content.content || '');
48
+ }
49
+
50
+ #setComponentData(content: string): void {
51
+ let parsingError = false;
52
+ let headerOverrides: Persistence.NetworkPersistenceManager.HeaderOverride[] = [];
53
+ content = content || '[]';
54
+ try {
55
+ headerOverrides = JSON.parse(content) as Persistence.NetworkPersistenceManager.HeaderOverride[];
56
+ if (!headerOverrides.every(Persistence.NetworkPersistenceManager.isHeaderOverride)) {
57
+ throw 'Type mismatch after parsing';
58
+ }
59
+ } catch (e) {
60
+ console.error('Failed to parse', this.#uiSourceCode.url(), 'for locally overriding headers.');
61
+ parsingError = true;
62
+ }
63
+
64
+ // Header overrides are stored as the key-value pairs of a JSON object on
65
+ // disk. For the editor we want them as an array instead, so that we can
66
+ // access/add/remove entries by their index.
67
+ const arrayOfHeaderOverrideArrays: HeaderOverride[] = headerOverrides.map(headerOverride => {
68
+ return {
69
+ applyTo: headerOverride.applyTo,
70
+ headers: Object.entries(headerOverride.headers).map(([headerName, headerValue]) => {
71
+ return {
72
+ name: headerName,
73
+ value: headerValue,
74
+ };
75
+ }),
76
+ };
77
+ });
78
+
79
+ this.#headersViewComponent.data = {
80
+ headerOverrides: arrayOfHeaderOverrideArrays,
81
+ uiSourceCode: this.#uiSourceCode,
82
+ parsingError,
83
+ };
84
+ }
85
+
86
+ commitEditing(): void {
87
+ this.#uiSourceCode.commitWorkingCopy();
88
+ Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance().updateInterceptionPatterns();
89
+ }
90
+
91
+ #onWorkingCopyChanged(): void {
92
+ this.#setComponentData(this.#uiSourceCode.workingCopy());
93
+ }
94
+
95
+ #onWorkingCopyCommitted(): void {
96
+ this.#setComponentData(this.#uiSourceCode.workingCopy());
97
+ }
98
+
99
+ dispose(): void {
100
+ this.#uiSourceCode.removeEventListener(
101
+ Workspace.UISourceCode.Events.WorkingCopyChanged, this.#onWorkingCopyChanged, this);
102
+ this.#uiSourceCode.removeEventListener(
103
+ Workspace.UISourceCode.Events.WorkingCopyCommitted, this.#onWorkingCopyCommitted, this);
104
+ }
105
+ }
106
+
107
+ type Header = {
108
+ name: string,
109
+ value: string,
110
+ };
111
+
112
+ type HeaderOverride = {
113
+ applyTo: string,
114
+ headers: Header[],
115
+ };
116
+
117
+ export interface HeadersViewComponentData {
118
+ headerOverrides: HeaderOverride[];
119
+ uiSourceCode: Workspace.UISourceCode.UISourceCode;
120
+ parsingError: boolean;
121
+ }
122
+
123
+ export class HeadersViewComponent extends HTMLElement {
124
+ static readonly litTagName = LitHtml.literal`devtools-sources-headers-view`;
125
+ readonly #shadow = this.attachShadow({mode: 'open'});
126
+ readonly #boundRender = this.#render.bind(this);
127
+ #headerOverrides: HeaderOverride[] = [];
128
+ #uiSourceCode: Workspace.UISourceCode.UISourceCode|null = null;
129
+ #parsingError = false;
130
+
131
+ constructor() {
132
+ super();
133
+ this.#shadow.addEventListener('focusin', this.#onFocusIn.bind(this));
134
+ this.#shadow.addEventListener('focusout', this.#onFocusOut.bind(this));
135
+ this.#shadow.addEventListener('input', this.#onInput.bind(this));
136
+ this.#shadow.addEventListener('keydown', this.#onKeyDown.bind(this));
137
+ }
138
+
139
+ connectedCallback(): void {
140
+ this.#shadow.adoptedStyleSheets = [HeadersViewStyles];
141
+ }
142
+
143
+ set data(data: HeadersViewComponentData) {
144
+ this.#headerOverrides = data.headerOverrides;
145
+ this.#uiSourceCode = data.uiSourceCode;
146
+ this.#parsingError = data.parsingError;
147
+ void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
148
+ }
149
+
150
+ // 'Enter' key should not create a new line in the contenteditable. Focus
151
+ // on the next contenteditable instead.
152
+ #onKeyDown(event: Event): void {
153
+ const keyboardEvent = event as KeyboardEvent;
154
+ const target = event.target as HTMLElement;
155
+ if (target.matches('.editable') && keyboardEvent.key === 'Enter') {
156
+ event.preventDefault();
157
+ this.#focusNext(target);
158
+ }
159
+ }
160
+
161
+ #focusNext(target: HTMLElement): void {
162
+ const elements = Array.from(this.#shadow.querySelectorAll('.editable')) as HTMLElement[];
163
+ const idx = elements.indexOf(target);
164
+ if (idx !== -1 && idx + 1 < elements.length) {
165
+ elements[idx + 1].focus();
166
+ }
167
+ }
168
+
169
+ #selectAllText(target: HTMLElement): void {
170
+ const selection = window.getSelection();
171
+ const range = document.createRange();
172
+ range.selectNodeContents(target);
173
+ selection?.removeAllRanges();
174
+ selection?.addRange(range);
175
+ }
176
+
177
+ #onFocusIn(e: Event): void {
178
+ const target = e.target as HTMLElement;
179
+ if (target.matches('.editable')) {
180
+ this.#selectAllText(target);
181
+ }
182
+ }
183
+
184
+ #onFocusOut(): void {
185
+ // clear selection
186
+ const selection = window.getSelection();
187
+ selection?.removeAllRanges();
188
+ }
189
+
190
+ #onInput(e: Event): void {
191
+ const target = e.target as HTMLButtonElement;
192
+ const rowElement = target.closest('.row') as HTMLElement;
193
+ const blockIndex = Number(rowElement.dataset.blockIndex);
194
+ const headerIndex = Number(rowElement.dataset.headerIndex);
195
+ if (target.matches('.header-name')) {
196
+ this.#headerOverrides[blockIndex].headers[headerIndex].name = target.innerText;
197
+ this.#onHeadersChanged();
198
+ }
199
+ if (target.matches('.header-value')) {
200
+ this.#headerOverrides[blockIndex].headers[headerIndex].value = target.innerText;
201
+ this.#onHeadersChanged();
202
+ }
203
+ if (target.matches('.apply-to')) {
204
+ this.#headerOverrides[blockIndex].applyTo = target.innerText;
205
+ this.#onHeadersChanged();
206
+ }
207
+ }
208
+
209
+ #onHeadersChanged(): void {
210
+ // In the editor header overrides are represented by items in an array, so
211
+ // that we can access/add/remove entries by their index. On disk, they are
212
+ // stored as key-value pairs of a JSON object instead.
213
+ const arrayOfHeaderOverrideObjects: Persistence.NetworkPersistenceManager.HeaderOverride[] =
214
+ this.#headerOverrides.map(headerOverride => {
215
+ return {
216
+ applyTo: headerOverride.applyTo,
217
+ headers: headerOverride.headers.reduce((a, v) => ({...a, [v.name]: v.value}), {}),
218
+ };
219
+ });
220
+ this.#uiSourceCode?.setWorkingCopy(JSON.stringify(arrayOfHeaderOverrideObjects, null, 2));
221
+ }
222
+
223
+ #render(): void {
224
+ if (!ComponentHelpers.ScheduledRender.isScheduledRender(this)) {
225
+ throw new Error('HeadersView render was not scheduled');
226
+ }
227
+
228
+ if (this.#parsingError) {
229
+ const fileName = this.#uiSourceCode?.name() || '.headers';
230
+ // clang-format off
231
+ LitHtml.render(LitHtml.html`
232
+ <div class="center-wrapper">
233
+ <div class="centered">
234
+ <div class="error-header">${i18nString(UIStrings.errorWhenParsing, {PH1: fileName})}</div>
235
+ <div class="error-body">${i18nString(UIStrings.parsingErrorExplainer, {PH1: fileName})}</div>
236
+ </div>
237
+ </div>
238
+ `, this.#shadow, {host: this});
239
+ // clang-format on
240
+ return;
241
+ }
242
+
243
+ // clang-format off
244
+ LitHtml.render(LitHtml.html`
245
+ ${this.#headerOverrides.map((headerOverride, blockIndex) =>
246
+ LitHtml.html`
247
+ ${this.#renderApplyToRow(headerOverride.applyTo, blockIndex)}
248
+ ${headerOverride.headers.map((header, headerIndex) =>
249
+ LitHtml.html`
250
+ ${this.#renderHeaderRow(header, blockIndex, headerIndex)}
251
+ `,
252
+ )}
253
+ `,
254
+ )}
255
+ `, this.#shadow, {host: this});
256
+ // clang-format on
257
+ }
258
+
259
+ #renderApplyToRow(pattern: string, blockIndex: number): LitHtml.TemplateResult {
260
+ // clang-format off
261
+ return LitHtml.html`
262
+ <div class="row" data-block-index=${blockIndex}>
263
+ <div>${i18n.i18n.lockedString('Apply to')}</div>
264
+ <div class="separator">:</div>
265
+ ${this.#renderEditable(pattern, 'apply-to')}
266
+ </div>
267
+ `;
268
+ // clang-format on
269
+ }
270
+
271
+ #renderHeaderRow(header: Header, blockIndex: number, headerIndex: number): LitHtml.TemplateResult {
272
+ // clang-format off
273
+ return LitHtml.html`
274
+ <div class="row padded" data-block-index=${blockIndex} data-header-index=${headerIndex}>
275
+ ${this.#renderEditable(header.name, 'header-name red')}
276
+ <div class="separator">:</div>
277
+ ${this.#renderEditable(header.value, 'header-value')}
278
+ `;
279
+ // clang-format on
280
+ }
281
+
282
+ #renderEditable(value: string, className?: string): LitHtml.TemplateResult {
283
+ // This uses LitHtml's `live`-directive, so that when checking whether to
284
+ // update during re-render, `value` is compared against the actual live DOM
285
+ // value of the contenteditable element and not the potentially outdated
286
+ // value from the previous render.
287
+ // clang-format off
288
+ return LitHtml.html`<span contenteditable="true" class="editable ${className}" tabindex="0" .innerText=${LitHtml.Directives.live(value)}></span>`;
289
+ // clang-format on
290
+ }
291
+ }
292
+
293
+ ComponentHelpers.CustomElements.defineComponent('devtools-sources-headers-view', HeadersViewComponent);
294
+
295
+ declare global {
296
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
297
+ interface HTMLElementTagNameMap {
298
+ 'devtools-sources-headers-view': HeadersViewComponent;
299
+ }
300
+ }
@@ -0,0 +1,9 @@
1
+ // Copyright 2022 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 HeadersView from './HeadersView.js';
6
+
7
+ export {
8
+ HeadersView,
9
+ };
@@ -80,18 +80,31 @@ export class TimelineController implements SDK.TargetManager.SDKModelObserver<SD
80
80
  function disabledByDefault(category: string): string {
81
81
  return 'disabled-by-default-' + category;
82
82
  }
83
+
84
+ // The following categories are also used in other tools, but this panel
85
+ // offers the possibility of turning them off (see below).
86
+ // 'disabled-by-default-devtools.screenshot'
87
+ // └ default: on, option: captureFilmStrip
88
+ // 'disabled-by-default-devtools.timeline.invalidationTracking'
89
+ // └ default: off, experiment: timelineInvalidationTracking
90
+ // 'disabled-by-default-v8.cpu_profiler'
91
+ // └ default: on, option: enableJSSampling
83
92
  const categoriesArray = [
84
93
  '-*',
94
+ TimelineModel.TimelineModel.TimelineModelImpl.Category.Console,
95
+ TimelineModel.TimelineModel.TimelineModelImpl.Category.UserTiming,
85
96
  'devtools.timeline',
86
97
  disabledByDefault('devtools.timeline'),
87
98
  disabledByDefault('devtools.timeline.frame'),
88
- 'v8.execute',
99
+ disabledByDefault('devtools.timeline.stack'),
89
100
  disabledByDefault('v8.compile'),
90
- TimelineModel.TimelineModel.TimelineModelImpl.Category.Console,
91
- TimelineModel.TimelineModel.TimelineModelImpl.Category.UserTiming,
101
+ disabledByDefault('v8.cpu_profiler.hires'),
102
+ TimelineModel.TimelineModel.TimelineModelImpl.Category.LatencyInfo,
92
103
  TimelineModel.TimelineModel.TimelineModelImpl.Category.Loading,
104
+ disabledByDefault('lighthouse'),
105
+ 'v8.execute',
106
+ 'v8',
93
107
  ];
94
- categoriesArray.push(TimelineModel.TimelineModel.TimelineModelImpl.Category.LatencyInfo);
95
108
 
96
109
  if (Root.Runtime.experiments.isEnabled('timelineV8RuntimeCallStats') && options.enableJSSampling) {
97
110
  categoriesArray.push(disabledByDefault('v8.runtime_stats_sampling'));
@@ -99,7 +112,6 @@ export class TimelineController implements SDK.TargetManager.SDKModelObserver<SD
99
112
  if (!Root.Runtime.Runtime.queryParam('timelineTracingJSProfileDisabled') && options.enableJSSampling) {
100
113
  categoriesArray.push(disabledByDefault('v8.cpu_profiler'));
101
114
  }
102
- categoriesArray.push(disabledByDefault('devtools.timeline.stack'));
103
115
  if (Root.Runtime.experiments.isEnabled('timelineInvalidationTracking')) {
104
116
  categoriesArray.push(disabledByDefault('devtools.timeline.invalidationTracking'));
105
117
  }
@@ -4,6 +4,10 @@
4
4
  * found in the LICENSE file.
5
5
  */
6
6
 
7
+ :host {
8
+ overflow: hidden;
9
+ }
10
+
7
11
  div {
8
12
  line-height: 1.7em;
9
13
  }
@@ -53,3 +57,9 @@ button.link {
53
57
  font-family: inherit;
54
58
  font-size: inherit;
55
59
  }
60
+
61
+ .text-ellipsis {
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ white-space: nowrap;
65
+ }
@@ -101,11 +101,11 @@ const dontCompleteIn = new Set([
101
101
  'TypeName',
102
102
  ]);
103
103
 
104
- // FIXME Implement Map property completion?
105
104
  export const enum QueryType {
106
105
  Expression = 0,
107
106
  PropertyName = 1,
108
107
  PropertyExpression = 2,
108
+ PotentiallyRetrievingFromMap = 3,
109
109
  }
110
110
 
111
111
  export function getQueryType(tree: CodeMirror.Tree, pos: number, doc: CodeMirror.Text): {
@@ -149,6 +149,22 @@ export function getQueryType(tree: CodeMirror.Tree, pos: number, doc: CodeMirror
149
149
  return {type: QueryType.PropertyName, relatedNode: node};
150
150
  }
151
151
  }
152
+ if (node.name === '(') {
153
+ // map.get(<auto-complete>
154
+ if (parent.name === 'ArgList' && parent.parent.name === 'CallExpression') {
155
+ // map.get
156
+ const callReceiver = parent.parent.firstChild;
157
+ if (callReceiver.name === 'MemberExpression') {
158
+ // get
159
+ const propertyExpression = callReceiver.lastChild;
160
+ if (doc.sliceString(propertyExpression.from, propertyExpression.to) === 'get') {
161
+ // map
162
+ const potentiallyMapObject = callReceiver.firstChild;
163
+ return {type: QueryType.PotentiallyRetrievingFromMap, relatedNode: potentiallyMapObject};
164
+ }
165
+ }
166
+ }
167
+ }
152
168
  return {type: QueryType.Expression};
153
169
  }
154
170
 
@@ -184,6 +200,12 @@ export async function javascriptCompletionSource(cx: CodeMirror.CompletionContex
184
200
  }
185
201
  result = await completeProperties(
186
202
  cx.state.sliceDoc(objectExpr.from, objectExpr.to), quote, cx.state.sliceDoc(cx.pos, cx.pos + 1) === ']');
203
+ } else if (query.type === QueryType.PotentiallyRetrievingFromMap) {
204
+ const potentialMapObject = query.relatedNode;
205
+ if (!potentialMapObject) {
206
+ return null;
207
+ }
208
+ result = await maybeCompleteKeysFromMap(cx.state.sliceDoc(potentialMapObject.from, potentialMapObject.to));
187
209
  } else {
188
210
  return null;
189
211
  }
@@ -272,6 +294,29 @@ class PropertyCache {
272
294
  }
273
295
  }
274
296
 
297
+ async function maybeCompleteKeysFromMap(objectVariable: string): Promise<CompletionSet> {
298
+ const result = new CompletionSet();
299
+ const context = getExecutionContext();
300
+ if (!context) {
301
+ return result;
302
+ }
303
+ const maybeRetrieveKeys =
304
+ await evaluateExpression(context, `[...Map.prototype.keys.call(${objectVariable})]`, 'completion');
305
+ if (!maybeRetrieveKeys) {
306
+ return result;
307
+ }
308
+ const properties = SDK.RemoteObject.RemoteArray.objectAsArray(maybeRetrieveKeys);
309
+ const numProperties = properties.length();
310
+ for (let i = 0; i < numProperties; i++) {
311
+ result.add({
312
+ label: `"${(await properties.at(i)).value}")`,
313
+ type: 'constant',
314
+ boost: i * -1,
315
+ });
316
+ }
317
+ return result;
318
+ }
319
+
275
320
  async function completeProperties(
276
321
  expression: string,
277
322
  quoted?: string,
package/package.json CHANGED
@@ -54,5 +54,5 @@
54
54
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
55
55
  "watch": "third_party/node/node.py --output scripts/watch_build.js"
56
56
  },
57
- "version": "1.0.976570"
57
+ "version": "1.0.977952"
58
58
  }