chrome-devtools-frontend 1.0.1697595 → 1.0.1697998
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/.stylelintignore +2 -0
- package/front_end/core/common/VersionController.ts +5 -1
- package/front_end/core/sdk/AnimationModel.ts +9 -1
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +8 -2
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +26 -0
- package/front_end/models/ai_assistance/ai_assistance.ts +4 -4
- package/front_end/models/ai_assistance/skills/performance.md +4 -3
- package/front_end/models/ai_assistance/tools/{GetFunctionCode.ts → GetTraceFunctionCode.ts} +26 -13
- package/front_end/models/ai_assistance/tools/{GetResourceContent.ts → GetTraceResourceContent.ts} +31 -11
- package/front_end/models/ai_assistance/tools/Tool.ts +2 -2
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +6 -6
- package/front_end/models/elements/DOMChanges.ts +238 -0
- package/front_end/models/elements/elements.ts +2 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +3 -1
- package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +25 -5
- package/front_end/panels/browser_debugger/ObjectEventListenersSidebarPane.ts +2 -3
- package/front_end/panels/elements/ElementsTreeElement.ts +98 -20
- package/front_end/panels/elements/ElementsTreeOutline.ts +271 -43
- package/front_end/panels/elements/EventListenersWidget.ts +0 -1
- package/front_end/panels/event_listeners/EventListenersView.ts +241 -297
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +1 -1
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +10 -2
- package/front_end/panels/network/NetworkConfigView.ts +141 -116
- package/front_end/panels/network/NetworkPanel.ts +7 -4
- package/front_end/panels/network/RequestHeadersView.ts +1 -1
- package/front_end/panels/network/forward/BackendLinking.ts +5 -2
- package/front_end/panels/settings/BackendLinkingSettingsTab.ts +7 -2
- package/front_end/panels/timeline/TimelineTreeView.ts +11 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/comments/CommentOverlayManager.ts +169 -40
- package/front_end/ui/comments/CommentThreadWidget.ts +221 -0
- package/front_end/ui/comments/CommentsOverlayWidget.ts +124 -12
- package/front_end/ui/comments/commentThreadWidget.css +173 -0
- package/front_end/ui/comments/comments.ts +2 -0
- package/front_end/ui/comments/commentsOverlay.css +6 -0
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +1 -1
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +4 -0
- package/package.json +5 -5
|
@@ -337,7 +337,9 @@ function getMarkdownRenderer(conversation?: AiAssistanceModel.AiConversation.AiC
|
|
|
337
337
|
return new AccessibilityAgentMarkdownRenderer(mainDocumentURL);
|
|
338
338
|
}
|
|
339
339
|
|
|
340
|
-
return new MarkdownRendererWithCodeBlock(
|
|
340
|
+
return new MarkdownRendererWithCodeBlock({
|
|
341
|
+
getEstablishedOrigin: () => conversation?.origin,
|
|
342
|
+
});
|
|
341
343
|
}
|
|
342
344
|
|
|
343
345
|
interface ToolbarViewInput {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Common from '../../../core/common/common.js';
|
|
6
6
|
import * as Platform from '../../../core/platform/platform.js';
|
|
7
|
+
import type * as SDK from '../../../core/sdk/sdk.js';
|
|
7
8
|
import * as AiAssistanceModel from '../../../models/ai_assistance/ai_assistance.js';
|
|
8
9
|
import * as Logs from '../../../models/logs/logs.js';
|
|
9
10
|
import type * as Marked from '../../../third_party/marked/marked.js';
|
|
@@ -12,7 +13,18 @@ import * as Lit from '../../../ui/lit/lit.js';
|
|
|
12
13
|
|
|
13
14
|
const {html} = Lit;
|
|
14
15
|
|
|
16
|
+
export interface MarkdownRendererWithCodeBlockOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Retrieves the established origin locked for the active conversation.
|
|
19
|
+
* Required to authorize #file-<id> links and prevent cross-origin file leakage.
|
|
20
|
+
* When omitted or unauthorized, file links safely render as plain inert text.
|
|
21
|
+
*/
|
|
22
|
+
getEstablishedOrigin?: () => SDK.SecurityOrigin.SecurityOrigin | undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
/**
|
|
26
|
+
* Markdown renderer for AI assistance conversations.
|
|
27
|
+
*
|
|
16
28
|
* The model returns multiline code blocks in an erroneous way with the language being in new line.
|
|
17
29
|
* This renderer takes that into account and correctly updates the parsed multiline token with the language
|
|
18
30
|
* correctly identified and stripped from the content.
|
|
@@ -23,8 +35,13 @@ const {html} = Lit;
|
|
|
23
35
|
* color: red;
|
|
24
36
|
* }
|
|
25
37
|
* ```
|
|
26
|
-
|
|
38
|
+
*
|
|
39
|
+
* Also handles linkifying DevTools internal resource links (#req- and origin-locked #file-).
|
|
40
|
+
*/
|
|
27
41
|
export class MarkdownRendererWithCodeBlock extends MarkdownView.MarkdownView.MarkdownInsightRenderer {
|
|
42
|
+
constructor(private readonly options: MarkdownRendererWithCodeBlockOptions = {}) {
|
|
43
|
+
super();
|
|
44
|
+
}
|
|
28
45
|
#revealableLink(revealable: unknown, label: string): Lit.LitTemplate {
|
|
29
46
|
return html`<devtools-link @click=${(e: Event) => {
|
|
30
47
|
e.preventDefault();
|
|
@@ -48,13 +65,16 @@ export class MarkdownRendererWithCodeBlock extends MarkdownView.MarkdownView.Mar
|
|
|
48
65
|
return html`${fallbackText}`;
|
|
49
66
|
}
|
|
50
67
|
if (href.startsWith('#file-')) {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
68
|
+
const fileId = Number(href.substring(6));
|
|
69
|
+
const file = AiAssistanceModel.ContextSelectionAgent.ContextSelectionAgent.getSourceById(
|
|
70
|
+
fileId,
|
|
71
|
+
this.options.getEstablishedOrigin?.(),
|
|
72
|
+
);
|
|
54
73
|
|
|
55
74
|
if (file) {
|
|
56
75
|
return this.#revealableLink(file, file.name());
|
|
57
76
|
}
|
|
77
|
+
// Fall back to plain text to prevent rendering unauthorized or unverified links.
|
|
58
78
|
return html`${fallbackText}`;
|
|
59
79
|
}
|
|
60
80
|
return null;
|
|
@@ -78,7 +98,7 @@ export class MarkdownRendererWithCodeBlock extends MarkdownView.MarkdownView.Mar
|
|
|
78
98
|
|
|
79
99
|
if (token.type === 'codespan') {
|
|
80
100
|
// LLM likes outputting the link inside a codespan block.
|
|
81
|
-
// Remove the codespan and render the link directly
|
|
101
|
+
// Remove the codespan and render the link directly.
|
|
82
102
|
const matches = token.text.match(/^\[(.*)\]\((.+)\)$/);
|
|
83
103
|
if (matches?.[2]) {
|
|
84
104
|
const link = this.#renderLink(
|
|
@@ -20,8 +20,6 @@ export class ObjectEventListenersSidebarPane extends UI.Widget.VBox implements U
|
|
|
20
20
|
this.contentElement.setAttribute('jslog', `${VisualLogging.section('sources.global-listeners')}`);
|
|
21
21
|
|
|
22
22
|
this.eventListenersView = new EventListeners.EventListenersView.EventListenersView();
|
|
23
|
-
this.eventListenersView.changeCallback = this.requestUpdate.bind(this);
|
|
24
|
-
this.eventListenersView.enableDefaultTreeFocus = true;
|
|
25
23
|
this.eventListenersView.show(this.element);
|
|
26
24
|
this.setDefaultFocusedChild(this.eventListenersView);
|
|
27
25
|
this.requestUpdate();
|
|
@@ -57,7 +55,8 @@ export class ObjectEventListenersSidebarPane extends UI.Widget.VBox implements U
|
|
|
57
55
|
windowObjects.push(result.object);
|
|
58
56
|
}
|
|
59
57
|
}
|
|
60
|
-
|
|
58
|
+
this.eventListenersView.objects = windowObjects;
|
|
59
|
+
await this.eventListenersView.updateComplete;
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
override wasShown(): void {
|
|
@@ -48,7 +48,8 @@ import * as Protocol from '../../generated/protocol.js';
|
|
|
48
48
|
import * as AIAssistance from '../../models/ai_assistance/ai_assistance.js';
|
|
49
49
|
import * as Badges from '../../models/badges/badges.js';
|
|
50
50
|
import * as Bindings from '../../models/bindings/bindings.js';
|
|
51
|
-
import
|
|
51
|
+
import * as ChangeTracker from '../../models/change_tracker/change_tracker.js';
|
|
52
|
+
import * as Elements from '../../models/elements/elements.js';
|
|
52
53
|
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
|
|
53
54
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
54
55
|
import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
|
|
@@ -65,6 +66,7 @@ import * as PanelsCommon from '../common/common.js';
|
|
|
65
66
|
import * as Media from '../media/media.js';
|
|
66
67
|
|
|
67
68
|
import * as ElementsComponents from './components/components.js';
|
|
69
|
+
import {cssPath} from './DOMPath.js';
|
|
68
70
|
import {getElementIssueDetails} from './ElementIssueUtils.js';
|
|
69
71
|
import {ElementsPanel} from './ElementsPanel.js';
|
|
70
72
|
import * as ElementStatePaneWidget from './ElementStatePaneWidget.js';
|
|
@@ -72,6 +74,33 @@ import {type ElementsTreeOutline, MappedCharToEntity} from './ElementsTreeOutlin
|
|
|
72
74
|
import {ImagePreviewPopover} from './ImagePreviewPopover.js';
|
|
73
75
|
import {getRegisteredDecorators, type MarkerDecorator, type MarkerDecoratorRegistration} from './MarkerDecorator.js';
|
|
74
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Returns the CSS selector of `node` that is used as the text signature of the anchor a change is
|
|
79
|
+
* recorded on, or `undefined` if `tracker` is absent or not recording changes.
|
|
80
|
+
*
|
|
81
|
+
* Resolving the selector walks the ancestor chain and scans sibling lists, so it is skipped
|
|
82
|
+
* entirely while change tracking is disabled.
|
|
83
|
+
*/
|
|
84
|
+
export function buildChangeSelector(tracker: ChangeTracker.ChangeTracker.ChangeTracker|undefined,
|
|
85
|
+
node: SDK.DOMModel.DOMNode): string|undefined {
|
|
86
|
+
if (!tracker?.isTracking) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
if (node.nodeType() === Node.ELEMENT_NODE) {
|
|
90
|
+
const selector = cssPath(node, true);
|
|
91
|
+
if (selector) {
|
|
92
|
+
return selector;
|
|
93
|
+
}
|
|
94
|
+
} else if (node.parentNode && node.parentNode.nodeType() === Node.ELEMENT_NODE) {
|
|
95
|
+
const selector = cssPath(node.parentNode, true);
|
|
96
|
+
if (selector) {
|
|
97
|
+
return selector;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
75
104
|
const {html, nothing, render, Directives: {classMap, ref, repeat, until}} = Lit;
|
|
76
105
|
const {animateOn} = UI.UIUtils;
|
|
77
106
|
|
|
@@ -770,14 +799,6 @@ function renderTag(node: SDK.DOMModel.DOMNode, tagName: string, isClosingTag: bo
|
|
|
770
799
|
hasUpdates = hasUpdates || (!expanded && updateRecord.hasChangedChildren());
|
|
771
800
|
}
|
|
772
801
|
|
|
773
|
-
// We are taking full text content of the tag, including attributes and children, to set the aria label.
|
|
774
|
-
// FIXME: we should compute the aria label ourselves if it is event needed.
|
|
775
|
-
const setAriaLabel = ref(el => {
|
|
776
|
-
if (el?.textContent) {
|
|
777
|
-
UI.ARIAUtils.setLabel(el, el.textContent);
|
|
778
|
-
}
|
|
779
|
-
});
|
|
780
|
-
|
|
781
802
|
const tagNameClass = isClosingTag ? 'webkit-html-close-tag-name' : 'webkit-html-tag-name';
|
|
782
803
|
const hasTagIssues = !isClosingTag && Boolean(issues?.some(issue => {
|
|
783
804
|
const details = getElementIssueDetails(issue);
|
|
@@ -790,8 +811,13 @@ function renderTag(node: SDK.DOMModel.DOMNode, tagName: string, isClosingTag: bo
|
|
|
790
811
|
const tagString = (isClosingTag ? '/' : '') + tagName;
|
|
791
812
|
const jslog = !isClosingTag ? VisualLogging.value('tag-name').track({change: true, dblclick: true}) : '';
|
|
792
813
|
|
|
814
|
+
const ariaLabel = isClosingTag ?
|
|
815
|
+
`</${tagName}>` :
|
|
816
|
+
`<${tagName}${
|
|
817
|
+
attributes.map(attr => (attr.value ? ` ${attr.name}="${attr.value}"` : ` ${attr.name}`)).join('')}>`;
|
|
818
|
+
|
|
793
819
|
return html`<span
|
|
794
|
-
class=${classMap(tagClasses)}
|
|
820
|
+
class=${classMap(tagClasses)} aria-label=${ariaLabel}
|
|
795
821
|
><<span class=${classMap(tagNameClasses)} jslog=${jslog || nothing} ${
|
|
796
822
|
animateOn(hasUpdates, DOM_UPDATE_ANIMATION_CLASS_NAME)}>${tagString}</span>${
|
|
797
823
|
attributes.map(attr => html` ${renderAttribute(attr, updateRecord, false, node, issues)}`)}></span>\u200B`;
|
|
@@ -1102,7 +1128,10 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
1102
1128
|
if (event.key === 'Escape') {
|
|
1103
1129
|
event.consume(true);
|
|
1104
1130
|
}
|
|
1105
|
-
}}
|
|
1131
|
+
}}
|
|
1132
|
+
@mousedown=${(event: Event) => event.stopPropagation()}
|
|
1133
|
+
@click=${(event: Event) => event.stopPropagation()}
|
|
1134
|
+
class="source-code elements-tree-editor" style="width: ${input.editorWidth ?? 0}px;">
|
|
1106
1135
|
<devtools-text-editor .state=${input.editorState} ${ref(el => {
|
|
1107
1136
|
output.editorRef = el as TextEditor.TextEditor.TextEditor;
|
|
1108
1137
|
})}></devtools-text-editor>
|
|
@@ -1124,9 +1153,14 @@ export interface InitialEditState {
|
|
|
1124
1153
|
}
|
|
1125
1154
|
|
|
1126
1155
|
export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
1127
|
-
static override readonly INJECT: readonly[typeof IssuesManager.DOMIssuesManager.DOMIssuesManager
|
|
1128
|
-
|
|
1156
|
+
static override readonly INJECT: readonly[typeof IssuesManager.DOMIssuesManager.DOMIssuesManager,
|
|
1157
|
+
typeof ChangeTracker.ChangeTracker.ChangeTracker] =
|
|
1158
|
+
[
|
|
1159
|
+
IssuesManager.DOMIssuesManager.DOMIssuesManager,
|
|
1160
|
+
ChangeTracker.ChangeTracker.ChangeTracker,
|
|
1161
|
+
] as const;
|
|
1129
1162
|
#domIssuesManager?: IssuesManager.DOMIssuesManager.DOMIssuesManager;
|
|
1163
|
+
#changeTracker?: ChangeTracker.ChangeTracker.ChangeTracker;
|
|
1130
1164
|
|
|
1131
1165
|
#node!: SDK.DOMModel.DOMNode;
|
|
1132
1166
|
#eventsBound = false;
|
|
@@ -1370,13 +1404,25 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
1370
1404
|
return this.#domIssuesManager?.issuesForNode(this.node) ?? [];
|
|
1371
1405
|
}
|
|
1372
1406
|
|
|
1407
|
+
get changeTracker(): ChangeTracker.ChangeTracker.ChangeTracker|undefined {
|
|
1408
|
+
// The widget is currently created for non-widget ElementsTreeElement so
|
|
1409
|
+
// the changeTracker can be empty, relying on the manual resolution.
|
|
1410
|
+
// Note that this only works once the widget is attached to the DOM.
|
|
1411
|
+
this.#changeTracker ??=
|
|
1412
|
+
UI.Widget.lookupUniverseForElement(this.contentElement)?.get(ChangeTracker.ChangeTracker.ChangeTracker);
|
|
1413
|
+
return this.#changeTracker;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1373
1416
|
constructor(
|
|
1374
1417
|
element?: HTMLElement,
|
|
1375
|
-
[domIssuesManager]:
|
|
1418
|
+
[domIssuesManager, changeTracker]:
|
|
1419
|
+
UI.Widget.WidgetDependencies<typeof ElementsTreeWidget>|[IssuesManager.DOMIssuesManager.DOMIssuesManager?,
|
|
1420
|
+
ChangeTracker.ChangeTracker.ChangeTracker?] = [],
|
|
1376
1421
|
view: View = DEFAULT_VIEW,
|
|
1377
1422
|
) {
|
|
1378
1423
|
super(element);
|
|
1379
1424
|
this.#domIssuesManager = domIssuesManager;
|
|
1425
|
+
this.#changeTracker = changeTracker;
|
|
1380
1426
|
this.#view = view;
|
|
1381
1427
|
|
|
1382
1428
|
this.#expandedChildrenLimit = InitialChildrenLimit;
|
|
@@ -1461,6 +1507,7 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
1461
1507
|
}
|
|
1462
1508
|
|
|
1463
1509
|
#clearDOMNextUpdate = false;
|
|
1510
|
+
|
|
1464
1511
|
#isBound = false;
|
|
1465
1512
|
|
|
1466
1513
|
override wasShown(): void {
|
|
@@ -2448,7 +2495,8 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
2448
2495
|
}
|
|
2449
2496
|
// The relatedTarget is null when no element gains focus, e.g. switching windows.
|
|
2450
2497
|
const relatedTarget = (event.relatedTarget as Node | null);
|
|
2451
|
-
if (relatedTarget && !relatedTarget.isSelfOrDescendant(this.#editorRef)
|
|
2498
|
+
if (relatedTarget && !relatedTarget.isSelfOrDescendant(this.#editorRef) &&
|
|
2499
|
+
!relatedTarget.isSelfOrDescendant(this.contentElement)) {
|
|
2452
2500
|
this.editing?.commit();
|
|
2453
2501
|
}
|
|
2454
2502
|
},
|
|
@@ -2595,10 +2643,16 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
2595
2643
|
}
|
|
2596
2644
|
|
|
2597
2645
|
if (attributeName !== null && (attributeName.trim() || newText.trim()) && oldText !== newText) {
|
|
2646
|
+
const edit = {attributeName, oldText, newText};
|
|
2598
2647
|
this.node.setAttribute(attributeName, newText, (error: string|null) => {
|
|
2648
|
+
if (!error) {
|
|
2649
|
+
const changeTracker = this.changeTracker;
|
|
2650
|
+
Elements.DOMChanges.trackAttributeEdit(changeTracker, this.node,
|
|
2651
|
+
buildChangeSelector(changeTracker, this.node), edit);
|
|
2652
|
+
Badges.UserBadges.instance().recordAction(Badges.BadgeAction.DOM_ELEMENT_OR_ATTRIBUTE_EDITED);
|
|
2653
|
+
}
|
|
2599
2654
|
moveToNextAttributeIfNeeded.call(this, error);
|
|
2600
2655
|
});
|
|
2601
|
-
Badges.UserBadges.instance().recordAction(Badges.BadgeAction.DOM_ELEMENT_OR_ATTRIBUTE_EDITED);
|
|
2602
2656
|
return;
|
|
2603
2657
|
}
|
|
2604
2658
|
|
|
@@ -2660,6 +2714,9 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
2660
2714
|
}
|
|
2661
2715
|
|
|
2662
2716
|
Badges.UserBadges.instance().recordAction(Badges.BadgeAction.DOM_ELEMENT_OR_ATTRIBUTE_EDITED);
|
|
2717
|
+
const changeTracker = this.changeTracker;
|
|
2718
|
+
Elements.DOMChanges.trackTagNameEdit(changeTracker, newNode, buildChangeSelector(changeTracker, newNode),
|
|
2719
|
+
oldText ?? tagName ?? '', newText);
|
|
2663
2720
|
if (this.selectNodeAfterEdit) {
|
|
2664
2721
|
this.selectNodeAfterEdit(wasExpanded, error, newNode, moveDirection);
|
|
2665
2722
|
}
|
|
@@ -2668,8 +2725,14 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
2668
2725
|
|
|
2669
2726
|
private textNodeEditingCommitted(textNode: SDK.DOMModel.DOMNode, _element: Element, newText: string): void {
|
|
2670
2727
|
this.editing = null;
|
|
2728
|
+
const oldValue = textNode.nodeValue() ?? '';
|
|
2671
2729
|
|
|
2672
|
-
function callback(this: ElementsTreeWidget): void {
|
|
2730
|
+
function callback(this: ElementsTreeWidget, error?: string|null): void {
|
|
2731
|
+
if (!error && oldValue !== newText) {
|
|
2732
|
+
const changeTracker = this.changeTracker;
|
|
2733
|
+
Elements.DOMChanges.trackTextNodeEdit(changeTracker, textNode, buildChangeSelector(changeTracker, textNode),
|
|
2734
|
+
oldValue, newText);
|
|
2735
|
+
}
|
|
2673
2736
|
this.#clearDOMNextUpdate = true;
|
|
2674
2737
|
this.updateTitle();
|
|
2675
2738
|
}
|
|
@@ -2821,7 +2884,7 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
2821
2884
|
async remove(): Promise<void> {
|
|
2822
2885
|
if (this.isToggledToHidden?.(this.node)) {
|
|
2823
2886
|
// Unhide the node before removing. This avoids inconsistent state if the node is restored via undo.
|
|
2824
|
-
await this.toggleHideElement
|
|
2887
|
+
await this.node.toggleHideElement();
|
|
2825
2888
|
}
|
|
2826
2889
|
if (this.node.pseudoType()) {
|
|
2827
2890
|
return;
|
|
@@ -2830,7 +2893,14 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
2830
2893
|
if (!this.node.parentNode || this.node.parentNode.nodeType() === Node.DOCUMENT_NODE) {
|
|
2831
2894
|
return;
|
|
2832
2895
|
}
|
|
2833
|
-
|
|
2896
|
+
// The selector has to be resolved before the node is detached from the tree.
|
|
2897
|
+
const changeTracker = this.changeTracker;
|
|
2898
|
+
const selector = buildChangeSelector(changeTracker, this.node);
|
|
2899
|
+
await this.node.removeNode((err: string|null) => {
|
|
2900
|
+
if (!err) {
|
|
2901
|
+
Elements.DOMChanges.trackNodeRemoval(changeTracker, this.node, selector);
|
|
2902
|
+
}
|
|
2903
|
+
});
|
|
2834
2904
|
}
|
|
2835
2905
|
|
|
2836
2906
|
toggleEditAsHTML(callback?: ((arg0: boolean) => void), startEditing?: boolean): void {
|
|
@@ -2851,7 +2921,15 @@ export class ElementsTreeWidget extends UI.Widget.Widget {
|
|
|
2851
2921
|
|
|
2852
2922
|
const commitChange = (initialValue: string, value: string): void => {
|
|
2853
2923
|
if (initialValue !== value) {
|
|
2854
|
-
node.
|
|
2924
|
+
// The selector has to be resolved before the node is detached from the tree.
|
|
2925
|
+
const changeTracker = this.changeTracker;
|
|
2926
|
+
const selector = buildChangeSelector(changeTracker, node);
|
|
2927
|
+
node.setOuterHTML(value, (error: string|null) => {
|
|
2928
|
+
if (!error) {
|
|
2929
|
+
Elements.DOMChanges.trackHTMLEdit(changeTracker, node, selector, initialValue, value);
|
|
2930
|
+
}
|
|
2931
|
+
selectNode(error);
|
|
2932
|
+
});
|
|
2855
2933
|
}
|
|
2856
2934
|
};
|
|
2857
2935
|
|