chrome-devtools-frontend 1.0.1011333 → 1.0.1012587

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 (38) hide show
  1. package/codereview.settings +4 -0
  2. package/config/gni/devtools_grd_files.gni +2 -0
  3. package/docs/workflows.md +3 -3
  4. package/front_end/core/common/Mutex.ts +42 -0
  5. package/front_end/core/common/common.ts +2 -0
  6. package/front_end/core/host/UserMetrics.ts +3 -1
  7. package/front_end/core/i18n/locales/en-US.json +17 -2
  8. package/front_end/core/i18n/locales/en-XL.json +17 -2
  9. package/front_end/core/root/Runtime.ts +2 -0
  10. package/front_end/core/sdk/CSSMatchedStyles.ts +1 -1
  11. package/front_end/core/sdk/CSSModel.ts +4 -0
  12. package/front_end/core/sdk/DOMModel.ts +49 -27
  13. package/front_end/entrypoints/main/MainImpl.ts +9 -0
  14. package/front_end/entrypoints/wasmparser_worker/WasmParserWorker.ts +2 -14
  15. package/front_end/generated/protocol.ts +4 -0
  16. package/front_end/legacy_test_runner/elements_test_runner/ElementsTestRunner.js +1 -1
  17. package/front_end/models/bindings/BreakpointManager.ts +3 -2
  18. package/front_end/models/emulation/EmulatedDevices.ts +29 -2
  19. package/front_end/models/javascript_metadata/NativeFunctions.js +8 -17
  20. package/front_end/models/persistence/NetworkPersistenceManager.ts +60 -13
  21. package/front_end/panels/application/DOMStorageItemsView.ts +5 -5
  22. package/front_end/panels/elements/ElementsTreeOutline.ts +2 -0
  23. package/front_end/panels/profiler/HeapSnapshotView.ts +3 -1
  24. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +7 -1
  25. package/front_end/panels/sources/NavigatorView.ts +50 -22
  26. package/front_end/panels/sources/SourcesNavigator.ts +45 -1
  27. package/front_end/panels/sources/SourcesPanel.ts +26 -4
  28. package/front_end/panels/sources/navigatorTree.css +4 -0
  29. package/front_end/panels/sources/sourcesNavigator.css +10 -0
  30. package/front_end/panels/webauthn/WebauthnPane.ts +8 -1
  31. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +34 -13
  32. package/front_end/ui/components/panel_feedback/previewToggle.css +21 -1
  33. package/front_end/ui/components/text_editor/config.ts +2 -2
  34. package/front_end/ui/legacy/ContextMenu.ts +11 -2
  35. package/front_end/ui/legacy/components/data_grid/dataGrid.css +1 -1
  36. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +15 -12
  37. package/package.json +1 -1
  38. package/scripts/eslint_rules/lib/lit_template_result_or_nothing.js +6 -0
