Skip to content

Commit

Permalink
[REF] component: introduce RootFiber.setCounter and update scheduler
Browse files Browse the repository at this point in the history
The goal is to be able to execute code whenever a root fiber is ready,
and before the next animation frame
  • Loading branch information
ged-odoo authored and sdegueldre committed Mar 29, 2022
1 parent d80fad7 commit 828be28
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 47 deletions.
1 change: 1 addition & 0 deletions src/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export class App<

destroy() {
if (this.root) {
this.scheduler.flush();
this.root.destroy();
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/component/component_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ export class ComponentNode<P extends object = any, E = any> implements VNode<Com
_render(fiber: Fiber | RootFiber) {
try {
fiber.bdom = this.renderFn();
fiber.root!.counter--;
const root = fiber.root!;
root.setCounter(root.counter - 1);
} catch (e) {
handleError({ node: this, error: e });
}
Expand Down
3 changes: 2 additions & 1 deletion src/component/error_handling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ function _handleError(node: ComponentNode | null, error: any, isFirstRound = fal

if (stopped) {
if (isFirstRound && fiber && fiber.node.fiber) {
fiber.root!.counter--;
const root = fiber.root!;
root.setCounter(root.counter - 1);
}
return true;
}
Expand Down
11 changes: 9 additions & 2 deletions src/component/fibers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function makeRootFiber(node: ComponentNode): Fiber {
let current = node.fiber;
if (current) {
let root = current.root!;
root.counter = root.counter + 1 - cancelFibers(current.children);
root.setCounter(root.counter + 1 - cancelFibers(current.children));
current.children = [];
current.bdom = null;
if (fibersInError.has(current)) {
Expand Down Expand Up @@ -74,7 +74,7 @@ export class Fiber {
if (parent) {
this.deep = parent.deep;
const root = parent.root!;
root.counter++;
root.setCounter(root.counter + 1);
this.root = root;
parent.children.push(this);
} else {
Expand Down Expand Up @@ -144,6 +144,13 @@ export class RootFiber extends Fiber {
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";
Expand Down
69 changes: 26 additions & 43 deletions src/component/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,67 +11,50 @@ export class Scheduler {
// interactions with other code, such as test frameworks that override them
static requestAnimationFrame = window.requestAnimationFrame.bind(window);
tasks: Set<RootFiber> = new Set();
isRunning: boolean = false;
requestAnimationFrame: Window["requestAnimationFrame"];
frame: number = 0;

constructor() {
this.requestAnimationFrame = Scheduler.requestAnimationFrame;
}

start() {
this.isRunning = true;
this.scheduleTasks();
}

stop() {
this.isRunning = false;
}

addFiber(fiber: Fiber) {
this.tasks.add(fiber.root!);
if (!this.isRunning) {
this.start();
}
}

/**
* Process all current tasks. This only applies to the fibers that are ready.
* Other tasks are left unchanged.
*/
flush() {
this.tasks.forEach((fiber) => {
if (fiber.root !== fiber) {
this.tasks.delete(fiber);
return;
}
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();
if (this.frame === 0) {
this.frame = this.requestAnimationFrame(() => {
this.frame = 0;
this.tasks.forEach((fiber) => this.processFiber(fiber));
});
}
}

scheduleTasks() {
this.requestAnimationFrame(() => {
this.flush();
if (this.isRunning) {
this.scheduleTasks();
processFiber(fiber: RootFiber) {
if (fiber.root !== fiber) {
this.tasks.delete(fiber);
return;
}
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);
}
}
}

0 comments on commit 828be28

Please sign in to comment.