[FIX] component: reorganize fiber update algorithm

Closes #473
Closes #484
Closes #489
Closes #492
Closes #512

Co-authored-by: Aaron Bohy <aab@odoo.com>
This commit is contained in:
Géry Debongnie
2019-11-21 11:23:05 +01:00
parent 7f6782d009
commit 8c17bb0411
15 changed files with 458 additions and 163 deletions
+44 -35
View File
@@ -120,6 +120,7 @@ export class Fiber {
*/
_remapFiber(oldFiber: Fiber) {
oldFiber.cancel();
this.shouldPatch = oldFiber.shouldPatch;
if (oldFiber === oldFiber.root) {
oldFiber.counter++;
}
@@ -178,54 +179,62 @@ export class Fiber {
* are ready, and the scheduler decides to process it.
*/
complete() {
const component = this.component;
if (this.target) {
component.__patch(this.vnode);
this.target.appendChild(component.el!);
if (document.body.contains(this.target)) {
component.__callMounted();
}
} else if (component.__owl__.isMounted && this === this.root) {
this.patchComponents();
}
let component = this.component;
this.isCompleted = true;
}
if (!this.target && !component.__owl__.isMounted) {
return;
}
/**
* Compute and apply the patch queue of the fiber.
* 1) Call 'willPatch' on the component of each patch
* 2) Call '__patch' on the component of each patch
* 3) Call 'patched' on the component of each patch, in reverse order
*/
patchComponents() {
// build patchQueue
const patchQueue: Fiber[] = [];
const doWork: (Fiber) => Fiber | null = function(f) {
if (f.shouldPatch) {
patchQueue.push(f);
return f.child;
}
patchQueue.push(f);
return f.child;
};
this._walk(doWork);
let component: Component<any, any> = this.component;
const patchLen = patchQueue.length;
for (let i = 0; i < patchLen; i++) {
component = patchQueue[i].component;
if (component.__owl__.willPatchCB) {
component.__owl__.willPatchCB();
}
component.willPatch();
}
// call willPatch hook on each fiber of patchQueue
for (let i = 0; i < patchLen; i++) {
const fiber = patchQueue[i];
if (fiber.shouldPatch) {
component = fiber.component;
if (component.__owl__.willPatchCB) {
component.__owl__.willPatchCB();
}
component.willPatch();
}
}
// call __patch on each fiber of (reversed) patchQueue
for (let i = patchLen - 1; i >= 0; i--) {
const fiber = patchQueue[i];
component = fiber.component;
component.__patch(fiber.vnode);
component.__patch(fiber.vnode!);
if (!fiber.shouldPatch && (!fiber.target || i !== 0)) {
component.__owl__.pvnode!.elm = component.__owl__.vnode!.elm;
}
component.__owl__.currentFiber = null;
}
// insert into the DOM (mount case)
let inDOM = false;
if (this.target) {
this.target.appendChild(this.component.el!);
inDOM = document.body.contains(this.target);
}
// call patched/mounted hook on each fiber of (reversed) patchQueue
for (let i = patchLen - 1; i >= 0; i--) {
component = patchQueue[i].component;
component.patched();
if (component.__owl__.patchedCB) {
component.__owl__.patchedCB();
const fiber = patchQueue[i];
component = fiber.component;
if (fiber.shouldPatch && !this.target) {
component.patched();
if (component.__owl__.patchedCB) {
component.__owl__.patchedCB();
}
} else if (this.target ? inDOM : true) {
component.__callMounted();
}
}
}