mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[REF] component: introduce RootFiber.setCounter and update scheduler
The goal is to be able to execute code whenever a root fiber is ready, and before the next animation frame
This commit is contained in:
committed by
Samuel Degueldre
parent
d80fad760c
commit
828be28653
@@ -101,6 +101,7 @@ export class App<
|
|||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
if (this.root) {
|
if (this.root) {
|
||||||
|
this.scheduler.flush();
|
||||||
this.root.destroy();
|
this.root.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,7 +245,8 @@ export class ComponentNode<P extends object = any, E = any> implements VNode<Com
|
|||||||
_render(fiber: Fiber | RootFiber) {
|
_render(fiber: Fiber | RootFiber) {
|
||||||
try {
|
try {
|
||||||
fiber.bdom = this.renderFn();
|
fiber.bdom = this.renderFn();
|
||||||
fiber.root!.counter--;
|
const root = fiber.root!;
|
||||||
|
root.setCounter(root.counter - 1);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError({ node: this, error: e });
|
handleError({ node: this, error: e });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ function _handleError(node: ComponentNode | null, error: any, isFirstRound = fal
|
|||||||
|
|
||||||
if (stopped) {
|
if (stopped) {
|
||||||
if (isFirstRound && fiber && fiber.node.fiber) {
|
if (isFirstRound && fiber && fiber.node.fiber) {
|
||||||
fiber.root!.counter--;
|
const root = fiber.root!;
|
||||||
|
root.setCounter(root.counter - 1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export function makeRootFiber(node: ComponentNode): Fiber {
|
|||||||
let current = node.fiber;
|
let current = node.fiber;
|
||||||
if (current) {
|
if (current) {
|
||||||
let root = current.root!;
|
let root = current.root!;
|
||||||
root.counter = root.counter + 1 - cancelFibers(current.children);
|
root.setCounter(root.counter + 1 - cancelFibers(current.children));
|
||||||
current.children = [];
|
current.children = [];
|
||||||
current.bdom = null;
|
current.bdom = null;
|
||||||
if (fibersInError.has(current)) {
|
if (fibersInError.has(current)) {
|
||||||
@@ -74,7 +74,7 @@ export class Fiber {
|
|||||||
if (parent) {
|
if (parent) {
|
||||||
this.deep = parent.deep;
|
this.deep = parent.deep;
|
||||||
const root = parent.root!;
|
const root = parent.root!;
|
||||||
root.counter++;
|
root.setCounter(root.counter + 1);
|
||||||
this.root = root;
|
this.root = root;
|
||||||
parent.children.push(this);
|
parent.children.push(this);
|
||||||
} else {
|
} else {
|
||||||
@@ -144,6 +144,13 @@ export class RootFiber extends Fiber {
|
|||||||
handleError({ fiber: current || this, error: e });
|
handleError({ fiber: current || this, error: e });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCounter(newValue: number) {
|
||||||
|
this.counter = newValue;
|
||||||
|
if (newValue === 0) {
|
||||||
|
this.node.app.scheduler.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Position = "first-child" | "last-child";
|
type Position = "first-child" | "last-child";
|
||||||
|
|||||||
+26
-43
@@ -11,27 +11,15 @@ export class Scheduler {
|
|||||||
// interactions with other code, such as test frameworks that override them
|
// interactions with other code, such as test frameworks that override them
|
||||||
static requestAnimationFrame = window.requestAnimationFrame.bind(window);
|
static requestAnimationFrame = window.requestAnimationFrame.bind(window);
|
||||||
tasks: Set<RootFiber> = new Set();
|
tasks: Set<RootFiber> = new Set();
|
||||||
isRunning: boolean = false;
|
|
||||||
requestAnimationFrame: Window["requestAnimationFrame"];
|
requestAnimationFrame: Window["requestAnimationFrame"];
|
||||||
|
frame: number = 0;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.requestAnimationFrame = Scheduler.requestAnimationFrame;
|
this.requestAnimationFrame = Scheduler.requestAnimationFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
|
||||||
this.isRunning = true;
|
|
||||||
this.scheduleTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
this.isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
addFiber(fiber: Fiber) {
|
addFiber(fiber: Fiber) {
|
||||||
this.tasks.add(fiber.root!);
|
this.tasks.add(fiber.root!);
|
||||||
if (!this.isRunning) {
|
|
||||||
this.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,39 +27,34 @@ export class Scheduler {
|
|||||||
* Other tasks are left unchanged.
|
* Other tasks are left unchanged.
|
||||||
*/
|
*/
|
||||||
flush() {
|
flush() {
|
||||||
this.tasks.forEach((fiber) => {
|
if (this.frame === 0) {
|
||||||
if (fiber.root !== fiber) {
|
this.frame = this.requestAnimationFrame(() => {
|
||||||
this.tasks.delete(fiber);
|
this.frame = 0;
|
||||||
return;
|
this.tasks.forEach((fiber) => this.processFiber(fiber));
|
||||||
}
|
});
|
||||||
const hasError = fibersInError.has(fiber);
|
|
||||||
if (hasError && fiber.counter !== 0) {
|
|
||||||
this.tasks.delete(fiber);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (fiber.node.status === STATUS.DESTROYED) {
|
|
||||||
this.tasks.delete(fiber);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fiber.counter === 0) {
|
|
||||||
if (!hasError) {
|
|
||||||
fiber.complete();
|
|
||||||
}
|
|
||||||
this.tasks.delete(fiber);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (this.tasks.size === 0) {
|
|
||||||
this.stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleTasks() {
|
processFiber(fiber: RootFiber) {
|
||||||
this.requestAnimationFrame(() => {
|
if (fiber.root !== fiber) {
|
||||||
this.flush();
|
this.tasks.delete(fiber);
|
||||||
if (this.isRunning) {
|
return;
|
||||||
this.scheduleTasks();
|
}
|
||||||
|
const hasError = fibersInError.has(fiber);
|
||||||
|
if (hasError && fiber.counter !== 0) {
|
||||||
|
this.tasks.delete(fiber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fiber.node.status === STATUS.DESTROYED) {
|
||||||
|
this.tasks.delete(fiber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fiber.counter === 0) {
|
||||||
|
if (!hasError) {
|
||||||
|
fiber.complete();
|
||||||
}
|
}
|
||||||
});
|
this.tasks.delete(fiber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user