mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
handle situation when widget is destroyed before willStart
This commit is contained in:
@@ -80,9 +80,13 @@ export class Widget<T extends WEnv> {
|
|||||||
// Public
|
// Public
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
async mount(target: HTMLElement): Promise<VNode> {
|
async mount(target: HTMLElement): Promise<void> {
|
||||||
await this._start();
|
await this._start();
|
||||||
const vnode = await this.render();
|
await this.render();
|
||||||
|
if (!this.el) {
|
||||||
|
// widget was destroyed before we get here...
|
||||||
|
return;
|
||||||
|
}
|
||||||
target.appendChild(this.el!);
|
target.appendChild(this.el!);
|
||||||
|
|
||||||
if (document.body.contains(target)) {
|
if (document.body.contains(target)) {
|
||||||
@@ -93,7 +97,6 @@ export class Widget<T extends WEnv> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return vnode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
@@ -134,19 +137,23 @@ export class Widget<T extends WEnv> {
|
|||||||
// Private
|
// Private
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
async render(): Promise<VNode> {
|
async render(): Promise<void> {
|
||||||
|
if (this.__widget__.isDestroyed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const vnode = await this._render();
|
const vnode = await this._render();
|
||||||
this.__widget__.vnode = patch(
|
this.__widget__.vnode = patch(
|
||||||
this.__widget__.vnode || document.createElement(vnode.sel!),
|
this.__widget__.vnode || document.createElement(vnode.sel!),
|
||||||
vnode
|
vnode
|
||||||
);
|
);
|
||||||
return this.__widget__.vnode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _start(): Promise<void> {
|
private async _start(): Promise<void> {
|
||||||
await this.willStart();
|
await this.willStart();
|
||||||
|
if (!this.__widget__.isDestroyed) {
|
||||||
this.__widget__.isStarted = true;
|
this.__widget__.isStarted = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async _render(): Promise<VNode> {
|
private async _render(): Promise<VNode> {
|
||||||
if (this.template) {
|
if (this.template) {
|
||||||
|
|||||||
@@ -422,6 +422,42 @@ describe("destroy method", () => {
|
|||||||
expect(child.__widget__.parent).toBe(null);
|
expect(child.__widget__.parent).toBe(null);
|
||||||
expect(children(parent).length).toBe(0);
|
expect(children(parent).length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("destroying a widget before willStart is done", async () => {
|
||||||
|
let resolve;
|
||||||
|
let isRendered = false;
|
||||||
|
let p: Promise<void> = new Promise(function(r) {
|
||||||
|
resolve = r;
|
||||||
|
});
|
||||||
|
class DelayedWidget extends Widget<WEnv> {
|
||||||
|
willStart() {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(fixture.innerHTML).toBe("");
|
||||||
|
const widget = new DelayedWidget(env);
|
||||||
|
widget.mount(fixture);
|
||||||
|
expect(widget.__widget__.isStarted).toBe(false);
|
||||||
|
expect(widget.__widget__.isMounted).toBe(false);
|
||||||
|
expect(widget.__widget__.isDestroyed).toBe(false);
|
||||||
|
widget.destroy();
|
||||||
|
expect(widget.__widget__.isMounted).toBe(false);
|
||||||
|
expect(widget.__widget__.isStarted).toBe(false);
|
||||||
|
expect(widget.__widget__.isDestroyed).toBe(true);
|
||||||
|
resolve();
|
||||||
|
// Note: should we abandon await and not have to do this?
|
||||||
|
// TODO: talk to vsc
|
||||||
|
await nextTick();
|
||||||
|
await nextTick();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
expect(widget.__widget__.isStarted).toBe(false);
|
||||||
|
expect(widget.__widget__.isMounted).toBe(false);
|
||||||
|
expect(widget.__widget__.isDestroyed).toBe(true);
|
||||||
|
expect(widget.__widget__.vnode).toBe(null);
|
||||||
|
expect(fixture.innerHTML).toBe("");
|
||||||
|
expect(isRendered).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("composition", () => {
|
describe("composition", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user