feat: add Value.Equal bail-out check before reconciliation
Add TypeBox Value.Equal deep-comparison as first optimization layer in reconcileProps. When a fiber's cached node is deep-equal to the next node, skip prepareUpdate, commitUpdate, and children reconciliation entirely. New cachedNode field on Fiber stores the last reconciled node for comparison.
This commit is contained in:
@@ -1,6 +1,15 @@
|
||||
import { describe, it, expect, expectTypeOf } from "vitest";
|
||||
import type { Fiber, Effect } from "../src/host/fiber.js";
|
||||
|
||||
const baseFiber: Omit<Fiber<string>, "instance" | "tag" | "props" | "key"> = {
|
||||
children: [],
|
||||
parent: null,
|
||||
effect: null,
|
||||
signalDisposers: [],
|
||||
prevProps: null,
|
||||
cachedNode: null,
|
||||
};
|
||||
|
||||
describe("Fiber<I> interface", () => {
|
||||
it("has all required fields", () => {
|
||||
const fiber: Fiber<string> = {
|
||||
@@ -8,11 +17,7 @@ describe("Fiber<I> interface", () => {
|
||||
tag: "div",
|
||||
props: { class: "test" },
|
||||
key: "a",
|
||||
children: [],
|
||||
parent: null,
|
||||
effect: null,
|
||||
signalDisposers: [],
|
||||
prevProps: null,
|
||||
...baseFiber,
|
||||
};
|
||||
expect(fiber.instance).toBe("inst-1");
|
||||
expect(fiber.tag).toBe("div");
|
||||
@@ -23,6 +28,7 @@ describe("Fiber<I> interface", () => {
|
||||
expect(fiber.effect).toBeNull();
|
||||
expect(fiber.signalDisposers).toEqual([]);
|
||||
expect(fiber.prevProps).toBeNull();
|
||||
expect(fiber.cachedNode).toBeNull();
|
||||
});
|
||||
|
||||
it("supports key as undefined", () => {
|
||||
@@ -31,11 +37,7 @@ describe("Fiber<I> interface", () => {
|
||||
tag: "span",
|
||||
props: {},
|
||||
key: undefined,
|
||||
children: [],
|
||||
parent: null,
|
||||
effect: null,
|
||||
signalDisposers: [],
|
||||
prevProps: null,
|
||||
...baseFiber,
|
||||
};
|
||||
expect(fiber.key).toBeUndefined();
|
||||
});
|
||||
@@ -46,22 +48,15 @@ describe("Fiber<I> interface", () => {
|
||||
tag: "div",
|
||||
props: {},
|
||||
key: undefined,
|
||||
children: [],
|
||||
parent: null,
|
||||
effect: null,
|
||||
signalDisposers: [],
|
||||
prevProps: null,
|
||||
...baseFiber,
|
||||
};
|
||||
const child: Fiber<string> = {
|
||||
instance: "child-inst",
|
||||
tag: "span",
|
||||
props: {},
|
||||
key: "child-1",
|
||||
children: [],
|
||||
...baseFiber,
|
||||
parent,
|
||||
effect: null,
|
||||
signalDisposers: [],
|
||||
prevProps: null,
|
||||
};
|
||||
parent.children.push(child);
|
||||
expect(child.parent).toBe(parent);
|
||||
@@ -75,11 +70,8 @@ describe("Fiber<I> interface", () => {
|
||||
tag: "div",
|
||||
props: {},
|
||||
key: undefined,
|
||||
children: [],
|
||||
parent: null,
|
||||
effect: null,
|
||||
...baseFiber,
|
||||
signalDisposers: [() => disposed.push("a"), () => disposed.push("b")],
|
||||
prevProps: null,
|
||||
};
|
||||
fiber.signalDisposers.forEach((d) => d());
|
||||
expect(disposed).toEqual(["a", "b"]);
|
||||
@@ -104,11 +96,7 @@ describe("Effect<I> union type", () => {
|
||||
tag: "span",
|
||||
props: {},
|
||||
key: undefined,
|
||||
children: [],
|
||||
parent: null,
|
||||
effect: null,
|
||||
signalDisposers: [],
|
||||
prevProps: null,
|
||||
...baseFiber,
|
||||
};
|
||||
const effect: Effect<string> = { type: "insert", before };
|
||||
expect(effect.type).toBe("insert");
|
||||
@@ -121,11 +109,7 @@ describe("Effect<I> union type", () => {
|
||||
tag: "span",
|
||||
props: {},
|
||||
key: undefined,
|
||||
children: [],
|
||||
parent: null,
|
||||
effect: null,
|
||||
signalDisposers: [],
|
||||
prevProps: null,
|
||||
...baseFiber,
|
||||
};
|
||||
const effect: Effect<string> = { type: "move", before };
|
||||
expect(effect.type).toBe("move");
|
||||
@@ -148,10 +132,8 @@ describe("Effect<I> union type", () => {
|
||||
tag: "div",
|
||||
props: {},
|
||||
key: undefined,
|
||||
children: [],
|
||||
parent: null,
|
||||
...baseFiber,
|
||||
effect: { type: "update", payload: "x" },
|
||||
signalDisposers: [],
|
||||
prevProps: {},
|
||||
};
|
||||
expect(fiber.effect!.type).toBe("update");
|
||||
@@ -179,11 +161,7 @@ describe("Fiber re-export from barrel", () => {
|
||||
tag: "div",
|
||||
props: {},
|
||||
key: undefined,
|
||||
children: [],
|
||||
parent: null,
|
||||
effect: null,
|
||||
signalDisposers: [],
|
||||
prevProps: null,
|
||||
...baseFiber,
|
||||
};
|
||||
const _effect: _EffectCheck = { type: "remove" };
|
||||
expect(_fiber.instance).toBe("inst");
|
||||
|
||||
Reference in New Issue
Block a user