Merge feat/value-equal-bailout: add Value.Equal bail-out + cachedNode on Fiber (resolved conflicts with fiber-disposal's disposed field)

This commit is contained in:
2026-05-18 17:26:42 +00:00
9 changed files with 285 additions and 289 deletions

View File

@@ -71,6 +71,7 @@ export function createRoot<TTag extends string, Instance, RootCtx>(
effect: null,
signalDisposers: [],
prevProps: null,
cachedNode: node,
disposed: false,
};
if (parentFiber) parentFiber.children.push(fiber);
@@ -108,6 +109,7 @@ export function createRoot<TTag extends string, Instance, RootCtx>(
effect: null,
signalDisposers: [],
prevProps: null,
cachedNode: node,
disposed: false,
};
@@ -135,6 +137,7 @@ export function createRoot<TTag extends string, Instance, RootCtx>(
effect: null,
signalDisposers: [],
prevProps: null,
cachedNode: node,
disposed: false,
};
}
@@ -162,6 +165,7 @@ export function createRoot<TTag extends string, Instance, RootCtx>(
effect: null,
signalDisposers: [],
prevProps: null,
cachedNode: node,
disposed: false,
};
@@ -286,6 +290,7 @@ export function createRoot<TTag extends string, Instance, RootCtx>(
effect: null,
signalDisposers: [],
prevProps: null,
cachedNode: null,
disposed: false,
};
const payloadChildren = isURoot(node) ? (node as URoot).children : [node];

View File

@@ -1,3 +1,5 @@
import type { UNode } from "../core/schema.js";
export interface Fiber<I> {
instance: I;
tag: string;
@@ -9,6 +11,7 @@ export interface Fiber<I> {
signalDisposers: (() => void)[];
prevProps: Record<string, unknown> | null;
disposed: boolean;
cachedNode: UNode | null;
}
export type Effect<I> =

View File

@@ -1,4 +1,5 @@
import { effect } from "@preact/signals-core";
import { Value } from "@alkdev/typebox/value";
import type { Fiber, Effect } from "./fiber.js";
import type { HostConfig } from "./config.js";
import type { UNode, UElement } from "../core/schema.js";
@@ -59,6 +60,10 @@ export function reconcileProps<I>(
host: HostConfig<string, I, unknown>,
ctx: unknown,
): void {
if (fiber.cachedNode !== null && Value.Equal(fiber.cachedNode, nextNode)) {
return;
}
if (isUPrimitive(nextNode)) {
if (fiber.tag === "#text") {
const text = nextNode === null ? "" : String(nextNode);
@@ -78,6 +83,7 @@ export function reconcileProps<I>(
}
}
}
fiber.cachedNode = nextNode;
return;
}
@@ -87,6 +93,7 @@ export function reconcileProps<I>(
for (let i = 0; i < count; i++) {
reconcileProps(fiber.children[i]!, rootChildren[i]!, host, ctx);
}
fiber.cachedNode = nextNode;
return;
}
@@ -96,6 +103,7 @@ export function reconcileProps<I>(
const component = el.type as (props: Record<string, unknown>) => UNode;
const out = component({ ...el.props, children: el.children });
reconcileProps(fiber, out, host, ctx);
fiber.cachedNode = nextNode;
return;
}
@@ -120,6 +128,7 @@ export function reconcileProps<I>(
for (let i = 0; i < count; i++) {
reconcileProps(fiber.children[i]!, el.children[i]!, host, ctx);
}
fiber.cachedNode = nextNode;
}
export function commitEffects<I>(

View File

@@ -19,8 +19,7 @@ export { ValuePointer, selectNode, setNode } from "./core/pointer.js";
export { createRoot as createHostRoot } from "./host/config.js";
export type { HostConfig, Root } from "./host/config.js";
export { disposeFiber } from "./host/fiber.js";
export type { Fiber, Effect, HostLike } from "./host/fiber.js";
export type { Fiber, Effect } from "./host/fiber.js";
export { scheduleUpdate, flushUpdates, reconcileProps, commitEffects, commitMutations, wireSignalToFiber, resetUpdateQueue, reconcileChildren, longestIncreasingSubsequence } from "./host/reconcile.js";
export type { MatchedChild, ChildClassification, CommitContext } from "./host/reconcile.js";