Commit 5f22b169 authored by Olivia Flynn's avatar Olivia Flynn Committed by Commit Bot

DevTools: Widgets can be marked as removable

Addresses a bug where CodeMirror's update view process, which deletes
non-visible nodes, causes Widget.js to throw many errors and crash the
source code frame because Widgets have been inserted into CodeMirror
lines, but cannot be removed by regular DOM operations. This occurs
when scrolling with an edit breakpoint dialog open.

This solution introduces a function to mark a widget as externally
managed, which excludes it from its ancestor's __widgetCounter.

Before and after gifs:
https://imgur.com/a/CIFNO8Y

Bug: 984762
Change-Id: Id569d201569461c863e53fe07b22f81683b4862e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1705174Reviewed-by: default avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#698838}
parent f301da98
...@@ -48,6 +48,7 @@ Sources.BreakpointEditDialog = class extends UI.Widget { ...@@ -48,6 +48,7 @@ Sources.BreakpointEditDialog = class extends UI.Widget {
this._editor.configureAutocomplete(ObjectUI.JavaScriptAutocompleteConfig.createConfigForEditor(this._editor)); this._editor.configureAutocomplete(ObjectUI.JavaScriptAutocompleteConfig.createConfigForEditor(this._editor));
if (oldCondition) if (oldCondition)
this._editor.setText(oldCondition); this._editor.setText(oldCondition);
this._editor.widget().markAsExternallyManaged();
this._editor.widget().show(this.contentElement); this._editor.widget().show(this.contentElement);
this._editor.setSelection(this._editor.fullRange()); this._editor.setSelection(this._editor.fullRange());
this._editor.widget().focus(); this._editor.widget().focus();
......
...@@ -654,6 +654,7 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin { ...@@ -654,6 +654,7 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._createNewBreakpoint(editorLineNumber, result.condition, true); this._createNewBreakpoint(editorLineNumber, result.condition, true);
}); });
this._textEditor.addDecoration(decorationElement, editorLineNumber); this._textEditor.addDecoration(decorationElement, editorLineNumber);
dialog.markAsExternallyManaged();
dialog.show(decorationElement); dialog.show(decorationElement);
} }
......
...@@ -308,7 +308,8 @@ UI.Widget = class extends Common.Object { ...@@ -308,7 +308,8 @@ UI.Widget = class extends Common.Object {
// Reparent // Reparent
if (this.element.parentElement !== parentElement) { if (this.element.parentElement !== parentElement) {
UI.Widget._incrementWidgetCounter(parentElement, this.element); if (!this._externallyManaged)
UI.Widget._incrementWidgetCounter(parentElement, this.element);
if (insertBefore) if (insertBefore)
UI.Widget._originalInsertBefore.call(parentElement, this.element, insertBefore); UI.Widget._originalInsertBefore.call(parentElement, this.element, insertBefore);
else else
...@@ -586,6 +587,19 @@ UI.Widget = class extends Common.Object { ...@@ -586,6 +587,19 @@ UI.Widget = class extends Common.Object {
else else
this.doLayout(); this.doLayout();
} }
// Excludes the widget from being tracked by its parents/ancestors via
// __widgetCounter because the widget is being handled by external code.
// Widgets marked as being externally managed are responsible for
// finishing out their own lifecycle (i.e. calling detach() before being
// removed from the DOM). This is e.g. used for CodeMirror.
//
// Also note that this must be called before the widget is shown so that
// so that its ancestor's __widgetCounter is not incremented.
markAsExternallyManaged() {
UI.Widget.__assert(!this._parentWidget, 'Attempt to mark widget as externally managed after insertion to the DOM');
this._externallyManaged = true;
}
}; };
UI.Widget._originalAppendChild = Element.prototype.appendChild; UI.Widget._originalAppendChild = Element.prototype.appendChild;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment