chrome-devtools-frontend 1.0.1009515 → 1.0.1009983
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/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/sdk/CSSProperty.ts +3 -3
- package/front_end/core/sdk/Script.ts +3 -2
- package/front_end/models/bindings/BreakpointManager.ts +57 -21
- package/front_end/models/bindings/ResourceScriptMapping.ts +1 -1
- package/front_end/models/extensions/ExtensionAPI.ts +11 -2
- package/front_end/models/extensions/RecorderExtensionEndpoint.ts +11 -0
- package/front_end/models/persistence/Automapping.ts +18 -12
- package/front_end/models/persistence/PersistenceImpl.ts +10 -2
- package/front_end/models/workspace/WorkspaceImpl.ts +16 -9
- package/front_end/panels/application/DOMStorageItemsView.ts +6 -0
- package/front_end/ui/components/data_grid/DataGrid.ts +5 -0
- package/front_end/ui/components/data_grid/DataGridController.ts +5 -0
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -1
- package/package.json +1 -1
@@ -3293,6 +3293,9 @@
|
|
3293
3293
|
"panels/application/DOMStorageItemsView.ts | domStorageItems": {
|
3294
3294
|
"message": "DOM Storage Items"
|
3295
3295
|
},
|
3296
|
+
"panels/application/DOMStorageItemsView.ts | domStorageItemsCleared": {
|
3297
|
+
"message": "{PH1} cleared"
|
3298
|
+
},
|
3296
3299
|
"panels/application/DOMStorageItemsView.ts | domStorageNumberEntries": {
|
3297
3300
|
"message": "Number of entries shown in table: {PH1}"
|
3298
3301
|
},
|
@@ -3293,6 +3293,9 @@
|
|
3293
3293
|
"panels/application/DOMStorageItemsView.ts | domStorageItems": {
|
3294
3294
|
"message": "D̂ÓM̂ Śt̂ór̂áĝé Ît́êḿŝ"
|
3295
3295
|
},
|
3296
|
+
"panels/application/DOMStorageItemsView.ts | domStorageItemsCleared": {
|
3297
|
+
"message": "{PH1} ĉĺêár̂éd̂"
|
3298
|
+
},
|
3296
3299
|
"panels/application/DOMStorageItemsView.ts | domStorageNumberEntries": {
|
3297
3300
|
"message": "N̂úm̂b́êŕ ôf́ êńt̂ŕîéŝ śĥóŵń îń t̂áb̂ĺê: {PH1}"
|
3298
3301
|
},
|
@@ -188,7 +188,7 @@ export class CSSProperty {
|
|
188
188
|
if (insideProperty) {
|
189
189
|
result += propertyText;
|
190
190
|
}
|
191
|
-
result = result.substring(2, result.length - 1).
|
191
|
+
result = result.substring(2, result.length - 1).trimEnd();
|
192
192
|
return result + (indentation ? '\n' + endIndentation : '');
|
193
193
|
|
194
194
|
function processToken(token: string, tokenType: string|null): void {
|
@@ -230,8 +230,8 @@ export class CSSProperty {
|
|
230
230
|
}
|
231
231
|
if (cssMetadata().isGridAreaDefiningProperty(propertyName)) {
|
232
232
|
const rowResult = GridAreaRowRegex.exec(token);
|
233
|
-
if (rowResult && rowResult.index === 0 && !propertyText.
|
234
|
-
propertyText = propertyText.
|
233
|
+
if (rowResult && rowResult.index === 0 && !propertyText.trimEnd().endsWith(']')) {
|
234
|
+
propertyText = propertyText.trimEnd() + '\n' + doubleIndent;
|
235
235
|
}
|
236
236
|
}
|
237
237
|
if (!propertyName && token === ':') {
|
@@ -192,7 +192,6 @@ export class Script implements TextUtils.ContentProvider.ContentProvider, FrameA
|
|
192
192
|
|
193
193
|
originalContentProvider(): TextUtils.ContentProvider.ContentProvider {
|
194
194
|
if (!this.#originalContentProviderInternal) {
|
195
|
-
/* } */
|
196
195
|
let lazyContentPromise: Promise<TextUtils.ContentProvider.DeferredContent>|null;
|
197
196
|
this.#originalContentProviderInternal =
|
198
197
|
new TextUtils.StaticContentProvider.StaticContentProvider(this.contentURL(), this.contentType(), () => {
|
@@ -220,7 +219,9 @@ export class Script implements TextUtils.ContentProvider.ContentProvider, FrameA
|
|
220
219
|
return {content: bytecode, isEncoded: true};
|
221
220
|
}
|
222
221
|
let content: string = scriptSource || '';
|
223
|
-
if (this.hasSourceURL) {
|
222
|
+
if (this.hasSourceURL && this.sourceURL.startsWith('snippet://')) {
|
223
|
+
// TODO(crbug.com/1330846): Find a better way to establish the snippet automapping binding then adding
|
224
|
+
// a sourceURL comment before evaluation and removing it here.
|
224
225
|
content = Script.trimSourceURLComment(content);
|
225
226
|
}
|
226
227
|
return {content, isEncoded: false};
|
@@ -51,6 +51,7 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
|
|
51
51
|
readonly debuggerWorkspaceBinding: DebuggerWorkspaceBinding;
|
52
52
|
readonly #breakpointsForUISourceCode: Map<Workspace.UISourceCode.UISourceCode, Map<string, BreakpointLocation>>;
|
53
53
|
readonly #breakpointByStorageId: Map<string, Breakpoint>;
|
54
|
+
#updateBindingsCallbacks: ((uiSourceCode: Workspace.UISourceCode.UISourceCode) => Promise<void>)[];
|
54
55
|
|
55
56
|
private constructor(
|
56
57
|
targetManager: SDK.TargetManager.TargetManager, workspace: Workspace.Workspace.WorkspaceImpl,
|
@@ -69,6 +70,7 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
|
|
69
70
|
this.#workspace.addEventListener(Workspace.Workspace.Events.ProjectRemoved, this.projectRemoved, this);
|
70
71
|
|
71
72
|
this.targetManager.observeModels(SDK.DebuggerModel.DebuggerModel, this);
|
73
|
+
this.#updateBindingsCallbacks = [];
|
72
74
|
}
|
73
75
|
|
74
76
|
static instance(opts: {
|
@@ -108,6 +110,10 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
|
|
108
110
|
debuggerModel.setSynchronizeBreakpointsCallback(null);
|
109
111
|
}
|
110
112
|
|
113
|
+
addUpdateBindingsCallback(callback: ((uiSourceCode: Workspace.UISourceCode.UISourceCode) => Promise<void>)): void {
|
114
|
+
this.#updateBindingsCallbacks.push(callback);
|
115
|
+
}
|
116
|
+
|
111
117
|
async copyBreakpoints(fromURL: Platform.DevToolsPath.UrlString, toSourceCode: Workspace.UISourceCode.UISourceCode):
|
112
118
|
Promise<void> {
|
113
119
|
const breakpointItems = this.storage.breakpointItems(fromURL);
|
@@ -122,15 +128,13 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
|
|
122
128
|
if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS)) {
|
123
129
|
return;
|
124
130
|
}
|
131
|
+
if (!script.sourceURL) {
|
132
|
+
return;
|
133
|
+
}
|
134
|
+
|
125
135
|
const debuggerModel = script.debuggerModel;
|
136
|
+
const uiSourceCode = await this.getUpdatedUISourceCode(script);
|
126
137
|
if (this.#hasBreakpointsForUrl(script.sourceURL)) {
|
127
|
-
// Handle inline scripts without sourceURL comment separately:
|
128
|
-
// The UISourceCode of inline scripts without sourceURLs will not be availabe
|
129
|
-
// until a later point. Use the v8 script for setting the breakpoint.
|
130
|
-
const isInlineScriptWithoutSourceURL = script.isInlineScript() && !script.hasSourceURL;
|
131
|
-
const sourceURL =
|
132
|
-
isInlineScriptWithoutSourceURL ? DefaultScriptMapping.createV8ScriptURL(script) : script.sourceURL;
|
133
|
-
const uiSourceCode = await Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURLPromise(sourceURL);
|
134
138
|
await this.#restoreBreakpointsForUrl(uiSourceCode);
|
135
139
|
}
|
136
140
|
|
@@ -161,6 +165,34 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
|
|
161
165
|
}
|
162
166
|
}
|
163
167
|
|
168
|
+
async getUpdatedUISourceCode(script: SDK.Script.Script): Promise<Workspace.UISourceCode.UISourceCode> {
|
169
|
+
const isSnippet = script.sourceURL.startsWith('snippet://');
|
170
|
+
const projectType = isSnippet ? Workspace.Workspace.projectTypes.Network : undefined;
|
171
|
+
|
172
|
+
// Handle inline scripts without sourceURL comment separately:
|
173
|
+
// The UISourceCode of inline scripts without sourceURLs will not be availabe
|
174
|
+
// until a later point. Use the v8 script for setting the breakpoint.
|
175
|
+
const isInlineScriptWithoutSourceURL = script.isInlineScript() && !script.hasSourceURL;
|
176
|
+
const sourceURL =
|
177
|
+
isInlineScriptWithoutSourceURL ? DefaultScriptMapping.createV8ScriptURL(script) : script.sourceURL;
|
178
|
+
const uiSourceCode =
|
179
|
+
await Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURLPromise(sourceURL, projectType);
|
180
|
+
|
181
|
+
if (this.#updateBindingsCallbacks.length > 0) {
|
182
|
+
// It's possible to set breakpoints on files on the file system, and to have them
|
183
|
+
// hit whenever we navigate to a page that serves that file.
|
184
|
+
// To make sure that we have all breakpoint information moved from the file system
|
185
|
+
// to the served file, we need to update the bindings and await it. This will
|
186
|
+
// move the breakpoints from the FileSystem UISourceCode to the Network UiSourceCode.
|
187
|
+
const promises = [];
|
188
|
+
for (const callback of this.#updateBindingsCallbacks) {
|
189
|
+
promises.push(callback(uiSourceCode));
|
190
|
+
}
|
191
|
+
await Promise.all(promises);
|
192
|
+
}
|
193
|
+
return uiSourceCode;
|
194
|
+
}
|
195
|
+
|
164
196
|
async #restoreBreakpointsForUrl(uiSourceCode: Workspace.UISourceCode.UISourceCode): Promise<void> {
|
165
197
|
this.restoreBreakpoints(uiSourceCode);
|
166
198
|
const breakpoints = this.#breakpointByStorageId.values();
|
@@ -713,20 +745,24 @@ export class ModelBreakpoint {
|
|
713
745
|
};
|
714
746
|
});
|
715
747
|
newState = new Breakpoint.State(positions, condition);
|
716
|
-
} else if (
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
748
|
+
} else if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS)) {
|
749
|
+
// Use this fallback if we do not have instrumentation breakpoints enabled yet. This currently makes
|
750
|
+
// sure that v8 knows about the breakpoint and is able to restore it whenever the script is parsed.
|
751
|
+
if (this.#breakpoint.currentState) {
|
752
|
+
newState = new Breakpoint.State(this.#breakpoint.currentState.positions, condition);
|
753
|
+
} else {
|
754
|
+
// TODO(bmeurer): This fallback doesn't make a whole lot of sense, we should
|
755
|
+
// at least signal a warning to the developer that this #breakpoint wasn't
|
756
|
+
// really resolved.
|
757
|
+
const position = {
|
758
|
+
url: this.#breakpoint.url(),
|
759
|
+
scriptId: '' as Protocol.Runtime.ScriptId,
|
760
|
+
scriptHash: '',
|
761
|
+
lineNumber,
|
762
|
+
columnNumber,
|
763
|
+
};
|
764
|
+
newState = new Breakpoint.State([position], condition);
|
765
|
+
}
|
730
766
|
}
|
731
767
|
}
|
732
768
|
|
@@ -298,7 +298,7 @@ export class ResourceScriptFile extends Common.ObjectWrapper.ObjectWrapper<Resou
|
|
298
298
|
}
|
299
299
|
|
300
300
|
// Match ignoring sourceURL.
|
301
|
-
if (!workingCopy.startsWith(this.#scriptSource.
|
301
|
+
if (!workingCopy.startsWith(this.#scriptSource.trimEnd())) {
|
302
302
|
return true;
|
303
303
|
}
|
304
304
|
const suffix = this.#uiSourceCodeInternal.workingCopy().substr(this.#scriptSource.length);
|
@@ -111,6 +111,7 @@ export namespace PrivateAPI {
|
|
111
111
|
|
112
112
|
export const enum RecorderExtensionPluginCommands {
|
113
113
|
Stringify = 'stringify',
|
114
|
+
StringifyStep = 'stringifyStep',
|
114
115
|
}
|
115
116
|
|
116
117
|
export const enum RecorderExtensionPluginEvents {
|
@@ -277,7 +278,12 @@ export namespace PrivateAPI {
|
|
277
278
|
parameters: {recording: Record<string, unknown>},
|
278
279
|
};
|
279
280
|
|
280
|
-
|
281
|
+
type StringifyStepRequest = {
|
282
|
+
method: RecorderExtensionPluginCommands.StringifyStep,
|
283
|
+
parameters: {step: Record<string, unknown>},
|
284
|
+
};
|
285
|
+
|
286
|
+
export type RecorderExtensionRequests = StringifyRequest|StringifyStepRequest;
|
281
287
|
}
|
282
288
|
|
283
289
|
declare global {
|
@@ -721,11 +727,14 @@ self.injectedExtensionAPI = function(
|
|
721
727
|
.catch(error => port.postMessage({requestId, error: {message: error.message}}));
|
722
728
|
};
|
723
729
|
|
724
|
-
function dispatchMethodCall(request: PrivateAPI.RecorderExtensionRequests): Promise<unknown> {
|
730
|
+
async function dispatchMethodCall(request: PrivateAPI.RecorderExtensionRequests): Promise<unknown> {
|
725
731
|
switch (request.method) {
|
726
732
|
case PrivateAPI.RecorderExtensionPluginCommands.Stringify:
|
727
733
|
return plugin.stringify(request.parameters.recording);
|
734
|
+
case PrivateAPI.RecorderExtensionPluginCommands.StringifyStep:
|
735
|
+
return plugin.stringifyStep(request.parameters.step);
|
728
736
|
default:
|
737
|
+
// @ts-expect-error
|
729
738
|
throw new Error(`'${request.method}' is not recognized`);
|
730
739
|
}
|
731
740
|
}
|
@@ -46,4 +46,15 @@ export class RecorderExtensionEndpoint extends ExtensionEndpoint {
|
|
46
46
|
stringify(recording: Object): Promise<string> {
|
47
47
|
return this.sendRequest(PrivateAPI.RecorderExtensionPluginCommands.Stringify, {recording});
|
48
48
|
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* In practice, `step` is a Step[1], but we avoid defining this type on the
|
52
|
+
* API in order to prevent dependencies between Chrome and puppeteer. Extensions
|
53
|
+
* are responsible for working out compatibility issues.
|
54
|
+
*
|
55
|
+
* [1]: https://github.com/puppeteer/replay/blob/main/src/Schema.ts#L243
|
56
|
+
*/
|
57
|
+
stringifyStep(step: Object): Promise<string> {
|
58
|
+
return this.sendRequest(PrivateAPI.RecorderExtensionPluginCommands.StringifyStep, {step});
|
59
|
+
}
|
49
60
|
}
|
@@ -88,7 +88,7 @@ export class Automapping {
|
|
88
88
|
const networkProjects = this.workspace.projectsForType(Workspace.Workspace.projectTypes.Network);
|
89
89
|
for (const networkProject of networkProjects) {
|
90
90
|
for (const uiSourceCode of networkProject.uiSourceCodes()) {
|
91
|
-
this.computeNetworkStatus(uiSourceCode);
|
91
|
+
void this.computeNetworkStatus(uiSourceCode);
|
92
92
|
}
|
93
93
|
}
|
94
94
|
this.onSweepHappenedForTest();
|
@@ -137,7 +137,7 @@ export class Automapping {
|
|
137
137
|
this.fileSystemUISourceCodes.add(uiSourceCode);
|
138
138
|
this.scheduleSweep();
|
139
139
|
} else if (project.type() === Workspace.Workspace.projectTypes.Network) {
|
140
|
-
this.computeNetworkStatus(uiSourceCode);
|
140
|
+
void this.computeNetworkStatus(uiSourceCode);
|
141
141
|
}
|
142
142
|
}
|
143
143
|
|
@@ -173,20 +173,24 @@ export class Automapping {
|
|
173
173
|
this.scheduleSweep();
|
174
174
|
}
|
175
175
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
return;
|
176
|
+
computeNetworkStatus(networkSourceCode: Workspace.UISourceCode.UISourceCode): Promise<void> {
|
177
|
+
const processingPromise = this.sourceCodeToProcessingPromiseMap.get(networkSourceCode);
|
178
|
+
if (processingPromise) {
|
179
|
+
return processingPromise;
|
180
|
+
}
|
181
|
+
if (this.sourceCodeToAutoMappingStatusMap.has(networkSourceCode)) {
|
182
|
+
return Promise.resolve();
|
180
183
|
}
|
181
184
|
if (this.interceptors.some(interceptor => interceptor(networkSourceCode))) {
|
182
|
-
return;
|
185
|
+
return Promise.resolve();
|
183
186
|
}
|
184
187
|
if (networkSourceCode.url().startsWith('wasm://')) {
|
185
|
-
return;
|
188
|
+
return Promise.resolve();
|
186
189
|
}
|
187
190
|
const createBindingPromise =
|
188
191
|
this.createBinding(networkSourceCode).then(validateStatus.bind(this)).then(onStatus.bind(this));
|
189
192
|
this.sourceCodeToProcessingPromiseMap.set(networkSourceCode, createBindingPromise);
|
193
|
+
return createBindingPromise;
|
190
194
|
|
191
195
|
async function validateStatus(this: Automapping, status: AutomappingStatus|null): Promise<AutomappingStatus|null> {
|
192
196
|
if (!status) {
|
@@ -242,7 +246,7 @@ export class Automapping {
|
|
242
246
|
} else {
|
243
247
|
if (networkContent.content) {
|
244
248
|
// Trim trailing whitespaces because V8 adds trailing newline.
|
245
|
-
isValid = fileContent.
|
249
|
+
isValid = fileContent.trimEnd() === networkContent.content.trimEnd();
|
246
250
|
}
|
247
251
|
}
|
248
252
|
if (!isValid) {
|
@@ -252,18 +256,19 @@ export class Automapping {
|
|
252
256
|
return status;
|
253
257
|
}
|
254
258
|
|
255
|
-
function onStatus(this: Automapping, status: AutomappingStatus|null): void {
|
259
|
+
async function onStatus(this: Automapping, status: AutomappingStatus|null): Promise<void> {
|
256
260
|
if (this.sourceCodeToProcessingPromiseMap.get(networkSourceCode) !== createBindingPromise) {
|
257
261
|
return;
|
258
262
|
}
|
259
|
-
this.sourceCodeToProcessingPromiseMap.delete(networkSourceCode);
|
260
263
|
if (!status) {
|
261
264
|
this.onBindingFailedForTest();
|
265
|
+
this.sourceCodeToProcessingPromiseMap.delete(networkSourceCode);
|
262
266
|
return;
|
263
267
|
}
|
264
268
|
// TODO(lushnikov): remove this check once there's a single uiSourceCode per url. @see crbug.com/670180
|
265
269
|
if (this.sourceCodeToAutoMappingStatusMap.has(status.network) ||
|
266
270
|
this.sourceCodeToAutoMappingStatusMap.has(status.fileSystem)) {
|
271
|
+
this.sourceCodeToProcessingPromiseMap.delete(networkSourceCode);
|
267
272
|
return;
|
268
273
|
}
|
269
274
|
|
@@ -277,7 +282,8 @@ export class Automapping {
|
|
277
282
|
this.scheduleSweep();
|
278
283
|
}
|
279
284
|
}
|
280
|
-
|
285
|
+
await this.onStatusAdded.call(null, status);
|
286
|
+
this.sourceCodeToProcessingPromiseMap.delete(networkSourceCode);
|
281
287
|
}
|
282
288
|
}
|
283
289
|
|
@@ -29,6 +29,7 @@ export class PersistenceImpl extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
29
29
|
super();
|
30
30
|
this.workspace = workspace;
|
31
31
|
this.breakpointManager = breakpointManager;
|
32
|
+
this.breakpointManager.addUpdateBindingsCallback(this.#setupBindings.bind(this));
|
32
33
|
this.filePathPrefixesToBindingCount = new FilePathPrefixesBindingCounts();
|
33
34
|
|
34
35
|
this.subscribedBindingEventListeners = new Platform.MapUtilities.Multimap();
|
@@ -79,6 +80,13 @@ export class PersistenceImpl extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
79
80
|
await this.innerRemoveBinding(binding);
|
80
81
|
}
|
81
82
|
|
83
|
+
#setupBindings(networkUISourceCode: Workspace.UISourceCode.UISourceCode): Promise<void> {
|
84
|
+
if (networkUISourceCode.project().type() !== Workspace.Workspace.projectTypes.Network) {
|
85
|
+
return Promise.resolve();
|
86
|
+
}
|
87
|
+
return this.mapping.computeNetworkStatus(networkUISourceCode);
|
88
|
+
}
|
89
|
+
|
82
90
|
private async innerAddBinding(binding: PersistenceBinding): Promise<void> {
|
83
91
|
bindings.set(binding.network, binding);
|
84
92
|
bindings.set(binding.fileSystem, binding);
|
@@ -140,10 +148,10 @@ export class PersistenceImpl extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
140
148
|
this.dispatchEventToListeners(Events.BindingRemoved, binding);
|
141
149
|
}
|
142
150
|
|
143
|
-
private
|
151
|
+
private onStatusAdded(status: AutomappingStatus): Promise<void> {
|
144
152
|
const binding = new PersistenceBinding(status.network, status.fileSystem);
|
145
153
|
statusBindings.set(status, binding);
|
146
|
-
|
154
|
+
return this.innerAddBinding(binding);
|
147
155
|
}
|
148
156
|
|
149
157
|
private async onStatusRemoved(status: AutomappingStatus): Promise<void> {
|
@@ -261,8 +261,8 @@ export class WorkspaceImpl extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
261
261
|
|
262
262
|
// This method explicitly awaits the UISourceCode if not yet
|
263
263
|
// available.
|
264
|
-
uiSourceCodeForURLPromise(url: Platform.DevToolsPath.UrlString): Promise<UISourceCode> {
|
265
|
-
const uiSourceCode = this.uiSourceCodeForURL(url);
|
264
|
+
uiSourceCodeForURLPromise(url: Platform.DevToolsPath.UrlString, type?: projectTypes): Promise<UISourceCode> {
|
265
|
+
const uiSourceCode = this.uiSourceCodeForURL(url, type);
|
266
266
|
if (uiSourceCode) {
|
267
267
|
return Promise.resolve(uiSourceCode);
|
268
268
|
}
|
@@ -270,24 +270,31 @@ export class WorkspaceImpl extends Common.ObjectWrapper.ObjectWrapper<EventTypes
|
|
270
270
|
const descriptor = this.addEventListener(Events.UISourceCodeAdded, event => {
|
271
271
|
const uiSourceCode = event.data;
|
272
272
|
if (uiSourceCode.url() === url) {
|
273
|
-
|
274
|
-
|
273
|
+
if (!type || type === uiSourceCode.project().type()) {
|
274
|
+
this.removeEventListener(Events.UISourceCodeAdded, descriptor.listener);
|
275
|
+
resolve(uiSourceCode);
|
276
|
+
}
|
275
277
|
}
|
276
278
|
});
|
277
279
|
});
|
278
280
|
}
|
279
281
|
|
280
|
-
uiSourceCodeForURL(url: Platform.DevToolsPath.UrlString): UISourceCode|null {
|
282
|
+
uiSourceCodeForURL(url: Platform.DevToolsPath.UrlString, type?: projectTypes): UISourceCode|null {
|
281
283
|
for (const project of this.projectsInternal.values()) {
|
282
|
-
|
283
|
-
|
284
|
-
|
284
|
+
// For snippets, we may get two different UISourceCodes for the same url (one belonging to
|
285
|
+
// the file system project, one belonging to the network project). Allow selecting the UISourceCode
|
286
|
+
// for a specific project type.
|
287
|
+
if (!type || project.type() === type) {
|
288
|
+
const uiSourceCode = project.uiSourceCodeForURL(url);
|
289
|
+
if (uiSourceCode) {
|
290
|
+
return uiSourceCode;
|
291
|
+
}
|
285
292
|
}
|
286
293
|
}
|
287
294
|
return null;
|
288
295
|
}
|
289
296
|
|
290
|
-
uiSourceCodesForProjectType(type:
|
297
|
+
uiSourceCodesForProjectType(type: projectTypes): UISourceCode[] {
|
291
298
|
const result: UISourceCode[] = [];
|
292
299
|
for (const project of this.projectsInternal.values()) {
|
293
300
|
if (project.type() === type) {
|
@@ -56,6 +56,11 @@ const UIStrings = {
|
|
56
56
|
*@description Data grid name for DOM Storage Items data grids
|
57
57
|
*/
|
58
58
|
domStorageItems: 'DOM Storage Items',
|
59
|
+
/**
|
60
|
+
*@description Text for announcing number of entries after filtering
|
61
|
+
*@example {'DOM Storage Items'} PH1
|
62
|
+
*/
|
63
|
+
domStorageItemsCleared: '{PH1} cleared',
|
59
64
|
/**
|
60
65
|
*@description Text in DOMStorage Items View of the Application panel
|
61
66
|
*/
|
@@ -149,6 +154,7 @@ export class DOMStorageItemsView extends StorageItemsView {
|
|
149
154
|
|
150
155
|
this.dataGrid.rootNode().removeChildren();
|
151
156
|
this.dataGrid.addCreationNode(false);
|
157
|
+
UI.ARIAUtils.alert(i18nString(UIStrings.domStorageItemsCleared, {PH1: this.dataGrid.displayName}));
|
152
158
|
this.setCanDeleteSelected(false);
|
153
159
|
}
|
154
160
|
|
@@ -53,6 +53,7 @@ export interface DataGridData {
|
|
53
53
|
rows: Row[];
|
54
54
|
activeSort: SortState|null;
|
55
55
|
contextMenus?: DataGridContextMenusConfiguration;
|
56
|
+
label?: string;
|
56
57
|
}
|
57
58
|
|
58
59
|
const enum UserScrollState {
|
@@ -76,6 +77,7 @@ export class DataGrid extends HTMLElement {
|
|
76
77
|
#isRendering = false;
|
77
78
|
#userScrollState: UserScrollState = UserScrollState.NOT_SCROLLED;
|
78
79
|
#contextMenus?: DataGridContextMenusConfiguration = undefined;
|
80
|
+
#label?: string = undefined;
|
79
81
|
#currentResize: {
|
80
82
|
rightCellCol: HTMLTableColElement,
|
81
83
|
leftCellCol: HTMLTableColElement,
|
@@ -132,6 +134,7 @@ export class DataGrid extends HTMLElement {
|
|
132
134
|
rows: this.#rows as Row[],
|
133
135
|
activeSort: this.#sortState,
|
134
136
|
contextMenus: this.#contextMenus,
|
137
|
+
label: this.#label,
|
135
138
|
};
|
136
139
|
}
|
137
140
|
|
@@ -143,6 +146,7 @@ export class DataGrid extends HTMLElement {
|
|
143
146
|
});
|
144
147
|
this.#sortState = data.activeSort;
|
145
148
|
this.#contextMenus = data.contextMenus;
|
149
|
+
this.#label = data.label;
|
146
150
|
|
147
151
|
/**
|
148
152
|
* On first render, now we have data, we can figure out which cell is the
|
@@ -711,6 +715,7 @@ export class DataGrid extends HTMLElement {
|
|
711
715
|
})}
|
712
716
|
<div class="wrapping-container" @scroll=${this.#onScroll} @focusout=${this.#onFocusOut}>
|
713
717
|
<table
|
718
|
+
aria-label=${LitHtml.Directives.ifDefined(this.#label)}
|
714
719
|
aria-rowcount=${this.#rows.length}
|
715
720
|
aria-colcount=${this.#columns.length}
|
716
721
|
@keydown=${this.#onTableKeyDown}
|
@@ -23,6 +23,7 @@ export interface DataGridControllerData {
|
|
23
23
|
*/
|
24
24
|
initialSort?: SortState;
|
25
25
|
contextMenus?: DataGridContextMenusConfiguration;
|
26
|
+
label?: string;
|
26
27
|
}
|
27
28
|
|
28
29
|
export class DataGridController extends HTMLElement {
|
@@ -33,6 +34,7 @@ export class DataGridController extends HTMLElement {
|
|
33
34
|
#columns: readonly Column[] = [];
|
34
35
|
#rows: Row[] = [];
|
35
36
|
#contextMenus?: DataGridContextMenusConfiguration = undefined;
|
37
|
+
#label?: string = undefined;
|
36
38
|
|
37
39
|
/**
|
38
40
|
* Because the controller will sort data in place (e.g. mutate it) when we get
|
@@ -56,6 +58,7 @@ export class DataGridController extends HTMLElement {
|
|
56
58
|
rows: this.#originalRows as Row[],
|
57
59
|
filters: this.#filters,
|
58
60
|
contextMenus: this.#contextMenus,
|
61
|
+
label: this.#label,
|
59
62
|
};
|
60
63
|
}
|
61
64
|
|
@@ -65,6 +68,7 @@ export class DataGridController extends HTMLElement {
|
|
65
68
|
this.#contextMenus = data.contextMenus;
|
66
69
|
this.#filters = data.filters || [];
|
67
70
|
this.#contextMenus = data.contextMenus;
|
71
|
+
this.#label = data.label;
|
68
72
|
|
69
73
|
this.#columns = [...this.#originalColumns];
|
70
74
|
this.#rows = this.#cloneAndFilterRows(data.rows, this.#filters);
|
@@ -210,6 +214,7 @@ export class DataGridController extends HTMLElement {
|
|
210
214
|
rows: this.#rows,
|
211
215
|
activeSort: this.#sortState,
|
212
216
|
contextMenus: this.#contextMenus,
|
217
|
+
label: this.#label,
|
213
218
|
} as DataGridData}
|
214
219
|
@columnheaderclick=${this.#onColumnHeaderClick}
|
215
220
|
@contextmenucolumnsortclick=${this.#onContextMenuColumnSortClick}
|
@@ -122,7 +122,7 @@ const elementToIndexMap = new WeakMap<Element, number>();
|
|
122
122
|
|
123
123
|
export class DataGridImpl<T> extends Common.ObjectWrapper.ObjectWrapper<EventTypes<T>> {
|
124
124
|
element: HTMLDivElement;
|
125
|
-
|
125
|
+
displayName: string;
|
126
126
|
private editCallback: ((arg0: any, arg1: string, arg2: any, arg3: any) => void)|undefined;
|
127
127
|
private readonly deleteCallback: ((arg0: any) => void)|undefined;
|
128
128
|
private readonly refreshCallback: (() => void)|undefined;
|
package/package.json
CHANGED