From 614ee05364a83cb6ceb9a45ece0d476677cbb44f Mon Sep 17 00:00:00 2001 From: "glm-5.1" Date: Mon, 18 May 2026 16:41:35 +0000 Subject: [PATCH] Extract key from props in h() for UElement, keep key in props for URoot --- src/core/h.ts | 7 ++++--- test/mod.test.ts | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/core/h.ts b/src/core/h.ts index 10900ec..bb37718 100644 --- a/src/core/h.ts +++ b/src/core/h.ts @@ -3,18 +3,19 @@ import type { UNode, UElement, URoot, UType, UComponent, UniversalProps } from " let _idCounter = 0; export function h(type: UType, props?: UniversalProps | null, ...children: UNode[]): UElement | URoot { - const { key, ...restProps } = props ?? {}; - const resolvedProps: UniversalProps = restProps; const flatChildren = children.flat(Infinity as 1).filter((c: UNode) => c != null && c !== false) as UNode[]; if (type === "root") { return { type: "root", - props: resolvedProps, + props: { ...(props ?? {}) }, children: flatChildren, } as URoot; } + const { key, ...restProps } = props ?? {}; + const resolvedProps: UniversalProps = restProps; + return { type: type as string, props: resolvedProps, diff --git a/test/mod.test.ts b/test/mod.test.ts index 50f5856..c0f3dd3 100644 --- a/test/mod.test.ts +++ b/test/mod.test.ts @@ -100,6 +100,34 @@ describe("type guards", () => { }); describe("UElement key field", () => { + it("h('div', { key: 'a' }) produces UElement with key: 'a' and no key in props", () => { + const el = h("div", { key: "a" }); + expect(isUElement(el)).toBe(true); + if (isUElement(el)) { + expect(el.key).toBe("a"); + expect(el.props.key).toBeUndefined(); + } + }); + + it("h('div', { key: 'b', class: 'x' }) — key promoted, class remains in props", () => { + const el = h("div", { key: "b", class: "x" }); + expect(isUElement(el)).toBe(true); + if (isUElement(el)) { + expect(el.key).toBe("b"); + expect(el.props.key).toBeUndefined(); + expect(el.props.class).toBe("x"); + } + }); + + it("h('div', null) — key is undefined, no key in props", () => { + const el = h("div", null); + expect(isUElement(el)).toBe(true); + if (isUElement(el)) { + expect(el.key).toBeUndefined(); + expect(el.props).toEqual({}); + } + }); + it("h() extracts key from props and promotes to element level", () => { const el = h("div", { key: "item-1", class: "test" }, "hello"); expect(isUElement(el)).toBe(true); @@ -144,11 +172,11 @@ describe("UElement key field", () => { }); it("h() with root type does not promote key to URoot", () => { - const root = h("root", { key: "should-not-appear", id: "test" }, "child"); + const root = h("root", { key: "x", id: "test" }, "child"); expect(isURoot(root)).toBe(true); if (isURoot(root)) { expect("key" in root).toBe(false); - expect(root.props.key).toBeUndefined(); + expect(root.props.key).toBe("x"); } }); });