diff --git a/web/static/src/ts/core/Widget.ts b/web/static/src/ts/core/Widget.ts index 4c90164b..fc9c7fca 100644 --- a/web/static/src/ts/core/Widget.ts +++ b/web/static/src/ts/core/Widget.ts @@ -21,6 +21,7 @@ interface Meta { vnode: VNode | null; isStarted: boolean; isMounted: boolean; + isDestroyed: boolean; parent: Widget | null; children: Widget[]; } @@ -57,6 +58,7 @@ export class Widget { vnode: null, isStarted: false, isMounted: false, + isDestroyed: false, parent: p, children: [] }; @@ -91,8 +93,13 @@ export class Widget { } destroy() { - if (this.el) { - this.el.remove(); + if (!this._.isDestroyed) { + if (this.el) { + this.el.remove(); + delete this._.vnode; + } + this._.isDestroyed = true; + this.destroyed(); } } diff --git a/web/static/tests/widget.test.ts b/web/static/tests/widget.test.ts index 74e92376..f77e874b 100644 --- a/web/static/tests/widget.test.ts +++ b/web/static/tests/widget.test.ts @@ -249,6 +249,21 @@ describe("destroy method", () => { widget.destroy(); expect(document.contains(widget.el)).toBe(false); }); + + test("destroying a widget twice only call destroyed once", async () => { + let count = 0; + class TestWidget extends Widget { + destroyed() { + count++; + } + } + const widget = new TestWidget(env); + await widget.mount(fixture); + widget.destroy(); + expect(count).toBe(1); + widget.destroy(); + expect(count).toBe(1); + }); }); describe("composition", () => {