chrome-devtools-frontend 1.0.1009515 → 1.0.1010780

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 (33) hide show
  1. package/extension-api/ExtensionAPI.d.ts +5 -5
  2. package/front_end/core/host/UserMetrics.ts +3 -1
  3. package/front_end/core/i18n/locales/en-US.json +16 -7
  4. package/front_end/core/i18n/locales/en-XL.json +16 -7
  5. package/front_end/core/sdk/CSSProperty.ts +3 -3
  6. package/front_end/core/sdk/DebuggerModel.ts +12 -3
  7. package/front_end/core/sdk/EmulationModel.ts +9 -3
  8. package/front_end/core/sdk/Script.ts +3 -2
  9. package/front_end/generated/InspectorBackendCommands.js +3 -6
  10. package/front_end/generated/SupportedCSSProperties.js +2 -2
  11. package/front_end/generated/protocol.ts +24 -7
  12. package/front_end/models/bindings/BreakpointManager.ts +58 -22
  13. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +72 -65
  14. package/front_end/models/bindings/ResourceScriptMapping.ts +13 -1
  15. package/front_end/models/extensions/ExtensionAPI.ts +14 -5
  16. package/front_end/models/extensions/ExtensionServer.ts +2 -2
  17. package/front_end/models/extensions/RecorderExtensionEndpoint.ts +16 -5
  18. package/front_end/models/issues_manager/DeprecationIssue.ts +1 -10
  19. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -4
  20. package/front_end/models/persistence/Automapping.ts +18 -12
  21. package/front_end/models/persistence/PersistenceImpl.ts +10 -2
  22. package/front_end/models/workspace/WorkspaceImpl.ts +16 -9
  23. package/front_end/panels/application/DOMStorageItemsView.ts +6 -0
  24. package/front_end/panels/console/ConsoleViewMessage.ts +2 -1
  25. package/front_end/panels/sources/CallStackSidebarPane.ts +11 -4
  26. package/front_end/panels/sources/DebuggerPlugin.ts +51 -1
  27. package/front_end/ui/components/data_grid/DataGrid.ts +5 -0
  28. package/front_end/ui/components/data_grid/DataGridController.ts +5 -0
  29. package/front_end/ui/legacy/Infobar.ts +1 -0
  30. package/front_end/ui/legacy/ViewManager.ts +2 -2
  31. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -1
  32. package/front_end/ui/legacy/infobar.css +17 -0
  33. package/package.json +1 -1
@@ -59,12 +59,12 @@ const UIStrings = {
59
59
  *@description Error message that is displayed in UI debugging information cannot be found for a call frame
60
60
  *@example {main} PH1
61
61
  */
62
- failedToLoadDebugSymbolsForFunction: 'Missing debug symbols for function "{PH1}"',
62
+ failedToLoadDebugSymbolsForFunction: 'No debug information for function "{PH1}"',
63
63
  /**
64
64
  *@description Error message that is displayed in UI when a file needed for debugging information for a call frame is missing
65
- *@example {src/myapp.debug.wasm.dwp} PH1
65
+ *@example {mainp.debug.wasm.dwp} PH1
66
66
  */
67
- symbolFileNotFound: 'Symbol file "{PH1}" not found',
67
+ debugSymbolsIncomplete: 'The debug information for function {PH1} is incomplete',
68
68
  };
69
69
  const str_ = i18n.i18n.registerUIStrings('models/bindings/DebuggerLanguagePlugins.ts', UIStrings);
70
70
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -766,7 +766,7 @@ export class DebuggerLanguagePluginManager implements
766
766
  rawModuleId: string,
767
767
  plugin: DebuggerLanguagePlugin,
768
768
  scripts: Array<SDK.Script.Script>,
769
- addRawModulePromise: Promise<Array<Platform.DevToolsPath.UrlString>>,
769
+ addRawModulePromise: Promise<Array<Platform.DevToolsPath.UrlString>|{missingSymbolFiles: string[]}>,
770
770
  }>;
771
771
 
772
772
  constructor(
@@ -819,17 +819,19 @@ export class DebuggerLanguagePluginManager implements
819
819
  .all(callFrames.map(async callFrame => {
820
820
  const functionInfo = await this.getFunctionInfo(callFrame.script, callFrame.location());
821
821
  if (functionInfo) {
822
- const {frames, missingSymbolFiles} = functionInfo;
823
- if (frames.length) {
824
- return frames.map(({name}, index) => callFrame.createVirtualCallFrame(index, name));
822
+ if ('frames' in functionInfo && functionInfo.frames.length) {
823
+ return functionInfo.frames.map(({name}, index) => callFrame.createVirtualCallFrame(index, name));
825
824
  }
826
- if (missingSymbolFiles && missingSymbolFiles.length) {
827
- for (const file of missingSymbolFiles) {
828
- callFrame.addWarning(i18nString(UIStrings.symbolFileNotFound, {PH1: file}));
829
- }
825
+ if ('missingSymbolFiles' in functionInfo && functionInfo.missingSymbolFiles.length) {
826
+ const resources = functionInfo.missingSymbolFiles;
827
+ const details = i18nString(UIStrings.debugSymbolsIncomplete, {PH1: callFrame.functionName});
828
+ callFrame.setMissingDebugInfoDetails({details, resources});
829
+ } else {
830
+ callFrame.setMissingDebugInfoDetails({
831
+ resources: [],
832
+ details: i18nString(UIStrings.failedToLoadDebugSymbolsForFunction, {PH1: callFrame.functionName}),
833
+ });
830
834
  }
831
- callFrame.addWarning(
832
- i18nString(UIStrings.failedToLoadDebugSymbolsForFunction, {PH1: callFrame.functionName}));
833
835
  }
834
836
  return callFrame;
835
837
  }))
@@ -1069,40 +1071,45 @@ export class DebuggerLanguagePluginManager implements
1069
1071
  const rawModuleId = rawModuleIdForScript(script);
1070
1072
  let rawModuleHandle = this.#rawModuleHandles.get(rawModuleId);
1071
1073
  if (!rawModuleHandle) {
1072
- const sourceFileURLsPromise = (async(): Promise<Platform.DevToolsPath.UrlString[]> => {
1073
- const console = Common.Console.Console.instance();
1074
- const url = script.sourceURL;
1075
- const symbolsUrl = (script.debugSymbols && script.debugSymbols.externalURL) || '';
1076
- if (symbolsUrl) {
1077
- console.log(i18nString(UIStrings.loadingDebugSymbolsForVia, {PH1: plugin.name, PH2: url, PH3: symbolsUrl}));
1078
- } else {
1079
- console.log(i18nString(UIStrings.loadingDebugSymbolsFor, {PH1: plugin.name, PH2: url}));
1080
- }
1081
- try {
1082
- const code = (!symbolsUrl && url.startsWith('wasm://')) ? await script.getWasmBytecode() : undefined;
1083
- const sourceFileURLs =
1084
- await plugin.addRawModule(rawModuleId, symbolsUrl, {url, code}) as Platform.DevToolsPath.UrlString[];
1085
- // Check that the handle isn't stale by now. This works because the code that assigns to
1086
- // `rawModuleHandle` below will run before this code because of the `await` in the preceding
1087
- // line. This is primarily to avoid logging the message below, which would give the developer
1088
- // the misleading information that we're done, while in reality it was a stale call that finished.
1089
- if (rawModuleHandle !== this.#rawModuleHandles.get(rawModuleId)) {
1090
- return [];
1091
- }
1092
- if (sourceFileURLs.length === 0) {
1093
- console.warn(i18nString(UIStrings.loadedDebugSymbolsForButDidnt, {PH1: plugin.name, PH2: url}));
1094
- } else {
1095
- console.log(i18nString(
1096
- UIStrings.loadedDebugSymbolsForFound, {PH1: plugin.name, PH2: url, PH3: sourceFileURLs.length}));
1097
- }
1098
- return sourceFileURLs;
1099
- } catch (error) {
1100
- console.error(
1101
- i18nString(UIStrings.failedToLoadDebugSymbolsFor, {PH1: plugin.name, PH2: url, PH3: error.message}));
1102
- this.#rawModuleHandles.delete(rawModuleId);
1103
- return [];
1104
- }
1105
- })();
1074
+ const sourceFileURLsPromise =
1075
+ (async(): Promise<Platform.DevToolsPath.UrlString[]|{missingSymbolFiles: string[]}> => {
1076
+ const console = Common.Console.Console.instance();
1077
+ const url = script.sourceURL;
1078
+ const symbolsUrl = (script.debugSymbols && script.debugSymbols.externalURL) || '';
1079
+ if (symbolsUrl) {
1080
+ console.log(
1081
+ i18nString(UIStrings.loadingDebugSymbolsForVia, {PH1: plugin.name, PH2: url, PH3: symbolsUrl}));
1082
+ } else {
1083
+ console.log(i18nString(UIStrings.loadingDebugSymbolsFor, {PH1: plugin.name, PH2: url}));
1084
+ }
1085
+ try {
1086
+ const code = (!symbolsUrl && url.startsWith('wasm://')) ? await script.getWasmBytecode() : undefined;
1087
+ const addModuleResult = await plugin.addRawModule(rawModuleId, symbolsUrl, {url, code});
1088
+ // Check that the handle isn't stale by now. This works because the code that assigns to
1089
+ // `rawModuleHandle` below will run before this code because of the `await` in the preceding
1090
+ // line. This is primarily to avoid logging the message below, which would give the developer
1091
+ // the misleading information that we're done, while in reality it was a stale call that finished.
1092
+ if (rawModuleHandle !== this.#rawModuleHandles.get(rawModuleId)) {
1093
+ return [];
1094
+ }
1095
+ if ('missingSymbolFiles' in addModuleResult) {
1096
+ return {missingSymbolFiles: addModuleResult.missingSymbolFiles};
1097
+ }
1098
+ const sourceFileURLs = addModuleResult as Platform.DevToolsPath.UrlString[];
1099
+ if (sourceFileURLs.length === 0) {
1100
+ console.warn(i18nString(UIStrings.loadedDebugSymbolsForButDidnt, {PH1: plugin.name, PH2: url}));
1101
+ } else {
1102
+ console.log(i18nString(
1103
+ UIStrings.loadedDebugSymbolsForFound, {PH1: plugin.name, PH2: url, PH3: sourceFileURLs.length}));
1104
+ }
1105
+ return sourceFileURLs;
1106
+ } catch (error) {
1107
+ console.error(i18nString(
1108
+ UIStrings.failedToLoadDebugSymbolsFor, {PH1: plugin.name, PH2: url, PH3: error.message}));
1109
+ this.#rawModuleHandles.delete(rawModuleId);
1110
+ return [];
1111
+ }
1112
+ })();
1106
1113
  rawModuleHandle = {rawModuleId, plugin, scripts: [script], addRawModulePromise: sourceFileURLsPromise};
1107
1114
  this.#rawModuleHandles.set(rawModuleId, rawModuleHandle);
1108
1115
  } else {
@@ -1114,12 +1121,14 @@ export class DebuggerLanguagePluginManager implements
1114
1121
  // for the DebuggerModel again, which may disappear
1115
1122
  // in the meantime...
1116
1123
  void rawModuleHandle.addRawModulePromise.then(sourceFileURLs => {
1117
- // The script might have disappeared meanwhile...
1118
- if (script.debuggerModel.scriptForId(script.scriptId) === script) {
1119
- const modelData = this.#debuggerModelToData.get(script.debuggerModel);
1120
- if (modelData) { // The DebuggerModel could have disappeared meanwhile...
1121
- modelData.addSourceFiles(script, sourceFileURLs);
1122
- void this.#debuggerWorkspaceBinding.updateLocations(script);
1124
+ if (!('missingSymbolFiles' in sourceFileURLs)) {
1125
+ // The script might have disappeared meanwhile...
1126
+ if (script.debuggerModel.scriptForId(script.scriptId) === script) {
1127
+ const modelData = this.#debuggerModelToData.get(script.debuggerModel);
1128
+ if (modelData) { // The DebuggerModel could have disappeared meanwhile...
1129
+ modelData.addSourceFiles(script, sourceFileURLs);
1130
+ void this.#debuggerWorkspaceBinding.updateLocations(script);
1131
+ }
1123
1132
  }
1124
1133
  }
1125
1134
  });
@@ -1127,7 +1136,8 @@ export class DebuggerLanguagePluginManager implements
1127
1136
  }
1128
1137
  }
1129
1138
 
1130
- getSourcesForScript(script: SDK.Script.Script): Promise<Array<Platform.DevToolsPath.UrlString>|undefined> {
1139
+ getSourcesForScript(script: SDK.Script.Script):
1140
+ Promise<Array<Platform.DevToolsPath.UrlString>|{missingSymbolFiles: string[]}|undefined> {
1131
1141
  const rawModuleId = rawModuleIdForScript(script);
1132
1142
  const rawModuleHandle = this.#rawModuleHandles.get(rawModuleId);
1133
1143
  if (rawModuleHandle) {
@@ -1173,10 +1183,8 @@ export class DebuggerLanguagePluginManager implements
1173
1183
  }
1174
1184
  }
1175
1185
 
1176
- async getFunctionInfo(script: SDK.Script.Script, location: SDK.DebuggerModel.Location): Promise<{
1177
- frames: Array<Chrome.DevTools.FunctionInfo>,
1178
- missingSymbolFiles?: Array<string>,
1179
- }|null> {
1186
+ async getFunctionInfo(script: SDK.Script.Script, location: SDK.DebuggerModel.Location):
1187
+ Promise<{frames: Array<Chrome.DevTools.FunctionInfo>}|{missingSymbolFiles: string[]}|null> {
1180
1188
  const {rawModuleId, plugin} = await this.rawModuleIdAndPluginForScript(script);
1181
1189
  if (!plugin) {
1182
1190
  return null;
@@ -1189,7 +1197,8 @@ export class DebuggerLanguagePluginManager implements
1189
1197
  };
1190
1198
 
1191
1199
  try {
1192
- return await plugin.getFunctionInfo(rawLocation);
1200
+ const functionInfo = await plugin.getFunctionInfo(rawLocation);
1201
+ return functionInfo;
1193
1202
  } catch (error) {
1194
1203
  Common.Console.Console.instance().warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin, {PH1: error.message}));
1195
1204
  return {frames: []};
@@ -1362,7 +1371,7 @@ class ModelData {
1362
1371
  }
1363
1372
  }
1364
1373
 
1365
- export class DebuggerLanguagePlugin {
1374
+ export class DebuggerLanguagePlugin implements Chrome.DevTools.LanguageExtensionPlugin {
1366
1375
  name: string;
1367
1376
  constructor(name: string) {
1368
1377
  this.name = name;
@@ -1378,7 +1387,7 @@ export class DebuggerLanguagePlugin {
1378
1387
  /** Notify the #plugin about a new script
1379
1388
  */
1380
1389
  async addRawModule(_rawModuleId: string, _symbolsURL: string, _rawModule: Chrome.DevTools.RawModule):
1381
- Promise<string[]> {
1390
+ Promise<string[]|{missingSymbolFiles: string[]}> {
1382
1391
  throw new Error('Not implemented yet');
1383
1392
  }
1384
1393
 
@@ -1445,10 +1454,8 @@ export class DebuggerLanguagePlugin {
1445
1454
  /**
1446
1455
  * Find #locations in source files from a #location in a raw module
1447
1456
  */
1448
- async getFunctionInfo(_rawLocation: Chrome.DevTools.RawLocation): Promise<{
1449
- frames: Array<Chrome.DevTools.FunctionInfo>,
1450
- missingSymbolFiles?: Array<string>,
1451
- }> {
1457
+ async getFunctionInfo(_rawLocation: Chrome.DevTools.RawLocation):
1458
+ Promise<{frames: Array<Chrome.DevTools.FunctionInfo>}|{missingSymbolFiles: string[]}> {
1452
1459
  throw new Error('Not implemented yet');
1453
1460
  }
1454
1461
 
@@ -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.trimRight())) {
301
+ if (!workingCopy.startsWith(this.#scriptSource.trimEnd())) {
302
302
  return true;
303
303
  }
304
304
  const suffix = this.#uiSourceCodeInternal.workingCopy().substr(this.#scriptSource.length);
@@ -423,6 +423,18 @@ export class ResourceScriptFile extends Common.ObjectWrapper.ObjectWrapper<Resou
423
423
  return this.scriptInternal !== undefined && Boolean(this.scriptInternal.sourceMapURL);
424
424
  }
425
425
 
426
+ async missingSymbolFiles(): Promise<string[]|null> {
427
+ if (!this.scriptInternal) {
428
+ return null;
429
+ }
430
+ const {pluginManager} = this.#resourceScriptMapping.debuggerWorkspaceBinding;
431
+ if (!pluginManager) {
432
+ return null;
433
+ }
434
+ const sources = await pluginManager.getSourcesForScript(this.scriptInternal);
435
+ return sources && 'missingSymbolFiles' in sources ? sources.missingSymbolFiles : null;
436
+ }
437
+
426
438
  get script(): SDK.Script.Script|null {
427
439
  return this.scriptInternal || null;
428
440
  }
@@ -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 {
@@ -132,7 +133,7 @@ export namespace PrivateAPI {
132
133
  type RegisterRecorderExtensionPluginRequest = {
133
134
  command: Commands.RegisterRecorderExtensionPlugin,
134
135
  pluginName: string,
135
- mimeType: string,
136
+ mediaType: string,
136
137
  port: MessagePort,
137
138
  };
138
139
  type SubscribeRequest = {command: Commands.Subscribe, type: string};
@@ -277,7 +278,12 @@ export namespace PrivateAPI {
277
278
  parameters: {recording: Record<string, unknown>},
278
279
  };
279
280
 
280
- export type RecorderExtensionRequests = StringifyRequest;
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 {
@@ -707,7 +713,7 @@ self.injectedExtensionAPI = function(
707
713
  Pick<APIImpl.RecorderExtensions, 'registerRecorderExtensionPlugin'|'unregisterRecorderExtensionPlugin'>) = {
708
714
  registerRecorderExtensionPlugin: async function(
709
715
  this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, pluginName: string,
710
- mimeType: string): Promise<void> {
716
+ mediaType: string): Promise<void> {
711
717
  if (this._plugins.has(plugin)) {
712
718
  throw new Error(`Tried to register plugin '${pluginName}' twice`);
713
719
  }
@@ -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
  }
@@ -735,7 +744,7 @@ self.injectedExtensionAPI = function(
735
744
  {
736
745
  command: PrivateAPI.Commands.RegisterRecorderExtensionPlugin,
737
746
  pluginName,
738
- mimeType,
747
+ mediaType,
739
748
  port: channel.port2,
740
749
  },
741
750
  () => resolve(), [channel.port2]);
@@ -224,8 +224,8 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
224
224
  if (message.command !== PrivateAPI.Commands.RegisterRecorderExtensionPlugin) {
225
225
  return this.status.E_BADARG('command', `expected ${PrivateAPI.Commands.RegisterRecorderExtensionPlugin}`);
226
226
  }
227
- const {pluginName, mimeType, port} = message;
228
- RecorderPluginManager.instance().addPlugin(new RecorderExtensionEndpoint(pluginName, mimeType, port));
227
+ const {pluginName, mediaType, port} = message;
228
+ RecorderPluginManager.instance().addPlugin(new RecorderExtensionEndpoint(pluginName, mediaType, port));
229
229
  return this.status.OK();
230
230
  }
231
231
 
@@ -8,20 +8,20 @@ import {RecorderPluginManager} from './RecorderPluginManager.js';
8
8
 
9
9
  export class RecorderExtensionEndpoint extends ExtensionEndpoint {
10
10
  private readonly name: string;
11
- private readonly mimeType: string;
11
+ private readonly mediaType: string;
12
12
 
13
- constructor(name: string, mimeType: string, port: MessagePort) {
13
+ constructor(name: string, mediaType: string, port: MessagePort) {
14
14
  super(port);
15
15
  this.name = name;
16
- this.mimeType = mimeType;
16
+ this.mediaType = mediaType;
17
17
  }
18
18
 
19
19
  getName(): string {
20
20
  return this.name;
21
21
  }
22
22
 
23
- getMimeType(): string {
24
- return this.mimeType;
23
+ getMediaType(): string {
24
+ return this.mediaType;
25
25
  }
26
26
 
27
27
  protected handleEvent({event}: {event: string}): void {
@@ -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
  }
@@ -113,7 +113,7 @@ const UIStrings = {
113
113
  getUserMediaInsecureOrigin:
114
114
  '`getUserMedia()` no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gle/chrome-insecure-origins for more details.',
115
115
  /**
116
- * @description TODO(crbug.com/1320342): Description needed for translation
116
+ * @description A deprecation warning shown to developers in the DevTools Issues tab when code tries to use the deprecated hostCandidate field, guiding developers to use the the equivalent information in the .address and .port fields instead.
117
117
  */
118
118
  hostCandidateAttributeGetter:
119
119
  '`RTCPeerConnectionIceErrorEvent.hostCandidate` is deprecated. Please use `RTCPeerConnectionIceErrorEvent.address` or `RTCPeerConnectionIceErrorEvent.port` instead.',
@@ -164,10 +164,6 @@ const UIStrings = {
164
164
  */
165
165
  obsoleteWebRtcCipherSuite:
166
166
  'Your partner is negotiating an obsolete (D)TLS version. Please check with your partner to have this fixed.',
167
- /**
168
- * @description TODO(crbug.com/1320349): Description needed for translation
169
- */
170
- paymentRequestBasicCard: 'The `basic-card` payment method is deprecated and will be removed.',
171
167
  /**
172
168
  * @description This issue indicates that a `<source>` element with a `<picture>` parent was using an `src` attribute, which is not valid and is ignored by the browser. The `srcset` attribute should be used instead.
173
169
  */
@@ -411,11 +407,6 @@ export class DeprecationIssue extends Issue {
411
407
  messageFunction = i18nLazyString(UIStrings.obsoleteWebRtcCipherSuite);
412
408
  milestone = 81;
413
409
  break;
414
- case Protocol.Audits.DeprecationIssueType.PaymentRequestBasicCard:
415
- messageFunction = i18nLazyString(UIStrings.paymentRequestBasicCard);
416
- feature = 5730051011117056;
417
- milestone = 100;
418
- break;
419
410
  case Protocol.Audits.DeprecationIssueType.PictureSourceSrc:
420
411
  messageFunction = i18nLazyString(UIStrings.pictureSourceSrc);
421
412
  break;
@@ -7865,10 +7865,6 @@ export const NativeFunctions = [
7865
7865
  name: 'colorMaskiOES',
7866
7866
  signatures: [['buf','r','g','b','a']]
7867
7867
  },
7868
- {
7869
- name: 'isEnablediOES',
7870
- signatures: [['target','index']]
7871
- },
7872
7868
  {
7873
7869
  name: 'WebGLContextEvent',
7874
7870
  signatures: [['type','?eventInit']]
@@ -7909,6 +7905,10 @@ export const NativeFunctions = [
7909
7905
  name: 'releaseVideoFrame',
7910
7906
  signatures: [['handle']]
7911
7907
  },
7908
+ {
7909
+ name: 'requestAdapterInfo',
7910
+ signatures: [['?unmaskHints']]
7911
+ },
7912
7912
  {
7913
7913
  name: 'mapAsync',
7914
7914
  signatures: [['mode','?offset','?size']]
@@ -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
- private computeNetworkStatus(networkSourceCode: Workspace.UISourceCode.UISourceCode): void {
177
- if (this.sourceCodeToProcessingPromiseMap.has(networkSourceCode) ||
178
- this.sourceCodeToAutoMappingStatusMap.has(networkSourceCode)) {
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.trimRight() === networkContent.content.trimRight();
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
- void this.onStatusAdded.call(null, status);
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 async onStatusAdded(status: AutomappingStatus): Promise<void> {
151
+ private onStatusAdded(status: AutomappingStatus): Promise<void> {
144
152
  const binding = new PersistenceBinding(status.network, status.fileSystem);
145
153
  statusBindings.set(status, binding);
146
- await this.innerAddBinding(binding);
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
- this.removeEventListener(Events.UISourceCodeAdded, descriptor.listener);
274
- resolve(uiSourceCode);
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
- const uiSourceCode = project.uiSourceCodeForURL(url);
283
- if (uiSourceCode) {
284
- return uiSourceCode;
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: string): UISourceCode[] {
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
 
@@ -1397,7 +1397,8 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
1397
1397
  if (scripts.length) {
1398
1398
  const location =
1399
1399
  new SDK.DebuggerModel.Location(debuggerModel, scripts[0].scriptId, lineNumber || 0, columnNumber);
1400
- return await debuggerWorkspaceBinding.pluginManager.getFunctionInfo(scripts[0], location) ?? {frames: []};
1400
+ const functionInfo = await debuggerWorkspaceBinding.pluginManager.getFunctionInfo(scripts[0], location);
1401
+ return functionInfo && 'frames' in functionInfo ? functionInfo : {frames: []};
1401
1402
  }
1402
1403
  }
1403
1404