chrome-devtools-frontend 1.0.1544076 → 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.
- package/config/typescript/tsconfig.eslint.json +1 -0
- package/front_end/core/common/ParsedURL.ts +1 -1
- package/front_end/core/common/common.ts +0 -2
- package/front_end/core/protocol_client/CDPConnection.ts +3 -3
- package/front_end/core/protocol_client/DevToolsCDPConnection.ts +2 -1
- package/front_end/core/sdk/CSSMetadata.ts +17 -5
- package/front_end/core/sdk/NetworkManager.ts +6 -8
- package/front_end/core/sdk/NetworkRequest.ts +4 -0
- package/front_end/core/sdk/SDKModel.ts +4 -2
- package/front_end/core/sdk/TargetManager.ts +14 -15
- package/front_end/generated/Deprecation.ts +4 -0
- package/front_end/generated/InspectorBackendCommands.ts +2 -5
- package/front_end/generated/SupportedCSSProperties.js +0 -23
- package/front_end/generated/protocol-mapping.d.ts +0 -15
- package/front_end/generated/protocol-proxy-api.d.ts +0 -11
- package/front_end/generated/protocol.ts +2 -34
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -1
- package/front_end/panels/ai_assistance/components/UserActionRow.ts +2 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +6 -7
- package/front_end/panels/application/{components/FrameDetailsView.ts → FrameDetailsView.ts} +134 -165
- package/front_end/panels/application/{components/OriginTrialTreeView.ts → OriginTrialTreeView.ts} +9 -9
- package/front_end/panels/application/application.ts +4 -0
- package/front_end/panels/application/components/StackTrace.ts +5 -3
- package/front_end/panels/application/components/components.ts +2 -4
- package/front_end/panels/application/{components/frameDetailsReportView.css → frameDetailsReportView.css} +5 -1
- package/front_end/panels/common/BadgeNotification.ts +2 -1
- package/front_end/panels/common/DOMLinkifier.ts +7 -2
- package/front_end/panels/common/GdpSignUpDialog.ts +2 -1
- package/front_end/panels/elements/ElementStatePaneWidget.ts +2 -1
- package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
- package/front_end/panels/elements/elements-meta.ts +0 -22
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +3 -6
- package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +2 -1
- package/front_end/panels/settings/SettingsScreen.ts +3 -2
- package/front_end/panels/timeline/components/LiveMetricsView.ts +14 -5
- package/front_end/panels/timeline/components/MetricCard.ts +2 -2
- package/front_end/panels/timeline/components/insights/NodeLink.ts +2 -3
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +2 -1
- package/front_end/panels/timeline/timeline-meta.ts +0 -10
- package/front_end/panels/timeline/timeline.ts +0 -2
- package/front_end/panels/whats_new/ReleaseNoteView.ts +2 -1
- package/front_end/panels/whats_new/WhatsNewImpl.ts +3 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/tsconfig.json +1 -0
- package/front_end/ui/components/buttons/Button.docs.ts +6 -5
- package/front_end/ui/components/snackbars/Snackbars.docs.ts +1 -1
- package/front_end/ui/components/spinners/Spinners.docs.ts +1 -1
- package/front_end/ui/components/survey_link/SurveyLink.docs.ts +2 -1
- package/front_end/ui/components/switch/Switch.docs.ts +1 -1
- package/front_end/ui/components/tooltips/Tooltip.docs.ts +3 -3
- package/front_end/ui/helpers/OpenInNewTab.ts +87 -0
- package/front_end/ui/helpers/helpers.ts +5 -0
- package/front_end/ui/legacy/ContextMenu.docs.ts +12 -11
- package/front_end/ui/legacy/RadioButton.docs.ts +1 -1
- package/front_end/ui/legacy/SelectMenu.docs.ts +1 -1
- package/front_end/ui/legacy/Slider.docs.ts +1 -1
- package/front_end/ui/legacy/UIUtils.ts +0 -33
- package/front_end/ui/legacy/XLink.ts +4 -4
- package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +2 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +144 -143
- package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -1
- package/mcp/tsconfig.json +16 -0
- package/package.json +2 -2
- package/front_end/core/common/Linkifier.ts +0 -55
- package/front_end/panels/timeline/CLSLinkifier.ts +0 -58
- /package/front_end/panels/application/{components/originTrialTokenRows.css → originTrialTokenRows.css} +0 -0
- /package/front_end/panels/application/{components/originTrialTreeView.css → originTrialTreeView.css} +0 -0
|
@@ -40,7 +40,6 @@ import * as Common from '../../core/common/common.js';
|
|
|
40
40
|
import * as Host from '../../core/host/host.js';
|
|
41
41
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
42
42
|
import * as Platform from '../../core/platform/platform.js';
|
|
43
|
-
import * as Root from '../../core/root/root.js';
|
|
44
43
|
import * as Geometry from '../../models/geometry/geometry.js';
|
|
45
44
|
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
46
45
|
import * as Buttons from '../components/buttons/buttons.js';
|
|
@@ -1989,38 +1988,6 @@ export function measuredScrollbarWidth(document?: Document|null): number {
|
|
|
1989
1988
|
return cachedMeasuredScrollbarWidth;
|
|
1990
1989
|
}
|
|
1991
1990
|
|
|
1992
|
-
/**
|
|
1993
|
-
* Opens the given `url` in a new Chrome tab.
|
|
1994
|
-
*
|
|
1995
|
-
* If the `url` is a Google owned documentation page (currently that includes
|
|
1996
|
-
* `web.dev`, `developers.google.com`, and `developer.chrome.com`), the `url`
|
|
1997
|
-
* will also be checked for UTM parameters:
|
|
1998
|
-
*
|
|
1999
|
-
* - If no `utm_source` search parameter is present, this method will add a new
|
|
2000
|
-
* search parameter `utm_source=devtools` to `url`.
|
|
2001
|
-
* - If no `utm_campaign` search parameter is present, and DevTools is running
|
|
2002
|
-
* within a branded build, this method will add `utm_campaign=<channel>` to
|
|
2003
|
-
* the search parameters, with `<channel>` being the release channel of
|
|
2004
|
-
* Chrome ("stable", "beta", "dev", or "canary").
|
|
2005
|
-
*
|
|
2006
|
-
* @param url the URL to open in a new tab.
|
|
2007
|
-
* @throws TypeError if `url` is not a valid URL.
|
|
2008
|
-
* @see https://en.wikipedia.org/wiki/UTM_parameters
|
|
2009
|
-
*/
|
|
2010
|
-
export function openInNewTab(url: URL|string): void {
|
|
2011
|
-
url = new URL(`${url}`);
|
|
2012
|
-
if (['developer.chrome.com', 'developers.google.com', 'web.dev'].includes(url.hostname)) {
|
|
2013
|
-
if (!url.searchParams.has('utm_source')) {
|
|
2014
|
-
url.searchParams.append('utm_source', 'devtools');
|
|
2015
|
-
}
|
|
2016
|
-
const {channel} = Root.Runtime.hostConfig;
|
|
2017
|
-
if (!url.searchParams.has('utm_campaign') && typeof channel === 'string') {
|
|
2018
|
-
url.searchParams.append('utm_campaign', channel);
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(Platform.DevToolsPath.urlString`${url}`);
|
|
2022
|
-
}
|
|
2023
|
-
|
|
2024
1991
|
export interface PromotionDisplayState {
|
|
2025
1992
|
displayCount: number;
|
|
2026
1993
|
firstRegistered: number;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Host from '../../core/host/host.js';
|
|
6
6
|
import * as Platform from '../../core/platform/platform.js';
|
|
7
|
+
import * as UIHelpers from '../helpers/helpers.js';
|
|
7
8
|
import * as VisualLogging from '../visual_logging/visual_logging.js';
|
|
8
9
|
|
|
9
10
|
import * as ARIAUtils from './ARIAUtils.js';
|
|
@@ -13,7 +14,6 @@ import {Tooltip} from './Tooltip.js';
|
|
|
13
14
|
import {
|
|
14
15
|
copyLinkAddressLabel,
|
|
15
16
|
MaxLengthForDisplayedURLs,
|
|
16
|
-
openInNewTab,
|
|
17
17
|
openLinkExternallyLabel,
|
|
18
18
|
} from './UIUtils.js';
|
|
19
19
|
import {XElement} from './XElement.js';
|
|
@@ -54,14 +54,14 @@ export class XLink extends XElement {
|
|
|
54
54
|
this.onClick = (event: Event) => {
|
|
55
55
|
event.consume(true);
|
|
56
56
|
if (this.#href) {
|
|
57
|
-
openInNewTab(this.#href);
|
|
57
|
+
UIHelpers.openInNewTab(this.#href);
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
60
|
this.onKeyDown = (event: KeyboardEvent) => {
|
|
61
61
|
if (Platform.KeyboardUtilities.isEnterOrSpaceKey(event)) {
|
|
62
62
|
event.consume(true);
|
|
63
63
|
if (this.#href) {
|
|
64
|
-
openInNewTab(this.#href);
|
|
64
|
+
UIHelpers.openInNewTab(this.#href);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
};
|
|
@@ -140,7 +140,7 @@ export class ContextMenuProvider implements Provider<Node> {
|
|
|
140
140
|
const node: XLink = targetNode;
|
|
141
141
|
contextMenu.revealSection().appendItem(openLinkExternallyLabel(), () => {
|
|
142
142
|
if (node.href) {
|
|
143
|
-
openInNewTab(node.href);
|
|
143
|
+
UIHelpers.openInNewTab(node.href);
|
|
144
144
|
}
|
|
145
145
|
}, {jslogContext: 'open-in-new-tab'});
|
|
146
146
|
contextMenu.revealSection().appendItem(copyLinkAddressLabel(), () => {
|
|
@@ -11,6 +11,7 @@ import * as i18n from '../../../../core/i18n/i18n.js';
|
|
|
11
11
|
import * as Platform from '../../../../core/platform/platform.js';
|
|
12
12
|
import * as Root from '../../../../core/root/root.js';
|
|
13
13
|
import * as IconButton from '../../../../ui/components/icon_button/icon_button.js';
|
|
14
|
+
import * as UIHelpers from '../../../helpers/helpers.js';
|
|
14
15
|
import * as UI from '../../legacy.js';
|
|
15
16
|
|
|
16
17
|
import {type ContrastInfo, Events as ContrastInfoEvents} from './ContrastInfo.js';
|
|
@@ -363,7 +364,7 @@ export class ContrastDetails extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
363
364
|
}
|
|
364
365
|
|
|
365
366
|
private static showHelp(): void {
|
|
366
|
-
|
|
367
|
+
UIHelpers.openInNewTab('https://web.dev/color-and-contrast-accessibility/');
|
|
367
368
|
}
|
|
368
369
|
|
|
369
370
|
setVisible(visible: boolean): void {
|
|
@@ -49,7 +49,7 @@ import objectPropertiesSectionStyles from './objectPropertiesSection.css.js';
|
|
|
49
49
|
import objectValueStyles from './objectValue.css.js';
|
|
50
50
|
import {RemoteObjectPreviewFormatter, renderNodeTitle} from './RemoteObjectPreviewFormatter.js';
|
|
51
51
|
|
|
52
|
-
const {repeat, ifDefined} = Directives;
|
|
52
|
+
const {ref, repeat, ifDefined, classMap} = Directives;
|
|
53
53
|
const UIStrings = {
|
|
54
54
|
/**
|
|
55
55
|
* @description Text in Object Properties Section
|
|
@@ -874,45 +874,116 @@ export class RootElement extends UI.TreeOutline.TreeElement {
|
|
|
874
874
|
export const InitialVisibleChildrenLimit = 200;
|
|
875
875
|
|
|
876
876
|
export interface TreeElementViewInput {
|
|
877
|
+
startEditing(): unknown;
|
|
878
|
+
invokeGetter(getter: SDK.RemoteObject.RemoteObject): unknown;
|
|
877
879
|
onAutoComplete(expression: string, filter: string, force: boolean): unknown;
|
|
880
|
+
linkifier: Components.Linkifier.Linkifier|undefined;
|
|
878
881
|
completions: string[];
|
|
879
|
-
expandedValueElement: HTMLElement|undefined;
|
|
880
882
|
expanded: boolean;
|
|
881
883
|
editing: boolean;
|
|
882
884
|
editingEnded(): unknown;
|
|
883
885
|
editingCommitted(detail: string): unknown;
|
|
884
886
|
node: ObjectTreeNode;
|
|
885
|
-
nameElement: HTMLElement;
|
|
886
|
-
valueElement: HTMLElement;
|
|
887
887
|
}
|
|
888
|
-
|
|
888
|
+
interface TreeElementViewOutput {
|
|
889
|
+
valueElement: Element|undefined;
|
|
890
|
+
nameElement: Element|undefined;
|
|
891
|
+
}
|
|
892
|
+
type TreeElementView = (input: TreeElementViewInput, output: TreeElementViewOutput, target: HTMLElement) => void;
|
|
889
893
|
export const TREE_ELEMENT_DEFAULT_VIEW: TreeElementView = (input, output, target) => {
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
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
|
|
916
987
|
};
|
|
917
988
|
export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
918
989
|
property: ObjectTreeNode;
|
|
@@ -920,15 +991,13 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
920
991
|
private highlightChanges: UI.UIUtils.HighlightChange[];
|
|
921
992
|
private linkifier: Components.Linkifier.Linkifier|undefined;
|
|
922
993
|
private readonly maxNumPropertiesToShow: number;
|
|
923
|
-
nameElement!: HTMLElement;
|
|
924
|
-
valueElement!: HTMLElement;
|
|
925
994
|
readOnly!: boolean;
|
|
926
995
|
private prompt!: ObjectPropertyPrompt|undefined;
|
|
927
|
-
private editableDiv!: HTMLElement;
|
|
928
|
-
expandedValueElement?: HTMLElement;
|
|
929
996
|
#editing = false;
|
|
930
997
|
readonly #view: TreeElementView;
|
|
931
998
|
#completions: string[] = [];
|
|
999
|
+
#nameElement: Element|undefined;
|
|
1000
|
+
#valueElement: Element|undefined;
|
|
932
1001
|
constructor(property: ObjectTreeNode, linkifier?: Components.Linkifier.Linkifier, view = TREE_ELEMENT_DEFAULT_VIEW) {
|
|
933
1002
|
// Pass an empty title, the title gets made later in onattach.
|
|
934
1003
|
super();
|
|
@@ -1071,6 +1140,10 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1071
1140
|
return rootElement;
|
|
1072
1141
|
}
|
|
1073
1142
|
|
|
1143
|
+
get nameElement(): Element|undefined {
|
|
1144
|
+
return this.#nameElement;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1074
1147
|
setSearchRegex(regex: RegExp, additionalCssClassName?: string): boolean {
|
|
1075
1148
|
let cssClasses = UI.UIUtils.highlightedSearchResultClassName;
|
|
1076
1149
|
if (additionalCssClassName) {
|
|
@@ -1078,11 +1151,13 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1078
1151
|
}
|
|
1079
1152
|
this.revertHighlightChanges();
|
|
1080
1153
|
|
|
1081
|
-
|
|
1154
|
+
if (this.#nameElement) {
|
|
1155
|
+
this.applySearch(regex, this.#nameElement, cssClasses);
|
|
1156
|
+
}
|
|
1082
1157
|
if (this.property.object) {
|
|
1083
1158
|
const valueType = this.property.object.type;
|
|
1084
|
-
if (valueType !== 'object') {
|
|
1085
|
-
this.applySearch(regex, this
|
|
1159
|
+
if (valueType !== 'object' && this.#valueElement) {
|
|
1160
|
+
this.applySearch(regex, this.#valueElement, cssClasses);
|
|
1086
1161
|
}
|
|
1087
1162
|
}
|
|
1088
1163
|
|
|
@@ -1144,17 +1219,6 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1144
1219
|
}
|
|
1145
1220
|
}
|
|
1146
1221
|
|
|
1147
|
-
override ondblclick(event: Event): boolean {
|
|
1148
|
-
const target = (event.target as HTMLElement);
|
|
1149
|
-
const inEditableElement = target.isSelfOrDescendant(this.valueElement) ||
|
|
1150
|
-
(this.expandedValueElement && target.isSelfOrDescendant(this.expandedValueElement));
|
|
1151
|
-
if (this.property.object && !this.property.object.customPreview() && inEditableElement &&
|
|
1152
|
-
(this.property.property.writable || this.property.property.setter)) {
|
|
1153
|
-
this.startEditing();
|
|
1154
|
-
}
|
|
1155
|
-
return false;
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
1222
|
override onenter(): boolean {
|
|
1159
1223
|
if (this.property.object && !this.property.object.customPreview() &&
|
|
1160
1224
|
(this.property.property.writable || this.property.property.setter)) {
|
|
@@ -1165,7 +1229,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1165
1229
|
}
|
|
1166
1230
|
|
|
1167
1231
|
override onattach(): void {
|
|
1168
|
-
this.
|
|
1232
|
+
this.performUpdate();
|
|
1169
1233
|
this.updateExpandable();
|
|
1170
1234
|
}
|
|
1171
1235
|
|
|
@@ -1177,87 +1241,6 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1177
1241
|
this.performUpdate();
|
|
1178
1242
|
}
|
|
1179
1243
|
|
|
1180
|
-
private createExpandedValueElement(value: SDK.RemoteObject.RemoteObject, isSyntheticProperty: boolean): HTMLElement
|
|
1181
|
-
|undefined {
|
|
1182
|
-
const needsAlternateValue = value.hasChildren && !value.customPreview() && value.subtype !== 'node' &&
|
|
1183
|
-
value.type !== 'function' && (value.type !== 'object' || value.preview);
|
|
1184
|
-
if (!needsAlternateValue) {
|
|
1185
|
-
return undefined;
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
const valueElement = document.createElement('span');
|
|
1189
|
-
valueElement.classList.add('value');
|
|
1190
|
-
if (value.description === 'Object') {
|
|
1191
|
-
valueElement.textContent = '';
|
|
1192
|
-
} else {
|
|
1193
|
-
valueElement.setTextContentTruncatedIfNeeded(value.description || '');
|
|
1194
|
-
}
|
|
1195
|
-
valueElement.classList.add('object-value-' + (value.subtype || value.type));
|
|
1196
|
-
UI.Tooltip.Tooltip.install(valueElement, value.description || '');
|
|
1197
|
-
if (!isSyntheticProperty) {
|
|
1198
|
-
ObjectPropertiesSection.appendMemoryIcon(valueElement, value);
|
|
1199
|
-
}
|
|
1200
|
-
return valueElement;
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
update(): void {
|
|
1204
|
-
this.nameElement =
|
|
1205
|
-
(ObjectPropertiesSection.createNameElement(this.property.name, this.property.property.private) as HTMLElement);
|
|
1206
|
-
if (!this.property.property.enumerable) {
|
|
1207
|
-
this.nameElement.classList.add('object-properties-section-dimmed');
|
|
1208
|
-
}
|
|
1209
|
-
if (this.property.property.isOwn) {
|
|
1210
|
-
this.nameElement.classList.add('own-property');
|
|
1211
|
-
}
|
|
1212
|
-
if (this.property.property.synthetic) {
|
|
1213
|
-
this.nameElement.classList.add('synthetic-property');
|
|
1214
|
-
}
|
|
1215
|
-
this.nameElement.title = this.property.path;
|
|
1216
|
-
|
|
1217
|
-
const isInternalEntries = this.property.property.synthetic && this.property.name === '[[Entries]]';
|
|
1218
|
-
if (isInternalEntries) {
|
|
1219
|
-
this.valueElement = document.createElement('span');
|
|
1220
|
-
this.valueElement.classList.add('value');
|
|
1221
|
-
} else if (this.property.object) {
|
|
1222
|
-
const showPreview = this.property.name !== '[[Prototype]]';
|
|
1223
|
-
this.valueElement = ObjectPropertiesSection.createPropertyValueWithCustomSupport(
|
|
1224
|
-
this.property.object, this.property.property.wasThrown, showPreview, this.linkifier,
|
|
1225
|
-
this.property.property.synthetic, this.property.path /* variableName */);
|
|
1226
|
-
} else if (this.property.property.getter) {
|
|
1227
|
-
this.valueElement = document.createElement('span');
|
|
1228
|
-
const element = this.valueElement.createChild('span');
|
|
1229
|
-
element.textContent = i18nString(UIStrings.dots);
|
|
1230
|
-
element.classList.add('object-value-calculate-value-button');
|
|
1231
|
-
UI.Tooltip.Tooltip.install(element, i18nString(UIStrings.invokePropertyGetter));
|
|
1232
|
-
const getter = this.property.property.getter;
|
|
1233
|
-
element.addEventListener('click', (event: Event) => {
|
|
1234
|
-
event.consume();
|
|
1235
|
-
const invokeGetter = `
|
|
1236
|
-
function invokeGetter(getter) {
|
|
1237
|
-
return Reflect.apply(getter, this, []);
|
|
1238
|
-
}`;
|
|
1239
|
-
// Also passing a string instead of a Function to avoid coverage implementation messing with it.
|
|
1240
|
-
void this.property.parent
|
|
1241
|
-
?.object
|
|
1242
|
-
// @ts-expect-error No way to teach TypeScript to preserve the Function-ness of `getter`.
|
|
1243
|
-
?.callFunction(invokeGetter, [SDK.RemoteObject.RemoteObject.toCallArgument(getter)])
|
|
1244
|
-
.then(this.onInvokeGetterClick.bind(this));
|
|
1245
|
-
}, false);
|
|
1246
|
-
} else {
|
|
1247
|
-
this.valueElement = document.createElement('span');
|
|
1248
|
-
this.valueElement.classList.add('object-value-unavailable');
|
|
1249
|
-
this.valueElement.textContent = i18nString(UIStrings.valueUnavailable);
|
|
1250
|
-
UI.Tooltip.Tooltip.install(this.valueElement, i18nString(UIStrings.valueNotAccessibleToTheDebugger));
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
const valueText = this.valueElement.textContent;
|
|
1254
|
-
if (this.property.object && valueText && !this.property.property.wasThrown) {
|
|
1255
|
-
this.expandedValueElement =
|
|
1256
|
-
this.createExpandedValueElement(this.property.object, this.property.property.synthetic);
|
|
1257
|
-
}
|
|
1258
|
-
this.performUpdate();
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
1244
|
async #updateCompletions(expression: string, filter: string, force: boolean): Promise<void> {
|
|
1262
1245
|
const suggestions = await TextEditor.JavaScript.completeInContext(expression, filter, force);
|
|
1263
1246
|
this.#completions = suggestions.map(v => v.text);
|
|
@@ -1266,18 +1249,27 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1266
1249
|
|
|
1267
1250
|
performUpdate(): void {
|
|
1268
1251
|
const input: TreeElementViewInput = {
|
|
1269
|
-
expandedValueElement: this.expandedValueElement,
|
|
1270
1252
|
expanded: this.expanded,
|
|
1271
1253
|
editing: this.#editing,
|
|
1272
1254
|
editingEnded: this.editingEnded.bind(this),
|
|
1273
1255
|
editingCommitted: this.editingCommitted.bind(this),
|
|
1274
1256
|
node: this.property,
|
|
1275
|
-
|
|
1276
|
-
valueElement: this.valueElement,
|
|
1257
|
+
linkifier: this.linkifier,
|
|
1277
1258
|
completions: this.#editing ? this.#completions : [],
|
|
1278
1259
|
onAutoComplete: this.#updateCompletions.bind(this),
|
|
1260
|
+
invokeGetter: this.onInvokeGetterClick.bind(this),
|
|
1261
|
+
startEditing: this.startEditing.bind(this),
|
|
1279
1262
|
};
|
|
1280
|
-
|
|
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);
|
|
1281
1273
|
}
|
|
1282
1274
|
|
|
1283
1275
|
getContextMenu(event: Event): UI.ContextMenu.ContextMenu {
|
|
@@ -1299,9 +1291,9 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1299
1291
|
i18nString(UIStrings.copyValue), copyValueHandler, {jslogContext: 'copy-value'});
|
|
1300
1292
|
}
|
|
1301
1293
|
}
|
|
1302
|
-
if (!this.property.property.synthetic && this.
|
|
1294
|
+
if (!this.property.property.synthetic && this.property.path) {
|
|
1303
1295
|
const copyPathHandler = Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText.bind(
|
|
1304
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance, this.
|
|
1296
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance, this.property.path);
|
|
1305
1297
|
contextMenu.clipboardSection().appendItem(
|
|
1306
1298
|
i18nString(UIStrings.copyPropertyPath), copyPathHandler, {jslogContext: 'copy-property-path'});
|
|
1307
1299
|
}
|
|
@@ -1375,7 +1367,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1375
1367
|
void parent.onpopulate();
|
|
1376
1368
|
}
|
|
1377
1369
|
} else {
|
|
1378
|
-
this.
|
|
1370
|
+
this.performUpdate();
|
|
1379
1371
|
}
|
|
1380
1372
|
return;
|
|
1381
1373
|
}
|
|
@@ -1385,7 +1377,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1385
1377
|
expression ? parentObject.setPropertyValue(property, expression) : parentObject.deleteProperty(property);
|
|
1386
1378
|
const error = await errorPromise;
|
|
1387
1379
|
if (error) {
|
|
1388
|
-
this.
|
|
1380
|
+
this.performUpdate();
|
|
1389
1381
|
return;
|
|
1390
1382
|
}
|
|
1391
1383
|
|
|
@@ -1409,14 +1401,23 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1409
1401
|
this.property.removeChildren();
|
|
1410
1402
|
}
|
|
1411
1403
|
|
|
1412
|
-
|
|
1413
|
-
|
|
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) {
|
|
1414
1415
|
return;
|
|
1415
1416
|
}
|
|
1416
1417
|
this.property.property.value = result.object;
|
|
1417
1418
|
this.property.property.wasThrown = result.wasThrown || false;
|
|
1418
1419
|
|
|
1419
|
-
this.
|
|
1420
|
+
this.performUpdate();
|
|
1420
1421
|
this.invalidateChildren();
|
|
1421
1422
|
this.updateExpandable();
|
|
1422
1423
|
}
|
|
@@ -1432,7 +1433,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
1432
1433
|
}
|
|
1433
1434
|
|
|
1434
1435
|
path(): string {
|
|
1435
|
-
return this.
|
|
1436
|
+
return this.property.path;
|
|
1436
1437
|
}
|
|
1437
1438
|
}
|
|
1438
1439
|
|
|
@@ -17,6 +17,7 @@ import * as TextUtils from '../../../../models/text_utils/text_utils.js';
|
|
|
17
17
|
import type * as Trace from '../../../../models/trace/trace.js';
|
|
18
18
|
import * as Workspace from '../../../../models/workspace/workspace.js';
|
|
19
19
|
import type * as IconButton from '../../../components/icon_button/icon_button.js';
|
|
20
|
+
import * as UIHelpers from '../../../helpers/helpers.js';
|
|
20
21
|
import {html, render} from '../../../lit/lit.js';
|
|
21
22
|
import * as VisualLogging from '../../../visual_logging/visual_logging.js';
|
|
22
23
|
import * as UI from '../../legacy.js';
|
|
@@ -920,7 +921,7 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
|
|
|
920
921
|
section: 'reveal',
|
|
921
922
|
title: UI.UIUtils.openLinkExternallyLabel(),
|
|
922
923
|
jslogContext: 'open-in-new-tab',
|
|
923
|
-
handler: () =>
|
|
924
|
+
handler: () => UIHelpers.openInNewTab(url),
|
|
924
925
|
});
|
|
925
926
|
result.push({
|
|
926
927
|
section: 'clipboard',
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../config/typescript/tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"allowUmdGlobalAccess": true,
|
|
5
|
+
"outDir": "ignored",
|
|
6
|
+
"target": "ES2023",
|
|
7
|
+
"lib": [
|
|
8
|
+
"ES2023",
|
|
9
|
+
"ES2024.Promise",
|
|
10
|
+
"ESNext.Iterator",
|
|
11
|
+
"ESNext.Collection",
|
|
12
|
+
"ESNext.Array"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"references": [{ "path": "../front_end/tsconfig.json" }]
|
|
16
|
+
}
|
package/package.json
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@types/glob": "7.2.0",
|
|
47
47
|
"@types/karma-chai-sinon": "0.1.20",
|
|
48
48
|
"@types/mocha": "10.0.10",
|
|
49
|
-
"@types/node": "
|
|
49
|
+
"@types/node": "24.10.0",
|
|
50
50
|
"@types/sinon": "17.0.4",
|
|
51
51
|
"@types/webidl2": "24.4.3",
|
|
52
52
|
"@types/yargs": "17.0.33",
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"flat-cache": "6.1.12"
|
|
104
104
|
}
|
|
105
105
|
},
|
|
106
|
-
"version": "1.0.
|
|
106
|
+
"version": "1.0.1545096"
|
|
107
107
|
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// Copyright 2019 The Chromium Authors
|
|
2
|
-
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
-
// found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
import type * as Platform from '../platform/platform.js';
|
|
6
|
-
|
|
7
|
-
export abstract class Linkifier {
|
|
8
|
-
abstract linkify(object: Object, options?: Options): Node;
|
|
9
|
-
|
|
10
|
-
static async linkify(object: Object|null, options?: Options): Promise<Node> {
|
|
11
|
-
if (!object) {
|
|
12
|
-
throw new Error('Can\'t linkify ' + object);
|
|
13
|
-
}
|
|
14
|
-
const linkifierRegistration = getApplicableRegisteredlinkifiers(object)[0];
|
|
15
|
-
if (!linkifierRegistration) {
|
|
16
|
-
throw new Error('No linkifiers registered for object ' + object);
|
|
17
|
-
}
|
|
18
|
-
const linkifier = await linkifierRegistration.loadLinkifier();
|
|
19
|
-
return linkifier.linkify(object, options);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export interface Options {
|
|
23
|
-
tooltip?: string;
|
|
24
|
-
preventKeyboardFocus?: boolean;
|
|
25
|
-
textContent?: string;
|
|
26
|
-
// Dynamic links include hyperlinks and anchorlinks -- links that navigate the content.
|
|
27
|
-
isDynamicLink?: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const registeredLinkifiers: LinkifierRegistration[] = [];
|
|
31
|
-
|
|
32
|
-
export function registerLinkifier(registration: LinkifierRegistration): void {
|
|
33
|
-
registeredLinkifiers.push(registration);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function getApplicableRegisteredlinkifiers(object: Object): LinkifierRegistration[] {
|
|
37
|
-
return registeredLinkifiers.filter(isLinkifierApplicableToContextTypes);
|
|
38
|
-
|
|
39
|
-
function isLinkifierApplicableToContextTypes(linkifierRegistration: LinkifierRegistration): boolean {
|
|
40
|
-
if (!linkifierRegistration.contextTypes) {
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
for (const contextType of linkifierRegistration.contextTypes()) {
|
|
44
|
-
if (object instanceof contextType) {
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface LinkifierRegistration {
|
|
53
|
-
loadLinkifier: () => Promise<Linkifier>;
|
|
54
|
-
contextTypes?: () => Array<Platform.Constructor.Constructor<unknown>>;
|
|
55
|
-
}
|