@@ -0,0 +1,4 @@
1
+ # This file is used by git-cl to get repository specific information.
2
+ GERRIT_HOST: True
3
+ CODE_REVIEW_SERVER: codereview.chromium.org
4
+ PROJECT: devtools-frontend
@@ -544,6 +544,7 @@ grd_files_debug_sources = [
544
544
  "front_end/core/common/JavaScriptMetaData.js",
545
545
  "front_end/core/common/Lazy.js",
546
546
  "front_end/core/common/Linkifier.js",
547
+ "front_end/core/common/Mutex.js",
547
548
  "front_end/core/common/Object.js",
548
549
  "front_end/core/common/ParsedURL.js",
549
550
  "front_end/core/common/Progress.js",
@@ -1251,6 +1252,7 @@ grd_files_debug_sources = [
1251
1252
  "front_end/panels/sources/navigatorTree.css.js",
1252
1253
  "front_end/panels/sources/navigatorView.css.js",
1253
1254
  "front_end/panels/sources/scopeChainSidebarPane.css.js",
1255
+ "front_end/panels/sources/sourcesNavigator.css.js",
1254
1256
  "front_end/panels/sources/sourcesPanel.css.js",
1255
1257
  "front_end/panels/sources/sourcesView.css.js",
1256
1258
  "front_end/panels/sources/threadsSidebarPane.css.js",
package/docs/workflows.md CHANGED
@@ -59,7 +59,7 @@ This works with Chromium 79 or later.
59
59
  **(Requires `brew install coreutils` on Mac.)**
60
60
 
61
61
  ```bash
62
- <path-to-chrome>/chrome --custom-devtools-frontend=file://$(realpath out/Default/gen/front_end)
62
+ <path-to-devtools-frontend>/third_party/chrome/chrome-<platform>/chrome --custom-devtools-frontend=file://$(realpath out/Default/gen/front_end)
63
63
  ```
64
64
 
65
65
  Note that `$(realpath out/Default/gen/front_end)` expands to the absolute path to build artifacts for DevTools frontend.
@@ -79,7 +79,7 @@ Serve the content of `out/Default/gen/front_end` on a web server, e.g. via `pyth
79
79
  Then point to that web server when starting Chromium, for example:
80
80
 
81
81
  ```bash
82
- <path-to-chrome>/chrome --custom-devtools-frontend=http://localhost:8000/
82
+ <path-to-devtools-frontend>/third_party/chrome/chrome-<platform>/chrome --custom-devtools-frontend=http://localhost:8000/
83
83
  ```
84
84
 
85
85
  Open DevTools via F12 on Windows/Linux or Cmd+Option+I on Mac.
@@ -91,7 +91,7 @@ Serve the content of `out/Default/gen/front_end` on a web server, e.g. via `pyth
91
91
  Then point to that web server when starting Chromium, for example:
92
92
 
93
93
  ```bash
94
- <path-to-chrome>/chrome --custom-devtools-frontend=http://localhost:8000/ --remote-debugging-port=9222
94
+ <path-to-devtools-frontend>/third_party/chrome/chrome-<platform>/chrome --custom-devtools-frontend=http://localhost:8000/ --remote-debugging-port=9222
95
95
  ```
96
96
 
97
97
  In a regular Chrome tab, go to the URL `http://localhost:9222#custom=true`. It lists URLs that can be copied to new Chrome tabs to inspect individual debug targets.
@@ -0,0 +1,42 @@
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
+ type ReleaseFn = () => void;
6
+
7
+ /**
8
+ * Use Mutex class to coordinate local concurrent operations.
9
+ * Once `acquire` promise resolves, you hold the lock and must
10
+ * call `release` function returned by `acquire` to release the
11
+ * lock. Failing to `release` the lock may lead to deadlocks.
12
+ */
13
+ export class Mutex {
14
+ #locked = false;
15
+ #acquiringQueue: Array<(release: ReleaseFn) => void> = [];
16
+
17
+ acquire(): Promise<ReleaseFn> {
18
+ let resolver = (_release: ReleaseFn): void => {};
19
+ const promise = new Promise<ReleaseFn>((resolve): void => {
20
+ resolver = resolve;
21
+ });
22
+ this.#acquiringQueue.push(resolver);
23
+ this.#processAcquiringQueue();
24
+ return promise;
25
+ }
26
+
27
+ #processAcquiringQueue(): void {
28
+ if (this.#locked) {
29
+ return;
30
+ }
31
+ const nextAquirePromise = this.#acquiringQueue.shift();
32
+ if (nextAquirePromise) {
33
+ this.#locked = true;
34
+ nextAquirePromise(this.#release.bind(this));
35
+ }
36
+ }
37
+
38
+ #release(): void {
39
+ this.#locked = false;
40
+ this.#processAcquiringQueue();
41
+ }
42
+ }
@@ -14,6 +14,7 @@ import * as EventTarget from './EventTarget.js';
14
14
  import * as JavaScriptMetaData from './JavaScriptMetaData.js';
15
15
  import * as Lazy from './Lazy.js';
16
16
  import * as Linkifier from './Linkifier.js';
17
+ import * as Mutex from './Mutex.js';
17
18
  import * as ObjectWrapper from './Object.js';
18
19
  import * as ParsedURL from './ParsedURL.js';
19
20
  import * as Progress from './Progress.js';
@@ -58,6 +59,7 @@ export {
58
59
  JavaScriptMetaData,
59
60
  Lazy,
60
61
  Linkifier,
62
+ Mutex,
61
63
  ObjectWrapper,
62
64
  ParsedURL,
63
65
  Progress,
@@ -626,8 +626,10 @@ export enum DevtoolsExperiments {
626
626
  'cssLayers' = 59,
627
627
  'eyedropperColorPicker' = 60,
628
628
  'instrumentationBreakpoints' = 61,
629
+ 'cssAuthoringHints' = 62,
630
+ 'authoredDeployedGrouping' = 63,
629
631
  // Increment this when new experiments are added.
630
- 'MaxValue' = 62,
632
+ 'MaxValue' = 64,
631
633
  }
632
634
  /* eslint-enable @typescript-eslint/naming-convention */
633
635
 
@@ -3291,7 +3291,7 @@
3291
3291
  "message": "DOM Storage Items"
3292
3292
  },
3293
3293
  "panels/application/DOMStorageItemsView.ts | domStorageItemsCleared": {
3294
- "message": "{PH1} cleared"
3294
+ "message": "DOM Storage Items cleared"
3295
3295
  },
3296
3296
  "panels/application/DOMStorageItemsView.ts | domStorageNumberEntries": {
3297
3297
  "message": "Number of entries shown in table: {PH1}"
@@ -9794,6 +9794,9 @@
9794
9794
  "panels/sources/NavigatorView.ts | authored": {
9795
9795
  "message": "Authored"
9796
9796
  },
9797
+ "panels/sources/NavigatorView.ts | authoredTooltip": {
9798
+ "message": "Contains original sources"
9799
+ },
9797
9800
  "panels/sources/NavigatorView.ts | delete": {
9798
9801
  "message": "Delete"
9799
9802
  },
@@ -9803,6 +9806,9 @@
9803
9806
  "panels/sources/NavigatorView.ts | deployed": {
9804
9807
  "message": "Deployed"
9805
9808
  },
9809
+ "panels/sources/NavigatorView.ts | deployedTooltip": {
9810
+ "message": "Contains final sources the browser sees"
9811
+ },
9806
9812
  "panels/sources/NavigatorView.ts | excludeFolder": {
9807
9813
  "message": "Exclude folder"
9808
9814
  },
@@ -10163,6 +10169,9 @@
10163
10169
  "panels/sources/sources-meta.ts | watch": {
10164
10170
  "message": "Watch"
10165
10171
  },
10172
+ "panels/sources/SourcesNavigator.ts | authoredDescription": {
10173
+ "message": "Group files by Authored/Deployed"
10174
+ },
10166
10175
  "panels/sources/SourcesNavigator.ts | clearConfiguration": {
10167
10176
  "message": "Clear configuration"
10168
10177
  },
@@ -10233,7 +10242,7 @@
10233
10242
  "message": "Drop workspace folder here"
10234
10243
  },
10235
10244
  "panels/sources/SourcesPanel.ts | groupByAuthored": {
10236
- "message": "Group by Authored/Deployed (experimental)"
10245
+ "message": "Group by Authored/Deployed"
10237
10246
  },
10238
10247
  "panels/sources/SourcesPanel.ts | groupByFolder": {
10239
10248
  "message": "Group by folder"
@@ -11906,9 +11915,15 @@
11906
11915
  "ui/components/panel_feedback/PanelFeedback.ts | videoAndDocumentation": {
11907
11916
  "message": "Video and documentation"
11908
11917
  },
11918
+ "ui/components/panel_feedback/PreviewToggle.ts | learnMoreLink": {
11919
+ "message": "Learn More"
11920
+ },
11909
11921
  "ui/components/panel_feedback/PreviewToggle.ts | previewTextFeedbackLink": {
11910
11922
  "message": "Send us your feedback."
11911
11923
  },
11924
+ "ui/components/panel_feedback/PreviewToggle.ts | shortFeedbackLink": {
11925
+ "message": "Send feedback"
11926
+ },
11912
11927
  "ui/components/request_link_icon/RequestLinkIcon.ts | clickToShowRequestInTheNetwork": {
11913
11928
  "message": "Click to open the network panel and show request for URL: {url}"
11914
11929
  },
@@ -3291,7 +3291,7 @@
3291
3291
  "message": "D̂ÓM̂ Śt̂ór̂áĝé Ît́êḿŝ"
3292
3292
  },
3293
3293
  "panels/application/DOMStorageItemsView.ts | domStorageItemsCleared": {
3294
- "message": "{PH1} ĉĺêár̂éd̂"
3294
+ "message": "D̂ÓM̂ Śt̂ór̂áĝé Ît́êḿŝ ćl̂éâŕêd́"
3295
3295
  },
3296
3296
  "panels/application/DOMStorageItemsView.ts | domStorageNumberEntries": {
3297
3297
  "message": "N̂úm̂b́êŕ ôf́ êńt̂ŕîéŝ śĥóŵń îń t̂áb̂ĺê: {PH1}"
@@ -9794,6 +9794,9 @@
9794
9794
  "panels/sources/NavigatorView.ts | authored": {
9795
9795
  "message": "Âút̂h́ôŕêd́"
9796
9796
  },
9797
+ "panels/sources/NavigatorView.ts | authoredTooltip": {
9798
+ "message": "Ĉón̂t́âín̂ś ôŕîǵîńâĺ ŝóûŕĉéŝ"
9799
+ },
9797
9800
  "panels/sources/NavigatorView.ts | delete": {
9798
9801
  "message": "D̂él̂ét̂é"
9799
9802
  },
@@ -9803,6 +9806,9 @@
9803
9806
  "panels/sources/NavigatorView.ts | deployed": {
9804
9807
  "message": "D̂ép̂ĺôýêd́"
9805
9808
  },
9809
+ "panels/sources/NavigatorView.ts | deployedTooltip": {
9810
+ "message": "Ĉón̂t́âín̂ś f̂ín̂ál̂ śôúr̂ćêś t̂h́ê b́r̂óŵśêŕ ŝéêś"
9811
+ },
9806
9812
  "panels/sources/NavigatorView.ts | excludeFolder": {
9807
9813
  "message": "Êx́ĉĺûd́ê f́ôĺd̂ér̂"
9808
9814
  },
@@ -10163,6 +10169,9 @@
10163
10169
  "panels/sources/sources-meta.ts | watch": {
10164
10170
  "message": "Ŵát̂ćĥ"
10165
10171
  },
10172
+ "panels/sources/SourcesNavigator.ts | authoredDescription": {
10173
+ "message": "Ĝŕôúp̂ f́îĺêś b̂ý Âút̂h́ôŕêd́/D̂ép̂ĺôýêd́"
10174
+ },
10166
10175
  "panels/sources/SourcesNavigator.ts | clearConfiguration": {
10167
10176
  "message": "Ĉĺêár̂ ćôńf̂íĝúr̂át̂íôń"
10168
10177
  },
@@ -10233,7 +10242,7 @@
10233
10242
  "message": "D̂ŕôṕ ŵór̂ḱŝṕâćê f́ôĺd̂ér̂ h́êŕê"
10234
10243
  },
10235
10244
  "panels/sources/SourcesPanel.ts | groupByAuthored": {
10236
- "message": "Ĝŕôúp̂ b́ŷ Áût́ĥór̂éd̂/D́êṕl̂óŷéd̂ (éx̂ṕêŕîḿêńt̂ál̂)"
10245
+ "message": "Ĝŕôúp̂ b́ŷ Áût́ĥór̂éd̂/D́êṕl̂óŷéd̂"
10237
10246
  },
10238
10247
  "panels/sources/SourcesPanel.ts | groupByFolder": {
10239
10248
  "message": "Ĝŕôúp̂ b́ŷ f́ôĺd̂ér̂"
@@ -11906,9 +11915,15 @@
11906
11915
  "ui/components/panel_feedback/PanelFeedback.ts | videoAndDocumentation": {
11907
11916
  "message": "V̂íd̂éô án̂d́ d̂óĉúm̂én̂t́ât́îón̂"
11908
11917
  },
11918
+ "ui/components/panel_feedback/PreviewToggle.ts | learnMoreLink": {
11919
+ "message": "L̂éâŕn̂ Ḿôŕê"
11920
+ },
11909
11921
  "ui/components/panel_feedback/PreviewToggle.ts | previewTextFeedbackLink": {
11910
11922
  "message": "Ŝén̂d́ ûś ŷóûŕ f̂éêd́b̂áĉḱ."
11911
11923
  },
11924
+ "ui/components/panel_feedback/PreviewToggle.ts | shortFeedbackLink": {
11925
+ "message": "Ŝén̂d́ f̂éêd́b̂áĉḱ"
11926
+ },
11912
11927
  "ui/components/request_link_icon/RequestLinkIcon.ts | clickToShowRequestInTheNetwork": {
11913
11928
  "message": "Ĉĺîćk̂ t́ô óp̂én̂ t́ĥé n̂ét̂ẃôŕk̂ ṕâńêĺ âńd̂ śĥóŵ ŕêq́ûéŝt́ f̂ór̂ ÚR̂Ĺ: {url}"
11914
11929
  },
@@ -291,6 +291,8 @@ export enum ExperimentName {
291
291
  CSS_LAYERS = 'cssLayers',
292
292
  EYEDROPPER_COLOR_PICKER = 'eyedropperColorPicker',
293
293
  INSTRUMENTATION_BREAKPOINTS = 'instrumentationBreakpoints',
294
+ CSS_AUTHORING_HINTS = 'cssAuthoringHints',
295
+ AUTHORED_DEPLOYED_GROUPING = 'authoredDeployedGrouping',
294
296
  }
295
297
 
296
298
  // TODO(crbug.com/1167717): Make this a const enum again
@@ -315,7 +315,7 @@ export class CSSMatchedStyles {
315
315
  for (let i = 0; i < pseudoPayload.length; ++i) {
316
316
  const entryPayload = pseudoPayload[i];
317
317
  // PseudoElement nodes are not created unless "content" css property is set.
318
- const pseudoElement = this.#nodeInternal.pseudoElements().get(entryPayload.pseudoType) || null;
318
+ const pseudoElement = this.#nodeInternal.pseudoElements().get(entryPayload.pseudoType)?.at(-1) || null;
319
319
  const pseudoStyles = [];
320
320
  const rules = entryPayload.matches || [];
321
321
 
@@ -517,6 +517,10 @@ export class CSSModel extends SDKModel<EventTypes> {
517
517
  return [...this.#fontFaces.values()];
518
518
  }
519
519
 
520
+ fontFaceForSource(src: string): CSSFontFace|undefined {
521
+ return this.#fontFaces.get(src);
522
+ }
523
+
520
524
  styleSheetHeaderForId(id: Protocol.CSS.StyleSheetId): CSSStyleSheetHeader|null {
521
525
  return this.#styleSheetIdToHeader.get(id) || null;
522
526
  }
@@ -69,7 +69,7 @@ export class DOMNode {
69
69
  #xmlVersion!: string|undefined;
70
70
  #isSVGNodeInternal!: boolean;
71
71
  #creationStackTraceInternal: Promise<Protocol.Runtime.StackTrace|null>|null;
72
- pseudoElementsInternal: Map<string, DOMNode>;
72
+ #pseudoElements: Map<string, DOMNode[]>;
73
73
  #distributedNodesInternal: DOMNodeShortcut[];
74
74
  assignedSlot: DOMNodeShortcut|null;
75
75
  readonly shadowRootsInternal: DOMNode[];
@@ -100,7 +100,7 @@ export class DOMNode {
100
100
  this.#agent = this.#domModelInternal.getAgent();
101
101
  this.index = undefined;
102
102
  this.#creationStackTraceInternal = null;
103
- this.pseudoElementsInternal = new Map();
103
+ this.#pseudoElements = new Map();
104
104
  this.#distributedNodesInternal = [];
105
105
  this.assignedSlot = null;
106
106
  this.shadowRootsInternal = [];
@@ -319,32 +319,33 @@ export class DOMNode {
319
319
  }
320
320
 
321
321
  hasPseudoElements(): boolean {
322
- return this.pseudoElementsInternal.size > 0;
322
+ return this.#pseudoElements.size > 0;
323
323
  }
324
324
 
325
- pseudoElements(): Map<string, DOMNode> {
326
- return this.pseudoElementsInternal;
325
+ pseudoElements(): Map<string, DOMNode[]> {
326
+ return this.#pseudoElements;
327
327
  }
328
328
 
329
- beforePseudoElement(): DOMNode|null {
330
- if (!this.pseudoElementsInternal) {
331
- return null;
332
- }
333
- return this.pseudoElementsInternal.get(DOMNode.PseudoElementNames.Before) || null;
329
+ beforePseudoElement(): DOMNode|undefined {
330
+ return this.#pseudoElements.get(DOMNode.PseudoElementNames.Before)?.at(-1);
334
331
  }
335
332
 
336
- afterPseudoElement(): DOMNode|null {
337
- if (!this.pseudoElementsInternal) {
338
- return null;
339
- }
340
- return this.pseudoElementsInternal.get(DOMNode.PseudoElementNames.After) || null;
333
+ afterPseudoElement(): DOMNode|undefined {
334
+ return this.#pseudoElements.get(DOMNode.PseudoElementNames.After)?.at(-1);
341
335
  }
342
336
 
343
- markerPseudoElement(): DOMNode|null {
344
- if (!this.pseudoElementsInternal) {
345
- return null;
346
- }
347
- return this.pseudoElementsInternal.get(DOMNode.PseudoElementNames.Marker) || null;
337
+ markerPseudoElement(): DOMNode|undefined {
338
+ return this.#pseudoElements.get(DOMNode.PseudoElementNames.Marker)?.at(-1);
339
+ }
340
+
341
+ pageTransitionPseudoElements(): DOMNode[] {
342
+ return [
343
+ ...this.#pseudoElements.get(DOMNode.PseudoElementNames.PageTransition) || [],
344
+ ...this.#pseudoElements.get(DOMNode.PseudoElementNames.PageTransitionContainer) || [],
345
+ ...this.#pseudoElements.get(DOMNode.PseudoElementNames.PageTransitionImageWrapper) || [],
346
+ ...this.#pseudoElements.get(DOMNode.PseudoElementNames.PageTransitionOutgoingImage) || [],
347
+ ...this.#pseudoElements.get(DOMNode.PseudoElementNames.PageTransitionIncomingImage) || [],
348
+ ];
348
349
  }
349
350
 
350
351
  hasAssignedSlot(): boolean {
@@ -632,7 +633,12 @@ export class DOMNode {
632
633
  removeChild(node: DOMNode): void {
633
634
  const pseudoType = node.pseudoType();
634
635
  if (pseudoType) {
635
- this.pseudoElementsInternal.delete(pseudoType);
636
+ const updatedPseudoElements = this.#pseudoElements.get(pseudoType)?.filter(element => element !== node);
637
+ if (updatedPseudoElements && updatedPseudoElements.length > 0) {
638
+ this.#pseudoElements.set(pseudoType, updatedPseudoElements);
639
+ } else {
640
+ this.#pseudoElements.delete(pseudoType);
641
+ }
636
642
  } else {
637
643
  const shadowRootIndex = this.shadowRootsInternal.indexOf(node);
638
644
  if (shadowRootIndex !== -1) {
@@ -678,7 +684,12 @@ export class DOMNode {
678
684
  if (!pseudoType) {
679
685
  throw new Error('DOMNode.pseudoType() is expected to be defined.');
680
686
  }
681
- this.pseudoElementsInternal.set(pseudoType, node);
687
+ const currentPseudoElements = this.#pseudoElements.get(pseudoType);
688
+ if (currentPseudoElements) {
689
+ currentPseudoElements.push(node);
690
+ } else {
691
+ this.#pseudoElements.set(pseudoType, [node]);
692
+ }
682
693
  }
683
694
  }
684
695
 
@@ -960,6 +971,11 @@ export namespace DOMNode {
960
971
  Before = 'before',
961
972
  After = 'after',
962
973
  Marker = 'marker',
974
+ PageTransition = 'page-transition',
975
+ PageTransitionContainer = 'page-transition-container',
976
+ PageTransitionImageWrapper = 'page-transition-image-wrapper',
977
+ PageTransitionOutgoingImage = 'page-transition-outgoing-image',
978
+ PageTransitionIncomingImage = 'page-transition-incoming-image',
963
979
  }
964
980
 
965
981
  // TODO(crbug.com/1167717): Make this a const enum again
@@ -1375,11 +1391,15 @@ export class DOMModel extends SDKModel<EventTypes> {
1375
1391
  if (!pseudoType) {
1376
1392
  throw new Error('DOMModel._pseudoElementAdded expects pseudoType to be defined.');
1377
1393
  }
1378
- const previousPseudoType = parent.pseudoElements().get(pseudoType);
1379
- if (previousPseudoType) {
1380
- throw new Error('DOMModel._pseudoElementAdded expects parent to not already have this pseudo type added.');
1394
+ const currentPseudoElements = parent.pseudoElements().get(pseudoType);
1395
+ if (currentPseudoElements) {
1396
+ Platform.DCHECK(
1397
+ () => pseudoType.startsWith('page-transition'),
1398
+ 'DOMModel.pseudoElementAdded expects parent to not already have this pseudo type added; only page-transition* pseudo elements can coexist under the same parent.');
1399
+ currentPseudoElements.push(node);
1400
+ } else {
1401
+ parent.pseudoElements().set(pseudoType, [node]);
1381
1402
  }
1382
- parent.pseudoElements().set(pseudoType, node);
1383
1403
  this.dispatchEventToListeners(Events.NodeInserted, node);
1384
1404
  this.scheduleMutationEvent(node);
1385
1405
  }
@@ -1420,7 +1440,9 @@ export class DOMModel extends SDKModel<EventTypes> {
1420
1440
  }
1421
1441
  const pseudoElements = node.pseudoElements();
1422
1442
  for (const value of pseudoElements.values()) {
1423
- this.unbind(value);
1443
+ for (const pseudoElement of value) {
1444
+ this.unbind(pseudoElement);
1445
+ }
1424
1446
  }
1425
1447
  const templateContent = node.templateContent();
1426
1448
  if (templateContent) {
@@ -386,6 +386,11 @@ export class MainImpl {
386
386
  Root.Runtime.experiments.register(
387
387
  Root.Runtime.ExperimentName.HEADER_OVERRIDES, 'Local overrides for response headers');
388
388
 
389
+ // Enable CSS Authoring hints for inactive rules, deprecated properties, etc.
390
+ Root.Runtime.experiments.register(
391
+ Root.Runtime.ExperimentName.CSS_AUTHORING_HINTS,
392
+ 'Enable CSS Authoring hints for inactive rules, deprecated properties, etc.');
393
+
389
394
  // New Lighthouse panel with timespan and snapshot mode
390
395
  Root.Runtime.experiments.register('lighthousePanelFR', 'Use Lighthouse panel with timespan and snapshot modes');
391
396
 
@@ -397,6 +402,10 @@ export class MainImpl {
397
402
  Root.Runtime.experiments.register(
398
403
  Root.Runtime.ExperimentName.EYEDROPPER_COLOR_PICKER, 'Enable color picking outside the browser window');
399
404
 
405
+ // Change grouping of sources panel to use Authored/Deployed trees
406
+ Root.Runtime.experiments.register(
407
+ Root.Runtime.ExperimentName.AUTHORED_DEPLOYED_GROUPING, 'Group sources into Authored and Deployed trees');
408
+
400
409
  Root.Runtime.experiments.enableExperimentsByDefault([
401
410
  'sourceOrderViewer',
402
411
  'hideIssuesFeature',
@@ -55,7 +55,6 @@ export function dissambleWASM(
55
55
  const lines = [];
56
56
  const offsets = [];
57
57
  const functionBodyOffsets = [];
58
- const MAX_LINES = 1000 * 1000;
59
58
  let chunkSize: number = 128 * 1024;
60
59
  let buffer: Uint8Array = new Uint8Array(chunkSize);
61
60
  let pendingSize = 0;
@@ -86,6 +85,7 @@ export function dissambleWASM(
86
85
  end: number,
87
86
  }>,
88
87
  });
88
+
89
89
  for (const line of result.lines) {
90
90
  lines.push(line);
91
91
  }
@@ -96,14 +96,6 @@ export function dissambleWASM(
96
96
  functionBodyOffsets.push(functionBodyOffset);
97
97
  }
98
98
 
99
- if (lines.length > MAX_LINES) {
100
- lines[MAX_LINES] = ';; .... text is truncated due to size';
101
- lines.splice(MAX_LINES + 1);
102
- if (offsets) {
103
- offsets.splice(MAX_LINES + 1);
104
- }
105
- break;
106
- }
107
99
  if (finished) {
108
100
  break;
109
101
  }
@@ -124,13 +116,9 @@ export function dissambleWASM(
124
116
  postMessage({event: 'progress', params: {percentage}});
125
117
  }
126
118
 
127
- postMessage({event: 'progress', params: {percentage: 99}});
128
-
129
- const source = lines.join('\n');
130
-
131
119
  postMessage({event: 'progress', params: {percentage: 100}});
132
120
 
133
- postMessage({method: 'disassemble', result: {source, offsets, functionBodyOffsets}});
121
+ postMessage({method: 'disassemble', result: {lines, offsets, functionBodyOffsets}});
134
122
  } catch (error) {
135
123
  postMessage({method: 'disassemble', error});
136
124
  }
@@ -2351,6 +2351,10 @@ export namespace CSS {
2351
2351
  * The font-stretch.
2352
2352
  */
2353
2353
  fontStretch: string;
2354
+ /**
2355
+ * The font-display.
2356
+ */
2357
+ fontDisplay: string;
2354
2358
  /**
2355
2359
  * The unicode-range.
2356
2360
  */
@@ -64,7 +64,7 @@ ElementsTestRunner.findNode = async function(matchFunction, callback) {
64
64
  }
65
65
 
66
66
  const pseudoElementsMap = node.pseudoElements();
67
- const pseudoElements = pseudoElementsMap ? [...pseudoElementsMap.values()] : [];
67
+ const pseudoElements = pseudoElementsMap ? [...pseudoElementsMap.values()].flat() : [];
68
68
  const children = (node.children() || []).concat(node.shadowRoots()).concat(pseudoElements);
69
69
  if (node.templateContent()) {
70
70
  children.push(node.templateContent());
@@ -133,7 +133,7 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
133
133
  }
134
134
 
135
135
  const debuggerModel = script.debuggerModel;
136
- const uiSourceCode = await this.getUpdatedUISourceCode(script);
136
+ const uiSourceCode = await this.getUISourceCodeWithUpdatedBreakpointInfo(script);
137
137
  if (this.#hasBreakpointsForUrl(script.sourceURL)) {
138
138
  await this.#restoreBreakpointsForUrl(uiSourceCode);
139
139
  }
@@ -165,7 +165,8 @@ export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper<EventT
165
165
  }
166
166
  }
167
167
 
168
- async getUpdatedUISourceCode(script: SDK.Script.Script): Promise<Workspace.UISourceCode.UISourceCode> {
168
+ async getUISourceCodeWithUpdatedBreakpointInfo(script: SDK.Script.Script):
169
+ Promise<Workspace.UISourceCode.UISourceCode> {
169
170
  const isSnippet = script.sourceURL.startsWith('snippet://');
170
171
  const projectType = isSnippet ? Workspace.Workspace.projectTypes.Network : undefined;
171
172
 
@@ -725,6 +725,8 @@ const emulatedDevices = [
725
725
  'capabilities': ['touch', 'mobile'],
726
726
  'user-agent':
727
727
  'Mozilla/5.0 (Linux; Android 11; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36',
728
+ 'user-agent-metadata':
729
+ {'platform': 'Android', 'platformVersion': '11', 'architecture': '', 'model': 'Pixel 3', 'mobile': true},
728
730
  'type': 'phone',
729
731
  },
730
732
  {
@@ -745,6 +747,8 @@ const emulatedDevices = [
745
747
  'capabilities': ['touch', 'mobile'],
746
748
  'user-agent':
747
749
  'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36',
750
+ 'user-agent-metadata':
751
+ {'platform': 'Android', 'platformVersion': '11', 'architecture': '', 'model': 'Pixel 5', 'mobile': true},
748
752
  'type': 'phone',
749
753
  },
750
754
  {
@@ -765,6 +769,8 @@ const emulatedDevices = [
765
769
  'capabilities': ['touch', 'mobile'],
766
770
  'user-agent':
767
771
  'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36',
772
+ 'user-agent-metadata':
773
+ {'platform': 'Android', 'platformVersion': '8.0.0', 'architecture': '', 'model': 'SM-G955U', 'mobile': true},
768
774
  'type': 'phone',
769
775
  },
770
776
  {
@@ -785,6 +791,8 @@ const emulatedDevices = [
785
791
  'capabilities': ['touch', 'mobile'],
786
792
  'user-agent':
787
793
  'Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36',
794
+ 'user-agent-metadata':
795
+ {'platform': 'Android', 'platformVersion': '10', 'architecture': '', 'model': 'SM-G981B', 'mobile': true},
788
796
  'type': 'phone',
789
797
  },
790
798
  {
@@ -869,7 +877,9 @@ const emulatedDevices = [
869
877
  },
870
878
  'capabilities': ['touch', 'mobile'],
871
879
  'user-agent':
872
- 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36',
880
+ 'Mozilla/5.0 (Linux; Android 11.0; Surface Duo) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36',
881
+ 'user-agent-metadata':
882
+ {'platform': 'Android', 'platformVersion': '11.0', 'architecture': '', 'model': 'Surface Duo', 'mobile': true},
873
883
  'type': 'phone',
874
884
  'modes': [
875
885
  {'title': 'default', 'orientation': 'vertical', 'insets': {'left': 0, 'top': 0, 'right': 0, 'bottom': 0}},
@@ -896,7 +906,9 @@ const emulatedDevices = [
896
906
  },
897
907
  'capabilities': ['touch', 'mobile'],
898
908
  'user-agent':
899
- 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36',
909
+ 'Mozilla/5.0 (Linux; Android 9.0; SAMSUNG SM-F900U Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36',
910
+ 'user-agent-metadata':
911
+ {'platform': 'Android', 'platformVersion': '9.0', 'architecture': '', 'model': 'SM-F900U', 'mobile': true},
900
912
  'type': 'phone',
901
913
  'modes': [
902
914
  {'title': 'default', 'orientation': 'vertical', 'insets': {'left': 0, 'top': 0, 'right': 0, 'bottom': 0}},
@@ -927,6 +939,8 @@ const emulatedDevices = [
927
939
  'capabilities': ['touch', 'mobile'],
928
940
  'user-agent':
929
941
  'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36',
942
+ 'user-agent-metadata':
943
+ {'platform': 'Android', 'platformVersion': '8.0.0', 'architecture': '', 'model': 'SM-G955U', 'mobile': true},
930
944
  'type': 'phone',
931
945
  },
932
946
  {
@@ -976,6 +990,8 @@ const emulatedDevices = [
976
990
  'capabilities': ['touch', 'mobile'],
977
991
  'user-agent':
978
992
  'Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666',
993
+ 'user-agent-metadata':
994
+ {'platform': 'Android', 'platformVersion': '', 'architecture': '', 'model': '', 'mobile': true},
979
995
  'type': 'tablet',
980
996
  'modes': [{'title': 'default', 'orientation': 'horizontal'}],
981
997
  },
@@ -1409,6 +1425,8 @@ const emulatedDevices = [
1409
1425
  'capabilities': ['touch', 'mobile'],
1410
1426
  'user-agent':
1411
1427
  'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263',
1428
+ 'user-agent-metadata':
1429
+ {'platform': 'Android', 'platformVersion': '4.2.1', 'architecture': '', 'model': 'Lumia 550', 'mobile': true},
1412
1430
  'type': 'phone',
1413
1431
  },
1414
1432
  {
@@ -1422,6 +1440,8 @@ const emulatedDevices = [
1422
1440
  'capabilities': ['touch', 'mobile'],
1423
1441
  'user-agent':
1424
1442
  'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263',
1443
+ 'user-agent-metadata':
1444
+ {'platform': 'Android', 'platformVersion': '4.2.1', 'architecture': '', 'model': 'Lumia 950', 'mobile': true},
1425
1445
  'type': 'phone',
1426
1446
  },
1427
1447
  {
@@ -1512,6 +1532,13 @@ const emulatedDevices = [
1512
1532
  'capabilities': ['touch', 'mobile'],
1513
1533
  'user-agent':
1514
1534
  'Mozilla/5.0 (Mobile; LYF/F300B/LYF-F300B-001-01-15-130718-i;Android; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5',
1535
+ 'user-agent-metadata': {
1536
+ 'platform': 'Android',
1537
+ 'platformVersion': '',
1538
+ 'architecture': '',
1539
+ 'model': 'LYF/F300B/LYF-F300B-001-01-15-130718-i',
1540
+ 'mobile': true,
1541
+ },
1515
1542
  'type': 'phone',
1516
1543
  },
1517
1544
  {