chrome-devtools-frontend 1.0.1543472 → 1.0.1545096

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 (166) hide show
  1. package/AUTHORS +1 -0
  2. package/config/typescript/tsconfig.eslint.json +1 -0
  3. package/front_end/core/common/ParsedURL.ts +1 -1
  4. package/front_end/core/common/common.ts +0 -2
  5. package/front_end/core/host/AidaClient.ts +10 -7
  6. package/front_end/core/host/DispatchHttpRequestClient.ts +18 -3
  7. package/front_end/core/protocol_client/CDPConnection.ts +3 -3
  8. package/front_end/core/protocol_client/DevToolsCDPConnection.ts +2 -1
  9. package/front_end/core/root/Runtime.ts +8 -7
  10. package/front_end/core/sdk/CPUThrottlingManager.ts +0 -4
  11. package/front_end/core/sdk/CSSMatchedStyles.ts +7 -9
  12. package/front_end/core/sdk/CSSMetadata.ts +17 -5
  13. package/front_end/core/sdk/CSSModel.ts +1 -1
  14. package/front_end/core/sdk/CSSRule.ts +18 -6
  15. package/front_end/core/sdk/ChildTargetManager.ts +2 -2
  16. package/front_end/core/sdk/NetworkManager.ts +6 -8
  17. package/front_end/core/sdk/NetworkRequest.ts +4 -0
  18. package/front_end/core/sdk/SDKModel.ts +4 -2
  19. package/front_end/core/sdk/TargetManager.ts +14 -15
  20. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +2 -0
  21. package/front_end/entrypoints/main/MainImpl.ts +0 -16
  22. package/front_end/foundation/Universe.ts +12 -1
  23. package/front_end/generated/Deprecation.ts +4 -0
  24. package/front_end/generated/InspectorBackendCommands.ts +2 -5
  25. package/front_end/generated/SupportedCSSProperties.js +0 -23
  26. package/front_end/generated/protocol-mapping.d.ts +0 -15
  27. package/front_end/generated/protocol-proxy-api.d.ts +0 -11
  28. package/front_end/generated/protocol.ts +2 -34
  29. package/front_end/models/ai_assistance/agents/AiAgent.ts +10 -8
  30. package/front_end/models/ai_assistance/agents/PatchAgent.ts +7 -1
  31. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +0 -5
  32. package/front_end/models/ai_assistance/agents/StylingAgent.ts +4 -8
  33. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +1 -1
  34. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +5 -3
  35. package/front_end/models/bindings/CSSWorkspaceBinding.ts +8 -7
  36. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +9 -8
  37. package/front_end/models/bindings/ResourceMapping.ts +57 -15
  38. package/front_end/models/live-metrics/LiveMetrics.ts +12 -20
  39. package/front_end/panels/accessibility/AccessibilityNodeView.ts +6 -2
  40. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +3 -2
  41. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -4
  42. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +2 -1
  43. package/front_end/panels/ai_assistance/components/UserActionRow.ts +2 -1
  44. package/front_end/panels/animation/AnimationTimeline.ts +6 -6
  45. package/front_end/panels/application/ApplicationPanelSidebar.ts +6 -7
  46. package/front_end/panels/application/{components/FrameDetailsView.ts → FrameDetailsView.ts} +134 -165
  47. package/front_end/panels/application/{components/OriginTrialTreeView.ts → OriginTrialTreeView.ts} +9 -9
  48. package/front_end/panels/application/application.ts +4 -0
  49. package/front_end/panels/application/components/ReportsGrid.ts +7 -2
  50. package/front_end/panels/application/components/SharedStorageAccessGrid.ts +5 -3
  51. package/front_end/panels/application/components/StackTrace.ts +5 -3
  52. package/front_end/panels/application/components/TrustTokensView.ts +7 -1
  53. package/front_end/panels/application/components/components.ts +2 -4
  54. package/front_end/panels/application/{components/frameDetailsReportView.css → frameDetailsReportView.css} +5 -1
  55. package/front_end/panels/application/preloading/PreloadingView.ts +10 -4
  56. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +7 -11
  57. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +15 -3
  58. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +12 -13
  59. package/front_end/panels/common/BadgeNotification.ts +2 -1
  60. package/front_end/panels/{elements → common}/DOMLinkifier.ts +13 -8
  61. package/front_end/panels/common/GdpSignUpDialog.ts +2 -1
  62. package/front_end/panels/common/common.ts +1 -0
  63. package/front_end/panels/console/ConsoleViewMessage.ts +4 -4
  64. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -1
  65. package/front_end/panels/elements/ElementStatePaneWidget.ts +2 -1
  66. package/front_end/panels/elements/ElementsTreeElement.ts +3 -1
  67. package/front_end/panels/elements/StylePropertiesSection.ts +52 -15
  68. package/front_end/panels/elements/StylePropertyTreeElement.ts +8 -3
  69. package/front_end/panels/elements/StylesSidebarPane.ts +24 -14
  70. package/front_end/panels/elements/elements-meta.ts +0 -13
  71. package/front_end/panels/elements/elements.ts +0 -3
  72. package/front_end/panels/explain/components/ConsoleInsight.ts +31 -20
  73. package/front_end/panels/issues/AffectedResourcesView.ts +2 -1
  74. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +3 -6
  75. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +2 -1
  76. package/front_end/panels/network/NetworkLogView.ts +1 -1
  77. package/front_end/panels/recorder/RecorderController.ts +7 -1
  78. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +2 -1
  79. package/front_end/panels/settings/SettingsScreen.ts +3 -2
  80. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +42 -294
  81. package/front_end/panels/sources/DebuggerPausedMessage.ts +3 -3
  82. package/front_end/panels/sources/SourcesPanel.ts +5 -1
  83. package/front_end/panels/timeline/TimelineUIUtils.ts +3 -2
  84. package/front_end/panels/timeline/components/LiveMetricsView.ts +18 -6
  85. package/front_end/panels/timeline/components/MetricCard.ts +2 -2
  86. package/front_end/panels/timeline/components/insights/NodeLink.ts +4 -4
  87. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +2 -1
  88. package/front_end/panels/timeline/timeline-meta.ts +0 -10
  89. package/front_end/panels/timeline/timeline.ts +0 -2
  90. package/front_end/panels/whats_new/ReleaseNoteView.ts +2 -1
  91. package/front_end/panels/whats_new/WhatsNewImpl.ts +3 -2
  92. package/front_end/third_party/chromium/README.chromium +1 -1
  93. package/front_end/third_party/puppeteer/README.chromium +2 -2
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.d.ts +1 -0
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.js +4 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.js.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.d.ts +1 -0
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.js +8 -0
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkEventManager.js.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +22 -0
  104. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  105. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  107. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  108. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  110. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +34 -6
  113. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.d.ts +1 -0
  114. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.js +4 -1
  116. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.js.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.d.ts +1 -0
  118. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.d.ts.map +1 -1
  119. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.js +8 -0
  120. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkEventManager.js.map +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +22 -0
  123. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  124. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  125. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  126. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  127. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  129. package/front_end/third_party/puppeteer/package/package.json +2 -2
  130. package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +5 -1
  131. package/front_end/third_party/puppeteer/package/src/cdp/NetworkEventManager.ts +16 -1
  132. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +28 -0
  133. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  134. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  135. package/front_end/tsconfig.json +1 -0
  136. package/front_end/ui/components/buttons/Button.docs.ts +6 -5
  137. package/front_end/ui/components/snackbars/Snackbars.docs.ts +1 -1
  138. package/front_end/ui/components/spinners/Spinners.docs.ts +1 -1
  139. package/front_end/ui/components/survey_link/SurveyLink.docs.ts +2 -1
  140. package/front_end/ui/components/switch/Switch.docs.ts +1 -1
  141. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +8 -5
  142. package/front_end/ui/components/tooltips/Tooltip.docs.ts +3 -3
  143. package/front_end/ui/helpers/OpenInNewTab.ts +87 -0
  144. package/front_end/ui/helpers/helpers.ts +5 -0
  145. package/front_end/ui/i18n/i18n.ts +16 -0
  146. package/front_end/ui/legacy/ContextMenu.docs.ts +12 -11
  147. package/front_end/ui/legacy/RadioButton.docs.ts +1 -1
  148. package/front_end/ui/legacy/SelectMenu.docs.ts +1 -1
  149. package/front_end/ui/legacy/Slider.docs.ts +1 -1
  150. package/front_end/ui/legacy/UIUtils.ts +1 -34
  151. package/front_end/ui/legacy/Widget.ts +56 -25
  152. package/front_end/ui/legacy/XLink.ts +4 -6
  153. package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +2 -1
  154. package/front_end/ui/legacy/components/object_ui/ObjectPopoverHelper.ts +3 -1
  155. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +294 -336
  156. package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -1
  157. package/front_end/ui/legacy/inspectorCommon.css +0 -4
  158. package/mcp/mcp.ts +1 -0
  159. package/mcp/tsconfig.json +16 -0
  160. package/package.json +2 -2
  161. package/front_end/core/common/Linkifier.ts +0 -55
  162. package/front_end/panels/timeline/CLSLinkifier.ts +0 -58
  163. package/front_end/ui/components/expandable_list/ExpandableList.docs.ts +0 -30
  164. /package/front_end/panels/application/{components/originTrialTokenRows.css → originTrialTokenRows.css} +0 -0
  165. /package/front_end/panels/application/{components/originTrialTreeView.css → originTrialTreeView.css} +0 -0
  166. /package/front_end/panels/{elements → common}/domLinkifier.css +0 -0
@@ -37,9 +37,8 @@ import * as SDK from '../../../../core/sdk/sdk.js';
37
37
  import type * as Protocol from '../../../../generated/protocol.js';
38
38
  import * as TextUtils from '../../../../models/text_utils/text_utils.js';
39
39
  import * as uiI18n from '../../../../ui/i18n/i18n.js';
40
- import * as IconButton from '../../../components/icon_button/icon_button.js';
41
40
  import * as TextEditor from '../../../components/text_editor/text_editor.js';
42
- import {Directives, html, render} from '../../../lit/lit.js';
41
+ import {Directives, html, type LitTemplate, nothing, render} from '../../../lit/lit.js';
43
42
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
44
43
  import * as UI from '../../legacy.js';
45
44
  import type * as Components from '../utils/utils.js';
@@ -50,7 +49,7 @@ import objectPropertiesSectionStyles from './objectPropertiesSection.css.js';
50
49
  import objectValueStyles from './objectValue.css.js';
51
50
  import {RemoteObjectPreviewFormatter, renderNodeTitle} from './RemoteObjectPreviewFormatter.js';
52
51
 
53
- const {repeat, ifDefined} = Directives;
52
+ const {ref, repeat, ifDefined, classMap} = Directives;
54
53
  const UIStrings = {
55
54
  /**
56
55
  * @description Text in Object Properties Section
@@ -504,86 +503,82 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
504
503
  return UI.Fragment.html`<span class="name">${name}</span>`;
505
504
  }
506
505
 
507
- static valueElementForFunctionDescription(description?: string, includePreview?: boolean, defaultName?: string):
508
- HTMLElement {
509
- const valueElement = document.createElement('span');
510
- valueElement.classList.add('object-value-function');
511
- description = description || '';
512
- const text = description.replace(/^function [gs]et /, 'function ')
513
- .replace(/^function [gs]et\(/, 'function\(')
514
- .replace(/^[gs]et /, '');
515
- defaultName = defaultName || '';
516
-
517
- // This set of best-effort regular expressions captures common function descriptions.
518
- // Ideally, some parser would provide prefix, arguments, function body text separately.
519
- const asyncMatch = text.match(/^(async\s+function)/);
520
- const isGenerator = text.startsWith('function*');
521
- const isGeneratorShorthand = text.startsWith('*');
522
- const isBasic = !isGenerator && text.startsWith('function');
523
- const isClass = text.startsWith('class ') || text.startsWith('class{');
524
- const firstArrowIndex = text.indexOf('=>');
525
- const isArrow = !asyncMatch && !isGenerator && !isBasic && !isClass && firstArrowIndex > 0;
526
-
527
- let textAfterPrefix;
528
- if (isClass) {
529
- textAfterPrefix = text.substring('class'.length);
530
- const classNameMatch = /^[^{\s]+/.exec(textAfterPrefix.trim());
531
- let className: string = defaultName;
532
- if (classNameMatch) {
533
- className = classNameMatch[0].trim() || defaultName;
534
- }
535
- addElements('class', textAfterPrefix, className);
536
- } else if (asyncMatch) {
537
- textAfterPrefix = text.substring(asyncMatch[1].length);
538
- addElements('async \u0192', textAfterPrefix, nameAndArguments(textAfterPrefix));
539
- } else if (isGenerator) {
540
- textAfterPrefix = text.substring('function*'.length);
541
- addElements('\u0192*', textAfterPrefix, nameAndArguments(textAfterPrefix));
542
- } else if (isGeneratorShorthand) {
543
- textAfterPrefix = text.substring('*'.length);
544
- addElements('\u0192*', textAfterPrefix, nameAndArguments(textAfterPrefix));
545
- } else if (isBasic) {
546
- textAfterPrefix = text.substring('function'.length);
547
- addElements('\u0192', textAfterPrefix, nameAndArguments(textAfterPrefix));
548
- } else if (isArrow) {
549
- const maxArrowFunctionCharacterLength = 60;
550
- let abbreviation: string = text;
551
- if (defaultName) {
552
- abbreviation = defaultName + '()';
553
- } else if (text.length > maxArrowFunctionCharacterLength) {
554
- abbreviation = text.substring(0, firstArrowIndex + 2) + ' {…}';
555
- }
556
- addElements('', text, abbreviation);
557
- } else {
558
- addElements('\u0192', text, nameAndArguments(text));
559
- }
560
- UI.Tooltip.Tooltip.install(valueElement, Platform.StringUtilities.trimEndWithMaxLength(description, 500));
561
- return valueElement;
506
+ static valueElementForFunctionDescription(
507
+ description?: string, includePreview?: boolean, defaultName?: string, className?: string): LitTemplate {
508
+ const contents =
509
+ (description: string, defaultName: string): {prefix: string, abbreviation: string, body: string} => {
510
+ const text = description.replace(/^function [gs]et /, 'function ')
511
+ .replace(/^function [gs]et\(/, 'function\(')
512
+ .replace(/^[gs]et /, '');
513
+
514
+ // This set of best-effort regular expressions captures common function descriptions.
515
+ // Ideally, some parser would provide prefix, arguments, function body text separately.
516
+ const asyncMatch = text.match(/^(async\s+function)/);
517
+ const isGenerator = text.startsWith('function*');
518
+ const isGeneratorShorthand = text.startsWith('*');
519
+ const isBasic = !isGenerator && text.startsWith('function');
520
+ const isClass = text.startsWith('class ') || text.startsWith('class{');
521
+ const firstArrowIndex = text.indexOf('=>');
522
+ const isArrow = !asyncMatch && !isGenerator && !isBasic && !isClass && firstArrowIndex > 0;
523
+
524
+ if (isClass) {
525
+ const body = text.substring('class'.length);
526
+ const classNameMatch = /^[^{\s]+/.exec(body.trim());
527
+ let className: string = defaultName;
528
+ if (classNameMatch) {
529
+ className = classNameMatch[0].trim() || defaultName;
530
+ }
531
+ return {prefix: 'class', body, abbreviation: className};
532
+ }
533
+ if (asyncMatch) {
534
+ const body = text.substring(asyncMatch[1].length);
535
+ return {prefix: 'async \u0192', body, abbreviation: nameAndArguments(body)};
536
+ }
537
+ if (isGenerator) {
538
+ const body = text.substring('function*'.length);
539
+ return {prefix: '\u0192*', body, abbreviation: nameAndArguments(body)};
540
+ }
541
+ if (isGeneratorShorthand) {
542
+ const body = text.substring('*'.length);
543
+ return {prefix: '\u0192*', body, abbreviation: nameAndArguments(body)};
544
+ }
545
+ if (isBasic) {
546
+ const body = text.substring('function'.length);
547
+ return {prefix: '\u0192', body, abbreviation: nameAndArguments(body)};
548
+ }
549
+ if (isArrow) {
550
+ const maxArrowFunctionCharacterLength = 60;
551
+ let abbreviation: string = text;
552
+ if (defaultName) {
553
+ abbreviation = defaultName + '()';
554
+ } else if (text.length > maxArrowFunctionCharacterLength) {
555
+ abbreviation = text.substring(0, firstArrowIndex + 2) + ' {…}';
556
+ }
557
+ return {prefix: '', body: text, abbreviation};
558
+ }
559
+ return {prefix: '\u0192', body: text, abbreviation: nameAndArguments(text)};
560
+ };
561
+
562
+ const {prefix, body, abbreviation} = contents(description ?? '', defaultName ?? '');
563
+ const maxFunctionBodyLength = 200;
564
+ return html`<span
565
+ class="object-value-function ${className ?? ''}"
566
+ title=${Platform.StringUtilities.trimEndWithMaxLength(description ?? '', 500)}>${
567
+ prefix && html`<span class=object-value-function-prefix>${prefix} </span>`}${
568
+ includePreview ? Platform.StringUtilities.trimEndWithMaxLength(body.trim(), maxFunctionBodyLength) :
569
+ abbreviation.replace(/\n/g, ' ')}</span>`;
562
570
 
563
571
  function nameAndArguments(contents: string): string {
564
572
  const startOfArgumentsIndex = contents.indexOf('(');
565
573
  const endOfArgumentsMatch = contents.match(/\)\s*{/);
566
574
  if (startOfArgumentsIndex !== -1 && endOfArgumentsMatch?.index !== undefined &&
567
575
  endOfArgumentsMatch.index > startOfArgumentsIndex) {
568
- const name = contents.substring(0, startOfArgumentsIndex).trim() || defaultName;
576
+ const name = contents.substring(0, startOfArgumentsIndex).trim() || (defaultName ?? '');
569
577
  const args = contents.substring(startOfArgumentsIndex, endOfArgumentsMatch.index + 1);
570
578
  return name + args;
571
579
  }
572
580
  return defaultName + '()';
573
581
  }
574
-
575
- function addElements(prefix: string, body: string, abbreviation: string): void {
576
- const maxFunctionBodyLength = 200;
577
- if (prefix.length) {
578
- valueElement.createChild('span', 'object-value-function-prefix').textContent = prefix + ' ';
579
- }
580
- if (includePreview) {
581
- UI.UIUtils.createTextChild(
582
- valueElement, Platform.StringUtilities.trimEndWithMaxLength(body.trim(), maxFunctionBodyLength));
583
- } else {
584
- UI.UIUtils.createTextChild(valueElement, abbreviation.replace(/\n/g, ' '));
585
- }
586
- }
587
582
  }
588
583
 
589
584
  static createPropertyValueWithCustomSupport(
@@ -598,141 +593,100 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
598
593
  value, wasThrown, showPreview, linkifier, isSyntheticProperty, variableName);
599
594
  }
600
595
 
601
- static appendMemoryIcon(element: Element, object: SDK.RemoteObject.RemoteObject, expression?: string): void {
602
- if (!object.isLinearMemoryInspectable()) {
603
- return;
604
- }
605
-
606
- const memoryIcon = new IconButton.Icon.Icon();
607
- memoryIcon.name = 'memory';
608
- memoryIcon.style.width = 'var(--sys-size-8)';
609
- memoryIcon.style.height = '13px';
610
- memoryIcon.addEventListener('click', event => {
611
- event.consume();
612
- void Common.Revealer.reveal(new SDK.RemoteObject.LinearMemoryInspectable(object, expression));
613
- });
614
- memoryIcon.setAttribute('jslog', `${VisualLogging.action('open-memory-inspector').track({click: true})}`);
615
-
616
- const revealText = i18nString(UIStrings.openInMemoryInpector);
617
- UI.Tooltip.Tooltip.install(memoryIcon, revealText);
618
- UI.ARIAUtils.setLabel(memoryIcon, revealText);
619
-
620
- // Directly set property on memory icon, so that the memory icon is also
596
+ static getMemoryIcon(object: SDK.RemoteObject.RemoteObject, expression?: string): LitTemplate {
597
+ // Directly set styles on memory icon, so that the memory icon is also
621
598
  // styled within the context of code mirror.
622
- memoryIcon.style.setProperty('vertical-align', 'sub');
623
- memoryIcon.style.setProperty('cursor', 'pointer');
599
+ // clang-format off
600
+ return !object.isLinearMemoryInspectable() ? nothing : html`<devtools-icon
601
+ name=memory
602
+ style="width: var(--sys-size-8); height: 13px; vertical-align: sub; cursor: pointer;"
603
+ @click=${(event: Event) => {
604
+ event.consume();
605
+ void Common.Revealer.reveal(new SDK.RemoteObject.LinearMemoryInspectable(object, expression));
606
+ }}
607
+ jslog=${VisualLogging.action('open-memory-inspector').track({click: true})}
608
+ title=${i18nString(UIStrings.openInMemoryInpector)}
609
+ aria-label=${i18nString(UIStrings.openInMemoryInpector)}></devtools-icon>`;
610
+ // clang-format on
611
+ }
624
612
 
625
- element.appendChild(memoryIcon);
613
+ static appendMemoryIcon(element: Element, object: SDK.RemoteObject.RemoteObject, expression?: string): void {
614
+ const fragment = document.createDocumentFragment();
615
+ // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
616
+ render(ObjectPropertiesSection.getMemoryIcon(object, expression), fragment);
617
+ element.appendChild(fragment);
626
618
  }
627
619
 
628
620
  static createPropertyValue(
629
621
  value: SDK.RemoteObject.RemoteObject, wasThrown: boolean, showPreview: boolean,
630
622
  linkifier?: Components.Linkifier.Linkifier, isSyntheticProperty = false, variableName?: string): HTMLElement {
631
- let propertyValue: HTMLElement;
623
+ const propertyValue = document.createDocumentFragment();
632
624
  const type = value.type;
633
625
  const subtype = value.subtype;
634
626
  const description = value.description || '';
635
627
  const className = value.className;
636
- if (type === 'object' && subtype === 'internal#location') {
637
- const rawLocation = value.debuggerModel().createRawLocationByScriptId(
638
- value.value.scriptId, value.value.lineNumber, value.value.columnNumber);
639
- if (rawLocation && linkifier) {
640
- return linkifier.linkifyRawLocation(rawLocation, Platform.DevToolsPath.EmptyUrlString);
628
+
629
+ const contents = (): LitTemplate => {
630
+ if (type === 'object' && subtype === 'internal#location') {
631
+ const rawLocation = value.debuggerModel().createRawLocationByScriptId(
632
+ value.value.scriptId, value.value.lineNumber, value.value.columnNumber);
633
+ if (rawLocation && linkifier) {
634
+ return html`${linkifier.linkifyRawLocation(rawLocation, Platform.DevToolsPath.EmptyUrlString, 'value')}`;
635
+ }
636
+ return html`<span class=value title=${description}>${'<' + i18nString(UIStrings.unknown) + '>'}</span>`;
641
637
  }
642
- propertyValue = createUnknownInternalLocationElement();
643
- } else if (type === 'string' && typeof description === 'string') {
644
- propertyValue = createStringElement();
645
- } else if (type === 'object' && subtype === 'trustedtype') {
646
- propertyValue = createTrustedTypeElement();
647
- } else if (type === 'function') {
648
- propertyValue = ObjectPropertiesSection.valueElementForFunctionDescription(description);
649
- } else if (type === 'object' && subtype === 'node' && description) {
650
- propertyValue = createNodeElement();
651
- } else {
652
- const valueElement = document.createElement('span');
653
- valueElement.classList.add('object-value-' + (subtype || type));
654
- if (value.preview && showPreview) {
655
- const previewFormatter = new RemoteObjectPreviewFormatter();
656
- /* eslint-disable-next-line @devtools/no-lit-render-outside-of-view */
657
- render(previewFormatter.renderObjectPreview(value.preview), valueElement);
658
- propertyValue = valueElement;
659
- UI.Tooltip.Tooltip.install(propertyValue as HTMLElement, description || '');
660
- } else if (description.length > maxRenderableStringLength) {
661
- propertyValue = new ExpandableTextPropertyValue(valueElement, description, EXPANDABLE_MAX_LENGTH).element;
662
- } else {
663
- propertyValue = valueElement;
664
- propertyValue.textContent = description;
665
- UI.Tooltip.Tooltip.install(propertyValue as HTMLElement, description);
638
+ if (type === 'string' && typeof description === 'string') {
639
+ const text = JSON.stringify(description);
640
+ const tooLong = description.length > maxRenderableStringLength;
641
+ return html`<span class="value object-value-string" title=${ifDefined(tooLong ? undefined : description)}>${
642
+ tooLong ? new ExpandableTextPropertyValue(text, EXPANDABLE_MAX_LENGTH).element : text}</span>`;
666
643
  }
667
- if (!isSyntheticProperty) {
668
- this.appendMemoryIcon(valueElement, value, variableName);
644
+ if (type === 'object' && subtype === 'trustedtype') {
645
+ const text = `${className} '${description}'`;
646
+ const tooLong = text.length > maxRenderableStringLength;
647
+ return html`<span class="value object-value-trustedtype" title=${ifDefined(tooLong ? undefined : text)}>${
648
+ tooLong ? new ExpandableTextPropertyValue(text, EXPANDABLE_MAX_LENGTH).element :
649
+ html`${className} <span class=object-value-string title=${description}>${
650
+ JSON.stringify(description)}</span>`}</span>`;
669
651
  }
670
- }
671
-
672
- if (wasThrown) {
673
- const wrapperElement = document.createElement('span');
674
- wrapperElement.classList.add('error');
675
- wrapperElement.classList.add('value');
676
- wrapperElement.appendChild(uiI18n.getFormatLocalizedString(str_, UIStrings.exceptionS, {PH1: propertyValue}));
677
- propertyValue = wrapperElement;
678
- }
679
- propertyValue.classList.add('value');
680
- return propertyValue;
681
-
682
- function createUnknownInternalLocationElement(): HTMLElement {
683
- const valueElement = document.createElement('span');
684
- valueElement.textContent = '<' + i18nString(UIStrings.unknown) + '>';
685
- UI.Tooltip.Tooltip.install(valueElement, description || '');
686
- return valueElement;
687
- }
688
-
689
- function createStringElement(): HTMLElement {
690
- const valueElement = document.createElement('span');
691
- valueElement.classList.add('object-value-string');
692
- const text = JSON.stringify(description);
693
- let propertyValue: HTMLElement;
694
- if (description.length > maxRenderableStringLength) {
695
- propertyValue = new ExpandableTextPropertyValue(valueElement, text, EXPANDABLE_MAX_LENGTH).element;
696
- } else {
697
- UI.UIUtils.createTextChild(valueElement, text);
698
- propertyValue = valueElement;
699
- UI.Tooltip.Tooltip.install(valueElement, description);
652
+ if (type === 'function') {
653
+ return ObjectPropertiesSection.valueElementForFunctionDescription(description, undefined, undefined, 'value');
700
654
  }
701
- return propertyValue;
702
- }
703
-
704
- function createTrustedTypeElement(): HTMLElement {
705
- const valueElement = document.createElement('span');
706
- valueElement.classList.add('object-value-trustedtype');
707
- const text = `${className} "${description}"`;
708
- let propertyValue;
709
- if (text.length > maxRenderableStringLength) {
710
- propertyValue = new ExpandableTextPropertyValue(valueElement, text, EXPANDABLE_MAX_LENGTH).element;
711
- } else {
712
- const contentString = createStringElement();
713
- UI.UIUtils.createTextChild(valueElement, `${className} `);
714
- valueElement.appendChild(contentString);
715
- propertyValue = valueElement;
716
- UI.Tooltip.Tooltip.install(valueElement, text);
655
+ if (type === 'object' && subtype === 'node' && description) {
656
+ return html`<span class="value object-value-node"
657
+ @click=${(event: Event) => {
658
+ void Common.Revealer.reveal(value);
659
+ event.consume(true);
660
+ }}
661
+ @mousemove=${() => SDK.OverlayModel.OverlayModel.highlightObjectAsDOMNode(value)}
662
+ @mouseleave=${() => SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight()}
663
+ >${renderNodeTitle(description)}</span>`;
717
664
  }
665
+ if (description.length > maxRenderableStringLength) {
666
+ return html`<span class="value object-value-${subtype || type}" title=${description}>${
667
+ new ExpandableTextPropertyValue(description, EXPANDABLE_MAX_LENGTH).element}</span>`;
668
+ }
669
+ const hasPreview = value.preview && showPreview;
670
+ return html`<span class="value object-value-${subtype || type}" title=${description}>${
671
+ hasPreview ? new RemoteObjectPreviewFormatter().renderObjectPreview(value.preview) :
672
+ description}${isSyntheticProperty ? nothing : this.getMemoryIcon(value, variableName)}</span>`;
673
+ };
718
674
 
719
- return propertyValue;
675
+ if (wasThrown) {
676
+ // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
677
+ render(
678
+ html`<span class="error value">${
679
+ uiI18n.getFormatLocalizedStringTemplate(str_, UIStrings.exceptionS, {PH1: contents()})}</span>`,
680
+ propertyValue);
681
+ } else {
682
+ // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
683
+ render(contents(), propertyValue);
720
684
  }
721
-
722
- function createNodeElement(): HTMLElement {
723
- const valueElement = document.createElement('span');
724
- valueElement.classList.add('object-value-node');
725
- /* eslint-disable-next-line @devtools/no-lit-render-outside-of-view */
726
- render(renderNodeTitle(description), valueElement);
727
- valueElement.addEventListener('click', event => {
728
- void Common.Revealer.reveal(value);
729
- event.consume(true);
730
- }, false);
731
- valueElement.addEventListener(
732
- 'mousemove', () => SDK.OverlayModel.OverlayModel.highlightObjectAsDOMNode(value), false);
733
- valueElement.addEventListener('mouseleave', () => SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight(), false);
734
- return valueElement;
685
+ const child = propertyValue.firstElementChild;
686
+ if (!(child instanceof HTMLElement)) {
687
+ throw new Error('Expected an HTML element');
735
688
  }
689
+ return child;
736
690
  }
737
691
 
738
692
  static formatObjectAsFunction(
@@ -754,8 +708,11 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
754
708
  if (response?.functionName) {
755
709
  defaultName = response.functionName;
756
710
  }
757
- const valueElement =
758
- ObjectPropertiesSection.valueElementForFunctionDescription(func.description, includePreview, defaultName);
711
+ const valueElement = document.createDocumentFragment();
712
+ // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
713
+ render(
714
+ ObjectPropertiesSection.valueElementForFunctionDescription(func.description, includePreview, defaultName),
715
+ valueElement);
759
716
  element.appendChild(valueElement);
760
717
  }
761
718
  }
@@ -917,43 +874,116 @@ export class RootElement extends UI.TreeOutline.TreeElement {
917
874
  export const InitialVisibleChildrenLimit = 200;
918
875
 
919
876
  export interface TreeElementViewInput {
877
+ startEditing(): unknown;
878
+ invokeGetter(getter: SDK.RemoteObject.RemoteObject): unknown;
920
879
  onAutoComplete(expression: string, filter: string, force: boolean): unknown;
880
+ linkifier: Components.Linkifier.Linkifier|undefined;
921
881
  completions: string[];
922
- expandedValueElement: HTMLElement|undefined;
923
882
  expanded: boolean;
924
883
  editing: boolean;
925
884
  editingEnded(): unknown;
926
885
  editingCommitted(detail: string): unknown;
927
886
  node: ObjectTreeNode;
928
- nameElement: HTMLElement;
929
- valueElement: HTMLElement;
930
887
  }
931
- type TreeElementView = (input: TreeElementViewInput, output: object, target: HTMLElement) => void;
888
+ interface TreeElementViewOutput {
889
+ valueElement: Element|undefined;
890
+ nameElement: Element|undefined;
891
+ }
892
+ type TreeElementView = (input: TreeElementViewInput, output: TreeElementViewOutput, target: HTMLElement) => void;
932
893
  export const TREE_ELEMENT_DEFAULT_VIEW: TreeElementView = (input, output, target) => {
933
- const isInternalEntries = input.node.property.synthetic && input.node.name === '[[Entries]]';
934
- if (isInternalEntries) {
935
- render(html`<span class=name-and-value>${input.nameElement}</span>`, target);
936
- } else {
937
- const completionsId = `completions-${input.node.parent?.object?.objectId?.replaceAll('.', '-')}-${input.node.name}`;
938
- const onAutoComplete = async(e: UI.TextPrompt.TextPromptElement.BeforeAutoCompleteEvent): Promise<void> => {
939
- if (!(e.target instanceof UI.TextPrompt.TextPromptElement)) {
940
- return;
941
- }
942
- input.onAutoComplete(e.detail.expression, e.detail.filter, e.detail.force);
943
- };
944
- // clang-format off
945
- render(html`<span class=name-and-value>${input.nameElement}<span class='separator'>: </span><devtools-prompt
946
- @commit=${(e: UI.TextPrompt.TextPromptElement.CommitEvent) => input.editingCommitted(e.detail)}
947
- @cancel=${() => input.editingEnded()}
948
- @beforeautocomplete=${onAutoComplete}
949
- completions=${completionsId}
950
- placeholder=${i18nString(UIStrings.stringIsTooLargeToEdit)}
951
- ?editing=${input.editing}>
952
- ${input.expanded && input.expandedValueElement || input.valueElement}
953
- <datalist id=${completionsId}>${repeat(input.completions, c => html`<option>${c}</option>`)}</datalist>
954
- </devtools-prompt></span><span>`, target);
955
- // clang-format on
956
- }
894
+ const {property} = input.node;
895
+ const isInternalEntries = property.synthetic && input.node.name === '[[Entries]]';
896
+ const completionsId = `completions-${input.node.parent?.object?.objectId?.replaceAll('.', '-')}-${input.node.name}`;
897
+ const onAutoComplete = async(e: UI.TextPrompt.TextPromptElement.BeforeAutoCompleteEvent): Promise<void> => {
898
+ if (!(e.target instanceof UI.TextPrompt.TextPromptElement)) {
899
+ return;
900
+ }
901
+ input.onAutoComplete(e.detail.expression, e.detail.filter, e.detail.force);
902
+ };
903
+ const nameClasses = classMap({
904
+ name: true,
905
+ 'object-properties-section-dimmed': !property.enumerable,
906
+ 'own-property': property.isOwn,
907
+ 'synthetic-property': property.synthetic,
908
+ });
909
+ const quotedName =
910
+ /^\s|\s$|^$|\n/.test(property.name) ? `"${property.name.replace(/\n/g, '\u21B5')}"` : property.name;
911
+ const isExpandable = !isInternalEntries && property.value && !property.wasThrown && property.value.hasChildren &&
912
+ !property.value.customPreview() && property.value.subtype !== 'node' && property.value.type !== 'function' &&
913
+ (property.value.type !== 'object' || property.value.preview);
914
+
915
+ const value = (): LitTemplate|HTMLElement => {
916
+ const valueRef = ref(e => {
917
+ output.valueElement = e;
918
+ });
919
+ if (isInternalEntries) {
920
+ return html`<span ${valueRef} class=value></span>`;
921
+ }
922
+ if (property.value) {
923
+ const showPreview = property.name !== '[[Prototype]]';
924
+ const value = ObjectPropertiesSection.createPropertyValueWithCustomSupport(
925
+ property.value, property.wasThrown, showPreview, input.linkifier, property.synthetic,
926
+ input.node.path /* variableName */);
927
+ output.valueElement = value;
928
+ return value;
929
+ }
930
+ if (property.getter) {
931
+ const getter = property.getter;
932
+ const invokeGetter = (event: Event): void => {
933
+ event.consume();
934
+ input.invokeGetter(getter);
935
+ };
936
+ return html`<span ${valueRef}><span
937
+ class=object-value-calculate-value-button
938
+ title=${i18nString(UIStrings.invokePropertyGetter)}
939
+ @click=${invokeGetter}
940
+ >${i18nString(UIStrings.dots)}</span></span>`;
941
+ }
942
+ return html`<span ${valueRef}
943
+ class=object-value-unavailable
944
+ title=${i18nString(UIStrings.valueNotAccessibleToTheDebugger)}>${
945
+ i18nString(UIStrings.valueUnavailable)}</span>`;
946
+ };
947
+
948
+ const onDblClick = (event: Event): void => {
949
+ event.consume(true);
950
+ if (property.value && !property.value.customPreview() && (property.writable || property.setter)) {
951
+ input.startEditing();
952
+ }
953
+ };
954
+
955
+ // clang-format off
956
+ render(
957
+ html`<span class=name-and-value><span
958
+ ${ref(e => { output.nameElement = e; })}
959
+ class=${nameClasses}
960
+ title=${input.node.path}>${property.private ?
961
+ html`<span class="private-property-hash">${property.name[0]}</span>${
962
+ property.name.substring(1)}</span>` : quotedName}</span>${
963
+ isInternalEntries ? nothing :
964
+ html`<span class='separator'>: </span><devtools-prompt
965
+ @commit=${(e: UI.TextPrompt.TextPromptElement.CommitEvent) => input.editingCommitted(e.detail)}
966
+ @cancel=${() => input.editingEnded()}
967
+ @beforeautocomplete=${onAutoComplete}
968
+ @dblclick=${onDblClick}
969
+ completions=${completionsId}
970
+ placeholder=${i18nString(UIStrings.stringIsTooLargeToEdit)}
971
+ ?editing=${input.editing}>
972
+ ${input.expanded && isExpandable && property.value ?
973
+ html`<span
974
+ class="value object-value-${property.value.subtype || property.value.type}"
975
+ title=${ifDefined(property.value.description)}>${
976
+ property.value.description === 'Object' ? '' :
977
+ Platform.StringUtilities.trimMiddle(property.value.description ?? '',
978
+ maxRenderableStringLength)}${
979
+ property.synthetic ? nothing :
980
+ ObjectPropertiesSection.getMemoryIcon(property.value)}</span>` :
981
+ value()
982
+ }
983
+ <datalist id=${completionsId}>${repeat(input.completions, c => html`<option>${c}</option>`)}</datalist>
984
+ </devtools-prompt></span>`}</span>`,
985
+ target);
986
+ // clang-format on
957
987
  };
958
988
  export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
959
989
  property: ObjectTreeNode;
@@ -961,16 +991,13 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
961
991
  private highlightChanges: UI.UIUtils.HighlightChange[];
962
992
  private linkifier: Components.Linkifier.Linkifier|undefined;
963
993
  private readonly maxNumPropertiesToShow: number;
964
- nameElement!: HTMLElement;
965
- valueElement!: HTMLElement;
966
994
  readOnly!: boolean;
967
995
  private prompt!: ObjectPropertyPrompt|undefined;
968
- private editableDiv!: HTMLElement;
969
- propertyValue?: HTMLElement;
970
- expandedValueElement?: HTMLElement;
971
996
  #editing = false;
972
997
  readonly #view: TreeElementView;
973
998
  #completions: string[] = [];
999
+ #nameElement: Element|undefined;
1000
+ #valueElement: Element|undefined;
974
1001
  constructor(property: ObjectTreeNode, linkifier?: Components.Linkifier.Linkifier, view = TREE_ELEMENT_DEFAULT_VIEW) {
975
1002
  // Pass an empty title, the title gets made later in onattach.
976
1003
  super();
@@ -1113,6 +1140,10 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1113
1140
  return rootElement;
1114
1141
  }
1115
1142
 
1143
+ get nameElement(): Element|undefined {
1144
+ return this.#nameElement;
1145
+ }
1146
+
1116
1147
  setSearchRegex(regex: RegExp, additionalCssClassName?: string): boolean {
1117
1148
  let cssClasses = UI.UIUtils.highlightedSearchResultClassName;
1118
1149
  if (additionalCssClassName) {
@@ -1120,11 +1151,13 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1120
1151
  }
1121
1152
  this.revertHighlightChanges();
1122
1153
 
1123
- this.applySearch(regex, this.nameElement, cssClasses);
1154
+ if (this.#nameElement) {
1155
+ this.applySearch(regex, this.#nameElement, cssClasses);
1156
+ }
1124
1157
  if (this.property.object) {
1125
1158
  const valueType = this.property.object.type;
1126
- if (valueType !== 'object') {
1127
- this.applySearch(regex, this.valueElement, cssClasses);
1159
+ if (valueType !== 'object' && this.#valueElement) {
1160
+ this.applySearch(regex, this.#valueElement, cssClasses);
1128
1161
  }
1129
1162
  }
1130
1163
 
@@ -1186,17 +1219,6 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1186
1219
  }
1187
1220
  }
1188
1221
 
1189
- override ondblclick(event: Event): boolean {
1190
- const target = (event.target as HTMLElement);
1191
- const inEditableElement = target.isSelfOrDescendant(this.valueElement) ||
1192
- (this.expandedValueElement && target.isSelfOrDescendant(this.expandedValueElement));
1193
- if (this.property.object && !this.property.object.customPreview() && inEditableElement &&
1194
- (this.property.property.writable || this.property.property.setter)) {
1195
- this.startEditing();
1196
- }
1197
- return false;
1198
- }
1199
-
1200
1222
  override onenter(): boolean {
1201
1223
  if (this.property.object && !this.property.object.customPreview() &&
1202
1224
  (this.property.property.writable || this.property.property.setter)) {
@@ -1207,7 +1229,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1207
1229
  }
1208
1230
 
1209
1231
  override onattach(): void {
1210
- this.update();
1232
+ this.performUpdate();
1211
1233
  this.updateExpandable();
1212
1234
  }
1213
1235
 
@@ -1219,88 +1241,6 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1219
1241
  this.performUpdate();
1220
1242
  }
1221
1243
 
1222
- private createExpandedValueElement(value: SDK.RemoteObject.RemoteObject, isSyntheticProperty: boolean): HTMLElement
1223
- |undefined {
1224
- const needsAlternateValue = value.hasChildren && !value.customPreview() && value.subtype !== 'node' &&
1225
- value.type !== 'function' && (value.type !== 'object' || value.preview);
1226
- if (!needsAlternateValue) {
1227
- return undefined;
1228
- }
1229
-
1230
- const valueElement = document.createElement('span');
1231
- valueElement.classList.add('value');
1232
- if (value.description === 'Object') {
1233
- valueElement.textContent = '';
1234
- } else {
1235
- valueElement.setTextContentTruncatedIfNeeded(value.description || '');
1236
- }
1237
- valueElement.classList.add('object-value-' + (value.subtype || value.type));
1238
- UI.Tooltip.Tooltip.install(valueElement, value.description || '');
1239
- if (!isSyntheticProperty) {
1240
- ObjectPropertiesSection.appendMemoryIcon(valueElement, value);
1241
- }
1242
- return valueElement;
1243
- }
1244
-
1245
- update(): void {
1246
- this.nameElement =
1247
- (ObjectPropertiesSection.createNameElement(this.property.name, this.property.property.private) as HTMLElement);
1248
- if (!this.property.property.enumerable) {
1249
- this.nameElement.classList.add('object-properties-section-dimmed');
1250
- }
1251
- if (this.property.property.isOwn) {
1252
- this.nameElement.classList.add('own-property');
1253
- }
1254
- if (this.property.property.synthetic) {
1255
- this.nameElement.classList.add('synthetic-property');
1256
- }
1257
- this.nameElement.title = this.property.path;
1258
-
1259
- const isInternalEntries = this.property.property.synthetic && this.property.name === '[[Entries]]';
1260
- if (isInternalEntries) {
1261
- this.valueElement = document.createElement('span');
1262
- this.valueElement.classList.add('value');
1263
- } else if (this.property.object) {
1264
- const showPreview = this.property.name !== '[[Prototype]]';
1265
- this.propertyValue = ObjectPropertiesSection.createPropertyValueWithCustomSupport(
1266
- this.property.object, this.property.property.wasThrown, showPreview, this.linkifier,
1267
- this.property.property.synthetic, this.property.path /* variableName */);
1268
- this.valueElement = this.propertyValue;
1269
- } else if (this.property.property.getter) {
1270
- this.valueElement = document.createElement('span');
1271
- const element = this.valueElement.createChild('span');
1272
- element.textContent = i18nString(UIStrings.dots);
1273
- element.classList.add('object-value-calculate-value-button');
1274
- UI.Tooltip.Tooltip.install(element, i18nString(UIStrings.invokePropertyGetter));
1275
- const getter = this.property.property.getter;
1276
- element.addEventListener('click', (event: Event) => {
1277
- event.consume();
1278
- const invokeGetter = `
1279
- function invokeGetter(getter) {
1280
- return Reflect.apply(getter, this, []);
1281
- }`;
1282
- // Also passing a string instead of a Function to avoid coverage implementation messing with it.
1283
- void this.property.parent
1284
- ?.object
1285
- // @ts-expect-error No way to teach TypeScript to preserve the Function-ness of `getter`.
1286
- ?.callFunction(invokeGetter, [SDK.RemoteObject.RemoteObject.toCallArgument(getter)])
1287
- .then(this.onInvokeGetterClick.bind(this));
1288
- }, false);
1289
- } else {
1290
- this.valueElement = document.createElement('span');
1291
- this.valueElement.classList.add('object-value-unavailable');
1292
- this.valueElement.textContent = i18nString(UIStrings.valueUnavailable);
1293
- UI.Tooltip.Tooltip.install(this.valueElement, i18nString(UIStrings.valueNotAccessibleToTheDebugger));
1294
- }
1295
-
1296
- const valueText = this.valueElement.textContent;
1297
- if (this.property.object && valueText && !this.property.property.wasThrown) {
1298
- this.expandedValueElement =
1299
- this.createExpandedValueElement(this.property.object, this.property.property.synthetic);
1300
- }
1301
- this.performUpdate();
1302
- }
1303
-
1304
1244
  async #updateCompletions(expression: string, filter: string, force: boolean): Promise<void> {
1305
1245
  const suggestions = await TextEditor.JavaScript.completeInContext(expression, filter, force);
1306
1246
  this.#completions = suggestions.map(v => v.text);
@@ -1309,18 +1249,27 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1309
1249
 
1310
1250
  performUpdate(): void {
1311
1251
  const input: TreeElementViewInput = {
1312
- expandedValueElement: this.expandedValueElement,
1313
1252
  expanded: this.expanded,
1314
1253
  editing: this.#editing,
1315
1254
  editingEnded: this.editingEnded.bind(this),
1316
1255
  editingCommitted: this.editingCommitted.bind(this),
1317
1256
  node: this.property,
1318
- nameElement: this.nameElement,
1319
- valueElement: this.valueElement,
1257
+ linkifier: this.linkifier,
1320
1258
  completions: this.#editing ? this.#completions : [],
1321
1259
  onAutoComplete: this.#updateCompletions.bind(this),
1260
+ invokeGetter: this.onInvokeGetterClick.bind(this),
1261
+ startEditing: this.startEditing.bind(this),
1322
1262
  };
1323
- this.#view(input, {}, this.listItemElement);
1263
+ const that = this;
1264
+ const output: TreeElementViewOutput = {
1265
+ set nameElement(e: Element|undefined) {
1266
+ that.#nameElement = e;
1267
+ },
1268
+ set valueElement(e: Element|undefined) {
1269
+ that.#valueElement = e;
1270
+ },
1271
+ };
1272
+ this.#view(input, output, this.listItemElement);
1324
1273
  }
1325
1274
 
1326
1275
  getContextMenu(event: Event): UI.ContextMenu.ContextMenu {
@@ -1342,9 +1291,9 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1342
1291
  i18nString(UIStrings.copyValue), copyValueHandler, {jslogContext: 'copy-value'});
1343
1292
  }
1344
1293
  }
1345
- if (!this.property.property.synthetic && this.nameElement?.title) {
1294
+ if (!this.property.property.synthetic && this.property.path) {
1346
1295
  const copyPathHandler = Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText.bind(
1347
- Host.InspectorFrontendHost.InspectorFrontendHostInstance, this.nameElement.title);
1296
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance, this.property.path);
1348
1297
  contextMenu.clipboardSection().appendItem(
1349
1298
  i18nString(UIStrings.copyPropertyPath), copyPathHandler, {jslogContext: 'copy-property-path'});
1350
1299
  }
@@ -1418,7 +1367,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1418
1367
  void parent.onpopulate();
1419
1368
  }
1420
1369
  } else {
1421
- this.update();
1370
+ this.performUpdate();
1422
1371
  }
1423
1372
  return;
1424
1373
  }
@@ -1428,7 +1377,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1428
1377
  expression ? parentObject.setPropertyValue(property, expression) : parentObject.deleteProperty(property);
1429
1378
  const error = await errorPromise;
1430
1379
  if (error) {
1431
- this.update();
1380
+ this.performUpdate();
1432
1381
  return;
1433
1382
  }
1434
1383
 
@@ -1452,14 +1401,23 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1452
1401
  this.property.removeChildren();
1453
1402
  }
1454
1403
 
1455
- private onInvokeGetterClick(result: SDK.RemoteObject.CallFunctionResult): void {
1456
- if (!result.object) {
1404
+ async onInvokeGetterClick(getter: SDK.RemoteObject.RemoteObject): Promise<void> {
1405
+ const invokeGetter = `
1406
+ function invokeGetter(getter) {
1407
+ return Reflect.apply(getter, this, []);
1408
+ }`;
1409
+ // Also passing a string instead of a Function to avoid coverage implementation messing with it.
1410
+ const result = await this.property.parent
1411
+ ?.object
1412
+ // @ts-expect-error No way to teach TypeScript to preserve the Function-ness of `getter`.
1413
+ ?.callFunction(invokeGetter, [SDK.RemoteObject.RemoteObject.toCallArgument(getter)]);
1414
+ if (!result?.object) {
1457
1415
  return;
1458
1416
  }
1459
1417
  this.property.property.value = result.object;
1460
1418
  this.property.property.wasThrown = result.wasThrown || false;
1461
1419
 
1462
- this.update();
1420
+ this.performUpdate();
1463
1421
  this.invalidateChildren();
1464
1422
  this.updateExpandable();
1465
1423
  }
@@ -1475,7 +1433,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1475
1433
  }
1476
1434
 
1477
1435
  path(): string {
1478
- return this.nameElement.title;
1436
+ return this.property.path;
1479
1437
  }
1480
1438
  }
1481
1439
 
@@ -1788,10 +1746,10 @@ export class ExpandableTextPropertyValue {
1788
1746
  private readonly maxDisplayableTextLength: number;
1789
1747
  readonly #byteCount: number;
1790
1748
  #expanded = false;
1791
- #element: HTMLElement;
1749
+ #element: DocumentFragment;
1792
1750
 
1793
- constructor(element: HTMLElement, text: string, maxLength: number) {
1794
- this.#element = element;
1751
+ constructor(text: string, maxLength: number) {
1752
+ this.#element = document.createDocumentFragment();
1795
1753
  this.text = text;
1796
1754
  this.maxLength = maxLength;
1797
1755
  this.maxDisplayableTextLength = 10000000;
@@ -1799,7 +1757,7 @@ export class ExpandableTextPropertyValue {
1799
1757
  this.#render();
1800
1758
  }
1801
1759
 
1802
- get element(): HTMLElement {
1760
+ get element(): DocumentFragment {
1803
1761
  return this.#element;
1804
1762
  }
1805
1763