Skip to content

Commit b4fd279

Browse files
OrKoNDevtools-frontend LUCI CQ
authored andcommitted
Mark root-less <devtools-widget>s as roots
Bug: none Change-Id: I8aa32990961146a76861067a2e630f5d24a25bf3 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6216263 Reviewed-by: Benedikt Meurer <[email protected]> Reviewed-by: Danil Somsikov <[email protected]> Commit-Queue: Alex Rudenko <[email protected]>
1 parent ca20b6e commit b4fd279

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

front_end/ui/legacy/Widget.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,20 @@ describe('Widget', () => {
151151
await widget.updateComplete;
152152
});
153153
});
154+
155+
describe('WidgetElement', () => {
156+
it('renders WidgetElement into DOM without a root element', async () => {
157+
const widget = new UI.Widget.WidgetElement();
158+
class WidgetInstance extends UI.Widget.Widget {
159+
constructor(element: HTMLElement) {
160+
super(false, false, element);
161+
}
162+
override performUpdate(): void {
163+
// no-op
164+
}
165+
}
166+
widget.widgetConfig = UI.Widget.widgetConfig(WidgetInstance, {});
167+
renderElementIntoDOM(widget);
168+
});
169+
});
154170
});

front_end/ui/legacy/Widget.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ export class WidgetElement<WidgetT extends Widget&WidgetParams, WidgetParams = {
104104
}
105105

106106
connectedCallback(): void {
107-
Widget.getOrCreateWidget(this).show(this.parentElement as HTMLElement);
107+
// When using <devtools-widget> we suppress
108+
// suppressOrphanWidgetError and allow the Widget instance to be
109+
// treated as a root instance if no root widget was found.
110+
Widget.getOrCreateWidget(this).show(
111+
this.parentElement as HTMLElement, undefined, /* suppressOrphanWidgetError= */ true);
108112
}
109113
}
110114

@@ -349,7 +353,7 @@ export class Widget {
349353
async ownerViewDisposed(): Promise<void> {
350354
}
351355

352-
show(parentElement: Element, insertBefore?: Node|null): void {
356+
show(parentElement: Element, insertBefore?: Node|null, suppressOrphanWidgetError = false): void {
353357
assert(parentElement, 'Attempt to attach widget with no parent element');
354358

355359
if (!this.isRoot) {
@@ -358,6 +362,12 @@ export class Widget {
358362
let currentWidget = undefined;
359363
while (!currentWidget) {
360364
if (!currentParent) {
365+
if (suppressOrphanWidgetError) {
366+
this.isRoot = true;
367+
console.warn('A Widget has silently been marked as a root widget');
368+
this.show(parentElement, insertBefore);
369+
return;
370+
}
361371
throw new Error('Attempt to attach widget to orphan node');
362372
}
363373
currentWidget = widgetMap.get(currentParent);

0 commit comments

Comments
 (0)