handle situation when widget is destroyed before willStart

This commit is contained in:
Géry Debongnie
2019-01-27 21:50:22 +01:00
parent fb6ad6e56b
commit d8c37a2942
2 changed files with 49 additions and 6 deletions
+13 -6
View File
@@ -80,9 +80,13 @@ export class Widget<T extends WEnv> {
// Public
//--------------------------------------------------------------------------
async mount(target: HTMLElement): Promise<VNode> {
async mount(target: HTMLElement): Promise<void> {
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!);
if (document.body.contains(target)) {
@@ -93,7 +97,6 @@ export class Widget<T extends WEnv> {
}
});
}
return vnode;
}
destroy() {
@@ -134,18 +137,22 @@ export class Widget<T extends WEnv> {
// Private
//--------------------------------------------------------------------------
async render(): Promise<VNode> {
async render(): Promise<void> {
if (this.__widget__.isDestroyed) {
return;
}
const vnode = await this._render();
this.__widget__.vnode = patch(
this.__widget__.vnode || document.createElement(vnode.sel!),
vnode
);
return this.__widget__.vnode;
}
private async _start(): Promise<void> {
await this.willStart();
this.__widget__.isStarted = true;
if (!this.__widget__.isDestroyed) {
this.__widget__.isStarted = true;
}
}
private async _render(): Promise<VNode> {
+36
View File
@@ -422,6 +422,42 @@ describe("destroy method", () => {
expect(child.__widget__.parent).toBe(null);
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", () => {