mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] component: fix issue with crash caused by async rendering
This may (or may not?) closes #85
This commit is contained in:
+1
-1
@@ -200,7 +200,7 @@ a owl component:
|
|||||||
| ------------------------------------------------ | --------------------------------------- |
|
| ------------------------------------------------ | --------------------------------------- |
|
||||||
| **[constructor](#constructor)** | constructor |
|
| **[constructor](#constructor)** | constructor |
|
||||||
| **[willStart](#willStart)** | async, before first rendering |
|
| **[willStart](#willStart)** | async, before first rendering |
|
||||||
| **[mounted](#mounted)** | when component is render and in DOM |
|
| **[mounted](#mounted)** | just after component is rendered and added to the DOM |
|
||||||
| **[willUpdateProps](#willupdatepropsnextprops)** | async, before props update |
|
| **[willUpdateProps](#willupdatepropsnextprops)** | async, before props update |
|
||||||
| **[willPatch](#willpatch)** | just before the DOM is patched |
|
| **[willPatch](#willpatch)** | just before the DOM is patched |
|
||||||
| **[patched](#patchedsnapshot)** | just after the DOM is patched |
|
| **[patched](#patchedsnapshot)** | just after the DOM is patched |
|
||||||
|
|||||||
+2
-1
@@ -248,7 +248,8 @@ export class Component<
|
|||||||
const renderVDom = this._render(force, patchQueue);
|
const renderVDom = this._render(force, patchQueue);
|
||||||
const renderId = this.__owl__.renderId;
|
const renderId = this.__owl__.renderId;
|
||||||
const vnode = await renderVDom;
|
const vnode = await renderVDom;
|
||||||
if (renderId === this.__owl__.renderId) {
|
|
||||||
|
if (this.__owl__.isMounted && renderId === this.__owl__.renderId) {
|
||||||
// we only update the vnode and the actual DOM if no other rendering
|
// we only update the vnode and the actual DOM if no other rendering
|
||||||
// occurred between now and when the render method was initially called.
|
// occurred between now and when the render method was initially called.
|
||||||
if (shouldCallPatchHooks) {
|
if (shouldCallPatchHooks) {
|
||||||
|
|||||||
@@ -1645,6 +1645,59 @@ describe("async rendering", () => {
|
|||||||
"<div><span>a2</span><span>b2</span></div>"
|
"<div><span>a2</span><span>b2</span></div>"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.only("properly behave when destroyed/unmounted while rendering ", async () => {
|
||||||
|
let def = Promise.resolve();
|
||||||
|
|
||||||
|
class Child extends Widget {
|
||||||
|
inlineTemplate = `<div><t t-widget="SubChild"/></div>`;
|
||||||
|
widgets = { SubChild };
|
||||||
|
mounted() {
|
||||||
|
// from now on, each rendering in child widget will be delayed (see
|
||||||
|
// _render)
|
||||||
|
def = makeDeferred();
|
||||||
|
}
|
||||||
|
async _render(f, p) {
|
||||||
|
const result = await super._render(f, p);
|
||||||
|
await def;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SubChild extends Widget {
|
||||||
|
willPatch() {
|
||||||
|
throw new Error("Should not happen!");
|
||||||
|
}
|
||||||
|
patched() {
|
||||||
|
throw new Error("Should not happen!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parent extends Widget {
|
||||||
|
inlineTemplate = `
|
||||||
|
<div><t t-if="state.flag"><t t-widget="Child" t-props="{val: state.val}"/></t></div>`;
|
||||||
|
widgets = { Child };
|
||||||
|
state = { flag: true, val: "Framboise Lindemans" };
|
||||||
|
}
|
||||||
|
const parent = new Parent(env);
|
||||||
|
await parent.mount(fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<div><div><div></div></div></div>");
|
||||||
|
|
||||||
|
// this change triggers a rendering of the parent. This rendering is delayed,
|
||||||
|
// because child is now waiting for def to be resolved
|
||||||
|
parent.state.val = "Framboise Girardin";
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// with this, we remove child, and childchild, even though it is not finished
|
||||||
|
// rendering from previous changes
|
||||||
|
parent.state.flag = false;
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// we now resolve def, so the child rendering is now complete.
|
||||||
|
(<any>def).resolve();
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe("<div></div>");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("updating environment", () => {
|
describe("updating environment", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user