mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] fiber, lifecycle: trigger a render during the fiber.complete
Have a component which does a render in its onWillPatch, onPatched, onMounted hooks. Before this commit, the result was incorrect: the second rendering was not taken into account. After this commit, those renderings are correctly applied at the price of a delayed render when the fiber is in a critical state.
This commit is contained in:
committed by
Aaron Bohy
parent
e2819323ee
commit
ddc358f48a
@@ -136,13 +136,19 @@ export class ComponentNode<T extends typeof Component = typeof Component>
|
||||
}
|
||||
|
||||
async render() {
|
||||
const current = this.fiber;
|
||||
let current = this.fiber;
|
||||
if (current && current.root.locked) {
|
||||
await Promise.resolve();
|
||||
// situation may have changed after the microtask tick
|
||||
current = this.fiber;
|
||||
}
|
||||
if (current && !current.bdom && !fibersInError.has(current)) {
|
||||
return;
|
||||
}
|
||||
if (!this.bdom && !current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fiber = makeRootFiber(this);
|
||||
this.fiber = fiber;
|
||||
this.app.scheduler.addFiber(fiber);
|
||||
|
||||
+15
-3
@@ -118,9 +118,13 @@ export class RootFiber extends Fiber {
|
||||
willPatch: Fiber[] = [];
|
||||
patched: Fiber[] = [];
|
||||
mounted: Fiber[] = [];
|
||||
// A fiber is typically locked when it is completing and the patch has not, or is being applied.
|
||||
// i.e.: render triggered in onWillUnmount or in willPatch will be delayed
|
||||
locked: boolean = false;
|
||||
|
||||
complete() {
|
||||
const node = this.node;
|
||||
this.locked = true;
|
||||
let current: Fiber | undefined = undefined;
|
||||
try {
|
||||
// Step 1: calling all willPatch lifecycle hooks
|
||||
@@ -142,6 +146,11 @@ export class RootFiber extends Fiber {
|
||||
node.bdom!.patch(this.bdom!, Object.keys(node.children).length > 0);
|
||||
this.appliedToDom = true;
|
||||
|
||||
this.locked = false;
|
||||
// unregistering the fiber before mounted since it can do another render
|
||||
// and that the current rendering is obviously completed
|
||||
node.fiber = null;
|
||||
|
||||
// Step 4: calling all mounted lifecycle hooks
|
||||
let mountedFibers = this.mounted;
|
||||
while ((current = mountedFibers.pop())) {
|
||||
@@ -163,9 +172,8 @@ export class RootFiber extends Fiber {
|
||||
}
|
||||
}
|
||||
}
|
||||
// unregistering the fiber
|
||||
node.fiber = null;
|
||||
} catch (e) {
|
||||
this.locked = false;
|
||||
handleError({ fiber: current || this, error: e });
|
||||
}
|
||||
}
|
||||
@@ -205,6 +213,11 @@ export class MountFiber extends RootFiber {
|
||||
mount(node.bdom!, this.target, firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
// unregistering the fiber before mounted since it can do another render
|
||||
// and that the current rendering is obviously completed
|
||||
node.fiber = null;
|
||||
|
||||
node.status = STATUS.MOUNTED;
|
||||
this.appliedToDom = true;
|
||||
let mountedFibers = this.mounted;
|
||||
@@ -215,7 +228,6 @@ export class MountFiber extends RootFiber {
|
||||
}
|
||||
}
|
||||
}
|
||||
node.fiber = null;
|
||||
} catch (e) {
|
||||
handleError({ fiber: current as Fiber, error: e });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user